diff --git a/desmume/src/NDSSystem.cpp b/desmume/src/NDSSystem.cpp index c1a769373..5601d506d 100644 --- a/desmume/src/NDSSystem.cpp +++ b/desmume/src/NDSSystem.cpp @@ -505,36 +505,45 @@ bool GameInfo::loadROM(std::string fname, u32 type) reader->Read(fROM, &secureArea[0], 0x4000); } - if (CommonSettings.loadToMemory) + //for now, we have to do this, because the DLDI patching requires it + bool loadToMemory = CommonSettings.loadToMemory; + if(isHomebrew()) + loadToMemory = true; + + //convert to an in-memory reader around a pre-read buffer if that's what's requested + if (loadToMemory) { reader->Seek(fROM, headerOffset, SEEK_SET); - romdata = new u8[romsize + 4]; - if (reader->Read(fROM, romdata, romsize) != romsize) + romdataForReader = new u8[romsize]; + if (reader->Read(fROM, romdataForReader, romsize) != romsize) { - delete [] romdata; romdata = NULL; + delete [] romdataForReader; romdataForReader = NULL; romsize = 0; return false; } - if(hasRomBanner()) - { - memcpy(&banner, romdata + header.IconOff, sizeof(RomBanner)); - - banner.version = LE_TO_LOCAL_16(banner.version); - banner.crc16 = LE_TO_LOCAL_16(banner.crc16); - - for(size_t i = 0; i < ARRAY_SIZE(banner.palette); i++) - { - banner.palette[i] = LE_TO_LOCAL_16(banner.palette[i]); - } - } - - _isDSiEnhanced = (LE_TO_LOCAL_32(*(u32*)(romdata + 0x180) == 0x8D898581U) && LE_TO_LOCAL_32(*(u32*)(romdata + 0x184) == 0x8C888480U)); - reader->DeInit(fROM); fROM = NULL; - return true; + reader->DeInit(fROM); + fROM = NULL; + reader = MemROMReaderRead_TrueInit(romdataForReader, romsize); + fROM = reader->Init(NULL); } + + if(hasRomBanner()) + { + reader->Seek(fROM, header.IconOff, SEEK_SET); + reader->Read(fROM, &banner, sizeof(RomBanner)); + + banner.version = LE_TO_LOCAL_16(banner.version); + banner.crc16 = LE_TO_LOCAL_16(banner.crc16); + + for(size_t i = 0; i < ARRAY_SIZE(banner.palette); i++) + { + banner.palette[i] = LE_TO_LOCAL_16(banner.palette[i]); + } + } + _isDSiEnhanced = ((readROM(0x180) == 0x8D898581U) && (readROM(0x184) == 0x8C888480U)); if (hasRomBanner()) { @@ -561,14 +570,15 @@ bool GameInfo::loadROM(std::string fname, u32 type) void GameInfo::closeROM() { - if (fROM) + if (reader) reader->DeInit(fROM); - if (romdata) - delete [] romdata; + if (romdataForReader) + delete [] romdataForReader; fROM = NULL; - romdata = NULL; + reader = NULL; + romdataForReader = NULL; romsize = 0; lastReadPos = 0xFFFFFFFF; } @@ -577,36 +587,10 @@ u32 GameInfo::readROM(u32 pos) { u32 num; u32 data; - if (!romdata) - { - if (lastReadPos != pos) - reader->Seek(fROM, pos + headerOffset, SEEK_SET); - num = reader->Read(fROM, &data, 4); - lastReadPos = (pos + num); - } - else - { - if(pos + 4 <= romsize) - { - //fast path - data = LE_TO_LOCAL_32(*(u32*)(romdata + pos)); - num = 4; - } - else - { - data = 0; - num = 0; - for(int i=0;i<4;i++) - { - if(pos >= romsize) - break; - data |= (romdata[pos]<<(i*8)); - pos++; - num++; - } - } - } - + if (lastReadPos != pos) + reader->Seek(fROM, pos + headerOffset, SEEK_SET); + num = reader->Read(fROM, &data, 4); + lastReadPos = (pos + num); //in case we didn't read enough data, pad the remainder with 0xFF u32 pad = 0; @@ -669,8 +653,16 @@ static int rom_init_path(const char *filename, const char *physicalName, const c return 1; } +struct LastRom { + std::string filename, physicalName, logicalFilename; +} lastRom; + int NDS_LoadROM(const char *filename, const char *physicalName, const char *logicalFilename) { + lastRom.filename = filename; + lastRom.physicalName = physicalName; + lastRom.logicalFilename = logicalFilename; + int ret; char buf[MAX_PATH]; @@ -693,10 +685,15 @@ int NDS_LoadROM(const char *filename, const char *physicalName, const char *logi gameInfo.populate(); - if (CommonSettings.loadToMemory) - gameInfo.crc = crc32(0, (u8*)gameInfo.romdata, gameInfo.romsize); - else - gameInfo.crc = 0; + //run crc over the whole buffer (chunk at a time, to avoid coding a streaming crc + gameInfo.reader->Seek(gameInfo.fROM, 0, SEEK_SET); + gameInfo.crc = 0; + for(;;) { + u8 buf[4096]; + int read = gameInfo.reader->Read(gameInfo.fROM,buf,4096); + if(read == 0) break; + gameInfo.crc = crc32(gameInfo.crc, buf, read); + } gameInfo.chipID = 0xC2; // The Manufacturer ID is defined by JEDEC (C2h = Macronix) if (!gameInfo.isHomebrew()) @@ -720,8 +717,7 @@ int NDS_LoadROM(const char *filename, const char *physicalName, const char *logi } INFO("\nROM game code: %c%c%c%c\n", gameInfo.header.gameCode[0], gameInfo.header.gameCode[1], gameInfo.header.gameCode[2], gameInfo.header.gameCode[3]); - if (gameInfo.crc) - INFO("ROM crc: %08X\n", gameInfo.crc); + INFO("ROM crc: %08X\n", gameInfo.crc); if (!gameInfo.isHomebrew()) { INFO("ROM serial: %s\n", gameInfo.ROMserial); @@ -762,14 +758,11 @@ int NDS_LoadROM(const char *filename, const char *physicalName, const char *logi //for homebrew, try auto-patching DLDI. should be benign if there is no DLDI or if it fails if(gameInfo.isHomebrew()) { - if(!CommonSettings.loadToMemory) - msgbox->warn("Sorry.. right now, you can't use the default (stream rom from disk) with homebrew due to a bug with DLDI-autopatching"); - else if (slot1_GetCurrentType() == NDS_SLOT1_R4) - DLDI::tryPatch((void*)gameInfo.romdata, gameInfo.romsize, 1); - else - if (slot2_GetCurrentType() == NDS_SLOT2_CFLASH) - DLDI::tryPatch((void*)gameInfo.romdata, gameInfo.romsize, 0); - + //note: gameInfo.romdataForReader is safe here because we made sure to load the rom into memory for isHomebrew + if (slot1_GetCurrentType() == NDS_SLOT1_R4) + DLDI::tryPatch((void*)gameInfo.romdataForReader, gameInfo.romsize, 1); + else if (slot2_GetCurrentType() == NDS_SLOT2_CFLASH) + DLDI::tryPatch((void*)gameInfo.romdataForReader, gameInfo.romsize, 0); } if (cheats != NULL) @@ -2510,6 +2503,15 @@ bool NDS_FakeBoot() bool _HACK_DONT_STOPMOVIE = false; void NDS_Reset() { + //reload last paths if needed + if(!gameInfo.reader) + { + LastRom stash = lastRom; + NDS_LoadROM(stash.filename.c_str(), stash.physicalName.c_str(), stash.logicalFilename.c_str()); + //yeah, great. LoadROM calls NDS_Reset. Geeze. + return; + } + PrepareLogfiles(); CommonSettings.gamehacks.apply(); diff --git a/desmume/src/NDSSystem.h b/desmume/src/NDSSystem.h index 7052b4ebd..7b5edda84 100644 --- a/desmume/src/NDSSystem.h +++ b/desmume/src/NDSSystem.h @@ -317,7 +317,7 @@ struct GameInfo { void *fROM; ROMReader_struct *reader; - u8 *romdata; + u8 *romdataForReader; u32 romsize; u32 cardSize; u32 mask; @@ -336,7 +336,7 @@ struct GameInfo const RomBanner& getRomBanner(); GameInfo() : fROM(NULL), - romdata(NULL), + romdataForReader(NULL), crc(0), chipID(0x00000FC2), romsize(0), diff --git a/desmume/src/ROMReader.cpp b/desmume/src/ROMReader.cpp index 778c50e60..5d01bd3ef 100644 --- a/desmume/src/ROMReader.cpp +++ b/desmume/src/ROMReader.cpp @@ -1,6 +1,6 @@ /* Copyright 2007 Guillaume Duhamel - Copyright 2007-2012 DeSmuME team + Copyright 2007-2017 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 @@ -55,6 +55,7 @@ void STDROMReaderDeInit(void *); u32 STDROMReaderSize(void *); int STDROMReaderSeek(void *, int, int); int STDROMReaderRead(void *, void *, u32); +int STDROMReaderWrite(void *, void *, u32); ROMReader_struct STDROMReader = { @@ -64,7 +65,8 @@ ROMReader_struct STDROMReader = STDROMReaderDeInit, STDROMReaderSize, STDROMReaderSeek, - STDROMReaderRead + STDROMReaderRead, + STDROMReaderWrite }; void * STDROMReaderInit(const char * filename) @@ -91,7 +93,7 @@ u32 STDROMReaderSize(void * file) { u32 size; - if (!file) return 0 ; + if (!file) return 0; fseek((FILE*)file, 0, SEEK_END); size = ftell((FILE*)file); @@ -102,22 +104,29 @@ u32 STDROMReaderSize(void * file) int STDROMReaderSeek(void * file, int offset, int whence) { - if (!file) return 0 ; + if (!file) return 0; return fseek((FILE*)file, offset, whence); } int STDROMReaderRead(void * file, void * buffer, u32 size) { - if (!file) return 0 ; + if (!file) return 0; return fread(buffer, 1, size, (FILE*)file); } +int STDROMReaderWrite(void *, void *, u32) +{ + //not supported, for now + return 0; +} + #ifdef HAVE_LIBZ void * GZIPROMReaderInit(const char * filename); void GZIPROMReaderDeInit(void *); u32 GZIPROMReaderSize(void *); int GZIPROMReaderSeek(void *, int, int); int GZIPROMReaderRead(void *, void *, u32); +int GZIPROMReaderWrite(void *, void *, u32); ROMReader_struct GZIPROMReader = { @@ -127,7 +136,8 @@ ROMReader_struct GZIPROMReader = GZIPROMReaderDeInit, GZIPROMReaderSize, GZIPROMReaderSeek, - GZIPROMReaderRead + GZIPROMReaderRead, + GZIPROMReaderWrite }; void * GZIPROMReaderInit(const char * filename) @@ -164,6 +174,12 @@ int GZIPROMReaderRead(void * file, void * buffer, u32 size) { return gzread((gzFile)file, buffer, size); } + +int GZIPROMReaderWrite(void *, void *, u32) +{ + //not supported, ever + return 0; +} #endif #ifdef HAVE_LIBZZIP @@ -172,6 +188,7 @@ void ZIPROMReaderDeInit(void *); u32 ZIPROMReaderSize(void *); int ZIPROMReaderSeek(void *, int, int); int ZIPROMReaderRead(void *, void *, u32); +int ZIPROMReaderWrite(void *, void *, u32); ROMReader_struct ZIPROMReader = { @@ -182,6 +199,7 @@ ROMReader_struct ZIPROMReader = ZIPROMReaderSize, ZIPROMReaderSeek, ZIPROMReaderRead + ZIPROMReaderWrite }; void * ZIPROMReaderInit(const char * filename) @@ -230,4 +248,95 @@ int ZIPROMReaderRead(void * file, void * buffer, u32 size) return zzip_read((ZZIP_FILE*)file, buffer, size); #endif } + +int ZIPROMReaderWrite(void *, void *, u32) +{ + //not supported ever + return 0; +} #endif + +struct { + void* buf; + int len; + int pos; +} mem; + +void * MemROMReaderInit(const char * filename) +{ + return NULL; //dummy +} + +void MemROMReaderDeInit(void *) +{ + //nothing to do +} +u32 MemROMReaderSize(void *) +{ + return (u32)mem.len; +} +int MemROMReaderSeek(void * file, int offset, int whence) +{ + switch(whence) { + case SEEK_SET: + mem.pos = offset; + break; + case SEEK_CUR: + mem.pos += offset; + break; + case SEEK_END: + mem.pos = mem.len + offset; + break; + } + return mem.pos; +} + +int MemROMReaderRead(void * file, void * buffer, u32 size) +{ + if(mem.pos<0) return 0; + + int todo = (int)size; + int remain = mem.len - mem.pos; + if(remainrebuildFAT(pathData); } diff --git a/desmume/src/frontend/windows/fsnitroView.cpp b/desmume/src/frontend/windows/fsnitroView.cpp index 27e585aed..b12147a6f 100644 --- a/desmume/src/frontend/windows/fsnitroView.cpp +++ b/desmume/src/frontend/windows/fsnitroView.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2016 DeSmuME team + Copyright (C) 2013-2017 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 @@ -91,7 +91,8 @@ void refreshQView(HWND hWnd, u16 id) u32 len = std::min(sizeof(buf), fs->getFileSizeById(id)); u32 start = fs->getStartAddrById(id); - memcpy(&buf[0], &gameInfo.romdata[start], len); + gameInfo.reader->Seek(gameInfo.fROM, start, SEEK_SET); + gameInfo.reader->Read(gameInfo.fROM, &buf[0], len); for (u32 i = 0; i < len; i++) if (buf[i] < 0x20) buf[i] = 0x20; @@ -108,7 +109,7 @@ BOOL CALLBACK ViewFSNitroProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam { case WM_INITDIALOG: { - fs = new FS_NITRO(gameInfo.romdata); + fs = new FS_NITRO(); if (!fs) { diff --git a/desmume/src/frontend/windows/main.cpp b/desmume/src/frontend/windows/main.cpp index eba4dbc4c..346c943f9 100644 --- a/desmume/src/frontend/windows/main.cpp +++ b/desmume/src/frontend/windows/main.cpp @@ -5693,11 +5693,6 @@ DOKEYDOWN: return 0; case ID_TOOLS_VIEWFSNITRO: - if (!CommonSettings.loadToMemory) - { - msgbox->error("Change ROM loading mode to \"Load entirely to RAM\""); - return 0; - } ViewFSNitro->open(); return 0; //========================================================== Tools end diff --git a/desmume/src/frontend/windows/memView.cpp b/desmume/src/frontend/windows/memView.cpp index 5bf31718a..2b78b22ae 100644 --- a/desmume/src/frontend/windows/memView.cpp +++ b/desmume/src/frontend/windows/memView.cpp @@ -1,6 +1,6 @@ /* Copyright (C) 2006 yopyop - Copyright (C) 2006-2016 DeSmuME team + Copyright (C) 2006-2017 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 @@ -81,10 +81,6 @@ u8 memRead8 (MemRegionType regionType, HWAddressType address) case MEMVIEW_FIRMWARE: value = MMU.fw.data[address]; return value; - case MEMVIEW_ROM: - if (address < gameInfo.romsize) - value = gameInfo.romdata[address]; - return value; case MEMVIEW_FULL: MMU_DumpMemBlock(0, address, 1, &value); return value; @@ -92,69 +88,6 @@ u8 memRead8 (MemRegionType regionType, HWAddressType address) return 0; } -u16 memRead16 (MemRegionType regionType, HWAddressType address) -{ - MemViewRegion& region = s_memoryRegions[regionType]; - if (address < region.hardwareAddress || (address + 1) >= (region.hardwareAddress + region.size)) - { - return 0; - } - - u16 value = 0; - switch (regionType) - { - case MEMVIEW_ARM9: - MMU_DumpMemBlock(ARMCPU_ARM9, address, 2, (u8*)&value); - return value; - case MEMVIEW_ARM7: - MMU_DumpMemBlock(ARMCPU_ARM7, address, 2, (u8*)&value); - return value; - case MEMVIEW_FIRMWARE: - value = *(u16*)(&MMU.fw.data[address]); - return value; - case MEMVIEW_ROM: - if (address < (gameInfo.romsize - 2)) - value = T1ReadWord(gameInfo.romdata, address); - return value; - case MEMVIEW_FULL: - MMU_DumpMemBlock(0, address, 2, (u8*)&value); - return value; - } - return 0; -} - -u32 memRead32 (MemRegionType regionType, HWAddressType address) -{ - MemViewRegion& region = s_memoryRegions[regionType]; - if (address < region.hardwareAddress || (address + 3) >= (region.hardwareAddress + region.size)) - { - return 0; - } - - u32 value = 0; - switch (regionType) - { - case MEMVIEW_ARM9: - MMU_DumpMemBlock(ARMCPU_ARM9, address, 4, (u8*)&value); - return value; - case MEMVIEW_ARM7: - MMU_DumpMemBlock(ARMCPU_ARM7, address, 4, (u8*)&value); - return value; - case MEMVIEW_FIRMWARE: - value = *(u32*)(&MMU.fw.data[address]); - return value; - case MEMVIEW_ROM: - if (address < (gameInfo.romsize - 4)) - value = T1ReadLong(gameInfo.romdata, address); - - return value; - case MEMVIEW_FULL: - MMU_DumpMemBlock(0, address, 4, (u8*)&value); - return value; - } - return 0; -} - void memRead(u8* buffer, MemRegionType regionType, HWAddressType address, size_t size) { switch (regionType) @@ -165,6 +98,10 @@ void memRead(u8* buffer, MemRegionType regionType, HWAddressType address, size_t case MEMVIEW_ARM7: MMU_DumpMemBlock(ARMCPU_ARM7, address, size, buffer); break; + case MEMVIEW_ROM: + gameInfo.reader->Seek(gameInfo.fROM, address, SEEK_SET); + gameInfo.reader->Read(gameInfo.fROM, buffer, size); + break; default: for (size_t i = 0; i < size; i++) { @@ -199,7 +136,8 @@ void memWrite8(MemRegionType regionType, HWAddressType address, u8 value) MMU.fw.data[address] = value; break; case MEMVIEW_ROM: - gameInfo.romdata[address] = value; + gameInfo.reader->Seek(gameInfo.fROM, address, SEEK_SET); + gameInfo.reader->Write(gameInfo.fROM, &value, 1); break; case MEMVIEW_FULL: MMU_write8(ARMCPU_ARM9, address, value); @@ -222,7 +160,8 @@ void memWrite16(MemRegionType regionType, HWAddressType address, u16 value) *((u16*)&MMU.fw.data[address]) = value; break; case MEMVIEW_ROM: - *((u16*)&gameInfo.romdata[address]) = value; + gameInfo.reader->Seek(gameInfo.fROM, address, SEEK_SET); + gameInfo.reader->Write(gameInfo.fROM, &value, 2); break; case MEMVIEW_FULL: MMU_write16(ARMCPU_ARM9, address, value); @@ -245,7 +184,8 @@ void memWrite32(MemRegionType regionType, HWAddressType address, u32 value) *((u32*)&MMU.fw.data[address]) = value; break; case MEMVIEW_ROM: - *((u32*)&gameInfo.romdata[address]) = value; + gameInfo.reader->Seek(gameInfo.fROM, address, SEEK_SET); + gameInfo.reader->Write(gameInfo.fROM, &value, 4); break; case MEMVIEW_FULL: MMU_write32(ARMCPU_ARM9, address, value); @@ -274,8 +214,7 @@ CMemView::CMemView(MemRegionType memRegion, u32 start_address) s_memoryRegions.push_back(s_arm7Region); s_memoryRegions.push_back(s_firmwareRegion); s_memoryRegions.push_back(s_fullRegion); - if (CommonSettings.loadToMemory) - s_memoryRegions.push_back(s_RomRegion); + s_memoryRegions.push_back(s_RomRegion); } PostInitialize(); diff --git a/desmume/src/utils/fsnitro.cpp b/desmume/src/utils/fsnitro.cpp index 2714590e1..e2d0dc319 100644 --- a/desmume/src/utils/fsnitro.cpp +++ b/desmume/src/utils/fsnitro.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2016 DeSmuME team + Copyright (C) 2013-2017 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 @@ -22,8 +22,9 @@ #include "types.h" #include "fsnitro.h" #include "file/file_path.h" +#include "NDSSystem.h" -FS_NITRO::FS_NITRO(u8 *cart_rom) +FS_NITRO::FS_NITRO() { inited = false; numDirs = numFiles = numOverlay7 = numOverlay9 = currentID =0; @@ -32,9 +33,9 @@ FS_NITRO::FS_NITRO(u8 *cart_rom) ovr9 = NULL; ovr7 = NULL; - if (!cart_rom) return; - - rom = cart_rom; + u8 rom[256]; + gameInfo.reader->Seek(gameInfo.fROM, 0, SEEK_SET); + gameInfo.reader->Read(gameInfo.fROM, rom, 256); FNameTblOff = *(u32*)(rom + 0x40); FNameTblSize = *(u32*)(rom + 0x44); @@ -62,7 +63,8 @@ FS_NITRO::FS_NITRO(u8 *cart_rom) if (FATOff < 0x8000) return; if (FATSize == 0) return; - numDirs = *(u16*)(rom + FNameTblOff + 6); + gameInfo.reader->Seek(gameInfo.fROM, FNameTblOff + 6, SEEK_SET); + gameInfo.reader->Read(gameInfo.fROM, &numDirs, 2); numFiles = FATSize / 8; if (numFiles == 0 || numDirs == 0) @@ -140,12 +142,12 @@ bool FS_NITRO::loadFileTables() fnt = new FNT_NITRO[numDirs]; // ========= 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); + gameInfo.reader->Seek(gameInfo.fROM, FATOff + ofs, SEEK_SET); + gameInfo.reader->Read(gameInfo.fROM, &fat[i].start, 4); + gameInfo.reader->Read(gameInfo.fROM, &fat[i].end, 4); fat[i].size = fat[i].end - fat[i].start; fat[i].sizeFile = fat[i].size; fat[i].isOverlay = false; @@ -154,7 +156,9 @@ bool FS_NITRO::loadFileTables() // ========= Overlays ARM9 if (numOverlay9) { - memcpy(ovr9, (rom + ARM9OverlayOff), ARM9OverlaySize); + gameInfo.reader->Seek(gameInfo.fROM, ARM9OverlayOff, SEEK_SET); + gameInfo.reader->Read(gameInfo.fROM, ovr9, ARM9OverlaySize); + for (u32 i = 0 ; i < numOverlay9; i++) { char buf[129] = {0}; @@ -168,7 +172,9 @@ bool FS_NITRO::loadFileTables() // ========= Overlays ARM7 if (numOverlay7) { - memcpy(ovr7, (rom + ARM7OverlayOff), ARM7OverlaySize); + gameInfo.reader->Seek(gameInfo.fROM, ARM7OverlayOff, SEEK_SET); + gameInfo.reader->Read(gameInfo.fROM, ovr7, ARM7OverlaySize); + for (u32 i = 0 ; i < numOverlay7; i++) { char buf[129] = {0}; @@ -180,23 +186,24 @@ bool FS_NITRO::loadFileTables() } // ========= FNT (File Names Table) - u8 *_FNT = (u8*)(rom + FNameTblOff); + gameInfo.reader->Seek(gameInfo.fROM, FNameTblOff, SEEK_SET); for (u32 i = 0; i < numDirs; i++) { - memcpy(&fnt[i], _FNT, 8); + gameInfo.reader->Read(gameInfo.fROM, &fnt[i], 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); + //u8 *sub = (u8*)(rom + FNameTblOff + fnt[0].offset); + //u8 *_end = (u8*)(rom + FNameTblOff + FNameTblSize - 1); + u32 subptr = FNameTblOff + fnt[0].offset; + u32 _endptr = FNameTblOff + FNameTblSize - 1; u16 fileCount = fnt[0].firstID; u16 fntID = 0xF000; - uintptr_t *store = new uintptr_t[numDirs]; + uintptr_t *store = new u32[numDirs]; if (!store) return false; - memset(store, 0, sizeof(uintptr_t) * numDirs); + memset(store, 0, sizeof(u32) * numDirs); fnt[0].filename = path_default_slash(); fnt[0].parentID = 0xF000; @@ -205,13 +212,17 @@ bool FS_NITRO::loadFileTables() while (true) { - u8 len = (sub[0] & 0x7F); - FNT_TYPES type = getFNTType(sub[0]); + u8 sub; + gameInfo.reader->Seek(gameInfo.fROM, subptr, SEEK_SET); + gameInfo.reader->Read(gameInfo.fROM, &sub, 1); + + u8 len = (sub & 0x7F); + FNT_TYPES type = getFNTType(sub); if (type == FS_END_SUBTABLE) { //printf("********** End Subdir (%04Xh, parent %04X)\n", fntID, fnt[fntID & 0x0FFF].parentID); - sub = (u8*)store[fntID & 0x0FFF]; + subptr = store[fntID & 0x0FFF]; fntID = fnt[fntID & 0x0FFF].parentID; continue; } @@ -220,14 +231,17 @@ bool FS_NITRO::loadFileTables() { //printf("********** Subdir Entry\n"); char buf[129] = {0}; - memcpy(buf, (sub + 1), len); buf[len] = 0; - sub += (len + 1); - fntID = (*(u16*)sub); - sub += 2; + gameInfo.reader->Seek(gameInfo.fROM, subptr + 1, SEEK_SET); + gameInfo.reader->Read(gameInfo.fROM, buf, len); + buf[len] = 0; + subptr += (len + 1); + gameInfo.reader->Seek(gameInfo.fROM, subptr, SEEK_SET); + gameInfo.reader->Read(gameInfo.fROM, &fntID, 2); + subptr += 2; u32 id = (fntID & 0x0FFF); - store[id] = (uintptr_t)sub; - sub = (u8*)(rom + FNameTblOff + fnt[id].offset); + store[id] = subptr; + subptr = FNameTblOff + fnt[id].offset; 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); @@ -238,11 +252,13 @@ bool FS_NITRO::loadFileTables() { //printf("********** File Entry\n"); char buf[129] = {0}; - memcpy(buf, (sub + 1), len); buf[len] = 0; + gameInfo.reader->Seek(gameInfo.fROM, subptr + 1, SEEK_SET); + gameInfo.reader->Read(gameInfo.fROM, buf, len); + buf[len] = 0; fat[fileCount].filename = buf; 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); + subptr += (len + 1); fileCount++; if (fileCount >= numFiles) break; @@ -272,8 +288,6 @@ bool FS_NITRO::rebuildFAT(u32 addr, u32 size, std::string pathData) 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; @@ -467,7 +481,19 @@ bool FS_NITRO::extract(u16 id, std::string to) FILE *fp = fopen(to.c_str(), "wb"); if (fp) { - fwrite((rom + fat[id].start), 1, fat[id].size, fp); + u32 remain = fat[id].size; + u32 dstofs = 0; + gameInfo.reader->Seek(gameInfo.fROM, fat[id].start, SEEK_SET); + while(remain>0) { + u8 tmp[4096]; + u32 todo = remain; + if(todo>4096) todo=4096; + int done = gameInfo.reader->Read(gameInfo.fROM, tmp, todo); + if(done != todo) break; //panic + fwrite(tmp, 1, done, fp); + dstofs += done; + remain -= done; + } fclose(fp); return true; } diff --git a/desmume/src/utils/fsnitro.h b/desmume/src/utils/fsnitro.h index 519eb6ca3..724d3f916 100644 --- a/desmume/src/utils/fsnitro.h +++ b/desmume/src/utils/fsnitro.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2016 DeSmuME team + Copyright (C) 2013-2017 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 @@ -118,7 +118,6 @@ private: u32 currentID; - u8 *rom; FAT_NITRO *fat; FNT_NITRO *fnt; OVR_NITRO *ovr9; @@ -131,7 +130,7 @@ private: void destroy(); public: - FS_NITRO(u8 *cart_rom); + FS_NITRO(); ~FS_NITRO(); bool getFileIdByAddr(u32 addr, u16 &id);