I ran out of space in the video description to mention this, but sorry for not adding any commentary to the side explaining what's going on. I know I usually do that for these kinds of videos, but I decided that can wait for whatever this TAS looks like when it's finished. Anyway, I'm having fun with this and I plan to make this a couple minutes longer. I don't usually share my work in progress projects, but I thought it was too good not to.
Hey, just an FYI, to italicize your text on RUclips, surround your text with one underscore on each end. Surrounding your text with one asterisk on each end does bold, as you've already found out.
lol this is amazing. I assume you need DPCM bug or something too precise to start to do anything like this RTA? (I mean just to start the ACE, I know writing the payload is probably way too much)
Starting the ACE is simply killing Bowser with fireballs in world 'N'. (You also need to be holding the A button and _Not_ the B button when the final fireball hits Bowser, but that's certainly doable RTA.) But yeah, writing the payload required subframe inputs in SMB3, and utilizing the payload required subframe inputs in SMB1.
I have actually played a Next Fest demo of your game at some point, pretty wild you're working on that and made this. That gives me some confidence of the quality the final game will have, considering the technical knowledge something like this project requires. Impressive work.
That's why I always provide a link to download the TAS in the description. If you're skeptical, you can download the sequence of inputs and watch it run on your own computer. I appreciate the compliment!
Don't have much to say about the video itself (other than the ACE is cool) but your game seems pretty interesting and I'll probably play the demo tomorrow Edit: The game was indeed pretty interesting and I ended up 100%ing it. Looking forward to the full release!
It is genuinely criminal how underrated of a creator you are. keep up the good work mate! Also, question, do you happen to know how the game actually jumps to arbitrary code when killing bowser? i don't quite understand that.
Okay, so when bowser is killed with fireballs, his sprite is replaced with another sprite. The sprite Bowser transforms into is different for each world, so in world 1 he becomes a Goomba, in world 2 a Buzzy Beetle, and so on. This is an intended feature of the game, and I think the "lore" is that it's just one of his minions in disguise, and burning him to death "Reveals his true form". This effect works perfectly fine for the 8 worlds of the game, but if Mario is beyond world 8 things go wrong. This can be done through manipulating RAM in another game and swapping cartridges. World 'N' is what you get if the byte that determines the world number has a value of hex 0x16. (22 in base ten) So when bowser dies via fireballs, we grab the 23rd value in a table only 8 bytes long. This returns an unrelated byte with a value of 0xC9, so bowser becomes "Object C9". Now on the next frame, the game needs to run the code for each of the existing objects. This works through a "Jump Table", essentially the game has a list of addresses to jump to corresponding to the ID of each object. C9 is once again out of the bounds of the list, so unrelated bytes are used for this jump instruction. This doesn't go directly to running the ACE, but it's going to set up what does. Object C9 jumps the PC to address $D007, which normally runs at the end of the level loading routine. Level loading is in it's own "Game state", indicated by address $0772, and level loading ends by incrementing $0772 from a value of 2 to 3. '3" being the value of $0772 for the main game loop. This is also done through a jump table. The "Game State" jump table only has 4 entries with a 0 based index, so the highest value is 3. Since Object C9 takes us to the routine that increments $0772, the game state is now set to 4. On the following frame, the game uses a value of 4 in that jump table, and jumps to address $53AE, which isn't mapped to anything. When fetching data from an address that isn't mapped to anything, we call that "Open Bus". Essentially, when the PC fetches an opcode, nothing replaces the data that already exists on the consoles databus, so whatever was already there is interpreted as the opcode. In this case, by jumping to address $53AE, "0x53" is on the databus. This forms the instruction "SRE ($53), Y". To make a long story short, this ends up shifting the byte at address $000A to the right, and that new value is then on the databus. Miraculously, I can manipulate the value of $000A. If I simply hold down the A button (and not the B button) on the frame the last fireball hits Bowser, this byte will have the value 0x80. This shifts to the right to become 0x40, and since 0x40 is on the databus, the next instruction to execute will be the instruction corresponding to a byte with the value of 0x40, the RTI instruction. This pulls 3 bytes off the stack, and ends up sending the PC to address $1181, which is a location in RAM Super Mario bros never writes to. Since SMB1 never writes there, I can use an ACE exploit in another game (Super Mario Bros. 3) to write custom code at address $1181 (or just address $0181, since those are mirrors of eachother) and then killing Bowser in world 'N' of SMB1 leads to a series of events ending with a return to the custom code I wrote.
So far I've using about 32 bytes on the zero page, about 80% of the stack is replaced with my controller reading and code writing routines, I''m using the $200 page for OAM, the entire $300 page is dedicated to my graphics changing code (I'm using 128 bytes starting at $380 dedicated for writing a large series of bytes to be copy-pasted into the PPU), the entire $400 page is dedicated to my main loop that happens each frame, about half the $500 page is my audio code. So far I'm not using the $600 or $700 page. Edit: Oh, and I'll probably make this 4 minutes longer? That's a rough estimate, I have no idea what I'm going to do with this yet.
@@100thCoin Wow, that's amazing, and I got what you said due to having written a little for the NES a few months back using NesHacker's tutorials. It could be fun to see more computer science references that you could connect with Mario, like Game of -Life- Luigi, Bo(g)o Sort, etc. :)
The way I have it working, it should sync up pretty fast even if the CPU/PPUs aren't aligned exactly in the same way the emulator was when making this TAS. Assuming a TAS like this *can* be verified on console with a replay device, the worst case scenario would be a few lag frames during the "Bowser is defeated" screen. But yeah, not being able to use the NMI to check for V-Blank is pretty rough. In my ASM code for the main loop, the lowest bit of the first input read every frame is either going to be a "0" or a "1" depending on if I need to waste a single CPU cycle to prevent the false-negative read from $2002. I set up a LUA script to automatically add a button press there if the lag frame occurs when working on this TAS.
A rom hack that has a game similar to this would certainly be possible. Keep in mind, this was the prototype of what would become the bad apple TAS. The "game" shown in this TAS is very much not playable, and it's just a music engine that can move sprites around the screen and update the background.
It was discovered in April last year. It requires writing a payload in RAM that SMB1 doesn't initialize, and swapping cartridges so you can start the game in world 'N'.
@@BooeythePatooie You would still be able to kill bowser with fireballs, thus leading the to PC executing code at $181, but unless you also have a significant list of cheats to write a payload at address $181, you would just crash the game.
Would it be possible to set up the payload RTA? Like using similar method to the 7-1 wrong warp. Also do you think it will ever be possible to set up a payload in smb1?
In theory, the payload could be set up RTA, though in practice it would be tedious, near impossible, and likely take multiple hours of manually storing specific bytes inside the stack (since SMB3 doesn't clear that region) to create an advanced payload for SMB3, run it, then have it set up the RAM for you. Alternatively, you could create a custom cartridge to just set up the RAM, which would be easy and RTA viable to just power on and swap carts.
i suppose it's now theoretically possible to play back cory arcangel's 2010 hack Super Mario Movie (ruclips.net/video/f0sBjNp0Z-Q/видео.html) inside the actual super mario bros
So many button presses. Essentially, with an ACE exploit jumping the PC to uninitialized RAM, I'm able to put any custom payload there before swapping cartridges. The code I write lets me write more code through reading the controller a whole bunch, and it cascades from there. I added code for changing the Nametables (the backgrounds), the APU Registers (The music) and the OAM data (sprites). Everything is updated via reading the controller a bunch. I only have 2kib or RAM so I don't actually have space to program a whole "Travelling Salesman The Game" so it's just pretending there's gameplay by manually writing data to the screen and audio chip.
I ran out of space in the video description to mention this, but sorry for not adding any commentary to the side explaining what's going on. I know I usually do that for these kinds of videos, but I decided that can wait for whatever this TAS looks like when it's finished. Anyway, I'm having fun with this and I plan to make this a couple minutes longer. I don't usually share my work in progress projects, but I thought it was too good not to.
Hey, just an FYI, to italicize your text on RUclips, surround your text with one underscore on each end. Surrounding your text with one asterisk on each end does bold, as you've already found out.
There's something delightful about hearing Famitracker cracktro music over SMB1 graphics
SMB has ACE?????? And nobody told me??
Looks incredible :O Can’t wait to see the finished product!!
I see you every popular video.
I hadn't realized we have discovered ACE in SMB.
Here's the video I made in April after discovering a way to set up a payload an execute it: ruclips.net/video/xoDakIA31jc/видео.html
They made a entire Mario game in a TAS
HOLY COW!
lol this is amazing. I assume you need DPCM bug or something too precise to start to do anything like this RTA? (I mean just to start the ACE, I know writing the payload is probably way too much)
Starting the ACE is simply killing Bowser with fireballs in world 'N'. (You also need to be holding the A button and _Not_ the B button when the final fireball hits Bowser, but that's certainly doable RTA.) But yeah, writing the payload required subframe inputs in SMB3, and utilizing the payload required subframe inputs in SMB1.
@@100thCoin ok, yeah that's pretty much what I thought. Doing anything useful with the exploit seems out of the scope of RTA at the moment. Thanks!
I have actually played a Next Fest demo of your game at some point, pretty wild you're working on that and made this. That gives me some confidence of the quality the final game will have, considering the technical knowledge something like this project requires. Impressive work.
Oh wow, that's awesome! I really appreciate the kind words!
I mean this as a compliment: this is so surprising and amazing and good that I can't shake the feeling that it's an April Fools joke or something.
That's why I always provide a link to download the TAS in the description. If you're skeptical, you can download the sequence of inputs and watch it run on your own computer.
I appreciate the compliment!
This is so cool, nice work!
Don't have much to say about the video itself (other than the ACE is cool) but your game seems pretty interesting and I'll probably play the demo tomorrow
Edit: The game was indeed pretty interesting and I ended up 100%ing it. Looking forward to the full release!
I'm glad to hear you enjoyed the demo! The game will be coming out on Leap Day, Feb 29! I'm probably going to upload a video soon about it.
love your creativity
YESS!!! Love it when you drop new videos!!!!!! This one is awesome!!!! GG 100th Coin!
It is genuinely criminal how underrated of a creator you are. keep up the good work mate!
Also, question, do you happen to know how the game actually jumps to arbitrary code when killing bowser? i don't quite understand that.
Okay, so when bowser is killed with fireballs, his sprite is replaced with another sprite. The sprite Bowser transforms into is different for each world, so in world 1 he becomes a Goomba, in world 2 a Buzzy Beetle, and so on. This is an intended feature of the game, and I think the "lore" is that it's just one of his minions in disguise, and burning him to death "Reveals his true form". This effect works perfectly fine for the 8 worlds of the game, but if Mario is beyond world 8 things go wrong. This can be done through manipulating RAM in another game and swapping cartridges.
World 'N' is what you get if the byte that determines the world number has a value of hex 0x16. (22 in base ten) So when bowser dies via fireballs, we grab the 23rd value in a table only 8 bytes long. This returns an unrelated byte with a value of 0xC9, so bowser becomes "Object C9". Now on the next frame, the game needs to run the code for each of the existing objects. This works through a "Jump Table", essentially the game has a list of addresses to jump to corresponding to the ID of each object. C9 is once again out of the bounds of the list, so unrelated bytes are used for this jump instruction. This doesn't go directly to running the ACE, but it's going to set up what does. Object C9 jumps the PC to address $D007, which normally runs at the end of the level loading routine. Level loading is in it's own "Game state", indicated by address $0772, and level loading ends by incrementing $0772 from a value of 2 to 3. '3" being the value of $0772 for the main game loop.
This is also done through a jump table. The "Game State" jump table only has 4 entries with a 0 based index, so the highest value is 3. Since Object C9 takes us to the routine that increments $0772, the game state is now set to 4. On the following frame, the game uses a value of 4 in that jump table, and jumps to address $53AE, which isn't mapped to anything. When fetching data from an address that isn't mapped to anything, we call that "Open Bus". Essentially, when the PC fetches an opcode, nothing replaces the data that already exists on the consoles databus, so whatever was already there is interpreted as the opcode. In this case, by jumping to address $53AE, "0x53" is on the databus. This forms the instruction "SRE ($53), Y". To make a long story short, this ends up shifting the byte at address $000A to the right, and that new value is then on the databus. Miraculously, I can manipulate the value of $000A. If I simply hold down the A button (and not the B button) on the frame the last fireball hits Bowser, this byte will have the value 0x80. This shifts to the right to become 0x40, and since 0x40 is on the databus, the next instruction to execute will be the instruction corresponding to a byte with the value of 0x40, the RTI instruction. This pulls 3 bytes off the stack, and ends up sending the PC to address $1181, which is a location in RAM Super Mario bros never writes to.
Since SMB1 never writes there, I can use an ACE exploit in another game (Super Mario Bros. 3) to write custom code at address $1181 (or just address $0181, since those are mirrors of eachother) and then killing Bowser in world 'N' of SMB1 leads to a series of events ending with a return to the custom code I wrote.
This is amazing! How much of your 2 KiB did you use up, and up to how many more minutes of fun TASing do you think will fit?
So far I've using about 32 bytes on the zero page, about 80% of the stack is replaced with my controller reading and code writing routines, I''m using the $200 page for OAM, the entire $300 page is dedicated to my graphics changing code (I'm using 128 bytes starting at $380 dedicated for writing a large series of bytes to be copy-pasted into the PPU), the entire $400 page is dedicated to my main loop that happens each frame, about half the $500 page is my audio code. So far I'm not using the $600 or $700 page.
Edit: Oh, and I'll probably make this 4 minutes longer? That's a rough estimate, I have no idea what I'm going to do with this yet.
@@100thCoin Wow, that's amazing, and I got what you said due to having written a little for the NES a few months back using NesHacker's tutorials. It could be fun to see more computer science references that you could connect with Mario, like Game of -Life- Luigi, Bo(g)o Sort, etc. :)
ACE, quite a funny thing...
Is that really the best way to wait for vblank? Feels a little bad...
Also, making a game sounds quite hard, so good luck!
The way I have it working, it should sync up pretty fast even if the CPU/PPUs aren't aligned exactly in the same way the emulator was when making this TAS. Assuming a TAS like this *can* be verified on console with a replay device, the worst case scenario would be a few lag frames during the "Bowser is defeated" screen.
But yeah, not being able to use the NMI to check for V-Blank is pretty rough. In my ASM code for the main loop, the lowest bit of the first input read every frame is either going to be a "0" or a "1" depending on if I need to waste a single CPU cycle to prevent the false-negative read from $2002. I set up a LUA script to automatically add a button press there if the lag frame occurs when working on this TAS.
Oh my GOD
Okay, now make it compute the optimal path for all graphs
Right after I saw that Pokemon Yellow video 💀
are you able to make this into a rom hack by any chance? i love this.
A rom hack that has a game similar to this would certainly be possible. Keep in mind, this was the prototype of what would become the bad apple TAS. The "game" shown in this TAS is very much not playable, and it's just a music engine that can move sprites around the screen and update the background.
Hold up, ACE can be done in SMB? I always thought it was impossible.. When did it get discovered?
It was discovered in April last year. It requires writing a payload in RAM that SMB1 doesn't initialize, and swapping cartridges so you can start the game in world 'N'.
@@100thCoincan you also do so using a cheat code that lets you start in World N?
@@BooeythePatooie You would still be able to kill bowser with fireballs, thus leading the to PC executing code at $181, but unless you also have a significant list of cheats to write a payload at address $181, you would just crash the game.
I shudder to think what the optimal route is.
Aw, no 2hues and bad apples in this one. :(
Would it be possible to set up the payload RTA? Like using similar method to the 7-1 wrong warp.
Also do you think it will ever be possible to set up a payload in smb1?
In theory, the payload could be set up RTA, though in practice it would be tedious, near impossible, and likely take multiple hours of manually storing specific bytes inside the stack (since SMB3 doesn't clear that region) to create an advanced payload for SMB3, run it, then have it set up the RAM for you. Alternatively, you could create a custom cartridge to just set up the RAM, which would be easy and RTA viable to just power on and swap carts.
Woah
Any chance for the release of the music? Would love to listen to them.
Sure! Give me a little bit, I'll upload the tracks...
Here you go!
ruclips.net/video/4KB7-td0X1M/видео.html
i wanna ask, why when i try playing any tas like this its slowed down? speeding it up doesnt help
Can we have OST?
Here you go!
ruclips.net/video/4KB7-td0X1M/видео.html
when is the optimal route speedrun for nerds :((
i suppose it's now theoretically possible to play back cory arcangel's 2010 hack Super Mario Movie (ruclips.net/video/f0sBjNp0Z-Q/видео.html) inside the actual super mario bros
With the way my TAS is set up, in theory, yes! I *could* recreate that in an unmodified version of SMB1.
Oh, sure, just (GARBAGE NOISE) your way into becoming a sailsman.
wtf how
So many button presses. Essentially, with an ACE exploit jumping the PC to uninitialized RAM, I'm able to put any custom payload there before swapping cartridges. The code I write lets me write more code through reading the controller a whole bunch, and it cascades from there. I added code for changing the Nametables (the backgrounds), the APU Registers (The music) and the OAM data (sprites). Everything is updated via reading the controller a bunch.
I only have 2kib or RAM so I don't actually have space to program a whole "Travelling Salesman The Game" so it's just pretending there's gameplay by manually writing data to the screen and audio chip.
@@100thCoin epic