NOTE: Some of the things in the CODE Box will be repeated a few times, because these were parts of a few seperate documents I made. So don't bitch at me about it. --- If you open a Sonic ROM (it can be any Sonic game), you will see a lot of "00000200" in the ROM headers. Those are exceptions. If something occurs that isn't supposed to happen, one of these exceptions are called. It can be an illegal instruction, an address error, or a 1111 emulation error. The exceptions are like sub routines, but they are interrupting whatever was running when the exception occured, so you need to kill the exceptions with a "RTE" instead of a "RTS" RTE stands for ReTurn from Exception. Code (Text): Open a Sonic 1 ROM: RTE (ReTurn from Exception) = ?4E 73 Go to offset 0 (the beginning of the ROM) You will find these values: 00 FF FE 00 At offset 4 (the starting address in a genesis ROM), you will find the values: 00 00 02 06 This is the first exception pointer. It's probably that exception that shows the "ILLEGAL INSTRUCTION" text when something goes wrong. The exception starts at offset 206. If you want to kill that exception code, you put a RTE at that offset. There are a lot of these exceptions. ?You can see how it continues with a new exception pointer at offset 8: 00 00 03 D6 The exceptions end at offset FF. The last exception you'll find points at the default exception handler at offset 200 (You can see this at offset FC : 00 00 02 00) Now there are two important exceptions in the header. The HBlank and the VBlank interrupt. HBLANK = HORIZONTAL BLANK VBLANK = VERTICAL BLANK The HBlank occurs every time one scanline has been drawn on the screen. The VBlank occurs when all the scanlines have been drawn. You will find the pointer to the HBlank interrupt at offset 70. The value will be: 00 00 11 26 So every scanline, the code which is currently executed will be interrupted, and a call to the HBlank will occur automatically. So if you want to kill the water effect, you can just put a RTE "4E 73" at offset 1126. You will find the VBlank interrupt pointer at offset 78. The values will be: 00 00 0B 10 The VBlank copies every sprite, palette to the screen during the gameplay. It also plays the music. If you decide to RTE the VBlank, put a RTE at offset B10... BUT nothing will be shown on the screen. It will just be black. ABOUT BLANK PERIOD: The blank period is when the Electron beam has drawn the screen and needs to retrace. It's a small period where you can copy data and move sprites without affecting the display. A Vertical Blank interrupt is called when a whole screen has been drawn and the Electron beam has to retrace all the way back to its starting point. You can make the game to run in 60 Hz by waiting for a VBlank to occur. The Horizontal Blank occurs when one scan line has been drawn and the beam needs go back to the start of the next scan line. You can see this as when you press enter to make a line feed when you write a document, the cursor needs to go down and back so that you can start to write on the next line. The HBlank is used for effects like switching the pallete at a special scan line to make a water surface in the Sonic games, or to scroll one pixel during every HBlank to make the background look like it's been drawn in 3D. The HBlank and VBlank are interrupts. They will interrupt whatever code that was executed, and therefore they must be exited with a RTE so that the game can continue to be executed from where it was interrupted. So now you know: These two exceptions called the Horizontal and Vertical Blank are critical for the game. Without them, nothing will be drawn on the screen. And you need to use the RTE instruction to kill the exception handlers. The RTE will stop the exception, and go back to where the code was interrupted before the exception was called. To call an exception...the CHK and TRAPV commands force an exception I hope this helps anyone. Oh, and if something in here is wrong, tell me immediatly. Thanks. EDIT 1: Fixed grammatical errors pointed out by Icy Guy. Fixed part about if calling an exception is possible as pointed out by Quick Man. Added part about how offset 4 if the starting address in a genesis ROM, as pointed out by Gerbil.
That's the stack pointer loaded to address register 7. Just so you know. Actually it's exactly the opposite; that's normal gameplay. The CHK and TRAPV commands force an exception ("CHK COMMAND" and "TRAPV COMMAND" respectively).
Wow, that's very informative! You should make a site with all your finds, it would help a lot of people learn how these things work. EDIT: I guess one of those exceptions is what makes you go to the secret level select in Sonic 3D, right?
Thanks. Heh. Someday, maybe. Yes. Instead of giving you the ILLEGAL INSTRUCTION text, it gives you "You found the secret level select screen!" screen. Or at least that is what I understand. I don't know jack about S3D.
Quite correct. If we look at the S3D vector table... Code (Text): FFFF0400 00000200 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 000054E0 00000928 FFFF04E8 00000928 0000546E 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 00000928 The vector table is just a great big huge list of pointers. The first is the stack pointer loaded into address register 7 upon bootup. I don't know what every single pointer does, but the important ones are the ones at the end. Those are the exceptions (ILLEGAL INSTRUCTION, BUS ERROR, CHK INSTRUCTION, TRAPV INSTRUCTION etc.). In Sonic 2 they point to $200 (hang). However, in Sonic 3D they point to $928 which happens to be the "Congratulations you have found the secret level select".
*goes to load up S2OP in VC++ to see if that makes a difference to the ol' CPZ bug* [edit] Hmm. It still hangs, even though I've changed all the $200 pointers to $206. Either that isn't the reset code or something is explicitly telling it to hang.