/**************************************************************************** * DVD.CPP * * This module manages all dvd i/o etc. * There is also a simple ISO9660 parser included. ****************************************************************************/ #include #include #include #include #include #include #include #include "sz.h" #include "gcdvd.h" #ifdef HW_RVL #include "wiisd/vfat.h" /*Front SCARD*/ VFATFS vfs; FSDIRENTRY vfsfile; #endif /*** Simplified Directory Entry Record I only care about a couple of values ***/ #define RECLEN 0 #define EXTENT 6 #define FILE_LENGTH 14 #define FILE_FLAGS 25 #define FILENAME_LENGTH 32 #define FILENAME 33 #define PAGESIZE 11 #define FCEUDIR "fceu" #define ROMSDIR "roms" FILEENTRIES filelist[MAXFILES]; int maxfiles = 0; int offset = 0; int selection = 0; /*** DVD Read Buffer ***/ unsigned char readbuffer[2048] ATTRIBUTE_ALIGN(32); volatile long *dvd=(volatile long *)0xCC006000; extern void SendDriveCode( int model ); extern int font_height; extern bool isZipFile(); extern void writex(int x, int y, int sx, int sy, char *string, unsigned int selected); extern unsigned char *nesromptr; extern int IsXenoGCImage( char *buffer ); void GetSDInfo (); extern u8 ChosenSlot; /** true if we the emulator is running on a wii **/ extern bool isWii; extern int WiiSD_Available; u8 UseSDCARD = 0; u8 UseWiiSDCARD = 0; sd_file * filehandle = NULL; char rootSDdir[SDCARD_MAX_PATH_LEN]; char rootWiiSDdir[SDCARD_MAX_PATH_LEN]; int haveSDdir = 0; int haveWiiSDdir = 0; int sdslot = 0; /**************************************************************************** * DVD Lowlevel Functions * * These are here simply because the same functions in libogc are not * exposed to the user ****************************************************************************/ void dvd_inquiry() { dvd[0] = 0x2e; dvd[1] = 0; dvd[2] = 0x12000000; dvd[3] = 0; dvd[4] = 0x20; dvd[5] = 0x80000000; dvd[6] = 0x20; dvd[7] = 3; while( dvd[7] & 1 ); DCFlushRange((void *)0x80000000, 32); } void dvd_unlock() { dvd[0] |= 0x00000014; dvd[1] = 0x00000000; dvd[2] = 0xFF014D41; dvd[3] = 0x54534849; dvd[4] = 0x54410200; dvd[7] = 1; while ((dvd[0] & 0x14) == 0) { } dvd[0] |= 0x00000014; dvd[1] = 0x00000000; dvd[2] = 0xFF004456; dvd[3] = 0x442D4741; dvd[4] = 0x4D450300; dvd[7] = 1; while ((dvd[0] & 0x14) == 0) { } } void dvd_extension() { dvd[0] = 0x2E; dvd[1] = 0; dvd[2] = 0x55010000; dvd[3] = 0; dvd[4] = 0; dvd[5] = 0; dvd[6] = 0; dvd[7] = 1; // enable reading! while (dvd[7] & 1); } #define DEBUG_STOP_DRIVE 0 #define DEBUG_START_DRIVE 0x100 #define DEBUG_ACCEPT_COPY 0x4000 #define DEBUG_DISC_CHECK 0x8000 void dvd_motor_on_extra() { dvd[0] = 0x2e; dvd[1] = 0; dvd[2] = 0xfe110000 | DEBUG_START_DRIVE | DEBUG_ACCEPT_COPY | DEBUG_DISC_CHECK; dvd[3] = 0; dvd[4] = 0; dvd[5] = 0; dvd[6] = 0; dvd[7] = 1; while ( dvd[7] & 1 ); } void dvd_motor_off( ) { dvd[0] = 0x2e; dvd[1] = 0; dvd[2] = 0xe3000000; dvd[3] = 0; dvd[4] = 0; dvd[5] = 0; dvd[6] = 0; dvd[7] = 1; // Do immediate while (dvd[7] & 1); /*** PSO Stops blackscreen at reload ***/ dvd[0] = 0x14; dvd[1] = 0; } void dvd_setstatus() { dvd[0] = 0x2E; dvd[1] = 0; dvd[2] = 0xee060300; dvd[3] = 0; dvd[4] = 0; dvd[5] = 0; dvd[6] = 0; dvd[7] = 1; // enable reading! while (dvd[7] & 1); } unsigned int dvd_read_id(void *dst) { if ((((int)dst) & 0xC0000000) == 0x80000000) // cached? DCInvalidateRange((void *)dst, 0x20); dvd[0] = 0x2E; dvd[1] = 0; dvd[2] = 0xA8000040; dvd[3] = 0; dvd[4] = 0x20; dvd[5] = (unsigned long)dst; dvd[6] = 0x20; dvd[7] = 3; // enable reading! while (dvd[7] & 1); if (dvd[0] & 0x4) return 1; return 0; } unsigned int dvd_read(void *dst, unsigned int len, u64 offset) { unsigned char* buffer = (unsigned char*)(unsigned int)readbuffer; if (len > 2048) return 0; DCInvalidateRange((void *) buffer, len); // don't read past 8,543,666,176 (DVD9) if (offset < 0x57057C00 || (isWii == true && offset < 0x1FD3E0000LL)) { offset >>= 2; dvd[0] = 0x2E; dvd[1] = 0; dvd[2] = 0xA8000000; dvd[3] = (u32)offset; dvd[4] = len; dvd[5] = (unsigned long)buffer; dvd[6] = len; dvd[7] = 3; // enable reading! while (dvd[7] & 1); memcpy (dst, buffer, len); } else // Let's not read past end of DVD return 0; if (dvd[0] & 0x4) /* Ensure it has completed */ return 0; return 1; } void dvd_reset(void) { int i; *(unsigned long*)0xcc006004 = 2; unsigned long v = *(unsigned long*)0xcc003024; *(unsigned long*)0xcc003024 = (v &~4) | 1; for ( i = 0; i < 10000; i++ ); *(unsigned long*)0xcc003024 = v | 5; } /**************************************************************************** * ISO Parsing Functions ****************************************************************************/ #define PVDROOT 0x9c static int IsJoliet = 0; static u64 rootdir = 0; static int rootdirlength = 0; int IsPVD() { int sector = 16; u32 rootdir32; rootdir = rootdirlength = 0; IsJoliet = -1; /*** Read the ISO section looking for a valid Primary Volume Decriptor. Spec says first 8 characters are id ***/ // Look for Joliet PVD first while ( sector < 32 ) { int res = dvd_read( &readbuffer, 2048, (u64)sector << 11 ); if (res) { if ( memcmp( &readbuffer, "\2CD001\1", 8 ) == 0 ) { memcpy(&rootdir32, &readbuffer[PVDROOT + EXTENT], 4); rootdir = (u64)rootdir32; rootdir <<= 11; memcpy(&rootdirlength, &readbuffer[PVDROOT + FILE_LENGTH], 4); IsJoliet = 1; break; } } else return 0; sector++; } if (IsJoliet > 0) return 1; sector = 16; // Look for standard ISO9660 PVD while ( sector < 32 ) { int res = dvd_read( &readbuffer, 2048, (u64)sector << 11 ); if (res) { if ( memcmp( &readbuffer, "\1CD001\1", 8 ) == 0 ) { memcpy(&rootdir32, &readbuffer[PVDROOT + EXTENT], 4); rootdir = (u64)rootdir32; rootdir <<= 11; memcpy(&rootdirlength, &readbuffer[PVDROOT + FILE_LENGTH], 4); IsJoliet = 0; break; } } else return 0; sector++; } return (IsJoliet == 0); } /**************************************************************************** * getfiles * * Retrieve the current file directory entry ****************************************************************************/ static int diroffset = 0; int getfiles( int filecount ) { char fname[MAXJOLIET+1]; char *ptr; char *filename; char *filenamelength; char *rr; int j; u32 offset32; /*** Do some basic checks ***/ if ( filecount == MAXFILES ) return 0; if ( diroffset >= 2048 ) return 0; /*** Now decode this entry ***/ if ( readbuffer[diroffset] != 0 ) { ptr = (char *)&readbuffer[0]; ptr += diroffset; filename = ptr + FILENAME; filenamelength = ptr + FILENAME_LENGTH; /* Check for wrap round - illegal in ISO spec, * but certain crap writers do it! */ if ( diroffset + readbuffer[diroffset] > 2048 ) return 0; if ( *filenamelength ) { memset(&fname, 0, 128); /*** Return the values needed ***/ if (!IsJoliet) strcpy(fname, filename); else { for ( j = 0; j < ( *filenamelength >> 1 ); j++ ) { fname[j] = filename[j*2+1]; } fname[j] = 0; if ( strlen(fname) >= MAXJOLIET ) fname[MAXJOLIET] = 0; if ( strlen(fname) == 0 ) fname[0] = filename[0]; } if ( strlen(fname) == 0 ) strcpy(fname,"ROOT"); else { if ( fname[0] == 1 ) strcpy(fname,".."); else{ //fname[ *filenamelength ] = 0; /* * Move *filenamelength to t, * Only to stop gcc warning for noobs :) */ int t = *filenamelength; fname[t] = 0; } } /** Rockridge Check **/ /*** Remove any trailing ;1 from ISO name ***/ rr = strstr (fname, ";"); //if ( fname[ strlen(fname) - 2 ] == ';' ) if (rr != NULL) *rr = 0; //fname[ strlen(fname) - 2 ] = 0;*/ strcpy(filelist[filecount].filename, fname); memcpy(&offset32, &readbuffer[diroffset + EXTENT], 4); filelist[filecount].offset = (u64)offset32; memcpy(&filelist[filecount].length, &readbuffer[diroffset + FILE_LENGTH], 4); memcpy(&filelist[filecount].flags, &readbuffer[diroffset + FILE_FLAGS], 1); filelist[filecount].offset <<= 11; filelist[filecount].flags = filelist[filecount].flags & 2; /*** Prepare for next entry ***/ diroffset += readbuffer[diroffset]; return 1; } } return 0; } /**************************************************************************** * ParseDirectory * * Parse the isodirectory, returning the number of files found ****************************************************************************/ int parsedir() { int pdlength; u64 pdoffset; u64 rdoffset; int len = 0; int filecount = 0; pdoffset = rdoffset = rootdir; pdlength = rootdirlength; filecount = 0; /*** Clear any existing values ***/ memset(&filelist, 0, sizeof(FILEENTRIES) * MAXFILES); /*** Get as many files as possible ***/ while ( len < pdlength ) { if (dvd_read (&readbuffer, 2048, pdoffset) == 0) return 0; diroffset = 0; while ( getfiles( filecount ) ) { if ( filecount < MAXFILES ) filecount++; } len += 2048; pdoffset = rdoffset + len; } return filecount; } /*************************************************************************** * 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 */ if (strcmp(filelist[selection].filename,"..") == 0) { /* determine last subdirectory namelength */ sprintf(temp,"%s",rootSDdir); test = strtok(temp,"\\"); while (test != NULL) { size = strlen(test); test = strtok(NULL,"\\"); } /* remove last subdirectory name */ size = strlen(rootSDdir) - size - 1; rootSDdir[size] = 0; /* handles root name */ //sprintf(tmpCompare, "dev%d:",ChosenSlot); if (strcmp(rootSDdir, sdslot ? "dev1:":"dev0:") == 0) sprintf(rootSDdir,"dev%d:\\%s\\..", sdslot, FCEUDIR); return 1; } else { /* test new directory namelength */ if ((strlen(rootSDdir)+1+strlen(filelist[selection].filename)) < SDCARD_MAX_PATH_LEN) { /* handles root name */ sprintf(temp, "dev%d:\\%s\\..", sdslot, FCEUDIR); if (strcmp(rootSDdir, temp) == 0) sprintf(rootSDdir,"dev%d:",sdslot); /* update current directory name */ sprintf(rootSDdir, "%s\\%s",rootSDdir, filelist[selection].filename); return 1; } else { WaitPrompt ("Dirname is too long !"); return -1; } } } #ifdef HW_RVL /*************************************************************************** * * Update WiiSDCARD curent directory name * ***************************************************************************/ int updateWiiSDdirname() { 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 */ sprintf(temp,"%s",rootWiiSDdir); test = strtok(temp,"/"); while (test != NULL) { size = strlen(test); test = strtok(NULL,"/"); } /* remove last subdirectory name */ size = strlen(rootWiiSDdir) - size - 1; rootWiiSDdir[size] = 0; return 1; } else { /* test new directory namelength */ if ((strlen(rootWiiSDdir)+1+strlen(filelist[selection].filename)) < SDCARD_MAX_PATH_LEN) { /* update current directory name */ sprintf(rootWiiSDdir, "%s/%s",rootWiiSDdir, filelist[selection].filename); return 1; } else { WaitPrompt ((char*)"Dirname is too long !"); return -1; } } } #endif /*************************************************************************** * Browse SDCARD subdirectories ***************************************************************************/ int parseSDdirectory() { int entries = 0; int nbfiles = 0; int numstored = 0; DIR *sddir = NULL; /* initialize selection */ selection = offset = 0; /* Get a list of files from the actual root directory */ entries = SDCARD_ReadDir (rootSDdir, &sddir); //entries = SDCARD_ReadDir (sdcardpath, &sddir); if (entries <= 0) entries = 0; if (entries>MAXFILES) entries = MAXFILES; while (entries) { if (strcmp((const char*)sddir[nbfiles].fname, ".") != 0) { // Skip "." directory memset (&filelist[numstored], 0, sizeof (FILEENTRIES)); strncpy(filelist[numstored].filename,(const char*)sddir[nbfiles].fname,MAXJOLIET); filelist[numstored].filename[MAXJOLIET-1] = 0; filelist[numstored].length = sddir[nbfiles].fsize; filelist[numstored].flags = (char)(sddir[nbfiles].fattr & SDCARD_ATTR_DIR); numstored++; } nbfiles++; entries--; } free(sddir); return nbfiles; } /*************************************************************************** * Browse WiiSD subdirectories ***************************************************************************/ #ifdef HW_RVL int parseWiiSDdirectory() { int entries = 0; int nbfiles = 0; int numstored = 0; char msg[1024]; /* initialize selection */ selection = offset = 0; /* Get a list of files from the actual root directory */ FSDIRENTRY vfsdir; int result = VFAT_opendir(0, &vfsdir, rootWiiSDdir); if(result != FS_SUCCESS) { sprintf(msg, "Opendir(%s) failed with %d.", rootWiiSDdir, result); WaitPrompt(msg); return 0; } while (VFAT_readdir(&vfsdir) == FS_SUCCESS) { memset (&filelist[numstored], 0, sizeof (FILEENTRIES)); strncpy(filelist[numstored].filename,(char *)(vfsdir.longname), MAX_LONG_NAME); filelist[numstored].filename[MAX_LONG_NAME-1] = 0; filelist[numstored].length = vfsdir.fsize; filelist[numstored].flags = (char)(vfsdir.dirent.attribute & ATTR_DIRECTORY); numstored++; nbfiles++; } VFAT_closedir(&vfsdir); return numstored; } #endif /**************************************************************************** * ShowFiles * * Support function for FileSelector ****************************************************************************/ void ShowFiles( int offset, int selection ) { int i,j; char text[80]; ClearScreen(); j = 0; for ( i = offset; i < ( offset + PAGESIZE ) && ( i < maxfiles ); i++ ) { if ( filelist[i].flags ) { strcpy(text,"["); strncat(text, filelist[i].filename, 78); strcat(text,"]"); } else strncpy(text, filelist[i].filename, 80); text[80]=0; char dir[1024]; if (UseSDCARD) strcpy(dir, rootSDdir); else if (UseWiiSDCARD) strcpy(dir, rootWiiSDdir); else dir[0] = 0; writex(CentreTextPosition(dir), 22, GetTextWidth(dir), font_height, dir, 0); while (GetTextWidth(text) > 620) text[strlen(text)-2] = 0; writex( CentreTextPosition(text), ( j * font_height ) + 110, GetTextWidth(text), font_height, text, j == ( selection - offset ) ); j++; } SetScreen(); } /**************************************************************************** * FileSelector * * Let user select another ROM to load ****************************************************************************/ bool inSz = false; extern u8 PADCAL; void FileSelector() { short p; short q = 0; signed char a; int haverom = 0; int redraw = 1; while ( haverom == 0 ) { if ( redraw ) ShowFiles( offset, selection ); redraw = 0; p = PAD_ButtonsDown(0); a = PAD_StickY(0); if (p & PAD_BUTTON_B) return; if ( ( p & PAD_BUTTON_DOWN ) || ( a < -PADCAL ) ) { selection++; if (selection == maxfiles) selection = offset = 0; if ((selection - offset) >= PAGESIZE) offset += PAGESIZE; redraw = 1; } // End of down if ( ( p & PAD_BUTTON_UP ) || ( a > PADCAL ) ) { selection--; if ( selection < 0 ){ selection = maxfiles - 1; offset = selection - PAGESIZE + 1; } if (selection < offset) offset -= PAGESIZE; if ( offset < 0 ) offset = 0; redraw = 1; } // End of Up if ( (p & PAD_BUTTON_LEFT) || (p & PAD_TRIGGER_L) ) { /*** Go back a page ***/ selection -= PAGESIZE; if ( selection < 0 ) { selection = maxfiles - 1; offset = selection-PAGESIZE + 1; } if ( selection < offset ) offset -= PAGESIZE; if ( offset < 0 ) offset = 0; redraw = 1; } if (( p & PAD_BUTTON_RIGHT ) || (p & PAD_TRIGGER_R)) { /*** Go forward a page ***/ selection += PAGESIZE; if ( selection > maxfiles - 1 ) selection = offset = 0; if ( ( selection - offset ) >= PAGESIZE ) offset += PAGESIZE; redraw = 1; } if ( p & PAD_BUTTON_A ) { if ( filelist[selection].flags ) { /*** This is directory ***/ if (UseSDCARD) { //if ( filelist[selection].filename[0] == 0x2e) { /* update current directory and set new entry list if directory has changed */ int status = updateSDdirname(); if (status == 1) { maxfiles = parseSDdirectory(); if (!maxfiles) { WaitPrompt ("Error reading directory !"); haverom = 1; // quit SD menu haveSDdir = 0; // reset everything at next access } } else if (status == -1) { haverom = 1; // quit SD menu haveSDdir = 0; // reset everything at next access } #ifdef HW_RVL } else if (UseWiiSDCARD) { /* update current directory and set new entry list if directory has changed */ int status = updateWiiSDdirname(); if (status == 1) { maxfiles = parseWiiSDdirectory(); if (!maxfiles) { WaitPrompt ((char*)"Error reading directory !"); haverom = 1; // quit SD menu haveWiiSDdir = 0; // reset everything at next access } } else if (status == -1) { haverom = 1; // quit SD menu haveWiiSDdir = 0; // reset everything at next access } #endif } else { rootdir = filelist[selection].offset; rootdirlength = filelist[selection].length; offset = selection = 0; maxfiles = parsedir(); } } else if (selection == 0 && inSz == true) { rootdir = filelist[1].offset; rootdirlength = filelist[1].length; offset = 0; maxfiles = parsedir(); inSz = false; SzClose(); } else if (inSz == false && SzDvdIsArchive(filelist[selection].offset) == SZ_OK) { // parse the 7zip file WaitPrompt("Found 7z"); SzParse(); if(SzRes == SZ_OK) { inSz = true; offset = selection = 0; } else { SzDisplayError(SzRes); } } else if (inSz == true) { // extract the selected ROM from the 7zip file to the buffer if(SzExtractROM(filelist[selection].offset, nesromptr) == true) { haverom = 1; inSz = false; // go one directory up rootdir = filelist[1].offset; rootdirlength = filelist[1].length; offset = selection = 0; maxfiles = parsedir(); } } else { rootdir = filelist[selection].offset; rootdirlength = filelist[selection].length; // Now load the DVD file to it's offset LoadDVDFile(nesromptr); haverom = 1; } redraw = 1; } } } /**************************************************************************** * LoadDVDFile ****************************************************************************/ int LoadDVDFile( unsigned char *buffer ) { u64 offset; int blocks; int i; u64 discoffset; #ifdef HW_RVL if(UseWiiSDCARD) { ShowAction((char*)"Loading ... Wait"); char filename[1024]; sprintf(filename, "%s/%s", rootWiiSDdir, filelist[selection].filename); int res = VFAT_fopen(0, &vfsfile, filename, FS_READ); if (res != FS_SUCCESS) { char msg[1024]; sprintf(msg, "Open %s failed, error %d", filename, res); WaitPrompt(msg); return 0; } } #endif /*** SDCard Addition ***/ if (UseSDCARD) GetSDInfo(); if (rootdirlength == 0) return 0; /*** How many 2k blocks to read ***/ blocks = rootdirlength / 2048; offset = 0; discoffset = rootdir; ShowAction("Loading ... Wait"); if (UseSDCARD) SDCARD_ReadFile (filehandle, &readbuffer, 2048); #ifdef HW_RVL else if (UseWiiSDCARD) VFAT_fread(&vfsfile, &readbuffer, 2048); #endif else dvd_read(&readbuffer, 2048, discoffset); if ( isZipFile() == false ) { if (UseSDCARD) SDCARD_SeekFile (filehandle, 0, SDCARD_SEEK_SET); #ifdef HW_RVL else if (UseWiiSDCARD) VFAT_fseek(&vfsfile, 0, SEEK_SET); #endif for ( i = 0; i < blocks; i++ ) { if (UseSDCARD) SDCARD_ReadFile (filehandle, &readbuffer, 2048); #ifdef HW_RVL else if (UseWiiSDCARD) VFAT_fread(&vfsfile, &readbuffer, 2048); #endif else dvd_read(&readbuffer, 2048, discoffset); memcpy(&buffer[offset], &readbuffer, 2048); offset += 2048; discoffset += 2048; } /*** And final cleanup ***/ if( rootdirlength % 2048 ) { i = rootdirlength % 2048; if (UseSDCARD) SDCARD_ReadFile (filehandle, &readbuffer, i); #ifdef HW_RVL else if (UseWiiSDCARD) VFAT_fread(&vfsfile, &readbuffer, i); #endif else dvd_read(&readbuffer, 2048, discoffset); memcpy(&buffer[offset], &readbuffer, i); } } else { return unzipDVDFile( buffer, (u32)discoffset, rootdirlength); } if (UseSDCARD) SDCARD_CloseFile (filehandle); #ifdef HW_RVL else if (UseWiiSDCARD) VFAT_fclose(&vfsfile); #endif return rootdirlength; } /**************************************************************************** * OpenDVD * * This function performs the swap task for softmodders. * For Viper/Qoob users, sector 0 is read, and if it contains all nulls * an ISO disc is assumed. ****************************************************************************/ static int havedir = 0; int OpenDVD() { haveSDdir = 0; havedir = offset = selection = 0; // Mount the DVD if necessary if (!IsPVD()) { ShowAction("Mounting DVD"); DVD_Mount(); ShowAction("Done Mounting"); havedir = 0; if (!IsPVD()) { WaitPrompt("No vallid ISO9660 DVD"); return 0; // No correct ISO9660 DVD } } /*** At this point I should have an unlocked DVD ... so let's do the ISO ***/ if ( havedir != 1 ) { if ( IsPVD() ) { /*** Have a valid PVD, so start reading directory entries ***/ maxfiles = parsedir(); if ( maxfiles ) { offset = selection = 0; FileSelector(); havedir = 1; } } else { return 0; } } else FileSelector(); return 1; } #ifdef HW_RVL int OpenWiiSD () { UseWiiSDCARD = 1; UseSDCARD = 0; haveSDdir = 0; char msg[128]; /*if (WiiSD_Available == 0) { sprintf(msg, "Insert SD card: %d\n", WiiSD_Available); WaitPrompt(msg); //return 0; }*/ memset(&vfs, 0, sizeof(VFATFS)); if (haveWiiSDdir == 0) { /* don't mess with DVD entries */ havedir = 0; /* Mount WiiSD with VFAT */ VFAT_unmount(0, &vfs); int res = VFAT_mount(FS_SLOTA, &vfs); if (res != FS_TYPE_FAT16) { sprintf(msg, "Error mounting WiiSD: %d", res); WaitPrompt(msg); return 0; } /* Reset SDCARD root directory */ sprintf(rootWiiSDdir,"/%s/%s", FCEUDIR, ROMSDIR); /* Parse initial root directory and get entries list */ ShowAction((char *)"Reading Directory ..."); if ((maxfiles = parseWiiSDdirectory ())) { sprintf (msg, "Found %d entries", maxfiles); ShowAction(msg); /* Select an entry */ FileSelector (); /* memorize last entries list, actual root directory and selection for next access */ /* TODO: Bugged, do not activate cached dir listing haveWiiSDdir = 1;*/ } else { /* no entries found */ sprintf (msg, "Error reading %s", rootWiiSDdir); WaitPrompt (msg); return 0; } } /* Retrieve previous entries list and made a new selection */ else FileSelector (); return 1; } #endif int OpenSD () { UseSDCARD = 1; UseWiiSDCARD = 0; haveWiiSDdir = 0; char msg[128]; if (ChosenSlot != sdslot) haveSDdir = 0; if (haveSDdir == 0) { /* don't mess with DVD entries */ havedir = 0; /* Reset SDCARD root directory */ sprintf(rootSDdir,"dev%d:\\%s\\%s", ChosenSlot, FCEUDIR, ROMSDIR); sdslot = ChosenSlot; /* Parse initial root directory and get entries list */ ShowAction("Reading Directory ..."); if ((maxfiles = parseSDdirectory ())) { sprintf (msg, "Found %d entries", maxfiles); ShowAction(msg); /* Select an entry */ FileSelector (); /* memorize last entries list, actual root directory and selection for next access */ haveSDdir = 1; } else { /* no entries found */ sprintf (msg, "Error reading %s", rootSDdir); WaitPrompt (msg); return 0; } } /* Retrieve previous entries list and made a new selection */ else FileSelector (); return 1; } /**************************************************************************** * SDCard Get Info ****************************************************************************/ void GetSDInfo () { char fname[SDCARD_MAX_PATH_LEN]; rootdirlength = 0; /* Check filename length */ if ((strlen(rootSDdir)+1+strlen(filelist[selection].filename)) < SDCARD_MAX_PATH_LEN) sprintf(fname, "%s\\%s",rootSDdir,filelist[selection].filename); else { WaitPrompt ("Maximum Filename Length reached !"); haveSDdir = 0; // reset everything before next access } filehandle = SDCARD_OpenFile (fname, "rb"); if (filehandle == NULL) { WaitPrompt ("Unable to open file!"); return; } rootdirlength = SDCARD_GetFileSize (filehandle); }