I'm afraid I have to inform you that you've missed the best game ever produced for the Nintendo Entertainment System. I've been waiting for a sequel to this game for 17 years now but Hudson Soft let me down. Seems like someone else has to produce Faxanadu II and I've decided that this someone is me. Patching an original Faxanadu ROM (the US version) seems to be the way to go.
As a consequence I've strayed away from the good old x86 CPUs in the last days and focused on 6502 assembler which is used by the NES. Now that I've finished my first steps with this system I'm confident that I can program a level editor for Faxanadu which is probably the most important step for modding the game. My confidence is based on a
written by a guy named Vagla I've found online which already contains an enormous amount of information about the Faxanadu ROM.
Vagla's document is not complete though and that's why I still have to pick up 6502 assembler if I want to reverse engineer the missing information from the ROM file myself. My first attempt was to reverse engineer a part of the game which I assumed to be both easy to locate and easy to reverse engineer because it does not depend on the underlying CPU: The password generation. In Faxanadu you can get passwords (so called Mantras) at certain locations that allow you to continue a game later.
The debugger I've used to debug the ROM file is
FCE Ultra eXtended-Debugger 1.0a. It has this awesome feature that you can switch into single-step mode at any point during debugging even if you have no breakpoints set. As the NES is a single-process/single-thread CPU that works pretty well. With this knowledge locating the part of the ROM where the password is entered becomes trivial: Open the password screen and switch the debugger into single step mode. That's it.
Technically speaking that's not 100% correct though. Let me give a brief explanation of a technical aspect of the NES first. The RAM of the NES is so small (64 KB) that only two 16KB chunks (so called PRG banks) of code can be in memory at any given time (one at offset 0x8000 and the other one at 0xC000). Games with more than two PRG banks need to switch banks during runtime. This bank switching is done through a
memory mapper which is a piece of hardware that resides on the NES cartridge. There are lots and lots of different memory mappers used by different games, Faxanadu uses one called
MMC1 (this can be read from the
header of the ROM file). I've read that MMC1 games usually only switch the PRG bank at offset 0x8000, the one at 0xC000 contains code that's needed basically everywhere and stays in memory all the time. Faxanadu seems to work like that too.
When thinking of the two banks I tend to call the PRG bank at 0xC000 the Kernel of the ROM because it contains all the important stuff. I'm going to use this name here too even though it's of course technically incorrect.
This brings us back to the part where you enter the password and switch into single-step mode. You won't get to the part where the password is handled, you'll get to the part that handles user input which resides in the Kernel. There's a small loop that goes on until a button was pressed (0xCA29 - 0xCA2B) and if you check the stack you can see the return address (0x9142). That's the part where the password is handled. Observing the behaviour of the program after a fake password is entered it's quickly obvious that the relevant code is just a few instructions down at 0x914F - 0x915E.
CODE:
<br />$914f-> ad 66 06: LDA $0666 ; $0666 = Length of Mantra
<br />$9152-> f0 21: BEQ $9175 ; Branch if no mantra was entered
<br />$9154-> 20 50 98: JSR $9850 ; Check checksum of mantra
<br />$9157-> b0 06: BCS $915f ; Branch if wrong checksum
<br />$9159-> 20 e9 95: JSR $95e9 ; Check data of mantra
<br />$915c-> b0 01: BCS $915f ; Branch if wrong data
<br />$915e-> 60: RTS ; If this point is reached
<br /> ; a valid mantra was entered
<br />
The disassembly was generated using Scott Konash's
NES diassembler.
I had originally planned to discuss the two subroutines that check checksum and data of the mantra today but I think this post is already long enough. I'll save that for my next update.
One last note: If you've been careful you've probably noticed that I've talked about offset 0x914F even though different code can be found at that offset depending on which PRG bank is present in memory at that time. The part that handles the password is located in PRG bank 12 (the first PRG bank is PRG bank 0). In the original ROM file you can find that PRG bank at offset 0x30010 (the header size of a NES rom is 0x10 bytes), offset 0x914F of that PRG bank can therefore be found at offset 0x3115F in the file.
The Kernel PRG bank is always the last one in a file. Faxanadu has 16 PRG banks (this can be read from the file header of the ROM file), that makes the one loaded at 0xC000 the one with the number 15. It can be found at offset 0x3C010 in the ROM file.
As I had promised in my last update here's a complete discussion of the mantra checking code of the NES game Faxanadu. Let's recall what I had already posted last time, the code where the mantra is checked for validity. If you don't know the 6502 ass
Tracked: Mar 27, 16:04