- first implementation a slot1 debugger (for debug reading files from game card, romhacking and fan-made translations);
This commit is contained in:
mtabachenko 2013-08-31 00:32:59 +00:00
parent e62995291a
commit 89606483cc
19 changed files with 849 additions and 14 deletions

View File

@ -47,6 +47,7 @@ libdesmume_a_SOURCES = \
utils/datetime.cpp utils/datetime.h \ utils/datetime.cpp utils/datetime.h \
utils/ConvertUTF.c utils/ConvertUTF.h utils/guid.cpp utils/guid.h \ utils/ConvertUTF.c utils/ConvertUTF.h utils/guid.cpp utils/guid.h \
utils/emufat.cpp utils/emufat.h utils/emufat_types.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/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/crc.cpp utils/decrypt/crc.h utils/decrypt/decrypt.cpp \
utils/decrypt/decrypt.h utils/decrypt/header.cpp utils/decrypt/header.h \ 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/tinyxmlerror.cpp \
utils/tinyxml/tinyxmlparser.cpp \ utils/tinyxml/tinyxmlparser.cpp \
addons.cpp addons.h \ 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 \ cheatSystem.cpp cheatSystem.h \
texcache.cpp texcache.h rasterize.cpp rasterize.h \ texcache.cpp texcache.h rasterize.cpp rasterize.h \
metaspu/metaspu.cpp metaspu/metaspu.h \ metaspu/metaspu.cpp metaspu/metaspu.h \

View File

@ -41,7 +41,6 @@
#include "debug.h" #include "debug.h"
#include "firmware.h" #include "firmware.h"
#include "version.h" #include "version.h"
#include "slot1.h"
#include "path.h" #include "path.h"
//int xxctr=0; //int xxctr=0;
@ -447,8 +446,6 @@ static void loadrom(std::string fname) {
gameInfo.resize(size); gameInfo.resize(size);
extern NDS_SLOT1_TYPE slot1_device_type;
fread(gameInfo.romdata,1,size,inf); fread(gameInfo.romdata,1,size,inf);
gameInfo.fillGap(); gameInfo.fillGap();
@ -2756,7 +2753,6 @@ void NDS_Reset()
Screen_Reset(); Screen_Reset();
gfx3d_reset(); gfx3d_reset();
gpu3D->NDS_3D_Reset(); gpu3D->NDS_3D_Reset();
slot1_Reset();
WIFI_Reset(); WIFI_Reset();
memcpy(FW_Mac, (MMU.fw.data + 0x36), 6); memcpy(FW_Mac, (MMU.fw.data + 0x36), 6);

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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(); }

View File

@ -91,3 +91,15 @@ u32 Slot1Comp_Rom::read()
} //switch(operation) } //switch(operation)
} //Slot1Comp_Rom::read() } //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;
}

View File

@ -26,6 +26,8 @@ class Slot1Comp_Rom
public: public:
void start(eSlot1Operation operation, u32 addr); void start(eSlot1Operation operation, u32 addr);
u32 read(); u32 read();
u32 getAddress();
u32 incAddress();
private: private:
u32 address; u32 address;
eSlot1Operation operation; eSlot1Operation operation;

View File

@ -306,5 +306,7 @@ void CommandLine::process_addonCommands()
slot1_Change(NDS_SLOT1_RETAIL_NAND); slot1_Change(NDS_SLOT1_RETAIL_NAND);
else if(slot1 == "RETAILMCROM") 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);
} }

View File

@ -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 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 it under the terms of the GNU General Public License as published by
@ -90,6 +90,7 @@ public:
#define NEEDSSAVINGKEY "needsSaving" #define NEEDSSAVINGKEY "needsSaving"
#define LASTVISITKEY "lastVisit" #define LASTVISITKEY "lastVisit"
#define LUAKEY "Lua" #define LUAKEY "Lua"
#define SLOT1DKEY "Slot1D"
char screenshotFormat[MAX_FORMAT]; char screenshotFormat[MAX_FORMAT];
bool savelastromvisit; bool savelastromvisit;
@ -105,6 +106,7 @@ public:
SOUNDS, SOUNDS,
FIRMWARE, FIRMWARE,
MODULE, MODULE,
SLOT1D,
MAXKNOWNPATH = MODULE MAXKNOWNPATH = MODULE
}; };
@ -118,6 +120,7 @@ public:
char pathToFirmware[MAX_PATH]; char pathToFirmware[MAX_PATH];
char pathToModule[MAX_PATH]; char pathToModule[MAX_PATH];
char pathToLua[MAX_PATH]; char pathToLua[MAX_PATH];
char pathToSlot1D[MAX_PATH];
void init(const char *filename) { void init(const char *filename) {
@ -206,6 +209,7 @@ public:
ReadKey(pathToSounds, SOUNDKEY); ReadKey(pathToSounds, SOUNDKEY);
ReadKey(pathToFirmware, FIRMWAREKEY); ReadKey(pathToFirmware, FIRMWAREKEY);
ReadKey(pathToLua, LUAKEY); ReadKey(pathToLua, LUAKEY);
ReadKey(pathToSlot1D, SLOT1DKEY);
#ifdef _WINDOWS #ifdef _WINDOWS
GetPrivateProfileString(SECTION, FORMATKEY, "%f_%s_%r", screenshotFormat, MAX_FORMAT, IniName); GetPrivateProfileString(SECTION, FORMATKEY, "%f_%s_%r", screenshotFormat, MAX_FORMAT, IniName);
savelastromvisit = GetPrivateProfileBool(SECTION, LASTVISITKEY, true, IniName); savelastromvisit = GetPrivateProfileBool(SECTION, LASTVISITKEY, true, IniName);
@ -258,6 +262,9 @@ public:
case MODULE: case MODULE:
pathToCopy = pathToModule; pathToCopy = pathToModule;
break; break;
case SLOT1D:
pathToCopy = pathToSlot1D;
break;
} }
if(action == GET) if(action == GET)

