Document remainder of save.c

This commit is contained in:
GriffinR 2021-10-28 22:54:41 -04:00
parent ab1074e629
commit adf773f1ed
18 changed files with 428 additions and 364 deletions

View File

@ -3,11 +3,11 @@ gLastSaveCounter
gLastKnownGoodSector gLastKnownGoodSector
gDamagedSaveSectors gDamagedSaveSectors
gSaveCounter gSaveCounter
gFastSaveSection gReadWriteSector
gUnknown_03006208 gIncrementalSectorId
gSaveUnusedVar gSaveUnusedVar
gSaveFileStatus gSaveFileStatus
gGameContinueCallback gGameContinueCallback
gRamSaveSectionLocations gRamSaveSectorLocations
gSaveUnusedVar2 gSaveUnusedVar2
gSaveAttemptStatus gSaveAttemptStatus

View File

@ -24,8 +24,8 @@ void SavePlayerParty(void);
void LoadPlayerParty(void); void LoadPlayerParty(void);
void SaveObjectEvents(void); void SaveObjectEvents(void);
void LoadObjectEvents(void); void LoadObjectEvents(void);
void SaveSerializedGame(void); void CopyPartyAndObjectsToSave(void);
void LoadSerializedGame(void); void CopyPartyAndObjectsFromSave(void);
void LoadPlayerBag(void); void LoadPlayerBag(void);
void SavePlayerBag(void); void SavePlayerBag(void);
void ApplyNewEncryptionKeyToHword(u16 *hWord, u32 newKey); void ApplyNewEncryptionKeyToHword(u16 *hWord, u32 newKey);

View File

