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;
}