The current URL is datacrystal.tcrf.net.
Castlevania II: Belmont's Revenge/ROM map: Difference between revisions
No edit summary |
No edit summary |
||
(75 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
{{subpage}} | |||
{{rommap|game=Castlevania II - Belmont's Revenge}} | {{rommap|game=Castlevania II - Belmont's Revenge}} | ||
Line 4: | Line 5: | ||
(r:symbol) marks the start of a callable subroutine. | (r:symbol) marks the start of a callable subroutine. | ||
(RSTxy:symbol) marks a callable subroutine which can be called with the special quick-access RST commands. | |||
(t:symbol) marks the start of a data table. | |||
Note that many functions take as an input the current entity in register d, and the entity property in register e. As a rule, entities are $20 bytes long and the first $20 bytes of every each page ($100 bytes) compose an entity. | |||
X:7FFF all swappable banks store list their bank number as the last byte of the bank. | X:7FFF all swappable banks store list their bank number as the last byte of the bank. | ||
0:0038 ( | 0:0000 (RST00:jumptable_entity_state) jumptable (indirect jump by entry in table following call to RST00 according to current entity's state variable) | ||
0:01D9 (r: | 0:0003 (r:jumptable) jumptable by A. | ||
0: | 0:0008 (RST08:ld_from_table) hl <- (hl + 2a) | ||
0:000C (r:ld_hl_hl) hl <- (hl) | |||
0:0010 (RST10:entity_set_image) sets entity's image (see "Images" section below) | |||
0:0018 (RST18:entity_set_timer) sets entity property $08 to A. This seems to be the entity's timer, such as how long until fire despawns or belmont's hitstun. | |||
0:0020 (RST20:entity_get_x) e <- $17, a <- x position of entity. | |||
0:0028 (RST28:add_hl_a) hl += a, then a <- l. | |||
0:0030 (RST30:entity_inc_state) increments the state variable (D:01) of the current entity. | |||
0:0038 (RST38:entity_get_y) get Y position of current entity. | |||
0:01D9 (r:longcall_2_438D) stores current bank (read from $7FFF) on stack, calls routine 2:438D (write screen's worth of tiles to vram), then returns to caller bank. | |||
0:031b This routine does a lot, but the first thing it does is check if the player is holding a+b+start+select and if so restarts the game. | |||
0:0D23 (r:entity_set_state_and_substate) entity state <- b, substate (attacking) <- c | |||
0:0D2A (r:belmont_apply_velocity) adds belmont's velocity to belmont's x position | |||
0:2838 (r:standard_scanline_effect) ($dec1) <- 01, ($c898) <- 7e | |||
0:283B (r:store_bc_scanline_effect) ($dec1) <- b, ($c898) < | |||
0:2868 (r:load_substage_word_from_table) hl <- ((hl + 2*stage) + substage*2) | |||
0:286D (r:load_substage_byte_from_table) a <- ((hl + 2*stage) + substage) | |||
0:2873 (r:load_stage_data) hl <- (hl + 2*stage); a <- substage. | |||
0:2881 (r:add_bc_a) bc += a, then a <- c. | |||
0:2886 (r:add_de_a) de += a, then a <- e | |||
0:2934 (r:clear_all_entities) zeros-out all entities from C100-D700 inclusive. Only Belmont (C000) is spared. | |||
0:2958 (r:memcpy) directly copies bc+1 bytes from hl to de. After this, hl and de point to the end of their respective buffers. Before calling, if de=hl+1, smears bc copies of [hl]. This can be a handy way to zero out a large buffer. | |||
0:2978 (r:negative) a <- 0x100 - a | |||
0:297B (r:leftshift_bc_4) leftshifts bc by 4. | |||
0:2986 (r:lda_00) a <- $00 | |||
0:2989 (r:lda_06) a <- $06 | |||
0:298C (r:lda_7F) a <- $7F | |||
0:298F (r:lda_06) a <- $80 | |||
0:2AC7 (r:wait_for_blank) Seems to wait to the end of the current blanking period (if applicable) and then to the start of the next. | |||
0:2ca4 change this 2-byte word from 41c0 to 4280 to free up some extra space behind Belmont's head for sprite-hacking. Specifically, this means the map screen blank tile will be loaded from somewhere else. (You'll want to do the same at 0:2ce4 for the map screen as well.) | |||
0:2E24 (r:transfer_buffers_to_vram) Transfers multiple buffers to vram. Before calling, ($ca81) should be set to the transfer scheme (see 0:2E57, below), and hl should point to a zero-terminated meta-buffer containing structs as follows: | |||
- 2 bytes (Big-Endian): destination vram address divided by 0x10 | |||
- 1 byte: destination length in units of 0x10 (source length depends on this and $ca81 scheme) | |||
- 1 byte: source bank | |||
- 2 bytes (Little-Endian) source address | |||
0:2E57 (r:transfer_buffer_to_vram) transfers bc from buffer:hl into vram:de, using one of four schemes as selected by ($ca81): | |||
- 0: copy bytes from hl 1:1 (e.g. 0, 1, 2, 3, 4, 5...) | |||
- 1: duplicate every byte in hl (e.g. 0, 0, 1, 1, 2, 2, ...) | |||
- 2: even bytes from hl, odd bytes 0 (e.g. 0, 0, 1, 0, 2, 0, ...) | |||
- 3: odd bytes from hl, even bytes 0 (e.g 0, 0, 0, 1, 0, 2, ...) | |||
0:2FE7 (r:2fe7) Runs during vblank. transfers $c980 buffer to vram (see ram map) | |||
0:305A (r:305A) Runs during vblank. transfers ($cac0) bytes from bank ($cac1), address ($cac2.w) to vram ($cac4.w) | |||
0:3366 (r:copy_32_bytes) copies 32 bytes from [bc...bc+32] to [hl...hl+32]. As a result, hl and bc are incremented 32 times. | |||
0:3369 (r:copy_16_bytes) copies 16 bytes from [bc...bc+16] to [hl...hl+16]. As a result, hl and bc are incremented 16 times. | |||
0:3553 (r:play_music) plays music in argument a. If a is 0, stops music? | |||
0:35A9 (r:mbc_bankswap_1) loads swappable bank 1. | 0:35A9 (r:mbc_bankswap_1) loads swappable bank 1. | ||
0:35AA (r:mbc_bankswap) loads swappable bank from cpu register a. | |||
0:35AF (r:mbc_bankswap_2) loads swappable bank 2. | 0:35AF (r:mbc_bankswap_2) loads swappable bank 2. | ||
0:35B5 (r:mbc_bankswap_6) loads swappable bank 6. | 0:35B5 (r:mbc_bankswap_6) loads swappable bank 6. | ||
0:35BB (r:mbc_bankswap_7) loads swappable bank 7. | 0:35BB (r:mbc_bankswap_7) loads swappable bank 7. | ||
0:35C1 (r:mbc_bankswap_3) loads swappable bank 3. | 0:35C1 (r:mbc_bankswap_3) loads swappable bank 3. | ||
6:421D (r: | 0:36B5 (r:get_tilechunk_address_from_de_plus_4ea2) hl <- 4x4 tile-chunk address (points to bank 2), indexed from [de+$(4ea2)] in bank 6 | ||
0:3372 (r:transfer_tile_to_vram) Runs during vblank. Transfers 8x8 tile from (bc) to (hl). If ($cacb) is non-zero, the source format is in reduplicated format (each source byte results in two subsequence destination bytes). | |||
0:38E0 (r:entity_set_animation) Set animation (prop 0C,0B,0A) to (bc):0:(bc+1) (bc):0:(bc+1) | |||
0:3B42 (r:entity_set_y_velocity_from_table) Entity y velocity <- word [hl + 2*a] | |||
0:3B80 (r:entity_decrement_hitstun) decrements hitstun if positive | |||
0:3B82 (r:entity_decrement_variable) decrements Entity variable [dl] if positive. | |||
0:3E02 (r:entity_set_state) sets Entity variable state [d:01] <- a | |||
0:3DAC (r:entity_set_x_velocity_0) Entity x velocity <- 00. | |||
0:3DAF (r:entity_set_x_velocity) Entity x velocity <- cb. | |||
0:3DB4 (r:entity_set_y_velocity_0) Entity y velocity <- 00. | |||
0:3DB7 (r:entity_set_y_velocity) Entity y velocity <- cb. | |||
0:3DBA (r:write_word) (hl) <- cb | |||
0:3DBE (r:entity_get_x_velocity) cb <- Entity x velocity. | |||
0:3DC5 (r:entity_get_y_velocity) cb <- Entity x velocity. | |||
0:3DC8 (r:read_word) cb <- (hl) | |||
0:3DEC (r:entity_reset_13b0) reset bit 0 of Entity var 13 | |||
2:43ae (r:get_pointer_to_tiledata) de <- a*20 + (tiledata_ptr / ca92:ca93). | |||
2:4407 (r:transfer_4x4_tiles_to_vram) input: bc points to top-left of 4x4 vram tiles, hl points to length-16 array. Also copies the tiles to to bc+$3C00 (i.e. $D000-$D800) | |||
3:5242 (t:substage_misc_entities) (index via load_substage_data): copied (with some modification) to $d240/$d340. | |||
3:58AC (t:substage_enemies) (index via load_substage_data): copied (with some modification) to $d440/$d540. | |||
3:5D25 (t:substage_items) (index via load_substage_data): copied (with some modification) to $d640/$d740. | |||
3:6bdc (r:clear_entity) clears the current entity (d:00-d:20) | |||
3:6C49 (r:screen_coords_arithmetic) bc <- a plus bc in screen-radix. "screen-radix" here means that b represents screen dimensions ($A0 or $80 depending on vertical or horizontal), and c ranges between 0 and the screen dimension. Before calling, store screen dimension ($80 or $A0) in $(CBC3). | |||
3:6D6B (r:inc_CBC4) increments $(CBC4) | |||
3:702C (r:load_substage_sprites) | |||
3:703D (r:load_substage_quadref_from_table) hl <- [hl + 2*level] + 4*sublevel | |||
3:7048 (r:load_sprites) copy *b* bytes from [hl...] to [$df00 + 2*a] | |||
6:421D (r:entity_update) Belmont frame update routine. Called from 0:05FA. | |||
6:4235-4241 Belmont update jumptable | |||
6:427F Belmont state 0 (standing) routine | |||
6:4289 Belmont state 2 (crouching) routine | |||
6:42E9 Belmont state 1 (walking) routine | |||
6:4293 Belmont state 3 (jumping) routine | |||
6:42A1 Belmont state 4 (??) routine | |||
6:44A6 Belmont state 5 (??) routine | |||
6:44D2 Belmont state 6 (??) routine | |||
6:4510 Belmont state 7 (??) routine | |||
6:461B (r:input_A_pressed) A gets zero or 10 depending on if the A button was pressed this frame. Status flags set | 6:461B (r:input_A_pressed) A gets zero or 10 depending on if the A button was pressed this frame. Status flags set | ||
6:4621 (r:input_up_down_held) A and status flags | 6:4621 (r:input_up_down_held) A and status flags | ||
Line 25: | Line 108: | ||
6:464B (r:input_up_held) A and status flags | 6:464B (r:input_up_held) A and status flags | ||
6:4651 (r:input_any_held) A and status flags | 6:4651 (r:input_any_held) A and status flags | ||
6:4801 (r:belmont_set_walk) Read left/right input and set Belmont to be walking left or right accordingly. | |||
6:4817 (r:entity_move_face_right) Entity moves and faces right at velocity 0x90 | |||
6:4817 (r:entity_move_face_left) Entity moves and faces left at velocity -0x90 | |||
7:4000 (r:memcpy7) do ([de++] = [hl++]) while (--bc) | |||
Bank swap routines: | Bank swap routines: | ||
- All are in bank 0, and all write to $2180 to change the bank. For some reason, bank 5 is always swapped inline rather than by function call. | - All are in bank 0, and all write to $2180 to change the bank. For some reason, bank 5 is always swapped inline rather than by function call. | ||
== Sprites == | |||
Sprites comprise a set of 8x16 tiles with x/y offsets and vram object flags. They are stored in the following format: | |||
- 1 byte: number of 8x16 tiles in the sprite | |||
- (for each sprite:) | |||
- 1 byte [s] y offset | |||
- 1 byte [s] x offset | |||
- 1 byte high 7 bits: vram tile index. 1 bit: object flags | |||
- (optional) 1 byte: object flags. (Only if previous byte low bit is set.) | |||
- Entities' sprites are stored in property 0A (for example, Belmont's sprite is at 0xC00A—see RAM map). The value is looked up in a table in RAM starting at address 0xD00 to get a pointer to a sprite as defined above. Editing this value will change the entity's image—for example, the axe might appear as a torch, at least until the axe's animation restores the image to the next frame of axe animation. Below is a partially-complete table of images (Please contribute!). Note that the sprite will look like garbage if the correct vram tiles aren't loaded yet. | |||
0: Torch (frame 0) | |||
1: Torch (frame 1) | |||
2: Coin (frame 0) | |||
3: Coin (frame 1) | |||
4: Score Orb | |||
5: Small heart | |||
6: Large Heart | |||
7: Wall meat | |||
08: fire (frame 0) | |||
09: fire (frame 1) | |||
0A: 1-up | |||
0B: holy water (icon) | |||
0C: holy water (projectile) | |||
0D-10: Axe/Cross (frames 0-3) | |||
11-23: Belmont poses | |||
24-29: whip | |||
38-39: Punaguchi | |||
3C: Punaguchi bullet | |||
40-43: Bat | |||
44-45: knight | |||
4D-55: Forneus | |||
57: Moving Platform | |||
5D: Rope Spike Ball | |||
5E-60: Pulley | |||
5D-64: Eyeball | |||
5D-: Giant Bat | |||
61: Raven | |||
75-76: Dagger thrower | |||
76*: Angel Mummy spine | |||
and so on. | |||
== Entity indices == | |||
(stored in RAM addresses XY00, XY >= $C6) -- range from 0-7F. | |||
00: (no entity) | |||
01: Lantern/Item: Axe/Cross | |||
02: Lantern/Item: Holy Water | |||
03: Lantern/Item: Coin | |||
04: Lantern/Item: Whip Upgrade Orb | |||
05: Lantern/Item: Small Heart | |||
06: Big Heart | |||
07: (debris) | |||
08: (debris with big heart?) | |||
09: Rat? | |||
0A: ? | |||
0B: breakable block? | |||
0C: Punaguchi | |||
0D: Punaguchi | |||
0E: Rat? | |||
0F: ? (explodes when struck) | |||
10-13: ? | |||
14: vertically moving flame? | |||
15-16: ? | |||
17-1B: ? (palette cycles, and turns to flame when struck.) | |||
1C: ? (ascends) | |||
1D: ? (gravity) | |||
1E: ? (descends) | |||
1F: bat? | |||
20: bat? | |||
21: ? (sessile enemy) | |||
22: Lantern/Item: orb that crashes the game | |||
23-24: ? | |||
25: eyeball spawner (right) | |||
26: eyeball spawner (left) | |||
27-29: ? | |||
2A: (immediately explodes) | |||
2B: ? (deals contact damage, but cannot be destroyed) | |||
2C: ? (like 2B but larger and does more damage) | |||
2D: ? (like 2D) | |||
2E-2F: ? | |||
30: ? (sessile enemy) | |||
31: ? (like 2B) | |||
32: ? | |||
33: ? (descending enemy) | |||
34: raven | |||
35: whip upgrade orb | |||
36: ? | |||
37-3A: ? | |||
3B: ? (sessile enemy, explodes) | |||
3C: eyeball spawner (above) | |||
3D-3E: ? | |||
3F: ? (sessile enemy) | |||
40: ? | |||
41: jumping dagger-thrower | |||
42-44: ? (like 2B) | |||
45: Lantern/Item: boss start (Darkside) | |||
46: ? | |||
47: ? (enemy, drops and dies) | |||
48-49: ? | |||
4A: moving platform, contact damage? | |||
4B-4D: ? | |||
4E: background flame | |||
50: moving platform, covers screen? | |||
51: ? (sticks to top of screen) | |||
52: ? | |||
53: Lantern/Item/Controller: boss start (Angel mummy) | |||
54: Angel Mummy Head | |||
55: Angel Mummy Vertebrae | |||
56: ? (moves across screen, leaving trail.) | |||
57: like 56, but in reverse. | |||
58-5A: ? | |||
5B: Night Stalker | |||
5C: ? (contact damage) | |||
5D: ? | |||
60: Lantern/Item: boss start? | |||
61: ? | |||
62: ? (palette cycles, deals damage) | |||
64: ? (like 5C) | |||
65-68: ? | |||
69: Lantern/Item: boss start (Bone Serpent) | |||
6A: Bone Serpent (part) | |||
6B: ? (moves to constant position at top of screen) | |||
6C: Bone Serpent (part) | |||
6D: Bone Serpent (part) | |||
6E: moves to side of screen | |||
6F: Bone Serpent (part) | |||
70: ? (strange glitching tiles) | |||
71: ? | |||
72: Lantern/Item: boss start (Soleil) | |||
73: Lantern/Item: boss start | |||
74: ? (circular movement) | |||
75-78: ? | |||
79-7E: (crashes game) | |||
7F: ? | |||
{{Internal Data}} |
Latest revision as of 14:26, 24 January 2024
This is a sub-page of Castlevania II: Belmont's Revenge.
The following article is a ROM map for Castlevania II: Belmont's Revenge.
Format for PRG-ROM is Bank:RAM address.
(r:symbol) marks the start of a callable subroutine. (RSTxy:symbol) marks a callable subroutine which can be called with the special quick-access RST commands. (t:symbol) marks the start of a data table.
Note that many functions take as an input the current entity in register d, and the entity property in register e. As a rule, entities are $20 bytes long and the first $20 bytes of every each page ($100 bytes) compose an entity.
X:7FFF all swappable banks store list their bank number as the last byte of the bank. 0:0000 (RST00:jumptable_entity_state) jumptable (indirect jump by entry in table following call to RST00 according to current entity's state variable) 0:0003 (r:jumptable) jumptable by A. 0:0008 (RST08:ld_from_table) hl <- (hl + 2a) 0:000C (r:ld_hl_hl) hl <- (hl) 0:0010 (RST10:entity_set_image) sets entity's image (see "Images" section below) 0:0018 (RST18:entity_set_timer) sets entity property $08 to A. This seems to be the entity's timer, such as how long until fire despawns or belmont's hitstun. 0:0020 (RST20:entity_get_x) e <- $17, a <- x position of entity. 0:0028 (RST28:add_hl_a) hl += a, then a <- l. 0:0030 (RST30:entity_inc_state) increments the state variable (D:01) of the current entity. 0:0038 (RST38:entity_get_y) get Y position of current entity. 0:01D9 (r:longcall_2_438D) stores current bank (read from $7FFF) on stack, calls routine 2:438D (write screen's worth of tiles to vram), then returns to caller bank. 0:031b This routine does a lot, but the first thing it does is check if the player is holding a+b+start+select and if so restarts the game. 0:0D23 (r:entity_set_state_and_substate) entity state <- b, substate (attacking) <- c 0:0D2A (r:belmont_apply_velocity) adds belmont's velocity to belmont's x position 0:2838 (r:standard_scanline_effect) ($dec1) <- 01, ($c898) <- 7e 0:283B (r:store_bc_scanline_effect) ($dec1) <- b, ($c898) < 0:2868 (r:load_substage_word_from_table) hl <- ((hl + 2*stage) + substage*2) 0:286D (r:load_substage_byte_from_table) a <- ((hl + 2*stage) + substage) 0:2873 (r:load_stage_data) hl <- (hl + 2*stage); a <- substage. 0:2881 (r:add_bc_a) bc += a, then a <- c. 0:2886 (r:add_de_a) de += a, then a <- e 0:2934 (r:clear_all_entities) zeros-out all entities from C100-D700 inclusive. Only Belmont (C000) is spared. 0:2958 (r:memcpy) directly copies bc+1 bytes from hl to de. After this, hl and de point to the end of their respective buffers. Before calling, if de=hl+1, smears bc copies of [hl]. This can be a handy way to zero out a large buffer. 0:2978 (r:negative) a <- 0x100 - a 0:297B (r:leftshift_bc_4) leftshifts bc by 4. 0:2986 (r:lda_00) a <- $00 0:2989 (r:lda_06) a <- $06 0:298C (r:lda_7F) a <- $7F 0:298F (r:lda_06) a <- $80 0:2AC7 (r:wait_for_blank) Seems to wait to the end of the current blanking period (if applicable) and then to the start of the next. 0:2ca4 change this 2-byte word from 41c0 to 4280 to free up some extra space behind Belmont's head for sprite-hacking. Specifically, this means the map screen blank tile will be loaded from somewhere else. (You'll want to do the same at 0:2ce4 for the map screen as well.) 0:2E24 (r:transfer_buffers_to_vram) Transfers multiple buffers to vram. Before calling, ($ca81) should be set to the transfer scheme (see 0:2E57, below), and hl should point to a zero-terminated meta-buffer containing structs as follows: - 2 bytes (Big-Endian): destination vram address divided by 0x10 - 1 byte: destination length in units of 0x10 (source length depends on this and $ca81 scheme) - 1 byte: source bank - 2 bytes (Little-Endian) source address 0:2E57 (r:transfer_buffer_to_vram) transfers bc from buffer:hl into vram:de, using one of four schemes as selected by ($ca81): - 0: copy bytes from hl 1:1 (e.g. 0, 1, 2, 3, 4, 5...) - 1: duplicate every byte in hl (e.g. 0, 0, 1, 1, 2, 2, ...) - 2: even bytes from hl, odd bytes 0 (e.g. 0, 0, 1, 0, 2, 0, ...) - 3: odd bytes from hl, even bytes 0 (e.g 0, 0, 0, 1, 0, 2, ...) 0:2FE7 (r:2fe7) Runs during vblank. transfers $c980 buffer to vram (see ram map) 0:305A (r:305A) Runs during vblank. transfers ($cac0) bytes from bank ($cac1), address ($cac2.w) to vram ($cac4.w) 0:3366 (r:copy_32_bytes) copies 32 bytes from [bc...bc+32] to [hl...hl+32]. As a result, hl and bc are incremented 32 times. 0:3369 (r:copy_16_bytes) copies 16 bytes from [bc...bc+16] to [hl...hl+16]. As a result, hl and bc are incremented 16 times. 0:3553 (r:play_music) plays music in argument a. If a is 0, stops music? 0:35A9 (r:mbc_bankswap_1) loads swappable bank 1. 0:35AA (r:mbc_bankswap) loads swappable bank from cpu register a. 0:35AF (r:mbc_bankswap_2) loads swappable bank 2. 0:35B5 (r:mbc_bankswap_6) loads swappable bank 6. 0:35BB (r:mbc_bankswap_7) loads swappable bank 7. 0:35C1 (r:mbc_bankswap_3) loads swappable bank 3. 0:36B5 (r:get_tilechunk_address_from_de_plus_4ea2) hl <- 4x4 tile-chunk address (points to bank 2), indexed from [de+$(4ea2)] in bank 6 0:3372 (r:transfer_tile_to_vram) Runs during vblank. Transfers 8x8 tile from (bc) to (hl). If ($cacb) is non-zero, the source format is in reduplicated format (each source byte results in two subsequence destination bytes). 0:38E0 (r:entity_set_animation) Set animation (prop 0C,0B,0A) to (bc):0:(bc+1) (bc):0:(bc+1) 0:3B42 (r:entity_set_y_velocity_from_table) Entity y velocity <- word [hl + 2*a] 0:3B80 (r:entity_decrement_hitstun) decrements hitstun if positive 0:3B82 (r:entity_decrement_variable) decrements Entity variable [dl] if positive. 0:3E02 (r:entity_set_state) sets Entity variable state [d:01] <- a 0:3DAC (r:entity_set_x_velocity_0) Entity x velocity <- 00. 0:3DAF (r:entity_set_x_velocity) Entity x velocity <- cb. 0:3DB4 (r:entity_set_y_velocity_0) Entity y velocity <- 00. 0:3DB7 (r:entity_set_y_velocity) Entity y velocity <- cb. 0:3DBA (r:write_word) (hl) <- cb 0:3DBE (r:entity_get_x_velocity) cb <- Entity x velocity. 0:3DC5 (r:entity_get_y_velocity) cb <- Entity x velocity. 0:3DC8 (r:read_word) cb <- (hl) 0:3DEC (r:entity_reset_13b0) reset bit 0 of Entity var 13 2:43ae (r:get_pointer_to_tiledata) de <- a*20 + (tiledata_ptr / ca92:ca93). 2:4407 (r:transfer_4x4_tiles_to_vram) input: bc points to top-left of 4x4 vram tiles, hl points to length-16 array. Also copies the tiles to to bc+$3C00 (i.e. $D000-$D800) 3:5242 (t:substage_misc_entities) (index via load_substage_data): copied (with some modification) to $d240/$d340. 3:58AC (t:substage_enemies) (index via load_substage_data): copied (with some modification) to $d440/$d540. 3:5D25 (t:substage_items) (index via load_substage_data): copied (with some modification) to $d640/$d740. 3:6bdc (r:clear_entity) clears the current entity (d:00-d:20) 3:6C49 (r:screen_coords_arithmetic) bc <- a plus bc in screen-radix. "screen-radix" here means that b represents screen dimensions ($A0 or $80 depending on vertical or horizontal), and c ranges between 0 and the screen dimension. Before calling, store screen dimension ($80 or $A0) in $(CBC3). 3:6D6B (r:inc_CBC4) increments $(CBC4) 3:702C (r:load_substage_sprites) 3:703D (r:load_substage_quadref_from_table) hl <- [hl + 2*level] + 4*sublevel 3:7048 (r:load_sprites) copy *b* bytes from [hl...] to [$df00 + 2*a] 6:421D (r:entity_update) Belmont frame update routine. Called from 0:05FA. 6:4235-4241 Belmont update jumptable 6:427F Belmont state 0 (standing) routine 6:4289 Belmont state 2 (crouching) routine 6:42E9 Belmont state 1 (walking) routine 6:4293 Belmont state 3 (jumping) routine 6:42A1 Belmont state 4 (??) routine 6:44A6 Belmont state 5 (??) routine 6:44D2 Belmont state 6 (??) routine 6:4510 Belmont state 7 (??) routine 6:461B (r:input_A_pressed) A gets zero or 10 depending on if the A button was pressed this frame. Status flags set 6:4621 (r:input_up_down_held) A and status flags 6:4627 (r:input_left_right_held) A and status flags 6:462D (r:input_B_pressed) A and status flags 6:4633 (r:input_B_held) A and status flags 6:4639 (r:input_down_held) A and status flags 6:464B (r:input_up_held) A and status flags 6:4651 (r:input_any_held) A and status flags 6:4801 (r:belmont_set_walk) Read left/right input and set Belmont to be walking left or right accordingly. 6:4817 (r:entity_move_face_right) Entity moves and faces right at velocity 0x90 6:4817 (r:entity_move_face_left) Entity moves and faces left at velocity -0x90 7:4000 (r:memcpy7) do ([de++] = [hl++]) while (--bc)
Bank swap routines:
- All are in bank 0, and all write to $2180 to change the bank. For some reason, bank 5 is always swapped inline rather than by function call.
Sprites
Sprites comprise a set of 8x16 tiles with x/y offsets and vram object flags. They are stored in the following format:
- 1 byte: number of 8x16 tiles in the sprite - (for each sprite:) - 1 byte [s] y offset - 1 byte [s] x offset - 1 byte high 7 bits: vram tile index. 1 bit: object flags - (optional) 1 byte: object flags. (Only if previous byte low bit is set.)
- Entities' sprites are stored in property 0A (for example, Belmont's sprite is at 0xC00A—see RAM map). The value is looked up in a table in RAM starting at address 0xD00 to get a pointer to a sprite as defined above. Editing this value will change the entity's image—for example, the axe might appear as a torch, at least until the axe's animation restores the image to the next frame of axe animation. Below is a partially-complete table of images (Please contribute!). Note that the sprite will look like garbage if the correct vram tiles aren't loaded yet.
0: Torch (frame 0) 1: Torch (frame 1) 2: Coin (frame 0) 3: Coin (frame 1) 4: Score Orb 5: Small heart 6: Large Heart 7: Wall meat 08: fire (frame 0) 09: fire (frame 1) 0A: 1-up 0B: holy water (icon) 0C: holy water (projectile) 0D-10: Axe/Cross (frames 0-3) 11-23: Belmont poses 24-29: whip 38-39: Punaguchi 3C: Punaguchi bullet 40-43: Bat 44-45: knight 4D-55: Forneus 57: Moving Platform 5D: Rope Spike Ball 5E-60: Pulley 5D-64: Eyeball 5D-: Giant Bat 61: Raven 75-76: Dagger thrower 76*: Angel Mummy spine
and so on.
Entity indices
(stored in RAM addresses XY00, XY >= $C6) -- range from 0-7F.
00: (no entity) 01: Lantern/Item: Axe/Cross 02: Lantern/Item: Holy Water 03: Lantern/Item: Coin 04: Lantern/Item: Whip Upgrade Orb 05: Lantern/Item: Small Heart 06: Big Heart 07: (debris) 08: (debris with big heart?) 09: Rat? 0A: ? 0B: breakable block? 0C: Punaguchi 0D: Punaguchi 0E: Rat? 0F: ? (explodes when struck) 10-13: ? 14: vertically moving flame? 15-16: ? 17-1B: ? (palette cycles, and turns to flame when struck.) 1C: ? (ascends) 1D: ? (gravity) 1E: ? (descends) 1F: bat? 20: bat? 21: ? (sessile enemy) 22: Lantern/Item: orb that crashes the game 23-24: ? 25: eyeball spawner (right) 26: eyeball spawner (left) 27-29: ? 2A: (immediately explodes) 2B: ? (deals contact damage, but cannot be destroyed) 2C: ? (like 2B but larger and does more damage) 2D: ? (like 2D) 2E-2F: ? 30: ? (sessile enemy) 31: ? (like 2B) 32: ? 33: ? (descending enemy) 34: raven 35: whip upgrade orb 36: ? 37-3A: ? 3B: ? (sessile enemy, explodes) 3C: eyeball spawner (above) 3D-3E: ? 3F: ? (sessile enemy) 40: ? 41: jumping dagger-thrower 42-44: ? (like 2B) 45: Lantern/Item: boss start (Darkside) 46: ? 47: ? (enemy, drops and dies) 48-49: ? 4A: moving platform, contact damage? 4B-4D: ? 4E: background flame 50: moving platform, covers screen? 51: ? (sticks to top of screen) 52: ? 53: Lantern/Item/Controller: boss start (Angel mummy) 54: Angel Mummy Head 55: Angel Mummy Vertebrae 56: ? (moves across screen, leaving trail.) 57: like 56, but in reverse. 58-5A: ? 5B: Night Stalker 5C: ? (contact damage) 5D: ? 60: Lantern/Item: boss start? 61: ? 62: ? (palette cycles, deals damage) 64: ? (like 5C) 65-68: ? 69: Lantern/Item: boss start (Bone Serpent) 6A: Bone Serpent (part) 6B: ? (moves to constant position at top of screen) 6C: Bone Serpent (part) 6D: Bone Serpent (part) 6E: moves to side of screen 6F: Bone Serpent (part) 70: ? (strange glitching tiles) 71: ? 72: Lantern/Item: boss start (Soleil) 73: Lantern/Item: boss start 74: ? (circular movement) 75-78: ? 79-7E: (crashes game) 7F: ?
Internal Data for Castlevania II: Belmont's Revenge
| |
---|---|