diff options
author | Daniel Harding <33dannye@gmail.com> | 2021-11-15 13:31:15 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-15 13:31:15 -0600 |
commit | f516a91f5fa02a741631c77b9097598f466d1328 (patch) | |
tree | bac2ee5e3fad02983b061580f5c085baecb5439a /src/engine/save.asm | |
parent | 15e986d374fdd11ed0f412fbdc9b858d4c4b9f50 (diff) | |
parent | 1fd16cd27fcd4f432bfc09fc5b7a262798b72430 (diff) |
Some more bank splitting
Diffstat (limited to 'src/engine/save.asm')
-rw-r--r-- | src/engine/save.asm | 622 |
1 files changed, 622 insertions, 0 deletions
diff --git a/src/engine/save.asm b/src/engine/save.asm new file mode 100644 index 0000000..2674b91 --- /dev/null +++ b/src/engine/save.asm @@ -0,0 +1,622 @@ +; xors sb800 +; this has the effect of invalidating the save data checksum +; which the game interprets as being having no save data +InvalidateSaveData: + push hl + ldh a, [hBankSRAM] + + push af + ld a, BANK("SRAM2") + call BankswitchSRAM + ld a, $08 + xor $ff + ld [sBackupGeneralSaveData + 0], a + ld a, $00 + xor $ff + ld [sBackupGeneralSaveData + 1], a + pop af + + call BankswitchSRAM + call DisableSRAM + call EnableSRAM + bank1call DiscardSavedDuelData + call DisableSRAM + pop hl + ret + +; saves all data to SRAM, including +; General save data and Album/Deck data +; and backs up in SRAM2 +SaveAndBackupData: + push de + ld de, sGeneralSaveData + call SaveGeneralSaveDataFromDE + ld de, sAlbumProgress + call UpdateAlbumProgress + call WriteBackupGeneralSaveData + call WriteBackupCardAndDeckSaveData + pop de + ret + +_SaveGeneralSaveData: + push de + call GetReceivedLegendaryCards + ld de, sGeneralSaveData + call SaveGeneralSaveDataFromDE + ld de, sAlbumProgress + call UpdateAlbumProgress + pop de + ret + +; de = pointer to general game data in SRAM +SaveGeneralSaveDataFromDE: + push hl + push bc + call EnableSRAM + push de + farcall TryGiveMedalPCPacks + ld [wMedalCount], a + farcall OverworldMap_GetOWMapID + ld [wCurOverworldMap], a + pop de + push de + call CopyGeneralSaveDataToSRAM + pop de + call DisableSRAM + pop bc + pop hl + ret + +; writes in de total num of cards collected +; and in (de + 1) total num of cards to collect +; also updates wTotalNumCardsCollected and wTotalNumCardsToCollect +UpdateAlbumProgress: + push hl + push de + push de + call GetCardAlbumProgress + call EnableSRAM + pop hl + ld a, d + ld [wTotalNumCardsCollected], a + ld [hli], a + ld a, e + ld [wTotalNumCardsToCollect], a + ld [hl], a + call DisableSRAM + pop de + pop hl + ret + +; save values that are listed in WRAMToSRAMMapper +; from WRAM to SRAM, and calculate its checksum +CopyGeneralSaveDataToSRAM: + push hl + push bc + push de + push de + ld hl, sGeneralSaveDataHeaderEnd - sGeneralSaveData + add hl, de + ld e, l + ld d, h + xor a + ld [wGeneralSaveDataByteCount + 0], a + ld [wGeneralSaveDataByteCount + 1], a + ld [wGeneralSaveDataCheckSum + 0], a + ld [wGeneralSaveDataCheckSum + 1], a + + ld hl, WRAMToSRAMMapper +.loop_map + ld a, [hli] + ld [wTempPointer + 0], a + ld c, a + ld a, [hli] + ld [wTempPointer + 1], a + or c + jr z, .done_copy + ld a, [hli] + ld c, a ; number of bytes LO + ld a, [hli] + ld b, a ; number of bytes HI + ld a, [wGeneralSaveDataByteCount + 0] + add c + ld [wGeneralSaveDataByteCount + 0], a + ld a, [wGeneralSaveDataByteCount + 1] + adc b + ld [wGeneralSaveDataByteCount + 1], a + call .CopyBytesToSRAM + inc hl + inc hl + jr .loop_map + +.done_copy + pop hl + ld a, $08 + ld [hli], a + ld a, $00 + ld [hli], a + ld a, [wGeneralSaveDataByteCount + 0] + ld [hli], a + ld a, [wGeneralSaveDataByteCount + 1] + ld [hli], a + ld a, [wGeneralSaveDataCheckSum + 0] + ld [hli], a + ld a, [wGeneralSaveDataCheckSum + 1] + ld [hli], a + pop de + pop bc + pop hl + ret + +.CopyBytesToSRAM + push hl + ld a, [wTempPointer + 0] + ld l, a + ld a, [wTempPointer + 1] + ld h, a +.loop_bytes + push bc + ld a, [hli] + ld [de], a + inc de + ld c, a + ld a, [wGeneralSaveDataCheckSum + 0] + add c + ld [wGeneralSaveDataCheckSum + 0], a + ld a, [wGeneralSaveDataCheckSum + 1] + adc 0 + ld [wGeneralSaveDataCheckSum + 1], a + pop bc + dec bc + ld a, c + or b + jr nz, .loop_bytes + ld a, l + ld [wTempPointer + 0], a + ld a, h + ld [wTempPointer + 1], a + pop hl + ret + +; returns carry if no error +; is found in sBackupGeneralSaveData +ValidateBackupGeneralSaveData: + push de + ldh a, [hBankSRAM] + push af + ld a, BANK(sBackupGeneralSaveData) + call BankswitchSRAM + ld de, sBackupGeneralSaveData + call ValidateGeneralSaveDataFromDE + ld de, sAlbumProgress + call LoadAlbumProgressFromSRAM + pop af + call BankswitchSRAM + call DisableSRAM + pop de + ld a, [wNumSRAMValidationErrors] + cp 1 + ret + +; returns carry if no error +; is found in sGeneralSaveData +_ValidateGeneralSaveData: + push de + call EnableSRAM + ld de, sGeneralSaveData + call ValidateGeneralSaveDataFromDE + ld de, sAlbumProgress + call LoadAlbumProgressFromSRAM + call DisableSRAM + pop de + ld a, [wNumSRAMValidationErrors] + cp 1 + ret + +; validates the general game data saved in SRAM +; de = pointer to general game data in SRAM +ValidateGeneralSaveDataFromDE: + push hl + push bc + push de + xor a + ld [wNumSRAMValidationErrors], a + push de + + push de + inc de + inc de + ld a, [de] + inc de + ld [wGeneralSaveDataByteCount + 0], a + ld a, [de] + inc de + ld [wGeneralSaveDataByteCount + 1], a + ld a, [de] + inc de + ld [wGeneralSaveDataCheckSum + 0], a + ld a, [de] + inc de + ld [wGeneralSaveDataCheckSum + 1], a + pop de + + ld hl, sGeneralSaveDataHeaderEnd - sGeneralSaveData + add hl, de + ld e, l + ld d, h + ld hl, WRAMToSRAMMapper +.loop + ld a, [hli] + ld c, a + ld a, [hli] + or c + jr z, .exit_loop + ld a, [hli] + ld c, a ; number of bytes LO + ld a, [hli] + ld b, a ; number of bytes HI + ld a, [wGeneralSaveDataByteCount + 0] + sub c + ld [wGeneralSaveDataByteCount + 0], a + ld a, [wGeneralSaveDataByteCount + 1] + sbc b + ld [wGeneralSaveDataByteCount + 1], a + +; loop all the bytes of this struct +.loop_bytes + push hl + push bc + ld a, [de] + push af + ld c, a + ld a, [wGeneralSaveDataCheckSum + 0] + sub c + ld [wGeneralSaveDataCheckSum + 0], a + ld a, [wGeneralSaveDataCheckSum + 1] + sbc 0 + ld [wGeneralSaveDataCheckSum + 1], a + pop af + + ; check if it's within the specified values + cp [hl] ; min value + jr c, .error + inc hl + cp [hl] ; max value + jr z, .next_byte + jr c, .next_byte +.error + ld a, [wNumSRAMValidationErrors] + inc a + ld [wNumSRAMValidationErrors], a +.next_byte + inc de + pop bc + pop hl + dec bc + ld a, c + or b + jr nz, .loop_bytes + ; next mapped struct + inc hl + inc hl + jr .loop + +.exit_loop + pop hl + ld a, [hli] + sub $8 + ld c, a + ld a, [hl] + sub 0 + or c + ld hl, wGeneralSaveDataByteCount + or [hl] + inc hl + or [hl] + ld hl, wGeneralSaveDataCheckSum + or [hl] + inc hl + or [hl] + jr z, .no_header_error + ld hl, wNumSRAMValidationErrors + inc [hl] +.no_header_error + pop de + ; copy play time minutes and hours + ld hl, (sPlayTimeCounter + 2) - sGeneralSaveData + add hl, de + ld a, [hli] + ld [wPlayTimeHourMinutes + 0], a + ld a, [hli] + ld [wPlayTimeHourMinutes + 1], a + ld a, [hli] + ld [wPlayTimeHourMinutes + 2], a + + ; copy medal count and current overworld map + ld hl, sGeneralSaveDataHeaderEnd - sGeneralSaveData + add hl, de + ld a, [hli] + ld [wMedalCount], a + ld a, [hl] + ld [wCurOverworldMap], a + pop bc + pop hl + ret + +LoadAlbumProgressFromSRAM: + push de + ld a, [de] + ld [wTotalNumCardsCollected], a + inc de + ld a, [de] + ld [wTotalNumCardsToCollect], a + pop de + ret + +; first copies data from backup SRAM to main SRAM +; then loads it to WRAM from main SRAM +LoadBackupSaveData: + push hl + push de + call EnableSRAM + bank1call DiscardSavedDuelData + call DisableSRAM + call LoadBackupGeneralSaveData + call LoadBackupCardAndDeckSaveData + ld de, sGeneralSaveData + call LoadGeneralSaveDataFromDE + pop de + pop hl + ret + +_LoadGeneralSaveData: + push de + ld de, sGeneralSaveData + call LoadGeneralSaveDataFromDE + pop de + ret + +; de = pointer to save data +LoadGeneralSaveDataFromDE: + push hl + push bc + call EnableSRAM + call .LoadData + call DisableSRAM + pop bc + pop hl + ret + +.LoadData + push hl + push bc + push de + ld a, e + add sGeneralSaveDataHeaderEnd - sGeneralSaveData + ld [wTempPointer + 0], a + ld a, d + adc 0 + ld [wTempPointer + 1], a + + ld hl, WRAMToSRAMMapper +.asm_11459 + ld a, [hli] + ld e, a + ld d, [hl] + or d + jr z, .done_copy + inc hl + ld a, [hli] + ld c, a + ld a, [hli] + ld b, a + +; copy bc bytes from wTempPointer to de + push hl + ld a, [wTempPointer + 0] + ld l, a + ld a, [wTempPointer + 1] + ld h, a +.loop_copy + ld a, [hli] + ld [de], a + inc de + dec bc + ld a, c + or b + jr nz, .loop_copy + + ld a, l + ld [wTempPointer + 0], a + ld a, h + ld [wTempPointer + 1], a + pop hl + inc hl + inc hl + jr .asm_11459 + +.done_copy + call EnableSRAM + ld a, [sAnimationsDisabled] + ld [wAnimationsDisabled], a + ld a, [sTextSpeed] + ld [wTextSpeed], a + call DisableSRAM + pop de + pop bc + pop hl + ret + +wram_sram_map: MACRO + dw \1 ; WRAM address + dw \2 ; number of bytes + db \3 ; min allowed value + db \4 ; max allowed value +ENDM + +; maps WRAM addresses to SRAM addresses in order +; to save and subsequently retrieve them on game load +; also works as a test in order check whether +; the saved values is SRAM are legal, within the given value range +WRAMToSRAMMapper: + wram_sram_map wMedalCount, 1, $00, $ff ; sMedalCount + wram_sram_map wCurOverworldMap, 1, $00, $ff ; sCurOverworldMap + wram_sram_map wPlayTimeCounter + 0, 1, $00, $ff ; sPlayTimeCounter + wram_sram_map wPlayTimeCounter + 1, 1, $00, $ff + wram_sram_map wPlayTimeCounter + 2, 1, $00, $ff + wram_sram_map wPlayTimeCounter + 3, 2, $00, $ff + wram_sram_map wOverworldMapSelection, 1, $00, $ff ; sOverworldMapSelection + wram_sram_map wTempMap, 1, $00, $ff ; sTempMap + wram_sram_map wTempPlayerXCoord, 1, $00, $ff ; sTempPlayerXCoord + wram_sram_map wTempPlayerYCoord, 1, $00, $ff ; sTempPlayerYCoord + wram_sram_map wTempPlayerDirection, 1, $00, $ff ; sTempPlayerDirection + wram_sram_map wActiveGameEvent, 1, $00, $ff ; sActiveGameEvent + wram_sram_map wDuelResult, 1, $00, $ff ; sDuelResult + wram_sram_map wNPCDuelist, 1, $00, $ff ; sNPCDuelist + wram_sram_map wChallengeHallNPC, 1, $00, $ff ; sChallengeHallNPC + wram_sram_map wd698, 4, $00, $ff ; sb818 + wram_sram_map wOWMapEvents, NUM_MAP_EVENTS, $00, $ff ; sOWMapEvents + wram_sram_map .EmptySRAMSlot, 1, $00, $ff ; sb827 + wram_sram_map wSelectedPauseMenuItem, 1, $00, $ff ; sSelectedPauseMenuItem + wram_sram_map wSelectedPCMenuItem, 1, $00, $ff ; sSelectedPCMenuItem + wram_sram_map wConfigCursorYPos, 1, $00, $ff ; sConfigCursorYPos + wram_sram_map wSelectedGiftCenterMenuItem, 1, $00, $ff ; sSelectedGiftCenterMenuItem + wram_sram_map wPCPackSelection, 1, 0, 14 ; sPCPackSelection + wram_sram_map wPCPacks, NUM_PC_PACKS, $00, $ff ; sPCPacks + wram_sram_map wDefaultSong, 1, $00, $ff ; sDefaultSong + wram_sram_map wDebugPauseAllowed, 1, $00, $ff ; sDebugPauseAllowed + wram_sram_map wRonaldIsInMap, 1, $00, $ff ; sRonaldIsInMap + wram_sram_map wMastersBeatenList, 10, $00, $ff ; sMastersBeatenList + wram_sram_map wNPCDuelistDirection, 1, $00, $ff ; sNPCDuelistDirection + wram_sram_map wMultichoiceTextboxResult_ChooseDeckToDuelAgainst, 1, $00, $ff ; sMultichoiceTextboxResult_ChooseDeckToDuelAgainst + wram_sram_map wd10e, 1, $00, $ff ; sb84b + wram_sram_map .EmptySRAMSlot, 15, $00, $ff ; sb84c + wram_sram_map .EmptySRAMSlot, 16, $00, $ff ; sb85b + wram_sram_map .EmptySRAMSlot, 16, $00, $ff ; sb86b + wram_sram_map wEventVars, 64, $00, $ff ; sEventVars + dw NULL + +; fills an empty SRAM slot with zero +.EmptySRAMSlot: + db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 + +; save the game +; if c is 0, save the player at their current position +; otherwise, save the player in Mason's lab +_SaveGame: + ld a, c + or a + jr nz, .force_mason_lab + farcall BackupPlayerPosition + jr .save + +.force_mason_lab + ld a, $2 + ld [wTempPlayerXCoord], a + ld a, $4 + ld [wTempPlayerYCoord], a + ld a, SOUTH + ld [wTempPlayerDirection], a + ld a, MASON_LABORATORY + ld [wTempMap], a + ld a, OWMAP_MASON_LABORATORY + ld [wOverworldMapSelection], a + +.save + call SaveAndBackupData + ret + +_AddCardToCollectionAndUpdateAlbumProgress: + ld [wCardToAddToCollection], a + push hl + push bc + push de + ldh a, [hBankSRAM] + push af + ld a, BANK(sAlbumProgress) + call BankswitchSRAM + ld a, [wCardToAddToCollection] + call AddCardToCollection + ld de, sAlbumProgress + call UpdateAlbumProgress + pop af + call BankswitchSRAM + call DisableSRAM ; unnecessary + +; unintentional? runs the same write operation +; on the same address but on the current SRAM bank + ld a, [wCardToAddToCollection] + call AddCardToCollection + ld de, $b8fe + call UpdateAlbumProgress + pop de + pop bc + pop hl + ret + +WriteBackupCardAndDeckSaveData: + ld bc, sCardAndDeckSaveDataEnd - sCardAndDeckSaveData + ld hl, sCardCollection + jr WriteDataToBackup + +WriteBackupGeneralSaveData: + ld bc, sGeneralSaveDataEnd - sGeneralSaveData + ld hl, sGeneralSaveData +; fallthrough + +; bc = number of bytes to copy to backup +; hl = pointer in SRAM of data to backup +WriteDataToBackup: + ldh a, [hBankSRAM] + push af +.loop + xor a ; SRAM0 + call BankswitchSRAM + ld a, [hl] + push af + ld a, BANK("SRAM2") + call BankswitchSRAM + pop af + ld [hli], a + dec bc + ld a, b + or c + jr nz, .loop + pop af + call BankswitchSRAM + call DisableSRAM + ret + +LoadBackupCardAndDeckSaveData: + ld bc, sCardAndDeckSaveDataEnd - sCardAndDeckSaveData + ld hl, sCardCollection + jr LoadDataFromBackup + +LoadBackupGeneralSaveData: + ld bc, sGeneralSaveDataEnd - sGeneralSaveData + ld hl, sGeneralSaveData +; fallthrough + +; bc = number of bytes to load from backup +; hl = pointer in SRAM of backup data +LoadDataFromBackup: + ldh a, [hBankSRAM] + push af + +.loop + ld a, BANK("SRAM2") + call BankswitchSRAM + ld a, [hl] + push af + xor a + call BankswitchSRAM + pop af + ld [hli], a + dec bc + ld a, b + or c + jr nz, .loop + pop af + call BankswitchSRAM + call DisableSRAM + ret |