diff --git a/TODO.txt b/TODO.txt deleted file mode 100644 index 6b1b11a3..00000000 --- a/TODO.txt +++ /dev/null @@ -1,85 +0,0 @@ - -================================================================ -Porting features from IFB CustomROMBase branch -For other TODO items, recommend using the github issue system -================================================================ - -================================================================ -Features that are being ported now -================================================================ - -- Capture Cropping - -- Count Boss Damage - -- Demo Timer - -- Factory Reset option - -- Force Stand shortcut - -- Infinite Ammo - -- No Steam Collision option - -- Phantoon always visible - -- Random bubble SFX - -- Randomize on load - -- Randomize RNG shortcut - -- Reveal Boss Damage shortcut - -================================================================ -Features intentionally not ported -This isn't a forever list, nor is it an indictment -Most of these items are simply differences where both work -and there isn't much benefit in porting or backporting them -================================================================ - -- Resources folder structure and unusued resources - -- Order of included sources and bank freespace locations - -- Structure of defines.asm and main.asm (and separating printdebug.asm from main.asm) - -- The SM Practice Hack title screen (the difference helps identify which practice hack is being used) - -- Various sound effect macros - -- Walk Through Walls option and unfinished dboost infohud mode - -- Detect emulator inaccuracy developer option - -- The taller menu (this is available as a build option) - -- Leading > or arrow on menu items, or menuing layout and text differences in general - -- Differences in how menu options can be scrolled through - -- AREA_ID stored in custom presets - -- Additional custom flags in the preset data - -- Differences in room names - -- Differences in preset file names or organization - -- The separate ih_update_timers routine (too much duplication with ih_update_hud_code) - -- Tiny states fast flag (that was removed from main branch) - -- Differences in how gamemode is implemented - -- Differences in magic/space/loud pants implementation - -- Differences in how scroll offsets are fixed - -- Differences in how WRAM and SRAM are initialized - -- Differences in PAL debug movement implementation - -- Replacing TDC with LDA #$0000 - diff --git a/resources/cm_gfx.bin b/resources/cm_gfx.bin index d6423cd5..98f06777 100644 Binary files a/resources/cm_gfx.bin and b/resources/cm_gfx.bin differ diff --git a/resources/cm_gfx2.bin b/resources/cm_gfx2.bin index 5f67c83f..7091b64f 100644 Binary files a/resources/cm_gfx2.bin and b/resources/cm_gfx2.bin differ diff --git a/src/BRBmenu.asm b/src/BRBmenu.asm index 29ed21c2..8ebb37be 100644 --- a/src/BRBmenu.asm +++ b/src/BRBmenu.asm @@ -10,6 +10,10 @@ cm_brb_table: ; 1000h bytes transferred incbin ../resources/cm_brb_gfx.bin +%endfree(8E) + + +%startfree(A1) ; -------- ; BRB Menu @@ -51,10 +55,10 @@ brb_menu_timer_mode: db #$FF brb_menu_timer_min: - %cm_numfield("Minutes on Timer", !ram_cm_brb_mins, 0, 99, 1, 5, #0) + %cm_numfield("Minutes on Timer", !ram_cm_brb_mins, 0, 99, 1, 2, #0) brb_menu_timer_sec: - %cm_numfield("Seconds on Timer", !ram_cm_brb_secs, 0, 59, 1, 5, #0) + %cm_numfield("Seconds on Timer", !ram_cm_brb_secs, 0, 59, 1, 2, #0) brb_menu_timer_clear: %cm_jsl("Clear Timer", .routine, #0) @@ -182,9 +186,15 @@ cm_brb_loop: cm_draw_brb: { JSL cm_tilemap_bg_interior_long + LDA !ram_sram_detection : BNE .splash_screen JSR cm_tilemap_brb JSL cm_tilemap_transfer_long JMP cm_brb_scroll_BG3 + + .splash_screen + JSR cm_tilemap_splash_screen + JSL cm_tilemap_transfer_long + RTS } cm_tilemap_brb: @@ -230,11 +240,11 @@ cm_tilemap_brb: ; Same bank for all of the BRB text PHK : PHK : PLA : STA !DP_CurrentMenu+2 - LDA.w #BRB_common_1 : STA !DP_CurrentMenu + LDA.w #BRB_common_line1 : STA !DP_CurrentMenu LDX #$01C6 JSR cm_draw_brb_text - LDA.w #BRB_common_2 : STA !DP_CurrentMenu + LDA.w #BRB_common_line2 : STA !DP_CurrentMenu LDX #$0286 JSR cm_draw_brb_text @@ -274,19 +284,71 @@ cm_tilemap_brb: ; Draw cycling text ; first cycled line LDA !ram_cm_brb_screen : ASL : TAX - LDA.l BRBTilemapAddress,X : STA !DP_CurrentMenu + LDA.l BRBTilemapTableLine1,X : STA !DP_CurrentMenu LDX #$04C6 JSR cm_draw_brb_text ; second cycled line LDA !ram_cm_brb_screen : ASL : TAX - LDA.l BRBTilemapAddress2,X : STA !DP_CurrentMenu + LDA.l BRBTilemapTableLine2,X : STA !DP_CurrentMenu LDX #$0586 JSR cm_draw_brb_text RTS } +cm_tilemap_splash_screen: +{ + ; Same bank for all of the BRB text + PHK : PHK : PLA : STA !DP_CurrentMenu+2 + + LDA !ram_sram_detection + CMP !SRAM_DETECTION_32KB : BEQ .legacy + CMP !SRAM_DETECTION_128KB : BEQ .tinystates + CMP !SRAM_DETECTION_ZSNES : BEQ .zsnes + BRK + + .legacy + LDA.w #BRB_legacy_line2 : STA !DP_CurrentMenu + LDX #$0406 + JSR cm_draw_brb_text + LDA.w #BRB_legacy_line3 : STA !DP_CurrentMenu + LDX #$04C6 + JSR cm_draw_brb_text + BRA .splashLine4 + + .tinystates + LDA.w #BRB_tinystates_line2 : STA !DP_CurrentMenu + LDX #$0406 + JSR cm_draw_brb_text + LDA.w #BRB_tinystates_line3 : STA !DP_CurrentMenu + LDX #$04C6 + JSR cm_draw_brb_text + BRA .splashLine4 + + .zsnes + LDA.w #BRB_zsnes_line2 : STA !DP_CurrentMenu + LDX #$0406 + JSR cm_draw_brb_text + LDA.w #BRB_zsnes_line4 : STA !DP_CurrentMenu + LDX #$0586 + JSR cm_draw_brb_text + BRA .splashLine1 + + .splashLine4 + LDA.w #BRB_splash_line4 : STA !DP_CurrentMenu + LDX #$0586 + JSR cm_draw_brb_text + + .splashLine1 + LDA.w #BRB_splash_line1 : STA !DP_CurrentMenu + LDX #$0346 + JSR cm_draw_brb_text + LDA.w #BRB_splash_title : STA !DP_CurrentMenu + LDX #$01C6 + JMP cm_draw_brb_text +} + brb_handle_countup_timer: { LDA !ram_cm_brb_frames : INC : STA !ram_cm_brb_frames @@ -464,74 +526,104 @@ cm_brb_scroll_BG3: ; BRB Text Data ; ------------- -BRB_common_1: table ../resources/header.tbl +BRB_common_line1: db #$28, " The Streamer", #$FF - -BRB_common_2: +BRB_common_line2: db #$28, " Will Be Right Back", #$FF + + +BRB_splash_title: + db #$28, " Wrong Platform Selected", #$FF + + +BRB_zsnes_line4: + db #$28, " DO NOT USE ZSNES", #$FF table ../resources/normal.tbl -BRBTilemapAddress: - dw #BRB_screen_01 - dw #BRB_screen_02 - dw #BRB_screen_03 - dw #BRB_screen_04 - dw #BRB_screen_05 - dw #BRB_screen_06 - dw #BRB_screen_07 -BRB_screen_01: - db #$28, " SM Speedrunning Wiki", #$FF +BRB_splash_line1: + db #$28, " You need to select", #$FF +BRB_splash_line4: + db #$28, " at smpractice.speedga.me", #$FF -BRB_screen_02: - db #$28, " SM Speedrunning Discord", #$FF -BRB_screen_03: - db #$28, "Find the practice hack at", #$FF +BRB_legacy_line2: + db #$28, " SNES Classic or", #$FF +BRB_legacy_line3: + db #$28, " Virtual Console", #$FF -BRB_screen_04: - db #$28, " Control Schemes for SM", #$FF -BRB_screen_05: - db #$28, "Support FUNtoon on Patreon", #$FF +BRB_tinystates_line2: + db #$28, " Everdrive or", #$FF +BRB_tinystates_line3: + db #$28, " Snes9x 1.60 or older", #$FF + + +BRB_zsnes_line2: + db #$28, " another emulator", #$FF -BRB_screen_06: - db #$28, " Crazy chain damage clips", #$FF -BRB_screen_07: - db #$28, " Customized practice hacks", #$FF +BRBTilemapTableLine1: + dw #BRB_screen1_line1 + dw #BRB_screen2_line1 + dw #BRB_screen3_line1 + dw #BRB_screen4_line1 + dw #BRB_screen5_line1 + dw #BRB_screen6_line1 + dw #BRB_screen7_line1 -BRBTilemapAddress2: - dw #BRB_screen2_01 - dw #BRB_screen2_02 - dw #BRB_screen2_03 - dw #BRB_screen2_04 - dw #BRB_screen2_05 - dw #BRB_screen2_06 - dw #BRB_screen2_07 +BRBTilemapTableLine2: + dw #BRB_screen1_line2 + dw #BRB_screen2_line2 + dw #BRB_screen3_line2 + dw #BRB_screen4_line2 + dw #BRB_screen5_line2 + dw #BRB_screen6_line2 + dw #BRB_screen7_line2 -BRB_screen2_01: + +BRB_screen1_line1: + db #$28, " SM Speedrunning Wiki", #$FF +BRB_screen1_line2: db #$28, " wiki.supermetroid.run", #$FF -BRB_screen2_02: + +BRB_screen2_line1: + db #$28, " SM Speedrunning Discord", #$FF +BRB_screen2_line2: db #$28, " SMDiscord.spazer.link", #$FF -BRB_screen2_03: + +BRB_screen3_line1: + db #$28, "Find the practice hack at", #$FF +BRB_screen3_line2: db #$28, " smpractice.speedga.me", #$FF -BRB_screen2_04: + +BRB_screen4_line1: + db #$28, " Control Schemes for SM", #$FF +BRB_screen4_line2: db #$28, " controls.spazer.link", #$FF -BRB_screen2_05: + +BRB_screen5_line1: + db #$28, "Support FUNtoon on Patreon", #$FF +BRB_screen5_line2: ; !funtoonpatreon db #$28, " ", #$1A, "funtoonpatreon", #$FF -BRB_screen2_06: + +BRB_screen6_line1: + db #$28, " Crazy chain damage clips", #$FF +BRB_screen6_line2: db #$28, " chain.spazer.link", #$FF -BRB_screen2_07: - db #$28, " by InsaneFirebat", #$FF -%endfree(8E) +BRB_screen7_line1: + db #$28, " Learn new SM strats at", #$FF +BRB_screen7_line2: + db #$28, " crocomi.re", #$FF + +%endfree(A1) diff --git a/src/crash.asm b/src/crash.asm index 6ecbd2d1..6d079096 100644 --- a/src/crash.asm +++ b/src/crash.asm @@ -212,8 +212,8 @@ CrashViewer: STA !ram_crash_input : STA !ram_crash_input_new LDA #$0001 : STA !ram_crash_bg LDA !IH_CONTROLLER_PRI_NEW : STA !ram_crash_input_prev - LDA #$0A44 : STA !ram_crash_mem_viewer - LDA #$007E : STA !ram_crash_mem_viewer_bank + LDA.w !CRASH_INITIAL_ADDRESS : STA !ram_crash_mem_viewer + LDA.w !CRASH_INITIAL_ADDRESS>>16 : STA !ram_crash_mem_viewer_bank ; fall through to CrashLoop } @@ -247,16 +247,10 @@ CrashLoop: .skipSoftReset if !FEATURE_SD2SNES - ; check for load state shortcut - LDA !ram_crash_input : CMP !sram_ctrl_load_state : BNE .skipLoadState + ; check for load state shortcut (Select+Y+L) + LDA !ram_crash_input : CMP #$6020 : BNE .skipLoadState AND !ram_crash_input_new : BEQ .skipLoadState - LDA !SRAM_SAVED_STATE : CMP !SAFEWORD : BNE .skipLoadState - ; prepare to jump to load_state - %a8() - LDA.b #gamemode_start>>16 : PHA : PLB - %a16() - PEA.w gamemode_start_return-1 - JML gamemode_shortcuts_load_state + JSL gamemode_load_state .skipLoadState endif diff --git a/src/custompresets.asm b/src/custompresets.asm index 2d8e4a4a..e68efd08 100644 --- a/src/custompresets.asm +++ b/src/custompresets.asm @@ -622,8 +622,8 @@ preset_scroll_fixes: CPX.w #ROOM_AlphaPowerBombRoom : BEQ .alpha_pbs CPX.w #ROOM_BelowSpazer : BEQ .below_spazer CPX.w #ROOM_WarehouseEntrance : BEQ .warehouse_entrance - CPX.w #ROOM_CaterpillarRoom : BEQ .caterpillar - BRA .topdone + CPX.w #ROOM_CaterpillarRoom : BNE .topdone + BRA .caterpillar .gauntlet_etank LDY !SAMUS_X : CPY #$0510 ; no fix if Xpos >= 1296 @@ -634,6 +634,8 @@ preset_scroll_fixes: .green_brin_main_shaft LDY !SAMUS_Y : CPY #$0700 ; no fix if Ypos < 1792 BMI .topdone + LDY !SAMUS_X : CPY #$0100 ; no fix if Xpos >= 256 + BPL .topdone INC : STA $CD3C BRA .topdone @@ -645,9 +647,10 @@ preset_scroll_fixes: .big_pink_pbs LDY !SAMUS_Y : CPY #$0136 ; no fix if Ypos >= 310 - BMI .topdone + BMI .big_pink_pbs_done STZ $CD21 STA $CD22 : STA $CD23 + .big_pink_pbs_done JMP .topdone .taco_tank_room diff --git a/src/cutscenes.asm b/src/cutscenes.asm index 41322eaf..b464e631 100644 --- a/src/cutscenes.asm +++ b/src/cutscenes.asm @@ -247,14 +247,13 @@ cutscenes_game_over: ; check for cutscene flag or whatever LDA !sram_cutscenes : BIT !CUTSCENE_SKIP_GAMEOVER : BEQ .game_over if !FEATURE_SD2SNES - ; check if valid savestate - LDA !SRAM_SAVED_STATE : CMP !SAFEWORD : BNE .no_savestate - JML gamemode_shortcuts_load_state + JSL gamemode_load_state endif .no_savestate ; reload last preset if it exists LDA !sram_last_preset : BEQ .save_file : STA !ram_load_preset + JSL preset_load BRA .skip_gameplay .save_file @@ -1732,6 +1731,83 @@ org $A9B5E1 endif JSL cutscenes_mb_custom_damage +if !FEATURE_PAL +org $A9B672 +else +org $A9B625 +endif + CMP !eram_mb_normal_walking_rng + +if !FEATURE_PAL +org $A9B684 +else +org $A9B637 +endif + CMP !eram_mb_ketchup_walking_rng + +if !FEATURE_PAL +org $A9B68C +else +org $A9B63F +endif + CMP !eram_mb_ketchup_rng + +if !FEATURE_PAL +org $A9B6B9 +else +org $A9B66C +endif + LDX !eram_mb_ground_attack_rng_table + +if !FEATURE_PAL +org $A9B6D2 +else +org $A9B685 +endif + LDX !eram_mb_close_attack_rng_table + +if !FEATURE_PAL +org $A9B742 +else +org $A9B6F5 +endif + CMP !eram_mb_air_rings_rng + +if !FEATURE_PAL +org $A9B75F +else +org $A9B712 +endif + CMP !eram_mb_ground_bomb_rng + +if !FEATURE_PAL +org $A9B7D1 +else +org $A9B784 +endif + CMP !eram_mb_try_bomb_crouch + +if !FEATURE_PAL +org $A9B808 +else +org $A9B7BB +endif + CMP !eram_mb_bomb_crouch + +if !FEATURE_PAL +org $A9BDC7 +else +org $A9BD7A +endif + CMP !eram_mb_damage_down_rng + +if !FEATURE_PAL +org $A9C282 +else +org $A9C235 +endif + CMP !eram_mb_phase3_attack_rng + %startfree(A9) @@ -1741,7 +1817,7 @@ cutscenes_mb_fast_init: ; If loading a preset, certain flags may already be set ; which allow MB to take damage, so setting value high, ; but also set below 18000 to avoid confusion with vanilla logic - LDA #$464F : STA !ENEMY_HP+$40 + LDA #$464F : STA !ENEMY_HP+!ENEMY_1_OFFSET ; If MB already defeated, reset health to full to simulate baby metroid refill LDA $7ED82D : BIT #$0002 : BEQ .end_refill @@ -1775,7 +1851,7 @@ endif cutscenes_mb_fake_death_pause: { - LDA !ENEMY_HP+$40 : BEQ .continue + LDA !ENEMY_HP+!ENEMY_1_OFFSET : BEQ .continue LDA #$0001 : STA !ENEMY_VAR_5 .continue @@ -1790,7 +1866,7 @@ endif cutscenes_mb_fake_death_lock: { - LDA !ENEMY_HP+$40 : BEQ .continue + LDA !ENEMY_HP+!ENEMY_1_OFFSET : BEQ .continue LDA #$0001 : STA !ENEMY_VAR_5 .continue @@ -1827,7 +1903,7 @@ endif STA !ENEMY_FUNCTION_POINTER LDA #$000C : STA !ENEMY_VAR_5 - LDA !ENEMY_HP+$40 : BEQ .continue + LDA !ENEMY_HP+!ENEMY_1_OFFSET : BEQ .continue LDA #$0002 : STA !ENEMY_VAR_5 .continue @@ -1839,7 +1915,7 @@ endif cutscenes_mb_fake_death_unlock: { - LDA !ENEMY_HP+$40 : BEQ .continue + LDA !ENEMY_HP+!ENEMY_1_OFFSET : BEQ .continue LDA #$0001 : STA !ENEMY_VAR_5 .continue @@ -1871,8 +1947,8 @@ endif cutscenes_mb_bottom_left_tube: { - LDA !ENEMY_HP+$40 : BEQ .continue - LDA #$0010 : STA !ENEMY_VAR_5+$40 + LDA !ENEMY_HP+!ENEMY_1_OFFSET : BEQ .continue + LDA #$0010 : STA !ENEMY_VAR_5+!ENEMY_1_OFFSET .continue if !FEATURE_PAL @@ -1880,14 +1956,14 @@ if !FEATURE_PAL else LDA #$8983 endif - STA !ENEMY_VAR_4+$40 - JMP (!ENEMY_VAR_4+$40) + STA !ENEMY_VAR_4+!ENEMY_1_OFFSET + JMP (!ENEMY_VAR_4+!ENEMY_1_OFFSET) } cutscenes_mb_ceiling_column_9: { - LDA !ENEMY_HP+$40 : BEQ .continue - LDA #$0010 : STA !ENEMY_VAR_5+$40 + LDA !ENEMY_HP+!ENEMY_1_OFFSET : BEQ .continue + LDA #$0010 : STA !ENEMY_VAR_5+!ENEMY_1_OFFSET .continue if !FEATURE_PAL @@ -1895,14 +1971,14 @@ if !FEATURE_PAL else LDA #$89B5 endif - STA !ENEMY_VAR_4+$40 - JMP (!ENEMY_VAR_4+$40) + STA !ENEMY_VAR_4+!ENEMY_1_OFFSET + JMP (!ENEMY_VAR_4+!ENEMY_1_OFFSET) } cutscenes_mb_ceiling_column_6: { - LDA !ENEMY_HP+$40 : BEQ .continue - LDA #$0010 : STA !ENEMY_VAR_5+$40 + LDA !ENEMY_HP+!ENEMY_1_OFFSET : BEQ .continue + LDA #$0010 : STA !ENEMY_VAR_5+!ENEMY_1_OFFSET .continue if !FEATURE_PAL @@ -1910,14 +1986,14 @@ if !FEATURE_PAL else LDA #$89E7 endif - STA !ENEMY_VAR_4+$40 - JMP (!ENEMY_VAR_4+$40) + STA !ENEMY_VAR_4+!ENEMY_1_OFFSET + JMP (!ENEMY_VAR_4+!ENEMY_1_OFFSET) } cutscenes_mb_bottom_right_tube: { - LDA !ENEMY_HP+$40 : BEQ .continue - LDA #$0010 : STA !ENEMY_VAR_5+$40 + LDA !ENEMY_HP+!ENEMY_1_OFFSET : BEQ .continue + LDA #$0010 : STA !ENEMY_VAR_5+!ENEMY_1_OFFSET .continue if !FEATURE_PAL @@ -1925,14 +2001,14 @@ if !FEATURE_PAL else LDA #$8A0F endif - STA !ENEMY_VAR_4+$40 - JMP (!ENEMY_VAR_4+$40) + STA !ENEMY_VAR_4+!ENEMY_1_OFFSET + JMP (!ENEMY_VAR_4+!ENEMY_1_OFFSET) } cutscenes_mb_bottom_middle_left_tube: { - LDA !ENEMY_HP+$40 : BEQ .continue - LDA #$0010 : STA !ENEMY_VAR_5+$40 + LDA !ENEMY_HP+!ENEMY_1_OFFSET : BEQ .continue + LDA #$0010 : STA !ENEMY_VAR_5+!ENEMY_1_OFFSET .continue if !FEATURE_PAL @@ -1940,14 +2016,14 @@ if !FEATURE_PAL else LDA #$8A37 endif - STA !ENEMY_VAR_4+$40 - JMP (!ENEMY_VAR_4+$40) + STA !ENEMY_VAR_4+!ENEMY_1_OFFSET + JMP (!ENEMY_VAR_4+!ENEMY_1_OFFSET) } cutscenes_mb_ceiling_column_7: { - LDA !ENEMY_HP+$40 : BEQ .continue - LDA #$0010 : STA !ENEMY_VAR_5+$40 + LDA !ENEMY_HP+!ENEMY_1_OFFSET : BEQ .continue + LDA #$0010 : STA !ENEMY_VAR_5+!ENEMY_1_OFFSET .continue if !FEATURE_PAL @@ -1955,14 +2031,14 @@ if !FEATURE_PAL else LDA #$8A69 endif - STA !ENEMY_VAR_4+$40 - JMP (!ENEMY_VAR_4+$40) + STA !ENEMY_VAR_4+!ENEMY_1_OFFSET + JMP (!ENEMY_VAR_4+!ENEMY_1_OFFSET) } cutscenes_mb_ceiling_column_8: { - LDA !ENEMY_HP+$40 : BEQ .continue - LDA #$0010 : STA !ENEMY_VAR_5+$40 + LDA !ENEMY_HP+!ENEMY_1_OFFSET : BEQ .continue + LDA #$0010 : STA !ENEMY_VAR_5+!ENEMY_1_OFFSET .continue if !FEATURE_PAL @@ -1970,8 +2046,8 @@ if !FEATURE_PAL else LDA #$8A9B endif - STA !ENEMY_VAR_4+$40 - JMP (!ENEMY_VAR_4+$40) + STA !ENEMY_VAR_4+!ENEMY_1_OFFSET + JMP (!ENEMY_VAR_4+!ENEMY_1_OFFSET) } cutscenes_mb_setup_fight_or_escape: @@ -1988,12 +2064,12 @@ else endif .mb - LDA !ENEMY_HP+$40 : BEQ .init_health - TDC : STA !ENEMY_VAR_5 : STA !ENEMY_HP+$40 + LDA !ENEMY_HP+!ENEMY_1_OFFSET : BEQ .init_health + TDC : STA !ENEMY_VAR_5 : STA !ENEMY_HP+!ENEMY_1_OFFSET BRA .continue .init_health - LDA #$4650 : STA !ENEMY_HP+$40 + LDA #$4650 : STA !ENEMY_HP+!ENEMY_1_OFFSET .continue if !FEATURE_PAL @@ -2007,7 +2083,7 @@ endif cutscenes_mb_pause_phase_2: { - LDA !ENEMY_HP+$40 : BNE .continue + LDA !ENEMY_HP+!ENEMY_1_OFFSET : BNE .continue TDC : STA !ENEMY_VAR_5 LDA !sram_cutscenes : BIT !CUTSCENE_FAST_MB : BEQ .lower_acid LDA !sram_room_layout : BIT !ROOM_LAYOUT_DASH_RECALL : BEQ .continue @@ -2027,7 +2103,7 @@ endif cutscenes_mb_load_tiles_phase_2: { - LDA !ENEMY_HP+$40 : BNE .continue + LDA !ENEMY_HP+!ENEMY_1_OFFSET : BNE .continue TDC : STA !ENEMY_VAR_5 .continue @@ -2071,7 +2147,7 @@ cutscenes_mb_choose_phase_2_or_3: LDA #$0004 : STA $7E7800 ; 36000 health - LDA #$8CA0 : STA !ENEMY_HP+$40 + LDA #$8CA0 : STA !ENEMY_HP+!ENEMY_1_OFFSET ; Enable health-based palette TDC : STA $7E7860 : STA $7E7868 @@ -2093,7 +2169,7 @@ endif LDA #$0002 : STA $7E7800 ; 18000 health - LDA #$4650 : STA !ENEMY_HP+$40 + LDA #$4650 : STA !ENEMY_HP+!ENEMY_1_OFFSET if !FEATURE_PAL JMP $8EE1 else @@ -2197,7 +2273,7 @@ cutscenes_mb_death_brain_falling_fast: { ; Vanilla logic except add $40 instead of $20 LDA !ENEMY_VAR_5 : CLC : ADC #$0040 : STA !ENEMY_VAR_5 - XBA : AND #$00FF : CLC : ADC !ENEMY_Y+$40 + XBA : AND #$00FF : CLC : ADC !ENEMY_Y+!ENEMY_1_OFFSET CMP #$00C4 : BCC .rts if !FEATURE_PAL @@ -2207,7 +2283,7 @@ else endif .rts - STA !ENEMY_Y+$40 + STA !ENEMY_Y+!ENEMY_1_OFFSET RTS } diff --git a/src/damage.asm b/src/damage.asm index 65dca29e..cc5a6b30 100644 --- a/src/damage.asm +++ b/src/damage.asm @@ -3,8 +3,8 @@ org $8DE37C AND !ram_suits_heat_damage_check : BNE $29 LDA !ram_suits_heat_damage_value : BEQ $23 - CLC : ADC $0A4E : STA $0A4E - BCC $03 : INC $0A50 + CLC : ADC !SAMUS_PERIODIC_SUBDAMAGE : STA !SAMUS_PERIODIC_SUBDAMAGE + BCC $03 : INC !SAMUS_PERIODIC_DAMAGE warnpc $8DE394 @@ -14,11 +14,11 @@ org $9081DB ; Everything else is vanilla but needs to be shifted down three bytes AND !SAMUS_LAVA_DAMAGE_SUITS CMP !SAMUS_LAVA_DAMAGE_SUITS : BEQ $2C - LDA $09DA : BIT #$0007 : BNE $0F - LDA $09C2 : CMP #$0047 : BMI $07 + LDA !IGT_FRAMES : BIT #$0007 : BNE $0F + LDA !SAMUS_HP : CMP #$0047 : BMI $07 LDA #$002D : JSL $809139 - LDA $0A4E : CLC : ADC $9E8B : STA $0A4E - LDA $0A50 : ADC $9E8D + LDA !SAMUS_PERIODIC_SUBDAMAGE : CLC : ADC $9E8B : STA !SAMUS_PERIODIC_SUBDAMAGE + LDA !SAMUS_PERIODIC_DAMAGE : ADC $9E8D ; Originally STA $0A50 and BRA $40 to $90824C ; Conveniently the command at $908249 is STA $0A50 so we can save three bytes BRA $3D @@ -143,10 +143,10 @@ endif suit_metroid_damage: { LDA #$C000 : STA $12 - LDA $09A2 : AND !ram_suits_enemy_damage_check : BEQ .checkGrav + LDA !SAMUS_ITEMS_EQUIPPED : AND !ram_suits_enemy_damage_check : BEQ .checkGrav LSR $12 .checkGrav - LDA $09A2 : BIT #$0020 : BEQ .noGrav + LDA !SAMUS_ITEMS_EQUIPPED : BIT #$0020 : BEQ .noGrav LSR $12 .noGrav ; Continue vanilla routine @@ -157,8 +157,8 @@ suit_metroid_damage: damage_overwritten_movement_routine: ; We overwrote an unnecessary JSR, a STZ command, and a jump to the movement routine - STZ $0A6E - JMP ($0A58) + STZ !SAMUS_CONTACT_DAMAGE_INDEX + JMP (!SAMUS_NORMAL_MOVEMENT_HANDLER) periodic_damage_table: if !FEATURE_PAL @@ -207,14 +207,14 @@ endif periodic_damage_balanced: { PHP : REP #$30 - LDA $0A78 : BEQ $03 + LDA !TIME_IS_FROZEN : BEQ $03 ; Nothing to do, jump back to vanilla routine if !FEATURE_PAL JMP $EA32 else JMP $EA35 endif - LDA $09A2 : BIT #$0001 : BNE $03 + LDA !SAMUS_ITEMS_EQUIPPED : BIT #$0001 : BNE $03 ; Either jump to gravity (75% reduction) or power suit (no reduction) if !FEATURE_PAL JMP $EA0E ; Varia not equipped @@ -228,7 +228,7 @@ endif periodic_damage_progressive: { PHP : REP #$30 - LDA $0A78 : BEQ $03 + LDA !TIME_IS_FROZEN : BEQ $03 ; Nothing to do, jump back to vanilla routine if !FEATURE_PAL JMP $EA32 @@ -236,18 +236,18 @@ else JMP $EA35 endif - LDA $09A2 : BIT #$0020 : BEQ .nogravity + LDA !SAMUS_ITEMS_EQUIPPED : BIT #$0020 : BEQ .nogravity ; Gravity equipped, so halve damage - LDA $0A4F : LSR - PHA : XBA : AND #$FF00 : STA $0A4E - PLA : XBA : AND #$00FF : STA $0A50 + LDA !SAMUS_PERIODIC_DAMAGECOMBINED : LSR + PHA : XBA : AND #$FF00 : STA !SAMUS_PERIODIC_SUBDAMAGE + PLA : XBA : AND #$00FF : STA !SAMUS_PERIODIC_DAMAGE .nogravity - LDA $09A2 : BIT #$0001 : BEQ .novaria + LDA !SAMUS_ITEMS_EQUIPPED : BIT #$0001 : BEQ .novaria ; Varia equipped, so halve damage - LDA $0A4F : LSR - PHA : XBA : AND #$FF00 : STA $0A4E - PLA : XBA : AND #$00FF : STA $0A50 + LDA !SAMUS_PERIODIC_DAMAGECOMBINED : LSR + PHA : XBA : AND #$FF00 : STA !SAMUS_PERIODIC_SUBDAMAGE + PLA : XBA : AND #$00FF : STA !SAMUS_PERIODIC_DAMAGE .novaria ; Jump back into the vanilla routine @@ -261,7 +261,7 @@ endif periodic_damage_dash_recall: { PHP : REP #$30 - LDA $0A78 : BEQ $03 + LDA !TIME_IS_FROZEN : BEQ $03 ; Nothing to do, jump back to vanilla routine if !FEATURE_PAL JMP $EA32 @@ -269,7 +269,7 @@ else JMP $EA35 endif - LDA $09A2 : BIT #$0001 : BEQ .novaria + LDA !SAMUS_ITEMS_EQUIPPED : BIT #$0001 : BEQ .novaria ; Jump back to gravity vanilla routine for 75% reduction if !FEATURE_PAL JMP $E9F9 @@ -278,11 +278,11 @@ else endif .novaria - LDA $09A2 : BIT #$0020 : BEQ .nogravity + LDA !SAMUS_ITEMS_EQUIPPED : BIT #$0020 : BEQ .nogravity ; Gravity equipped, so halve damage - LDA $0A4F : LSR - PHA : XBA : AND #$FF00 : STA $0A4E - PLA : XBA : AND #$00FF : STA $0A50 + LDA !SAMUS_PERIODIC_DAMAGECOMBINED : LSR + PHA : XBA : AND #$FF00 : STA !SAMUS_PERIODIC_SUBDAMAGE + PLA : XBA : AND #$00FF : STA !SAMUS_PERIODIC_DAMAGE .nogravity ; Jump back into the vanilla routine @@ -296,7 +296,7 @@ endif periodic_damage_heat_shield: { PHP : REP #$30 - LDA $0A78 : BEQ $03 + LDA !TIME_IS_FROZEN : BEQ $03 ; Nothing to do, jump back to vanilla routine if !FEATURE_PAL JMP $EA32 @@ -304,11 +304,11 @@ else JMP $EA35 endif - LDA $09A2 : BIT #$0020 : BEQ .nogravity + LDA !SAMUS_ITEMS_EQUIPPED : BIT #$0020 : BEQ .nogravity ; Gravity equipped, so halve damage - LDA $0A4F : LSR - PHA : XBA : AND #$FF00 : STA $0A4E - PLA : XBA : AND #$00FF : STA $0A50 + LDA !SAMUS_PERIODIC_DAMAGECOMBINED : LSR + PHA : XBA : AND #$FF00 : STA !SAMUS_PERIODIC_SUBDAMAGE + PLA : XBA : AND #$00FF : STA !SAMUS_PERIODIC_DAMAGE .nogravity ; Jump back into the vanilla routine @@ -329,12 +329,12 @@ healthalarm_turn_on_table: healthalarm_turn_on_improved: ; Do not sound alarm until below 30 combined health - LDA $09C2 : CLC : ADC $09D6 : CMP #$001E : BPL healthalarm_turn_on_done + LDA !SAMUS_HP : CLC : ADC !SAMUS_RESERVE_ENERGY : CMP #$001E : BPL healthalarm_turn_on_done healthalarm_turn_on_always_on: healthalarm_turn_on_pb_fix: ; Do not sound alarm if it won't play due to power bomb explosion - LDA $0592 : BMI healthalarm_turn_on_done + LDA !PB_EXPLOSION_STATUS : BMI healthalarm_turn_on_done healthalarm_turn_on_vanilla: LDA #$0002 : JSL $80914D @@ -356,7 +356,7 @@ healthalarm_turn_off_table: healthalarm_turn_off_improved: healthalarm_turn_off_pb_fix: ; Do not stop alarm if it won't stop due to power bomb explosion - LDA $0592 : BMI healthalarm_turn_off_done + LDA !PB_EXPLOSION_STATUS : BMI healthalarm_turn_off_done healthalarm_turn_off_vanilla: LDA #$0001 : JSL $80914D @@ -369,7 +369,7 @@ healthalarm_turn_off_done: healthalarm_turn_off_always_on: ; Do not sound alarm if it won't play due to power bomb explosion - LDA $0592 : BMI healthalarm_turn_off_done + LDA !PB_EXPLOSION_STATUS : BMI healthalarm_turn_off_done LDA #$0002 : JSL $80914D BRA healthalarm_turn_off_never @@ -394,32 +394,32 @@ damage_init_beam: ; so we can inject custom damage without a CPU hit PHP : PHB : PHK : PLB %ai16() - LDA $0C04,X : AND #$000F + LDA !SAMUS_PROJ_DIRECTION,X : AND #$000F ASL : STA $12 - LDA $0C18,X + LDA !SAMUS_PROJ_PROPERTIES,X BIT #$0010 : BNE .charged AND #$000F : ASL TAY : LDA $83C1,Y : TAY LDA !sram_custom_damage : BNE .nonVanillaUncharged - LDA $0000,Y : STA $0C2C,X + LDA $0000,Y : STA !SAMUS_PROJ_DAMAGE,X JMP $8048 .charged AND #$000F : ASL TAY : LDA $83D9,Y : TAY LDA !sram_custom_damage : BNE .nonVanillaCharged - LDA $0000,Y : STA $0C2C,X + LDA $0000,Y : STA !SAMUS_PROJ_DAMAGE,X JMP $8048 .nonVanillaUncharged DEC : BEQ .customUncharged .dashCharge0 - PHX : JSL compute_dash_charge_0_damage : PLX : STA $0C2C,X + PHX : JSL compute_dash_charge_0_damage : PLX : STA !SAMUS_PROJ_DAMAGE,X JMP $8048 .customUncharged - LDA !sram_custom_uncharge_damage : STA $0C2C,X + LDA !sram_custom_uncharge_damage : STA !SAMUS_PROJ_DAMAGE,X JMP $8048 .nonVanillaCharged @@ -428,23 +428,23 @@ damage_init_beam: DEC : BEQ .dashCharge1 DEC : BEQ .dashCharge2 DEC : BEQ .dashCharge3 - PHX : JSL compute_dash_charge_4_damage : PLX : STA $0C2C,X + PHX : JSL compute_dash_charge_4_damage : PLX : STA !SAMUS_PROJ_DAMAGE,X JMP $8048 .customCharged - LDA !sram_custom_charge_damage : STA $0C2C,X + LDA !sram_custom_charge_damage : STA !SAMUS_PROJ_DAMAGE,X JMP $8048 .dashCharge1 - PHX : JSL compute_dash_charge_1_damage : PLX : STA $0C2C,X + PHX : JSL compute_dash_charge_1_damage : PLX : STA !SAMUS_PROJ_DAMAGE,X JMP $8048 .dashCharge2 - PHX : JSL compute_dash_charge_2_damage : PLX : STA $0C2C,X + PHX : JSL compute_dash_charge_2_damage : PLX : STA !SAMUS_PROJ_DAMAGE,X JMP $8048 .dashCharge3 - PHX : JSL compute_dash_charge_3_damage : PLX : STA $0C2C,X + PHX : JSL compute_dash_charge_3_damage : PLX : STA !SAMUS_PROJ_DAMAGE,X JMP $8048 } diff --git a/src/defines.asm b/src/defines.asm index a78c2285..11600207 100644 --- a/src/defines.asm +++ b/src/defines.asm @@ -3,16 +3,40 @@ ; Work RAM ; --------- -!ram_tilemap_buffer = $7E5800 -!CRASHDUMP_TILEMAP_BUFFER = !ram_tilemap_buffer +; The crash buffer and initial address can be moved around as needed +; It is currently placed in the back half of the backup of BG2 tilemap during x-ray, +; which means it is unlikely to overwrite anything relevant for debugging +!CRASHDUMP_TILEMAP_BUFFER = $7E5800 ; 2048 bytes +!CRASH_INITIAL_ADDRESS = #$7E0A44 + +; Practice hack menu tilemap buffer +!ram_tilemap_buffer = $7EF500 ; 2048 bytes + +; Shortcut routine is written on boot and each time the menu closes, +; so it can use the same space as the practice hack menu tilemap buffer +!CTRL_SHORTCUT_ROUTINE = $7EF502 ; up to 1883 bytes or +$75A +!CTRL_SHORTCUT_TABLE = !CTRL_SHORTCUT_ROUTINE+$7B6 ; 48 bytes +!CTRL_SHORTCUT_TYPE = !CTRL_SHORTCUT_ROUTINE+$7E6 +!CTRL_SHORTCUT_PRI = !CTRL_SHORTCUT_ROUTINE+$7E8 +!CTRL_SHORTCUT_SEC = !CTRL_SHORTCUT_ROUTINE+$7EA +!CTRL_SHORTCUT_JSL_WORD_LSB = !CTRL_SHORTCUT_ROUTINE+$7EC +!CTRL_SHORTCUT_JSL_WORD_MSB = !CTRL_SHORTCUT_ROUTINE+$7EE +!CTRL_SHORTCUT_PRI_TO_SEC_DUAL_JUMP = !CTRL_SHORTCUT_ROUTINE+$7F0 +!CTRL_SHORTCUT_SEC_TO_DUAL_JUMP = !CTRL_SHORTCUT_ROUTINE+$7F2 +!CTRL_SHORTCUT_TABLE_PRI_INDEX = !CTRL_SHORTCUT_ROUTINE+$7F4 +!CTRL_SHORTCUT_TABLE_SEC_INDEX = !CTRL_SHORTCUT_ROUTINE+$7F6 +!CTRL_SHORTCUT_TABLE_DUAL_INDEX = !CTRL_SHORTCUT_ROUTINE+$7F8 +; Shortcuts can skip remaining checks by replacing the return address word +!CTRL_SHORTCUT_SKIP_REMAINING_PEA = !CTRL_SHORTCUT_ROUTINE+$7FA +!CTRL_SHORTCUT_SKIP_REMAINING_PEA_VALUE = $FCFC -!WRAM_BANK = !WRAM_START>>16 !WRAM_SIZE = #$0200 !WRAM_START = $7EFD00 !WRAM_PERSIST_START = $7EFD80 !WRAM_MENU_START = $7EFE00 !WRAM_END = $7EFF00 !CRASHDUMP = $7EFF00 +!WRAM_BANK = !WRAM_START>>16 ; These variables are NOT PERSISTENT across savestates -- ; they're saved and reloaded along with the game state. @@ -63,12 +87,12 @@ !ram_room_has_set_rng = !WRAM_START+$42 !ram_HUD_top = !WRAM_START+$44 !ram_HUD_middle = !WRAM_START+$46 -!ram_HUD_check = !WRAM_START+$48 +!ram_infidoppler_active = !WRAM_START+$48 !ram_roomstrat_counter = !WRAM_START+$4A !ram_roomstrat_state = !WRAM_START+$4C !ram_enemy_hp = !WRAM_START+$4E -!ram_mb_hp = !WRAM_START+$50 -!ram_shot_timer = !WRAM_START+$52 +!ram_HUD_top_counter = !WRAM_START+$50 +!ram_HUD_middle_counter = !WRAM_START+$52 !ram_shine_counter = !WRAM_START+$54 !ram_dash_counter = !WRAM_START+$56 @@ -90,13 +114,19 @@ !ram_xpos = !WRAM_START+$6E !ram_ypos = !WRAM_START+$70 !ram_subpixel_pos = !WRAM_START+$72 -!ram_HUD_top_counter = !WRAM_START+$74 -!ram_HUD_middle_counter = !WRAM_START+$76 +!ram_HUD_check = !WRAM_START+$74 +!ram_shot_timer = !WRAM_START+$76 !ram_quickdrop_counter = !WRAM_START+$78 !ram_walljump_counter = !WRAM_START+$7A !ram_fail_sum = !WRAM_START+$7C !ram_fail_count = !WRAM_START+$7E +; Shot timer also reuses values +!ram_shot_timer_past1 = !WRAM_START+$78 +!ram_shot_timer_past2 = !WRAM_START+$7A +!ram_shot_timer_past3 = !WRAM_START+$7C +!ram_shot_timer_past4 = !WRAM_START+$7E + ; Kihunter manip !ram_enemy0_last_xpos = !WRAM_START+$6E !ram_enemy0_last_ypos = !WRAM_START+$70 @@ -141,21 +171,22 @@ !ram_space_pants_enabled = !WRAM_PERSIST_START+$0C !ram_kraid_claw_rng = !WRAM_PERSIST_START+$0E !ram_kraid_wait_rng = !WRAM_PERSIST_START+$10 -!ram_botwoon_first = !WRAM_PERSIST_START+$12 -!ram_botwoon_second = !WRAM_PERSIST_START+$14 -!ram_botwoon_hidden = !WRAM_PERSIST_START+$16 -!ram_botwoon_spit = !WRAM_PERSIST_START+$18 -!ram_botwoon_rng = !WRAM_PERSIST_START+$1A +!ram_draygon_rng_left = !WRAM_PERSIST_START+$12 +!ram_draygon_rng_right = !WRAM_PERSIST_START+$14 +!ram_turret_rng = !WRAM_PERSIST_START+$16 +!ram_ridley_rng_flags = !WRAM_PERSIST_START+$18 +!ram_ridley_rng_times_and_fireball = !WRAM_PERSIST_START+$1A !ram_crocomire_rng = !WRAM_PERSIST_START+$1C -!ram_phantoon_rng_round_1 = !WRAM_PERSIST_START+$1E -!ram_phantoon_rng_round_2 = !WRAM_PERSIST_START+$20 -!ram_phantoon_rng_inverted = !WRAM_PERSIST_START+$22 -!ram_phantoon_rng_eyeclose = !WRAM_PERSIST_START+$24 -!ram_phantoon_rng_flames = !WRAM_PERSIST_START+$26 -!ram_phantoon_rng_next_flames = !WRAM_PERSIST_START+$28 -!ram_phantoon_flame_direction = !WRAM_PERSIST_START+$2A -!ram_draygon_rng_left = !WRAM_PERSIST_START+$2C -!ram_draygon_rng_right = !WRAM_PERSIST_START+$2E +!ram_phantoon_phase_rng = !WRAM_PERSIST_START+$1E +!ram_phantoon_eye_and_flames_rng = !WRAM_PERSIST_START+$20 +!ram_botwoon_rng = !WRAM_PERSIST_START+$22 +!ram_baby_rng = !WRAM_PERSIST_START+$24 +!ram_mb_rng = !WRAM_PERSIST_START+$26 + +!ram_itempickups_all = !WRAM_PERSIST_START+$28 +!ram_itempickups_visible = !WRAM_PERSIST_START+$2A +!ram_itempickups_chozo = !WRAM_PERSIST_START+$2C +!ram_itempickups_hidden = !WRAM_PERSIST_START+$2E !ram_suits_enemy_damage_check = !WRAM_PERSIST_START+$30 !ram_suits_heat_damage_check = !WRAM_PERSIST_START+$32 @@ -175,25 +206,16 @@ !ram_watch_edit_lock_right = !WRAM_PERSIST_START+$4C !ram_game_loop_extras = !WRAM_PERSIST_START+$4E -!ram_game_mode_extras = !WRAM_PERSIST_START+$50 +!ram_infinite_ammo = !WRAM_PERSIST_START+$50 !ram_suits_heat_damage_value = !WRAM_PERSIST_START+$52 !ram_sprite_feature_flags = !WRAM_PERSIST_START+$54 !ram_door_portal_flags = !WRAM_PERSIST_START+$56 !ram_door_source = !WRAM_PERSIST_START+$58 !ram_door_destination = !WRAM_PERSIST_START+$5A -!ram_itempickups_all = !WRAM_PERSIST_START+$5C -!ram_itempickups_visible = !WRAM_PERSIST_START+$5E -!ram_itempickups_chozo = !WRAM_PERSIST_START+$60 -!ram_itempickups_hidden = !WRAM_PERSIST_START+$62 -!ram_frames_held = !WRAM_PERSIST_START+$64 -!ram_baby_rng = !WRAM_PERSIST_START+$66 -!ram_turret_rng = !WRAM_PERSIST_START+$68 - -!ram_quickboot_spc_state = !WRAM_PERSIST_START+$6A -!ram_display_backup = !WRAM_PERSIST_START+$6C -!ram_phantoon_always_visible = !WRAM_PERSIST_START+$6E -!ram_loadstate_rando_enable = !WRAM_PERSIST_START+$70 -!ram_infinite_ammo = !WRAM_PERSIST_START+$72 +!ram_frames_held = !WRAM_PERSIST_START+$5C +!ram_quickboot_spc_state = !WRAM_PERSIST_START+$5E +!ram_display_backup = !WRAM_PERSIST_START+$60 +!ram_drop_chance_table = !WRAM_PERSIST_START+$62 ; ^ FREE SPACE ^ up to +$7C (!WRAM_START+$FC - !WRAM_PERSIST_START) @@ -216,56 +238,45 @@ !ram_cm_menu_bank = !WRAM_MENU_START+$26 !ram_cm_horizontal_cursor = !WRAM_MENU_START+$28 -!ram_cm_etanks = !WRAM_MENU_START+$2A -!ram_cm_reserve = !WRAM_MENU_START+$2C -!ram_cm_leave = !WRAM_MENU_START+$2E -!ram_cm_input_counter = !WRAM_MENU_START+$30 -!ram_cm_last_nmi_counter = !WRAM_MENU_START+$32 - -!ram_cm_ctrl_mode = !WRAM_MENU_START+$34 -!ram_cm_ctrl_timer = !WRAM_MENU_START+$36 -!ram_cm_ctrl_last_input = !WRAM_MENU_START+$38 -!ram_cm_ctrl_assign = !WRAM_MENU_START+$3A -!ram_cm_ctrl_swap = !WRAM_MENU_START+$3C - -!ram_cm_slowdown_mode = !WRAM_MENU_START+$3E -!ram_cm_slowdown_frames = !WRAM_MENU_START+$40 - -!ram_cm_botwoon_rng = !WRAM_MENU_START+$42 -!ram_cm_botwoon_first = !WRAM_MENU_START+$44 -!ram_cm_botwoon_hidden = !WRAM_MENU_START+$46 -!ram_cm_botwoon_second = !WRAM_MENU_START+$48 -!ram_cm_botwoon_spit = !WRAM_MENU_START+$4A -!ram_cm_custom_preset_labels = !WRAM_MENU_START+$4C - -!ram_seed_X = !WRAM_MENU_START+$4E -!ram_seed_Y = !WRAM_MENU_START+$50 - -!ram_cm_sfxlib1 = !WRAM_MENU_START+$52 -!ram_cm_sfxlib2 = !WRAM_MENU_START+$54 -!ram_cm_sfxlib3 = !WRAM_MENU_START+$56 - -!ram_cm_fast_scroll_menu_selection = !WRAM_MENU_START+$58 -!ram_timers_autoupdate = !WRAM_MENU_START+$5A -!ram_cm_suit_properties = !WRAM_MENU_START+$5C - -!ram_cm_palette_border = !WRAM_MENU_START+$5E -!ram_cm_palette_headeroutline = !WRAM_MENU_START+$60 -!ram_cm_palette_text = !WRAM_MENU_START+$62 -!ram_cm_palette_background = !WRAM_MENU_START+$64 -!ram_cm_palette_numoutline = !WRAM_MENU_START+$66 -!ram_cm_palette_numfill = !WRAM_MENU_START+$68 -!ram_cm_palette_toggleon = !WRAM_MENU_START+$6A -!ram_cm_palette_seltext = !WRAM_MENU_START+$6C -!ram_cm_palette_seltextbg = !WRAM_MENU_START+$6E -!ram_cm_palette_numseloutline = !WRAM_MENU_START+$70 -!ram_cm_palette_numsel = !WRAM_MENU_START+$72 - -!ram_infidoppler_active = !WRAM_START+$74 - -; ^ FREE SPACE ^ up to +$76 - -!ram_cm_preserved_timers = !WRAM_MENU_START+$78 ; 8 bytes +!ram_cm_leave = !WRAM_MENU_START+$2A +!ram_cm_input_counter = !WRAM_MENU_START+$2C +!ram_cm_last_nmi_counter = !WRAM_MENU_START+$2E +!ram_cm_ctrl_mode = !WRAM_MENU_START+$30 +!ram_cm_custom_preset_labels = !WRAM_MENU_START+$32 + +!ram_cm_slowdown_mode = !WRAM_MENU_START+$34 +!ram_cm_slowdown_frames = !WRAM_MENU_START+$36 + +!ram_seed_X = !WRAM_MENU_START+$38 +!ram_seed_Y = !WRAM_MENU_START+$3A + +!ram_cm_fast_scroll_menu_selection = !WRAM_MENU_START+$3C +!ram_cm_suit_properties = !WRAM_MENU_START+$3E + +!ram_cm_palette_border = !WRAM_MENU_START+$40 +!ram_cm_palette_headeroutline = !WRAM_MENU_START+$42 +!ram_cm_palette_text = !WRAM_MENU_START+$44 +!ram_cm_palette_background = !WRAM_MENU_START+$46 +!ram_cm_palette_numoutline = !WRAM_MENU_START+$48 +!ram_cm_palette_numfill = !WRAM_MENU_START+$4A +!ram_cm_palette_toggleon = !WRAM_MENU_START+$4C +!ram_cm_palette_seltext = !WRAM_MENU_START+$4E +!ram_cm_palette_seltextbg = !WRAM_MENU_START+$50 +!ram_cm_palette_numseloutline = !WRAM_MENU_START+$52 +!ram_cm_palette_numsel = !WRAM_MENU_START+$54 + +!ram_cm_sfxlib1 = !WRAM_MENU_START+$56 +!ram_cm_sfxlib2 = !WRAM_MENU_START+$58 +!ram_cm_sfxlib3 = !WRAM_MENU_START+$5A + +!ram_sram_detection = !WRAM_MENU_START+$5C + +!ram_timers_autoupdate = !WRAM_MENU_START+$5E +!ram_cm_gmode = !WRAM_MENU_START+$60 + +; ^ FREE SPACE ^ up to +$86 + +!ram_cm_preserved_timers = !WRAM_MENU_START+$88 ; 8 bytes ; ------------------ ; Reusable RAM Menu @@ -274,81 +285,119 @@ ; The following RAM may be used multiple times, ; as long as it isn't used multiple times on the same menu page -!ram_cm_watch_enemy_property = !WRAM_MENU_START+$80 -!ram_cm_watch_enemy_index = !WRAM_MENU_START+$82 -!ram_cm_watch_enemy_side = !WRAM_MENU_START+$84 -!ram_cm_watch_common_address = !WRAM_MENU_START+$86 - -!ram_cm_preset_elevator = !WRAM_MENU_START+$80 - -!ram_cm_door_dynamic = !WRAM_MENU_START+$80 -!ram_cm_door_menu_value = !WRAM_MENU_START+$82 -!ram_cm_door_menu_bank = !WRAM_MENU_START+$84 -!ram_cm_door_direction_index = !WRAM_MENU_START+$86 -!ram_cm_itempickups_visible = !WRAM_MENU_START+$88 -!ram_cm_itempickups_chozo = !WRAM_MENU_START+$8A -!ram_cm_itempickups_hidden = !WRAM_MENU_START+$8C - -!ram_cm_phan_first_phase = !WRAM_MENU_START+$80 -!ram_cm_phan_second_phase = !WRAM_MENU_START+$82 -!ram_cm_turret_rng = !WRAM_MENU_START+$84 - -!ram_cm_varia = !WRAM_MENU_START+$80 -!ram_cm_gravity = !WRAM_MENU_START+$82 -!ram_cm_morph = !WRAM_MENU_START+$84 -!ram_cm_bombs = !WRAM_MENU_START+$86 -!ram_cm_spring = !WRAM_MENU_START+$88 -!ram_cm_screw = !WRAM_MENU_START+$8A -!ram_cm_hijump = !WRAM_MENU_START+$8C -!ram_cm_space = !WRAM_MENU_START+$8E -!ram_cm_speed = !WRAM_MENU_START+$90 -!ram_cm_charge = !WRAM_MENU_START+$92 -!ram_cm_ice = !WRAM_MENU_START+$94 -!ram_cm_wave = !WRAM_MENU_START+$96 -!ram_cm_spazer = !WRAM_MENU_START+$98 -!ram_cm_plasma = !WRAM_MENU_START+$9A - -!ram_cm_zeb1 = !WRAM_MENU_START+$80 -!ram_cm_zeb2 = !WRAM_MENU_START+$82 -!ram_cm_zeb3 = !WRAM_MENU_START+$84 -!ram_cm_zeb4 = !WRAM_MENU_START+$86 -!ram_cm_zebmask = !WRAM_MENU_START+$88 - -!ram_cm_custompalette_blue = !WRAM_MENU_START+$80 -!ram_cm_custompalette_green = !WRAM_MENU_START+$82 -!ram_cm_custompalette_red = !WRAM_MENU_START+$84 -!ram_cm_custompalette = !WRAM_MENU_START+$86 -!ram_cm_dummy_on = !WRAM_MENU_START+$8A -!ram_cm_dummy_off = !WRAM_MENU_START+$8C -!ram_cm_dummy_num = !WRAM_MENU_START+$8E - -!ram_cm_ceres_seconds = !WRAM_MENU_START+$80 -!ram_cm_zebes_seconds = !WRAM_MENU_START+$82 - -!ram_cm_crop_mode = !WRAM_MENU_START+$80 -!ram_cm_crop_tile = !WRAM_MENU_START+$82 - -!ram_cm_brb = !WRAM_MENU_START+$80 -!ram_cm_brb_timer = !WRAM_MENU_START+$82 -!ram_cm_brb_frames = !WRAM_MENU_START+$84 -!ram_cm_brb_secs = !WRAM_MENU_START+$86 -!ram_cm_brb_mins = !WRAM_MENU_START+$88 -!ram_cm_brb_screen = !WRAM_MENU_START+$8A -!ram_cm_brb_timer_mode = !WRAM_MENU_START+$8C -!ram_cm_brb_scroll = !WRAM_MENU_START+$8E -!ram_cm_brb_scroll_X = !WRAM_MENU_START+$90 -!ram_cm_brb_scroll_Y = !WRAM_MENU_START+$92 -!ram_cm_brb_scroll_H = !WRAM_MENU_START+$94 -!ram_cm_brb_scroll_V = !WRAM_MENU_START+$96 -!ram_cm_brb_scroll_timer = !WRAM_MENU_START+$98 -!ram_cm_brb_palette = !WRAM_MENU_START+$9A -!ram_cm_brb_set_cycle = !WRAM_MENU_START+$9C -!ram_cm_brb_cycle_time = !WRAM_MENU_START+$9E - -!ram_cm_keyboard_buffer = !WRAM_MENU_START+$80 ; $18 bytes - -!ram_cm_manage_slots = !WRAM_MENU_START+$80 -!ram_cm_selected_slot = !WRAM_MENU_START+$82 +!ram_cm_watch_enemy_property = !WRAM_MENU_START+$90 +!ram_cm_watch_enemy_index = !WRAM_MENU_START+$92 +!ram_cm_watch_enemy_side = !WRAM_MENU_START+$94 +!ram_cm_watch_common_address = !WRAM_MENU_START+$96 + +!ram_cm_door_dynamic = !WRAM_MENU_START+$90 +!ram_cm_door_menu_value = !WRAM_MENU_START+$92 +!ram_cm_door_menu_bank = !WRAM_MENU_START+$94 +!ram_cm_door_direction_index = !WRAM_MENU_START+$96 +!ram_cm_itempickups_visible = !WRAM_MENU_START+$98 +!ram_cm_itempickups_chozo = !WRAM_MENU_START+$9A +!ram_cm_itempickups_hidden = !WRAM_MENU_START+$9C + +!ram_cm_turret_rng = !WRAM_MENU_START+$90 +!ram_cm_drop_chances = !WRAM_MENU_START+$92 + +!ram_cm_phantoon_first_phase_rng = !WRAM_MENU_START+$9C +!ram_cm_phantoon_second_phase_rng = !WRAM_MENU_START+$9E +!ram_cm_phantoon_flip_rng = !WRAM_MENU_START+$A0 +!ram_cm_phantoon_eyeclose_rng = !WRAM_MENU_START+$A2 +!ram_cm_phantoon_flames_rng = !WRAM_MENU_START+$A4 +!ram_cm_phantoon_next_flames_rng = !WRAM_MENU_START+$A6 +!ram_cm_phantoon_flame_direction_rng = !WRAM_MENU_START+$A8 + +!ram_cm_ridley_pogo_height_rng = !WRAM_MENU_START+$9C +!ram_cm_ridley_lunge_pogo_rng = !WRAM_MENU_START+$9E +!ram_cm_ridley_swoop_pogo_rng = !WRAM_MENU_START+$A0 +!ram_cm_ridley_ceres_ai_rng = !WRAM_MENU_START+$A2 +!ram_cm_ridley_hover_fireball_rng = !WRAM_MENU_START+$A4 +!ram_cm_ridley_backpogo_rng = !WRAM_MENU_START+$A6 +!ram_cm_ridley_pogo_time_rng = !WRAM_MENU_START+$A8 +!ram_cm_ridley_pogo_time_value_rng = !WRAM_MENU_START+$AA +!ram_cm_ridley_hover_time_rng = !WRAM_MENU_START+$AC +!ram_cm_ridley_hover_time_value_rng = !WRAM_MENU_START+$AE + +!ram_cm_botwoon_first_rng = !WRAM_MENU_START+$9C +!ram_cm_botwoon_hidden_rng = !WRAM_MENU_START+$9E +!ram_cm_botwoon_second_rng = !WRAM_MENU_START+$A0 +!ram_cm_botwoon_spit_rng = !WRAM_MENU_START+$A2 +!ram_cm_botwoon_after_spit_rng = !WRAM_MENU_START+$A4 + +!ram_cm_mb_walking_rng = !WRAM_MENU_START+$9C +!ram_cm_mb_ketchup_rng = !WRAM_MENU_START+$9E +!ram_cm_mb_damage_down_rng = !WRAM_MENU_START+$A0 +!ram_cm_mb_phase3_attack_rng = !WRAM_MENU_START+$A2 +!ram_cm_mb_normal_attack_rng = !WRAM_MENU_START+$A4 +!ram_cm_mb_bomb_crouch_rng = !WRAM_MENU_START+$A6 + +!ram_cm_varia = !WRAM_MENU_START+$90 +!ram_cm_gravity = !WRAM_MENU_START+$92 +!ram_cm_morph = !WRAM_MENU_START+$94 +!ram_cm_bombs = !WRAM_MENU_START+$96 +!ram_cm_spring = !WRAM_MENU_START+$98 +!ram_cm_screw = !WRAM_MENU_START+$9A +!ram_cm_hijump = !WRAM_MENU_START+$9C +!ram_cm_space = !WRAM_MENU_START+$9E +!ram_cm_speed = !WRAM_MENU_START+$A0 +!ram_cm_charge = !WRAM_MENU_START+$A2 +!ram_cm_ice = !WRAM_MENU_START+$A4 +!ram_cm_wave = !WRAM_MENU_START+$A6 +!ram_cm_spazer = !WRAM_MENU_START+$A8 +!ram_cm_plasma = !WRAM_MENU_START+$AA +!ram_cm_etanks = !WRAM_MENU_START+$AC +!ram_cm_reserve = !WRAM_MENU_START+$AE + +!ram_cm_zebmask = !WRAM_MENU_START+$90 +!ram_cm_metmask = !WRAM_MENU_START+$92 + +!ram_cm_ceres_seconds = !WRAM_MENU_START+$90 +!ram_cm_zebes_seconds = !WRAM_MENU_START+$92 + +!ram_cm_ctrl_add_shortcut_slot = !WRAM_MENU_START+$90 +!ram_cm_ctrl_last_pri = !WRAM_MENU_START+$92 +!ram_cm_ctrl_last_sec = !WRAM_MENU_START+$94 +!ram_cm_ctrl_assign = !WRAM_MENU_START+$96 +!ram_cm_ctrl_swap = !WRAM_MENU_START+$98 +!ram_cm_ctrl_timer = !WRAM_MENU_START+$9A +!ram_cm_ctrl_savestates_allowed = !WRAM_MENU_START+$9C + +!ram_cm_crop_mode = !WRAM_MENU_START+$90 +!ram_cm_crop_tile = !WRAM_MENU_START+$92 + +!ram_cm_brb = !WRAM_MENU_START+$90 +!ram_cm_brb_timer = !WRAM_MENU_START+$92 +!ram_cm_brb_frames = !WRAM_MENU_START+$94 +!ram_cm_brb_secs = !WRAM_MENU_START+$96 +!ram_cm_brb_mins = !WRAM_MENU_START+$98 +!ram_cm_brb_screen = !WRAM_MENU_START+$9A +!ram_cm_brb_timer_mode = !WRAM_MENU_START+$9C +!ram_cm_brb_scroll = !WRAM_MENU_START+$9E +!ram_cm_brb_scroll_X = !WRAM_MENU_START+$A0 +!ram_cm_brb_scroll_Y = !WRAM_MENU_START+$A2 +!ram_cm_brb_scroll_H = !WRAM_MENU_START+$A4 +!ram_cm_brb_scroll_V = !WRAM_MENU_START+$A6 +!ram_cm_brb_scroll_timer = !WRAM_MENU_START+$A8 +!ram_cm_brb_palette = !WRAM_MENU_START+$AA +!ram_cm_brb_set_cycle = !WRAM_MENU_START+$AC +!ram_cm_brb_cycle_time = !WRAM_MENU_START+$AE + +!ram_cm_manage_slots = !WRAM_MENU_START+$90 +!ram_cm_selected_slot = !WRAM_MENU_START+$92 +!ram_cm_preset_elevator = !WRAM_MENU_START+$94 + +; keyboard used by both presets and customize menus +!ram_cm_keyboard_buffer = !WRAM_MENU_START+$98 ; $18 bytes + +!ram_cm_custompalette_blue = !WRAM_MENU_START+$90 +!ram_cm_custompalette_green = !WRAM_MENU_START+$92 +!ram_cm_custompalette_red = !WRAM_MENU_START+$94 +!ram_cm_custompalette = !WRAM_MENU_START+$96 +!ram_cm_dummy_on = !WRAM_MENU_START+$AA +!ram_cm_dummy_off = !WRAM_MENU_START+$AC +!ram_cm_dummy_num = !WRAM_MENU_START+$AE ; ^ FREE SPACE ^ up to +$CE ; Note: +$B8 to +$CE range also used as frames held counters @@ -409,27 +458,12 @@ !LEVEL_DATA = $7F0002 ; Temporary stack written here since level data will be initialized afterwards +; There is room for 256 entries in the stack before risking leaving data behind, +; since even the smallest room has 512 bytes of level data !CATEGORY_PRESET_STACK = !LEVEL_DATA !END_OF_SINGLE_SCROLL_ROOM_LEVEL_DATA = $7F0202 -; Phantoon infidoppler can use the next $200 of RAM, -; since the room outside phantoon's room is larger and will overwrite this data, -; so the only way this could have some impact is you went OOB -; either from Phantoon's room or after teleporting to another single scroll room, -; and then fell a long ways out of bounds - -; An array of 5 words, one per projectile, representing -; the distance Samus travelled horizontally before firing. -; The low byte of each word is integer pixels, -; and the high byte is fractional pixels. -; Yes, that sounds weird, but the math is a little easier. -!ram_infidoppler_offsets = !END_OF_SINGLE_SCROLL_ROOM_LEVEL_DATA ; array of 5 words -!ram_infidoppler_x = !END_OF_SINGLE_SCROLL_ROOM_LEVEL_DATA+$10 -!ram_infidoppler_subx = !END_OF_SINGLE_SCROLL_ROOM_LEVEL_DATA+$12 -!ram_infidoppler_y = !END_OF_SINGLE_SCROLL_ROOM_LEVEL_DATA+$14 -!ram_infidoppler_suby = !END_OF_SINGLE_SCROLL_ROOM_LEVEL_DATA+$16 - ; Do not use RAM for variables at or beyond this point !LEVEL_BTS = $7F6402 @@ -438,30 +472,15 @@ ; SRAM ; ----- -!SRAM_VERSION = #$0019 +!SRAM_VERSION = #$001A !SRAM_START = $702000 !SRAM_SIZE = #$1000 !PRESET_SLOTS = $703000 !sram_initialized = !SRAM_START+$00 - -!sram_ctrl_menu = !SRAM_START+$02 -!sram_ctrl_kill_enemies = !SRAM_START+$04 -!sram_ctrl_full_equipment = !SRAM_START+$06 -!sram_ctrl_reset_segment_timer = !SRAM_START+$08 -!sram_ctrl_reset_segment_later = !SRAM_START+$0A -!sram_ctrl_load_state = !SRAM_START+$0C -!sram_ctrl_save_state = !SRAM_START+$0E -!sram_ctrl_load_last_preset = !SRAM_START+$10 -!sram_ctrl_random_preset = !SRAM_START+$12 -!sram_ctrl_save_custom_preset = !SRAM_START+$14 -!sram_ctrl_load_custom_preset = !SRAM_START+$16 -!sram_ctrl_inc_custom_preset = !SRAM_START+$18 -!sram_ctrl_dec_custom_preset = !SRAM_START+$1A -!sram_ctrl_toggle_tileviewer = !SRAM_START+$1C -!sram_ctrl_update_timers = !SRAM_START+$1E -; More ctrl shortcuts starting at $F0 +!sram_ctrl_shortcut_selections = !SRAM_START+$02 ; 30 bytes +; More ctrl shortcut selections starting at $EE !sram_artificial_lag = !SRAM_START+$20 !sram_rerandomize = !SRAM_START+$22 @@ -534,15 +553,10 @@ !sram_ceres_timer = !SRAM_START+$A0 !sram_zebes_timer = !SRAM_START+$A2 -; ^ FREE SPACE ^ up to +$EE +; ^ FREE SPACE ^ up to +$EC -!sram_ctrl_auto_save_state = !SRAM_START+$F0 -!sram_ctrl_toggle_spin_lock = !SRAM_START+$F2 -!sram_ctrl_randomize_rng = !SRAM_START+$F4 -!sram_ctrl_reveal_damage = !SRAM_START+$F6 -!sram_ctrl_force_stand = !SRAM_START+$F8 - -; ^ FREE SPACE ^ up to +$FE +; This is a continuation of sram_ctrl_shortcut_selections +!sram_ctrl_additional_selections = !SRAM_START+$D0 ; 18 bytes starting from +$EE !sram_presetequiprando = !SRAM_START+$100 !sram_presetequiprando_beampref = !SRAM_START+$102 @@ -557,6 +571,12 @@ !sram_loadstate_rando_missiles = !SRAM_START+$114 !sram_loadstate_rando_supers = !SRAM_START+$116 !sram_loadstate_rando_powerbombs = !SRAM_START+$118 +!sram_loadstate_rando_enable = !SRAM_START+$11A + +; ^ FREE SPACE ^ up to +$13E + +!sram_ctrl_1_shortcut_inputs = !SRAM_START+$140 ; 96 bytes +!sram_ctrl_2_shortcut_inputs = !SRAM_START+$1A0 ; 96 bytes ; ^ FREE SPACE ^ up to +$BA6 @@ -634,22 +654,18 @@ !IH_MORPH_BALL_GREEN = #$10C9 !IH_STUCK_GREEN = #$106B -!IH_PAUSE = #$0100 ; right -!IH_SLOWDOWN = #$0400 ; down -!IH_SPEEDUP = #$0800 ; up -!IH_RESET = #$0200 ; left -!IH_STATUS_R = #$0010 ; r -!IH_STATUS_L = #$0020 ; l - !IH_INPUT_START = #$1000 +!IH_INPUT_DPAD = #$0F00 !IH_INPUT_UPDOWN = #$0C00 !IH_INPUT_UP = #$0800 !IH_INPUT_DOWN = #$0400 +!IH_INPUT_XLEFTRIGHTHELD = #$0341 !IH_INPUT_LEFTRIGHT = #$0300 !IH_INPUT_LEFT = #$0200 !IH_INPUT_RIGHT = #$0100 !IH_INPUT_HELD = #$0001 ; used by menu +!CTRL_AB = #$8080 !CTRL_B = #$8000 !CTRL_Y = #$4000 !CTRL_SELECT = #$2000 @@ -745,6 +761,7 @@ !ENEMY_POPULATION = $07CF !ENEMY_SET = $07D1 !ROOM_MAIN_ASM_POINTER = $07DF +!SCROLLING_FINISHED_HOOK = $07E9 !CERES_HDMA_DATA = $07EB !MUSIC_DATA = $07F3 !MUSIC_TRACK = $07F5 @@ -823,6 +840,9 @@ !SAMUS_LOCKED_HANDLER = $0A42 !SAMUS_MOVEMENT_HANDLER = $0A44 !SAMUS_SUBUNIT_ENERGY = $0A4C +!SAMUS_PERIODIC_SUBDAMAGE = $0A4E +!SAMUS_PERIODIC_DAMAGECOMBINED = $0A4F +!SAMUS_PERIODIC_DAMAGE = $0A50 !SAMUS_KNOCKBACK_DIRECTION = $0A54 !SAMUS_BOMB_JUMP_DIRECTION = $0A56 !SAMUS_NORMAL_MOVEMENT_HANDLER = $0A58 @@ -835,6 +855,7 @@ !SAMUS_CONTACT_DAMAGE_INDEX = $0A6E !SAMUS_WATER_PHYSICS = $0A70 ; Not used in vanilla !SAMUS_HYPER_BEAM = $0A76 +!TIME_IS_FROZEN = $0A78 !DEMO_PREINSTRUCTION_POINTER = $0A7A !DEMO_INSTRUCTION_TIMER = $0A7C !DEMO_INSTRUCTION_POINTER = $0A7E @@ -879,6 +900,7 @@ !SAMUS_PROJ_Y_SUBPX = $0BA0 !SAMUS_PROJ_RADIUS_X = $0BB4 !SAMUS_PROJ_RADIUS_Y = $0BC8 +!SAMUS_PROJ_DIRECTION = $0C04 !SAMUS_PROJ_PROPERTIES = $0C18 !SAMUS_PROJ_DAMAGE = $0C2C !SAMUS_COOLDOWN = $0CCC @@ -911,6 +933,7 @@ !ENEMY_TIMER = $0F90 !ENEMY_INIT_PARAM = $0F92 !ENEMY_PALETTE_INDEX = $0F96 +!ENEMY_FROZEN_TIMER = $0F9E !ENEMY_BANK = $0FA6 !ENEMY_FUNCTION_POINTER = $0FA8 !ENEMY_VAR_1 = $0FAA @@ -926,6 +949,7 @@ !SAMUS_KNOCKBACK_TIMER = $18AA !LAVA_ACID_Y = $1962 !FX_BASE_Y = $1978 +!ENEMY_PROJ_ENABLE = $198D !ENEMY_PROJ_ID = $1997 !ENEMY_PROJ_X_SUBPX = $1A27 !ENEMY_PROJ_X = $1A4B @@ -936,6 +960,7 @@ !ENEMY_PROJ_RADIUS = $1BB3 !ENEMY_PROJ_PROPERTIES = $1BD7 !MESSAGE_BOX_INDEX = $1C1F +!PLM_ENABLE = $1C23 !PLM_GFX_INDEX = $1C2D !PLM_ID = $1C37 !PLM_BLOCK_INDEX = $1C87 @@ -945,6 +970,7 @@ !PLM_ROOM_ARGUMENT = $1DC7 !PLM_VARIABLE = $1E17 !SAVE_STATION_LOCKOUT = $1E75 +!PALETTE_FX_ENABLE = $1E79 !PALETTE_FX_ID = $1E7D !PALETTE_FX_COLOR_INDICES = $1E8D !PALETTE_FX_VARIABLE = $1E9D @@ -952,11 +978,79 @@ !PALETTE_FX_INSTRUCTION_POINTER = $1EBD !PALETTE_FX_INSTRUCTION_TIMER = $1ECD !PALETTE_FX_TIMER = $1EDD +!ANIMATED_TILES_ENABLE = $1EF1 !CINEMATIC_FUNCTION_POINTER = $1F51 !DEMO_TIMER = $1F53 !DEMO_CURRENT_SET = $1F55 !DEMO_CURRENT_SCENE = $1F57 +; In rooms with fewer enemies, some enemy RAM is available for use +!ENEMY_1_OFFSET = $40 +!ENEMY_2_OFFSET = $80 +!ENEMY_1C_OFFSET = $700 +!ENEMY_1D_OFFSET = $740 +!ENEMY_1E_OFFSET = $780 +!ENEMY_1F_OFFSET = $7C0 + +; An array of 5 words, one per projectile, representing +; the distance Samus travelled horizontally before firing. +; The low byte of each word is integer pixels, +; and the high byte is fractional pixels. +; Yes, that sounds weird, but the math is a little easier. +!eram_infidoppler_offsets = !ENEMY_VAR_1+!ENEMY_1C_OFFSET ; array of 5 words +!eram_infidoppler_x = !ENEMY_VAR_1+!ENEMY_1D_OFFSET +!eram_infidoppler_subx = !ENEMY_VAR_2+!ENEMY_1D_OFFSET +!eram_infidoppler_y = !ENEMY_VAR_3+!ENEMY_1D_OFFSET +!eram_infidoppler_suby = !ENEMY_VAR_4+!ENEMY_1D_OFFSET +!eram_phantoon_always_visible = !ENEMY_VAR_5+!ENEMY_1D_OFFSET +!eram_phantoon_rng_round_1 = !ENEMY_VAR_1+!ENEMY_1E_OFFSET +!eram_phantoon_rng_round_2 = !ENEMY_VAR_2+!ENEMY_1E_OFFSET +!eram_phantoon_rng_flip = !ENEMY_VAR_3+!ENEMY_1E_OFFSET +!eram_phantoon_rng_eyeclose = !ENEMY_VAR_4+!ENEMY_1E_OFFSET +!eram_phantoon_rng_flames = !ENEMY_VAR_1+!ENEMY_1F_OFFSET +!eram_phantoon_rng_next_flames = !ENEMY_VAR_2+!ENEMY_1F_OFFSET +!eram_phantoon_rng_flame_direction = !ENEMY_VAR_3+!ENEMY_1F_OFFSET + +!eram_ceres_ridley_rng = !ENEMY_VAR_1+!ENEMY_1E_OFFSET +!eram_ridley_lunge_pogo_rng = !ENEMY_VAR_2+!ENEMY_1E_OFFSET +!eram_ridley_swoop_pogo_rng = !ENEMY_VAR_3+!ENEMY_1E_OFFSET +!eram_ridley_pogo_swoop_rng = !ENEMY_VAR_4+!ENEMY_1E_OFFSET +!eram_ridley_fireball_rng = !ENEMY_VAR_5+!ENEMY_1E_OFFSET +!eram_ridley_hover_time_rng = !ENEMY_VAR_1+!ENEMY_1F_OFFSET +!eram_ridley_pogo_time_rng = !ENEMY_VAR_2+!ENEMY_1F_OFFSET +!eram_ridley_pogo_height_rng = !ENEMY_VAR_3+!ENEMY_1F_OFFSET +!eram_ridley_backpogo_rng = !ENEMY_VAR_4+!ENEMY_1F_OFFSET + +!eram_mb_normal_walking_rng = !ENEMY_VAR_5+!ENEMY_1D_OFFSET +!eram_mb_ketchup_walking_rng = !ENEMY_VAR_1+!ENEMY_1E_OFFSET +!eram_mb_ketchup_rng = !ENEMY_VAR_2+!ENEMY_1E_OFFSET +!eram_mb_try_bomb_crouch = !ENEMY_VAR_3+!ENEMY_1E_OFFSET +!eram_mb_bomb_crouch = !ENEMY_VAR_4+!ENEMY_1E_OFFSET +!eram_mb_air_rings_rng = !ENEMY_VAR_5+!ENEMY_1E_OFFSET +!eram_mb_ground_bomb_rng = !ENEMY_VAR_1+!ENEMY_1F_OFFSET +!eram_mb_ground_attack_rng_table = !ENEMY_VAR_2+!ENEMY_1F_OFFSET +!eram_mb_close_attack_rng_table = !ENEMY_VAR_3+!ENEMY_1F_OFFSET +!eram_mb_damage_down_rng = !ENEMY_VAR_4+!ENEMY_1F_OFFSET +!eram_mb_phase3_attack_rng = !ENEMY_VAR_5+!ENEMY_1F_OFFSET + +!eram_botwoon_first_roll = !ENEMY_VAR_4+!ENEMY_1E_OFFSET +!eram_botwoon_all_pattern_rng = !ENEMY_VAR_5+!ENEMY_1E_OFFSET +!eram_botwoon_first_rng = !ENEMY_VAR_1+!ENEMY_1F_OFFSET +!eram_botwoon_hidden_rng = !ENEMY_VAR_2+!ENEMY_1F_OFFSET +!eram_botwoon_second_rng = !ENEMY_VAR_3+!ENEMY_1F_OFFSET +!eram_botwoon_spit_rng = !ENEMY_VAR_4+!ENEMY_1F_OFFSET +!eram_botwoon_after_spit_rng = !ENEMY_VAR_5+!ENEMY_1F_OFFSET + +!eram_baby_leaving_left = !ENEMY_VAR_2+!ENEMY_1E_OFFSET +!eram_baby_leaving_right = !ENEMY_VAR_3+!ENEMY_1E_OFFSET +!eram_baby_backing_off = !ENEMY_VAR_4+!ENEMY_1E_OFFSET +!eram_baby_rising_delay = !ENEMY_VAR_5+!ENEMY_1E_OFFSET +!eram_baby_after_drain_delay = !ENEMY_VAR_1+!ENEMY_1F_OFFSET +!eram_baby_target_x_pos = !ENEMY_VAR_2+!ENEMY_1F_OFFSET +!eram_baby_dead_hop_delay = !ENEMY_VAR_3+!ENEMY_1F_OFFSET +!eram_baby_hop_velocity_tables = !ENEMY_VAR_4+!ENEMY_1F_OFFSET +!eram_baby_initial_delay = !ENEMY_VAR_5+!ENEMY_1F_OFFSET + !HUD_TILEMAP = $7EC600 !MAP_COUNTER = $7ECAE8 ; Not used in vanilla !SCROLLS = $7ECD20 @@ -1090,6 +1184,7 @@ endif !DP_KB_Row = $1A !DP_KB_Control = $1C !DP_KB_Shift = $1E +!DP_Ctrl2Input = $1C ; 0x4 ; v single digit editing v !DP_DigitAddress = $20 ; 0x4 !DP_DigitValue = $24 @@ -1122,10 +1217,24 @@ endif if !FEATURE_PAL !FRAMERATE = #$0032 +!FRAMERATE_2X = #$0064 else !FRAMERATE = #$003C +!FRAMERATE_2X = #$0078 endif +!CTRL_SHORTCUT_TYPE_MASK = #$007F +!CTRL_SHORTCUT_EXACT_MATCH = #$0080 + +; By default, value is zero and we assume there are no issues +!SRAM_DETECTION_32KB = #$0032 +!SRAM_DETECTION_128KB = #$0128 +!SRAM_DETECTION_ZSNES = #$0505 + +!SLOWDOWN_FRAME_ADVANCE = #$8000 +!SLOWDOWN_PAUSED_MAIN_MENU = #$FFFE +!SLOWDOWN_PAUSED = #$FFFF + !SUIT_PROPERTIES_MASK = #$0007 !SUIT_PROPRETIES_PAL_DEBUG_FLAG = #$0008 @@ -1195,6 +1304,91 @@ endif !DOOR_PORTAL_HORIZONTAL_MIRRORING_BIT = #$0010 !DOOR_PORTAL_EXCLUDE_JUMP_MASK = #$FFF7 +!PHANTOON_RNG_PHASE_1_MASK = #$003F +!PHANTOON_RNG_PHASE_1_INVERTED = #$FFC0 +!PHANTOON_RNG_FLIP_MASK = #$00C0 +!PHANTOON_RNG_FLIP_INVERTED = #$FF3F +!PHANTOON_RNG_PHASE_2_MASK = #$3F00 +!PHANTOON_RNG_PHASE_2_INVERTED = #$C0FF +!PHANTOON_RNG_PHASE_2_FLIP_INVERTED = #$C03F +!PHANTOON_RNG_VISIBLE_BIT = #$4000 +!PHANTOON_RNG_VISIBLE_INVERTED = #$BFFF + +!PHANTOON_RNG_FLAMES_MASK = #$0007 +!PHANTOON_RNG_FLAMES_INVERTED = #$FFF8 +!PHANTOON_RNG_FLAMES_PATH_MASK = #$00C0 +!PHANTOON_RNG_FLAMES_PATH_INVERTED = #$FF3F +!PHANTOON_RNG_FLAMES_NEXT_MASK = #$0700 +!PHANTOON_RNG_FLAMES_NEXT_INVERTED = #$F8FF +!PHANTOON_RNG_EYE_CLOSE_MASK = #$C000 +!PHANTOON_RNG_EYE_CLOSE_INVERTED = #$3FFF + +!RIDLEY_RNG_CERES_FIREBALL = #$0001 +!RIDLEY_RNG_CERES_LUNGE = #$0002 +!RIDLEY_RNG_CERES_SWOOP = #$0003 +!RIDLEY_RNG_CERES_MASK = #$0007 +!RIDLEY_RNG_CERES_INVERTED = #$FFF8 +!RIDLEY_RNG_POGO_HEIGHT_MASK = #$0038 +!RIDLEY_RNG_POGO_HEIGHT_INVERTED = #$FFC7 +!RIDLEY_RNG_75_25_LUNGE = #$0040 +!RIDLEY_RNG_75_25_POGO = #$0080 +!RIDLEY_RNG_75_25_MASK = #$00C0 +!RIDLEY_RNG_75_25_INVERTED = #$FF3F +!RIDLEY_RNG_BACKPOGO_MASK = #$3F00 +!RIDLEY_RNG_BACKPOGO_INVERTED = #$C0FF +!RIDLEY_RNG_50_50_SWOOP = #$4000 +!RIDLEY_RNG_50_50_POGO = #$8000 +!RIDLEY_RNG_50_50_MASK = #$C000 +!RIDLEY_RNG_50_50_INVERTED = #$3FFF + +!RIDLEY_RNG_HOVER_TIME_MASK = #$003F +!RIDLEY_RNG_HOVER_TIME_INVERTED = #$FFC0 +!RIDLEY_RNG_ALL_FIREBALL = #$0040 +!RIDLEY_RNG_NO_FIREBALL = #$0080 +!RIDLEY_RNG_FIREBALL_MASK = #$00C0 +!RIDLEY_RNG_FIREBALL_INVERTED = #$FF3F +!RIDLEY_RNG_POGO_TIME_MASK = #$FF00 +!RIDLEY_RNG_POGO_TIME_INVERTED = #$00FF + +!MB_RNG_WALKING_MASK = #$0003 +!MB_RNG_WALKING_INVERTED = #$FFFC +!MB_RNG_KETCHUP_MASK = #$000C +!MB_RNG_KETCHUP_INVERTED = #$FFF3 +!MB_RNG_DAMAGE_DOWN_MASK = #$0030 +!MB_RNG_DAMAGE_DOWN_INVERTED = #$FFCF +!MB_RNG_PHASE3_ATTACK_RINGS = #$0080 +!MB_RNG_PHASE3_ATTACK_BOMBS = #$0100 +!MB_RNG_PHASE3_ATTACK_MASK = #$0180 +!MB_RNG_PHASE3_ATTACK_INVERTED = #$FE7F +!MB_RNG_NORMAL_ATTACK_MASK = #$0E00 +!MB_RNG_NORMAL_ATTACK_INVERTED = #$F1FF +!MB_RNG_BOMB_CROUCH_MASK = #$C000 +!MB_RNG_BOMB_CROUCH_INVERTED = #$3FFF + +; Each botwoon pattern can be #$00 (off), #$01, #$09, #$11, #$19 +; (except hidden pattern cannot be #$19) +; This corresponds to just three bits of information +; For efficiency this information can be overlapped, +; allowing for the spit value (#$00, #$04, #$08) to be included +; and also the after spit value in the most and least significant bits +!BOTWOON_RNG_FIRST_MASK = #$0032 ; #$0019 << 1 +!BOTWOON_RNG_FIRST_INVERTED = #$FFCD +!BOTWOON_RNG_FIRST_ENABLED = #$0002 +!BOTWOON_RNG_FIRST_VALUE = #$0030 +!BOTWOON_RNG_HIDDEN_MASK = #$0C80 ; #$1900 >> 1 +!BOTWOON_RNG_HIDDEN_INVERTED = #$F37F +!BOTWOON_RNG_HIDDEN_ENABLED = #$0080 +!BOTWOON_RNG_HIDDEN_VALUE = #$0C00 +!BOTWOON_RNG_SECOND_MASK = #$3200 ; #$1900 << 1 +!BOTWOON_RNG_SECOND_INVERTED = #$CDFF +!BOTWOON_RNG_SECOND_ENABLED = #$0200 +!BOTWOON_RNG_SECOND_VALUE = #$3000 +!BOTWOON_RNG_SPIT_MASK = #$000C +!BOTWOON_RNG_SPIT_INVERTED = #$FFF3 +!BOTWOON_RNG_AFTER_SPIT_ENABLED = #$8000 +!BOTWOON_RNG_AFTER_SPIT_MASK = #$8001 +!BOTWOON_RNG_AFTER_SPIT_INVERTED = #$7FFE + !PROFILE_CUSTOM = #$0000 !PROFILE_Twitch = #$0001 !PROFILE_Default = #$0002 diff --git a/src/enemy_rng.asm b/src/enemy_rng.asm index 9bd1451b..67418a84 100644 --- a/src/enemy_rng.asm +++ b/src/enemy_rng.asm @@ -1,4 +1,16 @@ +if !FEATURE_PAL +org $86F14A +else +org $86F10E +endif + LDA !ram_drop_chance_table : BNE $10 + ; Since we replaced unnecessary logic, + ; we need to burn some cycles to compensate + BRA $00 : BRA $00 +%warnpc($86F118, $86F154) + + ; ---------------- ; Phantoon hijacks ; ---------------- @@ -15,7 +27,7 @@ org $A7893D endif phantoon_always_visible: { - LDA !ram_phantoon_always_visible : BNE .enabled + LDA !eram_phantoon_always_visible : BNE .enabled ; overwritten code if !FEATURE_PAL JMP $DBCE @@ -25,13 +37,13 @@ endif .enabled ; fake the fade in so it takes the same number of frames - LDA !ENEMY_VAR_3+$40 : INC - CMP !ENEMY_VAR_4+$40 : BCS .inc - STZ !ENEMY_VAR_4+$40 + LDA !ENEMY_VAR_3+!ENEMY_1_OFFSET : INC + CMP !ENEMY_VAR_4+!ENEMY_1_OFFSET : BCS .inc + STZ !ENEMY_VAR_4+!ENEMY_1_OFFSET SEC : RTS .inc - INC !ENEMY_VAR_4+$40 + INC !ENEMY_VAR_4+!ENEMY_1_OFFSET CLC : RTS } @@ -129,6 +141,67 @@ endif ; Botwoon hijack ; -------------- +if !FEATURE_PAL +org $A0F2CB +else +org $A0F2AB +endif + dw #botwoon_vanilla_main_ai + +if !FEATURE_PAL +org $B395BD +else +org $B395AD +endif + RTL + +if !FEATURE_PAL +org $B39677 +else +org $B39667 +endif + LDA #$0001 : STA !eram_botwoon_first_roll + ; fallthrough to initialize botwoon RNG + +init_botwoon_rng: +{ + LDA !ram_botwoon_rng : AND !BOTWOON_RNG_SPIT_INVERTED : STA !eram_botwoon_all_pattern_rng + AND !BOTWOON_RNG_FIRST_MASK : LSR : STA !eram_botwoon_first_rng + LDA !ram_botwoon_rng : AND !BOTWOON_RNG_HIDDEN_MASK + ASL : XBA : STA !eram_botwoon_hidden_rng + LDA !ram_botwoon_rng : AND !BOTWOON_RNG_SECOND_MASK + LSR : XBA : STA !eram_botwoon_second_rng + LDA !ram_botwoon_rng : AND !BOTWOON_RNG_SPIT_MASK : STA !eram_botwoon_spit_rng + LDA !ram_botwoon_rng : AND !BOTWOON_RNG_AFTER_SPIT_MASK : STA !eram_botwoon_after_spit_rng + RTL +} + +; Vanilla main AI routine, just migrated +botwoon_vanilla_main_ai: +{ + LDX !ENEMY_INDEX +if !FEATURE_PAL + JSR $96D6 +else + JSR $96C6 +endif + JSR (!ENEMY_VAR_3,X) +if !FEATURE_PAL + JSR $983B +else + JSR $982B +endif + RTL +} +%warnpc($B396C6, $B396D6) + +if !FEATURE_PAL +org $B398D1 +else +org $B398C1 +endif + JSL hook_botwoon_spit + if !FEATURE_PAL org $B39953 else @@ -138,11 +211,12 @@ endif JSL hook_botwoon_move if !FEATURE_PAL -org $B398D1 +org $B39A2A else -org $B398C1 +org $B39A1A endif - JSL hook_botwoon_spit + ; $B3:9A1A 22 11 81 80 JSL $808111[$80:8111] + JSL hook_botwoon_move_after_spit ; --------------- @@ -187,6 +261,17 @@ endif JSR hook_draygon_damage +; ------------------ +; Spore Spawn hijack +; ------------------ +if !FEATURE_PAL +org $A5EADC +else +org $A5EAD7 +endif + JSR hook_spore_spawn_scroll + + ; ---------------- ; Crocomire hijack ; ---------------- @@ -198,6 +283,13 @@ org $A48753 endif JSR hook_crocomire_rng +if !FEATURE_PAL +org $A48A9F +else +org $A48A8F +endif + JSR hook_crocomire_scroll + if !FEATURE_PAL org $A48CED else @@ -261,10 +353,61 @@ endif JSR hook_kraid_claw_rng +; ------------------- +; Mother Brain hijack +; ------------------- + +if !FEATURE_PAL +org $A9874A +else +org $A9873A +endif + JML hook_mb_init_rng + + ; ----------- ; Baby hijack ; ----------- +if !FEATURE_PAL +org $A9D963 +else +org $A9D916 +endif + LDA !eram_baby_dead_hop_delay + +if !FEATURE_PAL +org $A9D98E +else +org $A9D941 +endif + CLC : ADC !eram_baby_hop_velocity_tables : TAY + LDA $0000,Y : STA $7E7816,X + LDA $0008,Y : STA $7E7814,X + RTS +%warnpc($A9D961, $A9D9AE) + +if !FEATURE_PAL +org $A9F002 +else +org $A9EFB5 +endif + JML hook_baby_init + +if !FEATURE_PAL +org $A9F07E +else +org $A9F031 +endif + LDA !eram_baby_initial_delay + +if !FEATURE_PAL +org $A9F096 +else +org $A9F049 +endif + LDA !eram_baby_target_x_pos + if !FEATURE_PAL org $A9F21B else ; Baby skip rng @@ -272,6 +415,41 @@ org $A9F1CE endif JMP hook_baby_skip_rng +if !FEATURE_PAL +org $A9F2F5 +else +org $A9F2A8 +endif + LDA !eram_baby_after_drain_delay + +if !FEATURE_PAL +org $A9F307 +else +org $A9F2BA +endif + LDA !eram_baby_rising_delay + +if !FEATURE_PAL +org $A9F333 +else +org $A9F2E6 +endif + LDA !eram_baby_backing_off + +if !FEATURE_PAL +org $A9F36B +else +org $A9F31E +endif + LDA !eram_baby_leaving_left + +if !FEATURE_PAL +org $A9F397 +else +org $A9F34A +endif + LDA !eram_baby_leaving_right + ; ----------------- ; "Set rng" hijacks @@ -375,6 +553,7 @@ hook_beetom_set_rng: ; $A7:D4AE 10 3D BPL $3D [$D4ED] ; else, return hook_phantoon_init: { + JSL init_phantoon_rng LDA !sram_cutscenes : AND !CUTSCENE_FAST_PHANTOON : BNE .skip_cutscene DEC !ENEMY_VAR_4,X @@ -394,6 +573,27 @@ else endif } +init_phantoon_rng: +{ + LDA !ram_phantoon_phase_rng : AND !PHANTOON_RNG_VISIBLE_BIT + STA !eram_phantoon_always_visible + LDA !ram_phantoon_phase_rng : AND !PHANTOON_RNG_PHASE_1_MASK + STA !eram_phantoon_rng_round_1 + LDA !ram_phantoon_phase_rng : AND !PHANTOON_RNG_PHASE_2_MASK + XBA : STA !eram_phantoon_rng_round_2 + LDA !ram_phantoon_phase_rng : AND !PHANTOON_RNG_FLIP_MASK + ASL #2 : XBA : STA !eram_phantoon_rng_flip + LDA !ram_phantoon_eye_and_flames_rng : AND !PHANTOON_RNG_FLAMES_MASK + STA !eram_phantoon_rng_flames + LDA !ram_phantoon_eye_and_flames_rng : AND !PHANTOON_RNG_FLAMES_PATH_MASK + ASL #2 : XBA : STA !eram_phantoon_rng_flame_direction + LDA !ram_phantoon_eye_and_flames_rng : AND !PHANTOON_RNG_FLAMES_NEXT_MASK + XBA : STA !eram_phantoon_rng_next_flames + LDA !ram_phantoon_eye_and_flames_rng : AND !PHANTOON_RNG_EYE_CLOSE_MASK + XBA : ASL #2 : XBA : STA !eram_phantoon_rng_eyeclose + RTL +} + ; Table of Phantoon pattern durations & directions ; bit 0 is direction, remaining bits are duration @@ -427,7 +627,7 @@ hook_phantoon_1st_rng: .rng ; If set to all-on or all-off, don't mess with RNG - LDA !ram_phantoon_rng_round_1 : BEQ .no_manip + LDA !eram_phantoon_rng_round_1 : BEQ .no_manip CMP #$003F : BNE choose_phantoon_pattern .no_manip @@ -438,7 +638,7 @@ if !FEATURE_PAL else LDA $CD53,Y endif - STA !ENEMY_FUNCTION_POINTER+$40 + STA !ENEMY_FUNCTION_POINTER+!ENEMY_1_OFFSET JSL $808111 BIT #$0001 RTL @@ -457,7 +657,7 @@ endif hook_phantoon_2nd_rng: { ; If set to all-on or all-off, don't mess with RNG - LDA !ram_phantoon_rng_round_2 : BEQ .no_manip + LDA !eram_phantoon_rng_round_2 : BEQ .no_manip CMP #$003F : BNE choose_phantoon_pattern .no_manip @@ -468,28 +668,29 @@ if !FEATURE_PAL else LDA $CD53,Y endif - STA !ENEMY_FUNCTION_POINTER+$40 ; Intentional fallthrough to invert logic + STA !ENEMY_FUNCTION_POINTER+!ENEMY_1_OFFSET + ; Intentional fallthrough to flip logic } -hook_phantoon_invert: +hook_phantoon_flip: { - LDA !ram_phantoon_rng_inverted : BEQ .vanilla_inverted - CMP #$0001 : BEQ .inverted - CMP #$0002 : BEQ .not_inverted + LDA !eram_phantoon_rng_flip : BEQ .vanilla_flip + DEC : BEQ .flipped + DEC : BEQ .not_flipped ; Random LDA !CACHED_RANDOM_NUMBER : BIT #$0080 RTL - .inverted - LDA #$0000 : BIT #$0001 + .flipped + TDC : BIT #$0001 RTL - .not_inverted + .not_flipped LDA #$0001 : BIT #$0001 RTL - .vanilla_inverted + .vanilla_flip LDA !FRAME_COUNTER : BIT #$0001 RTL } @@ -542,7 +743,7 @@ endif BNE .round1 ; Save the pattern timer, check the direction, ; and set Phantoon's starting point and pattern index. - LSR : STA !ENEMY_FUNCTION_POINTER+$40 : BCS .round2left + LSR : STA !ENEMY_FUNCTION_POINTER+!ENEMY_1_OFFSET : BCS .round2left ; Right pattern LDA #$0088 : LDY #$00D0 @@ -555,11 +756,11 @@ endif STA !ENEMY_FUNCTION_POINTER ; Index into figure-8 movement table STY !ENEMY_X ; X position LDA #$0060 : STA !ENEMY_Y ; Y position - BRA hook_phantoon_invert + BRA hook_phantoon_flip .round1 ; Save the pattern timer and check the direction - LSR : STA !ENEMY_FUNCTION_POINTER+$40 + LSR : STA !ENEMY_FUNCTION_POINTER+!ENEMY_1_OFFSET BCS .round1left ; Round 1 right pattern @@ -573,7 +774,7 @@ endif hook_phantoon_eyeclose: { - LDA !ram_phantoon_rng_eyeclose : BEQ .no_manip + LDA !eram_phantoon_rng_eyeclose : BEQ .no_manip DEC : ASL ; return with 0-slow, 2-mid, 4-fast RTL @@ -587,9 +788,9 @@ hook_phantoon_flame_pattern: { JSL $808111 ; Trying to preserve the number of RNG calls being done in the frame - LDA !ram_phantoon_rng_flames : TAY - LDA !ram_phantoon_rng_next_flames : STA !ram_phantoon_rng_flames - TYA : STA !ram_phantoon_rng_next_flames : BEQ .no_manip + LDA !eram_phantoon_rng_flames : TAY + LDA !eram_phantoon_rng_next_flames : STA !eram_phantoon_rng_flames + TYA : STA !eram_phantoon_rng_next_flames : BEQ .no_manip DEC RTL @@ -600,7 +801,7 @@ hook_phantoon_flame_pattern: hook_phantoon_flame_direction: { - LDA !ram_phantoon_flame_direction : BEQ .no_manip + LDA !eram_phantoon_rng_flame_direction : BEQ .no_manip DEC : BNE .right .left @@ -623,38 +824,45 @@ endif RTL } - hook_botwoon_move: { - LDA !ram_botwoon_rng : BEQ .no_manip + LDA !eram_botwoon_all_pattern_rng : BEQ .no_manip_maybe_first_roll + ; check if first round + LDA !eram_botwoon_first_roll : BNE .first_round ; 0 = head visible, 1 = behind wall LDA $7E8026 : BNE .hidden - ; check if first round, $7E8022 unused by Botwoon - LDA $7E8022 : BEQ .first_round + ; check if second round pattern fixed + LDA !eram_botwoon_second_rng : BEQ .no_manip ; preserve number of RNG calls in the frame JSL $808111 ; return chosen pattern - LDA !ram_botwoon_second + LDA !eram_botwoon_second_rng RTL .first_round + ; check if first round pattern fixed + LDA !eram_botwoon_first_rng : BEQ .no_manip_maybe_first_roll ; preserve number of RNG calls in the frame JSL $808111 ; mark first round complete - LDA #$0001 : STA $7E8022 + STZ !eram_botwoon_first_roll ; return chosen pattern - LDA !ram_botwoon_first + LDA !eram_botwoon_first_rng RTL .hidden - LDA !ram_botwoon_hidden : BEQ .no_manip + ; check if hidden round pattern fixed + LDA !eram_botwoon_hidden_rng : BEQ .no_manip ; preserve number of RNG calls in the frame JSL $808111 ; return chosen pattern - LDA !ram_botwoon_hidden + LDA !eram_botwoon_hidden_rng RTL + .no_manip_maybe_first_roll + ; mark first round complete + STZ !eram_botwoon_first_roll .no_manip ; return random pattern JML $808111 @@ -662,16 +870,22 @@ hook_botwoon_move: hook_botwoon_spit: { - LDA !ram_botwoon_spit : BEQ .no_manip + LDA !eram_botwoon_spit_rng : BEQ hook_botwoon_move_no_manip ; preserve number of RNG calls in the frame JSL $808111 ; return chosen pattern - LDA !ram_botwoon_spit + LDA !eram_botwoon_spit_rng RTL +} - .no_manip - ; return random pattern - JML $808111 +hook_botwoon_move_after_spit: +{ + LDA !eram_botwoon_after_spit_rng : BEQ hook_botwoon_move_no_manip + ; preserve number of RNG calls in the frame + JSL $808111 + ; return chosen pattern + LDA !eram_botwoon_after_spit_rng + RTL } %endfree(83) @@ -683,7 +897,7 @@ hook_crocomire_rng: { LDA !ram_crocomire_rng : BEQ .no_manip DEC : BEQ .step - LDA #$0000 ; return with <400 for swipe + TDC ; return with <400 for swipe RTS .step @@ -695,6 +909,23 @@ hook_crocomire_rng: RTS } +hook_crocomire_scroll: +{ + LDA !ram_door_portal_flags : AND !DOOR_PORTAL_MODE_MASK + CMP #$0002 : BNE .vanilla + LDA !ram_door_destination : ASL : TAX + LDA portals_right_vanilla_table,X : CMP #$93DE : BNE .vanilla + + ; In map rando when right door selected, + ; do not set red scrolls + LDA $7ECD20 + RTS + + .vanilla + TDC + RTS +} + hook_crocomire_damage: { LDA !sram_suppress_flashing : BIT !SUPPRESS_BOSS_DAMAGE_FLASH : BNE .suppress @@ -996,6 +1227,172 @@ endif RTS } +hook_spore_spawn_scroll: +{ + LDA !ram_door_portal_flags : AND !DOOR_PORTAL_MODE_MASK + CMP #$0002 : BNE .vanilla + LDA !ram_door_source : ASL : TAX + LDA portals_left_vanilla_table,X : CMP #$8E4A : BNE .vanilla + + ; In map rando when top door selected, + ; do not use a scroll hook for spore spawn + TDC + RTS + + .vanilla + ; Overwritten scrolling finished hook + LDA #$9589 + RTS +} + +; Migrated from bank A6 since not enough freespace there +init_ceres_ridley_rng: +{ + LDA !ram_ridley_rng_flags : AND !RIDLEY_RNG_CERES_MASK : BEQ .set_ceres_rng + CMP !RIDLEY_RNG_CERES_FIREBALL : BEQ .ceres_fireball + CMP !RIDLEY_RNG_CERES_LUNGE : BEQ .ceres_lunge + CMP !RIDLEY_RNG_CERES_SWOOP : BEQ .ceres_swoop + TDC : BRA .set_ceres_rng + + .ceres_fireball +if !FEATURE_PAL + LDA #$A792 +else + LDA #$A782 +endif + BRA .set_ceres_rng + + .ceres_lunge +if !FEATURE_PAL + LDA #$A84C +else + LDA #$A83C +endif + BRA .set_ceres_rng + + .ceres_swoop +if !FEATURE_PAL + LDA #$A89D +else + LDA #$A88D +endif + + .set_ceres_rng + STA !eram_ceres_ridley_rng + RTL +} + +init_zebes_ridley_rng: +{ + LDA !ram_ridley_rng_flags + BIT !RIDLEY_RNG_75_25_LUNGE : BNE .set_75_25_lunge + BIT !RIDLEY_RNG_75_25_POGO : BNE .set_75_25_pogo +if !FEATURE_PAL + LDA #$B3BC +else + LDA #$B3AC +endif + BRA .set_75_25 + + .set_75_25_lunge +if !FEATURE_PAL + LDA #$B3EC +else + LDA #$B3DC +endif + BRA .set_75_25 + + .set_75_25_pogo +if !FEATURE_PAL + LDA #$B3CC +else + LDA #$B3BC +endif + + .set_75_25 + STA !eram_ridley_lunge_pogo_rng + + LDA !ram_ridley_rng_flags + BIT !RIDLEY_RNG_50_50_SWOOP : BNE .set_50_50_swoop + BIT !RIDLEY_RNG_50_50_POGO : BNE .set_50_50_pogo +if !FEATURE_PAL + LDA #$B3AC +else + LDA #$B39C +endif + STA !eram_ridley_swoop_pogo_rng +if !FEATURE_PAL + LDA #$B39C +else + LDA #$B38C +endif + BRA .set_50_50 + + .set_50_50_swoop + LDA #ridley_all_swoop_table + BRA .set_50_50_both + + .set_50_50_pogo +if !FEATURE_PAL + LDA #$B3CC +else + LDA #$B3BC +endif + + .set_50_50_both + STA !eram_ridley_swoop_pogo_rng + .set_50_50 + STA !eram_ridley_pogo_swoop_rng + + LDA !ram_ridley_rng_times_and_fireball + BIT !RIDLEY_RNG_ALL_FIREBALL : BNE .set_all_fireball + BIT !RIDLEY_RNG_NO_FIREBALL : BNE .set_no_fireball + TDC : BRA .set_fireball + + .set_all_fireball + LDA #$0081 + BRA .set_fireball + + .set_no_fireball + TDC : INC + + .set_fireball + STA !eram_ridley_fireball_rng + + LDA !ram_ridley_rng_times_and_fireball : AND !RIDLEY_RNG_HOVER_TIME_MASK + STA !eram_ridley_hover_time_rng + + LDA !ram_ridley_rng_times_and_fireball : AND !RIDLEY_RNG_POGO_TIME_MASK + XBA : STA !eram_ridley_pogo_time_rng + + LDA !ram_ridley_rng_flags : AND !RIDLEY_RNG_POGO_HEIGHT_MASK + LSR #3 : STA !eram_ridley_pogo_height_rng + + PHX : LDA !ram_ridley_rng_flags : AND !RIDLEY_RNG_BACKPOGO_MASK + XBA : ASL : TAX : LDA.l ridley_backpogo_threshold_table,X + STA !eram_ridley_backpogo_rng : PLX + RTL +} + +ridley_backpogo_threshold_table: + dw #$0555, #$0000 + dw #$FFFF, #$0AAA, #$0FFF + dw #$1554, #$1AA9, #$1FFE + dw #$2553, #$2AA8, #$2FFD + dw #$3552, #$3AA7, #$3FFC + dw #$4551, #$4AA6, #$4FFB + dw #$5550, #$5AA5, #$5FFA + dw #$654F, #$6AA4, #$6FF9 + dw #$754E, #$7AA3, #$7FF8 + dw #$854D, #$8AA2, #$8FF7 + dw #$954C, #$9AA1, #$9FF6 + dw #$A54B, #$AAA0, #$AFF5 + dw #$B54A, #$BA9F, #$BFF4 + dw #$C549, #$CA9E, #$CFF3 + dw #$D548, #$DA9D, #$DFF2 + dw #$E547, #$EA9C, #$EFF1 + dw #$F546, #$FA9B, #$FFF0 + %endfree(A5) @@ -1031,6 +1428,261 @@ org $A6A360 endif LDA #ridley_init_hook +if !FEATURE_PAL +org $A6A72C +else +org $A6A71C +endif + BCC $0E ; overwrite a NOP to save one byte + +if !FEATURE_PAL +org $A6A73A +else +org $A6A72A +endif + BCC $55 ; branch to a different RTS since we overwrite the original + + ; See if Ceres Ridley RNG is fixed, requires five bytes + LDA !eram_ceres_ridley_rng : BNE ceres_ridley_set_ai + + ; Original vanilla RNG + LDA !CACHED_RANDOM_NUMBER : AND #$000F + ASL : TAX : LDA.w ceres_ridley_set_ai_table,X +ceres_ridley_set_ai: + STA !ENEMY_FUNCTION_POINTER + + ; We need to save five bytes, but we already saved one + ; Replacing LDA #$0000 with TDC saves two more + ; Jumping to another location that does STA $7E7800 : RTS saves two more + TDC +if !FEATURE_PAL + JMP $B4CE +else + JMP $B4BE +endif +ceres_ridley_set_ai_table: +%warnpc($A6A743, $A6A753) + +if !FEATURE_PAL +org $A6B36F +else +org $A6B35F +endif + LDY !eram_ridley_pogo_swoop_rng + +if !FEATURE_PAL +org $A6B385 +else +org $A6B375 +endif + LDY !eram_ridley_lunge_pogo_rng + +if !FEATURE_PAL +org $A6B38B +else +org $A6B37B +endif + LDY !eram_ridley_pogo_swoop_rng + +if !FEATURE_PAL +org $A6B396 +else +org $A6B386 +endif + LDY !eram_ridley_swoop_pogo_rng + +if !FEATURE_PAL +org $A6B3DC +else +org $A6B3CC +endif +ridley_all_hover_table: + ; move hover start back five bytes +if !FEATURE_PAL + dw $B5CF, $B5CF, $B5CF, $B5CF, $B5CF, $B5CF, $B5CF, $B5CF +else + dw $B5BF, $B5BF, $B5BF, $B5BF, $B5BF, $B5BF, $B5BF, $B5BF +endif + +if !FEATURE_PAL +org $A6B5CF +else +org $A6B5BF +endif + ; Vanilla logic from $A6:B5C4 + LDA #$000B : STA $7E201E + LDA #$0180 : STA $7E2012 +if !FEATURE_PAL + LDA #$B5F5 +else + LDA #$B5E5 +endif + STA !ENEMY_FUNCTION_POINTER + + ; Check if we have a fixed hover delay + LDA !eram_ridley_hover_time_rng : BNE $0A + + ; Continue to vanilla logic +%warnpc($A6B5D8, $A6B5E8) + +if !FEATURE_PAL +org $A6B605 + JMP $B69C +else ; Move jump by one byte due to below changes +org $A6B5F5 + JMP $B68C +endif + +if !FEATURE_PAL +org $A6B633 + JMP $B69C +else ; Move jump by one byte due to below changes +org $A6B623 + JMP $B68C +endif + +if !FEATURE_PAL +org $A6B651 +else +org $A6B641 +endif + ; We need to save five bytes, which we can do if we switch to 8-bit mode, + ; but this means we now need to save eleven bytes + ; Start by replacing LDX #$0000 with TDC : TAX (saved 1, spent 0) + TDC : TAX + ; Vanilla logic + LDA !SAMUS_Y : CMP #$0160 : BMI $03 + LDA #$0160 + STA $14 +if !FEATURE_PAL + JSR $B43E + JSR $D533 +else + JSR $B42E + JSR $D523 +endif + ; Replace LDA #$0001 with TDC : INC (saved 2, spent 0) + TDC : INC : STA $7E2004 + ; Switch to 8-bit mode (saved 2, spent 2) + %a8() + ; Skip AND #$00FF and reduce CMP #$0003 (saved 6, spent 2) + LDA !SAMUS_MOVEMENT_TYPE : CMP #$03 + BNE $23 + ; New logic (saved 6, spent 7) + LDA !eram_ridley_fireball_rng : BNE $03 + ; Original logic, but skip AND #$00FF and reduce #$0080 (saved 10, spent 7) + LDA !CACHED_RANDOM_NUMBER : CMP #$80 + ; Switch back to 16-bit mode (saved 10, spent 9) + %a16() + ; Vanilla logic + BCC $13 + LDA $7E781E : BNE $0D + LDA $7E7820 : DEC : BEQ $06 +if !FEATURE_PAL + LDA #$E711 + JSR $D43E +else + LDA #$E73A + JSR $D467 +endif + CLC : RTS + ; Switch back to 16-bit mode (saved 10, spent 11) + %a16() + SEC : RTS + ; Start into the next routine one byte later than vanilla + LDA #$00F0 : STA $7E2012 + LDA #$0010 : STA $7E201E + ; Replace LDA #$0001 with TDC : INC (saved 11, spent 11) + TDC : INC +%warnpc($A6B69C, $A6B6AC) + +if !FEATURE_PAL +org $A6B6BD +else ; Migrate vanilla routine up five bytes +org $A6B6AD +endif + BMI $1A + +if !FEATURE_PAL +org $A6B6C5 +else +org $A6B6B5 +endif + LDA.w ridley_acceleration_table,Y + +if !FEATURE_PAL +org $A6B6D9 + JSR $D92C + LDA #$B6E8 +else ; Migrate vanilla routine up five bytes +org $A6B6C9 + JSR $D955 + LDA #$B6D8 +endif + STA !ENEMY_FUNCTION_POINTER + LDA #$0020 : STA !ENEMY_VAR_5 + ; Start into the next routine five bytes earlier than vanilla + LDA !ENEMY_X : STA $12 + LDA #$0120 : STA $14 + LDX #$0000 : LDY #$0000 +if !FEATURE_PAL + JSR $D4FA +else + JSR $D523 +endif + DEC !ENEMY_VAR_5 : BPL $1D +if !FEATURE_PAL + JSR $CB0A + JSR ridley_set_pogo_height + LDA #$B71E +else + JSR $CB33 + JSR ridley_set_pogo_height + LDA #$B70E +endif + STA !ENEMY_FUNCTION_POINTER + ; Add new logic here + LDA !eram_ridley_pogo_time_rng : BNE $09 +%warnpc($A6B701, $A6B711) + + if !FEATURE_PAL +org $A6B772 +else +org $A6B762 +endif + JSR ridley_set_pogo_height + +if !FEATURE_PAL +org $A6B8EB +else +org $A6B8DB +endif + CMP !eram_ridley_backpogo_rng + +if !FEATURE_PAL +org $A6B90D +else +org $A6B8FD +endif + CMP !eram_ridley_backpogo_rng + +if !FEATURE_PAL +org $A6B93B +else +org $A6B92B +endif + LDA.w ridley_pogo_parameter_table,Y + +if !FEATURE_PAL +org $A6B95D +else +org $A6B94D +endif +ridley_set_pogo_height: + LDA !eram_ridley_pogo_height_rng : BEQ $BD + DEC : BRA $C0 +%warnpc($A6B959, $A6B969) + if !FEATURE_PAL org $A6EFA9 else @@ -1100,6 +1752,19 @@ endif %startfree(A6) +ridley_acceleration_table: + dw #$00B0, #$0080, #$0060 + +ridley_pogo_parameter_table: + dw #$000A, #$0010, #$0020, #$0030, #$0040, #$0050 + +ridley_all_swoop_table: +if !FEATURE_PAL + dw $B451, $B451, $B451, $B451, $B451, $B451, $B451, $B451 +else + dw $B441, $B441, $B441, $B441, $B441, $B441, $B441, $B441 +endif + ridley_reset_damagecounter: { TDC : STA !DAMAGE_COUNTER @@ -1108,7 +1773,9 @@ ridley_reset_damagecounter: ridley_init_hook: { - LDA !ROOM_ID : CMP.w #ROOM_CeresRidleyRoom : BNE .continue + LDA !ROOM_ID : CMP.w #ROOM_CeresRidleyRoom : BNE .not_ceres + JSL init_ceres_ridley_rng + LDA $7ED82E : BIT #$0001 : BEQ .continue ; Ceres Ridley is already dead, so skip to the escape @@ -1132,6 +1799,9 @@ endif STA !ENEMY_FUNCTION_POINTER JMP (!ENEMY_FUNCTION_POINTER) + .not_ceres + JSL init_zebes_ridley_rng + .continue if !FEATURE_PAL LDA #$A387 @@ -1314,5 +1984,162 @@ else endif } +baby_vanilla_hop_initial_velocities: + dw #$FE00, #$FE00, #$FE00, #$FC00 + dw #$01C0, #$0120, #$0120, #$0300 + +baby_maprando_hop_initial_velocities: + dw #$FE00, #$FE00, #$FC00, #$FE00 + dw #$0120, #$0250, #$0300, #$01C0 + +mb_ground_attack_max_rings_rng_table: + db #$00, #$FF, #$FF + +mb_ground_attack_max_fries_rng_table: + db #$00, #$00, #$FF + +mb_ground_attack_max_bombs_rng_table: + db #$00, #$00, #$00 + +mb_ground_attack_min_rings_rng_table: + db #$54, #$54, #$AA + +mb_ground_attack_min_fries_rng_table: + db #$54, #$AA, #$AA + +mb_ground_attack_min_bombs_rng_table: + db #$55, #$AA, #$FF + +mb_ground_attack_minimized_rng_table: + db #$FF, #$FF, #$FF + %endfree(A9) + +%startfree(AA) + +mb_normal_walking_rng_table: + dw #$1000, #$0000, #$FFFF, #$1000 + +mb_ketchup_walking_rng_table: + dw #$2000, #$FFFF, #$0000, #$2000 + +mb_damage_down_rng_table: + dw #$0FF0, #$1000, #$0000, #$0FF0 + +mb_ketchup_rng_table: + dw #$A000, #$FFFF, #$0000, #$A000 + +mb_air_rings_rng_table: + dw #$0080, #$0000, #$0080, #$0100, #$0100, #$0080, #$0000, #$0080 + +mb_ground_bomb_rng_table: + dw #$0080, #$0100, #$0000, #$0100, #$0080, #$0100, #$0080, #$0100 + +mb_ground_attack_rng_tables_table: +if !FEATURE_PAL + dw $B729 +else + dw $B6DC +endif + dw #mb_ground_attack_max_rings_rng_table + dw #mb_ground_attack_max_bombs_rng_table + dw #mb_ground_attack_max_fries_rng_table + dw #mb_ground_attack_min_rings_rng_table + dw #mb_ground_attack_min_bombs_rng_table + dw #mb_ground_attack_min_fries_rng_table + dw #mb_ground_attack_minimized_rng_table + +mb_close_attack_rng_tables_table: +if !FEATURE_PAL + dw $B72C +else + dw $B6DF +endif + dw #mb_ground_attack_max_rings_rng_table + dw #mb_ground_attack_max_bombs_rng_table + dw #mb_ground_attack_max_fries_rng_table + dw #mb_ground_attack_min_rings_rng_table + dw #mb_ground_attack_min_bombs_rng_table + dw #mb_ground_attack_min_fries_rng_table + dw #mb_ground_attack_minimized_rng_table + +mb_try_bomb_crouch_rng_table: + dw #$FF80, #$0000, #$FFFF, #$FF80 + +mb_bomb_crouch_rng_table: + dw #$8000, #$0000, #$FFFF, #$8000 + +init_mb_rng_from_menu: +{ + LDA !ENEMY_VAR_4 : PHA + JSL hook_mb_init_rng + PLA : STA !ENEMY_VAR_4 + RTL +} + +hook_mb_init_rng: +{ + LDA !ram_mb_rng : AND !MB_RNG_WALKING_MASK : ASL : TAX + LDA.l mb_normal_walking_rng_table,X : STA !eram_mb_normal_walking_rng + LDA.l mb_ketchup_walking_rng_table,X : STA !eram_mb_ketchup_walking_rng + LDA !ram_mb_rng : AND !MB_RNG_KETCHUP_MASK : LSR : TAX + LDA.l mb_ketchup_rng_table,X : STA !eram_mb_ketchup_rng + LDA !ram_mb_rng : AND !MB_RNG_DAMAGE_DOWN_MASK : LSR #3 : TAX + LDA.l mb_damage_down_rng_table,X : STA !eram_mb_damage_down_rng + LDA !ram_mb_rng : AND !MB_RNG_PHASE3_ATTACK_MASK + EOR !MB_RNG_PHASE3_ATTACK_RINGS : STA !eram_mb_phase3_attack_rng + LDA !ram_mb_rng : AND !MB_RNG_NORMAL_ATTACK_MASK : XBA : TAX + LDA.l mb_air_rings_rng_table,X : STA !eram_mb_air_rings_rng + LDA.l mb_ground_bomb_rng_table,X : STA !eram_mb_ground_bomb_rng + LDA.l mb_ground_attack_rng_tables_table,X : STA !eram_mb_ground_attack_rng_table + LDA.l mb_close_attack_rng_tables_table,X : STA !eram_mb_close_attack_rng_table + LDA !ram_mb_rng : AND !MB_RNG_BOMB_CROUCH_MASK : XBA : ASL #3 : XBA : TAX + LDA.l mb_try_bomb_crouch_rng_table,X : STA !eram_mb_try_bomb_crouch + LDA.l mb_bomb_crouch_rng_table,X : STA !eram_mb_bomb_crouch + + ; Overwritten logic + LDA #$000A : STA !ENEMY_VAR_4 + RTL +} + +hook_baby_init: +{ +if !FEATURE_PAL + JSL $A9D343 +else ; Overridden logic + JSL $A9D2F6 +endif + + LDA !ram_door_portal_flags : AND !DOOR_PORTAL_MODE_MASK + CMP #$0002 : BNE .vanilla + LDA !ram_door_source : ASL : TAX + LDA portals_left_vanilla_table,X : CMP #$AA38 : BNE .vanilla + + ; Use maprando values + LDA #$0001 : STA !eram_baby_dead_hop_delay + LDA #baby_maprando_hop_initial_velocities : STA !eram_baby_hop_velocity_tables + LDA #$002C : STA !eram_baby_initial_delay + LDA #$01B0 : STA !eram_baby_target_x_pos + LDA #$0020 : STA !eram_baby_after_drain_delay + LDA #$0030 : STA !eram_baby_rising_delay + LDA #$0016 : STA !eram_baby_backing_off + STA !eram_baby_leaving_left + STA !eram_baby_leaving_right + RTL + + .vanilla + LDA #$0040 : STA !eram_baby_dead_hop_delay + LDA #baby_vanilla_hop_initial_velocities : STA !eram_baby_hop_velocity_tables + LDA #$01D0 : STA !eram_baby_initial_delay + LDA #$0248 : STA !eram_baby_target_x_pos + LDA #$0078 : STA !eram_baby_after_drain_delay + LDA #$00C0 : STA !eram_baby_rising_delay + LDA #$0058 : STA !eram_baby_backing_off + STA !eram_baby_leaving_left + LDA #$0100 : STA !eram_baby_leaving_right + RTL +} + +%endfree(AA) + diff --git a/src/fanfare.asm b/src/fanfare.asm index dc479e85..a0861688 100644 --- a/src/fanfare.asm +++ b/src/fanfare.asm @@ -266,7 +266,8 @@ endif hook_message_box_wait: { LDA !sram_fanfare : BNE .fanfareloop - ; shorten message box length + ; shorten message box length if necessary + CPX #$0020 : BMI .nofanfareloop LDX #$0020 .nofanfareloop @@ -294,11 +295,33 @@ if !FEATURE_SD2SNES LDA $4212 : BIT #$01 : BNE .wait_joypad %a16() - LDA $4218 : BEQ .done - CMP !sram_ctrl_load_state : BNE .done - LDA !SRAM_SAVED_STATE : CMP !SAFEWORD : BNE .done - PHB : PHK : PLB - JML load_state + ; Check if any input present + LDA $4218 : ORA $421A : BEQ .done + + ; We need to run the controller shortcut routine, but we can't save here + ; Set game mode to invalid value to signify we should not save + LDA !GAMEMODE : PHA + LDA #$0003 : STA !GAMEMODE + ; We need to update the controller input variables, so remember the original values + LDA !IH_CONTROLLER_PRI : PHA + LDA !IH_CONTROLLER_PRI_NEW : PHA + LDA !IH_CONTROLLER_SEC : PHA + LDA !IH_CONTROLLER_SEC_NEW : PHA + + LDA $4218 : STA !IH_CONTROLLER_PRI : STA !IH_CONTROLLER_PRI_NEW + LDA $421A : STA !IH_CONTROLLER_SEC : STA !IH_CONTROLLER_SEC_NEW + + ; Set overflow and carry flags before calling routine + PHP : SEP #$41 + JSL !CTRL_SHORTCUT_ROUTINE + PLP + + ; Restore controller inputs and gamemode + PLA : STA !IH_CONTROLLER_SEC_NEW + PLA : STA !IH_CONTROLLER_SEC + PLA : STA !IH_CONTROLLER_PRI_NEW + PLA : STA !IH_CONTROLLER_PRI + PLA : STA !GAMEMODE .done endif @@ -336,8 +359,11 @@ hook_end_fanfare: LDA !sram_healthalarm : CMP #$0004 : BNE .done_health_alarm LDA #$0002 : JSL $80914D .done_health_alarm - PLY : PLX ; original logic - PLB : PLP : RTL + ; original logic + PLY : PLX + PLB : PLP + ; initialize water physics in case we just collected gravity or space jump + JML init_physics_ram } %endfree(85) diff --git a/src/flagmenu.asm b/src/flagmenu.asm index 8fa05a2f..11e298e1 100644 --- a/src/flagmenu.asm +++ b/src/flagmenu.asm @@ -827,75 +827,54 @@ eventflags_setmapstations: eventflags_prepare_events_menu: { - LDA $7ED820 : AND #$0038 : STA !ram_cm_zebmask - JSL eventflags_setup_zeb_ram - %setmenubank() - JML action_submenu -} - -eventflags_set_zeb_ram: -{ - LDA $7ED820 : AND #$FFC7 - ORA !ram_cm_zebmask : STA $7ED820 - - ; Intentional fallthrough - LDA !ram_cm_zebmask -} - -eventflags_setup_zeb_ram: -{ - CMP #$0020 : BPL .zeb4 - CMP #$0018 : BPL .zeb3 - CMP #$0010 : BPL .zeb2 - CMP #$0008 : BPL .zeb1 - STA !ram_cm_zeb1 - .clear_zeb2 - STA !ram_cm_zeb2 - .clear_zeb3 - STA !ram_cm_zeb3 - .clear_zeb4 - STA !ram_cm_zeb4 - RTL + ; Zebettites + LDA $7ED820 : AND #$0038 + CMP #$0020 : BEQ .fourZeb + CMP #$0018 : BEQ .threeZeb + CMP #$0010 : BEQ .twoZeb + CMP #$0008 : BEQ .oneZeb + LDA #$0000 : BRA .doneZeb + .fourZeb + LDA #$0004 : BRA .doneZeb + .threeZeb + LDA #$0003 : BRA .doneZeb + .twoZeb + LDA #$0002 : BRA .doneZeb + .oneZeb + LDA #$0001 : BRA .doneZeb + .doneZeb + STA !ram_cm_zebmask - .zeb4 - LDA #$0020 : STA !ram_cm_zeb4 - LDA #$0018 : STA !ram_cm_zeb3 - LDA #$0010 : STA !ram_cm_zeb2 - LDA #$0008 : STA !ram_cm_zeb1 - RTL + ; Metroids + LDA $7ED822 : AND #$000F + BIT #$0008 : BNE .fourMet + BIT #$0004 : BNE .threeMet + BIT #$0002 : BNE .twoMet + BIT #$0001 : BNE .oneMet + LDA #$0000 : BRA .doneMet + .fourMet + LDA #$0004 : BRA .doneMet + .threeMet + LDA #$0003 : BRA .doneMet + .twoMet + LDA #$0002 : BRA .doneMet + .oneMet + LDA #$0001 : BRA .doneMet + .doneMet + STA !ram_cm_metmask - .zeb3 - LDA #$0018 : STA !ram_cm_zeb3 - LDA #$0010 : STA !ram_cm_zeb2 - LDA #$0008 : STA !ram_cm_zeb1 - TDC - BRA .clear_zeb4 - - .zeb2 - LDA #$0010 : STA !ram_cm_zeb2 - LDA #$0008 : STA !ram_cm_zeb1 - TDC - BRA .clear_zeb3 - - .zeb1 - LDA #$0008 : STA !ram_cm_zeb1 - TDC - BRA .clear_zeb2 + %setmenubank() + JML action_submenu } EventsMenu: dw #events_zebesawake + dw #events_speedboostquake dw #events_maridiatubebroken dw #events_shaktool dw #events_chozoacid - dw #events_metroid1 - dw #events_metroid2 - dw #events_metroid3 - dw #events_metroid4 - dw #events_zeb1 - dw #events_zeb2 - dw #events_zeb3 - dw #events_zeb4 + dw #events_metroids + dw #events_zebettites dw #events_mb1glass dw #events_zebesexploding dw #events_animals @@ -911,6 +890,9 @@ EventsMenu: events_zebesawake: %cm_toggle_bit("Zebes Awake", $7ED820, #$0001, #0) +events_speedboostquake: + %cm_toggle_bit("Speedbooster Lavaquake", $7ED822, #$0020, #0) + events_maridiatubebroken: %cm_toggle_bit("Maridia Tube Broken", $7ED820, #$0800, #0) @@ -920,53 +902,47 @@ events_shaktool: events_chozoacid: %cm_toggle_bit("Chozo Lowered Acid", $7ED821, #$0010, #0) -events_metroid1: - %cm_toggle_bit("1st Metroids Cleared", $7ED822, #$0001, #0) - -events_metroid2: - %cm_toggle_bit("2nd Metroids Cleared", $7ED822, #$0002, #0) - -events_metroid3: - %cm_toggle_bit("3rd Metroids Cleared", $7ED822, #$0004, #0) - -events_metroid4: - %cm_toggle_bit("4th Metroids Cleared", $7ED822, #$0008, #0) - -events_zeb1: - %cm_toggle("1st Zebitite Cleared", !ram_cm_zeb1, #$08, #.routine) +events_metroids: + %cm_numfield("Metroid Rooms Cleared", !ram_cm_metmask, 0, 4, 1, 1, #.routine) .routine - LDA !ram_cm_zeb1 : BNE .set - TDC - .set - STA !ram_cm_zebmask - JML eventflags_set_zeb_ram + CMP #$0000 : BEQ .done + CMP #$0001 : BEQ .one + CMP #$0002 : BEQ .two + CMP #$0003 : BEQ .three + + LDA #$000F : BRA .done + .three + LDA #$0007 : BRA .done + .two + LDA #$0003 : BRA .done + .one + LDA #$0001 : BRA .done -events_zeb2: - %cm_toggle("2nd Zebitite Cleared", !ram_cm_zeb2, #$10, #.routine) - .routine - LDA !ram_cm_zeb2 : BNE .set - LDA #$0008 - .set - STA !ram_cm_zebmask - JML eventflags_set_zeb_ram + .done + STA $C1 + LDA $7ED822 : AND #$FFF0 : ORA $C1 : STA $7ED822 + RTL -events_zeb3: - %cm_toggle("3rd Zebitite Cleared", !ram_cm_zeb3, #$18, #.routine) +events_zebettites: + %cm_numfield("Zebs Killed", !ram_cm_zebmask, 0, 4, 1, 1, #.routine) .routine - LDA !ram_cm_zeb3 : BNE .set - LDA #$0010 - .set - STA !ram_cm_zebmask - JML eventflags_set_zeb_ram + CMP #$0000 : BEQ .done + CMP #$0001 : BEQ .one + CMP #$0002 : BEQ .two + CMP #$0003 : BEQ .three + + LDA #$0020 : BRA .done + .three + LDA #$0018 : BRA .done + .two + LDA #$0010 : BRA .done + .one + LDA #$0008 -events_zeb4: - %cm_toggle("4th Zebitite Cleared", !ram_cm_zeb4, #$20, #.routine) - .routine - LDA !ram_cm_zeb4 : BNE .set - LDA #$0018 - .set - STA !ram_cm_zebmask - JML eventflags_set_zeb_ram + .done + STA $C1 + LDA $7ED820 : AND #$FFC7 : ORA $C1 : STA $7ED820 + RTL events_mb1glass: %cm_toggle_bit("MB1 Glass Broken", $7ED820, #$0004, #0) @@ -2633,9 +2609,8 @@ misc_killenemies: misc_forcestand: %cm_jsl("Force Samus to Stand Up", .routine, #0) .routine - JSL $90E2D4 ; bridge to: Release Samus from Draygon %sfxconfirm() - RTL + JML misc_force_stand_routine %endfree(85) diff --git a/src/gamemenu.asm b/src/gamemenu.asm index ba5ac8a7..e9a7a2ab 100644 --- a/src/gamemenu.asm +++ b/src/gamemenu.asm @@ -219,10 +219,17 @@ game_pacifist: %cm_toggle("Deal Zero Damage", !ram_pacifist, #$01, #0) game_debugplms: - %cm_toggle_bit_inverted("Pseudo G-Mode", $7E1C23, #$8000, #0) + %cm_toggle_bit_inverted("Pseudo G-Mode", !ram_cm_gmode, #$8000, #.routine) + .routine + LDA !ram_cm_gmode + STA !PALETTE_FX_ENABLE + STA !PLM_ENABLE + STA !ENEMY_PROJ_ENABLE + STA !ANIMATED_TILES_ENABLE + RTL game_debugprojectiles: - %cm_toggle_bit("Enable Projectiles", $7E198D, #$8000, #0) + %cm_toggle_bit("Enable Projectiles", !ENEMY_PROJ_ENABLE, #$8000, #0) game_debugfixscrolloffsets: %cm_toggle_bit("Fix Scroll Offsets", !ram_fix_scroll_offsets, #$0001, #0) diff --git a/src/gamemode.asm b/src/gamemode.asm index 229f2f05..16d4b56b 100644 --- a/src/gamemode.asm +++ b/src/gamemode.asm @@ -3,7 +3,7 @@ org $82894B ; gamemode_shortcuts will either CLC or SEC ; to control if normal gameplay will happen on this frame - JSL gamemode_start : BCC resume_gameplay + JSL gamemode_start : BCS resume_gameplay BRA end_of_normal_gameplay resume_gameplay: @@ -24,26 +24,112 @@ endif %startfree(85) +if !FEATURE_SD2SNES +gamemode_door_transition: +{ + .checkloadstate + ; We need to run the controller shortcut routine, but we can't save here + ; Set game mode to invalid value to signify we should not save + LDA !GAMEMODE : PHA + LDA #$0003 : STA !GAMEMODE + + ; Set overflow and carry flags before calling routine + PHP : SEP #$41 + JSL !CTRL_SHORTCUT_ROUTINE + PLP -gamemode_start: + ; Restore gamemode + PLA : STA !GAMEMODE + + .checktransition + ; check if door is done scrolling + LDA !DOOR_FINISHED_SCROLLING : BPL .checkloadstate + RTL +} + +gamemode_door_transtion_load_sprites: { - PHB + ; Check for auto-save mid-transition + LDA !ram_auto_save_state : BEQ .check + BMI .auto_save + TDC : STA !ram_auto_save_state + .auto_save + PHP : PHB PHK : PLB + JSL save_state + PLB : PLP + .done + JML $82E4A9 ; return to hijacked code + .check +if !FEATURE_PAL + JML $82E4A9 ; return to hijacked code +else + LDA !IH_CONTROLLER_PRI : CMP #$C0C0 : BNE .done + LDA !AREA_ID : BEQ .done : CMP #$0002 : BEQ .done + PHX : PHP + %ai16() : TDC : TAX : %a8() + .firstLoop + LDA !sram_ctrl_shortcut_selections,X : BEQ .firstNext + %a16() : TXA : ASL : TAX + LDA !sram_ctrl_1_shortcut_inputs,X : CMP #$C0C0 : BEQ .end + TXA : LSR : TAX : %a8() + .firstNext + INX : CPX #$001E : BMI .firstLoop + .secondLoop + LDA !sram_ctrl_additional_selections,X : BEQ .secondNext + %a16() : TXA : ASL : TAX + LDA !sram_ctrl_1_shortcut_inputs,X : CMP #$C0C0 : BEQ .end + TXA : LSR : TAX : %a8() + .secondNext + INX : CPX #$0030 : BMI .secondLoop + %a16() : LDA #custom_intro_init : STA !CINEMATIC_FUNCTION_POINTER + LDA #$001E : STA !GAMEMODE + .end + PLP : PLX + JML $82E4A9 ; return to hijacked code +endif +} +endif - JSR gamemode_shortcuts - .return - %ai16() +gamemode_start: +{ + ; Set overflow and carry flags before calling routine + SEP #$41 + JSL !CTRL_SHORTCUT_ROUTINE PHP - BCS .skip_gameplay + BCC .skip_gameplay + ; Check if we need to reset the fading to pause state + BVS .done_pause + LDA !GAMEMODE : CMP #$000C : BNE .skip_gameplay_done_pause + LDA #$0008 : STA !GAMEMODE + + ; Clear screen fade delay/counter + STZ !SCREEN_FADE_DELAY : STZ !SCREEN_FADE_COUNTER + ; Brightness = $F (max) + LDA !REG_2100_BRIGHTNESS : ORA #$000F : STA !REG_2100_BRIGHTNESS + + .done_pause ; Overwritten logic JSL $8884B9 JSL ih_game_loop_code PLP - PLB + CLV RTL .skip_gameplay + ; Check if we need to reset the fading to pause state + BVS .skip_gameplay_done_pause + LDA !GAMEMODE : CMP #$000C : BNE .skip_gameplay_done_pause + LDA #$0008 : STA !GAMEMODE + + ; Clear screen fade delay/counter + STZ !SCREEN_FADE_DELAY : STZ !SCREEN_FADE_COUNTER + + ; Brightness = $F (max) + LDA !REG_2100_BRIGHTNESS : ORA #$000F : STA !REG_2100_BRIGHTNESS + + .skip_gameplay_done_pause ; Don't load presets or decrement counters if we're in credits LDA !GAMEMODE : CMP #$0027 : BEQ .skip_load @@ -55,7 +141,7 @@ gamemode_start: .skip_load PLP - PLB + CLV RTL .dec_rta @@ -83,470 +169,2003 @@ gamemode_start: BRA .skip_load } -gamemode_shortcuts: +gamemode_main_menu: { - LDA !IH_CONTROLLER_PRI_NEW : BNE .check_shortcuts - ; CLC so we won't skip normal gameplay - CLC : RTS - .check_shortcuts + ; Check if main menu not allowed + LDA !GAMEMODE : CMP #$0003 : BEQ gamemode_placeholder - LDA !IH_CONTROLLER_PRI : AND !sram_ctrl_menu : CMP !sram_ctrl_menu : BNE .skip_menu - AND !IH_CONTROLLER_PRI_NEW : BEQ .skip_menu - JMP .menu - .skip_menu + ; Check for paused states + LDA !ram_slowdown_mode : BPL .openMainMenu + CMP !SLOWDOWN_PAUSED_MAIN_MENU : BNE .paused -if !FEATURE_SD2SNES - LDA !IH_CONTROLLER_PRI : CMP !sram_ctrl_save_state : BNE .skip_save_state - AND !IH_CONTROLLER_PRI_NEW : BEQ .skip_save_state - JMP .save_state - .skip_save_state - - LDA !IH_CONTROLLER_PRI : CMP !sram_ctrl_load_state : BNE .skip_load_state - AND !IH_CONTROLLER_PRI_NEW : BEQ .skip_load_state - JMP .load_state - .skip_load_state - - LDA !IH_CONTROLLER_PRI : CMP !sram_ctrl_auto_save_state : BNE .skip_auto_save_state - AND !IH_CONTROLLER_PRI_NEW : BEQ .skip_auto_save_state - JMP .auto_save_state - .skip_auto_save_state -endif - - LDA !IH_CONTROLLER_PRI : AND !sram_ctrl_load_last_preset : CMP !sram_ctrl_load_last_preset : BNE .skip_load_last_preset - AND !IH_CONTROLLER_PRI_NEW : BEQ .skip_load_last_preset - JMP .load_last_preset - .skip_load_last_preset - - LDA !IH_CONTROLLER_PRI : AND !sram_ctrl_random_preset : CMP !sram_ctrl_random_preset : BNE .skip_random_preset - AND !IH_CONTROLLER_PRI_NEW : BEQ .skip_random_preset - JMP .random_preset - .skip_random_preset - - LDA !IH_CONTROLLER_PRI : AND !sram_ctrl_save_custom_preset : CMP !sram_ctrl_save_custom_preset : BNE .skip_save_custom_preset - AND !IH_CONTROLLER_PRI_NEW : BEQ .skip_save_custom_preset - JMP .save_custom_preset - .skip_save_custom_preset - - LDA !IH_CONTROLLER_PRI : AND !sram_ctrl_load_custom_preset : CMP !sram_ctrl_load_custom_preset : BNE .skip_load_custom_preset - AND !IH_CONTROLLER_PRI_NEW : BEQ .skip_load_custom_preset - JMP .load_custom_preset - .skip_load_custom_preset - - ; Check if any less common shortcuts are configured - LDA !ram_game_mode_extras : BNE .check_less_common_shortcuts - JMP .no_shortcuts - .check_less_common_shortcuts - - LDA !IH_CONTROLLER_PRI : AND !sram_ctrl_inc_custom_preset : CMP !sram_ctrl_inc_custom_preset : BNE .skip_next_preset_slot - AND !IH_CONTROLLER_PRI_NEW : BEQ .skip_next_preset_slot - JMP .next_preset_slot - .skip_next_preset_slot - - LDA !IH_CONTROLLER_PRI : AND !sram_ctrl_dec_custom_preset : CMP !sram_ctrl_dec_custom_preset : BNE .skip_prev_preset_slot - AND !IH_CONTROLLER_PRI_NEW : BEQ .skip_prev_preset_slot - JMP .prev_preset_slot - .skip_prev_preset_slot - - LDA !IH_CONTROLLER_PRI : AND !sram_ctrl_full_equipment : CMP !sram_ctrl_full_equipment : BNE .skip_full_equipment - AND !IH_CONTROLLER_PRI_NEW : BEQ .skip_full_equipment - JMP .full_equipment - .skip_full_equipment - - LDA !IH_CONTROLLER_PRI : AND !sram_ctrl_kill_enemies : CMP !sram_ctrl_kill_enemies : BNE .skip_kill_enemies - AND !IH_CONTROLLER_PRI_NEW : BEQ .skip_kill_enemies - JMP .kill_enemies - .skip_kill_enemies - - LDA !IH_CONTROLLER_PRI : AND !sram_ctrl_reset_segment_timer : CMP !sram_ctrl_reset_segment_timer : BNE .skip_reset_segment_timer - AND !IH_CONTROLLER_PRI_NEW : BEQ .skip_reset_segment_timer - JMP .reset_segment_timer - .skip_reset_segment_timer - - LDA !IH_CONTROLLER_PRI : AND !sram_ctrl_reset_segment_later : CMP !sram_ctrl_reset_segment_later : BNE .skip_reset_segment_later - AND !IH_CONTROLLER_PRI_NEW : BEQ .skip_reset_segment_later - JMP .reset_segment_later - .skip_reset_segment_later - - LDA !IH_CONTROLLER_PRI : AND !sram_ctrl_toggle_tileviewer : CMP !sram_ctrl_toggle_tileviewer : BNE .skip_toggle_tileviewer - AND !IH_CONTROLLER_PRI_NEW : BEQ .skip_toggle_tileviewer - JMP .toggle_tileviewer - .skip_toggle_tileviewer - - LDA !IH_CONTROLLER_PRI : AND !sram_ctrl_reveal_damage : CMP !sram_ctrl_reveal_damage : BNE .skip_reveal_damage - AND !IH_CONTROLLER_PRI_NEW : BEQ .skip_reveal_damage - JMP .reveal_damage - .skip_reveal_damage - - LDA !IH_CONTROLLER_PRI : AND !sram_ctrl_randomize_rng : CMP !sram_ctrl_randomize_rng : BNE .skip_randomize_rng - AND !IH_CONTROLLER_PRI_NEW : BEQ .skip_randomize_rng - JMP .randomize_rng - .skip_randomize_rng - - LDA !IH_CONTROLLER_PRI : AND !sram_ctrl_force_stand : CMP !sram_ctrl_force_stand : BNE .skip_force_stand - AND !IH_CONTROLLER_PRI_NEW : BEQ .skip_force_stand - JMP .force_stand - .skip_force_stand - - LDA !IH_CONTROLLER_PRI : AND !sram_ctrl_update_timers : CMP !sram_ctrl_update_timers : BNE .skip_update_timers - AND !IH_CONTROLLER_PRI_NEW : BEQ .skip_update_timers - JMP .update_timers - .skip_update_timers - - LDA !IH_CONTROLLER_PRI : AND !sram_ctrl_toggle_spin_lock : CMP !sram_ctrl_toggle_spin_lock : BNE .skip_toggle_spin_lock - AND !IH_CONTROLLER_PRI_NEW : BEQ .skip_toggle_spin_lock - JMP .toggle_spin_lock - .skip_toggle_spin_lock - - .no_shortcuts - ; No shortcuts matched, CLC so we won't skip normal gameplay - CLC : RTS + ; Set slowdown mode to paused but allow menu to open + LDA !SLOWDOWN_PAUSED : STA !ram_slowdown_mode + + .openMainMenu + ; Set IRQ vector + LDA !IRQ_CMD : PHA + LDA #$0004 : STA !IRQ_CMD + + ; Enter Main Menu + JSL cm_start + + ; Restore IRQ vector + PLA : STA !IRQ_CMD + BRA .done + + .paused + ; We are paused in the NMI routine, so we cannot open the menu here + ; Set flag so we know to open the menu later + LDA !SLOWDOWN_PAUSED_MAIN_MENU : STA !ram_slowdown_mode + + .done + ; Skip remaining shortcuts + PLA : PEA !CTRL_SHORTCUT_SKIP_REMAINING_PEA_VALUE + + ; Fallthrough to below RTL +} + +gamemode_placeholder: + RTL if !FEATURE_SD2SNES - .save_state -; This if statement is to prevent an assembler error from an unknown method. The one on the call to this -; prevents the button combo from being intercepted by the non-sd2snes rom +gamemode_save_state: +{ + ; Check if save not allowed + LDA !GAMEMODE : CMP #$0003 : BEQ .done if !FEATURE_TINYSTATES ; Disallow tiny states outside of gameplay ; Most other gamemodes will crash on load - LDA !GAMEMODE : CMP #$0020 : BEQ .save ; end of Ceres allowed - CMP #$0007 : BMI .save_state_fail - CMP #$001C : BMI .save - - .save_state_fail - ; CLC to continue normal gameplay - LDA !sram_ctrl_save_state - CLC : JMP skip_pause - + CMP #$0020 : BEQ .save + CMP #$0007 : BMI .done + CMP #$001C : BPL .done .save endif + PHP + PHB JSL save_state - %ai16() - LDA !ram_auto_save_state : BMI .clc - ; SEC to skip normal gameplay for one frame after saving state - SEC : RTS - .clc - ; CLC to continue normal gameplay after auto-saving in a door transition - CLC : RTS - - .load_state - ; check if a saved state exists - LDA !SRAM_SAVED_STATE : CMP !SAFEWORD : BNE .load_state_fail - JSL load_state - ; SEC to skip normal gameplay for one frame after loading state - SEC : RTS - - .load_state_fail - ; CLC to continue normal gameplay - LDA !sram_ctrl_load_state - CLC : JMP skip_pause - - .auto_save_state - LDA #$0001 : STA !ram_auto_save_state - ; CLC to continue normal gameplay after setting savestate flag - LDA !sram_ctrl_auto_save_state - CLC : JMP skip_pause -endif + PLB + PLP - .kill_enemies - JSL kill_enemies - ; CLC to continue normal gameplay after killing enemies - LDA !sram_ctrl_kill_enemies - CLC : JMP skip_pause + ; Skip remaining shortcuts + PLA : PEA !CTRL_SHORTCUT_SKIP_REMAINING_PEA_VALUE - .reset_segment_timer - LDA !sram_frame_counter_mode : BEQ .reset_segment_timer_rta - STZ !IGT_FRAMES : STZ !IGT_SECONDS - STZ !IGT_MINUTES : STZ !IGT_HOURS - .reset_segment_timer_rta - TDC : STA !ram_seg_rt_frames - STA !ram_seg_rt_seconds : STA !ram_seg_rt_minutes - %sfxconfirm() - ; CLC to continue normal gameplay after resetting segment timer - LDA !sram_ctrl_reset_segment_timer - CLC : JMP skip_pause + .done + RTL +} - .reset_segment_later - LDA #$FFFF : STA !ram_reset_segment_later - %sfxconfirm() - ; CLC to continue normal gameplay after setting reset flag - LDA !sram_ctrl_reset_segment_later - CLC : JMP skip_pause +gamemode_load_state: +{ + ; Check if a saved state exists + LDA !SRAM_SAVED_STATE : CMP !SAFEWORD : BNE .not_available - .full_equipment - LDA !SAMUS_HP_MAX : STA !SAMUS_HP - LDA !SAMUS_MISSILES_MAX : CMP !SAMUS_MISSILES : BCC .full_equip_done_missiles - STA !SAMUS_MISSILES - .full_equip_done_missiles - LDA !SAMUS_SUPERS_MAX : CMP !SAMUS_SUPERS : BCC .full_equip_done_supers - STA !SAMUS_SUPERS - .full_equip_done_supers - LDA !SAMUS_PBS_MAX : CMP !SAMUS_PBS : BCC .full_equip_done_pbs - STA !SAMUS_PBS - .full_equip_done_pbs - LDA !SAMUS_RESERVE_MAX : STA !SAMUS_RESERVE_ENERGY - %sfxconfirm() - ; CLC to continue normal gameplay after equipment refill - LDA !sram_ctrl_full_equipment - CLC : JMP skip_pause + ; We will not return from this method, + ; since loading the state includes loading the stack + JML load_state - .toggle_tileviewer - LDA !ram_sprite_feature_flags : BIT !SPRITE_OOB_WATCH : BEQ .turnOnTileViewer - EOR !SPRITE_OOB_WATCH : STA !ram_sprite_feature_flags - ; CLC to continue normal gameplay after disabling OoB Tile Viewer - LDA !sram_ctrl_toggle_tileviewer - CLC : JMP skip_pause + .not_available + RTL +} - .turnOnTileViewer - ORA !SPRITE_OOB_WATCH : STA !ram_sprite_feature_flags - JSL upload_sprite_oob_tiles - ; CLC to continue normal gameplay after enabling OoB Tile Viewer - LDA !sram_ctrl_toggle_tileviewer - CLC : JMP skip_pause +gamemode_auto_save_state: +{ + LDA #$0001 : STA !ram_auto_save_state + RTL +} +endif - .reveal_damage if !FEATURE_VANILLAHUD else - LDA !sram_display_mode : CMP !IH_MODE_COUNTDAMAGE_INDEX : BEQ .unreveal_damage - STA !ram_display_backup - LDA !IH_MODE_COUNTDAMAGE_INDEX : STA !sram_display_mode - ; set ram_HUD_check to some value that cannot match the damage counter - ; conveniently the current value of A will work - STA !ram_HUD_check +gamemode_update_timers: +{ + JML ih_update_hud_early +} endif - %sfxconfirm() - ; CLC to continue normal gameplay after reveal damage - LDA !sram_ctrl_reveal_damage - CLC : JMP skip_pause - - .unreveal_damage - LDA !ram_display_backup : STA !sram_display_mode - %sfxreset() - ; CLC to continue normal gameplay after unreveal damage - LDA !sram_ctrl_reveal_damage - CLC : JMP skip_pause - .load_last_preset +gamemode_reload_preset: +{ ; Choose a random preset if zero - LDA !sram_last_preset : BEQ .random_preset : STA !ram_load_preset - ; SEC to skip normal gameplay for one frame after loading preset - SEC : RTS + LDA !sram_last_preset : BEQ gamemode_random_preset + STA !ram_load_preset + + ; Skip remaining shortcuts + PLA : PEA !CTRL_SHORTCUT_SKIP_REMAINING_PEA_VALUE + RTL +} - .random_preset +gamemode_random_preset: +{ JSL LoadRandomPreset - ; SEC to skip normal gameplay for one frame after loading preset - SEC : RTS - .save_custom_preset + ; Skip remaining shortcuts + PLA : PEA !CTRL_SHORTCUT_SKIP_REMAINING_PEA_VALUE + RTL +} + +gamemode_save_custom_preset: +{ ; check gamestate first - LDA !GAMEMODE : CMP #$0008 : BEQ .save_custom_safe - CMP #$000C : BMI .save_custom_not_safe - CMP #$0013 : BPL .save_custom_not_safe + LDA !GAMEMODE : CMP #$0008 : BEQ .safe + CMP #$000C : BMI .not_safe + CMP #$0013 : BPL .not_safe - .save_custom_safe + .safe JSL custom_preset_save - ; CLC to continue normal gameplay after saving preset %sfxconfirm() - LDA !sram_ctrl_save_custom_preset - CLC : JMP skip_pause + RTL + + .not_safe + %sfxfail() + RTL +} - .load_custom_preset +gamemode_load_custom_preset: +{ ; check if slot is populated first LDA !sram_custom_preset_slot %presetslotsize() - LDA !PRESET_SLOTS,X : CMP !SAFEWORD : BEQ .load_safe - - %sfxfail() - ; CLC to continue normal gameplay after failing to load preset - LDA !sram_ctrl_load_custom_preset - CLC : JMP skip_pause - - .save_custom_not_safe + LDA !PRESET_SLOTS,X : CMP !SAFEWORD : BEQ .safe %sfxfail() - ; CLC to continue normal gameplay after failing to save preset - LDA !sram_ctrl_save_custom_preset - CLC : JMP skip_pause + RTL - .load_safe + .safe STA !ram_custom_preset - JSL preset_load - ; SEC to skip normal gameplay for one frame after loading preset - SEC : RTS + JML preset_load +} - .next_preset_slot - LDA !sram_custom_preset_slot : CMP !TOTAL_PRESET_SLOTS : BNE .increment_slot +gamemode_increment_custom_preset: +{ + LDA !sram_custom_preset_slot : CMP !TOTAL_PRESET_SLOTS : BNE .increment LDA #$FFFF - .increment_slot + .increment INC : STA !sram_custom_preset_slot if !FEATURE_VANILLAHUD else ASL : TAX : LDA.l NumberGFXTable,X : STA !HUD_TILEMAP+$7C endif - LDA !sram_last_preset : BMI .done_preset_slot + LDA !sram_last_preset : BMI .done TDC : STA !sram_last_preset + .done %sfxnumber() - ; CLC to continue normal gameplay after incrementing preset slot - LDA !sram_ctrl_inc_custom_preset - CLC : JMP skip_pause + RTL +} - .prev_preset_slot - LDA !sram_custom_preset_slot : BNE .decrement_slot +gamemode_decrement_custom_preset: +{ + LDA !sram_custom_preset_slot : BNE .decrement LDA !TOTAL_PRESET_SLOTS+1 - .decrement_slot + .decrement DEC : STA !sram_custom_preset_slot if !FEATURE_VANILLAHUD else ASL : TAX : LDA.l NumberGFXTable,X : STA !HUD_TILEMAP+$7C endif - LDA !sram_last_preset : BMI .done_preset_slot + LDA !sram_last_preset : BMI .done TDC : STA !sram_last_preset - .done_preset_slot + .done %sfxnumber() - ; CLC to continue normal gameplay after decrementing preset slot - LDA !sram_ctrl_dec_custom_preset - CLC : JMP skip_pause + RTL +} + +gamemode_reset_segment_timer: +{ + LDA !sram_frame_counter_mode : BEQ .rta + STZ !IGT_FRAMES : STZ !IGT_SECONDS + STZ !IGT_MINUTES : STZ !IGT_HOURS + .rta + TDC : STA !ram_seg_rt_frames + STA !ram_seg_rt_seconds : STA !ram_seg_rt_minutes + %sfxconfirm() +if !FEATURE_VANILLAHUD + RTL +else + JML ih_update_hud_early +endif +} + +gamemode_reset_segment_later: +{ + LDA #$FFFF : STA !ram_reset_segment_later + %sfxconfirm() + RTL +} + +gamemode_full_equipment: +{ + LDA !SAMUS_HP_MAX : STA !SAMUS_HP + LDA !SAMUS_MISSILES_MAX : CMP !SAMUS_MISSILES : BCC .done_missiles + STA !SAMUS_MISSILES + .done_missiles + LDA !SAMUS_SUPERS_MAX : CMP !SAMUS_SUPERS : BCC .done_supers + STA !SAMUS_SUPERS + .done_supers + LDA !SAMUS_PBS_MAX : CMP !SAMUS_PBS : BCC .done_pbs + STA !SAMUS_PBS + .done_pbs + LDA !SAMUS_RESERVE_MAX : STA !SAMUS_RESERVE_ENERGY + %sfxconfirm() + RTL +} + +gamemode_kill_enemies: +{ + JML kill_enemies +} + +gamemode_toggle_oob_tile_viewer: +{ + LDA !ram_sprite_feature_flags : BIT !SPRITE_OOB_WATCH : BEQ .turnOn + EOR !SPRITE_OOB_WATCH : STA !ram_sprite_feature_flags + RTL - .randomize_rng + .turnOn + ORA !SPRITE_OOB_WATCH : STA !ram_sprite_feature_flags + JML upload_sprite_oob_tiles +} + +gamemode_randomize_rng: +{ JSL MenuRNG2 AND #$00FF : STA !FRAME_COUNTER_8BIT ; little extra for Phantoon JSL MenuRNG : STA !CACHED_RANDOM_NUMBER %sfxbeep() - ; CLC to continue normal gameplay after reseeding RNG - LDA !sram_ctrl_randomize_rng - CLC : JMP skip_pause - - .force_stand - JSL $90E2D4 ; Release Samus from Draygon - %sfxconfirm() - ; CLC to continue normal gameplay after forced stand - LDA !sram_ctrl_force_stand - CLC : JMP skip_pause + RTL +} - .update_timers if !FEATURE_VANILLAHUD else - JSL ih_update_hud_early +gamemode_reveal_damage: +{ + LDA !sram_display_mode : CMP !IH_MODE_ROOMSTRAT_INDEX : BEQ .checkRoomStrat + CMP !IH_MODE_COUNTDAMAGE_INDEX : BNE .reveal + ; revert to prior mode + LDA !ram_display_backup : STA !sram_display_mode + %sfxreset() + JML init_print_segment_timer + + .revealRoomStrat + LDA !sram_display_mode + .reveal + STA !ram_display_backup + LDA !IH_MODE_COUNTDAMAGE_INDEX : STA !sram_display_mode + ; set ram_HUD_check to some value that cannot match the damage counter + ; conveniently the current value of A will work + STA !ram_HUD_check + %sfxconfirm() + JML init_print_segment_timer + + .checkRoomStrat + LDA !sram_room_strat : BNE .revealRoomStrat + ; handle Super HUD case + LDA !sram_superhud_bottom : CMP !IH_SUPERHUD_COUNTDAMAGE_BOTTOM_INDEX : BNE .revealSuperHUD + ; revert to prior Super HUD mode + LDA !ram_display_backup : STA !sram_superhud_bottom + %sfxreset() + JML init_print_segment_timer + + .revealSuperHUD + STA !ram_display_backup + LDA !IH_SUPERHUD_COUNTDAMAGE_BOTTOM_INDEX : STA !sram_superhud_bottom + ; set ram_HUD_check to some value that cannot match the damage counter + ; conveniently the current value of A will work + STA !ram_HUD_check + %sfxconfirm() + JML init_print_segment_timer +} endif - ; CLC to continue normal gameplay after updating HUD timers - LDA !sram_ctrl_update_timers - CLC : JMP skip_pause - .toggle_spin_lock - LDA !sram_spin_lock : BEQ .turn_on_spin_lock +gamemode_force_stand: +{ + %sfxconfirm() + JML $90E2D4 ; Release Samus from Draygon +} + +gamemode_toggle_spin_lock: +{ + LDA !sram_spin_lock : BEQ .turnOn + TDC : STA !sram_spin_lock + RTL + + .turnOn + LDA #$0001 : STA !sram_spin_lock + RTL +} + +gamemode_pause: +{ + LDA !ram_slowdown_mode : CMP !SLOWDOWN_PAUSED : BEQ .frameAdvance + TDC : STA !ram_slowdown_frames + DEC : STA !ram_slowdown_mode + RTL + + .frameAdvance + LDA #$8000 : STA !ram_slowdown_mode + RTL +} + +gamemode_unpause: +{ + TDC : STA !ram_slowdown_mode : STA !ram_slowdown_frames + RTL +} + +gamemode_slowdown: +{ + LDA !ram_slowdown_mode : BMI .done + CMP #$0078 : BPL .done + INC : STA !ram_slowdown_mode + LDA !ram_slowdown_frames : INC : STA !ram_slowdown_frames + .done + RTL +} + +gamemode_speedup: +{ + LDA !ram_slowdown_mode : BEQ .done : BMI .done + DEC : STA !ram_slowdown_mode + .done + RTL +} + +if !FEATURE_VANILLAHUD +else +gamemode_increment_display_mode: +{ + LDA !sram_display_mode : INC + CMP !IH_MODE_COUNT : BNE .set TDC - BRA .set_spin_lock - .turn_on_spin_lock - TDC : INC - .set_spin_lock - STA !sram_spin_lock - ; CLC to continue normal gameplay after toggling spin lock - LDA !sram_ctrl_toggle_spin_lock - CLC : JMP skip_pause - - .menu - ; Set IRQ vector - LDA !IRQ_CMD : PHA - LDA #$0004 : STA !IRQ_CMD + .set + STA !sram_display_mode + JML ih_update_status +} - LDA !sram_ctrl_menu - JSR skip_pause +gamemode_decrement_display_mode: +{ + LDA !sram_display_mode : DEC + CMP #$FFFF : BNE .set + LDA !IH_MODE_COUNT-1 + .set + STA !sram_display_mode + JML ih_update_status +} - ; Enter MainMenu - JSL cm_start +gamemode_increment_room_strat: +{ + LDA !sram_room_strat : INC + CMP !IH_ROOM_STRAT_COUNT : BNE .set + TDC + .set + STA !sram_room_strat + ; enable ROOM STRAT mode + LDA !IH_MODE_ROOMSTRAT_INDEX : STA !sram_display_mode + JML ih_update_status +} - ; Restore IRQ vector - PLA : STA !IRQ_CMD +gamemode_decrement_room_strat: +{ + LDA !sram_room_strat : DEC + CMP #$FFFF : BNE .set + LDA !IH_ROOM_STRAT_COUNT-1 + .set + STA !sram_room_strat + ; enable ROOM STRAT mode + LDA !IH_MODE_ROOMSTRAT_INDEX : STA !sram_display_mode + JML ih_update_status +} - ; SEC to skip normal gameplay for one frame after handling the menu - SEC : RTS +gamemode_increment_super_hud: +{ + LDA !sram_superhud_bottom : INC + CMP !IH_SUPERHUD_BOTTOM_COUNT : BNE .set + TDC + .set + STA !sram_superhud_bottom + ; enable Super HUD + LDA !IH_MODE_ROOMSTRAT_INDEX : STA !sram_display_mode + TDC : STA !sram_room_strat + JML ih_update_status } -; If the current shortcut (register A) contains start, -; and the current game mode is $C (fading out to pause), set it to $8 (normal), -; so that shortcuts involving the start button don't trigger accidental pauses. -; Called after handling most controller shortcuts, except save/load state -; (because the user might want to practice gravity jumps or something) -; and load preset (because presets reset the game mode anyway). -skip_pause: +gamemode_decrement_super_hud: { - PHP ; preserve carry - BIT !IH_INPUT_START : BEQ .done - LDA !GAMEMODE : CMP #$000C : BNE .done - LDA #$0008 : STA !GAMEMODE + LDA !sram_superhud_bottom : DEC + CMP #$FFFF : BNE .set + LDA !IH_SUPERHUD_BOTTOM_COUNT-1 + .set + STA !sram_superhud_bottom + ; enable Super HUD + LDA !IH_MODE_ROOMSTRAT_INDEX : STA !sram_display_mode + TDC : STA !sram_room_strat + JML ih_update_status +} +endif - ; clear screen fade delay/counter - STZ !SCREEN_FADE_DELAY : STZ !SCREEN_FADE_COUNTER +gamemode_soft_reset: +{ + STZ !DISABLE_SOUNDS + JML $808462 +} - ; Brightness = $F (max) - LDA !REG_2100_BRIGHTNESS : ORA #$000F : STA !REG_2100_BRIGHTNESS +if !FEATURE_DEV +gamemode_dev_shortcut: +{ + ; Could put anything here for development purposes + BRK +} +endif - .done - PLP +; Write a customized routine based on ctrl shortcut selections +!GAMEMODE_CTRL_SHORTCUT_COUNT = #$0021 +cm_write_ctrl_routine: +{ + ; No bounds check on X is done as we shouldn't exceed our buffer. + ; In fact, we are using the end of the buffer for temporary variables + ; and a table to track which shortcuts we still need to write. + PHB : PEA $7070 : PLB : PLB + TDC : TAX : TAY : STA !CTRL_SHORTCUT_TYPE + STA !CTRL_SHORTCUT_PRI_TO_SEC_DUAL_JUMP : STA !CTRL_SHORTCUT_SEC_TO_DUAL_JUMP + + ; Initialize category indices to 48 indicating no shortcut found. + LDA #$0030 : STA !CTRL_SHORTCUT_TABLE_DUAL_INDEX + STA !CTRL_SHORTCUT_TABLE_SEC_INDEX : STA !CTRL_SHORTCUT_TABLE_PRI_INDEX + %a8() + + ; As we check shortcuts, we need to remember if gameplay should be skipped, + ; and we need to remember if Start was used in an exact match shortcut. + ; Use carry flag for gameplay (initially set, clear if gameplay skipped). + ; Use overflow flag for start (initially set, clear if pause should be cancelled). + ; The flags are already set prior to entering routine, so we just need to + ; push flags to the stack, so that shortcut routines can pull-modify-push. + + ; PHP (skipping first INX, remember it should be #$0001 when we resume writing) + LDA #$08 : STA !CTRL_SHORTCUT_ROUTINE,X + + ; Look for first shortcut of each category. + ; This time only we can directly check shortcut types since + ; we haven't written any shortcuts yet so we know written table is empty. + ; Also this time only, fully validate selections. + .initialFirstLoop + LDA.w !sram_ctrl_shortcut_selections,X : BEQ .initialFirstInvalid + STA !CTRL_SHORTCUT_TABLE,X : AND.b !CTRL_SHORTCUT_TYPE_MASK + BEQ .initialFirstInvalid : CMP.b !GAMEMODE_CTRL_SHORTCUT_COUNT : BPL .initialFirstInvalid +if !FEATURE_VANILLAHUD + CMP #$1F : BPL .initialFirstCheckInputs + CMP #$19 : BPL .initialFirstInvalid + CMP #$12 : BEQ .initialFirstInvalid + CMP #$05 : BEQ .initialFirstInvalid +else + CMP #$05 +endif + BPL .initialFirstCheckInputs + CMP #$01 : BEQ .initialFirstCheckInputs +if !FEATURE_SD2SNES + LDA !ram_sram_detection : BEQ .initialFirstCheckInputs +endif + .initialFirstInvalid + TDC : STA !CTRL_SHORTCUT_TABLE,X + BRA .initialFirstContinue + .initialFirstCheckInputs + TXA : ASL : TAX + LDY.w !sram_ctrl_1_shortcut_inputs,X : BEQ .initialFirstNoPri + LDY.w !sram_ctrl_2_shortcut_inputs,X : BEQ .initialFirstPri + TXA : LSR : TAX + LDA !CTRL_SHORTCUT_TABLE_DUAL_INDEX : CMP #$30 : BNE .initialFirstContinue + TXA : STA !CTRL_SHORTCUT_TABLE_DUAL_INDEX + BRA .initialFirstContinue + .initialFirstNoPri + LDY.w !sram_ctrl_2_shortcut_inputs,X : BNE .initialFirstSec + TXA : LSR : TAX + BRA .initialFirstInvalid + .initialFirstPri + TXA : LSR : TAX + LDA !CTRL_SHORTCUT_TABLE_PRI_INDEX : CMP #$30 : BNE .initialFirstContinue + TXA : STA !CTRL_SHORTCUT_TABLE_PRI_INDEX + BRA .initialFirstContinue + .initialFirstSec + TXA : LSR : TAX + LDA !CTRL_SHORTCUT_TABLE_SEC_INDEX : CMP #$30 : BNE .initialFirstContinue + TXA : STA !CTRL_SHORTCUT_TABLE_SEC_INDEX + .initialFirstContinue + INX : CPX #$001E : BEQ .initialSecondLoop + JMP .initialFirstLoop + + .initialSecondLoop + LDA.w !sram_ctrl_additional_selections,X : BEQ .initialSecondInvalid + STA !CTRL_SHORTCUT_TABLE,X : AND.b !CTRL_SHORTCUT_TYPE_MASK + BEQ .initialSecondInvalid : CMP.b !GAMEMODE_CTRL_SHORTCUT_COUNT : BPL .initialSecondInvalid +if !FEATURE_VANILLAHUD + CMP #$19 : BPL .initialSecondInvalid + CMP #$12 : BEQ .initialSecondInvalid + CMP #$05 : BEQ .initialSecondInvalid +else + CMP #$05 +endif + BPL .initialSecondCheckInputs + CMP #$01 : BEQ .initialSecondCheckInputs +if !FEATURE_SD2SNES + LDA !ram_sram_detection : BEQ .initialSecondCheckInputs +endif + .initialSecondInvalid + TDC : STA !CTRL_SHORTCUT_TABLE,X + BRA .initialSecondContinue + .initialSecondCheckInputs + TXA : ASL : TAX + LDY.w !sram_ctrl_1_shortcut_inputs,X : BEQ .initialSecondNoPri + LDY.w !sram_ctrl_2_shortcut_inputs,X : BEQ .initialSecondPri + TXA : LSR : TAX + LDA !CTRL_SHORTCUT_TABLE_DUAL_INDEX : CMP #$30 : BNE .initialSecondContinue + TXA : STA !CTRL_SHORTCUT_TABLE_DUAL_INDEX + BRA .initialSecondContinue + .initialSecondNoPri + LDY.w !sram_ctrl_2_shortcut_inputs,X : BNE .initialSecondSec + TXA : LSR : TAX + BRA .initialSecondInvalid + .initialSecondPri + TXA : LSR : TAX + LDA !CTRL_SHORTCUT_TABLE_PRI_INDEX : CMP #$30 : BNE .initialSecondContinue + TXA : STA !CTRL_SHORTCUT_TABLE_PRI_INDEX + BRA .initialSecondContinue + .initialSecondSec + TXA : LSR : TAX + LDA !CTRL_SHORTCUT_TABLE_SEC_INDEX : CMP #$30 : BNE .initialSecondContinue + TXA : STA !CTRL_SHORTCUT_TABLE_SEC_INDEX + .initialSecondContinue + INX : CPX #$0030 : BEQ .beginWriteShortcuts + JMP .initialSecondLoop + + .beginWriteShortcuts + ; Restore X to resume writing + LDX #$0001 + + ; Check if we have pri only shortcuts to write + LDA !CTRL_SHORTCUT_TABLE_PRI_INDEX : CMP #$30 : BPL .noPriShortcuts + + ; Write initial check for new controller 1 input + ; LDA $8F + LDA #$A5 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$8F : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; Branch over either two or nine bytes + ; BNE + LDA #$D0 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + + ; Check if we have sec only or dual shortcuts to write + LDA !CTRL_SHORTCUT_TABLE_SEC_INDEX : CMP #$30 : BMI .priToSecDualJump + LDA !CTRL_SHORTCUT_TABLE_DUAL_INDEX : CMP #$30 : BMI .priToSecDualJump + + ; No additional categories to check + ; Branch over two bytes (PLP : RTL) + LDA #$02 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$28 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$6B : STA !CTRL_SHORTCUT_ROUTINE,X : INX + JMP .priWriteShortcuts + + .priToSecDualJump + ; Branch over nine bytes + LDA #$09 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; Write initial check for new controller 2 input + ; LDA $91 + LDA #$A5 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$91 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; Branch over two bytes (PLP : RTL) + ; BNE $02 + LDA #$D0 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$02 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; PLP : RTL + LDA #$28 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$6B : STA !CTRL_SHORTCUT_ROUTINE,X : INX + + ; JMP + LDA #$4C : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; We don't yet know where to jump to. + ; Save this position and we'll write it later. + ; We know X is an 8-bit value at this point. + TXA : STA !CTRL_SHORTCUT_PRI_TO_SEC_DUAL_JUMP : INX #2 + JMP .priWriteShortcuts + + .noPriShortcuts + ; Check if we have sec only shortcuts to write + LDA !CTRL_SHORTCUT_TABLE_SEC_INDEX : CMP #$30 : BPL .onlyDualShortcuts + + ; Write initial check for new controller 2 input + ; LDA $91 + LDA #$A5 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$91 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; Branch over either two or nine bytes + ; BNE + LDA #$D0 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + + ; Check if we have dual shortcuts to write + LDA !CTRL_SHORTCUT_TABLE_DUAL_INDEX : CMP #$30 : BMI .secToDualJump + + ; No additional categories to check + ; Branch over two bytes (PLP : RTL) + LDA #$02 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$28 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$6B : STA !CTRL_SHORTCUT_ROUTINE,X : INX + JMP .secWriteShortcuts + + .onlyDualShortcuts + ; Check if we have dual only shortcuts to write + LDA !CTRL_SHORTCUT_TABLE_SEC_INDEX : CMP #$30 : BMI .onlyDualChecks + JMP .doneWriteShortcuts + + .secToDualJump + ; Branch over nine bytes + LDA #$09 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; Write initial check for new controller 1 input + ; LDA $8F + LDA #$A5 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$8F : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; Branch over two bytes (PLP : RTL) + ; BNE $02 + LDA #$D0 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$02 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; PLP : RTL + LDA #$28 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$6B : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; JMP + LDA #$4C : STA !CTRL_SHORTCUT_ROUTINE,X : INX + + ; We don't yet know where to jump to. + ; Save this position and we'll write it later. + ; We know X is an 8-bit value at this point. + TXA : STA !CTRL_SHORTCUT_SEC_TO_DUAL_JUMP : INX #2 + ; JMP + LDA #$4C : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; We don't yet know where to jump to. + ; Save this position and we'll write it later. + ; Since we may have written several primary shortcuts first, + ; we need to copy the full 16-bits from X. + %a16() : TXA : STA !CTRL_SHORTCUT_SEC_TO_DUAL_JUMP : %a8() : INX #2 + JMP .secWriteShortcuts + + .onlyDualChecks + ; Write dual only check for both controller inputs + ; LDA $8F + LDA #$A5 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$8F : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; ORA $91 + LDA #$05 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$91 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; Branch over two bytes (PLP : RTL) + ; BNE $02 + LDA #$D0 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$02 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + + ; No additional categories to check + ; PLP and RTL + LDA #$28 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$6B : STA !CTRL_SHORTCUT_ROUTINE,X : INX + JMP .dualWriteShortcuts + + .doneWriteShortcuts + ; Closing PLP and RTL (skipping final INX) + LDA #$28 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$6B : STA !CTRL_SHORTCUT_ROUTINE,X + + ; Write the skip remaining routine (PLP : RTL) + LDA #$28 : STA !CTRL_SHORTCUT_SKIP_REMAINING_PEA+1 + LDA #$6B : STA !CTRL_SHORTCUT_SKIP_REMAINING_PEA+2 + + %a16() + PLB + RTL + + .priWriteShortcuts + ; Populate variables for current shortcut + %a16() : LDA !CTRL_SHORTCUT_TABLE_PRI_INDEX + PHX : TAX : ASL : TAY + LDA.w !sram_ctrl_1_shortcut_inputs,Y : STA !CTRL_SHORTCUT_PRI + %a8() : LDA !CTRL_SHORTCUT_TABLE,X : STA !CTRL_SHORTCUT_TYPE + + ; Check for special case (single bit non exact match) + BMI .priWriteNotSpecial + %a16() : LDA !CTRL_SHORTCUT_PRI : DEC + AND !CTRL_SHORTCUT_PRI : BNE .priWriteNotSpecial + + ; Scan for other single bit non exact matches with same type, + ; and also for next pri only shortcut. + ; Don't forget to clear ourselves from the table and reset category index. + %a8() : LDA #$30 : STA !CTRL_SHORTCUT_TABLE_PRI_INDEX + TDC : STA !CTRL_SHORTCUT_TABLE,X + JMP .priWriteSpecialLoop + + .priWriteNotSpecial + ; Scan for duplicates, and also for next pri only shortcut. + ; Don't forget to clear ourselves from the table and reset category index. + %a8() : LDA #$30 : STA !CTRL_SHORTCUT_TABLE_PRI_INDEX + TDC : STA !CTRL_SHORTCUT_TABLE,X + .priWriteNormalLoop + INX : CPX #$0030 : BPL .priWriteNormal + INY #2 : LDA !CTRL_SHORTCUT_TABLE,X : BEQ .priWriteNormalLoop + CMP !CTRL_SHORTCUT_TYPE : BNE .priWriteNormalCheckPri + %a16() : LDA.w !sram_ctrl_2_shortcut_inputs,Y : %a8() : BNE .priWriteNormalLoop + %a16() : LDA.w !sram_ctrl_1_shortcut_inputs,Y + CMP !CTRL_SHORTCUT_PRI : %a8() : BNE .priWriteNormalCheckPri + TDC : STA !CTRL_SHORTCUT_TABLE,X + BRA .priWriteNormalLoop + .priWriteNormalCheckPri + LDA !CTRL_SHORTCUT_TABLE_PRI_INDEX : CMP #$30 : BMI .priWriteNormalLoop + %a16() : LDA.w !sram_ctrl_2_shortcut_inputs,Y : %a8() : BNE .priWriteNormalLoop + TXA : STA !CTRL_SHORTCUT_TABLE_PRI_INDEX + BRA .priWriteNormalLoop + + .priWriteNormal + PLX + ; LDA $8B + LDA #$A5 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$8B : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; Check if this is exact match + LDA !CTRL_SHORTCUT_TYPE : BMI .priWriteMatch + ; AND !CTRL_SHORTCUT_PRI + LDA #$29 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA !CTRL_SHORTCUT_PRI : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA !CTRL_SHORTCUT_PRI+1 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + .priWriteMatch + ; CMP !CTRL_SHORTCUT_PRI + LDA #$C9 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA !CTRL_SHORTCUT_PRI : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA !CTRL_SHORTCUT_PRI+1 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; BNE (value will be written later so do an extra INX) + LDA #$D0 : STA !CTRL_SHORTCUT_ROUTINE,X : INX #2 + ; AND $8F + LDA #$25 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$8F : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; BEQ + LDA #$F0 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + + ; Determine how much to branch by + PHX : TDC : LDA !CTRL_SHORTCUT_TYPE : AND.b !CTRL_SHORTCUT_TYPE_MASK : TAX + LDA.l ctrl_shortcut_jsl_word_lsb_table,X : STA !CTRL_SHORTCUT_JSL_WORD_LSB + LDA.l ctrl_shortcut_jsl_word_msb_table,X : STA !CTRL_SHORTCUT_JSL_WORD_MSB + LDA.l ctrl_shortcut_cancel_gameplay_table,X : BNE .priWriteMatchClc + LDA !CTRL_SHORTCUT_PRI+1 : BIT #$10 : BNE .priWriteMatchClv + ; Simple JSL case, so branch by four, earlier branch by eight + PLX : LDA #$08 : STA !CTRL_SHORTCUT_ROUTINE-$4,X + LDA #$04 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + JSR .writeJsl + JMP .nextPriWrite + + .priWriteMatchClc + LDA !CTRL_SHORTCUT_PRI+1 : BIT #$10 : BNE .priWriteMatchClcClv + ; PLP : CLC : PHP followed by JSL, so branch by seven, earlier branch by eleven + PLX : LDA #$0B : STA !CTRL_SHORTCUT_ROUTINE-$4,X + LDA #$07 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + JSR .writeClcJsl + JMP .nextPriWrite + + .priWriteMatchClv + ; PLP : CLV : PHP followed by JSL, so branch by seven, earlier branch by eleven + PLX : LDA #$0B : STA !CTRL_SHORTCUT_ROUTINE-$4,X + LDA #$07 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + JSR .writeClvJsl + JMP .nextPriWrite + + .priWriteMatchClcClv + ; PLP : REP $41 : PHP followed by JSL, so branch by eight, earlier branch by twelve + PLX : LDA #$0C : STA !CTRL_SHORTCUT_ROUTINE-$4,X + LDA #$08 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + JSR .writeClcClvJsl + JMP .nextPriWrite + + .priWriteSpecialLoop + INX : CPX #$0030 : BPL .priWriteSpecial + INY #2 : LDA !CTRL_SHORTCUT_TABLE,X : BEQ .priWriteSpecialLoop + CMP !CTRL_SHORTCUT_TYPE : BNE .priWriteSpecialCheckPri + %a16() : LDA.w !sram_ctrl_2_shortcut_inputs,Y : %a8() : BNE .priWriteSpecialLoop + %a16() : LDA.w !sram_ctrl_1_shortcut_inputs,Y + DEC : AND.w !sram_ctrl_1_shortcut_inputs,Y : %a8() : BNE .priWriteSpecialCheckPri + %a16() : LDA.w !sram_ctrl_1_shortcut_inputs,Y + ORA !CTRL_SHORTCUT_PRI : STA !CTRL_SHORTCUT_PRI + %a8() : TDC : STA !CTRL_SHORTCUT_TABLE,X + BRA .priWriteSpecialLoop + .priWriteSpecialCheckPri + LDA !CTRL_SHORTCUT_TABLE_PRI_INDEX : CMP #$30 : BMI .priWriteSpecialLoop + %a16() : LDA.w !sram_ctrl_2_shortcut_inputs,Y : %a8() : BNE .priWriteSpecialLoop + TXA : STA !CTRL_SHORTCUT_TABLE_PRI_INDEX + BRA .priWriteSpecialLoop + + .priWriteSpecial + PLX + ; LDA $8F + LDA #$A5 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$8F : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; BIT !CTRL_SHORTCUT_PRI + LDA #$89 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA !CTRL_SHORTCUT_PRI : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA !CTRL_SHORTCUT_PRI+1 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; BEQ + LDA #$F0 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + + ; Determine how much to branch by + PHX : TDC : LDA !CTRL_SHORTCUT_TYPE : AND.b !CTRL_SHORTCUT_TYPE_MASK : TAX + LDA.l ctrl_shortcut_jsl_word_lsb_table,X : STA !CTRL_SHORTCUT_JSL_WORD_LSB + LDA.l ctrl_shortcut_jsl_word_msb_table,X : STA !CTRL_SHORTCUT_JSL_WORD_MSB + LDA.l ctrl_shortcut_cancel_gameplay_table,X : BNE .priWriteSpecialClc + LDA !CTRL_SHORTCUT_PRI+1 : BIT #$10 : BNE .priWriteSpecialClv + ; Simple JSL case, so branch by four + PLX : LDA #$04 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + JSR .writeJsl + BRA .nextPriWrite + + .priWriteSpecialClc + LDA !CTRL_SHORTCUT_PRI+1 : BIT #$10 : BNE .priWriteSpecialClcClv + ; PLP : CLC : PHP followed by JSL, so branch by seven + PLX : LDA #$07 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + JSR .writeClcJsl + BRA .nextPriWrite + + .priWriteSpecialClv + ; PLP : CLV : PHP followed by JSL, so branch by seven + PLX : LDA #$07 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + JSR .writeClvJsl + BRA .nextPriWrite + + .priWriteSpecialClcClv + ; PLP : REP $41 : PHP followed by JSL, so branch by eight + PLX : LDA #$08 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + JSR .writeClcClvJsl + + .nextPriWrite + LDA !CTRL_SHORTCUT_TABLE_PRI_INDEX : CMP #$30 : BPL .donePriWrite + JMP .priWriteShortcuts + + .donePriNoSec + ; Check if we have dual shortcuts to write + LDA !CTRL_SHORTCUT_TABLE_DUAL_INDEX : CMP #$30 : BPL .donePriNoSecNoDual + + ; Write check for any controller 2 input + ; LDA $8D + LDA #$A5 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$8D : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; Branch over two bytes (PLP : RTL) + ; BNE $02 + LDA #$D0 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$02 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; PLP : RTL + LDA #$28 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$6B : STA !CTRL_SHORTCUT_ROUTINE,X : INX + + ; Write the jump location we skipped over earlier + %a16() : TXY : LDA !CTRL_SHORTCUT_PRI_TO_SEC_DUAL_JUMP : TAX + TYA : CLC : ADC.w #!CTRL_SHORTCUT_ROUTINE : STA !CTRL_SHORTCUT_ROUTINE,X + TYX : %a8() + JMP .dualWriteShortcuts + + .donePriNoSecNoDual + JMP .doneWriteShortcuts + + .donePriWrite + ; Check if we have sec only shortcuts to write + LDA !CTRL_SHORTCUT_TABLE_SEC_INDEX : CMP #$30 : BPL .donePriNoSec + + ; Write check for new controller 2 input + ; LDA $91 + LDA #$A5 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$91 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; Branch over either two or nine bytes + ; BNE + LDA #$D0 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + + ; Check if we have dual shortcuts to write + LDA !CTRL_SHORTCUT_TABLE_DUAL_INDEX : CMP #$30 : BMI .donePriJumpToDual + + ; No additional categories to check + ; Branch over two bytes (PLP : RTL) + LDA #$02 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$28 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$6B : STA !CTRL_SHORTCUT_ROUTINE,X : INX + + ; Write the jump location we skipped over earlier + %a16() : TXY : LDA !CTRL_SHORTCUT_PRI_TO_SEC_DUAL_JUMP : TAX + TYA : CLC : ADC.w #!CTRL_SHORTCUT_ROUTINE : STA !CTRL_SHORTCUT_ROUTINE,X + TYX : %a8() + JMP .secWriteShortcuts + + .donePriJumpToDual + ; Branch over nine bytes + LDA #$09 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; Write check for any controller 2 input + ; LDA $8D + LDA #$A5 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$8D : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; Branch over two bytes (PLP : RTL) + ; BNE $02 + LDA #$D0 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$02 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; PLP : RTL + LDA #$28 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$6B : STA !CTRL_SHORTCUT_ROUTINE,X : INX + + ; JMP + LDA #$4C : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; We don't yet know where to jump to. + ; Save this position and we'll write it later. + ; Since we may have written several primary shortcuts first, + ; we need to copy the full 16-bits from X. + %a16() : TXA : STA !CTRL_SHORTCUT_SEC_TO_DUAL_JUMP : %a8() : INX #2 + + ; Write the jump location we skipped over earlier + %a16() : TXY : LDA !CTRL_SHORTCUT_PRI_TO_SEC_DUAL_JUMP : TAX + TYA : CLC : ADC.w #!CTRL_SHORTCUT_ROUTINE : STA !CTRL_SHORTCUT_ROUTINE,X + TYX : %a8() + JMP .secWriteShortcuts + + .secWriteShortcuts + ; Populate variables for current shortcut + %a16() : LDA !CTRL_SHORTCUT_TABLE_SEC_INDEX + PHX : TAX : ASL : TAY + LDA.w !sram_ctrl_2_shortcut_inputs,Y : STA !CTRL_SHORTCUT_SEC + %a8() : LDA !CTRL_SHORTCUT_TABLE,X : STA !CTRL_SHORTCUT_TYPE + + ; Check for special case (single bit non exact match) + BMI .secWriteNotSpecial + %a16() : LDA !CTRL_SHORTCUT_SEC : DEC + AND !CTRL_SHORTCUT_SEC : BNE .secWriteNotSpecial + + ; Scan for other single bit non exact matches with same type, + ; and also for next sec only shortcut. + ; Don't forget to clear ourselves from the table and reset category index. + %a8() : LDA #$30 : STA !CTRL_SHORTCUT_TABLE_SEC_INDEX + TDC : STA !CTRL_SHORTCUT_TABLE,X + JMP .secWriteSpecialLoop + + .secWriteNotSpecial + ; Scan for duplicates, and also for next sec only shortcut. + ; Don't forget to clear ourselves from the table and reset category index. + %a8() : LDA #$30 : STA !CTRL_SHORTCUT_TABLE_SEC_INDEX + TDC : STA !CTRL_SHORTCUT_TABLE,X + .secWriteNormalLoop + INX : CPX #$0030 : BPL .secWriteNormal + INY #2 : LDA !CTRL_SHORTCUT_TABLE,X : BEQ .secWriteNormalLoop + CMP !CTRL_SHORTCUT_TYPE : BNE .secWriteNormalCheckSec + %a16() : LDA.w !sram_ctrl_1_shortcut_inputs,Y : %a8() : BNE .secWriteNormalLoop + %a16() : LDA.w !sram_ctrl_2_shortcut_inputs,Y + CMP !CTRL_SHORTCUT_SEC : %a8() : BNE .secWriteNormalCheckSec + TDC : STA !CTRL_SHORTCUT_TABLE,X + BRA .secWriteNormalLoop + .secWriteNormalCheckSec + LDA !CTRL_SHORTCUT_TABLE_SEC_INDEX : CMP #$30 : BMI .secWriteNormalLoop + %a16() : LDA.w !sram_ctrl_1_shortcut_inputs,Y : %a8() : BNE .secWriteNormalLoop + TXA : STA !CTRL_SHORTCUT_TABLE_SEC_INDEX + BRA .secWriteNormalLoop + + .secWriteNormal + PLX + ; LDA $8D + LDA #$A5 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$8D : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; Check if this is exact match + LDA !CTRL_SHORTCUT_TYPE : BMI .secWriteMatch + ; AND !CTRL_SHORTCUT_SEC + LDA #$29 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA !CTRL_SHORTCUT_SEC : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA !CTRL_SHORTCUT_SEC+1 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + .secWriteMatch + ; CMP !CTRL_SHORTCUT_SEC + LDA #$C9 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA !CTRL_SHORTCUT_SEC : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA !CTRL_SHORTCUT_SEC+1 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; BNE (value will be written later so do an extra INX) + LDA #$D0 : STA !CTRL_SHORTCUT_ROUTINE,X : INX #2 + ; AND $91 + LDA #$25 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$91 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; BEQ + LDA #$F0 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + + ; Determine how much to branch by + PHX : TDC : LDA !CTRL_SHORTCUT_TYPE : AND.b !CTRL_SHORTCUT_TYPE_MASK : TAX + LDA.l ctrl_shortcut_jsl_word_lsb_table,X : STA !CTRL_SHORTCUT_JSL_WORD_LSB + LDA.l ctrl_shortcut_jsl_word_msb_table,X : STA !CTRL_SHORTCUT_JSL_WORD_MSB + LDA.l ctrl_shortcut_cancel_gameplay_table,X : BNE .secWriteMatchClc + LDA !CTRL_SHORTCUT_SEC+1 : BIT #$10 : BNE .secWriteMatchClv + ; Simple JSL case, so branch by four, earlier branch by eight + PLX : LDA #$08 : STA !CTRL_SHORTCUT_ROUTINE-$4,X + LDA #$04 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + JSR .writeJsl + JMP .nextSecWrite + + .secWriteMatchClc + LDA !CTRL_SHORTCUT_SEC+1 : BIT #$10 : BNE .secWriteMatchClcClv + ; PLP : CLC : PHP followed by JSL, so branch by seven, earlier branch by eleven + PLX : LDA #$0B : STA !CTRL_SHORTCUT_ROUTINE-$4,X + LDA #$07 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + JSR .writeClcJsl + JMP .nextSecWrite + + .secWriteMatchClv + ; PLP : CLV : PHP followed by JSL, so branch by seven, earlier branch by eleven + PLX : LDA #$0B : STA !CTRL_SHORTCUT_ROUTINE-$4,X + LDA #$07 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + JSR .writeClvJsl + JMP .nextSecWrite + + .secWriteMatchClcClv + ; PLP : REP $41 : PHP followed by JSL, so branch by eight, earlier branch by twelve + PLX : LDA #$0C : STA !CTRL_SHORTCUT_ROUTINE-$4,X + LDA #$08 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + JSR .writeClcClvJsl + JMP .nextSecWrite + + .secWriteSpecialLoop + INX : CPX #$0030 : BPL .secWriteSpecial + INY #2 : LDA !CTRL_SHORTCUT_TABLE,X : BEQ .secWriteSpecialLoop + CMP !CTRL_SHORTCUT_TYPE : BNE .secWriteSpecialCheckSec + %a16() : LDA.w !sram_ctrl_1_shortcut_inputs,Y : %a8() : BNE .secWriteSpecialLoop + %a16() : LDA.w !sram_ctrl_2_shortcut_inputs,Y + DEC : AND.w !sram_ctrl_2_shortcut_inputs,Y : %a8() : BNE .secWriteSpecialCheckSec + %a16() : LDA.w !sram_ctrl_2_shortcut_inputs,Y + ORA !CTRL_SHORTCUT_SEC : STA !CTRL_SHORTCUT_SEC + %a8() : TDC : STA !CTRL_SHORTCUT_TABLE,X + BRA .secWriteSpecialLoop + .secWriteSpecialCheckSec + LDA !CTRL_SHORTCUT_TABLE_SEC_INDEX : CMP #$30 : BMI .secWriteSpecialLoop + %a16() : LDA.w !sram_ctrl_1_shortcut_inputs,Y : %a8() : BNE .secWriteSpecialLoop + TXA : STA !CTRL_SHORTCUT_TABLE_SEC_INDEX + BRA .secWriteSpecialLoop + + .secWriteSpecial + PLX + ; LDA $91 + LDA #$A5 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$91 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; BIT !CTRL_SHORTCUT_SEC + LDA #$89 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA !CTRL_SHORTCUT_SEC : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA !CTRL_SHORTCUT_SEC+1 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; BEQ + LDA #$F0 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + + ; Determine how much to branch by + PHX : TDC : LDA !CTRL_SHORTCUT_TYPE : AND.b !CTRL_SHORTCUT_TYPE_MASK : TAX + LDA.l ctrl_shortcut_jsl_word_lsb_table,X : STA !CTRL_SHORTCUT_JSL_WORD_LSB + LDA.l ctrl_shortcut_jsl_word_msb_table,X : STA !CTRL_SHORTCUT_JSL_WORD_MSB + LDA.l ctrl_shortcut_cancel_gameplay_table,X : BNE .secWriteSpecialClc + LDA !CTRL_SHORTCUT_SEC+1 : BIT #$10 : BNE .secWriteSpecialClv + ; Simple JSL case, so branch by four + PLX : LDA #$04 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + JSR .writeJsl + BRA .nextSecWrite + + .secWriteSpecialClc + LDA !CTRL_SHORTCUT_SEC+1 : BIT #$10 : BNE .secWriteSpecialClcClv + ; PLP : CLC : PHP followed by JSL, so branch by seven + PLX : LDA #$07 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + JSR .writeClcJsl + BRA .nextSecWrite + + .secWriteSpecialClv + ; PLP : CLV : PHP followed by JSL, so branch by seven + PLX : LDA #$07 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + JSR .writeClvJsl + BRA .nextSecWrite + + .secWriteSpecialClcClv + ; PLP : REP $41 : PHP followed by JSL, so branch by eight + PLX : LDA #$08 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + JSR .writeClcClvJsl + + .nextSecWrite + LDA !CTRL_SHORTCUT_TABLE_SEC_INDEX : CMP #$30 : BPL .doneSecWrite + JMP .secWriteShortcuts + + .doneSecWrite + ; Check if we have dual shortcuts to write + LDA !CTRL_SHORTCUT_TABLE_DUAL_INDEX : CMP #$30 : BMI .doneSecHasDual + JMP .doneWriteShortcuts + + .doneSecHasDual + ; Write check for any controller 1 input + ; LDA $8B + LDA #$A5 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$8B : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; Branch over two bytes (PLP : RTL) + ; BNE $02 + LDA #$D0 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$02 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; PLP : RTL + LDA #$28 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$6B : STA !CTRL_SHORTCUT_ROUTINE,X : INX + + ; Write the jump location we skipped over earlier + %a16() : TXY : LDA !CTRL_SHORTCUT_SEC_TO_DUAL_JUMP : TAX + TYA : CLC : ADC.w #!CTRL_SHORTCUT_ROUTINE : STA !CTRL_SHORTCUT_ROUTINE,X + TYX : %a8() + + .dualWriteShortcuts + ; Populate variables for current shortcut + %a16() : LDA !CTRL_SHORTCUT_TABLE_DUAL_INDEX + PHX : TAX : ASL : TAY + LDA.w !sram_ctrl_1_shortcut_inputs,Y : STA !CTRL_SHORTCUT_PRI + LDA.w !sram_ctrl_2_shortcut_inputs,Y : STA !CTRL_SHORTCUT_SEC + %a8() : LDA !CTRL_SHORTCUT_TABLE,X : STA !CTRL_SHORTCUT_TYPE + + ; Scan for duplicates, and also for next shortcut. + ; Don't forget to clear ourselves from the table and reset category index. + %a8() : LDA #$30 : STA !CTRL_SHORTCUT_TABLE_DUAL_INDEX + TDC : STA !CTRL_SHORTCUT_TABLE,X + .dualWriteNormalLoop + INX : CPX #$0030 : BPL .dualWriteNormal + INY #2 : LDA !CTRL_SHORTCUT_TABLE,X : BEQ .dualWriteNormalLoop + CMP !CTRL_SHORTCUT_TYPE : BNE .dualWriteNormalCheckDual + %a16() : LDA.w !sram_ctrl_1_shortcut_inputs,Y + CMP !CTRL_SHORTCUT_PRI : %a8() : BNE .dualWriteNormalCheckDual + %a16() : LDA.w !sram_ctrl_2_shortcut_inputs,Y + CMP !CTRL_SHORTCUT_SEC : %a8() : BNE .dualWriteNormalCheckDual + TDC : STA !CTRL_SHORTCUT_TABLE,X + BRA .dualWriteNormalLoop + .dualWriteNormalCheckDual + LDA !CTRL_SHORTCUT_TABLE_DUAL_INDEX : CMP #$30 : BMI .dualWriteNormalLoop + TXA : STA !CTRL_SHORTCUT_TABLE_DUAL_INDEX + BRA .dualWriteNormalLoop + + .dualWriteNormal + PLX + ; LDA $8B + LDA #$A5 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$8B : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; Check if this is exact match + LDA !CTRL_SHORTCUT_TYPE : BMI .dualWriteMatchPri + ; AND !CTRL_SHORTCUT_PRI + LDA #$29 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA !CTRL_SHORTCUT_PRI : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA !CTRL_SHORTCUT_PRI+1 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + .dualWriteMatchPri + ; CMP !CTRL_SHORTCUT_PRI + LDA #$C9 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA !CTRL_SHORTCUT_PRI : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA !CTRL_SHORTCUT_PRI+1 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; BNE (value will be written later so do an extra INX) + LDA #$D0 : STA !CTRL_SHORTCUT_ROUTINE,X : INX #2 + ; LDA $8D + LDA #$A5 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$8D : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; Check if this is exact match + LDA !CTRL_SHORTCUT_TYPE : BMI .dualWriteMatchSec + ; AND !CTRL_SHORTCUT_SEC + LDA #$29 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA !CTRL_SHORTCUT_SEC : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA !CTRL_SHORTCUT_SEC+1 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + .dualWriteMatchSec + ; CMP !CTRL_SHORTCUT_SEC + LDA #$C9 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA !CTRL_SHORTCUT_SEC : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA !CTRL_SHORTCUT_SEC+1 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; BNE (value will be written later so do an extra INX) + LDA #$D0 : STA !CTRL_SHORTCUT_ROUTINE,X : INX #2 + ; AND $91 + LDA #$25 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$91 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; BNE $07 + LDA #$D0 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$07 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; LDA !CTRL_SHORTCUT_PRI + LDA #$A9 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA !CTRL_SHORTCUT_PRI : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA !CTRL_SHORTCUT_PRI+1 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; AND $8F + LDA #$25 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$8F : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; BEQ + LDA #$F0 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + + ; Determine how much to branch by + PHX : TDC : LDA !CTRL_SHORTCUT_TYPE : AND.b !CTRL_SHORTCUT_TYPE_MASK : TAX + LDA.l ctrl_shortcut_jsl_word_lsb_table,X : STA !CTRL_SHORTCUT_JSL_WORD_LSB + LDA.l ctrl_shortcut_jsl_word_msb_table,X : STA !CTRL_SHORTCUT_JSL_WORD_MSB + LDA.l ctrl_shortcut_cancel_gameplay_table,X : BNE .dualWriteMatchClc + LDA !CTRL_SHORTCUT_PRI+1 : BIT #$10 : BNE .dualWriteMatchClv + LDA !CTRL_SHORTCUT_SEC+1 : BIT #$10 : BNE .dualWriteMatchClv + ; Simple JSL case, so branch by four, earlier branches by 15 and 25 + PLX : LDA #$19 : STA !CTRL_SHORTCUT_ROUTINE-$15,X + LDA #$0F : STA !CTRL_SHORTCUT_ROUTINE-$B,X + LDA #$04 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + JSR .writeJsl + BRA .nextDualWrite + + .dualWriteMatchClc + LDA !CTRL_SHORTCUT_PRI+1 : BIT #$10 : BNE .dualWriteMatchClcClv + LDA !CTRL_SHORTCUT_SEC+1 : BIT #$10 : BNE .dualWriteMatchClcClv + ; PLP : CLC : PHP followed by JSL, so branch by seven, earlier branches by 18 and 28 + PLX : LDA #$1C : STA !CTRL_SHORTCUT_ROUTINE-$15,X + LDA #$12 : STA !CTRL_SHORTCUT_ROUTINE-$B,X + LDA #$07 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + JSR .writeClcJsl + BRA .nextDualWrite + + .dualWriteMatchClv + ; PLP : CLV : PHP followed by JSL, so branch by seven, earlier branches by 18 and 28 + PLX : LDA #$1C : STA !CTRL_SHORTCUT_ROUTINE-$15,X + LDA #$12 : STA !CTRL_SHORTCUT_ROUTINE-$B,X + LDA #$07 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + JSR .writeClvJsl + BRA .nextDualWrite + + .dualWriteMatchClcClv + ; PLP : REP $41 : PHP followed by JSL, so branch by eight, earlier branches by 19 and 29 + PLX : LDA #$1D : STA !CTRL_SHORTCUT_ROUTINE-$15,X + LDA #$13 : STA !CTRL_SHORTCUT_ROUTINE-$B,X + LDA #$08 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + JSR .writeClcClvJsl + + .nextDualWrite + LDA !CTRL_SHORTCUT_TABLE_DUAL_INDEX : CMP #$30 : BPL .doneDualWrite + JMP .dualWriteShortcuts + + .doneDualWrite + JMP .doneWriteShortcuts + + ; The following four subroutines jumped into from within this method + .writeClvJsl + ; PLP + LDA #$28 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; CLV + LDA #$B8 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; PHP + LDA #$08 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + + ; Fallthrough + .writeJsl + ; JSL + LDA #$22 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA !CTRL_SHORTCUT_JSL_WORD_LSB : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA !CTRL_SHORTCUT_JSL_WORD_MSB : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA.b #ctrl_shortcut_jsl_word_msb_table>>16 : STA !CTRL_SHORTCUT_ROUTINE,X : INX RTS + + .writeClcJsl + ; PLP + LDA #$28 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; CLC + LDA #$18 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; PHP + LDA #$08 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + BRA .writeJsl + + .writeClcClvJsl + ; PLP + LDA #$28 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; REP $41 (equivalent of CLC : CLV) + LDA #$C2 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + LDA #$41 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + ; PHP + LDA #$08 : STA !CTRL_SHORTCUT_ROUTINE,X : INX + BRA .writeJsl } -if !FEATURE_SD2SNES -gamemode_door_transition: +cm_condense_ctrl_shortcuts: { - .checkloadstate - LDA !IH_CONTROLLER_PRI : BEQ .checktransition - CMP !sram_ctrl_load_state : BNE .checktransition - ; check if a saved state exists - LDA !SRAM_SAVED_STATE : CMP !SAFEWORD : BNE .checktransition - PHB : PHK : PLB - JML load_state + PHB : PEA $7070 : PLB : PLB + LDA.w #!sram_ctrl_1_shortcut_inputs : STA $00 : STA $02 + LDA.w #!sram_ctrl_2_shortcut_inputs : STA $04 : STA $06 + TDC : TAX : TAY + + .firstLoop + LDA.w !sram_ctrl_shortcut_selections,X + AND !CTRL_SHORTCUT_TYPE_MASK : BEQ .firstSkip + LDA ($00) : ORA ($04) : BNE .firstCopyCheck + %a8() : STA.w !sram_ctrl_shortcut_selections,X : %a16() + BRA .firstSkip + .firstCopyCheck + LDA $00 : CMP $02 : BEQ .firstCopyDone + LDA ($00) : STA ($02) : LDA ($04) : STA ($06) + %a8() : LDA.w !sram_ctrl_shortcut_selections,X : STA.w !sram_ctrl_shortcut_selections,Y + TDC : STA.w !sram_ctrl_shortcut_selections,X + %a16() : STA ($00) : STA ($04) + .firstCopyDone + INY : INC $02 : INC $02 : INC $06 : INC $06 + .firstSkip + INX : INC $00 : INC $00 : INC $04 : INC $04 + CPX #$001E : BMI .firstLoop + + .secondLoop + LDA.w !sram_ctrl_additional_selections,X + AND !CTRL_SHORTCUT_TYPE_MASK : BEQ .secondSkip + LDA ($00) : ORA ($04) : BNE .secondCopyCheck + %a8() : STA.w !sram_ctrl_additional_selections,X : %a16() + BRA .secondSkip + .secondCopyCheck + LDA $00 : CMP $02 : BEQ .secondCopyDone + LDA ($00) : STA ($02) : LDA ($04) : STA ($06) + %a8() : CPY #$001E : BMI .secondToFirst + LDA.w !sram_ctrl_additional_selections,X : STA.w !sram_ctrl_additional_selections,Y + BRA .secondClear + .secondToFirst + LDA.w !sram_ctrl_additional_selections,X : STA.w !sram_ctrl_shortcut_selections,Y + .secondClear + TDC : STA.w !sram_ctrl_additional_selections,X + %a16() : STA ($00) : STA ($04) + .secondCopyDone + INY : INC $02 : INC $02 : INC $06 : INC $06 + .secondSkip + INX : INC $00 : INC $00 : INC $04 : INC $04 + CPX #$0030 : BMI .secondLoop - .checktransition - ; check if door is done scrolling - LDA !DOOR_FINISHED_SCROLLING : BPL .checkloadstate + PLB RTL } -gamemode_door_transtion_load_sprites: +validate_sram: { - ; Check for auto-save mid-transition - LDA !ram_auto_save_state : BEQ .check - BMI .auto_save - TDC : STA !ram_auto_save_state - .auto_save - PHP : PHB - PHK : PLB - JSL save_state - PLB : PLP - .done - JML $82E4A9 ; return to hijacked code - .check -if !FEATURE_PAL - JML $82E4A9 ; return to hijacked code + ; check if this is ZSNES + PHP : SEP #$28 + LDA #$FF : CLC : ADC #$FF + CMP #$64 : CLD : BNE .doneZSNES + PLP + LDA !SRAM_DETECTION_ZSNES : STA !ram_sram_detection + JMP .fail + + .doneZSNES + PLP + +if !FEATURE_SD2SNES + ; check if required SRAM range is valid + ; writes to SRAM will mirror in other banks if not valid + LDA $707FFE : PHA + LDA $737FFE : INC : STA $707FFE + CMP $737FFE : BNE .first128CheckPass + + ; double check + LDA $702FFE : PHA + LDA $732FFE : INC : STA $702FFE + CMP $732FFE : BNE .second128CheckPass + + ; 128kb check failed + PLA : STA $702FFE + PLA : STA $707FFE + LDA !SRAM_DETECTION_32KB : STA !ram_sram_detection + BRA .fail + + .second128CheckPass + PLA : STA $702FFE + .first128CheckPass + PLA : STA $707FFE + +if !FEATURE_TINYSTATES else - LDA !IH_CONTROLLER_PRI : CMP #$C0C0 : BNE .done - LDA !AREA_ID : BEQ .done : CMP #$0002 : BEQ .done - LDA !sram_ctrl_menu : CMP #$C0C0 : BEQ .done - LDA !sram_ctrl_save_state : CMP #$C0C0 : BEQ .done - LDA !sram_ctrl_load_state : CMP #$C0C0 : BEQ .done - LDA !sram_ctrl_load_last_preset : CMP #$C0C0 : BEQ .done - LDA !sram_ctrl_full_equipment : CMP #$C0C0 : BEQ .done - LDA !sram_ctrl_kill_enemies : CMP #$C0C0 : BEQ .done - LDA !sram_ctrl_reset_segment_timer : CMP #$C0C0 : BEQ .done - LDA !sram_ctrl_reset_segment_later : CMP #$C0C0 : BEQ .done - LDA !sram_ctrl_random_preset : CMP #$C0C0 : BEQ .done - LDA !sram_ctrl_save_custom_preset : CMP #$C0C0 : BEQ .end - LDA !sram_ctrl_load_custom_preset : CMP #$C0C0 : BEQ .end - LDA !sram_ctrl_inc_custom_preset : CMP #$C0C0 : BEQ .end - LDA !sram_ctrl_dec_custom_preset : CMP #$C0C0 : BEQ .end - LDA !sram_ctrl_toggle_tileviewer : CMP #$C0C0 : BEQ .end - LDA !sram_ctrl_update_timers : CMP #$C0C0 : BEQ .end - LDA !sram_ctrl_auto_save_state : CMP #$C0C0 : BEQ .end - LDA !sram_ctrl_toggle_spin_lock : CMP #$C0C0 : BEQ .end - LDA !sram_ctrl_randomize_rng : CMP #$C0C0 : BEQ .end - LDA !sram_ctrl_reveal_damage : CMP #$C0C0 : BEQ .end - LDA !sram_ctrl_force_stand : CMP #$C0C0 : BEQ .end - LDA #custom_intro_init : STA !CINEMATIC_FUNCTION_POINTER - LDA #$001E : STA !GAMEMODE - .end - JML $82E4A9 ; return to hijacked code + LDA $737FFE : PHA + LDA $777FFE : INC : STA $737FFE + CMP $777FFE : BNE .first256CheckPass + + ; double check + LDA $732FFE : PHA + LDA $772FFE : INC : STA $732FFE + CMP $772FFE : BNE .second256CheckPass + + ; 256kb check failed + PLA : STA $732FFE + PLA : STA $737FFE + LDA !SRAM_DETECTION_128KB : STA !ram_sram_detection + BRA .fail + + .second256CheckPass + PLA : STA $732FFE + .first256CheckPass + PLA : STA $737FFE endif +endif + + ; success + TDC : STA !ram_sram_detection + RTL + + .fail + LDA !sram_cutscenes : ORA !CUTSCENE_QUICKBOOT : STA !sram_cutscenes +if !FEATURE_SD2SNES + ; disable savestate controls + TDC : TAX + %a8() + .firstLoop + LDA !sram_ctrl_shortcut_selections,X : ASL + CMP #$04 : BCC .firstContinue : CMP #$0A : BCS .firstContinue + TDC : STA !sram_ctrl_shortcut_selections,X + .firstContinue + INX : CPX #$001E : BMI .firstLoop + .secondLoop + LDA !sram_ctrl_additional_selections,X : ASL + CMP #$04 : BCC .secondContinue : CMP #$0A : BCS .secondContinue + TDC : STA !sram_ctrl_additional_selections,X + .secondContinue + INX : CPX #$0030 : BMI .secondLoop + .found + %a16() +endif + RTL } + + +; ------------------ +; Ctrl Shortcut Menu +; ------------------ + +CtrlShortcutMenu: + dw #ctrlshortcut_00 + dw #ctrlshortcut_01 + dw #ctrlshortcut_02 + dw #ctrlshortcut_03 + dw #ctrlshortcut_04 + dw #ctrlshortcut_05 + dw #ctrlshortcut_06 + dw #ctrlshortcut_07 + dw #ctrlshortcut_08 + dw #ctrlshortcut_09 + dw #ctrlshortcut_10 + dw #ctrlshortcut_11 + dw #ctrlshortcut_12 + dw #ctrlshortcut_13 + dw #ctrlshortcut_14 + dw #ctrlshortcut_15 + dw #ctrlshortcut_goto_page2 + dw #ctrlshortcut_goto_page3 + dw #ctrlshortcut_reset_defaults + dw #$0000 + %cm_header("CONTROLLER SHORTCUTS") + %cm_footer_ctrlshortcut("PRESS AND HOLD FOR ONE SEC", "TOGGLES EXACT MATCH") + +CtrlShortcutMenu2: + dw #ctrlshortcut_16 + dw #ctrlshortcut_17 + dw #ctrlshortcut_18 + dw #ctrlshortcut_19 + dw #ctrlshortcut_20 + dw #ctrlshortcut_21 + dw #ctrlshortcut_22 + dw #ctrlshortcut_23 + dw #ctrlshortcut_24 + dw #ctrlshortcut_25 + dw #ctrlshortcut_26 + dw #ctrlshortcut_27 + dw #ctrlshortcut_28 + dw #ctrlshortcut_29 + dw #ctrlshortcut_30 + dw #ctrlshortcut_31 + dw #ctrlshortcut_goto_page1 + dw #ctrlshortcut_goto_page3 + dw #ctrlshortcut_reset_defaults + dw #$0000 + %cm_header("CONTROLLER SHORTCUTS") + %cm_footer_ctrlshortcut("PRESS AND HOLD FOR 2 SEC", "TOGGLES EXACT MATCH") + +CtrlShortcutMenu3: + dw #ctrlshortcut_32 + dw #ctrlshortcut_33 + dw #ctrlshortcut_34 + dw #ctrlshortcut_35 + dw #ctrlshortcut_36 + dw #ctrlshortcut_37 + dw #ctrlshortcut_38 + dw #ctrlshortcut_39 + dw #ctrlshortcut_40 + dw #ctrlshortcut_41 + dw #ctrlshortcut_42 + dw #ctrlshortcut_43 + dw #ctrlshortcut_44 + dw #ctrlshortcut_45 + dw #ctrlshortcut_46 + dw #ctrlshortcut_47 + dw #ctrlshortcut_goto_page1 + dw #ctrlshortcut_goto_page2 + dw #ctrlshortcut_reset_defaults + dw #$0000 + %cm_header("CONTROLLER SHORTCUTS") + %cm_footer_ctrlshortcut("PRESS AND HOLD FOR 2 SEC", "TOGGLES EXACT MATCH") + +%cm_ctrl_shortcut(00) +%cm_ctrl_shortcut(01) +%cm_ctrl_shortcut(02) +%cm_ctrl_shortcut(03) +%cm_ctrl_shortcut(04) +%cm_ctrl_shortcut(05) +%cm_ctrl_shortcut(06) +%cm_ctrl_shortcut(07) +%cm_ctrl_shortcut(08) +%cm_ctrl_shortcut(09) +%cm_ctrl_shortcut(10) +%cm_ctrl_shortcut(11) +%cm_ctrl_shortcut(12) +%cm_ctrl_shortcut(13) +%cm_ctrl_shortcut(14) +%cm_ctrl_shortcut(15) +%cm_ctrl_shortcut(16) +%cm_ctrl_shortcut(17) +%cm_ctrl_shortcut(18) +%cm_ctrl_shortcut(19) +%cm_ctrl_shortcut(20) +%cm_ctrl_shortcut(21) +%cm_ctrl_shortcut(22) +%cm_ctrl_shortcut(23) +%cm_ctrl_shortcut(24) +%cm_ctrl_shortcut(25) +%cm_ctrl_shortcut(26) +%cm_ctrl_shortcut(27) +%cm_ctrl_shortcut(28) +%cm_ctrl_shortcut(29) +%cm_ctrl_shortcut(30) +%cm_ctrl_shortcut(31) +%cm_ctrl_shortcut(32) +%cm_ctrl_shortcut(33) +%cm_ctrl_shortcut(34) +%cm_ctrl_shortcut(35) +%cm_ctrl_shortcut(36) +%cm_ctrl_shortcut(37) +%cm_ctrl_shortcut(38) +%cm_ctrl_shortcut(39) +%cm_ctrl_shortcut(40) +%cm_ctrl_shortcut(41) +%cm_ctrl_shortcut(42) +%cm_ctrl_shortcut(43) +%cm_ctrl_shortcut(44) +%cm_ctrl_shortcut(45) +%cm_ctrl_shortcut(46) +%cm_ctrl_shortcut(47) + +ctrlshortcut_goto_page1: + %cm_adjacent_submenu("GOTO PAGE ONE", #CtrlShortcutMenu) + +ctrlshortcut_goto_page2: + %cm_adjacent_submenu("GOTO PAGE TWO", #CtrlShortcutMenu2) + +ctrlshortcut_goto_page3: + %cm_adjacent_submenu("GOTO PAGE THREE", #CtrlShortcutMenu3) + +ctrlshortcut_reset_defaults: + %cm_jsl("Reset to Defaults", .routine, #$0000) + .routine + %sfxreset() + JML init_sram_controller_shortcuts + +ctrl_add_shortcut: + %cm_submenu("Add Shortcut", #CtrlSelectShortcutTypeMenu) + +CtrlSelectShortcutTypeMenu: + dw #ctrl_add_main_menu + dw #ctrl_add_soft_reset +if !FEATURE_SD2SNES + dw #ctrl_add_save_state_dynamic + dw #ctrl_add_load_state_dynamic + dw #ctrl_add_auto_save_state_dynamic +endif +if !FEATURE_VANILLAHUD +else + dw #ctrl_add_update_timers +endif + dw #ctrl_add_reload_preset + dw #ctrl_add_random_preset + dw #ctrl_add_save_custom_preset + dw #ctrl_add_load_custom_preset + dw #ctrl_add_inc_custom_preset + dw #ctrl_add_dec_custom_preset + dw #ctrl_add_reset_segment_timer + dw #ctrl_add_reset_segment_later + dw #$FFFF + dw #ctrl_select_shortcut_goto_page2 + dw #ctrl_select_shortcut_goto_page3 + dw #$0000 + %cm_header("SELECT SHORTCUT TYPE") + +CtrlSelectShortcutTypeMenu2: + dw #ctrl_add_full_equipment + dw #ctrl_add_kill_enemies + dw #ctrl_add_toggle_tileviewer + dw #ctrl_add_randomize_rng +if !FEATURE_VANILLAHUD +else + dw #ctrl_add_reveal_damage +endif + dw #ctrl_add_force_stand + dw #ctrl_add_toggle_spin_lock + dw #$FFFF + dw #ctrl_select_shortcut_goto_page1 + dw #ctrl_select_shortcut_goto_page3 + dw #$0000 + %cm_header("SELECT SHORTCUT TYPE") + +CtrlSelectShortcutTypeMenu3: + dw #ctrl_add_pause + dw #ctrl_add_unpause + dw #ctrl_add_slowdown + dw #ctrl_add_speedup +if !FEATURE_VANILLAHUD +else + dw #ctrl_add_inc_display_mode + dw #ctrl_add_dec_display_mode + dw #ctrl_add_inc_room_strat + dw #ctrl_add_dec_room_strat + dw #ctrl_add_inc_super_hud + dw #ctrl_add_dec_super_hud +endif +if !FEATURE_DEV + dw #ctrl_add_dev_shortcut +endif + dw #$FFFF + dw #ctrl_select_shortcut_goto_page1 + dw #ctrl_select_shortcut_goto_page2 + dw #$0000 + %cm_header("SELECT SHORTCUT TYPE") + +ctrl_select_shortcut_goto_page1: + %cm_adjacent_submenu("GOTO PAGE ONE", #CtrlSelectShortcutTypeMenu) + +ctrl_select_shortcut_goto_page2: + %cm_adjacent_submenu("GOTO PAGE TWO", #CtrlSelectShortcutTypeMenu2) + +ctrl_select_shortcut_goto_page3: + %cm_adjacent_submenu("GOTO PAGE THREE", #CtrlSelectShortcutTypeMenu3) + +if !FEATURE_SD2SNES +ctrl_add_save_state_dynamic: + dw !ACTION_DYNAMIC + dl #!ram_cm_ctrl_savestates_allowed + dw #$0000 + dw #ctrl_add_save_state + +ctrl_add_load_state_dynamic: + dw !ACTION_DYNAMIC + dl #!ram_cm_ctrl_savestates_allowed + dw #$0000 + dw #ctrl_add_load_state + +ctrl_add_auto_save_state_dynamic: + dw !ACTION_DYNAMIC + dl #!ram_cm_ctrl_savestates_allowed + dw #$0000 + dw #ctrl_add_auto_save_state +endif + +ctrl_shortcut_text_table: + dw #ctrl_add_empty_dm_text + dw #ctrl_add_main_menu_dm_text +if !FEATURE_SD2SNES + dw #ctrl_add_save_state_dm_text + dw #ctrl_add_load_state_dm_text + dw #ctrl_add_auto_save_state_dm_text +else + dw #ctrl_add_empty_dm_text + dw #ctrl_add_empty_dm_text + dw #ctrl_add_empty_dm_text +endif +if !FEATURE_VANILLAHUD + dw #ctrl_add_empty_dm_text +else + dw #ctrl_add_update_timers_dm_text +endif + dw #ctrl_add_reload_preset_dm_text + dw #ctrl_add_random_preset_dm_text + dw #ctrl_add_save_custom_preset_dm_text + dw #ctrl_add_load_custom_preset_dm_text + dw #ctrl_add_inc_custom_preset_dm_text + dw #ctrl_add_dec_custom_preset_dm_text + dw #ctrl_add_reset_segment_timer_dm_text + dw #ctrl_add_reset_segment_later_dm_text + dw #ctrl_add_full_equipment_dm_text + dw #ctrl_add_kill_enemies_dm_text + dw #ctrl_add_toggle_tileviewer_dm_text + dw #ctrl_add_randomize_rng_dm_text +if !FEATURE_VANILLAHUD + dw #ctrl_add_empty_dm_text +else + dw #ctrl_add_reveal_damage_dm_text +endif + dw #ctrl_add_force_stand_dm_text + dw #ctrl_add_toggle_spin_lock_dm_text + dw #ctrl_add_pause_dm_text + dw #ctrl_add_unpause_dm_text + dw #ctrl_add_slowdown_dm_text + dw #ctrl_add_speedup_dm_text +if !FEATURE_VANILLAHUD + dw #ctrl_add_empty_dm_text + dw #ctrl_add_empty_dm_text + dw #ctrl_add_empty_dm_text + dw #ctrl_add_empty_dm_text + dw #ctrl_add_empty_dm_text + dw #ctrl_add_empty_dm_text +else + dw #ctrl_add_inc_display_mode_dm_text + dw #ctrl_add_dec_display_mode_dm_text + dw #ctrl_add_inc_room_strat_dm_text + dw #ctrl_add_dec_room_strat_dm_text + dw #ctrl_add_inc_super_hud_dm_text + dw #ctrl_add_dec_super_hud_dm_text +endif + dw #ctrl_add_soft_reset_dm_text +if !FEATURE_DEV + dw #ctrl_add_dev_shortcut_dm_text +else + dw #ctrl_add_empty_dm_text +endif + +ctrl_shortcut_cancel_gameplay_table: + db $00 ; Empty + db $01 ; Main Menu + db $01 ; Save State + db $01 ; Load State + db $00 ; Auto Save State + db $00 ; Update Timers + db $01 ; Reload Preset + db $01 ; Random Preset + db $01 ; Save Custom Preset + db $01 ; Load Custom Preset + db $00 ; Increment Custom Preset + db $00 ; Decrement Custom Preset + db $00 ; Reset Segment Timer + db $00 ; Reset Segment Later + db $00 ; Full Equipment + db $00 ; Kill Enemies + db $00 ; Toggle OOB Tile Viewer + db $00 ; Randomize RNG + db $00 ; Reveal Damage + db $00 ; Force Stand + db $00 ; Toggle Spin Lock + db $00 ; Pause + db $00 ; Unpause + db $00 ; Slowdown + db $00 ; Speedup + db $00 ; Increment Display Mode + db $00 ; Decrement Display Mode + db $00 ; Increment Room Strat + db $00 ; Decrement Room Strat + db $00 ; Increment Super HUD + db $00 ; Decrement Super HUD + db $01 ; Soft Reset + db $01 ; DEV Shortcut + +ctrl_shortcut_jsl_word_lsb_table: + db #gamemode_placeholder + db #gamemode_main_menu +if !FEATURE_SD2SNES + db #gamemode_save_state + db #gamemode_load_state + db #gamemode_auto_save_state +else + db #gamemode_placeholder + db #gamemode_placeholder + db #gamemode_placeholder +endif +if !FEATURE_VANILLAHUD + db #gamemode_placeholder +else + db #gamemode_update_timers +endif + db #gamemode_reload_preset + db #gamemode_random_preset + db #gamemode_save_custom_preset + db #gamemode_load_custom_preset + db #gamemode_increment_custom_preset + db #gamemode_decrement_custom_preset + db #gamemode_reset_segment_timer + db #gamemode_reset_segment_later + db #gamemode_full_equipment + db #gamemode_kill_enemies + db #gamemode_toggle_oob_tile_viewer + db #gamemode_randomize_rng +if !FEATURE_VANILLAHUD + db #gamemode_placeholder +else + db #gamemode_reveal_damage +endif + db #gamemode_force_stand + db #gamemode_toggle_spin_lock + db #gamemode_pause + db #gamemode_unpause + db #gamemode_slowdown + db #gamemode_speedup +if !FEATURE_VANILLAHUD + db #gamemode_placeholder + db #gamemode_placeholder + db #gamemode_placeholder + db #gamemode_placeholder + db #gamemode_placeholder + db #gamemode_placeholder +else + db #gamemode_increment_display_mode + db #gamemode_decrement_display_mode + db #gamemode_increment_room_strat + db #gamemode_decrement_room_strat + db #gamemode_increment_super_hud + db #gamemode_decrement_super_hud +endif + db #gamemode_soft_reset +if !FEATURE_DEV + db #gamemode_dev_shortcut +else + db #gamemode_placeholder +endif + +ctrl_shortcut_jsl_word_msb_table: + db #gamemode_placeholder>>8 + db #gamemode_main_menu>>8 +if !FEATURE_SD2SNES + db #gamemode_save_state>>8 + db #gamemode_load_state>>8 + db #gamemode_auto_save_state>>8 +else + db #gamemode_placeholder>>8 + db #gamemode_placeholder>>8 + db #gamemode_placeholder>>8 +endif +if !FEATURE_VANILLAHUD + db #gamemode_placeholder>>8 +else + db #gamemode_update_timers>>8 endif + db #gamemode_reload_preset>>8 + db #gamemode_random_preset>>8 + db #gamemode_save_custom_preset>>8 + db #gamemode_load_custom_preset>>8 + db #gamemode_increment_custom_preset>>8 + db #gamemode_decrement_custom_preset>>8 + db #gamemode_reset_segment_timer>>8 + db #gamemode_reset_segment_later>>8 + db #gamemode_full_equipment>>8 + db #gamemode_kill_enemies>>8 + db #gamemode_toggle_oob_tile_viewer>>8 + db #gamemode_randomize_rng>>8 +if !FEATURE_VANILLAHUD + db #gamemode_placeholder>>8 +else + db #gamemode_reveal_damage>>8 +endif + db #gamemode_force_stand>>8 + db #gamemode_toggle_spin_lock>>8 + db #gamemode_pause>>8 + db #gamemode_unpause>>8 + db #gamemode_slowdown>>8 + db #gamemode_speedup>>8 +if !FEATURE_VANILLAHUD + db #gamemode_placeholder>>8 + db #gamemode_placeholder>>8 + db #gamemode_placeholder>>8 + db #gamemode_placeholder>>8 + db #gamemode_placeholder>>8 + db #gamemode_placeholder>>8 +else + db #gamemode_increment_display_mode>>8 + db #gamemode_decrement_display_mode>>8 + db #gamemode_increment_room_strat>>8 + db #gamemode_decrement_room_strat>>8 + db #gamemode_increment_super_hud>>8 + db #gamemode_decrement_super_hud>>8 +endif + db #gamemode_soft_reset>>8 +if !FEATURE_DEV + db #gamemode_dev_shortcut>>8 +else + db #gamemode_placeholder>>8 +endif + +ctrl_add_empty: + %cm_jsl("", #ctrl_add_shortcut_select, #$0000) + +ctrl_add_main_menu: + %cm_jsl("Main Menu", #ctrl_add_shortcut_select, #$0081) + +if !FEATURE_SD2SNES +ctrl_add_save_state: + %cm_jsl("Save State", #ctrl_add_shortcut_select, #$0082) + +ctrl_add_load_state: + %cm_jsl("Load State", #ctrl_add_shortcut_select, #$0083) + +ctrl_add_auto_save_state: + %cm_jsl("Auto Save State", #ctrl_add_shortcut_select, #$0084) +endif + +if !FEATURE_VANILLAHUD +else +ctrl_add_update_timers: + %cm_jsl("Update Timers", #ctrl_add_shortcut_select, #$0005) +endif + +ctrl_add_reload_preset: + %cm_jsl("Reload Preset", #ctrl_add_shortcut_select, #$0086) + +ctrl_add_random_preset: + %cm_jsl("Random Preset", #ctrl_add_shortcut_select, #$0087) + +ctrl_add_save_custom_preset: + %cm_jsl("Save Cust Preset", #ctrl_add_shortcut_select, #$0088) + +ctrl_add_load_custom_preset: + %cm_jsl("Load Cust Preset", #ctrl_add_shortcut_select, #$0089) + +ctrl_add_inc_custom_preset: + %cm_jsl("Next Preset Slot", #ctrl_add_shortcut_select, #$008A) + +ctrl_add_dec_custom_preset: + %cm_jsl("Prev Preset Slot", #ctrl_add_shortcut_select, #$008B) + +ctrl_add_reset_segment_timer: + %cm_jsl("Reset Seg Timer", #ctrl_add_shortcut_select, #$000C) + +ctrl_add_reset_segment_later: + %cm_jsl("Reset Seg Later", #ctrl_add_shortcut_select, #$000D) + +ctrl_add_full_equipment: + %cm_jsl("Full Equipment", #ctrl_add_shortcut_select, #$000E) + +ctrl_add_kill_enemies: + %cm_jsl("Kill Enemies", #ctrl_add_shortcut_select, #$008F) + +ctrl_add_toggle_tileviewer: + %cm_jsl("Toggle OOB Tiles", #ctrl_add_shortcut_select, #$0010) + +ctrl_add_randomize_rng: + %cm_jsl("Randomize RNG", #ctrl_add_shortcut_select, #$0011) + +if !FEATURE_VANILLAHUD +else +ctrl_add_reveal_damage: + %cm_jsl("Toggle Boss Dmg", #ctrl_add_shortcut_select, #$0012) +endif + +ctrl_add_force_stand: + %cm_jsl("Force Stand", #ctrl_add_shortcut_select, #$0013) + +ctrl_add_toggle_spin_lock: + %cm_jsl("Toggle Spin Lock", #ctrl_add_shortcut_select, #$0014) + +ctrl_add_pause: + %cm_jsl("Pause", #ctrl_add_shortcut_select, #$0095) + +ctrl_add_unpause: + %cm_jsl("Unpause", #ctrl_add_shortcut_select, #$0096) + +ctrl_add_slowdown: + %cm_jsl("Slowdown", #ctrl_add_shortcut_select, #$0097) + +ctrl_add_speedup: + %cm_jsl("Speedup", #ctrl_add_shortcut_select, #$0098) + +if !FEATURE_VANILLAHUD +else +ctrl_add_inc_display_mode: + %cm_jsl("Next Status Mode", #ctrl_add_shortcut_select, #$0099) + +ctrl_add_dec_display_mode: + %cm_jsl("Prev Status Mode", #ctrl_add_shortcut_select, #$009A) + +ctrl_add_inc_room_strat: + %cm_jsl("Next Room Strat", #ctrl_add_shortcut_select, #$009B) + +ctrl_add_dec_room_strat: + %cm_jsl("Prev Room Strat", #ctrl_add_shortcut_select, #$009C) + +ctrl_add_inc_super_hud: + %cm_jsl("Next Super HUD", #ctrl_add_shortcut_select, #$009D) + +ctrl_add_dec_super_hud: + %cm_jsl("Prev Super HUD", #ctrl_add_shortcut_select, #$009E) +endif + +ctrl_add_soft_reset: + %cm_jsl("Soft Reset", #ctrl_add_shortcut_select, #$009F) + +ctrl_add_dev_shortcut: + %cm_jsl("DEV Shortcut", #ctrl_add_shortcut_select, #$0020) + +ctrl_add_shortcut_select: +{ + LDA !ram_cm_ctrl_add_shortcut_slot + TAX : CPX #$001E : BPL .additional + TYA : %a8() : STA !sram_ctrl_shortcut_selections,X + INX : CPX #$001E : BPL .secondLoop + .firstLoop + LDA !sram_ctrl_shortcut_selections,X : BEQ .foundNextOpenSlot + INX : CPX #$001E : BMI .firstLoop + .secondLoop + LDA !sram_ctrl_additional_selections,X : BEQ .foundNextOpenSlot + INX : CPX #$0030 : BMI .secondLoop + BRA .foundNextOpenSlot + + .additional + TYA : %a8() : STA !sram_ctrl_additional_selections,X + INX : CPX #$0030 : BMI .secondLoop + .foundNextOpenSlot + %a16() + TXA : STA !ram_cm_ctrl_add_shortcut_slot + JML cm_previous_menu +} %endfree(85) diff --git a/src/infohud.asm b/src/infohud.asm index f77cf3ba..a17c14db 100644 --- a/src/infohud.asm +++ b/src/infohud.asm @@ -3,7 +3,10 @@ ; ======================================================= org $809490 - JMP $9497 ; skip resetting player 2 inputs + BRA $05 ; skip resetting player 2 inputs + +org $8094C2 + BRA $10 ; skip hard-coded soft reset shortcut org $8094DF PLP ; patch out resetting of controller 2 buttons and enable debug mode @@ -256,7 +259,11 @@ ih_get_item_code: PLY if !FEATURE_VANILLAHUD else + ; assume we are about to collect an item + ; adding an extra beam will increase item % by one + LDA !SAMUS_BEAMS_COLLECTED : PHA : ORA #$0010 : STA !SAMUS_BEAMS_COLLECTED JSL ih_update_hud_code + PLA : STA !SAMUS_BEAMS_COLLECTED endif JSL init_heat_damage_ram JSL init_physics_ram @@ -295,23 +302,29 @@ else LDA !ram_seg_rt_minutes : INC : STA !ram_seg_rt_minutes endif - ; Slowdown / Pause / Frame Advance on P2 Dpad + ; Slowdown / Pause / Frame Advance .doneTimer LDA !ram_slowdown_mode : BNE .slowdown JMP .done .slowdown - CMP #$FFFF : BEQ .pause + BMI .pause LDA !ram_slowdown_frames : BNE .delay ; reset slowdown timer and restore previous inputs LDA !ram_slowdown_mode : STA !ram_slowdown_frames LDA !ram_slowdown_controller_1 : STA !IH_CONTROLLER_PRI_PREV LDA !ram_slowdown_controller_2 : STA !IH_CONTROLLER_SEC_PREV - JSL $809459 ; Read controller input + + .skipDelay JMP .done + .delayDoorTransition + LDA !DOOR_FUNCTION_POINTER : CMP #optimized_fade_in : BCC .skipDelay + CMP #hijack_after_load_level_data : BEQ .skipDelay + BRA .keepDelay + .delay CMP !ram_slowdown_mode : BNE .decTimer @@ -319,6 +332,13 @@ endif LDA !IH_CONTROLLER_PRI : EOR !IH_CONTROLLER_PRI_NEW : STA !ram_slowdown_controller_1 LDA !IH_CONTROLLER_SEC : EOR !IH_CONTROLLER_SEC_NEW : STA !ram_slowdown_controller_2 + LDA !GAMEMODE : CMP #$0007 : BMI .skipDelay + CMP #$000B : BEQ .delayDoorTransition + CMP #$000D : BMI .keepDelay + CMP #$0012 : BEQ .keepDelay + CMP #$001B : BNE .skipDelay + + .keepDelay LDA !ram_slowdown_frames .decTimer @@ -329,32 +349,12 @@ endif JMP .done .pause - LDA !IH_CONTROLLER_PRI : CMP !sram_ctrl_menu : BNE .noMenu - LDA !IH_PAUSE : STA !IH_CONTROLLER_SEC_NEW - BRA .frameAdvance - - .noMenu - LDA !ram_slowdown_frames : BNE .checkFrameAdvance - ; remain paused, store inputs - INC : STA !ram_slowdown_frames - - .storeInputs - LDA !IH_CONTROLLER_PRI : EOR !IH_CONTROLLER_PRI_NEW : STA !ram_slowdown_controller_1 - LDA !IH_CONTROLLER_SEC : EOR !IH_CONTROLLER_SEC_NEW : STA !ram_slowdown_controller_2 - - .checkFrameAdvance - LDA !IH_CONTROLLER_SEC_NEW : CMP !IH_PAUSE : BEQ .frameAdvance - CMP !IH_RESET : BNE .checkFreezeOnLoad - ; resume normal play - TDC : STA !ram_slowdown_mode : STA !ram_slowdown_frames - BRA .done - - .checkFreezeOnLoad ; option to pause on loadstate - LDA !ram_freeze_on_load : BEQ .frozen - LDA !IH_CONTROLLER_PRI_NEW : BEQ .frozen + LDA !ram_freeze_on_load : BEQ .checkFrameAdvance + LDA !IH_CONTROLLER_PRI_NEW : BEQ .checkFrameAdvance ; unfreeze TDC : STA !ram_slowdown_mode : STA !ram_slowdown_frames + STA !ram_freeze_on_load if !FEATURE_SD2SNES LDA !SRAM_SEG_TIMER_F : STA !ram_seg_rt_frames LDA !SRAM_SEG_TIMER_S : STA !ram_seg_rt_seconds @@ -364,16 +364,50 @@ else STA !ram_seg_rt_seconds STA !ram_seg_rt_minutes endif - BRA .done + JMP .done + + .pauseDoorTransition + LDA !DOOR_FUNCTION_POINTER : CMP #optimized_fade_in : BCC .done + CMP #hijack_after_load_level_data : BEQ .done + BRA .keepPause + + .checkFrameAdvance + LDA !ram_slowdown_mode : CMP !SLOWDOWN_PAUSED : BNE .frameAdvance + LDA !GAMEMODE : CMP #$0007 : BMI .done + CMP #$000B : BEQ .pauseDoorTransition + CMP #$000D : BMI .keepPause + CMP #$0012 : BEQ .keepPause + CMP #$001B : BNE .done + + .keepPause + LDA !ram_slowdown_frames : BNE .frozen + INC : STA !ram_slowdown_frames + + ; we just ran a new frame, store previous inputs + LDA !IH_CONTROLLER_PRI : EOR !IH_CONTROLLER_PRI_NEW : STA !ram_slowdown_controller_1 + LDA !IH_CONTROLLER_SEC : EOR !IH_CONTROLLER_SEC_NEW : STA !ram_slowdown_controller_2 .frozen - ; request a lag frame + ; Set overflow and carry flags before calling routine + SEP #$41 + JSL !CTRL_SHORTCUT_ROUTINE + CLV + + ; Main menu doesn't work out the NMI routine, + ; so instead of running, it changes ram_slowdown_mode instead + ; Use this as a trigger to run the current frame + ; Also check for regular frame advance here + LDA !ram_slowdown_mode : CMP !SLOWDOWN_PAUSED_MAIN_MENU : BEQ .done + BMI .frameAdvance + + ; Request a lag frame %a8() : LDA #$01 : STA !NMI_REQUEST_FLAG : %a16() BRA .done .frameAdvance ; run a new frame TDC : STA !ram_slowdown_frames + DEC : STA !ram_slowdown_mode LDA !ram_slowdown_controller_1 : STA !IH_CONTROLLER_PRI_PREV LDA !ram_slowdown_controller_2 : STA !IH_CONTROLLER_SEC_PREV JSL $809459 ; Read controller input @@ -407,17 +441,24 @@ ih_after_room_transition: ; Check if MBHP needs to be disabled LDA !sram_display_mode : CMP !IH_MODE_ROOMSTRAT_INDEX : BNE .segmentTimer - LDA !sram_room_strat : CMP !IH_STRAT_MBHP_INDEX : BNE .segmentTimer + LDA !sram_room_strat : BEQ .checkSuperHUD + CMP !IH_STRAT_MBHP_INDEX : BNE .segmentTimer LDA !ROOM_ID : CMP.w #ROOM_MotherBrainRoom : BEQ .segmentTimer TDC : STA !sram_display_mode + BRA .segmentTimer + + .checkSuperHUD + LDA !sram_superhud_bottom : CMP !IH_SUPERHUD_MBHP_BOTTOM_INDEX : BNE .segmentTimer + LDA !ROOM_ID : CMP.w #ROOM_MotherBrainRoom : BEQ .segmentTimer + TDC : STA !sram_superhud_bottom .segmentTimer - LDA !ram_reset_segment_later : AND #$0001 : BEQ .updateHud + LDA !ram_reset_segment_later : AND #$0001 : BEQ .updateHUD TDC : STA !ram_reset_segment_later : STA !ram_lag_counter STA !ram_seg_rt_frames : STA !ram_seg_rt_seconds : STA !ram_seg_rt_minutes - .updateHud - JSL ih_update_hud_code + .updateHUD + JSL ih_update_hud_after_transition ; Reset realtime and gametime/transition timers TDC : STA !ram_realtime_room : STA !ram_transition_counter @@ -486,6 +527,11 @@ ih_before_room_transition: LDX #$00C2 LDA !sram_top_display_mode : BIT.b !TOP_HUD_VANILLA_BIT : BNE .vanillaDoorLag LDA !ram_minimap : BEQ .draw3 + LDA !sram_display_mode : CMP.b !IH_MODE_ROOMSTRAT_INDEX : BNE .drawDoorMM + LDA !sram_room_strat : BNE .drawDoorMM + %a16() + BRA .done + .drawDoorMM LDX #$0054 .draw3 TYA : JSR Draw3 @@ -696,16 +742,53 @@ ih_update_hud_before_transition: ; Bank 80 PEA $8080 : PLB : PLB - LDA !sram_display_mode : CMP !IH_MODE_ARMPUMP_INDEX : BNE .start + LDA !sram_display_mode : CMP !IH_MODE_ARMPUMP_INDEX : BNE ih_update_hud_after_transition_start ; Report armpump room totals + .armpump LDA !ram_momentum_sum : CLC : ADC !ram_momentum_count : LDX #$0088 : JSR Draw4 LDA !ram_fail_sum : CLC : ADC !ram_fail_count : LDX #$0092 : JSR Draw4 TDC : STA !ram_momentum_count : STA !ram_fail_count STA !ram_momentum_sum : STA !ram_fail_sum : STA !ram_roomstrat_counter + BRA ih_update_hud_code_start +} + +ih_update_hud_after_transition: +{ + PHX : PHY : PHP : PHB + ; Bank 80 + PEA $8080 : PLB : PLB .start - BRA ih_update_hud_code_start + LDA !sram_display_mode : CMP !IH_MODE_ROOMSTRAT_INDEX : BNE ih_update_hud_code_start + LDA !sram_room_strat : BNE ih_update_hud_code_start + + ; Update Super HUD lag counters + LDA !sram_superhud_top : CMP !IH_SUPERHUD_LAG_COUNTER_TOP_INDEX : BNE .middleHUD + LDA !sram_lag_counter_mode : BNE .topFullTime + LDA !ram_last_door_lag_frames + BRA .topDrawTime + .topFullTime + LDA !ram_last_realtime_door + .topDrawTime + LDX #$0014 : JSR Draw3 + TDC : STA !ram_HUD_top + + .middleHUD + LDA !sram_superhud_middle : CMP !IH_SUPERHUD_LAG_COUNTER_MIDDLE_INDEX : BNE .bottomHUD + LDA !sram_lag_counter_mode : BNE .middleFullTime + LDA !ram_last_door_lag_frames + BRA .middleDrawTime + .middleFullTime + LDA !ram_last_realtime_door + .middleDrawTime + LDX #$0054 : JSR Draw3 + TDC : STA !ram_HUD_middle + + ; Check armpump + .bottomHUD + LDA !sram_superhud_bottom : CMP !IH_SUPERHUD_ARMPUMP_BOTTOM_INDEX : BNE ih_update_hud_code_start + JMP ih_update_hud_before_transition_armpump } ih_update_hud_code: @@ -715,15 +798,19 @@ ih_update_hud_code: PEA $8080 : PLB : PLB .start - LDA !ram_minimap : BNE .mmHud + LDA !ram_minimap : BNE .mmHUD JMP .startUpdate .mmVanilla JMP .end - .mmHud + .mmHUD ; Map visible, so draw map counter over item% LDA !sram_top_display_mode : BIT !TOP_HUD_VANILLA_BIT : BNE .mmVanilla + LDA !sram_display_mode : CMP !IH_MODE_ROOMSTRAT_INDEX : BNE .mmTileCounter + LDA !sram_room_strat : BEQ .mmRoomTimer + + .mmTileCounter LDA !MAP_COUNTER : LDX #$0014 : JSR Draw3 LDA !ram_print_segment_timer : BEQ .mmRoomTimer @@ -756,6 +843,7 @@ ih_update_hud_code: LDA $C1 : ASL : TAX LDA HexToNumberGFX1,X : STA !HUD_TILEMAP+$B6 LDA HexToNumberGFX2,X : STA !HUD_TILEMAP+$B8 + LDA !IH_BLANK : STA !HUD_TILEMAP+$AE : STA !HUD_TILEMAP+$BA JMP .end .startUpdate @@ -790,16 +878,18 @@ ih_update_hud_code: ; 3 tiles between input display and missile icon ; skip item% if display mode = vspeed - LDA !sram_display_mode : CMP !IH_MODE_VSPEED_INDEX : BEQ .skipToLag LDA !sram_top_display_mode : BNE .skipToLag + LDA !sram_display_mode : CMP !IH_MODE_VSPEED_INDEX : BEQ .skipToLag + CMP !IH_MODE_ROOMSTRAT_INDEX : BNE .drawItemPercent + LDA !sram_room_strat : BEQ .skipToLag - ; Draw Item percent + .drawItemPercent ; Max HP and Reserves LDA !SAMUS_HP_MAX : CLC : ADC !SAMUS_RESERVE_MAX JSR CalcEtank : STA $C1 - ; Max Missiles, Supers & Power Bombs - LDA !SAMUS_MISSILES_MAX : CLC : ADC !SAMUS_SUPERS_MAX : CLC : ADC !SAMUS_PBS_MAX + ; Max Missiles, Supers and Power Bombs + LDA !SAMUS_MISSILES_MAX : CLC : ADC !SAMUS_SUPERS_MAX : ADC !SAMUS_PBS_MAX JSR CalcItem : CLC : ADC $C1 : STA $C1 ; Collected items @@ -926,17 +1016,17 @@ ih_hud_vanilla_health: %a16() PEA $0000 : PLA ; wait for CPU math LDA $4214 : STA $14 - LDA $4216 : STA $12 + LDA $4216 : PHA LDA !SAMUS_HP_MAX : STA $4204 %a8() LDA #$64 : STA $4206 %a16() PEA $0000 : PLA ; wait for CPU math LDY #$0000 : LDA $4214 - INC : STA $16 + INC : STA $12 .loopTanks - DEC $16 : BEQ .drawEmptyTanks + DEC $12 : BEQ .drawEmptyTanks LDX #$3430 LDA $14 : BEQ .drawTankHealth DEC $14 : LDX #$2831 @@ -953,8 +1043,8 @@ ih_hud_vanilla_health: INY #2 : CPY #$001C : BMI .loopEmptyTanks .subtankHealth - LDA $12 : LDX #$0094 : JSR Draw2 - LDA $16 : BNE .subtankWhitespace + PLA : LDX #$0094 : JSR Draw2 + LDA $12 : BNE .subtankWhitespace ; Draw the leading zero LDA.w NumberGFXTable : STA !HUD_TILEMAP+$94 @@ -1081,7 +1171,11 @@ endif .reserves LDA !sram_top_display_mode : BEQ .statusIcons BIT !TOP_HUD_VANILLA_BIT : BNE .vanilla_check_health + LDA !sram_display_mode : CMP !IH_MODE_ROOMSTRAT_INDEX : BNE .checkReserves + LDA !sram_room_strat : BNE .checkReserves + RTL + .checkReserves LDA !SAMUS_RESERVE_MAX : BEQ .noReserves LDA !SAMUS_RESERVE_ENERGY : CMP !ram_reserves_last : BEQ .checkAuto STA !ram_reserves_last : LDX #$0014 : JSR Draw3 @@ -1094,11 +1188,11 @@ endif .autoOn LDA !SAMUS_RESERVE_ENERGY : BEQ .autoEmpty LDA !IH_RESERVE_AUTO : STA !HUD_TILEMAP+$1A - BRA .statusIcons + BRA .reservesStatusIcons .autoEmpty LDA !IH_RESERVE_EMPTY : STA !HUD_TILEMAP+$1A - BRA .statusIcons + BRA .reservesStatusIcons .noReserves LDA !IH_BLANK @@ -1106,6 +1200,10 @@ endif STA !HUD_TILEMAP+$18 : STA !HUD_TILEMAP+$1A ; Status Icons + .reservesStatusIcons + LDA !sram_status_icons : BNE .checkHealthBomb + RTL + .statusIcons LDA !sram_status_icons : BNE .checkSuperHUD RTL @@ -1143,25 +1241,25 @@ endif .checkSpark LDA !SAMUS_SHINE_TIMER : BEQ .clearSpark LDA !IH_SHINESPARK : STA !HUD_TILEMAP+$58 - BRA .checkReserves + BRA .checkReserveIcon .clearSpark LDA !IH_BLANK : STA !HUD_TILEMAP+$58 ; reserve tank - .checkReserves - LDA !SAMUS_RESERVE_MODE : CMP #$0001 : BNE .clearReserve + .checkReserveIcon + LDA !SAMUS_RESERVE_MODE : CMP #$0001 : BNE .clearReserveIcon LDA !SAMUS_RESERVE_ENERGY : BEQ .empty - LDA !SAMUS_RESERVE_MAX : BEQ .clearReserve + LDA !SAMUS_RESERVE_MAX : BEQ .clearReserveIcon LDA !IH_RESERVE_AUTO : STA !HUD_TILEMAP+$1A RTL .empty - LDA !SAMUS_RESERVE_MAX : BEQ .clearReserve + LDA !SAMUS_RESERVE_MAX : BEQ .clearReserveIcon LDA !IH_RESERVE_EMPTY : STA !HUD_TILEMAP+$1A RTL - .clearReserve + .clearReserveIcon LDA !IH_BLANK : STA !HUD_TILEMAP+$1A .end @@ -1566,8 +1664,6 @@ ih_game_loop_code: LDA !ram_game_loop_extras : BNE .extrafeatures - .checkinputs - LDA !IH_CONTROLLER_SEC_NEW : BNE .handleinputs ; overwritten code + return JML $808111 @@ -1589,79 +1685,37 @@ ih_game_loop_code: JSR magic_pants .pants_done - LDA !ram_infinite_ammo : BEQ .checkinputs + LDA !ram_infinite_ammo : BEQ .infinite_ammo_done LDA !SAMUS_MISSILES_MAX : STA !SAMUS_MISSILES LDA !SAMUS_SUPERS_MAX : STA !SAMUS_SUPERS LDA !SAMUS_PBS_MAX : STA !SAMUS_PBS - BRA .checkinputs - - .handleinputs - CMP !IH_PAUSE : BEQ .toggle_pause - CMP !IH_SLOWDOWN : BEQ .toggle_slowdown - CMP !IH_SPEEDUP : BEQ .toggle_speedup - CMP !IH_RESET : BEQ .reset_slowdown -if !FEATURE_VANILLAHUD -else - CMP !IH_STATUS_R : BEQ .inc_statusdisplay - CMP !IH_STATUS_L : BEQ .dec_statusdisplay -endif - - .done - JML $808111 ; overwritten code + return + .infinite_ammo_done - .toggle_pause - TDC : STA !ram_slowdown_frames - DEC : STA !ram_slowdown_mode - BRA .done - - .toggle_slowdown - LDA !ram_slowdown_mode : INC : STA !ram_slowdown_mode - BRA .done - - .toggle_speedup - LDA !ram_slowdown_mode : BEQ .done - DEC : STA !ram_slowdown_mode - BRA .done - - .reset_slowdown - TDC : STA !ram_slowdown_mode : STA !ram_slowdown_frames - BRA .done + ; overwritten code + return + JML $808111 +} if !FEATURE_VANILLAHUD else - .inc_statusdisplay - LDA !sram_display_mode : INC - CMP !IH_MODE_COUNT : BNE .set_displaymode - TDC - BRA .set_displaymode - - .dec_statusdisplay - LDA !sram_display_mode : DEC - CMP #$FFFF : BNE .set_displaymode - LDA !IH_MODE_COUNT-1 - - .set_displaymode - STA !sram_display_mode - JSL init_print_segment_timer - - .update_status +ih_update_status: +{ TDC STA !ram_momentum_sum : STA !ram_momentum_count - STA !ram_HUD_check + STA !ram_HUD_check : STA !ram_shot_timer + STA !ram_quickdrop_counter : STA !ram_walljump_counter STA !ram_roomstrat_counter : STA !ram_roomstrat_state STA !ram_armed_shine_duration STA !ram_fail_count : STA !ram_fail_sum INC - STA !ram_enemy_hp : STA !ram_mb_hp + STA !ram_enemy_hp STA !ram_dash_counter : STA !ram_shine_counter STA !ram_xpos : STA !ram_ypos : STA !ram_subpixel_pos LDA !ram_seed_X : LSR STA !ram_HUD_top : STA !ram_HUD_middle STA !ram_HUD_top_counter : STA !ram_HUD_middle_counter - - JML $808111 ; overwritten code + return -endif ; !FEATURE_VANILLAHUD + JML init_print_segment_timer } +endif ; !FEATURE_VANILLAHUD metronome: { @@ -1923,16 +1977,16 @@ infidoppler_hook_fire_missile: LDX $14 ; projectile index SEC - LDA !SAMUS_X_SUBPX : SBC !ram_infidoppler_subx - AND #$FF00 : STA !ram_infidoppler_offsets,X - LDA !SAMUS_X : SBC !ram_infidoppler_x - AND #$00FF : ORA !ram_infidoppler_offsets,X : STA !ram_infidoppler_offsets,X + LDA !SAMUS_X_SUBPX : SBC !eram_infidoppler_subx + AND #$FF00 : STA !eram_infidoppler_offsets,X + LDA !SAMUS_X : SBC !eram_infidoppler_x + AND #$00FF : ORA !eram_infidoppler_offsets,X : STA !eram_infidoppler_offsets,X - LDA !ram_infidoppler_x : STA !SAMUS_X - LDA !ram_infidoppler_subx : STA !SAMUS_X_SUBPX + LDA !eram_infidoppler_x : STA !SAMUS_X + LDA !eram_infidoppler_subx : STA !SAMUS_X_SUBPX - LDA !ram_infidoppler_y : STA !SAMUS_Y - LDA !ram_infidoppler_suby : STA !SAMUS_Y_SUBPX + LDA !eram_infidoppler_y : STA !SAMUS_Y + LDA !eram_infidoppler_suby : STA !SAMUS_Y_SUBPX .done DEC !SAMUS_MISSILES @@ -1966,21 +2020,23 @@ infidoppler_hook_projectile_collision: CPX #$0000 : BNE .no ; Is this phantoon? ; Is phantoon in a swoop? + LDA !ENEMY_VAR_5 if !FEATURE_PAL - LDA !ENEMY_VAR_5 : CMP #$D6AC : BNE .no + CMP #$D6AC else - LDA !ENEMY_VAR_5 : CMP #$D678 : BNE .no + CMP #$D678 endif + BNE .no ; Stop infidoppler if health is 100 or less LDA !ENEMY_HP : CMP #$0065 : BCC .disable ; Initialize infidoppler LDA #$FFFF : STA !ram_infidoppler_active - LDA !SAMUS_X : STA !ram_infidoppler_x - LDA !SAMUS_X_SUBPX : STA !ram_infidoppler_subx - LDA !SAMUS_Y : STA !ram_infidoppler_y - LDA !SAMUS_Y_SUBPX : STA !ram_infidoppler_suby + LDA !SAMUS_X : STA !eram_infidoppler_x + LDA !SAMUS_X_SUBPX : STA !eram_infidoppler_subx + LDA !SAMUS_Y : STA !eram_infidoppler_y + LDA !SAMUS_Y_SUBPX : STA !eram_infidoppler_suby BRA .no @@ -1989,7 +2045,7 @@ endif ; We've shot Phantoon with a missile in infidoppler mode. ; if projectile variable is 0, this missile has already hit - LDA !ram_infidoppler_offsets,X + LDA !eram_infidoppler_offsets,X BEQ .done ; Stop infidoppler if health is 100 or less @@ -1998,14 +2054,14 @@ endif ; Subtract projectile variable from missile position ; the LOW 8 bits are pixels, the HIGH 8 bits are fractional ; yes, it's weird. but it saves a couple XBAs - LDA !ram_infidoppler_offsets,X : PHA : AND #$FF00 : SEC + LDA !eram_infidoppler_offsets,X : PHA : AND #$FF00 : SEC EOR #$FFFF : ADC !SAMUS_PROJ_X_SUBPX,Y : STA !SAMUS_PROJ_X_SUBPX,Y PLA : AND #$00FF EOR #$FFFF : ADC !SAMUS_PROJ_X,Y : STA !SAMUS_PROJ_X,Y ; halve damage, since it will double hit LSR !SAMUS_PROJ_DAMAGE,X - TDC : STA !ram_infidoppler_offsets,X + TDC : STA !eram_infidoppler_offsets,X TAX : INC .done diff --git a/src/infohudmodes.asm b/src/infohudmodes.asm index a619ce19..770b6bdd 100644 --- a/src/infohudmodes.asm +++ b/src/infohudmodes.asm @@ -181,7 +181,7 @@ else endif ; Suppress Samus HP display - ; The segment timer is also suppressed elsewhere just for shinetune + ; The segment timer is also suppressed elsewhere LDA !SAMUS_HP : STA !ram_last_hp ; Track Samus momentum @@ -206,6 +206,9 @@ endif BRA .shinetune_start .average_momentum + ; Do not print out momentum if Super HUD is enabled + LDA !sram_room_strat : BEQ .invalid_momentum + ; We have total momentum (x256) over 44 frames ; To get the average (x1024), divide by 11 LDA !ram_momentum_sum @@ -217,7 +220,7 @@ endif LDA $4214 : LDX #$0054 : JSR Draw4Hundredths .invalid_momentum - LDA #$FFFF : STA !ram_momentum_count + TDC : DEC : STA !ram_momentum_count BRA .shinetune_start .wait_for_stop @@ -989,6 +992,7 @@ status_quickdrop: status_walljump: { ; Suppress Samus HP display + ; The segment timer is also suppressed elsewhere LDA !SAMUS_HP : STA !ram_last_hp ; Check if it is time to calculate average climb speed @@ -1416,7 +1420,25 @@ status_ypos: status_shottimer: { LDA !IH_CONTROLLER_PRI_NEW : AND !IH_INPUT_SHOT : BEQ .incShot + LDA !IH_BLANK : STA !HUD_TILEMAP+$AE + STA !HUD_TILEMAP+$B2 : STA !HUD_TILEMAP+$B6 + STA !HUD_TILEMAP+$BA : STA !HUD_TILEMAP+$BE + LDA !ram_shot_timer_past4 : BEQ .initPast + .doneInitPast + STA !HUD_TILEMAP+$BC + LDA !ram_shot_timer_past3 : STA !HUD_TILEMAP+$B8 : STA !ram_shot_timer_past4 + LDA !ram_shot_timer_past2 : STA !HUD_TILEMAP+$B4 : STA !ram_shot_timer_past3 + LDA !ram_shot_timer_past1 : STA !HUD_TILEMAP+$B0 : STA !ram_shot_timer_past2 LDA !ram_shot_timer : LDX #$0088 : JSR Draw4 + LDA !ram_shot_timer : CMP #$0042 : BPL .setX + ASL : TAX : LDA NumberGFXTable,X + BRA .setPast1 + + .setX + LDA !IH_LETTER_X + + .setPast1 + STA !ram_shot_timer_past1 TDC : STA !ram_shot_timer .incShot @@ -1424,6 +1446,11 @@ status_shottimer: LDA !ROOM_ID : CMP.w #ROOM_PhantoonRoom : BEQ .phantoon RTS + .initPast + LDA !IH_BLANK : STA !ram_shot_timer_past4 : STA !ram_shot_timer_past3 + STA !ram_shot_timer_past2 : STA !ram_shot_timer_past1 + BRA .doneInitPast + .phantoonCheckInit LDA !ENEMY_VAR_5 if !FEATURE_PAL @@ -1558,6 +1585,7 @@ superhud_bottom_table: dw status_cooldown dw status_shinetimer dw status_dashcounter + dw status_shinetune dw status_iframecounter dw status_spikesuit dw status_lagcounter @@ -1578,6 +1606,7 @@ superhud_bottom_table: dw status_tacotank dw status_pitdoor dw status_moondance + dw status_kraidradar dw status_gateglitch dw status_moatcwj dw status_robotflush @@ -1588,6 +1617,7 @@ superhud_bottom_table: dw status_snailclip dw status_wasteland dw status_ridleyai + dw status_kihuntermanip dw status_downbackzeb dw status_zebskip dw status_mbhp @@ -1605,6 +1635,10 @@ superhud_middle_table: dw middleHUD_cpuusage dw middleHUD_hspeed dw middleHUD_shottimer + dw middleHUD_itempercent + dw middleHUD_reserves + dw middleHUD_statusicons + dw middleHUD_tilecounter superhud_top_table: dw status_enemyhp_done @@ -1618,6 +1652,10 @@ superhud_top_table: dw topHUD_cpuusage dw topHUD_hspeed dw topHUD_shottimer + dw topHUD_itempercent + dw topHUD_reserves + dw topHUD_statusicons + dw topHUD_tilecounter middleHUD_chargetimer: { @@ -1959,6 +1997,272 @@ topHUD_shottimer: RTS } +middleHUD_itempercent: +{ + LDA !SAMUS_BEAMS_COLLECTED : CLC : ADC !SAMUS_HP_MAX : ADC !SAMUS_RESERVE_MAX + ADC !SAMUS_MISSILES_MAX : ADC !SAMUS_SUPERS_MAX : ADC !SAMUS_PBS_MAX + CMP !ram_HUD_middle_counter : BEQ .checkMajors + STA !ram_HUD_middle_counter : LDA !SAMUS_ITEMS_COLLECTED + BRA .calculate + + .checkMajors + LDA !SAMUS_ITEMS_COLLECTED : CMP !ram_HUD_middle : BEQ .done + + .calculate + STA !ram_HUD_middle + + ; Max HP and Reserves + LDA !SAMUS_HP_MAX : CLC : ADC !SAMUS_RESERVE_MAX + JSR CalcEtank : STA $C1 + + ; Max Missiles, Supers and Power Bombs + LDA !SAMUS_MISSILES_MAX : CLC : ADC !SAMUS_SUPERS_MAX : ADC !SAMUS_PBS_MAX + JSR CalcItem : CLC : ADC $C1 : STA $C1 + + ; Collected items + JSR CalcLargeItem : CLC : ADC $C1 : STA $C1 + + ; Collected beams and charge + JSR CalcBeams : CLC : ADC $C1 + + ; Percent counter -> decimal form and drawn on HUD + LDX #$0052 : JSR Draw3 + LDA !IH_PERCENT : STA !HUD_TILEMAP+$58 + + .done + RTS +} + +topHUD_itempercent: +{ + LDA !SAMUS_BEAMS_COLLECTED : CLC : ADC !SAMUS_HP_MAX : ADC !SAMUS_RESERVE_MAX + ADC !SAMUS_MISSILES_MAX : ADC !SAMUS_SUPERS_MAX : ADC !SAMUS_PBS_MAX + CMP !ram_HUD_top_counter : BEQ .checkMajors + STA !ram_HUD_top_counter : LDA !SAMUS_ITEMS_COLLECTED + BRA .calculate + + .checkMajors + LDA !SAMUS_ITEMS_COLLECTED : CMP !ram_HUD_top : BEQ .done + + .calculate + STA !ram_HUD_top + + ; Max HP and Reserves + LDA !SAMUS_HP_MAX : CLC : ADC !SAMUS_RESERVE_MAX + JSR CalcEtank : STA $C1 + + ; Max Missiles, Supers and Power Bombs + LDA !SAMUS_MISSILES_MAX : CLC : ADC !SAMUS_SUPERS_MAX : ADC !SAMUS_PBS_MAX + JSR CalcItem : CLC : ADC $C1 : STA $C1 + + ; Collected items + JSR CalcLargeItem : CLC : ADC $C1 : STA $C1 + + ; Collected beams and charge + JSR CalcBeams : CLC : ADC $C1 + + ; Percent counter -> decimal form and drawn on HUD + LDX #$0012 : JSR Draw3 + LDA !IH_PERCENT : STA !HUD_TILEMAP+$18 + + .done + RTS +} + +middleHUD_reserves: +{ + LDA !SAMUS_RESERVE_MAX : BEQ .noReserves + CMP !ram_HUD_middle : BEQ .checkReserves + STA !ram_HUD_middle : LDA !SAMUS_RESERVE_ENERGY + BRA .drawReserves + + .checkReserves + LDA !SAMUS_RESERVE_ENERGY : CMP !ram_HUD_middle_counter : BEQ .checkAuto + + .drawReserves + STA !ram_HUD_middle_counter : LDX #$0054 : JSR Draw3 + + .checkAuto + LDA !SAMUS_RESERVE_MODE : CMP #$0001 : BEQ .autoOn + LDA !IH_BLANK : STA !HUD_TILEMAP+$5A + RTS + + .autoOn + LDA !SAMUS_RESERVE_ENERGY : BEQ .autoEmpty + LDA !IH_RESERVE_AUTO : STA !HUD_TILEMAP+$5A + RTS + + .autoEmpty + LDA !IH_RESERVE_EMPTY : STA !HUD_TILEMAP+$5A + RTS + + .noReserves + CMP !ram_HUD_middle : BEQ .done + STA !ram_HUD_middle : LDA !IH_BLANK + STA !HUD_TILEMAP+$54 : STA !HUD_TILEMAP+$56 + STA !HUD_TILEMAP+$58 : STA !HUD_TILEMAP+$5A + + .done + RTS +} + +topHUD_reserves: +{ + LDA !SAMUS_RESERVE_MAX : BEQ .noReserves + CMP !ram_HUD_top : BEQ .checkReserves + STA !ram_HUD_top : LDA !SAMUS_RESERVE_ENERGY + BRA .drawReserves + + .checkReserves + LDA !SAMUS_RESERVE_ENERGY : CMP !ram_HUD_top_counter : BEQ .checkAuto + + .drawReserves + STA !ram_HUD_top_counter : LDX #$0014 : JSR Draw3 + + .checkAuto + LDA !SAMUS_RESERVE_MODE : CMP #$0001 : BEQ .autoOn + LDA !IH_BLANK : STA !HUD_TILEMAP+$1A + RTS + + .autoOn + LDA !SAMUS_RESERVE_ENERGY : BEQ .autoEmpty + LDA !IH_RESERVE_AUTO : STA !HUD_TILEMAP+$1A + RTS + + .autoEmpty + LDA !IH_RESERVE_EMPTY : STA !HUD_TILEMAP+$1A + RTS + + .noReserves + CMP !ram_HUD_top : BEQ .done + STA !ram_HUD_top : LDA !IH_BLANK + STA !HUD_TILEMAP+$14 : STA !HUD_TILEMAP+$16 + STA !HUD_TILEMAP+$18 : STA !HUD_TILEMAP+$1A + + .done + RTS +} + +middleHUD_statusicons: +{ + ; health bomb + LDA !HEALTH_BOMB_FLAG : BEQ .clearHealthBomb + LDA !SAMUS_HP : CMP #$0032 : BMI .inHealthBomb + LDA !IH_LETTER_E : STA !HUD_TILEMAP+$54 + BRA .checkElevator + + .inHealthBomb + LDA !IH_HEALTHBOMB : STA !HUD_TILEMAP+$54 + BRA .checkElevator + + .clearHealthBomb + LDA !IH_BLANK : STA !HUD_TILEMAP+$54 + + ; elevator + .checkElevator + LDA !ELEVATOR_PROPERTIES : BEQ .clearElevator + LDA !IH_ELEVATOR : STA !HUD_TILEMAP+$56 + BRA .checkSpark + + .clearElevator + LDA !IH_BLANK : STA !HUD_TILEMAP+$56 + + ; shinespark + .checkSpark + LDA !SAMUS_SHINE_TIMER : BEQ .clearSpark + LDA !IH_SHINESPARK : STA !HUD_TILEMAP+$58 + BRA .checkReserves + + .clearSpark + LDA !IH_BLANK : STA !HUD_TILEMAP+$58 + + ; reserve tank + .checkReserves + LDA !SAMUS_RESERVE_MODE : CMP #$0001 : BNE .clearReserve + LDA !SAMUS_RESERVE_ENERGY : BEQ .empty + LDA !SAMUS_RESERVE_MAX : BEQ .clearReserve + LDA !IH_RESERVE_AUTO : STA !HUD_TILEMAP+$5A + RTS + + .empty + LDA !SAMUS_RESERVE_MAX : BEQ .clearReserve + LDA !IH_RESERVE_EMPTY : STA !HUD_TILEMAP+$5A + RTS + + .clearReserve + LDA !IH_BLANK : STA !HUD_TILEMAP+$5A + RTS +} + +topHUD_statusicons: +{ + ; health bomb + LDA !HEALTH_BOMB_FLAG : BEQ .clearHealthBomb + LDA !SAMUS_HP : CMP #$0032 : BMI .inHealthBomb + LDA !IH_LETTER_E : STA !HUD_TILEMAP+$14 + BRA .checkElevator + + .inHealthBomb + LDA !IH_HEALTHBOMB : STA !HUD_TILEMAP+$14 + BRA .checkElevator + + .clearHealthBomb + LDA !IH_BLANK : STA !HUD_TILEMAP+$14 + + ; elevator + .checkElevator + LDA !ELEVATOR_PROPERTIES : BEQ .clearElevator + LDA !IH_ELEVATOR : STA !HUD_TILEMAP+$16 + BRA .checkSpark + + .clearElevator + LDA !IH_BLANK : STA !HUD_TILEMAP+$16 + + ; shinespark + .checkSpark + LDA !SAMUS_SHINE_TIMER : BEQ .clearSpark + LDA !IH_SHINESPARK : STA !HUD_TILEMAP+$18 + BRA .checkReserves + + .clearSpark + LDA !IH_BLANK : STA !HUD_TILEMAP+$18 + + ; reserve tank + .checkReserves + LDA !SAMUS_RESERVE_MODE : CMP #$0001 : BNE .clearReserve + LDA !SAMUS_RESERVE_ENERGY : BEQ .empty + LDA !SAMUS_RESERVE_MAX : BEQ .clearReserve + LDA !IH_RESERVE_AUTO : STA !HUD_TILEMAP+$1A + RTS + + .empty + LDA !SAMUS_RESERVE_MAX : BEQ .clearReserve + LDA !IH_RESERVE_EMPTY : STA !HUD_TILEMAP+$1A + RTS + + .clearReserve + LDA !IH_BLANK : STA !HUD_TILEMAP+$1A + RTS +} + +middleHUD_tilecounter: +{ + LDA !MAP_COUNTER : CMP !ram_HUD_middle : BEQ .done : STA !ram_HUD_middle + LDX #$0054 : JSR Draw3 + + .done + RTS +} + +topHUD_tilecounter: +{ + LDA !MAP_COUNTER : CMP !ram_HUD_top : BEQ .done : STA !ram_HUD_top + LDX #$0014 : JSR Draw3 + + .done + RTS +} + status_ceresridley: { ; displays number of shots until Ridley "dies" @@ -3462,22 +3766,22 @@ status_robotflush: { ; Checking hit on first robot LDA !IH_BLANK : STA !HUD_TILEMAP+$88 - LDA !ENEMY_VAR_1+$40 : CMP #$0030 : BMI .checkfirstfall + LDA !ENEMY_VAR_1+!ENEMY_1_OFFSET : CMP #$0030 : BMI .checkfirstfall LDA #$0C3C : STA !HUD_TILEMAP+$88 .checkfirstfall LDA !IH_BLANK : STA !HUD_TILEMAP+$8A - LDA !ENEMY_Y+$40 : CMP #$0280 : BMI .checksecondhit + LDA !ENEMY_Y+!ENEMY_1_OFFSET : CMP #$0280 : BMI .checksecondhit LDA #$0C3C : STA !HUD_TILEMAP+$8A .checksecondhit LDA !IH_BLANK : STA !HUD_TILEMAP+$8C - LDA !ENEMY_VAR_1+$80 : CMP #$0030 : BMI .checksecondfall + LDA !ENEMY_VAR_1+!ENEMY_2_OFFSET : CMP #$0030 : BMI .checksecondfall LDA #$0C3D : STA !HUD_TILEMAP+$8C .checksecondfall LDA !IH_BLANK : STA !HUD_TILEMAP+$8E - LDA !ENEMY_VAR_5+$80 : CMP #$0280 : BMI .done + LDA !ENEMY_VAR_5+!ENEMY_2_OFFSET : CMP #$0280 : BMI .done LDA #$0C3D : STA !HUD_TILEMAP+$8E .done @@ -3652,11 +3956,11 @@ endif ; Note by only checking the lower byte of Y position, ; the same check now works for the shaktool CF clip ; Arbitrary wait of 90 frames before checking - CMP #$005A : BMI .inc - LDA !SAMUS_X : CMP !ram_xpos : BNE .inc - LDA !SAMUS_Y : AND #$00FF : CMP #$00B7 : BNE .inc - LDA !SAMUS_Y_SPEED : CMP #$0000 : BNE .inc - LDA !SAMUS_Y_SUBSPEED : CMP #$0000 : BNE .inc + CMP #$005A : BMI .incNonZeroSpeed + LDA !SAMUS_X : CMP !ram_xpos : BNE .incNonZeroSpeed + LDA !SAMUS_Y : AND #$00FF : CMP #$00B7 : BNE .incNonZeroSpeed + LDA !SAMUS_Y_SPEED : CMP #$0000 : BNE .incNonZeroSpeed + LDA !SAMUS_Y_SUBSPEED : CMP #$0000 : BNE .incY2 LDA !IH_LETTER_Y : STA !HUD_TILEMAP+$8A BRA .timecheck @@ -3680,7 +3984,14 @@ endif LDA !SAMUS_Y : STA !ram_ypos RTS + .incY2 + LDA #$0002 + BRA .inc + + .incNonZeroSpeed + TDC .inc + STA !ram_quickdrop_counter ; Arbitrary give up waiting after 192 frames LDA !ram_roomstrat_state : CMP #$00C0 : BPL .reset INC : STA !ram_roomstrat_state @@ -3703,12 +4014,19 @@ endif LDA #!botwooncf_frame : SEC : SBC !ram_roomstrat_state ASL : TAY : LDA.w NumberGFXTable,Y : STA !HUD_TILEMAP+$8E LDA !IH_LETTER_E : STA !HUD_TILEMAP+$8C - ; Keep waiting if we are early + ; Keep waiting if we are early for a potential Y1 + LDA #$0001 BRA .inc .frameperfect + LDA !ram_quickdrop_counter : BNE .frameY1Y2 LDA !IH_LETTER_Y : STA !HUD_TILEMAP+$8C : STA !HUD_TILEMAP+$8E BRA .reset + + .frameY1Y2 + ASL : TAY : LDA.w NumberGFXTable,Y : STA !HUD_TILEMAP+$8E + LDA !IH_LETTER_Y : STA !HUD_TILEMAP+$8C + BRA .reset } status_snailclip: @@ -4240,13 +4558,13 @@ if !FEATURE_PAL ; B2 -> END dw $B303, $B331, $B3FC ; [$00+6] B3 dw $B408, $B451, $B465, $B4A3, $B4E1 ; [$06+A] B4 - dw $B526, $B564, $B5A4, $B5F5 ; [$10+8] B5 - dw $B623, $B6B7, $B6ED ; [$18+6] B6 - dw $B71E, $B7C9 ; [$1E+4] B7 + dw $B526, $B564, $B5A4, $B5CF, $B5F5 ; [$10+A] B5 (B5D4 moved back to B5CF to recover five bytes) + dw $B623, $B6B7, $B6E8 ; [$1A+6] B6 + dw $B71E, $B7C9 ; [$20+4] B7 ; B8, B9 -> END - dw $BAC7 ; [$22+2] BA - dw $BB9F, $BBD4 ; [$24+4] BB - dw $BC01, $BC3E, $BC64 ; [$28+6] BC + dw $BAC7 ; [$24+2] BA + dw $BB9F, $BBD4 ; [$26+4] BB + dw $BC01, $BC3E ; [$2A+4] BC dw $BD5E ; [$2E+2] BD ; BE, BF, C0, C1, C2, C3, C4 -> END dw $C50F, $C55F ; [$30+4] C5 @@ -4254,13 +4572,13 @@ else dw $B2F3 ; [$00+2] B2 dw $B321, $B3EC, $B3F8 ; [$02+6] B3 dw $B441, $B455, $B493, $B4D1 ; [$08+8] B4 - dw $B516, $B554, $B594, $B5E5 ; [$10+8] B5 - dw $B613, $B6A7, $B6DD ; [$18+6] B6 - dw $B70E, $B7B9 ; [$1E+4] B7 + dw $B516, $B554, $B594, $B5BF, $B5E5 ; [$10+A] B5 (B5C4 moved back to B5BF to recover five bytes) + dw $B613, $B6A7, $B6D8 ; [$1A+6] B6 + dw $B70E, $B7B9 ; [$20+4] B7 ; B8, B9 -> END - dw $BAB7 ; [$22+2] BA - dw $BB8F, $BBC4, $BBF1 ; [$24+6] BB - dw $BC2E, $BC54 ; [$2A+4] BC + dw $BAB7 ; [$24+2] BA + dw $BB8F, $BBC4, $BBF1 ; [$26+6] BB + dw $BC2E ; [$2C+2] BC dw $BD4E ; [$2E+2] BD ; BE, BF, C0, C1, C2, C3, C4 -> END dw $C538, $C588 ; [$30+4] C5 @@ -4271,12 +4589,12 @@ RidleyAI_prefix_table: ; Unused entries are filled with $32 (the last element in the table) to finish the search faster if !FEATURE_PAL ; B2 B3 B4 B5 B6 B7 BA BB BC BD - db $34, $00, $06, $10, $18, $1E, $34, $34, $22, $24, $28, $2E, $34, $34, $34, $34 + db $34, $00, $06, $10, $1A, $20, $34, $34, $24, $26, $2A, $2E, $34, $34, $34, $34 ; C5 db $34, $34, $34, $30, $34, $34, $34, $34, $34, $34, $34, $34, $34, $34, $34, $34 else ; B2 B3 B4 B5 B6 B7 BA BB BC BD - db $00, $02, $08, $10, $18, $1E, $34, $34, $22, $24, $2A, $2E, $34, $34, $34, $34 + db $00, $02, $08, $10, $1A, $20, $34, $34, $24, $26, $2C, $2E, $34, $34, $34, $34 ; C5 db $34, $34, $34, $30, $34, $34, $34, $34, $34, $34, $34, $34, $34, $34, $34, $34 endif @@ -4293,6 +4611,7 @@ RidleyAI_text_table: dw #RidleyAIText_B516 ; climb dw #RidleyAIText_B554 ; climbing dw #RidleyAIText_B594 ; swoop end + dw #RidleyAIText_B5C4 ; hover start dw #RidleyAIText_B5E5 ; hover dw #RidleyAIText_B613 ; hover spin dw #RidleyAIText_B6A7 ; pogo start @@ -4304,7 +4623,6 @@ RidleyAI_text_table: dw #RidleyAIText_BBC4 ; grab move dw #RidleyAIText_BBF1 ; dropping dw #RidleyAIText_BC2E ; dropped - dw #RidleyAIText_BC54 ; hover start dw #RidleyAIText_BD4E ; dodge power bomb dw #RidleyAIText_C538 ; dead move dw #RidleyAIText_C588 ; explode @@ -4324,6 +4642,7 @@ table ../resources/HUDfont.tbl .B516 : db "CLIMB" : db $FF .B554 : db "CLIMBING" : db $FF .B594 : db "SWOOP END" : db $FF + .B5C4 : db "HOVER START" : db $FF .B5E5 : db "HOVER" : db $FF .B613 : db "HOVER SPIN" : db $FF .B6A7 : db "POGO START" : db $FF @@ -4335,7 +4654,6 @@ table ../resources/HUDfont.tbl .BBC4 : db "GRAB MOVE" : db $FF .BBF1 : db "DROP SAMUS" : db $FF .BC2E : db "DROPPED" : db $FF - .BC54 : db "HOVER START" : db $FF .BD4E : db "DODGE PB" : db $FF .C538 : db "DEAD MOVE" : db $FF .C588 : db "EXPLODE" : db $FF @@ -4631,7 +4949,7 @@ status_zebskip: status_mbhp: { - LDA !ENEMY_HP+$40 : CMP !ram_mb_hp : BEQ .done : STA !ram_mb_hp + LDA !ENEMY_HP+!ENEMY_1_OFFSET : CMP !ram_HUD_check : BEQ .done : STA !ram_HUD_check LDX #$0088 : JSR Draw4 .done diff --git a/src/init.asm b/src/init.asm index 795284d4..b9eb672d 100644 --- a/src/init.asm +++ b/src/init.asm @@ -37,6 +37,7 @@ init_code: ; Initialize RAM (Bank 7E required) TDC : STA !ram_slowdown_mode + JSL validate_sram ; Check if we should initialize SRAM LDA !sram_initialized : CMP !SRAM_VERSION : BEQ .sram_initialized @@ -47,9 +48,6 @@ init_code: JSR (init_sram_routine_table,X) .sram_initialized -if !FEATURE_SD2SNES - JSL validate_sram_for_savestates -endif PLA ; Execute overwritten logic and return if !FEATURE_PAL @@ -76,6 +74,8 @@ init_nonzero_wram: INC : STA !ram_cm_sfxlib1 STA !ram_cm_sfxlib2 : STA !ram_cm_sfxlib3 + LDA #$8000 : STA !ram_cm_gmode + JML init_wram_based_on_sram } @@ -106,10 +106,10 @@ init_sram_routine_table: dw init_sram_upgrade_16to17 dw init_sram_upgrade_17to18 dw init_sram_upgrade_18to19 + dw init_sram_upgrade_19to1A init_sram: { - JSL init_sram_controller_shortcuts LDA #$0015 : STA !sram_artificial_lag TDC : STA !sram_fanfare STA !sram_frame_counter_mode @@ -126,13 +126,10 @@ init_sram: LDA #$000A : STA !sram_metronome_tickrate .upgrade_9toA - TDC : STA !sram_ctrl_toggle_tileviewer - STA !sram_status_icons + TDC : STA !sram_status_icons STA !sram_suit_properties .upgrade_AtoB - TDC : STA !sram_ctrl_update_timers - .upgrade_BtoC TDC : STA !sram_top_display_mode STA !sram_room_layout @@ -166,7 +163,6 @@ endif .upgrade_11to12 JSL init_menu_customization - TDC : STA !sram_ctrl_auto_save_state .upgrade_12to13 TDC : STA !sram_custom_header @@ -194,7 +190,7 @@ endif LDA #$000A : STA !sram_presetequiprando_max_pbs .upgrade_16to17 - TDC : STA !sram_spin_lock : STA !sram_ctrl_toggle_spin_lock + TDC : STA !sram_spin_lock DEC : STA !sram_map_grid_alignment .upgrade_17to18 @@ -205,10 +201,7 @@ endif STA !sram_infidoppler_enabled .upgrade_18to19 - TDC : STA !sram_ctrl_randomize_rng - STA !sram_ctrl_reveal_damage - STA !sram_ctrl_force_stand - STA !sram_random_bubble_sfx + TDC : STA !sram_random_bubble_sfx STA !sram_loadstate_rando_energy STA !sram_loadstate_rando_reserves STA !sram_loadstate_rando_missiles @@ -218,34 +211,120 @@ endif LDA #$0100 : STA !sram_ceres_timer LDA #$0300 : STA !sram_zebes_timer + .upgrade_19to1A + LDA !sram_loadstate_rando_energy + ORA !sram_loadstate_rando_reserves + ORA !sram_loadstate_rando_missiles + ORA !sram_loadstate_rando_supers + ORA !sram_loadstate_rando_powerbombs + STA !sram_loadstate_rando_enable + JSL init_sram_controller_shortcuts + LDA !SRAM_VERSION : STA !sram_initialized RTS } init_sram_controller_shortcuts: { - ; branch called by ctrl_reset_defaults in mainmenu.asm - LDA #$3000 : STA !sram_ctrl_menu ; Start + Select - LDA #$6010 : STA !sram_ctrl_save_state ; Select + Y + R - LDA #$6020 : STA !sram_ctrl_load_state ; Select + Y + L - LDA #$5020 : STA !sram_ctrl_load_last_preset ; Start + Y + L - TDC : STA !sram_ctrl_full_equipment - STA !sram_ctrl_kill_enemies - STA !sram_ctrl_reset_segment_timer - STA !sram_ctrl_reset_segment_later - STA !sram_ctrl_random_preset - STA !sram_ctrl_save_custom_preset - STA !sram_ctrl_load_custom_preset - STA !sram_ctrl_inc_custom_preset - STA !sram_ctrl_dec_custom_preset - ; duplicates for reset defaults routine - STA !sram_ctrl_toggle_tileviewer - STA !sram_ctrl_update_timers - STA !sram_ctrl_auto_save_state - STA !sram_ctrl_toggle_spin_lock - STA !sram_ctrl_randomize_rng - STA !sram_ctrl_reveal_damage - STA !sram_ctrl_force_stand + TDC : TAX + .firstLoop + STA !sram_ctrl_shortcut_selections,X + STA !sram_ctrl_1_shortcut_inputs,X + STA !sram_ctrl_2_shortcut_inputs,X + INX : INX : CPX #$001E : BMI .firstLoop + .secondLoop + STA !sram_ctrl_additional_selections,X + STA !sram_ctrl_1_shortcut_inputs,X + STA !sram_ctrl_2_shortcut_inputs,X + INX : INX : CPX #$0030 : BMI .secondLoop + .thirdLoop + STA !sram_ctrl_1_shortcut_inputs,X + STA !sram_ctrl_2_shortcut_inputs,X + INX : INX : CPX #$0060 : BMI .thirdLoop + + %a8() + ; Main Menu + LDA #$81 : LDX #$0000 : STA !sram_ctrl_shortcut_selections,X + ; Soft Reset + LDA #$9F : INX : STA !sram_ctrl_shortcut_selections,X +if !FEATURE_SD2SNES + LDA !ram_sram_detection : BNE .skipTypes + ; Save State + LDA #$82 : INX : STA !sram_ctrl_shortcut_selections,X + ; Load State + LDA #$83 : INX : STA !sram_ctrl_shortcut_selections,X + .skipTypes +endif + ; Reload Preset + LDA #$86 : INX : STA !sram_ctrl_shortcut_selections,X + ; Main Menu + LDA #$81 : INX : STA !sram_ctrl_shortcut_selections,X + ; Pause + LDA #$95 : INX : STA !sram_ctrl_shortcut_selections,X + ; Unpause + LDA #$96 : INX : STA !sram_ctrl_shortcut_selections,X + ; Slowdown + LDA #$97 : INX : STA !sram_ctrl_shortcut_selections,X + ; Speedup + LDA #$98 : INX : STA !sram_ctrl_shortcut_selections,X +if !FEATURE_VANILLAHUD +else + ; Increment Display Mode + LDA #$99 : INX : STA !sram_ctrl_shortcut_selections,X + ; Decrement Display Mode + LDA #$9A : INX : STA !sram_ctrl_shortcut_selections,X + ; Increment Room Strat + LDA #$9B : INX : STA !sram_ctrl_shortcut_selections,X + ; Decrement Room Strat + LDA #$9C : INX : STA !sram_ctrl_shortcut_selections,X + ; Increment Super HUD + LDA #$9D : INX : STA !sram_ctrl_shortcut_selections,X + ; Decrement Super HUD + LDA #$9E : INX : STA !sram_ctrl_shortcut_selections,X +endif + ; Add Shortcut + INX : TXA : STA !ram_cm_ctrl_add_shortcut_slot + + %a16() + ; Main Menu (Controller 1, Start + Select) + LDA #$3000 : LDX #$0000 : STA !sram_ctrl_1_shortcut_inputs,X + ; Soft Reset (Controller 1, Start + Select + L + R) + LDA #$3030 : INX #2 : STA !sram_ctrl_1_shortcut_inputs,X +if !FEATURE_SD2SNES + LDA !ram_sram_detection : BNE .skipValues + ; Save State (Controller 1, Select + Y + R) + LDA #$6010 : INX #2 : STA !sram_ctrl_1_shortcut_inputs,X + ; Load State (Controller 1, Select + Y + L) + LDA #$6020 : INX #2 : STA !sram_ctrl_1_shortcut_inputs,X + .skipValues +endif + ; Reload Preset (Controller 1, Start + Y + L) + LDA #$5020 : INX #2 : STA !sram_ctrl_1_shortcut_inputs,X + ; Main Menu (Controller 2, Start + Select) + LDA #$3000 : INX #2 : STA !sram_ctrl_2_shortcut_inputs,X + ; Pause (Controller 2, Right) + LDA #$0100 : INX #2 : STA !sram_ctrl_2_shortcut_inputs,X + ; Unpause (Controller 2, Left) + LDA #$0200 : INX #2 : STA !sram_ctrl_2_shortcut_inputs,X + ; Slowdown (Controller 2, Down) + LDA #$0400 : INX #2 : STA !sram_ctrl_2_shortcut_inputs,X + ; Speedup (Controller 2, Up) + LDA #$0800 : INX #2 : STA !sram_ctrl_2_shortcut_inputs,X +if !FEATURE_VANILLAHUD +else + ; Increment Display Mode (Controller 2, R) + LDA #$0010 : INX #2 : STA !sram_ctrl_2_shortcut_inputs,X + ; Decrement Display Mode (Controller 2, L) + LDA #$0020 : INX #2 : STA !sram_ctrl_2_shortcut_inputs,X + ; Increment Room Strat (Controller 2, X + R) + LDA #$0050 : INX #2 : STA !sram_ctrl_2_shortcut_inputs,X + ; Decrement Room Strat (Controller 2, X + L) + LDA #$0060 : INX #2 : STA !sram_ctrl_2_shortcut_inputs,X + ; Increment Super HUD (Controller 2, A + R) + LDA #$0090 : INX #2 : STA !sram_ctrl_2_shortcut_inputs,X + ; Decrement Super HUD (Controller 2, A + L) + LDA #$00A0 : INX #2 : STA !sram_ctrl_2_shortcut_inputs,X +endif RTL } @@ -304,6 +383,7 @@ init_post_boot: JML cm_boot .done + JSL cm_write_ctrl_routine JML $82893D ; hijacked code: start main game loop } diff --git a/src/layout.asm b/src/layout.asm index 44056480..c4f50258 100644 --- a/src/layout.asm +++ b/src/layout.asm @@ -284,11 +284,13 @@ hijack_after_load_level_data: ; Swap to left side of room if necessary LDA !SAMUS_X : BIT #$0080 : BEQ .checkRoom + LDA !ram_door_portal_flags : BIT !DOOR_PORTAL_HORIZONTAL_MIRRORING_BIT : BEQ .checkRoom JSL layout_swap_left_right BRA .checkRoom .checkSwapToRight LDA !SAMUS_X : BIT #$0080 : BNE .checkRoom + LDA !ram_door_portal_flags : BIT !DOOR_PORTAL_HORIZONTAL_MIRRORING_BIT : BEQ .checkRoom JSL layout_swap_left_right .checkRoom @@ -1328,7 +1330,7 @@ layout_asm_waterway_external: layout_asm_mb_external: { ; Replace MB enemy with maprando variant - LDA #layout_maprando_mb_enemy_header : STA !ENEMY_ID+$40 + LDA #layout_maprando_mb_enemy_header : STA !ENEMY_ID+!ENEMY_1_OFFSET ; Place the four barrier ceiling LDA #$82E6 : STA $7F016E : STA $7F0170 : STA $7F0172 @@ -2300,7 +2302,7 @@ layout_asm_mb_spawn_escape_door: dw $0600, $B677 ; Replace MB enemy with maprando variant - LDA #layout_maprando_mb_enemy_header : STA !ENEMY_ID+$40 + LDA #layout_maprando_mb_enemy_header : STA !ENEMY_ID+!ENEMY_1_OFFSET ; Fallthrough to Mother Brain HP } @@ -2309,12 +2311,19 @@ layout_asm_mbhp: { if !FEATURE_VANILLAHUD else - LDA !sram_display_mode : BNE .done + LDA !sram_display_mode : BEQ .assignMBHP + CMP !IH_MODE_ROOMSTRAT_INDEX : BNE .done + LDA !sram_superhud_bottom : BNE .done + ; Switch Super HUD enemy HP to MB HP + LDA !IH_SUPERHUD_MBHP_BOTTOM_INDEX : STA !sram_superhud_bottom + RTS + + .assignMBHP + ; Switch enemy HP to MB HP LDA !IH_MODE_ROOMSTRAT_INDEX : STA !sram_display_mode LDA !IH_STRAT_MBHP_INDEX : STA !sram_room_strat - - .done endif ; !FEATURE_VANILLAHUD + .done RTS } diff --git a/src/macros.asm b/src/macros.asm index f98b6251..d111766a 100644 --- a/src/macros.asm +++ b/src/macros.asm @@ -86,7 +86,18 @@ macro cm_footer(title) ; optional outlined text below the menu items .dm_footer table ../resources/header.tbl - dw #$F007 : db #$28, "