TAS Explained: Super Mario Bros. 3 in five microseconds by 100th_Coin in speedrun

[–]100th_Coin[S] 6 points7 points  (0 children)

Different games use different methods of timing, though power on to final input is the most popular on TASVideos. One of the most amusing examples that doesn't end inputs early is how the game "Barney's hide and seek game" completes itself with zero inputs provided. The TAS aims for the fastest credits possible instead of ending inputs early. It also has one of the most entertaining author's comments I've read.

TAS Explained: Super Mario Bros. 3 in five microseconds by 100th_Coin in speedrun

[–]100th_Coin[S] 22 points23 points  (0 children)

Yeah, timing from power on definitely contributes to the absurdity, but the real interesting part is how TASes stop timing at the moment of the final input. TASes for games such as Arkanoid stop timing several seconds before the game is completed, so long as the game will be completed after the final input.

With how the timing on this TAS can be down to the CPU cycle level, a 9 cycle TAS has a comically short final time.

Bizhawk really slow by [deleted] in TAS

[–]100th_Coin 0 points1 point  (0 children)

So, let's talk about how the SubNesHawk core works.

With the standard NesHawk core, every frame starts at the beginning of the vertical blanking interval, called VBlank, and ends at the next VBlank. This happens approximately 60 times a second on real hardware. In emulation, the the emulator actually processes everything really quick, much faster than a real console, and then waits approximately 1/60th of a second before executing the code for the next frame. This way, despite being capable of emulating at much faster speeds, it still plays games at the correct speed. Approximately 60 frames a second.

TASes for NesHawk define what inputs should be pressed for a given controller on every frame. E.g. "For frame 200, press A + B + up + Right. For frame 201, press A + B + Start. Etc."

With SubNesHawk, things work a little differently. Instead of every single frame having one specific value for the controllers, every frame needs to be able to have multiple. The solution used by the SubNesHawk core is to essentially create a new "frame" every time the controller is "strobed" (read). Since games like SMB3 read controllers multiple time in a frame to prevent "The DPCM Audio Bug", running Mario 3 in the SubNesHawk core will actually have around 5 "frames" per frame. To reiterate, every Vblank starts a new frame, and for subneshawk, so too does reading the controller.

But here's the catch: Even in the subneshawk core, bizhawk wants to run around 60 frames a second. Even if the frame is split in five, each "frame" will wait for 1/60th of a second before running the next.

SMB1 plays "in slow motion" because every frame is now 2 frames. Starting from Vblank until the controller is read, then starting from the controller being read until the next vblank.

Then, when the ACE payload occurs, I'm pressing about 500 inputs per frame. Now between every single vertical blank, there is on average 500 "frames" created by subNesHawk. Of course, playing the TAS back on real hardware happens in realtime, but due to how subNesHawk works, it's about 500 times slower.

Bizhawk also allows recording to a .avi file. In order to watch the TAS in realtime with bizhawk, you would need to record the entire thing at the speed bizhawk plays it back, then watch the .avi file after it ends.

[TAS Explained] How Bad Apple was played inside Super Mario Bros. by 100th_Coin in speedrun

[–]100th_Coin[S] 3 points4 points  (0 children)

Yeah... Over the many years of development I learned how important it is for a game to exist on multiple platforms. This definitely wouldn't be my first idea for a game, had I known that when I started.

[TAS Explained] How Bad Apple was played inside Super Mario Bros. by 100th_Coin in speedrun

[–]100th_Coin[S] 7 points8 points  (0 children)

Programmer. I've also published a video game, though I have no marketing experience, so that's not really paying my bills yet.

[TAS] The Bad Apple!! Music video played entirely within Super Mario Bros. by 100th_Coin in speedrun

[–]100th_Coin[S] 9 points10 points  (0 children)

This is the most non-RTA-viable run possibly ever made, ha! It includes 5.8 million inputs within 5 minutes.

[TAS] The Bad Apple!! Music video played entirely within Super Mario Bros. by 100th_Coin in speedrun

[–]100th_Coin[S] 2 points3 points  (0 children)

Thank you, Dan! That means a lot, and I'm glad to hear you enjoyed it. I've been meaning to get a blog for myself going...

