define memory map explicity
This commit is contained in:
parent
430949a484
commit
961aa789c2
|
@ -68,6 +68,7 @@ rem show commands run in output
|
|||
echo Assembling PRG Rom Banks
|
||||
|
||||
@echo on
|
||||
ca65 -D %GAME% --debug-info -o obj\ram.o src\ram.asm
|
||||
ca65 -D %GAME% --debug-info -o obj\constants.o src\constants.asm
|
||||
ca65 -D %GAME% --debug-info -o obj\ines_header.o src\ines_header.asm
|
||||
ca65 -D %GAME% --debug-info -o obj\bank0.o src\bank0.asm
|
||||
|
@ -85,5 +86,5 @@ rem link assemblies together to single .nes ROM
|
|||
echo "Creating .nes ROM"
|
||||
|
||||
@echo on
|
||||
ld65 -C contra.cfg --dbgfile %DBG_NAME% .\obj\constants.o .\obj\ines_header.o .\obj\bank0.o .\obj\bank1.o .\obj\bank2.o .\obj\bank3.o .\obj\bank4.o .\obj\bank5.o .\obj\bank6.o .\obj\bank7.o -o %ROM_NAME%
|
||||
ld65 -C contra.cfg --dbgfile %DBG_NAME% .\obj\ram.o .\obj\constants.o .\obj\ines_header.o .\obj\bank0.o .\obj\bank1.o .\obj\bank2.o .\obj\bank3.o .\obj\bank4.o .\obj\bank5.o .\obj\bank6.o .\obj\bank7.o -o %ROM_NAME%
|
||||
@echo off
|
|
@ -110,6 +110,7 @@ Write-Output "Assembling PRG Rom Banks"
|
|||
|
||||
# show commands run in output
|
||||
Set-PSDebug -Trace 1
|
||||
ca65 -D $Game --debug-info -o obj\ram.o src\ram.asm
|
||||
ca65 -D $Game --debug-info -o obj\constants.o src\constants.asm
|
||||
ca65 -D $Game --debug-info -o obj\ines_header.o src\ines_header.asm
|
||||
ca65 -D $Game --debug-info -o obj\bank0.o src\bank0.asm
|
||||
|
@ -127,7 +128,7 @@ Set-PSDebug -Trace 0
|
|||
Write-Output "Creating .nes ROM"
|
||||
|
||||
Set-PSDebug -Trace 1
|
||||
ld65 -C contra.cfg --dbgfile $DBG_NAME .\obj\constants.o .\obj\ines_header.o .\obj\bank0.o .\obj\bank1.o .\obj\bank2.o .\obj\bank3.o .\obj\bank4.o .\obj\bank5.o .\obj\bank6.o .\obj\bank7.o -o $ROM_NAME
|
||||
ld65 -C contra.cfg --dbgfile $DBG_NAME .\obj\ram.o .\obj\constants.o .\obj\ines_header.o .\obj\bank0.o .\obj\bank1.o .\obj\bank2.o .\obj\bank3.o .\obj\bank4.o .\obj\bank5.o .\obj\bank6.o .\obj\bank7.o -o $ROM_NAME
|
||||
|
||||
# compare assembled ROM hash to expected hash if file exists
|
||||
Set-PSDebug -Trace 0
|
||||
|
|
3
build.sh
3
build.sh
|
@ -105,6 +105,7 @@ done < $ASSETS_NAME
|
|||
echo "$GAME" > $ASSET_GAME_TYPE
|
||||
|
||||
echo "Assembling PRG Rom Banks"
|
||||
ca65 -D $GAME --debug-info -o obj/ram.o src/ram.asm
|
||||
ca65 -D $GAME --debug-info -o obj/constants.o src/constants.asm
|
||||
ca65 -D $GAME --debug-info -o obj/ines_header.o src/ines_header.asm
|
||||
ca65 -D $GAME --debug-info -o obj/bank0.o src/bank0.asm
|
||||
|
@ -117,7 +118,7 @@ ca65 -D $GAME --debug-info -o obj/bank6.o src/bank6.asm
|
|||
ca65 -D $GAME --debug-info -o obj/bank7.o src/bank7.asm
|
||||
|
||||
echo "Creating .nes ROM"
|
||||
ld65 -C contra.cfg --dbgfile $DBG_NAME ./obj/constants.o ./obj/ines_header.o ./obj/bank0.o ./obj/bank1.o ./obj/bank2.o ./obj/bank3.o ./obj/bank4.o ./obj/bank5.o ./obj/bank6.o ./obj/bank7.o -o $ROM_NAME
|
||||
ld65 -C contra.cfg --dbgfile $DBG_NAME ./obj/ram.o ./obj/constants.o ./obj/ines_header.o ./obj/bank0.o ./obj/bank1.o ./obj/bank2.o ./obj/bank3.o ./obj/bank4.o ./obj/bank5.o ./obj/bank6.o ./obj/bank7.o -o $ROM_NAME
|
||||
|
||||
if test -f $ROM_NAME
|
||||
then
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
# defines where the banks will be loaded into CPU address space
|
||||
MEMORY {
|
||||
# Define CPU memory map for zero page, not saved to ROM
|
||||
ZEROPAGE: start = $00, size = $100, type = rw;
|
||||
RAM: start = $100, size = $6ff, type = rw, fill = no;
|
||||
|
||||
# INES Cartridge Header, not loaded into CPU memory
|
||||
HEADER: start = $0000, size = $0010, fill = yes;
|
||||
|
||||
|
@ -25,6 +29,8 @@ MEMORY {
|
|||
|
||||
# defines the order of the segments as they are stored in the .nes ROM file
|
||||
SEGMENTS {
|
||||
ZEROPAGE: load = ZEROPAGE, type = zp;
|
||||
RAM: load = RAM, type = bss;
|
||||
HEADER: load = HEADER, type = ro;
|
||||
OAMRAM: load = OAMRAM, type = bss, define=yes, optional=yes;
|
||||
BANK_0: load = BANK_0, type = ro;
|
||||
|
|
|
@ -16,7 +16,6 @@ player is in water and presses the d-pad down button.
|
|||
|-------------------------------------|-------------------------------------|-------------------------------------|-------------------------------------|
|
||||
|  |  |  |  |
|
||||
|
||||
|
||||
```
|
||||
@set_enter_water_sprite:
|
||||
...
|
||||
|
|
|
@ -1200,7 +1200,6 @@ Other Names: Gordea, JJ, Jumping Joey, Jumping Jack Flash, Giant Boss Robot,
|
|||
No attributes exist for this enemy. His health is calculated based on player's
|
||||
`PLAYER_WEAPON_STRENGTH` value. The formula is below
|
||||
|
||||
|
||||
#### Logic
|
||||
|
||||
* `ENEMY_VAR_1` - random number used to control boss action: jump, attack,
|
||||
|
|
|
@ -128,7 +128,6 @@ game by various other sounds.
|
|||
| #$5c | n/a | high hat | n/a | n/a | low | delta modulation |
|
||||
| #$ff | n/a | snowfield boss defeated door open (bug) | n/a | n/a | low | delta modulation |
|
||||
|
||||
|
||||
The sound for pausing the game is not in the sound mode menu, presumably to not
|
||||
confuse players into thinking the game is paused. As for names, I can guess at
|
||||
some of the abbreviations and name meanings.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
; Contra US Disassembly - v1.2
|
||||
; Contra US Disassembly - v1.3
|
||||
; https://github.com/vermiceli/nes-contra-us
|
||||
; Bank 0 is used exclusively for enemy routines. Enemy routines are the logic
|
||||
; controlling enemy behaviors, AI, movements, and attack patterns. Almost every
|
||||
|
@ -2800,7 +2800,7 @@ eye_projectile_routine_00:
|
|||
lda #$06 ; a = #$06 (projectile speed)
|
||||
sta $06
|
||||
lda #$01 ; a = #$01 (quadrant_aim_dir_01)
|
||||
sta $0f ; quadrant_aim_dir_lookup_tbl offset
|
||||
sta $0f ; quadrant_aim_dir_lookup_ptr_tbl offset
|
||||
jsr get_quadrant_aim_dir_for_player ; set a to the aim direction within a quadrant
|
||||
; based on source position ($09, $08) targeting player index $0a
|
||||
jsr set_bullet_velocities ; set the projectile X and Y velocities (both high and low) based on register a (#$01)
|
||||
|
@ -5688,7 +5688,7 @@ spinning_bubbles_routine_00:
|
|||
lda spinning_bubbles_speed_tbl,y ; load bullet velocity routine table value (bullet_velocity_adjust_xx)
|
||||
sta $06 ; store bullet direction velocity routine value (bullet_velocity_adjust_xx) in $06
|
||||
lda #$01 ; a = #$01 (quadrant_aim_dir_01)
|
||||
sta $0f ; set quadrant_aim_dir_lookup_tbl offset to #$01
|
||||
sta $0f ; set quadrant_aim_dir_lookup_ptr_tbl offset to #$01
|
||||
jsr get_quadrant_aim_dir_for_player ; set a to the aim direction within a quadrant
|
||||
; based on source position ($09, $08) targeting player index $0a
|
||||
pha ; push quadrant aim dir to the stack
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
; Contra US Disassembly - v1.2
|
||||
; Contra US Disassembly - v1.3
|
||||
; https://github.com/vermiceli/nes-contra-us
|
||||
; Bank 1 is responsible for audio and sprites. The audio code takes up about
|
||||
; 3/4 of the bank. The remaining 1/4 of the bank is for sprite data and code to
|
||||
|
@ -323,7 +323,7 @@ set_pulse_config:
|
|||
@continue:
|
||||
ora SOUND_CFG_HIGH,x ; merge with high nibble of pulse config value
|
||||
jsr ldx_pulse_triangle_reg ; set x to apu channel register [0, 1, 4, 5, 8, #$c]
|
||||
bcs @exit
|
||||
bcs @exit ; exit if there is already a sound playing on that channel that has priority
|
||||
sta APU_PULSE_CONFIG,x ; set either pulse channel 1 or 2 config
|
||||
; a is either (PULSE_VOLUME,x - UNKNOWN_SOUND_01) | SOUND_CFG_HIGH,x
|
||||
; or #$00 | SOUND_CFG_HIGH,x
|
||||
|
@ -517,7 +517,7 @@ read_sound_command_00:
|
|||
; output
|
||||
; * x - SOUND_CURRENT_SLOT [0-3]
|
||||
read_high_sound_cmd:
|
||||
lda SOUND_CURRENT_SLOT ; loud sound slot index
|
||||
lda SOUND_CURRENT_SLOT ; load sound slot index
|
||||
cmp #$03 ; compare to sound slot #$03 (noise/dmc channel)
|
||||
beq parse_percussion_cmd ; branch if sound slot #$03 (noise/dmc channel)
|
||||
lda ($e0),y ; not noise channel, load sound byte
|
||||
|
@ -671,7 +671,7 @@ interpret_sound_byte:
|
|||
|
||||
@set_sweep_continue:
|
||||
jsr ldx_pulse_triangle_reg ; set x to apu channel register [0, 1, 4, 5, 8, #$c]
|
||||
bcs @next_high_control_sound_byte
|
||||
bcs @next_high_control_sound_byte ; branch if there is already a sound playing on that channel that has priority
|
||||
sta APU_PULSE_SWEEP,x ; enable or disable sweep
|
||||
|
||||
@next_high_control_sound_byte:
|
||||
|
@ -712,7 +712,7 @@ interpret_sound_byte:
|
|||
; set config register ($4000, $4004, or $400c) and period & length register
|
||||
@set_cfg_period_length:
|
||||
jsr ldx_pulse_triangle_reg ; set x to apu channel register [0, 1, 4, 5, 8, #$c]
|
||||
bcs @load_set_period_length
|
||||
bcs @load_set_period_length ; branch if there is already a sound playing on that channel that has priority
|
||||
sta $4000,x ; set pulse, triangle, or noise channel configuration
|
||||
|
||||
@load_set_period_length:
|
||||
|
@ -853,7 +853,7 @@ set_note:
|
|||
sta SOUND_PULSE_LENGTH,x ; set in memory copy of current pulse length
|
||||
ora #$08 ; set bit 0 of high timer to be 1
|
||||
jsr ldx_pulse_triangle_reg ; set x to apu channel register [0, 1, 4, 5, 8, #$c]
|
||||
bcs @set_period
|
||||
bcs @set_period ; branch if there is already a sound playing on that channel that has priority
|
||||
sta APU_PULSE_LENGTH,x ; set duration and high 3 bits of the pulse, or triangle channel
|
||||
|
||||
; set low period
|
||||
|
@ -866,7 +866,7 @@ set_note:
|
|||
|
||||
@set_apu_period:
|
||||
jsr ldx_pulse_triangle_reg ; set x to apu channel register [0, 1, 4, 5, 8, #$c]
|
||||
bcs @restore_x_adv_sound_ptr ; if carry set, do not update APU register
|
||||
bcs @restore_x_adv_sound_ptr ; branch if there is already a sound playing on that channel that has priority
|
||||
; continue to restore x to the sound slot index, update SOUND_CMD_LOW_ADDR value, and exit
|
||||
sta APU_PULSE_PERIOD,x ; update APU pulse period
|
||||
|
||||
|
@ -1007,7 +1007,9 @@ skip_3_read_sound_command_01:
|
|||
; (except SOUND_FLAGS are loaded within read_sound_command_00)
|
||||
|
||||
; set sound channel configuration (mute), advance sound command address
|
||||
; input
|
||||
; * a - amount to multiply SOUND_CMD_LENGTH by
|
||||
; * y - current sound_xx read offset
|
||||
sound_cmd_routine_00:
|
||||
jsr calc_cmd_delay ; multiply SOUND_CMD_LENGTH by a
|
||||
lda #$00 ; sound config low nibble = #$00 (mute sound channel)
|
||||
|
@ -1017,7 +1019,7 @@ sound_cmd_routine_00:
|
|||
|
||||
@continue:
|
||||
jsr ldx_pulse_triangle_reg ; set x to apu channel register [0, 1, 4, 5, 8, #$c]
|
||||
bcs @adv_read_addr
|
||||
bcs @adv_read_addr ; branch if there is already a sound playing on that channel that has priority
|
||||
sta $4000,x ; set pulse 1, pulse 2, or triangle configuration
|
||||
|
||||
@adv_read_addr:
|
||||
|
@ -1028,12 +1030,14 @@ sound_cmd_routine_00:
|
|||
jmp adv_sound_cmd_addr ; set the sound_xx command read offset to current read location + 1
|
||||
|
||||
; set in memory configuration for channel, set multiplier, and sometimes read_high_sound_cmd
|
||||
; input
|
||||
; * a - low nibble of sound byte value
|
||||
; * y - current sound_xx read offset
|
||||
sound_cmd_routine_01:
|
||||
sta SOUND_LENGTH_MULTIPLIER,x ; store value used to calculate SOUND_CMD_LENGTH
|
||||
iny
|
||||
iny ; increment sound code read offset
|
||||
lda ($e0),y ; load sound code byte
|
||||
cpx #$02 ; compare to sound slot #$02 (triangle channel)
|
||||
cpx #$02 ; compare current sound slot to sound slot #$02 (triangle channel)
|
||||
beq set_sound_triangle_config ; branch if triangle channel to set triangle config in memory and read_high_sound_cmd
|
||||
and #$0f ; not triangle sound slot, get low nibble
|
||||
sec
|
||||
|
@ -1293,7 +1297,7 @@ sound_exit_00:
|
|||
mute_channel:
|
||||
lda #$30 ; a = #$30 (mute pulse channel register)
|
||||
jsr ldx_pulse_triangle_reg ; set x to apu channel register [0, 1, 4, 5, 8, #$c]
|
||||
bcs @continue
|
||||
bcs @continue ; branch if there is already a sound playing on that channel that has priority
|
||||
sta $4000,x ; update pulse channel config (mute pulse channel 1 or 2 register)
|
||||
|
||||
@continue:
|
||||
|
@ -1373,7 +1377,7 @@ sound_cmd_ptr_tbl:
|
|||
|
||||
; table for note period to use when writing notes to the APU (#$30 bytes)
|
||||
; the frequency of the pulse channels is a division of the CPU Clock (1.789773MHz NTSC, 1.662607MHz PAL)
|
||||
; the output frequency (f) of the generator can be determined by the 11-bit period value (f_pulse) written to $4002–$4003/$4006–$4007
|
||||
; the output frequency (f) of the generator can be determined by the 11-bit period value (f_pulse) written to $4002-$4003/$4006-$4007
|
||||
; note that triangle channel is one octave lower
|
||||
; frequency = cpu_speed / (#$0f * (f_pulse + 1))
|
||||
; ex: 1789773 / (#$0f * (#$06ae + 1)) => 65.38 Hz
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
; Contra US Disassembly - v1.2
|
||||
; Contra US Disassembly - v1.3
|
||||
; https://github.com/vermiceli/nes-contra-us
|
||||
; Bank 2 starts with RLE-encoded level data (graphic super tiles for the level
|
||||
; screens). It then contains compressed tile data and alternate tile data and
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
; Contra US Disassembly - v1.2
|
||||
; Contra US Disassembly - v1.3
|
||||
; https://github.com/vermiceli/nes-contra-us
|
||||
; Bank 3 starts with the data that specifies which pattern table tiles comprises
|
||||
; super-tiles along with the color palettes. This bank also has the routines
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
; Contra US Disassembly - v1.2
|
||||
; Contra US Disassembly - v1.3
|
||||
; https://github.com/vermiceli/nes-contra-us
|
||||
; Bank 4 mostly contains compressed graphic data. The rest of bank 4 is the code
|
||||
; for the ending scene animation and the ending credits, including the ending
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
; Contra US Disassembly - v1.2
|
||||
; Contra US Disassembly - v1.3
|
||||
; https://github.com/vermiceli/nes-contra-us
|
||||
; Bank 5 mostly contains compressed graphic data. The rest of bank 5 is the
|
||||
; code and lookup tables for automated input for the 3 demo (attract) levels.
|
||||
|
@ -86,15 +86,16 @@ graphic_data_17:
|
|||
graphic_data_18:
|
||||
.incbin "assets/graphic_data/graphic_data_18.bin"
|
||||
|
||||
; run as part of showing the demo
|
||||
; DEMO_FIRE_DELAY_TIMER starts at 0 increments to #$ff and stops
|
||||
; simulates player input for demo levels for both players
|
||||
; begins firing after #$e0 frames (see DEMO_FIRE_DELAY_TIMER)
|
||||
load_demo_input_table:
|
||||
lda CONTROLLER_STATE_DIFF ; get player input
|
||||
and #$30 ; start and select button
|
||||
bne end_demo_level ; exit demo if player has pressed start or select
|
||||
inc DEMO_FIRE_DELAY_TIMER ; increase DEMO_FIRE_DELAY_TIMER by 1
|
||||
inc DEMO_FIRE_DELAY_TIMER ; starts at 0 increments to #$ff and stops
|
||||
; used by demo logic to wait #$e0 frames until begin firing
|
||||
bne @player_loop ; branch when DEMO_FIRE_DELAY_TIMER is not 0 (hasn't wrapped around)
|
||||
dec DEMO_FIRE_DELAY_TIMER ; decrease DEMO_FIRE_DELAY_TIMER by 1 (setting to -1), this means delay is complete
|
||||
dec DEMO_FIRE_DELAY_TIMER ; wrapped around, pin to #$ff
|
||||
|
||||
@player_loop:
|
||||
ldx #$01 ; initialize X to 1 (player loop starting at player 2)
|
||||
|
@ -163,7 +164,7 @@ set_player_demo_input:
|
|||
; for non M, nor L weapon, press b button every #$07 frames
|
||||
@fire_weapon_input:
|
||||
lda FRAME_COUNTER ; load frame counter
|
||||
and #$07 ; checking every 7th frame
|
||||
and #$07 ; checking every 8th frame
|
||||
bne player_demo_input_chg_player ; move to next player without firing weapon
|
||||
lda CONTROLLER_STATE_DIFF,x ; load current controller input
|
||||
ora #$40 ; press b button
|
||||
|
@ -195,7 +196,7 @@ demo_input_pointer_table:
|
|||
; * second byte is number of even-numbered frames to apply the input for
|
||||
; while possible, player firing isn't specified in these input tables
|
||||
; instead, that is handled automatically as part of running the demo
|
||||
; * m or l weapons are always firing, other weapons fire every #$07 frames
|
||||
; * m or l weapons are always firing, other weapons fire every #$08 frames
|
||||
; $00, $00 is filler so the demo level doesn't end by reading a #$ff
|
||||
; input table for level 1 player 1 for demo (#$5A bytes)
|
||||
demo_input_tbl_l1_p1:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
; Contra US Disassembly - v1.2
|
||||
; Contra US Disassembly - v1.3
|
||||
; https://github.com/vermiceli/nes-contra-us
|
||||
; Bank 6 contains compressed graphics data, data for short text sequences like
|
||||
; level names and menu options. Bank 6 also contains the code for the players'
|
||||
|
@ -289,7 +289,7 @@ intro_background_palette2:
|
|||
; ensure player in valid state to fire a bullet, e.g. not being electrocuted
|
||||
check_player_fire:
|
||||
lda PLAYER_HIDDEN,x ; 0 - visible; #$01/#$ff = invisible (any non-zero)
|
||||
ora $c8,x ; counter for electrocution
|
||||
ora ELECTROCUTED_TIMER,x ; counter for electrocution
|
||||
bne check_player_fire_exit ; exit if being electrocuted or $ba,x is set
|
||||
lda PLAYER_WATER_STATE,x ; see if player in water
|
||||
beq @player_shoot_test
|
||||
|
@ -862,7 +862,7 @@ set_bullet_velocity:
|
|||
asl ; double twice to get correct offset
|
||||
tay
|
||||
lda ($01),y ; load x velocity fast value
|
||||
sta PLAYER_BULLET_VEL_X_FAST,x ; store x velocity fast value
|
||||
sta PLAYER_BULLET_X_VEL_FAST,x ; store x velocity fast value
|
||||
iny ; increment velocity table read offset
|
||||
lda ($01),y ; load x fractional velocity value
|
||||
sta PLAYER_BULLET_X_VEL_FRACT,x ; store x fractional velocity value
|
||||
|
@ -1000,7 +1000,7 @@ set_indoor_bullet_vel:
|
|||
@set_x_vel:
|
||||
jsr @set_vel_for_speed_code ; determine fast and fractional velocity based on a and whether rapid fire is enabled
|
||||
lda $0f ; load resulting fast velocity
|
||||
sta PLAYER_BULLET_VEL_X_FAST,x ; set indoor bullet fast x velocity
|
||||
sta PLAYER_BULLET_X_VEL_FAST,x ; set indoor bullet fast x velocity
|
||||
lda $0e ; load resulting fractional velocity
|
||||
sta PLAYER_BULLET_X_VEL_FRACT,x ; set indoor bullet fractional x velocity
|
||||
rts
|
||||
|
@ -1118,7 +1118,7 @@ s_weapon_init_bullet_velocities:
|
|||
lda ($04),y
|
||||
sta PLAYER_BULLET_Y_VEL_FAST,x
|
||||
lda ($06),y
|
||||
sta PLAYER_BULLET_VEL_X_FAST,x
|
||||
sta PLAYER_BULLET_X_VEL_FAST,x
|
||||
rts
|
||||
|
||||
; table for player aim direction (#$c bytes)
|
||||
|
@ -1651,7 +1651,7 @@ update_player_fs_bullet_x_pos:
|
|||
adc PLAYER_BULLET_X_VEL_FRACT,x ; add x fractional velocity, noting the carry being set if overflow
|
||||
sta PLAYER_BULLET_VEL_FS_X_ACCUM,x ; add accumulated value back
|
||||
lda PLAYER_BULLET_FS_X,x
|
||||
adc PLAYER_BULLET_VEL_X_FAST,x ; add fast X velocity and any carry from accumulator
|
||||
adc PLAYER_BULLET_X_VEL_FAST,x ; add fast X velocity and any carry from accumulator
|
||||
sta PLAYER_BULLET_FS_X,x
|
||||
rts
|
||||
|
||||
|
@ -1660,19 +1660,19 @@ update_player_bullet_pos:
|
|||
jsr check_bullet_solid_bg_collision ; if specified, check for bullet collision with solid background
|
||||
; and if so move bullet routine to player_bullet_collision_routine
|
||||
bmi bullet_logic_exit ; exit if bullet collided with solid object
|
||||
lda PLAYER_BULLET_VEL_X_ACCUM,x ; load accumulator value for bullet X velocity
|
||||
lda PLAYER_BULLET_X_VEL_ACCUM,x ; load accumulator value for bullet X velocity
|
||||
clc ; clear carry in preparation for addition
|
||||
adc PLAYER_BULLET_X_VEL_FRACT,x ; add x fractional velocity, noting the carry being set if overflow
|
||||
sta PLAYER_BULLET_VEL_X_ACCUM,x ; add accumulated value back
|
||||
sta PLAYER_BULLET_X_VEL_ACCUM,x ; add accumulated value back
|
||||
lda PLAYER_BULLET_X_POS,x ; load bullet X position
|
||||
adc PLAYER_BULLET_VEL_X_FAST,x ; add fast X velocity and any carry from accumulator
|
||||
adc PLAYER_BULLET_X_VEL_FAST,x ; add fast X velocity and any carry from accumulator
|
||||
sta PLAYER_BULLET_X_POS,x ; set new X position
|
||||
|
||||
update_player_bullet_y_pos:
|
||||
clc ; clear carry in preparation for addition
|
||||
lda PLAYER_BULLET_VEL_Y_ACCUM,x ; load accumulator value for bullet Y velocity
|
||||
lda PLAYER_BULLET_Y_VEL_ACCUM,x ; load accumulator value for bullet Y velocity
|
||||
adc PLAYER_BULLET_Y_VEL_FRACT,x ; add y fractional velocity, noting the carry being set if overflow
|
||||
sta PLAYER_BULLET_VEL_Y_ACCUM,x ; add accumulated value back
|
||||
sta PLAYER_BULLET_Y_VEL_ACCUM,x ; add accumulated value back
|
||||
lda PLAYER_BULLET_Y_POS,x ; load bullet Y position
|
||||
adc PLAYER_BULLET_Y_VEL_FAST,x ; add fast Y velocity and any carry from accumulator
|
||||
sta PLAYER_BULLET_Y_POS,x ; set new Y position
|
||||
|
@ -1726,7 +1726,7 @@ clear_bullet_values:
|
|||
sta PLAYER_BULLET_F_RAPID,x
|
||||
sta PLAYER_BULLET_DIST,x
|
||||
sta PLAYER_BULLET_AIM_DIR,x
|
||||
sta PLAYER_BULLET_VEL_X_FAST,x
|
||||
sta PLAYER_BULLET_X_VEL_FAST,x
|
||||
sta PLAYER_BULLET_X_VEL_FRACT,x
|
||||
sta PLAYER_BULLET_Y_VEL_FAST,x
|
||||
sta PLAYER_BULLET_Y_VEL_FRACT,x
|
||||
|
@ -1822,7 +1822,7 @@ update_s_bullet_indoor_pos:
|
|||
lda PLAYER_BULLET_VEL_FS_X_ACCUM,x ; ignore, no affect
|
||||
clc ; ignore, no affect
|
||||
adc PLAYER_BULLET_S_ADJ_ACCUM,x ; ignore, no affect
|
||||
sta PLAYER_BULLET_VEL_X_ACCUM,x ; unused result, never read for S indoor bullets !(WHY?)
|
||||
sta PLAYER_BULLET_X_VEL_ACCUM,x ; unused result, never read for S indoor bullets !(WHY?)
|
||||
lda PLAYER_BULLET_FS_X,x ; load center x position on screen f bullet swirls around
|
||||
clc ; clear carry in preparation for addition
|
||||
adc PLAYER_BULLET_S_INDOOR_ADJ,x ; add the indoor adjustment
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
; Contra US Disassembly - v1.2
|
||||
; Contra US Disassembly - v1.3
|
||||
; https://github.com/vermiceli/nes-contra-us
|
||||
; Bank 7 is the core of the game's programming. Reset, NMI, and IRQ vectors are
|
||||
; in this bank and is the entry point to the game. Bank 7 is always loaded in
|
||||
|
@ -4889,7 +4889,6 @@ set_vel_for_speed_code_a:
|
|||
sta $0e ; set $0e to #$00
|
||||
ldy #$07 ; set number of bits to rotate speed code to #$07
|
||||
|
||||
|
||||
; for a given value $0f, set fast ($0f) and fractional ($0e) velocities based on y
|
||||
; negate final results if $12 is greater than or equal to #$00
|
||||
; also used directly for indoor bullets
|
||||
|
@ -9734,7 +9733,7 @@ aim_and_create_enemy_bullet:
|
|||
sty $06 ; store bullet speed code in $06
|
||||
sta $00 ; store bullet type temporarily
|
||||
lda #$01 ; a = #$01, use quadrant_aim_dir_01
|
||||
sta $0f ; quadrant_aim_dir_lookup_tbl offset (quadrant_aim_dir_01)
|
||||
sta $0f ; quadrant_aim_dir_lookup_ptr_tbl offset (quadrant_aim_dir_01)
|
||||
lda $0a ; load player y position
|
||||
bpl @continue ; branch if >= #$00
|
||||
lda $0c ; load player y position
|
||||
|
@ -9857,10 +9856,10 @@ create_enemy_bullet:
|
|||
|
||||
@continue:
|
||||
sta $06 ; store speed code in $06
|
||||
lda $08 ; load enemy bullet y position
|
||||
sta ENEMY_Y_POS,x ; store enemy bullet y position on screen
|
||||
lda $09 ; load enemy bullet x position
|
||||
sta ENEMY_X_POS,x ; store enemy bullet x position on screen
|
||||
lda $08 ; load created bullet enemy y position
|
||||
sta ENEMY_Y_POS,x ; set created bullet enemy y position
|
||||
lda $09 ; load created bullet enemy y position
|
||||
sta ENEMY_X_POS,x ; set created bullet enemy x position
|
||||
lda $0a
|
||||
and #$1f ; keep bits ...x xxxx (quadrant aim dir)
|
||||
|
||||
|
@ -10151,7 +10150,7 @@ rotate_enemy_var_1:
|
|||
rts
|
||||
|
||||
; determines which direction to rotate based on quadrant_aim_dir_00
|
||||
; targetting player index ($0a)
|
||||
; targeting player index ($0a)
|
||||
; input
|
||||
; * $0a - player index to target, 0 = player 1, 1 = player 2
|
||||
; * $08 - source y position
|
||||
|
@ -10162,10 +10161,10 @@ rotate_enemy_var_1:
|
|||
; * $0c - new enemy aim direction
|
||||
get_rotate_00:
|
||||
lda #$00 ; a = #$00 (use quadrant_aim_dir_00)
|
||||
beq get_rotate_dir_for_index ; always jump, get enemy aim direction and rotation direction using quadrant_aim_dir_00
|
||||
beq get_rotate_dir_for_index ; always branch, get enemy aim direction and rotation direction using quadrant_aim_dir_00
|
||||
|
||||
; determines which direction to rotate based on quadrant_aim_dir_01
|
||||
; targetting player index ($0a)
|
||||
; targeting player index ($0a)
|
||||
; input
|
||||
; * $0a - player index to target, 0 = player 1, 1 = player 2
|
||||
; * $08 - source y position
|
||||
|
@ -10177,10 +10176,10 @@ get_rotate_00:
|
|||
get_rotate_01:
|
||||
lda #$01 ; a = #$01 (use quadrant_aim_dir_01)
|
||||
|
||||
; determines which direction to rotate based on quadrant_aim_dir_lookup_tbl index offset (a)
|
||||
; targetting player index ($0a)
|
||||
; determines which direction to rotate based on quadrant_aim_dir_lookup_ptr_tbl index offset (a)
|
||||
; targeting player index ($0a)
|
||||
; input
|
||||
; * a - quadrant_aim_dir_lookup_tbl offset table
|
||||
; * a - quadrant_aim_dir_lookup_ptr_tbl offset table
|
||||
; * $0a - player index to target, 0 = player 1, 1 = player 2
|
||||
; * $08 - source y position
|
||||
; * $09 - source x position
|
||||
|
@ -10189,7 +10188,7 @@ get_rotate_01:
|
|||
; * a - rotation direction, #$00 clockwise, #$01 counterclockwise, #$80 no rotation needed
|
||||
; * $0c - new enemy aim direction
|
||||
get_rotate_dir_for_index:
|
||||
sta $0f ; set quadrant_aim_dir_lookup_tbl index offset
|
||||
sta $0f ; set quadrant_aim_dir_lookup_ptr_tbl index offset
|
||||
lda $0a ; load player index
|
||||
bpl @get_quadrant_aim_dir ; branch if closest player has been determined
|
||||
lda $0c ; no player to target, not sure when this happens (see player_enemy_x_dist)
|
||||
|
@ -10211,14 +10210,14 @@ get_rotate_dir_for_index:
|
|||
; * $07 - specifies quadrant to aim in (0 = quadrant IV, 1 = quadrant I, 2 = quadrant III, 3 = quadrant II)
|
||||
; * bit 0 - 0 = bottom half of plane (quadrants III and IV), 1 = top half of plane (quadrants I and II)
|
||||
; * bit 1 - 0 = right half of the plan (quadrants I and IV), 1 = left half of plane (quadrants II and III)
|
||||
; * $0f - quadrant_aim_dir_lookup_tbl offset
|
||||
; * $0f - quadrant_aim_dir_lookup_ptr_tbl offset
|
||||
; output
|
||||
; * negative flag - set when enemy is already aiming at player and no rotation is needed
|
||||
; * a - rotation direction, #$00 clockwise, #$01 counterclockwise, #$80 no rotation needed
|
||||
; * $0c - new enemy aim direction
|
||||
get_rotate_dir:
|
||||
sta $0c ; store quadrant aim direction code in $0c
|
||||
lda $0f ; load quadrant_aim_dir_lookup_tbl offset (which quadrant_aim_dir_xx to use)
|
||||
lda $0f ; load quadrant_aim_dir_lookup_ptr_tbl offset (which quadrant_aim_dir_xx to use)
|
||||
lsr ; move bit 0 to the carry
|
||||
lda #$06 ; using either quadrant_aim_dir_00, or quadrant_aim_dir_02
|
||||
; midway direction, i.e. 9 o'clock
|
||||
|
@ -10324,7 +10323,7 @@ get_rotate_dir:
|
|||
dragon_arm_orb_seek_should_move:
|
||||
jsr set_08_09_to_enemy_pos ; set $08 and $09 to enemy x's X and Y position
|
||||
lda #$02 ; dragon arm orb is only enemy that uses quadrant_aim_dir_02
|
||||
sta $0f ; set quadrant_aim_dir_lookup_tbl offset to use quadrant_aim_dir_02
|
||||
sta $0f ; set quadrant_aim_dir_lookup_ptr_tbl offset to use quadrant_aim_dir_02
|
||||
jsr get_quadrant_aim_dir_for_player ; set a to the aim direction within a quadrant
|
||||
; based on source position ($09, $08) targeting player index $0a
|
||||
sta $0c ; store enemy aim direction in $0c
|
||||
|
@ -10393,7 +10392,7 @@ dragon_arm_orb_seek_should_move:
|
|||
|
||||
; determines the aim direction within a quadrant based on source position ($09, $08) targeting player index $0a
|
||||
; input
|
||||
; * $0f - quadrant_aim_dir_lookup_tbl offset [#$00-#$02]
|
||||
; * $0f - quadrant_aim_dir_lookup_ptr_tbl offset [#$00-#$02]
|
||||
; * $0a - player index of player to target (#$00 for p1 or #$01 for p2)
|
||||
; * $08 - source y position
|
||||
; * $09 - source x position
|
||||
|
@ -10443,7 +10442,7 @@ get_quadrant_aim_dir_for_player:
|
|||
; * $09 - source x position
|
||||
; * $0a - closest player y position
|
||||
; * $0b - closest player x position
|
||||
; * $0f - which of the #$03 tables from quadrant_aim_dir_lookup_tbl to use
|
||||
; * $0f - which of the #$03 tables from quadrant_aim_dir_lookup_ptr_tbl to use
|
||||
; output
|
||||
; * a - quadrant aim direction (quadrant_aim_dir_xx value)
|
||||
; * $07 - specifies quadrant to aim in (0 = quadrant IV, 1 = quadrant I, 2 = quadrant III, 3 = quadrant II)
|
||||
|
@ -10453,7 +10452,7 @@ get_quadrant_aim_dir:
|
|||
ldy #$00 ; default assume player is to the right and equal to or below enemy
|
||||
lda $0a ; load closest player y position
|
||||
sec ; set carry flag in preparation for subtraction
|
||||
sbc $08 ; subract enemy y position from player y position
|
||||
sbc $08 ; subtract enemy y position from player y position
|
||||
bcs @shift_get_x_diff ; branch if no overflow occurred (enemy above player or same vertical position)
|
||||
eor #$ff ; enemy below player, handle overflow, flip all bits and add one
|
||||
adc #$01
|
||||
|
@ -10477,33 +10476,33 @@ get_quadrant_aim_dir:
|
|||
iny ; if y was 0, now is 2, if y was 1, now is 3
|
||||
|
||||
@continue:
|
||||
lsr ; shift the difference between player and enemy x difference 6 bits
|
||||
lsr ; (every #$40 pixels difference is a new horizontal direction)
|
||||
lsr ; shift the difference between player and enemy x difference 6 bits
|
||||
lsr ; (every #$40 pixels difference is a new horizontal direction)
|
||||
lsr
|
||||
lsr
|
||||
lsr
|
||||
sty $07 ; store position of player relative to enemy in $07 (above/below, left/right)
|
||||
lsr ; push bit 5 to the carry flag for use after plp instruction below
|
||||
sta $0b ; overwrite player x position with shifted bits 6 and 7
|
||||
; (values [#$00-#$03]) of horizontal distance
|
||||
php ; backup CPU status flags on stack
|
||||
lda $0f ; load which of the #$03 tables from quadrant_aim_dir_lookup_tbl to use
|
||||
asl ; double since each entry is #$2 bytes
|
||||
tay ; transfer to offset register
|
||||
lda quadrant_aim_dir_lookup_tbl,y ; get low byte of quadrant_aim_dir_xx address
|
||||
sta $0c ; store low byte of pointer address in $0c
|
||||
lda quadrant_aim_dir_lookup_tbl+1,y ; get high byte of quadrant_aim_dir_xx address
|
||||
sta $0d ; store high byte of pointer address in $0d
|
||||
lda $0a ; load y difference to determine row offset
|
||||
sty $07 ; store position of player relative to enemy in $07 (above/below, left/right)
|
||||
lsr ; push bit 5 to the carry flag for use after plp instruction below
|
||||
sta $0b ; overwrite player x position with shifted bits 6 and 7
|
||||
; (values [#$00-#$03]) of horizontal distance
|
||||
php ; backup CPU status flags on stack
|
||||
lda $0f ; load which of the #$03 tables from quadrant_aim_dir_lookup_ptr_tbl to use
|
||||
asl ; double since each entry is #$2 bytes
|
||||
tay ; transfer to offset register
|
||||
lda quadrant_aim_dir_lookup_ptr_tbl,y ; get low byte of quadrant_aim_dir_xx address
|
||||
sta $0c ; store low byte of pointer address in $0c
|
||||
lda quadrant_aim_dir_lookup_ptr_tbl+1,y ; get high byte of quadrant_aim_dir_xx address
|
||||
sta $0d ; store high byte of pointer address in $0d
|
||||
lda $0a ; load y difference to determine row offset
|
||||
asl
|
||||
asl ; quadruple since each entry is #$04 bytes to get correct row
|
||||
adc $0b ; add the x distance between player and enemy as offset into the entry to load
|
||||
; this gets the column of the aim direction
|
||||
tay ; transfer to offset register
|
||||
lda ($0c),y ; load specific byte
|
||||
plp ; restore CPU status flags from stack
|
||||
bcs @set_and_exit ; branch if bit 5 of difference between player and enemy was set
|
||||
lsr ; this segments screen into bands for which nibble to use
|
||||
asl ; quadruple since each entry is #$04 bytes to get correct row
|
||||
adc $0b ; add the x distance between player and enemy as offset into the entry to load
|
||||
; this gets the column of the aim direction
|
||||
tay ; transfer to offset register
|
||||
lda ($0c),y ; load specific byte
|
||||
plp ; restore CPU status flags from stack
|
||||
bcs @set_and_exit ; branch if bit 5 of difference between player and enemy was set
|
||||
lsr ; this segments screen into bands for which nibble to use
|
||||
lsr
|
||||
lsr
|
||||
lsr
|
||||
|
@ -10512,8 +10511,8 @@ get_quadrant_aim_dir:
|
|||
and #$0f ; keep low nibble
|
||||
rts
|
||||
|
||||
; pointer table for set of quadran aim directions (#$3 * #$2 = #$6 bytes)
|
||||
quadrant_aim_dir_lookup_tbl:
|
||||
; pointer table for set of quadrant aim directions (#$3 * #$2 = #$6 bytes)
|
||||
quadrant_aim_dir_lookup_ptr_tbl:
|
||||
.addr quadrant_aim_dir_00 ; CPU address $f5b2 (soldiers, weapon boxes, red turrets, wall core)
|
||||
.addr quadrant_aim_dir_01 ; CPU address $f5d2 (rotating gun, wall turrets, sniper, eye projectile, spinning bubbles, jumping soldier, white blob)
|
||||
.addr quadrant_aim_dir_02 ; CPU address $f5f2 (dragon arm seeking)
|
||||
|
|
|
@ -1,438 +1,258 @@
|
|||
; Contra US Disassembly - v1.2
|
||||
; Contra US Disassembly - v1.3
|
||||
; https://github.com/vermiceli/nes-contra-us
|
||||
; constants.asm contains the list of constants with meaningful names for the
|
||||
; memory addresses used by the game. It also contains constants for the various
|
||||
; palette colors.
|
||||
|
||||
.importzp GAME_ROUTINE_INDEX ; $18
|
||||
.importzp GAME_END_ROUTINE_INDEX ; $19
|
||||
.importzp GAME_ROUTINE_INIT_FLAG ; $19
|
||||
.importzp FRAME_COUNTER ; $1a
|
||||
.importzp NMI_CHECK ; $1b
|
||||
.importzp DEMO_MODE ; $1c
|
||||
.importzp PLAYER_MODE_1D ; $1d
|
||||
.importzp DEMO_LEVEL_END_FLAG ; $1f
|
||||
.importzp PPU_READY ; $20
|
||||
.importzp GRAPHICS_BUFFER_OFFSET ; $21
|
||||
.importzp PLAYER_MODE ; $22
|
||||
.importzp GRAPHICS_BUFFER_MODE ; $23
|
||||
.importzp KONAMI_CODE_STATUS ; $24
|
||||
.importzp PAUSE_STATE ; $25
|
||||
.importzp DEMO_LEVEL ; $27
|
||||
.importzp INTRO_THEME_DELAY ; $28
|
||||
.importzp GAME_OVER_DELAY_TIMER ; $29
|
||||
.importzp DELAY_TIME_LOW_BYTE ; $2a
|
||||
.importzp DELAY_TIME_HIGH_BYTE ; $2b
|
||||
.importzp LEVEL_ROUTINE_INDEX ; $2c
|
||||
.importzp END_LEVEL_ROUTINE_INDEX ; $2d
|
||||
.importzp DEMO_FIRE_DELAY_TIMER ; $2e
|
||||
.importzp PLAYER_WEAPON_STRENGTH ; $2f
|
||||
.importzp CURRENT_LEVEL ; $30
|
||||
.importzp GAME_COMPLETION_COUNT ; $31
|
||||
.importzp P1_NUM_LIVES ; $32
|
||||
.importzp P2_NUM_LIVES ; $33
|
||||
.importzp RANDOM_NUM ; $34
|
||||
.importzp NUM_PALETTES_TO_LOAD ; $36
|
||||
.importzp INDOOR_SCREEN_CLEARED ; $37
|
||||
.importzp P1_GAME_OVER_STATUS ; $38
|
||||
.importzp P2_GAME_OVER_STATUS ; $39
|
||||
.importzp NUM_CONTINUES ; $3a
|
||||
.importzp BOSS_DEFEATED_FLAG ; $3b
|
||||
.importzp EXTRA_LIFE_SCORE_LOW ; $3c
|
||||
.importzp EXTRA_LIFE_SCORE_HIGH ; $3d
|
||||
.importzp KONAMI_CODE_NUM_CORRECT ; $3f
|
||||
.importzp LEVEL_LOCATION_TYPE ; $40
|
||||
.importzp LEVEL_SCROLLING_TYPE ; $41
|
||||
.importzp LEVEL_SCREEN_SUPERTILES_PTR ; $42
|
||||
.importzp LEVEL_SUPERTILE_DATA_PTR ; $44
|
||||
.importzp LEVEL_SUPERTILE_PALETTE_DATA ; $46
|
||||
.importzp LEVEL_ALT_GRAPHICS_POS ; $48
|
||||
.importzp COLLISION_CODE_1_TILE_INDEX ; $49
|
||||
.importzp COLLISION_CODE_0_TILE_INDEX ; $4a
|
||||
.importzp COLLISION_CODE_2_TILE_INDEX ; $4b
|
||||
.importzp LEVEL_PALETTE_CYCLE_INDEXES ; $4c
|
||||
.importzp LEVEL_PALETTE_INDEX ; $50
|
||||
.importzp LEVEL_STOP_SCROLL ; $58
|
||||
.importzp LEVEL_SOLID_BG_COLLISION_CHECK ; $59
|
||||
.importzp DEMO_INPUT_NUM_FRAMES ; $5a
|
||||
.importzp DEMO_INPUT_VAL ; $5c
|
||||
.importzp DEMO_INPUT_TBL_INDEX ; $5e
|
||||
.importzp PPU_WRITE_TILE_OFFSET ; $60
|
||||
.importzp LEVEL_TRANSITION_TIMER ; $61
|
||||
.importzp PPU_WRITE_ADDRESS_LOW_BYTE ; $62
|
||||
.importzp PPU_WRITE_ADDRESS_HIGH_BYTE ; $63
|
||||
.importzp LEVEL_SCREEN_NUMBER ; $64
|
||||
.importzp LEVEL_SCREEN_SCROLL_OFFSET ; $65
|
||||
.importzp ATTRIBUTE_TBL_WRITE_LOW_BYTE ; $66
|
||||
.importzp ATTRIBUTE_TBL_WRITE_HIGH_BYTE ; $67
|
||||
.importzp FRAME_SCROLL ; $68
|
||||
.importzp SUPERTILE_NAMETABLE_OFFSET ; $69
|
||||
.importzp SPRITE_LOAD_TYPE ; $6a
|
||||
.importzp CONT_END_SELECTION ; $6b
|
||||
.importzp ALT_GRAPHIC_DATA_LOADING_FLAG ; $71
|
||||
.importzp LEVEL_PALETTE_CYCLE ; $72
|
||||
.importzp INDOOR_SCROLL ; $73
|
||||
.importzp BG_PALETTE_ADJ_TIMER ; $74
|
||||
.importzp AUTO_SCROLL_TIMER_00 ; $75
|
||||
.importzp AUTO_SCROLL_TIMER_01 ; $76
|
||||
.importzp TANK_AUTO_SCROLL ; $77
|
||||
.importzp PAUSE_PALETTE_CYCLE ; $78
|
||||
.importzp SOLDIER_GENERATION_ROUTINE ; $79
|
||||
.importzp SOLDIER_GENERATION_TIMER ; $7a
|
||||
.importzp SOLDIER_GENERATION_X_POS ; $7b
|
||||
.importzp SOLDIER_GENERATION_Y_POS ; $7c
|
||||
.importzp FALCON_FLASH_TIMER ; $7d
|
||||
.importzp TANK_ICE_JOINT_SCROLL_FLAG ; $7f
|
||||
.importzp ENEMY_LEVEL_ROUTINES ; $80
|
||||
.importzp ENEMY_SCREEN_READ_OFFSET ; $82
|
||||
.importzp ENEMY_CURRENT_SLOT ; $83
|
||||
.importzp BOSS_AUTO_SCROLL_COMPLETE ; $84
|
||||
.importzp BOSS_SCREEN_ENEMIES_DESTROYED ; $85
|
||||
.importzp WALL_CORE_REMAINING ; $86
|
||||
.importzp WALL_PLATING_DESTROYED_COUNT ; $87
|
||||
.importzp INDOOR_ENEMY_ATTACK_COUNT ; $88
|
||||
.importzp INDOOR_RED_SOLDIER_CREATED ; $89
|
||||
.importzp GRENADE_LAUNCHER_FLAG ; $8a
|
||||
.importzp ALIEN_FETUS_AIM_TIMER_INDEX ; $8b
|
||||
.importzp ENEMY_ATTACK_FLAG ; $8e
|
||||
.importzp PLAYER_STATE ; $90
|
||||
.importzp INDOOR_TRANSITION_X_ACCUM ; $92
|
||||
.importzp PLAYER_JUMP_COEFFICIENT ; $94
|
||||
.importzp INDOOR_TRANSITION_X_FRACT_VEL ; $96
|
||||
.importzp PLAYER_X_VELOCITY ; $98
|
||||
.importzp INDOOR_TRANSITION_Y_FRACT_VEL ; $9a
|
||||
.importzp INDOOR_TRANSITION_Y_FAST_VEL ; $9c
|
||||
.importzp PLAYER_ANIM_FRAME_TIMER ; $9e
|
||||
.importzp PLAYER_JUMP_STATUS ; $a0
|
||||
.importzp PLAYER_FRAME_SCROLL ; $a2
|
||||
.importzp EDGE_FALL_CODE ; $a4
|
||||
.importzp PLAYER_ANIMATION_FRAME_INDEX ; $a6
|
||||
.importzp PLAYER_INDOOR_ANIM_Y ; $a8
|
||||
.importzp P1_CURRENT_WEAPON ; $aa
|
||||
.importzp P2_CURRENT_WEAPON ; $ab
|
||||
.importzp PLAYER_M_WEAPON_FIRE_TIME ; $ac
|
||||
.importzp NEW_LIFE_INVINCIBILITY_TIMER ; $ae
|
||||
.importzp INVINCIBILITY_TIMER ; $b0
|
||||
.importzp PLAYER_WATER_STATE ; $b2
|
||||
.importzp PLAYER_DEATH_FLAG ; $b4
|
||||
.importzp PLAYER_ON_ENEMY ; $b6
|
||||
.importzp PLAYER_FALL_X_FREEZE ; $b8
|
||||
.importzp PLAYER_HIDDEN ; $ba
|
||||
.importzp PLAYER_SPRITE_SEQUENCE ; $bc
|
||||
.importzp PLAYER_INDOOR_ANIM_X ; $be
|
||||
.importzp PLAYER_AIM_PREV_FRAME ; $c0
|
||||
.importzp PLAYER_AIM_DIR ; $c2
|
||||
.importzp PLAYER_Y_FRACT_VELOCITY ; $c4
|
||||
.importzp PLAYER_Y_FAST_VELOCITY ; $c6
|
||||
.importzp ELECTROCUTED_TIMER ; $c8
|
||||
.importzp INDOOR_PLAYER_JUMP_FLAG ; $ca
|
||||
.importzp PLAYER_WATER_TIMER ; $cc
|
||||
.importzp PLAYER_RECOIL_TIMER ; $ce
|
||||
.importzp INDOOR_PLAYER_ADV_FLAG ; $d0
|
||||
.importzp PLAYER_SPECIAL_SPRITE_TIMER ; $d2
|
||||
.importzp PLAYER_FAST_X_VEL_BOOST ; $d4
|
||||
.importzp PLAYER_SPRITE_CODE ; $d6
|
||||
.importzp PLAYER_SPRITE_FLIP ; $d8
|
||||
.importzp PLAYER_BG_FLAG_EDGE_DETECT ; $da
|
||||
.importzp PLAYER_GAME_OVER_BIT_FIELD ; $df
|
||||
.importzp SOUND_TABLE_PTR ; $ec
|
||||
.importzp CONTROLLER_STATE ; $f1
|
||||
.importzp CONTROLLER_STATE_DIFF ; $f5
|
||||
.importzp CTRL_KNOWN_GOOD ; $f9
|
||||
.importzp VERTICAL_SCROLL ; $fc
|
||||
.importzp HORIZONTAL_SCROLL ; $fd
|
||||
.importzp PPUMASK_SETTINGS ; $fe
|
||||
.importzp PPUCTRL_SETTINGS ; $ff
|
||||
|
||||
.import SOUND_CMD_LENGTH ; $0100
|
||||
.import SOUND_CODE ; $0106
|
||||
.import SOUND_PULSE_LENGTH ; $010c
|
||||
.import SOUND_CMD_LOW_ADDR ; $0112
|
||||
.import SOUND_CMD_HIGH_ADDR ; $0118
|
||||
.import SOUND_VOL_ENV ; $011e
|
||||
.import SOUND_CURRENT_SLOT ; $0120
|
||||
.import PERCUSSION_INDEX_BACKUP ; $0121
|
||||
.import INIT_SOUND_CODE ; $0122
|
||||
.import SOUND_CHNL_REG_OFFSET ; $0123
|
||||
.import SOUND_FLAGS ; $0124
|
||||
.import LVL_PULSE_VOL_INDEX ; $012a
|
||||
.import PULSE_VOL_DURATION ; $012a
|
||||
.import PAUSE_STATE_01 ; $012f
|
||||
.import DECRESCENDO_END_PAUSE ; $0131
|
||||
.import SOUND_PITCH_ADJ ; $0132
|
||||
.import UNKNOWN_SOUND_00 ; $0136
|
||||
.import UNKNOWN_SOUND_01 ; $013c
|
||||
.import SOUND_CFG_LOW ; $0142
|
||||
.import SOUND_TRIANGLE_CFG ; $0144
|
||||
.import SOUND_REPEAT_COUNT ; $0148
|
||||
.import SOUND_CFG_HIGH ; $014e
|
||||
.import SOUND_LENGTH_MULTIPLIER ; $0154
|
||||
.import SOUND_PERIOD_ROTATE ; $015a
|
||||
.import PULSE_VOLUME ; $0160
|
||||
.import NEW_SOUND_CODE_LOW_ADDR ; $0166
|
||||
.import NEW_SOUND_CODE_HIGH_ADDR ; $016c
|
||||
.import SOUND_PULSE_PERIOD ; $0172
|
||||
.import VIBRATO_CTRL ; $0178
|
||||
.import SOUND_VOL_TIMER ; $017a
|
||||
.import PULSE_NOTE ; $017c
|
||||
.import VIBRATO_DELAY ; $017e
|
||||
.import VIBRATO_AMOUNT ; $0180
|
||||
.import LEVEL_END_DELAY_TIMER ; $0190
|
||||
.import LEVEL_END_SQ_1_TIMER ; $0191
|
||||
.import LEVEL_END_LVL_ROUTINE_STATE ; $0193
|
||||
.import LEVEL_END_PLAYERS_ALIVE ; $0194
|
||||
.import SOLDIER_GEN_SCREEN ; $0195
|
||||
.import SCREEN_GEN_SOLDIERS ; $0196
|
||||
.import OAMDMA_CPU_BUFFER ; $0200
|
||||
.import CPU_SPRITE_BUFFER ; $0300
|
||||
.import PLAYER_SPRITES ; $0300
|
||||
.import ENEMY_SPRITES ; $030a
|
||||
.import SPRITE_Y_POS ; $031a
|
||||
.import ENEMY_Y_POS ; $0324
|
||||
.import SPRITE_X_POS ; $0334
|
||||
.import ENEMY_X_POS ; $033e
|
||||
.import SPRITE_ATTR ; $034e
|
||||
.import ENEMY_SPRITE_ATTR ; $0358
|
||||
.import PLAYER_BULLET_SPRITE_CODE ; $0368
|
||||
.import PLAYER_BULLET_SPRITE_ATTR ; $0378
|
||||
.import PLAYER_BULLET_SLOT ; $0388
|
||||
.import PLAYER_BULLET_Y_VEL_ACCUM ; $0398
|
||||
.import PLAYER_BULLET_X_VEL_ACCUM ; $03a8
|
||||
.import PLAYER_BULLET_Y_POS ; $03b8
|
||||
.import PLAYER_BULLET_X_POS ; $03c8
|
||||
.import PLAYER_BULLET_Y_VEL_FRACT ; $03d8
|
||||
.import PLAYER_BULLET_X_VEL_FRACT ; $03e8
|
||||
.import PLAYER_BULLET_Y_VEL_FAST ; $03f8
|
||||
.import PLAYER_BULLET_X_VEL_FAST ; $0408
|
||||
.import PLAYER_BULLET_TIMER ; $0418
|
||||
.import PLAYER_BULLET_AIM_DIR ; $0428
|
||||
.import PLAYER_BULLET_ROUTINE ; $0438
|
||||
.import PLAYER_BULLET_OWNER ; $0448
|
||||
.import PLAYER_BULLET_F_RAPID ; $0458
|
||||
.import PLAYER_BULLET_S_INDOOR_ADJ ; $0458
|
||||
.import PLAYER_BULLET_DIST ; $0468
|
||||
.import PLAYER_BULLET_S_ADJ_ACCUM ; $0468
|
||||
.import PLAYER_BULLET_FS_X ; $0478
|
||||
.import PLAYER_BULLET_F_Y ; $0488
|
||||
.import PLAYER_BULLET_S_RAPID ; $0488
|
||||
.import PLAYER_BULLET_VEL_FS_X_ACCUM ; $0498
|
||||
.import PLAYER_BULLET_VEL_F_Y_ACCUM ; $04a8
|
||||
.import PLAYER_BULLET_S_BULLET_NUM ; $04a8
|
||||
.import ENEMY_ROUTINE ; $04b8
|
||||
.import ENEMY_Y_VEL_ACCUM ; $04c8
|
||||
.import ENEMY_X_VEL_ACCUM ; $04d8
|
||||
.import ENEMY_Y_VELOCITY_FAST ; $04e8
|
||||
.import ENEMY_Y_VELOCITY_FRACT ; $04f8
|
||||
.import ENEMY_X_VELOCITY_FAST ; $0508
|
||||
.import ENEMY_X_VELOCITY_FRACT ; $0518
|
||||
.import ENEMY_TYPE ; $0528
|
||||
.import ENEMY_ANIMATION_DELAY ; $0538
|
||||
.import ENEMY_VAR_A ; $0548
|
||||
.import ENEMY_ATTACK_DELAY ; $0558
|
||||
.import ENEMY_VAR_B ; $0558
|
||||
.import ENEMY_FRAME ; $0568
|
||||
.import ENEMY_HP ; $0578
|
||||
.import ENEMY_SCORE_COLLISION ; $0588
|
||||
.import ENEMY_STATE_WIDTH ; $0598
|
||||
.import ENEMY_ATTRIBUTES ; $05a8
|
||||
.import ENEMY_VAR_1 ; $05b8
|
||||
.import ENEMY_VAR_2 ; $05c8
|
||||
.import ENEMY_VAR_3 ; $05d8
|
||||
.import ENEMY_VAR_4 ; $05e8
|
||||
.import LEVEL_SCREEN_SUPERTILES ; $0600
|
||||
.import BG_COLLISION_DATA ; $0680
|
||||
.import CPU_GRAPHICS_BUFFER ; $0700
|
||||
.import PALETTE_CPU_BUFFER ; $07c0
|
||||
.import HIGH_SCORE_LOW ; $07e0
|
||||
.import HIGH_SCORE_HIGH ; $07e1
|
||||
.import PLAYER_1_SCORE_LOW ; $07e2
|
||||
.import PLAYER_1_SCORE_HIGH ; $07e3
|
||||
.import PLAYER_2_SCORE_LOW ; $07e4
|
||||
.import PLAYER_2_SCORE_HIGH ; $07e5
|
||||
.import PREVIOUS_ROM_BANK ; $07ec
|
||||
.import PREVIOUS_ROM_BANK_1 ; $07ed
|
||||
|
||||
BANK_NUMBER = $8000
|
||||
GAME_ROUTINE_INDEX = $18 ; which part of the game routine to execute (see game_routine_pointer_table)
|
||||
GAME_END_ROUTINE_INDEX = $19 ; used after beating the game to know which part of the ending sequence to execute for sequencing the animations, credits, restart, etc. (see game_end_routine_tbl)
|
||||
GAME_ROUTINE_INIT_FLAG = $19 ; (same address as above) used to determine if the current game_routine has been initialized, used in game_routine_02 and game_routine_03
|
||||
FRAME_COUNTER = $1a ; the frame counter loops from #$00 to #$ff increments once per frame. Also known as the global timer
|
||||
NMI_CHECK = $1b ; set to #$01 at start of nmi and #$00 at end
|
||||
; used to track if nmi occurred during game loop
|
||||
; bit 7 is set when inside play_sound, i.e. init_sound_code_vars
|
||||
DEMO_MODE = $1c ; #$00 not in demo mode, #$01 demo mode on
|
||||
PLAYER_MODE_1D = $1d ; #$01 for 1 player, #$07 for 2 player. Not sure why developer just didn't use PLAYER_MODE instead
|
||||
DEMO_LEVEL_END_FLAG = $1f ; whether or not demo for the level is complete and new demo level should play
|
||||
PPU_READY = $20 ; #$00 when at least 5 executions of nmi_start have happened since last configure_PPU call
|
||||
GRAPHICS_BUFFER_OFFSET = $21 ; current write offset into CPU_GRAPHICS_BUFFER (CPU_GRAPHICS_BUFFER contains pattern table tiles that are written to PPU)
|
||||
PLAYER_MODE = $22 ; #$00 = single player, #$01 = 2 player
|
||||
GRAPHICS_BUFFER_MODE = $23 ; defines the format of the CPU_GRAPHICS_BUFFER. #$ff is for super-tile data, #$00 is for text strings and palette data
|
||||
KONAMI_CODE_STATUS = $24 ; #$00 not entered, #$01 entered, (30 lives code)
|
||||
PAUSE_STATE = $25 ; #$00 when not paused, #$01 when paused
|
||||
DEMO_LEVEL = $27 ; the current level when in DEMO mode
|
||||
; only ever 0, 1 or 2 as those are the only levels demoed
|
||||
INTRO_THEME_DELAY = $28 ; timer to prevent starting a level until the intro theme is complete (including explosion sound).
|
||||
; initialized to #a4, decrements every other frame for ~5 seconds for NTSC
|
||||
GAME_OVER_DELAY_TIMER = $29 ; goes from #$60 to #$00, timer after dying before showing score
|
||||
DELAY_TIME_LOW_BYTE = $2a ; the low byte of the delay
|
||||
DELAY_TIME_HIGH_BYTE = $2b ; the high byte of the delay
|
||||
LEVEL_ROUTINE_INDEX = $2c ; the index into level_routine_ptr_tbl of the routine to run
|
||||
END_LEVEL_ROUTINE_INDEX = $2d ; offset into either end_level_sequence_ptr_tbl or end_game_sequence_ptr_tbl
|
||||
DEMO_FIRE_DELAY_TIMER = $2e ; the number of frames to delay before starting to fire when demoing
|
||||
PLAYER_WEAPON_STRENGTH = $2f ; the damage strength of the player's current weapon (see weapon_strength) based on bits 0-2 of P1_CURRENT_WEAPON,x
|
||||
; Default = #$00, M = #$02, F = #$01, S = #$03, L = #$02
|
||||
CURRENT_LEVEL = $30 ; #$00-#$09, #$00 to #$07 represent levels 1 through 8. #$9 is interpreted as game over sequence
|
||||
GAME_COMPLETION_COUNT = $31 ; the number of times the game has been completed (final boss defeated)
|
||||
P1_NUM_LIVES = $32 ; P1 number of lives, #$00 is last life, on game over stays #$00, but P1_GAME_OVER_STATUS becomes #$01
|
||||
P2_NUM_LIVES = $33 ; P2 number of lives, #$00 is last life, on game over stays #$00, but P2_GAME_OVER_STATUS becomes #$01
|
||||
RANDOM_NUM = $34 ; random number increased in forever_loop
|
||||
NUM_PALETTES_TO_LOAD = $36 ; the number of palettes to load into CPU memory
|
||||
INDOOR_SCREEN_CLEARED = $37 ; whether indoor screen has had all cores destroyed (0 = not cleared, 1 = cleared, #$80 = cleared and fence removed)
|
||||
P1_GAME_OVER_STATUS = $38 ; #$00 not game over, #$01 game over
|
||||
P2_GAME_OVER_STATUS = $39 ; #$00 not game over, #$01 game over or player 2 not playing (1 player game)
|
||||
NUM_CONTINUES = $3a ; the number of continues remaining
|
||||
BOSS_DEFEATED_FLAG = $3b ; whether or not the level boss has been defeated (0 = no, 1 = yes)
|
||||
; after set to 1, end level sequence logic uses this value as well using values #$81 and #$02
|
||||
EXTRA_LIFE_SCORE_LOW = $3c ; the low byte of the score required for the next extra life
|
||||
EXTRA_LIFE_SCORE_HIGH = $3d ; the high byte of the score required for the next extra life
|
||||
; $3e is the EXTRA_LIFE_SCORE_LOW for player 2
|
||||
KONAMI_CODE_NUM_CORRECT = $3f ; the number of successful inputs of the Konami code sequence #$0a for all correct
|
||||
; also used as player 2's EXTRA_LIFE_SCORE_HIGH byte during game play
|
||||
|
||||
; level header data
|
||||
LEVEL_LOCATION_TYPE = $40 ; current level type #$00 outdoor, #$01 indoor (base level); #$80 on indoor/base boss screen and indoor/base levels when players advancing to next screen
|
||||
LEVEL_SCROLLING_TYPE = $41 ; current level scrolling type #$00 horizontal (and indoor/base level) #$01 vertical
|
||||
LEVEL_SCREEN_SUPERTILES_PTR = $42 ; $42,$43 stores 2-byte address to bank 2 containing which super-tiles to use for each screen of the level (level_x_supertiles_screen_ptr_table)
|
||||
LEVEL_SUPERTILE_DATA_PTR = $44 ; current level 2-byte pointer to super-tile data, which defines pattern table tiles of the super-tiles that are used to make level blocks
|
||||
LEVEL_SUPERTILE_PALETTE_DATA = $46 ; current level 2-byte pointer address to the palettes used for each super-tile, each byte describes the 4 palettes for a single super-tile
|
||||
LEVEL_ALT_GRAPHICS_POS = $48 ; how far into level (in number of screens) before loading alternate graphic data
|
||||
COLLISION_CODE_1_TILE_INDEX = $49 ; pattern table tiles below this tile index (but not #$00) are considered Collision Code 1 (floor)
|
||||
COLLISION_CODE_0_TILE_INDEX = $4a ; pattern table tiles >= $49 and less than this tile index are considered Collision Code 0 (empty)
|
||||
COLLISION_CODE_2_TILE_INDEX = $4b ; pattern table tiles >= $4a and less than this tile index are considered Collision Code 2 (water)
|
||||
|
||||
LEVEL_PALETTE_CYCLE_INDEXES = $4c ; palette indexes into game_palettes to cycle through for the level for the 4th nametable palette index [$4c-4f]
|
||||
LEVEL_PALETTE_INDEX = $50 ; the level's initial background palettes [$50 to $54) and sprite palettes [$54 to $58). Offsets into game_palettes table
|
||||
|
||||
LEVEL_STOP_SCROLL = $58 ; the screen of the level to stop scrolling, set to #$ff when boss auto scroll starts
|
||||
LEVEL_SOLID_BG_COLLISION_CHECK = $59 ; used to determine whether to check for bullet and weapon item solid bg collisions
|
||||
; 1. When non-zero, specifies weapon item should check for solid bg collisions (weapon_item_check_bg_collision)
|
||||
; 2. When negative, used to let bullet (player and enemy) collision detection code to know to look for bullet-solid background collisions
|
||||
; This is for levels 6 - energy zone and 7 - hangar. (see check_bullet_solid_bg_collision and enemy_bullet_routine_01)
|
||||
|
||||
DEMO_INPUT_NUM_FRAMES = $5a ; used to determine how many even-numbered frames to continue pressing the button specified in $5c for demo
|
||||
; $5b the DEMO_INPUT_NUM_FRAMES for player 2
|
||||
DEMO_INPUT_VAL = $5c ; the current controller input pressed during a demo
|
||||
; $5d is DEMO_INPUT_VAL for player 2
|
||||
DEMO_INPUT_TBL_INDEX = $5e ; when in demo, this stores the offset into specific demo_input_tbl_lX_pX table
|
||||
; $5f is for player 2
|
||||
PPU_WRITE_TILE_OFFSET = $60 ; the current write offset of the super-tile data, number of tiles outside the current view
|
||||
; horizontal levels loops #$00 to #$1f, vert starts with #$1d goes down to #$00 before looping
|
||||
LEVEL_TRANSITION_TIMER = $61 ; used in vertical levels to time animation between sections for every 'up' input
|
||||
; used in indoor levels between screens to animate moving forward
|
||||
PPU_WRITE_ADDRESS_LOW_BYTE = $62 ; used to populate the PPU write address in the CPU_GRAPHICS_BUFFER
|
||||
PPU_WRITE_ADDRESS_HIGH_BYTE = $63 ; used to populate the PPU write address in the CPU_GRAPHICS_BUFFER
|
||||
LEVEL_SCREEN_NUMBER = $64 ; the screen number of the current level (how many screens into the level)
|
||||
LEVEL_SCREEN_SCROLL_OFFSET = $65 ; the number of pixels into LEVEL_SCREEN_NUMBER the level has scrolled. Goes from #$00-#$ff for each screen (256 pixels)
|
||||
; for horizontal levels, this is how many pixels scrolled to the right
|
||||
; for vertical levels, this is how many pixels up scrolled, note this value is equal to #$f0 - VERTICAL_SCROLL
|
||||
; for indoor levels, after defeating a wall, increases from #$00 to #03
|
||||
ATTRIBUTE_TBL_WRITE_LOW_BYTE = $66 ; the low byte of the attribute table write address to write to (always #$c0, never read)
|
||||
ATTRIBUTE_TBL_WRITE_HIGH_BYTE = $67 ; the high byte of the attribute table write address to write to
|
||||
FRAME_SCROLL = $68 ; how much to scroll the screen this frame based on player velocity (usually #$00 or #$01), for vertical levels, up to #$04
|
||||
; note that this is not the scroll distance within the screen
|
||||
SUPERTILE_NAMETABLE_OFFSET = $69 ; base nametable offset into memory address into CPU graphics buffer starting at $0600 (LEVEL_SCREEN_SUPERTILES)
|
||||
; always either #$00 (nametable 0) or #$40 (nametable 1), points to area that contains the super-tile indexes for screen
|
||||
SPRITE_LOAD_TYPE = $6a ; which sprites to load #$0 for normal sprites, #$1 for HUD sprites
|
||||
CONT_END_SELECTION = $6b ; #$00 when "CONTINUE" is selected, #$01 when "END" is selected, used only in game over screen (level_routine_06)
|
||||
ALT_GRAPHIC_DATA_LOADING_FLAG = $71 ; #$00 means that the alternate graphics data should not be loaded, #$01 means it should be #$02 means it currently is being loaded
|
||||
LEVEL_PALETTE_CYCLE = $72 ; the current iteration of the palette animation loop #$00 up to entry for level in lvl_palette_animation_count
|
||||
INDOOR_SCROLL = $73 ; scrolling on indoor level changes (#$00 = not scrolling; #$01 = scrolling, #$02 = finished scrolling)
|
||||
BG_PALETTE_ADJ_TIMER = $74 ; timer used for adjusting background palette colors (not sprite palettes). Used for fade-in effect of dragon and boss ufo as well as indoor transitions
|
||||
AUTO_SCROLL_TIMER_00 = $75 ; used when completing scroll to show a boss, e.g. vertical level dragon screen
|
||||
AUTO_SCROLL_TIMER_01 = $76 ; used when completing scroll to show a boss, e.g. alien guardian
|
||||
TANK_AUTO_SCROLL = $77 ; amount to scroll every frame, regardless of AUTO_SCROLL_TIMER_xx, used for snow field tanks (dogras), breaks levels if used on other levels
|
||||
PAUSE_PALETTE_CYCLE = $78 ; #$00 - nametable palettes #$03 and #$04 will cycle through colors like normal. Non-zero values will pause palette color cycling (ice field tank pauses palette cycle)
|
||||
SOLDIER_GENERATION_ROUTINE = $79 ; which routine is currently in use for generating soldiers (index into soldier_generation_ptr_tbl)
|
||||
SOLDIER_GENERATION_TIMER = $7a ; a timer between soldier generation. #$00 means no generation. see level_soldier_generation_timer. When used in a level, every frame decrements by 2 (unless scrolling, then only by 1)
|
||||
SOLDIER_GENERATION_X_POS = $7b ; the initial x position of the generated soldier
|
||||
SOLDIER_GENERATION_Y_POS = $7c ; the initial y position of the generated soldier
|
||||
FALCON_FLASH_TIMER = $7d ; the number of frames to flash the screen for falcon weapon item
|
||||
TANK_ICE_JOINT_SCROLL_FLAG = $7f ; whether or not to have the ice joint enemy move left while player walks right to simulate being on the background
|
||||
ENEMY_LEVEL_ROUTINES = $80 ; two byte address to the correct enemy_routine_level_XX for the current level, used to retrieve enemy routines for the level-specific enemies
|
||||
ENEMY_SCREEN_READ_OFFSET = $82 ; read offset into level_xx_enemy_screen_xx table, which specifies the enemies on each screen of a level
|
||||
ENEMY_CURRENT_SLOT = $83 ; when in use, specifies the current enemy slot that is being executed, used to be able to restore x register after method has used it
|
||||
BOSS_AUTO_SCROLL_COMPLETE = $84 ; set when boss reveal auto-scrolling has completed, see AUTO_SCROLL_TIMER_00 and AUTO_SCROLL_TIMER_01
|
||||
BOSS_SCREEN_ENEMIES_DESTROYED = $85 ; used on level 3 and level 7 boss screens to keep track of how many dragon arm orbs or mortar launchers have been destroyed respectively
|
||||
WALL_CORE_REMAINING = $86 ; remaining wall cores/wall platings to destroy until can advance to next screen. For level 4 boss, used to count remaining boss gemini
|
||||
WALL_PLATING_DESTROYED_COUNT = $87 ; used in indoor/base boss levels to keep track of how many wall platings (ENEMY_TYPE #$0a) have been destroyed
|
||||
INDOOR_ENEMY_ATTACK_COUNT = $88 ; used in indoor/base levels to specify how many 'rounds' of attack have happened per screen, max #$07 before certain enemies no longer generate
|
||||
; indoor soldiers, jumping soldiers, indoor rollers, and wall core check this value
|
||||
INDOOR_RED_SOLDIER_CREATED = $89 ; used in indoor/base levels to indicate if a red jumping soldier has been created, to prevent creation of another
|
||||
GRENADE_LAUNCHER_FLAG = $8a ; used in indoor/base levels to indicate that a grenade launcher enemy (ENEMY_TYPE #$17) is on the screen. Prevents other indoor enemies from being generated
|
||||
ALIEN_FETUS_AIM_TIMER_INDEX = $8b ; used to keep track of the index into alien_fetus_aim_timer_tbl to set the delay between re-aiming towards the player
|
||||
ENEMY_ATTACK_FLAG = $8e ; whether or not enemies will fire at player, also whether or not random enemies are generated, bosses ignore this value
|
||||
PLAYER_STATE = $90 ; #$00 falling into level (only run once to init fall), #$01 normal state, #$02 when dead, #$03 can't move
|
||||
; $91 is for p2, if p2 not playing, set to #$00
|
||||
INDOOR_TRANSITION_X_ACCUM = $92 ; a variable to store INDOOR_TRANSITION_X_FRACT_VEL being added to itself to account for overflow before adding to player x velocity when moving between screens on indoor/base levels
|
||||
; $93 is for p2
|
||||
PLAYER_JUMP_COEFFICIENT = $94 ; related to jump height (used by speed runners to jump higher) (https://www.youtube.com/watch?v=K7MjxHvWof8 and https://www.youtube.com/watch?v=yrnW9yQXa9I)
|
||||
; used to keep track of fractional y velocity on vertical levels for overflowing fractional velocity. It isn't cleared between jumps
|
||||
; also used when walking into screen for indoor screen changes to keep track of overflow of animation y fractional velocity
|
||||
; $95 is for player 2
|
||||
INDOOR_TRANSITION_X_FRACT_VEL = $96 ; indoor animation transition when walking into screen x fractional velocity
|
||||
; $97 is for player 2
|
||||
PLAYER_X_VELOCITY = $98 ; the player's fast x velocity (#$00, #$01, or #$ff)
|
||||
; $99 is for p2
|
||||
INDOOR_TRANSITION_Y_FRACT_VEL = $9a ; indoor animation transition when walking into screen y fractional velocity
|
||||
; $9b is for player 2
|
||||
INDOOR_TRANSITION_Y_FAST_VEL = $9c ; indoor animation transition when walking into screen y fast velocity
|
||||
; $9d is for player 2
|
||||
PLAYER_ANIM_FRAME_TIMER = $9e ; value that is incremented every frame when player is walking, used to wait #$08 frames before incrementing PLAYER_ANIMATION_FRAME_INDEX for animating player walking
|
||||
; $9f is for player 2
|
||||
PLAYER_JUMP_STATUS = $a0 ; the status of the player jump (facing direction); similar to EDGE_FALL_CODE
|
||||
; high nibble is for facing direction
|
||||
; bit 7 - set when jumping left
|
||||
; low nibble is #$01 when jumping, #$00 when not
|
||||
; $a1 is for player 2
|
||||
PLAYER_FRAME_SCROLL = $a2 ; how much player 1 is causing the frame to scroll by, see FRAME_SCROLL
|
||||
; $a3 is for player 2, larger of the 2 is set to FRAME_SCROLL
|
||||
EDGE_FALL_CODE = $a4 ; similar to PLAYER_JUMP_STATUS. Used to initiate gravity pulling player down
|
||||
; if bit 7 set, then falling through platform
|
||||
; if bit 6 is set, then walking left off edge
|
||||
; if bit 5 is set, then walking right off ledge
|
||||
; can change if change direction during fall, bit 0 always set when EDGE_FALL_CODE non-zero
|
||||
; $a5 is for player 2
|
||||
PLAYER_ANIMATION_FRAME_INDEX = $a6 ; which frame of the player animation. Depends on player state. For example, if player is running, this cycles from #$00 to #$05
|
||||
; $a7 is for player 2
|
||||
PLAYER_INDOOR_ANIM_Y = $a8 ; the y position the player was at when they started walking into screen after clearing an indoor level. I believe it's always #$a8 since y pos is hard-coded for indoor levels
|
||||
; $a9 is player 2
|
||||
P1_CURRENT_WEAPON = $aa ; low nibble is what weapon P1 has, high nibble 1 is rapid fire flag, commonly abbreviated MFSL
|
||||
; #$00 - Regular, #$01 - Machine Gun, #$02 - Flame Thrower, #$03 - Spray, #$04 - Laser, bit 4 set for rapid fire
|
||||
P2_CURRENT_WEAPON = $ab ; byte 0 is what weapon P2 has, byte 1 is rapid fire flag
|
||||
PLAYER_M_WEAPON_FIRE_TIME = $ac ; used when holding down the B button with the m weapon. High nibble is number of bullets generated (up to #$06), low nibble is counter before next bullet is generated (up to #$07)
|
||||
; $ad is for player 2
|
||||
NEW_LIFE_INVINCIBILITY_TIMER = $ae ; timer for invincibility after dying
|
||||
; $af is for player 2
|
||||
INVINCIBILITY_TIMER = $b0 ; timer for player invincibility (b (barrier) weapon) (decreases every 8 frames), usually set to #$80 except level 7 when set to #$90
|
||||
; $b1 is for player 2
|
||||
PLAYER_WATER_STATE = $b2 ; bit 1 - horizontal sprite flip flag
|
||||
; bit 2 - set when player in water, or exiting water
|
||||
; bit 3 - player is walking out of water
|
||||
; bit 4 - finished initialization for entering water
|
||||
; bit 7 - player is walking out of water
|
||||
; $b3 is for player 2
|
||||
PLAYER_DEATH_FLAG = $b4 ; bit 0 specifies whether player has died, bit 1 specifies player was facing left when hit, used so player dies lying in appropriate direction
|
||||
; $b5 is for player 2
|
||||
PLAYER_ON_ENEMY = $b6 ; whether or not the player is on top of another enemy (#$14 - mining cart, #$15 - stationary mining cart, #$10 - floating rock platform)
|
||||
; $b7 is for player 2
|
||||
PLAYER_FALL_X_FREEZE = $b8 ; used to prevent changing X velocity shortly after walking off/falling through ledge, set to Y post of ledge + #$14
|
||||
; $b9 is for player 2
|
||||
PLAYER_HIDDEN = $ba ; #$00 player visible, #$01/#$ff player invisible (any non-zero). I believe it is meant to track distance off screen the player is
|
||||
; $bb is for player 2
|
||||
PLAYER_SPRITE_SEQUENCE = $bc ; which animation to show for the player
|
||||
; outdoor - #$00 standing (no animation), #$01 gun pointing up, #$02 crouching, #$03 walking or curled jump animation, #$04 dead animation
|
||||
; indoor - (see indoor_player_sprite_tbl), #$00 standing facing back wall, #$01 electrocuted, #$02 crouching, #$03 walking left/right animation, #$05 walking into screen (advancing), #$06 dead animation
|
||||
; $bd is for player 2
|
||||
PLAYER_INDOOR_ANIM_X = $be ; the x position the player was at when they started walking into screen after clearing an indoor level
|
||||
; $bf is player 2
|
||||
PLAYER_AIM_PREV_FRAME = $c0 ; backup of PLAYER_AIM_DIR
|
||||
; $c1 is for player 2
|
||||
PLAYER_AIM_DIR = $c2 ; which direction the player is aiming [#$00-#$0a] depends on level and jump status (00 up facing right, 1 up-right, 2 right, 3 right-down, 4 crouching facing right, 5 crouching facing left, etc)
|
||||
; there are #$02 up and #$02 down values depending on facing direction
|
||||
; $c3 is for player 2
|
||||
PLAYER_Y_FRACT_VELOCITY = $c4 ; the fractional portion of the player's y velocity
|
||||
; $c5 is for player 2
|
||||
PLAYER_Y_FAST_VELOCITY = $c6 ; the integer portion of the player's y velocity. Positive pulls down, negative pulls up
|
||||
; $c7 is for player 2
|
||||
ELECTROCUTED_TIMER = $c8 ; timer for player being electrocuted, used to freeze player and modify look after touching electricity
|
||||
; $c9 is for player 2
|
||||
INDOOR_PLAYER_JUMP_FLAG = $ca ; used when entering new screen to tell the engine to cause the player to jump
|
||||
; $cb is player 2
|
||||
PLAYER_WATER_TIMER = $cc ; timer used for getting into and out of water
|
||||
; $cd is for player 2
|
||||
PLAYER_RECOIL_TIMER = $ce ; how many frames to be pushed back/down from recoil
|
||||
; $cf is for player 2
|
||||
INDOOR_PLAYER_ADV_FLAG = $d0 ; whether or not the player is walking into screen when advancing between screens on indoor levels, used for animating player
|
||||
; $d1 is for player 2
|
||||
PLAYER_SPECIAL_SPRITE_TIMER = $d2 ; used to track animation for player death animation
|
||||
; outdoor is a timer that increments once player hit, every #$08 frames updates to next animation frame until #$04
|
||||
; also used to track jumping curl animation (loops from #$00-#$04)
|
||||
; $d3 is for player 2
|
||||
PLAYER_FAST_X_VEL_BOOST = $d4 ; the x fast velocity boost from landing on a non-dangerous enemy, e.g. moving cart or floating rock in vertical level
|
||||
; $d5 is for player 2
|
||||
PLAYER_SPRITE_CODE = $d6 ; sprite code of the player
|
||||
; $d7 is for player 2
|
||||
PLAYER_SPRITE_FLIP = $d8 ; stores player sprite horizontal (bit 6) and vertical (bit 7) flip flags before saving into SPRITE_ATTR, other bits are used
|
||||
; bit 3 specifies whether the PLAYER_ANIMATION_FRAME_INDEX is even or odd (see @check_anim_frame_and_collision)
|
||||
; $d9 is for player 2
|
||||
PLAYER_BG_FLAG_EDGE_DETECT = $da ; bit 7 specifies the player's sprite attribute for background priority, allows player to walk behind opaque background (OAM byte 2 bit 5)
|
||||
; 0 (clear) sprite in foreground, 1 (set) sprite is background
|
||||
; bit 0 allows the player to keep walking horizontally off a ledge without falling
|
||||
; $db is for player 2
|
||||
PLAYER_GAME_OVER_BIT_FIELD = $df ; combination of both players game over status
|
||||
; #$00 = p1 not game over, p2 game over (or not playing), #$01 = p1 game over, p2 not game over, #$02 = p1 nor p2 are in game over
|
||||
SOUND_TABLE_PTR = $ec ; low byte of address pointing of index into sound_table_00 offset INIT_SOUND_CODE
|
||||
CONTROLLER_STATE = $f1 ; stores the currently-pressed buttons for player 1
|
||||
; bit 7 - A, bit 6 - B, bit 5 - select, bit 4 - start
|
||||
; bit 3 - up, bit 2 - down, bit 1 - left, bit 0 - right
|
||||
; $f2 stores the currently-pressed buttons for player 2
|
||||
CONTROLLER_STATE_DIFF = $f5 ; stores the difference between the controller input between reads. Useful for events that should only trigger on first button press
|
||||
; $f6 is for player 2
|
||||
CTRL_KNOWN_GOOD = $f9 ; used in input-reading code to know the last known valid read of controller input (similar to CONTROLLER_STATE)
|
||||
; $fa is for player 2
|
||||
VERTICAL_SCROLL = $fc ; the number of pixels to vertically scroll down
|
||||
; (y component of PPUSCROLL) (see level_vert_scroll_and_song for initial values)
|
||||
; horizontal levels are always #$e0 (224 pixels or 28 tiles down), indoor/base are always #$e8 (232 or 29 tiles down)
|
||||
; waterfall level (vertical level) starts at #$00 and decrements as players move up screen (wrapping)
|
||||
HORIZONTAL_SCROLL = $fd ; the horizontal scroll component of the PPUSCROLL, [#$00 - #$ff]
|
||||
PPUMASK_SETTINGS = $fe ; used to store value of PPUMASK before writing to PPU
|
||||
PPUCTRL_SETTINGS = $ff ; used to set PPUCTRL value for next frame
|
||||
|
||||
SOUND_CMD_LENGTH = $0100 ; how many video frames the sound count should last for, i.e. the time to wait before reading next sound command
|
||||
; #$06 bytes, one for each sound slot
|
||||
SOUND_CODE = $0106 ; the sound code for the sound slot, #$06 slots
|
||||
SOUND_PULSE_LENGTH = $010c ; APU_PULSE_LENGTH, #$06 slots
|
||||
SOUND_CMD_LOW_ADDR = $0112 ; low byte of address to current sound command in sound_xx data. #$06 slots, one per sound slot
|
||||
SOUND_CMD_HIGH_ADDR = $0118 ; high byte of address to current sound command in sound_xx data. #$06 slots, one per sound slot
|
||||
SOUND_VOL_ENV = $011e ; either an offset into pulse_volume_ptr_tbl (c.f. LVL_PULSE_VOL_INDEX) which specifies the volume for the frame
|
||||
; or a specific volume to use. When bit 7 is set, then the volume will auto decrescendo
|
||||
SOUND_CURRENT_SLOT = $0120 ; the current sound slot [#$00-#$05]
|
||||
PERCUSSION_INDEX_BACKUP = $0121 ; backup location for percussion_tbl index to restore after call to play_sound
|
||||
INIT_SOUND_CODE = $0122 ; the sound code to load; sound codes greater than #$5a are dmc sounds
|
||||
SOUND_CHNL_REG_OFFSET = $0123 ; sound channel configuration register offset, i.e. #$00 for first pulse channel, #$04 for second, #$08 for triangle, #$0c for noise
|
||||
SOUND_FLAGS = $0124 ; sound channel flags
|
||||
; bit 0 - 0 = sound_xx command byte >= #$30 (read_low_sound_cmd), 1 = sound_xx command byte 0 < #$30 (read_high_sound_cmd)
|
||||
; bit 1 - 1 = DECRESCENDO_END_PAUSE has triggered and decrescendo can resume, 0 = keep volume constant
|
||||
; bit 2 - 0 = use lvl_config_pulse to set volume for frame, 1 = automatic decrescendo logic (handling DECRESCENDO_END_PAUSE)
|
||||
; bit 3 - used in sound_cmd_routine_03, signifies that a shared (child) sound command (sound_xx_part) is executing, specified by #$fd, or #$fe in sound command
|
||||
; used to know, after finishing parsing a sound command, whether or not to done or should return to parent sound command
|
||||
; bit 4 - slightly flatten note (see @flatten_note and @flip_flatten_note_adv)
|
||||
; bit 5 - 1 = PULSE_VOL_DURATION has counted down and decrescendo should be paused until DECRESCENDO_END_PAUSE
|
||||
; set to ignore SOUND_VOL_ENV negative check, i.e. override to decrescendo
|
||||
; bit 6 - mute flag (1 = muted, 0 = not muted)
|
||||
; bit 7 - sweep flag
|
||||
LVL_PULSE_VOL_INDEX = $012a ; index into lvl_x_pulse_volume_xx to read
|
||||
PULSE_VOL_DURATION = $012a ; the number of video frames to decrement the volume for, before stopping decrescendo and keeping final volume
|
||||
PAUSE_STATE_01 = $012f ; whether or not the game is paused, used for sound logic
|
||||
DECRESCENDO_END_PAUSE = $0130 ; number of video frames before end of sound command in which the decrescendo will resume
|
||||
; $0131 is for pulse channel 2
|
||||
SOUND_PITCH_ADJ = $0132 ; the amount added to the sound byte low nibble before loading the correct note_period_tbl values
|
||||
UNKNOWN_SOUND_00 = $0136 ; amount to multiply to SOUND_CMD_LENGTH,x when calculating DECRESCENDO_END_PAUSE,x
|
||||
UNKNOWN_SOUND_01 = $013c ; used to adjust volume amount when setting volume
|
||||
SOUND_CFG_LOW = $0142 ; the value to merge with the high nibble before storing in apu channel config register
|
||||
SOUND_TRIANGLE_CFG = $0144 ; in memory value for APU_TRIANGLE_CONFIG
|
||||
SOUND_REPEAT_COUNT = $0148 ; used for #$fe sound commands to specify how many times to repeat a shared sound part, e.g. .byte $fe, $03, .addr sound_xx_part to loop 3 times. #$06 slots
|
||||
SOUND_CFG_HIGH = $014e ; the value to merge with the volume when saving the pulse config
|
||||
SOUND_LENGTH_MULTIPLIER = $0154 ; value used when determining how many video frames to wait before reading next sound command, #$06 bytes, one for each sound slot
|
||||
; ultimately used when calculating SOUND_CMD_LENGTH, and kept around between sound commands so subsequent notes can be the same length
|
||||
; for low sound codes, SOUND_LENGTH_MULTIPLIER is set to SOUND_CMD_LENGTH directly with no multiplication (see @high_nibble_not_1)
|
||||
SOUND_PERIOD_ROTATE = $015a ; when not #$04, the number of times to shift the high byte of note_period_tbl into the low byte
|
||||
PULSE_VOLUME = $0160 ; low nibble only, stores the volume for the pulse channels
|
||||
NEW_SOUND_CODE_LOW_ADDR = $0166 ; sound command return location low byte once sound command specified in move_sound_code_read_addr executes, e.g. jungle boss siren
|
||||
NEW_SOUND_CODE_HIGH_ADDR = $016c ; sound command return location high byte once sound command specified in move_sound_code_read_addr executes, e.g. jungle boss siren
|
||||
SOUND_PULSE_PERIOD = $0172 ; APU_PULSE_PERIOD
|
||||
VIBRATO_CTRL = $0178 ; vibrato control mode [#$00-#$03], #$80 = no vibrato
|
||||
; even values cause the note to stay the same, odd values cause vibrato #$03 = pitch up, #$01 = pitch down
|
||||
; $0178 is for sound slot #$00 and $0719 is for sound slot #$01
|
||||
SOUND_VOL_TIMER = $017a ; sound command counter; increments up to VIBRATO_DELAY, at which vibrato will be checked
|
||||
; only increments when VIBRATO_CTRL is non-negative, i.e. not #$80
|
||||
PULSE_NOTE = $017c ; the note that is sustained or has the vibrato applied to for pulse channels (in Contra only ever sustained no vibrato)
|
||||
; $017c is for sound slot #$00 and $071d is for sound slot #$01
|
||||
VIBRATO_DELAY = $017e ; used to delay start of vibrato until SOUND_VOL_TIMER has counted up to this value
|
||||
; if a note isn't as long as VIBRATO_DELAY, i.e. SOUND_CMD_LENGTH < VIBRATO_DELAY, then vibrato won't be considered for a note
|
||||
; $017e is for sound slot #$00 and $071f is for sound slot #$01
|
||||
VIBRATO_AMOUNT = $0180 ; the amount of vibrato to apply
|
||||
LEVEL_END_DELAY_TIMER = $0190 ; a delay timer before beginning level end animation sequence
|
||||
LEVEL_END_SQ_1_TIMER = $0191 ; a delay timer specifying the duration of end_level_sequence_01, decremented every other frame
|
||||
LEVEL_END_LVL_ROUTINE_STATE = $0192 ; used by level end routines (end_of_lvl_routine_...) for managing animation state.
|
||||
; for example, indoor level end animations have 4 states: walk to elevator, initialize elevator sprite, ride elevator
|
||||
; $0193 is for player 2
|
||||
LEVEL_END_PLAYERS_ALIVE = $0194 ; the number of players alive at the end of the level, used to know if should play level end music
|
||||
SOLDIER_GEN_SCREEN = $0195 ; the current screen that soldiers are being generated for
|
||||
SCREEN_GEN_SOLDIERS = $0196 ; the total number of soldiers that have been generated for the current screen (exe_soldier_generation)
|
||||
OAMDMA_CPU_BUFFER = $0200 ; $0200-$02ff OAMDMA (sprite) read data, read once per frame, populated by load_sprite_to_CPU_mem, draw_hud_sprites, or draw_player_hud_sprites
|
||||
|
||||
CPU_SPRITE_BUFFER = $0300 ; sprites on screen, each byte is an entry into sprite_ptr_tbl [$0300-$0387], memory is segmented as defined below
|
||||
PLAYER_SPRITES = $0300 ; player sprites, p1 and p2 sprite, then player bullets, each byte is an entry into sprite_ptr_tbl (#$0a bytes)
|
||||
ENEMY_SPRITES = $030a ; enemy sprites to load on screen, each byte is an entry into sprite_ptr_tbl (#$0f bytes)
|
||||
SPRITE_Y_POS = $031a ; y position on screen of each player sprite. First 2 bytes are for player sprites. Starts at #$00 for top increases downward (#$0a bytes)
|
||||
ENEMY_Y_POS = $0324 ; y position on screen of each enemy sprite. Starts at #$00 for top increases downward (#$0f bytes)
|
||||
SPRITE_X_POS = $0334 ; x position of screen of each player sprite. First 2 bytes are for player sprites (#$0a bytes)
|
||||
ENEMY_X_POS = $033e ; x position on screen of each enemy sprite (#$0f bytes)
|
||||
SPRITE_ATTR = $034e ; sprite attribute, specifies palette, vertical flip, horizontal flip (#$0a bytes)
|
||||
; and whether to adjust y position
|
||||
; bit 0 and 1 - sprite palette
|
||||
; bit 2 - 0 to use default palette as specified in sprite code
|
||||
; - 1 to use palette specified in bits 0 and 1
|
||||
; bit 3 - whether to add #$01 to sprite y position, used for recoil effect firing weapon
|
||||
; bit 5 - bg priority
|
||||
; bit 6 - whether to flip the sprite horizontally
|
||||
; bit 7 - whether to flip the sprite vertically
|
||||
; bytes 0 and 1 are p1 and p2 sprite attributes, then each byte is the player bullet sprite attributes
|
||||
; examples: player being electrocuted or invincible (flashes various colors)
|
||||
ENEMY_SPRITE_ATTR = $0358 ; enemy sprite attribute. See specification above (#$0f bytes)
|
||||
|
||||
PLAYER_BULLET_SPRITE_CODE = $0368 ; The sprite codes to load for the bullet, eventually copied into CPU_SPRITE_BUFFER starting at offset 2
|
||||
PLAYER_BULLET_SPRITE_ATTR = $0378 ; The sprite attributes for the bullet (see SPRITE_ATTR for specification)
|
||||
; used for L bullets for flipping the angled sprites depending on direction
|
||||
PLAYER_BULLET_SLOT = $0388 ; #$00 when no bullet, otherwise stores bullet type + 1, i.e. #$01 basic, #$02 M, #$03 F bullet, #$04 S, #$05 L, can be negative sometimes
|
||||
PLAYER_BULLET_VEL_Y_ACCUM = $0398 ; an accumulator to keep track of PLAYER_BULLET_Y_VEL_FRACT being added to itself have elapsed before adding 1 to PLAYER_BULLET_Y_POS
|
||||
PLAYER_BULLET_VEL_X_ACCUM = $03a8 ; an accumulator to keep track of PLAYER_BULLET_X_VEL_FRACT being added to itself have elapsed before adding 1 to PLAYER_BULLET_X_POS
|
||||
PLAYER_BULLET_Y_POS = $03b8 ; the bullet's sprite y position
|
||||
PLAYER_BULLET_X_POS = $03c8 ; the bullet's sprite x position
|
||||
; for F bullets, PLAYER_BULLET_FS_X and PLAYER_BULLET_X_POS together determine x position
|
||||
PLAYER_BULLET_Y_VEL_FRACT = $03d8 ; percentage out of 0-255 set number of frames until Y position is incremented by an additional 1 unit
|
||||
PLAYER_BULLET_X_VEL_FRACT = $03e8 ; percentage out of 0-255 set number of frames until X position is incremented by an additional 1 unit
|
||||
PLAYER_BULLET_Y_VEL_FAST = $03f8 ; player bullet velocity y integer portion
|
||||
PLAYER_BULLET_VEL_X_FAST = $0408 ; player bullet velocity x integer portion
|
||||
PLAYER_BULLET_TIMER = $0418 ; 'timer' starts at #$00. Used by F, S (indoor only) and L
|
||||
; for indoor S, used to specify size of bullet
|
||||
; For F, used to set x and y pos when traveling to create swirl (see f_bullet_outdoor_x_swirl_amt_tbl, and f_bullet_outdoor_y_swirl_amt_tbl)
|
||||
; increments or decrements every frame depending on firing direction (left decrement, right increment)
|
||||
; For L used to spread out 4 lasers for one shot
|
||||
PLAYER_BULLET_AIM_DIR = $0428 ; the direction of the bullet #$00 for up facing right, incrementing clockwise up to #09 for up facing left
|
||||
PLAYER_BULLET_ROUTINE = $0438 ; #$00, #$01, or #$03, offset into player_bullet_routine_XX_(indoor_)ptr_tbl
|
||||
PLAYER_BULLET_OWNER = $0448 ; #$00 player 1 bullet, #$01 player 2 bullet, each byte is for a bullet
|
||||
PLAYER_BULLET_F_RAPID = $0458 ; #$01 for player indoor bullets for F weapon when rapid fire is enabled
|
||||
PLAYER_BULLET_S_INDOOR_ADJ = $0458 ; (same address as previous) for indoor S bullets, specifies whether to adjust PLAYER_BULLET_X_POS by an additional -1 (#$ff) every frame (see s_bullet_pos_mod_tbl)
|
||||
PLAYER_BULLET_DIST = $0468 ; represents how far a bullet has traveled
|
||||
; For S outdoor bullets, used to determine the size (scale) of the bullet
|
||||
; For F on indoor levels, used to determine spiraling position based on distance from player
|
||||
PLAYER_BULLET_S_ADJ_ACCUM = $0468 ; (same address as previous) for indoor S weapons, stores accumulated fractional velocity where overflow affects PLAYER_BULLET_S_INDOOR_ADJ (see update_s_bullet_indoor_pos)
|
||||
PLAYER_BULLET_FS_X = $0478 ; Used to offset from general x direction of bullet for swirl effect in F bullet and spread effect in S bullet (indoor)
|
||||
; Specifies center x position on screen f bullet swirls around. Used when firing f bullet either left, right, or at an angle
|
||||
PLAYER_BULLET_F_Y = $0488 ; Specifies center y position on screen f bullet swirls around. Used when firing f bullet either up, down, or at an angle.
|
||||
PLAYER_BULLET_S_RAPID = $0488 ; (same address as previous) for S weapon in indoor levels, specifies whether weapon is rapid fire or not, not sure why $09 wasn't used like other bullet routines
|
||||
PLAYER_BULLET_VEL_FS_X_ACCUM = $0498 ; (for F weapon only) an accumulator to keep track of PLAYER_BULLET_X_VEL_FRACT being added to itself have elapsed before adding 1 to PLAYER_BULLET_X_POS
|
||||
PLAYER_BULLET_VEL_F_Y_ACCUM = $04a8 ; (for F weapon only) an accumulator to keep track of PLAYER_BULLET_Y_VEL_FRACT being added to itself have elapsed before adding 1 to PLAYER_BULLET_Y_POS
|
||||
PLAYER_BULLET_S_BULLET_NUM = $04a8 ; (same address as previous) for S weapon only, specifies the number the bullet in the current 'spray' for the shot
|
||||
; per shot of S weapon, #$05 bullets are generated. If no other bullets exist then
|
||||
; $04a8 would have #$00, $04a9 would have #$01, $04a9 would have #$02, etc.
|
||||
|
||||
; each enemy property is #$10 bytes, one byte per enemy
|
||||
ENEMY_ROUTINE = $04b8 ; enemy routine indexes starting at offset #$f ($04c7) going to #$0 ($04b8)
|
||||
; subtract 1 to get real routine, since all offsets are off by 1 (...routine_ptr_tbl -2)
|
||||
; ex: for exploding bridge, setting ENEMY_ROUTINE to #$02 causes exploding_bridge_routine_01 to run the next frame
|
||||
|
||||
; the following 6 address ranges control the change in position of the enemy
|
||||
; every frame the position is moved by VELOCITY_FAST units
|
||||
; VELOCITY_FRACT can enable only moving by 1 unit every n frames
|
||||
; for example, if ENEMY_Y_VELOCITY_FAST is #$00 and ENEMY_Y_VELOCITY_FRACT is #$c0, (#$c0/#$ff = 75%),
|
||||
; then the enemy will move one position to the right 3 out of every 4 frames
|
||||
ENEMY_Y_VEL_ACCUM = $04c8 ; an accumulator to keep track of ENEMY_Y_VELOCITY_FRACT being added to itself have elapsed before adding 1 to ENEMY_Y_POS
|
||||
ENEMY_X_VEL_ACCUM = $04d8 ; an accumulator to keep track of ENEMY_X_VELOCITY_FRACT being added to itself have elapsed before adding 1 to ENEMY_X_POS
|
||||
ENEMY_Y_VELOCITY_FAST = $04e8 ; the number of units to add to ENEMY_Y_POS every frame
|
||||
ENEMY_Y_VELOCITY_FRACT = $04f8 ; percentage out of 0-255 of a unit to add, e.g. if #$80 (#$80/#$ff = 50%), then every other frame will cause Y pos to increment by 1
|
||||
ENEMY_X_VELOCITY_FAST = $0508 ; the number of units to add to ENEMY_X_POS every frame
|
||||
ENEMY_X_VELOCITY_FRACT = $0518 ; percentage out of 0-255 of a unit to add, e.g. if #$80 (#$80/#$ff = 50%), then every other frame will cause X pos to increment by 1
|
||||
|
||||
ENEMY_TYPE = $0528 ; enemy type, e.g. #$03 = flying capsule
|
||||
ENEMY_ANIMATION_DELAY = $0538 ; used for various delays by enemy logic
|
||||
ENEMY_VAR_A = $0548 ; the sound code to play when enemy hit by player bullet, also used for other logic
|
||||
; dragon arm orb uses it for adjusting enemy position, fire beam uses it for animation delay
|
||||
ENEMY_ATTACK_DELAY = $0558 ; the delay before an enemy attacks, for weapon items and grenades this is used for helping calculate falling arc trajectory instead of enemy delay
|
||||
ENEMY_VAR_B = $0558 ; for weapon items and grenades this is used for helping calculate falling arc trajectory
|
||||
ENEMY_FRAME = $0568 ; animation frame the enemy is in, typically indexes into an enemy type-specific table of sprite codes
|
||||
ENEMY_SCORE_COLLISION = $0588 ; represents 3 things for an enemy
|
||||
; SSSS CCCC - score code (see `score_codes_tbl`), and collision type (entry in collision_box_codes_XX)
|
||||
; also explosion type
|
||||
ENEMY_HP = $0578 ; the HP of the enemy
|
||||
ENEMY_STATE_WIDTH = $0598 ; loaded from enemy_prop_ptr_tbl
|
||||
; bit 7 set to allow bullets to travel through enemy, e.g. weapon item
|
||||
; bit 6 specifies whether player can land on enemy (floating rock and moving cart), bit 4 also has to be 0 (see `beq @land_on_enemy`)
|
||||
; bit 4 and 5 specify the collision box type (see collision_box_codes_tbl)
|
||||
; bit 3 determines the explosion type (explosion_type_ptr_tbl), either explosion_type_00 or explosion_type_01
|
||||
; bit 2 for bullets specifies whether to play sound on collision
|
||||
; bit 1 specifies whether to play explosion noise; also specifies width of enemy
|
||||
; bit 0 - #$00 test player-enemy collision, #$01 means to skip player-enemy collision test
|
||||
ENEMY_ATTRIBUTES = $05a8 ; enemy type-specific attributes that define how an enemy behaves and/or looks
|
||||
ENEMY_VAR_1 = $05b8 ; a byte available to each enemy for whatever they want to use it for (#$f bytes, 1 per enemy)
|
||||
ENEMY_VAR_2 = $05c8 ; a byte available to each enemy for whatever they want to use it for (#$f bytes, 1 per enemy)
|
||||
ENEMY_VAR_3 = $05d8 ; a byte available to each enemy for whatever they want to use it for (#$f bytes, 1 per enemy)
|
||||
ENEMY_VAR_4 = $05e8 ; a byte available to each enemy for whatever they want to use it for (#$f bytes, 1 per enemy)
|
||||
LEVEL_SCREEN_SUPERTILES = $0600 ; CPU memory address where super tiles indexes for the screens of the level are loaded (level_X_supertiles_screen_XX data)
|
||||
; 2 screens are stored in the CPU buffer. The second screen loaded at $0640. Indexes are into level_x_supertile_data
|
||||
; This data specifies the super-tiles (indexes) to load for the screens
|
||||
BG_COLLISION_DATA = $0680 ; map of collision types for each of the super-tiles for both nametables, each 2 bits encode 1/4 of a super-tile's collision information
|
||||
; first 8 nibbles are a row of the top of super-tile, the next 8 are the middle middle. Not used on base (indoor) levels
|
||||
CPU_GRAPHICS_BUFFER = $0700 ; used to store data that will be then moved to the PPU later on. $700 to $750, repeating structure
|
||||
; * byte $700 is multifaceted
|
||||
; * if $700 is #$0, then done writing graphics buffer to PPU
|
||||
; * if $700 is greater than #$0, then there is data to write, this byte is the offset into vram_address_increment
|
||||
; * both #$01, and #$03 signify VRAM address increment to 0, meaning to add #$1 every write to PPU (write across)
|
||||
; * #$02 signifies VRAM address increment is 1, meaning add #$20 (32 in decimal) every write to PPU (write down)
|
||||
; if GRAPHICS_BUFFER_MODE is #$ff
|
||||
; * byte $701 is length of the tiles being written per group
|
||||
; * byte $702 is the number of $701-sized blocks to write to the PPU
|
||||
; * for each block, the block prefixed with 2 bytes specifying PPU address (high byte, then low byte)
|
||||
; if GRAPHICS_BUFFER_MODE is #$00
|
||||
; * if byte #$00 is #$00, then no drawing takes place for frame
|
||||
; * blocks of text/palette data prefixed with 2 bytes specifying PPU address (high byte, then low byte)
|
||||
; the block of text is ended with a #$ff, if the byte after #$ff is the vram_address_increment offset
|
||||
; then the the process continues, i.e. read #$02 PPU address bytes, read next text
|
||||
|
||||
PALETTE_CPU_BUFFER = $07c0 ; [$07c0-$07df] the CPU memory address of the palettes eventually loaded into the PPU $3f00 to $3f1f
|
||||
|
||||
HIGH_SCORE_LOW = $07e0 ; the low byte of the high score score
|
||||
HIGH_SCORE_HIGH = $07e1 ; the high byte of the high score score
|
||||
PLAYER_1_SCORE_LOW = $07e2 ; the low byte of player 1 high score
|
||||
PLAYER_1_SCORE_HIGH = $07e3 ; the high byte of player 1 high score
|
||||
PLAYER_2_SCORE_LOW = $07e4 ; the low byte of player 1 high score
|
||||
PLAYER_2_SCORE_HIGH = $07e5 ; the high byte of player 1 high score
|
||||
PREVIOUS_ROM_BANK = $07ec ; the previously-loaded PRG BANK ($8000-$bfff)
|
||||
PREVIOUS_ROM_BANK_1 = $07ed ; the previously-loaded PRG BANK, but used only for load_bank_1 (from play_sound)
|
||||
|
||||
; PPU (picture processing unit)
|
||||
PPUCTRL = $2000
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
; Contra US Disassembly - v1.2
|
||||
; Contra US Disassembly - v1.3
|
||||
; https://github.com/vermiceli/nes-contra-us
|
||||
|
||||
.segment "HEADER"
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue