Sega Master System / Mark III / Game Gear
C000 : Last value written to port $3E C002 : Last value written to VDP register $81 C020 : Game mode (Next) C021 : Game mode (Current) C02B : Bank to map to $FFFE when switching from current to next game mode C025,6 : Strength (16-bit value, BCD, so $99,$09 is 999 STGH) C027,8 : Energy (16-bit value, BCD, so $99,$09 is 999 EGY) C029 : Current spell during action scenes (0=none, 1=Hakiri .. 9=Nobota) DFNS items C032 : 1= Have Bracers C033 : 1= Have Helmet C034 : 1= Have Body Armor C035 : 1= Have Leg Armor ATTK items C036 : 1= Have Dokko C037 : 1= Have Vajira C038 : 1= Have Trident C039 : 1= Have War Hammer C106 : Item to edit in stage select screen (0= stage number, 1= Energy count) C10F : R count at the time the RNG function (@065F) finishes C110,11 : Random number value (updated every frame) C200 : Window control in adventure mode D7 : 1= Update (redraw) command list D6 : 1= Close command list D5 : 1= Erase text box from bottom to top (10 lines) D4 : 1= Wait # of frames in C218 (variable length delay) D3 : 1= Open terrain window D2 : 1= Close terrain window C201 : Window control in adventure mode D3 : 1= Generate and display password. (Loads new font tiles) D2 : 1= Enter Continue/Break menu D1 : 1= Trigger damage flash in Kane's window D0 : 1= Trigger damage flash in terrain window C202 : Stage number ($00-$31) in stage select screen / Index into superscript pointer list C204 : Flags D1 : 1= Copy text window area of name table copy in work RAM to VRAM D0 : 1= Copy terrain window area and command list window of name table copy in work RAM to VRAM C205 : Adventure screen number C206,7 : Superscript pointer (always within bank $16) C208,9 : Script index C20C,D : Script pointer (within script bank) C20E : Script bank C20F : Pointer to name table in VRAM ($C800) C214 : Frames to delay before parsing next text. C218,9 : Number of frames to delay during adventure screen (via C200 bit 4) C222 : Index of command list item to print to name table during list printing C223,4 : Pointer to bytecode sequence (for command list) C238,9 : Pointer to bytecode sequence (for command list, Loaded in parallel with C223 frequently) C241 : Relates to menu processing C242 : Relates to submenu processing C24F : Flags used to repeatedly flash the terrain window white C252 : 01= Kane is dead in adventure mode (goes to Continue/Break scene), 00= Kane is alive C26C : Current offset into password being entered (0= first character, $17=last character) C280-C2BF : Temporary event flags (1= event happened, 0= event didn't happen) C2C0-C2CF : Event flags C2D0-C2DF : Event flags C2E0-C2E7 : Item flags C2E0 : 1= Have Charm C2E1 : 1= Have Fake Sword (1) C2E2 : 1= Have Fake Sword (2) C2E3 : 1= Have Sword of Branches C2E4 : 1= Have X-ray Glasses C2E5 : 1= Have Lute C2E6 : 1= Have Beads C2E7 : 1= Have Sword of Kusanagi C300-C63F : Object records (32 bytes/each) C700-C7FF : Copy of sprite table C800-CDFF : Copy of name table D100-D117 : Password buffer (24 6-bit values, this is the data you enter at the password screen) D120-D13F : Game state that is encoded into a password or decoded from a password DD01-DE0F : Sound (music/effects) related variables DD00 : $01 = FM unit detected, $00 = FM unit not detected DD04 : Sound code to play
The password consists of 24 six bit characters. The last two characters function like a checksum to validate the previous ones. The passwords are randomized so that unique passwords are generated even when the game state has not changed. This is done by taking the random value byte at $C10F and distributing the eight bits repeatedly across 19 bits in the password. If the ROM is patched to disable updates of $C10F, the same password is always generated.
The password stores variables such as integers (1 to 8 bits) and flag arrays (1 bit per byte). The bits that make up these variables are stored non-linearly across the 'password bit' buffer at $D120-D13F, which is later encoded as the final password at $D100-$D117. Data tables in bank $13 (mapped to $8000-$BFFF) are used to map a variable's bits to the password bits. These tables account for 112 of the 132 password bits. Each table has the following format:
byte num_bits ; The number of bits to unpack rept num_bits word ram_address ; A pointer within D120-D13F byte bit_mask ; A byte with a single bit set endr
For example, table $AB70 is used to extract or insert the value corresponding to the MSB of Kane's energy. It looks like this:
$04, $D124, $20, $D125, $04, $D126, $02, $D126, $04
This means four bits in the bit positions of the addresses listed are combined to create 4-bit value. Bits are loaded from the LSB and shifted to the right. It seems that if more than 8 bits are specified, the older data is shifted out and lost and the most recent 8 bits shifted in are kept when decoding.
When encoding the same 8 bits are recycled repeatedly when the bit count is greater than 8. For example the game deliberately encodes a single byte of random data from $C10F into 19 bits distributed around the password buffer.
The first 22 characters of the password consist of the following 132 bits of data, including a checksum. The latter 2 characters are a secondary checksum on the first 22 characters. Note that the individual bits are scattered around and not stored in order:
16 bits of primary checksum 19 bits of random data (8 bits of C20F used repeatedly) 3 bits of byte at C022 (?) 8 bits of byte at C025 (STGH LSB) 2 bits of byte at C026 (STGH MSB, strength is limited to 399) 8 bits of byte at C027 (EGY LSB) 4 bits of byte at C028 (EGY MSB, energy is limited to 999) 12 bits of flags at C032-C03D (DFNS/ATTK item flags, latter 4 bits unused by game) 6 bits of byte at C215 (?) 7 bits of byte at C205 (Adventure screen #) 6 bits of a count of the number of sequentially set temporary event flags at C281-C2BF 24 bits of flags at C2B0-C2C7 (Permanent event flags) 2 bits of flags at C2D0-C2D1 (Permanent event flags) 8 bits of flags at C2E0-C2E7 (Item flags) 7 bits of byte at C251 (?)
The password contains a 6-bit count of event flags to fill linearly from $C281 onwards. This means you cannot have a password with reset flags coming before set flags. During gameplay the game seems to set flags out of order, and the flag encode routine stops at the first reset flag. This means there may be parts in the game where your progress is set back slightly, but you'll always be near to where you left off.
When encoding a password the game sets the 16 primary checksum bits to '1' so they have a known value. Then it calculates the checksum and inserts the resulting 16 bits into the primary checksum bits. The 22 bytes are then copied to the final password buffer at $D100, the secondary checksum is calculated, and the result of that becomes the last 2 characters of the 24-character password
The actual primary and secondary checksums aren't really additive checksums, but I am still unclear about how the calculations work. Regardless they are used to validate the data like a checksum.
The game has a few checks to make sure the combination of password bits are valid. For example if Kane doesn't have the Dokko in his inventory, which is an item you get at the same time Daikok teaches you the 'Password' spell, it treats the password as being invalid.
These are all in bank $15:
$4D0B : Encode byte in C $4D24 : Encode flag array from BC $4BCB : Decode byte in C $4BE3 : Decode flag array to DE $4BFC : Encode password $4966 : Password entry screen main loop
The main loop starts at $00E0. The 'next' game mode is read and compared to the 'current' game mode, if they aren't equal (meaning we are switching to a new mode) the current mode is updated and the bank value at $C02B is written to $FFFE. The game mode is used as an index to call a subroutine from the jump table at $015F. Once the routine returns, the main loop restarts.
If bit 7 of the next mode is reset, an initialization function specific to each jump table item is called first (e.g., resetting variables or cursor positions), then the current mode is rewritten with bit 7 set so that the main loop of the selected mode runs.
Value Bank $00 $82 = During startup (just sets next mode to $05 to run the intro) $01 $95 = Title screen $02 $95 = Action mode (demonstration play) $03 $95 = Password screen $04 $92 = Pause menu $05 $95 = Intro sequence $06 $92 = Game ending sequence $07 $95 = Stage select $08 $95 = Adventure mode $09 $95 = Action mode (user controllable)
The event flags are set (and sometimes reset) as you make progress in the Adventure mode. C280-C2BF are temporary flags that are reset at major points in the story. The first time they are reset after being partially used are when you reach Shimono-seki. Resetting a flag allows the event that set it to repeat again.
The flags at C2E0 seem to be long-term event flags that retain their value when the temporaries are cleared.
This is the stage select screen. You can enter it by setting $C020=$07 at the title screen. It's not clear how (or if) the stage select can be entered normally.
Press to toggle between adjusting the stage number or energy value.
Press / to increase/decrease the stage number or energy value.
Press to start the stage. If you are currently editing the stage number you start the adventure scene, if you are currently editing the energy level you start the action scene.
There's a "superscript" which defines how the adventure scenes work (kind of like an interpreted language), and a regular script which is for formatted text messages. Both are streams of bytes that are a mix of control codes and data which are parsed sequentially.
Superscript codes are E8-FF, 01-0D. Each is a command that takes additional bytes as parameter data. Functions include writing to VRAM, playing music/SFX, block data copies, poking RAM bytes, and setting pointers to regular scripts or other superscript fragments. Known codes:
01 = Set C200.D0 (unknown flag) 02 = Set script index number 03 = Close terrain window 04 = Open terrain window 05 = Delay for N frames (N is 2-byte parameter) 06 = Erase text box 07 = Trigger damage flash in terrain window 08 = Trigger damage flash in Kane's window 09 = Relates to repeatedly flashing the terrain window white 0A = Relates to repeatedly flashing the terrain window white 0B = Enter Continue/Break menu 0C = Open Pause menu? (unsure) 0D = Generate and display password FF = Change next game mode to Action mode. Byte parameter. (Action stage number?) FE = Set byte flag to 01 at 2-byte address parameter FD = Reset byte flag to 00 at 2-byte address parameter FC = Set adventure screen number FB = Copy word data to name table FA = Reduce Kane's energy. Byte parameter is index into list of damage amounts. F9 = Reduce Kane's strength. Byte parameter is index into list of damage amounts. Can set dead flag. F7 = Set Kane's strength from a list of values (C022 is the index) F6 = Display sprite. Parms: object record offset pointer, xpos, ypos, sprite data table index # F5 = Clear all event flags at C280+ and C2C0+ F4 = Sprite related F3 = Sprite related F2 = Set new superscript pointer value F1 = Poke address with byte (params: ptr, byte) F0 = ??? EF = ??? EE = Request music/SFX using 1-byte parameter ED = Increment location at 2-byte address parameter EC = Decrement location at 2-byte address parameter EB = Set superscript index EA = ??? E9 = ??? E8 = ???
F6 is used to display the pointing hand for a "Look" command, or the flashing cursors in the command window or text window.
Script control codes are F8-FF.
FF = Clear screen. FD = New line. FC = Wait for user prompt (flashing cursor). Also ends a section of text. FB = Set text parsing delay to 16 frames FA = Print digit 2 of Kane's strength F9 = Print digits 2,1 of Kane's strength F8 = Print digit 0 of Kane's strength
Text is same as the ASCII character set, but starting at zero instead of 0x21. Valid characters are from 0x00 to 0x3A only.
When dumping the script there are areas that have no descriptions because those adventure screens are automatically transitioned to and the user isn't supposed to have control. These have the description text "??0xx??" where xx is a 8-bit hexadecimal number. It's likely a placeholder used during development. If you forcibly enter those scenes by changing $C205 you can see them printed.
The game script is stored in the following banks. Each has a list of pointers followed by strings. A single 16-bit index is used to reference all strings in the game by the superscript.
Bank $1E : Pointers and strings for string indexes $0000-$013F Bank $1F : Pointers and strings for string indexes $0140-$023F Bank $0C : Pointers and strings for string indexes $0240-$034F
The command list is made up of sequences of bytes that tell the game engine to print different strings and possibly perform additional functions. Known values:
00 = Copy text to name table buffer. Next byte is the string index. See list below. FF = End of list
Command list strings: Attach:Spellcaster-CommandListStrings.txt
The game stores sprites in a high level format at C300-C63F. Each record is 32 bytes. The game engine tends to manually poke fixed offsets as needed, making assumptions about the location of particular records.
Object record offsets:
+$00 : Sprite type +$02 : X position +$04 : Y position +$05 : Sprite image
Sprite type values:
$00 : Disabled sprite (default value) $01 : Flashing sprite. Used for down-facing arrow. $02 : Menu cursor. Up/Down moves up/down by 16 pixels. Used for the command list. $03 : Always displayed. Used for pointing finger. $06 : Password cursor. Direction pad moves it around by 16 pixels.
Sprite image values:
$11 : Right-facing arrow (for command list and continue/break menu) $16 : Down-facing arrow (when prompting the user during text output) $1B : Pointing finger (for Look command) $23 : Up-facing arrow (for scrolling up from a later page in the command list)
Superscript command F6 can be used to add sprites to an adventure screen. The game pokes the following addresses to manipulate specific sprites:
$C340 : Cursor sprite (password) $C360 : Cursor sprite (command list) $C380 : Pointing finger sprite
The superscript can add invisible objects at $C460 onwards. When you use the "Look At" command, the game will check for up to five object records from the starting address to see if they collided with the pointing finger sprite. On the first collision found the search routine exits, otherwise it continues until all objects were checked. This way regular sprite processing routines can be used to implement the "Look At" feature.
The game has a list of pointers for all $60 adventure screens. Each table the pointer addresses has a object count (zero if no objects to examine), otherwise multiple 6-byte records follow. The first byte gives the index of a temporary event flag to check, so the object can be skipped if the user already took it for example. The remaining bytes define the X,Y location and three other parameters, one of which is fixed to $B0 for all objects in the game.
Adventure screen # ($C205) values:
$02 : Town of Izumo (before Kuma appears) $04 : Unknown enemy challenging you to battle $05 : Izumo shrine $0A : Treasure room of Attaro shrine $0B : Treasure room of Attaro shrine $0E : Foothills of Mt. Miwa $0F : Inside Mt. Miwa shrine $13 : Town of Izumo $15 : Midori's house $16 : Pier Locations on the map of Dannoura: 2C 2D 2E 2F 30 27 28 29 2A 2B 22 23 24 25 26 1D 1E 1F 20 21 1C 1B 18 19 1A $34 : Dannoura, when surrounded by Iwato's family $35 : Summit Temple $36 : Town of Izumo $3A : Summoning Utusho $3C : Inside the shrine (facing the pot) $3D : Inside the shrine (spaceship) $3E : When you find Daikok's armor $3F : Kumano shrine $40 : North side of Pyramid $41 : South side of Pyramid $42 : West side of Pyramid $43 : East side of Pyramid $44 : Top of Pyramid $45 : During Regina's attack $46 : Gate (Entrance to the Underworld, also $47,$48) $49 : Misty Crossing / Misty Ferry / Ferryman $4A : Chizu Sea (Toyo with nectar) $4B : During Amano's attack $4C : Izanami $4D : Cerberus $4E : Rock with an open field behind it Holy Bridge rooms: $4F $50 $51 $52 $56 $55 $54 $53 $57 : ??? $58 : Izumo $59 : Kashima shrine $5A : Gate of huge mansion