This movie uses the same exploit used for the game end glitch to achieve total control and do some fun stuff. As I submit, dwangoAC is showing a slightly modified version on console for Awesome Games Done Quick 2016 [dead link removed]. Watch the movie before continuing if you don't want spoilers!

Goals

  • Colors a dinosaur
  • 1st TAS to get 99 lives for both Mario and Luigi
  • There were no other goals
I discovered how to achieve total control of SMB3 shortly after Tompa and I published the game end glitch version in 2014. I had it in mind to do a playaround movie integrating new custom powers with regular SMB3 gameplay.
A major challenge was the fact that almost all of my programming experience was in higher level languages like Java -- I knew next to nothing about assembly language or the NES architecture: terms like PPU, nametable and bank switching meant nothing to me.
Thanks to the many excellent web resources available for NES programmers, I worked my way up the learning curve and implemented increasingly sophisticated pieces of new functionality. Along the way, true encouraged me to tweak things so they'd verify on console, a process which required some rewrites to use the PRG1 ROM instead of PRG0.
I had a lot of code written, but no real plan as of Oct 2015 when dwangoAC contacted me about including SMB3 total control in Awesome Games Done Quick 2016. Having a deadline to work against forced me to focus and finally get this done.

Powers

When I first thought about doing this run, I was intrigued by the idea of pairing custom/augmented gameplay features with ordinary gameplay, so that was the starting point for much of what I ended up implementing.

Back Door

I thought it'd be fun to pretend that SMB3's legendary lead developer, Shigeru Miyamoto, had left an intentional "back door" hidden in the game which we had only just now discovered. Presented as an 80's style shell interface, the back door pretends to allow commands (with options) to be entered to enable the otherwise impossible happenings that follow.

Color a Dinosaur

Tasvideos.org has a bit of a running joke about the coloring of dinosaurs, ever since a couple of April Fool's submissions for an actual NES game called 'Color a Dinosaur' a few years back. SMB3 is widely felt to be the greatest NES game of all time, so I thought its first task under total control should be an homage to a game of more modest fame.
All of the coloring actions – change color, move the cursor, draw, and start over can be done by a human in realtime if anyone wants to try to top my masterpiece.

Speed Boost/Shine Spark

I'm a big fan of SNES Super Metroid and both its real time speedruns and TASs. I though it would be cool to create a speed mechanic for SMB3 as much as possible like how the speed boots/shine spark work in Super Metroid. This effect required several hundred bytes of code, hence the prolonged loading time, and was technically the most difficult to implement. It is quite easy to play around with in realtime, especially on levels like 2-4 that are big both horizontally and vertically.

Suit-Swap

The suit swap is a very simple but versatile bit of code that gives Mario a new suit based on the game's timer. As the player has no way of knowing the current timer value, the effect in realtime play is to choose a random suit. Under TAS conditions, of course, I can choose whichever suit I want based on which frame I activate the effect.
Of note, there are only 7 legal suits, but the Suit Swap rolls over every 8th frame. Assigning the 8th suit gives the surprising result of Mario's sprites being a complete jumble when standing, invisible when ducking, and the game physics treating him as if he's swimming! I use it a couple of times in this movie just to show the bizarre behavior.

Shell Shield

The shell shield wasn't based on any particular inspiration; I just thought it'd be cool. It was pretty easy to write, and involves using one of the 5 enemy slots for an invincible koopa shell that follows Mario around, killing enemies and laying waste to destructible blocks. The shell shield can be activated/deactivated with the select button. When deactivated, the shell becomes an ordinary, destructible koopa shell that can be stomped and grabbed if desired…though it can also hit you so you need to carefully time when you release it! It's my favorite power to play around with in realtime.
Mario will stomp the shell shield when falling, allowing him to essentially fly if he wishes by holding the a/jump button while in the air to maximize the boost achieved with each stomp. This was an actual case where a bug turned out to secretly be a feature – I did not intend this behavior, but liked the flexibility it provides so much that I left it in.

PwnScroll

Auto-scrolling levels are a dominant feature of most every SMB3 realtime speedrun and TAS that doesn't use the game end glitch. Autoscrollers can be frustrating to TAS because they're so long, there's little if anything you can do to save time, and it's difficult to think of entertaining ways to spend all that time.
The World 8 autoscrollers have a special place in my heart due to being difficult (for me, at least) in realtime play, and necessary for all non-glitched SMB3 TASs (since even with warps you still have to do world 8).
That made it a priority to imagine what the game might look like if Mario could control when and where the screen scrolled, or if the autoscrollers functioned as regular levels. Both are demonstrated here.
Watching Mario jump past the tank at full running speed may not look all that interesting to those less familiar with the game, but for someone who's spent hours watching those tanks scroll slooooowly by, there's something magical in it! (It might be worth querying Mitch or another realtime player on their thoughts on the autoscrollers and their pwnage).
The autoscroller functions can be used in realtime, but it's easy to crash the game or accidentally die. Disabling autoscrolling at the beginning of a stage seems pretty safe, at least for 8-Tank!

