As I was working through GBHawk Linked play support recently, I suddenly realized that what I was doing was really, really similar to what I needed to do to get subframe input working natively on NESHawk.
In fact, it was so similar that I decided to have a go at implementing it using what I learned from GBHawk.
As it turns out, it worked! I can run the NESHawk core at single cycle intervals until I hit a controller read, or until I hit a frame boundary.
The trick is that I had to modify FrameAdvance to return a bool value depending on whether or not a full frame had rendered. Obviously, all the other cores will just return true as usual, but SUBNESHawk will only return true at frame boundaries.
With this information, you can record video of only the actual frames. So even though a movie file might contain thousands of 'frames' (individual controller reads) when you record a video it will still be recorded at normal frame rate and produce a correct encode.
So, I can successfully bypass all of the problems with subframe input. I can make movies at the subframe level, I can use TAStudio since I have access to the complete core state at every cycle, and I can make encodes at the frame level as usual. Pretty neat!
I'll be making a PR in the coming days as I clean things up, but I don't foresee any major difficulties.
So if you find this interesting, please post suggestions so I can add them in as I go.
Joined: 4/7/2015
Posts: 331
Location: Porto Alegre, RS, Brazil
This is really interesting!
Is there any NES TAS that uses subframe inputs? SUBNESHawk would be a different core to be chosen in the core dropdown list? TAStudio would have subframes like "1234, 1234.1, 1234.2, 1234.3 ... 1234.999, 1235"? Could the same be done in the bsnes core, like Lsnes does?
Games are basically math with a visual representation of this math, that's why I make the scripts, to re-see games as math.
My things:
YouTube, GitHub, Pastebin, Twitter
It would be interesting to me if something like this existed for GBA with sub-frame hard-resets. Mario & Luigi Superstar Saga uses a "add everything % 256" checksum, so creating glitched savegames by copying or deleting and then resetting at the right time looks to be a possibility.
The SMB3 run from GDQ a couple years ago does. it constantly spams different controller readings until a stack overflow happens I believe. Hopefully this will allow that TAS to be remade and published.
You will choose with a checkbox in the core submenu (right below GB as SGB.) You'll need to have NESHawk selected also.
I'm not touching TAStudio, so you'll just have to re-interpret the frame number as input frames instead of video frames.
No this won't work for SNES. What I'm doing relies on the fact that I can run NESHawk at single PPU tick precision from a separate core layer. This is possible for GBHawk as well, so technically it would be possible to make something similar to MrWint's Pokemon Yellow ACE, but that's a long way off. A2600/7800 would also technically be possible to do this. SMS is possible in principle but the core would need to be re-written for single cycle execution.
So basically anything like SNES, GBA, or any ported core is not applicable here. You would need an entirely new emulator for it. This is basically just trickery with being able to run in-house cores with fine precision.
Alright I got everything straightened up for a pull request. Anyone who wants to try it out can check out the SubNESHawk branch.
Everything seems to be in working order. You can load up and use TAStudio (audio and video need a bit of work still for TAStudio) and I'm pretty sure savestates work correctly.
Right now I just have default 2 standard NES controllers plugged in, with no option to change them. As things mature I can add back in other options.
Resets aren't supported yet, only normal controller input. If there is a specific use case for it I can look into adding it in.
Subframes yeah!
Feel free to refer to Wiki: MESHUGGAH/ForbiddenTechniques 's "Sub frame inputs" and "NES DPCM glitch" for related and up to date informations.
PhD in TASing 🎓 speedrun enthusiast ❤🚷🔥 white hat hacker ▓ black box tester ░ censorships and rules...
Awesome!
I love that you figured this out in less than a month after telling me "Subframe input on the piano roll isn’t happening." here. Even if it is only for 1 or 2 cores.
This is essentially what I was suggesting/hoping for. WAY TO GO!
FWIW, I'm willing to help work on getting the SMB3 run re-done to see if it will work.
I've tried without any success. I don't see "subframes" where fceux (edit2) running with my lua script shows the game polls multiple times.
edit3: Missed point 1 as answered below me. Ignore this post :)1. I've downloaded this artifact: https://ci.appveyor.com/project/zeromus/bizhawk-udexo/builds/21420416/artifacts
2. Drop ROM
3. Core > NesHawk
4.1 Make a new movie and autofire
4.2 try with tastudio
4.3 copy paste empty and A for 2000 times in Input Log.txt
Result: no success with: Battletoads, Streemerz.
(edit: I'm not 100% sure about my lua script being reliable, but pretty sre Streemerz polls at least twice a frame)
PhD in TASing 🎓 speedrun enthusiast ❤🚷🔥 white hat hacker ▓ black box tester ░ censorships and rules...
It's not in the dev build yet, it's still a PR.
You have to build it from source until it's merged.
yeah funny how that works, I guess a change in perspective is all I needed from working on something completely unrelated. That's very often how it works for me.
Yeah SMB3 should probably be the first goal.
Checked NES Kirby's Adventure, seems to be 2 polling per frame consistently.
Note: In generally, this (or other games that poll multiple times within a frame) doesn't directly means it can be improved. It's very good sign if the subroutine call chain is similar, but the input dependent subroutines should also be called at least that many times to have an immediate effect of our extra input.
PhD in TASing 🎓 speedrun enthusiast ❤🚷🔥 white hat hacker ▓ black box tester ░ censorships and rules...
I didn't know this, but apparently there is a dev build for branches as well, you can download a compiled build with subneshawk here:
https://ci.appveyor.com/project/zeromus/bizhawk-udexo/builds/21423589/artifacts
Remember that to enable subneshawk, you need to both enable NESHawk in the core menu and also check the 'SubNESHawk' checkbox in the core menu.
I had to adjust it a bit due to timing differences from FCEUX, but here it is:
Super Mario Bros. 3 cleared in 126 polls by abusing the DPCM glitch workaround overflow.
It might not be actually 126 polls on console, as I assume there are blank, emulator-only polls, existing as a video frame so BizHawk can draw them.
Edit: I should probably add that the initial idea of abusing the workaround was by ais523, and total won the race of creating a way to jump to the credits. So all credit to them.
Warning: Might glitch to creditsI will finish this ACE soon as possible
(or will I?)
well...i guess that's at least one step closer to publication. I was hoping to help slightly more than just suggesting that I could help.
EDIT: Here's an encode of Masterjun's file.
Link to video
It works!
@Masterjun thanks for testing . Yeah each green frame is an input latch. Each red (lag) frame is a video frame edge , so a dump script for playback would only dump green frames.
@DrD2k9 well you can work on Gimmick too. Or anything that polls input often like Punch Out.
Wow, great job!
It's really cool to finally have this feature available in BizHawk.
Not only will it help bringing runs that uses subframe input to abuse the DPCM-glitch workaround in games, but it'll also enable faster ACE payload data transfers for future run that would use that.
I'll have to check it out when I can and try to convert the runs I've done for SMB3 and MM1 for AGDQ so people can check it out in an emulator if they wish.
I took some time and managed to convert the AGDQ2017 SMB3 ACE payload we used that does the DPCM glitching in 1-1 to lead into full total control. It's not the final version that was shown but it's mostly the same.
Wasn't too easy to convert though since I had to first convert the inputs from the binary format used for the hardware replay and then go in and manually resync inputs for every lag frame and frame boundary that didn't match up, but finally it worked :)
Here's the bk2:
http://tasvideos.org/userfiles/info/52514549789799992
Pretty cool to see it working at least!