From ef6daf9c10d66f28f533592ff12ba195fcc52d0b Mon Sep 17 00:00:00 2001 From: mtabachenko Date: Fri, 26 Jul 2013 01:31:58 +0000 Subject: [PATCH] core: - added part a new boot code (not finished yet and disabled by default). entry point ARM CPUs set to xxxx0000h and now booting a firmware from BIOS as on a real DS. all versions iQue and DS (patched with FlashME too) firmware works now, but can't run a games from firmware yet. --- desmume/src/MMU.cpp | 324 +++++++++++++++++++++------- desmume/src/MMU.h | 2 + desmume/src/NDSSystem.cpp | 62 +++++- desmume/src/NDSSystem.h | 109 ++++++---- desmume/src/addons/slot1_none.cpp | 4 + desmume/src/addons/slot1_retail.cpp | 95 +++++++- desmume/src/armcpu.cpp | 3 + desmume/src/armcpu.h | 16 ++ desmume/src/encrypt.cpp | 30 ++- desmume/src/encrypt.h | 19 +- desmume/src/firmware.cpp | 12 +- desmume/src/mc.cpp | 7 +- 12 files changed, 531 insertions(+), 152 deletions(-) diff --git a/desmume/src/MMU.cpp b/desmume/src/MMU.cpp index 5b66d0bbf..9f0d3fd36 100644 --- a/desmume/src/MMU.cpp +++ b/desmume/src/MMU.cpp @@ -40,12 +40,22 @@ #include "readwrite.h" #include "MMU_timing.h" +#ifdef _NEW_BOOT +#include "firmware.h" +#include "encrypt.h" +#endif + #ifdef DO_ASSERT_UNALIGNED #define ASSERT_UNALIGNED(x) assert(x) #else #define ASSERT_UNALIGNED(x) #endif +#ifdef _NEW_BOOT +_KEY1 key1(&MMU.ARM7_BIOS[0x0030]); +_KEY2 key2; +#endif + //http://home.utah.edu/~nahaj/factoring/isqrt.c.html static u64 isqrt (u64 x) { u64 squaredbit, remainder, root; @@ -1000,6 +1010,10 @@ void MMU_Reset() MMU.SPI_CNT = 0; MMU.AUX_SPI_CNT = 0; +#ifdef _NEW_BOOT + reconstruct(&key2); +#endif + MMU.WRAMCNT = 0; // Enable the sound speakers @@ -1274,95 +1288,243 @@ bool DSI_TSC::load_state(EMUFILE* is) return true; } +#ifdef _NEW_BOOT +//#define _LOG_NEW_BOOT 1 +#endif + template void FASTCALL MMU_writeToGCControl(u32 val) { - const int TEST_PROCNUM = PROCNUM; - nds_dscard& card = MMU.dscard[TEST_PROCNUM]; +#ifdef _NEW_BOOT +#ifdef _LOG_NEW_BOOT + extern bool dolog; + extern FILE *fp_dis9; + extern FILE *fp_dis7; - memcpy(&card.command[0], &MMU.MMU_MEM[TEST_PROCNUM][0x40][0x1A8], 8); + u32 oldCnt = T1ReadLong(MMU.MMU_MEM[PROCNUM][0x40], 0x1A4); +#endif +#endif + + + nds_dscard& card = MMU.dscard[PROCNUM]; + +#ifdef _NEW_BOOT + card.delay = 0; +#endif + + memcpy(&card.command[0], &MMU.MMU_MEM[PROCNUM][0x40][0x1A8], 8); card.blocklen = 0; + +#ifndef _NEW_BOOT slot1_device.write32(PROCNUM,0xFFFFFFFF,val); //Special case for some flashcarts if(card.blocklen==0x01020304) return; - if(!(val & 0x80000000)) + if ((val & 0x80000000) == 0) { card.address = 0; card.transfer_count = 0; val &= 0x7F7FFFFF; - T1WriteLong(MMU.MMU_MEM[TEST_PROCNUM][0x40], 0x1A4, val); + T1WriteLong(MMU.MMU_MEM[PROCNUM][0x40], 0x1A4, val); return; } +#else + if ((val & (1 << 15)) != 0) + { +#ifdef _LOG_NEW_BOOT + printf("--- ARM%c: cmd %02X (%016llX), ctrl %08X (%08X), delay %X/%X\n", PROCNUM?'7':'9', card.command[0], *(u64 *)&card.command[0], val, oldCnt, (val & 0x1FFF), ((val >> 16) & 0x3F)); + if (fp_dis7) + fprintf(fp_dis7, "--- ARM%c: KEY2 apply!!! ctrl %08X (PC:0x%08X)\n", PROCNUM?'7':'9', val, ARMPROC.instruct_adr); + printf("--- ARM%c: KEY2 apply!!! ctrl %08X (PC:0x%08X)\n", PROCNUM?'7':'9', val, ARMPROC.instruct_adr); +#endif + + key2.applySeed(PROCNUM); + } + + if ((val & 0x80000000) == 0) + { + card.address = 0; + card.transfer_count = 0; + val &= 0x7F7FFFFF; + T1WriteLong(MMU.MMU_MEM[PROCNUM][0x40], 0x1A4, val); + return; + } +#endif - u32 shift = (val>>24&7); + u32 shift = (val>>24&7); if(shift == 7) card.transfer_count = 1; else if(shift == 0) card.transfer_count = 0; else - card.transfer_count = (0x100<> 16) & 0x3F)); +#endif + +#endif + + if (card.mode == CardMode_Normal) { - case CardMode_Normal: - break; - - case CardMode_KEY1: + switch(card.command[0]) { - // TODO - INFO("Cartridge: KEY1 mode unsupported.\n"); + case 0x9F: //Dummy + card.address = 0; + card.transfer_count = 0x800; + break; + case 0x3C: //Switch to KEY1 mode +#ifdef _NEW_BOOT + { +#ifdef _LOG_NEW_BOOT + u32 chipID = MMU_read32(PROCNUM, 0x027FFE0C); + if (fp_dis7) + fprintf(fp_dis7, "ARM%c: Activate KEY1 encryption mode (id %08X)\n", PROCNUM?'7':'9', chipID); + printf("ARM%c: Activate KEY1 encryption mode (id %08X)\n", PROCNUM?'7':'9', chipID); +#endif + card.mode = CardMode_KEY1; + card.transfer_count = 0; + } +#else + printf("ARM%c: Activate unsupported KEY1 encryption mode\n", PROCNUM?'7':'9'); + card.mode = CardMode_KEY1; + card.transfer_count = 0; +#endif + break; + default: + //fall through to the special slot1 handler + slot1_device.write32(PROCNUM, REG_GCROMCTRL,val); + break; + } + } + else + if (card.mode == CardMode_KEY1 || card.mode == CardMode_KEY2) + { +#ifdef _NEW_BOOT + u32 chipID = MMU_read32(PROCNUM, 0x027FFE0C); + //u32 chipID = MMU_read32(PROCNUM, 0x037F8014); + u64 cmd = bswap64(*(u64 *)&card.command[0]); + + key1.init(chipID, 2, 0x08); + key1.decrypt((u32*)&cmd); + *(u64*)&card.command[0] = bswap64(cmd); + + switch (cmd >> 60) + { + case 0x02: // Get secure are block (4Kbytes) - 910h+11A8h + { + u32 size = ((cmd >> 44) & 0xFFFF) * (4 * 1024); + u32 addr = MMU_read32(PROCNUM, 0x0380FC00); +#ifdef _LOG_NEW_BOOT + if (fp_dis7) + fprintf(fp_dis7, "ARM%c: Get secure are block (4Kbytes)\n", PROCNUM?'7':'9'); + printf("ARM%c: Get secure are block (4Kbytes) src %08X size %04X\n", PROCNUM?'7':'9', addr, size); +#endif + + // TODO: check ChipID uppper bit + card.address = addr; + card.transfer_count = 0;//size / 4; + } + 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: // Invalid - get KEY2 stream XOR 00h - 910h+... + slot1_device.write32(PROCNUM, REG_GCROMCTRL, val); + break; + } +#else card.address = 0; card.transfer_count = 0; - - val &= 0x7F7FFFFF; - T1WriteLong(MMU.MMU_MEM[TEST_PROCNUM][0x40], 0x1A4, val); - return; + printf("ARM%c: Activate unsupported KEY2 encryption mode\n", PROCNUM?'7':'9'); + card.mode = CardMode_KEY2; + card.transfer_count = 0; +#endif } - break; - case CardMode_KEY2: - INFO("Cartridge: KEY2 mode unsupported.\n"); - break; - } + else + if (card.mode == CardMode_DATA_LOAD) + { +#ifdef _NEW_BOOT + u64 cmd = bswap64(*(u64 *)&card.command[0]); + *(u64*)&card.command[0] = bswap64(cmd); + slot1_device.write32(PROCNUM, REG_GCROMCTRL, val); +#else + INFO("Cartridge: KEY2 load data mode unsupported.\n"); + card.address = 0; + card.transfer_count = 0; +#endif + } - switch(card.command[0]) - { - case 0x9F: //Dummy - card.address = 0; - card.transfer_count = 0x800; - break; - - //case 0x90: //Get ROM chip ID - // break; - - case 0x3C: //Switch to KEY1 mode - card.mode = CardMode_KEY1; - break; - - default: - //fall through to the special slot1 handler - slot1_device.write32(TEST_PROCNUM, REG_GCROMCTRL,val); - break; - } - - if(card.transfer_count == 0) + if(card.delay == 0 && card.transfer_count == 0) { val &= 0x7F7FFFFF; - T1WriteLong(MMU.MMU_MEM[TEST_PROCNUM][0x40], 0x1A4, val); + T1WriteLong(MMU.MMU_MEM[PROCNUM][0x40], 0x1A4, val); +#ifdef _LOG_NEW_BOOT + if (fp_dis7) + fprintf(fp_dis7, "ARM%c: ctrl %08X - stop transfer !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n", PROCNUM?'7':'9', val); + printf("ARM%c: ctrl %08X - stop transfer !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n", PROCNUM?'7':'9', val); +#endif return; } - - val |= 0x00800000; - T1WriteLong(MMU.MMU_MEM[TEST_PROCNUM][0x40], 0x1A4, val); + + val |= 0x00800000; + T1WriteLong(MMU.MMU_MEM[PROCNUM][0x40], 0x1A4, val); // 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]; +#ifdef _NEW_BOOT + u32 val = T1ReadLong(MMU.MMU_MEM[PROCNUM][0x40], 0x1A4); + + if (card.delay > 0) + { + card.delay--; + if (card.delay == 0) + { + printf("ARM%c: delay stop\n", PROCNUM?'7':'9'); + val &= 0x7F7FFFFF; + T1WriteLong(MMU.MMU_MEM[PROCNUM][0x40], 0x1A4, val); + } + } + return val; +#else + card.delay = 0; + return T1ReadLong(MMU.MMU_MEM[PROCNUM][0x40], 0x1A4); +#endif + +} template u32 MMU_readFromGC() @@ -1375,7 +1537,11 @@ u32 MMU_readFromGC() if(card.transfer_count == 0) return 0; - switch(card.command[0]) + u8 cmd = card.command[0]; + if ((card.mode == CardMode_KEY1) || (card.mode == CardMode_KEY2)) + cmd >>= 4; + + switch(cmd) { case 0x9F: //Dummy val = 0xFFFFFFFF; @@ -2436,11 +2602,11 @@ static INLINE void write_auxspicnt(const int proc, const int size, const int adr case 8: switch(adr) { case 0: - T1WriteByte((u8*)&MMU.AUX_SPI_CNT,0,val); + T1WriteByte((u8*)&MMU.AUX_SPI_CNT, 0, val); if (val == 0) MMU_new.backupDevice.reset_command(); break; case 1: - T1WriteByte((u8*)&MMU.AUX_SPI_CNT,1,val); + T1WriteByte((u8*)&MMU.AUX_SPI_CNT, 1, val); break; } } @@ -2650,10 +2816,8 @@ void FASTCALL _MMU_ARM9_write08(u32 adr, u8 val) break; case REG_AUXSPICNT: - write_auxspicnt(9,8,0,val); - return; case REG_AUXSPICNT+1: - write_auxspicnt(9,8,1,val); + write_auxspicnt(9, 8, adr & 1, val); return; case REG_AUXSPIDATA: @@ -2709,7 +2873,6 @@ void FASTCALL _MMU_ARM9_write08(u32 adr, u8 val) case 0x040001AF : LOG("%08X : %02X\r\n", adr, val); #endif - } MMU.MMU_MEM[ARMCPU_ARM9][adr>>20][adr&MMU.MMU_MASK[ARMCPU_ARM9][adr>>20]]=val; @@ -3008,7 +3171,7 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val) } case REG_AUXSPICNT: - write_auxspicnt(9,16,0,val); + write_auxspicnt(9, 16, 0, val); return; case REG_AUXSPIDATA: @@ -4014,9 +4177,13 @@ void FASTCALL _MMU_ARM7_write08(u32 adr, u8 val) case REG_IF+3: REG_IF_WriteByte(3,val); break; case REG_POSTFLG: +#ifdef _LOG_NEW_BOOT + printf("ARM7: write POSTFLG %02X\n", val); +#endif //The NDS7 register can be written to only from code executed in BIOS. if (NDS_ARM7.instruct_adr > 0x3FFF) return; - + +#ifndef _NEW_BOOT // hack for patched firmwares if (val == 1) { @@ -4025,28 +4192,41 @@ void FASTCALL _MMU_ARM7_write08(u32 adr, u8 val) _MMU_write32(0x27FFE24, gameInfo.header.ARM9exe); _MMU_write32(0x27FFE34, gameInfo.header.ARM7exe); } +#endif break; case REG_HALTCNT: - //printf("halt 0x%02X\n", val); - switch(val) { - case 0xC0: NDS_Sleep(); break; - case 0x80: armcpu_Wait4IRQ(&NDS_ARM7); break; - default: break; + //printf("ARM7: Halt 0x%02X IME %02X, IE 0x%08X, IF 0x%08X PC 0x%08X\n", val, MMU.reg_IME[1], MMU.reg_IE[1], MMU.reg_IF_bits[1], NDS_ARM7.instruct_adr); + switch(val) + { + //case 0x10: printf("GBA mode unsupported\n"); break; + case 0xC0: NDS_Sleep(); break; + case 0x80: +#ifdef _NEW_BOOT + // FIXME: CrazyMax: HACK!!! for firmware boot form BIOS: + // i should study this and remove hack later + if (NDS_ARM7.instruct_adr == 0x00002F28 && + (MMU.reg_IE[1] & (1 << 19)) && + (MMU.reg_IF_bits[1] == 0)) + MMU.reg_IF_bits[1] |= (1 << 19); +#endif + armcpu_Wait4IRQ(&NDS_ARM7); + break; + default: break; + } + break; } - break; case REG_RTC: rtcWrite(val); return; case REG_AUXSPICNT: - write_auxspicnt(9,8,0,val); - return; case REG_AUXSPICNT+1: - write_auxspicnt(9,8,1,val); + write_auxspicnt(7, 8, adr & 1, val); return; + case REG_AUXSPIDATA: if(val!=0) MMU.AUX_SPI_CMD = val & 0xFF; T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, MMU_new.backupDevice.data_command((u8)val,ARMCPU_ARM7)); @@ -4054,8 +4234,8 @@ void FASTCALL _MMU_ARM7_write08(u32 adr, u8 val) return; case REG_SPIDATA: - // CrazyMax: 27 May 2013: BIOS write 8bit commands to flash controller - // (write firmware header into RAM at 0x027FF830) + // CrazyMax: 27 May 2013: BIOS write 8bit commands to flash controller when load firmware header + // into RAM at 0x027FF830 MMU_writeToSPIData(val); return; } @@ -4149,7 +4329,7 @@ void FASTCALL _MMU_ARM7_write16(u32 adr, u16 val) case REG_AUXSPICNT: - write_auxspicnt(7,16,0,val); + write_auxspicnt(7, 16, 0, val); return; case REG_AUXSPIDATA: @@ -4594,10 +4774,8 @@ u32 FASTCALL _MMU_ARM7_read32(u32 adr) return MMU.timer[ARMCPU_ARM7][(adr&0xF)>>2] | (val<<16); } case REG_GCROMCTRL: - { - //INFO("arm7 romctrl read\n"); - break; - } + return MMU_readFromGCControl(); + case REG_GCDATAIN: return MMU_readFromGC(); diff --git a/desmume/src/MMU.h b/desmume/src/MMU.h index 4c0212af3..06588f159 100644 --- a/desmume/src/MMU.h +++ b/desmume/src/MMU.h @@ -300,6 +300,7 @@ enum ECardMode CardMode_Normal = 0, CardMode_KEY1, CardMode_KEY2, + CardMode_DATA_LOAD }; typedef struct @@ -309,6 +310,7 @@ typedef struct u32 address; u32 transfer_count; + u32 delay; ECardMode mode; diff --git a/desmume/src/NDSSystem.cpp b/desmume/src/NDSSystem.cpp index 620f81536..fb88572c7 100644 --- a/desmume/src/NDSSystem.cpp +++ b/desmume/src/NDSSystem.cpp @@ -439,7 +439,6 @@ static std::vector buffer; static std::vector v; static void loadrom(std::string fname) { - FILE* inf = fopen(fname.c_str(),"rb"); if(!inf) return; @@ -448,7 +447,15 @@ static void loadrom(std::string fname) { fseek(inf,0,SEEK_SET); gameInfo.resize(size); - fread(gameInfo.romdata,1,size,inf); + +#ifdef _NEW_BOOT + extern NDS_SLOT1_TYPE slot1_device_type; + + if (slot1_device_type == NDS_SLOT1_NONE) + memset(gameInfo.romdata, 0xFF, size); + else +#endif + fread(gameInfo.romdata,1,size,inf); gameInfo.fillGap(); fclose(inf); @@ -566,6 +573,7 @@ int NDS_LoadROM(const char *filename, const char *physicalName, const char *logi if (ret < 1) return ret; +#ifndef _NEW_BOOT //decrypt if necessary.. //but this is untested and suspected to fail on big endian, so lets not support this on big endian #ifndef WORDS_BIGENDIAN @@ -575,6 +583,7 @@ int NDS_LoadROM(const char *filename, const char *physicalName, const char *logi printf("Specified file is not a valid rom\n"); return -1; } +#endif #endif if (cheatSearch) @@ -591,6 +600,10 @@ int NDS_LoadROM(const char *filename, const char *physicalName, const char *logi INFO("ROM serial: %s\n", gameInfo.ROMserial); INFO("ROM internal name: %s\n", gameInfo.ROMname); INFO("ROM developer: %s\n", getDeveloperNameByID(gameInfo.header.makerCode).c_str()); + +#ifdef _NEW_BOOT + gameInfo.storeSecureArea(); +#endif memset(buf, 0, MAX_PATH); strcpy(buf, path.pathToModule); @@ -1156,10 +1169,11 @@ template struct TSequenceItem_Timer : public TSequenceItem { IF_DEVELOPER(DEBUG_statistics.sequencerExecutionCounters[13+procnum*4+num]++); u8* regs = procnum==0?MMU.ARM9_REG:MMU.ARM7_REG; - bool first = true, over; + bool first = true; //we'll need to check chained timers.. for(int i=num;i<4;i++) { + bool over = false; //maybe too many checks if this is here, but we need it here for now if(!MMU.timerON[procnum][i]) return; @@ -2478,12 +2492,14 @@ void NDS_Reset() PrepareLogfiles(); +#ifndef _NEW_BOOT //according to smea, this is initialized to 3 by the time we get into a user game program. who does this? //well, the firmware load process is about to write a boot program into SIWRAM for the arm7. so we need it setup by now. //but, this is a bit weird.. I would be expecting the bioses to do that. maybe we have some more detail to emulate. //* is this setting the default, or does the bios do it before loading the firmware programs? //at any, it's important that this be done long before the user code ever runs _MMU_write08(REG_WRAMCNT,3); +#endif if (firmware) { @@ -2495,6 +2511,12 @@ void NDS_Reset() if (NDS_ARM7.BIOS_loaded && NDS_ARM9.BIOS_loaded && CommonSettings.BootFromFirmware && fw_success) { +#ifdef _NEW_BOOT + gameInfo.restoreSecureArea(); + + armcpu_init(&NDS_ARM7, 0x00000000); + armcpu_init(&NDS_ARM9, 0xFFFF0000); +#else //Copy secure area to memory if needed. //could we get a comment about what's going on here? //how does this stuff get copied before anything ever even runs? @@ -2526,6 +2548,7 @@ void NDS_Reset() armcpu_init(&NDS_ARM7, firmware->ARM7bootAddr); armcpu_init(&NDS_ARM9, firmware->ARM9bootAddr); } +#endif //set REG_POSTFLG to the value indicating pre-firmware status MMU.ARM9_REG[0x300] = 0; @@ -2535,6 +2558,20 @@ void NDS_Reset() { //fake firmware boot-up process +#ifdef _NEW_BOOT + gameInfo.restoreSecureArea(); + //decrypt if necessary.. + //but this is untested and suspected to fail on big endian, so lets not support this on big endian +#ifndef WORDS_BIGENDIAN + bool okRom = DecryptSecureArea((u8*)gameInfo.romdata,gameInfo.romsize); + + if(!okRom) { + printf("Specified file is not a valid rom\n"); + return; + } +#endif +#endif + // Create the dummy firmware NDS_CreateDummyFirmware(&CommonSettings.fw_config); @@ -2571,6 +2608,7 @@ void NDS_Reset() reconstruct(&cp15); cp15.reset(&NDS_ARM9); +#ifndef _NEW_BOOT //bitbox 4k demo is so stripped down it relies on default stack values //otherwise the arm7 will crash before making a sound //(these according to gbatek softreset bios docs) @@ -2588,6 +2626,7 @@ void NDS_Reset() NDS_ARM9.R[13] = NDS_ARM9.R13_usr; //n.b.: im not sure about all these, I dont know enough about arm9 svc/irq/etc modes //and how theyre named in desmume to match them up correctly. i just guessed. +#endif nds.wifiCycle = 0; memset(nds.timerCycle, 0, sizeof(u64) * 2 * 4); @@ -2603,15 +2642,18 @@ void NDS_Reset() nds.ensataIpcSyncCounter = 0; SetupMMU(nds.Is_DebugConsole(),nds.Is_DSI()); +#ifndef _NEW_BOOT _MMU_write16(REG_KEYINPUT, 0x3FF); _MMU_write16(REG_KEYINPUT, 0x3FF); _MMU_write08(REG_EXTKEYIN, 0x43); +#endif LidClosed = FALSE; countLid = 0; resetUserInput(); +#ifndef _NEW_BOOT //Setup a copy of the firmware user settings in memory. //(this is what the DS firmware would do). { @@ -2638,7 +2680,6 @@ void NDS_Reset() _MMU_write32(0x027FFE00+i*4, LE_TO_LOCAL_32(((u32*)MMU.CART_ROM)[i])); } - //-------------------------------- //setup the homebrew argv //this is useful for nitrofs apps which are emulating themselves via cflash @@ -2685,6 +2726,17 @@ void NDS_Reset() TSCal.adc.y2 = _MMU_read16(0x027FFC80 + 0x60); TSCal.scr.x2 = _MMU_read08(0x027FFC80 + 0x62); TSCal.scr.y2 = _MMU_read08(0x027FFC80 + 0x63); +#else + // TODO: hack!!! + TSCal.adc.x1 = 0x0228; + TSCal.adc.y1 = 0x0350; + TSCal.scr.x1 = 0x0020; + TSCal.scr.y1 = 0x0020; + TSCal.adc.x2 = 0x0DA0; + TSCal.adc.y2 = 0x0BFC; + TSCal.scr.x2 = 0xE0; + TSCal.scr.y2 = 0xA0; +#endif TSCal.adc.width = (TSCal.adc.x2 - TSCal.adc.x1); TSCal.adc.height = (TSCal.adc.y2 - TSCal.adc.y1); @@ -2694,7 +2746,9 @@ void NDS_Reset() MainScreen.offset = 0; SubScreen.offset = 192; +#ifndef _NEW_BOOT //_MMU_write32[ARMCPU_ARM9](0x02007FFC, 0xE92D4030); +#endif delete header; diff --git a/desmume/src/NDSSystem.h b/desmume/src/NDSSystem.h index 8d74ef445..1ecb480e4 100644 --- a/desmume/src/NDSSystem.h +++ b/desmume/src/NDSSystem.h @@ -83,6 +83,7 @@ extern BOOL click; #define NDS_FW_LANG_CHI 6 #define NDS_FW_LANG_RES 7 +extern CFIRMWARE *firmware; //#define LOG_ARM9 //#define LOG_ARM7 @@ -90,55 +91,55 @@ extern BOOL click; #include "PACKED.h" struct NDS_header { - char gameTile[12]; - char gameCode[4]; - u16 makerCode; - u8 unitCode; - u8 deviceCode; - u8 cardSize; - u8 cardInfo[8]; - u8 flags; - u8 romversion; - u8 reserved; + char gameTile[12]; // 000 - Game Title (uppercase ASCII, padded with 00h) + char gameCode[4]; // 00C - Gamecode (uppercase ASCII, NTR-, 0=homebrew) + u16 makerCode; // 010 - Makercode (uppercase ASCII, 0=homebrew) + 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 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) + u32 ARM9src; // 020 - + u32 ARM9exe; // 024 - + u32 ARM9cpy; // 028 - + u32 ARM9binSize; // 02C - + + u32 ARM7src; // 030 - + u32 ARM7exe; // 034 - + u32 ARM7cpy; // 038 - + u32 ARM7binSize; // 03C - + + u32 FNameTblOff; // 040 - + u32 FNameTblSize; // 044 - - u32 ARM9src; - u32 ARM9exe; - u32 ARM9cpy; - u32 ARM9binSize; + u32 FATOff; // 048 - + u32 FATSize; // 04C - - u32 ARM7src; - u32 ARM7exe; - u32 ARM7cpy; - u32 ARM7binSize; - - u32 FNameTblOff; - u32 FNameTblSize; - - u32 FATOff; - u32 FATSize; - - u32 ARM9OverlayOff; - u32 ARM9OverlaySize; - u32 ARM7OverlayOff; - u32 ARM7OverlaySize; - - u32 unknown2a; - u32 unknown2b; - - u32 IconOff; - u16 CRC16; - u16 ROMtimeout; - u32 ARM9unk; - u32 ARM7unk; - - u8 unknown3c[8]; - u32 ROMSize; - u32 HeaderSize; - u8 unknown5[56]; //"PASS" is contained within here? - u8 logo[156]; - u16 logoCRC16; - u16 headerCRC16; - u8 unknown6[160]; + u32 ARM9OverlayOff; // 050 - + u32 ARM9OverlaySize; // 054 - + u32 ARM7OverlayOff; // 058 - + u32 ARM7OverlaySize; // 05C - + + u32 unknown2a; // 060 - Port 40001A4h setting for normal commands (usually 00586000h) + u32 unknown2b; // 064 - Port 40001A4h setting for KEY1 commands (usually 001808F8h) + + u32 IconOff; // 068 - + u16 CRC16; // 06C - + u16 ROMtimeout; // 06E - + u32 ARM9unk; // 070 - + u32 ARM7unk; // 074 - + + u8 unknown3c[8]; // 078 - Secure Area Disable (by encrypted "NmMdOnly") (usually zero) + u32 ROMSize; // 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? + 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]; // }; #include "PACKED_END.h" @@ -325,6 +326,7 @@ struct GameInfo memset(&header, 0, sizeof(header)); memset(&ROMserial[0], 0, sizeof(ROMserial)); memset(&ROMname[0], 0, sizeof(ROMname)); + memset(&securyArea[0], 0, sizeof(securyArea)); } void loadData(char* buf, int size) @@ -335,6 +337,18 @@ struct GameInfo fillGap(); } + void storeSecureArea() + { + if ((header.ARM9src >= 0x4000) && (header.ARM9src < 0x8000)) + memcpy(&securyArea[0], &romdata[header.ARM9src], 0x8000 - header.ARM9src); + } + + void restoreSecureArea() + { + if ((header.ARM9src >= 0x4000) && (header.ARM9src < 0x8000)) + memcpy(&romdata[header.ARM9src], &securyArea[0], 0x8000 - header.ARM9src); + } + void fillGap() { memset(romdata+romsize,0xFF,allocatedSize-romsize); @@ -371,6 +385,7 @@ struct GameInfo const RomBanner& getRomBanner(); bool hasRomBanner(); bool isHomebrew; + u8 securyArea[0x4000]; }; typedef struct TSCalInfo diff --git a/desmume/src/addons/slot1_none.cpp b/desmume/src/addons/slot1_none.cpp index 004c34dba..01221b21d 100644 --- a/desmume/src/addons/slot1_none.cpp +++ b/desmume/src/addons/slot1_none.cpp @@ -18,6 +18,7 @@ #include "../slot1.h" #include "../registers.h" #include "../MMU.h" +#include "../NDSSystem.h" static void slot1_info(char *info) { strcpy(info, "Slot1 no-card emulation"); } static void slot1_config(void) {} @@ -27,6 +28,9 @@ static BOOL slot1_init() { return (TRUE); } static void slot1_reset() { // Write the header checksum to memory (the firmware needs it to see the cart) +#ifdef _NEW_BOOT + if (!CommonSettings.BootFromFirmware) +#endif _MMU_write16(0x027FF808, 0); } diff --git a/desmume/src/addons/slot1_retail.cpp b/desmume/src/addons/slot1_retail.cpp index 9c462144c..4649a9e73 100644 --- a/desmume/src/addons/slot1_retail.cpp +++ b/desmume/src/addons/slot1_retail.cpp @@ -28,6 +28,9 @@ static BOOL init() { return (TRUE); } static void reset() { // Write the header checksum to memory (the firmware needs it to see the cart) +#ifdef _NEW_BOOT + if (!CommonSettings.BootFromFirmware) +#endif _MMU_write16(0x027FF808, T1ReadWord(MMU.CART_ROM, 0x15E)); } @@ -43,21 +46,72 @@ static void write32_GCROMCTRL(u8 PROCNUM, u32 val) switch(card.command[0]) { - case 0x00: //Data read + 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 = 0x80; break; - case 0xB8: // Chip ID + case 0x90: // 1st Get ROM Chip ID - len 4 bytes + card.address = 0; + card.transfer_count = 1; + break; + + case 0xB8: // 3rd Get ROM Chip ID - len 4 bytes card.address = 0; card.transfer_count = 1; break; default: + 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 = 1; + break; + + default: + card.address = 0; + card.transfer_count = 0; + printf("ARM%c: SLOT1 invalid command %02X (write) - CardMode_KEY1/CardMode_KEY2 mode\n", PROCNUM?'7':'9', cmd); + break; + } + return; + } + + if (card.mode == CardMode_DATA_LOAD) + { + switch(card.command[0]) + { + case 0xB7: + card.address = (card.command[1] << 24) | (card.command[2] << 16) | (card.command[3] << 8) | card.command[4]; + card.transfer_count = 0x80; + break; + + case 0xB8: // 3nd Get ROM Chip ID - len 4 bytes + card.address = 0; + card.transfer_count = 1; + break; + + default: + card.address = 0; + card.transfer_count = 0; + printf("ARM%c: SLOT1 invalid command %02X (write) - CardMode_DATA_LOAD mode\n", PROCNUM?'7':'9', card.command[0]); + break; + } + return; + } + card.address = 0; card.transfer_count = 0; - break; +#ifdef _NEW_BOOT + printf("ARM%c: SLOT1 invalid command %02X (write)\n", PROCNUM?'7':'9', card.command[0]); +#endif + + break; } } @@ -83,13 +137,32 @@ static u16 read16(u8 PROCNUM, u32 adr) static u32 read32_GCDATAIN(u8 PROCNUM) { nds_dscard& card = MMU.dscard[PROCNUM]; + u8 cmd = card.command[0]; - switch(card.command[0]) + if (card.mode == CardMode_KEY1 || card.mode == CardMode_KEY2) + cmd >>= 4; + + switch(cmd) { - //Get ROM chip ID - case 0x90: - case 0xB8: + 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 { + // Returns RAW unencrypted Chip ID (eg. C2h,0Fh,00h,00h), repeated every 4 bytes. + // + // 1st byte - Manufacturer (C2h = Macronix) + // 2nd byte - Chip size in megabytes minus 1 (eg. 0Fh = 16MB) + // 3rd byte - Reserved/zero (probably upper bits of chip size) + // 4th byte - Bit7: Secure Area Block transfer mode (8x200h or 1000h) + +#ifdef _NEW_BOOT + u32 chipID = 0; + if (CommonSettings.BootFromFirmware) + chipID = 0x00000000 | 0x00000000 | 0x00000F00 | 0x000000C2;; +#else + u32 chipID = 0; +#endif + // 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 @@ -104,7 +177,8 @@ static u32 read32_GCDATAIN(u8 PROCNUM) //staff of kings verifies this (it also uses the arm7 IRQ 20) if(nds.cardEjected) //TODO - handle this with ejected card slot1 device (and verify using this case) return 0xFFFFFFFF; - else return 0; + else + return chipID; } break; @@ -119,7 +193,7 @@ static u32 read32_GCDATAIN(u8 PROCNUM) u32 address = card.address & (gameInfo.mask); // Make sure any reads below 0x8000 redirect to 0x8000+(adr&0x1FF) as on real cart - if((card.command[0] == 0xB7) && (address < 0x8000)) + if((cmd == 0xB7) && (address < 0x8000)) { //TODO - refactor this to include the PROCNUM, for debugging purposes if nothing else //(can refactor gbaslot also) @@ -142,6 +216,9 @@ static u32 read32_GCDATAIN(u8 PROCNUM) } break; default: +#ifdef _NEW_BOOT + printf("ARM%c: SLOT1 invalid command %02X (read)\n", PROCNUM?'7':'9', cmd); +#endif return 0; } //switch(card.command[0]) } //read32_GCDATAIN diff --git a/desmume/src/armcpu.cpp b/desmume/src/armcpu.cpp index 7d0ba3315..d3244dacc 100644 --- a/desmume/src/armcpu.cpp +++ b/desmume/src/armcpu.cpp @@ -667,11 +667,14 @@ void arm_jit_sync() template u32 armcpu_exec() { + // TODO: CrazyMax - temporarily disable JIT until finish a new boot code +#ifndef _NEW_BOOT if (jit) { ArmOpCompiled f = (ArmOpCompiled)JIT_COMPILED_FUNC(ARMPROC.instruct_adr, PROCNUM); return f ? f() : arm_jit_compile(); } +#endif return armcpu_exec(); } diff --git a/desmume/src/armcpu.h b/desmume/src/armcpu.h index 3aff73949..f23bc0853 100644 --- a/desmume/src/armcpu.h +++ b/desmume/src/armcpu.h @@ -55,6 +55,22 @@ inline T SIGNED_OVERFLOW(T a,T b,T c) { return BIT31(((a)&(b)&(~c)) | ((~a)&(~(b template inline T SIGNED_UNDERFLOW(T a,T b,T c) { return BIT31(((a)&(~(b))&(~c)) | ((~a)&(b)&(c))); } +#define bswap32(val) \ + ( (val << 24) & 0xFF000000) | \ + ( (val << 8) & 0x00FF0000) | \ + ( (val >> 8) & 0x0000FF00) | \ + ( (val >> 24) & 0x000000FF) + +#define bswap64(x) \ + ( (x << 56) & 0xff00000000000000UL ) | \ + ( (x << 40) & 0x00ff000000000000UL ) | \ + ( (x << 24) & 0x0000ff0000000000UL ) | \ + ( (x << 8) & 0x000000ff00000000UL ) | \ + ( (x >> 8) & 0x00000000ff000000UL ) | \ + ( (x >> 24) & 0x0000000000ff0000UL ) | \ + ( (x >> 40) & 0x000000000000ff00UL ) | \ + ( (x >> 56) & 0x00000000000000ffUL ) + // ============================= CPRS flags funcs inline bool CarryFrom(s32 left, s32 right) { diff --git a/desmume/src/encrypt.cpp b/desmume/src/encrypt.cpp index bbee6ff08..e829d926a 100644 --- a/desmume/src/encrypt.cpp +++ b/desmume/src/encrypt.cpp @@ -15,11 +15,11 @@ along with the this software. If not, see . */ -#include "encrypt.h" +#include "armcpu.h" #include "MMU.h" +#include "encrypt.h" //================================================================================== KEY1 -#define bswap32(val) (((val & 0x000000FF) << 24) | ((val & 0x0000FF00) << 8) | ((val & 0x00FF0000) >> 8) | ((val & 0xFF000000) >> 24)) #define DWNUM(i) ((i) >> 2) void _KEY1::init(u32 idcode, u8 level, u8 modulo) @@ -36,8 +36,6 @@ void _KEY1::init(u32 idcode, u8 level, u8 modulo) keyCode[2] >>= 1; if (level >= 3) // third apply (optional) applyKeycode(modulo); - - printf("keycode1: %08X%08X%08X\n", keyCode[2], keyCode[1], keyCode[0]); } void _KEY1::applyKeycode(u8 modulo) @@ -97,15 +95,33 @@ void _KEY1::encrypt(u32 *ptr) ptr[1] = y ^ keyBuf[DWNUM(0x44)]; } #undef DWNUM -#undef bswap32 //================================================================================== KEY2 +u64 _KEY2::bitsReverse39(u64 key) +{ + u64 tmp = 0; + for (u32 i = 0; i < 39; i++) + tmp |= ((key >> i) & 1) << (38 - i); + + return tmp; +} + void _KEY2::applySeed(u8 PROCNUM) { u64 tmp = (MMU_read8(PROCNUM, REG_ENCSEED0H) & 0xFF); seed0 = MMU_read32(PROCNUM, REG_ENCSEED0L) | (tmp << 32); tmp = (MMU_read8(PROCNUM, REG_ENCSEED1H) & 0xFF); seed1 = MMU_read32(PROCNUM, REG_ENCSEED1L) | (tmp << 32); - printf("ARM%c: set KEY2 seed0 to %010llX\n", PROCNUM?'7':'9', seed0); - printf("ARM%c: set KEY2 seed1 to %010llX\n", PROCNUM?'7':'9', seed1); + x = bitsReverse39(seed0); + y = bitsReverse39(seed1); + + //printf("ARM%c: set KEY2 seed0 to %010llX (reverse %010llX)\n", PROCNUM?'7':'9', seed0, x); + //printf("ARM%c: set KEY2 seed1 to %010llX (reverse %010llX)\n", PROCNUM?'7':'9', seed1, y); +} + +u8 _KEY2::apply(u8 data) +{ + x = (((x >> 5) ^ (x >> 17) ^ (x >> 18) ^ (x >> 31)) & 0xFF) + (x << 8); + y = (((y >> 5) ^ (y >> 23) ^ (y >> 18) ^ (y >> 31)) & 0xFF) + (y << 8); + return ((data ^ x ^ y) & 0xFF); } diff --git a/desmume/src/encrypt.h b/desmume/src/encrypt.h index 7d047ce66..87528c0a3 100644 --- a/desmume/src/encrypt.h +++ b/desmume/src/encrypt.h @@ -25,8 +25,8 @@ struct _KEY1 _KEY1(u8 *inKeyBufPtr) { if (keyBuf) delete keyBuf; - keyBuf = new u32 [0x1048 / sizeof(u32)]; - memset(keyBuf, 0x00, 0x1048); + keyBuf = new u32 [0x412]; + memset(keyBuf, 0x00, 0x412 * sizeof(u32)); memset(&keyCode[0], 0, sizeof(keyCode)); this->keyBufPtr = inKeyBufPtr; } @@ -52,14 +52,21 @@ struct _KEY1 struct _KEY2 { - _KEY2() : seed0(0x58C56DE0E8ULL), - seed1(0x5C879B9B05ULL) - {} - +private: u64 seed0; u64 seed1; + u64 x; + u64 y; + u64 bitsReverse39(u64 key); + +public: + _KEY2() : seed0(0x58C56DE0E8ULL), + seed1(0x5C879B9B05ULL) + {} + void applySeed(u8 PROCNUM); + u8 apply(u8 data); }; #endif \ No newline at end of file diff --git a/desmume/src/firmware.cpp b/desmume/src/firmware.cpp index 71d43af8d..3bae6205d 100644 --- a/desmume/src/firmware.cpp +++ b/desmume/src/firmware.cpp @@ -253,13 +253,13 @@ bool CFIRMWARE::load() fseek(fp, 0, SEEK_END); size = ftell(fp); fseek(fp, 0, SEEK_SET); - if( (size != 256*1024) && (size != 512*1024) ) + if( (size != NDS_FW_SIZE_V1) && (size != NDS_FW_SIZE_V2) ) { fclose(fp); return false; } -#if 1 +#ifndef _NEW_BOOT if (size == 512*1024) { INFO("ERROR: 32Mbit (512Kb) firmware not supported\n"); @@ -278,6 +278,7 @@ bool CFIRMWARE::load() if (fread(data, 1, size, fp) != size) { delete [] data; + data = NULL; fclose(fp); return false; } @@ -294,8 +295,12 @@ bool CFIRMWARE::load() #ifdef _NEW_BOOT if (CommonSettings.BootFromFirmware) { + if (MMU.fw.size != size) // reallocate + mc_alloc(&MMU.fw, size); + memcpy(MMU.fw.data, data, size); - MMU.fw.size = size; + delete [] data; + data = NULL; return true; } #endif @@ -475,6 +480,7 @@ bool CFIRMWARE::load() strncpy(MMU.fw.userfile, extFilePath.c_str(), MAX_PATH); fclose(fp); + fp = fopen(MMU.fw.userfile, "rb"); if (fp) { diff --git a/desmume/src/mc.cpp b/desmume/src/mc.cpp index b0dc200c8..f5f8c4965 100644 --- a/desmume/src/mc.cpp +++ b/desmume/src/mc.cpp @@ -147,13 +147,13 @@ void mc_init(memory_chip_t *mc, int type) u8 *mc_alloc(memory_chip_t *mc, u32 size) { - u8 *buffer; + u8 *buffer = NULL; buffer = new u8[size]; + if(!buffer) { return NULL; } memset(buffer,0,size); if (mc->data) delete [] mc->data; mc->data = buffer; - if(!buffer) { return NULL; } mc->size = size; mc->writeable_buffer = TRUE; @@ -176,6 +176,7 @@ void fw_reset_com(memory_chip_t *mc) fwrite(mc->data, mc->size, 1, mc->fp); } +#ifndef _NEW_BOOT if (mc->isFirmware&&CommonSettings.UseExtFirmware) { // copy User Settings 1 to User Settings 0 area @@ -200,7 +201,7 @@ void fw_reset_com(memory_chip_t *mc) else printf(" - failed\n"); } - +#endif mc->write_enable = FALSE; }