Anti-Gravity

This power was somewhat inspired by something you can do in NES Battle of Olympus to flip upside down and walk on the ceiling. I debated for a long time which level would best showcase this, and ended up on Bowser's Castle because it's prominently vertical and I found a surprising shortcut it enables – clipping into the wall as small Mario running upside down just above the lava. Because of the size and complexity of real collision detection in SMB3, this power is a total hack and not usable in realtime, though I have to say I like how it looks in the TASs I've done with it.

Bowser

I've played around with Bowser during previous TASs, doing things like fighting him with star invincibility active (he dies, but the game hangs). I was pleasantly surprised to see that the shell shield kills him with a single blow and actually proceeds to the ending (though in the interest of time I manually jump to the ending several seconds early).

Ending

Pretty much every TAS I've watched on YouTube has commenters denouncing videos clearly labeled as tool-assisted as fakes, cheats, etc, so I thought it'd be funny if Mario had to face a similarly skeptical Princess.
As a side note, the Princess's normal text here is hard-coded in the ROM. Because of how total control is achieved in SMB3, it can take a lot of effort to change something like that to read from customized RAM instead – in this case a few hundred bytes of code/data are required.

Bootstrapping to Total Control

As explained in the game end glitch run, touching the glitch tile, an invisible note block, makes the processor try to update memory outside of the normal tile data, at an address ($9C70) that reprograms how the processor interprets addresses. This causes execution to jump to an unintended area of the ROM and execute incorrect instructions due to byte misalignment. Eventually, the stack overflows and it starts executing RAM instructions starting at address $0081, which is just before the location of the player x value at $0090. The 10 bytes manipulated to boostrap total control are koopa x values at $0091-5, and koopa walking counters at $9A-9E.
For the game-end glitch, only a single assembly instruction was required: JSR $8FE1, a subroutine jump to the ending. This code was "written" by careful gameplay to manipulate enemies into x positions (20, 143, 225) that would generate the above instruction.
Total control starts with this loop at frame 11287, with execution starting at RAM address $0091:
$0091: JSR $96E5 ; subroutine that waits until frame ends; NMI updates controllers & $15 counter
$0094: LDA $F7   ; load controller 1 state
$0096: BRK       ; do nothing 
$0098: BRK       ; do nothing
$009a: INX       ; increment X register
$009b: STA,X $7d ; store controller data to next spot in RAM
$009d: BNE $0091 ; if X isn't zero, loop to $0091
The code is written around what the initial value of the X register is expected to be, and starts writing code at $0098: within the loop itself! This was necessary because $98 and $99 can't be manipulated by gameplay in 7-1. The modified loop will exit after the next phase of the total control program, written immediately following the initial loop, is ready.
$0091: JSR $96E5 ; subroutine that waits until frame ends; NMI updates controllers & $15 counter
$0094: LDA $F7   ; load controller 1 state
$0096: BRK       ; do nothing 
$0098: BEQ $009f ; if nothing pressed on controller 1, jump to $009f
$009a: INX       ; increment X register
$009b: STA,X $7d ; store controller data to next spot in RAM
$009d: BNE $0091 ; if X isn't zero, loop to $0091
Ultimately, the controllers are used to create general total control program that checks each frame for start+select on controller 2, and if detected uses the coming input to load a new payload into memory. If there's no new payload, it calls $0147 as a subroutine; payloads deposited here are the entry point for custom behavior.

My "IDE"

This project required thousands of instructions be introduced into memory using keypresses on 2 controllers. (Technical note: I could have cut loading times in half using 4 controllers via the NES 4-play device. I didn't pursue this because current replay devices don't support the 4-play, so console verification would not have been possible).
Obviously, there's no IDE that exists for the purpose of writing 6502 assembly code for output as an FCEUX movie file, so I did the best I could using Excel spreadsheets.
Each payload follows a standard format: a 4-byte header (2 frames of 2-controller input) indicates how many bytes (2-128) to write and to which RAM address. The controller presses that follow are read as the specified payload, 2 bytes per frame, and are written into RAM. Interestingly, because everything is happening in RAM, exactly the same process is used to inject code for execution as to, say, poke a memory value (e.g. set number of lives to 99).
My Excel setup used columns, formulas and the like to make it as easy as possible to lay out a payload in a standard way. For each payload, I'd hand-write the assembly instructions/data in human-readable form, then "compile" them myself into the correct bytes for each controller under columns C1/C2. The spreadsheet then automatically generates the correct FCEUX input which can be copied/pasted into the movie file.
Anyone who's curious can see my Excel IDE as of today, which includes most of the code used in the movie, and some (Zelda music code) that wasn't.
The above process worked pretty well. The major sources of error were typo's in converting instructions into bytes and forgetting to correctly update the header when a payload's size or location changed. Debugging was generally pretty straightforward using the FCEUX trace logger.

