Files
Wiseguy e7185d889e Note saving (#30)
* WIP note saving implementation

* Fix note saving affecting other files

* Prevent note collection in demo playback for safety

* Cache note saving enabled while in the lair or file select to prevent it changing in levels with notes

* Prevent "Grunty's magic" note dialog from being shown if note saving is enabled

* Implement dynamically spawned note saving

* Properly clear loaded save extension data when score status is cleared

* Hook up menu for note saving
2025-12-30 21:41:30 -05:00

170 lines
6.2 KiB
C

#include "patches.h"
#include "save.h"
#include "core1/eeprom.h"
#include "save_extension.h"
// Vanilla declarations.
extern SaveData gameFile_saveData[4]; //save_data
extern s8 gameFile_GameIdToFileIdMap[4]; //gamenum to filenum
extern s32 D_80383F04;
s32 savedata_8033CA2C(s32 filenum, SaveData *save_data);
int savedata_8033CC98(s32 filenum, u8 *buffer);
int savedata_8033CCD0(s32 filenum);
void __gameFile_8033CE14(s32 gamenum);
void savedata_clear(SaveData *savedata);
void savedata_update_crc(void *buffer, u32 size);
void saveData_load(SaveData *savedata);
void saveData_create(SaveData *savedata);
void bsStoredState_clear(void);
void func_8031FFAC(void);
void item_setItemsStartCounts(void);
void jiggyscore_clearAll(void);
void honeycombscore_clear(void);
void mumboscore_clear(void);
void volatileFlag_clear(void);
void func_802D6344(void);
// New declarations.
// One entry for each file and the backup.
SaveFileExtensionData save_file_extension_data[4];
SaveFileExtensionData loaded_file_extension_data;
SaveGlobalExtensionData save_global_extension_data;
_Static_assert(sizeof(save_file_extension_data) + sizeof(save_global_extension_data) == 1536, "Save extension data must be 1536 bytes");
// Place save file extensions after the 4K eeprom range.
#define SAVE_FILE_EXTENSION_OFFSET (EEPROM_BLOCK_SIZE * EEPROM_MAXBLOCKS)
// Number of blocks per save file extension slot.
#define SAVE_FILE_EXTENSION_DATA_BLOCK_COUNT (sizeof(SaveFileExtensionData) / EEPROM_BLOCK_SIZE)
// Place the global extension data after teh save file extensions
#define SAVE_GLOBAL_EXTENSION_OFFSET (SAVE_FILE_EXTENSION_OFFSET + sizeof(save_file_extension_data))
_Static_assert(sizeof(SaveFileExtensionData) % EEPROM_BLOCK_SIZE == 0, "SaveFileExtensionData size must be a multiple of EEPROM_BLOCK_SIZE");
_Static_assert(SAVE_GLOBAL_EXTENSION_OFFSET % EEPROM_BLOCK_SIZE == 0, "SAVE_GLOBAL_EXTENSION_OFFSET must be a multiple of EEPROM_BLOCK_SIZE");
#define SAVE_FILE_EXTENSION_OFFSET_BLOCKS (SAVE_FILE_EXTENSION_OFFSET / EEPROM_BLOCK_SIZE)
#define SAVE_GLOBAL_EXTENSION_OFFSET_BLOCKS (SAVE_GLOBAL_EXTENSION_OFFSET / EEPROM_BLOCK_SIZE)
// @recomp Patched to load the corresponding file number's extension data.
RECOMP_PATCH int __gameFile_8033CD90(s32 filenum){
int i;
s32 tmp_v1;
void *save_data_ptr;
save_data_ptr = &gameFile_saveData[filenum];
// @recomp Get a pointer to the extension data for this file number.
SaveFileExtensionData *extension_ptr = &save_file_extension_data[filenum];
i = 3;
do{
// @recomp Also load the extension data.
eeprom_readBlocks(0, SAVE_FILE_EXTENSION_OFFSET_BLOCKS + SAVE_FILE_EXTENSION_DATA_BLOCK_COUNT * filenum, extension_ptr, SAVE_FILE_EXTENSION_DATA_BLOCK_COUNT);
// Read save data from eeprom for file
tmp_v1 = savedata_8033CA2C(filenum, save_data_ptr);
if(!tmp_v1)
break;
i--;
}while(i != 0);
if(tmp_v1) {
savedata_clear(save_data_ptr);
// @recomp Also clear the extension data.
bzero(save_data_ptr, sizeof(*save_data_ptr));
}
return tmp_v1;
}
// @recomp Patched to save the corresponding file number's extension data.
RECOMP_PATCH s32 gameFile_8033CFD4(s32 gamenum){
s32 next;
s32 filenum;
u32 i = 3;
s32 eeprom_error;
SaveData *save_data;
filenum = D_80383F04;
next = gameFile_GameIdToFileIdMap[gamenum];
gameFile_GameIdToFileIdMap[gamenum] = D_80383F04;
bcopy(&gameFile_saveData[next], &gameFile_saveData[filenum], 0xF*8);
// @recomp Also copy the extension data from the next slot.
bcopy(&save_file_extension_data[next], &save_file_extension_data[filenum], sizeof(save_file_extension_data[0]));
save_data = gameFile_saveData + filenum;
// @recomp Get a pointer to the extension data for this file number.
SaveFileExtensionData *extension_ptr = &save_file_extension_data[filenum];
save_data->slotIndex = gamenum + 1;
savedata_update_crc(save_data, sizeof(SaveData));
for(eeprom_error = 1; eeprom_error && i > 0; i--){//L8033D070
// @recomp Also save the extension data.
eeprom_writeBlocks(0, SAVE_FILE_EXTENSION_OFFSET_BLOCKS + SAVE_FILE_EXTENSION_DATA_BLOCK_COUNT * filenum, extension_ptr, SAVE_FILE_EXTENSION_DATA_BLOCK_COUNT);
eeprom_error = savedata_8033CC98(filenum, save_data);
if(!eeprom_error){
__gameFile_8033CE14(gamenum);
}
}
if(!eeprom_error){
for(i = 3; i > 0; i--){//L8033D070
eeprom_error = savedata_8033CCD0(next);
if(!eeprom_error)
break;
}
}
if(eeprom_error){
gameFile_GameIdToFileIdMap[gamenum] = next;
}
else{
D_80383F04 = next;
}
return eeprom_error;
}
// @recomp Patched to clear extended file data.
RECOMP_PATCH void gameFile_clear(s32 gamenum){
s32 filenum = gameFile_GameIdToFileIdMap[gamenum];
savedata_clear(&gameFile_saveData[filenum]);
// @recomp Clear the extended file data for this file number.
bzero(&save_file_extension_data[filenum], sizeof(SaveFileExtensionData));
}
// @recomp Patched to load extended file data.
RECOMP_PATCH void gameFile_load(s32 gamenum){
s32 filenum = gameFile_GameIdToFileIdMap[gamenum];
saveData_load(&gameFile_saveData[filenum]);
// @recomp Load the extended file data for this file number.
memcpy(&loaded_file_extension_data, &save_file_extension_data[filenum], sizeof(SaveFileExtensionData));
}
// @recomp Patched to save extended file data.
RECOMP_PATCH void gameFile_save(s32 gamenum){
s32 filenum = gameFile_GameIdToFileIdMap[gamenum];
saveData_create(&gameFile_saveData[filenum]);
// @recomp Save the extended file data for this file number.
memcpy(&save_file_extension_data[filenum], &loaded_file_extension_data, sizeof(SaveFileExtensionData));
}
// @recomp Patched to clear the current loaded extended file data.
RECOMP_PATCH void clearScoreStates(void) {
bsStoredState_clear();
func_8031FFAC();
item_setItemsStartCounts();
jiggyscore_clearAll();
honeycombscore_clear();
mumboscore_clear();
volatileFlag_clear();
func_802D6344();
// @recomp Clear the current loaded extended file data.
bzero(&loaded_file_extension_data, sizeof(loaded_file_extension_data));
}