New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to compute frames as fast as possible #43

Open
DaniGuardiola opened this Issue Aug 16, 2018 · 4 comments

Comments

Projects
None yet
2 participants
@DaniGuardiola

DaniGuardiola commented Aug 16, 2018

Me and @Fieoner are working on a bot and we are using your (awesome) emulator in headless mode to make it work. However, the frames are limited so that it runs in real time, which makes sense for direct standard use. For computing frames, however, it makes more sense to run it as fast as possible, so we would like to know if there's any option to make this happen or if it can be implemented.

We are happy to help.

Thanks in advance!

@Baekalfen

This comment has been minimized.

Show comment
Hide comment
@Baekalfen

Baekalfen Aug 16, 2018

Owner

Thanks for your interest in the project!

Are you using DummyGameWindow to make it run headless? That should disable the frame limiter, and also skip the heavy part of the screen rendering. But you will end up without a screen buffer. Instead, you can access the tile views and sprites directly, which is a lot faster. I can try to make some wrappers and documentation to make it easier to use, if you would like.

Owner

Baekalfen commented Aug 16, 2018

Thanks for your interest in the project!

Are you using DummyGameWindow to make it run headless? That should disable the frame limiter, and also skip the heavy part of the screen rendering. But you will end up without a screen buffer. Instead, you can access the tile views and sprites directly, which is a lot faster. I can try to make some wrappers and documentation to make it easier to use, if you would like.

@Baekalfen

This comment has been minimized.

Show comment
Hide comment
@Baekalfen

Baekalfen Aug 16, 2018

Owner

I just noticed, I did actually implement some small wrappers called TileView and Sprite. I can extend them, if they lack any functionality.

https://github.com/Baekalfen/PyBoy/blob/master/Source/PyBoy/BotSupport/

Owner

Baekalfen commented Aug 16, 2018

I just noticed, I did actually implement some small wrappers called TileView and Sprite. I can extend them, if they lack any functionality.

https://github.com/Baekalfen/PyBoy/blob/master/Source/PyBoy/BotSupport/

@DaniGuardiola

This comment has been minimized.

Show comment
Hide comment
@DaniGuardiola

DaniGuardiola Aug 16, 2018

Hey thanks for the quick response! Two things:

  • I just realized that we haven't yet tried the headless mode. We are still on early stages of the project and we are using the standard window in order to see what's going on, sorry about that 😅

  • We are indeed using the screen buffer to get the pixel matrix and then render it into an image. We haven't looked yet into how to render the screen from the tileviews and the sprites, although we did notice a mention to it in the documentation. At some point I personally plan to read the report and try to understand the whole PyBoy codebase, just out of curiosity, but for now I wonder if it would be possible to render the screen selectively only on the frames that we want, even on headless mode, to obtain the pixel matrix, in the same way the standard window mode currently does. Would this make sense?

Thank you :)

DaniGuardiola commented Aug 16, 2018

Hey thanks for the quick response! Two things:

  • I just realized that we haven't yet tried the headless mode. We are still on early stages of the project and we are using the standard window in order to see what's going on, sorry about that 😅

  • We are indeed using the screen buffer to get the pixel matrix and then render it into an image. We haven't looked yet into how to render the screen from the tileviews and the sprites, although we did notice a mention to it in the documentation. At some point I personally plan to read the report and try to understand the whole PyBoy codebase, just out of curiosity, but for now I wonder if it would be possible to render the screen selectively only on the frames that we want, even on headless mode, to obtain the pixel matrix, in the same way the standard window mode currently does. Would this make sense?

Thank you :)

@Baekalfen

This comment has been minimized.

Show comment
Hide comment
@Baekalfen

Baekalfen Aug 16, 2018

Owner

No problem. Do try the dummy window at some point. It might give 30-50% speed-up, at the expense of the screen buffer.

