From d097191ab1648eae13a558b6282fecc0843c05e6 Mon Sep 17 00:00:00 2001 From: xCrystal Date: Fri, 15 Dec 2023 19:10:47 +0100 Subject: [PATCH] Implement the engine to backup map objects when chaning maps (#32) --- Makefile | 12 +- constants/hardware_constants.asm | 2 +- data/maps/setup_script_pointers.asm | 1 + data/maps/setup_scripts.asm | 4 + engine/board/menu.asm | 1 + engine/board/spaces.asm | 1 + engine/menus/save.asm | 35 ++++++ engine/overworld/events.asm | 30 ++++- engine/overworld/warp_connection.asm | 1 + home/map.asm | 175 ++++++++++++++++++++++++++- ram/wram.asm | 1 + 11 files changed, 249 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index 25acf880c..e85cadb6c 100644 --- a/Makefile +++ b/Makefile @@ -151,12 +151,12 @@ $(foreach obj, $(pokecrystal11_vc_obj), $(eval $(call DEP,$(obj),$(obj:11_vc.o=. endif -pokecrystal_opt = -Cjv -t PM_CRYSTAL -i BYTE -n 0 -k 01 -l 0x33 -m 0x1b -r 3 -p 0 -pokecrystal11_opt = -Cjv -t PM_CRYSTAL -i BYTE -n 1 -k 01 -l 0x33 -m 0x1b -r 3 -p 0 -pokecrystal_au_opt = -Cjv -t PM_CRYSTAL -i BYTU -n 0 -k 01 -l 0x33 -m 0x1b -r 3 -p 0 -pokecrystal_debug_opt = -Cjv -t PM_CRYSTAL -i BYTE -n 0 -k 01 -l 0x33 -m 0x1b -r 3 -p 0 -pokecrystal11_debug_opt = -Cjv -t PM_CRYSTAL -i BYTE -n 1 -k 01 -l 0x33 -m 0x1b -r 3 -p 0 -pokecrystal11_vc_opt = -Cjv -t PM_CRYSTAL -i BYTE -n 1 -k 01 -l 0x33 -m 0x1b -r 3 -p 0 +pokecrystal_opt = -Cjv -t PM_CRYSTAL -i BYTE -n 0 -k 01 -l 0x33 -m 0x1b -r 5 -p 0 +pokecrystal11_opt = -Cjv -t PM_CRYSTAL -i BYTE -n 1 -k 01 -l 0x33 -m 0x1b -r 5 -p 0 +pokecrystal_au_opt = -Cjv -t PM_CRYSTAL -i BYTU -n 0 -k 01 -l 0x33 -m 0x1b -r 5 -p 0 +pokecrystal_debug_opt = -Cjv -t PM_CRYSTAL -i BYTE -n 0 -k 01 -l 0x33 -m 0x1b -r 5 -p 0 +pokecrystal11_debug_opt = -Cjv -t PM_CRYSTAL -i BYTE -n 1 -k 01 -l 0x33 -m 0x1b -r 5 -p 0 +pokecrystal11_vc_opt = -Cjv -t PM_CRYSTAL -i BYTE -n 1 -k 01 -l 0x33 -m 0x1b -r 5 -p 0 %.gbc: $$(%_obj) layout.link $(RGBLINK) -n $*.sym -m $*.map -l layout.link -o $@ $(filter %.o,$^) diff --git a/constants/hardware_constants.asm b/constants/hardware_constants.asm index 579571864..60cfa489c 100644 --- a/constants/hardware_constants.asm +++ b/constants/hardware_constants.asm @@ -26,7 +26,7 @@ DEF MBC3RTC EQU $a000 DEF SRAM_DISABLE EQU $00 DEF SRAM_ENABLE EQU $0a -DEF NUM_SRAM_BANKS EQU 4 +DEF NUM_SRAM_BANKS EQU 8 DEF RTC_S EQU $08 ; Seconds 0-59 (0-3Bh) DEF RTC_M EQU $09 ; Minutes 0-59 (0-3Bh) diff --git a/data/maps/setup_script_pointers.asm b/data/maps/setup_script_pointers.asm index 58a7466fb..40dcb66f5 100644 --- a/data/maps/setup_script_pointers.asm +++ b/data/maps/setup_script_pointers.asm @@ -54,3 +54,4 @@ MapSetupCommands: add_mapsetup SpawnInCustomFacing ; 2f add_mapsetup ResetLevelScopedEventFlags ; 30 add_mapsetup AnchorPointAfterWarp ; 31 + add_mapsetup BackupMapObjects ; 32 diff --git a/data/maps/setup_scripts.asm b/data/maps/setup_scripts.asm index 9b1d910da..06fd56b1b 100644 --- a/data/maps/setup_scripts.asm +++ b/data/maps/setup_scripts.asm @@ -58,6 +58,7 @@ MapSetupScript_Fly: MapSetupScript_Warp: mapsetup DisableLCD mapsetup InitSound + mapsetup BackupMapObjects mapsetup EnterMapSpawnPoint mapsetup LoadMapAttributes mapsetup HandleNewMap @@ -82,6 +83,7 @@ MapSetupScript_Warp: db -1 ; end MapSetupScript_BadWarp: + mapsetup BackupMapObjects mapsetup EnterMapSpawnPoint mapsetup LoadMapAttributes mapsetup HandleNewMap @@ -108,6 +110,7 @@ MapSetupScript_BadWarp: MapSetupScript_Connection: mapsetup SuspendMapAnims + mapsetup BackupMapObjects mapsetup EnterMapConnection mapsetup LoadMapAttributes mapsetup HandleNewMap @@ -129,6 +132,7 @@ MapSetupScript_Fall: MapSetupScript_Door: mapsetup FadeOutPalettesToWhite MapSetupScript_Train: + mapsetup BackupMapObjects mapsetup EnterMapWarp mapsetup LoadMapAttributes mapsetup GetWarpDestCoords diff --git a/engine/board/menu.asm b/engine/board/menu.asm index 686b8018a..565f842c0 100755 --- a/engine/board/menu.asm +++ b/engine/board/menu.asm @@ -89,6 +89,7 @@ BoardMenuScript:: end .EnterViewMapMode: + call BackupMapObjectsOnEnterViewMapMode ld hl, wVramState res 2, [hl] ld a, BOARDEVENT_VIEW_MAP_MODE diff --git a/engine/board/spaces.asm b/engine/board/spaces.asm index 836b972b5..e5374debe 100755 --- a/engine/board/spaces.asm +++ b/engine/board/spaces.asm @@ -269,6 +269,7 @@ PromptPlayerToChooseBranchDirection: jp PlayClickSFX .EnterViewMapMode: + call BackupMapObjectsOnEnterViewMapMode ld a, BOARDEVENT_VIEW_MAP_MODE ldh [hCurBoardEvent], a ld a, 100 diff --git a/engine/menus/save.asm b/engine/menus/save.asm index 99018ec97..b156a266d 100644 --- a/engine/menus/save.asm +++ b/engine/menus/save.asm @@ -289,6 +289,7 @@ SaveGameData: call SaveOptions call SavePlayerData call SavePokemonData + call SaveMapObjectsBackupsData call SaveBox call SaveChecksum call ValidateBackupSave @@ -446,6 +447,22 @@ SavePokemonData: call CloseSRAM ret +SaveMapObjectsBackupsData: + ldh a, [rSVBK] + push af + ld a, BANK(wMapObjectsBackups) + ldh [rSVBK], a + ld a, BANK(sMapObjectsBackups) + call OpenSRAM + ld hl, wMapObjectsBackups + ld de, sMapObjectsBackups + ld bc, wMapObjectsBackupsEnd - wMapObjectsBackups + call CopyBytes + call CloseSRAM + pop af + ldh [rSVBK], a + ret + SaveBox: call GetBoxAddress call SaveBoxAddress @@ -526,6 +543,7 @@ TryLoadSaveFile: jr nz, .backup call LoadPlayerData call LoadPokemonData + call LoadMapObjectsBackupsData call LoadBox farcall RestorePartyMonMail call ValidateBackupSave @@ -541,6 +559,7 @@ TryLoadSaveFile: jr nz, .corrupt call LoadBackupPlayerData call LoadBackupPokemonData + call LoadMapObjectsBackupsData call LoadBox farcall RestorePartyMonMail call ValidateSave @@ -677,6 +696,22 @@ LoadPokemonData: call CloseSRAM ret +LoadMapObjectsBackupsData: + ldh a, [rSVBK] + push af + ld a, BANK(wMapObjectsBackups) + ldh [rSVBK], a + ld a, BANK(sMapObjectsBackups) + call OpenSRAM + ld hl, sMapObjectsBackups + ld de, wMapObjectsBackups + ld bc, wMapObjectsBackupsEnd - wMapObjectsBackups + call CopyBytes + call CloseSRAM + pop af + ldh [rSVBK], a + ret + LoadBox: call GetBoxAddress call LoadBoxAddress diff --git a/engine/overworld/events.asm b/engine/overworld/events.asm index 7f6f910de..2b2ee2d4a 100644 --- a/engine/overworld/events.asm +++ b/engine/overworld/events.asm @@ -135,7 +135,7 @@ CheckTrainerAndTalkerEvents: bit 5, [hl] ret -; on enter overworld loop +; on enter overworld loop (MAPSETUP_ENTERLEVEL or MAPSETUP_CONTINUE) StartMap: xor a ldh [hScriptVar], a @@ -147,13 +147,39 @@ StartMap: farcall InitCallReceiveDelay call ClearJoypad -; initialize board state ld a, [hMapEntryMethod] cp MAPSETUP_ENTERLEVEL jr nz, .not_starting_level + +; initialize board state xor a ld [wCurTurn], a ld [wCurSpace], a + +; initialize overworld state + ld hl, wNextWarp + xor a + ld [hli], a ; wNextWarp + ld [hli], a ; wNextMapGroup + ld [hli], a ; wNextMapNumber + ld [hli], a ; wPrevWarp + ld [hli], a ; wPrevMapGroup + ld [hl], a ; wPrevMapNumber + ld a, BANK(wMapObjectsBackups) + ld [rSVBK], a + ld e, NUM_MAP_OBJECTS_BACKUPS + ld hl, wMapObjectsBackups + ld bc, wMap2ObjectsBackup - wMap1ObjectsBackup +.loop + ld a, GROUP_N_A + ld [hl], a + add hl, bc + dec e + jr nz, .loop + ld [hl], $00 ; list terminator + ld a, 1 + ld [rSVBK], a + .not_starting_level ld a, BOARDEVENT_DISPLAY_MENU ldh [hCurBoardEvent], a diff --git a/engine/overworld/warp_connection.asm b/engine/overworld/warp_connection.asm index 2f3027373..335dbea11 100644 --- a/engine/overworld/warp_connection.asm +++ b/engine/overworld/warp_connection.asm @@ -144,6 +144,7 @@ EnterMapConnection: ld [wOverworldMapAnchor], a ld a, h ld [wOverworldMapAnchor + 1], a + .done scf ret diff --git a/home/map.asm b/home/map.asm index 1ad7b22c8..3d7e5da6e 100644 --- a/home/map.asm +++ b/home/map.asm @@ -358,6 +358,87 @@ CheckIndoorMap:: xor a ret ; z +BackupMapObjects:: +; this setup script is called just before the EnterMap* setup script, +; when wMapGroup and wMapNumber still contain the about-to-leave map. +; there is no need to backup map objects when going through connections during View Map mode, +; as during this mode there is no possible interaction that leads to a map objec changing status. +; BackupMapObjectsOnEnterViewMapMode is called when entering View Map mode. + ldh a, [hCurBoardEvent] + cp BOARDEVENT_VIEW_MAP_MODE + ret z + ; fallthrough + +BackupMapObjectsOnEnterViewMapMode:: + ld hl, wMapGroup + ld a, [hli] + ld d, a ; d = wMapGroup + ld e, [hl] ; e = wMapNumber + ld a, BANK(wMapObjectsBackups) + ld [rSVBK], a + ld hl, wMap1ObjectsBackup + ld bc, wMap2ObjectsBackup - wMap1ObjectsBackup - 2 +.find_loop + ld a, [hl] + cp GROUP_N_A + jr z, .found_available_entry + and a ; cp $00 (terminator at wMapObjectsBackupsEnd) + jr z, .done + cp d ; wMapObjectsBackupMapGroup == wMapGroup? + jr nz, .next + inc hl + ld a, [hl] + cp e ; wMapObjectsBackupMapNumber == wMapNumber? + jr nz, .next2 + inc hl + jr .found_matching_entry +.next + inc hl +.next2 + inc hl + add hl, bc + jr .find_loop + +.found_available_entry + ld [hl], d ; wMapGroup + inc hl + ld [hl], e ; wMapNumber + inc hl +.found_matching_entry + ld a, 1 + ld [rSVBK], a + ld de, wMapObject1 + ld a, [wCurMapObjectEventCount] ; how many object events are in the about-to-leave map? + and a + jr z, .done ; return if there's zero object events to be saved + sla a + sla a + sla a + sla a + ld c, a ; c = [wCurMapObjectEventCount] * MAPOBJECT_LENGTH +.copy_loop + ld a, 1 + ld [rSVBK], a + ld a, c + and %00001111 + ld a, $ff ; StructID (first byte) of each object event must be set to $ff + jr z, .got_value + ld a, [de] +.got_value + inc de + ld b, a + ld a, BANK(wMapObjectsBackups) + ld [rSVBK], a + ld a, b + ld [hli], a + dec c + jr nz, .copy_loop + +.done + ld a, 1 + ld [rSVBK], a + ret + LoadMapAttributes:: call CopyMapPartialAndAttributes call SwitchToMapScriptsBank @@ -579,8 +660,6 @@ ReadObjectEvents:: ld [wCurMapObjectEventsPointer], a ld a, d ld [wCurMapObjectEventsPointer + 1], a - - ld a, [wCurMapObjectEventCount] call CopyMapObjectEvents ; get NUM_OBJECTS - [wCurMapObjectEventCount] - 1 @@ -591,9 +670,13 @@ ReadObjectEvents:: jr z, .skip jr c, .skip - ; could have done "inc hl" instead - ld bc, 1 - add hl, bc + push af + ld a, [wCurMapObjectEventCount] + ld bc, MAPOBJECT_LENGTH + call AddNTimes + inc hl +; Fill the remaining MAPOBJECT_SPRITE and MAPOBJECT_Y_COORD with 0 and -1, respectively. + pop af ; a = (NUM_OBJECTS - 1) - [wCurMapObjectEventCount], a > 0 ld bc, MAPOBJECT_LENGTH .loop ld [hl], 0 @@ -610,9 +693,20 @@ ReadObjectEvents:: ret CopyMapObjectEvents:: + ld a, [wCurMapObjectEventCount] and a ret z + push hl + push de + call .FindMapObjectsBackup + pop de + pop hl + ret c + +; hl = wMapObject1 +; de = [wCurMapObjectEventsPointer] + ld a, [wCurMapObjectEventCount] ld c, a .loop push bc @@ -635,6 +729,77 @@ CopyMapObjectEvents:: jr nz, .loop ret +.FindMapObjectsBackup: +; this is called from the LoadMapAttributes map setup script. +; at this point wMapGroup and wMapNumber contain the about-to-enter map. +; if map is found in wMapObjectsBackups, copy object data from there and return carry. +; return nc otherwise. + ld hl, wMapGroup + ld a, [hli] + ld d, a ; d = wMapGroup + ld e, [hl] ; e = wMapNumber + ld a, BANK(wMapObjectsBackups) + ld [rSVBK], a + ld hl, wMap1ObjectsBackup + ld bc, wMap2ObjectsBackup - wMap1ObjectsBackup - 2 +.find_loop + ld a, [hl] + cp GROUP_N_A + jr z, .no_match + and a ; cp $00 (terminator at wMapObjectsBackupsEnd) + jr z, .no_match + cp d ; wMapObjectsBackupMapGroup == wMapGroup? + jr nz, .next + inc hl + ld a, [hl] + cp e ; wMapObjectsBackupMapNumber == wMapNumber? + jr nz, .next2 + inc hl + jr .found_matching_entry +.next + inc hl +.next2 + inc hl + add hl, bc + jr .find_loop + +.found_matching_entry + ld a, 1 + ld [rSVBK], a + ld de, wMapObject1 + ld a, [wCurMapObjectEventCount] + and a + jr z, .done ; return if there's zero object events to be read + sla a + sla a + sla a + sla a + ld c, a ; c = [wCurMapObjectEventCount] * OBJECT_LENGTH +.copy_loop + ld a, BANK(wMapObjectsBackups) + ld [rSVBK], a + ld a, [hli] + ld b, a + ld a, 1 + ld [rSVBK], a + ld a, b + ld [de], a + inc de + dec c + jr nz, .copy_loop + +.done + ld a, 1 + ld [rSVBK], a + scf + ret + +.no_match + ld a, 1 + ld [rSVBK], a + xor a + ret + ClearObjectStructs:: ld hl, wObjectStructs ld bc, OBJECT_LENGTH * NUM_OBJECT_STRUCTS diff --git a/ram/wram.asm b/ram/wram.asm index f44165742..238d439fa 100644 --- a/ram/wram.asm +++ b/ram/wram.asm @@ -2693,6 +2693,7 @@ wMapObjectsBackups:: ; wMap1ObjectsBackup* - wMap10ObjectsBackup* ; ds (2 + MAPOBJECT_LENGTH * (NUM_OBJECTS - 1)) * NUM_MAP_OBJECTS_BACKUPS for n, 1, NUM_MAP_OBJECTS_BACKUPS + wMap{d:n}ObjectsBackup:: wMap{d:n}ObjectsBackupMapGroup:: db wMap{d:n}ObjectsBackupMapNumber:: db wMap{d:n}ObjectsBackupData::