diff --git a/patches/ips/escape.ips b/patches/ips/escape.ips index 14c924830..f80451da6 100644 Binary files a/patches/ips/escape.ips and b/patches/ips/escape.ips differ diff --git a/patches/ips/escape_items.ips b/patches/ips/escape_items.ips index 0c1a28af8..0c832380f 100644 Binary files a/patches/ips/escape_items.ips and b/patches/ips/escape_items.ips differ diff --git a/patches/ips/item_count.ips b/patches/ips/item_count.ips new file mode 100644 index 000000000..49343a458 Binary files /dev/null and b/patches/ips/item_count.ips differ diff --git a/patches/ips/new_game.ips b/patches/ips/new_game.ips index 5328994b3..8cb3a2425 100644 Binary files a/patches/ips/new_game.ips and b/patches/ips/new_game.ips differ diff --git a/patches/rom_map/Bank 84.txt b/patches/rom_map/Bank 84.txt index f9ae260dc..d47b3aa74 100644 --- a/patches/rom_map/Bank 84.txt +++ b/patches/rom_map/Bank 84.txt @@ -3,7 +3,7 @@ EFD7 - EFE7: ; vanilla_camerafixes.asm F000 - F0E1: ; walljump_plm.asm F0E2 - F27F: ; split_speed_plm.asm F28B - F2FF: ; mb_barrier_clear.asm -F300 - F30C: ; escape_items.asm +F300 - F380: [FREE] F380 - F418: ; escape.asm F480 - F489: ; etank_refill_full.asm F490 - F499: ; reserve_hud.asm @@ -24,4 +24,4 @@ F900 - F98D: ; escape.asm FA00 - FB46: ; gray_doors.asm FC00 - FC0E: ; fix_kraid_vomit.asm FC40 - FC9D: ; escape_autosave.asm -FCC0 - FFEE: ; beam_doors.asm +FCC0 - FFEE: ; beam_doors.asm \ No newline at end of file diff --git a/patches/rom_map/Bank 8B.txt b/patches/rom_map/Bank 8B.txt index 356d55b11..67209653f 100644 --- a/patches/rom_map/Bank 8B.txt +++ b/patches/rom_map/Bank 8B.txt @@ -1,3 +1,3 @@ F760 - F769: ; escape_items.asm F770 - F893: ; credits.asm -F900 - F91B: ; escape.asm +F900 - FAC5: ; item_count.asm \ No newline at end of file diff --git a/patches/rom_map/Bank B5.txt b/patches/rom_map/Bank B5.txt index 7466a087e..09881a741 100644 --- a/patches/rom_map/Bank B5.txt +++ b/patches/rom_map/Bank B5.txt @@ -8,7 +8,7 @@ FE06 - FE07: Initial items equipped (to be copied to $09A2) FE08 - FE09: Initial beams collected (to be copied to $09A8) FE0A - FE0B: Initial beams equipped (to be copied to $09A6) FE0C - FE11: Initial boss bits (to be copied to $7ED828-2E) -FE12 - FE51: Initial item bits (to be copied to $7ED870-B0) +FE12 - FE51: Initial item bits (to be copied to $7ED870-B0); [new_game.asm, item_count.asm] FE52 - FE53: Initial energy (to be copied to $09C2) FE54 - FE55: Initial max energy (to be copied to $09C4) FE56 - FE57: Initial reserves (to be copied to $09D6) diff --git a/patches/rom_map/Bank DF.txt b/patches/rom_map/Bank DF.txt index e4411ab9c..270a1b95f 100644 --- a/patches/rom_map/Bank DF.txt +++ b/patches/rom_map/Bank DF.txt @@ -5,10 +5,11 @@ E200 - E212: ; alternate_door_colors.asm E212 - FEEF: [free] FEF0 - FEFF: seed name (null-terminated ASCII string) FF00 - FF03: display seed / internal seed hash -FF04 - FF04: [FREE] +FF04 - FF04: [free] FF05 - FF06: randomizer settings: - bitmask $0001: walljump-boots item enabled - bitmask $0002: split speedbooster item enabled FF07 - FF08: number of frames of artificial lag to add to the unpause black screen FF09 - FF0D: randomizer settings: skill/progression/qol/objectives/maplayout (autotracker use) - stored as single byte ordinal numbers, if a setting has a custom option then byte is set to 0 +FF0E - FF0F: sum of unplaced / nothing items (used for item credits fractional display with stop item placement early) diff --git a/patches/rom_map/RAM.txt b/patches/rom_map/RAM.txt index 97a1939d0..43f496c4e 100644 --- a/patches/rom_map/RAM.txt +++ b/patches/rom_map/RAM.txt @@ -4,8 +4,7 @@ $CF: vanilla_bugfixes.asm (used by crash dialogues to prevent unpause from reset $09EC: number of disabled ETanks (saved to SRAM) $0A1A: previous reserve health (reserve_hud.asm) $1F5B: map area (like $079F) -$1F5D: items collected before getting them all for free at hyper beam (to use in "rate for collecting items" - after credits). This is a snapshot of $09A4, captured in `escape.asm`, at the time of getting hyper beam. +$1F5D: [free]. $1F60: fast_reload.asm $1F62: map area backup in pause menu (like $079F) $1F64: escape refill complete diff --git a/patches/src/escape.asm b/patches/src/escape.asm index e195f1974..0e9e671c0 100644 --- a/patches/src/escape.asm +++ b/patches/src/escape.asm @@ -11,8 +11,6 @@ arch snes.cpu !bank_82_free_space_end = $82FD00 !bank_84_free_space_start = $84F380 !bank_84_free_space_end = $84F480 -!bank_8b_free_space_start = $8BF900 -!bank_8b_free_space_end = $8BF940 !bank_8f_free_space_start = $8FF600 !bank_8f_free_space_end = $8FF700 !bank_a1_free_space_start = $a1f000 ; careful moving this, as it must match things in patch.rs @@ -629,7 +627,6 @@ org !bank_84_free_space_start CLC RTL -print pc assert pc() <= !bank_84_free_space_end ; hook for when dachora hits block above it @@ -648,20 +645,6 @@ dachora_hit_top: assert pc() <= !bank_a7_free_space_end - -; Include walljump boots and split-speed in item collection count post-credits -org $8BE65B - LDX #$001A - -org $8BE661 - BIT item_bits,x - -org !bank_8b_free_space_start -item_bits: - dw $0001, $0020, $0004, $1000, $0002, $0008, $0100, $0200, $2000, $4000, $8000, $0400, $0040, $0080 - -assert pc() <= !bank_8b_free_space_end - org $82E026 jsr enemy_gfx_load_hook diff --git a/patches/src/escape_items.asm b/patches/src/escape_items.asm index 75ea62033..e47147299 100644 --- a/patches/src/escape_items.asm +++ b/patches/src/escape_items.asm @@ -6,8 +6,6 @@ org $A9CD12 org $A9FB70 get_hyper_beam: jsl $91E4AD ; run the hi-jacked instruction - lda $09A4 - sta $1F5D ; take a snapshot of items collected, to use in "rate for collecting items" percentage after credits. lda #$F72F sta $09A2 ; all items equipped (including WallJump = $0400) sta $09A4 ; all items collected @@ -20,43 +18,4 @@ get_hyper_beam: jsl $809A3E ; Add x-ray to HUD tilemap rtl -warnpc $A9FC00 - -; hi-jack item percentage count -org $8BE62F - jsr fix_item_percent - -; free space in bank $8B -org $8BF760 -fix_item_percent: - ; restore snapshot of items collected to their state before getting them all with hyper beam (except that - ; any items collected during the escape also count). - lda $1F5D - sta $09A4 - - ldx #$0008 ; run hi-jacked instruction - rts -warnpc $8BF770 - -org $848902 - jsr escape_collect_item - -org $848929 - jsr escape_collect_item - -org $848950 - jsr escape_collect_item - -; free space in bank $84 -org $84F300 -escape_collect_item: - sta $09A4 ; run hi-jacked instruction - - ; add collected item to snapshot, to count toward item collection percentage - ; (this only matters for items collected during escape) - lda $1F5D - ora $0000, y - sta $1F5D - - rts -warnpc $84F380 \ No newline at end of file +assert pc() <= $A9FC00 \ No newline at end of file diff --git a/patches/src/item_count.asm b/patches/src/item_count.asm new file mode 100644 index 000000000..51c283ec6 --- /dev/null +++ b/patches/src/item_count.asm @@ -0,0 +1,221 @@ +; Sum item bits to calculate collection percent. +; +; credits % is displayed as a fraction if every item isn't placed. +; nn_357 / StagShot + +!bank_8b_free_space_start = $8bf900 +!bank_8b_free_space_end = $8bfae9 +!nothing_item_total = $dfff0e ; overwritten by patch.rs, contains the sum of 'nothing' +!initial_item_bits = $b5fe12 ; modified by patch.rs, also used in new_game.asm +!item_count = $12 + +org !nothing_item_total + dw $0000 + +;;; $E627: Instruction - draw item percentage count ;;; + +org $8be627 +itempercent: + php + phb + phk + plb + rep #$30 + phx + phy + jsr countitems + lda !nothing_item_total + bne .fractional + + lda !item_count + and #$00ff + cmp #$0064 + bne .not_100 + + lda $e745 ; 100% completion + sta $7e339c + lda $e747 + sta $7e33dc + lda $e741 + sta $7e339e + lda $e743 + sta $7e33de + lda $e741 + sta $7e33a0 + lda $e743 + sta $7e33e0 + bra .percent_symbol + +.not_100 + ldx #$0002 + jsr .digit2 + bra .percent_symbol + +.fractional + jsr load_fractional_tiles + lda #$0064 + sec + sbc !nothing_item_total + sta $14 + + lda !item_count + and #$00ff + ldx #$0000 + jsr .digit2 + + lda $14 + ldx #$0006 + jsr .digit2 + + lda #$3888 ; add custom '/' tile to tilemap + sta $7e33a0 + lda #$3898 + sta $7e33e0 + bra .finished + +.percent_symbol + lda #$386a + sta $7e33a2 + lda #$387a + sta $7e33e2 +.finished + ply + plx + plb + plp + rts + +.digit2 + sta $4204 + sep #$20 + lda #$0A + sta $4206 + nop #6 + rep #$20 + lda $4214 + asl a + asl a + tay + lda $e741,y + sta $7e339c,x + lda $e743,y + sta $7e33dc,x + lda $4216 + asl a + asl a + tay + lda $e741,y + sta $7e339e,x + lda $e743,y + sta $7e33de,x + rts + +assert pc() <= $8be741 ; Tilemap values for decimal digits: + +org !bank_8b_free_space_start + +countitems: + php + sep #$30 + + lda #$00 + sta !item_count + ldx #$00 + +.loop + lda !initial_item_bits,x + eor #$ff + and $7ed870,x + tay + lda bitcounttable,y + clc + adc !item_count + sta !item_count + + inx + cpx #$14 + bne .loop + + plp + rts + +load_fractional_tiles: + php + sep #$30 +WaitVB: + lda $4212 + and #$80 + beq WaitVB + + lda #$80 ; top_slash → $4880 + sta $2115 + lda #$80 + sta $2116 + lda #$48 + sta $2117 + + lda #$01 + sta $4300 + lda #$18 + sta $4301 + lda.b #top_slash + sta $4302 + lda.b #top_slash>>8 + sta $4303 + lda #$8b + sta $4304 + lda #$20 + sta $4305 + stz $4306 + lda #$01 + sta $420B + + lda #$80 ; bottom_slash → $4980 + sta $2116 + lda #$49 + sta $2117 + + lda.b #bottom_slash + sta $4302 + lda.b #bottom_slash>>8 + sta $4303 + lda #$20 + sta $4305 + stz $4306 + lda #$01 + sta $420B + + plp + rts + +top_slash: + db $00, $07, $02, $0D, $06, $09, $06, $09 + db $0C, $13, $0C, $32, $18, $26, $18, $24 + db $00, $00, $00, $00, $00, $00, $00, $00 + db $00, $00, $00, $00, $00, $00, $00, $00 + +bottom_slash: + db $18, $64, $30, $4C, $30, $C8, $60, $98 + db $60, $90, $40, $B0, $00, $E0, $00, $00 + db $00, $00, $00, $00, $00, $00, $00, $00 + db $00, $00, $00, $00, $00, $00, $00, $00 + +bitcounttable: + db $00,$01,$01,$02,$01,$02,$02,$03,$01,$02,$02,$03,$02,$03,$03,$04 + db $01,$02,$02,$03,$02,$03,$03,$04,$02,$03,$03,$04,$03,$04,$04,$05 + db $01,$02,$02,$03,$02,$03,$03,$04,$02,$03,$03,$04,$03,$04,$04,$05 + db $02,$03,$03,$04,$03,$04,$04,$05,$03,$04,$04,$05,$04,$05,$05,$06 + db $01,$02,$02,$03,$02,$03,$03,$04,$02,$03,$03,$04,$03,$04,$04,$05 + db $02,$03,$03,$04,$03,$04,$04,$05,$03,$04,$04,$05,$04,$05,$05,$06 + db $02,$03,$03,$04,$03,$04,$04,$05,$03,$04,$04,$05,$04,$05,$05,$06 + db $03,$04,$04,$05,$04,$05,$05,$06,$04,$05,$05,$06,$05,$06,$06,$07 + db $01,$02,$02,$03,$02,$03,$03,$04,$02,$03,$03,$04,$03,$04,$04,$05 + db $02,$03,$03,$04,$03,$04,$04,$05,$03,$04,$04,$05,$04,$05,$05,$06 + db $02,$03,$03,$04,$03,$04,$04,$05,$03,$04,$04,$05,$04,$05,$05,$06 + db $03,$04,$04,$05,$04,$05,$05,$06,$04,$05,$05,$06,$05,$06,$06,$07 + db $02,$03,$03,$04,$03,$04,$04,$05,$03,$04,$04,$05,$04,$05,$05,$06 + db $03,$04,$04,$05,$04,$05,$05,$06,$04,$05,$05,$06,$05,$06,$06,$07 + db $03,$04,$04,$05,$04,$05,$05,$06,$04,$05,$05,$06,$05,$06,$06,$07 + db $04,$05,$05,$06,$05,$06,$06,$07,$05,$06,$06,$07,$06,$07,$07,$08 + +assert pc() <= !bank_8b_free_space_end \ No newline at end of file diff --git a/patches/src/new_game.asm b/patches/src/new_game.asm index 6bc8eefef..546771aeb 100644 --- a/patches/src/new_game.asm +++ b/patches/src/new_game.asm @@ -127,9 +127,6 @@ startup: dex bne .item_bits_loop - ; Set items collected for escape (to make item collection rate show 100%, only applicable for "Escape" start): - lda #$F32F - sta $1F5D ; Unlock Tourian statues room (to avoid camera glitching when entering from bottom, and also to ensure game is ; beatable since we don't take it into account as an obstacle in the item randomization logic) diff --git a/rust/maprando/src/patch.rs b/rust/maprando/src/patch.rs index a05f7ea5f..52e4f4e5e 100644 --- a/rust/maprando/src/patch.rs +++ b/rust/maprando/src/patch.rs @@ -487,6 +487,7 @@ impl Patcher<'_> { "fix_dust_torizo", "fix_choot", "resource_collection_hudcap", + "item_count", ]; patches.push("new_game"); @@ -839,6 +840,7 @@ impl Patcher<'_> { } fn place_items(&mut self) -> Result<()> { + let mut nothing_count: isize = 0; for (&item, &loc) in iter::zip( &self.randomization.item_placement, &self.game_data.item_locations, @@ -848,6 +850,7 @@ impl Patcher<'_> { let new_plm_type = item_to_plm_type(item, orig_plm_type); self.rom.write_u16(item_plm_ptr, new_plm_type)?; if item == Item::Nothing { + nothing_count += 1; let idx = self.rom.read_u16(item_plm_ptr + 4).unwrap() as usize; self.nothing_item_bitmask[idx >> 3] |= 1 << (idx & 7); @@ -859,6 +862,7 @@ impl Patcher<'_> { } } } + self.rom.write_u16(snes2pc(0xdfff0e), nothing_count)?; Ok(()) } @@ -2419,7 +2423,6 @@ impl Patcher<'_> { // Use Tourian load station 2, set up in escape_autosave.asm self.rom.write_u16(initial_area_addr, 5)?; self.rom.write_u16(initial_load_station_addr, 2)?; - // Set all bosses defeated: self.rom.write_n(initial_boss_bits, &[7, 7, 7, 7, 7, 7])?;