pokeemerald/src/load_save.c

294 lines
7.9 KiB
C
Raw Normal View History

2017-12-16 01:08:55 +01:00
#include "global.h"
#include "malloc.h"
2019-03-24 20:45:09 +01:00
#include "berry_powder.h"
2018-12-27 23:30:47 +01:00
#include "item.h"
2017-09-04 18:26:39 +02:00
#include "load_save.h"
#include "main.h"
2018-12-27 23:30:47 +01:00
#include "overworld.h"
2017-09-04 18:26:39 +02:00
#include "pokemon.h"
2018-12-20 22:53:08 +01:00
#include "pokemon_storage_system.h"
#include "random.h"
2018-12-27 23:30:47 +01:00
#include "save_location.h"
2019-01-13 13:15:23 +01:00
#include "trainer_hill.h"
2018-12-27 23:30:47 +01:00
#include "gba/flash_internal.h"
2018-11-18 19:37:18 +01:00
#include "decoration_inventory.h"
2019-03-02 08:44:02 +01:00
#include "agb_flash.h"
2018-11-18 19:37:18 +01:00
static void ApplyNewEncryptionKeyToAllEncryptedData(u32 encryptionKey);
2017-09-04 18:26:39 +02:00
#define SAVEBLOCK_MOVE_RANGE 128
2017-11-23 03:06:30 +01:00
struct LoadedSaveData
{
2018-04-29 14:21:59 +02:00
/*0x0000*/ struct ItemSlot items[BAG_ITEMS_COUNT];
/*0x0078*/ struct ItemSlot keyItems[BAG_KEYITEMS_COUNT];
/*0x00F0*/ struct ItemSlot pokeBalls[BAG_POKEBALLS_COUNT];
/*0x0130*/ struct ItemSlot TMsHMs[BAG_TMHM_COUNT];
/*0x0230*/ struct ItemSlot berries[BAG_BERRIES_COUNT];
2021-10-23 16:55:46 +02:00
/*0x02E8*/ struct Mail mail[MAIL_COUNT];
2017-11-23 03:06:30 +01:00
};
2018-04-29 14:21:59 +02:00
// EWRAM DATA
2022-09-07 14:37:03 +02:00
EWRAM_DATA struct SaveBlock2ASLR gSaveblock2 = {0};
EWRAM_DATA struct SaveBlock1ASLR gSaveblock1 = {0};
EWRAM_DATA struct PokemonStorageASLR gPokemonStorage = {0};
2017-09-04 18:26:39 +02:00
2017-11-23 03:06:30 +01:00
EWRAM_DATA struct LoadedSaveData gLoadedSaveData = {0};
2018-06-04 12:07:32 +02:00
EWRAM_DATA u32 gLastEncryptionKey = 0;
2017-11-23 03:06:30 +01:00
2018-04-29 14:21:59 +02:00
// IWRAM common
bool32 gFlashMemoryPresent;
struct SaveBlock1 *gSaveBlock1Ptr;
struct SaveBlock2 *gSaveBlock2Ptr;
struct PokemonStorage *gPokemonStoragePtr;
2018-04-29 14:21:59 +02:00
// code
2017-09-04 18:26:39 +02:00
void CheckForFlashMemory(void)
{
if (!IdentifyFlash())
{
gFlashMemoryPresent = TRUE;
InitFlashTimer();
}
else
2018-04-29 14:21:59 +02:00
{
2017-09-04 18:26:39 +02:00
gFlashMemoryPresent = FALSE;
2018-04-29 14:21:59 +02:00
}
2017-09-04 18:26:39 +02:00
}
void ClearSav2(void)
{
2022-09-07 14:37:03 +02:00
CpuFill16(0, &gSaveblock2, sizeof(struct SaveBlock2ASLR));
2017-09-04 18:26:39 +02:00
}
void ClearSav1(void)
{
2022-09-07 14:37:03 +02:00
CpuFill16(0, &gSaveblock1, sizeof(struct SaveBlock1ASLR));
2017-09-04 18:26:39 +02:00
}
// Offset is the sum of the trainer id bytes
2017-09-04 18:26:39 +02:00
void SetSaveBlocksPointers(u16 offset)
{
struct SaveBlock1** sav1_LocalVar = &gSaveBlock1Ptr;
offset = (offset + Random()) & (SAVEBLOCK_MOVE_RANGE - 4);
2022-07-29 16:52:35 +02:00
gSaveBlock2Ptr = (void *)(&gSaveblock2) + offset;
*sav1_LocalVar = (void *)(&gSaveblock1) + offset;
gPokemonStoragePtr = (void *)(&gPokemonStorage) + offset;
2017-09-04 18:26:39 +02:00
SetBagItemsPointers();
SetDecorationInventoriesPointers();
}
2017-09-04 21:43:13 +02:00
2017-09-04 18:26:39 +02:00
void MoveSaveBlocks_ResetHeap(void)
{
void *vblankCB, *hblankCB;
u32 encryptionKey;
2018-01-06 07:17:31 +01:00
struct SaveBlock2 *saveBlock2Copy;
struct SaveBlock1 *saveBlock1Copy;
struct PokemonStorage *pokemonStorageCopy;
2017-09-04 18:26:39 +02:00
// save interrupt functions and turn them off
vblankCB = gMain.vblankCallback;
hblankCB = gMain.hblankCallback;
gMain.vblankCallback = NULL;
gMain.hblankCallback = NULL;
2019-03-01 07:49:11 +01:00
gTrainerHillVBlankCounter = NULL;
2017-09-04 18:26:39 +02:00
2018-01-06 07:17:31 +01:00
saveBlock2Copy = (struct SaveBlock2 *)(gHeap);
saveBlock1Copy = (struct SaveBlock1 *)(gHeap + sizeof(struct SaveBlock2));
pokemonStorageCopy = (struct PokemonStorage *)(gHeap + sizeof(struct SaveBlock2) + sizeof(struct SaveBlock1));
// backup the saves.
2018-01-06 07:17:31 +01:00
*saveBlock2Copy = *gSaveBlock2Ptr;
*saveBlock1Copy = *gSaveBlock1Ptr;
*pokemonStorageCopy = *gPokemonStoragePtr;
2017-09-04 18:26:39 +02:00
// change saveblocks' pointers
// argument is a sum of the individual trainerId bytes
2018-01-06 07:17:31 +01:00
SetSaveBlocksPointers(
saveBlock2Copy->playerTrainerId[0] +
saveBlock2Copy->playerTrainerId[1] +
saveBlock2Copy->playerTrainerId[2] +
saveBlock2Copy->playerTrainerId[3]);
2017-09-04 18:26:39 +02:00
// restore saveblock data since the pointers changed
*gSaveBlock2Ptr = *saveBlock2Copy;
*gSaveBlock1Ptr = *saveBlock1Copy;
*gPokemonStoragePtr = *pokemonStorageCopy;
2017-09-04 18:26:39 +02:00
// heap was destroyed in the copying process, so reset it
InitHeap(gHeap, HEAP_SIZE);
2017-09-04 18:26:39 +02:00
// restore interrupt functions
gMain.hblankCallback = hblankCB;
gMain.vblankCallback = vblankCB;
// create a new encryption key
2021-03-30 23:38:09 +02:00
encryptionKey = (Random() << 16) + (Random());
2017-11-27 21:20:10 +01:00
ApplyNewEncryptionKeyToAllEncryptedData(encryptionKey);
2017-09-04 18:26:39 +02:00
gSaveBlock2Ptr->encryptionKey = encryptionKey;
}
2018-01-06 07:17:31 +01:00
2018-12-27 23:30:47 +01:00
u32 UseContinueGameWarp(void)
2017-11-23 03:06:30 +01:00
{
2018-12-27 23:30:47 +01:00
return gSaveBlock2Ptr->specialSaveWarpFlags & CONTINUE_GAME_WARP;
2017-11-23 03:06:30 +01:00
}
2018-12-27 23:30:47 +01:00
void ClearContinueGameWarpStatus(void)
2017-11-23 03:06:30 +01:00
{
2018-12-27 23:30:47 +01:00
gSaveBlock2Ptr->specialSaveWarpFlags &= ~CONTINUE_GAME_WARP;
2017-11-23 03:06:30 +01:00
}
2018-12-27 23:30:47 +01:00
void SetContinueGameWarpStatus(void)
2017-11-23 03:06:30 +01:00
{
2018-12-27 23:30:47 +01:00
gSaveBlock2Ptr->specialSaveWarpFlags |= CONTINUE_GAME_WARP;
2017-11-23 03:06:30 +01:00
}
2018-12-27 23:30:47 +01:00
void SetContinueGameWarpStatusToDynamicWarp(void)
2017-11-23 03:06:30 +01:00
{
2018-12-27 23:30:47 +01:00
SetContinueGameWarpToDynamicWarp(0);
gSaveBlock2Ptr->specialSaveWarpFlags |= CONTINUE_GAME_WARP;
2017-11-23 03:06:30 +01:00
}
2018-12-27 23:30:47 +01:00
void ClearContinueGameWarpStatus2(void)
2017-11-23 03:06:30 +01:00
{
2018-12-27 23:30:47 +01:00
gSaveBlock2Ptr->specialSaveWarpFlags &= ~CONTINUE_GAME_WARP;
2017-11-23 03:06:30 +01:00
}
2018-04-29 14:21:59 +02:00
void SavePlayerParty(void)
2017-11-23 03:06:30 +01:00
{
int i;
gSaveBlock1Ptr->playerPartyCount = gPlayerPartyCount;
2018-04-29 14:21:59 +02:00
for (i = 0; i < PARTY_SIZE; i++)
2017-11-23 03:06:30 +01:00
gSaveBlock1Ptr->playerParty[i] = gPlayerParty[i];
}
2018-04-29 14:21:59 +02:00
void LoadPlayerParty(void)
2017-11-23 03:06:30 +01:00
{
int i;
gPlayerPartyCount = gSaveBlock1Ptr->playerPartyCount;
2018-04-29 14:21:59 +02:00
for (i = 0; i < PARTY_SIZE; i++)
2017-11-23 03:06:30 +01:00
gPlayerParty[i] = gSaveBlock1Ptr->playerParty[i];
}
void SaveObjectEvents(void)
2017-11-23 03:06:30 +01:00
{
int i;
for (i = 0; i < OBJECT_EVENTS_COUNT; i++)
gSaveBlock1Ptr->objectEvents[i] = gObjectEvents[i];
2017-11-23 03:06:30 +01:00
}
void LoadObjectEvents(void)
2017-11-23 03:06:30 +01:00
{
int i;
for (i = 0; i < OBJECT_EVENTS_COUNT; i++)
gObjectEvents[i] = gSaveBlock1Ptr->objectEvents[i];
2017-11-23 03:06:30 +01:00
}
2021-10-29 04:54:41 +02:00
void CopyPartyAndObjectsToSave(void)
2017-11-23 03:06:30 +01:00
{
2018-04-29 14:21:59 +02:00
SavePlayerParty();
SaveObjectEvents();
2017-11-23 03:06:30 +01:00
}
2021-10-29 04:54:41 +02:00
void CopyPartyAndObjectsFromSave(void)
2017-11-23 03:06:30 +01:00
{
2018-04-29 14:21:59 +02:00
LoadPlayerParty();
LoadObjectEvents();
2017-11-23 03:06:30 +01:00
}
2018-04-29 14:21:59 +02:00
void LoadPlayerBag(void)
2017-11-23 03:06:30 +01:00
{
int i;
2017-12-16 01:08:55 +01:00
2017-11-23 03:06:30 +01:00
// load player items.
2018-04-29 14:21:59 +02:00
for (i = 0; i < BAG_ITEMS_COUNT; i++)
2017-11-23 03:06:30 +01:00
gLoadedSaveData.items[i] = gSaveBlock1Ptr->bagPocket_Items[i];
// load player key items.
2018-04-29 14:21:59 +02:00
for (i = 0; i < BAG_KEYITEMS_COUNT; i++)
2017-11-23 03:06:30 +01:00
gLoadedSaveData.keyItems[i] = gSaveBlock1Ptr->bagPocket_KeyItems[i];
// load player pokeballs.
2018-04-29 14:21:59 +02:00
for (i = 0; i < BAG_POKEBALLS_COUNT; i++)
2017-11-23 03:06:30 +01:00
gLoadedSaveData.pokeBalls[i] = gSaveBlock1Ptr->bagPocket_PokeBalls[i];
// load player TMs and HMs.
2018-04-29 14:21:59 +02:00
for (i = 0; i < BAG_TMHM_COUNT; i++)
2017-11-23 03:06:30 +01:00
gLoadedSaveData.TMsHMs[i] = gSaveBlock1Ptr->bagPocket_TMHM[i];
// load player berries.
2018-04-29 14:21:59 +02:00
for (i = 0; i < BAG_BERRIES_COUNT; i++)
2017-11-23 03:06:30 +01:00
gLoadedSaveData.berries[i] = gSaveBlock1Ptr->bagPocket_Berries[i];
// load mail.
2018-04-29 14:21:59 +02:00
for (i = 0; i < MAIL_COUNT; i++)
2017-11-23 03:06:30 +01:00
gLoadedSaveData.mail[i] = gSaveBlock1Ptr->mail[i];
gLastEncryptionKey = gSaveBlock2Ptr->encryptionKey;
}
2018-04-29 14:21:59 +02:00
void SavePlayerBag(void)
2017-11-23 03:06:30 +01:00
{
int i;
u32 encryptionKeyBackup;
// save player items.
2018-04-29 14:21:59 +02:00
for (i = 0; i < BAG_ITEMS_COUNT; i++)
2017-11-23 03:06:30 +01:00
gSaveBlock1Ptr->bagPocket_Items[i] = gLoadedSaveData.items[i];
// save player key items.
2018-04-29 14:21:59 +02:00
for (i = 0; i < BAG_KEYITEMS_COUNT; i++)
2017-11-23 03:06:30 +01:00
gSaveBlock1Ptr->bagPocket_KeyItems[i] = gLoadedSaveData.keyItems[i];
// save player pokeballs.
2018-04-29 14:21:59 +02:00
for (i = 0; i < BAG_POKEBALLS_COUNT; i++)
2017-11-23 03:06:30 +01:00
gSaveBlock1Ptr->bagPocket_PokeBalls[i] = gLoadedSaveData.pokeBalls[i];
// save player TMs and HMs.
2018-04-29 14:21:59 +02:00
for (i = 0; i < BAG_TMHM_COUNT; i++)
2017-11-23 03:06:30 +01:00
gSaveBlock1Ptr->bagPocket_TMHM[i] = gLoadedSaveData.TMsHMs[i];
// save player berries.
2018-04-29 14:21:59 +02:00
for (i = 0; i < BAG_BERRIES_COUNT; i++)
2017-11-23 03:06:30 +01:00
gSaveBlock1Ptr->bagPocket_Berries[i] = gLoadedSaveData.berries[i];
// save mail.
2018-04-29 14:21:59 +02:00
for (i = 0; i < MAIL_COUNT; i++)
2017-11-23 03:06:30 +01:00
gSaveBlock1Ptr->mail[i] = gLoadedSaveData.mail[i];
encryptionKeyBackup = gSaveBlock2Ptr->encryptionKey;
gSaveBlock2Ptr->encryptionKey = gLastEncryptionKey;
2017-11-27 21:20:10 +01:00
ApplyNewEncryptionKeyToBagItems(encryptionKeyBackup);
2017-11-23 03:06:30 +01:00
gSaveBlock2Ptr->encryptionKey = encryptionKeyBackup; // updated twice?
}
2017-11-27 21:20:10 +01:00
void ApplyNewEncryptionKeyToHword(u16 *hWord, u32 newKey)
2017-11-23 03:06:30 +01:00
{
*hWord ^= gSaveBlock2Ptr->encryptionKey;
*hWord ^= newKey;
}
2017-11-27 21:20:10 +01:00
void ApplyNewEncryptionKeyToWord(u32 *word, u32 newKey)
2017-11-23 03:06:30 +01:00
{
*word ^= gSaveBlock2Ptr->encryptionKey;
*word ^= newKey;
}
2018-11-18 19:37:18 +01:00
static void ApplyNewEncryptionKeyToAllEncryptedData(u32 encryptionKey)
2017-11-23 03:06:30 +01:00
{
2017-11-27 21:20:10 +01:00
ApplyNewEncryptionKeyToGameStats(encryptionKey);
ApplyNewEncryptionKeyToBagItems_(encryptionKey);
ApplyNewEncryptionKeyToBerryPowder(encryptionKey);
ApplyNewEncryptionKeyToWord(&gSaveBlock1Ptr->money, encryptionKey);
ApplyNewEncryptionKeyToHword(&gSaveBlock1Ptr->coins, encryptionKey);
2017-11-23 03:06:30 +01:00
}