Aug 11, 2012

Castlevania III RAM and ROM offsets

Bookmark this blog entry!
Last Update: 2022 / 10 / 08

IMPORTANT NOTICE:
If you just want the RAM table, visit the Castlevania 3 page on the Data Crystal Wiki! This is still my notes repository, but it's a chaotic mess.


Just in case my computer dies and I lose the RTF file I've been keeping my notes in, I will post my notes on the address indexing in CV3. That is, where Trevor's and enemy's coordinates are stored in the RAM, where the bounding box offsets (so-to-speak, since there aren't really bounding boxes) are stored, as well as image speeds and other alarms. All that fun stuff will be noted here.

There are up to 22 instances addressed at a time. Trevor always has the lowest address, then enemies, then 5 torches or lanterns, then 5 candles. Item drops use the same address as the enemy, torch or candle they were dropped from. The whip is at X:$13, then the three subweapons. I think X:$17 is reserved for the ally swap, while X:$18 is reserved for the subweapon HUD display.

RAM pages 4 through 7 are used, most of the data being stored in pages 4 and 5. Page 6 is frequently used for alarms or -- in the case of sinusoidal movement -- storing xstart and ystart. Pages 6 and 7 are used for the tile map(s).

Some non-ranged addresses will be included as well. Anything in page 0 is likely unique. An (R) denotes a ranged set of values. A (C) denotes a cascading set of values, meaning they are updated multiple times each step, usually for PPU purposes. All addresses listed as "Sprite index" or "Image index" relate in one way or another to the sprite displayed. Addresses listed below use the lowest index in the ranges (see above).

The US version has many offsets changed due to changes in coding. ROM offsets are often different between versions. RAM offsets in the Zero Page are one byte lower in the US version.


Instance Mapping in the X Register

Up to 28 (0x00 - 0x1B) instances can be mapped out into any room. Certain instance mappings are reserved for specific types. Addresses after 0x17 are used for special cases and as such some indirect addresses exclude them. Below is a list of each mapping.

0x00  Trevor or Ally
In many situations, especially when another instance is already mapped into the X register, this mapping is ignored and variables are referenced directly, such as $0438 instead of $0438,X. If you do see a variable referenced with a 0x00 X register, you're probably within a loop, such as a drawing loop.

0x01-0x0C  Hostiles
Most everything is spawned within free range. Most projectiles spawn within the range of 0x0A to 0x0D, limiting the number of projectiles on screen typically to 4 at a time. Axe Knights are an exception to the rule. 

0x0D-0x12  Luminaries
These higher values are reserved for candles, torches and such. 

0x13  Primary Attack
This is reserved for Trevor's whip or an ally's primary attack.

0x14-0x16  Item Attacks and Spells
Subweapons and Alucard's orbs occupy this range.

0x17  On-Hit Spark
The spark that appears over enemies or candles when hit.

0x18  Ally Icon
The sprite info for the ally icon is stored here (used in the draw phase).

0x19  Item Sprite
Secondary attack icon info is stored here (used in the draw phase).

0x1A-0x1B  Breakable Blocks
For double=blocks, refers to the lower block.


PROM Bank Allocation

Bank #04 Audio Engine; Background Music
Bank #05 Background Music;
Bank #0C Audio Engine; Sound Effects
Bank #0F System Routines; Common Subroutines
Bank #10 Graphics

PRAM Addressing

$E249(U:$E25F) Sound Play
The value in the accumulator specifies a sound or music to play

$E2D0 PRAM Bank
Set the current bank to the value in the accumulator.

$F543 Step Beginning
Essentially the start of  each step iteration as far as anyone attempting to hack the game would really even care about. Everything before it is technical stuff and drawing code, pretty much.

$FCDE Trevor's Collision Detection
The accumulator holds the relative x-offset to check, while the Y-register checks the relative y-offset to check for collisions with the tile map.



WRAM Addressing

$0011 Attack height (and miscellaneous)
Used for lots of temporary variables, but especially useful when trying to watch death sequences.

$0012 Temporary sprite_index
Used to keep track of $007F and $0565. Adds #$08 to Trevor's y when ducking ($0565==#$1C).

$0015 Temporary y
Used to keep track of $0041C when attacking.

$0017(U) Repeat Counter
Tracks number of loops in some repeated calls.

$0018(U:$0018) System State
Controls menus, screen transitions, and stuff. This is the byte you need to mess with in order to access the debug tools.
  $00  Intro & Title Screen
  $01  (unused?)
  $02  New Game Black Screen (goto $0A)
  $03  Gameplay Black Screen (goto $04)
  $04  Gameplay Screen
  $05  Game Over Black Screen (goto $06)
  $06  Game Over Screen
  $07  Stage Select Screen
  $08  Map Screen
  $09  Prayer Screen
 
$0A  Name Entry Screen
  $0B  Password Entry Screen
  $0C  Epilogue Screen
  $0D  Credits Screen
  $0E  Respawn Black Screen (goto $04)
  $0F  Sound Test Screen


$0019(U:$0019) System Substate
See above. This is why changing $18 directly will likely cause artifacting, unless this is set to #$00 first.

$001B(U:$001A) Step Counter
Incremented by 1 every step. Typical step counter found in most games. Frequently used for incremental timing or simple randomization.

$001D(U:$001C)  Blackout Timer
Set to #02 whenever a new tileset is loaded, then counts down after $0061 counts down. Forces the game to clear bits 3 and 4 of PPUMASK, resulting in nothing being drawn. Also prevents player pausing.

$0020(U:$001F) Randomizer
True randomizer in the game, although infrequently used. Incremented by 1 and then added to $001B while waiting for the system interrupt.

$0021 PPU Bank Mode
Can probably ignore, unless you mess with the VRC6 mapper stuff.

$0022(U:$0020) Unknown
Increases by #44 every frame. Don't know what it's used for.

$0025(U) Nametable Mapping
Write to register $5105.

$0028 Controller press (R)
Used to check if a new button on the controller is pressed.

$002A Controller hold (R)
Each button press adds a specific value to this. Right adds #01, left adds #02, down adds #04, up adds #08, Start adds #10, Select adds #20, B adds #40, and A adds #80.

$002C(U:$002A) Game State
As opposed to System State, used during gameplay. By default it's #$03. Set to #$08 when walking through a door. Set to #$06 when climbing stairs to another room, then to #$07, then to #$01, then to #$04 if it's a vertical room next, then increased so it's #$05 in the next room; if it's a horizontal room it's just increased from #$01 twice so it's #$03 again. In a new stage it's set to #$00 then increased, then set to #$03 or #$05.  
Gets set temporarily to #$19 when whip upgrade is collected and then reset back to #$03. 
Set to #$11 when soul crystal is retrieved or at Clocktower exit -- a value of #$11 at least is for converting time and hearts to score. 
Set to #$18 when walking out of the tower and when at the auto-walk door in the forest. So a value of #$18 is for auto-walking.
Set to #$1E when fleeing Grant's tower or exiting the Clocktower, then to #$17, then to #$1F, then normal stage start settings -- this appears to be normal behavior for a scripted automatic stage transition.
Set to #$09 when climbing stairs to the cloudy areas in Sypha's stage and then set to #$0A so it's actually set at #$0A throughout that room.
Set to #$0B when changing characters.
Set to #$0F for entering a room with auto-climb stairs (Forest, Main Hall). The next stairs out (the auto-climb) set it to #$10.
Set to #$1A when Sypha casts her ice spell in freezable water. After the water freezes over, this gets set to #$1B and is used to prevent conveyor tiles from moving.

$002D(U:$002B) Player Paused
Set when player pauses.

$002E Stage clear
Set when you defeat the boss and the soul shard drops. Prevents player pausing.

$0030 Password Checkpoint
Used by password verifier. Determines what stage and path is generated by the password.

$0031 Grant Defeated
Set when Grant is defeated.

$0032(U:$0030) Effect Timer (Word)
Timer for start menu effect, prayer scene timing, and whip upgrade timing.

$0034(U:$0032) Stage
This is the first value found in reVamp's room editor. Ex., 02:01.02. This gets displayed plus 1.

$0035(U:$0033) Block
This is the middle value found in reVamp's room editor. Ex., 02:01.02. This gets displayed directly. It is increased by 1 when walking through a door.

$0036(U:$0034) Sub-room
This is the third value found in reVamp's room editor. Ex., 02:01.02. This never gets displayed. These are not sequential. Walking down stairs decreases it. A safety check is in place to make sure if it's #$00 before going down stairs that it becomes #$01, yet most of the time the rooms are set so that doesn't happen.

$0037(U:$0035) Lives
Remaining lives. Note: the UI does not update until the tileset changes.

$0038(U:$0046) CHR 0
This is the first set of sprites loaded. This cannot be changed in reVamp. This affects Trevor's sprites. Spirit partners have different offsets, so you can't just change this to make Trevor look like Grant with a whip. In the PPU, this is the top set of tiles loaded on the left.

$0039(U:$0047) CHR 1
This is the second set of sprites loaded. This cannot be changed in reVamp. This affects Trevor's whip. In the PPU, this is the second set of tiles loaded on the left. Each of the CHR selects can be "cleared" by setting them to $7F.

$003A(U:$0048) CHR 2
This is the third set of sprites loaded. This can be changed in reVamp. This affects certain enemies and moving platforms. In the PPU, this is the third set of tiles loaded on the left.

$003B(U:$0049) CHR 3
This is the fourth set of sprites loaded. This can be changed in reVamp. This affects certain enemies and moving platforms. In the PPU, this is the bottom set of tiles loaded on the left.

$003C(U:$004A) CHR 4
This is the first set of tiles loaded. This cannot be changed in reVamp. In the PPU, this is the top set of tiles loaded on the right.

$003D(U:$004B) CHR 5
This is the second set of tiles loaded. This can be changed in reVamp. In the PPU, this is the second set of tiles loaded on the right.

$003E(U:$004C) CHR 6
This is the third set of tiles loaded. This can be changed in reVamp. In the PPU, this is the third set of tiles loaded on the right.

$003F(U:$004D) CHR 7
This is the last set of tiles loaded. This cannot be changed in reVamp. In the PPU, this is the bottom set of tiles loaded on the right.

$0040(J) IRQ Control
Write value to $F001 in VRC6 mapper.

$0040(U) Scanline IRQ Status
Read from register $5204. 

$0041(J) IRQ Latch HUD
Write value to $F000 in VRC6 mapper. Negated before writes. Lower y-coordinate for HUD.

$0041(U) Scanline Target
Write to register $5203.

$0042 IRQ Latch Ally Swap
Write value to $F000 in VRC6 mapper. Negated before writes. Set to 72 pixels above player, then alternates by 1 every step to create the ally swapping effect.

$0043(U:$003F) Default Drawing State
Default value written to $006A each step.

$0044 Score (R)
Bytes $0044 through $0046 hold the score formatted in decimal.

$0048(U:$003A) Spirit Partner
Sypha is #01, Grant is #02, Alucard is #03, Trevor solo is #FF. 

$0049(U:$003B) Spirit Swapped
This is set when Trevor swaps places with his partner.

$004A(U:$003C) PC Health
Max value is #40. One bar is equal to 4 HP.

$004B(U:$003D) Boss' health
During boss fights, this is the same as $067C, otherwise it's #40.

$004C(U:$003E) Score Target
Target value for $0046 to get an extra life.

$004E(U only) Alternate CHR Bank
Alternate CHR4 to use in Hard Mode.

$0053(U:$0056) View Position (Word)
This is the view's coordinates in the room. In horizontal stages, this is the xview, but in vertical stages it's yview.

$0055(U:$0058) View Position Subpixel
Used for when Trevor's hspeed isn't 1 or 2 exactly.

$0056(U:$0059) Spawn Area Left
This is essentially every 32 pixels in the view, but set outside the view. So when xview is #00, this is #FE. Only gets checked when walking left.

$0057(U:$005A) Spawn Area Right
Same as above, but this one is for the right. 

$0059(U:$005C) TSA Row Iterator
Used to track which row of tile assemblies is being loaded.

$005A(U:$005D) Tile Assembly Definitions (W)
Prefectched ddress of current tile assembly definitions.

$005C(U:$005F) Tile Assembly Pallets (W)
Prefetched address of current tile assembly pallets. Pallet definitions themselves are single byte values. Least significant nybble is top-left tile and most signficant nybble is bottom-right tile.

$005E(U:$0061) Tile Assembly Nametable Address (W)
Nametable address for next row of tiles to be written to PPU.

$0060(U:$0063) Tile Assembly Value
Fetched tile assembly value. Multiplied by 16 and added to $005A.

$0061(U:$0064) Transition Load Delay
Set to #0C whenever a new tileset is loaded, then counts down.

$0062 Movement
This is set according to Trevor's movement. If he walks left, this gets set to 0; if he walks right, it's set to 1. It will constantly toggle back to 2, possibly at the start of each step.

$0063 View Edge Previous
Previous edge of view. Used to track tile and spawner refresh times.

$0064 Update View
Set whenever the view has moved.

$0065(U:$0068) Room orientation
Setting this to anything less than $80 means the room is oriented horizontally. Setting this to $80 or greater means the room is oriented vertically. The chapel in stage 1 is set to $80. (More details in ROM addresses below.) Since there are no doors in vertical stages, this also affects how close to the edge of the screen Trevor can walk to.

