mirror of
https://github.com/suloku/gcmm.git
synced 2026-04-08 02:15:16 -05:00
- command line for both wii and gamecube - support sdgecko in wii mode - you can now insert/remove devices without reboot via device selector
758 lines
20 KiB
C
758 lines
20 KiB
C
/****************************************************************************
|
|
* SD Card Support Functions
|
|
****************************************************************************/
|
|
#include <gccore.h>
|
|
#include <network.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <sys/dir.h>
|
|
#include <dirent.h>
|
|
|
|
#include "sdsupp.h"
|
|
#include "freetype.h"
|
|
#include "gci.h"
|
|
#include "mcard.h"
|
|
#include "raw.h"
|
|
|
|
#define PAGESIZE 20
|
|
#define PADCAL 80
|
|
|
|
#define DIRENT_T_FILE 0
|
|
#define DIRENT_T_DIR 1
|
|
|
|
/*** Memory Card FileBuffer ***/
|
|
#define MAXFILEBUFFER (1024 * 2048) /*** 2MB Buffer ***/
|
|
extern u8 FileBuffer[MAXFILEBUFFER] ATTRIBUTE_ALIGN (32);
|
|
extern Header cardheader;
|
|
extern u8 CommentBuffer[64] ATTRIBUTE_ALIGN (32);
|
|
|
|
extern u16 bannerdata[CARD_BANNER_W*CARD_BANNER_H] ATTRIBUTE_ALIGN (32);
|
|
extern u8 bannerdataCI[CARD_BANNER_W*CARD_BANNER_H] ATTRIBUTE_ALIGN (32);
|
|
extern u8 icondata[8][1024] ATTRIBUTE_ALIGN (32);
|
|
extern u16 icondataRGB[8][1024] ATTRIBUTE_ALIGN (32);
|
|
extern u16 tlut[9][256] ATTRIBUTE_ALIGN (32);
|
|
extern u16 tlutbanner[256] ATTRIBUTE_ALIGN (32);
|
|
extern int numicons;
|
|
extern int frametable[2*CARD_MAXICONS - 2];
|
|
extern int iconindex[2*CARD_MAXICONS - 2];
|
|
extern int lastframe;
|
|
extern int lasticon;
|
|
|
|
extern u8 filelist[1024][1024];
|
|
extern u32 maxfile;
|
|
extern card_direntry gci;
|
|
extern int OFFSET;
|
|
|
|
extern u8 currFolder[260];
|
|
extern int folderCount;
|
|
extern char fatpath[4];
|
|
|
|
bool file_exists(const char * filename)
|
|
{
|
|
FILE * file = fopen(filename, "r");
|
|
if (file)
|
|
{
|
|
fclose(file);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int SDSaveMCImage ()
|
|
{
|
|
|
|
char filename[1024];
|
|
char tfile[40];
|
|
char company[4];
|
|
char gamecode[6];
|
|
int bytesToWrite = 0;
|
|
//sd_file *handle;
|
|
FILE *handle;
|
|
card_direntry thisgci;
|
|
int check;
|
|
int filenumber = 0;
|
|
int retries = 0;
|
|
|
|
/*** Make a copy of the Card Dir ***/
|
|
memcpy (&thisgci, FileBuffer, sizeof (card_direntry));
|
|
memset( tfile, 0, 40 );
|
|
company[2] = 0;
|
|
gamecode[4] = 0;
|
|
memcpy (company, &thisgci.company, 2);
|
|
memcpy (gamecode, &thisgci.gamecode, 4);
|
|
memcpy (tfile, &thisgci.filename, CARD_FILENAMELEN);
|
|
|
|
sprintf (filename, "%s:/%s", fatpath, MCSAVES);
|
|
|
|
mkdir(filename, S_IREAD | S_IWRITE);
|
|
|
|
sprintf (filename, "%s:/%s/%s-%s-%s_%02d.gci", fatpath, MCSAVES, company, gamecode, tfile, filenumber);
|
|
|
|
//Lets try if there's already a savegame (if it exists its name is legal, so theoretically the illegal name check will pass
|
|
//Illegal savegame should report as nonexisting...
|
|
//We will number the files
|
|
while (file_exists(filename)){
|
|
sprintf (filename, "%s:/%s/%s-%s-%s_%02d.gci", fatpath, MCSAVES, company, gamecode, tfile, filenumber);
|
|
filenumber++;
|
|
}
|
|
|
|
//filename[128] = 0; // limit filename length, there's a bug where a file is exported as DOS-type shortname ("8P-GPO~2.GCI") which I assume happens if the name is too long...? Nope that's not it.
|
|
|
|
while ( 1 ) // loop the writing because it sometimes fails (see above); I think this is an error in libfat but I dunno.
|
|
{
|
|
/*** Open SD Card file ***/
|
|
//handle = SDCARD_OpenFile (filename, "wb");
|
|
handle = fopen ( filename , "wb" );
|
|
if (handle <= 0)
|
|
{
|
|
// couldn't open file, probably either card full or filename illegal; let's assume illegal filename and retry
|
|
sprintf (filename, "%s:/%s/%s-%s-%s_%02d.gci", fatpath, MCSAVES, company, gamecode, "illegal_name", filenumber);
|
|
//let's see again if there aren't any saves already...
|
|
filenumber = 1;
|
|
while (file_exists(filename)){
|
|
sprintf (filename, "%s:/%s/%s-%s-%s_%02d.gci", fatpath, MCSAVES, company, gamecode, "illegal_name", filenumber);
|
|
filenumber++;
|
|
}
|
|
//filename[128] = 0;
|
|
handle = fopen ( filename , "wb" );
|
|
if (handle <= 0)
|
|
{
|
|
char msg[100];
|
|
sprintf(msg, "Couldn't open %s", filename);
|
|
WaitPrompt (msg);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
bytesToWrite = (thisgci.length * 8192) + MCDATAOFFSET;
|
|
//SDCARD_WriteFile (handle, FileBuffer, bytesToWrite);
|
|
//SDCARD_CloseFile (handle);
|
|
fwrite (FileBuffer , 1 , bytesToWrite , handle );
|
|
fclose (handle);
|
|
|
|
// check if file actually wrote correctly
|
|
handle = fopen ( filename , "rb" );
|
|
if (handle <= 0)
|
|
{
|
|
// file failed to open, so something failed in the write; retry
|
|
retries ++;
|
|
continue;
|
|
}
|
|
fseek (handle , 0 , SEEK_END);
|
|
check = ftell (handle);
|
|
fclose(handle);
|
|
if ( check > 0 ) {
|
|
// if filesize is bigger than 0, we can assume the file wrote correctly, break out of loop
|
|
// ... this will end in an endless loop if the file to write is 0 bytes but that's very unlikely
|
|
break;
|
|
}
|
|
|
|
//Try 10 times if needed, then give up. Better to avoid endless looping
|
|
if (retries > 9)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
int SDLoadMCImage(char *sdfilename)
|
|
{
|
|
|
|
//sd_file *handle;
|
|
FILE *handle;
|
|
char filename[1024];
|
|
char msg[256];
|
|
//int offset = 0;
|
|
//int bytesToRead = 0;
|
|
long bytesToRead = 0;
|
|
|
|
/*** Clear the work buffers ***/
|
|
memset (FileBuffer, 0, MAXFILEBUFFER);
|
|
memset (CommentBuffer, 0, 64);
|
|
|
|
/*** Make fullpath filename ***/
|
|
//sprintf (filename, "dev0:\\%s\\%s", MCSAVES, sdfilename);
|
|
sprintf (filename, "%s:/%s/%s", fatpath, currFolder, sdfilename);
|
|
|
|
//SDCARD_Init ();
|
|
|
|
/*** Does this file exist ? ***/
|
|
/*if (SDCARD_SeekFile(filename, 0, SDCARD_SEEK_SET) != SDCARD_ERROR_READY){
|
|
return 0;
|
|
}*/
|
|
|
|
/*** Open the SD Card file ***/
|
|
//handle = SDCARD_OpenFile (filename, "rb");
|
|
handle = fopen ( filename , "rb" );
|
|
if (handle <= 0)
|
|
{
|
|
sprintf(msg, "Couldn't open %s", filename);
|
|
WaitPrompt (msg);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* if (handle == NULL){
|
|
WaitPrompt ("Unable to open file!");
|
|
return 0;
|
|
}*/
|
|
|
|
// obtain file size:
|
|
fseek (handle , 0 , SEEK_END);
|
|
bytesToRead = ftell (handle);
|
|
rewind (handle);
|
|
|
|
//bytesToRead = SDCARD_GetFileSize(handle);
|
|
if (bytesToRead <= 0)
|
|
{
|
|
sprintf(msg, "Incorrect file size %ld .", bytesToRead);
|
|
WaitPrompt (msg);
|
|
//WaitPrompt("Incorrect file size.");
|
|
return 0;
|
|
}
|
|
fseek (handle , OFFSET , SEEK_SET);
|
|
/*** Read the file ***/
|
|
//SDCARD_ReadFile (handle, FileBuffer, bytesToRead);
|
|
fread (FileBuffer,1,bytesToRead,handle);
|
|
|
|
if(OFFSET == 0x80)
|
|
{
|
|
// swap byte pairs
|
|
// 0x06 and 0x07
|
|
u8 temp = FileBuffer[0x06];
|
|
FileBuffer[0x06] = FileBuffer[0x07];
|
|
FileBuffer[0x07] = temp;
|
|
|
|
// swap byte pairs
|
|
// 0x2C and 0x2D, 0x2E and 0x2F, 0x30 and 0x31, 0x32 and 0x33,
|
|
// 0x34 and 0x35, 0x36 and 0x37, 0x38 and 0x39, 0x3A and 0x3B,
|
|
// 0x3C and 0x3D,0x3E and 0x3F.
|
|
int i = 0;
|
|
while(i<10)
|
|
{
|
|
u8 temp = FileBuffer[0x2C + i*2];
|
|
FileBuffer[0x2C + i*2] = FileBuffer[0x2C + i*2+1];
|
|
FileBuffer[0x2C + i*2+1] = temp;
|
|
i++;
|
|
}
|
|
}
|
|
//sprintf(msg, "Offset: %d", bytesToRead);
|
|
//WaitPrompt (msg);
|
|
/*** Close the file ***/
|
|
//SDCARD_CloseFile (handle);
|
|
fclose (handle);
|
|
|
|
return bytesToRead;
|
|
}
|
|
|
|
int SDLoadMCImageHeader(char *sdfilename)
|
|
{
|
|
|
|
FILE *handle;
|
|
char filename[1024];
|
|
char msg[256];
|
|
//int offset = 0;
|
|
//int bytesToRead = 0;
|
|
long bytesToRead = 0;
|
|
int i;
|
|
|
|
/*** Clear the work buffers ***/
|
|
memset (FileBuffer, 0, MAXFILEBUFFER);
|
|
memset (CommentBuffer, 0, 64);
|
|
|
|
/*** Make fullpath filename ***/
|
|
sprintf (filename, "%s:/%s/%s", fatpath, currFolder, sdfilename);
|
|
|
|
|
|
/*** Open the SD Card file ***/
|
|
//handle = SDCARD_OpenFile (filename, "rb");
|
|
handle = fopen ( filename , "rb" );
|
|
if (handle <= 0)
|
|
{
|
|
sprintf(msg, "Couldn't open %s", filename);
|
|
WaitPrompt (msg);
|
|
return 0;
|
|
}
|
|
|
|
// obtain file size:
|
|
fseek (handle , 0 , SEEK_END);
|
|
bytesToRead = ftell (handle);
|
|
rewind (handle);
|
|
if (bytesToRead < 64) //We don't want to read something smaller than the header
|
|
{
|
|
sprintf(msg, "Incorrect file size %ld . Not GCI File", bytesToRead);
|
|
WaitPrompt (msg);
|
|
//WaitPrompt("Incorrect file size.");
|
|
return 0;
|
|
}
|
|
|
|
OFFSET = 0;
|
|
char tmp[0xD];
|
|
char fileType[1024];
|
|
|
|
char * dot;
|
|
int pos = 4;
|
|
dot = strrchr(filename,'.');
|
|
strncpy(fileType, dot+1,pos);
|
|
fileType[pos]='\0';
|
|
|
|
if(strcasecmp(fileType, "gci"))
|
|
{
|
|
fread(&tmp, 1, 0xD, handle);
|
|
rewind(handle);
|
|
if (!strcasecmp(fileType, "gcs"))
|
|
{
|
|
if (!memcmp(&tmp, "GCSAVE", 6)) // Header must be uppercase
|
|
{
|
|
OFFSET = 0x110;
|
|
}
|
|
else
|
|
{
|
|
WaitPrompt ("Incorrect Header. Not GCS File");
|
|
return 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!strcasecmp(fileType, "sav"))
|
|
{
|
|
if (!memcmp(tmp, "DATELGC_SAVE", 0xC)) // Header must be uppercase
|
|
{
|
|
OFFSET = 0x80;
|
|
}
|
|
else
|
|
{
|
|
WaitPrompt ("Incorrect Header. Not SAV File");
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else OFFSET = 0;
|
|
fseek(handle, OFFSET, SEEK_SET);
|
|
|
|
/*** Read the file header ***/
|
|
fread (FileBuffer,1,sizeof(card_direntry),handle);
|
|
|
|
u16 length = (bytesToRead - OFFSET - sizeof(card_direntry)) / 0x2000;
|
|
switch(OFFSET)
|
|
{
|
|
case 0x110:
|
|
{
|
|
// field containing the Block count as displayed within
|
|
// the GameSaves software is not stored in the GCS file.
|
|
// It is stored only within the corresponding GSV file.
|
|
// If the GCS file is added without using the GameSaves software,
|
|
// the value stored is always "1"
|
|
FileBuffer[0x38] = (u8)(length >> 8);
|
|
FileBuffer[0x39] = (u8)length;
|
|
}
|
|
break;
|
|
case 0x80:
|
|
{
|
|
// swap byte pairs
|
|
// 0x06 and 0x07
|
|
|
|
u8 temp = FileBuffer[0x06];
|
|
FileBuffer[0x06] = FileBuffer[0x07];
|
|
FileBuffer[0x07] = temp;
|
|
|
|
// swap byte pairs
|
|
// 0x2C and 0x2D, 0x2E and 0x2F, 0x30 and 0x31, 0x32 and 0x33,
|
|
// 0x34 and 0x35, 0x36 and 0x37, 0x38 and 0x39, 0x3A and 0x3B,
|
|
// 0x3C and 0x3D,0x3E and 0x3F.
|
|
int i = 0;
|
|
while(i<10)
|
|
{
|
|
u8 temp = FileBuffer[0x2C + i*2];
|
|
FileBuffer[0x2C + i*2] = FileBuffer[0x2C + i*2+1];
|
|
FileBuffer[0x2C + i*2+1] = temp;
|
|
i++;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
u16 l2 =(u16)(FileBuffer[0x38] << 8) | FileBuffer[0x39];
|
|
if (length != l2)
|
|
{
|
|
sprintf(msg, "File length does not equal file size. Wrong extension? (l1 = %x l2 = %x)", length,l2);
|
|
WaitPrompt (msg);//"File Length does not equal filesize");
|
|
return 0;
|
|
}
|
|
|
|
ExtractGCIHeader();
|
|
#ifdef STATUSOGC
|
|
GCIMakeHeader();
|
|
#else
|
|
//Let's get the full header as is, instead of populating it...
|
|
memset(&gci, 0xff, sizeof(card_direntry)); /*** Clear out the cgi header ***/
|
|
memcpy (&gci, FileBuffer, sizeof (card_direntry));
|
|
#endif
|
|
|
|
/***
|
|
Get the Banner/Icon Data from the SD save file.
|
|
Very specific if/else setup to avoid rewinds
|
|
***/
|
|
rewind(handle);
|
|
fseek(handle, MCDATAOFFSET + OFFSET + gci.icon_addr, SEEK_SET);
|
|
|
|
/*** Get the Banner/Icon Data from the save file ***/
|
|
if (SDCARD_GetBannerFmt(gci.banner_fmt) == CARD_BANNER_RGB) {
|
|
//RGB banners are 96*32*2 in size
|
|
fread (bannerdata, 1, 6144, handle);
|
|
}
|
|
else if (SDCARD_GetBannerFmt(gci.banner_fmt) == CARD_BANNER_CI) {
|
|
fread(bannerdataCI, 1, 3072, handle);
|
|
fread(tlutbanner, 1, 512, handle);
|
|
}
|
|
//Icon data
|
|
int shared_pal = 0;
|
|
lastframe = 0;
|
|
numicons = 0;
|
|
int j =0;
|
|
i=0;
|
|
int current_icon = 0;
|
|
for (current_icon=0;i<CARD_MAXICONS;++current_icon){
|
|
|
|
//no need to clear all values since we will only use the ones until lasticon
|
|
frametable[current_icon] = 0;
|
|
iconindex[current_icon] = 0;
|
|
|
|
//Animation speed is mandatory to be set even for a single icon
|
|
//When a speed is 0 there are no more icons
|
|
//Some games may have bits set after the "blank icon" both in
|
|
//speed (Baten Kaitos) and format (Wario Ware Inc.) bytes, which are just garbage
|
|
if (!SDCARD_GetIconSpeed(gci.icon_speed,current_icon)){
|
|
break;
|
|
}else
|
|
{//We've got a frame
|
|
lastframe+=SDCARD_GetIconSpeed(gci.icon_speed,current_icon)*4;//Count the total frames
|
|
frametable[current_icon]=lastframe; //Store the end frame of the icon
|
|
|
|
if (SDCARD_GetIconFmt(gci.icon_fmt,current_icon) != 0)
|
|
{
|
|
//count the number of real icons
|
|
numicons++;
|
|
iconindex[current_icon]=current_icon; //Map the icon
|
|
|
|
//CI with shared palette
|
|
if (SDCARD_GetIconFmt(gci.icon_fmt,current_icon) == 1) {
|
|
fread(icondata[current_icon], 1, 1024, handle);
|
|
shared_pal = 1;
|
|
}
|
|
//CI with palette after the icon
|
|
else if (SDCARD_GetIconFmt(gci.icon_fmt,current_icon) == 3)
|
|
{
|
|
fread(icondata[current_icon], 1, 1024, handle);
|
|
fread(tlut[current_icon], 1, 512, handle);
|
|
}
|
|
//RGB 16 bit icon
|
|
else if (SDCARD_GetIconFmt(gci.icon_fmt,current_icon) == 2)
|
|
{
|
|
fread(icondataRGB[current_icon], 1, 2048, handle);
|
|
}
|
|
}else
|
|
{ //Get next real icon
|
|
for(j=current_icon;j<CARD_MAXICONS;++j){
|
|
|
|
if (SDCARD_GetIconFmt(gci.icon_fmt,j) != 0)
|
|
{
|
|
iconindex[current_icon]=j; //Map blank frame to next real icon
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
lasticon = current_icon-1;
|
|
//Now get icon indexes for ping-pong style icons
|
|
if (SDCARD_GetIconAnim(gci.banner_fmt) == CARD_ANIM_BOUNCE && current_icon>1) //We need at least 3 icons
|
|
{
|
|
j=current_icon;
|
|
for (i = current_icon-2; 0 < i; --i, ++j)
|
|
{
|
|
lastframe += SDCARD_GetIconSpeed(gci.icon_speed,i)*4;
|
|
frametable[j] = lastframe;
|
|
iconindex[j] = iconindex[i];
|
|
}
|
|
lasticon = j-1;
|
|
}
|
|
//Get the shared palette
|
|
if (shared_pal) fread(tlut[8], 1, 512, handle);
|
|
|
|
//Get the comment
|
|
rewind(handle);
|
|
fseek(handle, MCDATAOFFSET + OFFSET + gci.comment_addr, SEEK_SET);
|
|
fread (CommentBuffer, 1, MCDATAOFFSET, handle);
|
|
|
|
/*** Close the file ***/
|
|
fclose (handle);
|
|
|
|
return bytesToRead;
|
|
}
|
|
|
|
int SDLoadCardImageHeader(char *sdfilename)
|
|
{
|
|
|
|
FILE *handle;
|
|
char filename[1024];
|
|
char msg[256];
|
|
long bytesToRead = 0;
|
|
|
|
/*** Clear the work buffers ***/
|
|
memset (&cardheader, 0, sizeof(Header));
|
|
|
|
/*** Make fullpath filename ***/
|
|
sprintf (filename, "%s:/%s/%s", fatpath, currFolder, sdfilename);
|
|
|
|
/*** Open the SD Card file ***/
|
|
handle = fopen ( filename , "rb" );
|
|
if (handle <= 0)
|
|
{
|
|
sprintf(msg, "Couldn't open %s", filename);
|
|
WaitPrompt (msg);
|
|
return 0;
|
|
}
|
|
|
|
// obtain file size:
|
|
fseek (handle , 0 , SEEK_END);
|
|
bytesToRead = ftell (handle);
|
|
rewind (handle);
|
|
if (bytesToRead < 8192) //We don't want to read something smaller than the card header
|
|
{
|
|
sprintf(msg, "Incorrect file size %ld . Not raw image file or header", bytesToRead);
|
|
WaitPrompt (msg);
|
|
return 0;
|
|
}
|
|
|
|
char fileType[1024];
|
|
char * dot;
|
|
int pos = 4;
|
|
dot = strrchr(filename,'.');
|
|
strncpy(fileType, dot+1,pos);
|
|
fileType[pos]='\0';
|
|
|
|
if(!strcasecmp(fileType, "mci"))
|
|
{
|
|
//MCI files have a 64 byte header
|
|
fseek(handle, 64, SEEK_SET);
|
|
}
|
|
memset(&cardheader, 0, sizeof(cardheader));
|
|
/*** Read the file header ***/
|
|
fread (&cardheader,1,sizeof(cardheader),handle);
|
|
|
|
/*** Close the file ***/
|
|
fclose (handle);
|
|
|
|
return bytesToRead;
|
|
}
|
|
|
|
int isdir_sd(char *path)
|
|
{
|
|
DIR* dir = opendir(path);
|
|
if(dir == NULL)
|
|
return 0;
|
|
|
|
closedir(dir);
|
|
|
|
return 1;
|
|
}
|
|
|
|
//Code from Kobie. Returns true if extension matches (also works with paths), should check only the last '.' in the string.
|
|
bool compare_extension(char *filename, char *extension)
|
|
{
|
|
/* Sanity checks */
|
|
|
|
if(filename == NULL || extension == NULL)
|
|
return false;
|
|
|
|
if(strlen(filename) == 0 || strlen(extension) == 0)
|
|
return false;
|
|
|
|
if(strchr(filename, '.') == NULL || strchr(extension, '.') == NULL)
|
|
return false;
|
|
|
|
/* Iterate backwards through respective strings and compare each char one at a time */
|
|
int i;
|
|
for(i = 0; i < strlen(filename); i++)
|
|
{
|
|
if(tolower(filename[strlen(filename) - i - 1]) == tolower(extension[strlen(extension) - i - 1]))
|
|
{
|
|
if(i == strlen(extension) - 1)
|
|
return true;
|
|
} else
|
|
break;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* SDGetFileList
|
|
*
|
|
* Get the directory listing from SD Card
|
|
* Mode 1: retrieves .gci, .sav and .gcs
|
|
* Mode 0: retrieves .raw, .gcp and .mci
|
|
****************************************************************************/
|
|
int SDGetFileList(int mode)
|
|
{
|
|
int filecount = 0;
|
|
DIR *dir;
|
|
struct dirent *dit;
|
|
static char namefile[256*4]; // enough room for UTF-8 encoding
|
|
int dirtype;
|
|
//static struct stat filestat;
|
|
|
|
int dirCount = 0;
|
|
|
|
char filename[1024];
|
|
sprintf (filename, "%s:/%s/", fatpath, currFolder);
|
|
|
|
|
|
//Add Folders
|
|
if ((dir = opendir(filename)) == NULL)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
while ((dit = readdir(dir)) != NULL)
|
|
{
|
|
if(strncmp(dit->d_name, ".", 1) != 0 && strncmp(dit->d_name, "..", 2) != 0)
|
|
{
|
|
sprintf(namefile, "%s%s", filename, dit->d_name);
|
|
|
|
if(isdir_sd(namefile) == 1)
|
|
{
|
|
strcpy((char *)filelist[filecount], dit->d_name);
|
|
dirCount++;
|
|
filecount++;
|
|
}
|
|
}
|
|
}
|
|
|
|
closedir(dir);
|
|
|
|
|
|
//Add Files
|
|
if ((dir = opendir(filename)) == NULL)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
while ((dit = readdir(dir)) != NULL)
|
|
{
|
|
if(strncmp(dit->d_name, ".", 1) != 0 && strncmp(dit->d_name, "..", 2) != 0)
|
|
{
|
|
if (mode)
|
|
{
|
|
if (compare_extension(dit->d_name, ".gci") || compare_extension(dit->d_name, ".sav") || compare_extension(dit->d_name, ".gcs"))
|
|
{
|
|
strcpy((char *)filelist[filecount], dit->d_name);
|
|
sprintf(namefile, "%s%s", filename, dit->d_name);
|
|
dirtype = ((isdir_sd(namefile) == 1) ? DIRENT_T_DIR : DIRENT_T_FILE);
|
|
|
|
filecount++;
|
|
}
|
|
}
|
|
else if (!mode)
|
|
{
|
|
if (compare_extension(dit->d_name, ".raw") || compare_extension(dit->d_name, ".gcp") || compare_extension(dit->d_name, ".mci"))
|
|
{
|
|
strcpy((char *)filelist[filecount], dit->d_name);
|
|
sprintf(namefile, "%s%s", filename, dit->d_name);
|
|
dirtype = ((isdir_sd(namefile) == 1) ? DIRENT_T_DIR : DIRENT_T_FILE);
|
|
|
|
filecount++;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
//Dragonbane: Sort folders alphabetically
|
|
int i=0;
|
|
int j=0;
|
|
|
|
for (i = 0; i < dirCount; i++)
|
|
{
|
|
for (j = i+1; j < dirCount; j++)
|
|
if (strcmp((char*)filelist[i], (char*)filelist[j]) > 0)
|
|
{
|
|
char temp[1024];
|
|
|
|
sprintf(temp, "%s", (char*)filelist[i]);
|
|
sprintf((char*)filelist[i], "%s", (char*)filelist[j]);
|
|
sprintf((char*)filelist[j], "%s", temp);
|
|
}
|
|
}
|
|
|
|
|
|
//Dragonbane: Sort files alphabetically
|
|
|
|
for (i = dirCount; i < filecount; i++)
|
|
{
|
|
for (j = i+1; j < filecount; j++)
|
|
if (strcmp((char*)filelist[i], (char*)filelist[j]) > 0)
|
|
{
|
|
char temp[1024];
|
|
|
|
sprintf(temp, "%s", (char*)filelist[i]);
|
|
sprintf((char*)filelist[i], "%s", (char*)filelist[j]);
|
|
sprintf((char*)filelist[j], "%s", temp);
|
|
}
|
|
}
|
|
|
|
/* while(1)
|
|
{
|
|
if(readdir(dir)!=0) break; // si no hay mas entradas en el directorio, sal
|
|
|
|
if(filestat.st_mode & S_IFDIR) // es el nombre de un directorio
|
|
{
|
|
// namefile contiene el nombre del directorio en formato UTF-8,que puede ser "." o ".." tambien
|
|
} else {
|
|
// namefile contiene el nombre del fichero en formato UTF-8
|
|
strcpy ((char *)filelist[filecount], namefile);
|
|
filecount++;
|
|
}
|
|
}*/
|
|
|
|
closedir(dir); // cierra el directorio
|
|
maxfile = filecount;
|
|
folderCount = dirCount;
|
|
return filecount;
|
|
|
|
/* int entries = 0;
|
|
int filecount = 0;
|
|
char filename[1024];
|
|
//DIR *sddir = NULL;
|
|
DIR_ITER *sddir = NULL;
|
|
|
|
SDCARD_Init ();
|
|
|
|
sprintf (filename, "dev0:\\%s\\", MCSAVES);
|
|
|
|
entries = SDCARD_ReadDir (filename, &sddir);
|
|
|
|
while (entries){
|
|
strcpy (filelist[filecount], sddir[filecount].fname);
|
|
filecount++;
|
|
entries--;
|
|
}
|
|
|
|
free(sddir);
|
|
|
|
maxfile = filecount;
|
|
return filecount;
|
|
*/
|
|
}
|