Need...Input...

One unexpected hurdle in making this was the need to make a custom input poller. The NMI is nice enough to load the controller data each frame, but SMB3 actually has logic to detect illegal button presses like L+R and U+D and zeroes the d-pad input out in those cases! That doesn't sound like a big deal, but when you're looking to write code, it's nice for each controller to be able to have 256 possible states (1 byte/controller/frame) rather than only 144. So one of the earliest tasks once I start setting up Total Control is to write my own input routine and use that to free up all possible controller states.

Limitations RAM Hacking the NES

It turns out that "Total Control" doesn't equate to omnipotence: NES architectural features place limits on what can be accomplished via RAM hacking.
Chief among these is that the vast majority of the game's code and data resides in ROM - which cannot be modified. As a result, many tasks that would be trivial for a ROM hacker -- e.g. minor changes to a subroutine or tweaking music/sound effects -- present much greater challenges. For example, modifying a subroutine generally requires replicating much of the code leading up to the section of interest - which can be hundreds of instructions!
The way the PPU works also limits graphical changes. The PPU assembles the game's backgrounds and sprites from a gallery 8x8 pixel tiles called pattern tables. These exist in ROM, so while a ROM hacker could easily make substitutions to make bricks look exactly as they do in SMB1, or create a sprite from original graphics, that just isn't possible here.
So -- true total control requires ROM hacking, but one thing no ROM hacker can honestly say is that their hack runs on the original, unmodified hardware. :)

Missing the Cut

One payload that I omitted from this submission was code that would substitute whatever music the game was trying to play with a custom music track, namely the level 9 dungeon music from NES The Legend of Zelda.
This task is complicated greatly by the inability to modify the ROM, and while I was able to get the music playing, some sound effects degraded the sound in unexpected ways and in the available time for AGDQ I couldn't get it polished enough to include.
As music and sound effects have to play nice to share the same sound channels, I think I can get this working perfectly with more research into how the sound/music code interacts, but it's out for now.

Running SMB3 Gameplay Under Total Control

The ideal model for running total control functionality alongside the regular game engine would be if an infinite loop like this executed every frame:
while (true)
  doNormalSMB3()
  doTotalControlStuff()
end
Unfortunately, the game developers weren't so thoughtful: the game's main loop looks more like this:
A:
  (dozens of instructions)
B:
  (dozens of instructions)
  goto D (i.e. the JMP instruction)
C:
  (dozens of instructions)
D:
  (dozens of instructions)
goto A
So the bottom of the call stack has several hundred instructions spanning the title screen, world map, mini-games, and regular gameplay. Even worse, under many conditions (dying, completing a level, entering a pipe, etc) dozens of frames could elapse in some deeply buried subroutine, and under some conditions the code will manually jump to another section of the main loop, rather than returning normally. Without careful management, such behaviors can easily allow the game to "escape" total control, reverting to normal or (more likely) glitched/unstable behavior.
The structure of the main loop necessitated a lot of work to pare it down to something that could reasonably be replicated in RAM while preserving the ability to play the game. The world map and mini-games were among the pieces of functionality sacrificed to achieve this; hence the movie jumps from level to level via a "back door" rather than other approaches that might have been used. I have the code written to enable use of doors/tubes but didn't load it for this run to save space and because I found enough antics to pull in the levels proper.

Thanks

  • My family for understanding that hours of holiday time just *had* to be spent hacking a 27 year old game
  • Tompa - my SMB3 partner in crime
  • true - for nudging me to work on console verification
  • dwangoAC - for the AGDQ idea and making it happen
  • Southbird - for the incomprehensibly massive job of disassembling and fully commenting the game
  • 6502.org and Nesdev Wiki for reference material I used constantly

