diff --git a/desmume/src/NDSSystem.cpp b/desmume/src/NDSSystem.cpp index f9ef31008..ab84be948 100644 --- a/desmume/src/NDSSystem.cpp +++ b/desmume/src/NDSSystem.cpp @@ -240,9 +240,9 @@ NDS_header * NDS_getROMHeader(void) { offsetof(NDS_header,CRC16), 2}, { offsetof(NDS_header,ROMtimeout), 2}, - { offsetof(NDS_header,ARM9unk), 4}, - { offsetof(NDS_header,ARM7unk), 4}, - { offsetof(NDS_header,ROMSize), 4}, + { offsetof(NDS_header,ARM9autoload), 4}, + { offsetof(NDS_header,ARM7autoload), 4}, + { offsetof(NDS_header,endROMoffset), 4}, { offsetof(NDS_header,HeaderSize), 4}, { offsetof(NDS_header,logoCRC16), 2}, @@ -452,7 +452,8 @@ static void loadrom(std::string fname) { gameInfo.resize(size); - fread(gameInfo.romdata,1,size,inf); + gameInfo.loadRom(inf); + gameInfo.fillGap(); fclose(inf); @@ -616,6 +617,21 @@ int NDS_LoadROM(const char *filename, const char *physicalName, const char *logi //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); + mask |= (mask >> 2); + mask |= (mask >> 4); + mask |= (mask >> 8); + mask |= (mask >> 16); + + 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("endROMoffset %10u (%08Xh) mask %08Xh\n", gameInfo.header.endROMoffset, gameInfo.header.endROMoffset, mask); + printf("======================================================================\n"); +#endif memset(buf, 0, MAX_PATH); strcpy(buf, path.pathToModule); diff --git a/desmume/src/NDSSystem.h b/desmume/src/NDSSystem.h index 1c781273c..1202638d8 100644 --- a/desmume/src/NDSSystem.h +++ b/desmume/src/NDSSystem.h @@ -97,8 +97,8 @@ struct NDS_header u8 unitCode; // 012 - Unitcode (00h=Nintendo DS) u8 deviceCode; // 013 - Encryption Seed Select (00..07h, usually 00h) u8 cardSize; // 014 - Devicecapacity (Chipsize = 128KB SHL nn) (eg. 7 = 16MB) - u8 cardInfo[8]; // 015 - ??? --> reversed (padded 00h) - u8 flags; // 01D - ??? | + u8 reserved1[8]; // 015 - Must be set to 0x00 + u8 region; // 01D - Specific region: 0x80 - China, 0x40 - Korea, 0x00 - Other u8 romversion; // 01E - ROM Version (usually 00h) u8 autostart; // 01F - Autostart (Bit2: Skip "Press Button" after Health and Safety) // (Also skips bootmenu, even in Manual mode & even Start pressed) @@ -127,19 +127,21 @@ struct NDS_header u32 Key1Cmd; // 064 - Port 40001A4h setting for KEY1 commands (usually 001808F8h) u32 IconOff; // 068 - Icon_title_offset (0=None) (8000h and up) - u16 CRC16; // 06C - Secure Area Checksum, CRC-16 of [ [20h]..7FFFh] + u16 CRC16; // 06C - Secure Area Checksum, CRC-16 of [ [20h]..7FFFh] - Calculations with this algorithm use 0xffff as the initial value u16 ROMtimeout; // 06E - Secure Area Loading Timeout (usually 051Eh) - u32 ARM9unk; // 070 - - u32 ARM7unk; // 074 - + u32 ARM9autoload; // 070 - ARM9 Auto Load List RAM Address + u32 ARM7autoload; // 074 - ARM7 Auto Load List RAM Address - u8 secAreaDisable[8]; // 078 - Secure Area Disable (by encrypted "NmMdOnly") (usually zero) - u32 ROMSize; // 080 - Total Used ROM size (remaining/unused bytes usually FFh-padded) + u8 infoResevedRegion[8]; // 078 - ROM Information Reserved Region (must be set to 0x00) + u32 endROMoffset; // 080 - Total Used ROM size (remaining/unused bytes usually FFh-padded) u32 HeaderSize; // 084 - ROM Header Size (4000h) - u8 unknown5[56]; // 088 - Reserved (zero filled) - "PASS" is contained within here? + u32 ARM9module; // 088 - ARM9 Module Parameter Address (auto-load parameters) + u32 ARM7module; // 08C - ARM7 Module Parameter Address (auto-load parameters) + u8 reserved2[58]; // 090 - Must be set to 0x00 - "PASS" is contained within here? u8 logo[156]; // 0C0 - Nintendo Logo (compressed bitmap, same as in GBA Headers) u16 logoCRC16; // 15C - Nintendo Logo Checksum, CRC-16 of [0C0h-15Bh], fixed CF56h u16 headerCRC16; // 15E - Header Checksum, CRC-16 of [000h-15Dh] - u8 reserved[160]; // + u8 reserved[160]; // Must be set to 0x00 }; #include "PACKED_END.h" @@ -324,8 +326,10 @@ struct GameInfo crc(0), chipID(0x00000FC2), romsize(0), + cardSize(0), allocatedSize(0), - mask(0) + mask(0), + filemask(0) { memset(&header, 0, sizeof(header)); memset(&ROMserial[0], 0, sizeof(ROMserial)); @@ -362,21 +366,38 @@ struct GameInfo if(romdata != NULL) delete[] romdata; //calculate the necessary mask for the requested size - mask = size-1; - mask |= (mask >>1); - mask |= (mask >>2); - mask |= (mask >>4); - mask |= (mask >>8); - mask |= (mask >>16); + 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 = mask+4; + 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; @@ -387,8 +408,10 @@ struct GameInfo void populate(); char* romdata; u32 romsize; + u32 cardSize; u32 allocatedSize; u32 mask; + u32 filemask; const RomBanner& getRomBanner(); bool hasRomBanner(); bool isHomebrew; diff --git a/desmume/src/addons/slot1_retail_nand.cpp b/desmume/src/addons/slot1_retail_nand.cpp index 5ef130db4..ad7337ffd 100644 --- a/desmume/src/addons/slot1_retail_nand.cpp +++ b/desmume/src/addons/slot1_retail_nand.cpp @@ -46,7 +46,6 @@ private: u32 mode; u32 handle_save; u32 save_adr; - u32 rom_mask; public: virtual Slot1Info const* info() @@ -63,9 +62,7 @@ public: handle_save = 0; - subAdr = T1ReadWord(gameInfo.header.unknown5, 0xE) << 17; - - rom_mask = (0x020000 << gameInfo.header.cardSize) - 1; + subAdr = T1ReadWord(gameInfo.header.reserved2, 0x6) << 17; mode = 0; } @@ -126,9 +123,7 @@ public: case 0xB2: //Set save position mode = cmd; - save_adr = protocol.address & rom_mask; - // to Normmatt: Made in Ore (UORJ, crc 2E7111B8) crash when save_addr < subAdr - save_adr -= subAdr; + save_adr = (protocol.address & gameInfo.mask) - subAdr; handle_save = 1; break; } diff --git a/desmume/src/addons/slot1comp_rom.cpp b/desmume/src/addons/slot1comp_rom.cpp index 57b51206c..902019bd6 100644 --- a/desmume/src/addons/slot1comp_rom.cpp +++ b/desmume/src/addons/slot1comp_rom.cpp @@ -49,11 +49,6 @@ u32 Slot1Comp_Rom::read() case eSlot1Operation_B7_Read: { - //is this legitimate? need some way to verify. - //if(length == 0) - // return 0xFFFFFFFF; - //length -= 4; - //TODO - check about non-4-byte aligned addresses //OBSOLETED? @@ -61,15 +56,16 @@ u32 Slot1Comp_Rom::read() ////but, a thought: does the internal rom address counter register wrap around? we may be making a mistake by keeping the extra precision ////but there is no test case yet //at any rate, this is good for safety's sake. + address &= gameInfo.mask; //"Can be used only for addresses 8000h and up, smaller addresses will be silently redirected to address `8000h+(addr AND 1FFh)`" if(address < 0x8000) - address = (0x8000 + (address&0x1FF)); + address = (0x8000 + (address & 0x1FF)); //as a sanity measure for funny-sized roms (homebrew and perhaps truncated retail roms) //we need to protect ourselves by returning 0xFF for things still out of range - if(address+4 >= gameInfo.romsize) + if (address > gameInfo.header.endROMoffset) { DEBUG_Notify.ReadBeyondEndOfCart(address,gameInfo.romsize); return 0xFFFFFFFF; @@ -81,7 +77,6 @@ u32 Slot1Comp_Rom::read() //"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); - return ret; } break; diff --git a/desmume/src/bios.h b/desmume/src/bios.h index 6ccaff00c..078519d5c 100644 --- a/desmume/src/bios.h +++ b/desmume/src/bios.h @@ -22,7 +22,7 @@ #include "armcpu.h" extern u32 (* ARM_swi_tab[2][32])(); -extern char* ARM_swi_names[2][32]; +extern const char* ARM_swi_names[2][32]; #endif diff --git a/desmume/src/mc.cpp b/desmume/src/mc.cpp index 65af639a8..de4f67c7a 100644 --- a/desmume/src/mc.cpp +++ b/desmume/src/mc.cpp @@ -457,6 +457,7 @@ u8 BackupDevice::data_command(u8 val, u8 PROCNUM) } #endif write_enable = FALSE; + com = 0; break; case BM_CMD_READSTATUS: @@ -467,6 +468,7 @@ u8 BackupDevice::data_command(u8 val, u8 PROCNUM) case BM_CMD_WRITEENABLE: //printf("MC%c: write enable\n", PROCNUM?'7':'9'); write_enable = TRUE; + com = 0; break; case BM_CMD_WRITELOW: