From e0d02ddda23f20798038b8bd10006904f755697f Mon Sep 17 00:00:00 2001 From: zeromus Date: Wed, 28 Aug 2013 06:48:05 +0000 Subject: [PATCH] massive slot-1 reorganization and code cleanup --- desmume/src/MMU.cpp | 297 +++-------- desmume/src/MMU.h | 65 ++- desmume/src/Makefile.am | 2 +- desmume/src/NDSSystem.cpp | 4 +- desmume/src/addons/slot1_none.cpp | 15 +- desmume/src/addons/slot1_r4.cpp | 462 +++++++++--------- desmume/src/addons/slot1_retail_auto.cpp | 27 +- desmume/src/addons/slot1_retail_mcrom.cpp | 311 ++---------- desmume/src/addons/slot1_retail_nand.cpp | 192 ++++---- desmume/src/addons/slot1comp_protocol.cpp | 217 ++++++++ desmume/src/addons/slot1comp_protocol.h | 105 ++++ desmume/src/addons/slot1comp_rom.cpp | 66 +++ desmume/src/addons/slot1comp_rom.h | 16 +- desmume/src/encrypt.cpp | 5 + desmume/src/encrypt.h | 4 +- desmume/src/rtc.cpp | 4 +- desmume/src/saves.cpp | 6 +- desmume/src/slot1.cpp | 126 ++++- desmume/src/slot1.h | 16 +- desmume/src/utils/decrypt/decrypt.cpp | 5 +- desmume/src/utils/decrypt/decrypt.h | 2 + desmume/src/windows/DeSmuME_2005.vcproj | 8 + desmume/src/windows/DeSmuME_2008.vcproj | 8 + desmume/src/windows/DeSmuME_2010.vcxproj | 2 + .../src/windows/DeSmuME_2010.vcxproj.filters | 6 + desmume/src/windows/DeSmuME_2012.vcxproj | 2 + .../src/windows/DeSmuME_2012.vcxproj.filters | 6 + desmume/src/windows/main.cpp | 4 +- 28 files changed, 1080 insertions(+), 903 deletions(-) create mode 100644 desmume/src/addons/slot1comp_protocol.cpp create mode 100644 desmume/src/addons/slot1comp_protocol.h diff --git a/desmume/src/MMU.cpp b/desmume/src/MMU.cpp index abdecd695..f4f526d65 100644 --- a/desmume/src/MMU.cpp +++ b/desmume/src/MMU.cpp @@ -48,7 +48,7 @@ #define ASSERT_UNALIGNED(x) #endif -//#define _LOG_NEW_BOOT +//TODO - do we need these here? _KEY1 key1(&MMU.ARM7_BIOS[0x0030]); _KEY2 key2; @@ -995,7 +995,7 @@ void MMU_Reset() memset(MMU.reg_IF_bits, 0, sizeof(u32) * 2); memset(MMU.reg_IF_pending, 0, sizeof(u32) * 2); - memset(MMU.dscard, 0, sizeof(nds_dscard) * 2); + memset(&MMU.dscard, 0, sizeof(MMU.dscard)); MMU.divRunning = 0; MMU.divResult = 0; @@ -1035,15 +1035,9 @@ void MMU_Reset() Mic_Reset(); MMU.gfx3dCycles = 0; - memset(MMU.dscard[ARMCPU_ARM9].command, 0, 8); - MMU.dscard[ARMCPU_ARM9].address = 0; - MMU.dscard[ARMCPU_ARM9].transfer_count = 0; - MMU.dscard[ARMCPU_ARM9].mode = CardMode_Normal; + MMU.dscard.transfer_count = 0; + MMU.dscard.mode = eCardMode_RAW; - memset(MMU.dscard[ARMCPU_ARM7].command, 0, 8); - MMU.dscard[ARMCPU_ARM7].address = 0; - MMU.dscard[ARMCPU_ARM7].transfer_count = 0; - MMU.dscard[ARMCPU_ARM7].mode = CardMode_Normal; //HACK!!! //until we improve all our session tracking stuff, we need to save the backup memory filename @@ -1285,9 +1279,10 @@ bool DSI_TSC::load_state(EMUFILE* is) return true; } -static void FASTCALL MMU_endTransfer(u32 PROCNUM, u32 cnt) +static void FASTCALL MMU_endTransfer(u32 PROCNUM) { - T1WriteLong(MMU.MMU_MEM[PROCNUM][0x40], 0x1A4, cnt & 0x7F7FFFFF); + u32 val = T1ReadLong(MMU.MMU_MEM[0][0x40], 0x1A4) & 0x7F7FFFFF; + T1WriteLong(MMU.MMU_MEM[0][0x40], 0x1A4, val); // if needed, throw irq for the end of transfer if(MMU.AUX_SPI_CNT & 0x4000) @@ -1314,189 +1309,78 @@ void FASTCALL MMU_writeToGCControl(u32 val) u32 oldCnt = T1ReadLong(MMU.MMU_MEM[PROCNUM][0x40], 0x1A4); #endif + + int dbsize = (val>>24)&7; + static int gcctr=0; + GCLOG("[GC] [%07d] GCControl: %08X (dbsize:%d)\n",gcctr,val,dbsize); + gcctr++; + GCBUS_Controller& card = MMU.dscard; - nds_dscard& card = MMU.dscard[PROCNUM]; + //....pick apart the fields.... + int keylength = (val&0x1FFF); //key1length high gcromctrl[21:16] ?? + u8 key2_encryptdata = (val>>13)&1; + u8 bit15 = (val>>14)&1; + u8 key2_applyseed = (val>>15)&1; //write only strobe + //key1length high gcromctrl[21:16] ?? + u8 key2_encryptcommand = (val>>22)&1; + //bit 23 read only status + int blocksize_field = (val>>24)&7; + u8 clockrate = (val>>27)&1; + u8 secureareamode = (val>>28)&1; + //RESB bit 29? + u8 wr = (val>>30)&1; + u8 start = (val>>31)&1; //doubles as busy on read + static const int blocksize_table[] = {0,0x200,0x400,0x800,0x1000,0x2000,0x4000,4}; + int blocksize = blocksize_table[blocksize_field]; - memcpy(&card.command[0], &MMU.MMU_MEM[PROCNUM][0x40][0x1A8], 8); + //store written value, without bit 31 and bit 23 set (those will be patched in as operations proceed) + T1WriteLong(MMU.MMU_MEM[0][0x40], 0x1A4, val & 0x7F7FFFFF); - card.blocklen = 0; - - if ((val & (1 << 15)) != 0) + //if this operation has been triggered by strobing that bit, run it + if (key2_applyseed) { -#ifdef _LOG_NEW_BOOT - if (fp_dis7) - fprintf(fp_dis7, "ARM%c: KEY2 apply seeds, ctrl %08X (PC:0x%08X)\n", PROCNUM?'7':'9', val, ARMPROC.instruct_adr); - printf("ARM%c: KEY2 apply seeds, ctrl %08X (PC:0x%08X)\n", PROCNUM?'7':'9', val, ARMPROC.instruct_adr); -#endif - key2.applySeed(PROCNUM); } - if ((val & 0x80000000) == 0) - { -#ifdef _LOG_NEW_BOOT - if (fp_dis7) - { - fprintf(fp_dis7, "ARM%c: Bad I/O, PC:%08X\tcmd %02X (%016llX), ctrl %08X/%08X, old len %08X\n", PROCNUM?'7':'9', ARMPROC.instruct_adr, card.command[0], *(u64 *)&card.command[0], val, oldCnt, card.transfer_count); - } - printf("ARM%c: Bad I/O, PC:%08X\n", PROCNUM?'7':'9', ARMPROC.instruct_adr); - printf("\tcmd %02X (%016llX), ctrl %08X/%08X, old len %08X\n", card.command[0], *(u64 *)&card.command[0], val, oldCnt, card.transfer_count); -#endif - card.address = 0; - card.transfer_count = 0; - T1WriteLong(MMU.MMU_MEM[PROCNUM][0x40], 0x1A4, val & 0x7F7FFFFF); - return; - } - - u32 shift = ((val >> 24) & 0x07); - if(shift == 7) - card.transfer_count = 4; - else if(shift == 0) - card.transfer_count = 0; - else - card.transfer_count = (0x100 << shift); + //pluck out the command registers into a more convenient format + GC_Command rawcmd = *(GC_Command*)&MMU.MMU_MEM[PROCNUM][0x40][0x1A8]; -#ifdef _LOG_NEW_BOOT - if (fp_dis7) - fprintf(fp_dis7, "ARM%c: cmd %02X (%016llX), ctrl %08X, old ctrl %08X, size %08X, PC:%08X, delay %X/%X\n", PROCNUM?'7':'9', card.command[0], *(u64 *)&card.command[0], val, oldCnt, card.transfer_count, ARMPROC.instruct_adr, (val & 0x1FFF), ((val >> 16) & 0x3F)); - printf("ARM%c: cmd %02X (%016llX), ctrl %08X/%08X, size %08X, PC:%08X\n", PROCNUM?'7':'9', card.command[0], *(u64 *)&card.command[0], val, oldCnt, card.transfer_count, ARMPROC.instruct_adr); - if (card.mode != CardMode_Normal) + //when writing a 1 to the start bit, a command runs. + //the command is transferred to the GC during the next 8 clocks + if(start) { - u64 rawCmd = (u64)MMU_read32(PROCNUM, 0x037F8074) | ((u64)MMU_read32(PROCNUM, 0x037F8078) << 32); - u64 rawCmd2 = rawCmd >> 56; - if (card.mode != CardMode_DATA_LOAD) - rawCmd2 >>= 4; - if (fp_dis7) - fprintf(fp_dis7, " RAW cmd %02X (%016llX)\n", rawCmd2, rawCmd); - printf(" RAW cmd %02X (%016llX)\n", rawCmd2, rawCmd); - } -#endif - - if (card.mode == CardMode_Normal) - { - switch(card.command[0]) - { - case 0x9F: //Dummy - card.address = 0; - card.transfer_count = 0x2000; - break; - - case 0x3C: //Switch to KEY1 mode - { - u32 gameID = MMU_read32(PROCNUM, 0x027FFE0C); - key1.init(gameID, 2, 0x08); -#ifdef _LOG_NEW_BOOT - if (fp_dis7) - fprintf(fp_dis7, "ARM%c: Activate KEY1 encryption mode (id %08X)\n", PROCNUM?'7':'9', gameID); - printf("ARM%c: Activate KEY1 encryption mode (id %08X)\n", PROCNUM?'7':'9', gameID); -#endif - card.mode = CardMode_KEY1; - card.transfer_count = 0; - } - break; - default: - //fall through to the special slot1 handler - slot1_device->write32(PROCNUM, REG_GCROMCTRL,val); - break; - } + GCLOG("[GC] command:"); rawcmd.print(); + slot1_device->write_command(PROCNUM,rawcmd); } else - if (card.mode == CardMode_KEY1 || card.mode == CardMode_KEY2) - { - // really? the values from memory are used here? - //somehow I doubt it. are they stored in the gamecard controllers somehow? - u32 gameID = MMU_read32(PROCNUM, 0x027FFE0C); - u32 chipID = MMU_read32(PROCNUM, 0x027FF800); - u64 cmd = bswap64(*(u64 *)&card.command[0]); - - //key1.init(gameID, 2, 0x08); - key1.decrypt((u32*)&cmd); - *(u64*)&card.command[0] = bswap64(cmd); - - switch (cmd >> 60) - { - case 0x02: // Get secure area block (4Kbytes) - 910h+11A8h - { - u32 addr = (u32)((cmd >> 32) & 0xF000); -#ifdef _LOG_NEW_BOOT - u32 area = (u32)((cmd >> 32) & 0xF000); - u32 src = MMU_read32(PROCNUM, 0x0380FC00); - u32 dst = MMU_read32(PROCNUM, 0x0380FC04); - u32 len = MMU_read32(PROCNUM, 0x0380FC08); - u32 size = MMU_read32(PROCNUM, 0x0380FC10); - u32 size2 = size; - if (size2 == 7) - size2 = 4; - else - if (size2 != 0) - size2 = (0x100 << size2); - - if (fp_dis7) - fprintf(fp_dis7, "ARM%c: Get secure are block: area %04X, src %08X, dst %08X, len %08X, bsize %08X\n", PROCNUM?'7':'9', area, src, dst, len, size); - printf("ARM%c: Get secure are block: area %04X, src %08X, dst %08X, len %08X, bsize %08X|%08X\n", PROCNUM?'7':'9', area, src, dst, len, size, size2); -#endif - card.address = addr; - } - break; - - case 0x04: // Activate KEY2 encryption mode - 910h+0 - card.mode = CardMode_KEY2; -#ifdef _LOG_NEW_BOOT - if (fp_dis7) - fprintf(fp_dis7, "ARM%c: Activate KEY2 encryption mode\n", PROCNUM?'7':'9'); - printf("ARM%c: Activate KEY2 encryption mode\n", PROCNUM?'7':'9'); -#endif - //key2.applySeed(PROCNUM); - //card.delay = 0x910; - break; - case 0x06: // Optional KEY2 disable - 910h+? - break; - case 0x0A: // Enter main data mode - 910h+0 -#ifdef _LOG_NEW_BOOT - if (fp_dis7) - fprintf(fp_dis7, "ARM%c: Enter main data mode\n", PROCNUM?'7':'9'); - printf("ARM%c: Enter main data mode\n", PROCNUM?'7':'9'); -#endif - card.mode = CardMode_DATA_LOAD; - //card.delay = 0x910; - break; - default: - slot1_device->write32(PROCNUM, REG_GCROMCTRL, val); - break; - } - } - else - if (card.mode == CardMode_DATA_LOAD) - { - slot1_device->write32(PROCNUM, REG_GCROMCTRL, val); -#ifdef _LOG_NEW_BOOT - if (fp_dis7) - fprintf(fp_dis7, "ARM%c: main data mode cmd %02X (addr %08X, len %08X)\n", PROCNUM?'7':'9', card.command[0], card.address, card.transfer_count); - printf("ARM%c: main data mode cmd %02X (addr %08X, len %08X)\n", PROCNUM?'7':'9', card.command[0], card.address, card.transfer_count); -#endif - } - - if(card.delay == 0 && card.transfer_count == 0) { - MMU_endTransfer(PROCNUM, val); - return; + //GCLOG("GC operation terminated or declined. please report, unless you just booted from firmware.\n"); } + //the transfer size is determined by the specification here in GCROMCTRL, not any logic private to the card. + card.transfer_count = blocksize; + val |= 0x00800000; - T1WriteLong(MMU.MMU_MEM[PROCNUM][0x40], 0x1A4, val); - + T1WriteLong(MMU.MMU_MEM[0][0x40], 0x1A4, val); + + //if there was nothing to be done here, go ahead and flag it as done + if(card.transfer_count == 0) + { + MMU_endTransfer(PROCNUM); + return; + } + // Launch DMA if start flag was set to "DS Cart" - //printf("triggering card dma\n"); triggerDma(EDMAMode_Card); } template u32 FASTCALL MMU_readFromGCControl() { - nds_dscard& card = MMU.dscard[PROCNUM]; + GCBUS_Controller& card = MMU.dscard; - u32 val = T1ReadLong(MMU.MMU_MEM[PROCNUM][0x40], 0x1A4); + u32 val = T1ReadLong(MMU.MMU_MEM[0][0x40], 0x1A4); return val; } @@ -1504,57 +1388,18 @@ u32 FASTCALL MMU_readFromGCControl() template u32 MMU_readFromGC() { - const int TEST_PROCNUM = PROCNUM; - - nds_dscard& card = MMU.dscard[TEST_PROCNUM]; - u32 val = 0; + GCBUS_Controller& card = MMU.dscard; + //???? return the latched / last read value instead perhaps? if(card.transfer_count == 0) return 0; - u8 cmd = card.command[0]; - if ((card.mode == CardMode_KEY1) || (card.mode == CardMode_KEY2)) - cmd >>= 4; + u32 val = slot1_device->read_GCDATAIN(PROCNUM); - switch(cmd) - { - case 0x9F: //Dummy - val = 0xFFFFFFFF; - break; - - case 0x3C: //Switch to KEY1 mode - val = 0xFFFFFFFF; - break; - - case 0x02: - val = T1ReadLong(MMU.CART_ROM, card.address); - -#ifdef _LOG_NEW_BOOT - { - extern FILE *fp_dis7; - if (fp_dis7) - fprintf(fp_dis7, "ARM%c: read secury area from %08X (val %08X)\n", PROCNUM?'7':'9', card.address, val); - printf("ARM%c: read secury area from %08X (val %08X)\n", PROCNUM?'7':'9', card.address, val); - } -#endif - break; - - default: - val = slot1_device->read32(TEST_PROCNUM, REG_GCDATAIN); - break; - } - - card.address += 4; // increment address - - card.transfer_count -= 4; // update transfer counter - if(card.transfer_count) // if transfer is not ended - return val; // return data - - // transfer is done - T1WriteLong(MMU.MMU_MEM[TEST_PROCNUM][0x40], 0x1A4, - T1ReadLong(MMU.MMU_MEM[TEST_PROCNUM][0x40], 0x1A4) & 0x7F7FFFFF); - - MMU_endTransfer(PROCNUM, T1ReadLong(MMU.MMU_MEM[TEST_PROCNUM][0x40], 0x1A4)); + //update transfer counter and complete the transfer if necessary + card.transfer_count -= 4; + if(!card.transfer_count) + MMU_endTransfer(PROCNUM); return val; } @@ -2440,7 +2285,7 @@ void DmaController::doCopy() if(nds.VCount==191) enable = 0; } - if(startmode == EDMAMode_Card) todo = MMU.dscard[PROCNUM].transfer_count / sz; + if(startmode == EDMAMode_Card) todo = MMU.dscard.transfer_count / sz; if(startmode == EDMAMode_GXFifo) todo = std::min(todo,(u32)112); //determine how we're going to copy @@ -3333,10 +3178,10 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val) } case REG_GCROMCTRL : - MMU_writeToGCControl( (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x1A4) & 0xFFFF0000) | val); + MMU_writeToGCControl( (T1ReadLong(MMU.MMU_MEM[0][0x40], 0x1A4) & 0xFFFF0000) | val); return; case REG_GCROMCTRL+2 : - MMU_writeToGCControl( (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x1A4) & 0xFFFF) | ((u32) val << 16)); + MMU_writeToGCControl( (T1ReadLong(MMU.MMU_MEM[0][0x40], 0x1A4) & 0xFFFF) | ((u32) val << 16)); return; } @@ -3771,7 +3616,7 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val) case REG_DISPA_DISP3DCNT: writereg_DISP3DCNT(32,adr,val); return; case REG_GCDATAIN: - slot1_device->write32(ARMCPU_ARM9, REG_GCDATAIN,val); + slot1_device->write_GCDATAIN(ARMCPU_ARM9 ,val); return; } @@ -4121,7 +3966,9 @@ u32 FASTCALL _MMU_ARM9_read32(u32 adr) return MMU.timer[ARMCPU_ARM9][(adr&0xF)>>2] | (val<<16); } - case REG_GCDATAIN: return MMU_readFromGC(); + case REG_GCDATAIN: + return MMU_readFromGC(); + case REG_POWCNT1: return readreg_POWCNT1(32,adr); case REG_DISPA_DISP3DCNT: return readreg_DISP3DCNT(32,adr); @@ -4415,10 +4262,10 @@ void FASTCALL _MMU_ARM7_write16(u32 adr, u16 val) } case REG_GCROMCTRL : - MMU_writeToGCControl( (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x1A4) & 0xFFFF0000) | val); + MMU_writeToGCControl( (T1ReadLong(MMU.MMU_MEM[0][0x40], 0x1A4) & 0xFFFF0000) | val); return; case REG_GCROMCTRL+2 : - MMU_writeToGCControl( (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x1A4) & 0xFFFF) | ((u32) val << 16)); + MMU_writeToGCControl( (T1ReadLong(MMU.MMU_MEM[0][0x40], 0x1A4) & 0xFFFF) | ((u32) val << 16)); return; } @@ -4521,7 +4368,7 @@ void FASTCALL _MMU_ARM7_write32(u32 adr, u32 val) return; case REG_GCDATAIN: - slot1_device->write32(ARMCPU_ARM7, REG_GCDATAIN,val); + slot1_device->write_GCDATAIN(ARMCPU_ARM7, val); return; } T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM7][adr>>20], adr & MMU.MMU_MASK[ARMCPU_ARM7][adr>>20], val); diff --git a/desmume/src/MMU.h b/desmume/src/MMU.h index a69e0d03d..255ecd337 100644 --- a/desmume/src/MMU.h +++ b/desmume/src/MMU.h @@ -296,27 +296,60 @@ public: }; -enum ECardMode +enum eCardMode : u32 { - CardMode_Normal = 0, - CardMode_KEY1, - CardMode_KEY2, - CardMode_DATA_LOAD + //when the GC system is first booted up, the protocol is in raw mode + eCardMode_RAW = 0, + + //an intermediate stage during the protocol bootup process. commands are KEY1 encrypted. + eCardMode_KEY1, + + //an intermediate stage during the protocol bootup process. commands are KEY1 encrypted, while replies are KEY2 encrypted + eCardMode_KEY2, + + //the final stage of the protocol bootup process. "main data load" mode. commands are KEY2 encrypted, and replies are KEY2 encrypted. + //optionally, according to some flag we havent designed yet but should probably go in GCBUS_Controller, the whole KEY2 part can be bypassed + //(this is typical when skipping the firmware boot process) + eCardMode_NORMAL, + + //help fix to 32bit + eCardMode_Pad = 0xFFFFFFFF }; -//should rather be known as gamecard bus controller, or somesuch -struct nds_dscard +//#define GCLOG(...) printf(__VA_ARGS__); +#define GCLOG(...) + +struct GC_Command { - u8 command[8]; + u8 bytes[8]; + void print() + { + GCLOG("%02X%02X%02X%02X%02X%02X%02X%02X\n",bytes[0],bytes[1],bytes[2],bytes[3],bytes[4],bytes[5],bytes[6],bytes[7]); + } + void toCryptoBuffer(u32 buf[2]) + { + u8 temp[8] = { bytes[7], bytes[6], bytes[5], bytes[4], bytes[3], bytes[2], bytes[1], bytes[0] }; + buf[0] = T1ReadLong(temp,0); + buf[1] = T1ReadLong(temp,4); + } + void fromCryptoBuffer(u32 buf[2]) + { + bytes[7] = (buf[0]>>0)&0xFF; + bytes[6] = (buf[0]>>8)&0xFF; + bytes[5] = (buf[0]>>16)&0xFF; + bytes[4] = (buf[0]>>24)&0xFF; + bytes[3] = (buf[1]>>0)&0xFF; + bytes[2] = (buf[1]>>8)&0xFF; + bytes[1] = (buf[1]>>16)&0xFF; + bytes[0] = (buf[1]>>24)&0xFF; + } +}; - u32 address; +//should rather be known as GCBUS controller, or somesuch +struct GCBUS_Controller +{ u32 transfer_count; - u32 delay; - - ECardMode mode; - - // NJSD stuff - int blocklen; + eCardMode mode; }; #define DUP2(x) x, x @@ -432,7 +465,7 @@ struct MMU_struct fw_memory_chip fw; - nds_dscard dscard[2]; + GCBUS_Controller dscard; }; diff --git a/desmume/src/Makefile.am b/desmume/src/Makefile.am index 52a896458..a21e53af4 100644 --- a/desmume/src/Makefile.am +++ b/desmume/src/Makefile.am @@ -87,7 +87,7 @@ libdesmume_a_SOURCES = \ utils/tinyxml/tinyxmlerror.cpp \ utils/tinyxml/tinyxmlparser.cpp \ 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/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 \ cheatSystem.cpp cheatSystem.h \ texcache.cpp texcache.h rasterize.cpp rasterize.h \ metaspu/metaspu.cpp metaspu/metaspu.h \ diff --git a/desmume/src/NDSSystem.cpp b/desmume/src/NDSSystem.cpp index cd882495a..561abe424 100644 --- a/desmume/src/NDSSystem.cpp +++ b/desmume/src/NDSSystem.cpp @@ -47,8 +47,8 @@ //int xxctr=0; //#define LOG_ARM9 //#define LOG_ARM7 -//#define dolog (currFrameCounter>15) -bool dolog=false; +#define dolog (currFrameCounter>30) +//bool dolog=false; //#define LOG_TO_FILE //#define LOG_TO_FILE_REGS diff --git a/desmume/src/addons/slot1_none.cpp b/desmume/src/addons/slot1_none.cpp index 9be49ede4..6b16f4728 100644 --- a/desmume/src/addons/slot1_none.cpp +++ b/desmume/src/addons/slot1_none.cpp @@ -29,18 +29,9 @@ public: return &info; } - virtual void connect() - { - } - - virtual u32 read32(u8 PROCNUM, u32 adr) - { - //return a chip ID of 0. - //if (adr == REG_GCDATAIN && MMU.dscard[PROCNUM].command[0] == 0xB8) return 0; - //EDIT - not sure who did this or why, but... but if a card is ejected, there can be no chip ID. - //we certainly want it to appear differently from chipId 0, which is something we are faking in other slot-1 devices - return 0xFFFFFFFF; - } + //pretty much every access to the card should just be ignored and reading HIGH-Z off the GC bus. + //so, nothing really to do here + //(notably, it results in a 0xFFFFFFFF card ID) }; diff --git a/desmume/src/addons/slot1_r4.cpp b/desmume/src/addons/slot1_r4.cpp index e1dc8ab29..60cd8e2ce 100644 --- a/desmume/src/addons/slot1_r4.cpp +++ b/desmume/src/addons/slot1_r4.cpp @@ -1,231 +1,231 @@ -/* - Copyright (C) 2010-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 . -*/ - -#include - -#include "../slot1.h" -#include "../registers.h" -#include "../MMU.h" -#include "../NDSSystem.h" -#include "../emufile.h" - -class Slot1_R4 : public ISlot1Interface -{ -private: - EMUFILE *img; - u32 write_count; - u32 write_enabled; - -public: - Slot1_R4() - : img(NULL) - , write_count(0) - , write_enabled(0) - { - } - - virtual Slot1Info const* info() - { - static Slot1InfoSimple info("R4","Slot1 R4 emulation"); - return &info; - } - - - //called once when the emulator starts up, or when the device springs into existence - virtual bool init() - { - //strange to do this here but we need to make sure its done at some point - srand(time(NULL)); - return true; - } - - virtual void connect() - { - img = slot1_GetFatImage(); - - if(!img) - INFO("slot1 fat not successfully mounted\n"); - } - - //called when the emulator disconnects the device - virtual void disconnect() - { - img = NULL; - } - - //called when the emulator shuts down, or when the device disappears from existence - virtual void shutdown() - { - } - - - virtual u32 read32(u8 PROCNUM, u32 adr) - { - switch(adr) - { - case REG_GCDATAIN: - return read32_GCDATAIN(); - default: - return 0; - } - } - - - virtual void write32(u8 PROCNUM, u32 adr, u32 val) - { - switch(adr) - { - case REG_GCROMCTRL: - write32_GCROMCTRL(val); - break; - case REG_GCDATAIN: - write32_GCDATAIN(val); - break; - } - } - -private: - - u32 read32_GCDATAIN() - { - nds_dscard& card = MMU.dscard[0]; - - u32 val; - - switch(card.command[0]) - { - //Get ROM chip ID - case 0x90: - case 0xB8: - val = 0xFC2; - break; - - case 0xB0: - val = 0x1F4; - break; - case 0xB9: - val = (rand() % 100) ? 0x1F4 : 0; - break; - case 0xBB: - case 0xBC: - val = 0; - break; - case 0xBA: - //INFO("Read from sd at sector %08X at adr %08X ",card.address/512,ftell(img)); - img->fread(&val, 4); - //INFO("val %08X\n",val); - break; - - default: - val = 0; - } - - /*INFO("READ CARD command: %02X%02X%02X%02X% 02X%02X%02X%02X RET: %08X ", - card.command[0], card.command[1], card.command[2], card.command[3], - card.command[4], card.command[5], card.command[6], card.command[7], - val); - INFO("FROM: %08X LR: %08X\n", NDS_ARM9.instruct_adr, NDS_ARM9.R[14]);*/ - - - return val; - } //read32_GCDATAIN - - - void write32_GCROMCTRL(u32 val) - { - nds_dscard& card = MMU.dscard[0]; - - switch(card.command[0]) - { - case 0xB0: - break; - case 0xB9: - case 0xBA: - card.address = (card.command[1] << 24) | (card.command[2] << 16) | (card.command[3] << 8) | card.command[4]; - img->fseek(card.address,SEEK_SET); - break; - case 0xBB: - write_enabled = 1; - write_count = 0x80; - case 0xBC: - card.address = (card.command[1] << 24) | (card.command[2] << 16) | (card.command[3] << 8) | card.command[4]; - img->fseek(card.address,SEEK_SET); - break; - } - } - - void write32_GCDATAIN(u32 val) - { - nds_dscard& card = MMU.dscard[0]; - //bool log=false; - - memcpy(&card.command[0], &MMU.MMU_MEM[0][0x40][0x1A8], 8); - - //last_write_count = write_count; - if(card.command[4]) - { - // transfer is done - T1WriteLong(MMU.MMU_MEM[0][0x40], 0x1A4,val & 0x7F7FFFFF); - - // if needed, throw irq for the end of transfer - if(MMU.AUX_SPI_CNT & 0x4000) - NDS_makeIrq(ARMCPU_ARM9, IRQ_BIT_GC_TRANSFER_COMPLETE); - - return; - } - - switch(card.command[0]) - { - case 0xBB: - { - if(write_count && write_enabled) - { - img->fwrite(&val, 4); - img->fflush(); - write_count--; - } - break; - } - default: - break; - } - - if(write_count==0) - { - write_enabled = 0; - - // transfer is done - T1WriteLong(MMU.MMU_MEM[0][0x40], 0x1A4,val & 0x7F7FFFFF); - - // if needed, throw irq for the end of transfer - if(MMU.AUX_SPI_CNT & 0x4000) - NDS_makeIrq(ARMCPU_ARM9, IRQ_BIT_GC_TRANSFER_COMPLETE); - } - - /*if(log) - { - INFO("WRITE CARD command: %02X%02X%02X%02X%02X%02X%02X%02X\t", - card.command[0], card.command[1], card.command[2], card.command[3], - card.command[4], card.command[5], card.command[6], card.command[7]); - INFO("FROM: %08X\t", NDS_ARM9.instruct_adr); - INFO("VAL: %08X\n", val); - }*/ - } - -}; - -ISlot1Interface* construct_Slot1_R4() { return new Slot1_R4(); } \ No newline at end of file +///* +// Copyright (C) 2010-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 . +//*/ +// +//#include +// +//#include "../slot1.h" +//#include "../registers.h" +//#include "../MMU.h" +//#include "../NDSSystem.h" +//#include "../emufile.h" +// +//class Slot1_R4 : public ISlot1Interface +//{ +//private: +// EMUFILE *img; +// u32 write_count; +// u32 write_enabled; +// +//public: +// Slot1_R4() +// : img(NULL) +// , write_count(0) +// , write_enabled(0) +// { +// } +// +// virtual Slot1Info const* info() +// { +// static Slot1InfoSimple info("R4","Slot1 R4 emulation"); +// return &info; +// } +// +// +// //called once when the emulator starts up, or when the device springs into existence +// virtual bool init() +// { +// //strange to do this here but we need to make sure its done at some point +// srand(time(NULL)); +// return true; +// } +// +// virtual void connect() +// { +// img = slot1_GetFatImage(); +// +// if(!img) +// INFO("slot1 fat not successfully mounted\n"); +// } +// +// //called when the emulator disconnects the device +// virtual void disconnect() +// { +// img = NULL; +// } +// +// //called when the emulator shuts down, or when the device disappears from existence +// virtual void shutdown() +// { +// } +// +// +// virtual u32 read32(u8 PROCNUM, u32 adr) +// { +// switch(adr) +// { +// case REG_GCDATAIN: +// return read32_GCDATAIN(); +// default: +// return 0; +// } +// } +// +// +// virtual void write32(u8 PROCNUM, u32 adr, u32 val) +// { +// switch(adr) +// { +// case REG_GCROMCTRL: +// write32_GCROMCTRL(val); +// break; +// case REG_GCDATAIN: +// write32_GCDATAIN(val); +// break; +// } +// } +// +//private: +// +// u32 read32_GCDATAIN() +// { +// nds_dscard& card = MMU.dscard[0]; +// +// u32 val; +// +// switch(card.command[0]) +// { +// //Get ROM chip ID +// case 0x90: +// case 0xB8: +// val = 0xFC2; +// break; +// +// case 0xB0: +// val = 0x1F4; +// break; +// case 0xB9: +// val = (rand() % 100) ? 0x1F4 : 0; +// break; +// case 0xBB: +// case 0xBC: +// val = 0; +// break; +// case 0xBA: +// //INFO("Read from sd at sector %08X at adr %08X ",card.address/512,ftell(img)); +// img->fread(&val, 4); +// //INFO("val %08X\n",val); +// break; +// +// default: +// val = 0; +// } +// +// /*INFO("READ CARD command: %02X%02X%02X%02X% 02X%02X%02X%02X RET: %08X ", +// card.command[0], card.command[1], card.command[2], card.command[3], +// card.command[4], card.command[5], card.command[6], card.command[7], +// val); +// INFO("FROM: %08X LR: %08X\n", NDS_ARM9.instruct_adr, NDS_ARM9.R[14]);*/ +// +// +// return val; +// } //read32_GCDATAIN +// +// +// void write32_GCROMCTRL(u32 val) +// { +// nds_dscard& card = MMU.dscard[0]; +// +// switch(card.command[0]) +// { +// case 0xB0: +// break; +// case 0xB9: +// case 0xBA: +// card.address = (card.command[1] << 24) | (card.command[2] << 16) | (card.command[3] << 8) | card.command[4]; +// img->fseek(card.address,SEEK_SET); +// break; +// case 0xBB: +// write_enabled = 1; +// write_count = 0x80; +// case 0xBC: +// card.address = (card.command[1] << 24) | (card.command[2] << 16) | (card.command[3] << 8) | card.command[4]; +// img->fseek(card.address,SEEK_SET); +// break; +// } +// } +// +// void write32_GCDATAIN(u32 val) +// { +// nds_dscard& card = MMU.dscard[0]; +// //bool log=false; +// +// memcpy(&card.command[0], &MMU.MMU_MEM[0][0x40][0x1A8], 8); +// +// //last_write_count = write_count; +// if(card.command[4]) +// { +// // transfer is done +// T1WriteLong(MMU.MMU_MEM[0][0x40], 0x1A4,val & 0x7F7FFFFF); +// +// // if needed, throw irq for the end of transfer +// if(MMU.AUX_SPI_CNT & 0x4000) +// NDS_makeIrq(ARMCPU_ARM9, IRQ_BIT_GC_TRANSFER_COMPLETE); +// +// return; +// } +// +// switch(card.command[0]) +// { +// case 0xBB: +// { +// if(write_count && write_enabled) +// { +// img->fwrite(&val, 4); +// img->fflush(); +// write_count--; +// } +// break; +// } +// default: +// break; +// } +// +// if(write_count==0) +// { +// write_enabled = 0; +// +// // transfer is done +// T1WriteLong(MMU.MMU_MEM[0][0x40], 0x1A4,val & 0x7F7FFFFF); +// +// // if needed, throw irq for the end of transfer +// if(MMU.AUX_SPI_CNT & 0x4000) +// NDS_makeIrq(ARMCPU_ARM9, IRQ_BIT_GC_TRANSFER_COMPLETE); +// } +// +// /*if(log) +// { +// INFO("WRITE CARD command: %02X%02X%02X%02X%02X%02X%02X%02X\t", +// card.command[0], card.command[1], card.command[2], card.command[3], +// card.command[4], card.command[5], card.command[6], card.command[7]); +// INFO("FROM: %08X\t", NDS_ARM9.instruct_adr); +// INFO("VAL: %08X\n", val); +// }*/ +// } +// +//}; +// +//ISlot1Interface* construct_Slot1_R4() { return new Slot1_R4(); } \ No newline at end of file diff --git a/desmume/src/addons/slot1_retail_auto.cpp b/desmume/src/addons/slot1_retail_auto.cpp index aa152d2fb..4efb94b7e 100644 --- a/desmume/src/addons/slot1_retail_auto.cpp +++ b/desmume/src/addons/slot1_retail_auto.cpp @@ -39,23 +39,38 @@ public: virtual void connect() { - //TODO - check game ID in core emulator and select right implementation - mSelectedImplementation = slot1_List[NDS_SLOT1_RETAIL_MCROM]; + + NDS_SLOT1_TYPE selection = NDS_SLOT1_RETAIL_MCROM; + + //check game ID in core emulator and select right implementation + if(!memcmp(gameInfo.header.gameCode,"UORE",4)) + selection = NDS_SLOT1_RETAIL_NAND; + + mSelectedImplementation = slot1_List[selection]; + mSelectedImplementation->connect(); + printf("slot1 auto-selected device type: %s\n",mSelectedImplementation->info()->name()); + } virtual void disconnect() { + if(mSelectedImplementation) mSelectedImplementation->disconnect(); mSelectedImplementation = NULL; } - virtual void write32(u8 PROCNUM, u32 adr, u32 val) + virtual void write_command(u8 PROCNUM, GC_Command command) { - mSelectedImplementation->write32(PROCNUM, adr, val); + mSelectedImplementation->write_command(PROCNUM, command); } - virtual u32 read32(u8 PROCNUM, u32 adr) + virtual void write_GCDATAIN(u8 PROCNUM, u32 val) { - return mSelectedImplementation->read32(PROCNUM, adr); + mSelectedImplementation->write_GCDATAIN(PROCNUM, val); + } + + virtual u32 read_GCDATAIN(u8 PROCNUM) + { + return mSelectedImplementation->read_GCDATAIN(PROCNUM); } virtual u8 auxspi_transaction(int PROCNUM, u8 value) diff --git a/desmume/src/addons/slot1_retail_mcrom.cpp b/desmume/src/addons/slot1_retail_mcrom.cpp index dc75cf3f2..1a2392a7e 100644 --- a/desmume/src/addons/slot1_retail_mcrom.cpp +++ b/desmume/src/addons/slot1_retail_mcrom.cpp @@ -21,10 +21,22 @@ #include "../NDSSystem.h" #include "slot1comp_mc.h" #include "slot1comp_rom.h" +#include "slot1comp_protocol.h" -class Slot1_Retail_MCROM : public ISlot1Interface +//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_MCROM : public ISlot1Interface, public ISlot1Comp_Protocol_Client { +private: + Slot1Comp_Protocol protocol; + Slot1Comp_Rom rom; + public: + virtual Slot1Info const* info() { static Slot1InfoSimple info("Retail MC+ROM","Slot1 Retail MC+ROM (standard) card emulation"); @@ -33,28 +45,9 @@ public: virtual void connect() { - } - - virtual void write32(u8 PROCNUM, u32 adr, u32 val) - { - switch(adr) - { - case REG_GCROMCTRL: - write32_GCROMCTRL(PROCNUM, val); - break; - } - } - - - virtual u32 read32(u8 PROCNUM, u32 adr) - { - switch(adr) - { - case REG_GCDATAIN: - return read32_GCDATAIN(PROCNUM); - default: - return 0; - } + protocol.reset(this); + protocol.chipId = gameInfo.chipID; + protocol.gameCode = T1ReadLong((u8*)gameInfo.header.gameCode,0); } virtual u8 auxspi_transaction(int PROCNUM, u8 value) @@ -67,262 +60,30 @@ public: g_Slot1Comp_MC.auxspi_reset(PROCNUM); } -private: - - u32 read32_GCDATAIN(u8 PROCNUM) + virtual void write_command(u8 PROCNUM, GC_Command command) { - nds_dscard& card = MMU.dscard[PROCNUM]; - u8 cmd = card.command[0]; - - if (card.mode == CardMode_KEY1 || card.mode == CardMode_KEY2) - cmd >>= 4; - - switch(cmd) - { - case 0x01: // 2nd Get ROM Chip ID - len 4 bytes - case 0x90: // 1st Get ROM Chip ID - len 4 bytes - case 0xB8: // 3rd Get ROM Chip ID - len 4 bytes - { - // Note: the BIOS stores the chip ID in main memory - // Most games continuously compare the chip ID with - // the value in memory, probably to know if the card - // was removed. - // As DeSmuME normally boots directly from the game, the chip - // ID in main mem is zero and this value needs to be - // zero too. - - //staff of kings verifies this (it also uses the arm7 IRQ 20) - return gameInfo.chipID; - } - break; - - - // Data read - case 0x00: - case 0xB7: - { - //it seems that etrian odyssey 3 doesnt work unless we mask this to cart size. - //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 - u32 address = card.address & (gameInfo.mask); - - // Make sure any reads below 0x8000 redirect to 0x8000+(adr&0x1FF) as on real card - if((cmd == 0xB7) && (address < 0x8000)) - { - //TODO - refactor this to include the PROCNUM, for debugging purposes if nothing else - //(can refactor gbaslot also) - - //INFO("Read below 0x8000 (0x%04X) from: ARM%s %08X\n", - // card.address, (PROCNUM ? "7":"9"), (PROCNUM ? NDS_ARM7:NDS_ARM9).instruct_adr); - - 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 >= gameInfo.romsize) - { - DEBUG_Notify.ReadBeyondEndOfCart(address,gameInfo.romsize); - return 0xFFFFFFFF; - } - - return T1ReadLong(MMU.CART_ROM, address); - } - break; - default: - //printf("ARM%c: SLOT1 invalid command %02X (read)\n", PROCNUM?'7':'9', cmd); - return 0; - } //switch(card.command[0]) - } //read32_GCDATAIN - - void write32_GCROMCTRL(u8 PROCNUM, u32 val) - { - nds_dscard& card = MMU.dscard[PROCNUM]; - - if (card.mode == CardMode_Normal) - { - switch(card.command[0]) - { - case 0x00: //Data read (0000000000000000h Get Cartridge Header) - len 200h bytes - case 0xB7: - card.address = (card.command[1] << 24) | (card.command[2] << 16) | (card.command[3] << 8) | card.command[4]; - card.transfer_count = 0x200; - break; - - case 0x90: // 1st Get ROM Chip ID - len 4 bytes - case 0xB8: - card.address = 0; - card.transfer_count = 4; - break; - - default: - card.address = 0; - card.transfer_count = 0; - printf("ARM%c: SLOT1 invalid command %02X (write) - CardMode_Normal\n", PROCNUM?'7':'9', card.command[0]); - break; - } - return; - } - - if (card.mode == CardMode_KEY1 || card.mode == CardMode_KEY2) - { - u8 cmd = (card.command[0] >> 4); - switch(cmd) - { - case 0x01: // 2nd Get ROM Chip ID - len 4 bytes - card.address = 0; - card.transfer_count = 4; - break; - - default: - card.address = 0; - card.transfer_count = 0; - printf("ARM%c: SLOT1 invalid command %02X (write) - %s\n", PROCNUM?'7':'9', cmd, (card.mode == CardMode_KEY1)?"CardMode_KEY1":"CardMode_KEY2"); - break; - } - return; - } - - if (card.mode == CardMode_DATA_LOAD) - { - switch(card.command[0]) - { - case 0xB7: // Encrypted Data Read (B7aaaaaaaa000000h) - len 200h bytes - card.address = (card.command[1] << 24) | (card.command[2] << 16) | (card.command[3] << 8) | card.command[4]; - card.transfer_count = 0x200; - break; - - case 0xB8: // 3nd Get ROM Chip ID - len 4 bytes - card.address = 0; - card.transfer_count = 4; - break; - - default: - card.address = 0; - card.transfer_count = 0; - card.mode = CardMode_KEY1; - printf("ARM%c: SLOT1 invalid command %02X (write) - CardMode_DATA_LOAD\n", PROCNUM?'7':'9', card.command[0]); - break; - } - return; - } + 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) + { + rom.start(operation,protocol.address); + } +private: + + u32 slot1client_read_GCDATAIN(eSlot1Operation operation) + { + return rom.read(); + } }; ISlot1Interface* construct_Slot1_Retail_MCROM() { return new Slot1_Retail_MCROM(); } - - // ///writetoGCControl: - //// --- Ninja SD commands ------------------------------------- - - // // NJSD init/reset - // case 0x20: - // { - // card.address = 0; - // card.transfer_count = 0; - // } - // break; - - // // NJSD_sendCLK() - // case 0xE0: - // { - // card.address = 0; - // card.transfer_count = 0; - // NDS_makeInt(PROCNUM, 20); - // } - // break; - - // // NJSD_sendCMDN() / NJSD_sendCMDR() - // case 0xF0: - // case 0xF1: - // switch (card.command[2]) - // { - // // GO_IDLE_STATE - // case 0x40: - // card.address = 0; - // card.transfer_count = 0; - // NDS_makeInt(PROCNUM, 20); - // break; - - // case 0x42: // ALL_SEND_CID - // case 0x43: // SEND_RELATIVE_ADDR - // case 0x47: // SELECT_CARD - // case 0x49: // SEND_CSD - // case 0x4D: - // case 0x77: // APP_CMD - // case 0x69: // SD_APP_OP_COND - // card.address = 0; - // card.transfer_count = 6; - // NDS_makeInt(PROCNUM, 20); - // break; - - // // SET_BLOCKLEN - // case 0x50: - // card.address = 0; - // card.transfer_count = 6; - // card.blocklen = card.command[6] | (card.command[5] << 8) | (card.command[4] << 16) | (card.command[3] << 24); - // NDS_makeInt(PROCNUM, 20); - // break; - - // // READ_SINGLE_BLOCK - // case 0x51: - // card.address = card.command[6] | (card.command[5] << 8) | (card.command[4] << 16) | (card.command[3] << 24); - // card.transfer_count = (card.blocklen + 3) >> 2; - // NDS_makeInt(PROCNUM, 20); - // break; - // } - // break; - - // // --- Ninja SD commands end --------------------------------- - - - - // //GCDATAIN: - // // --- Ninja SD commands ------------------------------------- - - // // NJSD_sendCMDN() / NJSD_sendCMDR() - // case 0xF0: - // case 0xF1: - // switch (card.command[2]) - // { - // // ALL_SEND_CID - // case 0x42: - // if (card.transfer_count == 2) val = 0x44534A4E; - // else val = 0x00000000; - - // // SEND_RELATIVE_ADDR - // case 0x43: - // case 0x47: - // case 0x49: - // case 0x50: - // val = 0x00000000; - // break; - - // case 0x4D: - // if (card.transfer_count == 2) val = 0x09000000; - // else val = 0x00000000; - // break; - - // // APP_CMD - // case 0x77: - // if (card.transfer_count == 2) val = 0x00000037; - // else val = 0x00000000; - // break; - - // // SD_APP_OP_COND - // case 0x69: - // if (card.transfer_count == 2) val = 0x00008000; - // else val = 0x00000000; - // break; - - // // READ_SINGLE_BLOCK - // case 0x51: - // val = 0x00000000; - // break; - // } - // break; - - // // --- Ninja SD commands end --------------------------------- - - diff --git a/desmume/src/addons/slot1_retail_nand.cpp b/desmume/src/addons/slot1_retail_nand.cpp index ba430c645..57efab953 100644 --- a/desmume/src/addons/slot1_retail_nand.cpp +++ b/desmume/src/addons/slot1_retail_nand.cpp @@ -27,9 +27,22 @@ #include "../registers.h" #include "../MMU.h" #include "../NDSSystem.h" +#include "slot1comp_rom.h" +#include "slot1comp_protocol.h" -class Slot1_Retail_NAND : public ISlot1Interface +//quick architecture overview: +//NAND receives GC bus commands from MMU.cpp +//those are passed on to the protocol component for parsing +//protocol calls back into NAND via ISlot1Comp_Protocol_Client interface for things the protocol doesnt know about (the contents of the rom, chiefly) +//NAND utilizes the rom component for address logic and delivering data. +//it also processes some commands itself which arent rom-related (the NANDy stuff) + +class Slot1_Retail_NAND : public ISlot1Interface, public ISlot1Comp_Protocol_Client { +private: + Slot1Comp_Protocol protocol; + Slot1Comp_Rom rom; + public: virtual Slot1Info const* info() { @@ -39,135 +52,75 @@ public: virtual void connect() { + protocol.reset(this); + protocol.chipId = gameInfo.chipID; + protocol.gameCode = T1ReadLong((u8*)gameInfo.header.gameCode,0); } - virtual u32 read32(u8 PROCNUM, u32 adr) + virtual void write_command(u8 PROCNUM, GC_Command command) { - switch(adr) + 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) + { + //pass the normal rom operations along to the rom component + switch(operation) { - case REG_GCDATAIN: - return read32_GCDATAIN(PROCNUM); - default: - return 0; + case eSlot1Operation_00_ReadHeader_Unencrypted: + case eSlot1Operation_B7_Read: + rom.start(operation,protocol.address); + return; } - } - virtual void write32(u8 PROCNUM, u32 adr, u32 val) - { - switch(adr) + //handle special commands ourselves + int cmd = protocol.command.bytes[0]; + switch(cmd) { - case REG_GCROMCTRL: - write32_GCROMCTRL(PROCNUM, val); - break; - } - } - - -private: - - - void write32_GCROMCTRL(u8 PROCNUM, u32 val) - { - nds_dscard& card = MMU.dscard[PROCNUM]; - - switch(card.command[0]) - { - case 0x00: //Data read - case 0xB7: - card.address = (card.command[1] << 24) | (card.command[2] << 16) | (card.command[3] << 8) | card.command[4]; - card.transfer_count = 0x200; - break; - - case 0xB8: // Chip ID - card.address = 0; - card.transfer_count = 4; - break; - // Nand Init case 0x94: - card.address = 0; - card.transfer_count = 0x200; + //GCLOG("NAND 0x94\n"); + //length = 0x200; break; // Nand Error? case 0xD6: - card.address = 0; - card.transfer_count = 4; + //GCLOG("NAND 0xD6\n"); + //length = 4; break; - + // Nand Write? ---- PROGRAM for INTERNAL DATA MOVE/RANDOM DATA INPUT //case 0x8B: case 0x85: - card.address = 0; - card.transfer_count = 0x200; - break; - - default: - card.address = 0; - card.transfer_count = 0; + //GCLOG("NAND 0x85\n"); + //length = 0x200; break; } } - - u32 read32_GCDATAIN(u8 PROCNUM) + virtual u32 slot1client_read_GCDATAIN(eSlot1Operation operation) { - nds_dscard& card = MMU.dscard[PROCNUM]; - - switch(card.command[0]) + //pass the normal rom operations along to the rom component + switch(operation) { - //Get ROM chip ID - case 0x90: - case 0xB8: - { - // Note: the BIOS stores the chip ID in main memory - // Most games continuously compare the chip ID with - // the value in memory, probably to know if the card - // was removed. - // As DeSmuME boots directly from the game, the chip - // ID in main mem is zero and this value needs to be - // zero too. - - //note that even if desmume was booting from firmware, and reading this chip ID to store in main memory, - //this still works, since it will have read 00 originally and then read 00 to validate. - return gameInfo.chipID; - } - break; - - - // Data read - case 0x00: - case 0xB7: - { - // Make sure any reads below 0x8000 redirect to 0x8000+(adr&0x1FF) as on real cart - if((card.command[0] == 0xB7) && (card.address < 0x8000)) - { - //TODO - refactor this to include the PROCNUM, for debugging purposes if nothing else - //(can refactor gbaslot also) - - //INFO("Read below 0x8000 (0x%04X) from: ARM%s %08X\n", - // card.address, (PROCNUM ? "7":"9"), (PROCNUM ? NDS_ARM7:NDS_ARM9).instruct_adr); - - card.address = (0x8000 + (card.address&0x1FF)); - } - - //it seems that etrian odyssey 3 doesnt work unless we mask this to cart size. - //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 - u32 address = card.address & (gameInfo.mask); - - //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 >= gameInfo.romsize) - { - DEBUG_Notify.ReadBeyondEndOfCart(address,gameInfo.romsize); - return 0xFFFFFFFF; - } - - return T1ReadLong(MMU.CART_ROM, address); - } - break; + case eSlot1Operation_00_ReadHeader_Unencrypted: + case eSlot1Operation_B7_Read: + return rom.read(); + } + //handle special commands ourselves + int cmd = protocol.command.bytes[0]; + switch(cmd) + { // Nand Init? case 0x94: return 0; //Unsure what to return here so return 0 for now @@ -177,11 +130,30 @@ private: //0x80 == busy // Made in Ore/WarioWare D.I.Y. need set value to 0x80 return 0x80; //0x20 == ready + } + + return 0; + } + + virtual void slot1client_write_GCDATAIN(eSlot1Operation operation, u32 val) + { + //pass the normal rom operations along to the rom component + switch(operation) + { + case eSlot1Operation_00_ReadHeader_Unencrypted: + case eSlot1Operation_B7_Read: + return; + } + + //handle special commands ourselves + int cmd = protocol.command.bytes[0]; + switch(cmd) + { + } + } + + - default: - return 0; - } //switch(card.command[0]) - } //read32_GCDATAIN }; diff --git a/desmume/src/addons/slot1comp_protocol.cpp b/desmume/src/addons/slot1comp_protocol.cpp new file mode 100644 index 000000000..61cf2480c --- /dev/null +++ b/desmume/src/addons/slot1comp_protocol.cpp @@ -0,0 +1,217 @@ +/* + Copyright (C) 2012-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 . +*/ + +#include "slot1comp_protocol.h" +#include "MMU.h" +#include "armcpu.h" +#include "encrypt.h" +#include "utils/decrypt/decrypt.h" + +static _KEY1 key1((const u8*)arm7_key); + +void Slot1Comp_Protocol::reset(ISlot1Comp_Protocol_Client* client) +{ + this->client = client; + + //we have to initialize this to something.. lets use dummy. + //(need to clean this up...) + memcpy(&command,"\x9F\0\0\0\0\0\0\0",8); + operation = eSlot1Operation_9F_Dummy; + + length = 0; + delay = 0; + mode = eCardMode_RAW; +} + +void Slot1Comp_Protocol::write_command_RAW(GC_Command command) +{ + int cmd = command.bytes[0]; + if(cmd == 0xB7) + { + //HACK!!!!!!!!!!!!!!!!!! + //switch to normal mode. we should do it in the NDSSystem bootup process. + //WAY cleaner it will be. + mode = eCardMode_NORMAL; + //be suer to forward this command to the NORMAL command handler... + write_command_NORMAL(command); + } + if(cmd == 0x9F) + { + operation = eSlot1Operation_9F_Dummy; + delay = 0, length = 0x2000; + } + if(cmd == 0x90) + { + operation = eSlot1Operation_90_ChipID; + delay = 0, length = 4; + //we handle this operation ourselves + } + if(cmd == 0x3C) + { + //switch to KEY1 + delay = 0, length = 0; + mode = eCardMode_KEY1; + + //defer initialization of KEY1 until we know we need it, just to save some CPU time. + //TODO - some information about these parameters + //level == 2 + //modulo == 8 + key1.init(gameCode, 2, 0x08); + GCLOG("[GC] KEY1 ACTIVATED\n"); + } + if(cmd == 0x00) + { + operation = eSlot1Operation_00_ReadHeader_Unencrypted; + client->slot1client_startOperation(operation); + } +} + +void Slot1Comp_Protocol::write_command_KEY1(GC_Command command) +{ + //decrypt the KEY1-format command + u32 temp[2]; + command.toCryptoBuffer(temp); + key1.decrypt(temp); + command.fromCryptoBuffer(temp); + GCLOG("[GC] (key1-decrypted):"); command.print(); + + //and process it: + int cmd = command.bytes[0]&0xF0; + switch(cmd&0xF0) + { + case 0x10: + operation = eSlot1Operation_1x_ChipID; + delay = 0x910, length = 4; + //we handle this operation ourselves + break; + case 0x20: + delay = 0x910, length = 0x11A8; + break; + case 0x30: + break; + case 0x40: + //switch to KEY2 + delay = 0x910, length = 0; + //well.. not really... yet. + GCLOG("[GC] KEY2 ACTIVATED\n"); + break; + case 0x60: + //KEY2 disable? any info? + break; + case 0xA0: + delay = 0x910, length = 0; + mode = eCardMode_NORMAL; + GCLOG("[GC] NORMAL MODE ACTIVATED\n"); + break; + case 0xB0: + break; + } +} + +void Slot1Comp_Protocol::write_command_NORMAL(GC_Command command) +{ + switch(command.bytes[0]) + { + case 0xB7: + { + operation = eSlot1Operation_B7_Read; + + //TODO - more endian-safe way of doing this + u64 cmd64 = bswap64(*(u64*)command.bytes); + address = (u32)((cmd64 >> 24)); + length = 0x200; + + client->slot1client_startOperation(operation); + } + break; + + case 0xB8: + operation = eSlot1Operation_B8_ChipID; + delay = 0, length = 4; + //we handle this operation ourselves + break; + + default: + operation = eSlot1Operation_Unknown; + client->slot1client_startOperation(operation); + break; + } +} + +void Slot1Comp_Protocol::write_command(GC_Command command) +{ + this->command = command; + + //unrecognized commands will do something depending on the current state of the card + delay = 0; + length = 0; + address = 0; + + switch(mode) + { + case eCardMode_RAW: + write_command_RAW(command); + break; + + case eCardMode_KEY1: + write_command_KEY1(command); + break; + + case eCardMode_NORMAL: + write_command_NORMAL(command); + break; + } +} + +void Slot1Comp_Protocol::write_GCDATAIN(u8 PROCNUM, u32 val) +{ + switch(operation) + { + case eSlot1Operation_Unknown: + client->slot1client_write_GCDATAIN(operation,val); + break; + } +} + +u32 Slot1Comp_Protocol::read_GCDATAIN(u8 PROCNUM) +{ + switch(operation) + { + case eSlot1Operation_00_ReadHeader_Unencrypted: + case eSlot1Operation_B7_Read: + return client->slot1client_read_GCDATAIN(operation); + + case eSlot1Operation_Unknown: + return client->slot1client_read_GCDATAIN(operation); + + case eSlot1Operation_90_ChipID: + case eSlot1Operation_1x_ChipID: + case eSlot1Operation_B8_ChipID: + // Note: the BIOS stores the chip ID in main memory + // Most games continuously compare the chip ID with + // the value in memory, probably to know if the card + // was removed. + // As DeSmuME normally boots directly from the game, the chip + // ID in main mem is zero and this value needs to be + // zero too. + + //staff of kings verifies this (it also uses the arm7 IRQ 20 to detect card ejects) + return chipId; + } + + return 0xFFFFFFFF; +} \ No newline at end of file diff --git a/desmume/src/addons/slot1comp_protocol.h b/desmume/src/addons/slot1comp_protocol.h new file mode 100644 index 000000000..06228a612 --- /dev/null +++ b/desmume/src/addons/slot1comp_protocol.h @@ -0,0 +1,105 @@ +/* + 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 . +*/ + +//this file contains the components used for emulating standard gamecard protocol. +//this largely means the complex boot-up process. +//i think there's no reason why proprietary cards couldn't speak any protocol they wish, as long as they didn't mind being unbootable. +//TODO - could this be refactored into a base class? that's probably more reasonable. but we've gone with this modular mix-in architecture so... not yet. + +#ifndef _SLOT1COMP_PROTOCOL_H +#define _SLOT1COMP_PROTOCOL_H + +#include "MMU.h" + +enum eSlot1Operation +{ + //---------- + //RAW mode operations + //before encrypted communications can be established, some values from the rom header must be read. + //this is the only way to read the header, actually, since the only reading commands available to games (after KEY2 mode is set) are + eSlot1Operation_00_ReadHeader_Unencrypted, + //it's not clear why this exists + eSlot1Operation_9F_Dummy, + eSlot1Operation_90_ChipID, + //---------- + + //---------- + //KEY2 mode operations + eSlot1Operation_1x_ChipID, + //---------- + + //---------- + //NORMAL mode operations + //the main rom data reading command + eSlot1Operation_B7_Read, + eSlot1Operation_B8_ChipID, + //---------- + + eSlot1Operation_Unknown +}; + +class ISlot1Comp_Protocol_Client +{ +public: + virtual void slot1client_write_GCDATAIN(eSlot1Operation operation, u32 val) { } + virtual u32 slot1client_read_GCDATAIN(eSlot1Operation operation) = 0; + virtual void slot1client_startOperation(eSlot1Operation operation) {} +}; + + +class Slot1Comp_Protocol +{ +public: + + //set some kind of protocol/hardware reset state + void reset(ISlot1Comp_Protocol_Client* client); + + //signals from the GC bus + void write_command(GC_Command command); + void write_GCDATAIN(u8 PROCNUM, u32 val); + u32 read_GCDATAIN(u8 PROCNUM); + + //helpers for write_command() + void write_command_RAW(GC_Command command); + void write_command_KEY1(GC_Command command); + void write_command_NORMAL(GC_Command command); + + //operations not related to obscurities of the protocol or otherwise unknown are passed through to the client here + ISlot1Comp_Protocol_Client* client; + + //the major operational mode. the protocol shifts modes and interprets commands into operations differently depending on the mode + eCardMode mode; + + //the current operational state + eSlot1Operation operation; + + //the command we're currently crunching on + GC_Command command; + + //most operations are defined in terms of returning a series of bytes + //the meaning of these varies by operation. they are provided publicly as a service to clients + u32 address; + s32 length, delay; //the expected length and delay of this state + + //chipId which should be returned by the various chipId commands + u32 chipId; + + //gameCode used by the protocol KEY1 crypto + u32 gameCode; +}; + +#endif //_SLOT1COMP_PROTOCOL_H \ No newline at end of file diff --git a/desmume/src/addons/slot1comp_rom.cpp b/desmume/src/addons/slot1comp_rom.cpp index 79e0d770e..d1523683b 100644 --- a/desmume/src/addons/slot1comp_rom.cpp +++ b/desmume/src/addons/slot1comp_rom.cpp @@ -15,3 +15,69 @@ along with the this software. If not, see . */ +#include "slot1comp_rom.h" +#include "MMU.h" +#include "NDSSystem.h" + + +void Slot1Comp_Rom::start(eSlot1Operation operation, u32 addr) +{ + this->operation = operation; + this->address = addr; +} + +u32 Slot1Comp_Rom::read() +{ + switch(operation) + { + case eSlot1Operation_00_ReadHeader_Unencrypted: + { + u32 ret = T1ReadLong(MMU.CART_ROM, address); + address = (address + 4) & 0xFFF; + return ret; + } + break; + + 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? + ////it seems that etrian odyssey 3 doesnt work unless we mask this to cart size. + ////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)); + + //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) + { + DEBUG_Notify.ReadBeyondEndOfCart(address,gameInfo.romsize); + return 0xFFFFFFFF; + } + + //actually read from the ROM provider + u32 ret = T1ReadLong(MMU.CART_ROM, 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); + + return ret; + } + break; + + default: + return 0; + + } //switch(operation) +} //Slot1Comp_Rom::read() diff --git a/desmume/src/addons/slot1comp_rom.h b/desmume/src/addons/slot1comp_rom.h index 711bac511..f1924a622 100644 --- a/desmume/src/addons/slot1comp_rom.h +++ b/desmume/src/addons/slot1comp_rom.h @@ -16,6 +16,18 @@ */ //this file contains the components used for emulating standard gamecard ROMs -//this is largely done by accessing the rom resource in the cor eemulator +//this is largely done by accessing the rom provided in the core emulator + +#include "slot1comp_protocol.h" + + +class Slot1Comp_Rom +{ +public: + void start(eSlot1Operation operation, u32 addr); + u32 read(); +private: + u32 address; + eSlot1Operation operation; +}; -//(TBD) \ No newline at end of file diff --git a/desmume/src/encrypt.cpp b/desmume/src/encrypt.cpp index e829d926a..ca43b2f1b 100644 --- a/desmume/src/encrypt.cpp +++ b/desmume/src/encrypt.cpp @@ -19,6 +19,11 @@ #include "MMU.h" #include "encrypt.h" +//TODO - a lot of redundant code (maybe?) with utils/decrypt.cpp +//we should try unifying all that. + +//TODO - endian unsafeness in here... dont like the way these take u32. maybe it makes sense and the user is genuinely supposed to present data in units of u32 + //================================================================================== KEY1 #define DWNUM(i) ((i) >> 2) diff --git a/desmume/src/encrypt.h b/desmume/src/encrypt.h index 87528c0a3..c191135c9 100644 --- a/desmume/src/encrypt.h +++ b/desmume/src/encrypt.h @@ -22,7 +22,7 @@ struct _KEY1 { - _KEY1(u8 *inKeyBufPtr) + _KEY1(const u8 *inKeyBufPtr) { if (keyBuf) delete keyBuf; keyBuf = new u32 [0x412]; @@ -42,7 +42,7 @@ struct _KEY1 u32 *keyBuf; u32 keyCode[3]; - u8 *keyBufPtr; + const u8 *keyBufPtr; void init(u32 idcode, u8 level, u8 modulo); void applyKeycode(u8 modulo); diff --git a/desmume/src/rtc.cpp b/desmume/src/rtc.cpp index 077d9b734..e98e397b2 100644 --- a/desmume/src/rtc.cpp +++ b/desmume/src/rtc.cpp @@ -241,8 +241,10 @@ void rtcInit() u16 rtcRead() { + //ZEROMUS HACK! MAKE SOMETHING PREDICTABLE FOR FIRMWARE BOOT TESTS! //INFO("MMU Read RTC 0x%02X (%03i)\n", rtc._REG, rtc.bitsCount); - return (rtc._REG); + //return (rtc._REG); + return 0; } void rtcWrite(u16 val) diff --git a/desmume/src/saves.cpp b/desmume/src/saves.cpp index b80891d1a..c27f9808a 100644 --- a/desmume/src/saves.cpp +++ b/desmume/src/saves.cpp @@ -242,10 +242,8 @@ SFORMAT SF_MMU[]={ { "BUWR", 4, 1, &MMU.fw.writeable_buffer}, //end memory chips - { "MC0A", 4, 1, &MMU.dscard[0].address}, - { "MC0T", 4, 1, &MMU.dscard[0].transfer_count}, - { "MC1A", 4, 1, &MMU.dscard[1].address}, - { "MC1T", 4, 1, &MMU.dscard[1].transfer_count}, + { "GCTC", 4, 1, &MMU.dscard.transfer_count}, + { "GCMO", 4, 1, &MMU.dscard.mode}, //{ "MCHT", 4, 1, &MMU.CheckTimers}, //{ "MCHD", 4, 1, &MMU.CheckDMAs}, diff --git a/desmume/src/slot1.cpp b/desmume/src/slot1.cpp index e06cd362f..bde8a8f76 100644 --- a/desmume/src/slot1.cpp +++ b/desmume/src/slot1.cpp @@ -24,6 +24,8 @@ Since GCROMCTRL[26:24] can't represent 'data block size' of 1 or 2, it is assume ...so, any 8/16bit accesses to GCDATAIN would transfer a whole 32bit unit and then just return the requested portion */ +//TODO - create a Slot1_TurboRom which we can select when booting from fakebios/nonfirmware and which would provide a useful service to people porting to tighter platforms by bypassing largely useless cruft + #include #include "types.h" @@ -74,7 +76,7 @@ EMUFILE* slot1_GetFatImage() //------------ -ISlot1Interface* slot1_List[NDS_SLOT1_COUNT]; +ISlot1Interface* slot1_List[NDS_SLOT1_COUNT] = {0}; ISlot1Interface* slot1_device = NULL; NDS_SLOT1_TYPE slot1_device_type = NDS_SLOT1_RETAIL_AUTO; //default for frontends that dont even configure this @@ -95,7 +97,7 @@ void slot1_Init() extern TISlot1InterfaceConstructor construct_Slot1_Retail_MCROM; slot1_List[NDS_SLOT1_NONE] = construct_Slot1_None(); 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_None(); //HACK!!! R4 IS BROKEN RIGHT NOW slot1_List[NDS_SLOT1_RETAIL_NAND] = construct_Slot1_Retail_NAND(); slot1_List[NDS_SLOT1_RETAIL_MCROM] = construct_Slot1_Retail_MCROM(); } @@ -104,7 +106,8 @@ void slot1_Shutdown() { for(int i=0;ishutdown(); + if(slot1_List[i]) + slot1_List[i]->shutdown(); delete slot1_List[i]; } } @@ -159,4 +162,119 @@ bool slot1_Change(NDS_SLOT1_TYPE changeToType) NDS_SLOT1_TYPE slot1_GetCurrentType() { return slot1_device_type; -} \ No newline at end of file +} + + + //// --- Ninja SD commands notes ------------------------------------- + // ///writetoGCControl: + + // // NJSD init/reset + // case 0x20: + // { + // card.address = 0; + // card.transfer_count = 0; + // } + // break; + + // // NJSD_sendCLK() + // case 0xE0: + // { + // card.address = 0; + // card.transfer_count = 0; + // NDS_makeInt(PROCNUM, 20); + // } + // break; + + // // NJSD_sendCMDN() / NJSD_sendCMDR() + // case 0xF0: + // case 0xF1: + // switch (card.command[2]) + // { + // // GO_IDLE_STATE + // case 0x40: + // card.address = 0; + // card.transfer_count = 0; + // NDS_makeInt(PROCNUM, 20); + // break; + + // case 0x42: // ALL_SEND_CID + // case 0x43: // SEND_RELATIVE_ADDR + // case 0x47: // SELECT_CARD + // case 0x49: // SEND_CSD + // case 0x4D: + // case 0x77: // APP_CMD + // case 0x69: // SD_APP_OP_COND + // card.address = 0; + // card.transfer_count = 6; + // NDS_makeInt(PROCNUM, 20); + // break; + + // // SET_BLOCKLEN + // case 0x50: + // card.address = 0; + // card.transfer_count = 6; + // card.blocklen = card.command[6] | (card.command[5] << 8) | (card.command[4] << 16) | (card.command[3] << 24); + // NDS_makeInt(PROCNUM, 20); + // break; + + // // READ_SINGLE_BLOCK + // case 0x51: + // card.address = card.command[6] | (card.command[5] << 8) | (card.command[4] << 16) | (card.command[3] << 24); + // card.transfer_count = (card.blocklen + 3) >> 2; + // NDS_makeInt(PROCNUM, 20); + // break; + // } + // break; + + // // --- Ninja SD commands end --------------------------------- + + + + // //GCDATAIN: + // // --- Ninja SD commands ------------------------------------- + + // // NJSD_sendCMDN() / NJSD_sendCMDR() + // case 0xF0: + // case 0xF1: + // switch (card.command[2]) + // { + // // ALL_SEND_CID + // case 0x42: + // if (card.transfer_count == 2) val = 0x44534A4E; + // else val = 0x00000000; + + // // SEND_RELATIVE_ADDR + // case 0x43: + // case 0x47: + // case 0x49: + // case 0x50: + // val = 0x00000000; + // break; + + // case 0x4D: + // if (card.transfer_count == 2) val = 0x09000000; + // else val = 0x00000000; + // break; + + // // APP_CMD + // case 0x77: + // if (card.transfer_count == 2) val = 0x00000037; + // else val = 0x00000000; + // break; + + // // SD_APP_OP_COND + // case 0x69: + // if (card.transfer_count == 2) val = 0x00008000; + // else val = 0x00000000; + // break; + + // // READ_SINGLE_BLOCK + // case 0x51: + // val = 0x00000000; + // break; + // } + // break; + + // // --- Ninja SD commands end --------------------------------- + + diff --git a/desmume/src/slot1.h b/desmume/src/slot1.h index 616e7d90f..fca367f78 100644 --- a/desmume/src/slot1.h +++ b/desmume/src/slot1.h @@ -22,6 +22,7 @@ #include "common.h" #include "types.h" #include "debug.h" +#include "MMU.h" class EMUFILE; @@ -64,15 +65,14 @@ public: //called when the emulator shuts down, or when the device disappears from existence virtual void shutdown() { } - //called when the emulator write to the slot (TODO - refactors necessary) - void write08(u8 PROCNUM, u32 adr, u8 val) { printf("WARNING: 8bit write to slot-1\n"); } - void write16(u8 PROCNUM, u32 adr, u16 val) { printf("WARNING: 16bit write to slot-1\n"); } - virtual void write32(u8 PROCNUM, u32 adr, u32 val) { } + //called then the cpu begins a new command/block on the GC bus + virtual void write_command(u8 PROCNUM, GC_Command command) { } - //called when the emulator reads from the slot (TODO - refactors necessary) - u8 read08(u8 PROCNUM, u32 adr) { printf("WARNING: 8bit read from slot-1\n"); return 0xFF; } - u16 read16(u8 PROCNUM, u32 adr) { printf("WARNING: 16bit read from slot-1\n"); return 0xFFFF; } - virtual u32 read32(u8 PROCNUM, u32 adr) { return 0xFFFFFFFF; } + //called when the cpu writes to the GC bus + virtual void write_GCDATAIN(u8 PROCNUM, u32 val) { } + + //called when the cpu reads from the GC bus + virtual u32 read_GCDATAIN(u8 PROCNUM) { return 0xFFFFFFFF; } //transfers a byte to the slot-1 device via auxspi, and returns the incoming byte //cpu is provided for diagnostic purposes only.. the slot-1 device wouldn't know which CPU it is. diff --git a/desmume/src/utils/decrypt/decrypt.cpp b/desmume/src/utils/decrypt/decrypt.cpp index ecc684278..8fa2ad90b 100644 --- a/desmume/src/utils/decrypt/decrypt.cpp +++ b/desmume/src/utils/decrypt/decrypt.cpp @@ -30,7 +30,8 @@ #include "header.h" #include "decrypt.h" -const unsigned char encr_data[] = +//encr_data +const unsigned char arm7_key[] = { 0x99,0xD5,0x20,0x5F,0x57,0x44,0xF5,0xB9,0x6E,0x19,0xA4,0xD9,0x9E,0x6A,0x5A,0x94, 0xD8,0xAE,0xF1,0xEB,0x41,0x75,0xE2,0x3A,0x93,0x82,0xD0,0x32,0x33,0xEE,0x31,0xD5, @@ -396,7 +397,7 @@ static void init2(u32 *magic, u32 a[3]) static void init1(u32 cardheader_gamecode) { - memcpy(card_hash, &encr_data, 4*(1024 + 18)); + memcpy(card_hash, &arm7_key, 4*(1024 + 18)); arg2[0] = *(u32 *)&cardheader_gamecode; arg2[1] = (*(u32 *)&cardheader_gamecode) >> 1; arg2[2] = (*(u32 *)&cardheader_gamecode) << 1; diff --git a/desmume/src/utils/decrypt/decrypt.h b/desmume/src/utils/decrypt/decrypt.h index 7909ee021..8180a6247 100644 --- a/desmume/src/utils/decrypt/decrypt.h +++ b/desmume/src/utils/decrypt/decrypt.h @@ -21,6 +21,8 @@ #ifndef _DECRYPT_H_ #define _DECRYPT_H_ +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); diff --git a/desmume/src/windows/DeSmuME_2005.vcproj b/desmume/src/windows/DeSmuME_2005.vcproj index 5dc5fcca0..ec0b8374f 100644 --- a/desmume/src/windows/DeSmuME_2005.vcproj +++ b/desmume/src/windows/DeSmuME_2005.vcproj @@ -2223,6 +2223,14 @@ RelativePath="..\addons\slot1comp_mc.h" > + + + + diff --git a/desmume/src/windows/DeSmuME_2008.vcproj b/desmume/src/windows/DeSmuME_2008.vcproj index b43eb6401..6577fc2b7 100644 --- a/desmume/src/windows/DeSmuME_2008.vcproj +++ b/desmume/src/windows/DeSmuME_2008.vcproj @@ -1029,6 +1029,14 @@ RelativePath="..\addons\slot1comp_mc.h" > + + + + diff --git a/desmume/src/windows/DeSmuME_2010.vcxproj b/desmume/src/windows/DeSmuME_2010.vcxproj index b8ace2dcd..9a858e32a 100644 --- a/desmume/src/windows/DeSmuME_2010.vcxproj +++ b/desmume/src/windows/DeSmuME_2010.vcxproj @@ -371,6 +371,7 @@ + @@ -653,6 +654,7 @@ + diff --git a/desmume/src/windows/DeSmuME_2010.vcxproj.filters b/desmume/src/windows/DeSmuME_2010.vcxproj.filters index df63bcdd2..cd415742a 100644 --- a/desmume/src/windows/DeSmuME_2010.vcxproj.filters +++ b/desmume/src/windows/DeSmuME_2010.vcxproj.filters @@ -795,6 +795,9 @@ Core\utils + + Core\addons + @@ -1533,6 +1536,9 @@ Core\utils + + Core\addons + diff --git a/desmume/src/windows/DeSmuME_2012.vcxproj b/desmume/src/windows/DeSmuME_2012.vcxproj index f90843e1c..ead696ed0 100644 --- a/desmume/src/windows/DeSmuME_2012.vcxproj +++ b/desmume/src/windows/DeSmuME_2012.vcxproj @@ -382,6 +382,7 @@ + @@ -664,6 +665,7 @@ + diff --git a/desmume/src/windows/DeSmuME_2012.vcxproj.filters b/desmume/src/windows/DeSmuME_2012.vcxproj.filters index 290e9931c..b8301ef9f 100644 --- a/desmume/src/windows/DeSmuME_2012.vcxproj.filters +++ b/desmume/src/windows/DeSmuME_2012.vcxproj.filters @@ -787,6 +787,9 @@ Core\utils + + Core\addons + @@ -1395,6 +1398,9 @@ Core\utils + + Core\addons + diff --git a/desmume/src/windows/main.cpp b/desmume/src/windows/main.cpp index f5bd26aa1..3e5ce8db7 100644 --- a/desmume/src/windows/main.cpp +++ b/desmume/src/windows/main.cpp @@ -3544,7 +3544,7 @@ int WINAPI WinMain (HINSTANCE hThisInstance, if (gShowConsole) { OpenConsole(); // Init debug console - ConsoleAlwaysTop(gConsoleTopmost); + //ConsoleAlwaysTop(gConsoleTopmost); } //-------------------------------- @@ -6082,7 +6082,7 @@ DOKEYDOWN: case IDM_CONSOLE_ALWAYS_ON_TOP: { gConsoleTopmost = !gConsoleTopmost; - ConsoleAlwaysTop(gConsoleTopmost); + //ConsoleAlwaysTop(gConsoleTopmost); WritePrivateProfileBool("Console", "Always On Top", gConsoleTopmost, IniName); } return 0;