- add streaming ROM data from disk. I was broke all ports except windows, on linux/mac ports need fix rom_init_path in NDSSystem.cpp but i can't test this;
This commit is contained in:
mtabachenko 2013-10-28 13:18:37 +00:00
parent 76de7fc3ec
commit 8edec83002
18 changed files with 276 additions and 245 deletions

View File

@ -908,8 +908,6 @@ void MMU_Init(void)
memset(&MMU, 0, sizeof(MMU_struct));
MMU.CART_ROM = MMU.UNUSED_RAM;
//MMU.DTCMRegion = 0x027C0000;
//even though apps may change dtcm immediately upon startup, this is the correct hardware starting value:
MMU.DTCMRegion = 0x08000000;
@ -1056,16 +1054,6 @@ void SetupMMU(bool debugConsole, bool dsi) {
_MMU_MAIN_MEM_MASK32 = _MMU_MAIN_MEM_MASK & ~3;
}
void MMU_setRom(u8 * rom, u32 mask)
{
MMU.CART_ROM = rom;
}
void MMU_unsetRom()
{
MMU.CART_ROM=MMU.UNUSED_RAM;
}
static void execsqrt() {
u32 ret;
u8 mode = MMU_new.sqrt.mode;

View File

@ -406,9 +406,6 @@ struct MMU_struct
//32KB of shared WRAM - can be switched between ARM7 & ARM9 in two blocks
u8 SWIRAM[0x8000];
//Card rom & ram
u8 * CART_ROM;
//Unused ram
u8 UNUSED_RAM[4];
@ -546,9 +543,6 @@ void MMU_DeInit(void);
void MMU_Reset( void);
void MMU_setRom(u8 * rom, u32 mask);
void MMU_unsetRom( void);
void print_memory_profiling( void);
// Memory reading/writing (old)

View File

@ -153,10 +153,9 @@ int NDS_Init( void)
return 0;
}
void NDS_DeInit(void) {
if(MMU.CART_ROM != MMU.UNUSED_RAM)
NDS_FreeROM();
void NDS_DeInit(void)
{
gameInfo.closeROM();
SPU_DeInit();
Screen_DeInit();
MMU_DeInit();
@ -191,23 +190,11 @@ void NDS_DeInit(void) {
#endif
}
BOOL NDS_SetROM(u8 * rom, u32 mask)
{
MMU_setRom(rom, mask);
return TRUE;
}
NDS_header * NDS_getROMHeader(void)
{
if(MMU.CART_ROM == MMU.UNUSED_RAM) return NULL;
NDS_header * header = new NDS_header;
//copy all data blindly, but not entirely blindly.. in case the header is smaller than normal, we dont want to read junk data
//(we memset to 0xFF since thats likely to be what gets read from the invalid area)
memset(header,0xFF,sizeof(NDS_header));
int todo = std::min<u32>(gameInfo.romsize,sizeof(NDS_header));
memcpy(header,MMU.CART_ROM,todo);
memcpy(header, &gameInfo.header, sizeof(gameInfo.header));
//endian swap necessary fields. It would be better if we made accessors for these. I wonder if you could make a macro for a field accessor that would take the bitsize and do the swap on the fly
struct FieldSwap {
@ -245,6 +232,9 @@ NDS_header * NDS_getROMHeader(void)
{ offsetof(NDS_header,endROMoffset), 4},
{ offsetof(NDS_header,HeaderSize), 4},
{ offsetof(NDS_header, ARM9module), 4},
{ offsetof(NDS_header, ARM7module), 4},
{ offsetof(NDS_header,logoCRC16), 2},
{ offsetof(NDS_header,headerCRC16), 2},
};
@ -339,14 +329,7 @@ bool GameInfo::hasRomBanner()
const RomBanner& GameInfo::getRomBanner()
{
//we may not have a valid banner. return a default one
if(!hasRomBanner())
{
static RomBanner defaultBanner(true);
return defaultBanner;
}
return *(RomBanner*)(romdata+header.IconOff);
return banner;
}
void GameInfo::populate()
@ -440,31 +423,105 @@ void GameInfo::populate()
}
bool GameInfo::isDSiEnhanced()
{
return ((*(u32*)(romdata + 0x180) == 0x8D898581U) && (*(u32*)(romdata + 0x184) == 0x8C888480U));
}
#ifdef _WINDOWS
static std::vector<char> buffer;
static std::vector<char> v;
static void loadrom(std::string fname) {
FILE* inf = fopen(fname.c_str(),"rb");
if(!inf) return;
bool GameInfo::loadROM(std::string fname)
{
printf("ROM %s\n", CommonSettings.loadToMemory?"loaded to RAM":"stream from disk");
fseek(inf,0,SEEK_END);
int size = ftell(inf);
fseek(inf,0,SEEK_SET);
closeROM();
gameInfo.resize(size);
fROM = fopen(fname.c_str(), "rb");
if (!fROM) return false;
gameInfo.loadRom(inf);
fseek(fROM, 0, SEEK_END);
romsize = ftell(fROM);
fseek(fROM, 0, SEEK_SET);
gameInfo.fillGap();
bool res = (fread(&header, 1, sizeof(header), fROM) == sizeof(header));
fclose(inf);
if (res)
{
cardSize = (128 * 1024) << header.cardSize;
mask = (cardSize - 1);
mask |= (mask >>1);
mask |= (mask >>2);
mask |= (mask >>4);
mask |= (mask >>8);
mask |= (mask >>16);
fseek(fROM, 0x4000, SEEK_SET);
fread(&secureArea[0], 1, 0x4000, fROM);
if (CommonSettings.loadToMemory)
{
fseek(fROM, 0, SEEK_SET);
romdata = new u8[romsize + 4];
if (fread(romdata, 1, romsize, fROM) != romsize)
{
delete [] romdata; romdata = NULL;
romsize = 0;
return false;
}
if(hasRomBanner())
memcpy(&banner, romdata + header.IconOff, sizeof(RomBanner));
_isDSiEnhanced = ((*(u32*)(romdata + 0x180) == 0x8D898581U) && (*(u32*)(romdata + 0x184) == 0x8C888480U));
fclose(fROM); fROM = NULL;
return true;
}
_isDSiEnhanced = ((readROM(0x180) == 0x8D898581U) && (readROM(0x184) == 0x8C888480U));
if (hasRomBanner())
{
fseek(fROM, header.IconOff, SEEK_SET);
fread(&banner, 1, sizeof(RomBanner), fROM);
}
fseek(fROM, 0, SEEK_SET);
lastReadPos = 0;
return true;
}
romsize = 0;
fclose(fROM); fROM = NULL;
return false;
}
void GameInfo::closeROM()
{
if (fROM)
fclose(fROM);
if (romdata)
delete [] romdata;
fROM = NULL;
romdata = NULL;
romsize = 0;
lastReadPos = 0xFFFFFFFF;
}
u32 GameInfo::readROM(u32 pos)
{
if ((pos < 0x8000) && (pos >= 0x4000))
return *(u32*)(secureArea + (pos - 0x4000));
if (!romdata)
{
u32 data;
if (lastReadPos != pos)
fseek(fROM, pos, SEEK_SET);
u32 num = fread(&data, 1, 4, fROM);
lastReadPos = (pos + num);
return data;
}
else
return *(u32*)(romdata + pos);
}
static int rom_init_path(const char *filename, const char *physicalName, const char *logicalFilename)
@ -475,11 +532,11 @@ static int rom_init_path(const char *filename, const char *physicalName, const c
if ( path.isdsgba(path.path)) {
type = ROM_DSGBA;
loadrom(path.path);
gameInfo.loadROM(path.path);
}
else if ( !strcasecmp(path.extension().c_str(), "nds")) {
type = ROM_NDS;
loadrom(physicalName ? physicalName : path.path); //n.b. this does nothing if the file can't be found (i.e. if it was an extracted tempfile)...
gameInfo.loadROM(physicalName ? physicalName : path.path); //n.b. this does nothing if the file can't be found (i.e. if it was an extracted tempfile)...
//...but since the data was extracted to gameInfo then it is ok
}
//ds.gba in archives, it's already been loaded into memory at this point
@ -488,14 +545,17 @@ static int rom_init_path(const char *filename, const char *physicalName, const c
} else {
//well, try to load it as an nds rom anyway
type = ROM_NDS;
loadrom(physicalName ? physicalName : path.path);
gameInfo.loadROM(physicalName ? physicalName : path.path);
}
// TODO: !!!!!
#if 0
if(type == ROM_DSGBA)
{
std::vector<char> v(gameInfo.romdata + DSGBA_LOADER_SIZE, gameInfo.romdata + gameInfo.romsize);
gameInfo.loadData(&v[0],gameInfo.romsize - DSGBA_LOADER_SIZE);
}
#endif
//check that size is at least the size of the header
if (gameInfo.romsize < 352) {
@ -555,6 +615,7 @@ static int rom_init_path(const char *filename, const char *physicalName, const c
// Make sure old ROM is freed first(at least this way we won't be eating
// up a ton of ram before the old ROM is freed)
if(MMU.CART_ROM != MMU.UNUSED_RAM)
NDS_FreeROM();
@ -585,17 +646,19 @@ int NDS_LoadROM(const char *filename, const char *physicalName, const char *logi
//check whether this rom is any kind of valid
if(!CheckValidRom((u8*)gameInfo.romdata,gameInfo.romsize))
if(!CheckValidRom((u8*)&gameInfo.header, gameInfo.secureArea))
{
printf("Specified file is not a valid rom\n");
return -1;
}
MMU_unsetRom();
NDS_SetROM((u8*)gameInfo.romdata, gameInfo.mask);
gameInfo.populate();
gameInfo.crc = crc32(0,(u8*)gameInfo.romdata,gameInfo.romsize);
if (CommonSettings.loadToMemory)
gameInfo.crc = crc32(0, (u8*)gameInfo.romdata, gameInfo.romsize);
else
gameInfo.crc = 0;
gameInfo.chipID = 0xC2; // The Manufacturer ID is defined by JEDEC (C2h = Macronix)
gameInfo.chipID |= ((((128 << gameInfo.header.cardSize) / 1024) - 1) << 8); // Chip size in megabytes minus 1
@ -623,9 +686,6 @@ int NDS_LoadROM(const char *filename, const char *physicalName, const char *logi
if (gameInfo.isDSiEnhanced()) INFO("ROM DSi Enhanced\n");
INFO("ROM developer: %s\n", getDeveloperNameByID(gameInfo.header.makerCode).c_str());
//crazymax: how would it have got whacked? dont think we need this
//gameInfo.storeSecureArea();
#if 1
u32 mask = gameInfo.header.endROMoffset - 1;
mask |= (mask >> 1);
@ -636,7 +696,7 @@ int NDS_LoadROM(const char *filename, const char *physicalName, const char *logi
printf("======================================================================\n");
printf("card size %10u (%08Xh) mask %08Xh\n", gameInfo.cardSize, gameInfo.cardSize, gameInfo.mask);
printf("file size %10u (%08Xh) mask %08Xh\n", gameInfo.romsize, gameInfo.romsize, gameInfo.filemask);
printf("file size %10u (%08Xh)\n", gameInfo.romsize, gameInfo.romsize);
printf("endROMoffset %10u (%08Xh) mask %08Xh\n", gameInfo.header.endROMoffset, gameInfo.header.endROMoffset, mask);
printf("======================================================================\n");
#endif
@ -672,7 +732,7 @@ int NDS_LoadROM(const char *filename, const char *physicalName, const char *logi
printf("\n");
//for homebrew, try auto-patching DLDI. should be benign if there is no DLDI or if it fails
if(gameInfo.isHomebrew)
if(gameInfo.isHomebrew && CommonSettings.loadToMemory)
DLDI::tryPatch((void*)gameInfo.romdata, gameInfo.romsize);
if (cheats != NULL)
@ -691,11 +751,7 @@ int NDS_LoadROM(const char *filename, const char *physicalName, const char *logi
void NDS_FreeROM(void)
{
FCEUI_StopMovie();
if ((u8*)MMU.CART_ROM == (u8*)gameInfo.romdata)
gameInfo.romdata = NULL;
if (MMU.CART_ROM != MMU.UNUSED_RAM)
delete [] MMU.CART_ROM;
MMU_unsetRom();
gameInfo.closeROM();
}
u32 NDS_ImportSaveSize(const char *filename)
@ -2505,7 +2561,7 @@ bool NDS_LegitBoot()
//since firmware only boots encrypted roms, we have to make sure it's encrypted first
//this has not been validated on big endian systems. it almost positively doesn't work.
EncryptSecureArea((u8*)gameInfo.romdata,gameInfo.romsize);
EncryptSecureArea((u8*)&gameInfo.header, (u8*)gameInfo.secureArea);
//boot processors from their bios entrypoints
armcpu_init(&NDS_ARM7, 0x00000000);
@ -2548,7 +2604,7 @@ bool NDS_FakeBoot()
//since we're bypassing the code to decrypt the secure area, we need to make sure its decrypted first
//this has not been validated on big endian systems. it almost positively doesn't work.
bool okRom = DecryptSecureArea((u8*)gameInfo.romdata,gameInfo.romsize);
bool okRom = DecryptSecureArea((u8*)&gameInfo.header, (u8*)gameInfo.secureArea);
if(!okRom) {
printf("Specified file is not a valid rom\n");
@ -2578,7 +2634,8 @@ bool NDS_FakeBoot()
u32 dst = header->ARM9cpy;
for(u32 i = 0; i < (header->ARM9binSize>>2); ++i)
{
_MMU_write32<ARMCPU_ARM9>(dst, T1ReadLong(MMU.CART_ROM, src));
_MMU_write32<ARMCPU_ARM9>(dst, gameInfo.readROM(src));
dst += 4;
src += 4;
}
@ -2588,7 +2645,8 @@ bool NDS_FakeBoot()
dst = header->ARM7cpy;
for(u32 i = 0; i < (header->ARM7binSize>>2); ++i)
{
_MMU_write32<ARMCPU_ARM7>(dst, T1ReadLong(MMU.CART_ROM, src));
_MMU_write32<ARMCPU_ARM7>(dst, gameInfo.readROM(src));
dst += 4;
src += 4;
}
@ -2613,13 +2671,13 @@ bool NDS_FakeBoot()
if(nds.Is_DSI())
{
//dsi needs this copied later in memory. there are probably a number of things that get copied to a later location in memory.. thats where the NDS consoles tend to stash stuff.
for (int i = 0; i < ((0x170)/4); i++)
_MMU_write32<ARMCPU_ARM9>(0x02FFFE00+i*4, LE_TO_LOCAL_32(((u32*)MMU.CART_ROM)[i]));
for (int i = 0; i < (0x170); i+=4)
_MMU_write32<ARMCPU_ARM9>(0x027FFE00 + i, LE_TO_LOCAL_32(gameInfo.readROM(i)));
}
else
{
for (int i = 0; i < ((0x170)/4); i++)
_MMU_write32<ARMCPU_ARM9>(0x027FFE00+i*4, LE_TO_LOCAL_32(((u32*)MMU.CART_ROM)[i]));
for (int i = 0; i < (0x170); i+=4)
_MMU_write32<ARMCPU_ARM9>(0x027FFE00 + i, LE_TO_LOCAL_32(gameInfo.readROM(i)));
}
//the firmware will be booting to these entrypoint addresses via BX (well, the arm9 at least; is unverified for the arm7)

View File

@ -297,7 +297,7 @@ NDS_header * NDS_getROMHeader(void);
struct RomBanner
{
RomBanner(bool defaultInit);
RomBanner(bool defaultInit = true);
u16 version; //Version (0001h)
u16 crc16; //CRC16 across entries 020h..83Fh
u8 reserved[0x1C]; //Reserved (zero-filled)
@ -322,102 +322,48 @@ struct RomBanner
struct GameInfo
{
GameInfo() : romdata(NULL),
FILE *fROM;
u8 *romdata;
u32 romsize;
u32 cardSize;
u32 mask;
u32 crc;
u32 chipID;
u32 lastReadPos;
char ROMserial[20];
char ROMname[20];
bool _isDSiEnhanced;
bool isHomebrew;
NDS_header header;
//a copy of the pristine secure area from the rom
u8 secureArea[0x4000];
RomBanner banner;
const RomBanner& getRomBanner();
GameInfo() : fROM(NULL),
romdata(NULL),
crc(0),
chipID(0x00000FC2),
romsize(0),
cardSize(0),
allocatedSize(0),
mask(0),
filemask(0)
lastReadPos(0xFFFFFFFF),
_isDSiEnhanced(false)
{
memset(&header, 0, sizeof(header));
memset(&ROMserial[0], 0, sizeof(ROMserial));
memset(&ROMname[0], 0, sizeof(ROMname));
memset(&secureArea[0], 0, sizeof(secureArea));
}
void loadData(char* buf, int size)
{
resize(size);
memcpy(romdata,buf,size);
romsize = (u32)size;
fillGap();
}
~GameInfo() { closeROM(); }
void storeSecureArea()
{
if ((header.ARM9src >= 0x4000) && (header.ARM9src < 0x8000))
memcpy(&secureArea[0], &romdata[header.ARM9src], 0x8000 - header.ARM9src);
}
void restoreSecureArea()
{
if ((header.ARM9src >= 0x4000) && (header.ARM9src < 0x8000))
memcpy(&romdata[header.ARM9src], &secureArea[0], 0x8000 - header.ARM9src);
}
void fillGap()
{
memset(romdata+romsize,0xFF,allocatedSize-romsize);
}
void resize(int size) {
if(romdata != NULL) delete[] romdata;
//calculate the necessary mask for the requested size
filemask = (size - 1);
filemask |= (filemask >>1);
filemask |= (filemask >>2);
filemask |= (filemask >>4);
filemask |= (filemask >>8);
filemask |= (filemask >>16);
//now, we actually need to over-allocate, because bytes from anywhere protected by that mask
//could be read from the rom
allocatedSize = (filemask + 4);
romdata = new char[allocatedSize];
romsize = size;
}
bool loadRom(FILE *fp)
{
bool res = (fread(romdata, 1, romsize, fp) == romsize);
if (res)
{
cardSize = (128 * 1024) << romdata[0x14];
mask = (cardSize - 1);
mask |= (mask >>1);
mask |= (mask >>2);
mask |= (mask >>4);
mask |= (mask >>8);
mask |= (mask >>16);
return true;
}
return false;
}
bool isDSiEnhanced();
u32 crc;
u32 chipID;
NDS_header header;
char ROMserial[20];
char ROMname[20];
//char ROMfullName[7][0x100];
bool loadROM(std::string fname);
void closeROM();
u32 readROM(u32 pos);
void populate();
char* romdata;
u32 romsize;
u32 cardSize;
u32 allocatedSize;
u32 mask;
u32 filemask;
const RomBanner& getRomBanner();
bool isDSiEnhanced() { return _isDSiEnhanced; };
bool hasRomBanner();
bool isHomebrew;
//a copy of the pristine secure area from the rom
u8 secureArea[0x4000];
};
typedef struct TSCalInfo
@ -551,6 +497,7 @@ extern struct TCommonSettings {
, GFX3D_Zelda_Shadow_Depth_Hack(0)
, GFX3D_Renderer_Multisample(false)
, jit_max_block_size(100)
, loadToMemory(true)
, UseExtBIOS(false)
, SWIFromBIOS(false)
, PatchSWI3(false)
@ -604,6 +551,8 @@ extern struct TCommonSettings {
int GFX3D_Zelda_Shadow_Depth_Hack;
bool GFX3D_Renderer_Multisample;
bool loadToMemory;
bool UseExtBIOS;
char ARM9BIOS[256];
char ARM7BIOS[256];

View File

@ -51,17 +51,23 @@ public:
virtual void connect()
{
if (!MMU.CART_ROM) return;
protocol.reset(this);
protocol.chipId = gameInfo.chipID;
protocol.gameCode = T1ReadLong((u8*)gameInfo.header.gameCode,0);
curr_file_id = 0xFFFF;
fpROM = NULL;
fs = NULL;
if (!CommonSettings.loadToMemory)
{
printf("NitroFS: change load type to \"Load to RAM\"\n");
return;
}
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 = new FS_NITRO(gameInfo.romdata);
fs->rebuildFAT(pathData);
}
@ -113,13 +119,13 @@ public:
u16 file_id = 0xFFFF; u32 offset = 0;
bool bFromFile = false;
if (fs->isFAT(protocol.address))
if (fs && fs->isFAT(protocol.address))
{
fs->rebuildFAT(protocol.address, protocol.length, pathData);
}
else
{
if (fs->getFileIdByAddr(protocol.address, file_id, offset))
if (fs && fs->getFileIdByAddr(protocol.address, file_id, offset))
{
if (file_id != curr_file_id)
{
@ -178,7 +184,7 @@ private:
u32 address = rom.getAddress();
if (fs->isFAT(address))
if (fs && fs->isFAT(address))
{
u32 res = fs->getFATRecord(address);
if (res != 0xFFFFFFFF)

View File

@ -32,7 +32,7 @@ u32 Slot1Comp_Rom::read()
{
case eSlot1Operation_00_ReadHeader_Unencrypted:
{
u32 ret = T1ReadLong(MMU.CART_ROM, address);
u32 ret = gameInfo.readROM(address);
address = (address + 4) & 0xFFF;
return ret;
}
@ -42,7 +42,7 @@ u32 Slot1Comp_Rom::read()
{
//see B7 for details
address &= gameInfo.mask; //sanity check
u32 ret = T1ReadLong(MMU.CART_ROM, address);
u32 ret = gameInfo.readROM(address);
address = (address&~0xFFF) + ((address+4)&0xFFF);
return ret;
}
@ -72,7 +72,7 @@ u32 Slot1Comp_Rom::read()
}
//actually read from the ROM provider
u32 ret = T1ReadLong(MMU.CART_ROM, address);
u32 ret = gameInfo.readROM(address);
//"However, the datastream wraps to the begin of the current 4K block when address+length crosses a 4K boundary (1000h bytes)"
address = (address&~0xFFF) + ((address+4)&0xFFF);

View File

@ -33,6 +33,7 @@ int _commandline_linux_nojoy = 0;
CommandLine::CommandLine()
: is_cflash_configured(false)
, _load_to_memory(-1)
, error(NULL)
, ctx(g_option_context_new (""))
, _play_movie_file(0)
@ -80,6 +81,7 @@ void CommandLine::loadCommonOptions()
//but also see the gtk port for an example of how to combine this with other options
//(you may need to use ifdefs to cause options to be entered in the desired order)
static const GOptionEntry options[] = {
{ "load-type", 0, 0, G_OPTION_ARG_INT, &_load_to_memory, "Load ROM type, 0 - stream from disk, 1 - to RAM (default 1)", "LOAD_TYPE"},
{ "load-slot", 0, 0, G_OPTION_ARG_INT, &load_slot, "Loads savegame from slot NUM", "NUM"},
{ "play-movie", 0, 0, G_OPTION_ARG_FILENAME, &_play_movie_file, "Specifies a dsm format movie to play", "PATH_TO_PLAY_MOVIE"},
{ "record-movie", 0, 0, G_OPTION_ARG_FILENAME, &_record_movie_file, "Specifies a path to a new dsm format movie", "PATH_TO_RECORD_MOVIE"},
@ -143,6 +145,7 @@ bool CommandLine::parse(int argc,char **argv)
if(_slot1_fat_dir) slot1_fat_dir = _slot1_fat_dir;
if(_slot1) slot1 = _slot1; slot1 = strtoupper(slot1);
if(_console_type) console_type = _console_type;
if(_load_to_memory != -1) CommonSettings.loadToMemory = (_load_to_memory == 1)?true:false;
if(_play_movie_file) play_movie_file = _play_movie_file;
if(_record_movie_file) record_movie_file = _record_movie_file;
if(_cflash_image) cflash_image = _cflash_image;
@ -210,6 +213,11 @@ bool CommandLine::validate()
}
}
if (_load_to_memory < -1 || _load_to_memory > 1) {
g_printerr("Invalid parameter (0 - stream from disk, 1 - from RAM)\n");
return false;
}
if (load_slot < -1 || load_slot > 10) {
g_printerr("I only know how to load from slots 0-10; -1 means 'do not load savegame' and is default\n");
return false;

View File

@ -85,6 +85,7 @@ private:
char* _cflash_path;
char* _gbaslot_rom;
char* _bios_arm9, *_bios_arm7;
int _load_to_memory;
int _bios_swi;
int _spu_advanced;
int _num_cores;

View File

@ -487,12 +487,12 @@ static void encrypt_arm9(u32 cardheader_gamecode, unsigned char *data)
//0x0200 - 0x3FFF : typically, nothing is stored here. on retail cards, you can't read from that area anyway, but im not sure if that's done in the game card or the GC bus controller on the system
//0x4000 - 0x7FFF : secure area (details in gbatek)
bool DecryptSecureArea(u8 *romdata, long romlen)
bool DecryptSecureArea(u8 *romheader, u8 *secure)
{
//this looks like it will only work on little endian hosts
Header* header = (Header*)romdata;
Header* header = (Header*)romheader;
int romType = DetectRomType(*header,(char*)romdata);
int romType = DetectRomType(*header, (char*)secure);
if(romType == ROMTYPE_INVALID)
return false;
@ -512,7 +512,7 @@ bool DecryptSecureArea(u8 *romdata, long romlen)
//// write secure 0x800
//memcpy(romdata+0x4000,data,0x800);
decrypt_arm9(*(u32 *)header->gamecode, romdata+0x4000);
decrypt_arm9(*(u32 *)header->gamecode, secure);
printf("Decrypted.\n");
}
@ -524,12 +524,12 @@ bool DecryptSecureArea(u8 *romdata, long romlen)
return true;
}
bool EncryptSecureArea(u8 *romdata, long romlen)
bool EncryptSecureArea(u8 *romheader, u8 *secure)
{
//this looks like it will only work on little endian hosts
Header* header = (Header*)romdata;
Header* header = (Header*)romheader;
int romType = DetectRomType(*header,(char*)romdata);
int romType = DetectRomType(*header, (char*)secure);
if(romType == ROMTYPE_INVALID)
return false;
@ -544,7 +544,7 @@ bool EncryptSecureArea(u8 *romdata, long romlen)
//// write secure 0x800
//memcpy(romdata+0x4000,data,0x800);
encrypt_arm9(*(u32 *)header->gamecode, romdata+0x4000);
encrypt_arm9(*(u32 *)header->gamecode, secure);
printf("Encrypted.\n");
}
@ -552,11 +552,11 @@ bool EncryptSecureArea(u8 *romdata, long romlen)
return true;
}
bool CheckValidRom(u8 *romdata, long romlen)
bool CheckValidRom(u8 *header, u8 *secure)
{
Header* header = (Header*)romdata;
Header* hdr = (Header*)header;
int romType = DetectRomType(*header,(char*)romdata);
int romType = DetectRomType(*hdr, (char*)secure);
return (romType != ROMTYPE_INVALID);
}

View File

@ -24,12 +24,12 @@
extern const unsigned char arm7_key[];
//decrypts the secure area of a rom (or does nothing if it is already decrypted)
bool DecryptSecureArea(u8 *romdata, long romlen);
bool DecryptSecureArea(u8 *romheader, u8 *secure);
//encrypts the secure area of a rom (or does nothing if it is already encrypted)
bool EncryptSecureArea(u8 *romdata, long romlen);
bool EncryptSecureArea(u8 *romheader, u8 *secure);
//since we have rom-type detection heuristics here, this module is responsible for checking whether a rom is valid
bool CheckValidRom(u8 *romdata, long romlen);
bool CheckValidRom(u8 *header, u8 *secure);
#endif

View File

@ -66,9 +66,9 @@
/*
* DetectRomType
*/
int DetectRomType(const Header& header, char* romdata)
int DetectRomType(const Header& header, char* secure)
{
unsigned int * data = (unsigned int*)(romdata + 0x4000);
unsigned int * data = (unsigned int*)(secure);
//this is attempting to check for an utterly invalid nds header
if(header.unitcode < 0 && header.unitcode > 3) return ROMTYPE_INVALID;
@ -76,8 +76,9 @@ int DetectRomType(const Header& header, char* romdata)
if (header.arm9_rom_offset < 0x4000) return ROMTYPE_HOMEBREW;
if (data[0] == 0x00000000 && data[1] == 0x00000000) return ROMTYPE_MULTIBOOT;
if (data[0] == 0xE7FFDEFF && data[1] == 0xE7FFDEFF) return ROMTYPE_NDSDUMPED;
for (int i=0x200; i<0x4000; i++)
if (romdata[i]) return ROMTYPE_MASKROM; // found something odd ;)
//TODO
//for (int i=0x200; i<0x4000; i++)
// if (romdata[i]) return ROMTYPE_MASKROM; // found something odd ;)
return ROMTYPE_ENCRSECURE;
}

View File

@ -121,7 +121,7 @@ unsigned short CalcLogoCRC(Header &header);
void FixHeaderCRC(char *ndsfilename);
void ShowInfo(char *ndsfilename);
int HashAndCompareWithList(char *filename, unsigned char sha1[]);
int DetectRomType(const Header& header, char* romdata);
int DetectRomType(const Header& header, char* secure);
unsigned short CalcSecureAreaCRC(bool encrypt);
#define ROMTYPE_HOMEBREW 0

View File

@ -21,6 +21,7 @@
#include "fsnitroView.h"
#include "CWindow.h"
#include "../MMU.h"
#include "../NDSSystem.h"
#include "../path.h"
#include "../utils/fsnitro.h"
#include "memView.h"
@ -87,7 +88,7 @@ void refreshQView(HWND hWnd, u16 id)
u32 len = std::min<u32>(sizeof(buf), fs->getFileSizeById(id));
u32 start = fs->getStartAddrById(id);
memcpy(&buf[0], &MMU.CART_ROM[start], len);
memcpy(&buf[0], &gameInfo.romdata[start], len);
for (u32 i = 0; i < len; i++)
if (buf[i] < 0x20) buf[i] = 0x20;
@ -104,7 +105,8 @@ BOOL CALLBACK ViewFSNitroProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
{
case WM_INITDIALOG:
{
fs = new FS_NITRO(MMU.CART_ROM);
fs = new FS_NITRO(gameInfo.romdata);
if (!fs)
{
msgbox->error("Error reading FS from ROM");

View File

@ -110,82 +110,81 @@ LRESULT GInfo_Paint(HWND hDlg, WPARAM wParam, LPARAM lParam)
//TODO - pull this from the header, not straight out of the rom (yuck!)
memcpy(text, MMU.CART_ROM, 12);
memcpy(text, (u8*)&gameInfo.header, 12);
text[12] = '\0';
SetWindowText(GetDlgItem(hDlg, IDC_GI_GAMETITLE), text);
memcpy(text, (MMU.CART_ROM+0xC), 4);
memcpy(text, ((u8*)&gameInfo.header+0xC), 4);
text[4] = '\0';
SetWindowText(GetDlgItem(hDlg, IDC_GI_GAMECODE), text);
memcpy(text, (MMU.CART_ROM+0x10), 2);
memcpy(text, ((u8*)&gameInfo.header+0x10), 2);
text[2] = '\0';
SetWindowText(GetDlgItem(hDlg, IDC_GI_MAKERCODE), text);
SetWindowText(GetDlgItem(hDlg, IDC_SDEVELOPER), getDeveloperNameByID(T1ReadWord(MMU.CART_ROM, 0x10)).c_str());
SetWindowText(GetDlgItem(hDlg, IDC_SDEVELOPER), getDeveloperNameByID(T1ReadWord((u8*)&gameInfo.header, 0x10)).c_str());
val = T1ReadByte(MMU.CART_ROM, 0x14);
val = T1ReadByte((u8*)&gameInfo.header, 0x14);
sprintf(text, "%i kilobytes", (0x80 << val));
SetWindowText(GetDlgItem(hDlg, IDC_GI_CHIPSIZE), text);
val = T1ReadLong(MMU.CART_ROM, 0x20);
val = T1ReadLong((u8*)&gameInfo.header, 0x20);
sprintf(text, "0x%08X", val);
SetWindowText(GetDlgItem(hDlg, IDC_GI_ARM9ROM), text);
val = T1ReadLong(MMU.CART_ROM, 0x24);
val = T1ReadLong((u8*)&gameInfo.header, 0x24);
sprintf(text, "0x%08X", val);
SetWindowText(GetDlgItem(hDlg, IDC_GI_ARM9ENTRY), text);
val = T1ReadLong(MMU.CART_ROM, 0x28);
val = T1ReadLong((u8*)&gameInfo.header, 0x28);
sprintf(text, "0x%08X", val);
SetWindowText(GetDlgItem(hDlg, IDC_GI_ARM9START), text);
val = T1ReadLong(MMU.CART_ROM, 0x2C);
val = T1ReadLong((u8*)&gameInfo.header, 0x2C);
sprintf(text, "%i bytes", val);
SetWindowText(GetDlgItem(hDlg, IDC_GI_ARM9SIZE), text);
val = T1ReadLong(MMU.CART_ROM, 0x30);
val = T1ReadLong((u8*)&gameInfo.header, 0x30);
sprintf(text, "0x%08X", val);
SetWindowText(GetDlgItem(hDlg, IDC_GI_ARM7ROM), text);
val = T1ReadLong(MMU.CART_ROM, 0x34);
val = T1ReadLong((u8*)&gameInfo.header, 0x34);
sprintf(text, "0x%08X", val);
SetWindowText(GetDlgItem(hDlg, IDC_GI_ARM7ENTRY), text);
val = T1ReadLong(MMU.CART_ROM, 0x38);
val = T1ReadLong((u8*)&gameInfo.header, 0x38);
sprintf(text, "0x%08X", val);
SetWindowText(GetDlgItem(hDlg, IDC_GI_ARM7START), text);
val = T1ReadLong(MMU.CART_ROM, 0x3C);
val = T1ReadLong((u8*)&gameInfo.header, 0x3C);
sprintf(text, "%i bytes", val);
SetWindowText(GetDlgItem(hDlg, IDC_GI_ARM7SIZE), text);
val = T1ReadLong(MMU.CART_ROM, 0x40);
val = T1ReadLong((u8*)&gameInfo.header, 0x40);
sprintf(text, "0x%08X", val);
SetWindowText(GetDlgItem(hDlg, IDC_GI_FNTOFS), text);
val = T1ReadLong(MMU.CART_ROM, 0x44);
val = T1ReadLong((u8*)&gameInfo.header, 0x44);
sprintf(text, "%i bytes", val);
SetWindowText(GetDlgItem(hDlg, IDC_GI_FNTSIZE), text);
val = T1ReadLong(MMU.CART_ROM, 0x48);
val = T1ReadLong((u8*)&gameInfo.header, 0x48);
sprintf(text, "0x%08X", val);
SetWindowText(GetDlgItem(hDlg, IDC_GI_FATOFS), text);
val = T1ReadLong(MMU.CART_ROM, 0x4C);
val = T1ReadLong((u8*)&gameInfo.header, 0x4C);
sprintf(text, "%i bytes", val);
SetWindowText(GetDlgItem(hDlg, IDC_GI_FATSIZE), text);
icontitleOffset = T1ReadLong(MMU.CART_ROM, 0x68);
icontitleOffset = T1ReadLong((u8*)&gameInfo.header, 0x68);
sprintf(text, "0x%08X", icontitleOffset);
SetWindowText(GetDlgItem(hDlg, IDC_GI_ICONTITLEOFS), text);
val = T1ReadLong(MMU.CART_ROM, 0x80);
val = T1ReadLong((u8*)&gameInfo.header, 0x80);
sprintf(text, "0x%08X", val);
SetWindowText(GetDlgItem(hDlg, IDC_GI_USEDROMSIZE), text);
EndPaint(hDlg, &ps);
return 0;

View File

@ -2935,10 +2935,11 @@ int _main()
msgbox = &msgBoxWnd;
char text[80];
char text[80] = {0};
path.ReadPathSettings();
CommonSettings.loadToMemory = GetPrivateProfileBool("General", "loadType", true, IniName);
CommonSettings.cheatsDisable = GetPrivateProfileBool("General", "cheatsDisable", false, IniName);
CommonSettings.autodetectBackupMethod = GetPrivateProfileInt("General", "autoDetectMethod", 0, IniName);
@ -3975,11 +3976,10 @@ void CloseRom()
{
StopAllLuaScripts();
// cheatsSearchClose();
NDS_FreeROM();
romloaded = false;
execute = false;
Hud.resetTransient();
NDS_Reset();
NDS_FreeROM();
// clear screen so the last frame we rendered doesn't stick around
// (TODO: maybe NDS_Reset should do this?)
@ -4151,7 +4151,7 @@ void ScreenshotToClipboard(bool extraInfo)
int exHeight = 0;
if(extraInfo)
{
exHeight = (14 * (twolinever ? 7:6));
exHeight = (14 * (twolinever ? 8:7));
}
HDC hScreenDC = GetDC(NULL);
@ -4196,21 +4196,19 @@ void ScreenshotToClipboard(bool extraInfo)
else
TextOut(hMemDC, 0, 384 + 14, nameandver, strlen(nameandver));
char str[32];
memcpy(&str[0], &MMU.CART_ROM[0], 12); str[12] = '\0';
int titlelen = strlen(str);
str[titlelen] = ' ';
memcpy(&str[titlelen+1], &MMU.CART_ROM[12], 6); str[titlelen+1+6] = '\0';
TextOut(hMemDC, 8, 384 + 14 * (twolinever ? 3:2), str, strlen(str));
char str[32] = {0};
TextOut(hMemDC, 8, 384 + 14 * (twolinever ? 3:2), gameInfo.ROMname, strlen(gameInfo.ROMname));
TextOut(hMemDC, 8, 384 + 14 * (twolinever ? 4:3), gameInfo.ROMserial, strlen(gameInfo.ROMserial));
sprintf(str, "CPU: %s", CommonSettings.use_jit ? "JIT":"Interpreter");
TextOut(hMemDC, 8, 384 + 14 * (twolinever ? 4:3), str, strlen(str));
sprintf(str, "FPS: %i/%i (%02d%%/%02d%%) | %s", mainLoopData.fps, mainLoopData.fps3d, Hud.cpuload[0], Hud.cpuload[1], paused ? "Paused":"Running");
TextOut(hMemDC, 8, 384 + 14 * (twolinever ? 5:4), str, strlen(str));
sprintf(str, "3D Render: %s", core3DList[cur3DCore]->name);
sprintf(str, "FPS: %i/%i (%02d%%/%02d%%) | %s", mainLoopData.fps, mainLoopData.fps3d, Hud.cpuload[0], Hud.cpuload[1], paused ? "Paused":"Running");
TextOut(hMemDC, 8, 384 + 14 * (twolinever ? 6:5), str, strlen(str));
sprintf(str, "3D Render: %s", core3DList[cur3DCore]->name);
TextOut(hMemDC, 8, 384 + 14 * (twolinever ? 7:6), str, strlen(str));
}
OpenClipboard(NULL);
@ -4404,6 +4402,9 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
DesEnableMenuItem(mainMenu, IDC_BACKGROUNDINPUT, !lostFocusPause);
DesEnableMenuItem(mainMenu, ID_LOADTORAM, !romloaded);
DesEnableMenuItem(mainMenu, ID_STREAMFROMDISK, !romloaded);
//Update savestate slot items based on ROM loaded
for (int x = 0; x < 10; x++)
{
@ -4556,6 +4557,10 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
DesEnableMenuItem(mainMenu, IDM_SCREENSEP_COLORBLACK, false);
}
// load type
MainWindow->checkMenu(ID_STREAMFROMDISK, ((CommonSettings.loadToMemory == false)));
MainWindow->checkMenu(ID_LOADTORAM, ((CommonSettings.loadToMemory == true)));
// Tools
MainWindow->checkMenu(IDM_CONSOLE_ALWAYS_ON_TOP, gConsoleTopmost);
@ -5585,6 +5590,11 @@ DOKEYDOWN:
return 0;
case ID_TOOLS_VIEWFSNITRO:
if (!CommonSettings.loadToMemory)
{
msgbox->error("Change load type to \"Load to RAM\"");
return 0;
}
ViewFSNitro->open();
return 0;
//========================================================== Tools end
@ -5800,6 +5810,16 @@ DOKEYDOWN:
ResetGame();
return 0;
case ID_STREAMFROMDISK:
CommonSettings.loadToMemory = false;
WritePrivateProfileBool("General", "loadType", CommonSettings.loadToMemory, IniName);
return 0;
case ID_LOADTORAM:
CommonSettings.loadToMemory = true;
WritePrivateProfileBool("General", "loadType", CommonSettings.loadToMemory, IniName);
return 0;
case IDM_3DCONFIG:
{
bool tpaused = false;

View File

@ -82,7 +82,7 @@ u8 memRead8 (MemRegionType regionType, HWAddressType address)
return value;
case MEMVIEW_ROM:
if (address < gameInfo.romsize)
value = MMU.CART_ROM[address];
value = gameInfo.romdata[address];
return value;
case MEMVIEW_FULL:
MMU_DumpMemBlock(0, address, 1, &value);
@ -113,7 +113,7 @@ u16 memRead16 (MemRegionType regionType, HWAddressType address)
return value;
case MEMVIEW_ROM:
if (address < (gameInfo.romsize - 2))
value = T1ReadWord(MMU.CART_ROM, address);
value = T1ReadWord(gameInfo.romdata, address);
return value;
case MEMVIEW_FULL:
MMU_DumpMemBlock(0, address, 2, (u8*)&value);
@ -144,7 +144,8 @@ u32 memRead32 (MemRegionType regionType, HWAddressType address)
return value;
case MEMVIEW_ROM:
if (address < (gameInfo.romsize - 4))
value = T1ReadLong(MMU.CART_ROM, address);
value = T1ReadLong(gameInfo.romdata, address);
return value;
case MEMVIEW_FULL:
MMU_DumpMemBlock(0, address, 4, (u8*)&value);
@ -197,7 +198,7 @@ void memWrite8(MemRegionType regionType, HWAddressType address, u8 value)
MMU.fw.data[address] = value;
break;
case MEMVIEW_ROM:
MMU.CART_ROM[address] = value;
gameInfo.romdata[address] = value;
break;
case MEMVIEW_FULL:
MMU_write8(ARMCPU_ARM9, address, value);
@ -220,7 +221,7 @@ void memWrite16(MemRegionType regionType, HWAddressType address, u16 value)
*((u16*)&MMU.fw.data[address]) = value;
break;
case MEMVIEW_ROM:
*((u16*)&MMU.CART_ROM[address]) = value;
*((u16*)&gameInfo.romdata[address]) = value;
break;
case MEMVIEW_FULL:
MMU_write16(ARMCPU_ARM9, address, value);
@ -243,7 +244,7 @@ void memWrite32(MemRegionType regionType, HWAddressType address, u32 value)
*((u32*)&MMU.fw.data[address]) = value;
break;
case MEMVIEW_ROM:
*((u32*)&MMU.CART_ROM[address]) = value;
*((u32*)&gameInfo.romdata[address]) = value;
break;
case MEMVIEW_FULL:
MMU_write32(ARMCPU_ARM9, address, value);
@ -271,8 +272,9 @@ CMemView::CMemView(MemRegionType memRegion, u32 start_address)
s_memoryRegions.push_back(s_arm9Region);
s_memoryRegions.push_back(s_arm7Region);
s_memoryRegions.push_back(s_firmwareRegion);
s_memoryRegions.push_back(s_RomRegion);
s_memoryRegions.push_back(s_fullRegion);
if (CommonSettings.loadToMemory)
s_memoryRegions.push_back(s_RomRegion);
}
PostInitialize();

View File

@ -934,8 +934,11 @@
#define IDC_VIEW_PADTOINTEGER 40107
#define ID_TOOLS_VIEWFSNITRO 40108
#define ID_EXTRACTFILE 40109
#define ID_CONFIG_LOADROMTYPE 40109
#define ID_EXTRACTALL 40110
#define ID_LOADTORAM 40110
#define ID_CLOSE 40111
#define ID_STREAMFROMDISK 40111
#define ID_FSNITRO_VIEW 40112
#define ID_LABEL_HK3b 44670
#define ID_LABEL_HK3c 44671
@ -1043,7 +1046,7 @@
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 1
#define _APS_NEXT_RESOURCE_VALUE 128
#define _APS_NEXT_COMMAND_VALUE 40109
#define _APS_NEXT_COMMAND_VALUE 40111
#define _APS_NEXT_CONTROL_VALUE 1057
#define _APS_NEXT_SYMED_VALUE 101
#endif

Binary file not shown.