Hacker News new | past | comments | ask | show | jobs | submit login
Metroid Source Code Expanded (romhacking.net)
182 points by rograndom on Oct 14, 2011 | hide | past | favorite | 59 comments



When I worked at Sega in the console era, I found out that every console game was open to inspection by other developers in this way. Because they were all in assembly, if you were ever curious about how a character moved or how a graphics trick was done, well, you would just find out.

After all, our development consoles (which the PC debugger connected to) worked just as well on a cartridge from the store as on the code we uploaded to it. So if you were impressed by an effect in a game like Ranger-X, you just plugged it in and explored it in the debugger for a while. You'd end up with a new technique and (quite possibly) a snippet of code you could try out on your project. Happened all the time.

Now, I don't think anyone really undertook an effort such as this to lovingly decompile a game with comments on this level, but there were decompilers too. I was always suspicious that our studio's highly sophisticated platformer engine was based on lots of, uh, best practices. If you know what I mean. But that wasn't a big deal.

It's interesting because when I later heard about the tech behind the Halo engine, I realized I'd never seen their architecture before — because things had moved on and gentlemen of game development didn't decompile each other's games. They licensed their engines instead. If this had been the cartridge age, lots of people would have totally lifted their approach.

By the way, the talk I heard, a detailed overview of how the Halo 2 engine works, is available at the page below. Yeah, it's from seven years ago but it was a ten-year-old engine already. Good code design lasts. If you like game guts, this page is a little-known treasure.

http://www.game-tech.com/Talks/Talks.htm


This is great stuff. When I was working on a platformer I'd read a lot of the code for these classic games (Mario, Metroid, Sonic, Megaman, etc.) to see how they did platforming and what the character physics tuning numbers looked like. I've been meaning to do a series of articles that break down games, focusing mostly on gameplay code, enemy behavior and physics. The only comprehensive article I've found like this is the Pacman dossier (http://home.comcast.net/~jpittman2/pacman/pacmandossier.html). Everything else is random bits and pieces that can be pieced together, but would be nice to have in one place.


Sonic Retro has a writeup of the physics behind Sonic 2. Check it out, it's exactly what you're looking for and would be a good template to follow for other games.

http://info.sonicretro.org/Sonic_Physics_Guide


Yeah I've seen that and it's excellent. My idea was basically to expand on that sort of stuff.


I'd love to read such an article. Platformer physics can be very fiddly and there are a lot of small variations that have a significant impact on "feel".


Please please do this. It would be great. I'd love to read a comprehensive breakdown of classic console platformer code.


If you find this interesting, I'd highly recommend "Racing the Beam" by Montfort and Bogost, which talks about Atari development from both a technical and a cultural perspective. It really goes into detail about some of the landmark games that introduced new techniques to push the platform to the edges of its capabilities (e.g. the scrolling and color-shifting "neutral zone" in Yar's Revenge was actually created by repurposing the game's machine code as opposed to being algorithmically generated)


The first thing to know about the crazy limitations of Atari 2600 development is this number: 128.

That's how much RAM there was. That's 128 bytes. The entire in-memory program state was one eighth of a kilobyte. Then imagine everything else was limited like this. It's hard to understand how challenging it was to get a coherent game out of this thing.

Someone who was really inspired by "Racing the Beam" to try 2600 programming recently was Xbox daddy Ed Fries. Here's him talking about what he made:

http://www.atariage.com/forums/topic/166916-halo-for-the-260...

Yes, it's a loving rendition of Halo on the 2600 platform! You can even play it now online:

http://www.codemystics.com/halo2600/


For those who don't want to download: it's 1.7 MiB of assembler instructions with comments. Looking at this you start to understand how hard game development was in 80's (this game is from 1986).


It has always amazed me that so many quality games were made with assembly alone, both on NES and SNES. I built small SNES games in school, and man that's a lot of work.

Gamedev these days is so easy in comparison.


It would be hard to make Crysis in 8-bit assembly, but it's not especially hard to make an NES game in 8-bit assembly. In many ways, it is much easier than modern game development:

- There is no hardware abstraction layer. There is one hardware target, you know exactly how it works, and you can use/abuse it any way you like. And all the hardware is designed together for the sole purpose of making games.