View File

@ -95,11 +95,13 @@ void slot1_Init()
extern TISlot1InterfaceConstructor construct_Slot1_R4; extern TISlot1InterfaceConstructor construct_Slot1_R4;
extern TISlot1InterfaceConstructor construct_Slot1_Retail_NAND; extern TISlot1InterfaceConstructor construct_Slot1_Retail_NAND;
extern TISlot1InterfaceConstructor construct_Slot1_Retail_MCROM; extern TISlot1InterfaceConstructor construct_Slot1_Retail_MCROM;
extern TISlot1InterfaceConstructor construct_Slot1_Retail_DEBUG;
slot1_List[NDS_SLOT1_NONE] = construct_Slot1_None(); slot1_List[NDS_SLOT1_NONE] = construct_Slot1_None();
slot1_List[NDS_SLOT1_RETAIL_AUTO] = construct_Slot1_Retail_Auto(); slot1_List[NDS_SLOT1_RETAIL_AUTO] = construct_Slot1_Retail_Auto();
slot1_List[NDS_SLOT1_R4] = construct_Slot1_R4(); slot1_List[NDS_SLOT1_R4] = construct_Slot1_R4();
slot1_List[NDS_SLOT1_RETAIL_NAND] = construct_Slot1_Retail_NAND(); 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_MCROM] = construct_Slot1_Retail_MCROM();
slot1_List[NDS_SLOT1_RETAIL_DEBUG] = construct_Slot1_Retail_DEBUG();
} }
void slot1_Shutdown() void slot1_Shutdown()

View File

@ -91,6 +91,7 @@ enum NDS_SLOT1_TYPE
NDS_SLOT1_R4, //R4 flash card NDS_SLOT1_R4, //R4 flash card
NDS_SLOT1_RETAIL_NAND, //Made in Ore/WarioWare D.I.Y. 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_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!!! NDS_SLOT1_COUNT //use to count addons - MUST BE LAST!!!
}; };

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <string>
#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 "<directory>";
if (id > numFiles) return "<!ERROR invalid id>";
id &= 0x0FFF;
return (string)fat[id].filename;
}
string FS_NITRO::getFullPathByFileID(u16 id)
{
if (!inited) return "";
if (id > numFiles) return "<!ERROR invalid id>";
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);
}

138
desmume/src/utils/fsnitro.h Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef _FS_NITRO_H_
#define _FS_NITRO_H_
#include <string>
#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

View File

@ -1585,6 +1585,14 @@
RelativePath="..\utils\emufat.h" RelativePath="..\utils\emufat.h"
> >
</File> </File>
<File
RelativePath="..\utils\fsnitro.cpp"
>
</File>
<File
RelativePath="..\utils\fsnitro.h"
>
</File>
<File <File
RelativePath="..\utils\emufat_types.h" RelativePath="..\utils\emufat_types.h"
> >
@ -2211,6 +2219,10 @@
RelativePath="..\addons\slot1_retail_mcrom.cpp" RelativePath="..\addons\slot1_retail_mcrom.cpp"
> >
</File> </File>
<File
RelativePath="..\addons\slot1_retail_mcrom_debug.cpp"
>
</File>
<File <File
RelativePath="..\addons\slot1_retail_nand.cpp" RelativePath="..\addons\slot1_retail_nand.cpp"
> >

View File

