fceugx/source/fceuram.cpp

295 lines
6.4 KiB
C++
Raw Normal View History

/****************************************************************************
2009-07-22 04:05:49 +02:00
* FCE Ultra
* Nintendo Wii/Gamecube Port
*
2022-01-09 17:40:41 +01:00
* Tantric 2008-2022
*
2009-03-28 18:23:08 +01:00
* fceustate.cpp
*
* Memory Based Load/Save RAM Manager
*
* These are the battery-backed RAM (save data) routines, brought together
* as GCxxxxx
* The original file I/O is replaced with Memory Read/Writes to the
* savebuffer below
****************************************************************************/
#include <gccore.h>
#include <string.h>
#include <malloc.h>
#include <fat.h>
#include <string.h>
#include "fceugx.h"
2009-07-17 19:27:04 +02:00
#include "fceusupport.h"
2009-03-28 18:23:08 +01:00
#include "menu.h"
#include "filebrowser.h"
#include "fileop.h"
#include "pocketnes/goombasav.h"
2010-04-01 23:37:03 +02:00
static u32 WiiFCEU_GameSave(CartInfo *LocalHWInfo, int operation)
{
u32 offset = 0;
if(LocalHWInfo->battery && LocalHWInfo->SaveGame[0])
{
int x;
for(x=0;x<4;x++)
{
if(LocalHWInfo->SaveGame[x])
{
if(operation == 0) // save to file
memcpy(savebuffer+offset, LocalHWInfo->SaveGame[x], LocalHWInfo->SaveGameLen[x]);
else // load from file
memcpy(LocalHWInfo->SaveGame[x], savebuffer+offset, LocalHWInfo->SaveGameLen[x]);
offset += LocalHWInfo->SaveGameLen[x];
}
}
}
return offset;
}
2009-10-02 00:21:25 +02:00
bool SaveRAM (char * filepath, bool silent)
{
2008-11-12 09:40:09 +01:00
bool retval = false;
int datasize = 0;
int offset = 0;
2009-10-02 00:21:25 +02:00
int device;
if(!FindDevice(filepath, &device))
return 0;
2008-11-12 09:40:09 +01:00
if(GameInfo->type == GIT_FDS)
2008-10-03 20:11:32 +02:00
{
if(!silent)
2009-03-28 18:23:08 +01:00
InfoPrompt("RAM saving is not available for FDS games!");
2008-10-03 20:11:32 +02:00
return false;
}
AllocSaveBuffer ();
// save game save to savebuffer
if(GameInfo->type == GIT_CART)
2010-04-01 23:37:03 +02:00
datasize = WiiFCEU_GameSave(&iNESCart, 0);
else if(GameInfo->type == GIT_VSUNI)
2010-04-01 23:37:03 +02:00
datasize = WiiFCEU_GameSave(&UNIFCart, 0);
if (datasize)
{
// Check to see if this is a PocketNES save file
FILE* file = fopen(filepath, "rb");
if (file)
{
uint32 tag;
fread(&tag, sizeof(uint32), 1, file);
fclose(file);
if (goomba_is_sram(&tag))
{
2017-08-30 01:00:17 +02:00
void* gba_data = malloc(GOOMBA_COLOR_SRAM_SIZE);
file = fopen(filepath, "rb");
fread(gba_data, 1, GOOMBA_COLOR_SRAM_SIZE, file);
fclose(file);
void* cleaned = goomba_cleanup(gba_data);
if (!cleaned) {
ErrorPrompt(goomba_last_error());
} else if (cleaned != gba_data) {
memcpy(gba_data, cleaned, GOOMBA_COLOR_SRAM_SIZE);
free(cleaned);
}
// Look for just one save file. If there aren't any, or there is more than one, don't read any data.
const stateheader* sh1 = NULL;
const stateheader* sh2 = NULL;
const stateheader* sh = stateheader_first(gba_data);
while (sh && stateheader_plausible(sh)) {
if (little_endian_conv_16(sh->type) != GOOMBA_SRAMSAVE) {}
else if (sh1 == NULL) {
sh1 = sh;
}
else {
sh2 = sh;
break;
}
sh = stateheader_advance(sh);
}
if (sh1 == NULL)
{
ErrorPrompt("PocketNES save file has no SRAM.");
datasize = 0;
}
else if (sh2 != NULL)
{
ErrorPrompt("PocketNES save file has more than one SRAM.");
datasize = 0;
}
else
{
2017-08-30 01:00:17 +02:00
char* newdata = goomba_new_sav(gba_data, sh1, savebuffer, datasize);
if (!newdata) {
ErrorPrompt(goomba_last_error());
datasize = 0;
} else {
memcpy(savebuffer, newdata, GOOMBA_COLOR_SRAM_SIZE);
datasize = GOOMBA_COLOR_SRAM_SIZE;
free(newdata);
}
}
}
}
}
2008-11-12 09:40:09 +01:00
if (datasize)
{
2009-10-02 00:21:25 +02:00
offset = SaveFile(filepath, datasize, silent);
if (offset > 0)
{
2009-03-28 18:23:08 +01:00
if (!silent)
InfoPrompt("Save successful");
retval = true;
}
}
else
{
2009-03-28 18:23:08 +01:00
if (!silent)
InfoPrompt("No data to save!");
}
FreeSaveBuffer ();
return retval;
}
2009-03-28 18:23:08 +01:00
bool
2009-10-02 00:21:25 +02:00
SaveRAMAuto (bool silent)
{
2008-11-12 09:40:09 +01:00
char filepath[1024];
2009-03-28 18:23:08 +01:00
2009-10-02 00:21:25 +02:00
if(!MakeFilePath(filepath, FILE_RAM, romFilename, 0))
2009-03-28 18:23:08 +01:00
return false;
2009-10-02 00:21:25 +02:00
return SaveRAM(filepath, silent);
2009-03-28 18:23:08 +01:00
}
2009-10-02 00:21:25 +02:00
bool LoadRAM (char * filepath, bool silent)
2009-03-28 18:23:08 +01:00
{
2008-11-12 09:40:09 +01:00
int offset = 0;
bool retval = false;
2009-10-02 00:21:25 +02:00
int device;
if(!FindDevice(filepath, &device))
return 0;
2008-11-12 09:40:09 +01:00
if(GameInfo->type == GIT_FDS) // RAM saves don't exist for FDS games
2008-10-03 20:11:32 +02:00
return false;
AllocSaveBuffer ();
2009-10-02 00:21:25 +02:00
offset = LoadFile(filepath, silent);
// Check to see if this is a PocketNES save file
if (goomba_is_sram(savebuffer))
{
2017-08-30 01:00:17 +02:00
void* cleaned = goomba_cleanup(savebuffer);
if (!cleaned) {
ErrorPrompt(goomba_last_error());
} else if (cleaned != savebuffer) {
memcpy(savebuffer, cleaned, GOOMBA_COLOR_SRAM_SIZE);
free(cleaned);
}
2017-08-30 00:02:03 +02:00
// Look for just one save file. If there aren't any, or there is more than one, don't read any data.
const stateheader* sh1 = NULL;
const stateheader* sh2 = NULL;
const stateheader* sh = stateheader_first(savebuffer);
while (sh && stateheader_plausible(sh)) {
2017-08-30 01:00:17 +02:00
if (little_endian_conv_16(sh->type) != GOOMBA_SRAMSAVE) { }
else if (sh1 == NULL) {
sh1 = sh;
}
else {
sh2 = sh;
break;
}
sh = stateheader_advance(sh);
}
if (sh1 == NULL)
{
ErrorPrompt("PocketNES save file has no SRAM.");
offset = 0;
}
else if (sh2 != NULL)
{
ErrorPrompt("PocketNES save file has more than one SRAM.");
offset = 0;
}
else
{
goomba_size_t len;
void* extracted = goomba_extract(savebuffer, sh1, &len);
if (!extracted)
ErrorPrompt(goomba_last_error());
else
{
memcpy(savebuffer, extracted, len);
offset = len;
free(extracted);
}
}
}
if (offset > 0)
{
if(GameInfo->type == GIT_CART)
2010-04-01 23:37:03 +02:00
WiiFCEU_GameSave(&iNESCart, 1);
else if(GameInfo->type == GIT_VSUNI)
2010-04-01 23:37:03 +02:00
WiiFCEU_GameSave(&UNIFCart, 1);
ResetNES();
retval = true;
}
else
{
// if we reached here, nothing was done!
if(!silent)
2009-03-28 18:23:08 +01:00
InfoPrompt ("Save file not found");
}
FreeSaveBuffer ();
return retval;
}
2009-03-28 18:23:08 +01:00
bool
2009-10-02 00:21:25 +02:00
LoadRAMAuto (bool silent)
2009-03-28 18:23:08 +01:00
{
2009-04-09 09:49:28 +02:00
char filepath[MAXPATHLEN];
char filepath2[MAXPATHLEN];
2009-03-28 18:23:08 +01:00
2009-04-09 09:49:28 +02:00
// look for Auto save file
2009-10-02 00:21:25 +02:00
if(!MakeFilePath(filepath, FILE_RAM, romFilename, 0))
2009-03-28 18:23:08 +01:00
return false;
2009-10-02 00:21:25 +02:00
if (LoadRAM(filepath, silent))
2009-04-09 09:49:28 +02:00
return true;
if (!GCSettings.AppendAuto)
return false;
2009-04-09 09:49:28 +02:00
// look for file with no number or Auto appended
2009-10-02 00:21:25 +02:00
if(!MakeFilePath(filepath2, FILE_RAM, romFilename, -1))
2009-04-09 09:49:28 +02:00
return false;
2009-10-02 00:21:25 +02:00
if(LoadRAM(filepath2, silent))
2009-04-09 09:49:28 +02:00
{
// rename this file - append Auto
2009-10-02 00:21:25 +02:00
rename(filepath2, filepath); // rename file (to avoid duplicates)
2009-04-09 09:49:28 +02:00
return true;
}
return false;
2009-03-28 18:23:08 +01:00
}