fix GC DVD support

This commit is contained in:
dborth 2008-08-16 00:02:08 +00:00
parent 1a366b7a1f
commit d253f9f590
9 changed files with 443 additions and 277 deletions

View File

@ -11,7 +11,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dvd.h>
#include "menudraw.h"
#include "snes9xGx.h"
@ -20,6 +19,10 @@
extern int offset;
extern int selection;
extern FILEENTRIES filelist[MAXFILES];
extern int maxfiles;
u64 dvddir = 0;
u64 dvdrootdir = 0;
int dvddirlength = 0;
/** DVD I/O Address base **/
volatile unsigned long *dvd = (volatile unsigned long *) 0xCC006000;
@ -105,8 +108,6 @@ dvd_read (void *dst, unsigned int len, u64 offset)
/** Minimal Primary Volume Descriptor **/
#define PVDROOT 0x9c
static int IsJoliet = 0;
u64 rootdir = 0;
int rootdirlength = 0;
/**
* Primary Volume Descriptor
@ -120,7 +121,7 @@ getpvd ()
int sector = 16;
u32 rootdir32;
rootdir = rootdirlength = 0;
dvddir = dvddirlength = 0;
IsJoliet = -1;
/** Look for Joliet PVD first **/
@ -131,16 +132,16 @@ getpvd ()
if (memcmp (&dvdbuffer, "\2CD001\1", 8) == 0)
{
memcpy(&rootdir32, &dvdbuffer[PVDROOT + EXTENT], 4);
rootdir = (u64)rootdir32;
rootdir <<= 11;
memcpy (&rootdirlength, &dvdbuffer[PVDROOT + FILE_LENGTH], 4);
dvddir = (u64)rootdir32;
dvddir <<= 11;
dvdrootdir = dvddir;
memcpy (&dvddirlength, &dvdbuffer[PVDROOT + FILE_LENGTH], 4);
IsJoliet = 1;
break;
}
}
else
return 0; /*** Can't read sector! ***/
sector++;
}
@ -157,22 +158,41 @@ getpvd ()
if (memcmp (&dvdbuffer, "\1CD001\1", 8) == 0)
{
memcpy (&rootdir32, &dvdbuffer[PVDROOT + EXTENT], 4);
rootdir = (u64)rootdir32;
rootdir <<= 11;
memcpy (&rootdirlength, &dvdbuffer[PVDROOT + FILE_LENGTH], 4);
dvddir = (u64)rootdir32;
dvddir <<= 11;
dvdrootdir = dvddir;
memcpy (&dvddirlength, &dvdbuffer[PVDROOT + FILE_LENGTH], 4);
IsJoliet = 0;
break;
}
}
else
return 0; /*** Can't read sector! ***/
sector++;
}
return (IsJoliet == 0);
}
return (IsJoliet == 0);
/****************************************************************************
* TestDVD()
*
* Tests if a ISO9660 DVD is inserted and available
****************************************************************************/
bool TestDVD()
{
// DVD not available on Wii - disable
#ifdef HW_RVL
return false;
#endif
if (!getpvd())
{
DVD_Mount();
if (!getpvd())
return false;
}
return true;
}
/**
@ -222,7 +242,6 @@ getentry (int entrycount)
strcpy (fname, filename);
else
{ /*** The more tortuous unicode joliet entries ***/
for (j = 0; j < (*filenamelength >> 1); j++)
{
fname[j] = filename[j * 2 + 1];
@ -237,14 +256,22 @@ getentry (int entrycount)
fname[0] = filename[0];
}
if (strlen (fname) == 0)
strcpy (fname, "ROOT");
if (strlen (fname) == 0) // root entry
{
fname[0] = 0; // we'll skip it by setting the filename to 0 length
}
else
{
if (fname[0] == 1)
strcpy (fname, "..");
{
if(dvddir == dvdrootdir) // at root already, don't show ..
fname[0] = 0;
else
{ /*
strcpy (fname, "..");
}
else
{
/*
* Move *filenamelength to t,
* Only to stop gcc warning for noobs :)
*/
@ -252,7 +279,6 @@ getentry (int entrycount)
fname[t] = 0;
}
}
/** Rockridge Check **/
rr = strstr (fname, ";");
if (rr != NULL)
@ -262,35 +288,29 @@ getentry (int entrycount)
fname[MAXDISPLAY] = 0;
strcpy (filelist[entrycount].displayname, fname);
memcpy (&offset32,
&dvdbuffer[diroffset + EXTENT], 4);
memcpy (&offset32, &dvdbuffer[diroffset + EXTENT], 4);
filelist[entrycount].offset = (u64)offset32;
memcpy (&filelist[entrycount].length,
&dvdbuffer[diroffset + FILE_LENGTH], 4);
memcpy (&filelist[entrycount].flags,
&dvdbuffer[diroffset + FILE_FLAGS], 1);
memcpy (&filelist[entrycount].length, &dvdbuffer[diroffset + FILE_LENGTH], 4);
memcpy (&filelist[entrycount].flags, &dvdbuffer[diroffset + FILE_FLAGS], 1);
filelist[entrycount].offset <<= 11;
filelist[entrycount].flags = filelist[entrycount].flags & 2;
/*** Prepare for next entry ***/
diroffset += dvdbuffer[diroffset];
return 1;
}
}
return 0;
}
/**
* parseDVDdirectory
*
* This function will parse the directory tree.
* It relies on rootdir and rootdirlength being pre-populated by a call to
* It relies on dvddir and dvddirlength being pre-populated by a call to
* getpvd, a previous parse or a menu selection.
*
* The return value is number of files collected, or 0 on failure.
@ -307,11 +327,11 @@ ParseDVDdirectory ()
// initialize selection
selection = offset = 0;
pdoffset = rdoffset = rootdir;
pdlength = rootdirlength;
pdoffset = rdoffset = dvddir;
pdlength = dvddirlength;
filecount = 0;
/*** Clear any existing values ***/
// Clear any existing values
memset (&filelist, 0, sizeof (FILEENTRIES) * MAXFILES);
/*** Get as many files as possible ***/
@ -324,7 +344,7 @@ ParseDVDdirectory ()
while (getentry (filecount))
{
if (filecount < MAXFILES)
if(strlen(filelist[filecount].filename) > 0 && filecount < MAXFILES)
filecount++;
}
@ -332,14 +352,81 @@ ParseDVDdirectory ()
pdoffset = rdoffset + len;
}
// Sort the file list
qsort(filelist, filecount, sizeof(FILEENTRIES), FileSortCallback);
return filecount;
}
/**
* DirectorySearch
*
* Searches for the directory name specified within the current directory
* Returns the index of the directory, or 0 if not found
*/
int DirectorySearch(char dir[512])
{
for (int i = 0; i < maxfiles; i++ )
if (strcmp(filelist[i].filename, dir) == 0)
return i;
return 0;
}
/**
* SwitchDVDFolder
*
* Function to switch to the directory snes9x/roms, if it exists
* Also loads the folder contents
* Recursively searches for any directory path 'dir' specified
*/
bool SwitchDVDFolder(char * dir, int maxDepth)
{
if(maxDepth > 8) // only search to a max depth of 8 levels
return false;
bool lastdir = false;
char * nextdir = 0;
unsigned int t = strcspn(dir, "/");
if(t != strlen(dir))
nextdir = dir + t + 1; // next directory path to find
else
lastdir = true;
dir[t] = 0;
int dirindex = DirectorySearch(dir);
if(dirindex)
{
dvddir = filelist[dirindex].offset;
dvddirlength = filelist[dirindex].length;
maxfiles = ParseDVDdirectory();
if(lastdir)
return true;
else
return SwitchDVDFolder(nextdir, maxDepth++);
}
return false;
}
bool SwitchDVDFolder(char * dir)
{
// strip off leading/trailing slashes on the directory path
// we don't want to screw up our recursion!
if(dir[0] == '/')
dir = dir + 1;
if(dir[strlen(dir)-1] == '/')
dir[strlen(dir)-1] = 0;
return SwitchDVDFolder(dir, 0);
}
/****************************************************************************
* LoadDVDFile
* This function will load a file from DVD, in BIN, SMD or ZIP format.
* The values for offset and length are inherited from rootdir and
* rootdirlength.
* The values for offset and length are inherited from dvddir and
* dvddirlength.
*
* The buffer parameter should re-use the initial ROM buffer.
****************************************************************************/
@ -354,17 +441,15 @@ LoadDVDFile (unsigned char *buffer)
char readbuffer[2048];
// How many 2k blocks to read
blocks = rootdirlength / 2048;
blocks = dvddirlength / 2048;
offset = 0;
discoffset = rootdir;
discoffset = dvddir;
ShowAction ((char*) "Loading...");
dvd_read (readbuffer, 2048, discoffset);
if (!IsZipFile (readbuffer))
{
for (i = 0; i < blocks; i++)
{
dvd_read (readbuffer, 2048, discoffset);
memcpy (buffer + offset, readbuffer, 2048);
@ -373,21 +458,18 @@ LoadDVDFile (unsigned char *buffer)
}
/*** And final cleanup ***/
if (rootdirlength % 2048)
if (dvddirlength % 2048)
{
i = rootdirlength % 2048;
i = dvddirlength % 2048;
dvd_read (readbuffer, 2048, discoffset);
memcpy (buffer + offset, readbuffer, i);
}
}
else
{
return UnZipBuffer (buffer, discoffset, 1, NULL); // unzip from dvd
}
return rootdirlength;
return dvddirlength;
}
/****************************************************************************
@ -401,7 +483,6 @@ LoadDVDFile (unsigned char *buffer)
****************************************************************************/
void uselessinquiry ()
{
dvd[0] = 0;
dvd[1] = 0;
dvd[2] = 0x12000000;

View File

@ -10,12 +10,11 @@
#ifndef _NGCDVD_
#define _NGCDVD_
extern u64 rootdir;
extern int rootdirlength;
int getpvd ();
int ParseDVDdirectory ();
int LoadDVDFile (unsigned char *buffer);
bool TestDVD();
int dvd_read (void *dst, unsigned int len, u64 offset);
bool SwitchDVDFolder(char dir[]);
#endif

View File

@ -123,6 +123,9 @@ ParseFATdirectory(int method)
// initialize selection
selection = offset = 0;
// Clear any existing values
memset (&filelist, 0, sizeof (FILEENTRIES) * MAXFILES);
// open the directory
fatdir = diropen(currentdir);
if (fatdir == NULL)

View File

@ -38,7 +38,11 @@ char currentdir[MAXPATHLEN];
int maxfiles;
extern int screenheight;
extern unsigned long ARAM_ROMSIZE;
int havedir = 0;
int havedir = -1;
extern u64 dvddir;
extern int dvddirlength;
int hasloaded = 0;
// Global file entry table
@ -68,7 +72,7 @@ int autoLoadMethod()
return METHOD_SD;
else if(ChangeFATInterface(METHOD_USB, SILENT))
return METHOD_USB;
else if(false) // FIX ME - WARNING - MOUNTING DVD in Wii mode hangs
else if(TestDVD())
return METHOD_DVD;
else if(ConnectShare (SILENT))
return METHOD_SMB;
@ -108,12 +112,20 @@ int autoSaveMethod()
/***************************************************************************
* Update curent directory name
***************************************************************************/
int UpdateDirName()
int UpdateDirName(int method)
{
int size=0;
char *test;
char temp[1024];
// update DVD directory (does not utilize 'currentdir')
if(method == METHOD_DVD)
{
dvddir = filelist[selection].offset;
dvddirlength = filelist[selection].length;
return 1;
}
/* current directory doesn't change */
if (strcmp(filelist[selection].filename,".") == 0)
{
@ -257,7 +269,7 @@ FileSelector (int method)
if (filelist[selection].flags) // This is directory
{
/* update current directory and set new entry list if directory has changed */
int status = UpdateDirName();
int status = UpdateDirName(method);
if (status == 1) // ok, open directory
{
switch (method)
@ -303,6 +315,8 @@ FileSelector (int method)
break;
case METHOD_DVD:
dvddir = filelist[selection].offset;
dvddirlength = filelist[selection].length;
ARAM_ROMSIZE = LoadDVDFile (Memory.ROM);
break;
@ -336,7 +350,6 @@ FileSelector (int method)
#endif
)
VIDEO_WaitVSync();
//if ((strcmp(filelist[1].filename,"..") == 0) && (strlen (filelist[0].filename) != 0))
if ( strcmp(filelist[0].filename,"..") == 0 )
{
selection = 0;
@ -441,26 +454,28 @@ OpenDVD (int method)
if (!getpvd())
{
ShowAction((char*) "Loading DVD...");
DVD_Mount(); /* mount the DVD unit again */
havedir = 0; /* this may be a new DVD: content need to be parsed again */
DVD_Mount(); // mount the DVD unit again
if (!getpvd())
return 0; /* no correct ISO9660 DVD */
return 0; // not a ISO9660 DVD
}
if (havedir == 0)
{
maxfiles = ParseDVDdirectory();
maxfiles = ParseDVDdirectory(); // load root folder
// switch to rom folder
SwitchDVDFolder(GCSettings.LoadFolder);
if (maxfiles > 0)
{
return FileSelector (method);
havedir = 1;
}
}
else
return FileSelector (method);
{
// no entries found
WaitPrompt ((char *)"No Files Found!");
return 0;
}
}
/****************************************************************************
* OpenSMB

View File

@ -77,6 +77,11 @@ CardFileExists (char *filename, int slot)
****************************************************************************/
bool TestCard(int slot, bool silent)
{
// Memory Cards do not work in Wii mode - disable
#ifdef HW_RVL
return false;
#endif
/*** Initialize Card System ***/
memset (SysArea, 0, CARD_WORKAREA);
CARD_Init ("SNES", "00");
@ -112,58 +117,24 @@ bool TestCard(int slot, bool silent)
/****************************************************************************
* MountCard
*
* Mounts the memory card in the given slot. Error checking is done and
* workarounds implemented for when the mount fails.
* Mounts the memory card in the given slot.
* Returns the result of the last attempted CARD_Mount command.
****************************************************************************/
int MountCard(int cslot, bool silent)
{
int ret;
int tries;
int ret = -1;
int tries = 0;
EXI_ProbeReset();
*(unsigned long *) (0xcc006800) |= 1 << 13; // Disable Encryption
// Mount the card
ret = CARD_Mount (cslot, SysArea, NULL);
tries = 0;
while ( tries < 3 && ret == CARD_ERROR_IOERROR )
while ( tries < 10 && ret != 0)
{
EXI_ProbeReset ();
if (cslot == CARD_SLOTA)
WaitPrompt((char*) "Replug card in slot A!");
else
WaitPrompt((char*) "Replug card in slot B!");
ret = CARD_Mount (cslot, SysArea, NULL);
VIDEO_WaitVSync ();
tries++;
}
tries = 0;
while ( tries < 2 && ret == CARD_ERROR_NOCARD )
{
EXI_ProbeReset ();
if(!silent)
ShowAction ((char*) "Mounting card...");
CARD_Unmount (cslot);
usleep(500000); // wait half second
ret = CARD_Mount (cslot, SysArea, NULL);
tries++;
}
tries = 0;
while ( tries < 3 && ret == CARD_ERROR_UNLOCKED )
{
EXI_ProbeReset ();
if(!silent)
ShowAction ((char*) "Waiting for unlock...");
usleep(500000); // wait half second
ret = CARD_Probe(cslot);
tries++;
}
return ret;
}

View File

@ -140,24 +140,36 @@ PreferencesMenu ()
while (quit == 0)
{
// some load/save methods are not implemented - here's where we skip them
// they need to be skipped in the order they were enumerated in snes9xGX.h
#ifndef HW_RVL
// no USB ports on GameCube
#ifndef HW_RVL
if(GCSettings.LoadMethod == METHOD_USB)
GCSettings.LoadMethod++;
if(GCSettings.SaveMethod == METHOD_USB)
GCSettings.SaveMethod++;
#else
// Wii DVD access not implemented
#endif
// disable DVD access in Wii mode
#ifdef HW_RVL
if(GCSettings.LoadMethod == METHOD_DVD)
GCSettings.LoadMethod++;
#endif
if(GCSettings.SaveMethod == METHOD_DVD) // saving to DVD is impossible
// saving to DVD is impossible
if(GCSettings.SaveMethod == METHOD_DVD)
GCSettings.SaveMethod++;
#ifdef HW_RVL
// disable SMB in GC mode (stalls out)
#ifndef HW_RVL
if(GCSettings.LoadMethod == METHOD_SMB)
GCSettings.LoadMethod++;
if(GCSettings.SaveMethod == METHOD_SMB)
GCSettings.SaveMethod++;
#endif
// disable MC saving in Wii mode - does not work for some reason!
#ifdef HW_RVL
if(GCSettings.SaveMethod == METHOD_MC_SLOTA)
GCSettings.SaveMethod++;
if(GCSettings.SaveMethod == METHOD_MC_SLOTB)

View File

@ -25,6 +25,8 @@
#include "smbop.h"
#include "filesel.h"
#include "mxml.h"
extern unsigned char savebuffer[];
extern int currconfig[4];
@ -39,6 +41,82 @@ extern unsigned int ncpadmap[];
char prefscomment[2][32] = { {PREFSVERSTRING}, {"Preferences"} };
/****************************************************************************
* Prepare Preferences Data
*
* This sets up the save buffer for saving.
****************************************************************************/
void CreateXmlFile(char* filename)
{
mxml_node_t *xml;
mxml_node_t *data;
mxml_node_t *group;
xml = mxmlNewXML("1.0");
data = mxmlNewElement(xml, "screen");
//Create Some config value
mxmlElementSetAttr(data, "height","480");
mxmlElementSetAttr(data, "width","640");
//Lets do some sub items for funs
group = mxmlNewElement(data, "properties");
mxmlElementSetAttr(group, "username", "beardface");
mxmlElementSetAttr(group, "favorite_food", "dead babies");
/* now lets save the xml file to a file! */
FILE *fp;
fp = fopen(filename, "w");
mxmlSaveFile(xml, fp, MXML_NO_CALLBACK);
/*Time to clean up!*/
fclose(fp);
mxmlDelete(group);
mxmlDelete(data);
mxmlDelete(xml);
}
/****************************************************************************
* Prepare Preferences Data
*
* This sets up the save buffer for saving.
****************************************************************************/
void LoadXmlFile(char* filename)
{
FILE *fp;
mxml_node_t *tree;
mxml_node_t *data;
mxml_node_t *group;
/*Load our xml file! */
fp = fopen(filename, "r");
tree = mxmlLoadFile(NULL, fp, MXML_NO_CALLBACK);
fclose(fp);
/*Load and printf our values! */
/* As a note, its a good idea to normally check if node* is NULL */
data = mxmlFindElement(tree, tree, "screen", NULL, NULL, MXML_DESCEND);
printf("Loaded following values from xml file:\n");
printf(" Height: %s\n",mxmlElementGetAttr(data,"height"));
printf(" Width: %s\n",mxmlElementGetAttr(data,"width"));
group = mxmlFindElement(tree, tree, "properties", NULL, NULL, MXML_DESCEND);
printf(" %s's favorite food is %s\n",mxmlElementGetAttr(group, "username"), mxmlElementGetAttr(group, "favorite_food"));
/* Yay Done! Now lets be considerate programmers, and put memory back how
we found it before we started playing with it...*/
mxmlDelete(group);
mxmlDelete(data);
mxmlDelete(tree);
}
/****************************************************************************
* Prepare Preferences Data
*

View File

@ -85,11 +85,13 @@ bool InitializeNetwork(bool silent)
bool
ConnectShare (bool silent)
{
// Crashes system in GameCube mode - so disable for now
#ifdef HW_RVL // Wii mode
// Crashes or stalls system in GameCube mode - so disable
#ifndef HW_RVL
return false;
#endif
if(!networkInit)
networkInit = InitializeNetwork(silent);
#endif
if(networkInit)
{
@ -152,6 +154,9 @@ ParseSMBdirectory ()
// initialize selection
selection = offset = 0;
// Clear any existing values
memset (&filelist, 0, sizeof (FILEENTRIES) * MAXFILES);
if(strlen(currentdir) <= 1) // root
sprintf(searchpath, "*");
else

View File

@ -885,8 +885,10 @@ main ()
//fatInit(8192, false);
//fat_enable_readahead_all();
// Initialize DVD subsystem
// Initialize DVD subsystem (GameCube only)
#ifndef HW_RVL
DVD_Init ();
#endif
#ifdef FORCE_WII
isWii = TRUE;