- There is no I/O. All your code and data is just mapped into memory from a ROM pack. You have to swap memory banks in and out, but you can layout the banks explicitly. You typically do one level per bank and just swap banks to change levels.

- There is no memory management. RAM is all yours. You just layout your dynamic data explicitly, or let the assembler do it, or some combination of the two.

- There are no data types or undefined language behavior. Just n-bit registers and instructions. Need to use 12.4 fixed point math? Or pack a flag in the high bit of a pointer? No problem, just write some assembler macros.

Of course, in exchange for control, you have to give up some power. Maximum 16k of code, can only write to video memory between rescans, no divide instruction.. that kind of thing. But better the devil you know. It's a lot more fun solving "how can I do this with what I have?" than "what the hell is going on?"


Counters:

-You think you know how it works. But lots of little hardware quirks will still bite you in the ass.

-This means that all your data has to fit in your code space, so you either trim code or you trim data.

-Generally you wouldn't do dynamic data at all, ever, so instead you were stuck constantly balancing and tweaking constant arrays of data and balancing them against everything else in the world. Do I allow 3 entries for explosion effects? Or 5? Am I willing to have one less enemy on screen for those extra effects?

-There's also often very few registers and an extremely limited stack.

I mean, I'm not saying you are wrong, and from certain angles sure it's easier to write in 8 bit assembler vs modern day high level languages. But there's also things to consider that happen above the language. What happens when there's a bug in some code and you have to hand it to a programmer who isn't familiar with that code? What happens when two subroutines are too far away from each other to jump? What happens when you get graphic corruption bugs and don't have the modern conveniences of data breakpoints and other tools?


Interesting factoid: Roller Coaster Tycoon was written entirely in x86 assembly (released in 1999) http://www.chrissawyergames.com/faq3.htm


I'd have to respectfully disagree. I've written 100% asm games on the Amiga all the way up to PS2 games in C++ and the amiga game was a lot easier to write and debug.

Modern games hardware is SO much more complicated, modern games are SO much more complicated.

Where I would agree is that writing game on the Amiga in C++ would be easier but that's not game dev these days.


Debugging I'm with you, but the actual time to create simple parts of the game? Going to have to disagree with your disagreement. It's like two lines of code nowadays to move a sprite around on screen and draw it, because you don't have to write your blit function yourself.


You didn't have to write blit functions yourself on the NES either, it had hardware (PPU) that would handle blitting of sprites for you. There were a lot of restrictions that you'd have to work around, but actually displaying something on screen didn't take that much code.

This also indulges the fallacy that the hard part of game development is writing low level graphics routines. That can be difficult to learn but once you know it its relatively straight forward. People don't judge your game on the quality of your sprite drawing functions (unless they're extremely buggy :)).


Trust me, I've been doing this a long time, I'm not pushing out fallacies. But you had to do a hell of a lot more management in NES/SNES/Asm than a simple ->Draw() call.


Gamedev is simpler today than it was by then, but games (we are talking about AAA titles, as Metroid was at the time) have escalated in complexity by several orders of magnitudes.

Today is simply impossible for a single person/small team to create a rival to Call of Duty 4 or Fallout 3, while back then it was relatively simple for someone with the skills and talent to emerge.


Not as rivals to those games, perhaps. But Minecraft and Angry Birds show that it's easier than ever for a single person/small team to create and sell an extremely successful game.


> But Minecraft and Angry Birds show that it's easier than ever for a single person/small team to create and sell an extremely successful game.

More so, they prove (again) that the technology arms race in today's video games is utterly retarded. It's also the reason many indie games tend to be so good and refreshing - they can't make a hitech ultra-HD game, so they focus on what really matters: gameplay and design.


"Utterly retarded" is far too strong a statement. The indie games of tomorrow may be built on "hitech ultra-HD" engines. The exploration of the space of games is advancing along many dimensions (including technology) and I think technology improvements will be needed for many of the great games to come.


The technology race in video games is as utterly retarded as it is in the movie industry. There's as much room for Clerks and the Blair Witch Project as there is for Toy Story and Avatar.


Easier than ever, when you stand on the shoulders of giants:

http://m.techcrunch.com/2011/02/28/creator-of-angry-birds-ph...