@ -1017,6 +1017,10 @@
RelativePath="..\addons\slot1_retail_mcrom.cpp" RelativePath="..\addons\slot1_retail_mcrom.cpp"
> >
</File> </File>
<File
RelativePath="..\addons\slot1_retail_mcrom_debug.cpp"
>
</File>
<File <File
RelativePath="..\addons\slot1_retail_nand.cpp" RelativePath="..\addons\slot1_retail_nand.cpp"
> >
@ -1129,6 +1133,14 @@
RelativePath="..\utils\emufat.h" RelativePath="..\utils\emufat.h"
> >
</File> </File>
<File
RelativePath="..\utils\fsnitro.cpp"
>
</File>
<File
RelativePath="..\utils\fsnitro.h"
>
</File>
<File <File
RelativePath="..\utils\guid.cpp" RelativePath="..\utils\guid.cpp"
> >

View File

@ -375,6 +375,7 @@
<ClCompile Include="..\addons\slot1comp_rom.cpp" /> <ClCompile Include="..\addons\slot1comp_rom.cpp" />
<ClCompile Include="..\addons\slot1_retail_auto.cpp" /> <ClCompile Include="..\addons\slot1_retail_auto.cpp" />
<ClCompile Include="..\addons\slot1_retail_mcrom.cpp" /> <ClCompile Include="..\addons\slot1_retail_mcrom.cpp" />
<ClCompile Include="..\addons\slot1_retail_mcrom_debug.cpp" />
<ClCompile Include="..\addons\slot2_piano.cpp" /> <ClCompile Include="..\addons\slot2_piano.cpp" />
<ClCompile Include="..\addons\slot1_none.cpp" /> <ClCompile Include="..\addons\slot1_none.cpp" />
<ClCompile Include="..\addons\slot1_r4.cpp" /> <ClCompile Include="..\addons\slot1_r4.cpp" />
@ -464,6 +465,7 @@
<ClCompile Include="..\utils\datetime.cpp" /> <ClCompile Include="..\utils\datetime.cpp" />
<ClCompile Include="..\utils\dlditool.cpp" /> <ClCompile Include="..\utils\dlditool.cpp" />
<ClCompile Include="..\utils\emufat.cpp" /> <ClCompile Include="..\utils\emufat.cpp" />
<ClCompile Include="..\utils\fsnitro.cpp" />
<ClCompile Include="..\utils\libfat\cache.cpp" /> <ClCompile Include="..\utils\libfat\cache.cpp" />
<ClCompile Include="..\utils\libfat\directory.cpp" /> <ClCompile Include="..\utils\libfat\directory.cpp" />
<ClCompile Include="..\utils\libfat\disc.cpp" /> <ClCompile Include="..\utils\libfat\disc.cpp" />
@ -751,6 +753,7 @@
<ClInclude Include="..\utils\datetime.h" /> <ClInclude Include="..\utils\datetime.h" />
<ClInclude Include="..\utils\emufat.h" /> <ClInclude Include="..\utils\emufat.h" />
<ClInclude Include="..\utils\emufat_types.h" /> <ClInclude Include="..\utils\emufat_types.h" />
<ClInclude Include="..\utils\fsnitro.h" />
<ClInclude Include="..\utils\libfat\bit_ops.h" /> <ClInclude Include="..\utils\libfat\bit_ops.h" />
<ClInclude Include="..\utils\libfat\cache.h" /> <ClInclude Include="..\utils\libfat\cache.h" />
<ClInclude Include="..\utils\libfat\common.h" /> <ClInclude Include="..\utils\libfat\common.h" />

View File

@ -798,6 +798,12 @@
<ClCompile Include="..\addons\slot1comp_protocol.cpp"> <ClCompile Include="..\addons\slot1comp_protocol.cpp">
<Filter>Core\addons</Filter> <Filter>Core\addons</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\addons\slot1_retail_mcrom_debug.cpp">
<Filter>Core\addons</Filter>
</ClCompile>
<ClCompile Include="..\utils\fsnitro.cpp">
<Filter>Core\utils</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\addons.h"> <ClInclude Include="..\addons.h">
@ -1539,6 +1545,9 @@
<ClInclude Include="..\addons\slot1comp_protocol.h"> <ClInclude Include="..\addons\slot1comp_protocol.h">
<Filter>Core\addons</Filter> <Filter>Core\addons</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\utils\fsnitro.h">
<Filter>Core\utils</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\instruction_tabdef.inc"> <None Include="..\instruction_tabdef.inc">

View File