@ -1,63 +1,18 @@
#ifndef GUARD_SAVE_H #ifndef GUARD_SAVE_H
#define GUARD_SAVE_H #define GUARD_SAVE_H
struct SaveSectionLocation // Each 4 KiB flash sector contains 3968 bytes of actual data followed by a 128 byte footer.
{ // Only 12 bytes of the footer are used.
void *data;
u16 size;
};
struct SaveSection
{
u8 data[0xFF4];
u16 id;
u16 checksum;
u32 security;
u32 counter;
}; // size is 0x1000
// headless save section?
struct UnkSaveSection
{
u8 data[0xFF4];
u32 security;
}; // size is 0xFF8
struct SaveSectionOffsets
{
u16 toAdd;
u16 size;
};
// Each 4 KiB flash sector contains 3968 bytes of actual data followed by a 128 byte footer
#define SECTOR_DATA_SIZE 3968 #define SECTOR_DATA_SIZE 3968
#define SECTOR_FOOTER_SIZE 128 #define SECTOR_FOOTER_SIZE 128
#define SECTOR_SIZE (SECTOR_DATA_SIZE + SECTOR_FOOTER_SIZE) #define SECTOR_SIZE (SECTOR_DATA_SIZE + SECTOR_FOOTER_SIZE)
#define NUM_SAVE_SLOTS 2 #define NUM_SAVE_SLOTS 2
#define UNKNOWN_CHECK_VALUE 0x8012025 // If the sector's security field is not this value then the sector is either invalid or empty.
#define SPECIAL_SECTION_SENTINEL 0xB39D #define SECTOR_SECURITY_NUM 0x8012025
// SetDamagedSectorBits states #define SPECIAL_SECTOR_SENTINEL 0xB39D
enum
{
ENABLE,
DISABLE,
CHECK // unused
};
// Do save types
enum
{
SAVE_NORMAL,
SAVE_LINK,
//EREADER_SAVE, // deprecated in Emerald
SAVE_LINK2, // unknown 2nd link save
SAVE_HALL_OF_FAME,
SAVE_OVERWRITE_DIFFERENT_FILE,
SAVE_HALL_OF_FAME_ERASE_BEFORE // unused
};
#define SECTOR_ID_SAVEBLOCK2 0 #define SECTOR_ID_SAVEBLOCK2 0
#define SECTOR_ID_SAVEBLOCK1_START 1 #define SECTOR_ID_SAVEBLOCK1_START 1
@ -72,41 +27,87 @@ enum
#define SECTOR_ID_RECORDED_BATTLE 31 #define SECTOR_ID_RECORDED_BATTLE 31
#define SECTORS_COUNT 32 #define SECTORS_COUNT 32
#define NUM_HOF_SECTORS 2
#define SAVE_STATUS_EMPTY 0 #define SAVE_STATUS_EMPTY 0
#define SAVE_STATUS_OK 1 #define SAVE_STATUS_OK 1
#define SAVE_STATUS_CORRUPT 2 #define SAVE_STATUS_CORRUPT 2
#define SAVE_STATUS_NO_FLASH 4 #define SAVE_STATUS_NO_FLASH 4
#define SAVE_STATUS_ERROR 0xFF #define SAVE_STATUS_ERROR 0xFF
// Special sector id value for certain save functions to
// indicate that no specific sector should be used.
#define FULL_SAVE_SLOT 0xFFFF
// SetDamagedSectorBits states
enum
{
ENABLE,
DISABLE,
CHECK // unused
};
// Do save types
enum
{
SAVE_NORMAL,
SAVE_LINK, // Link / Battle Frontier
//EREADER_SAVE, // deprecated in Emerald
SAVE_LINK2, // unknown 2nd link save
SAVE_HALL_OF_FAME,
SAVE_OVERWRITE_DIFFERENT_FILE,
SAVE_HALL_OF_FAME_ERASE_BEFORE // unused
};
// A save sector location holds a pointer to the data for a particular sector
// and the size of that data. Size cannot be greater than SECTOR_DATA_SIZE.
struct SaveSectorLocation
{
void *data;
u16 size;
};
struct SaveSector
{
u8 data[SECTOR_DATA_SIZE];
u8 unused[SECTOR_FOOTER_SIZE - 12]; // Unused portion of the footer
u16 id;
u16 checksum;
u32 security;
u32 counter;
}; // size is SECTOR_SIZE (0x1000)
#define SECTOR_SECURITY_OFFSET offsetof(struct SaveSector, security)
#define SECTOR_COUNTER_OFFSET offsetof(struct SaveSector, counter)
extern u16 gLastWrittenSector; extern u16 gLastWrittenSector;
extern u32 gLastSaveCounter; extern u32 gLastSaveCounter;
extern u16 gLastKnownGoodSector; extern u16 gLastKnownGoodSector;
extern u32 gDamagedSaveSectors; extern u32 gDamagedSaveSectors;
extern u32 gSaveCounter; extern u32 gSaveCounter;
extern struct SaveSection *gFastSaveSection; extern struct SaveSector *gFastSaveSector;
extern u16 gUnknown_03006208; extern u16 gIncrementalSectorId;
extern u16 gSaveFileStatus; extern u16 gSaveFileStatus;
extern void (*gGameContinueCallback)(void); extern void (*gGameContinueCallback)(void);
extern struct SaveSectionLocation gRamSaveSectionLocations[]; extern struct SaveSectorLocation gRamSaveSectorLocations[];
extern u16 gUnknown_03006294;
extern struct SaveSection gSaveDataBuffer; extern struct SaveSector gSaveDataBuffer;
void ClearSaveData(void); void ClearSaveData(void);
void Save_ResetSaveCounters(void); void Save_ResetSaveCounters(void);
u8 HandleSavingData(u8 saveType); u8 HandleSavingData(u8 saveType);
u8 TrySavingData(u8 saveType); u8 TrySavingData(u8 saveType);
bool8 sub_8153380(void); bool8 LinkFullSave_Init(void);
bool8 sub_81533AC(void); bool8 LinkFullSave_WriteSector(void);
bool8 sub_81533E0(void); bool8 LinkFullSave_ReplaceLastSector(void);
bool8 sub_8153408(void); bool8 LinkFullSave_SetLastSectorSecurity(void);
bool8 FullSaveGame(void); bool8 WriteSaveBlock2(void);
bool8 CheckSaveFile(void); bool8 WriteSaveBlock1Sector(void);
u8 Save_LoadGameData(u8 saveType); u8 LoadGameSave(u8 saveType);
u16 GetSaveBlocksPointersBaseOffset(void); u16 GetSaveBlocksPointersBaseOffset(void);
u32 TryReadSpecialSaveSection(u8 sector, u8* dst); u32 TryReadSpecialSaveSector(u8 sector, u8* dst);
u32 TryWriteSpecialSaveSection(u8 sector, u8* src); u32 TryWriteSpecialSaveSector(u8 sector, u8* src);
void Task_LinkSave(u8 taskId); void Task_LinkFullSave(u8 taskId);
// save_failed_screen.c // save_failed_screen.c
void DoSaveFailedScreen(u8 saveType); void DoSaveFailedScreen(u8 saveType);

