Genesis-Plus-GX/source/gx/fileio/file_fat.c
ekeeke31 2c2f760f44 .optimized memory footprint
.improved hardware initialization (fixes Ultimate Mortal Kombat Trilogy)
.improved soft-reset emulation
.fixed some menu bugs on Gamecube
2010-05-28 12:08:00 +00:00

306 lines
7.6 KiB
C

/*
* file_fat.c
*
* FAT loading support
*
* Eke-Eke (2008,2009)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
********************************************************************************/
#include "shared.h"
#include "gui.h"
#include "history.h"
#include "unzip.h"
#include "filesel.h"
#include "file_fat.h"
#include "file_dvd.h"
/* current FAT directory */
static char *fatdir;
/* current FAT device */
static int fatType = -1;
/***************************************************************************
* FAT_ClearDirectory
*
* Clear FAT access flag
***************************************************************************/
void FAT_ClearDirectory(void)
{
fatType = -1;
}
/***************************************************************************
* FAT_UpdateDirectory
*
* Update FAT current directory
* return zero if exiting root
***************************************************************************/
int FAT_UpdateDirectory(bool go_up, char *dirname)
{
int size=0;
char *test;
char temp[MAXPATHLEN];
/* go up to parent directory */
if (strcmp(dirname,"..") == 0)
{
/* determine last subdirectory namelength */
sprintf(temp,"%s",fatdir);
test= strtok(temp,"/");
while (test != NULL)
{
size = strlen(test);
test = strtok(NULL,"/");
}
/* remove last subdirectory name */
size = strlen(fatdir) - size;
fatdir[size-1] = 0;
}
else if (go_up)
{
/* root has no parent directory */
return 0;
}
else
{
/* by default, simply append folder name */
sprintf(fatdir, "%s%s/",fatdir, dirname);
}
return 1;
}
/***************************************************************************
* FAT_ParseDirectory
*
* List files into one FAT directory
***************************************************************************/
int FAT_ParseDirectory(void)
{
int nbfiles = 0;
char filename[MAXPATHLEN];
struct stat filestat;
/* open directory */
DIR_ITER *dir = diropen (fatdir);
if (dir == NULL)
{
GUI_WaitPrompt("Error","Unable to open directory !");
return -1;
}
while ((dirnext(dir, filename, &filestat) == 0) && (nbfiles < MAXFILES))
{
if (strcmp(filename,".") != 0)
{
memset(&filelist[nbfiles], 0, sizeof (FILEENTRIES));
sprintf(filelist[nbfiles].filename,"%s",filename);
filelist[nbfiles].length = filestat.st_size;
filelist[nbfiles].flags = (filestat.st_mode & S_IFDIR) ? 1 : 0;
nbfiles++;
}
}
dirclose(dir);
/* Sort the file list */
qsort(filelist, nbfiles, sizeof(FILEENTRIES), FileSortCallback);
return nbfiles;
}
/****************************************************************************
* FAT_LoadFile
*
* This function will load a BIN, SMD or ZIP file from DVD into the ROM buffer.
* This functions return the actual size of data copied into the buffer
*
****************************************************************************/
int FAT_LoadFile(u8 *buffer, u32 selection)
{
char fname[MAXPATHLEN];
int length = 0;
/* Loading from history */
if(fatType == TYPE_RECENT)
{
/* full filename */
sprintf(fname,"%s%s",history.entries[selection].filepath,filelist[selection].filename);
/* get the length of the file */
struct stat filestat;
if(stat(fname, &filestat) == 0)
length = filestat.st_size;
}
else
{
/* full filename */
sprintf(fname, "%s%s",fatdir,filelist[selection].filename);
/* get the length of the file */
length = filelist[selection].length;
}
if (length > 0)
{
/* Open file */
FILE *sdfile = fopen(fname, "rb");
if (sdfile == NULL)
{
GUI_WaitPrompt("Error","Unable to open file !");
return 0;
}
/* Add/move the file to the top of the history. */
if(fatType == TYPE_RECENT)
history_add_file(history.entries[selection].filepath, filelist[selection].filename);
else
history_add_file(fatdir, filelist[selection].filename);
/* file browser should be reinitialized */
if(fatType == TYPE_RECENT)
fatType = -1;
/* Read first data chunk */
unsigned char temp[FATCHUNK];
fread(temp, FATCHUNK, 1, sdfile);
fclose(sdfile);
/* Determine file type */
if (!IsZipFile ((char *) temp))
{
if (length > MAXROMSIZE)
{
GUI_WaitPrompt("Error","File size not supported !");
return 0;
}
/* re-open and read file */
sdfile = fopen(fname, "rb");
if (sdfile)
{
char msg[64];
sprintf(msg,"Loading %d bytes ...", length);
GUI_MsgBoxOpen("Information",msg,1);
int done = 0;
while (length > FATCHUNK)
{
fread(buffer + done, FATCHUNK, 1, sdfile);
length -= FATCHUNK;
done += FATCHUNK;
}
fread(buffer + done, length, 1, sdfile);
done += length;
fclose(sdfile);
return done;
}
}
else
{
/* unzip file */
return UnZipBuffer(buffer, 0, fname);
}
}
return 0;
}
/****************************************************************************
* OpenFAT
*
* Function to load a FAT directory and display to user.
****************************************************************************/
int FAT_Open(int type)
{
int max = 0;
if (type == TYPE_RECENT)
{
/* fetch history list */
int i;
for(i=0; i < NUM_HISTORY_ENTRIES; i++)
{
if(history.entries[i].filepath[0] > 0)
{
filelist[i].offset = 0;
filelist[i].length = 0;
filelist[i].flags = 0;
strncpy(filelist[i].filename,history.entries[i].filename, MAXJOLIET-1);
filelist[i].filename[MAXJOLIET-1] = '\0';
max++;
}
else
{
/* Found the end of the list. */
break;
}
}
}
else
{
/* default directory */
fatdir = config.sddir;
#ifdef HW_RVL
if (type == TYPE_USB)
fatdir = config.usbdir;
#endif
/* verify current dir exists, otherwise browse from root */
DIR_ITER *dir = diropen(fatdir);
if (dir)
dirclose(dir);
#ifdef HW_RVL
else if (type == TYPE_USB)
sprintf (fatdir, "usb:/");
else
sprintf (fatdir, "sd:/");
#else
else
sprintf (fatdir, "/");
#endif
/* parse current directory */
max = FAT_ParseDirectory ();
}
if (max < 0)
return 0;
if (max == 0)
{
GUI_WaitPrompt("Error","No files found !");
return 0;
}
/* check if access type has changed */
if (type != fatType)
{
/* set current access type */
fatType = type;
/* reset File selector */
ClearSelector(max);
/* clear DVD access flag */
DVD_ClearDirectory();
}
return 1;
}