I'd just like to point out that Minecraft's code is absolutely horrible from an algorithmic standpoint. On performance/speed and code quality metrics, Minecraft is a statistical fluke.


Isn't there a lot of awful video game code around? Optimization is usually delayed until the end of a project, and crunch time is a norm at most AAA game developers.


Yet by any other conceivable metric it is a huge success.

I love good code & elegant design, but it doesen't beat having a successful product out there.

Remember, shipping is a feature ;)


60FPS is also a feature. Not crashing when sent invalid input on the wire is a feature. Being able to support more than 100 concurrent connections without requiring a monstrous top-of-the-line server is a feature. These are all missing from Minecraft.

Remember, usability is a feature. >:3


Many arcade games were done entirely in assembly.

Everything that came out of Williams/Midway for example (From Defender all the way to Mortal Kombat, NBA Jam, Crusin', basically everything not on PC-based hardware) were all completely done in assembly. Wrap your noggin around that one.


RollerCoaster Tycoon (released in 1999) is well known for being written almost entirely in x86 assembly.

http://www.chrissawyergames.com/faq3.htm


Yeah, but generally arcade games tend to be a lot simpler than some of the more complex offerings on SNES, say. The systems were more powerful, but the gameplay itself tended to be simpler, owing as much to the need to play for quarter increments as anything. Less state to keep track of, generally, at the very least.


Remember that 20 years ago, before the era of superpowerful consoles, arcade titles usually pushed the state of the art in game mechanics and graphics. Home consoles could benefit from longer gameplay, but that usually came from larger game maps and way too many boss screens.

And...weren't some of the most popular SNES games ports of popular arcade titles?


Sure. But graphics and basic game mechanics are actually really easy to code in assembly -- it's crazy state and decisions that get way more difficult. I'd bet coding up a triangle rasterizer would be significantly easier than coding up a cutscene.


And...weren't some of the most popular SNES games ports of popular arcade titles?

Yes! Street Fighter II (and sequels). The Mortal Kombat series. These were HUGE when they arrived on the SNES. I still remember how amazing it was when SF2 came out.


What were the development cycles for those later arcade games? How long did it take to build Mortal Kombat and how many people did they have working on it?

I should've looked at Wikipedia first, it answered part of my question.

"The first Mortal Kombat game was 4 guys, literally, one programmer, myself (Boon), two graphics guys (Tobias and Vogel), and a sound guy (Forden) was the entire team, literally"


In those days it took about a year, maybe a year and a half.

Many teams would carry a core "operating system" (really a library of system routines/process scheduler/IO/audits) from game to game and build off of that. That left more time to write the game mechanics and choreography.


I also didn't know they did motion capture for Mortal Kombat. That's even more impressive considering they only had a team of 4.


Was it motion capture (driving a 3D model from sensors) or was it video capture (making sprites from videos). I believe it was the latter. MK's photographic realism really made it stand out in the arcade.


You're right. Here's the relevant paragraph.

The team switched from digitized actors to motion capture technology (the quote is incorrectly referring to Midway as Acclaim): "To make the characters in video games more realistic, actors are being recruited to serve as models. Acclaim, the video-game company that made Mortal Kombat, has created a special 'motion capture studio' for this purpose. A martial-arts expert with as many as 100 electronic sensors taped to his body sends precise readings to a camera as he goes through his moves—running, jumping, kicking, punching. The action is captured, digitized and synthesized into a 'naked' wire-frame model stored in a computer. Those models can then be 'dressed' with clothing, facial expressions and other characteristics by means of a computer technique called texture mapping.


MK1-3 were 2D characters, all done with video capture. MK4 was a 3D camera-based game and was done with motion capture.

There were other 2D fighting games around that time that used video capture (remember Atari Pit Fighter?) but MK avoided the sprite scaling and kept it flat.


I'm pretty sure the original was done by digitising video frames & tidying them up. There probably weren't many people doing motion capture as we know it today in 1992.


Was this actually written in assembly by its original developers? I'm not familiar with the history--I get the sense the code explained here was originally disassembled from a ROM, and then systematically analyzed to gain an understanding of how it worked.[0] If so, couldn't it have been written in C or somesuch?

Not that that wouldn't make this presentation here an impressive feat.

[0] http://www.metroid-database.com/m1/sourcecode.php


The N64 was the first nintendo platform to support a C compiler out of the box.

I suppose it's possible that some crazy developer wrote their own C compiler back in the day, but if that ever happened I didn't hear about it. And I was trained by people who worked for Nintendo.


The PS1 was released before the N64 and supported C compilation. In fact, in the early days Sony didn't want people to use much ASM because they were worried about backwards compatibility on future systems. The PS1 port of Doom suffered from a lack of assembly optimization.


Gran Turismo and Metal Gear Solid were written in C. Ken Kutaragi used them as examples of what could be done with efficient programming techniques and good use of Sony's performance profiling tools. (citation needed: one of my old gaming mags that's probably been recycled three times over by now)