It might be "cheating", but by using the tiles and sprites directly, you wouldn't exactly need to render anything. Both tiles and sprites provide their coordinate on screen, which for a bot would be the important part. Then observe and hardcode which tile/sprite-indices are noteworthy (enemies, boxes etc.). In the report, this should be covered on page 19 through 22.
Do be aware, that the report is quite old, so class names and such might not be correct anymore. But everything about the Game Boy hardware should be correct.

It should be possible to only render the frames selectively. I just reinstalled my computer, and I'm struggling with some dependencies, so I cannot test my code, but give this patch a try:

diff --git a/Source/PyBoy/GameWindow/GameWindow_SDL2.py b/Source/PyBoy/GameWindow/GameWindow_SDL2.py
index 5a2a0cf..dce2d0c 100644
--- a/Source/PyBoy/GameWindow/GameWindow_SDL2.py
+++ b/Source/PyBoy/GameWindow/GameWindow_SDL2.py
@@ -183,6 +183,9 @@ class SdlGameWindow(AbstractGameWindow):
         return events
 
     def updateDisplay(self):
+        pass
+
+    def _updateDisplay(self):
         self._window.refresh()
         self._screenBuffer.update() # TODO: Flip order?
         if __debug__:
@@ -207,6 +210,10 @@ class SdlGameWindow(AbstractGameWindow):
         self.scanlineParameters[y] = viewPos + windowPos
 
     def renderScreen(self, lcd):
+        self._lcd = lcd
+        pass
+
+    def _renderScreen(self, lcd):
         self.refreshTileData(lcd)
 
         # All VRAM addresses are offset by 0x8000
@@ -333,6 +340,8 @@ class SdlGameWindow(AbstractGameWindow):
 
 
     def getScreenBuffer(self):
+        self._renderScreen(self, self._lcd)
+        self._updateDisplay(self)
         return self._screenBuffer.get_buffer()
 
     #################################################################
Owner

Baekalfen commented Aug 16, 2018

No problem. Do try the dummy window at some point. It might give 30-50% speed-up, at the expense of the screen buffer.

It might be "cheating", but by using the tiles and sprites directly, you wouldn't exactly need to render anything. Both tiles and sprites provide their coordinate on screen, which for a bot would be the important part. Then observe and hardcode which tile/sprite-indices are noteworthy (enemies, boxes etc.). In the report, this should be covered on page 19 through 22.
Do be aware, that the report is quite old, so class names and such might not be correct anymore. But everything about the Game Boy hardware should be correct.

It should be possible to only render the frames selectively. I just reinstalled my computer, and I'm struggling with some dependencies, so I cannot test my code, but give this patch a try:

diff --git a/Source/PyBoy/GameWindow/GameWindow_SDL2.py b/Source/PyBoy/GameWindow/GameWindow_SDL2.py
index 5a2a0cf..dce2d0c 100644
--- a/Source/PyBoy/GameWindow/GameWindow_SDL2.py
+++ b/Source/PyBoy/GameWindow/GameWindow_SDL2.py
@@ -183,6 +183,9 @@ class SdlGameWindow(AbstractGameWindow):
         return events
 
     def updateDisplay(self):
+        pass
+
+    def _updateDisplay(self):
         self._window.refresh()
         self._screenBuffer.update() # TODO: Flip order?
         if __debug__:
@@ -207,6 +210,10 @@ class SdlGameWindow(AbstractGameWindow):
         self.scanlineParameters[y] = viewPos + windowPos
 
     def renderScreen(self, lcd):
+        self._lcd = lcd
+        pass
+
+    def _renderScreen(self, lcd):
         self.refreshTileData(lcd)
 
         # All VRAM addresses are offset by 0x8000
@@ -333,6 +340,8 @@ class SdlGameWindow(AbstractGameWindow):
 
 
     def getScreenBuffer(self):
+        self._renderScreen(self, self._lcd)
+        self._updateDisplay(self)
         return self._screenBuffer.get_buffer()
 
     #################################################################
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment