summaryrefslogtreecommitdiff
path: root/src/load_save.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/load_save.c')
-rw-r--r--src/load_save.c231
1 files changed, 208 insertions, 23 deletions
diff --git a/src/load_save.c b/src/load_save.c
index 68d978e3d..a516c08c2 100644
--- a/src/load_save.c
+++ b/src/load_save.c
@@ -3,19 +3,34 @@
#include "load_save.h"
#include "main.h"
#include "pokemon.h"
-#include "rng.h"
-#include "malloc.h"
+#include "random.h"
extern void* gUnknown_0203CF5C;
extern bool16 IdentifyFlash(void);
extern void SetBagItemsPointers(void);
extern void SetDecorationInventoriesPointers(void);
+extern void ApplyNewEncryptionKeyToGameStats(u32 key);
+extern void ApplyNewEncryptionKeyToBagItems(u32 newKey);
+extern void ApplyNewEncryptionKeyToBagItems_(u32 key);
+extern void ApplyNewEncryptionKeyToBerryPowder(u32 key);
+extern void sub_8084FAC(int unused);
-void ApplyNewEncyprtionKeyToAllEncryptedData(u32 encryptionKey);
+// this is probably wrong or misleading due to it being used in ResetHeap...
+extern void InitHeap(void *pointer, u32 size);
#define SAVEBLOCK_MOVE_RANGE 128
+struct LoadedSaveData
+{
+ /*0x0000*/ struct ItemSlot items[30];
+ /*0x0078*/ struct ItemSlot keyItems[30];
+ /*0x00F0*/ struct ItemSlot pokeBalls[16];
+ /*0x0130*/ struct ItemSlot TMsHMs[64];
+ /*0x0230*/ struct ItemSlot berries[46];
+ /*0x02E8*/ struct MailStruct mail[MAIL_COUNT];
+};
+
EWRAM_DATA struct SaveBlock2 gSaveblock2 = {0};
EWRAM_DATA u8 gSaveblock2_DMA[SAVEBLOCK_MOVE_RANGE] = {0};
@@ -25,6 +40,11 @@ EWRAM_DATA u8 gSaveblock1_DMA[SAVEBLOCK_MOVE_RANGE] = {0};
EWRAM_DATA struct PokemonStorage gPokemonStorage = {0};
EWRAM_DATA u8 gSaveblock3_DMA[SAVEBLOCK_MOVE_RANGE] = {0};
+EWRAM_DATA struct LoadedSaveData gLoadedSaveData = {0};
+EWRAM_DATA u32 gLastEncryptionKey = {0};
+
+void ApplyNewEncryptionKeyToAllEncryptedData(u32 encryptionKey);
+
void CheckForFlashMemory(void)
{
if (!IdentifyFlash())
@@ -60,18 +80,15 @@ void SetSaveBlocksPointers(u16 offset)
SetDecorationInventoriesPointers();
}
-struct SaveBlocksInOne
-{
- struct SaveBlock2 sav2;
- struct SaveBlock1 sav1;
- struct PokemonStorage sav3;
-};
-/*
+extern u8 gHeap[];
+
void MoveSaveBlocks_ResetHeap(void)
{
void *vblankCB, *hblankCB;
u32 encryptionKey;
- struct SaveBlocksInOne* copiedSavs;
+ struct SaveBlock2 *saveBlock2Copy;
+ struct SaveBlock1 *saveBlock1Copy;
+ struct PokemonStorage *pokemonStorageCopy;
// save interrupt functions and turn them off
vblankCB = gMain.vblankCallback;
@@ -80,24 +97,30 @@ void MoveSaveBlocks_ResetHeap(void)
gMain.hblankCallback = NULL;
gUnknown_0203CF5C = NULL;
- copiedSavs = (void*)(gHeap);
+ saveBlock2Copy = (struct SaveBlock2 *)(gHeap);
+ saveBlock1Copy = (struct SaveBlock1 *)(gHeap + sizeof(struct SaveBlock2));
+ pokemonStorageCopy = (struct PokemonStorage *)(gHeap + sizeof(struct SaveBlock2) + sizeof(struct SaveBlock1));
- // copy saveblocks' content
- copiedSavs->sav2 = *gSaveBlock2Ptr;
- copiedSavs->sav1 = *gSaveBlock1Ptr;
- copiedSavs->sav3 = *gPokemonStoragePtr;
+ // backup the saves.
+ *saveBlock2Copy = *gSaveBlock2Ptr;
+ *saveBlock1Copy = *gSaveBlock1Ptr;
+ *pokemonStorageCopy = *gPokemonStoragePtr;
// change saveblocks' pointers
// argument is a sum of the individual trainerId bytes
- SetSaveBlocksPointers(copiedSavs->sav2.playerTrainerId[0] + copiedSavs->sav2.playerTrainerId[1] + copiedSavs->sav2.playerTrainerId[2] + copiedSavs->sav2.playerTrainerId[3]);
+ SetSaveBlocksPointers(
+ saveBlock2Copy->playerTrainerId[0] +
+ saveBlock2Copy->playerTrainerId[1] +
+ saveBlock2Copy->playerTrainerId[2] +
+ saveBlock2Copy->playerTrainerId[3]);
// restore saveblock data since the pointers changed
- *gSaveBlock2Ptr = copiedSavs->sav2;
- *gSaveBlock1Ptr = copiedSavs->sav1;
- *gPokemonStoragePtr = copiedSavs->sav3;
+ *gSaveBlock2Ptr = *saveBlock2Copy;
+ *gSaveBlock1Ptr = *saveBlock1Copy;
+ *gPokemonStoragePtr = *pokemonStorageCopy;
// heap was destroyed in the copying process, so reset it
- InitHeap(gHeap, sizeof(gHeap));
+ InitHeap(gHeap, HEAP_SIZE);
// restore interrupt functions
gMain.hblankCallback = hblankCB;
@@ -105,6 +128,168 @@ void MoveSaveBlocks_ResetHeap(void)
// create a new encryption key
encryptionKey = (Random() << 0x10) + (Random());
- ApplyNewEncyprtionKeyToAllEncryptedData(encryptionKey);
+ ApplyNewEncryptionKeyToAllEncryptedData(encryptionKey);
gSaveBlock2Ptr->encryptionKey = encryptionKey;
-}*/
+}
+
+
+u8 sav2_x1_query_bit1(void)
+{
+ return gSaveBlock2Ptr->specialSaveWarp & 1;
+}
+
+void sav2_x9_clear_bit1(void)
+{
+ gSaveBlock2Ptr->specialSaveWarp &= ~1;
+}
+
+void sub_8076D48(void)
+{
+ gSaveBlock2Ptr->specialSaveWarp |= 1;
+}
+
+void sub_8076D5C(void)
+{
+ sub_8084FAC(0);
+ gSaveBlock2Ptr->specialSaveWarp |= 1;
+}
+
+void sav2_gender2_inplace_and_xFE(void)
+{
+ gSaveBlock2Ptr->specialSaveWarp &= ~1;
+}
+
+void copy_player_party_to_sav1(void) // SavePlayerParty
+{
+ int i;
+
+ gSaveBlock1Ptr->playerPartyCount = gPlayerPartyCount;
+
+ for (i = 0; i < 6; i++)
+ gSaveBlock1Ptr->playerParty[i] = gPlayerParty[i];
+}
+
+void copy_player_party_from_sav1(void) // LoadPlayerParty
+{
+ int i;
+
+ gPlayerPartyCount = gSaveBlock1Ptr->playerPartyCount;
+
+ for (i = 0; i < 6; i++)
+ gPlayerParty[i] = gSaveBlock1Ptr->playerParty[i];
+}
+
+void save_serialize_npcs(void) // SaveMapObjects
+{
+ int i;
+
+ for (i = 0; i < 16; i++)
+ gSaveBlock1Ptr->mapObjects[i] = gMapObjects[i];
+}
+
+void save_deserialize_npcs(void) // LoadMapObjects
+{
+ int i;
+
+ for (i = 0; i < 16; i++)
+ gMapObjects[i] = gSaveBlock1Ptr->mapObjects[i];
+}
+
+void SaveSerializedGame(void)
+{
+ copy_player_party_to_sav1();
+ save_serialize_npcs();
+}
+
+void LoadSerializedGame(void)
+{
+ copy_player_party_from_sav1();
+ save_deserialize_npcs();
+}
+
+void copy_bags_and_unk_data_from_save_blocks(void)
+{
+ int i;
+
+ // load player items.
+ for (i = 0; i < 30; i++)
+ gLoadedSaveData.items[i] = gSaveBlock1Ptr->bagPocket_Items[i];
+
+ // load player key items.
+ for (i = 0; i < 30; i++)
+ gLoadedSaveData.keyItems[i] = gSaveBlock1Ptr->bagPocket_KeyItems[i];
+
+ // load player pokeballs.
+ for (i = 0; i < 16; i++)
+ gLoadedSaveData.pokeBalls[i] = gSaveBlock1Ptr->bagPocket_PokeBalls[i];
+
+ // load player TMs and HMs.
+ for (i = 0; i < 64; i++)
+ gLoadedSaveData.TMsHMs[i] = gSaveBlock1Ptr->bagPocket_TMHM[i];
+
+ // load player berries.
+ for (i = 0; i < 46; i++)
+ gLoadedSaveData.berries[i] = gSaveBlock1Ptr->bagPocket_Berries[i];
+
+ // load mail.
+ for (i = 0; i < 16; i++)
+ gLoadedSaveData.mail[i] = gSaveBlock1Ptr->mail[i];
+
+ gLastEncryptionKey = gSaveBlock2Ptr->encryptionKey;
+}
+
+void copy_bags_and_unk_data_to_save_blocks(void)
+{
+ int i;
+ u32 encryptionKeyBackup;
+
+ // save player items.
+ for (i = 0; i < 30; i++)
+ gSaveBlock1Ptr->bagPocket_Items[i] = gLoadedSaveData.items[i];
+
+ // save player key items.
+ for (i = 0; i < 30; i++)
+ gSaveBlock1Ptr->bagPocket_KeyItems[i] = gLoadedSaveData.keyItems[i];
+
+ // save player pokeballs.
+ for (i = 0; i < 16; i++)
+ gSaveBlock1Ptr->bagPocket_PokeBalls[i] = gLoadedSaveData.pokeBalls[i];
+
+ // save player TMs and HMs.
+ for (i = 0; i < 64; i++)
+ gSaveBlock1Ptr->bagPocket_TMHM[i] = gLoadedSaveData.TMsHMs[i];
+
+ // save player berries.
+ for (i = 0; i < 46; i++)
+ gSaveBlock1Ptr->bagPocket_Berries[i] = gLoadedSaveData.berries[i];
+
+ // save mail.
+ for (i = 0; i < 16; i++)
+ gSaveBlock1Ptr->mail[i] = gLoadedSaveData.mail[i];
+
+ encryptionKeyBackup = gSaveBlock2Ptr->encryptionKey;
+ gSaveBlock2Ptr->encryptionKey = gLastEncryptionKey;
+ ApplyNewEncryptionKeyToBagItems(encryptionKeyBackup);
+ gSaveBlock2Ptr->encryptionKey = encryptionKeyBackup; // updated twice?
+}
+
+void ApplyNewEncryptionKeyToHword(u16 *hWord, u32 newKey)
+{
+ *hWord ^= gSaveBlock2Ptr->encryptionKey;
+ *hWord ^= newKey;
+}
+
+void ApplyNewEncryptionKeyToWord(u32 *word, u32 newKey)
+{
+ *word ^= gSaveBlock2Ptr->encryptionKey;
+ *word ^= newKey;
+}
+
+void ApplyNewEncryptionKeyToAllEncryptedData(u32 encryptionKey)
+{
+ ApplyNewEncryptionKeyToGameStats(encryptionKey);
+ ApplyNewEncryptionKeyToBagItems_(encryptionKey);
+ ApplyNewEncryptionKeyToBerryPowder(encryptionKey);
+ ApplyNewEncryptionKeyToWord(&gSaveBlock1Ptr->money, encryptionKey);
+ ApplyNewEncryptionKeyToHword(&gSaveBlock1Ptr->coins, encryptionKey);
+}