Power Quest is a fighter / RPG from the Gameboy Color in which the player can choose one of five robot models (Max, Gong, Speed, Axe, and Lon) and fight AI until s/he gets enough money to progress in the story. It's a massive grind, and instead of using save files, the game uses a password system. The passwords are 12 characters long, and each of the 31 symbols are listed below: ★BCDFGHJKLMNPQRSTVWXYZ0123456789 My first attempts to play with the password system involved taking a few assumptions and trying to work it out by hand. The assumptions were: 1) Each character (in order) was represented by values 0x00 to 0x1F. 2) The bits would be stored adjacent to one another to make one long string (this turned out to be false). Eventually, I realized I couldn't find any consistencies between passwords and decided to throw the game into a debugger. The debugger / emulator I used is called BGB and can be found here: http://bgb.bircd.org/ The manual I used for the GBC can be found here: http://marc.rawer.de/Gameboy/Docs/GBCPUman.pdf Basic overview of the architecture used for the GBC - taken directly from the above manual: You have 8 general purpose registers, each 8 bits wide. They are: A F B C D E H L They can be concatenated as shown above to make 16 bit registers - useful for addresses. You also have a stack pointer (SP) and a program counter (PC), as well as a flags register. When powered on, the PC initializes to $0100. The general address space layout is shown below: Interrupt Enable Register --------------------------- FFFF Internal RAM --------------------------- FF80 Empty but unusable for I/O --------------------------- FF4C I/O ports --------------------------- FF00 Empty but unusable for I/O --------------------------- FEA0 Sprite Attrib Memory (OAM) --------------------------- FE00 Echo of 8kB Internal RAM --------------------------- E000 8kB Internal RAM --------------------------- C000 8kB switchable RAM bank --------------------------- A000 8kB Video RAM --------------------------- 8000-- 16kB switchable ROM bank | --------------------------- 4000 |= 32kB Cartrigbe 16kB ROM bank #0 | --------------------------- 0000-- Note: I have no idea why there is an Echo section for internal RAM. I will spend most of my time here working in the $C000 section (8kB internal RAM) and the $FF80 section (internal RAM) as they end up containing the information I need to work with most. Next, some information on the debugger. It had a lot of the standard stuff that you'd need to function in working with a program. Breakpoints, access breakpoints (these were a godsend), a memory dump, a disassembly, and register status sections. I defintely missed IDA for this - there was a whole lot of stuff to look through and I didn't have much to look at the purpose of subroutines. My best option seemed to be "run it, and hopefully set a breakpoint that's useful." My first attempt at trying to get myself into the password evaluating subroutine happened because I noticed that $FFC4 was getting updated with each input. I figured that by breaking on an A button press at the end of password entry I could find the subroutine that did that - but there was way too much stuff to look through, so I gave up on that. I also drifted out into the memory dump of the video RAM and would have tried to play with stuff when the screen got updated with password characters but then I realized that would be a terrible idea. Eventually, by just scrolling through the later sections of the memory dump, I found a section with values corresponding to the letters (i.e., they were values between 00 and 1F). It was in the Echo RAM, so I went to the corresponding section in regular RAM and set a breakpoint there. The subroutine which decoded a password entry and checked it started at about $4E42, and tracing through it confirmed that it was definitely more complicated than I thought. I noted that the game values from the password were being stored between $FFD4 and $FFDA, so I decided to break on a write to there and see where those values updated from. The adjacent instructions pointed at around $C8C0. Modifying the data in that byte didn't seem to do anything for the time being (it did end up being relevant, though). Playing a bit more with the loading subroutine showed me another address of interest - about $CF10. Around this space was the information that ended up being used to make the password. The bytes which were relevant to the password were: $CF0E $CF0F $CF10 $CF11 $CF12 $CF13 $CF14 $CF15 $CF16 Money Money Money Money Model Story Lang Parts1 Parts2 As it turned out, while $CF0E was used in generating number values for the interface, it was never used in the password. Additionally, $CF14 (language) was determined before the game started, so it was not factored into the password. So the actual set of bytes which were relevant were: $CF0F $CF10 $CF11 $CF12 $CF13 $CF15 $CF16 Money Money Money Model Story Parts1 Parts2 The money bytes ($CF0F-$CF11), were entered at face value. For example - if $CF0F had 0x12, $CF10 had 0x34, and $CF11 had 0x50, then you'd have 123450 credits in game. The model value contained a number from 1 to 5. The corresponding models were: 1: Max 2: Gong 3: Speed 4: Axe 5: Lon The story value was not directly read by the game - it was actually controlled by $C8BF and then updated to $CF13 (found while examining Parts1 and Parts2). It doesn't seem to have much rhyme or reason to it. I took guesses until I found some noteworthy parts: 0x00 - start of game 0x01 - selected your first model 0x3F - beat the first boss 0x41 - spring tournament open 0x5F - spring tournament won 0xA3 - national tournament open 0xC0 - game over Modifying Parts1 and Parts2 directly did not affect in-game status, meaning that information was being read elsewhere. I set an access breakpoint on $CF15 and adjacent instructions told me that the parts were coming from around $C8C1. It turned out that $C8C1 through $C8C7 controlled in-game parts directly. The byte map appeared as follows: $C8C1 $C8C2 $C8C3 $C8C4 $C8C5 $C8C6 $C8C7 Part1 Part2 Part3 CtrAtk Heal Power Special These corresponded to your character's 3 special abilities, a counterattack ability, a "powerup" which healed you over time, another "powerup" which filled your special attack meter over time, and your special attack part. These translated back into the Parts1 and Parts2 bytes in $CF15 and $CF16 as follows: $CF15 X Spc 2L4 2L2 2L1 1L4 1L2 1L1 $CF16 Pwr Heal CT4 CT2 CT1 3L4 3L2 3L1 There were four levels to each of the three main parts and the counterattack. 1L1 bit => Part 1 (Level 1) 1L2 bit => Part 1 (Level 2) 1L1 and 1L2 bits => Part 1 (Level 3) 1L4 bit => Part 1 (Level 4) ...and so on for parts 2, 3, and counterattack. While playing with the values in $C8C1-$C8C7, I found that setting the bits for L1, L2, and L4 together for a move would give you a super version of that move - doing extra damage and in some cases making the game behave erratically. But using generated passwords with all three bits set would allow you to keep all the parts so I decided the password generator should contain that option. I also later discovered that there were actually two special parts for two separate special attacks (I had previously thought there was one special part which allowed you to use both special attacks) which went into the X bit above. With $CF0F through $CF16 properly understood, I decided to take a look at the password encoding by setting a breakpoint in the range of data at $FFD4 - as it's where the stuff originally gets decoded to. This is where I learned that there was actually another nibble of information necessary - the Announcer. Every time you fight, a counter will increment from 0x00 to 0x0F, at which point you can fight a character called the Announcer. He's really hard to beat, but if you win he'll give you 1000 credits. This counter was in $C8C0. With all that known, I went back to the encoding algorithm. Here's how it worked: Put the first byte of money in $FFD4. Put the second byte of money in $FFD5. Put the third byte of money in $FFD6. Put the announcer counter in the lower nibble of $FFD6 (and you now lose the ones place for money storage). Put the model in $FFD7. Put the story flag in $FFD8. Put the parts bytes in $FFD9 and $FFDA. Add the top and bottom nibbles of $FFD4 through $FFDA. Shift the result left 4 times and put the final value in $FFDB (so $FFDB will contain between 0 and F in the top nibble and 0 in the bottom nibble). Load the value in $FFDB, copy the top nibble into the bottom nibble (so a register now has a value of 0xXX where $FFDB has 0xX0), and XOR everything from $FFD4 to $FFDA with this value. From here on out, all references to "B" are a reference to register B. Load $FFD4, shift right 3 times, store in $C248 Load $FFD4, shift left 2 times, AND 1C, store in B Load $FFD5, swap, shift right 2 times, AND 03, OR B, store in $C249 Load $FFD5, shift right, AND 1F, store in $C24A Load $FFD5, swap, AND 10, store in B Load $FFD6, swap, AND 0F, OR B, store in $C24B Load $FFD6, shift left, AND 1E, store in B Load $FFD7, swap, shift right 3 times, AND 01, OR B, store $C24C Load $FFD7, shift right 2 times, AND 1F, store in $C24D Load $FFD7, shift left 3 times, AND 18, store in B Load $FFD8, swap, shift right, AND 07, OR B, store in $C24E Load $FFD8, AND 1F, store in $C24F Load $FFD9, shift right 3 times, store in $C250 Load $FFD9, shift left 2 times, AND 1C, store in B Load $FFDA, swap, shift right 2 times, AND 03, OR B, store in $C251 Load $FFDA, shift right, AND 1F, store in $C252 Load $FFDA, swap, AND 10, store in B Load $FFDB, swap, and 0F, OR B, store in $C253 $C248 through $C253 now have bytes between 0x00 and 0x1F which correspond to password symbols. With all this information, I made the password generator. You can check the JavaScript implementation by viewing the source and going to encoder.js.