diff --git a/desmume/src/Makefile.am b/desmume/src/Makefile.am index a21e53af4..d2d191a36 100644 --- a/desmume/src/Makefile.am +++ b/desmume/src/Makefile.am @@ -47,6 +47,7 @@ libdesmume_a_SOURCES = \ 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/fsnitro.cpp utils/fsnitro.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 \ @@ -87,7 +88,7 @@ libdesmume_a_SOURCES = \ utils/tinyxml/tinyxmlerror.cpp \ utils/tinyxml/tinyxmlparser.cpp \ addons.cpp addons.h \ - addons/slot2_mpcf.cpp addons/slot2_paddle.cpp addons/slot2_gbagame.cpp addons/slot2_none.cpp addons/slot2_rumblepak.cpp addons/slot2_guitarGrip.cpp addons/slot2_expMemory.cpp addons/slot2_piano.cpp addons/slot1_none.cpp addons/slot1_r4.cpp addons/slot1_retail_nand.cpp addons/slot1_retail_auto.cpp addons/slot1_retail_mcrom.cpp addons/slot1comp_mc.cpp addons/slot1comp_mc.h addons/slot1comp_rom.h addons/slot1comp_rom.cpp addons/slot1comp_protocol.h addons/slot1comp_protocol.cpp \ + addons/slot2_mpcf.cpp addons/slot2_paddle.cpp addons/slot2_gbagame.cpp addons/slot2_none.cpp addons/slot2_rumblepak.cpp addons/slot2_guitarGrip.cpp addons/slot2_expMemory.cpp addons/slot2_piano.cpp addons/slot1_none.cpp addons/slot1_r4.cpp addons/slot1_retail_nand.cpp addons/slot1_retail_auto.cpp addons/slot1_retail_mcrom.cpp addons/slot1_retail_mcrom_debug.cpp addons/slot1comp_mc.cpp addons/slot1comp_mc.h addons/slot1comp_rom.h addons/slot1comp_rom.cpp addons/slot1comp_protocol.h addons/slot1comp_protocol.cpp \ cheatSystem.cpp cheatSystem.h \ texcache.cpp texcache.h rasterize.cpp rasterize.h \ metaspu/metaspu.cpp metaspu/metaspu.h \ diff --git a/desmume/src/NDSSystem.cpp b/desmume/src/NDSSystem.cpp index 561abe424..d2adcfa4c 100644 --- a/desmume/src/NDSSystem.cpp +++ b/desmume/src/NDSSystem.cpp @@ -41,7 +41,6 @@ #include "debug.h" #include "firmware.h" #include "version.h" -#include "slot1.h" #include "path.h" //int xxctr=0; @@ -447,8 +446,6 @@ static void loadrom(std::string fname) { gameInfo.resize(size); - extern NDS_SLOT1_TYPE slot1_device_type; - fread(gameInfo.romdata,1,size,inf); gameInfo.fillGap(); @@ -2756,7 +2753,6 @@ void NDS_Reset() Screen_Reset(); gfx3d_reset(); gpu3D->NDS_3D_Reset(); - slot1_Reset(); WIFI_Reset(); memcpy(FW_Mac, (MMU.fw.data + 0x36), 6); diff --git a/desmume/src/addons/slot1_retail_mcrom_debug.cpp b/desmume/src/addons/slot1_retail_mcrom_debug.cpp new file mode 100644 index 000000000..c95c96c38 --- /dev/null +++ b/desmume/src/addons/slot1_retail_mcrom_debug.cpp @@ -0,0 +1,194 @@ +/* + Copyright (C) 2013 DeSmuME team + + This file 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. + + This file 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 the this software. If not, see . +*/ + +#include "../slot1.h" +#include "../registers.h" +#include "../MMU.h" +#include "../NDSSystem.h" +#include "../utils/fsnitro.h" +#include "../path.h" +#include "slot1comp_mc.h" +#include "slot1comp_rom.h" +#include "slot1comp_protocol.h" + +//quick architecture overview: +//MCROM receives GC bus commands from MMU.cpp +//those are passed on to the protocol component for parsing +//protocol calls back into MCROM via ISlot1Comp_Protocol_Client interface for things the protocol doesnt know about (the contents of the rom, chiefly) +//MCROM utilizes the rom component for address logic and delivering data + +class Slot1_Retail_DEBUG : public ISlot1Interface, public ISlot1Comp_Protocol_Client +{ +private: + Slot1Comp_Protocol protocol; + Slot1Comp_Rom rom; + FILE *fpROM; + FS_NITRO *fs; + u16 curr_file_id; + string pathData; + +public: + + virtual Slot1Info const* info() + { + static Slot1InfoSimple info("Retail DEBUG","Slot1 Retail (standard) card emulation + FS Nitro DEBUG"); + return &info; + } + + virtual void connect() + { + if (!MMU.CART_ROM) return; + protocol.reset(this); + protocol.chipId = gameInfo.chipID; + protocol.gameCode = T1ReadLong((u8*)gameInfo.header.gameCode,0); + + pathData = path.getpath(path.SLOT1D) + path.GetRomNameWithoutExtension(); + printf("Path to Slot1 data: %s\n", pathData.c_str()); + + curr_file_id = 0xFFFF; + fpROM = NULL; + fs = new FS_NITRO(MMU.CART_ROM); + fs->rebuildFAT(pathData); + } + + virtual u8 auxspi_transaction(int PROCNUM, u8 value) + { + return g_Slot1Comp_MC.auxspi_transaction(PROCNUM,value); + } + + virtual void auxspi_reset(int PROCNUM) + { + g_Slot1Comp_MC.auxspi_reset(PROCNUM); + } + + virtual void write_command(u8 PROCNUM, GC_Command command) + { + protocol.write_command(command); + } + virtual void write_GCDATAIN(u8 PROCNUM, u32 val) + { + protocol.write_GCDATAIN(PROCNUM, val); + } + virtual u32 read_GCDATAIN(u8 PROCNUM) + { + return protocol.read_GCDATAIN(PROCNUM); + } + + virtual void slot1client_startOperation(eSlot1Operation operation) + { + if (protocol.operation == eSlot1Operation_B7_Read) + { + u16 file_id = 0xFFFF; u32 offset = 0; + bool bFromFile = false; + + if (fs->isFAT(protocol.address)) + { + fs->rebuildFAT(protocol.address, protocol.length, pathData); + } + else + { + if (fs->getFileIdByAddr(protocol.address, file_id, offset)) + { + if (file_id != curr_file_id) + { + string tmp = fs->getFullPathByFileID(file_id); + printf("%04X:[%08X, ofs %08X] %s\n", file_id, protocol.address, offset, tmp.c_str()); + + if (fpROM) + { + fclose(fpROM); + fpROM = NULL; + } + tmp = pathData + tmp; + + fpROM = fopen(tmp.c_str(), "rb"); + if (fpROM) + { + bFromFile = true; + printf("\t * found at disk, offset %08X\n", offset); + if (fseek(fpROM, offset, SEEK_SET) != 0) + { + printf("\t\t - ERROR seek file position\n"); + } + } + } + else + { + if (fpROM) + { + bFromFile = true; + if (ftell(fpROM) != offset) + { + printf("\t * new file seek %08Xh\n", offset); + fseek(fpROM, offset, SEEK_SET); + } + } + } + } + } + if (!bFromFile && fpROM) + { + fclose(fpROM); + fpROM = NULL; + } + + curr_file_id = file_id; + } + rom.start(operation, protocol.address); + } + +private: + + u32 slot1client_read_GCDATAIN(eSlot1Operation operation) + { + if (protocol.operation == eSlot1Operation_B7_Read) + { + + u32 address = rom.getAddress(); + + if (fs->isFAT(address)) + { + u32 res = fs->getFATRecord(address); + if (res != 0xFFFFFFFF) + { + rom.incAddress(); + return res; + } + } + else + if (fpROM) + { + u32 data = 0; + u32 readed = fread(&data, 1, 4, fpROM); + if (readed) + { + rom.incAddress(); + if (readed < 4) + data |= ((u32)0xFFFFFFFF << (readed * 8)); + return data; + } + + fclose(fpROM); + fpROM = NULL; + } + } + + return rom.read(); + } +}; + +ISlot1Interface* construct_Slot1_Retail_DEBUG() { return new Slot1_Retail_DEBUG(); } diff --git a/desmume/src/addons/slot1comp_rom.cpp b/desmume/src/addons/slot1comp_rom.cpp index 4517a3a61..6d264fe23 100644 --- a/desmume/src/addons/slot1comp_rom.cpp +++ b/desmume/src/addons/slot1comp_rom.cpp @@ -91,3 +91,15 @@ u32 Slot1Comp_Rom::read() } //switch(operation) } //Slot1Comp_Rom::read() + +u32 Slot1Comp_Rom::getAddress() +{ + return address & gameInfo.mask; +} //Slot1Comp_Rom::getAddress() + +u32 Slot1Comp_Rom::incAddress() +{ + address &= gameInfo.mask; + address = (address&~0xFFF) + ((address+4)&0xFFF); + return address; +} diff --git a/desmume/src/addons/slot1comp_rom.h b/desmume/src/addons/slot1comp_rom.h index f1924a622..bbb10acc4 100644 --- a/desmume/src/addons/slot1comp_rom.h +++ b/desmume/src/addons/slot1comp_rom.h @@ -26,6 +26,8 @@ class Slot1Comp_Rom public: void start(eSlot1Operation operation, u32 addr); u32 read(); + u32 getAddress(); + u32 incAddress(); private: u32 address; eSlot1Operation operation; diff --git a/desmume/src/commandline.cpp b/desmume/src/commandline.cpp index 7749243ff..2ca86c7e6 100644 --- a/desmume/src/commandline.cpp +++ b/desmume/src/commandline.cpp @@ -305,6 +305,8 @@ void CommandLine::process_addonCommands() else if(slot1 == "RETAILNAND") slot1_Change(NDS_SLOT1_RETAIL_NAND); else if(slot1 == "RETAILMCROM") - slot1_Change(NDS_SLOT1_RETAIL_MCROM); + slot1_Change(NDS_SLOT1_RETAIL_MCROM); + else if(slot1 == "RETAILDEBUG") + slot1_Change(NDS_SLOT1_RETAIL_DEBUG); } diff --git a/desmume/src/path.h b/desmume/src/path.h index 0fa2260cc..b8c581b38 100644 --- a/desmume/src/path.h +++ b/desmume/src/path.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2011 DeSmuME team + Copyright (C) 2009-2013 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -90,6 +90,7 @@ public: #define NEEDSSAVINGKEY "needsSaving" #define LASTVISITKEY "lastVisit" #define LUAKEY "Lua" + #define SLOT1DKEY "Slot1D" char screenshotFormat[MAX_FORMAT]; bool savelastromvisit; @@ -105,6 +106,7 @@ public: SOUNDS, FIRMWARE, MODULE, + SLOT1D, MAXKNOWNPATH = MODULE }; @@ -118,6 +120,7 @@ public: char pathToFirmware[MAX_PATH]; char pathToModule[MAX_PATH]; char pathToLua[MAX_PATH]; + char pathToSlot1D[MAX_PATH]; void init(const char *filename) { @@ -206,6 +209,7 @@ public: ReadKey(pathToSounds, SOUNDKEY); ReadKey(pathToFirmware, FIRMWAREKEY); ReadKey(pathToLua, LUAKEY); + ReadKey(pathToSlot1D, SLOT1DKEY); #ifdef _WINDOWS GetPrivateProfileString(SECTION, FORMATKEY, "%f_%s_%r", screenshotFormat, MAX_FORMAT, IniName); savelastromvisit = GetPrivateProfileBool(SECTION, LASTVISITKEY, true, IniName); @@ -258,6 +262,9 @@ public: case MODULE: pathToCopy = pathToModule; break; + case SLOT1D: + pathToCopy = pathToSlot1D; + break; } if(action == GET) diff --git a/desmume/src/slot1.cpp b/desmume/src/slot1.cpp index 2aafb73f1..b80962765 100644 --- a/desmume/src/slot1.cpp +++ b/desmume/src/slot1.cpp @@ -95,11 +95,13 @@ void slot1_Init() extern TISlot1InterfaceConstructor construct_Slot1_R4; extern TISlot1InterfaceConstructor construct_Slot1_Retail_NAND; extern TISlot1InterfaceConstructor construct_Slot1_Retail_MCROM; + extern TISlot1InterfaceConstructor construct_Slot1_Retail_DEBUG; slot1_List[NDS_SLOT1_NONE] = construct_Slot1_None(); slot1_List[NDS_SLOT1_RETAIL_AUTO] = construct_Slot1_Retail_Auto(); slot1_List[NDS_SLOT1_R4] = construct_Slot1_R4(); slot1_List[NDS_SLOT1_RETAIL_NAND] = construct_Slot1_Retail_NAND(); slot1_List[NDS_SLOT1_RETAIL_MCROM] = construct_Slot1_Retail_MCROM(); + slot1_List[NDS_SLOT1_RETAIL_DEBUG] = construct_Slot1_Retail_DEBUG(); } void slot1_Shutdown() diff --git a/desmume/src/slot1.h b/desmume/src/slot1.h index fca367f78..5864f455c 100644 --- a/desmume/src/slot1.h +++ b/desmume/src/slot1.h @@ -87,11 +87,12 @@ typedef ISlot1Interface* TISlot1InterfaceConstructor(); enum NDS_SLOT1_TYPE { NDS_SLOT1_NONE, - NDS_SLOT1_RETAIL_AUTO, //autodetect which kind of retail card to use - NDS_SLOT1_R4, //R4 flash card - NDS_SLOT1_RETAIL_NAND, //Made in Ore/WarioWare D.I.Y. - NDS_SLOT1_RETAIL_MCROM, //a standard MC (eeprom, flash, fram) -bearing retail card. Also supports motion, for now, because that's the way we originally coded it - NDS_SLOT1_COUNT //use to count addons - MUST BE LAST!!! + NDS_SLOT1_RETAIL_AUTO, //autodetect which kind of retail card to use + NDS_SLOT1_R4, //R4 flash card + NDS_SLOT1_RETAIL_NAND, //Made in Ore/WarioWare D.I.Y. + NDS_SLOT1_RETAIL_MCROM, //a standard MC (eeprom, flash, fram) -bearing retail card. Also supports motion, for now, because that's the way we originally coded it + NDS_SLOT1_RETAIL_DEBUG, //for romhacking and fan-made translations + NDS_SLOT1_COUNT //use to count addons - MUST BE LAST!!! }; extern ISlot1Interface* slot1_device; //the current slot1 device instance diff --git a/desmume/src/utils/fsnitro.cpp b/desmume/src/utils/fsnitro.cpp new file mode 100644 index 000000000..31a7b5569 --- /dev/null +++ b/desmume/src/utils/fsnitro.cpp @@ -0,0 +1,428 @@ +/* + Copyright (C) 2013 DeSmuME team + + This file 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. + + This file 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 the this software. If not, see . +*/ + +#include +#include +#include "fsnitro.h" + +using namespace std; + +#ifdef _WINDOWS +#define FS_DIRECTORY_DELIMITER_CHAR "\\" +#else +#define FS_DIRECTORY_DELIMITER_CHAR "/" +#endif + +FS_NITRO::FS_NITRO(u8 *cart_rom) +{ + inited = false; + numDirs = numFiles = numOverlay7 = numOverlay9 = currentID =0; + fat = NULL; + fnt = NULL; + ovr9 = NULL; + ovr7 = NULL; + + if (!cart_rom) return; + + rom = cart_rom; + + FNameTblOff = *(u32*)(rom + 0x40); + FNameTblSize = *(u32*)(rom + 0x44); + FATOff = *(u32*)(rom + 0x48); + FATSize = *(u32*)(rom + 0x4C); + + ARM9OverlayOff = *(u32*)(rom + 0x50); + ARM9OverlaySize = *(u32*)(rom + 0x54); + ARM7OverlayOff = *(u32*)(rom + 0x58); + ARM7OverlaySize = *(u32*)(rom + 0x5C); + + ARM9exeSize = *(u32*)(rom + 0x2C); + ARM9exeStart = *(u32*)(rom + 0x20); + ARM9exeEnd = (ARM9exeStart + ARM9exeSize); + + ARM7exeSize = *(u32*)(rom + 0x3C); + ARM7exeStart = *(u32*)(rom + 0x30); + ARM7exeEnd = (ARM7exeStart + ARM7exeSize); + + //printf("ARM9exe %08Xh - %08Xh, size %08Xh\n", ARM9exeStart, ARM9exeEnd, ARM9exeSize); + //printf("ARM7exe %08Xh - %08Xh, size %08Xh\n", ARM7exeStart, ARM7exeEnd, ARM7exeSize); + + if (FNameTblOff < 0x8000) return; + if (FNameTblOff == 0) return; + if (FATOff < 0x8000) return; + if (FATSize == 0) return; + + numDirs = *(u16*)(rom + FNameTblOff + 6); + numFiles = FATSize / 8; + + if (numFiles == 0 || numDirs == 0) + { + numFiles = numDirs = 0; + return; + } + + FATEnd = (FATOff + FATSize); + + numOverlay9 = ARM9OverlaySize / sizeof(OVR_NITRO); + numOverlay7 = ARM7OverlaySize / sizeof(OVR_NITRO); + + printf("Nitro File System:\n"); + printf("\t* FNT at 0x%08X, size 0x%08X\n", FNameTblOff, FNameTblSize); + printf("\t* FAT at 0x%08X, size 0x%08X\n", FATOff, FATSize); + printf("\t* ARM9 at Overlay 0x%08X, size 0x%08X\n", ARM9OverlayOff, ARM9OverlaySize); + printf("\t* ARM7 at Overlay 0x%08X, size 0x%08X\n", ARM7OverlayOff, ARM7OverlaySize); + printf("\t* ARM9 exe at %08X, size %08Xh\n", ARM9exeStart, ARM9exeSize); + printf("\t* ARM7 exe at %08X, size %08Xh\n", ARM7exeStart, ARM7exeSize); + printf("\t* Directories: %d\n", numDirs); + printf("\t* Files %d\n", numFiles); + printf("\t* ARM9 Overlays %d\n", numOverlay9); + printf("\t* ARM7 Overlays %d\n", numOverlay7); + + fat = new FAT_NITRO[numFiles]; + fnt = new FNT_NITRO[numDirs]; + if (numOverlay7) ovr7 = new OVR_NITRO[numOverlay7]; + if (numOverlay9) ovr9 = new OVR_NITRO[numOverlay9]; + + if (!loadFileTables()) + { + destroy(); + printf("FSNITRO: Error loading file system tables\n"); + return; + } + + inited = true; +} + +FS_NITRO::~FS_NITRO() +{ + destroy(); +} + +void FS_NITRO::destroy() +{ + if (fat) { delete [] fat; fat = NULL; } + if (fnt) { delete [] fnt; fnt = NULL; } + if (ovr9) { delete [] ovr9; ovr9 = NULL; } + if (ovr7) { delete [] ovr7; ovr7 = NULL; } + numDirs = numFiles = numOverlay7 = numOverlay9 = currentID = 0; + inited = false; +} + +FNT_TYPES FS_NITRO::getFNTType(u8 type) +{ + if (type == 0x00) return FS_END_SUBTABLE; + if (type == 0x80) return FS_RESERVED; + if (type < 0x80) return FS_FILE_ENTRY; + + return FS_SUBDIR_ENTRY; +} + +bool FS_NITRO::loadFileTables() +{ + if (!fnt) return false; + if (!fat) return false; + if (numOverlay7 && !ovr7) return false; + if (numOverlay9 && !ovr9) return false; + + memset(fnt, 0, sizeof(FNT_NITRO) * numDirs); + memset(fat, 0, sizeof(FAT_NITRO) * numFiles); + + // ========= FAT (File Allocation Table) + u32 *_FAT = (u32*)(rom + FATOff); + for (u32 i = 0; i < numFiles; i++) + { + const u32 ofs = (i * 2); + fat[i].start = *(_FAT + ofs); + fat[i].end = *(_FAT + ofs + 1); + fat[i].size = fat[i].end - fat[i].start; + fat[i].sizeFile = fat[i].size; + fat[i].isOverlay = false; + } + + // ========= Overlays ARM9 + if (numOverlay9) + { + memcpy(ovr9, (rom + ARM9OverlayOff), ARM9OverlaySize); + for (u32 i = 0 ; i < numOverlay9; i++) + { + fat[ovr9[i].fileID].isOverlay = true; + sprintf(fat[i].filename, "overlay_%04d.bin", ovr9[i].id); + } + } + + // ========= Overlays ARM7 + if (numOverlay7) + { + memcpy(ovr7, (rom + ARM7OverlayOff), ARM7OverlaySize); + for (u32 i = 0 ; i < numOverlay7; i++) + { + fat[ovr7[i].fileID].isOverlay = true; + sprintf(fat[i].filename, "overlay_%04d.bin", ovr7[i].id); + } + } + + // ========= FNT (File Names Table) + u8 *_FNT = (u8*)(rom + FNameTblOff); + for (u32 i = 0; i < numDirs; i++) + { + memcpy(&fnt[i], _FNT, 8); + //printf("FNT %04Xh: sub:%08Xh, 1st ID:%04xh, parentID:%04Xh\n", i, fnt[i].offset, fnt[i].firstID, fnt[i].parentID); + _FNT += 8; + } + + // ========= Read file structure + u8 *sub = (u8*)(rom + FNameTblOff + fnt[0].offset); + u8 *_end = (u8*)(rom + FNameTblOff + FNameTblSize - 1); + u16 fileCount = fnt[0].firstID; + u16 fntID = 0xF000; + uintptr_t *store = new uintptr_t[numDirs]; + + if (!store) return false; + memset(store, NULL, sizeof(uintptr_t) * numDirs); + + strcpy((char*)fnt[0].filename, "/"); + fnt[0].parentID = 0xF000; + + //printf("FNT F000: Sub:%08Xh, 1st ID:%04xh, parentID:%04Xh <%s>\n", fnt[0].offset, fnt[0].firstID, fnt[0].parentID, fnt[0].filename); + + while (true) + { + u8 len = (sub[0] & 0x7F); + FNT_TYPES type = getFNTType(sub[0]); + + if (type == FS_END_SUBTABLE) + { + //printf("********** End Subdir (%04Xh, parent %04X)\n", fntID, fnt[fntID & 0x0FFF].parentID); + //sub = (store + (fntID & 0x0FFF)); + sub = (u8*)store[fntID & 0x0FFF]; + fntID = fnt[fntID & 0x0FFF].parentID; + continue; + } + + if (type == FS_SUBDIR_ENTRY) + { + //printf("********** Subdir Entry\n"); + char buf[129] = {0}; + memcpy(buf, (sub + 1), len); buf[len] = 0; + sub += (len + 1); + fntID = (*(u16*)sub); + sub += 2; + + u32 id = (fntID & 0x0FFF); + store[id] = (uintptr_t)sub; + sub = (u8*)(rom + FNameTblOff + fnt[id].offset); + strcpy(fnt[id].filename, buf); + + //printf("FNT %04X: Sub:%08Xh, 1st ID:%04xh, parentID:%04Xh <%s>\n", fntID, fnt[id].offset, fnt[id].firstID, fnt[id].parentID, buf); + continue; + } + + if (type == FS_FILE_ENTRY) + { + //printf("********** File Entry\n"); + memcpy(&fat[fileCount].filename[0], (sub + 1), len); + fat[fileCount].filename[len] = 0; + fat[fileCount].parentID = fntID; + //printf("ID:%04Xh, len %03d, type %d, parentID %04X, filename: %s\n", fileCount, len, (u32)type, fntID, fat[fileCount].filename); + sub += (len + 1); + fileCount++; + + if (fileCount >= numFiles) break; + continue; + } + + if (type == FS_RESERVED) + { + printf("********** FS_RESERVED\n"); + break; + } + } + delete [] store; store = NULL; + + return true; +} + +// ======================= tools +bool FS_NITRO::rebuildFAT(u32 addr, u32 size, string pathData) +{ + if (!inited) return false; + if (size == 0) return false; + if (addr < FATOff) return false; + if (addr > FATEnd) return false; + + const u32 startID = (addr - FATOff) / 8; + const u32 endID = startID + (size / 8); + //printf("Start rebuild FAT (start ID:%04Xh)\n", startID); + + u8 *romFAT = (u8*)(rom + addr); + + for (u32 i = startID; i < endID; i++) + { + if (i >= numFiles) break; + string path = pathData + getFullPathByFileID(i); + //printf("%04Xh - %s (%d)\n", i, path.c_str(), fat[i].size); + fat[i].file = false; + FILE *fp = fopen(path.c_str(), "rb"); + if (!fp) continue; + fseek(fp, 0, SEEK_END); + u32 size = ftell(fp); + fclose(fp); + + fat[i].file = true; + + if (fat[i].size != size) + { + //printf("Different size: %s (ROM: %d, file %d)\n", path.c_str(), fat[i].size, size); + fat[i].sizeFile = size; + } + else + fat[i].sizeFile = fat[i].size; + } + + return true; +} + +bool FS_NITRO::rebuildFAT(string pathData) +{ + return rebuildFAT(FATOff, FATSize, pathData); +} + +u32 FS_NITRO::getFATRecord(u32 addr) +{ + if (!inited) return 0xFFFFFFFF; + if (addr < FATOff) return 0xFFFFFFFF; + if (addr > FATEnd) return 0xFFFFFFFF; + + u32 id = (addr - FATOff) / 8; + u32 offs = (addr - FATOff) % 8; + + if (offs == 0) + { + return fat[id].start; + } + else + { + if (fat[id].file) + return (fat[id].start + fat[id].sizeFile); + else + return fat[id].end; + } + + return 0xFFFFFFFF; +} + +bool FS_NITRO::getFileIdByAddr(u32 addr, u16 &id) +{ + id = 0xFFFF; + if (!inited) return false; + + u32 pos = currentID; + while (true) + { + if ((addr >= fat[pos].start) && (addr < fat[pos].end)) + { + id = pos; + currentID = pos; + return true; + } + pos++; + if (pos >= numFiles) pos = 0; + if (pos == currentID) break; + } + return false; +} + +bool FS_NITRO::getFileIdByAddr(u32 addr, u16 &id, u32 &offset) +{ + id = 0xFFFF; offset = 0; + if (!inited) return false; + + u32 pos = currentID; + while (true) + { + if ((addr >= fat[pos].start) && (addr < fat[pos].end)) + { + id = pos; + offset = addr - fat[pos].start; + currentID = pos; + return true; + } + pos++; + if (pos >= numFiles) pos = 0; + if (pos == currentID) break; + } + + return false; +} + +string FS_NITRO::getFileNameByID(u16 id) +{ + if (!inited) return ""; + if ((id & 0xF000) == 0xF000) return ""; + if (id > numFiles) return ""; + id &= 0x0FFF; + + return (string)fat[id].filename; +} + +string FS_NITRO::getFullPathByFileID(u16 id) +{ + if (!inited) return ""; + if (id > numFiles) return ""; + string res = ""; + + if (!fat[id].isOverlay) + { + u32 parentID = (fat[id].parentID & 0x0FFF); + while (parentID) + { + res = fnt[parentID].filename + string(FS_DIRECTORY_DELIMITER_CHAR + res); + parentID = (fnt[parentID].parentID & 0x0FFF); + } + res = (string)FS_DIRECTORY_DELIMITER_CHAR + (string)"data" + (string)FS_DIRECTORY_DELIMITER_CHAR + res; + } + else + res = string("\\overlay") + FS_DIRECTORY_DELIMITER_CHAR; + + res += (string)fat[id].filename; + return res; +} + +u32 FS_NITRO::getFileSizeById(u16 id) +{ + if (!inited) return 0; + if (id > numFiles) return 0; + + return (fat[id].size); +} + +u32 FS_NITRO::getStartAddrById(u16 id) +{ + if (!inited) return 0; + if (id > numFiles) return 0; + + return (fat[id].start); +} + +u32 FS_NITRO::getEndAddrById(u16 id) +{ + if (!inited) return 0; + if (id > numFiles) return 0; + + return (fat[id].end); +} + diff --git a/desmume/src/utils/fsnitro.h b/desmume/src/utils/fsnitro.h new file mode 100644 index 000000000..2ccf561cb --- /dev/null +++ b/desmume/src/utils/fsnitro.h @@ -0,0 +1,138 @@ +/* + Copyright (C) 2013 DeSmuME team + + This file 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. + + This file 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 the this software. If not, see . +*/ + +#ifndef _FS_NITRO_H_ +#define _FS_NITRO_H_ +#include +#include "../types.h" + +using namespace std; + +enum FNT_TYPES +{ + FS_FILE_ENTRY = 0, + FS_SUBDIR_ENTRY = 1, + FS_END_SUBTABLE = 2, + FS_RESERVED = 3, +}; + +#include "PACKED.h" +struct FAT_NITRO +{ + u32 start; + u32 end; + u32 size; + u32 parentOffset; + bool isOverlay; + bool file; + u32 sizeFile; + u16 parentID; + char filename[128]; +}; + +struct FNT_MAIN +{ + u32 offset; + u16 firstID; + u16 parentID; +}; + +struct FNT_NITRO +{ + u32 offset; + u16 firstID; + u16 parentID; + char filename[128]; +}; + +struct OVR_NITRO +{ + u32 id; + u32 RAMaddr; + u32 RAMSize; + u32 BSSSize; + u32 start; + u32 end; + u32 fileID; + u32 reserved; +}; +#include "PACKED_END.h" + +class FS_NITRO +{ +private: + bool inited; + + u32 FNameTblOff; + u32 FNameTblSize; + u32 FATOff; + u32 FATSize; + u32 FATEnd; + u32 ARM9OverlayOff; + u32 ARM9OverlaySize; + u32 ARM7OverlayOff; + u32 ARM7OverlaySize; + + u32 ARM9exeStart; + u32 ARM9exeEnd; + u32 ARM9exeSize; + + u32 ARM7exeStart; + u32 ARM7exeEnd; + u32 ARM7exeSize; + + u32 numFiles; + u32 numDirs; + u32 numOverlay7; + u32 numOverlay9; + + u32 currentID; + + u8 *rom; + FAT_NITRO *fat; + FNT_NITRO *fnt; + OVR_NITRO *ovr9; + OVR_NITRO *ovr7; + + FNT_TYPES getFNTType(u8 type); + bool loadFileTables(); + +public: + FS_NITRO(u8 *cart_rom); + ~FS_NITRO(); + void destroy(); + + bool getFileIdByAddr(u32 addr, u16 &id); + bool getFileIdByAddr(u32 addr, u16 &id, u32 &offset); + string getFileNameByID(u16 id); + string getFullPathByFileID(u16 id); + u32 getFileSizeById(u16 id); + u32 getStartAddrById(u16 id); + u32 getEndAddrById(u16 id); + bool isARM9(u32 addr) { return ((addr >= ARM9exeStart) && (addr < ARM9exeEnd)); } + bool isARM7(u32 addr) { return ((addr >= ARM7exeStart) && (addr < ARM7exeEnd)); } + bool isFAT(u32 addr) { return ((addr >= FATOff) && (addr < FATEnd)); } + bool rebuildFAT(u32 addr, u32 size, string pathData); + bool rebuildFAT(string pathData); + u32 getFATRecord(u32 addr); + + u32 getNumDirs() { return numDirs; } + u32 getNumFiles() { return numFiles; } +}; + + +#endif diff --git a/desmume/src/windows/DeSmuME_2005.vcproj b/desmume/src/windows/DeSmuME_2005.vcproj index ec0b8374f..08d0ba347 100644 --- a/desmume/src/windows/DeSmuME_2005.vcproj +++ b/desmume/src/windows/DeSmuME_2005.vcproj @@ -1585,6 +1585,14 @@ RelativePath="..\utils\emufat.h" > + + + + @@ -2211,6 +2219,10 @@ RelativePath="..\addons\slot1_retail_mcrom.cpp" > + + diff --git a/desmume/src/windows/DeSmuME_2008.vcproj b/desmume/src/windows/DeSmuME_2008.vcproj index 6577fc2b7..a8f1c4e37 100644 --- a/desmume/src/windows/DeSmuME_2008.vcproj +++ b/desmume/src/windows/DeSmuME_2008.vcproj @@ -1017,6 +1017,10 @@ RelativePath="..\addons\slot1_retail_mcrom.cpp" > + + @@ -1129,6 +1133,14 @@ RelativePath="..\utils\emufat.h" > + + + + diff --git a/desmume/src/windows/DeSmuME_2010.vcxproj b/desmume/src/windows/DeSmuME_2010.vcxproj index 9a858e32a..ac3d840d1 100644 --- a/desmume/src/windows/DeSmuME_2010.vcxproj +++ b/desmume/src/windows/DeSmuME_2010.vcxproj @@ -375,6 +375,7 @@ + @@ -464,6 +465,7 @@ + @@ -751,6 +753,7 @@ + diff --git a/desmume/src/windows/DeSmuME_2010.vcxproj.filters b/desmume/src/windows/DeSmuME_2010.vcxproj.filters index cd415742a..6470a4982 100644 --- a/desmume/src/windows/DeSmuME_2010.vcxproj.filters +++ b/desmume/src/windows/DeSmuME_2010.vcxproj.filters @@ -798,6 +798,12 @@ Core\addons + + Core\addons + + + Core\utils + @@ -1539,6 +1545,9 @@ Core\addons + + Core\utils + diff --git a/desmume/src/windows/DeSmuME_2012.vcxproj b/desmume/src/windows/DeSmuME_2012.vcxproj index ead696ed0..cb8b88103 100644 --- a/desmume/src/windows/DeSmuME_2012.vcxproj +++ b/desmume/src/windows/DeSmuME_2012.vcxproj @@ -386,6 +386,7 @@ + @@ -475,6 +476,7 @@ + @@ -762,6 +764,7 @@ + diff --git a/desmume/src/windows/DeSmuME_2012.vcxproj.filters b/desmume/src/windows/DeSmuME_2012.vcxproj.filters index b8301ef9f..34f162503 100644 --- a/desmume/src/windows/DeSmuME_2012.vcxproj.filters +++ b/desmume/src/windows/DeSmuME_2012.vcxproj.filters @@ -790,6 +790,12 @@ Core\addons + + Core\addons + + + Core\utils + @@ -1401,6 +1407,9 @@ Core\addons + + Core\utils + diff --git a/desmume/src/windows/console.cpp b/desmume/src/windows/console.cpp index a314a5ce4..62b33ee20 100644 --- a/desmume/src/windows/console.cpp +++ b/desmume/src/windows/console.cpp @@ -82,7 +82,7 @@ void readConsole() { for (u32 i = 0; i < num; i++) { - if ((buf[i].EventType == KEY_EVENT) && (buf[i].Event.KeyEvent.bKeyDown) && (buf[i].Event.KeyEvent.wVirtualKeyCode == 0x13)) + if ((buf[i].EventType == KEY_EVENT) && (buf[i].Event.KeyEvent.bKeyDown) && (buf[i].Event.KeyEvent.wVirtualKeyCode == VK_PAUSE)) { if (execute) NDS_Pause(false); diff --git a/desmume/src/windows/slot1_config.cpp b/desmume/src/windows/slot1_config.cpp index 4dfc4e72a..72113bc25 100644 --- a/desmume/src/windows/slot1_config.cpp +++ b/desmume/src/windows/slot1_config.cpp @@ -99,14 +99,16 @@ u32 Slot1_IDDs[NDS_SLOT1_COUNT] = { IDD_SLOT1_R4, // NDS_SLOT1_R4, - R4 flash card IDD_SLOT1_NONE, // NDS_SLOT1_RETAIL_NAND - Made in Ore/WarioWare D.I.Y. IDD_SLOT1_NONE, // NDS_SLOT1_RETAIL_MCROM - a standard MC (eeprom, flash, fram) + IDD_SLOT1_NONE, // NDS_SLOT1_RETAIL_DEBUG - for romhacking and fan-made translations }; DLGPROC Slot1_Procs[NDS_SLOT1_COUNT] = { + Slot1None, Slot1None, // NDS_SLOT1_RETAIL_AUTO - autodetect which kind of retail card to use Slot1None, // NDS_SLOT1_R4, - R4 flash card Slot1R4, // NDS_SLOT1_RETAIL_NAND - Made in Ore/WarioWare D.I.Y. Slot1None, // NDS_SLOT1_RETAIL_MCROM - a standard MC (eeprom, flash, fram) - Slot1None + Slot1None // NDS_SLOT1_RETAIL_DEBUG - for romhacking and fan-made translations }; @@ -222,6 +224,8 @@ void slot1Dialog(HWND hwnd) break; case NDS_SLOT1_RETAIL_NAND: break; + case NDS_SLOT1_RETAIL_DEBUG: + break; default: return; }