diff --git a/patches/ips/map_area.ips b/patches/ips/map_area.ips index bbffbc2a3..ff409f6d5 100644 Binary files a/patches/ips/map_area.ips and b/patches/ips/map_area.ips differ diff --git a/patches/rom_map/Bank 85.txt b/patches/rom_map/Bank 85.txt index ff56a4d64..24ca85751 100644 --- a/patches/rom_map/Bank 85.txt +++ b/patches/rom_map/Bank 85.txt @@ -20,6 +20,6 @@ ACA0 - ACFF: load_flash_suit AD00 - AD40: ; crash_handle_springball.asm AD43 - AEDB: ; reserve_backward_fill.asm AEE0 - B599: ; crash_handle_base.asm -B600 - B93E: ; map_area.asm +B600 - B8E5: ; map_area.asm C000 - C450: ; savestate.asm C500 - C900: ; pause_menu_objectives.asm diff --git a/patches/src/map_area.asm b/patches/src/map_area.asm index b1a9a6320..ac17b1af0 100644 --- a/patches/src/map_area.asm +++ b/patches/src/map_area.asm @@ -1782,7 +1782,8 @@ assert pc() <= !bank_b6_freespace_end org !bank_85_freespace3_start assert pc() == !map_icon_settings -dw $0000 ; modified by customize.rs for toggling map tiles on / off. set bits high to disable tiles (bosses), (minibosses), (saves) +dw $0000 ; modified by customize.rs for toggling map tiles on / off. + ; set low nibble bits of low byte high to disable tiles (1 - bosses), (2 - minibosses), (4 - saves), (8 - helmet) ; write map icons and save markers to VRAM @@ -1813,7 +1814,6 @@ write_sprites: LDA #$0060 STA $36 ; initialize dachora state/frame count -.no_animals PLY PLX PLB @@ -1828,16 +1828,11 @@ sprite_table: ; [$b6xxxx, vram addr] .. null-terminated hook_map_icons: PHP PHB - -; draw save slot markers - LDA !map_icon_settings ; test if draw saves disabled on generation? - BIT #$0004 - BNE .finished_drawing_saves LDX #$0000 .load_lp LDA $702602,X ; area AND #$00FF - CMP #$0006 ; valid area set? + CMP #$0006 ; valid area? BCS .next CMP $1F5B ; current area? BNE .next @@ -1845,134 +1840,112 @@ hook_map_icons: LDA $702603,X ; sprite PHX ; save slot index PHA ; save sprite ID -; adjust coords for scroll LDA $702604,X ; coords JSR convert_coord_to_map PLA ; sprite -; A=sprite, X/Y=adjusted coords - JSR draw_sprite + JSR draw_sprite ; handles save/helmet toggles itself PLX ; index - .next INX #4 CPX #$000C BNE .load_lp + .finished_drawing_saves ; draw ship/bosses/mini-bosses/animals if appropriate - LDX #$0000 PHK PLB - + LDY #$0000 ; Y = marker table index .marker_lp - LDA marker_table,X ; boss byte|bit or FFFF to skip check - BNE .valid_entry - JMP .exit - -; check boss bit -.valid_entry - PHX ; index + LDA marker_table,Y ; boss byte|bit, $FFFF = always shown, 0 = end + BEQ .exit CMP #$FFFF - BEQ .boss_alive + BEQ .marker_draw PHA - AND #$FF00 XBA - TAX + AND #$00FF + TAX ; X = byte offset into $7ED828 PLA + AND #$00FF ; A = bit mask + AND $7ED828,X ; boss defeated? + BEQ .marker_draw ; no, show the marker + CPY #((marker_table_2-marker_table)*2) ; mother brain? + BNE .marker_next ; other dead bosses just lose their marker - AND #$00FF - AND $7ED828,X ; boss bit set? - BEQ .boss_alive - PLA ; index - CMP #((marker_table_2-marker_table)*2) ; mother brain? - BEQ .check_animals - JMP .next_marker_2 - -.check_animals ; MB dead, skip to dachora table if animals enabled +; mother brain dead: skip the remaining markers, show the animals instead LDA $7ED821 AND #$0080 ; already saved? - BNE .no_dachora + BNE .exit + JSR animate_dachora + LDY #(marker_table_dachora-marker_table) + BRA .marker_lp + +.marker_draw + JSR draw_marker +.marker_next + TYA + CLC + ADC #(marker_table_2-marker_table) ; index++ + TAY + BRA .marker_lp -; determine which dachora state to show (blink animation) -; $36: frame count, $37 = state (00-02) +.exit + PLB + PLP + RTL + +animate_dachora: +; $36 = (blink state << 8) | frames left until the next change DEC $36 LDA $36 - AND #$00FF ; frames - BNE .no_change - LDA $36 - XBA - AND #$00FF ; state - INC - CMP #$0003 - BNE .no_wrap - LDA #$0060 ; ~1.5s - BRA .save_state -.no_wrap - XBA - EOR #$0004 ; 4-frame delay between states -.save_state - STA $36 - XBA AND #$00FF - ASL #5 ; state*20h + BNE .done ; still counting down + LDA $36 ; low byte is 0 here, so A = state<<8 CLC - ADC #dachora_icon_open ; A = dachora_icon + state*20h -; update VRAM based on state + ADC #$0100 ; next state + CMP #$0300 + BCC .short_delay + LDA #$0060 ; wrapped to state 0, ~1.5s + BRA .set +.short_delay + ORA #$0004 ; 4-frame delay between states +.set + STA $36 + AND #$FF00 ; state<<8 + LSR #3 ; state*20h + CLC + ADC #dachora_icon_open TAX LDA #$2980 - JSR write_to_vram + JMP write_to_vram ; tail call +.done + RTS -.no_change - LDX #(marker_table_dachora-marker_table) ; set index to dachora table - BRA .marker_lp ; restart loop with new index -.no_dachora - JMP .exit - -.boss_alive - PLX ; index - PHX - LDA marker_table+2,X ; state header - TAX +draw_marker: +; Y = marker table index (preserved) + PHY + LDX marker_table+2,Y ; state header LDA $8F0010,X TAX LDA $B80000,X ; area AND #$00FF CMP $1F5B ; current area? - BNE .next_marker - PLX ; index - PHX - LDA marker_table+4,X ; room header - PHX - TAX - LDA $8F0000,X ; x/y coords - PLX ; index + BNE .done + + LDX marker_table+4,Y ; room x/y coords + LDA $8F0000,X ; A = y:x tile coords PHA - AND #$FF00 - XBA - CPX #((marker_table_2-marker_table)*2) - BCS .not_ship_1 - CLC - ADC #$0004 ; landing site map y adjustment -.not_ship_1 - TAY - PLA - AND #$00FF - CPX #((marker_table_2-marker_table)*2) - BCS .not_ship_2 - CLC - ADC #$0004 ; landing site map x adjustment -.not_ship_2 - TAX + CPY #((marker_table_2-marker_table)*2) + BCS .not_ship + ADC #$0404 ; ships: +4 tiles x and y (carry is clear here) +.not_ship JSR check_partial_reveal - BCC .next_marker - PLX ; index - PHX - PHX - LDA marker_table+4,X ; room coords - TAX - LDA $8F0000,X - JSR convert_coord_to_map + PLA ; room coords (PLA doesn't touch carry) + BCC .done + + JSR convert_coord_to_map ; X,Y = pixel position TXA - PLX ; index + PLX ; peek the index + PHX CLC ADC marker_table+8,X ; sprite x adjustment PHA @@ -1981,20 +1954,11 @@ hook_map_icons: ADC marker_table+10,X ; sprite y adjustment TAY LDA marker_table+6,X ; sprite id - PLX + PLX ; adjusted x JSR draw_sprite -.next_marker - PLA ; index -.next_marker_2 - CLC - ADC #(marker_table_2-marker_table) ; index++ - TAX - JMP .marker_lp - -.exit - PLB - PLP - RTL +.done + PLY + RTS ; marker table format ; boss bit ($7ED828 byte | bit), state header address, room header coords, sprite id, x adjustment, y adjustment @@ -2021,171 +1985,123 @@ marker_table_dachora: dw $0000 convert_coord_to_map: -; A = coords (x,y) -; returns X,Y - TAX - AND #$00FF - ASL - ASL - ASL - SEC - SBC $B1 - PHA - TXA - PLX - AND #$FF00 +; A = coords (x low byte, y high byte) +; returns X,Y = pixel position relative to map scroll + TAX ; keep copy XBA - ASL - ASL - ASL + AND #$00FF ; y + ASL #3 SEC SBC $B3 TAY + TXA + AND #$00FF ; x + ASL #3 + SEC + SBC $B1 + TAX RTS write_to_vram: ; constant: size = 0x20, src bank = $b6 ; A = vram addr ; X = src addr - PHA - PHX +; queues a 7-byte entry at $D0+$0330: size, src addr, bank, vram addr + PHA ; vram addr + PHX ; src addr LDX $0330 LDA #$0020 - STA $D0,x - INX - INX + STA $D0,x ; size PLA - STA $D0,x - INX - INX + STA $D2,x ; src addr LDA #$00B6 - STA $D0,x - INX + STA $D4,x ; bank (spills $00 into +5) PLA - STA $D0,x - INX - INX - STX $0330 + STA $D5,x ; vram addr, overwrites the spill + TXA + CLC + ADC #$0007 + STA $0330 RTS check_partial_reveal: -; X = x map coord -; Y = y map coord -; result in carry flag - PHP +; A = packed tile coords (x low byte, y high byte) +; returns carry set if the tile is partially revealed + TAX ; keep y:x copy + XBA + AND #$00FF ; y + INC + ASL #2 ; (y+1)*4 + STA $12 TXA - AND #$00FF - PHA AND #$0020 - STA $22 - PLA - AND #$001F - STA $12 - AND #$0007 - PHA ; save bit subindex of tile - LDA $12 - LSR - LSR - LSR - STA $14 - TYA - AND #$00FF - INC - STA $16 + ASL #2 ; x >= 32 ? $80 : 0 (right half of map) CLC - ADC $22 - ASL - ASL + ADC $12 + STA $12 + TXA + AND #$0018 + LSR #3 ; byte column 0-3 CLC - ADC $14 - TAX - SEP #$20 + ADC $12 ; byte offset within area + STA $12 + TXA - XBA + AND #$0007 + TAX + LDA $90AC04,X ; bit mask for x&7 + AND #$00FF + STA $14 + LDA $1F5B - XBA + AND #$00FF + XBA ; area*$100 + ORA $12 TAX - LDA $702700,X ; partial revealed byte - PLX ; bit subindex of ship tile - AND $90AC04,X ; check bit - BEQ .not_revealed - PLP - SEC + LDA $702700,X ; partial revealed byte + AND $14 + CMP #$0001 ; carry = (A != 0) RTS -.not_revealed - PLP - CLC - RTS - draw_sprite: ; A=sprite, X/Y=coords - CPY #$0020 ; check if above top map border - BCC .sprite_is_disabled + CPY #$0020 ; above top map border? + BCC .return AND #$007F - BRA .check_sprites -.sprite_enabled - PHA ; sprite - CMP #$0008 - BEQ .save_icon - CMP #$000E - BEQ .save_icon - CMP #$000F - BEQ .save_icon - CMP #$0018 - BEQ .dachora - CMP #$008D - BEQ .helmet - CMP #$004F - BCS .dachora - -.helmet - LDA #$0E00 ; helmet/ship/boss palette - BRA .write -.dachora - LDA #$0800 ; dachora palette - BRA .write -.save_icon - LDA #$0400 ; save icon palette - -.write + PHA ; sprite id for the draw call + CMP #$004F ; fold $4F-$52 onto table slots $19-$1C + BCC .lookup + SBC #$0036 ; carry is already set +.lookup + PHX ; keep x coord + TAX + LDA.l sprite_props,X ; long, so it doesn't depend on DB + PLX + AND #$00FF + STA $03 ; scratch + AND #$000F ; this sprite's disable bit(s) + AND.l !map_icon_settings + BNE .skip + LDA $03 + AND #$00F0 + ASL #5 ; palette number -> OAM attr bits 9-11 STA $03 - PLA ; sprite + PLA ; sprite id JSL $81891F -.sprite_is_disabled +.return RTS - -.check_sprites - PHA - CMP #$0013 - BEQ .test_miniboss - CMP #$000A - BEQ .test_boss - CMP #$000B - BEQ .test_ship - CMP #$000C - BEQ .test_ship - BRA .sprite_not_disabled -.test_boss - LDA !map_icon_settings - AND #$0001 - BRA .finished_spritecheck -.test_miniboss - LDA !map_icon_settings - AND #$0002 - BRA .finished_spritecheck -.test_ship - LDA !map_icon_settings - AND #$0004 -.finished_spritecheck - BNE .sprite_disabled -.sprite_not_disabled +.skip PLA - BRA .sprite_enabled -.sprite_disabled - PLA - BRA .sprite_is_disabled - + RTS + +; (palette << 4) | disable mask in !map_icon_settings +; palettes: 2 = save icon, 4 = dachora, 7 = helmet/ship/boss (default) +sprite_props: + db $70,$70,$70,$70,$70,$70,$70,$70 ; 00-07 + db $24,$70,$71,$74,$74,$78,$24,$24 ; 08 save, 0A boss, 0B/0C ship, 0D helmet, 0E/0F save + db $70,$70,$70,$72,$70,$70,$70,$70 ; 10-17 (13 = miniboss) + db $40,$40,$40,$40,$40 ; 18 dachora, 19-1C = 4F-52 dachora arms +print pc assert pc() <= !bank_85_freespace3_end ; Fixes FX for rare bug when entering right-sided door through East Pants Room diff --git a/rust/maprando-web/src/seed.rs b/rust/maprando-web/src/seed.rs index b8dd906ed..53b84ff2e 100644 --- a/rust/maprando-web/src/seed.rs +++ b/rust/maprando-web/src/seed.rs @@ -182,6 +182,7 @@ struct CustomizeRequest { save_icons: Text, boss_icons: Text, miniboss_icons: Text, + start_location_icon: Text, room_names: Text, statues_hallway_tiling: Text, statues_hallway_audio: Text, @@ -373,6 +374,7 @@ async fn customize_seed( boss_icons: req.boss_icons.0, miniboss_icons: req.miniboss_icons.0, save_icons: req.save_icons.0, + start_location_icon: req.start_location_icon.0, statues_hallway_tiling: match req.statues_hallway_tiling.0.as_str() { "Disabled" => StatuesHallwayTiling::Disabled, "Default" => StatuesHallwayTiling::Default, diff --git a/rust/maprando-web/templates/seed/help/save_icons.html b/rust/maprando-web/templates/seed/help/save_icons.html index b65d82a5d..44e5e5ead 100644 --- a/rust/maprando-web/templates/seed/help/save_icons.html +++ b/rust/maprando-web/templates/seed/help/save_icons.html @@ -14,7 +14,7 @@

