diff --git a/README.md b/README.md index 88b8943..1cada02 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,9 @@ To be assembled using [Asar](https://github.com/RPGHacker/asar), see the Makefil - infinite lives - DK coins will always respawn - manage your kongs on the map (by BlueImp) - - `L` to toggle between having 1 or 2 kongs - - `R` to change which kong is in front + - hold `R` and press `L` to toggle between having 1 or 2 kongs + - hold `R` and press `select` to change which kong is in front +- hold `L` and press `R` to toggle the autojump state on and off +- hold `L` and press `select` to quickly return to the overworld from a world map you're probably gonna need a completed save file for now, sorry diff --git a/src/defines.asm b/src/defines.asm index dfc0752..bea4c35 100644 --- a/src/defines.asm +++ b/src/defines.asm @@ -1,4 +1,4 @@ -@include +include ; define rom locations based on rom revision if !rom_revision == 0 @@ -15,6 +15,8 @@ if !rom_revision == 0 end_bananas = $BEC89F draw_digit = $BEC814 freerom_BE = $BEFB8A + play_high_priority_sound = $B58021 + vgheroes_check = $B4877D elseif !rom_revision == 1 hijack_level = $808640 hijack_nmi = $80F3D8 @@ -29,6 +31,8 @@ elseif !rom_revision == 1 end_bananas = $BEC8AA draw_digit = $BEC81F freerom_BE = $BEFB67 + play_high_priority_sound = $B58021 + vgheroes_check = $B4878F endif ; constants @@ -36,6 +40,8 @@ endif !dropped_frames_y = $0900 !timer_x = $00CC !timer_y = $0900 +!sfx_notallowed = $5F +!sfx_balloon = $2C ; wram !freeram = $1A00 @@ -46,6 +52,8 @@ macro def_freeram(id, size) !freeram_used #= !freeram_used+ endmacro +!nmi_pointer = $0020 +!nmi_pointer_dp = $20 !io_axlr = $050E !io_byetudlr = $050F !io_axlr_1f = $0510 @@ -53,13 +61,19 @@ endmacro !fade_type = $0513 !main_kong = $0593 !follower_kong = $0597 +!map_index = $06B1 !current_map_kong = $08A4 !pause_flags = $08C2 !extra_kong_flag = $08C2 !level_state = $0AF1 +!counter_60hz_pausable = $002A +!counter_60hz_pausable_dp = $2A !counter_60hz = $2C +!reg_joy1l = $4218 +!reg_joy1h = $4219 + %def_freeram(previous_60hz, 2) %def_freeram(dropped_frames, 2) diff --git a/src/edits.asm b/src/edits.asm index 4acf440..e7ea2b3 100644 --- a/src/edits.asm +++ b/src/edits.asm @@ -1,4 +1,4 @@ -@include +include ; u1.0 checksum org $00FFDC @@ -21,3 +21,7 @@ org bypass_hud_face ; always spawn dk coins as not collected org dk_coin_check BRA $0E + +; don't load the video game heroes screen +org vgheroes_check + BRA $11 : NOP diff --git a/src/hijacks.asm b/src/hijacks.asm index b23ca1d..322ddb8 100644 --- a/src/hijacks.asm +++ b/src/hijacks.asm @@ -1,4 +1,4 @@ -@include +include org hijack_level JSL every_igt_frame diff --git a/src/hud.asm b/src/hud.asm index 82e5d72..897c2fc 100644 --- a/src/hud.asm +++ b/src/hud.asm @@ -1,4 +1,4 @@ -@include +include handle_displays: SEP #$20 diff --git a/src/level.asm b/src/level.asm index 352bc41..eaec50e 100644 --- a/src/level.asm +++ b/src/level.asm @@ -1,4 +1,4 @@ -@include +include every_igt_frame: JSR handle_frame_counters diff --git a/src/main.asm b/src/main.asm index 20c8ff1..ce5af1f 100644 --- a/src/main.asm +++ b/src/main.asm @@ -1,3 +1,4 @@ +asar 1.91 hirom ; 0 for 1.0 @@ -13,9 +14,9 @@ org freerom_BB incsrc "level.asm" incsrc "map.asm" -warnpc $BBFFFF +assert pc() <= $BBFFFF org freerom_BE incsrc "hud.asm" -warnpc $BEFFFF +assert pc() <= $BEFFFF diff --git a/src/map.asm b/src/map.asm index 580bfc0..d315655 100644 --- a/src/map.asm +++ b/src/map.asm @@ -1,4 +1,4 @@ -@include +include every_map_frame: STZ !dropped_frames @@ -14,6 +14,8 @@ every_map_frame: LDA !counter_60hz STA !previous_60hz + JSR check_goto_overworld + JSR check_toggle_autojump JSR check_kong_swap SEP #$20 @@ -21,11 +23,49 @@ every_map_frame: RTL +check_goto_overworld: + LDA !io_axlr : BIT #$0020 : BEQ .done ; L held? + LDA !io_byetudlr_1f : BIT #$0020 : BEQ .done ; select pressed? + + ; the nmi_pointer selects the address in bank $80 to run at the start of each frame + ; $8087D9 jumps to $B5CDFD, which loads a world map screen based on the value in map_index + LDA #$87D9 : STA !nmi_pointer_dp + STZ !map_index ; 0 = overworld + + ; $06AF/B0 seems to store a movement value for when the kongs move between map nodes + ; if you try to load the overworld while this is non-zero, you will softlock as they run offscreen + STZ $06AF + + ; $06AD seems to store a value that dictates where the kongs move after beating a level + ; it gets set even when they don't move automatically, and is only cleared when a new node is reached + ; zeroing it prevents another softlock when loading the overworld immediately after beating a level + STZ $06AD + .done: + RTS + +; when deciding whether or not to allow a jump, the game checks if B was pressed in the last 15 frames: +; current_frame_counter - frame_counter_at_time_of_B_press < 16 +; if a value is greater than $8000, it is considered negative in two's complement +; so autojump is active if the current frame counter is at least $8000 (as long as the B press var remains at zero) +check_toggle_autojump: + LDA !io_axlr : BIT #$0020 : BEQ .done ; L held? + LDA !io_axlr_1f : BIT #$0010 : BEQ .done ; R pressed? + + ; flip the frame counter between 0 (inactive) and two's complement -32768 (active) + LDA !counter_60hz_pausable_dp : AND #$8000 : EOR #$8000 : STA !counter_60hz_pausable_dp + BMI + + LDA.w #!sfx_notallowed + BRA .play_sound + + + LDA.w #!sfx_balloon + .play_sound: + JSL play_high_priority_sound + .done: + RTS + check_kong_swap: - ; if L was pressed, toggle between 1 or 2 kongs - LDA !io_axlr_1f - BIT #$0020 - BEQ .check_swap + LDA !io_axlr : BIT #$0010 : BEQ .check_swap ; R held? + LDA !io_axlr_1f : BIT #$0020 : BEQ .check_swap ; L pressed? ; toggle sprite visibility LDX !follower_kong @@ -39,10 +79,8 @@ check_kong_swap: STA !extra_kong_flag .check_swap: - ; if R was pressed, change which kong is in front - LDA !io_axlr_1f - BIT #$0010 - BEQ .done + LDA !io_axlr : BIT #$0010 : BEQ .done ; R held? + LDA !io_byetudlr_1f : BIT #$0020 : BEQ .done ; select pressed? ; toggle between diddy and dixie LDA !current_map_kong