pmd-red/src/save.c
2023-09-01 01:14:34 -04:00

966 lines
26 KiB
C

#include "global.h"
#include "code_80118A4.h"
#include "code_80130A8.h"
#include "code_8097670.h"
#include "event_flag.h"
#include "exclusive_pokemon.h"
#include "flash.h"
#include "friend_area.h"
#include "game_options.h"
#include "memory.h"
#include "pokemon.h"
#include "random.h"
#include "save.h"
#include "team_inventory.h"
EWRAM_DATA_2 u32 gUnknown_203B17C = {0};
EWRAM_DATA_2 char *gUnknown_203B180 = {0};
EWRAM_DATA_2 struct UnkStruct_203B184 *gUnknown_203B184 = {0};
extern struct GameOptions *gGameOptionsRef;
// size: 0x800
struct unk_struct
{
u32 unk0;
u8 gameInternalName[16]; // has "POKE_DUNGEON__05
u32 checksum;
u32 unk18;
struct DungeonLocation dungeonLocation;
u32 unk20;
u32 padding[503];
};
struct SavePakRead
{
u32 state;
u32 readStatus;
};
EWRAM_DATA_2 struct SavePakRead *gSavePakRead = {0};
struct SavePakWrite
{
u32 state;
s32 unk4;
u32 saveStatus;
struct OpenedFile *faceFile;
u8 *faceData;
u16 unk14;
u16 unk16;
u8 unk18;
u8 unk19;
u8 unk1A;
u8 unk1B;
u16 pokeID;
};
EWRAM_DATA_2 struct SavePakWrite *gSavePakWrite = {0};
struct QuickSaveRead
{
s32 state;
u8 *dest;
u32 size;
bool8 saveValid;
};
EWRAM_DATA_2 struct QuickSaveRead *gQuickSaveRead = {0};
struct QuickSaveWrite
{
s32 state;
u8 *unk4;
u32 unk8;
u8 unkC;
u32 quickSaveStatus;
};
EWRAM_DATA_2 struct QuickSaveWrite *gQuickSaveWrite = {0};
extern s32 gUnknown_202DE28;
extern u32 *gUnknown_203B488;
ALIGNED(4) const char sGameInternalVersion[] = _("POKE_DUNGEON__05");
ALIGNED(4) static const char fill_save0[] = _("pksdir0");
ALIGNED(4) static const char fill_save1[] = _("pksdir0");
ALIGNED(4) static const char fill_save2[] = _("pksdir0");
ALIGNED(4) static const char fill_save3[] = _("pksdir0");
ALIGNED(4) const char gSaveCorrupted[] = _("{CENTER_ALIGN}The game data is corrupted.\n"
"{CENTER_ALIGN}Your data will be erased.");
ALIGNED(4) static const char fill_save4[] = _("pksdir0");
ALIGNED(4) const char gSavingAdventure[] = _("{CENTER_ALIGN}Saving your adventure...\n"
"{CENTER_ALIGN}Please don{APOSTROPHE}t turn off the power.");
ALIGNED(4) const char gWriteGamePak[] = _("{CENTER_ALIGN}Writing to GBA Game Pak.\n"
"{CENTER_ALIGN}Do not remove the GBA Game Pak.\n"
"{CENTER_ALIGN}Please wait with the power on.");
ALIGNED(4) const char gSaveCompleted[] = _("{CENTER_ALIGN}Save completed!");
ALIGNED(4) const char gSaveNotWritten[] = _("{CENTER_ALIGN}The data could not be written.\n"
"{CENTER_ALIGN}Please turn off the power and remove\n"
"{CENTER_ALIGN}and reinsert the DS Card.");
ALIGNED(4) const char gSaveFailed[] = _("{CENTER_ALIGN}Save failed.");
ALIGNED(4) static const char fill_save5[] = _("pksdir0");
ALIGNED(4) const char gUnknown_80D44C8[] = _("{CENTER_ALIGN}Your data was not properly saved{COMMA}\n"
"{CENTER_ALIGN}so your game cannot be resumed\n"
"{CENTER_ALIGN}from your last spot.{EXTRA_MSG}"
"{CENTER_ALIGN}Your last outing is considered a defeat.\n"
"{CENTER_ALIGN}Before shutting down{COMMA} save in your\n"
"{CENTER_ALIGN}team base{COMMA} or quicksave in a dungeon.");
ALIGNED(4) static const char fill_save6[] = _("pksdir0");
ALIGNED(4) const char gUnknown_80D45AC[] = _("{CENTER_ALIGN}Quicksaving your adventure...\n"
"{CENTER_ALIGN}Please don{APOSTROPHE}t turn off the power.");
ALIGNED(4) const char gUnknown_80D45F4[] = _("{CENTER_ALIGN}Your adventure has been saved.\n"
"{CENTER_ALIGN}When you are in a dungeon{COMMA} quicksave\n"
"{CENTER_ALIGN}your progress before ending the game.");
ALIGNED(4) const char gUnknown_80D4668[] = _("{CENTER_ALIGN}Your adventure has been saved.\n"
"{CENTER_ALIGN}When you resume play{COMMA} the quicksave\n"
"{CENTER_ALIGN}data will be deleted.{EXTRA_MSG}"
"{CENTER_ALIGN}When you are shutting down the game{COMMA}\n"
"{CENTER_ALIGN}save your progress in your team base{COMMA}\n"
"{CENTER_ALIGN}or quicksave in a dungeon.");
ALIGNED(4) const char gSaveNotWritten2[] = _("{CENTER_ALIGN}The data could not be written.\n"
"{CENTER_ALIGN}Please turn off the power and remove\n"
"{CENTER_ALIGN}and reinsert the DS Card.");
ALIGNED(4) const char gSaveFailed2[] = _("{CENTER_ALIGN}Save failed.");
ALIGNED(4) static const char fill_save7[] = _("pksdir0");
extern bool8 sub_800DAB0(u16, u8*, s32);
extern bool8 sub_800DAB4(u16, u8*, s32);
extern bool8 sub_800DAB8(void);
extern void sub_80140DC();
extern void sub_8014114();
extern u32 SaveRecruitedPokemon(u8 *, u32);
extern u32 RestoreRecruitedPokemon(void* a, s32 b);
extern u32 SavePokemonStruct2(u8 *, u32);
extern u32 RestorePokemonStruct2(void* a, s32 b);
extern u32 sub_80921C4(u8 *, u32);
extern u32 sub_80954CC(void* a, s32 b);
extern u32 sub_8095624(u8 *, u32);
extern u32 RestoreMailInfo(void* a, s32 b);
extern u32 SaveMailInfo(u8 *, u32);
extern u32 sub_8097D60(u8 *, u32);
extern u32 sub_8097D98(void* a, s32 b);
extern void sub_80993E4();
extern void sub_800135C(void);
extern void sub_80958E4(u32 *a, u32 b);
extern struct unkStruct_203B490 *GetMailInfo(void);
extern void InitializeMailJobsNews(void);
extern void sub_80972F4(void);
extern void sub_80974E8(void);
extern void sub_80993D8(void);
u32 sub_8011C1C(void)
{
return gUnknown_203B17C;
}
void sub_8011C28(u32 in)
{
gUnknown_203B17C = in;
}
s32 sub_8011C34(void)
{
return gUnknown_202DE28;
}
void sub_8011C40(s32 in)
{
gUnknown_202DE28 = in;
}
char *GetGameInternalName(void)
{
return gUnknown_203B180; // returns POKE_DUNGEON__05
}
void CalculateChecksum(u8 *out, u32 size)
{
u32 checksum = 0;
s32 i = size / 4;
if (i > 1)
{
u32 *ptr = (u32 *)&out[4];
--i;
do
checksum += *ptr++;
while (--i);
}
*(u32 *)out = checksum;
}
bool8 ValidateChecksum(u8 *in, u32 size)
{
u32 checksum = 0;
s32 i = size / 4;
if (i > 1)
{
u32 *ptr = (u32 *)&in[4];
--i;
do
checksum += *ptr++;
while (--i);
}
if (*(u32 *)in != checksum)
return TRUE;
return FALSE;
}
void sub_8011CA8(u32 *out, s32 size)
{
if (gUnknown_203B184 == NULL) {
AGB_WARNING("A warning most likely went here.");
*out += (size + 0xFFF) / 0x1000;
} else {
*out += (size + 0xFFF) / 0x1000;
}
}
u32 WriteSaveSector(s32 *a, u8 *src, s32 size)
{
u32 r1;
s32 sector = *a;
sub_8011CA8(a, size);
CalculateChecksum(src, size);
if (gUnknown_203B184 == NULL) {
r1 = WriteFlashData(sector, src, size);
}
else if (sub_800DAB8()) {
if (!sub_800DAB4(sector, src, size)) {
r1 = 3;
}
else {
r1 = 0;
}
}
else {
return SAVE_FAILED;
}
if (r1 == 4) {
return SAVE_NOT_WRTTEN;
}
if (r1) {
return SAVE_FAILED;
}
return SAVE_COMPLETED;
}
u32 ReadSaveSector(s32 *a, u8 *dest, s32 size)
{
u32 r1;
s32 sector = *a;
sub_8011CA8(a, size);
if (gUnknown_203B184 == NULL) {
r1 = ReadFlashData(sector, dest, size);
}
else if (sub_800DAB8()) {
if (!sub_800DAB0(sector, dest, size)) {
r1 = 1;
}
else {
r1 = 0;
}
}
else {
return READ_SAVE_FAILED;
}
if (r1) {
return READ_SAVE_FAILED;
}
if (ValidateChecksum(dest, size)) {
return READ_SAVE_CHECKSUM_ERROR;
}
return READ_SAVE_VALID;
}
// Unused
bool8 sub_8011DA8(void)
{
return TRUE;
}
u32 ReadSaveFromPak(u32 *a)
{
struct UnkStruct_sub_8011DAC *playerSave = MemoryAlloc(sizeof(struct UnkStruct_sub_8011DAC), 5);
u8 *r4 = playerSave->unk448;
u32 saveStatus = ReadSaveSector(a, (u8*)playerSave, sizeof(struct UnkStruct_sub_8011DAC));
u32 r1;
if (saveStatus)
{
saveStatus = ReadSaveSector(a, (u8*)playerSave, sizeof(struct UnkStruct_sub_8011DAC));
}
else
{
sub_8011CA8(a, sizeof(struct UnkStruct_sub_8011DAC));
}
if (!saveStatus)
{
if (playerSave->checksum != 0x5071412) {
saveStatus = 4;
}
}
if (!saveStatus)
{
if (gUnknown_203B184 == NULL) {
sub_8011C28(playerSave->unk41C);
sub_8011C40(playerSave->unk418);
SetRNGSeed(playerSave->RngState);
}
else {
gUnknown_203B184->unk054 = playerSave->unk41C;
gUnknown_203B184->unk050 = playerSave->unk418;
gUnknown_203B184->RngState = playerSave->RngState;
}
}
if (!saveStatus)
{
if (gUnknown_203B184 == NULL) {
if (!sub_8002718(playerSave->unk004)) {
saveStatus = 4;
}
}
else {
MemoryCopy8(gUnknown_203B184->unk04C, playerSave->unk004, ARRAY_COUNT(playerSave->unk004));
}
}
if (!saveStatus)
{
r1 = RestoreRecruitedPokemon(r4, 0x4650);
if (r1 != playerSave->savedRecruitedPokemon) {
saveStatus = 3;
}
r4 += 0x4650;
r1 = RestorePokemonStruct2(r4, 0x258);
if (r1 != playerSave->unk428) {
saveStatus = 3;
}
r4 += 0x258;
r1 = RestoreTeamInventory(r4, 0x1D8);
if (r1 != playerSave->savedTeamInventory) {
saveStatus = 3;
}
r4 += 0x1d8;
r1 = ReadRescueTeamInfo(r4, 0x10);
if (r1 != playerSave->savedRescueTeamInfo) {
saveStatus = 3;
}
r4 += 0x10;
r1 = ReadSavedFriendAreas(r4, 0x8);
if (r1 != playerSave->savedFriendAreas) {
saveStatus = 3;
}
r4 += 0x8;
r1 = sub_8097D98(r4, 0x100);
if (r1 != playerSave->unk43C) {
saveStatus = 3;
}
r4 += 0x100;
r1 = sub_80954CC(r4, 0x594);
if (r1 != playerSave->unk440) {
saveStatus = 3;
}
r4 += 0x594;
r1 = RestoreMailInfo(r4, 0x221);
if (r1 != playerSave->savedMailInfo) {
saveStatus = 3;
}
}
MemoryFree(playerSave);
return saveStatus;
}
u32 sub_8011F9C(s32 *r0, u8 *dest, s32 size)
{
return ReadSaveSector(r0, dest, size);
}
u32 sub_8011FA8(void)
{
u32 saveStatus;
u32 temp3;
u32 temp;
struct unk_struct *r5 = MemoryAlloc(sizeof(struct unk_struct), 5);
temp = 0x1F;
saveStatus = ReadSaveSector(&temp, (u8 *)r5, sizeof(struct unk_struct));
if( saveStatus == READ_SAVE_VALID)
{
if(r5->checksum != 0x5071412)
{
saveStatus = 4;
}
}
temp3 = 0xf1209;
if(saveStatus == READ_SAVE_VALID)
{
temp3 = r5->unk18;
}
MemoryFree(r5);
return temp3;
}
bool8 IsSaveCorrupted(void)
{
u32 temp;
bool8 isCorrupted;
struct unk_struct *r5 = MemoryAlloc(sizeof(struct unk_struct), 5);
temp = 0x1F;
isCorrupted = FALSE;
if(ReadSaveSector(&temp, (u8 *)r5, sizeof(struct unk_struct)) == READ_SAVE_VALID)
{
if(r5->checksum == 0x5071412)
{
isCorrupted = TRUE;
}
}
MemoryFree(r5);
return isCorrupted;
}
u32 WriteSavetoPak(s32 *param_1, u32 param_2)
{
struct UnkStruct_sub_8011DAC *playerSave;
char *gameName;
int saveStatus1;
int saveStatus2;
u8 *array_ptr;
playerSave = MemoryAlloc(sizeof(struct UnkStruct_sub_8011DAC),5);
array_ptr = playerSave->unk448;
if (gUnknown_203B184 == NULL) {
playerSave->unk41C = param_2;
playerSave->unk418 = sub_8011C34();
playerSave->RngState = GetRNGSeed();
}
else {
playerSave->unk41C = gUnknown_203B184->unk054;
playerSave->unk418 = gUnknown_203B184->unk050;
playerSave->RngState = gUnknown_203B184->RngState;
}
playerSave->checksum = 0x5071412;
gameName = GetGameInternalName();
strncpy(playerSave->gameInternalName,gameName, ARRAY_COUNT(playerSave->gameInternalName));
if (gUnknown_203B184 == NULL) {
sub_8002700(playerSave->unk004);
}
else {
MemoryCopy8(playerSave->unk004,gUnknown_203B184->unk04C,ARRAY_COUNT(playerSave->unk004));
}
playerSave->savedRecruitedPokemon = SaveRecruitedPokemon(array_ptr,0x4650);
array_ptr += 0x4650;
playerSave->unk428 = SavePokemonStruct2(array_ptr,0x258);
array_ptr += 0x258;
playerSave->savedTeamInventory = SaveTeamInventory(array_ptr,0x1D8);
array_ptr += 0x1D8;
playerSave->savedRescueTeamInfo = SaveRescueTeamInfo(array_ptr,0x10);
array_ptr += 0x10;
playerSave->savedFriendAreas = SaveFriendAreas(array_ptr,8);
array_ptr += 8;
playerSave->unk43C = sub_8097D60(array_ptr,0x100);
array_ptr += 0x100;
playerSave->unk440 = sub_8095624(array_ptr,0x594);
array_ptr += 0x594;
playerSave->savedMailInfo = SaveMailInfo(array_ptr,0x221);
saveStatus1 = WriteSaveSector(param_1,(u8 *)playerSave,sizeof(struct UnkStruct_sub_8011DAC));
saveStatus2 = WriteSaveSector(param_1,(u8 *)playerSave,sizeof(struct UnkStruct_sub_8011DAC));
MemoryFree(playerSave);
if (saveStatus1 != SAVE_COMPLETED)
return saveStatus1;
if (saveStatus2 != SAVE_COMPLETED)
return saveStatus2;
return SAVE_COMPLETED;
}
s32 sub_80121D4(s32 *a, u8 *src, s32 size)
{
return WriteSaveSector(a, src, size);
}
u32 sub_80121E0(u32 r0)
{
u32 temp;
char *gameName;
u32 saveStatus;
struct unk_struct *r4 = MemoryAlloc(sizeof(struct unk_struct), 5);
temp = 0x1F;
r4->unk18 = r0;
r4->dungeonLocation = *GetDungeonLocationInfo();
r4->checksum = 0x5071412;
gameName = GetGameInternalName();
strncpy(r4->gameInternalName, gameName, ARRAY_COUNT(r4->gameInternalName));
sub_80958E4(&r4->unk20, 0);
saveStatus = WriteSaveSector(&temp, (u8 *)r4, sizeof(struct unk_struct));
MemoryFree(r4);
return saveStatus;
}
u32 sub_8012240(void)
{
s32 status;
struct unk_struct *r5 = MemoryAlloc(sizeof(struct unk_struct), 5);
MemoryFill8((u8 *)r5, 0xFF, 0x4);
sub_8011830();
status = WriteFlashData(0x1F, (u8 *)r5, sizeof(struct unk_struct));
xxx_call_start_bg_music();
MemoryFree(r5);
if(status != 0)
return SAVE_FAILED;
else
return SAVE_COMPLETED;
}
void sub_8012284(void)
{
sub_80122D0();
sub_80122F4();
InitializePlayerData();
}
void sub_8012298(void)
{
sub_80976A8();
sub_80122A8();
}
void sub_80122A8(void)
{
sub_80122D0();
sub_80122F4();
InitializePlayerData();
sub_8012240();
}
void nullsub_33(void)
{
}
void sub_80122C4(void)
{
sub_80122A8();
}
void sub_80122D0(void)
{
sub_8011C28(0);
sub_8011C40(-1);
ResetNumAdventures();
ResetPlayTime(gPlayTimeRef);
}
void sub_80122F4(void)
{
sub_800135C();
}
void InitializePlayerData(void)
{
InitializeFriendAreas();
InitializeRecruitedPokemon();
InitializeMoneyItems();
InitializeRescueTeamInfo();
sub_80972F4();
sub_8095118();
InitializeMailJobsNews();
sub_80974E8();
InitializeGameOptions(TRUE);
InitializeExclusivePokemon();
}
UNUSED static void nullsub_200(u32 r0)
{
}
UNUSED static void sub_8012334(struct UnkStruct_203B184 *r0)
{
gUnknown_203B184 = r0;
if (r0 != NULL) {
gTeamInventoryRef = r0->MoneyItems;
gRecruitedPokemonRef = r0->recruitedPokemon;
gUnknown_203B480 = r0->unk8;
gUnknown_203B484 = r0->unkC;
gUnknown_203B488 = r0->unk10;
gUnknown_203B48C = r0->unk14;
gUnknown_203B490 = r0->mailInfo;
gRescueTeamInfoRef = r0->RescueTeamInfo;
gUnknown_203B494 = r0->unk20;
gUnknown_203B498 = r0->ExclusivePokemon;
gFriendAreas = r0->BoughtFriendAreas;
gGameOptionsRef = r0->gameOptions;
gPlayTimeRef = r0->playTime;
}
else {
gTeamInventoryRef = GetMoneyItemsInfo();
gRecruitedPokemonRef = GetRecruitedPokemon();
gUnknown_203B480 = sub_80950F8();
gUnknown_203B484 = sub_8095100();
gUnknown_203B488 = sub_8095108();
gUnknown_203B48C = sub_8095110();
gUnknown_203B490 = GetMailInfo();
gRescueTeamInfoRef = GetRescueTeamInfo();
gUnknown_203B494 = sub_8097680();
gUnknown_203B498 = GetExclusivePokemon();
gFriendAreas = GetBoughtFriendAreas();
gGameOptionsRef = GetGameOptions();
gPlayTimeRef = GetPlayTime();
}
}
void PrepareSavePakRead(void)
{
gSavePakRead = MemoryAlloc(sizeof(struct SavePakRead), 5);
gSavePakRead->state = 1;
}
u8 ReadSavePak(void)
{
u32 temp;
u32 temp2;
switch(gSavePakRead->state)
{
case 0:
gSavePakRead->state = 1;
break;
case 1:
temp = 0;
gSavePakRead->readStatus = ReadSaveFromPak(&temp);
gSavePakRead->state = 2;
break;
case 2:
if(gSavePakRead->readStatus != READ_SAVE_VALID)
{
if(IsSaveCorrupted())
{
sub_80141B4(gSaveCorrupted, 0, 0, 0x301);
gSavePakRead->state = 3;
}
else
{
gSavePakRead->state = 4;
}
}
else
{
gSavePakRead->state = 6;
}
break;
case 3:
if(sub_80144A4(&temp2) == 0)
gSavePakRead->state = 4;
break;
case 4:
sub_8012298();
gSavePakRead->state = 6;
case 5:
break;
case 6:
return 0;
}
return 1;
}
void FinishReadSavePak(void)
{
if(gSavePakRead != NULL)
{
MemoryFree(gSavePakRead);
gSavePakRead = NULL;
}
}
void PrepareSavePakWrite(s16 PokemonID)
{
struct OpenedFile *file;
s32 id_s32;
struct OpenedFile **preload_face;
id_s32 = PokemonID; // had to cast for asr shift
sub_80993D8();
gSavePakWrite = MemoryAlloc(sizeof(struct SavePakWrite),5);
gSavePakWrite->pokeID = id_s32;
gSavePakWrite->faceFile = NULL;
gSavePakWrite->faceData = NULL;
if (PokemonID != MONSTER_NONE) {
file = GetDialogueSpriteDataPtr(PokemonID);
gSavePakWrite->faceFile = file;
gSavePakWrite->faceData = file->data;
gSavePakWrite->unk18 = 0;
gSavePakWrite->unk19 = 0;
gSavePakWrite->unk1A = 0;
gSavePakWrite->unk14 = 2;
gSavePakWrite->unk16 = 8;
}
if (gSavePakWrite->faceFile != 0) {
preload_face = &gSavePakWrite->faceFile;
sub_80141B4(gSavingAdventure,0,preload_face,0x20);
}
else {
sub_80141B4(gSavingAdventure,0,NULL,0x20);
}
gSavePakWrite->state = 3;
}
bool8 WriteSavePak(void)
{
struct OpenedFile **faceFile;
u32 local_14;
u32 other_stack;
faceFile = NULL;
if (gSavePakWrite->faceFile != 0) {
faceFile = &gSavePakWrite->faceFile;
}
switch(gSavePakWrite->state)
{
case 0:
gSavePakWrite->state = 7;
break;
case 1:
gSavePakWrite->unk4++;
if (gSavePakWrite->unk4 > 8) {
sub_80141B4(gWriteGamePak, 0, 0, 0x20);
gSavePakWrite->state = 3;
}
break;
case 2:
break;
case 3:
gSavePakWrite->state = 4;
break;
case 4:
local_14 = 0;
sub_80140DC();
gSavePakWrite->saveStatus = WriteSavetoPak(&local_14, sub_8011C1C());
switch(gSavePakWrite->saveStatus)
{
case SAVE_COMPLETED:
if(gSavePakWrite->faceFile != NULL)
sub_80141B4(gSaveCompleted, 0, faceFile, 0x101);
else
sub_80141B4(gSaveCompleted, 0, faceFile, 0x101);
gSavePakWrite->state = 5;
break;
case SAVE_NOT_WRTTEN:
sub_80141B4(gSaveNotWritten, 0, 0, 0);
gSavePakWrite->state = 6;
break;
default:
if(gSavePakWrite->faceFile != NULL)
sub_80141B4(gSaveFailed, 0, faceFile, 0x101);
else
sub_80141B4(gSaveFailed, 0, faceFile, 0x101);
gSavePakWrite->state = 5;
break;
}
sub_8014114();
break;
case 5:
if (sub_80144A4(&other_stack) == 0)
gSavePakWrite->state = 7;
break;
case 6:
break;
case 7:
return FALSE;
}
return TRUE;
}
u32 GetSavePakStatus(void)
{
return gSavePakWrite->saveStatus;
}
void FinishWriteSavePak(void)
{
if(gSavePakWrite != NULL)
{
if(gSavePakWrite->faceFile != NULL)
CloseFile(gSavePakWrite->faceFile);
MemoryFree(gSavePakWrite);
gSavePakWrite = NULL;
}
sub_80993E4();
}
void PrepareQuickSaveRead(u8 *dest, u32 size)
{
gQuickSaveRead = MemoryAlloc(sizeof(struct QuickSaveRead), 5);
gQuickSaveRead->dest = dest;
gQuickSaveRead->size = size;
gQuickSaveRead->saveValid = FALSE;
gQuickSaveRead->state = 1;
}
bool8 ReadQuickSave(void)
{
u32 stack_1;
u32 stack_2;
switch(gQuickSaveRead->state)
{
case 0:
gQuickSaveRead->state = 1;
break;
case 1:
stack_1 = 16;
if(sub_8011F9C(&stack_1, gQuickSaveRead->dest, gQuickSaveRead->size) == READ_SAVE_VALID)
{
gQuickSaveRead->saveValid = TRUE;
gQuickSaveRead->state = 3;
}
else
{
// Data was not properly saved
// so your game cannot be resumed
// from your last spot. Your last outing is considered a defeat.
// Before shutting down, save in your
// team base or quicksave in a dungeon
sub_80141B4(gUnknown_80D44C8, 0, 0, 0x301);
gQuickSaveRead->state = 2;
}
break;
case 2:
if(sub_80144A4(&stack_2) == 0)
gQuickSaveRead->state = 3;
break;
case 3:
return FALSE;
default:
break;
}
return TRUE;
}
bool8 IsQuickSaveValid(void)
{
return gQuickSaveRead->saveValid;
}
void FinishQuickSaveRead(void)
{
if(gQuickSaveRead != NULL){
MemoryFree(gQuickSaveRead);
gQuickSaveRead = 0;
}
}
void PrepareQuickSaveWrite(u8 *r0, u32 r1, u8 r2)
{
gQuickSaveWrite = MemoryAlloc(sizeof(struct QuickSaveWrite), 5);
gQuickSaveWrite->unk4 = r0;
gQuickSaveWrite->unk8 = r1;
gQuickSaveWrite->unkC = r2;
gQuickSaveWrite->state = 0;
if(gQuickSaveWrite->unkC != 0)
// Quicksaving your adventure...
// Please don't turn off the power.
sub_80141B4(gUnknown_80D45AC, 0, 0, 0x20);
else
// Quicksaving your adventure...
// Please don't turn off the power.
sub_80141B4(gUnknown_80D45AC, 0, 0, 0x20);
}
u32 WriteQuickSave(void)
{
u32 stack_1;
u32 stack_2;
switch(gQuickSaveWrite->state)
{
case 0:
gQuickSaveWrite->state = 1;
break;
case 1:
sub_80140DC();
stack_1 = 16;
gQuickSaveWrite->quickSaveStatus = sub_80121D4(&stack_1, gQuickSaveWrite->unk4, gQuickSaveWrite->unk8);
gQuickSaveWrite->state = 2;
return 1;
case 2:
stack_1 = 0;
if(gQuickSaveWrite->quickSaveStatus == 0)
gQuickSaveWrite->quickSaveStatus = WriteSavetoPak(&stack_1, 2);
switch(gQuickSaveWrite->quickSaveStatus)
{
case SAVE_COMPLETED:
sub_80121E0(0xf1207);
if(gQuickSaveWrite->unkC != 0)
// Your adventure has been saved
// When you are in a dungeon, quicksave
// your progress before ending the game.
sub_80141B4(gUnknown_80D45F4, 0, 0, 0x301);
else
// Your adventure has been saved.
// When you resume play, the quicksave
// data will be deleted. When you are shutting down the game,
// save your progress in your team base,
// or quicksave in a dungeon.
sub_80141B4(gUnknown_80D4668, 0, 0, 0x301);
gQuickSaveWrite->state = 3;
break;
case SAVE_NOT_WRTTEN:
// The data could not be written.
// Please turn off the power and remove
// and reinsert the DS Card
sub_80141B4(gSaveNotWritten2, 0, 0, 0);
gQuickSaveWrite->state = 4;
break;
default:
sub_80121E0(0xf1209);
sub_80141B4(gSaveFailed2, 0, 0, 0x301);
gQuickSaveWrite->state = 3;
break;
}
sub_8014114();
break;
case 3:
if(sub_80144A4(&stack_2) == 0)
gQuickSaveWrite->state = 5;
break;
case 4:
break;
case 5:
if(gQuickSaveWrite->quickSaveStatus == SAVE_COMPLETED)
return 2;
else
return 3;
break;
default:
break;
}
return 0;
}
void FinishQuickSaveWrite()
{
if (gQuickSaveWrite) {
MemoryFree(gQuickSaveWrite);
gQuickSaveWrite = NULL;
}
}