Hacker News new | past | comments | ask | show | jobs | submit login
Disassembly of Pokémon Red (bitbucket.org)
158 points by kanzure on Jan 16, 2012 | hide | past | web | favorite | 32 comments

This is an incredible decompilation for another reason: graphical hacks. The Pokemon in Red and Blue were notoriously compressed, making it insanely difficult to add new Pokemon versus later games like Gold and Silver. These games were barely touched by the ROM hacking scene for that reason. From https://acmlm.kafuka.org:81/archive3/thread.php?pid=74848...:

> Pokemon Red and Blue was notorious for having a graphics compression format that nobody could crack.

>They used a very uniqie and strange compression that actually draws the graphics in different

> layers, based on color. If you see the Z80 assembly from the actual routines used for decompressing

> graphics you will see why nobody has ever figured it out.

Hopefully this will lead to some killer Gameboy hacks in the future.

What were the ROM sizes on the Red/Blue cartridge vs. the Gold/Silver cartridge?

Sure, take a look:

    Japanese RGB:  512 KB
    All other RB:  1 MB
    Yellow:        1 MB
    GSC:           2 MB
Yet a lot of this Red is empty space.

Not just a disassembly - an annotated, compilable version of one of the most iconic games of my generation.

This also facilitates conversion of the maps and scripts to alternative engines. I wonder how much more performant a native port would be than an emulator? Or how Mt Moon would look with HDR and Bloom effects?

I once recreated Pallet Town with the original bitmaps for the GoldSrc engine. Pokemon is one of those magical franchises that's so encouraging to engage with every time there's a new handheld game or news; i can't remember how many times i wrote battle simulators as a kid...

I fondly remember spending 2 weeks completely disassembling Sonic the Hedgehog once, I was always curious how games worked. Disassembling them turned into a little hobby of mine -- you always find leftover graphics, dead code and sometimes even whole unused levels when you poke around, it's lots of fun.

If you're interested, up-to-date versions of Sonic the Hedgehog disassemblies can be found here: http://info.sonicretro.org/Disassemblies

People have also disassembled other games like Super Mario Bros., etc.

If you're still interested in game archaeology, I would highly recommend you visit The Cutting Room Floor ( http://tcrf.net/ ), a wiki dedicated to uncovering unused/development-related content in early video games. Sometimes authors even put long, rambling messages against their coworkers into games (see the page on Erika to Satoru no Yume Bouken).

Yeah, I know the guy who runs the wiki, he's a really cool guy and has been doing this for a while too. The whole wiki is fascinating if you're into that sort of thing and have some spare time.

I am a huge Sonic the Hedgehog 2 fan and I remember being on SimonWai's site back in the day (~10 years ago?) and Sonic Retro.

Anyways, it's a small world. I definitely recognized your nickname from the Sonic forum and I think you helped unearthed a prototype(s). I can't tell you how much I appreciated your work!

Small world indeed, hi!

  _RED EQU 0  
  _BLUE EQU 1  
And with that we now have 2 games to sell, increasing our profits. With this they now have people talking, collaborating and trading. These two lines have caused many arguments of superiority over the years. A simplistic switch to me seems quite impressive and powerful.

While I get what you mean this overlooks all the instances of

    IF _RED

    IF _BLUE
that show up in common.asm

The switches themselves are simple but there are a lot of IFs in the main source file.

Running "%s/IF _RED//gn" and "%s/IF _BLUE//gn" in vim on common.asm gives 26 and 25 matches respectively. "IF _GREEN" shows up twice.

Right, there are a number of differences between Red/Blue. The most well known differences are on the title screen and which Pokémon you can find. But there are other differences that need to be taken into account, like some palettes and the game corner prizes.

Someone's working on those differences here: http://romendo.net/stag019/pokedex/rbdiff/

Their decision to make two complementary games is really fascinating, especially from a business perspective.

> Their decision to make two complementary games is really fascinating, especially from a business perspective.

Indeed. It seemed to be really successful especially given how small a development effort it apparently was. But why did no one but the Pokemon games seem to do it subsequently?

Oracle of Ages/Oracle of Seasons were two complementary Zelda games for game boy color. You can't fully beat the game without both.


Similar concept, though it's done with an attachment instead of linking systems.

Correct me if I'm wrong, but I think he's saying that you can change the Red version of the game into the Blue version by just changing the two constants.

Not yet. When stag019 is done incorporating his red/blue differences, the blue make target will compile correctly. Then the blue ROM md5 will be added to the README. But until then, the blue make target is definitely not working.

I just mean that wollw's comment doesn't make sense. An assemble-time IF checking for _RED or _BLUE just means that it's easier to switch between Red and Blue.

The original comment seemed to trivialize the differences between the games. If you wanted to you could say something similar about any conditional branch but doing so completely ignores the differences between the branches. Assemble time checking for _RED and _BLUE makes it easy to switch between versions sure, but the it doesn't say anything about the actual differences (large or small) between the versions. A simple flag like that can be used to build vastly different programs. Also, given that those flags are macros to begin with tells me we don't even know if that was how the originals were differentiated; you can't really disassemble a macro.

