Frame by frame emulation

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Frame by frame emulation
by on (#147522)
Hello.

I'm currently writing a NES emulator which will be integrated in an AI lab software platform.

To have AI programs have a high level of control over the game played, I'd like to run the emulation frame by frame, ie. get AI inputs, run the CPU/PPU/APU for one frame, and then output the state of the world back to the AI. Is this possible ? I don't know if i should run the different chips sequentially or in parallel (every clock cycle) yet.

I'm mainly worried about timing: if we return from emulation loop as soon as the PPU emits the VBlank interrupt, the CPU is not executed during the VBlank period, so i don't know if the game will have the time to execute properly.

Another thing I'd like to know is there is a way to execute PPU dynamically. Let me explain: AI algorithms often require a huge number of simulation loops to find a solution. I don't _need_ to render the image, but it can be nice for a supervisor to check what the AI is doing. So i was wondering if it's possible to enable/disable the PPU (only at startup, not during emulation properly), in order to save time on large-scale simulations.

This last request is (for me) in contradiction with the frame-based timing above : if we disable the PPU, we'll never get the VBlank interrupt, so executing CPU for just one frame is not possible.

Thanks for reading.

P-S: If Nesdev is not the appropriate place for my questions, I'll be glad if you could tell me better suited sites (general emulation forums, i guess)
Re: Frame by frame emulation
by on (#147523)
The answer that you don't really want to hear is ... it depends on the game.

Some treat the PPU as a write-only interface; they never check the returned value from $2002, or use IRQs, or other things. For those games, one-frame-a-time emulation would be fine. (By which I mean, you could emulate the CPU for a frame, keeping track of when the CPU writes to the PPU, and then render the PPU accordingly.) You could even simply fail to render the output for these games, and they'd still work correctly.

Others poll on sprite 0, or sprite overflow, or use various PPU-centric IRQs. Most of those will need one-scanline-at-a-time emulation. The worst I could imagine would be polling for a sprite 0 hit on an MMC2 or MMC4-based cartridge, where you'd basically have to have one-pixel-at-a-time emulation.)
Re: Frame by frame emulation
by on (#147531)
The only region where you actually have to poll for sprite 0 hit is the rectangular region occupied by the sprite.

But it sounds kind of like you want to high-level-emulate the PPU, and PocketNES on the GBA does this. Except that's a GBA program done in ARM ASM, it is writing to GBA hardware to render the image, etc...
Re: Frame by frame emulation
by on (#147535)
metanux wrote:
To have AI programs have a high level of control over the game played, I'd like to run the emulation frame by frame, ie. get AI inputs, run the CPU/PPU/APU for one frame, and then output the state of the world back to the AI. Is this possible ?

Yes. You don't need to write a whole new emulator to do this. An existing emulator can easily be modified to run one frame, then wait for your AI program, then run the next frame, then wait for the AI program...

metanux wrote:
I don't know if i should run the different chips sequentially or in parallel (every clock cycle) yet.

Some games will work if you run the chips sequentially. More games will work if you run the chips in parallel.

metanux wrote:
I'm mainly worried about timing: if we return from emulation loop as soon as the PPU emits the VBlank interrupt, the CPU is not executed during the VBlank period, so i don't know if the game will have the time to execute properly.

Why wouldn't the CPU execute during vblank? If you halt the emulator at vblank to run your AI, when you resume the emulator it will continue where it left off: at the beginning of vblank.

metanux wrote:
So i was wondering if it's possible to enable/disable the PPU (only at startup, not during emulation properly), in order to save time on large-scale simulations.

This depends on the game. Many will require the PPU emulation to run. You don't have to actually output a picture; you can emulate the PPU and throw away the output image when you don't need it.

metanux wrote:
This last request is (for me) in contradiction with the frame-based timing above : if we disable the PPU, we'll never get the VBlank interrupt, so executing CPU for just one frame is not possible.

The VBlank interrupt is predictable enough that you can figure out when it will happen without emulating the entire PPU.
Re: Frame by frame emulation
by on (#147536)
Something like this was done with FCEUX: http://meatfighter.com/nintendotetrisai/
Re: Frame by frame emulation
by on (#147598)
Thank you for all the replies.

Joe wrote:
metanux wrote:
So i was wondering if it's possible to enable/disable the PPU (only at startup, not during emulation properly), in order to save time on large-scale simulations.

This depends on the game. Many will require the PPU emulation to run. You don't have to actually output a picture; you can emulate the PPU and throw away the output image when you don't need it.

I suspected it would vary from game to game. I'll try the rendering to a sort of buffer and discard if I don't need the image. Concerning modifying an existing emulator, yeah, I guess I could do like http://www.cs.cmu.edu/~tom7/mario/mario.pdf did with FCEUX (thanks for the tetris link, btw).

The only thing bugging me is FCEUX is not so well written, but having full use case/class/sequence/state chart diagrams for a NES emulator would require definitely lots and lots of hard work just to be clean, accurate and slow. So I think I'll adapt FCEUX, anyway.