$0066 Stair Mapping (Word)
The PRG-ROM address for the index of values for any stairs in the current room is stored here. 

$0068 Transition State
In door-to-door room transitions, this is the substate. 0 sets up the transition, 1 is a slight delay before the transition progresses, 2 is the first scroll, 3 is a slight pause, 4 is the opening of the door, 5 is Trevor walking, 6 is the closing of the door, 7 is another pause, and 8 is the final scroll.

$0068 Trevor's phase counter
Appears to be a phase counter used during partner changes. Cleared when walking through a door.

$0069 Event object
I think this keeps track of which instance is currently being handled. Since X will change when a projectile is thrown, for example, the program needs to keep track of which value of X points to the instance that created said projectile. When the room starts, this is used to keep track of how many interactive terrains are in the room and is stored for each of those terrain objects.

$006A(U:$006D?) Active Drawing State
Appears to be a state machine for handling some drawing. Does not affect status bar, though.
 
$006B Object View Scroll Speed
This is dependent upon the room orientation. If the room is oriented horizontally, this value is subtracted from the x-coordinates of all instances except Trevor. If the room is oriented vertically, this value is added to the y-coordinates of all instances except Trevor. If Trevor's in the middle of the view, of a room with multiple screens, this value is added to his x-coordinate in a horizontal stage.

$006C View Offset (W)
The game has to tell the NES how far to shift the tiles over. This is how it does it. When Trevor moves, it increases or decreases and the value is passed to register $2005.

$006E Room Size
Signifies number of screens a room spans. One screen is technically 256px x 192px, or 48 tile assemblies. Compared against xview for horizontal stages or yview for vertical stages. 

$006F CHR Bank Mode
If set to #00 or #03, will load all CHR banks as set in $0038 thru $003F. If set to #01 or #02, will force tilesets #41 and #42 into banks 5 and 6 for the status bar, and will also clear banks 2 and 3 (rendering NPCs invisible) if set to #02.


$0070 Previous Orientation
The previous room's orientation is stored here. This is used in room transitions. Roundabout method. If it's negative, the previous room was vertical, which apparently affects what the next room is. Negative $0065 overrides this always.

$0071 Music Loaded
Set when stage music starts playing.

$0072
Unknown.

$0073 Horizontal Spawner Block
Initially set to the lowest spawner block (those 64px wide divisions that can only hold one spawner), which is determined by the view position. The value is used as an index pointer for the spawner database. This is also the ID of enemy spawners.

$0074 First Spawner Position
Coordinate of leftmost spawner block. Checked after view moves 64px.

$0075 (U:$78) Boss lock
This will freeze screen movement when a boss is present.

$0076 Vertical Spawner Block
Next section of a vertical room to load enemies in. If moving into the specified section, loads the next section of the vertical room.

$0077 Vertical Spawn Reset?
No idea what this is for. In some rooms it goes up along with $0076 as things are spawned in, but in other rooms it stays at 0. In auto-scrolling rooms, $0076 is set to this after spawning and it is never referenced again.

$0078 Horizontal Spawn Count
There are 8 spawn sections per screen in a horizontal room, so this value is $0063*8+8. This is used to prevent the spawner algorithm from trying to read beyond the right edge of the room.