Save icons

This option affects how the pause menu map appears:

  • Enabled: The three most recently used save stations are shown, color coded as follows: yellow for the most recent save (same appearance as in the vanilla game), orange for the previous save, and pink for the next to be overwritten. Samus's spawn point is also shown as a helmet until three saves have been used. An icon is also drawn for the Ship, with the same appearance as in the vanilla game. -
  • Disabled: Icons are not drawn for saves, the spawn point, nor the Ship. +
  • Disabled: Icons are not drawn for saves or the Ship.

diff --git a/rust/maprando-web/templates/seed/help/start_location_icon.html b/rust/maprando-web/templates/seed/help/start_location_icon.html new file mode 100644 index 000000000..6524e531f --- /dev/null +++ b/rust/maprando-web/templates/seed/help/start_location_icon.html @@ -0,0 +1,26 @@ + + + + \ No newline at end of file diff --git a/rust/maprando-web/templates/seed/map_appearance.html b/rust/maprando-web/templates/seed/map_appearance.html index f99bf19f6..4f6eba985 100644 --- a/rust/maprando-web/templates/seed/map_appearance.html +++ b/rust/maprando-web/templates/seed/map_appearance.html @@ -88,4 +88,19 @@ + + +
+
+ +
+
+ + + + +
\ No newline at end of file diff --git a/rust/maprando/src/bin/maprando-cli.rs b/rust/maprando/src/bin/maprando-cli.rs index 7aaf2b3a6..89c662ff0 100644 --- a/rust/maprando/src/bin/maprando-cli.rs +++ b/rust/maprando/src/bin/maprando-cli.rs @@ -250,6 +250,7 @@ fn main() -> Result<()> { save_icons: true, boss_icons: true, miniboss_icons: true, + start_location_icon: true, room_names: true, palette_theme: maprando::customize::PaletteTheme::AreaThemed, tile_theme: maprando::customize::TileTheme::Vanilla, diff --git a/rust/maprando/src/bin/maprando-test.rs b/rust/maprando/src/bin/maprando-test.rs index a8c235e5f..b86af451c 100644 --- a/rust/maprando/src/bin/maprando-test.rs +++ b/rust/maprando/src/bin/maprando-test.rs @@ -229,6 +229,7 @@ fn make_random_customization(app: &TestAppData) -> CustomizeSettings { boss_icons: true, save_icons: true, miniboss_icons: true, + start_location_icon: true, map_theme: maprando::customize::MapTheme::Light, palette_theme: maprando::customize::PaletteTheme::AreaThemed, tile_theme: maprando::customize::TileTheme::Vanilla, diff --git a/rust/maprando/src/customize.rs b/rust/maprando/src/customize.rs index 39dbe8514..df6246dd1 100644 --- a/rust/maprando/src/customize.rs +++ b/rust/maprando/src/customize.rs @@ -183,6 +183,7 @@ pub struct CustomizeSettings { pub save_icons: bool, pub boss_icons: bool, pub miniboss_icons: bool, + pub start_location_icon: bool, pub reserve_hud_style: bool, pub vanilla_screw_attack_animation: bool, pub palette_theme: PaletteTheme, @@ -209,6 +210,7 @@ impl Default for CustomizeSettings { save_icons: true, boss_icons: true, miniboss_icons: true, + start_location_icon: true, reserve_hud_style: true, vanilla_screw_attack_animation: true, room_names: true, @@ -587,6 +589,10 @@ pub fn customize_rom( if !settings.save_icons { map_icon_settings |= 4; } + if !settings.start_location_icon { + map_icon_settings |= 8; + } + rom.write_u16(snes2pc(0x85B600), map_icon_settings)?; // Fix Phantoon power-on sequence to not overwrite the first two palettes, since those contain