2008-08-06 03:09:59 +02:00
|
|
|
/****************************************************************************
|
|
|
|
* Snes9x 1.50
|
|
|
|
*
|
|
|
|
* Nintendo Gamecube Port
|
|
|
|
* softdev July 2006
|
|
|
|
* crunchy2 May 2007
|
|
|
|
*
|
|
|
|
* sdload.cpp
|
|
|
|
*
|
|
|
|
* Load ROMS from SD Card
|
|
|
|
****************************************************************************/
|
|
|
|
#include <gccore.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <ogcsys.h>
|
2008-08-06 03:39:43 +02:00
|
|
|
#include "sdload.h"
|
2008-08-06 03:09:59 +02:00
|
|
|
#include "ngcunzip.h"
|
|
|
|
#include "memmap.h"
|
|
|
|
#include "video.h"
|
|
|
|
#include "ftfont.h"
|
|
|
|
#include "dvd.h"
|
|
|
|
#include "filesel.h"
|
|
|
|
#include "sram.h"
|
|
|
|
#include "preferences.h"
|
|
|
|
|
|
|
|
#include <zlib.h>
|
|
|
|
extern unsigned char savebuffer[];
|
|
|
|
extern char output[16384];
|
2008-08-06 03:39:43 +02:00
|
|
|
FILE * filehandle;
|
|
|
|
char rootSDdir[MAXPATHLEN] = "fat:/";
|
|
|
|
char currSDdir[MAXPATHLEN];
|
2008-08-06 03:09:59 +02:00
|
|
|
extern int offset;
|
|
|
|
extern int selection;
|
|
|
|
|
2008-08-06 03:39:43 +02:00
|
|
|
extern FILEENTRIES filelist[MAXFILES];
|
2008-08-06 03:09:59 +02:00
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* Update SDCARD curent directory name
|
|
|
|
***************************************************************************/
|
|
|
|
int updateSDdirname()
|
|
|
|
{
|
|
|
|
int size=0;
|
|
|
|
char *test;
|
|
|
|
char temp[1024];
|
|
|
|
|
|
|
|
/* current directory doesn't change */
|
|
|
|
if (strcmp(filelist[selection].filename,".") == 0) return 0;
|
|
|
|
|
|
|
|
/* go up to parent directory */
|
|
|
|
else if (strcmp(filelist[selection].filename,"..") == 0)
|
|
|
|
{
|
|
|
|
/* determine last subdirectory namelength */
|
2008-08-06 03:39:43 +02:00
|
|
|
sprintf(temp,"%s",currSDdir);
|
|
|
|
test = strtok(temp,"/");
|
|
|
|
while (test != NULL) {
|
2008-08-06 03:09:59 +02:00
|
|
|
size = strlen(test);
|
2008-08-06 03:39:43 +02:00
|
|
|
test = strtok(NULL,"/");
|
2008-08-06 03:09:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* remove last subdirectory name */
|
2008-08-06 03:39:43 +02:00
|
|
|
size = strlen(currSDdir) - size - 1;
|
|
|
|
currSDdir[size] = 0;
|
2008-08-06 03:09:59 +02:00
|
|
|
|
|
|
|
/* handles root name */
|
2008-08-06 03:39:43 +02:00
|
|
|
if (strcmp(currSDdir, "/") == 0)
|
|
|
|
|
2008-08-06 03:09:59 +02:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
2008-08-06 03:39:43 +02:00
|
|
|
else /* Open a directory */
|
2008-08-06 03:09:59 +02:00
|
|
|
{
|
|
|
|
/* test new directory namelength */
|
2008-08-06 03:39:43 +02:00
|
|
|
if ((strlen(currSDdir)+1+strlen(filelist[selection].filename)) < MAXPATHLEN)
|
|
|
|
{
|
|
|
|
/* handles root name */
|
|
|
|
sprintf(temp, "/%s/..", SNESROMDIR);
|
|
|
|
if (strcmp(currSDdir, temp) == 0)
|
|
|
|
sprintf(currSDdir,"%s",rootSDdir);
|
2008-08-06 03:09:59 +02:00
|
|
|
|
2008-08-06 03:39:43 +02:00
|
|
|
/* update current directory name */
|
|
|
|
sprintf(currSDdir, "%s/%s",currSDdir, filelist[selection].filename);
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
WaitPrompt((char*)"Dirname is too long !");
|
|
|
|
return -1;
|
|
|
|
}
|
2008-08-06 03:09:59 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* Browse SDCARD subdirectories
|
|
|
|
***************************************************************************/
|
2008-08-06 03:39:43 +02:00
|
|
|
int parseSDdirectory() {
|
|
|
|
int nbfiles = 0;
|
|
|
|
DIR_ITER *sddir;
|
|
|
|
char filename[MAXPATHLEN];
|
|
|
|
struct stat filestat;
|
|
|
|
char msg[128];
|
|
|
|
|
|
|
|
/* initialize selection */
|
|
|
|
selection = offset = 0;
|
|
|
|
|
|
|
|
/* open the directory */
|
|
|
|
sddir = diropen(currSDdir);
|
|
|
|
if (sddir == NULL) {
|
|
|
|
sprintf(currSDdir,"%s",rootSDdir); // if we can't open the previous dir, open root dir
|
|
|
|
sddir = diropen(currSDdir);
|
|
|
|
WaitPrompt(msg);
|
|
|
|
if (sddir == NULL) {
|
|
|
|
sprintf(msg, "Error opening %s", currSDdir);
|
|
|
|
WaitPrompt(msg);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2008-08-06 03:09:59 +02:00
|
|
|
|
|
|
|
/* Move to DVD structure - this is required for the file selector */
|
2008-08-06 03:39:43 +02:00
|
|
|
while(dirnext(sddir,filename,&filestat) == 0) {
|
|
|
|
if(strcmp(filename,".") != 0) {
|
|
|
|
memset(&filelist[nbfiles], 0, sizeof(FILEENTRIES));
|
|
|
|
strncpy(filelist[nbfiles].filename, filename, MAXPATHLEN);
|
|
|
|
strncpy(filelist[nbfiles].displayname, filename, MAXDISPLAY+1); // crop name for display
|
|
|
|
filelist[nbfiles].length = filestat.st_size;
|
|
|
|
filelist[nbfiles].flags = (filestat.st_mode & _IFDIR) == 0 ? 0 : 1;
|
|
|
|
nbfiles++;
|
|
|
|
}
|
|
|
|
}
|
2008-08-06 03:09:59 +02:00
|
|
|
|
2008-08-06 03:39:43 +02:00
|
|
|
/*** close directory ***/
|
|
|
|
dirclose(sddir);
|
2008-08-06 03:09:59 +02:00
|
|
|
|
2008-08-06 03:39:43 +02:00
|
|
|
return nbfiles;
|
2008-08-06 03:09:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* LoadSDFile
|
|
|
|
****************************************************************************/
|
|
|
|
extern int haveSDdir;
|
|
|
|
int
|
|
|
|
LoadSDFile (char *filename, int length)
|
|
|
|
{
|
|
|
|
char zipbuffer[2048];
|
2008-08-06 03:39:43 +02:00
|
|
|
char filepath[MAXPATHLEN];
|
|
|
|
FILE *handle;
|
2008-08-06 03:09:59 +02:00
|
|
|
char *rbuffer;
|
|
|
|
PKZIPHEADER pkzip;
|
|
|
|
z_stream zs;
|
|
|
|
int res, outbytes = 0;
|
|
|
|
int size;
|
|
|
|
int have;
|
|
|
|
|
|
|
|
rbuffer = (char *) Memory.ROM;
|
|
|
|
|
|
|
|
/* Check filename length */
|
2008-08-06 03:39:43 +02:00
|
|
|
if ((strlen(currSDdir)+1+strlen(filelist[selection].filename)) < MAXPATHLEN)
|
|
|
|
sprintf(filepath, "%s/%s",currSDdir,filelist[selection].filename);
|
2008-08-06 03:09:59 +02:00
|
|
|
else
|
|
|
|
{
|
2008-08-06 03:39:43 +02:00
|
|
|
WaitPrompt((char*) "Maximum Filename Length reached !");
|
2008-08-06 03:09:59 +02:00
|
|
|
haveSDdir = 0; // reset everything before next access
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2008-08-06 03:39:43 +02:00
|
|
|
handle = fopen (filepath, "rb");
|
2008-08-06 03:09:59 +02:00
|
|
|
if (handle > 0)
|
|
|
|
{
|
2008-08-06 03:39:43 +02:00
|
|
|
fread (zipbuffer, 1, 2048, handle);
|
2008-08-06 03:09:59 +02:00
|
|
|
|
2008-08-06 03:39:43 +02:00
|
|
|
if (IsZipFile (zipbuffer))
|
|
|
|
{
|
|
|
|
/*** Unzip the ROM ***/
|
|
|
|
memcpy (&pkzip, zipbuffer, sizeof (PKZIPHEADER));
|
|
|
|
pkzip.uncompressedSize = FLIP32 (pkzip.uncompressedSize);
|
|
|
|
memset (&zs, 0, sizeof (zs));
|
|
|
|
zs.zalloc = Z_NULL;
|
|
|
|
zs.zfree = Z_NULL;
|
|
|
|
zs.opaque = Z_NULL;
|
|
|
|
zs.avail_in = 0;
|
|
|
|
zs.next_in = Z_NULL;
|
|
|
|
|
|
|
|
res = inflateInit2 (&zs, -MAX_WBITS);
|
|
|
|
|
|
|
|
if (res != Z_OK)
|
|
|
|
{
|
|
|
|
fclose (handle);
|
|
|
|
return 0;
|
|
|
|
}
|
2008-08-06 03:09:59 +02:00
|
|
|
|
2008-08-06 03:39:43 +02:00
|
|
|
size = (sizeof (PKZIPHEADER) +
|
|
|
|
FLIP16 (pkzip.filenameLength) +
|
|
|
|
FLIP16 (pkzip.extraDataLength));
|
2008-08-06 03:09:59 +02:00
|
|
|
|
2008-08-06 03:39:43 +02:00
|
|
|
do
|
2008-08-06 03:09:59 +02:00
|
|
|
{
|
2008-08-06 03:39:43 +02:00
|
|
|
zs.avail_in = 2048 - size;
|
|
|
|
zs.next_in = (Bytef *) zipbuffer + size;
|
2008-08-06 03:09:59 +02:00
|
|
|
|
2008-08-06 03:39:43 +02:00
|
|
|
do
|
|
|
|
{
|
|
|
|
zs.avail_out = 16384;
|
|
|
|
zs.next_out = (Bytef *) output;
|
2008-08-06 03:09:59 +02:00
|
|
|
|
2008-08-06 03:39:43 +02:00
|
|
|
res = inflate (&zs, Z_NO_FLUSH);
|
2008-08-06 03:09:59 +02:00
|
|
|
|
2008-08-06 03:39:43 +02:00
|
|
|
have = 16384 - zs.avail_out;
|
2008-08-06 03:09:59 +02:00
|
|
|
|
2008-08-06 03:39:43 +02:00
|
|
|
if (have)
|
|
|
|
{
|
|
|
|
memcpy (rbuffer + outbytes, output, have);
|
|
|
|
outbytes += have;
|
|
|
|
}
|
2008-08-06 03:09:59 +02:00
|
|
|
|
2008-08-06 03:39:43 +02:00
|
|
|
}
|
|
|
|
while (zs.avail_out == 0);
|
2008-08-06 03:09:59 +02:00
|
|
|
|
2008-08-06 03:39:43 +02:00
|
|
|
sprintf (filepath, "Read %d bytes of %d", outbytes,
|
|
|
|
pkzip.uncompressedSize);
|
|
|
|
//ShowAction (filepath);
|
|
|
|
ShowProgress (filepath, outbytes, pkzip.uncompressedSize);
|
2008-08-06 03:09:59 +02:00
|
|
|
|
2008-08-06 03:39:43 +02:00
|
|
|
size = 0;
|
|
|
|
fread (zipbuffer, 1, 2048, handle);
|
|
|
|
|
|
|
|
}
|
|
|
|
while (res != Z_STREAM_END
|
|
|
|
&& (u32) outbytes < pkzip.uncompressedSize);
|
|
|
|
|
|
|
|
inflateEnd (&zs);
|
|
|
|
|
|
|
|
fclose (handle);
|
|
|
|
return pkzip.uncompressedSize;
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*** Just load the file up ***/
|
|
|
|
|
|
|
|
fseek(handle, 0, SEEK_END);
|
|
|
|
length = ftell(handle); // get filesize
|
|
|
|
fseek(handle, 2048, SEEK_SET); // seek back to point where we left off
|
|
|
|
|
|
|
|
sprintf (filepath, "Loading %d bytes", length);
|
|
|
|
ShowAction (filepath);
|
|
|
|
memcpy (rbuffer, zipbuffer, 2048); // copy what we already read
|
|
|
|
fread (rbuffer + 2048, 1, length - 2048, handle);
|
|
|
|
fclose (handle);
|
|
|
|
|
|
|
|
return length;
|
|
|
|
}
|
2008-08-06 03:09:59 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-08-06 03:39:43 +02:00
|
|
|
WaitPrompt((char*) "Error opening file");
|
2008-08-06 03:09:59 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Load savebuffer from SD card file
|
|
|
|
****************************************************************************/
|
|
|
|
int
|
2008-08-06 03:39:43 +02:00
|
|
|
LoadBufferFromSD (char *filepath, bool silent)
|
2008-08-06 03:09:59 +02:00
|
|
|
{
|
2008-08-06 03:39:43 +02:00
|
|
|
FILE *handle;
|
2008-08-06 03:09:59 +02:00
|
|
|
int offset = 0;
|
|
|
|
int read = 0;
|
|
|
|
|
2008-08-06 03:39:43 +02:00
|
|
|
handle = fopen (filepath, "rb");
|
2008-08-06 03:09:59 +02:00
|
|
|
|
|
|
|
if (handle <= 0)
|
|
|
|
{
|
|
|
|
if ( !silent )
|
|
|
|
{
|
|
|
|
char msg[100];
|
|
|
|
sprintf(msg, "Couldn't open %s", filepath);
|
|
|
|
WaitPrompt (msg);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset (savebuffer, 0, 0x22000);
|
|
|
|
|
|
|
|
/*** This is really nice, just load the file and decode it ***/
|
2008-08-06 03:39:43 +02:00
|
|
|
while ((read = fread (savebuffer + offset, 1, 1024, handle)) > 0)
|
2008-08-06 03:09:59 +02:00
|
|
|
{
|
|
|
|
offset += read;
|
|
|
|
}
|
|
|
|
|
2008-08-06 03:39:43 +02:00
|
|
|
fclose (handle);
|
2008-08-06 03:09:59 +02:00
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Write savebuffer to SD card file
|
|
|
|
****************************************************************************/
|
|
|
|
int
|
2008-08-06 03:39:43 +02:00
|
|
|
SaveBufferToSD (char *filepath, int datasize, bool silent)
|
2008-08-06 03:09:59 +02:00
|
|
|
{
|
2008-08-06 03:39:43 +02:00
|
|
|
FILE *handle;
|
2008-08-06 03:09:59 +02:00
|
|
|
|
|
|
|
if (datasize)
|
|
|
|
{
|
2008-08-06 03:39:43 +02:00
|
|
|
handle = fopen (filepath, "wb");
|
2008-08-06 03:09:59 +02:00
|
|
|
|
|
|
|
if (handle <= 0)
|
|
|
|
{
|
|
|
|
char msg[100];
|
|
|
|
sprintf(msg, "Couldn't save %s", filepath);
|
|
|
|
WaitPrompt (msg);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-08-06 03:39:43 +02:00
|
|
|
fwrite (savebuffer, 1, datasize, handle);
|
|
|
|
fclose (handle);
|
2008-08-06 03:09:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return datasize;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Save SRAM to SD Card
|
|
|
|
****************************************************************************/
|
2008-08-06 03:39:43 +02:00
|
|
|
void SaveSRAMToSD (int slot, bool silent)
|
2008-08-06 03:09:59 +02:00
|
|
|
{
|
|
|
|
char filepath[1024];
|
|
|
|
int datasize;
|
|
|
|
int offset;
|
|
|
|
|
2008-08-06 03:39:43 +02:00
|
|
|
ShowAction ((char*) "Saving SRAM to SD...");
|
2008-08-06 03:09:59 +02:00
|
|
|
|
|
|
|
#ifdef SDUSE_LFN
|
2008-08-06 03:39:43 +02:00
|
|
|
sprintf (filepath, "%s/%s/%s.srm", rootSDdir, SNESSAVEDIR, Memory.ROMName);
|
2008-08-06 03:09:59 +02:00
|
|
|
#else
|
2008-08-06 03:39:43 +02:00
|
|
|
sprintf (filepath, "%s/SNESSAVE/%08x.srm", rootSDdir, Memory.ROMCRC32);
|
2008-08-06 03:09:59 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
datasize = prepareEXPORTsavedata ();
|
|
|
|
|
|
|
|
if ( datasize )
|
|
|
|
{
|
|
|
|
offset = SaveBufferToSD (filepath, datasize, silent);
|
|
|
|
|
|
|
|
if ( (offset > 0) && (!silent) )
|
|
|
|
{
|
|
|
|
sprintf (filepath, "Wrote %d bytes", offset);
|
|
|
|
WaitPrompt (filepath);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Load SRAM From SD Card
|
|
|
|
****************************************************************************/
|
|
|
|
void
|
2008-08-06 03:39:43 +02:00
|
|
|
LoadSRAMFromSD (int slot, bool silent)
|
2008-08-06 03:09:59 +02:00
|
|
|
{
|
|
|
|
char filepath[1024];
|
|
|
|
int offset = 0;
|
|
|
|
|
2008-08-06 03:39:43 +02:00
|
|
|
ShowAction ((char*) "Loading SRAM from SD...");
|
2008-08-06 03:09:59 +02:00
|
|
|
|
|
|
|
#ifdef SDUSE_LFN
|
2008-08-06 03:39:43 +02:00
|
|
|
sprintf (filepath, "%s/%s/%s.srm", rootSDdir, SNESSAVEDIR, Memory.ROMName);
|
2008-08-06 03:09:59 +02:00
|
|
|
#else
|
2008-08-06 03:39:43 +02:00
|
|
|
sprintf (filepath, "%s/%s/%08x.srm", rootSDdir, SNESSAVEDIR, Memory.ROMCRC32);
|
2008-08-06 03:09:59 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
offset = LoadBufferFromSD (filepath, silent);
|
|
|
|
|
|
|
|
if (offset > 0)
|
|
|
|
{
|
|
|
|
decodesavedata (offset);
|
|
|
|
if ( !silent )
|
|
|
|
{
|
|
|
|
sprintf (filepath, "Loaded %d bytes", offset);
|
|
|
|
WaitPrompt(filepath);
|
|
|
|
}
|
|
|
|
S9xSoftReset();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Save Preferences to SD Card
|
|
|
|
****************************************************************************/
|
|
|
|
void
|
2008-08-06 03:39:43 +02:00
|
|
|
SavePrefsToSD (int slot, bool silent)
|
2008-08-06 03:09:59 +02:00
|
|
|
{
|
|
|
|
char filepath[1024];
|
|
|
|
int datasize;
|
|
|
|
int offset;
|
|
|
|
|
2008-08-06 03:39:43 +02:00
|
|
|
ShowAction ((char*) "Saving prefs to SD...");
|
2008-08-06 03:09:59 +02:00
|
|
|
|
|
|
|
#ifdef SDUSE_LFN
|
2008-08-06 03:39:43 +02:00
|
|
|
sprintf (filepath, "%s/%s/%s", rootSDdir, SNESSAVEDIR, PREFS_FILE_NAME);
|
2008-08-06 03:09:59 +02:00
|
|
|
#else
|
2008-08-06 03:39:43 +02:00
|
|
|
sprintf (filepath, "%s/%s/%s", rootSDdir, SNESSAVEDIR, PREFS_FILE_NAME);
|
2008-08-06 03:09:59 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
datasize = preparePrefsData ();
|
|
|
|
offset = SaveBufferToSD (filepath, datasize, silent);
|
|
|
|
|
|
|
|
if ( (offset > 0) && (!silent) )
|
|
|
|
{
|
|
|
|
sprintf (filepath, "Wrote %d bytes", offset);
|
|
|
|
WaitPrompt (filepath);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Load Preferences from SD Card
|
|
|
|
****************************************************************************/
|
|
|
|
void
|
2008-08-06 03:39:43 +02:00
|
|
|
LoadPrefsFromSD (int slot, bool silent)
|
2008-08-06 03:09:59 +02:00
|
|
|
{
|
|
|
|
char filepath[1024];
|
|
|
|
int offset = 0;
|
|
|
|
|
2008-08-06 03:39:43 +02:00
|
|
|
ShowAction ((char*) "Loading prefs from SD...");
|
2008-08-06 03:09:59 +02:00
|
|
|
|
|
|
|
#ifdef SDUSE_LFN
|
2008-08-06 03:39:43 +02:00
|
|
|
sprintf (filepath, "%s/%s/%s", rootSDdir, SNESSAVEDIR, PREFS_FILE_NAME);
|
2008-08-06 03:09:59 +02:00
|
|
|
#else
|
2008-08-06 03:39:43 +02:00
|
|
|
sprintf (filepath, "%s/%s/%s", rootSDdir, SNESSAVEDIR, PREFS_FILE_NAME);
|
2008-08-06 03:09:59 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
offset = LoadBufferFromSD (filepath, silent);
|
|
|
|
|
|
|
|
if (offset > 0)
|
|
|
|
{
|
|
|
|
decodePrefsData ();
|
|
|
|
if ( !silent )
|
|
|
|
{
|
|
|
|
sprintf (filepath, "Loaded %d bytes", offset);
|
|
|
|
WaitPrompt(filepath);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|