Mesen has the handy feature of always keeping the last hundred or so instructions so you don't have to remember to turn on trace first

Actually, it keeps the last 30k instructions. That's mostly an arbitrary limit based on how much text I could fit into a regular textbox without performance being an issue, though.

Stepping backwards on a instruction-by-instruction basis would be pretty hard, essentially requiring a save state every instruction. The latest version does have a rewind feature though, with a shortcut to rewind 5 seconds, so it'd be relatively easy to use that to replay a particular sequence. Internally it saves the state every 30 frames, so I could add an option in the debugger to rewind to the previous one?

Stepping backwards on a instruction-by-instruction basis would be pretty hard, essentially requiring a save state every instruction. The latest version does have a rewind feature though, with a shortcut to rewind 5 seconds, so it'd be relatively easy to use that to replay a particular sequence. Internally it saves the state every 30 frames, so I could add an option in the debugger to rewind to the previous one?

I was thinking that it shouldn't be too processor-intensive to take save states on regular intervals, and when the user wants to step back just take the latest saved state and seek forward to the previous instruction. As an initialization step it could also take further additional save states inbetween (up to some preset memory limit) when doing it first time to speed up further backstepping.

On my PC, FCEUX can emulate about 3000 frames per second without framecaps, so with save states taken every 30 frames it should take at most 10 ms to backstep one instruction. (Of course the actual speed depends on the emulator and PC in use. But it's not like the user is going to be furiously smashing the backstep button. )

Working with savestates comes with its corner-cases. I think about gamepad inputs. (Does any other unpredictible data exists?). gamepad input may be handled by taking an extra save-state on $4016 write, but it commonly means a save-state per frame.

Maybe storing what's needed to rollback each instruction could be another solution. Basically, it means storing A before and LDA to be able to undo it. Somewhat like in the command pattern. But jumps and JSR exists, meaining it can be needed to save PC and S registers before each instruction ... And by itself it does not handle player inputs ...

3000 fps? That's pretty impressive - I typically get 500fps-ish at most out of FCEUX on mine with the old PPU (1st gen overclocked i5)

With Mesen I get anywhere between 300 and 450 depending on the game.So a save state every 30 frames takes 100ms or so to process - which is fine when rewinding gameplay, 100ms until the rewinding starts is not a big deal. But 100ms to rewind each instruction might be a bit frustrating to use if you have to go back 10+ instructions.

I guess I could load the previous state, execute until the cycle counter matches the value it had at the start of the previous instruction - it might be relatively easy to implement, I'll take a look when I get a chance.

@RogerBidonMesen (and probably most other rewind-capable emulators? unsure) records all controller input to be able to re-create the missing frames between save states as needed - it's a performance vs memory usage trade-off, really. The savestates are compressed with deflate & stored in memory - it takes roughly a MB of ram per minute (~120 save states). Taking a savestate every frame would end up being 30mb/minute, which is pretty high, and would probably have an impact on emulation speed, too.

But 100ms to rewind each instruction might be a bit frustrating to use if you have to go back 10+ instructions.

Yeah, some optimizations might be in order (e.g., the one I proposed earlier). That said...

Quote:

I guess I could load the previous state, execute until the cycle counter matches the value it had at the start of the previous instruction - it might be relatively easy to implement, I'll take a look when I get a chance.

...would be cool to see a proof-of-concept implementation of this, even if it's not the most optimal.

With newer releases using more CHR RAM, storing a lot of save states might take even more memory. Action 53 Volume 3 and The Curse of Possum Hollow, for instance, would each need 37K uncompressed: 32K for CHR RAM, 2K for nametables, 2K for CPU RAM, and 1K for OAM, CGRAM, and other machine state. So there should be some way to deduplicate data between adjacent save states, as the vast majority of video memory will remain unchanged from one frame to the next unless rendering is off. Just relying on gzip isn't enough, as this exceeds DEFLATE's window, and random access would still be painful.

...would be cool to see a proof-of-concept implementation of this, even if it's not the most optimal.

I've managed to get it working - only took a couple of hours or so. Surprisingly ended up being pretty simple to add.It has some limitations (in order to keep the code simple), but I think it's probably good enough for what you would typically need it for.Essentially, whenever you do "step back", it reloads the last save state, and keeps running (replaying previous input) to the previous instruction's PC.So it can't rewind past the last save state (so if the save state was taken 5 cycles ago, you'll only be able to rewind that far - but that's a pretty low probability, and I doubt anybody is going to start rewinding thousands of instructions).

Performance wasn't that great depending on how far the execution was to the last save state, so I added a save state cache for the last 100 cycles (e.g ~25-50 instructions) before the first step. On the first step back it makes a save state every instruction for the last 100 cycles before the target instruction, then it uses that cache until its empty and repeats the process. With this, stepping back is more or less as fast as stepping forward.

I made a preview build (windows-only, the code is on GitHub if you're using Linux) if anyone feels like giving it a try: linkIf you've ever used Mesen before, the emulator will most likely crash unless you remove the settings.xml file in the Documents\Mesen folder (because of other changes I've recently done to the settings.xml format that won't be upgraded properly since the build isn't marked as version 0.9.1)

I didn't test this all that much, so if you test it and see anything odd, let me know.

The cycle count was in hex because the generic UI binding code I use only supported hex notation for text boxes. The cycle count being in hex was annoying for me too though, so I took a few minutes and just changed it to decimal.

Who is online

Users browsing this forum: No registered users and 4 guests

You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot post attachments in this forum