Nach: I was really excited to see this movie, it incorporates most of what I threw out there on SMB3 over a year ago (what no Kuribo's Shoe???). I even suggested to Masterjun again just last Thursday that he should make a run where Mario has VVVVVV's gravity powers, based on some earlier work. I am thrilled that someone finally made this. There's a ton of potential with this kind of run, and this is a terrific start to show off what's possible and really get the ball rolling.
There is the question as to whether this should obsolete the existing run which uses the same exploit to just simply jump to the end of the game, as this is way more entertaining. With the precedent set, even though I personally disagree with it, I will consider this as a branch onto itself.
This movie did a good job in catering to in-house jokes, being super entertaining for viewers everywhere, and had excellent choices made in the abilities it showed off. The new abilities added are the kind of thing you'd expect from a movie of this genre, and were spot on. The levels chosen to show off the new abilities are among the most iconic in the game and well recognizable and quite fitting for the abilities portrayed in each one. Throughout the custom parts added, a lot of attention to details for entertainment can be seen.
Aside from not providing an opportunity to show off Kuribo's Shoe, I can't think of anything negative about this run. This is by far one of the most entertaining movies ever submitted, with practically every bit of it carefully selected to provide maximum entertainment value. Accepting to Stars.
fsvgm777:
-> encode-this-movie
Unable to encode this movie
-> sudo encode-this-movie


WE ENCODING, GRAB THE FILES!


Player (13)
Joined: 6/17/2006
Posts: 508
I never expected a serious code injection ACE with such depth. Amazing! Is there a simple way to enable/disable these new game modes and play through the entire game casually using them?
Lord_Tom
He/Him
Expert player (3144)
Joined: 5/25/2007
Posts: 399
Location: New England
SmashManiac wrote:
Is there a simple way to enable/disable these new game modes and play through the entire game casually using them?
Not *yet*...
Joined: 9/1/2014
Posts: 58
Pointless really to post saying I approve of this since it's probably obvious.
Enjoys speedruns but hasn't actually tried making any yet.
Glitcher
He/Him
Joined: 3/24/2007
Posts: 216
Location: London, U.K.
Words cannot describe how amazing that was! I haven't been this impressed with a TAS since the first Pokémon Yellow ACE run. This is one of the best gameplay videos I've seen.
Joined: 1/13/2007
Posts: 343
Not only does this show the credits, it also kills Bowser. So it seems clear that this is a playaround that completes the game. :) (Now if someone will just make a run that programs SMB1 in SMW, then TASes it..)
Editor, Expert player (2330)
Joined: 5/15/2007
Posts: 3933
Location: Germany
zaphod77 wrote:
(Now if someone will just make a run that programs SMB1 in SMW, then TASes it..)
But with some extras or unexpected cameos...
Post subject: This run is also a speedrecord. Brought to you by R.O.B.
Emulator Coder
Joined: 3/9/2004
Posts: 4588
Location: In his lab studying psychology to find new ways to torture TASers and forumers
I just wanted to highlight that with all the extra content added, this run is still faster than a non "ACE'd" run of this game. Also, the version shown at AGDQ which had Mitch playing around a bit at the end still took up less time than a normal person beating this game as fast as possible.
Warning: Opinions expressed by Nach or others in this post do not necessarily reflect the views, opinions, or position of Nach himself on the matter(s) being discussed therein.
Experienced player (690)
Joined: 11/23/2013
Posts: 2233
Location: Guatemala
Question, should the category name of this run be the same as SMW and Pokemon Yellow?
Here, my YouTube channel: http://www.youtube.com/user/dekutony
fsvgm777
She/Her
Senior Publisher, Player (226)
Joined: 5/28/2009
Posts: 1214
Location: Luxembourg
Who is interested in an alternate encode with input display?
Steam Community page - Bluesky profile Oh, I'm just a concerned observer.
Fortranm
He/Him
Editor, Experienced player (878)
Joined: 10/19/2013
Posts: 1121
fsvgm777 wrote:
Who is interested in an alternate encode with input display?
ME
WST
She/Her
Active player (489)
Joined: 10/6/2011
Posts: 1697
Location: RU · ID · AM
fsvgm777 wrote:
Who is interested in an alternate encode with input display?
me too
S3&A [Amy amy%] improvement (with Evil_3D & kaan55) — currently in SPZ2 my TAS channel · If I ever come into your dream, I’ll be riding an eggship :)
Post subject: re: sudo encode-this-movie, sudo color-a-dinosaur
Emulator Coder
Joined: 3/9/2004
Posts: 4588
Location: In his lab studying psychology to find new ways to torture TASers and forumers
Warning: Opinions expressed by Nach or others in this post do not necessarily reflect the views, opinions, or position of Nach himself on the matter(s) being discussed therein.
Site Admin, Skilled player (1254)
Joined: 4/17/2010
Posts: 11478
Location: Lake Char­gogg­a­gogg­man­chaugg­a­gogg­chau­bun­a­gung­a­maugg
fsvgm777 wrote:
Who is interested in an alternate encode with input display?
17:38	fsvgm777	Nach: By the way, if there's enough demand, I'm going to make an alternate (YT) encode with the button presses.
I guess there's no enough demand yet. sudo do-it
Warning: When making decisions, I try to collect as much data as possible before actually deciding. I try to abstract away and see the principles behind real world events and people's opinions. I try to generalize them and turn into something clear and reusable. I hate depending on unpredictable and having to make lottery guesses. Any problem can be solved by systems thinking and acting.
fsvgm777
She/Her
Senior Publisher, Player (226)
Joined: 5/28/2009
Posts: 1214
Location: Luxembourg
All right then, will do it once I'm done with the other encodes.
Steam Community page - Bluesky profile Oh, I'm just a concerned observer.
Post subject: Movie published
TASVideoAgent
They/Them
Moderator
Joined: 8/3/2004
Posts: 15585
Location: 127.0.0.1
This movie has been published. The posts before this message apply to the submission, and posts after this message apply to the published movie. ---- [3050] NES Super Mario Bros. 3 "arbitrary code execution" by Lord_Tom in 08:16.23
Post subject: Re: #4961: Lord Tom's NES Super Mario Bros. 3 "Total Control" in 08:16.23
Joined: 12/16/2005
Posts: 69
TASVideoAgent wrote:
This is by far one of the most entertaining movies ever submitted ...
You said it - this is amazing! Thank you for making this, Lord Tom!
Experienced player (634)
Joined: 5/2/2014
Posts: 21
WOW! This is completely perfect.
Joined: 11/20/2004
Posts: 236
Location: United States
Watching this movie on its own was pretty hilarious. Watching the Awesome Games Done Quick version, however, was phenominal. I'm still laughing!
I'm not that hard to find... if you know where to look. -=( http://jolikmc.tumblr.com )=-
Joined: 11/15/2004
Posts: 804
Location: Canada
That was the most amazing TAS I've ever seen. I love that you incorporated some of the most popular memes from the site, like Color A Dinosaur and Shinespark. The best for me, though was the sudo joke at 3:22. I totally burst out laughing. I'm in a network operating system class and we're all getting tired of being told that we can't do something after forgetting to type sudo. Great job!
TASing or playing back a DOS game? Make sure your files match the archive at RGB Classic Games.
Player (26)
Joined: 8/29/2011
Posts: 1206
Location: Amsterdam
hopper wrote:
That was the most amazing TAS I've ever seen. I love that you incorporated some of the most popular memes from the site, like Color A Dinosaur and Shinespark. The best for me, though was the sudo joke at 3:22. I totally burst out laughing. I'm in a network operating system class and we're all getting tired of being told that we can't do something after forgetting to type sudo. Great job!
Former player
Joined: 9/3/2012
Posts: 40
Location: boston
I'm the guy who did the first pokemon yellow hack back in 2013 -- this run is awesome! My original inspiration was to make an interactive terminal with code injection in-game; it's wonderful to see it finally happen. Going back into the game and giving yourself god-like powers is so satisfying to watch. It really feels like Mario becomes the master of his reality in this run. happy hacking! --Robert McIntyre
Joined: 8/2/2015
Posts: 4
This run says it has commentary, but I can't find it on either of the two encodes linked directly (this and this). Is it referring to the AGDQ showcase, or is the commentary elsewhere (e.g. in annotations I'm missing)?
Site Admin, Skilled player (1254)
Joined: 4/17/2010
Posts: 11478
Location: Lake Char­gogg­a­gogg­man­chaugg­a­gogg­chau­bun­a­gung­a­maugg
It is referring to subtitles, and they are in there for both downloadables.
Warning: When making decisions, I try to collect as much data as possible before actually deciding. I try to abstract away and see the principles behind real world events and people's opinions. I try to generalize them and turn into something clear and reusable. I hate depending on unpredictable and having to make lottery guesses. Any problem can be solved by systems thinking and acting.
fsvgm777
She/Her
Senior Publisher, Player (226)
Joined: 5/28/2009
Posts: 1214
Location: Luxembourg
They're also available on YouTube via the CC (closed captioning) button in the player.
Steam Community page - Bluesky profile Oh, I'm just a concerned observer.
Joined: 8/2/2015
Posts: 4
Ah, makes sense. I assumed it would have used annotations since that's what I've seen before. I also (incorrectly) assumed that the closed captions would have displayed by default had they existed (since that was the preference I set on YouTube's account_playback page). Ah well, thanks for letting me know.