diff --git a/desmume/src/MMU.cpp b/desmume/src/MMU.cpp index e34e80883..cd51f863d 100644 --- a/desmume/src/MMU.cpp +++ b/desmume/src/MMU.cpp @@ -944,7 +944,7 @@ void MMU_Reset() rtcInit(); partie = 1; addonsReset(); - slot1Close(); + slot1Reset(); Mic_Reset(); MMU.gfx3dCycles = 0; diff --git a/desmume/src/Makefile.am b/desmume/src/Makefile.am index 0ed99131b..a34f89c3d 100644 --- a/desmume/src/Makefile.am +++ b/desmume/src/Makefile.am @@ -19,8 +19,9 @@ libdesmume_a_SOURCES = \ common.cpp common.h \ debug.cpp debug.h \ Disassembler.cpp Disassembler.h \ - emufat.h emufat.cpp emufat_types.h emufile.h emufile.cpp emufile_types.h fat.h FIFO.cpp FIFO.h \ + emufile.h emufile.cpp emufile_types.h fat.h FIFO.cpp FIFO.h \ firmware.cpp firmware.h GPU.cpp GPU.h \ + fs.h \ GPU_osd.h \ mem.h mc.cpp mc.h \ path.cpp path.h \ @@ -44,10 +45,12 @@ libdesmume_a_SOURCES = \ PACKED.h PACKED_END.h \ utils/datetime.cpp utils/datetime.h \ utils/ConvertUTF.c utils/ConvertUTF.h utils/guid.cpp utils/guid.h \ + utils/emufat.cpp utils/emufat.h utils/emufat_types.h \ utils/md5.cpp utils/md5.h utils/valuearray.h utils/xstring.cpp utils/xstring.h \ utils/decrypt/crc.cpp utils/decrypt/crc.h utils/decrypt/decrypt.cpp \ utils/decrypt/decrypt.h utils/decrypt/header.cpp utils/decrypt/header.h \ utils/task.cpp utils/task.h \ + utils/vfat.h utils/vfat.cpp \ utils/dlditool.cpp \ utils/libfat/bit_ops.h \ utils/libfat/cache.cpp \ @@ -77,7 +80,7 @@ libdesmume_a_SOURCES = \ utils/libfat/partition.cpp \ utils/libfat/partition.h \ addons.cpp addons.h \ - addons/compactFlash.cpp addons/gbagame.cpp addons/none.cpp addons/rumblepak.cpp addons/guitarGrip.cpp addons/expMemory.cpp addons/piano.cpp addons/slot1_none.cpp addons/slot1_r4.cpp addons/slot1_retail.cpp fs.h \ + addons/slot2_mpcf.cpp addons/gbagame.cpp addons/none.cpp addons/rumblepak.cpp addons/guitarGrip.cpp addons/expMemory.cpp addons/piano.cpp addons/slot1_none.cpp addons/slot1_r4.cpp addons/slot1_retail.cpp \ cheatSystem.cpp cheatSystem.h \ texcache.cpp texcache.h rasterize.cpp rasterize.h \ metaspu/metaspu.cpp metaspu/metaspu.h \ diff --git a/desmume/src/addons/compactFlash.cpp b/desmume/src/addons/compactFlash.cpp deleted file mode 100644 index 36a9b0257..000000000 --- a/desmume/src/addons/compactFlash.cpp +++ /dev/null @@ -1,1036 +0,0 @@ -/* Copyright (C) 2006 yopyop - Copyright (C) 2006 Mic - Copyright (C) 2009-2010 DeSmuME team - - This file is part of DeSmuME - - DeSmuME is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - DeSmuME is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with DeSmuME; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include "../addons.h" -#include -#include -#include "debug.h" -#include -#include -#include - -#include "../emufat.h" - -#include "../utils/libfat/libfat_public_api.h" - -#include - -#include -#include -#ifdef _MSC_VER -#include -#define OPEN_MODE _O_RDWR | _O_BINARY - -#define OPEN_FN _open -#define CLOSE_FN _close -#define LSEEK_FN _lseek -#define WRITE_FN _write -#define READ_FN _read -#else -#include -#define OPEN_MODE O_RDWR - -#define OPEN_FN open -#define CLOSE_FN close -#define LSEEK_FN lseek -#define WRITE_FN write -#define READ_FN read -#endif - -#include "types.h" -#include "../fat.h" -#include "../fs.h" -#include "MMU.h" -#include "NDSSystem.h" -#include "../path.h" - -typedef struct { - int level,parent,filesInDir; -} FILE_INFO; - -// Set up addresses for GBAMP -#define CF_REG_DATA 0x9000000 -#define CF_REG_ERR 0x9020000 -#define CF_REG_SEC 0x9040000 -#define CF_REG_LBA1 0x9060000 -#define CF_REG_LBA2 0x9080000 -#define CF_REG_LBA3 0x90A0000 -#define CF_REG_LBA4 0x90C0000 -#define CF_REG_CMD 0x90E0000 -#define CF_REG_STS 0x98C0000 - -// CF Card commands -#define CF_CMD_LBA 0xE0 -#define CF_CMD_READ 0x20 -#define CF_CMD_WRITE 0x30 - -static u16 cf_reg_sts, - cf_reg_lba1, - cf_reg_lba2, - cf_reg_lba3, - cf_reg_lba4, - cf_reg_cmd; -static off_t currLBA; - -static const int lfnPos[13] = {1,3,5,7,9,14,16,18,20,22,24,28,30}; - -#define SECPERFAT 128 -#define SECPERCLUS 16 -#define MAXFILES 32768 -#define SECRESV 2 -#define NUMSECTORS 0x80000 -#define NUMCLUSTERS (NUMSECTORS/SECPERCLUS) -#define BYTESPERCLUS (512*SECPERCLUS) -#define DIRENTSPERCLUS ((BYTESPERCLUS)/32) - -BOOT_RECORD MBR; -static DIR_ENT *files,*dirEntries,**dirEntryPtr; -static FILE_INFO *fileLink,*dirEntryLink; -static u32 filesysFAT,filesysRootDir,filesysData; -static u16 FAT16[SECPERFAT*256]; -static u16 numExtraEntries[SECPERFAT*256]; -static DIR_ENT *extraDirEntries[SECPERFAT*256]; -static int numFiles,maxLevel,numRootFiles; -static int *dirEntriesInCluster, clusterNum, firstDirEntCluster, - lastDirEntCluster, lastFileDataCluster; -static int activeDirEnt=-1; -static u32 bufferStart; -static u32 fileStartLBA,fileEndLBA; -static u16 freadBuffer[256]; -static FILE * hFile; -static char fpath[255+1]; -static BOOL cflashDeviceEnabled = FALSE; - -static std::string sFlashPath; - -static EMUFILE* file; - -// =========================== -BOOL inited; - -static int lfn_checksum( void) -{ - int i; - u8 chk = 0; - - for (i=0; i < (NAME_LEN + EXT_LEN); i++) - { - chk = ((chk & 1) ? 0x80 : 0) + (chk >> 1) + - (i < NAME_LEN ? files[numFiles].name[i] : files[numFiles].ext[i - NAME_LEN]); - } - return chk; -} - -// Add a DIR_ENT for the files -static void add_file(char *fname, FsEntry * entry, int fileLevel) -{ - int i,j,k,n; - u8 chk; - - if (numFiles < MAXFILES-1) - { - if (strcmp(fname,"..") != 0) - { - for (i=strlen(fname)-1; i>=0; i--) - if (fname[i]=='.') break; - if ((i==0)&&(strcmp(fname,".")==0)) i = 1; - if (i<0) i = strlen(fname); - for (j=0; j=strlen(fname)) break; - files[numFiles].ext[j] = fname[j+i+1]; - } - for (; j<3; j++) - files[numFiles].ext[j] = 0x20; - - fileLink[fileLevel].filesInDir += 1; - - // See if LFN entries need to be added - if (strlen(entry->cAlternateFileName)>0) - { - char *p = NULL; - - chk = lfn_checksum(); - k = (strlen(entry->cFileName)/13) + (((strlen(entry->cFileName)%13)!=0)?1:0); - numFiles += k; - - fileLink[fileLevel].filesInDir += k; - - n = 0; - j = 13; - for (i=0; (size_t)icFileName); i++) - { - if (j == 13) - { - n++; - p = (char*)&files[numFiles-n].name[0]; - fileLink[numFiles-n].parent = fileLevel; - p[0] = n; - ((DIR_ENT*)p)->attrib = ATTRIB_LFN; - p[0xD] = chk; - j = 0; - } - *(p + lfnPos[j]) = entry->cFileName[i]; - *(p + lfnPos[j]+1) = 0; - j++; - } - for (; j<13; j++) - { - *(p + lfnPos[j]) = entry->cFileName[i]; - *(p + lfnPos[j]+1) = 0; - } - if (p != NULL) - p[0] |= 0x40; // END - for (i=strlen(fname)-1; i>=0; i--) - if (fname[i]=='.') break; - if ((i==0)&&(strcmp(fname,".")==0)) i = 1; - if (i<0) i = strlen(fname); - for (j=0; j=strlen(fname)) break; - files[numFiles].ext[j] = fname[j+i+1]; - } - for (; j<3; j++) - files[numFiles].ext[j] = 0x20; - } - - files[numFiles].fileSize = entry->fileSize; - - if (entry->flags & FS_IS_DIR) - { - if (strcmp(fname,".")==0) - fileLink[numFiles].level = maxLevel; - else - fileLink[numFiles].level = maxLevel+1; - files[numFiles].attrib = ATTRIB_DIR; - } - else - files[numFiles].attrib = 0; - - fileLink[numFiles].parent = fileLevel; - - numFiles++; - } - else - if (fileLevel > 0) - { - fileLink[fileLevel].filesInDir += 1; - strncpy((char*)&files[numFiles].name[0],".. ",NAME_LEN); - strncpy((char*)&files[numFiles].ext[0]," ",EXT_LEN); - fileLink[numFiles].parent = fileLevel; - files[numFiles].attrib = 0x10; - numFiles++; - } - } -} - -enum EListCallbackArg { - EListCallbackArg_Item, EListCallbackArg_Pop -}; - -typedef void (*ListCallback)(FsEntry* fs, EListCallbackArg); - -// List all files and subdirectories recursively -static void list_files(const char *filepath, ListCallback list_callback) -{ - char DirSpec[255+1], SubDir[255+1]; - FsEntry entry; - void * hFind; - char *fname; - u32 dwError; - int fileLevel; - - maxLevel++; - fileLevel = maxLevel; - - strncpy(DirSpec, filepath, ARRAY_SIZE(DirSpec)); - DirSpec[255] = 0 ; // hard limit the string here - - hFind = FsReadFirst(DirSpec, &entry); - if (hFind == NULL) return; - - fname = (strlen(entry.cAlternateFileName)>0) ? entry.cAlternateFileName : entry.cFileName; - list_callback(&entry,EListCallbackArg_Item); - //add_file(fname, &entry, fileLevel); - - while (FsReadNext(hFind, &entry) != 0) - { - fname = (strlen(entry.cAlternateFileName)>0) ? entry.cAlternateFileName : entry.cFileName; - //add_file(fname, &entry, fileLevel); - list_callback(&entry,EListCallbackArg_Item); - printf("cflash added %s\n",entry.cFileName); - - if (numFiles==MAXFILES-1) break; - - if ((entry.flags & FS_IS_DIR) && (strcmp(fname, ".")) && (strcmp(fname, ".."))) - { - if (strlen(fname)+strlen(filepath)+2 < 256) - { - sprintf(SubDir, "%s%c%s", filepath, FS_SEPARATOR, fname); - list_files(SubDir, list_callback); - list_callback(&entry, EListCallbackArg_Pop); - } - } - } - - dwError = FsError(); - FsClose(hFind); - if (dwError != FS_ERR_NO_MORE_FILES) return; - - //if (numFiles < MAXFILES) - //{ - // fileLink[numFiles].parent = fileLevel; - // files[numFiles++].name[0] = 0; - //} -} - -static u64 dataSectors = 0; -void count_ListCallback(FsEntry* fs, EListCallbackArg arg) -{ - if(arg == EListCallbackArg_Pop) return; - u32 sectors = 1; - if(fs->flags & FS_IS_DIR) - { - } - else - sectors += (fs->fileSize+511)/512 + 1; - dataSectors += sectors; -} - -static std::string currPath; -static std::stack pathStack; -static std::stack virtPathStack; -static std::string currVirtPath; -void build_ListCallback(FsEntry* fs, EListCallbackArg arg) -{ - char* fname = (strlen(fs->cAlternateFileName)>0) ? fs->cAlternateFileName : fs->cFileName; - - //we use cFileName always because it is a LFN and we are making sure that we always make a fat32 image - fname = fs->cFileName; - - if(arg == EListCallbackArg_Pop) - { - currPath = pathStack.top(); - pathStack.pop(); - currVirtPath = virtPathStack.top(); - virtPathStack.pop(); - return; - } - - if(fs->flags & FS_IS_DIR) - { - if(!strcmp(fname,".")) return; - if(!strcmp(fname,"..")) return; - - pathStack.push(currPath); - virtPathStack.push(currVirtPath); - - currVirtPath = currVirtPath + "/" + fname; - bool ok = LIBFAT::MkDir(currVirtPath.c_str()); - - if(!ok) - printf("ERROR adding dir %s via libfat\n",currVirtPath.c_str()); - - currPath = currPath + std::string(1,FS_SEPARATOR) + fname; - return; - } - else - { - std::string path = currPath + std::string(1,FS_SEPARATOR) + fname; - - FILE* inf = fopen(path.c_str(),"rb"); - if(inf) - { - fseek(inf,0,SEEK_END); - long len = ftell(inf); - fseek(inf,0,SEEK_SET); - u8 *buf = new u8[len]; - fread(buf,1,len,inf); - fclose(inf); - - std::string path = currVirtPath + "/" + fname; - bool ok = LIBFAT::WriteFile(path.c_str(),buf,len); - if(!ok) - printf("ERROR adding file %s via libfat\n",path.c_str()); - delete[] buf; - } - } - -} - - -// Set up the MBR, FAT and DIR_ENTs -static BOOL cflash_build_fat() -{ - dataSectors = 0; - currPath = sFlashPath; - currVirtPath = ""; - list_files(sFlashPath.c_str(), count_ListCallback); - - dataSectors += 8; //a few for reserved sectors, etc. - - dataSectors += 16*1024*1024/512; //add 16MB worth of write space. this is probably enough for anyone, but maybe it should be configurable. - //we could always suggest to users to add a big file to their directory to overwrite (that would cause the image to get padded) - - //this seems to be the minimum size that will turn into a solid fat32 - if(dataSectors<36*1024*1024/512) - dataSectors = 36*1024*1024/512; - - if(dataSectors>=(0x80000000>>9)) - { - printf("error allocating memory for fat (%d KBytes)\n",(dataSectors*512)/1024); - printf("total fat sizes > 2GB are never going to work\n"); - } - - delete file; - try - { - file = new EMUFILE_MEMORY(dataSectors*512); - } - catch(std::bad_alloc) - { - printf("error allocating memory for fat (%d KBytes)\n",(dataSectors*512)/1024); - printf("(out of memory)\n"); - return FALSE; - } - //file = new EMUFILE_FILE("c:\\temp.ima","rb+"); - - //format the disk - { - EmuFat fat(file); - EmuFatVolume vol; - u8 ok = vol.init(&fat); - vol.formatNew(dataSectors); - - //ensure we are working in memory, just in case we were testing with a disk file. - //libfat will need to go straight to memory (for now; we could easily change it to work with the disk) - file = file->memwrap(); - } - EMUFILE_MEMORY* memf = (EMUFILE_MEMORY*)file; - - //setup libfat and write all the files through it - LIBFAT::Init(memf->buf(),memf->size()); - list_files(sFlashPath.c_str(), build_ListCallback); - LIBFAT::Shutdown(); - - - //FILE* outf = fopen("d:\\test.ima","wb"); - //EMUFILE_MEMORY* memf = (EMUFILE_MEMORY*)file; - //fwrite(memf->buf(),1,memf->size(),outf); - //fclose(outf); - - - - //int i,j,k,l, - //clust,numClusters, - //clusterNum2,rootCluster; - //int fileLevel; - - //numFiles = 0; - //fileLevel = -1; - //maxLevel = -1; - - //files = (DIR_ENT *) malloc(MAXFILES*sizeof(DIR_ENT)); - //memset(files,0,MAXFILES*sizeof(DIR_ENT)); - //if (files == NULL) return FALSE; - //fileLink = (FILE_INFO *) malloc(MAXFILES*sizeof(FILE_INFO)); - //if (fileLink == NULL) - //{ - // free(files); - // return FALSE; - //} - - //for (i=0; i>8; - // clust += l; - // numClusters += l; - // } - // } - // else - // dirEntries[k-1].startCluster = clusterNum; - // } - // if (i==0) numRootFiles++; - // dirEntriesInCluster[clusterNum]++; - // if (dirEntriesInCluster[clusterNum]==256) - // clusterNum++; - // } - // } - // clusterNum = clusterNum2 + ((fileLink[i].filesInDir)>>8) + 1; - // numClusters++; - //} - - //// Free the file indexing buffer - //free(files); - //free(fileLink); - - //// Set up the MBR - //MBR.bytesPerSector = 512; - //MBR.numFATs = 1; - //// replaced strcpy with strncpy. It doesnt matter here, as the strings are constant - //// but we should extingish all unrestricted strcpy,strcat from the project - //strncpy((char*)&MBR.OEMName[0],"DESMUM",8); - //strncpy((char*)&MBR.fat16.fileSysType[0],"FAT16 ",8); - //MBR.reservedSectors = SECRESV; - //MBR.numSectors = 524288; - //MBR.numSectorsSmall = 0; - //MBR.sectorsPerCluster = SECPERCLUS; - //MBR.sectorsPerFAT = SECPERFAT; - //MBR.rootEntries = 512; - //MBR.fat16.signature = 0xAA55; - //MBR.mediaDesc = 1; - - //filesysFAT = 0 + MBR.reservedSectors; - //filesysRootDir = filesysFAT + (MBR.numFATs * MBR.sectorsPerFAT); - //filesysData = filesysRootDir + ((MBR.rootEntries * sizeof(DIR_ENT)) / 512); - - //// Set up the cluster values for all subdirectories - //clust = filesysData / SECPERCLUS; - //firstDirEntCluster = clust; - //for (i=1; i rootCluster) - // dirEntries[i].startCluster += clust-rootCluster; - // } - //} - //lastDirEntCluster = clust+numClusters-1; - - //// Set up the cluster values for all files - //clust += numClusters; //clusterNum; - //for (i=0; i 0) - // { - // if (dirEntries[i].startCluster+j < MAXFILES) - // FAT16[dirEntries[i].startCluster+j] = dirEntries[i].startCluster+j+1; - // j++; - // l -= (512*16); - // } - // if ((dirEntries[i].attrib & ATTRIB_DIR)==0) - // { - // if (dirEntries[i].startCluster+j < MAXFILES) - // FAT16[dirEntries[i].startCluster+j] = 0xFFFF; - // } - // k = dirEntries[i].startCluster+j; - // } - //} - - //for (i=(filesysData/SECPERCLUS); ifail()) - { - INFO("Failed to open file %s\n", sFlashPath.c_str()); - delete file; - file = NULL; - } - } - - // READY - cf_reg_sts = 0x58; - - currLBA = 0; - cf_reg_lba1 = cf_reg_lba2 = - cf_reg_lba3 = cf_reg_lba4 = 0; - - inited = TRUE; - return init_good; -} - -// Convert a space-padded 8.3 filename into an asciiz string -static void fatstring_to_asciiz(int dirent,char *out,DIR_ENT *d) -{ - int i,j; - DIR_ENT *pd; - - if (d == NULL) - pd = &dirEntries[dirent]; - else - pd = d; - - for (i=0; iname[i] == ' ') break; - out[i] = pd->name[i]; - } - if ((pd->attrib & 0x10)==0) - { - out[i++] = '.'; - for (j=0; jext[j] == ' ') break; - out[i++] = pd->ext[j]; - } - } - out[i] = '\0'; -} - -// Resolve the path of a files by working backwards through the directory entries -static void resolve_path(int dirent) -{ - int i; - char dirname[128]; - - while (dirEntryLink[dirent].parent > 0) - { - for (i=0; i= bufferStart + 512)) - { - if (!hFile) - { - CFLASHLOG("fread_buffered with hFile null with offset %lu and bufferStart %lu\n", - offset, bufferStart); - return 0; - } - fseek(hFile, offset, SEEK_SET); - elems_read += fread(&freadBuffer, 1, 512, hFile); - bufferStart = offset; - } - - return freadBuffer[(offset-bufferStart)>>1]; - } - if (activeDirEnt != -1) - fclose(hFile); - - strncpy(fpath,sFlashPath.c_str(),ARRAY_SIZE(fpath)); - strncat(fpath,DIR_SEP,ARRAY_SIZE(fpath)-strlen(fpath)); - - resolve_path(dirent); - - fatstring_to_asciiz(dirent,fname,NULL); - strncat(fpath,fname,ARRAY_SIZE(fpath)-strlen(fpath)); - - CFLASHLOG("CFLASH Opening %s\n",fpath); - hFile = fopen(fpath, "rb"); - if (!hFile) return 0; - bufferStart = offset; - fseek(hFile, offset, SEEK_SET); - elems_read += fread(&freadBuffer, 1, 512, hFile); - - bufferStart = offset; - activeDirEnt = dirent; - fileStartLBA = (dirEntries[dirent].startCluster*512*SECPERCLUS); - fileEndLBA = fileStartLBA + dirEntries[dirent].fileSize; - - return freadBuffer[(offset-bufferStart)>>1]; -} - -static unsigned int cflash_read(unsigned int address) -{ - unsigned int ret_value = 0; - size_t elems_read = 0; - - switch (address) - { - case CF_REG_STS: - ret_value = cf_reg_sts; - break; - - case CF_REG_DATA: - if (cf_reg_cmd == CF_CMD_READ) - { - if(file) - { - u8 data[2]; - file->fseek(currLBA, SEEK_SET); - elems_read += file->fread(data,2); - ret_value = data[1] << 8 | data[0]; - } - currLBA += 2; - } - break; - - case CF_REG_CMD: - break; - - case CF_REG_LBA1: - ret_value = cf_reg_lba1; - break; - } - - return ret_value; -} - -static void cflash_write(unsigned int address,unsigned int data) -{ - static u8 sector_data[512]; - static u32 sector_write_index = 0; - - switch (address) - { - case CF_REG_STS: - cf_reg_sts = data&0xFFFF; - break; - - case CF_REG_DATA: - if (cf_reg_cmd == CF_CMD_WRITE) - { - { - sector_data[sector_write_index] = (data >> 0) & 0xff; - sector_data[sector_write_index + 1] = (data >> 8) & 0xff; - - sector_write_index += 2; - - if (sector_write_index == 512) - { - CFLASHLOG( "Write sector to %ld\n", currLBA); - size_t written = 0; - - //TODO - calling size() every time we write something is sort of unnecessarily slow in the case of disk-backed files... - if(file) - if(currLBA + 512 < file->size()) - { - file->fseek(currLBA,SEEK_SET); - - while(written < 512) - { - size_t todo = 512-written; - file->fwrite(§or_data[written], todo); - size_t cur_write = todo; - written += cur_write; - if ( cur_write == (size_t)-1) break; - } - } - - CFLASHLOG("Wrote %u bytes\n", written); - - currLBA += 512; - sector_write_index = 0; - } - } - } - break; - - case CF_REG_CMD: - cf_reg_cmd = data&0xFF; - cf_reg_sts = 0x58; // READY - break; - - case CF_REG_LBA1: - cf_reg_lba1 = data&0xFF; - currLBA = (currLBA&0xFFFFFF00)| cf_reg_lba1; - break; - - case CF_REG_LBA2: - cf_reg_lba2 = data&0xFF; - currLBA = (currLBA&0xFFFF00FF)|(cf_reg_lba2<<8); - break; - - case CF_REG_LBA3: - cf_reg_lba3 = data&0xFF; - currLBA = (currLBA&0xFF00FFFF)|(cf_reg_lba3<<16); - break; - - case CF_REG_LBA4: - cf_reg_lba4 = data&0xFF; - - if ((cf_reg_lba4 & 0xf0) == CF_CMD_LBA) - { - currLBA = (currLBA&0x00FFFFFF)|((cf_reg_lba4&0x0F)<<24); - currLBA *= 512; - sector_write_index = 0; - } - break; - } -} - -static void cflash_close( void) -{ - if (!inited) return; - if (!CFlash_IsUsingPath()) - { - delete file; - file = NULL; - } - else - { - int i; - - if (cflashDeviceEnabled) - { - cflashDeviceEnabled = FALSE; - - for (i=0; i + #include "../slot1.h" #include "../registers.h" #include "../MMU.h" #include "../NDSSystem.h" -#include +#include "../emufile.h" -static FILE *img = NULL; +static EMUFILE *img = NULL; static u32 write_count = 0; static u32 write_enabled = 0; static void init_r4_flash() @@ -31,11 +33,11 @@ static void init_r4_flash() srand(time(NULL)); if (!img) - img = fopen("DLDI_R4DS.img", "r+b"); + img = slot1GetFatImage(); if(!img) { - INFO("DLDI_R4DS.img not found\n"); + INFO("slot1 fat not successfully mounted\n"); } } @@ -48,9 +50,13 @@ static BOOL init() return TRUE; } -static void reset() {} +static void reset() { + init_r4_flash(); +} -static void close() {} +static void close() { + img = NULL; +} static void write08(u8 PROCNUM, u32 adr, u8 val) {} @@ -67,14 +73,14 @@ static void write32_GCROMCTRL(u32 val) case 0xB9: case 0xBA: card.address = (card.command[1] << 24) | (card.command[2] << 16) | (card.command[3] << 8) | card.command[4]; - fseek(img,card.address,SEEK_SET); + img->fseek(card.address,SEEK_SET); break; case 0xBB: write_enabled = 1; write_count = 0x80; case 0xBC: card.address = (card.command[1] << 24) | (card.command[2] << 16) | (card.command[3] << 8) | card.command[4]; - fseek(img,card.address,SEEK_SET); + img->fseek(card.address,SEEK_SET); break; } } @@ -105,8 +111,8 @@ static void write32_GCDATAIN(u32 val) { if(write_count && write_enabled) { - fwrite(&val, 1, 4, img); - fflush(img); + img->fwrite(&val, 4); + img->fflush(); write_count--; } break; @@ -186,7 +192,7 @@ static u32 read32_GCDATAIN() break; case 0xBA: //INFO("Read from sd at sector %08X at adr %08X ",card.address/512,ftell(img)); - fread(&val, 1, 4, img); + img->fread(&val, 4); //INFO("val %08X\n",val); break; diff --git a/desmume/src/addons/slot2_mpcf.cpp b/desmume/src/addons/slot2_mpcf.cpp new file mode 100644 index 000000000..8c4b9d0a3 --- /dev/null +++ b/desmume/src/addons/slot2_mpcf.cpp @@ -0,0 +1,344 @@ +/* Copyright (C) 2006 yopyop + Copyright (C) 2006 Mic + Copyright (C) 2009-2011 DeSmuME team + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../addons.h" +#include +#include +#include "debug.h" +#include +#include +#include + +#include "types.h" +#include "../utils/vfat.h" +#include "../path.h" + +#include "MMU.h" +#include "NDSSystem.h" + +// Set up addresses for GBAMP +#define CF_REG_DATA 0x9000000 +#define CF_REG_ERR 0x9020000 +#define CF_REG_SEC 0x9040000 +#define CF_REG_LBA1 0x9060000 +#define CF_REG_LBA2 0x9080000 +#define CF_REG_LBA3 0x90A0000 +#define CF_REG_LBA4 0x90C0000 +#define CF_REG_CMD 0x90E0000 +#define CF_REG_STS 0x98C0000 + +// CF Card commands +#define CF_CMD_LBA 0xE0 +#define CF_CMD_READ 0x20 +#define CF_CMD_WRITE 0x30 + +static u16 cf_reg_sts, + cf_reg_lba1, + cf_reg_lba2, + cf_reg_lba3, + cf_reg_lba4, + cf_reg_cmd; +static off_t currLBA; + +static const int lfnPos[13] = {1,3,5,7,9,14,16,18,20,22,24,28,30}; + +static u32 fileStartLBA,fileEndLBA; +static std::string sFlashPath; +static BOOL cflashDeviceEnabled = FALSE; + +static EMUFILE* file; + +// =========================== +BOOL inited; + +enum EListCallbackArg { + EListCallbackArg_Item, EListCallbackArg_Pop +}; + +static BOOL cflash_init() +{ + if (inited) return FALSE; + BOOL init_good = FALSE; + + CFLASHLOG("CFlash_Mode: %d\n",CFlash_Mode); + + if (CFlash_Mode == ADDON_CFLASH_MODE_RomPath) + { + sFlashPath = path.pathToRoms; + INFO("Using CFlash directory of rom: %s\n", sFlashPath.c_str()); + } + else if(CFlash_Mode == ADDON_CFLASH_MODE_Path) + { + sFlashPath = CFlash_Path; + INFO("Using CFlash directory: %s\n", sFlashPath.c_str()); + } + + if(CFlash_IsUsingPath()) + { + cflashDeviceEnabled = FALSE; + currLBA = 0; + + fileStartLBA = fileEndLBA = 0xFFFFFFFF; + VFAT vfat; + bool ret = vfat.build(sFlashPath.c_str(),16); //allocate 16MB extra for writing. this is probably enough for anyone, but maybe it should be configurable. + //we could always suggest to users to add a big file to their directory to overwrite (that would cause the image to get padded) + + if(!ret) + { + CFLASHLOG("FAILED cflash_build_fat\n"); + return FALSE; + } + + file = vfat.detach(); + + cf_reg_sts = 0x58; // READY + + cflashDeviceEnabled = TRUE; + init_good = TRUE; + } + else + { + sFlashPath = CFlash_Path; + INFO("Using CFlash disk image file %s\n", sFlashPath.c_str()); + file = new EMUFILE_FILE(sFlashPath.c_str(),"rb+"); + if(file->fail()) + { + INFO("Failed to open file %s\n", sFlashPath.c_str()); + delete file; + file = NULL; + } + } + + // READY + cf_reg_sts = 0x58; + + currLBA = 0; + cf_reg_lba1 = cf_reg_lba2 = + cf_reg_lba3 = cf_reg_lba4 = 0; + + inited = TRUE; + return init_good; +} + +static unsigned int cflash_read(unsigned int address) +{ + unsigned int ret_value = 0; + size_t elems_read = 0; + + switch (address) + { + case CF_REG_STS: + ret_value = cf_reg_sts; + break; + + case CF_REG_DATA: + if (cf_reg_cmd == CF_CMD_READ) + { + if(file) + { + u8 data[2]; + file->fseek(currLBA, SEEK_SET); + elems_read += file->fread(data,2); + ret_value = data[1] << 8 | data[0]; + } + currLBA += 2; + } + break; + + case CF_REG_CMD: + break; + + case CF_REG_LBA1: + ret_value = cf_reg_lba1; + break; + } + + return ret_value; +} + +static void cflash_write(unsigned int address,unsigned int data) +{ + static u8 sector_data[512]; + static u32 sector_write_index = 0; + + switch (address) + { + case CF_REG_STS: + cf_reg_sts = data&0xFFFF; + break; + + case CF_REG_DATA: + if (cf_reg_cmd == CF_CMD_WRITE) + { + { + sector_data[sector_write_index] = (data >> 0) & 0xff; + sector_data[sector_write_index + 1] = (data >> 8) & 0xff; + + sector_write_index += 2; + + if (sector_write_index == 512) + { + CFLASHLOG( "Write sector to %ld\n", currLBA); + size_t written = 0; + + if(file) + if(currLBA + 512 < file->size()) + { + file->fseek(currLBA,SEEK_SET); + + while(written < 512) + { + size_t todo = 512-written; + file->fwrite(§or_data[written], todo); + size_t cur_write = todo; + written += cur_write; + if ( cur_write == (size_t)-1) break; + } + } + + CFLASHLOG("Wrote %u bytes\n", written); + + currLBA += 512; + sector_write_index = 0; + } + } + } + break; + + case CF_REG_CMD: + cf_reg_cmd = data&0xFF; + cf_reg_sts = 0x58; // READY + break; + + case CF_REG_LBA1: + cf_reg_lba1 = data&0xFF; + currLBA = (currLBA&0xFFFFFF00)| cf_reg_lba1; + break; + + case CF_REG_LBA2: + cf_reg_lba2 = data&0xFF; + currLBA = (currLBA&0xFFFF00FF)|(cf_reg_lba2<<8); + break; + + case CF_REG_LBA3: + cf_reg_lba3 = data&0xFF; + currLBA = (currLBA&0xFF00FFFF)|(cf_reg_lba3<<16); + break; + + case CF_REG_LBA4: + cf_reg_lba4 = data&0xFF; + + if ((cf_reg_lba4 & 0xf0) == CF_CMD_LBA) + { + currLBA = (currLBA&0x00FFFFFF)|((cf_reg_lba4&0x0F)<<24); + currLBA *= 512; + sector_write_index = 0; + } + break; + } +} + +static void cflash_close( void) +{ + if (!inited) return; + if (!CFlash_IsUsingPath()) + { + delete file; + file = NULL; + } + else + { + int i; + cflashDeviceEnabled = FALSE; + } + inited = FALSE; +} + +static BOOL init(void) +{ + return TRUE; +} + +static void reset(void) +{ + cflash_close(); + cflash_init(); +} + +static void close(void) +{ + cflash_close(); +} + +static void config(void) +{ +} + +static void write08(u32 adr, u8 val) +{ + cflash_write(adr, val); +} + +static void write16(u32 adr, u16 val) +{ + cflash_write(adr, val); +} + +static void write32(u32 adr, u32 val) +{ + cflash_write(adr, val); +} + +static u8 read08(u32 adr) +{ + return (cflash_read(adr)); +} + +static u16 read16(u32 adr) +{ + return (cflash_read(adr)); +} + +static u32 read32(u32 adr) +{ + return (cflash_read(adr)); +} + +static void info(char *info) +{ + strcpy(info, "MPCF Flash Card Device"); +} + +ADDONINTERFACE addonCFlash = { + "MPCF Flash Card Device", + init, + reset, + close, + config, + write08, + write16, + write32, + read08, + read16, + read32, + info}; + +#undef CFLASHDEBUG diff --git a/desmume/src/commandline.cpp b/desmume/src/commandline.cpp index 614719809..bb25c2ea8 100644 --- a/desmume/src/commandline.cpp +++ b/desmume/src/commandline.cpp @@ -1,6 +1,4 @@ -/* commandline.cpp - - Copyright (C) 2009-2010 DeSmuME team +/* Copyright (C) 2009-2011 DeSmuME team This file is part of DeSmuME @@ -52,6 +50,7 @@ CommandLine::CommandLine() , _rigorous_timing(0) , _advanced_timing(-1) , _slot1(NULL) +, _slot1_fat_dir(NULL) , depth_threshold(-1) , load_slot(-1) , arm9_gdb_port(0) @@ -94,6 +93,7 @@ void CommandLine::loadCommonOptions() { "rigorous-timing", 0, 0, G_OPTION_ARG_INT, &_rigorous_timing, "Use some rigorous timings instead of unrealistically generous (default 0)", "RIGOROUS_TIMING"}, { "advanced-timing", 0, 0, G_OPTION_ARG_INT, &_advanced_timing, "Use advanced BUS-level timing (default 1)", "ADVANCED_TIMING"}, { "slot1", 0, 0, G_OPTION_ARG_STRING, &_slot1, "Device to load in slot 1 (default retail)", "SLOT1"}, + { "slot1-fat-dir", 0, 0, G_OPTION_ARG_STRING, &_slot1_fat_dir, "Directory to scan for slot 1", "SLOT1_DIR"}, { "depth-threshold", 0, 0, G_OPTION_ARG_INT, &depth_threshold, "Depth comparison threshold (default 0)", "DEPTHTHRESHOLD"}, #ifndef _MSC_VER { "disable-sound", 0, 0, G_OPTION_ARG_NONE, &disable_sound, "Disables the sound emulation", NULL}, @@ -119,6 +119,7 @@ bool CommandLine::parse(int argc,char **argv) return false; } + if(_slot1_fat_dir) slot1_fat_dir = _slot1_fat_dir; if(_slot1) slot1 = _slot1; if(slot1.size() != 0) str_lcase((char*)&slot1[0]); if(_play_movie_file) play_movie_file = _play_movie_file; @@ -227,10 +228,12 @@ void CommandLine::process_addonCommands() is_cflash_configured = true; } + if(slot1_fat_dir != "") + slot1SetFatDir(slot1_fat_dir); + if(slot1 == "retail") slot1Change(NDS_SLOT1_RETAIL); else if(slot1 == "r4") slot1Change(NDS_SLOT1_R4); - } diff --git a/desmume/src/commandline.h b/desmume/src/commandline.h index fbd8c5346..9e6a7079b 100644 --- a/desmume/src/commandline.h +++ b/desmume/src/commandline.h @@ -1,6 +1,4 @@ -/* commandline.h - - Copyright (C) 2009-2010 DeSmuME team +/* Copyright (C) 2009-2011 DeSmuME team This file is part of DeSmuME @@ -50,6 +48,7 @@ public: std::string cflash_path; std::string gbaslot_rom; std::string slot1; + std::string slot1_fat_dir; #ifndef _MSC_VER int disable_sound; int disable_limiter; @@ -91,6 +90,7 @@ private: int _rigorous_timing; int _advanced_timing; char* _slot1; + char *_slot1_fat_dir; }; #endif diff --git a/desmume/src/emufile.cpp b/desmume/src/emufile.cpp index fbe004f89..7306bde07 100644 --- a/desmume/src/emufile.cpp +++ b/desmume/src/emufile.cpp @@ -61,7 +61,7 @@ size_t EMUFILE_MEMORY::_fread(const void *ptr, size_t bytes){ void EMUFILE_FILE::truncate(s32 length) { - fflush(fp); + ::fflush(fp); #ifdef _MSC_VER _chsize(_fileno(fp),length); #else diff --git a/desmume/src/emufile.h b/desmume/src/emufile.h index 6b2e4a622..99fa2e498 100644 --- a/desmume/src/emufile.h +++ b/desmume/src/emufile.h @@ -113,6 +113,7 @@ public: virtual int ftell() = 0; virtual int size() = 0; + virtual void fflush() = 0; virtual void truncate(s32 length) = 0; }; @@ -244,6 +245,8 @@ public: return pos; } + virtual void fflush() {} + void trim() { vec->resize(len); @@ -319,7 +322,7 @@ public: failbit = true; } - virtual int fseek(int offset, int origin){ + virtual int fseek(int offset, int origin) { return ::fseek(fp, offset, origin); } @@ -335,6 +338,10 @@ public: return len; } + virtual void fflush() { + ::fflush(fp); + } + }; #endif diff --git a/desmume/src/fat.h b/desmume/src/fat.h deleted file mode 100644 index 7ff4f7cf6..000000000 --- a/desmume/src/fat.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - FAT.H - Mic, 2006 - Structures taken from Michael Chisholm's FAT library -*/ - -#ifndef __FAT_H__ -#define __FAT_H__ - -#include "types.h" -#include "PACKED.h" -#include "PACKED_END.h" - -#define ATTRIB_DIR 0x10 -#define ATTRIB_LFN 0x0F - -#define FILE_FREE 0xE5 -/* Name and extension maximum length */ -#define NAME_LEN 8 -#define EXT_LEN 3 - -// Boot Sector - must be packed -#if defined(_MSC_VER) || defined(__INTEL_COMPILER) -#define DIR_SEP "\\" -#else -#define DIR_SEP "/" -#endif - -#include "PACKED.h" -struct boot_record -{ - u8 jmpBoot[3]; - u8 OEMName[8]; - // BIOS Parameter Block - u16 bytesPerSector; - u8 sectorsPerCluster; - u16 reservedSectors; - u8 numFATs; - u16 rootEntries; - u16 numSectorsSmall; - u8 mediaDesc; - u16 sectorsPerFAT; - u16 sectorsPerTrk; - u16 numHeads; - u32 numHiddenSectors; - u32 numSectors; - - struct - { - // Ext BIOS Parameter Block for FAT16 - u8 driveNumber; - u8 reserved1; - u8 extBootSig; - u32 volumeID; - u8 volumeLabel[11]; - u8 fileSysType[8]; - // Bootcode - u8 bootCode[448]; - u16 signature; - } __PACKED fat16; - -} __PACKED; -typedef struct boot_record BOOT_RECORD; -#include "PACKED_END.h" - -// Directory entry - must be packed -#include "PACKED.h" -struct dir_ent -{ - u8 name[NAME_LEN]; - u8 ext[EXT_LEN]; - u8 attrib; - u8 reserved; - u8 cTime_ms; - u16 cTime; - u16 cDate; - u16 aDate; - u16 startClusterHigh; - u16 mTime; - u16 mDate; - u16 startCluster; - u32 fileSize; -} __PACKED; -typedef struct dir_ent DIR_ENT; -#include "PACKED_END.h" - -#endif // diff --git a/desmume/src/mc.cpp b/desmume/src/mc.cpp index 30a68e639..a4952be7c 100644 --- a/desmume/src/mc.cpp +++ b/desmume/src/mc.cpp @@ -484,6 +484,7 @@ void BackupDevice::reset_command() default: //the archaic case: write the address and then some modulo-4 number of bytes //why modulo 4? who knows. + //SM64 (KOR) makes it here with autodetect_size=11 and nothing interesting in the buffer addr_size = autodetect_size & 3; break; } diff --git a/desmume/src/slot1.cpp b/desmume/src/slot1.cpp index 5bf223719..9f16e834a 100644 --- a/desmume/src/slot1.cpp +++ b/desmume/src/slot1.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2010 DeSmuME team +/* Copyright (C) 2010-2011 DeSmuME team This file is part of DeSmuME @@ -17,30 +17,57 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "slot1.h" #include +#include "types.h" +#include "slot1.h" + +#include "emufile.h" +#include "utils/vfat.h" + extern SLOT1INTERFACE slot1None; extern SLOT1INTERFACE slot1Retail; extern SLOT1INTERFACE slot1R4; +static EMUFILE* fatImage = NULL; +static std::string fatDir; + SLOT1INTERFACE slot1List[NDS_SLOT1_COUNT] = { slot1None, slot1Retail, slot1R4 }; -SLOT1INTERFACE slot1_device = slot1Retail; //default for frontends that dont even configure this -u8 slot1_device_type = NDS_SLOT1_RETAIL; +SLOT1INTERFACE slot1_device = slot1Retail; //default for frontends that dont even configure this +u8 slot1_device_type = NDS_SLOT1_RETAIL; + +static void scanDir() +{ + if(fatDir == "") return; + + delete fatImage; + fatImage = NULL; + + VFAT vfat; + if(vfat.build(fatDir.c_str(),16)) + { + fatImage = vfat.detach(); + } +} BOOL slot1Init() { + scanDir(); return slot1_device.init(); } void slot1Close() { slot1_device.close(); + + //be careful to do this second, maybe the device will write something more + delete fatImage; + fatImage = NULL; } void slot1Reset() @@ -56,4 +83,14 @@ BOOL slot1Change(NDS_SLOT1_TYPE changeToType) slot1_device_type = changeToType; slot1_device = slot1List[slot1_device_type]; return slot1_device.init(); +} + +void slot1SetFatDir(const std::string& dir) +{ + fatDir = dir; +} + +EMUFILE* slot1GetFatImage() +{ + return fatImage; } \ No newline at end of file diff --git a/desmume/src/slot1.h b/desmume/src/slot1.h index c9afac4d8..9f5adc3c0 100644 --- a/desmume/src/slot1.h +++ b/desmume/src/slot1.h @@ -20,10 +20,13 @@ #ifndef __SLOT1_H__ #define __SLOT1_H__ +#include #include "common.h" #include "types.h" #include "debug.h" +class EMUFILE; + struct SLOT1INTERFACE { // The name of the plugin, this name will appear in the plugins list @@ -65,10 +68,11 @@ enum NDS_SLOT1_TYPE NDS_SLOT1_COUNT // use for counter addons - MUST TO BE LAST!!! }; -extern BOOL slot1Init(); -extern void slot1Close(); -extern void slot1Reset(); -extern BOOL slot1Change(NDS_SLOT1_TYPE type); // change current adddon - +BOOL slot1Init(); +void slot1Close(); +void slot1Reset(); +BOOL slot1Change(NDS_SLOT1_TYPE type); // change current adddon +void slot1SetFatDir(const std::string& dir); +EMUFILE* slot1GetFatImage(); #endif //__ADDONS_H__ diff --git a/desmume/src/utils/dlditool.cpp b/desmume/src/utils/dlditool.cpp index 9a9c3ecab..fd694a4c1 100644 --- a/desmume/src/utils/dlditool.cpp +++ b/desmume/src/utils/dlditool.cpp @@ -649,6 +649,12 @@ bool tryPatch(void* data, size_t size) return false; } + if(memcmp(&pAH[DO_friendlyName],"Default (No interface)",22)) + { + printf("Would have been a candidate for auto-patch DLDI, but there was already a patch installed."); + return false; + } + //----should be able to patch OK----- addr_t memOffset; // Offset of DLDI after the file is loaded into memory diff --git a/desmume/src/emufat.cpp b/desmume/src/utils/emufat.cpp similarity index 100% rename from desmume/src/emufat.cpp rename to desmume/src/utils/emufat.cpp diff --git a/desmume/src/emufat.h b/desmume/src/utils/emufat.h similarity index 100% rename from desmume/src/emufat.h rename to desmume/src/utils/emufat.h diff --git a/desmume/src/emufat_types.h b/desmume/src/utils/emufat_types.h similarity index 100% rename from desmume/src/emufat_types.h rename to desmume/src/utils/emufat_types.h diff --git a/desmume/src/utils/vfat.cpp b/desmume/src/utils/vfat.cpp new file mode 100644 index 000000000..2d386ce16 --- /dev/null +++ b/desmume/src/utils/vfat.cpp @@ -0,0 +1,234 @@ +/* Copyright (C) 2006 yopyop + Copyright (C) 2006 Mic + Copyright (C) 2010-2011 DeSmuME team + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#include +#include +#include +#include + +#include "../types.h" +#include "../debug.h" +#include "../fs.h" + +#include "emufat.h" +#include "vfat.h" +#include "libfat/libfat_public_api.h" + + +enum EListCallbackArg { + EListCallbackArg_Item, EListCallbackArg_Pop +}; + +typedef void (*ListCallback)(FsEntry* fs, EListCallbackArg); + +// List all files and subdirectories recursively +static void list_files(const char *filepath, ListCallback list_callback) +{ + char DirSpec[255+1], SubDir[255+1]; + FsEntry entry; + void * hFind; + char *fname; + u32 dwError; + + strncpy(DirSpec, filepath, ARRAY_SIZE(DirSpec)); + DirSpec[255] = 0 ; // hard limit the string here + + hFind = FsReadFirst(DirSpec, &entry); + if (hFind == NULL) return; + + fname = (strlen(entry.cAlternateFileName)>0) ? entry.cAlternateFileName : entry.cFileName; + list_callback(&entry,EListCallbackArg_Item); + + while (FsReadNext(hFind, &entry) != 0) + { + fname = (strlen(entry.cAlternateFileName)>0) ? entry.cAlternateFileName : entry.cFileName; + list_callback(&entry,EListCallbackArg_Item); + printf("cflash added %s\n",entry.cFileName); + + if ((entry.flags & FS_IS_DIR) && (strcmp(fname, ".")) && (strcmp(fname, ".."))) + { + if (strlen(fname)+strlen(filepath)+2 < 256) + { + sprintf(SubDir, "%s%c%s", filepath, FS_SEPARATOR, fname); + list_files(SubDir, list_callback); + list_callback(&entry, EListCallbackArg_Pop); + } + } + } + + dwError = FsError(); + FsClose(hFind); + if (dwError != FS_ERR_NO_MORE_FILES) return; +} + +static u64 dataSectors = 0; +void count_ListCallback(FsEntry* fs, EListCallbackArg arg) +{ + if(arg == EListCallbackArg_Pop) return; + u32 sectors = 1; + if(fs->flags & FS_IS_DIR) + { + } + else + sectors += (fs->fileSize+511)/512 + 1; + dataSectors += sectors; +} + +static std::string currPath; +static std::stack pathStack; +static std::stack virtPathStack; +static std::string currVirtPath; +void build_ListCallback(FsEntry* fs, EListCallbackArg arg) +{ + char* fname = (strlen(fs->cAlternateFileName)>0) ? fs->cAlternateFileName : fs->cFileName; + + //we use cFileName always because it is a LFN and we are making sure that we always make a fat32 image + fname = fs->cFileName; + + if(arg == EListCallbackArg_Pop) + { + currPath = pathStack.top(); + pathStack.pop(); + currVirtPath = virtPathStack.top(); + virtPathStack.pop(); + return; + } + + if(fs->flags & FS_IS_DIR) + { + if(!strcmp(fname,".")) return; + if(!strcmp(fname,"..")) return; + + pathStack.push(currPath); + virtPathStack.push(currVirtPath); + + currVirtPath = currVirtPath + "/" + fname; + bool ok = LIBFAT::MkDir(currVirtPath.c_str()); + + if(!ok) + printf("ERROR adding dir %s via libfat\n",currVirtPath.c_str()); + + currPath = currPath + std::string(1,FS_SEPARATOR) + fname; + return; + } + else + { + std::string path = currPath + std::string(1,FS_SEPARATOR) + fname; + + FILE* inf = fopen(path.c_str(),"rb"); + if(inf) + { + fseek(inf,0,SEEK_END); + long len = ftell(inf); + fseek(inf,0,SEEK_SET); + u8 *buf = new u8[len]; + fread(buf,1,len,inf); + fclose(inf); + + std::string path = currVirtPath + "/" + fname; + bool ok = LIBFAT::WriteFile(path.c_str(),buf,len); + if(!ok) + printf("ERROR adding file %s via libfat\n",path.c_str()); + delete[] buf; + } + } + +} + + + +bool VFAT::build(const char* path, int extra_MB) +{ + dataSectors = 0; + currVirtPath = ""; + currPath = path; + list_files(path, count_ListCallback); + + dataSectors += 8; //a few for reserved sectors, etc. + + dataSectors += extra_MB*1024*1024/512; //add extra write space + //dataSectors += 16*1024*1024/512; //add 16MB worth of write space. this is probably enough for anyone, but maybe it should be configurable. + //we could always suggest to users to add a big file to their directory to overwrite (that would cause the image to get padded) + + //this seems to be the minimum size that will turn into a solid fat32 + if(dataSectors<36*1024*1024/512) + dataSectors = 36*1024*1024/512; + + if(dataSectors>=(0x80000000>>9)) + { + printf("error allocating memory for fat (%d KBytes)\n",(dataSectors*512)/1024); + printf("total fat sizes > 2GB are never going to work\n"); + } + + delete file; + try + { + file = new EMUFILE_MEMORY(dataSectors*512); + } + catch(std::bad_alloc) + { + printf("error allocating memory for fat (%d KBytes)\n",(dataSectors*512)/1024); + printf("(out of memory)\n"); + return false; + } + + //debug.. + //file = new EMUFILE_FILE("c:\\temp.ima","rb+"); + + //format the disk + { + EmuFat fat(file); + EmuFatVolume vol; + u8 ok = vol.init(&fat); + vol.formatNew(dataSectors); + + //ensure we are working in memory, just in case we were testing with a disk file. + //libfat will need to go straight to memory (for now; we could easily change it to work with the disk) + file = file->memwrap(); + } + EMUFILE_MEMORY* memf = (EMUFILE_MEMORY*)file; + + //setup libfat and write all the files through it + LIBFAT::Init(memf->buf(),memf->size()); + list_files(path, build_ListCallback); + LIBFAT::Shutdown(); + + return true; +} + +VFAT::VFAT() + : file(NULL) +{ +} + +VFAT::~VFAT() +{ + delete file; +} + +EMUFILE* VFAT::detach() +{ + EMUFILE* ret = file; + file = NULL; + return ret; +} \ No newline at end of file diff --git a/desmume/src/utils/vfat.h b/desmume/src/utils/vfat.h new file mode 100644 index 000000000..89ea16127 --- /dev/null +++ b/desmume/src/utils/vfat.h @@ -0,0 +1,39 @@ +/* Copyright (C) 2011 DeSmuME team + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + + +#ifndef _VFAT_H + +class EMUFILE; + +//THIS CLASS IS NOT THREAD SAFE!! SORRY SO SLOPPY +class VFAT +{ +public: + VFAT(); + ~VFAT(); + bool build(const char* path, int extra_MB=0); + + EMUFILE* detach(); + +private: + EMUFILE* file; +}; + +#endif //_VFAT_H diff --git a/desmume/src/windows/DeSmuME_2005.vcproj b/desmume/src/windows/DeSmuME_2005.vcproj index 2bab75f0a..6ea31a92f 100644 --- a/desmume/src/windows/DeSmuME_2005.vcproj +++ b/desmume/src/windows/DeSmuME_2005.vcproj @@ -454,7 +454,7 @@ StructMemberAlignment="0" BufferSecurityCheck="false" EnableFunctionLevelLinking="false" - EnableEnhancedInstructionSet="2" + EnableEnhancedInstructionSet="0" FloatingPointModel="2" RuntimeTypeInfo="false" WarningLevel="3" @@ -1232,7 +1232,7 @@ > @@ -1242,7 +1242,7 @@ > @@ -1252,7 +1252,7 @@ > @@ -1262,7 +1262,7 @@ > @@ -1272,7 +1272,7 @@ > @@ -1282,7 +1282,7 @@ > @@ -1377,6 +1377,18 @@ RelativePath="..\utils\dlditool.cpp" > + + + + + + @@ -1405,6 +1417,14 @@ RelativePath="..\utils\valuearray.h" > + + + + @@ -1611,10 +1631,6 @@ - - @@ -1651,6 +1667,10 @@ RelativePath="..\addons\slot1_retail.cpp" > + + - - - - - - diff --git a/desmume/src/windows/DeSmuME_2008.vcproj b/desmume/src/windows/DeSmuME_2008.vcproj index fe3ba78e5..f21af1276 100644 --- a/desmume/src/windows/DeSmuME_2008.vcproj +++ b/desmume/src/windows/DeSmuME_2008.vcproj @@ -718,18 +718,6 @@ RelativePath="..\driver.h" > - - - - - - @@ -1005,10 +993,6 @@ - - @@ -1045,6 +1029,10 @@ RelativePath="..\addons\slot1_retail.cpp" > + + + + + + @@ -1109,6 +1105,14 @@ RelativePath="..\utils\valuearray.h" > + + + + @@ -2005,7 +2009,7 @@ > @@ -2015,7 +2019,7 @@ > @@ -2025,7 +2029,7 @@ > @@ -2035,7 +2039,7 @@ > @@ -2045,7 +2049,7 @@ > @@ -2055,7 +2059,7 @@ > diff --git a/desmume/src/windows/DeSmuME_2010.vcxproj b/desmume/src/windows/DeSmuME_2010.vcxproj index fd97a78af..f353db9f6 100644 --- a/desmume/src/windows/DeSmuME_2010.vcxproj +++ b/desmume/src/windows/DeSmuME_2010.vcxproj @@ -432,6 +432,7 @@ + @@ -447,7 +448,6 @@ - @@ -475,6 +475,7 @@ + @@ -486,9 +487,9 @@ + - @@ -574,7 +575,6 @@ - @@ -609,6 +609,8 @@ + + @@ -625,6 +627,7 @@ + diff --git a/desmume/src/windows/DeSmuME_2010.vcxproj.filters b/desmume/src/windows/DeSmuME_2010.vcxproj.filters index a96a32289..84c877877 100644 --- a/desmume/src/windows/DeSmuME_2010.vcxproj.filters +++ b/desmume/src/windows/DeSmuME_2010.vcxproj.filters @@ -165,9 +165,6 @@ Core - - Core\addons - Core\addons @@ -396,9 +393,6 @@ Core\addons - - Core - Core\utils @@ -438,6 +432,15 @@ Core + + Core\addons + + + Core\utils + + + Core\utils + @@ -767,9 +770,6 @@ - - Core - Core\utils @@ -822,6 +822,15 @@ Core\utils\libfat + + Core\utils + + + Core\utils + + + Core\utils + diff --git a/desmume/src/windows/gbaslot_config.cpp b/desmume/src/windows/gbaslot_config.cpp index 1b4a27f28..15af63846 100644 --- a/desmume/src/windows/gbaslot_config.cpp +++ b/desmume/src/windows/gbaslot_config.cpp @@ -117,7 +117,7 @@ INT_PTR CALLBACK GbaSlotCFlash(HWND dialog, UINT msg,WPARAM wparam,LPARAM lparam ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = dialog; - const char *fileFilter = "Compact Flash image (*.img)\0*.img\0Any file (*.*)\0*.*\0"; + const char *fileFilter = "FAT image (*.img)\0*.img\0Any file (*.*)\0*.*\0"; ofn.lpstrFilter = fileFilter; ofn.nFilterIndex = 1; @@ -144,7 +144,7 @@ INT_PTR CALLBACK GbaSlotCFlash(HWND dialog, UINT msg,WPARAM wparam,LPARAM lparam bp.hwndOwner=dialog; bp.pidlRoot=NULL; bp.pszDisplayName=NULL; - bp.lpszTitle="Select directory for Compact Flash"; + bp.lpszTitle="Select directory for FAT image building"; bp.ulFlags=BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE | BIF_USENEWUI; bp.lpfn=NULL; diff --git a/desmume/src/windows/resources.rc b/desmume/src/windows/resources.rc index 76d2bed3d..ef3250b2b 100644 Binary files a/desmume/src/windows/resources.rc and b/desmume/src/windows/resources.rc differ