edit: I don't mean to be an ass about this. There's certainly a sort of poetic quality to the use of a flag like that to switch between versions but I just thought it was worth also pointing out the work it took to do so.

Yeah, but a simple script shows that version specific code is less than 10% (combined), at least in common.asm.

Hardly anyone bought both copies of the game. All this primarily did was encourage an incredible thriving social 'network' of players.

I wonder if the original system was written in ASM or a higher-level language (a variant of C, maybe?). Anyone do any GBC development care to comment?

Definitely ASM for GB/GBC. Not much C until GBA.

Z80 ASM is both quite limited (no multiply or division) and very straightforward. That's how I remember it, at least :) For fond memories, dig a copy of Rodney Zak's "Programming the Z80".

> Rodney Zak's "Programming the Z80"

The first and still the best programming book I ever read. It taught me architecture, instruction fetching and decoding, how the clock comes into it, as well as the usual assembly programming. I loved that book. I still regret throwing it out, 20 years later.

Good news: you can download a PDF. http://www.freetechbooks.com/programming-the-z80-t784.html

I don't know if it's because I'm a stupid old fart, but it seems to me that the explanation this book gives of microprocessor architecture, busses, etc are still unbeatable because Z80 is so simple. It's probably still a valuable introduction to computing, if only for the first few chapters on binary, computation, etc.

Well, I just assembled it using the ROM it requires (just search for it online) and in the GEST emulator it works. I'm wondering how it uses the ROM; I suppose it uses it for some base stuff like music, but I wonder for what else it uses it.

The idea is to move away from requiring the ROM. There are portions of the ROM that are still directly included by rgbasm. Music is one task, but also other obvious things like the main game loop, items, interrupts, lots of battle code, etc.

I can't wait for a complete reworking of the game, and this is great for emulation (and for the fun), but surely someone somewhere has long ago created an open framework allowing for different versions to be made, akin to Mugen?

Well, this sure brings back some memories... So much for my hopes of being productive this Wednesday.

Same here, trying to get some things done tonight, but how can you say 'no' to something like this.

For fun, I attempted to analyze a function with a friend who's a total Pokemon geek and came up with the following, which I figure I'll post here (no guarantee on accuracy):

    ; after using a move, decrement pp in battle and (if not transformed?) in party
        ld a,[de]                   ; load some variable?
        cp a,STRUGGLE               ; Check to see if the move we used was "struggle".
        ret z                       ; If the pokemon is using "struggle", there's nothing to do, so return,
                                    ; since we don't decrement PP for "struggle".
        ld hl,$D062
        ld a,[hli]                  ; load the D062 Pokemon status flags and increment hl to load the
                                    ; D063 status flags later.
        and a,7                     ; check to see if bits 0, 1, or 2 are set.
        ret nz                      ; If any of these statuses are true, don't decrement PP.
        bit 6,[hl]                  ; check bit 6 of the D063 status flags too.
        ret nz                      ; And return if it's set.
                                    ; bit 2 of D062: multiple-hit moves, like Wrap?
                                    ; bit 1 of D062: Thrashing about, I think?
                                    ; bit 0 of D062: paralyzed?
                                    ; bit 6 of D063: ?
        ld hl,$D02D                 ; load the address of the first move of the current pokemon
        call .DecrementPP\@         ; call the function (below) to actually decrement the PP

        ld a,[$D064]                ; load Pokemon status bits?
        bit 3,a                     ; Is the pokemon transformed?
        ret nz                      ; If it is, return.  Pokemon Red stores the "current pokemon's" PP
                                    ; separately from the "Pokemon in your party's" PP.  This is
                                    ; duplication -- in all cases *other* than Pokemon with Transform.
                                    ; Normally, this means we have to go on and make the same     
                                    ; modification to the "party's pokemon" PP that we made to the
                                    ; "current pokemon's" PP.  But, if we're dealing with a Transformed
                                    ; Pokemon, it has separate PP for the move set that it copied from
                                    ; its opponent, which is *not* the same as its real PP as part of your
                                    ; party.  So we return, and don't do that part.

        ld hl,$D188                 ; load the address of the first move of the first pokemon in the party
        ld a,[$CC2F]                ; which pokemon in party is active
        ld bc,$2C                   ; $2C is the size of one Pokemon's data structure, I assume?
        call AddNTimes              ; calculate the address of the mon to modify
                                    ; fall through into DecrementPP\@, to avoid calling it again.
        ld a,[$CC2E]                ; which move (0, 1, 2, 3) did we use?
        ld c,a
        ld b,0
        add hl,bc                   ; calculate the address in memory of the PP we need to decrement, 
                                    ; based on the move chosen.
        dec [hl]                    ; Decrement PP

Applications are open for YC Winter 2020

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