2008-08-06 03:09:59 +02:00
|
|
|
/****************************************************************************
|
2010-01-27 23:20:37 +01:00
|
|
|
* Snes9x Nintendo Wii/Gamecube Port
|
2008-08-14 00:44:59 +02:00
|
|
|
*
|
2018-12-27 00:10:12 +01:00
|
|
|
* Tantric 2008-2019
|
2008-08-10 05:14:39 +02:00
|
|
|
*
|
2009-03-28 20:03:35 +01:00
|
|
|
* filebrowser.cpp
|
2008-08-10 05:14:39 +02:00
|
|
|
*
|
|
|
|
* Generic file routines - reading, writing, browsing
|
2008-09-12 07:28:40 +02:00
|
|
|
***************************************************************************/
|
|
|
|
|
2008-08-06 03:09:59 +02:00
|
|
|
#include <gccore.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2008-08-06 03:39:43 +02:00
|
|
|
#include <wiiuse/wpad.h>
|
2008-08-06 04:31:44 +02:00
|
|
|
#include <sys/dir.h>
|
2008-09-26 06:34:33 +02:00
|
|
|
#include <malloc.h>
|
2008-08-10 05:14:39 +02:00
|
|
|
|
2008-12-30 01:08:17 +01:00
|
|
|
#ifdef HW_RVL
|
2008-08-19 08:05:57 +02:00
|
|
|
#include <di/di.h>
|
2008-08-23 05:20:54 +02:00
|
|
|
#endif
|
2008-08-19 08:05:57 +02:00
|
|
|
|
2018-08-01 20:44:21 +02:00
|
|
|
#include "snes9x/port.h"
|
2010-03-22 00:43:54 +01:00
|
|
|
#include "snes9xgx.h"
|
2009-03-11 18:28:37 +01:00
|
|
|
#include "filebrowser.h"
|
|
|
|
#include "menu.h"
|
2008-08-06 03:09:59 +02:00
|
|
|
#include "video.h"
|
2008-12-24 09:02:04 +01:00
|
|
|
#include "networkop.h"
|
2008-08-07 07:33:24 +02:00
|
|
|
#include "fileop.h"
|
2008-08-20 06:07:38 +02:00
|
|
|
#include "input.h"
|
2008-12-24 09:02:04 +01:00
|
|
|
#include "gcunzip.h"
|
2009-03-11 18:28:37 +01:00
|
|
|
#include "freeze.h"
|
|
|
|
#include "sram.h"
|
2008-08-06 03:09:59 +02:00
|
|
|
|
2010-03-22 00:43:54 +01:00
|
|
|
#include "snes9x/snes9x.h"
|
|
|
|
#include "snes9x/memmap.h"
|
|
|
|
#include "snes9x/cheats.h"
|
|
|
|
|
2018-08-30 18:11:24 +02:00
|
|
|
extern "C" {
|
|
|
|
extern char* strcasestr(const char *, const char *);
|
|
|
|
}
|
|
|
|
|
2008-12-30 01:08:17 +01:00
|
|
|
BROWSERINFO browser;
|
|
|
|
BROWSERENTRY * browserList = NULL; // list of files/folders in browser
|
2008-08-16 02:02:08 +02:00
|
|
|
|
2008-12-30 01:08:17 +01:00
|
|
|
static char szpath[MAXPATHLEN];
|
2014-10-24 04:47:59 +02:00
|
|
|
char szname[MAXPATHLEN];
|
|
|
|
bool inSz = false;
|
2008-09-27 09:57:03 +02:00
|
|
|
|
2008-12-30 01:08:17 +01:00
|
|
|
unsigned long SNESROMSize = 0;
|
2010-03-16 00:18:18 +01:00
|
|
|
bool loadingFile = false;
|
2008-09-27 09:13:52 +02:00
|
|
|
|
2018-11-12 00:57:16 +01:00
|
|
|
extern bool isBSX();
|
|
|
|
|
2008-08-07 05:25:02 +02:00
|
|
|
/****************************************************************************
|
2008-08-08 09:57:01 +02:00
|
|
|
* autoLoadMethod()
|
2009-10-02 00:35:12 +02:00
|
|
|
* Auto-determines and sets the load device
|
|
|
|
* Returns device set
|
2008-08-07 05:25:02 +02:00
|
|
|
****************************************************************************/
|
|
|
|
int autoLoadMethod()
|
2008-08-06 03:09:59 +02:00
|
|
|
{
|
2009-10-02 00:35:12 +02:00
|
|
|
ShowAction ("Attempting to determine load device...");
|
|
|
|
|
|
|
|
int device = DEVICE_AUTO;
|
|
|
|
|
|
|
|
if(ChangeInterface(DEVICE_SD, SILENT))
|
|
|
|
device = DEVICE_SD;
|
|
|
|
else if(ChangeInterface(DEVICE_USB, SILENT))
|
|
|
|
device = DEVICE_USB;
|
2010-04-02 23:02:16 +02:00
|
|
|
else if(ChangeInterface(DEVICE_SD_SLOTA, SILENT))
|
|
|
|
device = DEVICE_SD_SLOTA;
|
|
|
|
else if(ChangeInterface(DEVICE_SD_SLOTB, SILENT))
|
|
|
|
device = DEVICE_SD_SLOTB;
|
2019-12-24 06:30:59 +01:00
|
|
|
else if(ChangeInterface(DEVICE_SD_PORT2, SILENT))
|
|
|
|
device = DEVICE_SD_PORT2;
|
2009-10-02 00:35:12 +02:00
|
|
|
else if(ChangeInterface(DEVICE_DVD, SILENT))
|
|
|
|
device = DEVICE_DVD;
|
|
|
|
else if(ChangeInterface(DEVICE_SMB, SILENT))
|
|
|
|
device = DEVICE_SMB;
|
2008-08-08 09:57:01 +02:00
|
|
|
else
|
2009-10-02 00:35:12 +02:00
|
|
|
ErrorPrompt("Unable to locate a load device!");
|
2008-12-22 10:20:35 +01:00
|
|
|
|
2009-10-02 00:35:12 +02:00
|
|
|
if(GCSettings.LoadMethod == DEVICE_AUTO)
|
|
|
|
GCSettings.LoadMethod = device; // save device found for later use
|
2009-03-11 18:28:37 +01:00
|
|
|
CancelAction();
|
2009-10-02 00:35:12 +02:00
|
|
|
return device;
|
2008-08-07 05:25:02 +02:00
|
|
|
}
|
2008-08-06 03:09:59 +02:00
|
|
|
|
2008-08-07 05:25:02 +02:00
|
|
|
/****************************************************************************
|
2008-08-08 09:57:01 +02:00
|
|
|
* autoSaveMethod()
|
2009-10-02 00:35:12 +02:00
|
|
|
* Auto-determines and sets the save device
|
|
|
|
* Returns device set
|
2008-08-07 05:25:02 +02:00
|
|
|
****************************************************************************/
|
2008-12-22 10:20:35 +01:00
|
|
|
int autoSaveMethod(bool silent)
|
2008-08-07 05:25:02 +02:00
|
|
|
{
|
2008-12-22 10:20:35 +01:00
|
|
|
if(!silent)
|
2009-10-02 00:35:12 +02:00
|
|
|
ShowAction ("Attempting to determine save device...");
|
|
|
|
|
|
|
|
int device = DEVICE_AUTO;
|
|
|
|
|
|
|
|
if(ChangeInterface(DEVICE_SD, SILENT))
|
|
|
|
device = DEVICE_SD;
|
|
|
|
else if(ChangeInterface(DEVICE_USB, SILENT))
|
|
|
|
device = DEVICE_USB;
|
2010-04-02 23:02:16 +02:00
|
|
|
else if(ChangeInterface(DEVICE_SD_SLOTA, SILENT))
|
|
|
|
device = DEVICE_SD_SLOTA;
|
|
|
|
else if(ChangeInterface(DEVICE_SD_SLOTB, SILENT))
|
|
|
|
device = DEVICE_SD_SLOTB;
|
2019-12-24 06:30:59 +01:00
|
|
|
else if(ChangeInterface(DEVICE_SD_PORT2, SILENT))
|
|
|
|
device = DEVICE_SD_PORT2;
|
2009-10-02 00:35:12 +02:00
|
|
|
else if(ChangeInterface(DEVICE_SMB, SILENT))
|
|
|
|
device = DEVICE_SMB;
|
2008-12-22 10:20:35 +01:00
|
|
|
else if(!silent)
|
2009-10-02 00:35:12 +02:00
|
|
|
ErrorPrompt("Unable to locate a save device!");
|
2008-12-22 10:20:35 +01:00
|
|
|
|
2009-10-02 00:35:12 +02:00
|
|
|
if(GCSettings.SaveMethod == DEVICE_AUTO)
|
|
|
|
GCSettings.SaveMethod = device; // save device found for later use
|
2009-03-11 18:28:37 +01:00
|
|
|
|
|
|
|
CancelAction();
|
2009-10-02 00:35:12 +02:00
|
|
|
return device;
|
2008-08-07 05:25:02 +02:00
|
|
|
}
|
2008-08-06 03:09:59 +02:00
|
|
|
|
2008-12-30 01:08:17 +01:00
|
|
|
/****************************************************************************
|
|
|
|
* ResetBrowser()
|
|
|
|
* Clears the file browser memory, and allocates one initial entry
|
|
|
|
***************************************************************************/
|
|
|
|
void ResetBrowser()
|
|
|
|
{
|
2009-03-11 18:28:37 +01:00
|
|
|
browser.numEntries = 0;
|
|
|
|
browser.selIndex = 0;
|
|
|
|
browser.pageIndex = 0;
|
2010-06-23 19:34:19 +02:00
|
|
|
browser.size = 0;
|
2009-10-02 00:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool AddBrowserEntry()
|
|
|
|
{
|
2010-06-23 19:34:19 +02:00
|
|
|
if(browser.size >= MAX_BROWSER_SIZE)
|
2009-10-02 00:35:12 +02:00
|
|
|
{
|
|
|
|
ErrorPrompt("Out of memory: too many files!");
|
2010-06-23 19:34:19 +02:00
|
|
|
return false; // out of space
|
2009-10-02 00:35:12 +02:00
|
|
|
}
|
2010-06-23 19:34:19 +02:00
|
|
|
|
2009-10-02 00:35:12 +02:00
|
|
|
memset(&(browserList[browser.size]), 0, sizeof(BROWSERENTRY)); // clear the new entry
|
|
|
|
browser.size++;
|
|
|
|
return true;
|
2008-12-30 01:08:17 +01:00
|
|
|
}
|
|
|
|
|
2009-06-12 09:47:42 +02:00
|
|
|
/****************************************************************************
|
|
|
|
* CleanupPath()
|
|
|
|
* Cleans up the filepath, removing double // and replacing \ with /
|
|
|
|
***************************************************************************/
|
|
|
|
static void CleanupPath(char * path)
|
|
|
|
{
|
2009-10-02 00:35:12 +02:00
|
|
|
if(!path || path[0] == 0)
|
|
|
|
return;
|
|
|
|
|
2009-06-12 09:47:42 +02:00
|
|
|
int pathlen = strlen(path);
|
|
|
|
int j = 0;
|
|
|
|
for(int i=0; i < pathlen && i < MAXPATHLEN; i++)
|
|
|
|
{
|
|
|
|
if(path[i] == '\\')
|
|
|
|
path[i] = '/';
|
|
|
|
|
|
|
|
if(j == 0 || !(path[j-1] == '/' && path[i] == '/'))
|
|
|
|
path[j++] = path[i];
|
|
|
|
}
|
|
|
|
path[j] = 0;
|
2009-10-02 00:35:12 +02:00
|
|
|
}
|
2009-06-12 09:47:42 +02:00
|
|
|
|
2009-10-02 00:35:12 +02:00
|
|
|
bool IsDeviceRoot(char * path)
|
|
|
|
{
|
|
|
|
if(path == NULL || path[0] == 0)
|
|
|
|
return false;
|
|
|
|
|
2010-04-02 23:02:16 +02:00
|
|
|
if( strcmp(path, "sd:/") == 0 ||
|
|
|
|
strcmp(path, "usb:/") == 0 ||
|
|
|
|
strcmp(path, "dvd:/") == 0 ||
|
|
|
|
strcmp(path, "smb:/") == 0 ||
|
|
|
|
strcmp(path, "carda:/") == 0 ||
|
2019-12-24 06:30:59 +01:00
|
|
|
strcmp(path, "cardb:/") == 0 ||
|
|
|
|
strcmp(path, "port2:/") == 0)
|
2009-10-02 00:35:12 +02:00
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2009-06-12 09:47:42 +02:00
|
|
|
}
|
|
|
|
|
2008-09-12 07:28:40 +02:00
|
|
|
/****************************************************************************
|
|
|
|
* UpdateDirName()
|
|
|
|
* Update curent directory name for file browser
|
2008-08-10 05:14:39 +02:00
|
|
|
***************************************************************************/
|
2009-10-02 00:35:12 +02:00
|
|
|
int UpdateDirName()
|
2008-08-10 05:14:39 +02:00
|
|
|
{
|
|
|
|
int size=0;
|
2008-09-27 09:13:52 +02:00
|
|
|
char * test;
|
2008-08-10 05:14:39 +02:00
|
|
|
char temp[1024];
|
2009-10-02 00:35:12 +02:00
|
|
|
int device = 0;
|
|
|
|
|
|
|
|
if(browser.numEntries == 0)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
FindDevice(browser.dir, &device);
|
2008-08-10 05:14:39 +02:00
|
|
|
|
|
|
|
/* current directory doesn't change */
|
2008-12-30 01:08:17 +01:00
|
|
|
if (strcmp(browserList[browser.selIndex].filename,".") == 0)
|
2008-08-10 05:14:39 +02:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/* go up to parent directory */
|
2008-12-30 01:08:17 +01:00
|
|
|
else if (strcmp(browserList[browser.selIndex].filename,"..") == 0)
|
2008-08-10 05:14:39 +02:00
|
|
|
{
|
2009-10-02 00:35:12 +02:00
|
|
|
// already at the top level
|
|
|
|
if(IsDeviceRoot(browser.dir))
|
2008-08-10 05:14:39 +02:00
|
|
|
{
|
2009-10-02 00:35:12 +02:00
|
|
|
browser.dir[0] = 0; // remove device - we are going to the device listing screen
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* determine last subdirectory namelength */
|
|
|
|
sprintf(temp,"%s",browser.dir);
|
|
|
|
test = strtok(temp,"/");
|
|
|
|
while (test != NULL)
|
|
|
|
{
|
|
|
|
size = strlen(test);
|
|
|
|
test = strtok(NULL,"/");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* remove last subdirectory name */
|
|
|
|
size = strlen(browser.dir) - size - 1;
|
2014-10-24 04:47:59 +02:00
|
|
|
strncpy(GCSettings.LastFileLoaded, &browser.dir[size], strlen(browser.dir) - size - 1); //set as loaded file the previous dir
|
|
|
|
GCSettings.LastFileLoaded[strlen(browser.dir) - size - 1] = 0;
|
2009-10-02 00:35:12 +02:00
|
|
|
browser.dir[size] = 0;
|
2008-08-10 05:14:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
/* Open a directory */
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* test new directory namelength */
|
2008-12-30 01:08:17 +01:00
|
|
|
if ((strlen(browser.dir)+1+strlen(browserList[browser.selIndex].filename)) < MAXPATHLEN)
|
2008-08-10 05:14:39 +02:00
|
|
|
{
|
|
|
|
/* update current directory name */
|
2020-06-28 18:05:41 +02:00
|
|
|
sprintf(browser.dir+strlen(browser.dir), "%s/", browserList[browser.selIndex].filename);
|
2008-08-10 05:14:39 +02:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-03-11 18:28:37 +01:00
|
|
|
ErrorPrompt("Directory name is too long!");
|
2008-08-10 05:14:39 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-02 00:35:12 +02:00
|
|
|
bool MakeFilePath(char filepath[], int type, char * filename, int filenum)
|
2008-10-14 11:21:34 +02:00
|
|
|
{
|
2008-11-12 08:50:39 +01:00
|
|
|
char file[512];
|
|
|
|
char folder[1024];
|
2009-03-19 17:51:36 +01:00
|
|
|
char ext[4];
|
2008-10-14 11:21:34 +02:00
|
|
|
char temppath[MAXPATHLEN];
|
|
|
|
|
2008-11-12 08:50:39 +01:00
|
|
|
if(type == FILE_ROM)
|
2008-10-14 11:21:34 +02:00
|
|
|
{
|
2008-11-12 08:50:39 +01:00
|
|
|
// Check path length
|
2008-12-30 01:08:17 +01:00
|
|
|
if ((strlen(browser.dir)+1+strlen(browserList[browser.selIndex].filename)) >= MAXPATHLEN)
|
2008-11-12 08:50:39 +01:00
|
|
|
{
|
2009-03-11 18:28:37 +01:00
|
|
|
ErrorPrompt("Maximum filepath length reached!");
|
2008-11-12 08:50:39 +01:00
|
|
|
filepath[0] = 0;
|
|
|
|
return false;
|
|
|
|
}
|
2008-10-14 11:21:34 +02:00
|
|
|
else
|
2008-11-12 08:50:39 +01:00
|
|
|
{
|
2009-06-12 09:47:42 +02:00
|
|
|
sprintf(temppath, "%s%s",browser.dir,browserList[browser.selIndex].filename);
|
2008-11-12 08:50:39 +01:00
|
|
|
}
|
2008-10-14 11:21:34 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-10-02 05:09:36 +02:00
|
|
|
if(GCSettings.SaveMethod == DEVICE_AUTO)
|
|
|
|
GCSettings.SaveMethod = autoSaveMethod(SILENT);
|
2009-10-04 21:30:55 +02:00
|
|
|
|
2009-10-02 05:09:36 +02:00
|
|
|
if(GCSettings.SaveMethod == DEVICE_AUTO)
|
|
|
|
return false;
|
2009-10-04 21:30:55 +02:00
|
|
|
|
2008-11-12 08:50:39 +01:00
|
|
|
switch(type)
|
|
|
|
{
|
|
|
|
case FILE_SRAM:
|
|
|
|
case FILE_SNAPSHOT:
|
|
|
|
sprintf(folder, GCSettings.SaveFolder);
|
2009-03-16 07:58:50 +01:00
|
|
|
|
2009-03-19 17:51:36 +01:00
|
|
|
if(type == FILE_SRAM) sprintf(ext, "srm");
|
|
|
|
else sprintf(ext, "frz");
|
|
|
|
|
2009-04-09 09:43:59 +02:00
|
|
|
if(filenum >= -1)
|
2009-03-16 07:58:50 +01:00
|
|
|
{
|
2009-11-29 09:12:40 +01:00
|
|
|
if(filenum == -1)
|
|
|
|
sprintf(file, "%s.%s", filename, ext);
|
|
|
|
else if(filenum == 0)
|
2019-01-30 04:31:25 +01:00
|
|
|
if (GCSettings.AppendAuto <= 0)
|
|
|
|
sprintf(file, "%s.%s", filename, ext);
|
|
|
|
else
|
|
|
|
sprintf(file, "%s Auto.%s", filename, ext);
|
2009-03-16 07:58:50 +01:00
|
|
|
else
|
2009-11-29 09:12:40 +01:00
|
|
|
sprintf(file, "%s %i.%s", filename, filenum, ext);
|
2009-03-16 07:58:50 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-03-17 06:21:25 +01:00
|
|
|
sprintf(file, "%s", filename);
|
2009-03-16 07:58:50 +01:00
|
|
|
}
|
2008-11-12 08:50:39 +01:00
|
|
|
break;
|
|
|
|
case FILE_CHEAT:
|
|
|
|
sprintf(folder, GCSettings.CheatFolder);
|
|
|
|
sprintf(file, "%s.cht", Memory.ROMFilename);
|
|
|
|
break;
|
|
|
|
}
|
2009-11-29 09:12:40 +01:00
|
|
|
sprintf (temppath, "%s%s/%s", pathPrefix[GCSettings.SaveMethod], folder, file);
|
2008-11-12 08:50:39 +01:00
|
|
|
}
|
2009-06-12 09:47:42 +02:00
|
|
|
CleanupPath(temppath); // cleanup path
|
2011-03-20 18:17:51 +01:00
|
|
|
snprintf(filepath, MAXPATHLEN, "%s", temppath);
|
2008-11-12 08:50:39 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2008-09-12 07:28:40 +02:00
|
|
|
/****************************************************************************
|
2008-08-10 05:14:39 +02:00
|
|
|
* FileSortCallback
|
|
|
|
*
|
|
|
|
* Quick sort callback to sort file entries with the following order:
|
|
|
|
* .
|
|
|
|
* ..
|
|
|
|
* <dirs>
|
|
|
|
* <files>
|
|
|
|
***************************************************************************/
|
|
|
|
int FileSortCallback(const void *f1, const void *f2)
|
|
|
|
{
|
|
|
|
/* Special case for implicit directories */
|
2008-12-30 01:08:17 +01:00
|
|
|
if(((BROWSERENTRY *)f1)->filename[0] == '.' || ((BROWSERENTRY *)f2)->filename[0] == '.')
|
2008-08-10 05:14:39 +02:00
|
|
|
{
|
2008-12-30 01:08:17 +01:00
|
|
|
if(strcmp(((BROWSERENTRY *)f1)->filename, ".") == 0) { return -1; }
|
|
|
|
if(strcmp(((BROWSERENTRY *)f2)->filename, ".") == 0) { return 1; }
|
|
|
|
if(strcmp(((BROWSERENTRY *)f1)->filename, "..") == 0) { return -1; }
|
|
|
|
if(strcmp(((BROWSERENTRY *)f2)->filename, "..") == 0) { return 1; }
|
2008-08-10 05:14:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* If one is a file and one is a directory the directory is first. */
|
2008-12-30 01:08:17 +01:00
|
|
|
if(((BROWSERENTRY *)f1)->isdir && !(((BROWSERENTRY *)f2)->isdir)) return -1;
|
|
|
|
if(!(((BROWSERENTRY *)f1)->isdir) && ((BROWSERENTRY *)f2)->isdir) return 1;
|
2008-08-10 05:14:39 +02:00
|
|
|
|
2018-06-06 16:10:11 +02:00
|
|
|
return strcasecmp(((BROWSERENTRY *)f1)->filename, ((BROWSERENTRY *)f2)->filename);
|
2008-08-10 05:14:39 +02:00
|
|
|
}
|
|
|
|
|
2008-10-05 23:56:18 +02:00
|
|
|
/****************************************************************************
|
|
|
|
* IsValidROM
|
|
|
|
*
|
|
|
|
* Checks if the specified file is a valid ROM
|
|
|
|
* For now we will just check the file extension and file size
|
|
|
|
* If the file is a zip, we will check the file extension / file size of the
|
|
|
|
* first file inside
|
|
|
|
***************************************************************************/
|
2009-10-02 00:35:12 +02:00
|
|
|
static bool IsValidROM()
|
2008-10-05 23:56:18 +02:00
|
|
|
{
|
2008-12-30 01:08:17 +01:00
|
|
|
if (strlen(browserList[browser.selIndex].filename) > 4)
|
2008-10-05 23:56:18 +02:00
|
|
|
{
|
2008-12-30 01:08:17 +01:00
|
|
|
char * p = strrchr(browserList[browser.selIndex].filename, '.');
|
2008-10-05 23:56:18 +02:00
|
|
|
|
|
|
|
if (p != NULL)
|
|
|
|
{
|
2010-06-23 01:31:14 +02:00
|
|
|
char * zippedFilename = NULL;
|
|
|
|
|
2018-06-06 16:10:11 +02:00
|
|
|
if(strcasecmp(p, ".zip") == 0 && !inSz)
|
2008-10-05 23:56:18 +02:00
|
|
|
{
|
|
|
|
// we need to check the file extension of the first file in the archive
|
2010-06-23 01:31:14 +02:00
|
|
|
zippedFilename = GetFirstZipFilename ();
|
2008-10-05 23:56:18 +02:00
|
|
|
|
2010-06-23 01:31:14 +02:00
|
|
|
if(zippedFilename && strlen(zippedFilename) > 4)
|
2008-10-05 23:56:18 +02:00
|
|
|
p = strrchr(zippedFilename, '.');
|
|
|
|
else
|
|
|
|
p = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(p != NULL)
|
|
|
|
{
|
2018-06-06 16:10:11 +02:00
|
|
|
if (strcasecmp(p, ".smc") == 0 ||
|
|
|
|
strcasecmp(p, ".fig") == 0 ||
|
|
|
|
strcasecmp(p, ".sfc") == 0 ||
|
|
|
|
strcasecmp(p, ".swc") == 0)
|
2008-10-05 23:56:18 +02:00
|
|
|
{
|
2010-06-23 01:31:14 +02:00
|
|
|
if(zippedFilename) free(zippedFilename);
|
2008-10-05 23:56:18 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2010-06-23 01:31:14 +02:00
|
|
|
if(zippedFilename) free(zippedFilename);
|
2008-10-05 23:56:18 +02:00
|
|
|
}
|
|
|
|
}
|
2009-03-11 18:28:37 +01:00
|
|
|
ErrorPrompt("Unknown file type!");
|
2008-10-05 23:56:18 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2008-10-14 11:21:34 +02:00
|
|
|
/****************************************************************************
|
|
|
|
* IsSz
|
|
|
|
*
|
|
|
|
* Checks if the specified file is a 7z
|
|
|
|
***************************************************************************/
|
|
|
|
bool IsSz()
|
|
|
|
{
|
2008-12-30 01:08:17 +01:00
|
|
|
if (strlen(browserList[browser.selIndex].filename) > 4)
|
2008-10-14 11:21:34 +02:00
|
|
|
{
|
2008-12-30 01:08:17 +01:00
|
|
|
char * p = strrchr(browserList[browser.selIndex].filename, '.');
|
2008-10-14 11:21:34 +02:00
|
|
|
|
|
|
|
if (p != NULL)
|
2018-06-06 16:10:11 +02:00
|
|
|
if(strcasecmp(p, ".7z") == 0)
|
2008-10-14 11:21:34 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2008-08-07 05:25:02 +02:00
|
|
|
/****************************************************************************
|
|
|
|
* StripExt
|
|
|
|
*
|
|
|
|
* Strips an extension from a filename
|
2008-09-12 07:28:40 +02:00
|
|
|
***************************************************************************/
|
2008-08-07 05:25:02 +02:00
|
|
|
void StripExt(char* returnstring, char * inputstring)
|
|
|
|
{
|
|
|
|
char* loc_dot;
|
2008-08-07 07:19:17 +02:00
|
|
|
|
2011-03-20 18:17:51 +01:00
|
|
|
snprintf (returnstring, MAXJOLIET, "%s", inputstring);
|
2009-03-11 18:28:37 +01:00
|
|
|
|
|
|
|
if(inputstring == NULL || strlen(inputstring) < 4)
|
|
|
|
return;
|
|
|
|
|
2008-08-07 05:25:02 +02:00
|
|
|
loc_dot = strrchr(returnstring,'.');
|
|
|
|
if (loc_dot != NULL)
|
2008-09-27 10:36:22 +02:00
|
|
|
*loc_dot = 0; // strip file extension
|
2008-08-07 05:25:02 +02:00
|
|
|
}
|
2008-08-06 03:09:59 +02:00
|
|
|
|
2009-03-28 20:03:35 +01:00
|
|
|
/****************************************************************************
|
|
|
|
* BrowserLoadSz
|
|
|
|
*
|
|
|
|
* Opens the selected 7z file, and parses a listing of the files within
|
|
|
|
***************************************************************************/
|
2009-10-02 00:35:12 +02:00
|
|
|
int BrowserLoadSz()
|
2008-08-06 03:09:59 +02:00
|
|
|
{
|
2014-10-24 04:47:59 +02:00
|
|
|
memset(szpath, 0, MAXPATHLEN);
|
|
|
|
strncpy(szpath, browser.dir, strlen(browser.dir) - 1);
|
|
|
|
|
|
|
|
strncpy(szname, strrchr(szpath, '/') + 1, strrchr(szpath, '.') - strrchr(szpath, '/'));
|
|
|
|
*strrchr(szname, '.') = '\0';
|
2008-08-07 05:25:02 +02:00
|
|
|
|
2009-10-02 00:35:12 +02:00
|
|
|
int szfiles = SzParse(szpath);
|
2009-03-11 18:28:37 +01:00
|
|
|
if(szfiles)
|
|
|
|
{
|
|
|
|
browser.numEntries = szfiles;
|
|
|
|
inSz = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ErrorPrompt("Error opening archive!");
|
2008-10-14 11:21:34 +02:00
|
|
|
|
2009-03-11 18:28:37 +01:00
|
|
|
return szfiles;
|
|
|
|
}
|
2008-12-30 01:08:17 +01:00
|
|
|
|
2018-11-12 00:57:16 +01:00
|
|
|
static bool bsxBiosLoadFailed;
|
|
|
|
|
2010-01-27 23:08:56 +01:00
|
|
|
int WiiFileLoader()
|
|
|
|
{
|
2018-08-01 20:44:21 +02:00
|
|
|
size_t size;
|
2010-01-27 23:08:56 +01:00
|
|
|
char filepath[1024];
|
2010-03-16 00:18:18 +01:00
|
|
|
|
2010-01-27 23:08:56 +01:00
|
|
|
memset(Memory.NSRTHeader, 0, sizeof(Memory.NSRTHeader));
|
|
|
|
Memory.HeaderCount = 0;
|
2010-03-16 00:18:18 +01:00
|
|
|
loadingFile = true;
|
|
|
|
|
2010-01-27 23:08:56 +01:00
|
|
|
if(!inSz)
|
|
|
|
{
|
|
|
|
if(!MakeFilePath(filepath, FILE_ROM))
|
|
|
|
return 0;
|
|
|
|
|
2018-08-28 22:47:59 +02:00
|
|
|
size = LoadFile ((char *)Memory.ROM, filepath, 0, Memory.MAX_ROM_SIZE, NOTSILENT);
|
2010-01-27 23:08:56 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
size = LoadSzFile(szpath, (unsigned char *)Memory.ROM);
|
|
|
|
|
|
|
|
if(size <= 0)
|
|
|
|
{
|
|
|
|
browser.selIndex = 0;
|
|
|
|
BrowserChangeFolder();
|
|
|
|
}
|
|
|
|
}
|
2010-03-16 00:18:18 +01:00
|
|
|
loadingFile = false;
|
2010-01-27 23:08:56 +01:00
|
|
|
|
|
|
|
if(size <= 0)
|
|
|
|
return 0;
|
|
|
|
|
2018-11-12 00:57:16 +01:00
|
|
|
SNESROMSize = Memory.HeaderRemove(size, Memory.ROM);
|
|
|
|
bsxBiosLoadFailed = false;
|
|
|
|
|
|
|
|
if(isBSX()) {
|
|
|
|
sprintf (filepath, "%s%s/BS-X.bin", pathPrefix[GCSettings.LoadMethod], APPFOLDER);
|
|
|
|
if(LoadFile ((char *)Memory.BIOSROM, filepath, 0, 0x100000, SILENT) == 0) {
|
|
|
|
bsxBiosLoadFailed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-27 23:08:56 +01:00
|
|
|
return SNESROMSize;
|
|
|
|
}
|
|
|
|
|
2009-03-28 20:03:35 +01:00
|
|
|
/****************************************************************************
|
|
|
|
* BrowserLoadFile
|
|
|
|
*
|
|
|
|
* Loads the selected ROM
|
|
|
|
***************************************************************************/
|
2009-10-02 00:35:12 +02:00
|
|
|
int BrowserLoadFile()
|
2009-03-11 18:28:37 +01:00
|
|
|
{
|
|
|
|
int loaded = 0;
|
2009-10-02 00:35:12 +02:00
|
|
|
int device;
|
2010-01-27 23:08:56 +01:00
|
|
|
|
2009-10-02 00:35:12 +02:00
|
|
|
if(!FindDevice(browser.dir, &device))
|
|
|
|
return 0;
|
2008-10-14 11:21:34 +02:00
|
|
|
|
2009-03-11 18:28:37 +01:00
|
|
|
// check that this is a valid ROM
|
2009-10-02 00:35:12 +02:00
|
|
|
if(!IsValidROM())
|
2009-03-11 18:28:37 +01:00
|
|
|
goto done;
|
2008-08-07 05:25:02 +02:00
|
|
|
|
2010-04-10 08:33:28 +02:00
|
|
|
// store the filename (w/o ext) - used for sram/freeze naming
|
|
|
|
StripExt(Memory.ROMFilename, browserList[browser.selIndex].filename);
|
2014-10-24 04:47:59 +02:00
|
|
|
snprintf(GCSettings.LastFileLoaded, MAXPATHLEN, "%s", browserList[browser.selIndex].filename);
|
2018-01-17 15:23:10 +01:00
|
|
|
strncpy(Memory.ROMFilePath, browser.dir, PATH_MAX);
|
2010-04-10 08:33:28 +02:00
|
|
|
|
2009-03-11 18:28:37 +01:00
|
|
|
SNESROMSize = 0;
|
2009-07-09 00:28:26 +02:00
|
|
|
S9xDeleteCheats();
|
2010-01-27 23:08:56 +01:00
|
|
|
Memory.LoadROM("ROM");
|
2009-03-11 18:28:37 +01:00
|
|
|
|
2018-11-12 00:57:16 +01:00
|
|
|
if (SNESROMSize == 0)
|
2009-03-11 18:28:37 +01:00
|
|
|
{
|
2010-03-18 00:20:08 +01:00
|
|
|
ErrorPrompt("Error loading game!");
|
2009-03-11 18:28:37 +01:00
|
|
|
}
|
2018-11-12 00:57:16 +01:00
|
|
|
else if(bsxBiosLoadFailed) {
|
|
|
|
ErrorPrompt("BS-X BIOS file not found!");
|
|
|
|
}
|
2009-03-11 18:28:37 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
// load SRAM or snapshot
|
|
|
|
if (GCSettings.AutoLoad == 1)
|
2009-10-02 00:35:12 +02:00
|
|
|
LoadSRAMAuto(SILENT);
|
2009-03-11 18:28:37 +01:00
|
|
|
else if (GCSettings.AutoLoad == 2)
|
2009-11-25 07:35:14 +01:00
|
|
|
LoadSnapshotAuto(SILENT);
|
2009-03-11 18:28:37 +01:00
|
|
|
|
|
|
|
ResetBrowser();
|
|
|
|
loaded = 1;
|
|
|
|
}
|
|
|
|
done:
|
|
|
|
CancelAction();
|
|
|
|
return loaded;
|
|
|
|
}
|
|
|
|
|
2009-03-28 20:03:35 +01:00
|
|
|
/****************************************************************************
|
|
|
|
* BrowserChangeFolder
|
|
|
|
*
|
|
|
|
* Update current directory and set new entry list if directory has changed
|
|
|
|
***************************************************************************/
|
2009-10-02 00:35:12 +02:00
|
|
|
int BrowserChangeFolder()
|
2009-03-11 18:28:37 +01:00
|
|
|
{
|
2009-10-02 00:35:12 +02:00
|
|
|
int device = 0;
|
|
|
|
FindDevice(browser.dir, &device);
|
|
|
|
|
2009-03-11 18:28:37 +01:00
|
|
|
if(inSz && browser.selIndex == 0) // inside a 7z, requesting to leave
|
|
|
|
{
|
|
|
|
inSz = false;
|
|
|
|
SzClose();
|
|
|
|
}
|
|
|
|
|
2014-10-24 04:47:59 +02:00
|
|
|
if(!UpdateDirName())
|
2009-03-11 18:28:37 +01:00
|
|
|
return -1;
|
|
|
|
|
2014-10-24 04:47:59 +02:00
|
|
|
HaltParseThread();
|
2011-03-20 18:17:51 +01:00
|
|
|
CleanupPath(browser.dir);
|
2014-10-24 04:47:59 +02:00
|
|
|
ResetBrowser();
|
2009-06-12 09:47:42 +02:00
|
|
|
|
2009-10-02 00:35:12 +02:00
|
|
|
if(browser.dir[0] != 0)
|
2014-10-24 04:47:59 +02:00
|
|
|
{
|
|
|
|
if(strstr(browser.dir, ".7z"))
|
|
|
|
{
|
|
|
|
BrowserLoadSz();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ParseDirectory(true, true);
|
|
|
|
}
|
|
|
|
FindAndSelectLastLoadedFile();
|
|
|
|
}
|
2009-03-11 18:28:37 +01:00
|
|
|
|
2009-10-02 00:35:12 +02:00
|
|
|
if(browser.numEntries == 0)
|
|
|
|
{
|
|
|
|
browser.dir[0] = 0;
|
|
|
|
int i=0;
|
|
|
|
|
2010-04-02 23:02:16 +02:00
|
|
|
#ifdef HW_RVL
|
2009-10-02 00:35:12 +02:00
|
|
|
AddBrowserEntry();
|
|
|
|
sprintf(browserList[i].filename, "sd:/");
|
|
|
|
sprintf(browserList[i].displayname, "SD Card");
|
|
|
|
browserList[i].length = 0;
|
|
|
|
browserList[i].isdir = 1;
|
|
|
|
browserList[i].icon = ICON_SD;
|
|
|
|
i++;
|
|
|
|
|
|
|
|
AddBrowserEntry();
|
|
|
|
sprintf(browserList[i].filename, "usb:/");
|
|
|
|
sprintf(browserList[i].displayname, "USB Mass Storage");
|
|
|
|
browserList[i].length = 0;
|
|
|
|
browserList[i].isdir = 1;
|
|
|
|
browserList[i].icon = ICON_USB;
|
|
|
|
i++;
|
2010-04-02 23:02:16 +02:00
|
|
|
#else
|
|
|
|
AddBrowserEntry();
|
|
|
|
sprintf(browserList[i].filename, "carda:/");
|
|
|
|
sprintf(browserList[i].displayname, "SD Gecko Slot A");
|
|
|
|
browserList[i].length = 0;
|
|
|
|
browserList[i].isdir = 1;
|
|
|
|
browserList[i].icon = ICON_SD;
|
|
|
|
i++;
|
|
|
|
|
|
|
|
AddBrowserEntry();
|
|
|
|
sprintf(browserList[i].filename, "cardb:/");
|
|
|
|
sprintf(browserList[i].displayname, "SD Gecko Slot B");
|
|
|
|
browserList[i].length = 0;
|
|
|
|
browserList[i].isdir = 1;
|
|
|
|
browserList[i].icon = ICON_SD;
|
2019-12-24 06:30:59 +01:00
|
|
|
i++;
|
|
|
|
|
|
|
|
AddBrowserEntry();
|
|
|
|
sprintf(browserList[i].filename, "port2:/");
|
|
|
|
sprintf(browserList[i].displayname, "SD in SP2");
|
|
|
|
browserList[i].length = 0;
|
|
|
|
browserList[i].isdir = 1;
|
|
|
|
browserList[i].icon = ICON_SD;
|
2010-04-02 23:02:16 +02:00
|
|
|
i++;
|
2009-10-02 00:35:12 +02:00
|
|
|
#endif
|
2011-02-03 04:09:49 +01:00
|
|
|
AddBrowserEntry();
|
|
|
|
sprintf(browserList[i].filename, "smb:/");
|
|
|
|
sprintf(browserList[i].displayname, "Network Share");
|
|
|
|
browserList[i].length = 0;
|
|
|
|
browserList[i].isdir = 1;
|
|
|
|
browserList[i].icon = ICON_SMB;
|
|
|
|
i++;
|
|
|
|
|
2009-10-02 00:35:12 +02:00
|
|
|
AddBrowserEntry();
|
|
|
|
sprintf(browserList[i].filename, "dvd:/");
|
|
|
|
sprintf(browserList[i].displayname, "Data DVD");
|
|
|
|
browserList[i].length = 0;
|
|
|
|
browserList[i].isdir = 1;
|
|
|
|
browserList[i].icon = ICON_DVD;
|
|
|
|
i++;
|
|
|
|
|
|
|
|
browser.numEntries += i;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(browser.dir[0] == 0)
|
2009-03-11 18:28:37 +01:00
|
|
|
{
|
2009-10-02 00:35:12 +02:00
|
|
|
GCSettings.LoadFolder[0] = 0;
|
|
|
|
GCSettings.LoadMethod = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char * path = StripDevice(browser.dir);
|
|
|
|
if(path != NULL)
|
|
|
|
strcpy(GCSettings.LoadFolder, path);
|
|
|
|
FindDevice(browser.dir, &GCSettings.LoadMethod);
|
2009-03-11 18:28:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return browser.numEntries;
|
2008-08-06 03:09:59 +02:00
|
|
|
}
|
|
|
|
|
2008-08-07 05:25:02 +02:00
|
|
|
/****************************************************************************
|
2008-12-18 19:36:30 +01:00
|
|
|
* OpenROM
|
2009-03-11 18:28:37 +01:00
|
|
|
* Displays a list of ROMS on load device
|
2008-09-12 07:28:40 +02:00
|
|
|
***************************************************************************/
|
2008-08-06 03:09:59 +02:00
|
|
|
int
|
2009-03-11 18:28:37 +01:00
|
|
|
OpenGameList ()
|
2008-08-06 03:09:59 +02:00
|
|
|
{
|
2009-10-02 00:35:12 +02:00
|
|
|
int device = GCSettings.LoadMethod;
|
2009-03-11 18:28:37 +01:00
|
|
|
|
2009-10-06 08:37:53 +02:00
|
|
|
if(device == DEVICE_AUTO && strlen(GCSettings.LoadFolder) > 0)
|
2009-10-02 00:35:12 +02:00
|
|
|
device = autoLoadMethod();
|
2008-08-06 04:31:44 +02:00
|
|
|
|
2009-03-23 00:16:25 +01:00
|
|
|
// change current dir to roms directory
|
2009-10-02 00:35:12 +02:00
|
|
|
if(device > 0)
|
2009-10-02 05:09:36 +02:00
|
|
|
sprintf(browser.dir, "%s%s/", pathPrefix[device], GCSettings.LoadFolder);
|
2009-10-02 00:35:12 +02:00
|
|
|
else
|
|
|
|
browser.dir[0] = 0;
|
|
|
|
|
|
|
|
BrowserChangeFolder();
|
2009-03-11 18:28:37 +01:00
|
|
|
return browser.numEntries;
|
2008-08-06 04:31:44 +02:00
|
|
|
}
|
2018-08-30 18:11:24 +02:00
|
|
|
|
|
|
|
bool AutoloadGame(char* filepath, char* filename) {
|
|
|
|
ResetBrowser();
|
|
|
|
|
|
|
|
selectLoadedFile = 1;
|
|
|
|
std::string dir(filepath);
|
|
|
|
dir.assign(&dir[dir.find_last_of(":") + 2]);
|
|
|
|
strncpy(GCSettings.LoadFolder, dir.c_str(), sizeof(GCSettings.LoadFolder));
|
|
|
|
OpenGameList();
|
|
|
|
|
|
|
|
for(int i = 0; i < browser.numEntries; i++) {
|
|
|
|
// Skip it
|
|
|
|
if (strcmp(browserList[i].filename, ".") == 0 || strcmp(browserList[i].filename, "..") == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if(strcasestr(browserList[i].filename, filename) != NULL) {
|
|
|
|
browser.selIndex = i;
|
|
|
|
if(IsSz()) {
|
|
|
|
BrowserLoadSz();
|
|
|
|
browser.selIndex = 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(BrowserLoadFile() > 0) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|