Memory locations

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

Password structure

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.

Password data

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.

Password validation

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.

Password related functions

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

Game engine details

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.

Game mode values

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)

Event flags

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.

Stage select

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 [2] to toggle between adjusting the stage number or energy value.

Press [Up]/[Down] to increase/decrease the stage number or energy value.

Press [1] 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.

Scripts

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

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.

Game script

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

Command list bytecode

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

Object records

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

"Look At" implementation

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.

Miscellaneous

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



Return to top
0.34s