2017-09-03 14:13:01 +02:00
# include "global.h"
# include "gba/flash_internal.h"
# include "save.h"
2017-12-05 18:55:48 +01:00
# include "constants/game_stat.h"
2017-09-29 10:06:36 +02:00
# include "task.h"
2017-09-03 14:13:01 +02:00
2017-09-03 15:39:33 +02:00
extern struct SaveSectionLocation gRamSaveSectionLocations [ 0xE ] ;
extern u8 gDecompressionBuffer [ ] ;
extern u32 gFlashMemoryPresent ;
extern u16 gUnknown_03006294 ;
2017-09-29 10:06:36 +02:00
extern bool8 gSoftResetDisabled ;
extern const struct SaveSectionOffsets gSaveSectionOffsets [ 0xE ] ;
2017-09-03 15:39:33 +02:00
extern void DoSaveFailedScreen ( u8 ) ; // save_failed_screen
extern void LoadSerializedGame ( void ) ; // load_save
extern bool32 ProgramFlashSectorAndVerify ( u8 sector , u8 * data ) ;
// iwram common
u16 gLastWrittenSector ;
u32 gLastSaveCounter ;
u16 gLastKnownGoodSector ;
u32 gDamagedSaveSectors ;
u32 gSaveCounter ;
struct SaveSection * gFastSaveSection ;
u16 gUnknown_03006208 ;
u16 gSaveUnusedVar ;
2017-09-03 22:50:17 +02:00
u16 gSaveFileStatus ;
2017-09-03 15:39:33 +02:00
void ( * gGameContinueCallback ) ( void ) ;
EWRAM_DATA struct SaveSection gSaveDataBuffer = { 0 } ;
2017-09-03 14:13:01 +02:00
void ClearSaveData ( void )
{
u16 i ;
for ( i = 0 ; i < NUM_SECTORS_PER_SLOT ; i + + )
{
EraseFlashSector ( i ) ;
EraseFlashSector ( i + NUM_SECTORS_PER_SLOT ) ; // clear slot 2.
}
}
void ResetSaveCounters ( void )
{
gSaveCounter = 0 ;
gLastWrittenSector = 0 ;
gDamagedSaveSectors = 0 ;
}
bool32 SetDamagedSectorBits ( u8 op , u8 bit )
{
bool32 retVal = FALSE ;
switch ( op )
{
case ENABLE :
gDamagedSaveSectors | = ( 1 < < bit ) ;
break ;
case DISABLE :
gDamagedSaveSectors & = ~ ( 1 < < bit ) ;
break ;
case CHECK : // unused
if ( gDamagedSaveSectors & ( 1 < < bit ) )
retVal = TRUE ;
break ;
}
return retVal ;
}
u8 save_write_to_flash ( u16 a1 , const struct SaveSectionLocation * location )
{
u32 retVal ;
u16 i ;
2017-09-03 15:39:33 +02:00
gFastSaveSection = & gSaveDataBuffer ;
2017-09-03 14:13:01 +02:00
if ( a1 ! = 0xFFFF ) // for link
{
retVal = HandleWriteSector ( a1 , location ) ;
}
else
{
gLastKnownGoodSector = gLastWrittenSector ; // backup the current written sector before attempting to write.
gLastSaveCounter = gSaveCounter ;
gLastWrittenSector + + ;
gLastWrittenSector = gLastWrittenSector % 0xE ; // array count save sector locations
gSaveCounter + + ;
retVal = 1 ;
for ( i = 0 ; i < 0xE ; i + + )
HandleWriteSector ( i , location ) ;
if ( gDamagedSaveSectors ! = 0 ) // skip the damaged sector.
{
retVal = 0xFF ;
gLastWrittenSector = gLastKnownGoodSector ;
gSaveCounter = gLastSaveCounter ;
}
}
return retVal ;
}
u8 HandleWriteSector ( u16 a1 , const struct SaveSectionLocation * location )
{
u16 i ;
u16 sector ;
u8 * data ;
u16 size ;
sector = a1 + gLastWrittenSector ;
sector % = 0xE ;
sector + = 0xE * ( gSaveCounter % 2 ) ;
data = location [ a1 ] . data ;
size = location [ a1 ] . size ;
// clear save section.
for ( i = 0 ; i < sizeof ( struct SaveSection ) ; i + + )
( ( char * ) gFastSaveSection ) [ i ] = 0 ;
gFastSaveSection - > id = a1 ;
gFastSaveSection - > security = UNKNOWN_CHECK_VALUE ;
gFastSaveSection - > counter = gSaveCounter ;
for ( i = 0 ; i < size ; i + + )
gFastSaveSection - > data [ i ] = data [ i ] ;
gFastSaveSection - > checksum = CalculateChecksum ( data , size ) ;
return TryWriteSector ( sector , gFastSaveSection - > data ) ;
}
u8 HandleWriteSectorNBytes ( u8 sector , u8 * data , u16 size )
{
u16 i ;
2017-09-03 15:39:33 +02:00
struct SaveSection * section = & gSaveDataBuffer ;
2017-09-03 14:13:01 +02:00
for ( i = 0 ; i < sizeof ( struct SaveSection ) ; i + + )
( ( char * ) section ) [ i ] = 0 ;
section - > security = UNKNOWN_CHECK_VALUE ;
for ( i = 0 ; i < size ; i + + )
section - > data [ i ] = data [ i ] ;
section - > id = CalculateChecksum ( data , size ) ; // though this appears to be incorrect, it might be some sector checksum instead of a whole save checksum and only appears to be relevent to HOF data, if used.
return TryWriteSector ( sector , section - > data ) ;
}
u8 TryWriteSector ( u8 sector , u8 * data )
{
if ( ProgramFlashSectorAndVerify ( sector , data ) ! = 0 ) // is damaged?
{
SetDamagedSectorBits ( ENABLE , sector ) ; // set damaged sector bits.
return 0xFF ;
}
else
{
SetDamagedSectorBits ( DISABLE , sector ) ; // unset damaged sector bits. it's safe now.
return 1 ;
}
}
u32 RestoreSaveBackupVarsAndIncrement ( const struct SaveSectionLocation * location ) // location is unused
{
2017-09-03 15:39:33 +02:00
gFastSaveSection = & gSaveDataBuffer ;
2017-09-03 14:13:01 +02:00
gLastKnownGoodSector = gLastWrittenSector ;
gLastSaveCounter = gSaveCounter ;
gLastWrittenSector + + ;
gLastWrittenSector = gLastWrittenSector % 0xE ;
gSaveCounter + + ;
gUnknown_03006208 = 0 ;
gDamagedSaveSectors = 0 ;
return 0 ;
}
u32 RestoreSaveBackupVars ( const struct SaveSectionLocation * location ) // only ever called once, and gSaveBlock2 is passed to this function. location is unused
{
2017-09-03 15:39:33 +02:00
gFastSaveSection = & gSaveDataBuffer ;
2017-09-03 14:13:01 +02:00
gLastKnownGoodSector = gLastWrittenSector ;
gLastSaveCounter = gSaveCounter ;
gUnknown_03006208 = 0 ;
gDamagedSaveSectors = 0 ;
return 0 ;
}
u8 sub_81529D4 ( u16 a1 , const struct SaveSectionLocation * location )
{
u8 retVal ;
if ( gUnknown_03006208 < a1 - 1 )
{
retVal = 1 ;
HandleWriteSector ( gUnknown_03006208 , location ) ;
gUnknown_03006208 + + ;
if ( gDamagedSaveSectors )
{
retVal = 0xFF ;
gLastWrittenSector = gLastKnownGoodSector ;
gSaveCounter = gLastSaveCounter ;
}
}
else
{
retVal = 0xFF ;
}
return retVal ;
}
u8 sub_8152A34 ( u16 a1 , const struct SaveSectionLocation * location )
{
u8 retVal = 1 ;
ClearSaveData_2 ( a1 - 1 , location ) ;
if ( gDamagedSaveSectors )
{
retVal = 0xFF ;
gLastWrittenSector = gLastKnownGoodSector ;
gSaveCounter = gLastSaveCounter ;
}
return retVal ;
}
u8 ClearSaveData_2 ( u16 a1 , const struct SaveSectionLocation * location )
{
u16 i ;
u16 sector ;
u8 * data ;
u16 size ;
u8 status ;
sector = a1 + gLastWrittenSector ;
sector % = 0xE ;
sector + = 0xE * ( gSaveCounter % 2 ) ;
data = location [ a1 ] . data ;
size = location [ a1 ] . size ;
// clear temp save section.
for ( i = 0 ; i < sizeof ( struct SaveSection ) ; i + + )
( ( char * ) gFastSaveSection ) [ i ] = 0 ;
gFastSaveSection - > id = a1 ;
gFastSaveSection - > security = UNKNOWN_CHECK_VALUE ;
gFastSaveSection - > counter = gSaveCounter ;
// set temp section's data.
for ( i = 0 ; i < size ; i + + )
gFastSaveSection - > data [ i ] = data [ i ] ;
// calculate checksum.
gFastSaveSection - > checksum = CalculateChecksum ( data , size ) ;
EraseFlashSector ( sector ) ;
status = 1 ;
for ( i = 0 ; i < sizeof ( struct UnkSaveSection ) ; i + + )
{
if ( ProgramFlashByte ( sector , i , ( ( u8 * ) gFastSaveSection ) [ i ] ) )
{
status = 0xFF ;
break ;
}
}
if ( status = = 0xFF )
{
SetDamagedSectorBits ( ENABLE , sector ) ;
return 0xFF ;
}
else
{
status = 1 ;
for ( i = 0 ; i < 7 ; i + + )
{
if ( ProgramFlashByte ( sector , 0xFF9 + i , ( ( u8 * ) gFastSaveSection ) [ 0xFF9 + i ] ) )
{
status = 0xFF ;
break ;
}
}
if ( status = = 0xFF )
{
SetDamagedSectorBits ( ENABLE , sector ) ;
return 0xFF ;
}
else
{
SetDamagedSectorBits ( DISABLE , sector ) ;
return 1 ;
}
}
}
u8 sav12_xor_get ( u16 a1 , const struct SaveSectionLocation * location )
{
u16 sector ;
sector = a1 + gLastWrittenSector ; // no sub 1?
sector % = 0xE ;
sector + = 0xE * ( gSaveCounter % 2 ) ;
if ( ProgramFlashByte ( sector , sizeof ( struct UnkSaveSection ) , 0x25 ) )
{
// sector is damaged, so enable the bit in gDamagedSaveSectors and restore the last written sector and save counter.
SetDamagedSectorBits ( ENABLE , sector ) ;
gLastWrittenSector = gLastKnownGoodSector ;
gSaveCounter = gLastSaveCounter ;
return 0xFF ;
}
else
{
SetDamagedSectorBits ( DISABLE , sector ) ;
return 1 ;
}
}
u8 sub_8152CAC ( u16 a1 , const struct SaveSectionLocation * location )
{
u16 sector ;
sector = a1 + gLastWrittenSector - 1 ;
sector % = 0xE ;
sector + = 0xE * ( gSaveCounter % 2 ) ;
if ( ProgramFlashByte ( sector , sizeof ( struct UnkSaveSection ) , ( ( u8 * ) gFastSaveSection ) [ sizeof ( struct UnkSaveSection ) ] ) )
{
// sector is damaged, so enable the bit in gDamagedSaveSectors and restore the last written sector and save counter.
SetDamagedSectorBits ( ENABLE , sector ) ;
gLastWrittenSector = gLastKnownGoodSector ;
gSaveCounter = gLastSaveCounter ;
return 0xFF ;
}
else
{
SetDamagedSectorBits ( DISABLE , sector ) ;
return 1 ;
}
}
u8 sub_8152D44 ( u16 a1 , const struct SaveSectionLocation * location )
{
u16 sector ;
sector = a1 + gLastWrittenSector - 1 ; // no sub 1?
sector % = 0xE ;
sector + = 0xE * ( gSaveCounter % 2 ) ;
if ( ProgramFlashByte ( sector , sizeof ( struct UnkSaveSection ) , 0x25 ) )
{
// sector is damaged, so enable the bit in gDamagedSaveSectors and restore the last written sector and save counter.
SetDamagedSectorBits ( ENABLE , sector ) ;
gLastWrittenSector = gLastKnownGoodSector ;
gSaveCounter = gLastSaveCounter ;
return 0xFF ;
}
else
{
SetDamagedSectorBits ( DISABLE , sector ) ;
return 1 ;
}
}
u8 sub_8152DD0 ( u16 a1 , const struct SaveSectionLocation * location )
{
u8 retVal ;
2017-09-03 15:39:33 +02:00
gFastSaveSection = & gSaveDataBuffer ;
2017-09-03 14:13:01 +02:00
if ( a1 ! = 0xFFFF )
{
retVal = 0xFF ;
}
else
{
retVal = GetSaveValidStatus ( location ) ;
sub_8152E10 ( 0xFFFF , location ) ;
}
return retVal ;
}
u8 sub_8152E10 ( u16 a1 , const struct SaveSectionLocation * location )
{
u16 i ;
u16 checksum ;
u16 v3 = 0xE * ( gSaveCounter % 2 ) ;
u16 id ;
for ( i = 0 ; i < 0xE ; i + + )
{
DoReadFlashWholeSection ( i + v3 , gFastSaveSection ) ;
id = gFastSaveSection - > id ;
if ( id = = 0 )
gLastWrittenSector = i ;
checksum = CalculateChecksum ( gFastSaveSection - > data , location [ id ] . size ) ;
if ( gFastSaveSection - > security = = UNKNOWN_CHECK_VALUE
& & gFastSaveSection - > checksum = = checksum )
{
u16 j ;
for ( j = 0 ; j < location [ id ] . size ; j + + )
( ( u8 * ) location [ id ] . data ) [ j ] = gFastSaveSection - > data [ j ] ;
}
}
return 1 ;
}
u8 GetSaveValidStatus ( const struct SaveSectionLocation * location )
{
u16 i ;
u16 checksum ;
u32 saveSlot1Counter = 0 ;
u32 saveSlot2Counter = 0 ;
u32 slotCheckField = 0 ;
bool8 securityPassed = FALSE ;
u8 saveSlot1Status ;
u8 saveSlot2Status ;
// check save slot 1.
for ( i = 0 ; i < 0xE ; i + + )
{
DoReadFlashWholeSection ( i , gFastSaveSection ) ;
if ( gFastSaveSection - > security = = UNKNOWN_CHECK_VALUE )
{
securityPassed = TRUE ;
checksum = CalculateChecksum ( gFastSaveSection - > data , location [ gFastSaveSection - > id ] . size ) ;
if ( gFastSaveSection - > checksum = = checksum )
{
saveSlot1Counter = gFastSaveSection - > counter ;
slotCheckField | = 1 < < gFastSaveSection - > id ;
}
}
}
if ( securityPassed )
{
if ( slotCheckField = = 0x3FFF )
saveSlot1Status = 1 ;
else
saveSlot1Status = 255 ;
}
else
{
saveSlot1Status = 0 ;
}
slotCheckField = 0 ;
securityPassed = FALSE ;
// check save slot 2.
for ( i = 0 ; i < 0xE ; i + + )
{
DoReadFlashWholeSection ( i + 0xE , gFastSaveSection ) ;
if ( gFastSaveSection - > security = = UNKNOWN_CHECK_VALUE )
{
securityPassed = TRUE ;
checksum = CalculateChecksum ( gFastSaveSection - > data , location [ gFastSaveSection - > id ] . size ) ;
if ( gFastSaveSection - > checksum = = checksum )
{
saveSlot2Counter = gFastSaveSection - > counter ;
slotCheckField | = 1 < < gFastSaveSection - > id ;
}
}
}
if ( securityPassed )
{
if ( slotCheckField = = 0x3FFF )
saveSlot2Status = 1 ;
else
saveSlot2Status = 255 ;
}
else
{
saveSlot2Status = 0 ;
}
if ( saveSlot1Status = = 1 & & saveSlot2Status = = 1 )
{
if ( ( saveSlot1Counter = = - 1 & & saveSlot2Counter = = 0 ) | | ( saveSlot1Counter = = 0 & & saveSlot2Counter = = - 1 ) )
{
if ( ( unsigned ) ( saveSlot1Counter + 1 ) < ( unsigned ) ( saveSlot2Counter + 1 ) )
{
gSaveCounter = saveSlot2Counter ;
}
else
{
gSaveCounter = saveSlot1Counter ;
}
}
else
{
if ( saveSlot1Counter < saveSlot2Counter )
{
gSaveCounter = saveSlot2Counter ;
}
else
{
gSaveCounter = saveSlot1Counter ;
}
}
return 1 ;
}
if ( saveSlot1Status = = 1 )
{
gSaveCounter = saveSlot1Counter ;
if ( saveSlot2Status = = 255 )
return 255 ;
return 1 ;
}
if ( saveSlot2Status = = 1 )
{
gSaveCounter = saveSlot2Counter ;
if ( saveSlot1Status = = 255 )
return 255 ;
return 1 ;
}
if ( saveSlot1Status = = 0 & & saveSlot2Status = = 0 )
{
gSaveCounter = 0 ;
gLastWrittenSector = 0 ;
return 0 ;
}
gSaveCounter = 0 ;
gLastWrittenSector = 0 ;
return 2 ;
}
u8 sub_81530DC ( u8 a1 , u8 * data , u16 size )
{
u16 i ;
2017-09-03 15:39:33 +02:00
struct SaveSection * section = & gSaveDataBuffer ;
2017-09-03 14:13:01 +02:00
DoReadFlashWholeSection ( a1 , section ) ;
if ( section - > security = = UNKNOWN_CHECK_VALUE )
{
u16 checksum = CalculateChecksum ( section - > data , size ) ;
if ( section - > id = = checksum )
{
for ( i = 0 ; i < size ; i + + )
data [ i ] = section - > data [ i ] ;
return 1 ;
}
else
{
return 2 ;
}
}
else
{
return 0 ;
}
}
u8 DoReadFlashWholeSection ( u8 sector , struct SaveSection * section )
{
ReadFlash ( sector , 0 , section - > data , sizeof ( struct SaveSection ) ) ;
return 1 ;
}
u16 CalculateChecksum ( void * data , u16 size )
{
u16 i ;
u32 checksum = 0 ;
for ( i = 0 ; i < ( size / 4 ) ; i + + )
checksum + = * ( ( u32 * ) data ) + + ;
return ( ( checksum > > 16 ) + checksum ) ;
}
void UpdateSaveAddresses ( void )
{
2017-09-03 15:39:33 +02:00
int i = 0 ;
2017-09-03 14:13:01 +02:00
2017-09-29 10:06:36 +02:00
gRamSaveSectionLocations [ i ] . data = ( void * ) ( gSaveBlock2Ptr ) + gSaveSectionOffsets [ i ] . toAdd ;
gRamSaveSectionLocations [ i ] . size = gSaveSectionOffsets [ i ] . size ;
for ( i = 1 ; i < 5 ; i + + )
2017-09-03 14:13:01 +02:00
{
2017-09-29 10:06:36 +02:00
gRamSaveSectionLocations [ i ] . data = ( void * ) ( gSaveBlock1Ptr ) + gSaveSectionOffsets [ i ] . toAdd ;
2017-09-03 14:13:01 +02:00
gRamSaveSectionLocations [ i ] . size = gSaveSectionOffsets [ i ] . size ;
}
2017-09-29 10:06:36 +02:00
for ( i = 5 ; i < 14 ; i + + )
2017-09-03 14:13:01 +02:00
{
2017-09-29 10:06:36 +02:00
gRamSaveSectionLocations [ i ] . data = ( void * ) ( gPokemonStoragePtr ) + gSaveSectionOffsets [ i ] . toAdd ;
2017-09-03 14:13:01 +02:00
gRamSaveSectionLocations [ i ] . size = gSaveSectionOffsets [ i ] . size ;
2017-09-29 10:06:36 +02:00
i + + ; i - - ; // needed to match
2017-09-03 14:13:01 +02:00
}
}
extern u32 GetGameStat ( u8 index ) ; // rom4
extern void IncrementGameStat ( u8 index ) ; // rom4
extern void SaveSerializedGame ( void ) ; // load_save
extern u32 gUnknown_0203CF5C ;
u8 HandleSavingData ( u8 saveType )
{
u8 i ;
u32 backupVar = gUnknown_0203CF5C ;
u8 * tempAddr ;
gUnknown_0203CF5C = 0 ;
UpdateSaveAddresses ( ) ;
switch ( saveType )
{
case HOF_DELETE_SAVE : // deletes HOF before overwriting HOF completely. unused
for ( i = 0xE * 2 + 0 ; i < 32 ; i + + )
EraseFlashSector ( i ) ;
case HOF_SAVE : // hall of fame.
if ( GetGameStat ( GAME_STAT_ENTERED_HOF ) < 999 )
IncrementGameStat ( GAME_STAT_ENTERED_HOF ) ;
SaveSerializedGame ( ) ;
save_write_to_flash ( 0xFFFF , gRamSaveSectionLocations ) ;
tempAddr = ( u8 * ) 0x201C000 ; // FIXME: make this a label.
HandleWriteSectorNBytes ( 0x1C , tempAddr , 0xF80 ) ;
HandleWriteSectorNBytes ( 0x1D , tempAddr + 0xF80 , 0xF80 ) ;
break ;
case NORMAL_SAVE : // normal save. also called by overwriting your own save.
default :
SaveSerializedGame ( ) ;
save_write_to_flash ( 0xFFFF , gRamSaveSectionLocations ) ;
break ;
case LINK_SAVE : // _081532C4
case LINK2_SAVE :
SaveSerializedGame ( ) ;
for ( i = 0 ; i < 5 ; i + + )
ClearSaveData_2 ( i , gRamSaveSectionLocations ) ;
for ( i = 0 ; i < 5 ; i + + )
sav12_xor_get ( i , gRamSaveSectionLocations ) ;
break ;
// support for Ereader was removed in Emerald.
/*
case EREADER_SAVE : // used in mossdeep "game corner" before/after battling old man e-reader trainer
SaveSerializedGame ( ) ;
save_write_to_flash ( 0 , gRamSaveSectionLocations ) ;
break ;
*/
case DIFFERENT_FILE_SAVE :
for ( i = ( 0xE * 2 + 0 ) ; i < 32 ; i + + )
EraseFlashSector ( i ) ; // erase HOF.
SaveSerializedGame ( ) ;
save_write_to_flash ( 0xFFFF , gRamSaveSectionLocations ) ;
break ;
}
gUnknown_0203CF5C = backupVar ;
return 0 ;
}
u8 TrySavingData ( u8 saveType ) // TrySave
{
if ( gFlashMemoryPresent = = TRUE )
{
HandleSavingData ( saveType ) ;
if ( gDamagedSaveSectors )
DoSaveFailedScreen ( saveType ) ;
else
goto OK ; // really?
}
gUnknown_03006294 = 0xFF ;
return 0xFF ;
OK :
gUnknown_03006294 = 1 ;
return 1 ;
}
u8 sub_8153380 ( void ) // trade.s save
{
if ( gFlashMemoryPresent ! = TRUE )
return 1 ;
UpdateSaveAddresses ( ) ;
SaveSerializedGame ( ) ;
RestoreSaveBackupVarsAndIncrement ( gRamSaveSectionLocations ) ;
return 0 ;
}
bool8 sub_81533AC ( void ) // trade.s save
{
u8 retVal = sub_81529D4 ( 0xE , gRamSaveSectionLocations ) ;
if ( gDamagedSaveSectors )
DoSaveFailedScreen ( 0 ) ;
if ( retVal = = 0xFF )
return 1 ;
else
return 0 ;
}
u8 sub_81533E0 ( void ) // trade.s save
{
sub_8152A34 ( 0xE , gRamSaveSectionLocations ) ;
if ( gDamagedSaveSectors )
DoSaveFailedScreen ( 0 ) ;
return 0 ;
}
u8 sub_8153408 ( void ) // trade.s save
{
sub_8152CAC ( 0xE , gRamSaveSectionLocations ) ;
if ( gDamagedSaveSectors )
DoSaveFailedScreen ( 0 ) ;
return 0 ;
}
u8 sub_8153430 ( void )
{
if ( gFlashMemoryPresent ! = TRUE )
return 1 ;
UpdateSaveAddresses ( ) ;
SaveSerializedGame ( ) ;
RestoreSaveBackupVars ( gRamSaveSectionLocations ) ;
sub_8152A34 ( gUnknown_03006208 + 1 , gRamSaveSectionLocations ) ;
return 0 ;
}
bool8 sub_8153474 ( void )
{
u8 retVal = FALSE ;
u16 val = + + gUnknown_03006208 ;
if ( val < = 4 )
{
sub_8152A34 ( gUnknown_03006208 + 1 , gRamSaveSectionLocations ) ;
sub_8152D44 ( val , gRamSaveSectionLocations ) ;
}
else
{
sub_8152D44 ( val , gRamSaveSectionLocations ) ;
retVal = TRUE ;
}
if ( gDamagedSaveSectors )
DoSaveFailedScreen ( 1 ) ;
return retVal ;
}
u8 sub_81534D0 ( u8 a1 )
{
u8 result ;
if ( gFlashMemoryPresent ! = TRUE )
{
2017-09-03 22:50:17 +02:00
gSaveFileStatus = 4 ;
2017-09-03 14:13:01 +02:00
return 0xFF ;
}
UpdateSaveAddresses ( ) ;
switch ( a1 )
{
case 0 :
default :
result = sub_8152DD0 ( 0xFFFF , gRamSaveSectionLocations ) ;
LoadSerializedGame ( ) ;
2017-09-03 22:50:17 +02:00
gSaveFileStatus = result ;
2017-09-03 14:13:01 +02:00
gGameContinueCallback = 0 ;
break ;
case 3 :
result = sub_81530DC ( 0x1C , gDecompressionBuffer , 0xF80 ) ;
if ( result = = 1 )
result = sub_81530DC ( 0x1D , gDecompressionBuffer + 0xF80 , 0xF80 ) ;
break ;
}
return result ;
}
2017-09-03 15:39:33 +02:00
u16 sub_815355C ( void )
{
u16 i , v3 ;
struct SaveSection * savSection ;
savSection = gFastSaveSection = & gSaveDataBuffer ;
if ( gFlashMemoryPresent ! = 1 )
return 0 ;
UpdateSaveAddresses ( ) ;
GetSaveValidStatus ( gRamSaveSectionLocations ) ;
v3 = 0xE * ( gSaveCounter % 2 ) ;
for ( i = 0 ; i < 14 ; i + + )
{
DoReadFlashWholeSection ( i + v3 , gFastSaveSection ) ;
if ( gFastSaveSection - > id = = 0 )
return savSection - > data [ 10 ] +
savSection - > data [ 11 ] +
savSection - > data [ 12 ] +
savSection - > data [ 13 ] ;
}
return 0 ;
}
2017-11-13 18:07:23 +01:00
u32 TryCopySpecialSaveSection ( u8 sector , u8 * dst )
2017-09-03 15:39:33 +02:00
{
s32 i ;
s32 size ;
u8 * savData ;
if ( sector ! = 30 & & sector ! = 31 )
return 0xFF ;
2017-10-07 05:30:35 +02:00
ReadFlash ( sector , 0 , ( u8 * ) & gSaveDataBuffer , sizeof ( struct SaveSection ) ) ;
2017-09-03 15:39:33 +02:00
if ( * ( u32 * ) ( & gSaveDataBuffer . data [ 0 ] ) ! = 0xB39D )
return 0xFF ;
// copies whole save section except u32 counter
i = 0 ;
size = 0xFFB ;
savData = & gSaveDataBuffer . data [ 4 ] ;
for ( ; i < = size ; i + + )
dst [ i ] = savData [ i ] ;
return 1 ;
}
u32 sub_8153634 ( u8 sector , u8 * src )
{
s32 i ;
s32 size ;
u8 * savData ;
void * savDataBuffer ;
if ( sector ! = 30 & & sector ! = 31 )
return 0xFF ;
2017-11-13 18:07:23 +01:00
2017-09-03 15:39:33 +02:00
savDataBuffer = & gSaveDataBuffer ;
* ( u32 * ) ( savDataBuffer ) = 0xB39D ;
// copies whole save section except u32 counter
i = 0 ;
size = 0xFFB ;
savData = & gSaveDataBuffer . data [ 4 ] ;
for ( ; i < = size ; i + + )
savData [ i ] = src [ i ] ;
if ( ProgramFlashSectorAndVerify ( sector , savDataBuffer ) ! = 0 )
return 0xFF ;
return 1 ;
}
2017-09-29 10:06:36 +02:00
extern void save_serialize_map ( void ) ;
extern void sub_8076D5C ( void ) ;
extern void sav2_gender2_inplace_and_xFE ( void ) ;
extern void sub_800ADF8 ( void ) ;
extern bool8 sub_800A520 ( void ) ;
void sub_8153688 ( u8 taskId )
{
s16 * taskData = gTasks [ taskId ] . data ;
switch ( taskData [ 0 ] )
{
case 0 :
gSoftResetDisabled = TRUE ;
taskData [ 0 ] = 1 ;
break ;
case 1 :
sub_800ADF8 ( ) ;
taskData [ 0 ] = 2 ;
break ;
case 2 :
if ( sub_800A520 ( ) )
{
if ( taskData [ 2 ] = = 0 )
save_serialize_map ( ) ;
taskData [ 0 ] = 3 ;
}
break ;
case 3 :
if ( taskData [ 2 ] = = 0 )
sub_8076D5C ( ) ;
sub_8153380 ( ) ;
taskData [ 0 ] = 4 ;
break ;
case 4 :
if ( + + taskData [ 1 ] = = 5 )
{
taskData [ 1 ] = 0 ;
taskData [ 0 ] = 5 ;
}
break ;
case 5 :
if ( sub_81533AC ( ) )
taskData [ 0 ] = 6 ;
else
taskData [ 0 ] = 4 ;
break ;
case 6 :
sub_81533E0 ( ) ;
taskData [ 0 ] = 7 ;
break ;
case 7 :
if ( taskData [ 2 ] = = 0 )
sav2_gender2_inplace_and_xFE ( ) ;
sub_800ADF8 ( ) ;
taskData [ 0 ] = 8 ;
break ;
case 8 :
if ( sub_800A520 ( ) )
{
sub_8153408 ( ) ;
taskData [ 0 ] = 9 ;
}
break ;
case 9 :
sub_800ADF8 ( ) ;
taskData [ 0 ] = 10 ;
break ;
case 10 :
if ( sub_800A520 ( ) )
taskData [ 0 ] + + ;
break ;
case 11 :
if ( + + taskData [ 1 ] > 5 )
{
gSoftResetDisabled = FALSE ;
DestroyTask ( taskId ) ;
}
break ;
}
}