Disassembly of Pokémon Red
bitbucket.org
bitbucket.org
> 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.
Japanese RGB: 512 KB
All other RB: 1 MB
Yellow: 1 MB
GSC: 2 MB
Yet a lot of this Red is empty space.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...
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.
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!
_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. IF _RED
and IF _BLUE
that show up in common.asmThe 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.
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.
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?
Similar concept, though it's done with an attachment instead of linking systems.
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.
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
DecrementPP:
; 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.
.DecrementPP\@
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
ret