diff --git a/patches/ips/crash_handle_autoreserves.ips b/patches/ips/crash_handle_autoreserves.ips new file mode 100644 index 000000000..1813e5068 Binary files /dev/null and b/patches/ips/crash_handle_autoreserves.ips differ diff --git a/patches/ips/crash_handle_base.ips b/patches/ips/crash_handle_base.ips new file mode 100644 index 000000000..e6be8eb7c Binary files /dev/null and b/patches/ips/crash_handle_base.ips differ diff --git a/patches/ips/crash_handle_springball.ips b/patches/ips/crash_handle_springball.ips new file mode 100644 index 000000000..0cb943754 Binary files /dev/null and b/patches/ips/crash_handle_springball.ips differ diff --git a/patches/ips/crash_handle_xmode.ips b/patches/ips/crash_handle_xmode.ips new file mode 100644 index 000000000..f15618ca7 Binary files /dev/null and b/patches/ips/crash_handle_xmode.ips differ diff --git a/patches/ips/crash_handle_yapping.ips b/patches/ips/crash_handle_yapping.ips new file mode 100644 index 000000000..17457d6bc Binary files /dev/null and b/patches/ips/crash_handle_yapping.ips differ diff --git a/patches/ips/vanilla_bugfixes.ips b/patches/ips/vanilla_bugfixes.ips index 0bf3f141b..d905effe4 100644 Binary files a/patches/ips/vanilla_bugfixes.ips and b/patches/ips/vanilla_bugfixes.ips differ diff --git a/patches/rom_map/Bank 80.txt b/patches/rom_map/Bank 80.txt index 26575e8d3..26292fe90 100644 --- a/patches/rom_map/Bank 80.txt +++ b/patches/rom_map/Bank 80.txt @@ -6,7 +6,7 @@ D140 - D200: oob_death.asm D200 - D240: vanilla_bugfixes.asm D240 - D310: stats.asm D310 - D330: fast_reload.asm -D330 - D340: [FREE] +D330 - D340: crash_handle_base.asm [also referenced in patch.rs] D340 - DA00: reserve_hud.asm DA00 - DD00: msu1.asm DD00 - E100: Palette pointer table for Mosaic diff --git a/patches/rom_map/Bank 82.txt b/patches/rom_map/Bank 82.txt index 2d0926b14..861abc1cf 100644 --- a/patches/rom_map/Bank 82.txt +++ b/patches/rom_map/Bank 82.txt @@ -1,21 +1,21 @@ C262 - C27D: disableable_etanks.asm -C27D - C298: -C2A6 - C2B7: +C27D - C298: vanilla_bugfixes.asm +C2A6 - C2B7: split_speed.asm C362 - C369: C37E - C385: C3B6 - C3BD: map_area.asm C3C4 - C3D9: map_area.asm C411 - C42D: map_area.asm -C42D - C465: +C42D - C465: split_speed.asm F70F - F810: map_area.asm -F810 - F830: vanilla_bugfixes.asm +F810 - F830: crash_handle_springball.asm F830 - F9E0: disable_etanks.asm F9E0 - FA00: reserve_backward_fill.asm FA00 - FA80: alternate_door_colors.asm FA80 - FA90: fix_water_fx_bug.asm FA90 - FBB0: seed_hash_display.asm FBB0 - FBF0: fix_kraid_hud.asm -FBF0 - FC30: vanilla_bugfixes.asm +FBF0 - FC30: crash_handle_autoreserve.asm FC30 - FC50: fix_transition_bad_tiles.asm FC50 - FCD0: map_area.asm FCD0 - FD00: escape.asm diff --git a/patches/rom_map/Bank 83.txt b/patches/rom_map/Bank 83.txt index 46816f635..a10d6c739 100644 --- a/patches/rom_map/Bank 83.txt +++ b/patches/rom_map/Bank 83.txt @@ -3,8 +3,7 @@ AD66 - AD72: escape_autosave.asm B000 - B700: [FREE] B700 - B800: rng_fix.asm B800 - BA00: Mosaic (Area FX.asm) -BA00 - BA15: vanilla_bugfixes.asm -BA15 - BB00: [FREE] +BA00 - BB00: [FREE] BB00 - BC40: disableable_etanks.asm BC40 - E000: [FREE] E000 - F000: item_dots_disappear.asm diff --git a/patches/rom_map/Bank 84.txt b/patches/rom_map/Bank 84.txt index 934cc1b76..d141231be 100644 --- a/patches/rom_map/Bank 84.txt +++ b/patches/rom_map/Bank 84.txt @@ -1,3 +1,4 @@ +$858C - $85B2: vanilla_bugfixes.asm (unused vanilla code, repurposed for main street save station plm check.) $EFD3 - $EFD7: load_plms_early.asm $EFD7 - $F000: vanilla_bugfixes.asm $F000 - $F0E2: walljump_plm.asm diff --git a/patches/rom_map/Bank 85.txt b/patches/rom_map/Bank 85.txt index 318025ef4..48bec0a6f 100644 --- a/patches/rom_map/Bank 85.txt +++ b/patches/rom_map/Bank 85.txt @@ -16,7 +16,10 @@ $AA00 - $AAA0: pause_menu_objectives.asm $AAA0 - $AB00: [FREE] $AB00 - $ACA0: map_area.asm $ACA0 - $AD00: load_flash_suit -$AD00 - $AE20: [FREE] +$AD00 - $AD43: crash_handle_springball.asm +$AD43 - $AE20: [FREE] $AE20 - $B000: reserve_backward_fill.asm -$B000 - $B600: vanilla_bugfixes.asm +$B000 - $B5B4: crash_handle_base.asm +$B5B4 - $B5F1: crash_handle_yapping.asm +$B5F1 - $B600: [free] $B600 - $BA00: map_area.asm \ No newline at end of file diff --git a/patches/rom_map/Bank 90.txt b/patches/rom_map/Bank 90.txt index f47e31b18..3901f8d28 100644 --- a/patches/rom_map/Bank 90.txt +++ b/patches/rom_map/Bank 90.txt @@ -7,6 +7,6 @@ $F900 - $F910: escape_timer.asm $F980 - $FA00: respin.asm $FA00 - $FC00: map_progress_maintain.asm (list of cross-area tiles to reveal) $FC00 - $FC10: Fake Lava.asm -$FC10 - $FC20: vanilla_bugfixes.asm +$FC10 - $FC20: crash_handle_yapping.asm $FC20 - $FC40: remove_spikesuit.asm $FC40 - $FD00: split_speed.asm \ No newline at end of file diff --git a/patches/rom_map/Bank 91.txt b/patches/rom_map/Bank 91.txt index f393e4660..7641f5073 100644 --- a/patches/rom_map/Bank 91.txt +++ b/patches/rom_map/Bank 91.txt @@ -1,4 +1,4 @@ +95bc - 965a: {unused vanilla code - demo instructions} - crash_handle_xmode.asm F7F4 - F88C: {unused vanilla code} - split_speed.asm FC42 - FC66: {unsued vanilla code} - split_speed.asm - -FFEE - FFFE: mosaic\fake lava.asm +FFEE - FFFE: mosaic\fake lava.asm \ No newline at end of file diff --git a/patches/rom_map/RAM.txt b/patches/rom_map/RAM.txt index 9b4919b17..da84caccd 100644 --- a/patches/rom_map/RAM.txt +++ b/patches/rom_map/RAM.txt @@ -1,5 +1,6 @@ $95: temporary variable (unused debug location) - used by extended messageboxes, safe to use outside message boxes. $9B: decompression.asm +$CF: vanilla_bugfixes.asm (used by crash dialogues to prevent unpause from resetting gamestate.) $09EC: number of disabled ETanks (saved to SRAM) $0A1A: previous reserve health (reserve_hud.asm) $1F5B: map area (like $079F) @@ -44,7 +45,8 @@ $7EF594-$7EF596: fix_transition_bad_tiles.asm $7EF596: vanilla_bugfixes.asm $7EF597-$7EF599: split_speed.asm $7EF59A-$7EF59C: reserve_backward_fill.asm -$7EF59C-$7EFE00: [FREE] +$7EF59C-$7EF59E: crash_handle_xmode.asm +$7EF59E-$7EFE00: [FREE] $7EFE00: map area (copy of $1F5B to be saved to SRAM) $7EFE02: map area explored mask $7EFE04: copy of $1F5D (to be saved to SRAM for escape autosave) diff --git a/patches/rom_map/vanilla_hooks.txt b/patches/rom_map/vanilla_hooks.txt index f406e1ba1..33ab55fbe 100644 --- a/patches/rom_map/vanilla_hooks.txt +++ b/patches/rom_map/vanilla_hooks.txt @@ -990,6 +990,7 @@ $909e88 - walljump_plm.asm [BANK 91] $9181f4 - aim_anything.asm +$91cafe - crash_handle_xmode.asm $91e164 - fast_reload.asm $91e604 - fix_hyper_slowlock.asm $91deba - gravity_palette.asm diff --git a/patches/src/constants.asm b/patches/src/constants.asm index 483e01ffc..cef3b0386 100644 --- a/patches/src/constants.asm +++ b/patches/src/constants.asm @@ -56,3 +56,10 @@ ; target number of frames for the pause menu black screen to lag ; (to compensate for VRAM decompression being faster): !unpause_black_screen_lag_frames = $dfff07 + +; crash handler / sub patches variables + +!crash_toggles = $80D330 ; overwritten by patch.rs , defined in crash_handle_base.asm + +!kill_samus = $80D337 ; defined in crash_handle_base.asm +!bug_dialog = $80D332 ; defined in crash_handle_base.asm diff --git a/patches/src/crash_handle_autoreserves.asm b/patches/src/crash_handle_autoreserves.asm new file mode 100644 index 000000000..75bb1aa1a --- /dev/null +++ b/patches/src/crash_handle_autoreserves.asm @@ -0,0 +1,45 @@ +;;; Fix auto-reserve / pause bug +;;; +;;; This patch will initiate the death sequence if pause hit with auto-reserve enabled +;;; on exact frame that leads to crash. +;;; +;;; (thanks to Benox50 for his initial patch, nn44/aquanight for the light pillar fix) +;;; + + +incsrc "constants.asm" + +!bank_82_free_space_start = $82fbf0 ; pause / reserve bug +!bank_82_free_space_end = $82fc30 + + +;;; vanilla hooks + +org $828b3f + jsr pause_func : nop ; gamestate 1Ch (unused) handler + + +;;; custom code + +org !bank_82_free_space_start +pause_func: + lda !crash_toggles + and #$00F0 + beq .default + cmp #$0020 + beq .fix +.warn + lda #$0041 ; "fix" leaves the screen black like any pause close to fadeout, warning will relight the screen due to showing the dialog, could be changed to darken the screen again but it might be confusing. + jsl !bug_dialog +.fix + lda #$0008 + sta $0998 + rts +.default + lda #$0041 ; msg ID + jsl !bug_dialog + jsl !kill_samus + stz $9d6 ; clear reserve health + rts + +assert pc() <= !bank_82_free_space_end diff --git a/patches/src/crash_handle_base.asm b/patches/src/crash_handle_base.asm new file mode 100644 index 000000000..ef2d64da3 --- /dev/null +++ b/patches/src/crash_handle_base.asm @@ -0,0 +1,186 @@ +;;; crash handler (displays a custom message box explaining the crash) +;;; StagShot, toggle modifications - nn_357 +;;; +;;; Implementation of custom dialog boxes +;;; Requires hooking multiple functions to support extended msg IDs (0x40+) +;;; and additional lookup tables +;;; +;;; This code is used by other patches that handle hardlocks caused by the unequip springball, frame perfect pause on autoreserve trigger, yappingmaw shinespark +;;; X-mode solid tile collision. + +arch snes.cpu +lorom + +incsrc "constants.asm" + +!bank_80_free_space_start = $80D332 ; springboard for the sub patches.. They all point here for the crash loader / kill samus +!bank_80_free_space_end = $80D340 ; if moving the crash handler base patch then this needs to be changed too. + +!bank_85_free_space_start = $85b000 ; +!bank_85_free_space_end = $85b5b4 + +!msg_crash_timer_override = $7EF596 ; temporary variable used for overriding messagebox close delay times during crash box. + +;;; global code. +org !crash_toggles ; default at 80d330, srpringboard follows. + dw $0000 ; overwritten by patch.rs + +org !bank_80_free_space_start + jsl bug_dialog + rtl + jsl kill_samus + rtl + +assert pc() <= !bank_80_free_space_end + +;;; hooks into vanilla code + +org $858493 ; override messagebox delay if crash dialog + jsr hook_msgbox_delay + +org $858093 + jsr hook_message_box + +org $8582e5 + jsr hook_index_lookup + +org $8582ee + jsr hook_message_table + +org $85840c ; hook unpause to prevent resetting gamestate to 8 if crash ID set + jsr hook_button_lookup + +;;; custom code + +org !bank_85_free_space_start +bug_dialog: ; A = msg ID + and #$00ff + pha + sep #$20 + lda #$0f ; restore screen brightness to full + sta $51 + sta !msg_crash_timer_override ; messagebox timer will check if this is 0 (if its non zero load a longer time) + rep #$30 + jsl $808338 ; wait for NMI + + pla ; dlg box parameter + jsl $858080 ; dlg box + cmp #$0044 + bne .skipkill ; oob death (dlg 44) is removable via major glitches patch, if its thrown then the intent is to kill as it isn't toggleable. + jsl kill_samus +.skipkill + rtl + +hook_message_box: + rep #$30 + lda $1c1f + cmp #$0040 ; custom boxes >= 0x40 + bcs .custom + jmp $8241 ; original func + +.custom + ldx #(new_message_boxes-$869b) ; ptr for extended lookup table + jmp $824f + +hook_index_lookup: + lda $1c1f + cmp #$0040 + bcs .custom + rts + +.custom + sec + sbc #$0040 + rts + +hook_message_table: + adc $34 ; replaced code + tax ; + lda $1c1f + cmp #$0040 + bcs .custom + rts + +.custom + txa + clc + adc #(new_message_boxes-$869b) ; adjust ptr for extended table + tax + rts + +hook_button_lookup: + lda $1c1f + cmp #$0040 + bcs .custom + rts + +.custom + lda #$0001 ; blank button tilemap + ldy #(reserve_pause_msg-$8426) ; blank button letter + rts + +hook_msgbox_delay: + pha + lda !msg_crash_timer_override + beq .nochange + ldx #$005a ; (put 1.5 seconds on the clock) + lda #$00 + sta !msg_crash_timer_override ; clear our special variable so then next msgbox will have whatever timer was set on generation +.nochange + pla + jsr $8136 ; hi-jacked instruction. + rts + +; custom messages start at 0x41 +new_message_boxes: + dw $83c5, $825a, reserve_pause_msg ; 0x41 + dw $83c5, $825a, springball_msg ; 0x42 + dw $83c5, $825a, yapping_maw_msg ; 0x43 + dw $83c5, $825a, oob_msg ; 0x44 + dw $83c5, $825a, xmode_msg ; 0x45 + dw $0000, $0000, msg_end + +table "tables/dialog_chars.tbl",RTL + +reserve_pause_msg: + dw $000e,$000e,$000e, " GAME CRASH! ", $000e,$000e,$000e + dw $000e,$000e,$000e, " ", $000e,$000e,$000e + dw $000e,$000e,$000e, " PAUSED ON EXACT FRAME ", $000e,$000e,$000e + dw $000e,$000e,$000e, " AUTO-REFILL STARTED! ", $000e,$000e,$000e + +springball_msg: + dw $000e,$000e,$000e, " GAME CRASH! ", $000e,$000e,$000e + dw $000e,$000e,$000e, " ", $000e,$000e,$000e + dw $000e,$000e,$000e, " UNEQUIPPED SPRING BALL ", $000e,$000e,$000e + dw $000e,$000e,$000e, " IN NEUTRAL BOUNCE! ", $000e,$000e,$000e + +yapping_maw_msg: + dw $000e,$000e,$000e, " GAME CRASH! ", $000e,$000e,$000e + dw $000e,$000e,$000e, " ", $000e,$000e,$000e + dw $000e,$000e,$000e, " YAPPING MAW SHINESPARK ", $000e,$000e,$000e + dw $000e,$000e,$000e, " END WITH NO INPUTS HELD! ", $000e,$000e,$000e + +oob_msg: + dw $000e,$000e,$000e, " ", $000e,$000e,$000e + dw $000e,$000e,$000e, " SAMUS OUT-OF-BOUNDS! ", $000e,$000e,$000e + dw $000e,$000e,$000e, " ", $000e,$000e,$000e + dw $000e,$000e,$000e, " ", $000e,$000e,$000e + +xmode_msg: + dw $000e,$000e,$000e, " GAME CRASH! ", $000e,$000e,$000e + dw $000e,$000e,$000e, " ", $000e,$000e,$000e + dw $000e,$000e,$000e, " X-MODE TILE COLLISION ", $000e,$000e,$000e + dw $000e,$000e,$000e, "COLLIDED WITH A SOLID TILE", $000e,$000e,$000e + +msg_end: + +kill_samus: + lda #$8000 ; init death sequence (copied from $82db80) + sta $a78 + lda #$0011 + jsl $90f084 + lda #$0013 ; set gamestate + sta $998 + rtl + +assert pc() <= !bank_85_free_space_end \ No newline at end of file diff --git a/patches/src/crash_handle_springball.asm b/patches/src/crash_handle_springball.asm new file mode 100644 index 000000000..e7d322ccd --- /dev/null +++ b/patches/src/crash_handle_springball.asm @@ -0,0 +1,83 @@ +;;; Spring ball menu crash fix by strotlog. +;;; Fix obscure vanilla bug where: turning off spring ball while bouncing, can crash in $91:EA07, +;;; or exactly the same way as well in $91:F1FC. +;;; Adapted for map rando by Stag Shot: +;;; toggle-modifications nn_357. + +arch snes.cpu +lorom + +incsrc "constants.asm" + + +!bank_82_free_space_start = $82f810 ; hook unpause (springball crash) +!bank_82_free_space_end = $82f830 + +!bank_85_free_space_start = $85ad00 +!bank_85_free_space_end = $85ad45 + +;;; vanilla hooks + +org $8293bb + jmp check_unpause + +org $91ea07 + jsl spring_ball_crash + +org $91f1fc + jsl spring_ball_crash + +;;; custom code + + +org !bank_82_free_space_start +check_unpause: + php + sep #$20 + lda $00cf ; pending crash ID + stz $00cf + cmp #$42 ; springball? + bne .skip + plp + jmp $93c1 ; skip changing gamestate +.skip + plp + lda #$0008 ; replaced code + jmp $93be + +assert pc() <= !bank_82_free_space_end + + +org !bank_85_free_space_start +spring_ball_crash: + lda $0B20 ; morph bounce state + cmp #$0600 ; bugged? + bcc .skip + lda !crash_toggles + and #$000F + beq .default + cmp #$0002 + beq .fix +.warn + lda #$0042 + jsl !bug_dialog +.fix + lda #$0000 + stz $0b20 + rtl +.default + sep #$20 + lda #$42 ; bug ID + sta $00cf ; set flag to prevent unpause from resetting gamestate to 8 + rep #$30 + jsl !bug_dialog + jsl !kill_samus + lda #$0000 + stz $0B20 + rtl +.skip + lda $0B20 ; replaced code + asl ; + rtl + +assert pc() <= !bank_85_free_space_end diff --git a/patches/src/crash_handle_xmode.asm b/patches/src/crash_handle_xmode.asm new file mode 100644 index 000000000..1b436d44f --- /dev/null +++ b/patches/src/crash_handle_xmode.asm @@ -0,0 +1,69 @@ +;;; X-Mode collision fix - nn_357 +;;; rewrite original input handler for solid tile collision to free up space. +;;; thanks to StagShot for noticing the rep$30 isn't needed here, it's already initialized by the single caller to this function. +;;; whole fix can now fit in the original function. + +arch snes.cpu +lorom + +incsrc "constants.asm" + +;;; these variable are defined by the crash_handle_base.asm patch and patch.rs + + +!bank_91_free_space_start = $9195bc +!bank_91_free_space_end = $91965a + +!shown_warning = $7EF59C ; whether a warning has already been shown since X-Ray initialized + +org $91816f +xmodefix: + php + jsr $81a9 ; this fixes regular xmode collision by using the correct pose lookup routine for all collisions + lda $0a78 ; load frozen time variable + beq .skip ; if time is NOT frozen skip over the next instruction (jump to xmode crash handler.) + lda #$0045 ; load the msg bug id for X-Mode Collision + jsr xmode ; now in same bank so uses a jsr. +.skip + plp + rts + +assert pc() <= $918181 ; Make sure we don't overwrite the next routine. + +org $91cafe + jmp hook_setup_xray +return_setup_xray: + +;;; +;;; custom code - currently only using up to {9195D2} {approx 130bytes free, reserved for more future xmode warn fix.} +;;; +org !bank_91_free_space_start +xmode: + lda !crash_toggles + and #$F000 + beq .default + cmp #$2000 + beq .fix +.warn + lda !shown_warning + bne .fix + inc + sta !shown_warning ; set !shown_warning to 1 + lda #$0045 + jsl !bug_dialog +.fix + rts +.default + lda #$0045 + jsl !bug_dialog + jsl !kill_samus + rts + +; initialize shown_warning to 0 when starting to use x-ray +hook_setup_xray: + sta $0a78 ; run hi-jacked instruction: time-is-frozen flag = 1 + lda #$00 + sta !shown_warning + jmp return_setup_xray + +assert pc() <= !bank_91_free_space_end \ No newline at end of file diff --git a/patches/src/crash_handle_yapping.asm b/patches/src/crash_handle_yapping.asm new file mode 100644 index 000000000..417ff7d1d --- /dev/null +++ b/patches/src/crash_handle_yapping.asm @@ -0,0 +1,66 @@ +; Yapping maw shinespark crash +; Noted by PJBoy: https://patrickjohnston.org/bank/A8#fA68A + + +arch snes.cpu +lorom + +incsrc "constants.asm" + +;;; these variable are defined by the crash_handle_base.asm patch and patch.rs + + +!bank_85_free_space_start = $85b5b4 +!bank_85_free_space_end = $85b5f1 + +!bank_90_free_space_start = $90fc10 +!bank_90_free_space_end = $90fc20 + + +;;; hooks into vanilla code + +org $90d354 + jsr yapping_maw_crash + +;;; custom code + +org !bank_90_free_space_start +yapping_maw_crash: + cmp #$0005 ; valid table entries are 0-2 * 2 + bcc .skip + jsl ym_crash + rts +.skip + jmp ($d37d,x) ; valid entry + +assert pc() <= !bank_90_free_space_end + +org !bank_85_free_space_start +ym_crash: + lda !crash_toggles + and #$0f00 + beq .default + cmp #$0200 + beq .fix +.warn + lda #$0043 ; bug ID + jsl !bug_dialog +.fix + lda #$d3f3 + sta $0a58 + lda #$001e + sta $0aa2 + sta $0ac0 + sta $0ac2 + lda #$0000 + ldx #$0000 + ldy #$0004 + rtl +.default + lda #$0043 ; bug ID + jsl !bug_dialog + jsl !kill_samus + rtl + + +assert pc() <= !bank_85_free_space_end \ No newline at end of file diff --git a/patches/src/vanilla_bugfixes.asm b/patches/src/vanilla_bugfixes.asm index 324172bcb..3a6ec687e 100644 --- a/patches/src/vanilla_bugfixes.asm +++ b/patches/src/vanilla_bugfixes.asm @@ -8,30 +8,36 @@ arch snes.cpu lorom -!bank_80_free_space_start = $80D200 +incsrc "constants.asm" + +!bank_80_free_space_start = $80D200 ; camera alignment fix. !bank_80_free_space_end = $80D240 -!bank_86_free_space_start = $86F4B0 -!bank_86_free_space_end = $86F4D0 -!msg_crash_timer_override = $7EF596 +!bank_82_free_space_start = $82C27D ; reserve icon ui fix. +!bank_82_free_space_end = $82C298 + +!bank_84_free_space_start = $84EFD7 ; maridia tube fix +!bank_84_free_space_end = $84F000 + +!bank_86_free_space_start = $86F4B0 ; powamp projectile fix +!bank_86_free_space_end = $86F4D0 -incsrc "constants.asm" ; Fix the crash that occurs when you kill an eye door whilst a eye door projectile is alive ; See the comments in the bank logs for $86:B6B9 for details on the bug ; The fix here is setting the X register to the enemy projectile index, ; which can be done without free space due to an unnecessary RTS in the original code org $86B704 -BEQ ret -TYX + BEQ ret + TYX org $86B713 -ret: + ret: ;;; skips suits acquisition animation org $848717 ;rep 4 : nop - JSL $91DEBA ; call the load samus suit palette to update the suit. + JSL $91DEBA ; call the load samus suit palette to update the suit. assert pc() <= $84871B ; just to make sure the next instruction isn't overwritten @@ -43,21 +49,24 @@ org $91b629 ;;; fix screw attack select in pause menu org $82b4c4 cpx #$000c + ;;; In inventory menu, when having only a beam and a suit you have ;;; to press right+up to go from beam to suit. ;;; It's not natural, so fix it to only require right. + org $82b000 + bcc $64 ;; test of return of $B4B7 compare A and #$0000, ;; when no item found A==#$ffff, which sets the carry, ;; so when carry is clear it means that an item was found in misc. ;; if no item was found in misc, we check in boots then in suits, ;; so if an item is found in both boots and suits, as suits is ;; tested last the selection will be set on suits. - bcc $64 ;;; fix morph ball in hidden chozo PLM org $84e8ce db $04 + org $84ee02 db $04 @@ -83,6 +92,7 @@ assert pc() <= $a0f830 ;;; allow all possible save slots (needed for area rando extra stations) org $848d0c and #$001f + ;;; For an unknown reason, the save station we put in main street ;;; sometimes (circumstances unclear) spawn two detection PLMs ;;; instead of one. These PLMs are supposed to precisely detect @@ -96,14 +106,18 @@ org $848d0c ;;; hijack in detection block PLM code when samus is ;;; positioned correctly + org $84b5d4 search_loop_start: jmp save_station_check + org $84b5d9 search_loop_cont: + org $84b5df search_loop_found: -;;; some unused bank 84 space + +;;; some unused bank 84 space org $84858c save_station_check: cmp $1c87,x ; original block coord check @@ -119,7 +133,6 @@ save_station_check: pla jmp search_loop_found -;;; end of unused space assert pc() <= $8485b2 @@ -142,7 +155,6 @@ fix_big_boy: org $A9EF80 .done - ; Fix Bomb Torizo crumbling animation (which can be very messed up if the player earlier visited a room ; that maxed out enemy projectiles) org $86A8FD @@ -207,6 +219,7 @@ check_item_plm: rts assert pc() <= $848398 + org $848398 special_xray_end: @@ -216,27 +229,6 @@ special_xray_end: org $b4bda3 bpl $f8 ; was bne $f8 -; Fix auto-reserve / pause bug -; -; This patch will initiate the death sequence if pause hit with auto-reserve enabled -; on exact frame that leads to crash. -; -; (thanks to Benox50 for his initial patch, nn44/aquanight for the light pillar fix) - -!bank_82_free_space_start = $82fbf0 -!bank_82_free_space_end = $82fc30 - -org $828b3f - jsr pause_func : nop ; gamestate 1Ch (unused) handler - -org !bank_82_free_space_start -pause_func: - lda #$0041 ; msg ID - jsl bug_dialog - stz $9d6 ; clear reserve health - rts - -assert pc() <= !bank_82_free_space_end ; Fix for powamp projectile bug ; @@ -275,236 +267,6 @@ assert pc() <= !bank_86_free_space_end org $80a27a lda #$a29b -; Yapping maw shinespark crash -; Noted by PJBoy: https://patrickjohnston.org/bank/A8#fA68A -; If bug triggered, show dialog box and then initiate death sequence. - -org $90d354 - jsr yapping_maw_crash - -!bank_90_free_space_start = $90fc10 -!bank_90_free_space_end = $90fc20 - -org !bank_90_free_space_start -yapping_maw_crash: - cmp #$0005 ; valid table entries are 0-2 * 2 - bcc .skip - lda #$0043 ; bug ID - jsl bug_dialog - rts - -.skip - jmp ($d37d,x) ; valid entry - -assert pc() <= !bank_90_free_space_end - -;;; Spring ball menu crash fix by strotlog. -;;; Fix obscure vanilla bug where: turning off spring ball while bouncing, can crash in $91:EA07, -;;; or exactly the same way as well in $91:F1FC. -;;; Adapted for map rando by Stag Shot: -;;; If bug triggered, show dialog box and then initiate death sequence. - -org $91ea07 - jsl spring_ball_crash - -org $91f1fc - jsl spring_ball_crash - -!bank_85_free_space_start = $85b000 ; do not change, first jmp used externally -!bank_85_free_space_end = $85b5FF - -org !bank_85_free_space_start - jmp bug_dialog ; for external calls, do not move - -spring_ball_crash: - lda $0B20 ; morph bounce state - cmp #$0600 ; bugged? - bcc .skip - sep #$20 - lda #$42 ; bug ID - sta $00cf ; set flag to prevent unpause from resetting gamestate to 8 - rep #$30 - jsl bug_dialog - lda #$0000 - stz $0B20 - rtl - -.skip - lda $0B20 ; replaced code - asl ; - rtl - -;;; Implementation of custom dialog boxes -;;; Requires hooking multiple functions to support extended msg IDs (0x40+) -;;; and additional lookup tables - -bug_dialog: ; A = msg ID - and #$00ff - pha - sep #$20 - lda #$0f ; restore screen brightness to full - sta $51 - sta !msg_crash_timer_override ; messagebox timer will check if this is 0 (if its non zero load a longer time) - rep #$30 - jsl $808338 ; wait for NMI - - pla ; dlg box parameter - jsl $858080 ; dlg box - - lda #$8000 ; init death sequence (copied from $82db80) - sta $a78 - lda #$0011 - jsl $90f084 - - lda #$0013 ; set gamestate - sta $998 - rtl - -hook_message_box: - rep #$30 - lda $1c1f - cmp #$0040 ; custom boxes >= 0x40 - bcs .custom - jmp $8241 ; original func - -.custom - ldx #(new_message_boxes-$869b) ; ptr for extended lookup table - jmp $824f - -hook_index_lookup: - lda $1c1f - cmp #$0040 - bcs .custom - rts - -.custom - sec - sbc #$0040 - rts - -hook_message_table: - adc $34 ; replaced code - tax ; - lda $1c1f - cmp #$0040 - bcs .custom - rts - -.custom - txa - clc - adc #(new_message_boxes-$869b) ; adjust ptr for extended table - tax - rts - -hook_button_lookup: - lda $1c1f - cmp #$0040 - bcs .custom - rts - -.custom - lda #$0001 ; blank button tilemap - ldy #(reserve_pause_msg-$8426) ; blank button letter - rts - -; custom messages start at 0x41 -new_message_boxes: - dw $83c5, $825a, reserve_pause_msg ; 0x41 - dw $83c5, $825a, springball_msg ; 0x42 - dw $83c5, $825a, yapping_maw_msg ; 0x43 - dw $83c5, $825a, oob_msg ; 0x44 - dw $83c5, $825a, xmode_msg ; 0x45 - dw $0000, $0000, msg_end - -table "tables/dialog_chars.tbl",RTL - -reserve_pause_msg: - dw $000e,$000e,$000e, " GAME CRASH! ", $000e,$000e,$000e - dw $000e,$000e,$000e, " ", $000e,$000e,$000e - dw $000e,$000e,$000e, " PAUSED ON EXACT FRAME ", $000e,$000e,$000e - dw $000e,$000e,$000e, " AUTO-REFILL STARTED! ", $000e,$000e,$000e - -springball_msg: - dw $000e,$000e,$000e, " GAME CRASH! ", $000e,$000e,$000e - dw $000e,$000e,$000e, " ", $000e,$000e,$000e - dw $000e,$000e,$000e, "UNEQUIPPED SPRING BALL IN ", $000e,$000e,$000e - dw $000e,$000e,$000e, "UNDERWATER NEUTRAL BOUNCE!", $000e,$000e,$000e - -yapping_maw_msg: - dw $000e,$000e,$000e, " GAME CRASH! ", $000e,$000e,$000e - dw $000e,$000e,$000e, " ", $000e,$000e,$000e - dw $000e,$000e,$000e, " YAPPING MAW SHINESPARK ", $000e,$000e,$000e - dw $000e,$000e,$000e, " END WITH NO INPUTS HELD! ", $000e,$000e,$000e - -oob_msg: - dw $000e,$000e,$000e, " ", $000e,$000e,$000e - dw $000e,$000e,$000e, " SAMUS OUT-OF-BOUNDS! ", $000e,$000e,$000e - dw $000e,$000e,$000e, " ", $000e,$000e,$000e - dw $000e,$000e,$000e, " ", $000e,$000e,$000e - -xmode_msg: - dw $000e,$000e,$000e, " GAME CRASH! ", $000e,$000e,$000e - dw $000e,$000e,$000e, " ", $000e,$000e,$000e - dw $000e,$000e,$000e, " X-MODE TILE COLLISION ", $000e,$000e,$000e - dw $000e,$000e,$000e, "COLLIDED WITH A SOLID TILE", $000e,$000e,$000e - -msg_end: - -hook_msgbox_delay: - pha - lda !msg_crash_timer_override - beq .nochange - ldx #$005a ; (put 1.5 seconds on the clock) - lda #$00 - sta !msg_crash_timer_override ; clear our special variable so then next msgbox will have whatever timer was set on generation -.nochange - pla - jsr $8136 ; hi-jacked instruction. - rts - -assert pc() <= !bank_85_free_space_end - - ;$85:8493 20 36 81 JSR $8136 [$85:8136] ;\ -org $858493 ; before we do things, lets double check we are not in a crash dialog (if so we want a longer timer) - jsr hook_msgbox_delay - -org $858093 - jsr hook_message_box - -org $8582e5 - jsr hook_index_lookup - -org $8582ee - jsr hook_message_table - -org $85840c - jsr hook_button_lookup - -; hook unpause to prevent resetting gamestate to 8 if crash ID set - -org $8293bb - jmp check_unpause - -!bank_82_free_space2_start = $82f810 -!bank_82_free_space2_end = $82f830 - -org !bank_82_free_space2_start -check_unpause: - php - sep #$20 - lda $00cf ; pending crash ID - stz $00cf - cmp #$42 ; springball? - bne .skip - plp - jmp $93c1 ; skip changing gamestate -.skip - plp - lda #$0008 ; replaced code - jmp $93be - -assert pc() <= !bank_82_free_space2_end ; Map scrolling bug ; Leftmost edge function @ $829f4a has an off-by-one bug when scanning @@ -514,27 +276,9 @@ assert pc() <= !bank_82_free_space2_end org $829f90 adc #$7c -; X-Mode collision fix - nn_357 - -org $91816f ; rewrite original input handler for solid tile collision to free up space. -- thanks to StagShot for noticing the rep$30 isn't needed here, it's already initialized by the single caller to this function. - ; whole fix can now fit in the original function. - PHP - JSR $81A9 ; this fixes regular xmode collision by using the correct pose lookup routine for all collisions - LDA $0A78 ; load frozen time variable - BEQ $07 ; if time is NOT frozen skip over the next instruction (kill samus) - LDA #$0045 ; load the msg bug id for X-Mode Collision - JSL $85B000 ; collision with solid tile while time is frozen is only possible in x-mode so jump to code that will kill samus rather than hardlock (retain vanilla behaviour) - PLP - RTS - -assert pc() <= $918181 ; Make sure we don't overwrite the next routine. - ; (Maridia Tube Fix - written by AmoebaOfDoom) ;patches horizontal PLM updates to DMA tiles even when the PLM is above the screen if part of it is on the screen -!bank_84_free_space_start = $84EFD7 -!bank_84_free_space_end = $84F000 - org $848DA0 SkipEntry_Inject: JMP SkipEntry @@ -579,28 +323,19 @@ org $84B7EF ; PLM $B8AC (speed booster escape) LDA $09A4 [$7E:09A4] ; vanilla bugfix, ui shows reserve icon when only boots item is equipped. -; - -!bank_83_free_space_start = $83BA00 -!bank_83_free_space_end = $83BA15 - -org !bank_83_free_space_start - -BNE .found -INX -INX -CPX #$0006 -BMI .loop -JML $82AC15 +; this is due to a missing conditional branch instruction. +org $82AC03 + jmp $c27d ; !bank_82_free_space_start [bankless form of this] + nop #2 + +org !bank_82_free_space_start + bne .found + inx + inx + cpx #$0006 + jmp $AC08 .found -JML $82AC0C - -.loop -JML $82AC00 - -assert pc() <= !bank_83_free_space_end + jmp $AC0C -org $82AC03 - JML !bank_83_free_space_start - nop #5 \ No newline at end of file +assert pc() <= !bank_82_free_space_end diff --git a/rust/data/presets/full-settings/Community Race Season 4.json b/rust/data/presets/full-settings/Community Race Season 4.json index 58859f508..b8796bb3c 100644 --- a/rust/data/presets/full-settings/Community Race Season 4.json +++ b/rust/data/presets/full-settings/Community Race Season 4.json @@ -4544,6 +4544,13 @@ "all_items_spawn": true, "acid_chozo": true, "remove_climb_lava": true, + "crash_fixes": { + "preset": "Death", + "spring_ball": "Death", + "yapping_maw": "Death", + "auto_reserve": "Death", + "x_mode": "Death" + }, "etank_refill": "Full", "energy_station_reserves": true, "disableable_etanks": "Standard", diff --git a/rust/data/presets/full-settings/Default.json b/rust/data/presets/full-settings/Default.json index b7818e54d..82825ecb8 100644 --- a/rust/data/presets/full-settings/Default.json +++ b/rust/data/presets/full-settings/Default.json @@ -4544,6 +4544,13 @@ "all_items_spawn": true, "acid_chozo": true, "remove_climb_lava": true, + "crash_fixes": { + "preset": "Death", + "spring_ball": "Death", + "yapping_maw": "Death", + "auto_reserve": "Death", + "x_mode": "Death" + }, "energy_station_reserves": false, "etank_refill": "Vanilla", "disableable_etanks": "Standard", diff --git a/rust/data/presets/quality-of-life/Default.json b/rust/data/presets/quality-of-life/Default.json index d2f626b38..68a728d35 100644 --- a/rust/data/presets/quality-of-life/Default.json +++ b/rust/data/presets/quality-of-life/Default.json @@ -33,6 +33,13 @@ "all_items_spawn": true, "acid_chozo": true, "remove_climb_lava": true, + "crash_fixes": { + "preset": "Death", + "spring_ball": "Death", + "yapping_maw": "Death", + "auto_reserve": "Death", + "x_mode": "Death" + }, "energy_station_reserves": false, "etank_refill": "Vanilla", "disableable_etanks": "Standard", diff --git a/rust/data/presets/quality-of-life/High.json b/rust/data/presets/quality-of-life/High.json index fdcd0b9f9..26bfd1fef 100644 --- a/rust/data/presets/quality-of-life/High.json +++ b/rust/data/presets/quality-of-life/High.json @@ -33,6 +33,13 @@ "all_items_spawn": true, "acid_chozo": true, "remove_climb_lava": true, + "crash_fixes": { + "preset": "Death", + "spring_ball": "Death", + "yapping_maw": "Death", + "auto_reserve": "Death", + "x_mode": "Death" + }, "energy_station_reserves": true, "etank_refill": "Full", "disableable_etanks": "Standard", diff --git a/rust/data/presets/quality-of-life/Low.json b/rust/data/presets/quality-of-life/Low.json index 842fc58f6..9e85813fc 100644 --- a/rust/data/presets/quality-of-life/Low.json +++ b/rust/data/presets/quality-of-life/Low.json @@ -33,6 +33,13 @@ "all_items_spawn": false, "acid_chozo": false, "remove_climb_lava": false, + "crash_fixes": { + "preset": "Death", + "spring_ball": "Death", + "yapping_maw": "Death", + "auto_reserve": "Death", + "x_mode": "Death" + }, "energy_station_reserves": false, "etank_refill": "Vanilla", "disableable_etanks": "Standard", diff --git a/rust/data/presets/quality-of-life/Max.json b/rust/data/presets/quality-of-life/Max.json index a1f389638..c970895ed 100644 --- a/rust/data/presets/quality-of-life/Max.json +++ b/rust/data/presets/quality-of-life/Max.json @@ -33,6 +33,13 @@ "all_items_spawn": true, "acid_chozo": true, "remove_climb_lava": true, + "crash_fixes": { + "preset": "Silent", + "spring_ball": "Silent", + "yapping_maw": "Silent", + "auto_reserve": "Silent", + "x_mode": "Silent" + }, "energy_station_reserves": true, "etank_refill": "Full", "disableable_etanks": "Standard", diff --git a/rust/data/presets/quality-of-life/Off.json b/rust/data/presets/quality-of-life/Off.json index 93d16b12f..9d224a5de 100644 --- a/rust/data/presets/quality-of-life/Off.json +++ b/rust/data/presets/quality-of-life/Off.json @@ -33,6 +33,13 @@ "all_items_spawn": false, "acid_chozo": false, "remove_climb_lava": false, + "crash_fixes": { + "preset": "Death", + "spring_ball": "Death", + "yapping_maw": "Death", + "auto_reserve": "Death", + "x_mode": "Death" + }, "energy_station_reserves": false, "etank_refill": "Vanilla", "disableable_etanks": "Off", diff --git a/rust/maprando-web/src/randomize_helpers.rs b/rust/maprando-web/src/randomize_helpers.rs index 0ec7b32db..a263fd10a 100644 --- a/rust/maprando-web/src/randomize_helpers.rs +++ b/rust/maprando-web/src/randomize_helpers.rs @@ -10,9 +10,9 @@ use maprando::{ randomize::{DifficultyConfig, ItemPriorityGroup, Randomization, get_starting_items}, seed_repository::{Seed, SeedFile}, settings::{ - AreaAssignmentBaseOrder, AreaAssignmentPreset, DisableETankSetting, DoorLocksSize, - ETankRefill, FillerItemPriority, ItemCount, RandomizerSettings, SpeedBooster, WallJump, - get_objective_groups, + AreaAssignmentBaseOrder, AreaAssignmentPreset, CrashFixesPreset, DisableETankSetting, + DoorLocksSize, ETankRefill, FillerItemPriority, ItemCount, RandomizerSettings, + SpeedBooster, WallJump, get_objective_groups, }, spoiler_log::SpoilerLog, spoiler_map, @@ -139,6 +139,16 @@ impl SeedHeaderTemplate<'_> { .join(", ") } + fn crash_fix_preset(&self) -> &'static str { + match self.settings.quality_of_life_settings.crash_fixes.preset { + Some(CrashFixesPreset::Crash) => "Crash", + Some(CrashFixesPreset::Death) => "Death", + Some(CrashFixesPreset::Warn) => "Warn", + Some(CrashFixesPreset::Silent) => "Silent", + None => "Custom", + } + } + fn game_variations(&self) -> Vec<&str> { let mut game_variations = vec![]; let other_settings = &self.settings.other_settings; diff --git a/rust/maprando-web/templates/generate/crash_fixes.html b/rust/maprando-web/templates/generate/crash_fixes.html new file mode 100644 index 000000000..99bf2aa1e --- /dev/null +++ b/rust/maprando-web/templates/generate/crash_fixes.html @@ -0,0 +1,87 @@ +