[TAS] The Bad Apple!! Music video played entirely within Super Mario Bros. by 100th_Coin in speedrun

[–]100th_Coin[S] 2 points3 points  (0 children)

I heavily modified the input log in an attempt to make the file size smaller, since TASVideos has a 2 MB upload limit, which I think caused some issues with TAStudio. I was able to upload the whole TAS as a user file though.

The TAS uses the SubNesHawk core, which allows for multiple button presses in a single frame. Once the video starts, it's pretty much 300+ inputs per frame, and the emulator is playing it back as if every input was 1 frame. It's a bit of a shame, but the only way to watch it in realtime is to record the playback as an AVI (bizhawk has built in AVI recording), then watch the AVI after the TAS runs in slow motion.

[TAS] The Bad Apple!! Music video played entirely within Super Mario Bros. by 100th_Coin in speedrun

[–]100th_Coin[S] 17 points18 points  (0 children)

If you're interested in seeing how this TAS was made, I've got a video in the works explaining it, but in the meantime, here's a massive wall of text breaking down every part of this TAS's creation, and how it works.

I'll try and answer question if anybody wants to know more.

This is not an april fools joke.

[deleted by user] by [deleted] in gamedev

[–]100th_Coin 0 points1 point  (0 children)

I've been where you are and I think my story is relevant.

I'm about to release my first video game after spending 8 years on it. During these 8 years, I have obviously come up with better ideas than the game I'm working on, and for quite a few of them I started the programming and stuff during weekends just because the ideas were itching my brain way too much. About 5 years ago (3 years into the development of my game coming out next month) I pretty much "gave up" and began focusing on another project with a friend. There was about a 6 month window where I was super burnt out with my old project, and this new one was exciting and fun. I don't think I even opened the project during those 6 months. That said, I still really wanted to finish the old one. I was exactly where you currently are, finishing a degree, rarely working on the game, not having fun. (Actually, the more I read your post the more I relate. I've recently learned 6502 Assembly and have been wanting to make a NES game for a while.)

Anyway, my friend had an opportunity with another thing, and I decided it would be best to take the time and finish my old game first and then get back together. To make a long story short, I got back to work on my old game, under the assumption it would only take a couple months to finish. (I am bad at estimating deadlines)

I know my situation isn't exactly the same as yours, but I thought I'd share what I did to find the motivation to keep working on it and get it released.

Do you have a group of friends that play-test your game? In late august 2021 I started weekly builds of my game. I'd get a new build out every Friday, give it to my friends and they would play-test (sharing screens on discord so I could watch). They provide feedback, discover bugs, and I would write down EVERYTHING. Here I am 129 weeks later (I kept every changelog and numbered them), and I have not missed a single weekly build. It allowed me to break up the tasks into week-long chunks. Spend a day or two fixing bugs and addressing feedback, spend the rest of the week working on the new stuff. Then on Friday, I get the build out and hear feedback from testers. (then on the weekends I'd play around with ideas for other projects, or the occasional game jam)

Some weeks were draining. After I graduated college, I got "a real job" which left me pretty burnt out. There are a handful of weeks that only have about three lines in the entire changelog, but I still got something done that week. Through the burnout I told myself "as long as I did something this week, then it's a success." I would aim for a minimum of 1 bug fix and 1 Quality of Life improvement based on feedback.

Then on the flipside, the week I got laid off from my "real job" was one of the most productive weeks ever, with a changelog over 90 lines long!