@ -386,6 +386,7 @@
<ClCompile Include="..\addons\slot1comp_rom.cpp" /> <ClCompile Include="..\addons\slot1comp_rom.cpp" />
<ClCompile Include="..\addons\slot1_retail_auto.cpp" /> <ClCompile Include="..\addons\slot1_retail_auto.cpp" />
<ClCompile Include="..\addons\slot1_retail_mcrom.cpp" /> <ClCompile Include="..\addons\slot1_retail_mcrom.cpp" />
<ClCompile Include="..\addons\slot1_retail_mcrom_debug.cpp" />
<ClCompile Include="..\addons\slot2_piano.cpp" /> <ClCompile Include="..\addons\slot2_piano.cpp" />
<ClCompile Include="..\addons\slot1_none.cpp" /> <ClCompile Include="..\addons\slot1_none.cpp" />
<ClCompile Include="..\addons\slot1_r4.cpp" /> <ClCompile Include="..\addons\slot1_r4.cpp" />
@ -475,6 +476,7 @@
<ClCompile Include="..\utils\datetime.cpp" /> <ClCompile Include="..\utils\datetime.cpp" />
<ClCompile Include="..\utils\dlditool.cpp" /> <ClCompile Include="..\utils\dlditool.cpp" />
<ClCompile Include="..\utils\emufat.cpp" /> <ClCompile Include="..\utils\emufat.cpp" />
<ClCompile Include="..\utils\fsnitro.cpp" />
<ClCompile Include="..\utils\libfat\cache.cpp" /> <ClCompile Include="..\utils\libfat\cache.cpp" />
<ClCompile Include="..\utils\libfat\directory.cpp" /> <ClCompile Include="..\utils\libfat\directory.cpp" />
<ClCompile Include="..\utils\libfat\disc.cpp" /> <ClCompile Include="..\utils\libfat\disc.cpp" />
@ -762,6 +764,7 @@
<ClInclude Include="..\utils\datetime.h" /> <ClInclude Include="..\utils\datetime.h" />
<ClInclude Include="..\utils\emufat.h" /> <ClInclude Include="..\utils\emufat.h" />
<ClInclude Include="..\utils\emufat_types.h" /> <ClInclude Include="..\utils\emufat_types.h" />
<ClInclude Include="..\utils\fsnitro.h" />
<ClInclude Include="..\utils\libfat\bit_ops.h" /> <ClInclude Include="..\utils\libfat\bit_ops.h" />
<ClInclude Include="..\utils\libfat\cache.h" /> <ClInclude Include="..\utils\libfat\cache.h" />
<ClInclude Include="..\utils\libfat\common.h" /> <ClInclude Include="..\utils\libfat\common.h" />

View File

@ -790,6 +790,12 @@
<ClCompile Include="..\addons\slot1comp_protocol.cpp"> <ClCompile Include="..\addons\slot1comp_protocol.cpp">
<Filter>Core\addons</Filter> <Filter>Core\addons</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\addons\slot1_retail_mcrom_debug.cpp">
<Filter>Core\addons</Filter>
</ClCompile>
<ClCompile Include="..\utils\fsnitro.cpp">
<Filter>Core\utils</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\addons.h"> <ClInclude Include="..\addons.h">
@ -1401,6 +1407,9 @@
<ClInclude Include="..\addons\slot1comp_protocol.h"> <ClInclude Include="..\addons\slot1comp_protocol.h">
<Filter>Core\addons</Filter> <Filter>Core\addons</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\utils\fsnitro.h">
<Filter>Core\utils</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\instruction_tabdef.inc"> <None Include="..\instruction_tabdef.inc">

View File

@ -82,7 +82,7 @@ void readConsole()
{ {
for (u32 i = 0; i < num; i++) 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) if (execute)
NDS_Pause(false); NDS_Pause(false);

View File

@ -99,14 +99,16 @@ u32 Slot1_IDDs[NDS_SLOT1_COUNT] = {
IDD_SLOT1_R4, // NDS_SLOT1_R4, - R4 flash card 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_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_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] = { DLGPROC Slot1_Procs[NDS_SLOT1_COUNT] = {
Slot1None,
Slot1None, // NDS_SLOT1_RETAIL_AUTO - autodetect which kind of retail card to use Slot1None, // NDS_SLOT1_RETAIL_AUTO - autodetect which kind of retail card to use
Slot1None, // NDS_SLOT1_R4, - R4 flash card Slot1None, // NDS_SLOT1_R4, - R4 flash card
Slot1R4, // NDS_SLOT1_RETAIL_NAND - Made in Ore/WarioWare D.I.Y. Slot1R4, // NDS_SLOT1_RETAIL_NAND - Made in Ore/WarioWare D.I.Y.
Slot1None, // NDS_SLOT1_RETAIL_MCROM - a standard MC (eeprom, flash, fram) 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; break;
case NDS_SLOT1_RETAIL_NAND: case NDS_SLOT1_RETAIL_NAND:
break; break;
case NDS_SLOT1_RETAIL_DEBUG:
break;
default: default:
return; return;
} }