2008-09-16 07:42:21 +02:00
|
|
|
/****************************************************************************
|
2008-09-17 04:27:55 +02:00
|
|
|
* Visual Boy Advance GX
|
2008-09-16 07:42:21 +02:00
|
|
|
*
|
2008-09-17 04:27:55 +02:00
|
|
|
* Tantric September 2008
|
2008-09-16 07:42:21 +02:00
|
|
|
*
|
|
|
|
* fileop.cpp
|
|
|
|
*
|
|
|
|
* FAT File operations
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
#include <gccore.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <ogcsys.h>
|
|
|
|
#include <zlib.h>
|
|
|
|
|
|
|
|
#include "vba.h"
|
|
|
|
#include "vbasupport.h"
|
|
|
|
#include "fileop.h"
|
|
|
|
#include "gcunzip.h"
|
|
|
|
#include "video.h"
|
|
|
|
#include "menudraw.h"
|
|
|
|
#include "filesel.h"
|
|
|
|
#include "preferences.h"
|
|
|
|
|
2008-10-15 09:09:07 +02:00
|
|
|
// FAT file pointer - the only one we should ever use!
|
|
|
|
FILE * fatfile;
|
2008-09-16 07:42:21 +02:00
|
|
|
|
|
|
|
/****************************************************************************
|
2008-10-28 07:51:58 +01:00
|
|
|
* MountFAT
|
|
|
|
* Attempts to mount the FAT device specified
|
|
|
|
* Sets libfat to use the device by default
|
|
|
|
* Enables read-ahead cache for SD/USB
|
2008-09-16 07:42:21 +02:00
|
|
|
***************************************************************************/
|
2008-10-28 07:51:58 +01:00
|
|
|
bool MountFAT(PARTITION_INTERFACE part)
|
|
|
|
{
|
|
|
|
bool mounted = fatMountNormalInterface(part, 8);
|
2008-09-16 07:42:21 +02:00
|
|
|
|
2008-10-28 07:51:58 +01:00
|
|
|
if(mounted)
|
|
|
|
{
|
|
|
|
fatSetDefaultInterface(part);
|
|
|
|
#ifdef HW_RVL
|
|
|
|
if(part == PI_INTERNAL_SD || part == PI_USBSTORAGE)
|
|
|
|
fatEnableReadAhead (part, 6, 64);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
return mounted;
|
2008-09-16 07:42:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
2008-10-28 07:51:58 +01:00
|
|
|
* UnmountFAT
|
|
|
|
* Unmounts the FAT device specified
|
|
|
|
***************************************************************************/
|
|
|
|
void UnmountFAT(PARTITION_INTERFACE part)
|
|
|
|
{
|
|
|
|
if(!fatUnmount(part))
|
|
|
|
fatUnsafeUnmount(part);
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* UnmountAllFAT
|
|
|
|
* Unmounts all FAT devices
|
|
|
|
***************************************************************************/
|
|
|
|
void UnmountAllFAT()
|
|
|
|
{
|
|
|
|
#ifdef HW_RVL
|
|
|
|
UnmountFAT(PI_INTERNAL_SD);
|
|
|
|
UnmountFAT(PI_USBSTORAGE);
|
|
|
|
#endif
|
|
|
|
UnmountFAT(PI_SDGECKO_A);
|
|
|
|
UnmountFAT(PI_SDGECKO_B);
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* ChangeFATInterface
|
|
|
|
* Unmounts all devices and attempts to mount/configure the device specified
|
2008-09-16 07:42:21 +02:00
|
|
|
***************************************************************************/
|
|
|
|
bool ChangeFATInterface(int method, bool silent)
|
|
|
|
{
|
2008-10-28 07:51:58 +01:00
|
|
|
bool mounted = false;
|
|
|
|
|
|
|
|
// unmount all FAT devices
|
|
|
|
UnmountAllFAT();
|
2008-09-16 07:42:21 +02:00
|
|
|
|
|
|
|
if(method == METHOD_SD)
|
|
|
|
{
|
|
|
|
#ifdef HW_RVL
|
2008-10-28 07:51:58 +01:00
|
|
|
mounted = MountFAT(PI_INTERNAL_SD); // try Wii internal SD
|
2008-09-16 07:42:21 +02:00
|
|
|
#endif
|
|
|
|
|
2008-10-28 07:51:58 +01:00
|
|
|
if(!mounted) // internal SD not found
|
|
|
|
mounted = MountFAT(PI_SDGECKO_A); // try SD Gecko on slot A
|
|
|
|
if(!mounted) // internal SD and SD Gecko (on slot A) not found
|
|
|
|
mounted = MountFAT(PI_SDGECKO_B); // try SD Gecko on slot B
|
|
|
|
if(!mounted && !silent) // no SD device found
|
|
|
|
WaitPrompt ((char *)"SD card not found!");
|
2008-09-16 07:42:21 +02:00
|
|
|
}
|
|
|
|
else if(method == METHOD_USB)
|
|
|
|
{
|
|
|
|
#ifdef HW_RVL
|
2008-10-28 07:51:58 +01:00
|
|
|
mounted = MountFAT(PI_USBSTORAGE);
|
|
|
|
if(!mounted && !silent)
|
|
|
|
WaitPrompt ((char *)"USB drive not found!");
|
2008-09-16 07:42:21 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2008-10-28 07:51:58 +01:00
|
|
|
return mounted;
|
2008-09-16 07:42:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* Browse FAT subdirectories
|
|
|
|
**************************************************************************/
|
|
|
|
int
|
|
|
|
ParseFATdirectory(int method)
|
|
|
|
{
|
|
|
|
int nbfiles = 0;
|
|
|
|
DIR_ITER *fatdir;
|
|
|
|
char filename[MAXPATHLEN];
|
|
|
|
struct stat filestat;
|
|
|
|
char msg[128];
|
|
|
|
|
|
|
|
// initialize selection
|
|
|
|
selection = offset = 0;
|
|
|
|
|
|
|
|
// Clear any existing values
|
|
|
|
memset (&filelist, 0, sizeof (FILEENTRIES) * MAXFILES);
|
|
|
|
|
|
|
|
// open the directory
|
|
|
|
fatdir = diropen(currentdir);
|
|
|
|
if (fatdir == NULL)
|
|
|
|
{
|
|
|
|
sprintf(msg, "Couldn't open %s", currentdir);
|
|
|
|
WaitPrompt(msg);
|
|
|
|
|
|
|
|
// if we can't open the dir, open root dir
|
|
|
|
sprintf(currentdir,"%s",ROOTFATDIR);
|
|
|
|
|
|
|
|
fatdir = diropen(currentdir);
|
|
|
|
|
|
|
|
if (fatdir == NULL)
|
|
|
|
{
|
|
|
|
sprintf(msg, "Error opening %s", currentdir);
|
|
|
|
WaitPrompt(msg);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// index files/folders
|
|
|
|
while(dirnext(fatdir,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; // flag this as a dir
|
|
|
|
nbfiles++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// close directory
|
|
|
|
dirclose(fatdir);
|
|
|
|
|
|
|
|
// Sort the file list
|
|
|
|
qsort(filelist, nbfiles, sizeof(FILEENTRIES), FileSortCallback);
|
|
|
|
|
|
|
|
return nbfiles;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* LoadFATFile
|
|
|
|
***************************************************************************/
|
|
|
|
int
|
2008-09-29 09:35:26 +02:00
|
|
|
LoadFATFile (char * rbuffer, int length)
|
2008-09-16 07:42:21 +02:00
|
|
|
{
|
2008-09-26 08:23:00 +02:00
|
|
|
char zipbuffer[2048];
|
2008-09-17 04:27:55 +02:00
|
|
|
char filepath[MAXPATHLEN];
|
2008-09-26 08:23:00 +02:00
|
|
|
u32 size;
|
2008-09-17 04:27:55 +02:00
|
|
|
|
2008-09-16 07:42:21 +02:00
|
|
|
/* Check filename length */
|
2008-10-15 09:09:07 +02:00
|
|
|
if (!MakeROMPath(filepath, METHOD_SD))
|
2008-09-16 07:42:21 +02:00
|
|
|
{
|
|
|
|
WaitPrompt((char*) "Maximum filepath length reached!");
|
|
|
|
return -1;
|
|
|
|
}
|
2008-09-26 08:23:00 +02:00
|
|
|
|
2008-10-15 09:09:07 +02:00
|
|
|
fatfile = fopen (filepath, "rb");
|
|
|
|
if (fatfile > 0)
|
2008-09-16 07:42:21 +02:00
|
|
|
{
|
2008-10-15 09:09:07 +02:00
|
|
|
if(length > 0 && length <= 2048) // do a partial read (eg: to check file header)
|
2008-09-16 07:42:21 +02:00
|
|
|
{
|
2008-10-15 09:09:07 +02:00
|
|
|
fread (rbuffer, 1, length, fatfile);
|
2008-09-29 09:35:26 +02:00
|
|
|
size = length;
|
2008-09-16 07:42:21 +02:00
|
|
|
}
|
2008-09-29 09:35:26 +02:00
|
|
|
else // load whole file
|
2008-09-16 07:42:21 +02:00
|
|
|
{
|
2008-10-15 09:09:07 +02:00
|
|
|
fread (zipbuffer, 1, 2048, fatfile);
|
2008-09-29 09:35:26 +02:00
|
|
|
|
|
|
|
if (IsZipFile (zipbuffer))
|
|
|
|
{
|
2008-10-15 09:09:07 +02:00
|
|
|
size = UnZipBuffer ((unsigned char *)rbuffer, METHOD_SD); // unzip from FAT
|
2008-09-29 09:35:26 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Just load the file up
|
2008-10-15 09:09:07 +02:00
|
|
|
fseek(fatfile, 0, SEEK_END);
|
|
|
|
size = ftell(fatfile); // get filesize
|
|
|
|
fseek(fatfile, 2048, SEEK_SET); // seek back to point where we left off
|
2008-09-29 09:35:26 +02:00
|
|
|
memcpy (rbuffer, zipbuffer, 2048); // copy what we already read
|
2008-10-15 09:09:07 +02:00
|
|
|
|
|
|
|
ShowProgress ((char *)"Loading...", 2048, size);
|
|
|
|
|
|
|
|
u32 offset = 2048;
|
|
|
|
while(offset < size)
|
|
|
|
{
|
|
|
|
offset += fread (rbuffer + offset, 1, (1024*512), fatfile); // read in 512K chunks
|
|
|
|
ShowProgress ((char *)"Loading...", offset, size);
|
|
|
|
}
|
2008-09-29 09:35:26 +02:00
|
|
|
}
|
2008-09-16 07:42:21 +02:00
|
|
|
}
|
2008-10-15 09:09:07 +02:00
|
|
|
fclose (fatfile);
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
WaitPrompt((char*) "Error opening file");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* LoadFATSzFile
|
|
|
|
* Loads the selected file # from the specified 7z into rbuffer
|
|
|
|
* Returns file size
|
|
|
|
***************************************************************************/
|
|
|
|
int
|
|
|
|
LoadFATSzFile(char * filepath, unsigned char * rbuffer)
|
|
|
|
{
|
|
|
|
u32 size;
|
|
|
|
fatfile = fopen (filepath, "rb");
|
|
|
|
if (fatfile > 0)
|
|
|
|
{
|
|
|
|
size = SzExtractFile(filelist[selection].offset, rbuffer);
|
|
|
|
fclose (fatfile);
|
2008-09-16 07:42:21 +02:00
|
|
|
return size;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
WaitPrompt((char*) "Error opening file");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Load savebuffer from FAT file
|
|
|
|
***************************************************************************/
|
|
|
|
int
|
|
|
|
LoadBufferFromFAT (char *filepath, bool silent)
|
2008-10-27 05:31:59 +01:00
|
|
|
{
|
|
|
|
return LoadBufferFromFAT((char *)savebuffer, filepath, silent);
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Load buffer from FAT file
|
|
|
|
***************************************************************************/
|
|
|
|
int
|
|
|
|
LoadBufferFromFAT (char * buffer, char *filepath, bool silent)
|
2008-09-16 07:42:21 +02:00
|
|
|
{
|
2008-10-03 08:58:21 +02:00
|
|
|
int size = 0;
|
2008-09-16 07:42:21 +02:00
|
|
|
|
2008-10-15 09:09:07 +02:00
|
|
|
fatfile = fopen (filepath, "rb");
|
2008-09-16 07:42:21 +02:00
|
|
|
|
2008-10-15 09:09:07 +02:00
|
|
|
if (fatfile <= 0)
|
2008-09-16 07:42:21 +02:00
|
|
|
{
|
|
|
|
if ( !silent )
|
|
|
|
{
|
|
|
|
char msg[100];
|
|
|
|
sprintf(msg, "Couldn't open %s", filepath);
|
|
|
|
WaitPrompt (msg);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-10-15 09:09:07 +02:00
|
|
|
fseek(fatfile, 0, SEEK_END); // go to end of file
|
|
|
|
size = ftell(fatfile); // get filesize
|
|
|
|
fseek(fatfile, 0, SEEK_SET); // go to start of file
|
|
|
|
fread (savebuffer, 1, size, fatfile);
|
|
|
|
fclose (fatfile);
|
2008-09-16 07:42:21 +02:00
|
|
|
|
2008-10-03 08:58:21 +02:00
|
|
|
return size;
|
2008-09-16 07:42:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Write savebuffer to FAT card file
|
|
|
|
***************************************************************************/
|
|
|
|
int
|
|
|
|
SaveBufferToFAT (char *filepath, int datasize, bool silent)
|
|
|
|
{
|
2008-10-15 09:09:07 +02:00
|
|
|
if (datasize)
|
2008-09-16 07:42:21 +02:00
|
|
|
{
|
2008-10-15 09:09:07 +02:00
|
|
|
fatfile = fopen (filepath, "wb");
|
2008-09-16 07:42:21 +02:00
|
|
|
|
2008-10-15 09:09:07 +02:00
|
|
|
if (fatfile <= 0)
|
2008-09-16 07:42:21 +02:00
|
|
|
{
|
|
|
|
char msg[100];
|
|
|
|
sprintf(msg, "Couldn't save %s", filepath);
|
|
|
|
WaitPrompt (msg);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-10-15 09:09:07 +02:00
|
|
|
fwrite (savebuffer, 1, datasize, fatfile);
|
|
|
|
fclose (fatfile);
|
2008-09-16 07:42:21 +02:00
|
|
|
}
|
|
|
|
return datasize;
|
|
|
|
}
|