View File

@ -2785,7 +2785,7 @@ static bool8 LinkPlayAgainHandleSaving(void)
} }
break; break;
case 2: case 2:
FullSaveGame(); WriteSaveBlock2();
sBerryBlender->linkPlayAgainState++; sBerryBlender->linkPlayAgainState++;
sBerryBlender->framesToWait = 0; sBerryBlender->framesToWait = 0;
break; break;
@ -2799,7 +2799,7 @@ static bool8 LinkPlayAgainHandleSaving(void)
case 4: case 4:
if (IsLinkTaskFinished()) if (IsLinkTaskFinished())
{ {
if (CheckSaveFile()) if (WriteSaveBlock1Sector())
{ {
sBerryBlender->linkPlayAgainState = 5; sBerryBlender->linkPlayAgainState = 5;
} }

View File

@ -3244,10 +3244,10 @@ static u32 Cmd_SaveGame(struct BerryCrushGame *game, u8 *args)
DrawDialogueFrame(0, 0); DrawDialogueFrame(0, 0);
AddTextPrinterParameterized2(0, FONT_NORMAL, gText_SavingDontTurnOffPower, 0, 0, 2, 1, 3); AddTextPrinterParameterized2(0, FONT_NORMAL, gText_SavingDontTurnOffPower, 0, 0, 2, 1, 3);
CopyWindowToVram(0, 3); CopyWindowToVram(0, 3);
CreateTask(Task_LinkSave, 0); CreateTask(Task_LinkFullSave, 0);
break; break;
case 3: case 3:
if (FuncIsActiveTask(Task_LinkSave)) if (FuncIsActiveTask(Task_LinkFullSave))
return 0; return 0;
break; break;
case 4: case 4:

View File

@ -5035,12 +5035,12 @@ static void Msg_SavingDontTurnOff(void)
case 2: case 2:
if (!IsDma3ManagerBusyWithBgCopy()) if (!IsDma3ManagerBusyWithBgCopy())
{ {
CreateTask(Task_LinkSave, 0); CreateTask(Task_LinkFullSave, 0);
sGfx->state++; sGfx->state++;
} }
break; break;
case 3: case 3:
if (!FuncIsActiveTask(Task_LinkSave)) if (!FuncIsActiveTask(Task_LinkFullSave))
sGfx->state++; sGfx->state++;
break; break;
default: default:

View File

@ -481,7 +481,7 @@ static bool32 TryWriteTrainerHill_Internal(struct EReaderTrainerHillSet * hillSe
} }
hillTag->checksum = CalcByteArraySum((u8 *)hillTag->floors, NUM_TRAINER_HILL_FLOORS * sizeof(struct TrHillFloor)); hillTag->checksum = CalcByteArraySum((u8 *)hillTag->floors, NUM_TRAINER_HILL_FLOORS * sizeof(struct TrHillFloor));
if (TryWriteSpecialSaveSection(SECTOR_ID_TRAINER_HILL, (u8 *)hillTag) != SAVE_STATUS_OK) if (TryWriteSpecialSaveSector(SECTOR_ID_TRAINER_HILL, (u8 *)hillTag) != SAVE_STATUS_OK)
return FALSE; return FALSE;
return TRUE; return TRUE;
@ -497,7 +497,7 @@ bool32 TryWriteTrainerHill(struct EReaderTrainerHillSet * hillSet)
static bool32 TryReadTrainerHill_Internal(struct EReaderTrainerHillSet * dest, u8 * buffer) static bool32 TryReadTrainerHill_Internal(struct EReaderTrainerHillSet * dest, u8 * buffer)
{ {
if (TryReadSpecialSaveSection(SECTOR_ID_TRAINER_HILL, buffer) != SAVE_STATUS_OK) if (TryReadSpecialSaveSector(SECTOR_ID_TRAINER_HILL, buffer) != SAVE_STATUS_OK)
return FALSE; return FALSE;
memcpy(dest, buffer, sizeof(struct EReaderTrainerHillSet)); memcpy(dest, buffer, sizeof(struct EReaderTrainerHillSet));

View File

@ -487,12 +487,12 @@ static void Task_Hof_InitTeamSaveData(u8 taskId)
if (!gHasHallOfFameRecords) if (!gHasHallOfFameRecords)
{ {
memset(gDecompressionBuffer, 0, 0x2000); memset(gDecompressionBuffer, 0, SECTOR_SIZE * NUM_HOF_SECTORS);
} }
else else
{ {
if (Save_LoadGameData(SAVE_HALL_OF_FAME) != SAVE_STATUS_OK) if (LoadGameSave(SAVE_HALL_OF_FAME) != SAVE_STATUS_OK)
memset(gDecompressionBuffer, 0, 0x2000); memset(gDecompressionBuffer, 0, SECTOR_SIZE * NUM_HOF_SECTORS);
} }
for (i = 0; i < HALL_OF_FAME_MAX_TEAMS; i++, lastSavedTeam++) for (i = 0; i < HALL_OF_FAME_MAX_TEAMS; i++, lastSavedTeam++)
@ -853,7 +853,7 @@ void CB2_DoHallOfFamePC(void)
gTasks[taskId].tMonSpriteId(i) = SPRITE_NONE; gTasks[taskId].tMonSpriteId(i) = SPRITE_NONE;
} }
sHofMonPtr = AllocZeroed(0x2000); sHofMonPtr = AllocZeroed(SECTOR_SIZE * NUM_HOF_SECTORS);
SetMainCallback2(CB2_HallOfFame); SetMainCallback2(CB2_HallOfFame);
} }
break; break;
@ -863,7 +863,7 @@ void CB2_DoHallOfFamePC(void)
static void Task_HofPC_CopySaveData(u8 taskId) static void Task_HofPC_CopySaveData(u8 taskId)
{ {
sub_81980F0(0, 0x1E, 0, 0xC, 0x226); sub_81980F0(0, 0x1E, 0, 0xC, 0x226);
if (Save_LoadGameData(SAVE_HALL_OF_FAME) != SAVE_STATUS_OK) if (LoadGameSave(SAVE_HALL_OF_FAME) != SAVE_STATUS_OK)
{ {
gTasks[taskId].func = Task_HofPC_PrintDataIsCorrupted; gTasks[taskId].func = Task_HofPC_PrintDataIsCorrupted;
} }
@ -872,7 +872,7 @@ static void Task_HofPC_CopySaveData(u8 taskId)
u16 i; u16 i;
struct HallofFameTeam* savedTeams; struct HallofFameTeam* savedTeams;
CpuCopy16(gDecompressionBuffer, sHofMonPtr, 0x2000); CpuCopy16(gDecompressionBuffer, sHofMonPtr, SECTOR_SIZE * NUM_HOF_SECTORS);
savedTeams = sHofMonPtr; savedTeams = sHofMonPtr;
for (i = 0; i < HALL_OF_FAME_MAX_TEAMS; i++, savedTeams++) for (i = 0; i < HALL_OF_FAME_MAX_TEAMS; i++, savedTeams++)
{ {

View File

@ -1145,7 +1145,7 @@ void CB2_InitCopyrightScreenAfterBootup(void)
SetSaveBlocksPointers(GetSaveBlocksPointersBaseOffset()); SetSaveBlocksPointers(GetSaveBlocksPointersBaseOffset());
ResetMenuAndMonGlobals(); ResetMenuAndMonGlobals();
Save_ResetSaveCounters(); Save_ResetSaveCounters();
Save_LoadGameData(SAVE_NORMAL); LoadGameSave(SAVE_NORMAL);
if (gSaveFileStatus == SAVE_STATUS_EMPTY || gSaveFileStatus == SAVE_STATUS_CORRUPT) if (gSaveFileStatus == SAVE_STATUS_EMPTY || gSaveFileStatus == SAVE_STATUS_CORRUPT)
Sav2_ClearSetDefault(); Sav2_ClearSetDefault();
SetPokemonCryStereo(gSaveBlock2Ptr->optionsSound); SetPokemonCryStereo(gSaveBlock2Ptr->optionsSound);

View File

@ -198,13 +198,13 @@ void LoadObjectEvents(void)
gObjectEvents[i] = gSaveBlock1Ptr->objectEvents[i]; gObjectEvents[i] = gSaveBlock1Ptr->objectEvents[i];
} }
void SaveSerializedGame(void) void CopyPartyAndObjectsToSave(void)
{ {
SavePlayerParty(); SavePlayerParty();
SaveObjectEvents(); SaveObjectEvents();
} }
void LoadSerializedGame(void) void CopyPartyAndObjectsFromSave(void)
{ {
LoadPlayerParty(); LoadPlayerParty();
LoadObjectEvents(); LoadObjectEvents();

View File

@ -1282,12 +1282,12 @@ static bool32 SavePokeJump(void)
case 2: case 2:
if (AreLinkQueuesEmpty()) if (AreLinkQueuesEmpty())
{ {
CreateTask(Task_LinkSave, 6); CreateTask(Task_LinkFullSave, 6);
sPokemonJump->mainState++; sPokemonJump->mainState++;
} }
break; break;
case 3: case 3:
if (!FuncIsActiveTask(Task_LinkSave)) if (!FuncIsActiveTask(Task_LinkFullSave))
{ {
ClearMessageWindow(); ClearMessageWindow();
sPokemonJump->mainState++; sPokemonJump->mainState++;

View File

@ -1002,11 +1002,11 @@ static void Task_DoRecordMixing(u8 taskId)
case 2: case 2:
// Mixing Ruby/Sapphire records. // Mixing Ruby/Sapphire records.
SetContinueGameWarpStatusToDynamicWarp(); SetContinueGameWarpStatusToDynamicWarp();
FullSaveGame(); WriteSaveBlock2();
task->tState++; task->tState++;
break; break;
case 3: case 3:
if (CheckSaveFile()) if (WriteSaveBlock1Sector())
{ {
ClearContinueGameWarpStatus2(); ClearContinueGameWarpStatus2();
task->tState = 4; task->tState = 4;
@ -1030,12 +1030,12 @@ static void Task_DoRecordMixing(u8 taskId)
case 6: case 6:
if (!Rfu_SetLinkRecovery(FALSE)) if (!Rfu_SetLinkRecovery(FALSE))
{ {
CreateTask(Task_LinkSave, 5); CreateTask(Task_LinkFullSave, 5);
task->tState++; task->tState++;
} }
break; break;
case 7: // wait for Task_LinkSave to finish. case 7: // wait for Task_LinkFullSave to finish.
if (!FuncIsActiveTask(Task_LinkSave)) if (!FuncIsActiveTask(Task_LinkFullSave))
{ {
if (gWirelessCommType) if (gWirelessCommType)
{ {

View File

@ -306,14 +306,14 @@ static bool32 IsRecordedBattleSaveValid(struct RecordedBattleSave *save)
return TRUE; return TRUE;
} }
static bool32 RecordedBattleToSave(struct RecordedBattleSave *battleSave, struct RecordedBattleSave *saveSection) static bool32 RecordedBattleToSave(struct RecordedBattleSave *battleSave, struct RecordedBattleSave *saveSector)
{ {
memset(saveSection, 0, SECTOR_SIZE); memset(saveSector, 0, SECTOR_SIZE);
memcpy(saveSection, battleSave, sizeof(*battleSave)); memcpy(saveSector, battleSave, sizeof(*battleSave));
saveSection->checksum = CalcByteArraySum((void*)(saveSection), sizeof(*saveSection) - 4); saveSector->checksum = CalcByteArraySum((void*)(saveSector), sizeof(*saveSector) - 4);
if (TryWriteSpecialSaveSection(SECTOR_ID_RECORDED_BATTLE, (void*)(saveSection)) != SAVE_STATUS_OK) if (TryWriteSpecialSaveSector(SECTOR_ID_RECORDED_BATTLE, (void*)(saveSector)) != SAVE_STATUS_OK)
return FALSE; return FALSE;
else else
return TRUE; return TRUE;
@ -477,9 +477,9 @@ bool32 MoveRecordedBattleToSaveData(void)
return ret; return ret;
} }
static bool32 TryCopyRecordedBattleSaveData(struct RecordedBattleSave *dst, struct SaveSection *saveBuffer) static bool32 TryCopyRecordedBattleSaveData(struct RecordedBattleSave *dst, struct SaveSector *saveBuffer)
{ {
if (TryReadSpecialSaveSection(SECTOR_ID_RECORDED_BATTLE, (void*)(saveBuffer)) != SAVE_STATUS_OK) if (TryReadSpecialSaveSector(SECTOR_ID_RECORDED_BATTLE, (void*)(saveBuffer)) != SAVE_STATUS_OK)
return FALSE; return FALSE;
memcpy(dst, saveBuffer, sizeof(struct RecordedBattleSave)); memcpy(dst, saveBuffer, sizeof(struct RecordedBattleSave));
@ -492,7 +492,7 @@ static bool32 TryCopyRecordedBattleSaveData(struct RecordedBattleSave *dst, stru
static bool32 CopyRecordedBattleFromSave(struct RecordedBattleSave *dst) static bool32 CopyRecordedBattleFromSave(struct RecordedBattleSave *dst)
{ {
struct SaveSection *savBuffer = AllocZeroed(sizeof(struct SaveSection)); struct SaveSector *savBuffer = AllocZeroed(SECTOR_SIZE);
bool32 ret = TryCopyRecordedBattleSaveData(dst, savBuffer); bool32 ret = TryCopyRecordedBattleSaveData(dst, savBuffer);
Free(savBuffer); Free(savBuffer);

View File

@ -21,7 +21,7 @@ void ReloadSave(void)
SetSaveBlocksPointers(GetSaveBlocksPointersBaseOffset()); SetSaveBlocksPointers(GetSaveBlocksPointersBaseOffset());
ResetMenuAndMonGlobals(); ResetMenuAndMonGlobals();
Save_ResetSaveCounters(); Save_ResetSaveCounters();
Save_LoadGameData(SAVE_NORMAL); LoadGameSave(SAVE_NORMAL);
if (gSaveFileStatus == SAVE_STATUS_EMPTY || gSaveFileStatus == SAVE_STATUS_CORRUPT) if (gSaveFileStatus == SAVE_STATUS_EMPTY || gSaveFileStatus == SAVE_STATUS_CORRUPT)
Sav2_ClearSetDefault(); Sav2_ClearSetDefault();
SetPokemonCryStereo(gSaveBlock2Ptr->optionsSound); SetPokemonCryStereo(gSaveBlock2Ptr->optionsSound);

File diff suppressed because it is too large Load Diff

View File

@ -363,9 +363,10 @@ static bool8 VerifySectorWipe(u16 sector)
ReadFlash(sector, 0, (u8 *)ptr, SECTOR_SIZE); ReadFlash(sector, 0, (u8 *)ptr, SECTOR_SIZE);
for (i = 0; i < 0x400; i++, ptr++) // 1/4 because ptr is u32
for (i = 0; i < SECTOR_SIZE / 4; i++, ptr++)
if (*ptr) if (*ptr)
return TRUE; return TRUE; // Sector has nonzero data, failed
return FALSE; return FALSE;
} }
@ -375,6 +376,7 @@ static bool8 WipeSector(u16 sector)
u16 i, j; u16 i, j;
bool8 failed = TRUE; bool8 failed = TRUE;
// Attempt to wipe sector with an arbitrary attempt limit of 130
for (i = 0; failed && i < 130; i++) for (i = 0; failed && i < 130; i++)
{ {
for (j = 0; j < SECTOR_SIZE; j++) for (j = 0; j < SECTOR_SIZE; j++)

View File

@ -1269,11 +1269,11 @@ static void Task_SaveAfterLinkBattle(u8 taskId)
break; break;
case 1: case 1:
SetContinueGameWarpStatusToDynamicWarp(); SetContinueGameWarpStatusToDynamicWarp();
FullSaveGame(); WriteSaveBlock2();
*state = 2; *state = 2;
break; break;
case 2: case 2:
if (CheckSaveFile()) if (WriteSaveBlock1Sector())
{ {
ClearContinueGameWarpStatus2(); ClearContinueGameWarpStatus2();
*state = 3; *state = 3;
@ -1290,11 +1290,11 @@ static void Task_SaveAfterLinkBattle(u8 taskId)
DestroyTask(taskId); DestroyTask(taskId);
break; break;
case 5: case 5:
CreateTask(Task_LinkSave, 5); CreateTask(Task_LinkFullSave, 5);
*state = 6; *state = 6;
break; break;
case 6: case 6:
if (!FuncIsActiveTask(Task_LinkSave)) if (!FuncIsActiveTask(Task_LinkFullSave))
{ {
*state = 3; *state = 3;
} }
@ -1374,23 +1374,23 @@ static void RemoveSaveInfoWindow(void)
static void Task_WaitForBattleTowerLinkSave(u8 taskId) static void Task_WaitForBattleTowerLinkSave(u8 taskId)
{ {
if (!FuncIsActiveTask(Task_LinkSave)) if (!FuncIsActiveTask(Task_LinkFullSave))
{ {
DestroyTask(taskId); DestroyTask(taskId);
EnableBothScriptContexts(); EnableBothScriptContexts();
} }
} }
#define tPartialSave data[2] #define tInBattleTower data[2]
void SaveForBattleTowerLink(void) void SaveForBattleTowerLink(void)
{ {
u8 taskId = CreateTask(Task_LinkSave, 5); u8 taskId = CreateTask(Task_LinkFullSave, 5);
gTasks[taskId].tPartialSave = TRUE; gTasks[taskId].tInBattleTower = TRUE;
gTasks[CreateTask(Task_WaitForBattleTowerLinkSave, 6)].data[1] = taskId; gTasks[CreateTask(Task_WaitForBattleTowerLinkSave, 6)].data[1] = taskId;
} }
#undef tPartialSave #undef tInBattleTower
static void HideStartMenuWindow(void) static void HideStartMenuWindow(void)
{ {

View File

@ -4654,30 +4654,29 @@ static void CB2_SaveAndEndTrade(void)
MysteryGift_TryIncrementStat(CARD_STAT_NUM_TRADES, gLinkPlayers[GetMultiplayerId() ^ 1].trainerId); MysteryGift_TryIncrementStat(CARD_STAT_NUM_TRADES, gLinkPlayers[GetMultiplayerId() ^ 1].trainerId);
SetContinueGameWarpStatusToDynamicWarp(); SetContinueGameWarpStatusToDynamicWarp();
sub_8153380(); LinkFullSave_Init();
gMain.state++; gMain.state++;
sTradeData->timer = 0; sTradeData->timer = 0;
break; break;
case 51: case 51:
if (++sTradeData->timer == 5) if (++sTradeData->timer == 5)
{
gMain.state++; gMain.state++;
}
break; break;
case 52: case 52:
if (sub_81533AC()) if (LinkFullSave_WriteSector())
{ {
ClearContinueGameWarpStatus2(); ClearContinueGameWarpStatus2();
gMain.state = 4; gMain.state = 4;
} }
else else
{ {
// Save isn't finished, delay again
sTradeData->timer = 0; sTradeData->timer = 0;
gMain.state = 51; gMain.state = 51;
} }
break; break;
case 4: case 4:
sub_81533E0(); LinkFullSave_ReplaceLastSector();
gMain.state = 40; gMain.state = 40;
sTradeData->timer = 0; sTradeData->timer = 0;
break; break;
@ -4709,7 +4708,7 @@ static void CB2_SaveAndEndTrade(void)
case 42: case 42:
if (_IsLinkTaskFinished()) if (_IsLinkTaskFinished())
{ {
sub_8153408(); LinkFullSave_SetLastSectorSecurity();
gMain.state = 5; gMain.state = 5;
} }
break; break;
@ -4965,7 +4964,7 @@ static void CB2_SaveAndEndWirelessTrade(void)
StringExpandPlaceholders(gStringVar4, gText_SavingDontTurnOffPower); StringExpandPlaceholders(gStringVar4, gText_SavingDontTurnOffPower);
DrawTextOnTradeWindow(0, gStringVar4, 0); DrawTextOnTradeWindow(0, gStringVar4, 0);
IncrementGameStat(GAME_STAT_POKEMON_TRADES); IncrementGameStat(GAME_STAT_POKEMON_TRADES);
sub_8153380(); LinkFullSave_Init();
sTradeData->timer = 0; sTradeData->timer = 0;
} }
break; break;
@ -4974,7 +4973,7 @@ static void CB2_SaveAndEndWirelessTrade(void)
gMain.state = 4; gMain.state = 4;
break; break;
case 4: case 4:
if (sub_81533AC()) if (LinkFullSave_WriteSector())
{ {
gMain.state = 5; gMain.state = 5;
} }
@ -4985,7 +4984,7 @@ static void CB2_SaveAndEndWirelessTrade(void)
} }
break; break;
case 5: case 5:
sub_81533E0(); LinkFullSave_ReplaceLastSector();
gMain.state = 6; gMain.state = 6;
sTradeData->timer = 0; sTradeData->timer = 0;
break; break;
@ -5013,7 +5012,7 @@ static void CB2_SaveAndEndWirelessTrade(void)
case 8: case 8:
if (_IsLinkTaskFinished()) if (_IsLinkTaskFinished())
{ {
sub_8153408(); LinkFullSave_SetLastSectorSecurity();
gMain.state = 9; gMain.state = 9;
} }
break; break;