diff --git a/src/DSi.cpp b/src/DSi.cpp index b7056614..2f272e97 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -349,6 +349,12 @@ bool LoadNAND() { printf("Loading DSi NAND\n"); + if (!DSi_NAND::Init(SDMMCFile, &DSi::ARM7iBIOS[0x8308])) + { + printf("Failed to load DSi NAND\n"); + return false; + } + // Make sure NWRAM is accessible. // The Bits are set to the startup values in Reset() and we might // still have them on default (0) or some bits cleared by the previous @@ -368,155 +374,130 @@ bool LoadNAND() memset(NWRAMEnd, 0, sizeof(NWRAMEnd)); memset(NWRAMMask, 0, sizeof(NWRAMMask)); - if (SDMMCFile) + u32 bootparams[8]; + fseek(SDMMCFile, 0x220, SEEK_SET); + fread(bootparams, 4, 8, SDMMCFile); + + printf("ARM9: offset=%08X size=%08X RAM=%08X size_aligned=%08X\n", + bootparams[0], bootparams[1], bootparams[2], bootparams[3]); + printf("ARM7: offset=%08X size=%08X RAM=%08X size_aligned=%08X\n", + bootparams[4], bootparams[5], bootparams[6], bootparams[7]); + + // read and apply new-WRAM settings + + MBK[0][8] = 0; + MBK[1][8] = 0; + + u32 mbk[12]; + fseek(SDMMCFile, 0x380, SEEK_SET); + fread(mbk, 4, 12, SDMMCFile); + + MapNWRAM_A(0, mbk[0] & 0xFF); + MapNWRAM_A(1, (mbk[0] >> 8) & 0xFF); + MapNWRAM_A(2, (mbk[0] >> 16) & 0xFF); + MapNWRAM_A(3, mbk[0] >> 24); + + MapNWRAM_B(0, mbk[1] & 0xFF); + MapNWRAM_B(1, (mbk[1] >> 8) & 0xFF); + MapNWRAM_B(2, (mbk[1] >> 16) & 0xFF); + MapNWRAM_B(3, mbk[1] >> 24); + MapNWRAM_B(4, mbk[2] & 0xFF); + MapNWRAM_B(5, (mbk[2] >> 8) & 0xFF); + MapNWRAM_B(6, (mbk[2] >> 16) & 0xFF); + MapNWRAM_B(7, mbk[2] >> 24); + + MapNWRAM_C(0, mbk[3] & 0xFF); + MapNWRAM_C(1, (mbk[3] >> 8) & 0xFF); + MapNWRAM_C(2, (mbk[3] >> 16) & 0xFF); + MapNWRAM_C(3, mbk[3] >> 24); + MapNWRAM_C(4, mbk[4] & 0xFF); + MapNWRAM_C(5, (mbk[4] >> 8) & 0xFF); + MapNWRAM_C(6, (mbk[4] >> 16) & 0xFF); + MapNWRAM_C(7, mbk[4] >> 24); + + MapNWRAMRange(0, 0, mbk[5]); + MapNWRAMRange(0, 1, mbk[6]); + MapNWRAMRange(0, 2, mbk[7]); + + MapNWRAMRange(1, 0, mbk[8]); + MapNWRAMRange(1, 1, mbk[9]); + MapNWRAMRange(1, 2, mbk[10]); + + // TODO: find out why it is 0xFF000000 + mbk[11] &= 0x00FFFF0F; + MBK[0][8] = mbk[11]; + MBK[1][8] = mbk[11]; + + // load boot2 binaries + + AES_ctx ctx; + const u8 boot2key[16] = {0xAD, 0x34, 0xEC, 0xF9, 0x62, 0x6E, 0xC2, 0x3A, 0xF6, 0xB4, 0x6C, 0x00, 0x80, 0x80, 0xEE, 0x98}; + u8 boot2iv[16]; + u8 tmp[16]; + u32 dstaddr; + + *(u32*)&tmp[0] = bootparams[3]; + *(u32*)&tmp[4] = -bootparams[3]; + *(u32*)&tmp[8] = ~bootparams[3]; + *(u32*)&tmp[12] = 0; + for (int i = 0; i < 16; i++) boot2iv[i] = tmp[15-i]; + + AES_init_ctx_iv(&ctx, boot2key, boot2iv); + + fseek(SDMMCFile, bootparams[0], SEEK_SET); + dstaddr = bootparams[2]; + for (u32 i = 0; i < bootparams[3]; i += 16) { - u32 bootparams[8]; - fseek(SDMMCFile, 0x220, SEEK_SET); - fread(bootparams, 4, 8, SDMMCFile); + u8 data[16]; + fread(data, 16, 1, SDMMCFile); - printf("ARM9: offset=%08X size=%08X RAM=%08X size_aligned=%08X\n", - bootparams[0], bootparams[1], bootparams[2], bootparams[3]); - printf("ARM7: offset=%08X size=%08X RAM=%08X size_aligned=%08X\n", - bootparams[4], bootparams[5], bootparams[6], bootparams[7]); + for (int j = 0; j < 16; j++) tmp[j] = data[15-j]; + AES_CTR_xcrypt_buffer(&ctx, tmp, 16); + for (int j = 0; j < 16; j++) data[j] = tmp[15-j]; - // read and apply new-WRAM settings + ARM9Write32(dstaddr, *(u32*)&data[0]); dstaddr += 4; + ARM9Write32(dstaddr, *(u32*)&data[4]); dstaddr += 4; + ARM9Write32(dstaddr, *(u32*)&data[8]); dstaddr += 4; + ARM9Write32(dstaddr, *(u32*)&data[12]); dstaddr += 4; + } - MBK[0][8] = 0; - MBK[1][8] = 0; + *(u32*)&tmp[0] = bootparams[7]; + *(u32*)&tmp[4] = -bootparams[7]; + *(u32*)&tmp[8] = ~bootparams[7]; + *(u32*)&tmp[12] = 0; + for (int i = 0; i < 16; i++) boot2iv[i] = tmp[15-i]; - u32 mbk[12]; - fseek(SDMMCFile, 0x380, SEEK_SET); - fread(mbk, 4, 12, SDMMCFile); + AES_init_ctx_iv(&ctx, boot2key, boot2iv); - MapNWRAM_A(0, mbk[0] & 0xFF); - MapNWRAM_A(1, (mbk[0] >> 8) & 0xFF); - MapNWRAM_A(2, (mbk[0] >> 16) & 0xFF); - MapNWRAM_A(3, mbk[0] >> 24); + fseek(SDMMCFile, bootparams[4], SEEK_SET); + dstaddr = bootparams[6]; + for (u32 i = 0; i < bootparams[7]; i += 16) + { + u8 data[16]; + fread(data, 16, 1, SDMMCFile); - MapNWRAM_B(0, mbk[1] & 0xFF); - MapNWRAM_B(1, (mbk[1] >> 8) & 0xFF); - MapNWRAM_B(2, (mbk[1] >> 16) & 0xFF); - MapNWRAM_B(3, mbk[1] >> 24); - MapNWRAM_B(4, mbk[2] & 0xFF); - MapNWRAM_B(5, (mbk[2] >> 8) & 0xFF); - MapNWRAM_B(6, (mbk[2] >> 16) & 0xFF); - MapNWRAM_B(7, mbk[2] >> 24); + for (int j = 0; j < 16; j++) tmp[j] = data[15-j]; + AES_CTR_xcrypt_buffer(&ctx, tmp, 16); + for (int j = 0; j < 16; j++) data[j] = tmp[15-j]; - MapNWRAM_C(0, mbk[3] & 0xFF); - MapNWRAM_C(1, (mbk[3] >> 8) & 0xFF); - MapNWRAM_C(2, (mbk[3] >> 16) & 0xFF); - MapNWRAM_C(3, mbk[3] >> 24); - MapNWRAM_C(4, mbk[4] & 0xFF); - MapNWRAM_C(5, (mbk[4] >> 8) & 0xFF); - MapNWRAM_C(6, (mbk[4] >> 16) & 0xFF); - MapNWRAM_C(7, mbk[4] >> 24); + ARM7Write32(dstaddr, *(u32*)&data[0]); dstaddr += 4; + ARM7Write32(dstaddr, *(u32*)&data[4]); dstaddr += 4; + ARM7Write32(dstaddr, *(u32*)&data[8]); dstaddr += 4; + ARM7Write32(dstaddr, *(u32*)&data[12]); dstaddr += 4; + } - MapNWRAMRange(0, 0, mbk[5]); - MapNWRAMRange(0, 1, mbk[6]); - MapNWRAMRange(0, 2, mbk[7]); + // repoint the CPUs to the boot2 binaries - MapNWRAMRange(1, 0, mbk[8]); - MapNWRAMRange(1, 1, mbk[9]); - MapNWRAMRange(1, 2, mbk[10]); - - // TODO: find out why it is 0xFF000000 - mbk[11] &= 0x00FFFF0F; - MBK[0][8] = mbk[11]; - MBK[1][8] = mbk[11]; - - // load boot2 binaries - - AES_ctx ctx; - const u8 boot2key[16] = {0xAD, 0x34, 0xEC, 0xF9, 0x62, 0x6E, 0xC2, 0x3A, 0xF6, 0xB4, 0x6C, 0x00, 0x80, 0x80, 0xEE, 0x98}; - u8 boot2iv[16]; - u8 tmp[16]; - u32 dstaddr; - - *(u32*)&tmp[0] = bootparams[3]; - *(u32*)&tmp[4] = -bootparams[3]; - *(u32*)&tmp[8] = ~bootparams[3]; - *(u32*)&tmp[12] = 0; - for (int i = 0; i < 16; i++) boot2iv[i] = tmp[15-i]; - - AES_init_ctx_iv(&ctx, boot2key, boot2iv); - - fseek(SDMMCFile, bootparams[0], SEEK_SET); - dstaddr = bootparams[2]; - for (u32 i = 0; i < bootparams[3]; i += 16) - { - u8 data[16]; - fread(data, 16, 1, SDMMCFile); - - for (int j = 0; j < 16; j++) tmp[j] = data[15-j]; - AES_CTR_xcrypt_buffer(&ctx, tmp, 16); - for (int j = 0; j < 16; j++) data[j] = tmp[15-j]; - - ARM9Write32(dstaddr, *(u32*)&data[0]); dstaddr += 4; - ARM9Write32(dstaddr, *(u32*)&data[4]); dstaddr += 4; - ARM9Write32(dstaddr, *(u32*)&data[8]); dstaddr += 4; - ARM9Write32(dstaddr, *(u32*)&data[12]); dstaddr += 4; - } - - *(u32*)&tmp[0] = bootparams[7]; - *(u32*)&tmp[4] = -bootparams[7]; - *(u32*)&tmp[8] = ~bootparams[7]; - *(u32*)&tmp[12] = 0; - for (int i = 0; i < 16; i++) boot2iv[i] = tmp[15-i]; - - AES_init_ctx_iv(&ctx, boot2key, boot2iv); - - fseek(SDMMCFile, bootparams[4], SEEK_SET); - dstaddr = bootparams[6]; - for (u32 i = 0; i < bootparams[7]; i += 16) - { - u8 data[16]; - fread(data, 16, 1, SDMMCFile); - - for (int j = 0; j < 16; j++) tmp[j] = data[15-j]; - AES_CTR_xcrypt_buffer(&ctx, tmp, 16); - for (int j = 0; j < 16; j++) data[j] = tmp[15-j]; - - ARM7Write32(dstaddr, *(u32*)&data[0]); dstaddr += 4; - ARM7Write32(dstaddr, *(u32*)&data[4]); dstaddr += 4; - ARM7Write32(dstaddr, *(u32*)&data[8]); dstaddr += 4; - ARM7Write32(dstaddr, *(u32*)&data[12]); dstaddr += 4; - } - - // repoint the CPUs to the boot2 binaries - - BootAddr[0] = bootparams[2]; - BootAddr[1] = bootparams[6]; + BootAddr[0] = bootparams[2]; + BootAddr[1] = bootparams[6]; #define printhex(str, size) { for (int z = 0; z < (size); z++) printf("%02X", (str)[z]); printf("\n"); } #define printhex_rev(str, size) { for (int z = (size)-1; z >= 0; z--) printf("%02X", (str)[z]); printf("\n"); } - // read the nocash footer + DSi_NAND::GetIDs(eMMC_CID, ConsoleID); - fseek(SDMMCFile, -0x40, SEEK_END); - - char nand_footer[16]; - const char* nand_footer_ref = "DSi eMMC CID/CPU"; - fread(nand_footer, 1, 16, SDMMCFile); - if (memcmp(nand_footer, nand_footer_ref, 16)) - { - // There is another copy of the footer at 000FF800h for the case - // that by external tools the image was cut off - // See https://problemkaputt.de/gbatek.htm#dsisdmmcimages - fseek(SDMMCFile, 0x000FF800, SEEK_SET); - fread(nand_footer, 1, 16, SDMMCFile); - if (memcmp(nand_footer, nand_footer_ref, 16)) - { - printf("ERROR: NAND missing nocash footer\n"); - return false; - } - } - - fread(eMMC_CID, 1, 16, SDMMCFile); - fread(&ConsoleID, 1, 8, SDMMCFile); - - printf("eMMC CID: "); printhex(eMMC_CID, 16); - printf("Console ID: %" PRIx64 "\n", ConsoleID); - } + printf("eMMC CID: "); printhex(eMMC_CID, 16); + printf("Console ID: %" PRIx64 "\n", ConsoleID); memset(ITCMInit, 0, 0x8000); memcpy(&ITCMInit[0x4400], &ARM9iBIOS[0x87F4], 0x400); @@ -530,10 +511,9 @@ bool LoadNAND() memcpy(&ARM7Init[0x0254], &ARM7iBIOS[0xC6D0], 0x1048); memcpy(&ARM7Init[0x129C], &ARM7iBIOS[0xD718], 0x1048); - DSi_NAND::Init(); DSi_NAND::PatchTSC(); - DSi_NAND::ImportTest(); + DSi_NAND::DeInit(); return true; } diff --git a/src/DSi_NAND.cpp b/src/DSi_NAND.cpp index 9367d29f..629b9ca1 100644 --- a/src/DSi_NAND.cpp +++ b/src/DSi_NAND.cpp @@ -31,14 +31,46 @@ namespace DSi_NAND { +FILE* CurFile; + +u8 eMMC_CID[16]; +u64 ConsoleID; + u8 FATIV[16]; u8 FATKey[16]; u8 ESKey[16]; -void Init() +bool Init(FILE* nandfile, u8* es_keyY) { + if (!nandfile) + return false; + + // read the nocash footer + + fseek(nandfile, -0x40, SEEK_END); + + char nand_footer[16]; + const char* nand_footer_ref = "DSi eMMC CID/CPU"; + fread(nand_footer, 1, 16, nandfile); + if (memcmp(nand_footer, nand_footer_ref, 16)) + { + // There is another copy of the footer at 000FF800h for the case + // that by external tools the image was cut off + // See https://problemkaputt.de/gbatek.htm#dsisdmmcimages + fseek(nandfile, 0x000FF800, SEEK_SET); + fread(nand_footer, 1, 16, nandfile); + if (memcmp(nand_footer, nand_footer_ref, 16)) + { + printf("ERROR: NAND missing nocash footer\n"); + return false; + } + } + + fread(eMMC_CID, 1, 16, nandfile); + fread(&ConsoleID, 1, 8, nandfile); + // init NAND crypto SHA1_CTX sha; @@ -46,15 +78,15 @@ void Init() u8 keyX[16], keyY[16]; SHA1Init(&sha); - SHA1Update(&sha, DSi::eMMC_CID, 16); + SHA1Update(&sha, eMMC_CID, 16); SHA1Final(tmp, &sha); DSi_AES::Swap16(FATIV, tmp); - *(u32*)&keyX[0] = (u32)DSi::ConsoleID; - *(u32*)&keyX[4] = (u32)DSi::ConsoleID ^ 0x24EE6906; - *(u32*)&keyX[8] = (u32)(DSi::ConsoleID >> 32) ^ 0xE65B601D; - *(u32*)&keyX[12] = (u32)(DSi::ConsoleID >> 32); + *(u32*)&keyX[0] = (u32)ConsoleID; + *(u32*)&keyX[4] = (u32)ConsoleID ^ 0x24EE6906; + *(u32*)&keyX[8] = (u32)(ConsoleID >> 32) ^ 0xE65B601D; + *(u32*)&keyX[12] = (u32)(ConsoleID >> 32); *(u32*)&keyY[0] = 0x0AB9DC76; *(u32*)&keyY[4] = 0xBD4DC4D3; @@ -67,13 +99,28 @@ void Init() *(u32*)&keyX[0] = 0x4E00004A; *(u32*)&keyX[4] = 0x4A00004E; - *(u32*)&keyX[8] = (u32)(DSi::ConsoleID >> 32) ^ 0xC80C4B72; - *(u32*)&keyX[12] = (u32)DSi::ConsoleID; + *(u32*)&keyX[8] = (u32)(ConsoleID >> 32) ^ 0xC80C4B72; + *(u32*)&keyX[12] = (u32)ConsoleID; - memcpy(keyY, &DSi::ARM7iBIOS[0x8308], 16); + memcpy(keyY, es_keyY, 16); DSi_AES::DeriveNormalKey(keyX, keyY, tmp); DSi_AES::Swap16(ESKey, tmp); + + CurFile = nandfile; + return true; +} + +void DeInit() +{ + CurFile = nullptr; +} + + +void GetIDs(u8* emmc_cid, u64& consoleid) +{ + memcpy(emmc_cid, eMMC_CID, 16); + consoleid = ConsoleID; } diff --git a/src/DSi_NAND.h b/src/DSi_NAND.h index 1eb018b4..43061c8d 100644 --- a/src/DSi_NAND.h +++ b/src/DSi_NAND.h @@ -24,7 +24,10 @@ namespace DSi_NAND { -void Init(); +bool Init(FILE* nand, u8* es_keyY); +void DeInit(); + +void GetIDs(u8* emmc_cid, u64& consoleid); void PatchTSC(); diff --git a/src/frontend/qt_sdl/TitleManagerDialog.cpp b/src/frontend/qt_sdl/TitleManagerDialog.cpp index 8f96db6e..71ca4e38 100644 --- a/src/frontend/qt_sdl/TitleManagerDialog.cpp +++ b/src/frontend/qt_sdl/TitleManagerDialog.cpp @@ -36,7 +36,46 @@ TitleManagerDialog::TitleManagerDialog(QWidget* parent) : QDialog(parent), ui(ne ui->setupUi(this); setAttribute(Qt::WA_DeleteOnClose); - // + //ui->lstTitleList->setViewMode(QListView::IconMode); + //ui->lstTitleList->setFlow(QListView::LeftToRight); + ui->lstTitleList->setIconSize(QSize(32, 32)); + + { + QPixmap boobs(32, 32); + boobs.fill(Qt::blue); + QIcon piss(boobs); + + QListWidgetItem* derp = new QListWidgetItem("完全放棄宣言\nナナヲアカリ"); + derp->setIcon(piss); + ui->lstTitleList->addItem(derp); + } + { + QPixmap boobs(32, 32); + boobs.fill(Qt::red); + QIcon piss(boobs); + + QListWidgetItem* derp = new QListWidgetItem("death to\ncapitalism"); + derp->setIcon(piss); + ui->lstTitleList->addItem(derp); + } + { + QPixmap boobs(32, 32); + boobs.fill(Qt::green); + QIcon piss(boobs); + + QListWidgetItem* derp = new QListWidgetItem("piles of\ncontent"); + derp->setIcon(piss); + ui->lstTitleList->addItem(derp); + } + { + QPixmap boobs(32, 32); + boobs.fill(Qt::yellow); + QIcon piss(boobs); + + QListWidgetItem* derp = new QListWidgetItem("trans\nrights"); + derp->setIcon(piss); + ui->lstTitleList->addItem(derp); + } } TitleManagerDialog::~TitleManagerDialog()