HN Gopher Feed (2017-10-16) - page 1 of 10 ___________________________________________________________________
A Comprehensive Super Mario Bros. Disassembly
238 points by shubhamjain
https://gist.github.com/1wErt3r/4048722___________________________________________________________________
camhenlin - 3 hours ago
For people interested in the SMB disassembly, you may also be
interested in this one: http://bisqwit.iki.fi/jutut/megamansource/
NES MegaMan disassembly, with some comments
binarymax - 2 hours ago
I love that this is just a gist. Like 'hey just needed to copy and
paste this for a minute'
khedoros1 - 4 hours ago
There's also a Legend of Zelda disassembly, but it's not as
nice:https://github.com/camthesaxman/zeldasourceIt's a much larger
game, though.I haven't checked, but I'm assuming that a lot of the
giant chunks of statically-defined data are just graphics and audio
(unlike many games, LoZ stored graphics interspersed with the
program code and copied data over to an in-cartridge RAM chip,
instead of storing the complete graphics data in a ROM chip.)
derefr - 3 hours ago
> unlike many games, LoZ stored graphics interspersed with the
program code and copied data over to an in-cartridge RAM chip,
instead of storing the complete graphics data in a ROM chipThis
is because Zelda 1 was a port from the Famicom Disk System?no
memory-mapped ROM chip to rely on, so you've got to load
everything you're going to use to RAM. (Also like this:
Metroid.)I believe this is why both LoZ's and Metroid's maps are
built out of individual "screens" with a "pause to transition"
effect between them: in the FDD version, the game would be
reading the new map from disk, and there'd (sometimes, if the
load took long enough) be a loading screen involved. (You can see
the screen for LoZ here:
http://tcrf.net/The_Legend_of_Zelda/Console_Differences#Load...)
segmondy - 4 hours ago
The entire game in 16,000 lines of assembly code. :-)
webXL - 3 hours ago
I love stuff like this. Seeing the disassembly somehow adds to the
nostalgia for a childhood pastime.What's this endlessloop for:
https://gist.github.com/1wErt3r/4048722#file-smbdis-asm-L712(Yes,
please ;)
jepler - 3 hours ago
You can see that just above the endless loop, the code will
"enable NMIs". I'm not sure about the nomenclature here (because
normally NMI stands for non-maskable interrupts, meaning you
can't disable them) but basically the game at this point becomes
event (interrupt) driven, probably from the vertical retrace
interrupt or another kind of timer interrupt. When no event is
being handled, the CPU idles within this endless loop.
jepler - 3 hours ago
https://wiki.nesdev.com/w/index.php/PPU_registers#Controller...
states that bit 7 of the register at $2000 (which they call
PPUCTRL, and this disassembly calls PPU_CTRL_REG1) will
"generate an NMI at the start of the vertical blanking
interval"
1zael - 5 hours ago
This is insane.
MBCook - 1 hours ago
Is there a version of this somewhere that people have changed it to
C or some other higher level language for easier skimming? I?d love
to see that.(Yes, I know it was written in ASM).
wgrover - 4 hours ago
Looks like data for the various songs
here:https://gist.github.com/1wErt3r/4048722#file-smbdis-
asm-L160...I'd love to see the process of extracting actual audio
from that.
earenndil - 2 hours ago
There're tools that can extract audio from snes roms, I'm sure
there's something similar for nes.
strangecasts - 3 hours ago
The NES had a memory-mapped APU[1], so the game just sets sound
registers to play the appropriate notes, and ticks down a timer
until it's time to switch to the next note:
https://gist.github.com/1wErt3r/4048722#file-smbdis-
asm-L156...[1] https://wiki.nesdev.com/w/index.php/APU
DonHopkins - 2 hours ago
I wrote this earlier on another forum but I'll repost it here:I've
seen Shigeru Miyamoto speak at several game developer conferences
over the years. He's absolutely brilliant, a really nice guy, and
there's so much to learn by studying his work and listening to him
talk. Will Wright calls him the Stephen Spielberg of games.At one
of his earlier talks, he explained that he starts designing games
by thinking about how you touch, manipulate and interact with the
input device in the real world, instead of thinking about the
software and models inside the virtual world of the computer first.
The instantaneous response of Mario 64 and how you can run and jump
around is a great example of that.Shigeru Miyamoto GDC 1999 Keynote
(Full): https://www.youtube.com/watch?v=LC2Pf5F2acIAt a later talk
about how he designed the Wii, he said that he now starts designing
games by thinking about what kind of expression he wants it to
evoke on the player's faces, and how to make the players themselves
entertain the other people in the room who aren't even playing the
game themselves. That's why the Wii has so many great party games,
like Wii Sports. Then he showed a video of a little girl sitting in
her grandfather's lap playing a game --
http://youtu.be/SY3a4dCBQYs?t=12m29s , with a delighted expression
on her face. The grandfather was delighted and entertained by
watching his granddaughter enjoy the game.This photo --
https://i.imgur.com/zSbOYbk.jpg -- perfectly illustrates exactly
what he means!Shigeru Miyamoto 2007 GDC Keynote - Part 1:
https://www.youtube.com/watch?v=En9OXg7lZoEShigeru Miyamoto 2007
GDC Keynote - Part 2:
https://www.youtube.com/watch?v=jer1KCPTcdEShigeru Miyamoto 2007
GDC Keynote - Part 3:
https://www.youtube.com/watch?v=SY3a4dCBQYsShigeru Miyamoto 2007
GDC Keynote - Part 4:
https://www.youtube.com/watch?v=jqBee2YlDPgShigeru Miyamoto 2007
GDC Keynote - Part 5:
https://www.youtube.com/watch?v=WI3DB3tYiOwShigeru Miyamoto 2007
GDC Keynote - Part 6:
https://www.youtube.com/watch?v=XvwYBSkzevwShigeru Miyamoto Keynote
GDC 07 - Wife-o-meter: https://www.youtube.com/watch?v=6GMybmWHzfU
looperhacks - 3 hours ago
You might also be interested in the dissambly of the first pokemon
games:https://github.com/pret/pokeredAnd some other pokemon
games:https://github.com/pret/pokered#see-also
DarkTree - 1 hours ago
I loved this article regarding the algorithm used for capturing
pokemon: http://www.dragonflycave.com/mechanics/gen-i-capturing
raldi - 3 hours ago
Check out the section under "DemoActionData": this is where it
stores (and plays) the demo you see when you don't push Start and
Mario runs around on his own volition.It just simulates player
input and runs it through the regular game engine. (The
alternative, playing a recorded video, would have been laughably
data intensive.)
dEnigma - 3 hours ago
Same thing goes for Super Mario 64. The popular TASer pannenkoek
actually explored whether it was possible to manipulate Demo-
Mario's starting position in such a way that he collects a star
with the demo input (this was for the purposes of special
"A-Button Challenge" speedruns, where pressing the A-Button must
be kept to a minimum, but since the demo input isn't actual
player input it isn't counted) Sadly I think there was no
conceivable way to do it. (i.e. manipulating the starting
position is possible, but not in a way that leads to collecting a
star)https://youtu.be/-0emgkIEobI
opdahl - 52 minutes ago
That's an amazing youtube channel. Here [1] the creator
describes in an over seven-minute long video the intricacies of
Mario falling asleep.[1] https://www.youtube.com/watch?v=7OtW-
LLZ2OA
zxy_xyz - 5 hours ago
Is the gameplay logic in a different file or did i miss something?
psyc - 5 hours ago
It's all in there. Probably start with PlayerCtrlRoutine.
DonHopkins - 2 hours ago
How I love the sleek smooth razor sharp columns of three letter
6502 opcodes. The right edge of columns of opcodes in other
instruction sets look so rough and jagged like sandpaper in
comparison. That's what I've always hated about x86 code. It looks
rough and torn.
jordigh - 5 hours ago
https://gist.github.com/1wErt3r/4048722#file-smbdis-asm-L601...I
think this is where the real gems start. The biggest contribution
that SMB had was the "physics engine", to retrofit a modern term.
The friction, the jumping, the inertia. If you compare it with the
primitive physics in Donkey Kong or Mario Brothers, you can really
grasp the groundbreaking novelty that was SMB. You can change
direction in mid-air, but not too much. When you run, you skid if
you try to run in the opposite direction. The height of your jumps
is affected by your running speed.It's all of these little details
combined, barely noticed in tandem, which made the game new and
fun.
davidscolgan - 5 hours ago
I once read that the way SMB was able to pull off the physics
engine on such limited hardware was that it used lookup tables
for physics instead of actually calculating velocity. My
assembly-fu is weak but it looks like your link is to the section
that contains all the lookup tables. I think JumpMForceData for
example is a series of offsets for each successive frame after
you hit the jump button.https://gist.github.com/1wErt3r/4048722
#file-smbdis-asm-L611...This line shows the calculation that
makes use of the JumpMForceData.
bluedino - 3 hours ago
You can also fine-tune the feel of a jump when you're directly
editing a handful of values vs trying to find a function that
describes your desired results.
goialoq - 2 hours ago
How so? "Trying to find a function" is editing a handful of
parameters to a polynomial+exponential model -- the same
thing
chii - 2 hours ago
i'd say a lookup table is more easily edited than a
parameter in a function (provided that you are editing a
function with less parameters than the entries in the
lookup table).
Orangeair - 1 hours ago
When you edit one coefficient of a polynomial, you change
its behavior everywhere. When you change one value in a
lookup table, you're only changing the value for one point
in time.
dieterrams - 4 hours ago
Lookup tables were indeed a common technique used by games in
the past.
asveikau - 3 hours ago
And present, too, right? It's not the same reason as it
would have been in the 80s, but today in performance critical
code it is not uncommon to reduce the number of conditionals
for better CPU pipelining, and lookup tables are a very
common tool for this.
vardump - 2 hours ago
> it is not uncommon to reduce the number of conditionals
for better CPU pipelining, and lookup tables are a very
common tool for this.On modern CPUs, data dependency, such
as lookup tables often cause pipeline stalls ? worse
pipelining.L1 cache is at a premium as well, you rarely
want to waste it to access LUTs.You can compute a lot in 12
cycles caused by L2 hit (L1 miss). In theory up to 32 * 12
= 384 floating point operations.
derefr - 3 hours ago
I have a strong feeling that Super Mario Maker always has
the same physics engine going, but just has four different
lookup tables that it switches between depending on the
level theme. Anyone want to partially disassemble it for
comparison?
simooooo - moments ago
Yes I recall a Forza motorsport physics guy saying they
used a simple lookup table for the chart which holds the
curve for the limit if grip on a tyre. Beats the crab out
if calculating it every time.
white-flame - 1 hours ago
I think the biggest difference is that modern games tend to
be written for variable frame rates, stuffing floating
point time deltas through equations.A lookup table meshes
much better with fixed frame rate gameplay, either with one
entry per frame, or quantizing countdown timers of how many
frames to wait to go to the next state.
usernam - 39 minutes ago
Actually, modern (and not so modern) physics engines as
used in games generally use a fixed time delta for each
step, and just iterate faster/slower to keep the
simulation in sync[1]. This is done for many reasons, but
predominantly numerical stability.[1] not the full story
corysama - 3 hours ago
I'll plug the book http://www.game-feel.com/ here because it has
a 28-page chapter devoted to the physics of SMB.
salqadri - 3 hours ago
Tu tu tu turuturu turuturutururur...
tomduncalf - 5 hours ago
This seems like a really impressive effort to make sense of all
this!Would the original game have been written in assembly? And if
so, would the source have looked similar to this?Having never
touched assembly language (aside from learning some very basic
cracking many years ago swapping JE for JNE in the serial check
routine, haha), it seems like a true dark art to me, so I?m really
curious to know!
Kelbit - 5 hours ago
Yes, the original game would have been written in 6502 assembly,
and probably would have looked something like this. The label
names and defines would have been different, since the ones in
this file are the interpretation of the person who did the
disassembly.
bluedino - 4 hours ago
Yes, the original NES games were written in assembler. However,
the source probably didn't look quite like this. I'd guess the
assembler of the time didn't have as many features or things like
long label names.Here's some actual Atari 7800 (a less popular
console from the same generation) code that was found on disks in
a dumpster when some Atari offices closed. They both use a
6052-based CPU but have very different sound/graphics chips. I'd
bet the NES code looked a lot more like this -
https://github.com/OpenSourcedGames/Atari-7800
aquova - 4 hours ago
Yes, all old NES games were written in 6502 assembly (named after
the NES's 6502 processor), and even most games into the Super
Nintendo and Game Boy days were written using assembly
language.The source would've looked very similar to this,
although I can assume the original labels would've been in
Japanese. The difficulty in creating a disassembly like this
isn't converting the machine code back into assembly, which can
be done rather simply, but instead re-adding all the label names,
which are lost when the game is built. It's quite the
undertaking, and the author must know the complete game back to
front.
gp2000 - 2 hours ago
I imagine the original labels would have been in English. The
assembly source code I've seen for Japanese games has variables
and labels in English with Japanese comments in Shift-JIS. I
would guess the choice was forced because the assembler,
linker, debugger or other tools did not support Shift-JIS
properly. Often labels are restricted to 6 bytes which would
be 3 Japanese characters. Perhaps such a limit was also a
factor.
bluedino - 3 hours ago
For another interesting read there's the guy that disassembled
Robotron, and traced the code out by hand across 512 printed
pages of assembly and fixed 2 long-standing bugs.http://www.rob
otron2084guidebook.com/technical/christianging...
Pulcinella - 4 hours ago
Yes I believe on the Genesis most games were written in
assembly as well. Sonic Spinball was written in a ?high level
language? (i.e. C) and so it only runs at 30 FPS instead of 60.
khedoros1 - 4 hours ago
> Would the original game have been written in assembly? And if
so, would the source have looked similar to this?Yes, and
probably somewhat. The programmers were Japanese, so variable
names would almost certainly be different, and the assembler this
code was written for is actually for the CPU in the Super
Famicom/SNES, so although I'm not sure when the assembler was
written, it certainly wasn't around in 1984 when this game was
being written. I think that the notation style is based on
Nintendo's system development documentation, though.The NES would
actually be a good place to look at some assembly, at least to
get a basic idea of how it works. There aren't many operations,
they're pretty easy to understand. There are only a few
registers, and no layers of historic cruft layered on top ofit.
The same (well, very close) CPU was used in a lot of computers
from the same era:
https://en.wikipedia.org/wiki/MOS_Technology_6502#Computers_...
justin_ - 1 hours ago
I remember using this disassembly many years ago when writing a
little NES emulator. Having a reference available for a popular
game is incredibly useful.Here's one of my favorite parts:
https://gist.github.com/1wErt3r/4048722#file-smbdis-asm-L942The
byte here is for the BIT instruction, but why is it just a lonely
byte? Well, the BIT instruction in this case also includes the two
following bytes. When the game processes that instruction, the `ldy
#$04` is swallowed up as part of the BIT instruction, effectively
skipping over it. IIRC this was a pretty common trick used among
6502 programmers. It allows you to jump ahead over the next (2byte)
instruction with just a single byte!