$007A Animated backgrounds
Set for stages with animated backgrounds. The value denotes parallax scrolling or which tiles to change. Seems to hold two values (suggested by &#$F0 operation).
NOTE: STAGES WITH PARALLAX BACKGROUNDS (i.e., clouds) CANNOT HAVE ANY INTERACTIVE TERRAIN OBJECTS IN THEM BECAUSE PARALLAX CLOUDS OCCUPY THE SAME RAM OFFSETS AS TERRAIN OBJECTS. 

Known values:
  $10  Stormy Clouds (3-02)
  $11  Wide Clouds (Forest)
  $12  High Clouds (Castle Keep)
  $13  Low Clouds (Castle Keep)
  $20  Auto Stairs (Forest Ruins)
  $21  Auto Door (Forest Exit)

  $30  River + Waterfall (Causeway)
  $31  River + Waterfalls (Castle Tower)

  $40  Clockwork (Dracula's Tower)
  $41  Noisy Clockwork (Clocktower)
  $50  Watery Death (Sunken City)
  $51  Watery Death (Sunken City)
  $52  Watery Death (Sunken City) 
  $60  Watery Death (Sunken City, multiple pools)
  $71  Rising Water (Sunken City)
  $80  Collapsing Bridge (Causeway) 
  $81  Collapsing Bridge (Main Hall)

For the Watery Deaths, the lower bits set the depth at which the splash occurs. For #$5X range, these values are adjustable at PROM address 0x38C5D to  0x38C60. For the #$6X range, these are hard-coded, with #$60 being at depth #$C0 as defined in PROM address 0x38C2F, whereas any other value is the default screen depth of #$E0 (in other words, #$61 to #$6F are junk ranges and I have no idea why they are there other than as remnants of previous code).

$007B(U:$007E) Timer (Word) 
Converted into decimal and stored here. What you see is what you get. 

$007D(U:$0080) Wounded timer
Set when Trevor takes damage and becomes invincible. It counts down each step if set. While set, every other step toggles Trevor's visibility state.

$007E(U:$0081) Damage received
When an enemy hits Trevor, the damage level is temporarily stored here.

$007F(U:$0082) PC Height
This is the player's object index, increased by 4 when ducking, but not jumping. Set to #08 when Alucard is in Bat form. Used to determine where the top of the hitbox will be for each character.

$0081(U:$0084) Hearts
The game converts the heart count to decimal format before storing to this address. The highest this can be is 99 (hard-coded).
                                                                                                                                                        
$0082(U:$0085) Trevor's Subweapon
Axe is $01, Cross is $02, Dagger is $03, Holy Water is $04, Sypha's fire is $05, Sypha's ice is $06, Sypha's water is $07, Grant's dagger is $08, Grant's axe is $09, Alucard's fireball is $0A, Stopwatch is $0B.

$0083(U:$0086) Ally's Subweapon
Same as above, but for the current ally.

$0084(U:$0087) Trevor's Multiplier
Subweapon multiplier level for Trevor.

$0085(U:$0088) Grant's Multiplier
Subweapon multiplier level for Grant.

$0089(U) Status Bar Cutoff
Scanline value to start drawing room view.

$0088(U:$008B) Conveyance
When  terrain (conveyor or mud) hinders Trevor's movement, this gets set
  $01  Riding platforms or frozen enemies
  $02  Can only walk right
  $03  Uknown/No effect
  $04  Unknown/No effect
  $05  Teeter-Totter
  $06  Gears
  $07  Mud
  $08  Waterfall
  $09  Convey right under waterfall
  $0A  Convey left
  $0B  Convey right
  $0D  Petrified 
  $0E  Auto-Walk

$0089(U$:008C) Spark Timer
Controls when the spark from hitting an enemy disappears.

$008A(U:$008D) Rooom Initialized/Load Tileset
Set when (re)starting room, lets program know to load tileset.

$008B(U:$008E) Whip level

$008C(U:$008F) Alucard Orb Level


$008D Knockback direction
Set to determine direction Trevor gets knocked back when wounded.

$008E Conveyor
When Trevor's movement get affected by some object (enemy or terrain), this gets set to the spawn ID and used to knock back or lift Trevor. Only used by a few objects.

$0090 Gear Tooth Proximity
When on a gear, this gets set based on Belmont's proximity to the nearest gear tooth. A value of 1 means the tooth is either to the right or below. A value of 2 means the tooth is to the right and below. A value of 0 means there are no teeth in proximity. This is meant to dictate how the gear actually affects player movement.

$0091 Gear Tooth ID
For gears, this is the value of the tooth closest to Trevor.

$0092 Gear Size
Denotes if on a small gear (0) or big gear (1) when riding gears.

$0099 Subweapon Count
Counts how many times a subweapon is used on candles and enemies. Small hearts become multipliers when this gets high enough. Resets whenever a weapon or multiplier is grabbed.

$009A Grant Jump Cutoff
Tells the game when to cut off Grant's jump height.

$009B Subweapon Iterator
Used by system to loop across all subweapons checking for collisions. Ignore it.

 $009C Game State Previous
Temporary holder for $002C when collecting whip upgrade.

$009D PC Direction Recent
Temporary holder for $009E when collecting whip upgrade.

$009E PC Direction Previous
Temporary holder for $0062 when collecting whip upgrade. Yeah, it gets confusing. 

$00A0 In-Game Step Counter
Similar to $001B, except only incremented while game is not paused.

$00A2 Odd Tile Check
Set if the right tile is checked in a tile map read.

$00A3 thru $00A6
Temporary holder for $0040 thru $0043 when changing characters.

$00A7
Temporary holder for $2C when changing characters.

$00A8 Stopwatch status
Set when the Stopwatch is used. Prevents player pausing.

$00A9 Stopwatch timer
Counts down when Stopwatch used. Also affects sound effects.

$00AA Potion Timer
  Invinicibility Potion timer.

$00AB Bat Timer
Set to 1 when Alucard turns into a bat. Counts down while Alucard is a bat. When it reaches 0, decreases hearts by 1 and resets to #3C (1 second).

$00AC Landing Delay
When falling off a frozen enemy or when walking off a floating platform, this timer gets set and decremented. Prevents simply walking across floating platforms or frozen enemies.

$00AD Force Doppelganger Sprites
Forces sprite CHR bank write for Doppelganger.

$00AE Reference Cache
Used to save X register or PROM page pointers temporarily. 

$00AF
Unknown

$00B0
Related to the Stopwatch, it seems. 

$00B4
Gets set momentarily when colliding with a whip powerup.
On the Name Entry and Password screens, this is a counter for the fade-in and fade-out transition codes. The corresponding values added to each palette entry are: #$00, #$F0, #$E0, #$D0, #$C0, and #$FF. The #$FF marks the break. All this does is shift the palette entries up one row to darken the colors. If a value becomes negative, the entry is set to $0F (black).

$00B5 Platform Current
Set when landing on a floating platform or frozen enemy. Used to prevent walking across elevators or frozen enemies.

$00B5
On the Name Entry and Password screens, this is the timer between steps in the fade-in and fade-out transition codes.

$00B6 Rough landing
If Trevor falls from too high up, this gets set when he lands, preventing movement until it ticks down. 

$00B7 Boss fight
This gets set depending on which boss is fought.

$00BC Death pause
When Trevor dies, this gets set to #$80 to prevent damage calculations and pause the game while Trevor goes through his death animation and the room restarts.

$00BD
Unknown

$00BE
Unknown

$00BF
Unknown

$00C1-$00C2 Swapping Disabled(?) (REMOVED?)
Disables partner swapping when set. Gets reset to 0 when changing rooms. I haven't found code that sets it to anything other than 0.

$00C5 Horizontal lock
When this is set, the view will not move left, preventing Trevor from going less than 16 pixels from the left edge. This is set when a crumbling bridge is encountered, for example. This is not set by bosses.

$00C7 Flood Height
Height of water in flooding rooms.

$00C9

$00CA

$00CB Enemy drop counter
Incremented and checked when random check passes on enemy death ($001B & $07). When less than $05, enemies that pass the check drop a small heart. Every fifth enemy that passes the check has a 50% chance of dropping an Axe, 25% chance of dropping a Dagger, and 25% chance of dropping a Stopwatch. If Trevor already has the subweapon, a small heart is dropped instead. Potential drops are stored in PRG-ROM $04:BE93 thru $04:BE96 (see Item drop below).

$00CC Conveyance Previous
Holds previous value of $0088.

$00CD Vertical room ceiling
For vertical stages, this is the height at which Trevor will bump his head. Tile collisions will always return #$00 in that case.

$00EF Audio Sample
Temporarily holds currently passed audio value, which could be a track or DCM sample.

$00F0 Broken Luminary Tracker (R)
Tracks which luminaries have been broken in the current room. Prevents respawning luminaries.

$00F4 Breakable wall status (R)
This gets set to FF for each breakable wall in a block that gets destroyed. The variable that determines if a wall can be destroyed is set based on this. Along with the other variables between $00F0 and $00F7, this gets reset when changing rooms obviously.

$00F8 Controller Press Previous (R)
Supposed to hold previous inputs for detecting when buttons are released. Instead, just treated as a duplicate used when pausing or unpausing the game.

$00FA Controller Hold Previous (R)
Same as $002A, but used to set $0028.

$00FC(U:$006F) PPU Scroll Value (Word)
Value written to PPUSCROLL register.

$00FE PPUMASK Value
Value written to PPUMASK register. Handles color emphasis, edge clipping, and layer visibility. See NESdev.org for more info.

$00FF PPUCTRL Value
Value written to PPUCTRL register. Handles some of the stuff you shouldn't mess with. See NESdev.org for more info.

$0300 Tilemap (R) (C)
The TSA map is dumped here. The tile map is generated on the fly. The TSA map for the current stage is loaded into the PRG-ROM bank and evaluated on a tile-by-tile basis. The tile values correspond to their relative offset in the PPU. Tiles of value #$C0 or higher fall under the "universal interactive" category (in other words, spikes). This range of tiles is actually reserved for common sprites, but stationary spikes are included in this subset. Below is a list of value ranges used to determine the tile map.
    $DC - $DD Ceiling Spike
    $DE - $DF Floor Spike
    $E4 - $E5 Trap Door (counts as empty)

$0347 Palette (R) (C)
The background palette is stored here.

$0400 Image single (R)
Just making up names here. This is the actual frame displayed, whereas the image index is the offset for the address this points to. So sprite displayed is offset by image_single+image_index.

$0418 Subweapon Icon Image Single
Subweapon icon image.

$0419 Multiplier Icon Image_single
Subweapon multiplier image.

$041A (Word)
Unknown. Gets cleared when $002C==#$08 or #$1B.

$041C Y-coordinate (R)


$042F Whip Y-coordinate
This gets increased by 8 when ducking (but not jumping, since Trevor stands when jump-attacking).

$0434 Y-coordinate of subweapon icon


$0436 Y-coordinate of Breakable Blocks (W)


$0438 X-coordinate (R)


$0438 X-coordinate of Breakable Blocks (W)


$0450 X-coordinate of subweapon icon


$0454 Palette Offset (R)
Not the actual palette. Used for palette cycling.

$046C

$0470 Attributes (R)
Care when editing these. For Trevor, $00 is visible and $80 is invisible. Collecting a whip powerup will force this to #$00 so Trevor is visible during the shimmer effect. For luminaries, this seems to just be the type. For enemies, this determines if the enemy will move or stand still, be visible, or even interact with Trevor at all. Each bit serves a specific function:
 $HGFEDCBA
  A  Destroyed 
  B  Frozen
  C  Unknown
  D  Forces byte H
  E  Illusion
  F  Unanimated
  G  Moving
  H  Invisible
Clearing the lower nybble seems to have no effect for enemies. The lowest bit of the lower nybble should never be set (i.e., no odd numbered values), as this will instantly destroy the enemy. The lowest bit of the upper nybble will render the enemy illusionary -- Trevor will not be able to attack it, nor will it be able to attack Trevor. For some reason, enemies like Sword Skeletons set bit F when attacking, probably some unknown mechanic that made it necessary. Not sure what bit C is for. It's set for most enemies. It's cleared for Medusa Heads.

$048B
Unknown

$048C Sprite Page (R)
This determines which row in the PPU to read. Probably shouldn't mess with this.

$04A5

$04A8 X-scale (R)
Sprites face left in the ROM, so a value of 0 flips the sprite so it faces right. This is unnoticeable with torches and lanterns, but does have a slight effect on candles.

$04C0

$04C4 Fractional X-coordinate (R)
When integral speed is added to the X-coordinate, the X-coordinate increases, but not when a fractional speed is added (e.g., X=0; X+1/4=0). So what happens to that fractional speed? It gets added to this instead, which rolls over to the X-coordinate when the carry bit is set..

$04DB Fractional Y-coordinate (R)


$04F2 Integral horizontal speed (R)


$0505
Part of a partner swap counter, it seems. Adds #$10 to the hit alarm when it reaches 8.

$0509 Fractional horizontal speed (R)
Any speed value less than 1 is stored here as an 8-bit floating point (e.g., a speed of 1/4 will set this to #40, since #100 / 4=#40).

$051C
Denominator of partner swap counter (see $0505).

$0520 Integral vertical speed (R)
Very important. Not only does it move the instance, it is checked when climbing stairs.

$0537 Fractional vertical speed (R)


$054E Object index (R)
This is the same as $0048 for spirit partners. Always keep luminary values between #$80 and #$82; all inappropriate values pose a risk of actually crashing the game. This variable determines object-specific data, such as which sprite to use.

$0561 Whip level
This is the number of whip upgrades collected.

$0565 Action state(R)
Don't mess with it, as it more than likely freeze up on you. Very important variable, at least for Trevor. It can have the following values:
    #02 Stand Idle
    #04 Walking
    #06 Jump Start (unique for Grant)
    #08 Jumping (unique for Grant)
    #0A Ducking (unique for Grant)
    #0C Falling (unique for Grant)
    #0E Walk To Stair
    #10 Start Climb
    #12 Stair Idle
    #14 Stair Climb
    #16 Stair Transition
    #18 Stand Attack (ignored by Grant & Alucard)
    #1A Jump Attack  (ignored by Grant & Alucard)
    #1C Duck Attack (unique for Grant & Alucard)
    #1E Stair Attack (ignored by Grant & Alucard)
    #20 Stand Item (Attack for Grant & Alucard)
    #22 Jump Item (Attack for Grant & Alucard)

    #24 Stair Item (Attack for Grant & Alucard)
    #26 Knocked Back
    #28 Petrified
    #2A (same as $28)

    #2C Pitfalling
    #2E Dead Animation
    #30 Alucard Henshin! / Grant Wall
    #32 Alucard POOMF! / Grant Ceiling
    #34 Alucard Bat / Grant Reach Ceiling-to-Wall
    #36 Alucard Bat Crash / Grant Hug Ceiling-to-Wall
    #38 Alucard Bat Bump / Grant Reach Wall-to-Ceiling
    #3A Alucard Ascent / Grant Hug Wall-to-Ceiling
    #3C Alucard Revert / Grant Reach Wall-to-Floor
    #3E Alucard POP! / Grant Hug Wall-to-Floor
    #40 Alucard River Push / Grant Reach Floor-to-Wall
    #42 Alucard River Drown / Grant Hug Floor-to-Wall
    #44 Grant Wall Hop
    #46 Grant Wall Attack
    #48 Grant Ceiling Attack

    #80
     .  Any above value ORed with #$80
     .  will freeze Trevor in that action
     . 
Values $06 and $10 are logical. When he jumps, Trevor doesn't apply horizontal movement on the first frame, so it's not until $08 that he starts moving. When transitioning from the ground to stairs, certain variables are set, so this transitional phase is handled by $10. Value $0C is only applied when falling off a ledge. For jumps, it's always $08 (or $1A for jump attacks or $22 for jump items). 
For bosses, this determines their next action, usually.

$0578 (R) Weapon phase
 Same role as $0565 for Trevor, this tells the weapon what to do. For Trevor's whip and Sypha's staff, it just tells them to update their coordinates.

$057C Image speed (R)
Counts down to 0 then changes image index upon rolling over.

$0593 Image index (R)
This one is most definitely close to image_index. When Trevor walks, it cycles {0,2,4,6}. 

$05AA Sprite offset? (R)
No clue what this is for, but it is set at the same time the PPU address is set for instances, so clearly it's related to sprites. Since it's usually greater than 8, I think it's a sprite definition offset.

$05C1 (R) Fall switch / Enemy State
Although this is a range, this specific use applies only to Trevor. When he falls, this is set to 1. This is so the game knows whether to increase the jump offset or decrease it (see below).
For enemies and lanterns, this is the current state (cf. finite state machines).


$05D4 PC State Previous
Holds Trevor's action state temporarily when hit or his x when changing partners.

$05D8 PC Jump State/ Fall height
For PC, this is set to 9 when jumping and increased each step, then stored in the Y register. This is used to retrieve the integral vertical speed. When the value retrieved for speed is $81, it decreases and the integral speed is inverted. When the value retrieved is $80, the speed is set to $06 and this address no longer changes. Upon landing, if this is $00 (in other words, integral speed is $06), the rough landing flag is set.
For Grant, this gets set to #1E at the start of a jump and increases by $61D every step. Once it equals #39, Grant abruptly falls.


$05D9 Item drop (R)
This is where candle drops are stored. Any value below $83 seems to crash the game, while values over $A0 cause graphical glitches. Here are the known useable values:
    $83 Axe
    $84 Cross
    $85 Dagger
    $86 Holy Water
    $87 Stopwatch
    $88 Sypha's fire
    $89 Sypha's ice
    $8A Sypha's water
    $8B Grant's Dagger
    $8C Grant's Axe
    $8D Upgrade 1 (upgrades whip to 1)
    $8E Upgrade 2 (upgrades whip to 2)
    $8F Nothing? (looks like whip upgrade but no effect)
    $90 Mystery Meat
    $91 Invincibility Potion (duration = $B4)
    $92 Rosary
    $93 100 Point Bag
    $94 200 Point Bag
    $95 400 Point Bag
    $96 700 Point Bag
    $97 1 k Point Bag
    $98 2 k Point Bag
    $99 4 k Point Bag
    $9A 7 k Point Bag
    $9B 10G Point Bag
    $9C 1UP
    $9D Big Heart
    $9E Small Heart
    $9F 2x Multiplier
    $A0 3x Multiplier
    $A1 Fake Candle (can be useful glitch)

$05D9 Boss timer (R)
This is set when a boss appears and then counts down before starting the boss battle. 

$05EB Hit alarm
Set to #$20 when Trevor is hit. Reverts to previous action when zeroed. Used as numerator in partner swap counter (see $0505).

$05EF Various / Enemy Class
Somehow affects room transitions for Trevor. On stairs, this is the direction he's facing, basically. Additionally, this is Grant's factional jump frame and is incremented by $606 when jumping.  Since $606 is always 0, this is never used.
For enemies, this is actually a pointer to the set of routines and subroutines to call every step, vis a vis $5C1,X. See notes about Enemy State Addressing.


$0602 Hit On Stairs
Cleared when PC is hit on ground, set when hit on stairs. Stuns PC until $5EB counts down.

$0606 Alarm / Starting Y (R)
Some enemies use this as an alarm, others use it to store the starting x or y coordinate for use in sinusoidal movement.

$0619 Ally Swap Y-Offset
This is used for the IRQ pass in conjunction with $0630. Don't sweat it.

$061A Subweapon Damage (R)
Similar to $0630, but used by subweapons.

$061D Stair Timer / Grant Jump Counter
This is the alarm that determines how long Trevor climbs stairs until the next input check. When Grant jumps, this is set to #01 while A is held, otherwise it is #02.

$061E Enemy timer (R)
This one is almost always a dedicated timer for enemies.

$0630 Whip damage
How much damage the whip deals, shifted 4 bits.

$0630 Ally Swap IRQ Toggle
When swapping allies, this toggles and is subtracted from $0619 to create the ally swap effect.

$0633 Counter (R)
For enemies like crows, this counts how many dives they attempt. 

$0645 Spawn ID (R)
For candles, this is the object index. For enemies, this is the spawner ID that spawned it.
For Death, this is his appearance timer (instead of using $7F3).

$0657 Damage (R)
This determines the level of damage, (light, normal, heavy) an enemy or projectile deals. Hard Mode and any stage from the Abandoned Mines upward will typically increase damage. Note that $0657 itself belongs to the $0645 set, as it was seemingly not needed for anything by PCs.

$0669 Damage received (R)
This is how much damage an enemy has taken from Trevor. Note that $0669 itself belongs to the $0657 set, as it was seemingly not needed for anything by PCs.

$067C Health (R)
This is duplicated for bosses. All enemies have health, even "indestructible" ones. A blood skeleton can be slain if enough damage is dealt to it, but time will probably run out before it dies.

$068D Weapon Hit Tracker (R)
Bitmasked for enemies when hit by the whip or subweapons. Ensures no weapon will hit the enemy twice in too short of a time span.

$06A0 Audio Stuff? (R)
I think this section is all audio stuff.

$06DC BGM Paused
Set when stopwatch activated. Prevents music from playing.

$06DD Boss Scream Cutoff
Counts up to #F0, then stops boss scream DPCM.

$06E0 Tile map (Word) (R)
The tile collision map is read by columns, starting with the leftmost column on the screen. Only the top-left tile of each metatile is read. It is refreshed so only the tiles in the vicinity are registered. The map is very simplistic. One Word is equal to one TSA. Each Word reads left-to-right, top-to-bottom in the TSA. The address is retrieved for y+16 (less 32 to account for the status bar). Words can be visualized like so:
  $ABCD 
corresponds to 
    AB
    CD
The following values exist:
    $0 Empty
    $1 Mud
    $2 Conveyor right
    $3 Conveyor left
    $4 Crumbling ledge
    $5 Ceiling Spike
    $6 Solid
    $7 Floor Spike
    $C Crumbling (increments to $F)
Each of these are treated as solids when approached from the side. Because of this, you cannot have mud on top of a conveyor and expect the conveyor to pull you through it, but it will pull you out if you sink to the conveyor at just the right spot. ("Pull out, Peggy! You hit an artery!") The conveyor flags apply to the blocks under the water, not the water itself (which is $0). Because of this, you cannot have water and crumbling ledges at the same time (as nifty as that would be). That's not to say you couldn't program such a gimmick, but it's just not already incorporated. You can put mud over a collapsing ledge, if you wanted to for whatever reason. Trevor would have to jump out of the mud to avoid from falling. Crumbling ledges do not automatically disappear and falling ledges do not automatically fall. These addresses only affect the collision states. The spikes are essentially the same. I don't know why they have two separate values, as touching either of them from any direction will kill you. Any of the other solids can be placed over these, although only mud or crumbling blocks would make sense over a spike.

$0770 Solids definition (R)If a room has special tiles (such as conveyors or mud), their offsets are stored here. Byte $0776 and $0777 are always #$80. Bytes $077E and $077F are always #$C0. Bytes $0770 thru $0775 define the lower region of tiles whose PPU offset is less than $80, while $0778 thru $077D define the lower region of the specific tiles whose PPU offset is less than $C0. Six instances of a PPU offset translate to a tile map value of #$6. In other words, if you wanted three of the tiles to be mud, you'd specify the range of tiles to be treated as mud in byte $0778. If you wanted no tiles from a specific half of the PPU, you'd set all corresponding bytes to that max offset.

$0780 Background Animation Frame
Bone Dragon King uses this; don't remember seeing it used outside of him. There are 3 frames of animation for CHR 5 in the clocktower and sunken city.

$0781 Background Animation Speed
Bone Dragon King uses this; don't remember seeing it used outside of him. This is how frequently the CHR 5 (half the background tiles) change during his fight.
 
$0782 Epilogue partner
Needs to be set before picking up Dracula's crystal, I think. This is the value read for determining offsets used in the epilogue. This is the same as $0048.

$0783 Epilogue State
Castle falls at #00. Trevor's cape flutters at #01. Screen fades and text scrolls at #02.

$0784 Castle Speed
Reverses castle horizontal speed every 2 steps as it crumbles.

$0785 Epilogue text offset
This increases with each pass of the epilogue timer. It is used to retrieve the index for the next line of text or the end of the epilogue.

$0788 Epilogue Scroll Timer
Counts up to #06 if Trevor is solo, otherwise up to #05, then resets. Shifts the PPU scroll to create the text crawl effect.

$078A Epilogue timer
This is how fast the next chunk of text is loaded into the PPU during the epilogue. Messing with the scroll speed means you may need to edit this as well (see ROM Addresses). Also controls time until screen fades after castle falls.

$078B Password Errors
Bitmasked errors during password decryption.

$0790 Interactive terrain index (R)
Seems to hold $0069 for gears and crushers. Maybe other objects as well. 

$0790 Path at fork (R)
When the road forks, four variables are set. They determine the sprites to use for the path marker on the mini-map. 

$0790 Password Icon Value (R)
On the password entry screen, each cell has a value of 3n and each icon has a value of 1, 2 or 3. The icon value is added to the cell value, which is essentially the password.

$079D Byte 8 (R)
I don't know what else to call this. It holds byte 8 of breakable blocks (see ROM Addresses). Since this is written when X is #$1A or #$1B (and X cuts off at #$1C), only two values are found here and $7B8.

$07A1 Terrain screen
Seems to be a tracker for the current screen value relative to the first interactive terrain object.

$07A2 Active terrain
This is the number of interactive terrain objects (gears, crushers, breakable blocks, dripping water, etc.) in the view (horizontal stage) or the accessible room (vertical stages).

$07A7  Breakable Block Status (W)
Set to #$80 when the block is destroyed.

 $07B1 Dual-layer wall (R)
For breakable walls, this is set when the wall occupies two tiles. 

$07B3 Broken bottom tile (R)
For breakable walls, this is set to $FF when the lower wall is broken.

$07B5 Broken top wall (R)
For breakable walls, this is set to $FF when the top wall is broken.

$07B7 Wall ID (R)
This is the ID of the wall in the room, used to offset from $00F4. 

$07C2 Spawner offset (R)
This stores the ID of the enemy spawners. This is the same value as seen in reVamp. The value is shifted left 1 bit to retrieve the address indexed at $028533.

$07C8 Spawner count (R)
This gets incremented each time an enemy is spawned. This gets retrieved, shifted left, then used to offset the values retrieved by $7C2,X. For enemies that can only spawn once, this gets set to 1 when the enemy can be spawned and then cleared when once the enemy is spawned.

$07CE Spawn timer (R)
So far only used by non-flickering Ghost to delay spawning.

$07D4 Spawn y-coordinate (R)
This is the y-coordinate in the target screen for the spawner. This is where the enemy will be generated whenever the spawner code is called. Note that Spiders are hardcoded to start from #$30.

$07DA Spawn x-coordinate (R)
This is the x-coordinate in the target screen for the spawner. This is where the enemy will be generated whenever the spawner's code is called.

$07E0 Off-screen status (R)
This is cleared as long as the spawner is on the screen. As soon as the spawner leaves the screen (via x+screen_shift) this gets set, preventing its code from running. 

$07E6 Spawned X register (R) / Instance value 1 (R)
This stores the X register value used when an enemy was successfully spawned. When a spawner is first loaded, the first of any special instance-specific value is loaded here.

$07EC Bone Dragon King Frames (R)
Range is through $07F1. The head is always 1. Each of the 11 ribs has its image_index stored here, 1 nybble per rib.

$07EC Various
This increments slowly for Bone Dragons. It's used to handle movement.
For the Giant Bat, this stores the instance ID of the main bat.
For Big D, this is his form (0=sorceror, 1=floating heads, 2=Pazuzu).


$07ED Various
This controls how many blocks comprise a collapsing bridge. 
When a Bone Dragon is present, this controls the xscale of the ribs and fireball.
For the Giant Bat, this is the current state of all bats (not sure why it uses an extra byte).

$07EE Bone Dragon alarm
For Bone Dragons this counts down from $30. When it reaches 0, the Bone Dragon opens its mouth and this is set to $10. After the Bone Dragon spits, it's set to $80 and the Bone Dragon closes its mouth.
For Death, this is the number of scythes he can throw.

$07EF Bone Dragon spit
When the Bone Dragon finally attacks, this is set to #$01 briefly and the fireball is generated on the next pass.

$07F3 Boss State
Bit confusing to call it this. It's set to #$80 when the boss first spawns and while set to this it waits until Trevor is in range of the boss, at which point it is set to #$00 when the boss is active. When the boss dies and goes through its death sequence, it's set to #$01. When the boss is finally destroyed and the soul shard is supposed to drop, this gets set to #$02. When the soul shard finally appears, it's set to #$03.

$07F6 Hard mode
This is set when you play in hard mode. It's also used in password generation.

$07F8 Name (R)
Bytes $07F8 thru $07FF store each letter of the name, with A=$50, B=$51, and so on.



Some ROM addresses!


Scene Tiling
For stages, tile square assemblies are used (see below), but for simple aesthetics, tiles are placed individually row by row. There are shortcuts, however. When a tile is put in the room repeated 4 or more times, two values are used. The first value specifies how many tiles to draw, while the second value specifies which tile to draw. Afterwards, either another repeating tile is written or the next address in the PPU is set to a value greater than $80. The difference between that value and $80 is how many tiles will be specified individually, beyond which point the next value is a repeated tile. So for example:
    05 DE 81 B1 10 00 04 DE 82 8A 8B
In the above example, first tile $DE will be drawn in the room 5 times. After the fifth one is drawn, tile $B1 will be drawn next. After that, tile $00 will be drawn 16 times. Then tile $DE will be drawn 4 more times. Finally, tiles 8A and 8B will be drawn. Below are some scene addresses tiled as such. Below each scene's tile map is the CHR data as well. Loading $7F into a CHR select will result in a blank tile set.
    $033651 Intro Castle
      $00646F CHR 4
      $006473 CHR 5
      $006477 CHR 6
      $00647B CHR 7
        CHR 0 thru CHR 3 are set to #$00 and #$01.
    $00B552 Title Screen
      $006BC7 CHR 3 (path markers make up the lightning here)
      $00647F CHR 4
      $006480 CHR 5
      $006481 CHR 6
      $006482 CHR 7
    $00B552 Main Menu (yes, it's the same as Title Screen)
      $03E3BE CHR 0
      $03E3C2 CHR 1 (CHR_0+1, can't be changed easily)
      $03E3C6 CHR 4
      $03E3CA CHR 5
      $03E3CE CHR 6
      $03E3D2 CHR 7
    $007BE3 Name Entry
      $007414 CHR 0
      $007415 CHR 1
      $007416 CHR 2
      $007417 CHR 3
      $007418 CHR 4
      $007419 CHR 5
      $00741A CHR 6
      $00741B CHR 7
    $033302 Password
        Same CHR set as Name Entry
    $00668D Prayer
      $006547 CHR 0
      $00654B CHR 1
      $00654F CHR 2
      $006553 CHR 3
      $006557 CHR 4
      $00655B CHR 5
      $00655F CHR 6
      $006563 CHR 7
    $02BDFB Epilogue
      $02B02B CHR 0
      $02B02F CHR 1
      $02B033 CHR 2
      $02B037 CHR 3
      $02B03B CHR 4
      $02B03F CHR 5
      $02B043 CHR 6
      $02B047 CHR 7

Text
The prologue handles a little differently than the title screen. The border around the title screen is drawn. Each line of text is preceded by $80 for a line break and then the x-position of the first tile in that line, with $00 meaning no text. So $80080F would mean a new line is started and tile $0F would be drawn at x:#$08 of that line. At the end of the code, $8100 denotes a page break. Below each text address is the CHR 4 thru CHR 7 range loaded at the time. Diacritics (in Akumajou Densetsu) are drawn on the previous line, but written immediately after the character they follow.
    $03DC1D Prologue Paragraph 1
      $006483 thru $006486
    $03DD12 Prologue Paragraph 2
      $006487 thru $00648A
    $03DDEC Prologue Paragraph 3
      $00648B thru $00648E (Whip)
    $03DEA0 Prologue Paragraph 4
      $00648F thru $006492 (Bust of Trevor)
    $03DF65 Prologue Paragraph 5 (lots of line breaks here)
      $006493 thru $006496 (Trevor overlooking Castlevania)
      $006497 thru $00649A (font)
The final 12 bytes of CHR addressing are the same as $006493 thru $006496.
The epilogue text is handled quite differently. This time diacritics are handled on separate lines. Each line is assigned an absolute PPU address (written in reverse byte order). When the end of a line is reached, the value $FE is written. When a pause between lines is needed, $FF is written (I think). The same CHR values are used throughout the epilogue.
      $02B203 CHR 0
      $02B207 CHR 1
      $02B20B CHR 2
      $02B20F CHR 3
      $02B213 CHR 4
      $02B217 CHR 5
      $02B21B CHR 6
      $02B21F CHR 7
    $02B95E Epilogue Part 1 (generic)
    $02BC2D Epilogue Part 3 (Grant)

TSA Definitions
TSAs are stored in the ROM left to right, top to bottom, row by row. Solid black is routinely PPU address $00 while solid "sky" is $3D. Each TSA section is preceded by the tile maps for each stage (see below).
  $0182D0 - $187CF Catacombs
  $018EDB - $19EDA Abandoned Mines
  $01A2FB - $1A8FA Main Hall
  $01AC9A - $1B269 Inner Hall
  $01B592 - $1BD51 Castle Keep
  $01C459 - $1C9B8 Causeway
  $01CD94 - $1D143 Swamp
  $01D78E - $1DD8D Alucard's Cave
  $01E3BE - $1E9BD Sunken City
  $01EDFA - $1F3C9 Lookout Tower
  ??????
  $020451 - $20D60 Wallachia
  $02141A - $21965 Clocktower
  $022120 - $2263F Forest
  $022C7D - $232BC Ghost Ship
  $023737 - $23BB6 Tower

TSA Maps
Each tile map is preceded by a byte specifying the size of the room. So $200BA is set to #$02 since the first room takes up 2 extra screens, $2014B is set to #$00 since the next area doesn't take up any extra screens. One vertical screen is 64 bytes. One horizontal screen is 48 bytes. Tile maps read left to right, top to bottom, row by row. Stage 1 is expanded here as an example. For all other addresses, refer to reVamp's room editor (it shows the ROM address for each TSA in the room. Rooms, like stages, are not mapped out in order.
  $020039 Stage 1-02:1 size
  $02003A - $200B9 Stage 1-02:1
  $0200BA Stage 1-01:0 size
  $0200BB - $2014A Stage 1-01:0
  $02014B Stage 1-02:0 size
  $02014C - $2017B Stage 1-02:0
  $02017C Stage 1-02:2 size
  $02017D - $201DC Stage 1-02:2
  $0201DD Stage 1-02:3 size
  $0201DE - $2026D Stage 1-02:3
  $02026E Stage 1-03:0 size
  $02026F - $202FE Stage 1-03:0
  $0202FF Stage 1-03:1 size
  $020300 - $2038F Stage 1-03:1
  $020390 Stage 1-04:0
  $020391 - $20450 Stage 1-04:0
  $01802B Catacombs
  $01886D Abandoned Mines
  $019FF6 Main Hall

Stage CHRs
The CHR for each stage is pretty easy to find in the ROM, as they're in order according to stage, block, and room. CHR 0 is always set to #$00 and CHR 1 is simply CHR_0+1, although these values can be easily modified. CHR 4 is always set to #$40 and CHR 7 is always set to #$43, but these can be modified too.
  $00001F CHR 0
  $00001B CHR 1 offset from CHR 0
  $000F4F CHR 4
  $000F53 CHR 7
  $000275 CHR 2 | CHR 3
  $00018C CHR 5 | CHR 6
The values of CHR 5 and CHR 6 are indexed as Words, with the upper byte used for CHR 6. The range from $00018C to $000274 should include CHR 5/CHR 6 pairs for all levels in order, but this hasn't been tested. Likewise with CHR 2/CHR 3.

Solids Definitions
Solid tiles are pretty easy to define, but care is needed since the number of bytes required to define the solids for each room is dependent on the variety of solids present in that room.
  $0003D2 PRG-ROM Index
  $00042C Definitions
All the definitions are within the $00:84XX block of the PRG-RAM (by default). All the definitions follow a simple format of one WORD per solid. The lower byte specifies how many times the solid type, determined by the upper byte, should occur in the Solids Definition in the RAM. It then moves onto the next WORD. The sum of the lower bytes cannot exceed 8. The game will increment the X register by 1 every time a value is written to the RAM, which it then ANDs with #$07, branching to the second set of solids definitions and repeating the process. Special consideration is given to Pazuzu's lower tile group ($33), a Konami logo ($36) and a font ($37). The latter two apparently go together, but I don't know when they're actually used -- possibly the ending credits. The standard font is $41 and Konami logo is $72.

Unfortunately, the solid definitions for each CHR set are hard-coded, requiring them to always be laoded into CHR Bank 5 EOR CHR bank 6, but never interchangeably. For example, CHR #45 (bank 5 in the first stage) has solids defined at #7e, so if bank 6 is set to #45, all tiles from bank 6 will be solid, since they are all greater than #7E. Similarly, setting bank 5 to #47, which defines solids at #B7, will result in all tiles from bank 5 to be not solid.

The number of actual solid definitions is limited by default, so you should try to restrict yourself to following any of these. Background CHRs start at #44, so these are indexed by
$0003D2 + (CHR_ID - #44) in the CV3j ROM.
  $841C #0880             Bank 5, no solids
 
$841E #06BE02C0         Bank 6, #BE+ solid
 
$8422 #067E0280         Bank 5, #7E+ solid
 
$8426 #06B702C0         Bank 6, #B7+ solid
 
$842A #06B902C0         Bank 6, #B9+ solid
 
$842E #06B802C0         Bank 6, #B8+ solid
  $8432 #04B802B902C0     Bank 6, #B8 collapses, #B9+ solid
 
$8438 #067A0280         Bank 5, #7A+ solid
 
$843C #067C0280         Bank 5, #7C+ solid
 
$8440 #02B601B703B802C0 Bank 6, #B6 right, #B7 left, #B8+ solid
 
$8448 #06730280         Bank 5, #73+ solid
 
$844C #01B405B702C0     Bank 6, #B4-#B5 mud, #B7+ solid
 
$8452 #04B202B402C0     Bank 6, #B2-#B3 collapses, #B4+ solid
 
$8458 #04BA02BB02C0     Bank 6, #BA collapses, #BB+ solid
 
$845E #06A002C0         Bank 6, #A0+ solid
  $8462 #06B802C0         Bank 6, #B8+ solid same as $842E
 
$8466 #067C0280         Bank 5, #7C+ solid same as $843C
 
$846A
#04B802B902C0     Bank 6, #B8 collapses, #B9+ solid same as $8432
 
$8470 #04B202B302C0     Bank 6, #B2 collapses, #B3+ solid
 
$8476 #04B702B802C0     Bank 6, #B7 collapses, #B8+ solid
 
$847C #06B802C0         Bank 6, #B8+ solid same as $842E
As you can see, there are no Bank 6 sets with no solids. However, since there are duplicates, you could replace any of them with #08C0. Also, $8452 is an oddball in that it seemingly defines 2 tiles as collapsible, but the second tile is actually blank, as can be seen in set #5D. Similarly, $845E has an expansive set of solid tiles, but 45% of them are blank.
 


Palette sets
Most palette entries only hold 3 values and the game loads these three into the placeholders. Editing the background palette placeholder in reVamp automatically affects all other background colors, but by editing the ROM data directly, it's possible to set 4 different background colors. The palette sets for background colors contain 3 palettes per group. Intro, prologue, name, and password screens have their own separate palettes.
  For the preset sprite palettes, sets 1 and 2 are listed first (Trevor and relics), then #$0F0F0F0F as a placeholder for the room-specific sets, then set 4 (candles and hearts). Only the three colors unique to sprite palette entry 3 for each room is stored.
  Trevor's first color is the default background color apparently. After tweaking with background palettes in reVamp and searching for changes in the ROM, Trevor's palette was the only thing that changed. That really sucks. 
  $4BE Palette script
  This is the start of the palette loading code. 
  $00066F Palette set used (R)
  This is actually stored in order, addressed incrementally when rooms changed. The order of palette sets used will be sequential regardless of room index. Clocktower decrements when climbing back down, even though reVamp treats them as separate rooms.
  $6DE Status bar
  This is quadruplicated as a placeholder. Of course the first value is the status bar's palette always.
  $0006EF - $0006F5 Set #$00
        thru
  $000869 - $000871 Set #$2A
  $0008EF Trevor
  $0008F3 Relics & skeletons
  $0008F7 Room palette placeholder
  $0008FB Hearts and candles
  $000900 Grant
  $000926 Set #$00
        thru
  $000983 Set #$18

Background Music
The track order can be changed in reVamp easily enough, but known values will get posted here. NSF values will not be here... probably. Values get all wonky after using reVamp's Change Tracks function. Will need to test byte values later. Changing more than one or two at a time causes some weird readings in ExamDiff. These pairs are a map, not the music itself.
  $031010 Wallachia
  $031012 Black Forest
  $031014 Causeway
  $031016 Marsh
  $031018 Clock Tower
  $03101A Sunken City
  $03101C Tower of Terror
  $03101E Ship of Fools (2 bytes?)
  $031020 Alucard's Cave
    $AD92 Beginning
    $FD92 Clockwork
    $C192 Mad Forest
    $D592 Stream
    $E992 Dead Beat
    $1193 Aquarius
    $2593 Rising
    $3993 Anxiety
    $4D93 Nightmare

Damage Amounts
This is how much damage enemies and traps do. Damage values start at #$00 for 1 damage.
  $0382E8 Weak attacks (Trevor)
  $0382E9 Normal attacks (Trevor)
  $0382EA Strong attacks (Trevor)
  $0382EE Dull spikes (Trevor)
  $0382F6 Sharp spikes (Trevor)
  $0382F8 Weak attacks (partners)
  $0382F9 Normal attacks (partners)
  $0382FA Strong attacks (partners)
  $0382FE Dull spikes (partners)
  $038306 Sharp spikes (partners)
Damage levels for each enemy are stored in a list. The specific damage level is retrieved by subtracting #$38 from the object_index and then adding #$20 to that value if either Hard Mode is set or the current stage is #$0A (Abandoned Mines) or greater. 
  $02E03D  Damage (R)


Enemy Spawner
The program will check each enemy instance's object_index ($054E,X). When a match with the designated object_index is found, local var $000E is incremented. Upon verifying each object_index, it compares $000E against the value stored in $000D (which is hardcoded as #$03). If $000E<$000D, it looks for an available spot in the object_index list within a(n optionally) specified range. The program then clears all the preset RAM offsets within the current X register's range. Next, it sets the coordinates, object_index, and behavior. It then retrieves the enemy's health and damage.
  $028DD2(U:$028E65)  Multiple Object Limit
  $028533(U:$028537)  Address Map for Spawner Behaviors
Each step the game will retrieve the spawner's offset value and retrieves an address. It then takes the spawn count and uses it to retrieve another address offset from the first address then executes the code there. If no enemy exists, this usually jumps to $8B90, otherwise it goes to $8BB0, I think. Script $8BB0 simply updates the position of the spawner.

For the most part,  spawner data can be edited in reVamp by right-clicking on a spawner in the room. The first three values can be edited in reVamp, but the fourth and fifth values are special values for enemies or spawners that need them (e.g., Ghosts, Fuzzbusters, Harpies, Bone Dragons, Bone Pillars, Crows); the fourth byte is for RAM offset $07E6 and the fifth byte is for RAM offset $07CE. Neither value can be edited in reVamp. In GameMaker terms, these two bytes are equivalent to assigning instance creation code to each spawner.
  $02A13E(U:$02A217)  Spawner Types Data
    Byte 0:  Spawner ID
    Byte 1:  Spawner x mod 64
    Byte 2:  Spawner y
    Byte 3:  Value for $07E6,X
    Byte 4:  Value for $07CE,X

Here is a list of each spawner ID and its corresponding enemy object. Interactive terrain (e.g. trap) spawners were eventually replaced with separate terrain code, but their spawner data still exists, albeit with buggy behavior. A couple alternate enemies (e.g., bat, fuzz buster) also had their spawners diverted, but I haven't delved deeply enough to determine if their code was actually deleted, but most of the LUTs remain, such that setting the spawner state to #02, thus reveals each spawner's intended application.
  #00  Unused address used by diverted spawners
 
#01  Zombie (slow rate) normal zombie
  #02  Zombie (from ground)
  #03  Medusa Head (one)
  #04  Winged Demon (one)
  #05  Skull Knight (Boss)
  #06  Cyclops (Boss)
  #07  Grant (Boss)
  #08  Lightning (bolts) first visual effect
 
#09  Lightning (Sypha) cinematic visual effect
  #0A  Lightning (clouds) boss fight visual effect
  #0B  Hunchback
  #0C  Bats (flying)[1]
  #0D  Bats (asleep)
  #0E  Bone Pillar (3-shot)[1]
  #0F  Axe Knight
  #10  Crow (flying low)
  #11  Skeleton (sword)[1]
  #12  Fishmen (jumping) bridge variety
  #13  Skeleton (whip,red)
  #14  Floating Eye
  #15  Slime Ball
  #16  Skeleton (bones)
  #17  Skeleton (whip,blue)
  #18  Ghost (no flicker)
  #19  Skeleton (red)
  #1A  Mummies[1]
  #1B  Giant Bat (Boss)
  #1C  Alucard (Boss)
  #1D  Bone Dragon King (Boss)
  #1E  Medusa (Boss)
  #1F  Water Dragons (Boss)
  #20  Mummies + Cyclops (Boss)
  #21  Frankenstein's Monster (Boss)
  #22  UNUSED BOSS (no object, spawner position #2A)
  #23  Grim Reaper (Boss)
  #24  Doppelganger (Boss)
  #25  Mummy + Cyclops + Leviathan (Boss)
  #26  Dracula (Boss)
  #27  Crow (flying high)
  #28  Headless Pirate a.k.a. Dhuron
  #29  Spider
  #2A  Bone Pillar (2-shot)
  #2B  Bats (flying)[2] *unused in CV3j*
  #2C  Fuzz Buster[1] *unused in CV3j*
  #2D  Spore (floating)
  #2E  Spore
  #2F  Trap Door *unused*
  #30  Trap Door (spikes) *unused*
  #31  Gear Tooth *unused*
  #32  Skeleton (blue)
  #33  Pendulum *unused*
  #34  Falling Spikes[1] *unused*
  #35  Falling Spikes[2] *unused*
  #36  Water Current (4 blocks)
  #37  Falling Blocks *unused*
  #38  Acid Drops *unused*
  #39  Water Current (2 blocks)[1]
  #3A  Zombie (fast rate)[1]
  #3B  Mudmen
  #3C  Frog
  #3D  Fishmen (swimming) aqueduct variety
  #3E  Fishmen (swim+jump) deep water variety
  #3F  Fire Man
  #40  Knight
  #41  Bone Pillar (3-shot)[2]
  #42 
Auto-Walk (forest)
  #43  Bone Dragon
  #44  Owl
  #45  Fuzz Buster[2]
  #46  Harpy
  #47  Bats Flying[3]
  #48  Medusa Heads (two)[1]
  #49  Skeleton (sword)[2]
  #4A  Medusa Heads (two)[2]
  #4B  Ghost (w/flicker)
  #4C  Auto-Walk (caves)
  #4D  Water Current (6 blocks)
  #4E  Water Current (2 blocks)[2]
  #4F  Zombie (fast rate)[2]
  #50  Mummies[2]
  #51  Flood Controller
  #52  Winged Demon (two) *CV3u only*

Enemies and luminaries are not directly placed in the room, but rather a spawner is. Each spawner occupies a 64px block (as seen in reVamp) and is the pointer to the subroutine that handles spawning the enemy. You can access all available spawners by right-clicking the enemy or luminary list in reVamp. There is a hard limit of spawners -- 224 enemies (U:226) and 244 luminaries (U:254) -- for the entire game, although in actuality there are far fewer (see warning below). A skilled, patient hacker should be able to add more.

WARNING: Some spawners point to the same address, identifiable in reVamp as spawners with the same object, x and y. Editing these in reVamp will glitch it out, as the program apparently is designed to only change ROM values, not add them. 

All enemy spawners below #80 are reserved strictly for enemies appearing across both playthroughs. By default enemy spawners #A0 and up are reserved for the second playthrough, although you can alter this hard limit by editing $02813A (U: $028130). There is no such limitation for luminaries. With some skilled hacking, I'm sure you could reprogram the spawner data to allow 16bit spawner quantities. There can only be 6 spawners each loaded at any one time in a horizontal stage. Spawner indices for each room are stored as WORDs, with the lower byte corresponding to the luminary and the upper byte corresponding to the enemy. The address maps are stored in order by stage-block-subroom.
  $0292BE(U:$2938F) Address maps for enemies
  $02A57B(U:$2A654) Address maps for luminaries
  $0293DE First enemy  (1-01:0 far left)
  $0293DF First luminary  (1-01:0 far left) 

Luminary stats are stored as DWORDs, with each byte representing (in order) the luminary type, item dropped, x-coordinate, and y-coordinate (add #28 to the y-coordinates listed in reVamp).
Luminaries are stored as follows:
  $02A763(U:$02A850) Luminary #00 (Null)
  $02AB2B(U:$02AC40) Luminary #$FF
 
   #80(U:#90) Candle

    #81(U:#91) Candlestand
    #82(U:#92) Lantern

In vertical stages, enemies and luminaries are hard-coded starting at . The first byte is the screen the enemy or luminary appears in. The second byte is the y-coordinate in that screen. The third value is the enemy as can be seen in reVamp or the luminary value. The fourth byte is the x-coordinate in the screen. The fifth byte is the item dropped for luminaries, possibly ignored for enemies even though it's set (otherwise bats would drop big hearts). The sixth and seventh bytes aren't used as far as I can tell. A value of $FF in the first byte denotes the end of the list of spawners in that vertical room.
  $02AB2F(U:$02AC44) Vertical stage Spawners


Trevor's Starting Coordinates
Trevor's X is (KKKKK & #$F0). Trevor's Y is (KKKKK << 4). Every other byte corresponds to a block. These can be set in reVamp. Good for debugging if $36 is frozen.
  $037802 1-01:0
  $037804 1-02:0
  $037806 1-03:0

Scroll type
Vertical stages have a scroll type specified as #$80 (normal), #$82 (automatic), or #$84 (incremental, like the collapsing towers). When the stage scrolls down, it can take #$81 (normal), #$83 (automatic), or #$85 (incremental, not sure if implemented). You can set this for each room, but if a room isn't set up as vertical, it will fail to load.
  $03DA01 1-01:0 (starting address)
  $03DA03 1-02:1
  $03DA11 2-01:0 Up
  $03DA15 2-02:1 Up
  $03DA18 2-03:1 Up
  $03DA1B 2-03:1 Down
  $03DA1E 2-02:1 Down
  $03DA20 2-01:0 Down
  $03D961 - $3DA00 Scroll type map (and other?)

Prayer Values
These are some of the values set during the prayer scene.
  $00658d Trevor's mirrored state
  $006588 Trevor's x-coordinate
  $00658D Trevor's y-coordinate
  $00667F Trevor's PPU offset
  $006684 Trevor's palette
  $006689 Trevor's "image single"

Doors
Each door has 6 bytes of data. The location of this data is located in a series of WORDs offset by the current stage.
  $01F606-$01F623 PRG-ROM Address (Word) (R)
  $01F624 Door value (R)
    Each of these addresses contains 6 bytes of data, offset by the current block.
    Subroom
    Screen
    Side of room (#$00 = left, #$01 = right)
    First door y-coordinate
    Second door y-coordinate
    Subroom of next block
The first byte tells the game which subroom in the block the door is located. Obviously since there can be only one door per block, there can be only one subroom. The second byte tells the game which screen the door is on. The screen is the higher byte of the View X. The third byte specifies which side of the room the door is on. You can only use one side of the room, not both (CV2 had different screen transitions obviously). The next two bytes specify the y-coordinate Trevor needs to be standing at for either door when walking through. This is how you have two doors per level in the Alucard's cave. And yes, Trevor must be actually standing at that y-coordinate. The final byte tells the game which subroom of the next block to go to.

Stairs
Stairs have quite a bit of code associated with them. The stairs' stats are indexed by stage, block and room. This means adding new stairs is tedious. The indexing is as follows:
    $01F75F Index by stage (Word) (R)
    $01F77D Sub-index by block (Word) (R)
    $01F818 Sub-index by room (Word) (R)
    $01F828 Stair values and breaks (R)
Breaks are included because the game will cycle through all stair values if at any time Trevor's stats don't match those of the currently indexed stair. When a break is encountered, the game stops looking. Stair stats are stored in the format ABCCDD, with each nybble/byte corresponding to the following (coordinates of the reVamp icons are listed below each one):
    A = Direction
        $0 Up and right
            x = left edge
            y = bottom edge + #$10
        $4 Up and left
            x = right edge
            y = bottom edge + #$10

        $8 Down and left
            x = right edge
            y = top edge + #$10
        $C Down and right
            x = left edge
            y = top edge + #$10
    B = Y-coordinate >> 4 or Screen for vertical rooms
    C = X-coordinate or Y-coordinate for vertical rooms
    D = Screen or X-coordinate for horizontal rooms
Putting a solid tile directly under the top of a stair will prevent Trevor from walking down the stair. Climbing stairs makes Trevor ignore tile collisions normally, but if the tile directly below is a solid, the collision will register and he will snap out of the stair to the ledge above.

Special Values
A few stages have special attributes applied to background tiles and are listed in the ROM. The map is very simple. Every DWORD stores (in order of ascending byte) the stage, the block, and the room, then the code for the instructions, which is stored in RAM address $007A.
  $001595 Moving clouds (#$10 to #$13)
  $0015A5 One-way stairs? (#$20 and #$23)
  $0015AD Stream with waterfall (#$30 and #$31)
  $0015B5 Grinding clockwork (#$40)
  $0015E9 Cascading waterfall (#$41)
  $0015F5 Quicksand (#$32 to #$37)
  $00160D Water? (#$50 to #$53)
  $00161D Split room with water? (#$60)
  $001625 Flooding (#$71 and #$72)
  $001629 Collapsing bridge (#$80 and #$81)
  Obviously #$10 thru #$13 handle the values used to reference the instructions for animating background clouds. The lower bits correspond to RAM offsets.
  A value of #$20, I have no idea yet.
  A value of #$23 will make Trevor climb the stairs up to the next block automatically. Like doors, this clears all other instances from the screen.
  When using Sypha, #$30 and #$31 handle water that she can freeze. So no, she can't freeze all water, only the flowing streams with waterfalls in them. These flags also animate the water.
  Values #$40 and #$41 simply handle tile animations. The gears in the Clocktower use #$40 and the waterfalls in the background of the castle tower use #$41.
  The quicksand flag will make every part of Trevor's sprite that is completely under the mud flicker. The lower bits map to $00631A offset by [lower bits]-2. So a value of #$33 would map to $00631B. The values stored within that array correspond to the screen in which no flickering should occur (i.e., the screen with no mud at all). If the corresponding array value is higher than the room size (e.g., $0054 doesn't exceed #$01 but $00631A[n] is set to #$02), the game will render all screens in the room as full of mud. When the array value matches the current screen, no flickering will occur below ground-level at all.
  Not sure if the water flag is actually for water, but seeing as how it's only set in the Sunken City, that's a good sign. It has a similar format to the quicksand flag, but is only used for the lowest subroom. Perhaps Konami was planning something with it. Possibly only used by Fishmen. Both #$50 and #$60 are checked in the same subroutine, which suggests water. Furthermore, the code creates three new objects in the room, but they never appear (at least on my end). This kind of code only occurs when particles are created. In other words, there was probably supposed to be a splash when Trevor hit the water.

Epilogue
Not really something you'll probably ever want or need to change, but if you think it takes too long for the text to start scrolling in the epilogue after the castle crumbles, you can change these values.
  $02B224 Text Delay for Trevor
  $02B225 Text Delay for Sypha
  $02B226 Text Delay for Grant
  $02B227 Text Delay for Alucard
  $02B281 Scroll Speed for Trevor
  $02B282 Scroll Speed for Sypha
  $02B283 Scroll Speed for Grant
  $02B284 Scroll Speed for Alucard
  $02B25A Text Index
The index for the text is referenced by RAM address $0785 and increases with every pass of $078A. When the value retrieved is $FF, the text stops loading and scrolls to the top of the page. The three or four indices before the $FF are typically void of text so the epilogue scrolls off the screen before ending.



Respawn Conditions
Some enemies can be specified to respawn or perform other actions when slain.
  $02F553  #$4B
  $02F557  #$47
  $02F55B  #$49
  $02F55F  #$4D
  $02F563  #$38
Some have different displays when slain. 
  $02F53B  #$3D
  $02F53F  #$3E
  $02F543  #$4B
  $02F547  #$47

Collision Formula
The formula for horizontal collisions is
  abs(ALLY.x-OTHER.x)<=(ALLY.hbound+OTHER.hbound)
The formula for upper vertical collisions is
  ALLY.y+ALLY.vbound - (OTHER.y-OTHER.vbound)<#$12

Bounding Box Offsets
Using the object IDs below as Other pointers
  $02F683  Ally Vertical
  $02FB15  Ally Horizontal
  $02FB90  Other Horizontal
  $02FC18  Other Vertical

NPC Object IDs $0291FC (add $10 for CV3u)
$01  Skull Knight
$02  Cyclops
$03  Grant
$04  Giant Bat
$05  Alucard Bat / Cape
$06  Bone Dragon King
$07  The Monster
$08  Moat Dragon
$09  Triad Wisp / The Devil
$0A  Medusa
$0B  Doppelganger 
$0C  Death
$0D  Dracula
$0E  Mummy Boss 
$0F  Doppelganger Weapon
$12  Storm Clouds
$13  Small Lightning 
$14  Grant's Knife
$15  Grant's Axe
$16  Soul Shard 
$17  Alucard Fireball
$1A  Boss Death Effect
$1F  Cyclops' Killer Lightning?
$20  Timer for Cyclops' Lightning?
$21  Alucard Head
$23  Devil's Fireball
$24  Dracula's Pyre
$25  Dracula's Head
$27  Mummy Boss Wrap
$29  Legion's Drool / Pazuzu's Laser
$2A  Water Splash

$2B  Scythe
$30  Normal Fireball
$31  Axe 
$32  Teardrop 
$33  Bone
$34  Mummy Wrap
$35  Spiderling 
$36  Sporeling 
$37  Embers
$38  Zombie
$39  Crow 
$3A  Bats
$3B  Medusa Head
$3C  Ghost
$3D  Skeleton
$3E  Skeleton (Whip)
$3F  Floating Eye
$40  Spore Float
$41  Winged Demon (U:$51)
$42  Flea Man
$43  Slime 
$44  Skeleton (Sword)
$45  Axe Knight
$46  Bone Pillar
$47  Blood Skeleton (Whip) 
$48  Merman
$49  Bone Dragon
$4A  Mummy 
$4B  Blood Skeleton
$4C  Dhuron
$4D  Spider 
$4E  Spore Bloom
$4F  Owl 
$50  Mudman
$51  Frog
$52  Fireman
$53  Knight
$54  Fuzzy
$55  Harpy
$58  Spiderweb / Crumbling Mummy
$5C  Ice Giblets

$5D  Medusa Skull (CV3U only, $6D)
$61  6-Tile Current

$62  2-Tile Current(1)
$63  Auto-Walk (Caves)
$64  Auto-Walk (Forest)
$65  2-Tile Current (2)
$66  4-Tile current (U:Fast Zombie)
$68  Normal Lightning
$69  Collapsing Walkway
$6A  Teeter-Totter
$6B  Falling Block Spawner
$6C  Water Droplet Spawner
$6D  Trap Door
$6E  Spiked Platform
$6F  Clock Pendulum
$70  Gear Teeth
$71  Walkway Crumbles

$72  Spiked Trap Door
$73  Water Droplet/Falling Block
$74  Spike Crusher
$75  Medium Gear
$76  Vertical Platform
$77  Horizontal Platform 
$78  Scrolling Platform
$7A  Pazuzu Platform
$7B  Floating Platform
$80  Candle
$81  Candlestand
$82  Lantern

NPC Class IDs $0291A4
$00  Boss
$01  Zombie (from side, slow)

$02  Zombie (from ground)
$03  Crow (low)
$04  Crow (high)
$05  Bat (flying[1])
$06  Bat (sleeping) 
$07  Medusa Head
$08  Ghost (no flicker)
$09  Skeleton (bone)
$0A  Skeleton (whip)

$0B  Floating Eye 
$0C  Shroom (floating)
$0D  Winged Demon
$0E  Flea Man
$0F  Slime 
$10  Skeleton (sword)
$11  Axe Knight
$12  Bone Pillar (3-shot[1])
$13  Skeleton (normal)

$14  Fishman (Jump only)
$15  <unused?>

$16  Mummy
$17  Skeleton (blood normal)
$18  Enemy Death Spark

$19  Mummy (crumbling)
$1A  Skeleton (crumbling)
$1B  Splash (ice)

$1C  Dhuron
$1D  Spider
$1E  Bone Pillar (2-shot)
$1F  <unused?>
$20  Shroom (bloom floating)
$21  Skeleton (blood whip)

$22  Shroom (grounded)
$23  Shroom (bloom grounded)

$24  Zombie (from side, fast[2])
$25  Mudman

$26  Frog
$27  Fishman (Swim only)
$28  Fireman

$29  Fishman (Swim & Jump)
$2A  Splash (water)

$2B  Knight 
$2C  Bone Dragon Head
$2D  Bone Dragon Rib
$2E  Bone Dragon Base
$2F  Bone Pillar (3-shot[2])
$30  Candle
$31  Torch
$32  Lantern
$38  Zombie (from side, fast[1])

$43  Money Bags
...
$4C 
$4D 
$4E  Small Heart
$4F  Multiplier (2X)
$50  Multiplier (3X)

$57  Spiderweb
$58  Fireball
$59  Axe 
$5A  Teardrop
$5B  Bone

$5C  Mummy Wrap
$5D  Spiderling
$5E  Sporeling 
$5F  Embers
$60  Thunderstorm

$63  Owl / Boss Crystal
$64  Fuzzy
$65  Harpy

$66  Bat (flying[3])
$68  Ghost (flicker)
$69  Fleaman Bomb
$6E (U) Bat Flying[2]
$70 (U) Zombie (from side, fast[2], hard)
...
$9



APU Writes

APU Initialization
For regular audio tracks (#6E and lower), the APU is initialized as follows: Registers $4000, $4004, and $400C (Square and Noise volumes) are initialized to #30. Registers $4001 and $4005 (Square sweeps) are initialized to #7F. Registers $9000, $A000, and $B000 (VRC6 Pulse control and Saw volume) are initialized to #00. Register $4015 (APU channels) is initialized to #0F. For  DPCM samples, register $4015 is also initialized to #0F, but a few lines later it's set to #1F after the DPCM data has been loaded.

If the death jingle (J: #50, U: #4E) is playing, only the percussion noise tracks (#01-#05) are allowed. 

DPCM samples are stored in order of priority. The percussion DPCM samples (#6F-#73) have no priority, so any DPCM sample will cut off any percussion sample already playing. Otherwise, a quick glance at the sample order tells us the Trevor's whip and Sypha's staff have the lowest priority, then the grunting sounds when taking damage, then the boss laughs (including that scream from the floating head demon), and the boss death cry has the highest priority.

Sound Files
These are the values sent to the CPU for sound files via address $E249 (U:$E25F).
SFX
  $01  Hi-Hat Pedal
  $02  Hi-Hat Closed
  $03  Hi-Hat Open/Cymbal Light
  $04  Hi-Hat Open/Cymbal Heavy (unused)
  $05  Snare Hit
  $06 [U:$07]  Crumbling Room
  $07 [U:$09]  Footsteps
  $08 [U:$0B]  Rough Landing
  $09 [U:$0C]  Door Slam  
  $0A [U:$0D]  Bouncing Slime Landing
  --- [U:$0A]  Floating Heads Drool

  $0B [U:$0E]  Giant Rotating Gear
  $0C [U:$0F]  Mudman Appearance
  $0D [U:$10]  Crumbling Ledge 
  $0E [U:$08]  Corrosive Water Corrosion
  $0F [U:$11]  Ceiling Smash | Ledge Fall
  $10 [U:$12]  Crumbling Bridge
  $11 [U:$13]  Axe Weapon Toss
  $12 [U:$14]  Dagger Toss
  $13 [U:$15]  Cross Toss
  $14 [U:$16]  Holy Water Shatter
  $15 [U:$17]  Invincibility Potion
  $16 [U:$18]  Get Coins
  $17 [U:$19]  Timer Tally 
  $18 [$U:1A]  Hearts Tally | Name Letter Select
  $19 [U:$1B]  Get Heart | Name Letter Enter
  $1A [U:$1C]  Get Weapon
  $1B [U:$1D]  ****UNUSED EXPLOSION****
  $1C [U:$1E]  Water Attack (Lightning in v.US)
  $1D [U:$1F]  Alucard Fireball
  $1E [U:$20]  Flowing Water
  $1F [U:$21]  Ice Spell  
  $20 [U:$22]  Emerge Splash
  $21 [U:$23]  Submerge Splash 
  $22 [U:$06]  Corrosive Water Silencer
  $23 [U:$24]  Fire Spell (for Water Dragons also)
  $24  Resilient Enemy Hit 
  $25  Roaring Waterfall
  $26  Owl Flap
  $27  Enemy Shattered (e.g., skeletons)
  $28  Ineffective Attack 
  $29  Cyclops Pound
  $2A  Boss Hit
  $2B [U:$2C]  Mystery Meat 
  $2C  Thunder
  $2D  Title Screen Thunder
  $2E  Bat Form
  $2F  Water Dragon Emerge
  $30  Water Dragon Submerge
  $31 [U:$32]  Bone, Spit, Tears, et al Attack
  $32 [U:$33]  Object Destroy
  $33 [U:$34]  Block Break 
  $34 [U:$35]  River Freeze
  $35 [U:---]  Teeter-Totter (removed)
  $36  Trap Door Turn 
  $37  Collapsing Tower | Leviathan Stomp
  $38  Frozen Enemy Shattered
  $39  Creature Stomp
  $3A [U:$06]  Medusa Beam (removed)
  $3B [U:$06]  Medusa Arrow (removed)
  $3C [U:$3A]  Clocktower Quake
  $3D [U:$3B]  Sunken Room Quake
  $3E [U:$3C]  Stopwatch Tick
  $3F [U:$3D]  Flooding Sunken Room
  $40 [U:$3E]  Prayer Thunder
  $41 [U:$3F]  Big Thunder
  $42 [U:$40]  Invalid Password
  $43 [U:$41]  Partner Saved
  $44 [U:$42]  Flame Pillar
  $45 [U:$43]  Wisp Explode
  $46 [U:$44]  Pazuzu Laser
  $47 [U:$45]  Doppelganger Change
  $48 [U:$46]  Partner Change
  $49 [U:$47]  Pazuzu Hit
  $4A [U:$48]  Crystal Ping
  $4B [U:$49]  Time's Up
  $4C [U:$4A]  Rosario
  $4D [U:$4B]  1UP
  $4E [U:$4C]  Health Refill
  $4F [U:$4D]  Pause  
  $50 [U:$4E]  "Life Loss"
  $51 [U:$4F]  "Beginning"
  $52 [U:$50]  "Mad Forest"
  $53 [U:$51]  "Stream"
  $54 [U:$52]  "Dead Beat"
  $55 [U:$53]  "Clockwork"
  $56 [U:$54]  "Aquarius"
  $57 [U:$55]  "Rising"
  $58 [U:$56]  "Anxiety"
  $59 [U:$57]  "Nightmare"           
  $5A [U:$58]  "Demon Seed"          
  $5B [U:$59]  "Anxiety" (duplicated)
  $5C [U:$5A]  "Aquarius" (duplicated)
  $5D [U:$5B]  "Deja Vu"
  $5E [U:$5C]  "Riddle"
  $5F [U:$5D]  "Pressure"

  $60 [U:$5E]  "Overture"
  $61 [U:$5F]  "Boss Fight"
  $62 [U:$60]  "Big Battle"
  $63 [U:$61]  "Big Battle" (fast)
  $64 [U:$62]  "Epitaph"
  $65 [U:$63]  "Blk Clear"
  $66 [U:$64]  "All Clear"
  $67 [U:$65]  "Game Over"
  $68 [U:$66]  "Prelude"
  $69 [U:$67]  "Prayer"
  $6A [U:$68]  "Evergreen"
  $6B [U:$69]  "Flash Back"
  $6C [U:$6A]  "Pressure" (duplicated)
  $6D [U:$6B]  "Encounter"
  $6E [U:$6C]  "Destiny" 
  $6F [U:$6D]  Floor Tom (DPCM #00)
  $70 [U:$6E]  Low Tom (DPCM #01)
  $71 [U:$6F]  High Tom (DPCM #02)
  $72 [U:$70]  Snare Drum (DPCM #03)
  $73 [U:$71]  Bass Drum (DPCM #04)
  $74 [U:$72]  Attack / Main Menu Select (DPCM #05)
  $75 [U:$73]  Trevor Hurt
  $76 [U:$74]  Grant Hurt
  $77 [U:$75]  Sypha Hurt
  $78 [U:$76]  Alucard Hurt
  $79 [U:$77]  Death Laugh (DPCM)
  $7A [U:$78]  Whip Attack (duplicated)
  $7B [U:$79]  Ominous Laugh (DPCM)
  $7C [U:$7A]  Flying Heads Scream (DPCM)
  $7D [U:$7B]  Boss Scream (DPCM)


Constants
As I find them, I will include the constants (enemy stats, timer durations, etc.) here. Addresses identified as offsets should only be modified with extreme caution.
  $000F42  Starting Hearts
  $000F3D  Starting Lives
The above two can be easily changed in reVamp.
  $03BA3D  Stopwatch Duration
Default is #$B4, which is 180 steps. In other words, it's 3 seconds if running at 60 fps. Oddly, the timer requires 64 steps to count down 1 second, which I've noticed in other games as well.
  $02925E  Enemy Health (R)
Every enemy's health is stored in this range, sorted by object index. Every boss has a unique object index, which means bosses can have different health, but anything higher than #$40 will not register properly in the boss' health bar at the top of the screen.
  $013FA0  Point Value (R)
  $02C3E8  Byte $05AA (R)
The offset is retrieved by object_index-#$38. This is tripled and used as a sprite offset.
Hit detection is performed in Begin Step event (essentially). 

Notes To Self

$037724 (50) (7C & $F0 3A)

$3D909 (01 80) address for climbing up stairs to next room based on $0034
next address is $3D909 + $0035 << 1 offset, add #$18010 to find ROM address
0180 0
E28D 1
AF99 2
82A6 3
11B3 4
0180 5
FF89 6
6F91 7
DE9D 8
0180 9
1088 A
0EAA B
CB9F C
4BA9 D
B7B2 E
Above address offset by $0035 << 1

$038613 (R) Map to Trevor's x-coordinate offset when changing rooms via stairs
$038614 (R) Map to Trevor's y-coordinate when changing rooms via stairs
$03862B (R) Map to Trevor's y-coordinate offset (?) based on $054E and additional x-coordinate offset based on $05EF (whatever that is), usually +0

Y-values in reVamp vary from game values by 1 whole tile height as follows:
yrevamp = ygame - #$20{status bar} + #$10
When height checked uses that formula, collision is for at instance's feet. Discrepancy shouldn't ever be more than #$10 or less than #$F0 (above head).
Collisions in front of objects are checked 1 whole tile width (#$10) ahead.

These are the "hit box" settings for tile collision of various objects:
Trevor
In my engine, Trevor's y is $10 pixels higher than in the actual game, so y+$10-$20, $20 being the height of the status bar, in my engine would be y+$20 (I think).
(x±8,y±16) Wall collision
( x±5,y+16) Floor collision
(x,y-8 6r y-24) Jumping

( $800C + #$09 + $0036 << 1 + #$01 ) >> #$04 = next subroom when ascending from vertical
x($0A)+#$0C = AB; A = next subroom << 4, B = next screen
x($0A)+$0036 = BG palette offset or palette offset+#$1C

$9378 Trevor's Bounding box addressing
Indexed by $9375+$0565+1
2D95 $02
6796 $04
2496 $06
7797 $08
2099 $0A
7797 $0C
5799 $0E
6B99 $10
A499 $12
AB9A $14
4999 $16
0D94 $18
2F94 $1A
5A94 $1C
9394 $1E
AD94 $20
C994 $22
F494 $24
0783 $26
A693 $28
A693 $2A
588B $2C
DF8A $2E

view_x&$3F[0E]&$20+$C0[09] if ($0062)==0 else view_x&$3F&$20+$00
($0073)+$05(*$0062>0)[73]
$01[0A]
$8410,73 (enemy block)


Interactive Terrain (QWord)Moving objects between screens sometimes glitches in reVamp.
  $00A030  Index 4 (Object Map)
  $00A054  Index 1 (Word Map)
  $00A0F2  Index 2 (Offset Map)
  $00A17A  Index 3 (Stats Map)
A  B  C  D  E  F  G  H
02 E8 00 10 50 00 01 00
Breakable Block 
  A  Screen  
  B  X-coordinate (Y in vertical stages)
  (#$8 right from left edge)
  D  Object (#$10;#$11 in vertical stages)
  (used when loading into room)   E  Y-coordinate (X in vertical stages)
      (#$D down from top edge; subtract 8 if G set)
  F  Item  
      ($00=Meat, $01=Heart, $02=Empty, $03=Multiplier, $04=1UP)
  G  Dual Layer
  H  Instance ID (counter)
Horizontal Ledge
  C  Screen Trigger 
      (see reVamp)
  D  Object (#$0C)
  G  Velocity 
      (see reVamp)
      Minimum is #$01. Setting the highest bit moves ledge left.
  H  Range (see reVamp)
Vertical Ledge
  D  Object (#$0B)
  F  Range 
      (see reVamp)
  G  Velocity 
      (see reVamp)
      Minimum is #$01. Setting the highest bit moves ledge up.
Moving Spikes /Crusher
  D  Object (#$06;#$07)
  F  Up-Down State?
  G  Range 
      (see reVamp)
      Values in reVamp don't match values in ROM. Huge variance.
Trap Doors
  D  Object (#$02;#$03)
  F  Up-Down State?
  G  Location 
      (see reVamp)
      Not sure why this is used.
Pendulum
  D  Object (#$05)
  F  Location 
      (see reVamp)
  G  Velocity 
      (see reVamp)
      Positive for left, negative for right. 
Gears
  C  ??
  D  Object (#$0A;#$04)
  F  Direction 
      Clockwise=#$00; Counterclockwise=#$01)
   G  Location 
      (see reVamp)
Tilting Ledge
  D  Object (#$01)
  F  Location 
      (see reVamp)
  G  Tilt 
      L-tilt should be #$01, but this seems inconsistent.
Falling Blocks
  D  Object (#$08)
  F Location 
      (see reVamp)
Acid Drops
  D  Object (#$09)
  F  Location 
      (see reVamp)
Scrolling Ledges
  B  ??
  C  ??
  D  Object (#$0D)
  H  ??


Breakable Blocks
Breakable blocks occupy X offsets #$1A and #$1B.

Enemy State Addressing
Enemy states can be thought of as a jumbled mass of scripts (i.e., functions). Each of these are addressed in the LUT starting at (U: $02FD5F). The LUT is indexed based on addresses found in another LUT at (U: $02FEB1), sorted by an enemy's CLASS. This LUT itself points to a list of pointers and additional argument info starting at $02E5EE (U: $02E548), with an odd outlier at $02E4B6 (U: $02E41B), sorted by the enemy's STATE. For example, looking at a normal Zombie, whose CLASS maps to the X register as #02, $02FEB1,X(u) points to $02E5AC. If our Zombie is in STATE 0, the values fetched would be #07008000. This translates to script 7, with arguments #00, #80, and #00. If you look at script 7 (slow zombie state 0), arguments 1 and 2 are used for the horizontal speed (#0080, or 1/2), while argument 3 is unused. Similar mechanics are seen in the boss codes. This setup may seem confusing at first, but when you factor in the amount of repeated code (e.g., scripts #11, #12, #1F, #20), it has its benefits.
  $02FD77 (U:$02FD5F)  State Functions (J:#9E, U:#A9)
  $02FEB3 (U:$02FEB1)  Class Definitions (J:
#68, U:#73)
  $02E5EE (U:$02E548)  State Definitions
Bosses are handled similarly. There are #66 classes of boss behaviors, with each class defined at (U: $0249FF). Each class has data pairs sorted by state ($5C1,X for bosses). The first value of each pair is the function to run for the state, and the second value is a pointer to a list of arguments for that function, found at (U: $0250B7). For example, a pair #0501 means the state will execute function #05 using the second (#01+1) set of arguments {#00,#00,#00}. The pointers for each function start at (U: $024681).
  (U:$024681)  State Functions
  (U:$0249FF)  Class Definitions
  (U:$0250B7)  State Definitions

 

Sprite Handling
Byte $048C is essentially an Animation Batch Index (ABI), as it determines all sprite data to be used. Byte $05AA can be thought of as the Animation Index (AI), as it determines which frames are cycled and the animation speed. Byte $057C is the Animation Time (AT), as it counts down every step and increases the Frame Index upon rolling over at #00. Byte $0593 is the Animation Frame (AF), as it determines which frame of the animation to use. Byte $0400 is the Frame Index (FI), the actual frame of animation itself as defined by the ABI. 
 
When animated "automatically", the AT counts down until it is 0, then the program fetches the LUT for the ABI, which consists of 3 bytes of data per animation: frame offset, image speed, and final image index. The LUT is referenced by multiplying the AI by 3. The program fetches the first value, adds it to the AF, then saves that to the FI. It sets the AT to the next value in the LUT. Finally, it increases the AF and resets it to 0 if it is not less than the third value in the LUT.
 
If seeking authentic reproduction, this animation mechanic is somewhat important. If using animation similar to that found in Game Maker Studio 1.4 and earlier iterations, in most cases just setting image_index to image_speed when changing sprites would be enough to reproduce the animation mechanics in CV3. The biggest exception to this is Alucard, who actually changes his AI, which in turn modifies his AT. This is not the same as changing image_speed in Game Maker. Technically, the way Alucard's AI fluctuations affect the sprite, is the current frame will continue at the old speed, then the new speed will kick in on the next frame. Dealing with sprite-based timing in cases like Grant may be easier with this animation mechanic, as well.
 
There are 15 sprite sets, although most of them are identical. Each PC gets its own ABI, but they all use the same dataset because they share all of Trevor's states. Similarly, each doppelganger form gets its own ABI, but they all use the same dataset as Trevor. Most enemies don't have complex behavior, so they share the same two ABIs, distinguished by the AI. In a lot of cases, the ABI is set but the AI doesn't change, or they're both just completely ignored.
    #00 EFF0    Trevor,Items
    #02 EFF0    Sypha,Spells
    #04 EFF0    Grant
    #06 EFF0    Alucard
    #08 F0D7    Zombies,Skeletons,Bone,Bats,Medusa,Fleamen,Statue,Ghost,
                Crow,Spiders,Spores,Eye,Slime,Gargoyle,Frog(Tongue)
    #0A F173    Grant(boss),Cyclops Mallet,Lightning,Vampire Bat,
                Dracolich,Alucard(bat&fire)
    #0C F020    Markers,Traps,Gears,Pendulum,Teeter-Totter,PC meeting,
                Acid,Avalanche,Door
    #0E F359    Candles,Drops,Dying Flame,Debris,Armor's Ax,Scythe,Flooring
    #10 F272    Bone Knight,Cyclops,Mummy(Boss),Wisp,Death,Dracula,Alucard(boss)
    #12 F14C    Armor,Owl,Mudman,Flameman,Fuzzy,Merman,Bone Drac,Harpy,Frog(Hop)
    #14 F37D    Sypha release,Epilogue
    #16 EFF0    Trevor's Doppelganger
    #18 EFF0    Sypha's Doppelganger
    #1A EFF0    Grant's Doppelganger
    #1C EFF0    Alucard's Doppelganger
 
    Batch ID:Animation ID 
    08:00    Zombie | Frog Tongue
    08:01    Crow 
    08:02    Ghost
    08:03    Bat
    08:04    Medusa Head  |  Merman Jumping
    08:05    Bone Skeleton | Blood Skeleton
    08:06    Whip Skeleton
    08:07
    08:08    Gargoyle 
    08:09    Fleaman
    08:0B    Sword Skeleton
    08:0C
    08:0D    Axe Armor 
    08:0E
    08:0F    Merman Spitting
    08:10    Flying Eye
    08:12    Mummy
    08:14    Mummy Appearance
    08:16    Bone 
    08:18    Mummy Bandage
    08:19    Mummy Collapse
    08:23    Ghost Appear
    08:25    Ghost Wisp
    08:26    Normal Skeleton
 
    0A:00    Bone Knight Sword Strike 
                thru 0A:03
    0A:04    Bone Knight In-Air (& Sword Withdraw)
    0A:05    Bone Knight Bone 
    0A:0D    Bone Knight Walking
                thru 0A:10
    0A:12    Grant(B) Walking
    0A:13    Grant(B) Climb Up
    0A:14    Grant(B) On Ceiling
    0A:15    Grant(B) Climb Down
    0A:16    Grant(B) Axe 
    0A:17    Grant(B) Dagger 
    0A:18    Grant(B) Dead
    0A:19    Grant(B) On Wall
    0A:1A    Grant(B) Jump
    0A:1B    Giant Bat Large
    0A:1C    Giant Bat Medium
    0A:1D    Giant Bat Small
    0A:1E    Giant Bat
    0A:1F    Giant Bat Asleep 
    0A:21    Alucard(B) Attack
                thru 0A:23
    0A:24    Alucard(B) Bat
    0A:25    Alucard(B) Fireball
    0A:28    Alucard(B) Transform
                thru 0C:2B
    0A:29    Grant(B) Arm Dagger
    0A:2A    Grant(B) Throw Dagger
    0A:2C    Alucard(B) Formation
                thru 0A:2F
    0A:32(30?)    Alucard(B) Death
 
    0C:0B    Trapdoor
                thru 0C:0F
    0C:0F    Spiked Trapdoor     
                thru 0C:14
    0C:19    Gear Tooth
                thru 0C:21
    0C:22    Pendulum Arm
                thru 0C:26
    0C:27    Pendulum Bob
    0C:28    Floating Spikes
    0C:29    Acid Form
                thru 0C:2C
    0C:2D    Acid Droplet
    0C:2E    Acid Splash
    0C:2F    Acid Corrosion
                thru 0C:34
    0C:35    Cave-in   
 
    0E:00    Candle
    0E:01    Lantern
    0E:02    Torch
    0E:03    Armor Axe
    0E:04    Dying Flame 
    0E:05
    0E:06
    0E:07
    0E:08
    0E:09    Flooring 
    0E:0A    Crumbling Flooring
    0E:0B    Boss Crystal
    0E:0C    Item Drops
    0E:0D    1UP and Money
    0E:0E    Hundred Points
    0E:0F    Thousand Points
    0E:10 
     
    10:00    *Alucard(B) Head*
    10:05    Bone Knight Death
    10:26    Bone Knight Pile
                 thru 10:29
    10:4B    Bone Knight Block
    10:4C    Bone Knight Landing 
 
    12:00    Crow Perched | Toad Jump
    12:01
    12:02    Merman Shadow
    12:03    Flameman
    12:04    Flameman Ember
    12:05    Armor 
    12:07    Fuzzy Wallwalker
    12:08    Harpy
    12:0B    Crow Flying
 

Sprite Definition
Up to 64 sprites can be set each frame, as determined by $0007 in the sprite handling routine within the game. Each sprite takes 4 bytes as outlined on NESDev's PPU wiki. By default, unused sprites will have a y-coordinate of #f4, telling the PPU to not render any of those "sprites". Sprite data is thus pretty straightforward. The first number is always the number of 8x16 sprites comprising the overall sprite. The number of bytes after that relate to each of the bytes in the PPU as follow:

  1. Y-offset of sprite. ROR the value (set carry to highest bit first) to find y-offset. For example, if value is #f0, the y-offset will be #f8; if value is #04, y-offset will be #08. Added to instance's y-coordinate before write to PPU.
  2. First sprite in PPU to use, written directly to PPU. The sprite immediately afterward will be drawn below it.
  3. Sprite attributes. If the image is not flipped, this will be XORed by #40 before writing to PPU. If any sprite attributes are set for the instance, the default palette will be ignored.
  4. X-offset of sprite minus 8. In other words, #f8 means no offset. If this sets the sprite outside the screen, the sprite is given a y-value of #f4, making it unrendered. Otherwise, added to instance's x-coordinate before write to PPU.

After every 4 bytes written, $0007 decrements. If there are no more sprites allowed, the routine ends. Although this likely would never happen, it may become prudent to ensure the most significant sprites in each instance are rendered first.  

Unplaceable Sprites
The following sprites in CV3j have inexplicably failed to get mapped in FCEUX for me, excluding sprites clearly included as a batch, such as alphabet and punctuation, and tiles probably positioned behind the HUD.
    $40610 Mirrored Dagger

    $40E10 Grant reaching to floor? Somersault? Time-out on wall?
    $43410 Armor (alternate CHR)
    $44410 Grant Epilogue Cheer (garbage)
    $45410 Teeter-Totter (alternate CHR with Fireman)
    $47B10 Alucard artifact (looks like eyes?)
    $47E10 Alucard lightning (did they copy Sypha's set?)
    $49090 Medusa snake belly
    $4CBB0 Pazuzu tile
    $4CC70 Pazuzu tile
    $4CD00 Pazuzu tile
    $4CD40 Pazuzu tile
    $4CDE0 Pazuzu tile
    $4E9A0 Epilogue water tile
    $4EB10 Epilogue mountain/tree tile
    $4F0D0 Intro whip? (not the one you're thinking of)
    $4F330 Intro cloud (probably "covered" by Trevor's head)
    $52850 Large gear wheel side
    $53710 Crusher tiles (uses sprites, not tiles)
    

 

3 comments:

  1. Anonymous3/31/2020

    This is an excellent list for programmers like my self. I am hoping in time you list the values that control the map screens. I'd like to program a way to remove them and have the stages play back to back. Keep up the awesome work!

    ReplyDelete
    Replies
    1. That's a good question... It would appear to be handled by either byte $18 or byte $2C (my money's on $18), but simply freezing one or the other causes all kinds of bugs, so I (or someone) will need to delve deep into the subroutines for both bytes. Setting $18 to #09 immediately goes to the Prayer scene, and #04 keeps it in the normal gameplay, and #08 sends it to the map. You'd think freezing at #04 prevents it from going to the map, but it also prevents the stage from ending.

      Delete
    2. Well, in CV3(J), ROM address 0x004158 tells the game to go to the Map Screen between levels. However, the next level isn't actually set until you go to the map screen. Simply changing this address to #03 (stage start) or #05 (block restart) would do you no good because you'd be stuck playing the same room until you die.

      Furthermore, due to how the game is structured, the map screen resets certain variables, most notably $002E (stage cleared). Thus, bypassing the map screen without extensive restructuring of the code would lead to undesirable glitches such as not being able to pause the game.

      None of this is to say you couldn't bypass the map screen entirely. To do so would require extensive restructuring of the code in order to address all the lost functionality of the map screen. However, perhaps you could work within the map screen code itself. It is structured by substates. Just loading the map screen and getting to the point where Trevor chooses a path requires 8 substates. If you rewrite the code to bypass those undesired states, including the ones that draw the map, you could fairly easily treat the map screen as just another quick transition.

      Delete

©TheouAegis Productions™. Powered by Blogger.