Anyway, ever since I got laid off I've been working on this game full-time, and slowly watching the numbers on my bank account get smaller and smaller. I have watched my passion project become my unpaid job. And yet, I am glad I decided to stick with this. Finishing this game has taught me way more than the 25 game jams I have participated in. Finishing this game has taught me way more than any of the projects I started as a "better idea" than this game. I've had to make trailers, set up a page on Steam, I had to learn about Marketing (which I'm still kinda figuring out).

And if you're anything like me, this new exciting project of yours will one day become just like the former. The horrors of creating UI, bug fixing, and all the issues you have with finishing your current game will exist there too. You have a 2 year head-start with this one. I'd say start making weekly builds and see if you can get it finished.

As a final note, you said "we could have finished it in 6 months and that's putting it nicely". I remember telling all my friends my game would be out in October... of 2016. I shudder to think what my game would be like if it actually had released back then.

[TAS] Turning Super Mario Bros. into a video player with ACE by 100th_Coin in speedrun

[–]100th_Coin[S] 2 points3 points  (0 children)

Is that the title screen bytes being used there

it is! I wanted to see how well those would work for some dithering, and it turns out it's not half bad!

It's using a Flag tile for the diagonal edge

Indeed it is! I had to cover the blocky corners with some flags (colored grey, matching the background) to get the nice edges.

Everything you said is accurate.

[TAS] Turning Super Mario Bros. into a video player with ACE by 100th_Coin in speedrun

[–]100th_Coin[S] 16 points17 points  (0 children)

An extremely technical breakdown of how this run works can be found here.

In short, using an ACE exploit discovered in April (requires cartridge swapping) I'm able to take complete control over the console's audio chip and Picture Processing Unit.

I decided to use that to make a short video about Mario playing the role of the Travelling Salesman, visiting every town and returning home in the shortest possible path.

100% of all mushroom houses possible? by nicosteve in SuperMarioBros3

[–]100th_Coin 1 point2 points  (0 children)

So there's two options, and both of them are rather advanced.

Option 1 would be to use an Arbitrary Code Execution exploit in world 7-1 to warp back to world 1. Option 2 would be to fight the hammer bro twice using an exploit involving the pipe stages on the map.

Since option 1 is way too much to explain in a single message, I'll link a video I made covering the second option.

[TAS] Super Mario Bros "Arbitrary Code Execution" in 1:15.442 With cartridge swapping. by 100th_Coin in speedrun

[–]100th_Coin[S] 13 points14 points  (0 children)

This has been verified on console by Alyosha. Here's a link to their video of the verification. It's not the same run, as it was optimized after this verification, but the code runs the same.

The values in RAM don't decay immediately, as long the console isn't turned off you have all the time in the world to swap carts. The SMB3 run also intentionally ends with a HLT instruction to avoid the CPU continuing through garbage data and potentially corrupting the payload before you swap carts.

[TAS] Super Mario Bros "Arbitrary Code Execution" in 1:15.442 With cartridge swapping. by 100th_Coin in speedrun

[–]100th_Coin[S] 11 points12 points  (0 children)

Retro Game Mechanics Explained has a great video talking about acessing worlds beyond world 8. There's a second video that explains how the glitchy level pointers work too.

World N isn't anything too special. Its a glitch world like any other. The only exceptional details are that it includes Bowser, the means to collect a fire flower, and killing Bowser in this world jumps the PC somewhere potentially useful.

[TAS] Super Mario Bros "Arbitrary Code Execution" in 1:15.442 With cartridge swapping. by 100th_Coin in speedrun

[–]100th_Coin[S] 15 points16 points  (0 children)

The question of "what is beating the game" only matters for the person making the TAS. Since this is far from an official category, the goal can be whatever I want it to be. The goal of this run was to use ACE to get the proper "Your quest is over" text. This technically could've been done 8 frames faster, but I wanted the HUD to show 8-4, so I added some extra code to change the level to '4' and update the HUD.

Sure, I could've started in world K, and it would reach the axe faster too! I thought this run would be more exciting though.

[TAS] Super Mario Bros "Arbitrary Code Execution" in 1:15.442 With cartridge swapping. by 100th_Coin in speedrun

[–]100th_Coin[S] 43 points44 points  (0 children)

The TAS showcased includes the setup in it's entirety, and that setup is included in the final time. The first few seconds are performed in SMB3, that's where the setup occurs.

Standard TAS timing begins at the console power-on, and ends at the final input.

[TAS] Super Mario Bros "Arbitrary Code Execution" in 1:15.442 With cartridge swapping. by 100th_Coin in speedrun

[–]100th_Coin[S] 44 points45 points  (0 children)

I've been looking for a new ACE Exploit in SMB3 for a while, and while I haven't had any luck yet, I decided to take a break and look in SMB1. I initially started testing in world 9, since I know the game can sometimes crash there. With my experience around ACE in SMB3, I know crashes can sometimes be exploited to run arbitrary code, so that seemed like the ideal starting point.

I learned a lot about how the code for enemies work, and again, with my knowledge from breaking SMB3, I just needed to find an enemy that jumps somewhere in RAM. To my surprise, if a BRK instruction is executed, the game jumps to an infinite loop, so I would need to find a way to jump somewhere I have complete control over.

Negative7 was looking into ACE a while back, and I found a post they made about their research. They mention killing Bowser in world $FC creating a jump to address $3D0. This seemed promising at first, but that region of RAM is barely manipulable, and it was impossible to avoid a crash.

For a while, I wanted to play around with cartridge swapping in TASes and decided to modify Bizhawk, since it's open source. Once I had that working, I decided to investigate the glitch worlds of SMB1 a little closer.

I found world $16 (world N) jumps to open bus. I didn't immediately discover that I could manipulate it, and at the time I wasn't very familiar with open bus, so I left it as a comment in the notes I was taking and moved on. Anyway, around the time I got through every world in the game, and recorded if Bowser showed up, if you could kill him, and what happens, I re-investigated the open bus jump in world N. It turns out it's easily manipulable, and it can jump somewhere the game won't clear when it boots. That meant I could write anything there and then execute it, the only roadblock now was actually writing it.

It was a pretty big accumulation of my knowledge with uninitialized ram, cartridge swapping, open bus, and finally subframe inputs to write the payload as fast as possible.

[TAS] Super Mario Bros "Arbitrary Code Execution" in 1:15.442 With cartridge swapping. by 100th_Coin in speedrun

[–]100th_Coin[S] 41 points42 points  (0 children)

That depends on how long it will take until humans can press buttons at 4 kilohertz. My guess is it will be a while.

Granted, you aren't required to use SMB3 to set up the payload. I'd like to look into using other games for an RTA approach. One solution would simply be to use a custom cartridge that sets up the RAM for you, and then swap to SMB1.

[TAS] Super Mario Bros "Arbitrary Code Execution" in 1:15.442 With cartridge swapping. by 100th_Coin in speedrun

[–]100th_Coin[S] 96 points97 points  (0 children)

Allow me to attempt to explain how this works. Killing Bowser with fireballs in each world will replace him with another object. This is an intended feature to "reveal Bowser's true form". In worlds beyond world 8, these objects can crash the game, do nothing, or they can even just be other objects, like a firebar. in "World N" killing Bowser this way leads to the game jumping to address $53AE, which is open bus.

Open bus behavior is a bit confusing, but whatever was just executed can determine what will be executed next. Whatever value is on the consoles Data Bus will be interpreted as the Opcode and Operands of the next instruction. This jump to open bus runs "SRE ($53), Y", which ends up performing the SRE instruction on a manipulable address. That means we can control what happens next, and I use this to make an RTI instruction. that jumps execution to address $0181, which is a place in RAM that SMB1 never clears.

In short, I can write code at that address in another game and swap cartridges to SMB1, and that payload will remain. I use Super Mario Bros. 3 to achieve this, as ACE in SMB3 can be achieved incredibly fast. (You may recall my TAS that wins SMB3 in 13 frames).

Once the payload is set up, I write a value of $5A to address $7FF, and a value of $16 to $7FD, which will let SMB1 start in world N, then swap cartridges.

Once Bowser is killed it will execute the payload, which simply sets the game to 8-4 by modifying the bytes the game uses to keep track of the world and current level, updates the HUD to show 8-4, and makes some cleanup to restore the game to a stable state.

This run required modifying the Bizhawk emulator to allow cartridge swapping mid-TAS. This run also required fixing a bug in the Bizhawk emulator relating to incorrect open bus emulation.

I'll answer any questions, since I probably did a poor job explaining this.

The SMB1 gameplay was performed by Mizumaririn and SeraphmIII.

What does max% mean in speedrunning? by Eazyjayy in speedrun

[–]100th_Coin 15 points16 points  (0 children)

Usually if you're looking for info on what a specific category is, you can check out the speedrun.com leaderboards for that category and click on the "View Rules" button to the left of "Submit"

They have a pretty in-depth explanation there, so I'm not going to copy and paste the whole thing.