It's rather interesting how Sony went from starting with a system that was considered easy to develop for, to having the most complex product on the market--twice in a row!


From the looks of the comments, as well as the frequent references to "written, but unread" memory, this appears to be a dump of the US release. The original JP release was for the Famicom disk system, which had more sophisticated music playback, as well as a three save slot support (similar to Legend of Zelda) instead of passwords. These bits of vestigial code/memory likely still exist in "dummied out" form in this US based source.

IMO, Legend of Zelda source would probably look similar. But by that time, Nintendo of America started support for battery based save states, so someone more experienced in NES hardware might want to compare and contrast the two codes bases to see how much Disk System code was salvageable for battery based backup purposes.


This is awesome. I remember playing metroid at a friend's house who had a NES, wondering "Why do all rooms look similar?!". We spent hours drawing maps by hand so we wouldn't get lost through levels.

The map is super clever. The whole game map is 1Kb of memory (MetroidTilePage.txt:line 4658). A 2d array and each byte has the ID of a room sprite.

So that's why all rooms were the same :)


That is a great example of a genius/cheeky hack to fit a big world into tiny memory.

Thanks for that, made me smile & shake my head at the same time :)


If you like this, then you may also want to check out http://nesdev.com/. NES programming is alive and well, I assure you.


Man, this is an awesome contribution. ASCII art in the comments and everything.

You clearly put a lot of work into this, dude. I gotta shake your hand, let me see, uh... Dirty McDingus?

You know what, on second thought I'll just post a comment on HN. But, uh, thanks. We're cool, though. I'll just be over here.


Reading through source code for old games is always fascinating. Any developer worth his salt should take the time to explore this area. The tricks that the engine programmers used to squeeze every last ounce out of the hardware are truly inspiring.

I can appreciate how much effort has gone into this project. For years, I've been working on disassembling and commenting the Sonic 2 Master System engine (https://www.sonicretro.org/asm_svn/Sonic%202%20SMS%20Disasse...) and it's still only about 80% complete.


Even if you're not an assembler expert, there are a lot of detailed comments that explain how things are done. Well worth a read if you're interested in the real guts of classic games.


I'm guessing games built upon previous ones? I'm wondering to what extent they borrowed from previous prototypes/work. Also, I wonder what the total dev time for the game was.


Most definitely. There's another really good doc on Super Mario World that compares a lot of similar chunks of code to their counterparts in the Super Mario Bros. 3 code, which SMW was based off of.


Do you have a link to this? Sounds really interesting!


http://www.smwcentral.net/?p=list&type=documents

The doc in question is All.log++. There's a lot of really cool information spread across that site, though.


I looked for JUSTIN BAILEY, couldn't find it - but I discovered NARPASSWORD!

ValidatePassword: L8DDE: LDA NARPASSWORD ; L8DE1: BNE ++ ;If invincible Samus already active, branch. L8DE3: LDY #$0F ; L8DE5:* LDA PasswordChar00,Y ; L8DE8: CMP NARPASSWORDTbl,Y ;If NARPASSWORD was entered at the--> L8DEB: BNE + ;password screen, activate invincible--> L8DED: DEY ;Samus, else continue to process password.


JUSTIN BAILEY is not hardcoded; it is an emergent property of the password system: http://www.metroid-database.com/faq_metroid.php#metfaq35


Can anyone find the part that controls whether a missile door is red, orange, or purple?


wonder how much time it took to build this




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: