diff options
Diffstat (limited to 'src/NDSCart.cpp')
-rw-r--r-- | src/NDSCart.cpp | 789 |
1 files changed, 479 insertions, 310 deletions
diff --git a/src/NDSCart.cpp b/src/NDSCart.cpp index 474a13b..c959663 100644 --- a/src/NDSCart.cpp +++ b/src/NDSCart.cpp @@ -21,6 +21,7 @@ #include "NDS.h" #include "NDSCart.h" #include "ARM.h" +#include "CRC32.h" #include "melon_fopen.h" @@ -31,19 +32,10 @@ namespace NDSCart_SRAM u8* SRAM; u32 SRAMLength; -char SRAMPath[256]; +char SRAMPath[1024]; void (*WriteFunc)(u8 val, bool islast); -u32 Discover_MemoryType; -u32 Discover_Likeliness; -u8* Discover_Buffer; -u32 Discover_DataPos; -u32 Discover_LastPC; -u32 Discover_AddrLength; -u32 Discover_Addr; -u32 Discover_LikelySize; - u32 Hold; u8 CurCmd; u32 DataPos; @@ -63,36 +55,70 @@ void Write_Discover(u8 val, bool islast); bool Init() { SRAM = NULL; - Discover_Buffer = NULL; return true; } void DeInit() { if (SRAM) delete[] SRAM; - if (Discover_Buffer) delete[] Discover_Buffer; } void Reset() { if (SRAM) delete[] SRAM; - if (Discover_Buffer) delete[] Discover_Buffer; SRAM = NULL; - Discover_Buffer = NULL; } -void LoadSave(char* path) +void DoSavestate(Savestate* file) { - if (SRAM) delete[] SRAM; - if (Discover_Buffer) delete[] Discover_Buffer; + file->Section("NDCS"); + + // we reload the SRAM contents. + // it should be the same file (as it should be the same ROM, duh) + // but the contents may change + // TODO maybe: possibility to save to a separate file when using savestates???? + + // also the SRAM size shouldn't change. unless something something autodetect something but fuck that code. + + //if (!file->Saving && SRAMLength) + // delete[] SRAM; + + u32 oldlen = SRAMLength; + + file->Var32(&SRAMLength); + if (SRAMLength != oldlen) + { + printf("savestate: VERY BAD!!!! SRAM LENGTH DIFFERENT. %d -> %d\n", oldlen, SRAMLength); + printf("oh well. loading it anyway. adsfgdsf\n"); + + if (oldlen) delete[] SRAM; + if (SRAMLength) SRAM = new u8[SRAMLength]; + } + if (SRAMLength) + { + //if (!file->Saving) + // SRAM = new u8[SRAMLength]; - Discover_Buffer = NULL; - Discover_LastPC = 0; - Discover_AddrLength = 0x7FFFFFFF; - Discover_LikelySize = 0; + file->VarArray(SRAM, SRAMLength); + } + + // SPI status shito + + file->Var32(&Hold); + file->Var8(&CurCmd); + file->Var32(&DataPos); + file->Var8(&Data); - strncpy(SRAMPath, path, 255); - SRAMPath[255] = '\0'; + file->Var8(&StatusReg); + file->Var32(&Addr); +} + +void LoadSave(const char* path, u32 type) +{ + if (SRAM) delete[] SRAM; + + strncpy(SRAMPath, path, 1023); + SRAMPath[1023] = '\0'; FILE* f = melon_fopen(path, "rb"); if (f) @@ -105,32 +131,35 @@ void LoadSave(char* path) fread(SRAM, SRAMLength, 1, f); fclose(f); + } + else + { + if (type > 8) type = 0; + int sramlen[] = {0, 512, 8192, 65536, 256*1024, 512*1024, 1024*1024, 8192*1024, 32768*1024}; + SRAMLength = sramlen[type]; - switch (SRAMLength) + if (SRAMLength) { - case 512: WriteFunc = Write_EEPROMTiny; break; - case 8192: - case 65536: WriteFunc = Write_EEPROM; break; - case 256*1024: - case 512*1024: - case 1024*1024: - case 8192*1024: WriteFunc = Write_Flash; break; - default: - printf("!! BAD SAVE LENGTH %d\n", SRAMLength); - WriteFunc = Write_Null; - break; + SRAM = new u8[SRAMLength]; + memset(SRAM, 0, SRAMLength); } } - else + + switch (SRAMLength) { - SRAMLength = 0; - WriteFunc = Write_Discover; - Discover_MemoryType = 2; - Discover_Likeliness = 0; - - Discover_DataPos = 0; - Discover_Buffer = new u8[256*1024]; - memset(Discover_Buffer, 0, 256*1024); + case 512: WriteFunc = Write_EEPROMTiny; break; + case 8192: + case 65536: WriteFunc = Write_EEPROM; break; + case 256*1024: + case 512*1024: + case 1024*1024: + case 8192*1024: WriteFunc = Write_Flash; break; + case 32768*1024: WriteFunc = Write_Null; break; // NAND FLASH, handled differently + default: + printf("!! BAD SAVE LENGTH %d\n", SRAMLength); + case 0: + WriteFunc = Write_Null; + break; } Hold = 0; @@ -139,243 +168,31 @@ void LoadSave(char* path) StatusReg = 0x00; } -u8 Read() -{ - return Data; -} - -void SetMemoryType() +void RelocateSave(const char* path, bool write) { - SRAMLength = 0; - - if (Discover_LikelySize) + if (!write) { - if (Discover_LikelySize >= 0x40000) - { - Discover_MemoryType = 4; // FLASH - SRAMLength = Discover_LikelySize; - } - else if (Discover_LikelySize == 0x10000 || Discover_MemoryType == 3) - { - if (Discover_MemoryType > 3) - printf("incoherent detection result: type=%d size=%X\n", Discover_MemoryType, Discover_LikelySize); - - Discover_MemoryType = 3; - } - else if (Discover_LikelySize == 0x2000) - { - if (Discover_MemoryType > 3) - printf("incoherent detection result: type=%d size=%X\n", Discover_MemoryType, Discover_LikelySize); - - Discover_MemoryType = 2; - } - else if (Discover_LikelySize == 0x200 || Discover_MemoryType == 1) - { - if (Discover_MemoryType > 1) - printf("incoherent detection result: type=%d size=%X\n", Discover_MemoryType, Discover_LikelySize); - - Discover_MemoryType = 1; - } - else - { - printf("bad save size %X. assuming EEPROM 64K\n", Discover_LikelySize); - Discover_MemoryType = 2; - } - } - - switch (Discover_MemoryType) - { - case 1: - printf("Save memory type: EEPROM 4k\n"); - WriteFunc = Write_EEPROMTiny; - SRAMLength = 512; - break; - - case 2: - printf("Save memory type: EEPROM 64k\n"); - WriteFunc = Write_EEPROM; - SRAMLength = 8192; - break; - - case 3: - printf("Save memory type: EEPROM 512k\n"); - WriteFunc = Write_EEPROM; - SRAMLength = 65536; - break; - - case 4: - if (!SRAMLength) SRAMLength = 256*1024; - printf("Save memory type: Flash %dk\n", SRAMLength/1024); - WriteFunc = Write_Flash; - break; - - case 5: - printf("Save memory type: ...something else\n"); - WriteFunc = Write_Null; - SRAMLength = 0; - break; - } - - if (!SRAMLength) + LoadSave(path, 0); // lazy return; + } - SRAM = new u8[SRAMLength]; + strncpy(SRAMPath, path, 1023); + SRAMPath[1023] = '\0'; - // replay writes that occured during discovery - u8 prev_cmd = CurCmd; - u32 pos = 0; - while (pos < 256*1024) + FILE* f = melon_fopen(path, "wb"); + if (!f) { - u32 len = *(u32*)&Discover_Buffer[pos]; - pos += 4; - if (len == 0) break; - - CurCmd = Discover_Buffer[pos++]; - DataPos = 0; - Addr = 0; - Data = 0; - for (u32 i = 1; i < len; i++) - { - WriteFunc(Discover_Buffer[pos++], (i==(len-1))); - DataPos++; - } + printf("NDSCart_SRAM::RelocateSave: failed to create new file. fuck\n"); + return; } - CurCmd = prev_cmd; - - delete[] Discover_Buffer; - Discover_Buffer = NULL; + fwrite(SRAM, SRAMLength, 1, f); + fclose(f); } -void Write_Discover(u8 val, bool islast) +u8 Read() { - // attempt at autodetecting the type of save memory. - // we basically hope the game will be nice and clear whole pages of memory. - - if (CurCmd == 0x03 || CurCmd == 0x0B) - { - if (Discover_Likeliness) // writes have occured before this read - { - // apply. and pray. - SetMemoryType(); - - DataPos = 0; - Addr = 0; - Data = 0; - return WriteFunc(val, islast); - } - else - { - if (DataPos == 0) - { - Discover_LastPC = NDS::GetPC((NDS::ExMemCnt[0] >> 11) & 0x1); - Discover_Addr = val; - } - else - { - bool addrlenchange = false; - - Discover_Addr <<= 8; - Discover_Addr |= val; - - u32 pc = NDS::GetPC((NDS::ExMemCnt[0] >> 11) & 0x1); - if ((pc != Discover_LastPC) || islast) - { - if (DataPos < Discover_AddrLength) - { - Discover_AddrLength = DataPos; - addrlenchange = true; - } - } - - if (DataPos == Discover_AddrLength) - { - Discover_Addr >>= 8; - - // determine the address for this read - // the idea is to see how far the game reads - // but we need margins for games that have antipiracy - // as those will generally read just past the limit - // and expect it to wrap to zero - - u32 likelysize = 0; - - if (DataPos == 3) // FLASH - { - if (Discover_Addr >= 0x101000) - likelysize = 0x800000; // 8M - else if (Discover_Addr >= 0x81000) - likelysize = 0x100000; // 1M - else if (Discover_Addr >= 0x41000) - likelysize = 0x80000; // 512K - else - likelysize = 0x40000; // 256K - } - else if (DataPos == 2) // EEPROM - { - if (Discover_Addr >= 0x3000) - likelysize = 0x10000; // 64K - else - likelysize = 0x2000; // 8K - } - else if (DataPos == 1) // tiny EEPROM - { - likelysize = 0x200; // always 4K - } - - if ((likelysize > Discover_LikelySize) || addrlenchange) - Discover_LikelySize = likelysize; - } - } - - Data = 0; - return; - } - } - - if (CurCmd == 0x02 || CurCmd == 0x0A) - { - if (DataPos == 0) - Discover_Buffer[Discover_DataPos + 4] = CurCmd; - - Discover_Buffer[Discover_DataPos + 5 + DataPos] = val; - - if (islast) - { - u32 len = DataPos+1; - - *(u32*)&Discover_Buffer[Discover_DataPos] = len+1; - Discover_DataPos += 5+len; - - if (Discover_Likeliness <= len) - { - Discover_Likeliness = len; - - if (len > 3+256) // bigger Flash, FRAM, whatever - { - Discover_MemoryType = 5; - } - else if ((len > 2+128) || (len > 1+16 && CurCmd == 0xA)) // Flash - { - Discover_MemoryType = 4; - } - else if (len > 2+32) // EEPROM 512k - { - Discover_MemoryType = 3; - } - else if (len > 1+16 || (len != 1+16 && CurCmd != 0x0A)) // EEPROM 64k - { - Discover_MemoryType = 2; - } - else // EEPROM 4k - { - Discover_MemoryType = 1; - } - } - - printf("discover: type=%d likeliness=%d\n", Discover_MemoryType, Discover_Likeliness); - } - } + return Data; } void Write_Null(u8 val, bool islast) {} @@ -654,6 +471,7 @@ u32 DataOutLen; bool CartInserted; u8* CartROM; u32 CartROMSize; +u32 CartCRC; u32 CartID; bool CartIsHomebrew; @@ -666,6 +484,12 @@ u64 Key2_X; u64 Key2_Y; +void ROMCommand_Retail(u8* cmd); +void ROMCommand_RetailNAND(u8* cmd); + +void (*ROMCommandHandler)(u8* cmd); + + u32 ByteSwap(u32 val) { return (val >> 24) | ((val >> 8) & 0xFF00) | ((val << 8) & 0xFF0000) | (val << 24); @@ -807,14 +631,242 @@ void Reset() CartID = 0; CartIsHomebrew = false; + ROMCommandHandler = NULL; + CmdEncMode = 0; DataEncMode = 0; NDSCart_SRAM::Reset(); } +void DoSavestate(Savestate* file) +{ + file->Section("NDSC"); -bool LoadROM(const char* path, bool direct) + file->Var16(&SPICnt); + file->Var32(&ROMCnt); + + file->VarArray(ROMCommand, 8); + file->Var32(&ROMDataOut); + + file->VarArray(DataOut, 0x4000); + file->Var32(&DataOutPos); + file->Var32(&DataOutLen); + + // cart inserted/len/ROM/etc should be already populated + // savestate should be loaded after the right game is loaded + // (TODO: system to verify that indeed the right ROM is loaded) + // (what to CRC? whole ROM? code binaries? latter would be more convenient for ie. romhaxing) + + file->Var32(&CmdEncMode); + file->Var32(&DataEncMode); + + // TODO: check KEY1 shit?? + + NDSCart_SRAM::DoSavestate(file); +} + + +void ApplyDLDIPatch() +{ + // TODO: embed patches? let the user choose? default to some builtin driver? + + u32 offset = *(u32*)&CartROM[0x20]; + u32 size = *(u32*)&CartROM[0x2C]; + + u8* binary = &CartROM[offset]; + u32 dldioffset = 0; + + for (u32 i = 0; i < size; i++) + { + if (*(u32*)&binary[i ] == 0xBF8DA5ED && + *(u32*)&binary[i+4] == 0x69684320 && + *(u32*)&binary[i+8] == 0x006D6873) + { + dldioffset = i; + break; + } + } + + if (!dldioffset) + { + return; + } + + printf("DLDI shit found at %08X (%08X)\n", dldioffset, offset+dldioffset); + + FILE* f = fopen("dldi.bin", "rb"); + if (!f) + { + printf("no DLDI patch available. oh well\n"); + return; + } + + u32 dldisize; + fseek(f, 0, SEEK_END); + dldisize = ftell(f); + fseek(f, 0, SEEK_SET); + + u8* patch = new u8[dldisize]; + fread(patch, dldisize, 1, f); + fclose(f); + + if (*(u32*)&patch[0] != 0xBF8DA5ED || + *(u32*)&patch[4] != 0x69684320 || + *(u32*)&patch[8] != 0x006D6873) + { + printf("bad DLDI patch\n"); + delete[] patch; + return; + } + + if (patch[0x0D] > binary[dldioffset+0x0F]) + { + printf("DLDI driver ain't gonna fit, sorry\n"); + delete[] patch; + return; + } + + printf("existing driver is: %s\n", &binary[dldioffset+0x10]); + printf("new driver is: %s\n", &patch[0x10]); + + u32 memaddr = *(u32*)&binary[dldioffset+0x40]; + if (memaddr == 0) + memaddr = *(u32*)&binary[dldioffset+0x68] - 0x80; + + u32 patchbase = *(u32*)&patch[0x40]; + u32 delta = memaddr - patchbase; + + u32 patchsize = 1 << patch[0x0D]; + u32 patchend = patchbase + patchsize; + + memcpy(&binary[dldioffset], patch, dldisize); + + *(u32*)&binary[dldioffset+0x40] += delta; + *(u32*)&binary[dldioffset+0x44] += delta; + *(u32*)&binary[dldioffset+0x48] += delta; + *(u32*)&binary[dldioffset+0x4C] += delta; + *(u32*)&binary[dldioffset+0x50] += delta; + *(u32*)&binary[dldioffset+0x54] += delta; + *(u32*)&binary[dldioffset+0x58] += delta; + *(u32*)&binary[dldioffset+0x5C] += delta; + + *(u32*)&binary[dldioffset+0x68] += delta; + *(u32*)&binary[dldioffset+0x6C] += delta; + *(u32*)&binary[dldioffset+0x70] += delta; + *(u32*)&binary[dldioffset+0x74] += delta; + *(u32*)&binary[dldioffset+0x78] += delta; + *(u32*)&binary[dldioffset+0x7C] += delta; + + u8 fixmask = patch[0x0E]; + + if (fixmask & 0x01) + { + u32 fixstart = *(u32*)&patch[0x40] - patchbase; + u32 fixend = *(u32*)&patch[0x44] - patchbase; + + for (u32 addr = fixstart; addr < fixend; addr+=4) + { + u32 val = *(u32*)&binary[dldioffset+addr]; + if (val >= patchbase && val < patchend) + *(u32*)&binary[dldioffset+addr] += delta; + } + } + if (fixmask & 0x02) + { + u32 fixstart = *(u32*)&patch[0x48] - patchbase; + u32 fixend = *(u32*)&patch[0x4C] - patchbase; + + for (u32 addr = fixstart; addr < fixend; addr+=4) + { + u32 val = *(u32*)&binary[dldioffset+addr]; + if (val >= patchbase && val < patchend) + *(u32*)&binary[dldioffset+addr] += delta; + } + } + if (fixmask & 0x04) + { + u32 fixstart = *(u32*)&patch[0x50] - patchbase; + u32 fixend = *(u32*)&patch[0x54] - patchbase; + + for (u32 addr = fixstart; addr < fixend; addr+=4) + { + u32 val = *(u32*)&binary[dldioffset+addr]; + if (val >= patchbase && val < patchend) + *(u32*)&binary[dldioffset+addr] += delta; + } + } + if (fixmask & 0x08) + { + u32 fixstart = *(u32*)&patch[0x58] - patchbase; + u32 fixend = *(u32*)&patch[0x5C] - patchbase; + + memset(&binary[dldioffset+fixstart], 0, fixend-fixstart); + } + + delete[] patch; + printf("applied DLDI patch\n"); +} + + +bool ReadROMParams(u32* params) +{ + // format for romlist.bin: + // [CRC32] [ROM size] [save type] [reserved] + // list must be sorted by CRC + + FILE* f = melon_fopen_local("romlist.bin", "rb"); + if (!f) return false; + + fseek(f, 0, SEEK_END); + u32 len = (u32)ftell(f); + u32 maxlen = len; + len >>= 4; // 16 bytes per entry + + u32 offset = 0; + u32 chk_size = len >> 1; + for (;;) + { + u32 crc = 0; + fseek(f, offset + (chk_size << 4), SEEK_SET); + fread(&crc, 4, 1, f); + + printf("chk_size=%d, crc=%08X, wanted=%08X, offset=%08X\n", chk_size, crc, CartCRC, offset); + + if (crc == CartCRC) + { + fread(params, 4, 3, f); + fclose(f); + return true; + } + else + { + if (crc < CartCRC) + { + if (chk_size == 0) + offset += 0x10; + else + offset += (chk_size << 4); + } + else if (chk_size == 0) + { + fclose(f); + return false; + } + + chk_size >>= 1; + } + + if (offset >= maxlen) + { + fclose(f); + return false; + } + } +} + + +bool LoadROM(const char* path, const char* sram, bool direct) { // TODO: streaming mode? for really big ROMs or systems with limited RAM // for now we're lazy @@ -846,19 +898,62 @@ bool LoadROM(const char* path, bool direct) fclose(f); //CartROM = f; + CartCRC = CRC32(CartROM, CartROMSize); + printf("ROM CRC32: %08X\n", CartCRC); + + u32 romparams[3]; + if (!ReadROMParams(romparams)) + { + // set defaults + printf("ROM entry not found\n"); + + romparams[0] = CartROMSize; + if (*(u32*)&CartROM[0x20] < 0x4000) + romparams[1] = 0; // no saveRAM for homebrew + else + romparams[1] = 2; // assume EEPROM 64k (TODO FIXME) + } + else + printf("ROM entry: %08X %08X %08X\n", romparams[0], romparams[1], romparams[2]); + + if (romparams[0] != len) printf("!! bad ROM size %d (expected %d) rounded to %d\n", len, romparams[0], CartROMSize); + // generate a ROM ID // note: most games don't check the actual value // it just has to stay the same throughout gameplay - CartID = 0x00001FC2; + CartID = 0x000000C2; + + if (CartROMSize <= 128*1024*1024) + CartID |= ((CartROMSize >> 20) - 1) << 8; + else + CartID |= (0x100 - (CartROMSize >> 28)) << 8; + + if (romparams[1] == 8) + CartID |= 0x08000000; // NAND flag + + printf("Cart ID: %08X\n", CartID); + + if (*(u32*)&CartROM[0x20] < 0x4000) + { + //ApplyDLDIPatch(); + } if (direct) { + // TODO: in the case of an already-encrypted secure area, direct boot + // needs it decrypted NDS::SetupDirectBoot(); CmdEncMode = 2; } CartInserted = true; + // TODO: support more fancy cart types (homebrew?, flashcarts, etc) + if (CartID & 0x08000000) + ROMCommandHandler = ROMCommand_RetailNAND; + else + ROMCommandHandler = ROMCommand_Retail; + u32 arm9base = *(u32*)&CartROM[0x20]; if (arm9base < 0x8000) { @@ -888,16 +983,18 @@ bool LoadROM(const char* path, bool direct) // save - char savepath[256]; - strncpy(savepath, path, 255); - savepath[255] = '\0'; - strncpy(savepath + strlen(path) - 3, "sav", 3); - printf("Save file: %s\n", savepath); - NDSCart_SRAM::LoadSave(savepath); + printf("Save file: %s\n", sram); + NDSCart_SRAM::LoadSave(sram, romparams[1]); return true; } +void RelocateSave(const char* path, bool write) +{ + // herp derp + NDSCart_SRAM::RelocateSave(path, write); +} + void ReadROM(u32 addr, u32 len, u32 offset) { if (!CartInserted) return; @@ -949,6 +1046,89 @@ void ROMPrepareData(u32 param) NDS::CheckDMAs(0, 0x05); } + +void ROMCommand_Retail(u8* cmd) +{ + switch (cmd[0]) + { + case 0xB7: + { + u32 addr = (cmd[1]<<24) | (cmd[2]<<16) | (cmd[3]<<8) | cmd[4]; + memset(DataOut, 0, DataOutLen); + + if (((addr + DataOutLen - 1) >> 12) != (addr >> 12)) + { + u32 len1 = 0x1000 - (addr & 0xFFF); + ReadROM_B7(addr, len1, 0); + ReadROM_B7(addr+len1, DataOutLen-len1, len1); + } + else + ReadROM_B7(addr, DataOutLen, 0); + } + break; + + default: + printf("unknown retail cart command %02X\n", cmd[0]); + break; + } +} + +void ROMCommand_RetailNAND(u8* cmd) +{ + switch (cmd[0]) + { + case 0x94: // NAND init + { + // initial value: should have bit7 clear + NDSCart_SRAM::StatusReg = 0; + + // Jam with the Band stores words 6-9 of this at 0x02131BB0 + // it doesn't seem to use those anywhere later + for (u32 pos = 0; pos < DataOutLen; pos += 4) + *(u32*)&DataOut[pos] = 0; + } + break; + + case 0xB2: // set savemem addr + { + NDSCart_SRAM::StatusReg |= 0x20; + } + break; + + case 0xB7: + { + u32 addr = (cmd[1]<<24) | (cmd[2]<<16) | (cmd[3]<<8) | cmd[4]; + memset(DataOut, 0, DataOutLen); + + if (((addr + DataOutLen - 1) >> 12) != (addr >> 12)) + { + u32 len1 = 0x1000 - (addr & 0xFFF); + ReadROM_B7(addr, len1, 0); + ReadROM_B7(addr+len1, DataOutLen-len1, len1); + } + else + ReadROM_B7(addr, DataOutLen, 0); + } + break; + + case 0xD6: // NAND status + { + // status reg bits: + // * bit7: busy? error? + // * bit5: accessing savemem + + for (u32 pos = 0; pos < DataOutLen; pos += 4) + *(u32*)&DataOut[pos] = NDSCart_SRAM::StatusReg * 0x01010101; + } + break; + + default: + printf("unknown NAND command %02X %04Xn", cmd[0], DataOutLen); + break; + } +} + + void WriteROMCnt(u32 val) { ROMCnt = (val & 0xFF7F7FFF) | (ROMCnt & 0x00800000); @@ -1038,45 +1218,34 @@ void WriteROMCnt(u32 val) if (CartInserted) CmdEncMode = 1; break; - case 0xB7: + default: + if (CmdEncMode == 1) { - u32 addr = (cmd[1]<<24) | (cmd[2]<<16) | (cmd[3]<<8) | cmd[4]; - memset(DataOut, 0, DataOutLen); - - if (((addr + DataOutLen - 1) >> 12) != (addr >> 12)) + switch (cmd[0] & 0xF0) { - u32 len1 = 0x1000 - (addr & 0xFFF); - ReadROM_B7(addr, len1, 0); - ReadROM_B7(addr+len1, DataOutLen-len1, len1); - } - else - ReadROM_B7(addr, DataOutLen, 0); - } - break; + case 0x40: + DataEncMode = 2; + break; - default: - switch (cmd[0] & 0xF0) - { - case 0x40: - DataEncMode = 2; - break; + case 0x10: + for (u32 pos = 0; pos < DataOutLen; pos += 4) + *(u32*)&DataOut[pos] = CartID; + break; - case 0x10: - for (u32 pos = 0; pos < DataOutLen; pos += 4) - *(u32*)&DataOut[pos] = CartID; - break; + case 0x20: + { + u32 addr = (cmd[2] & 0xF0) << 8; + ReadROM(addr, 0x1000, 0); + } + break; - case 0x20: - { - u32 addr = (cmd[2] & 0xF0) << 8; - ReadROM(addr, 0x1000, 0); + case 0xA0: + CmdEncMode = 2; + break; } - break; - - case 0xA0: - CmdEncMode = 2; - break; } + else if (ROMCommandHandler) + ROMCommandHandler(cmd); break; } |