diff --git a/include/loader/ncch.hpp b/include/loader/ncch.hpp index 45db24cb..f0f93736 100644 --- a/include/loader/ncch.hpp +++ b/include/loader/ncch.hpp @@ -1,4 +1,5 @@ #pragma once +#include #include "helpers.hpp" struct NCCH { @@ -7,13 +8,20 @@ struct NCCH { bool compressExeFS = false; bool mountRomFS = false; bool encrypted = false; + bool fixedCryptoKey = false; static constexpr u64 mediaUnit = 0x200; u64 size = 0; // Size of NCCH converted to bytes u32 stackSize = 0; u32 bssSize = 0; + u32 exheaderSize = 0; // Header: 0x200 + 0x800 byte NCCH header + exheadr // Returns true on success, false on failure bool loadFromHeader(u8* header); + bool hasExtendedHeader() { return exheaderSize != 0; } + +private: + std::array primaryKey = {}; // For exheader, ExeFS header and icons + std::array secondaryKey = {}; // For RomFS and some files in ExeFS }; \ No newline at end of file diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp index cf2fe638..55623bfa 100644 --- a/src/core/loader/ncch.cpp +++ b/src/core/loader/ncch.cpp @@ -3,23 +3,44 @@ #include "memory.hpp" bool NCCH::loadFromHeader(u8* header) { - const u8* exheader = &header[0x200]; // Extended NCCH header - if (header[0x100] != 'N' || header[0x101] != 'C' || header[0x102] != 'C' || header[0x103] != 'H') { printf("Invalid header on NCCH\n"); return false; } size = u64(*(u32*)&header[0x104]) * mediaUnit; // TODO: Maybe don't type pun because big endian will break + exheaderSize = *(u32*)&header[0x180]; + + const u64 programID = *(u64*)&header[0x118]; // Read NCCH flags isNew3DS = header[0x188 + 4] == 2; - mountRomFS = (header[0x188 + 7] & 0x1) != 0x1; + fixedCryptoKey = (header[0x188 + 7] & 0x1) == 0x1; + mountRomFS = (header[0x188 + 7] & 0x2) != 0x2; encrypted = (header[0x188 + 7] & 0x4) != 0x4; - compressExeFS = (exheader[0xD] & 1) != 0; - stackSize = *(u32*)&exheader[0x1C]; - bssSize = *(u32*)&exheader[0x3C]; + bool encryptedExheader = encrypted; + + if (fixedCryptoKey) { + Helpers::panic("Fixed crypto keys for NCCH"); + } + + if (exheaderSize != 0) { + const u8* exheader = &header[0x200]; // Extended NCCH header + const u64 jumpID = *(u64*)&exheader[0x1C0 + 0x8]; + + // TODO: How does this even work + if (u32(programID) == u32(jumpID) && encryptedExheader) { + printf("Exheader is supposedly ecrypted but not actually encrypted\n"); + encryptedExheader = false; + } else if (encryptedExheader) { + Helpers::panic("Encrypted exheader"); + } + + compressExeFS = (exheader[0xD] & 1) != 0; + stackSize = *(u32*)&exheader[0x1C]; + bssSize = *(u32*)&exheader[0x3C]; + } printf("Stack size: %08X\nBSS size: %08X\n", stackSize, bssSize); diff --git a/src/core/loader/ncsd.cpp b/src/core/loader/ncsd.cpp index b94d3221..a0d3bb35 100644 --- a/src/core/loader/ncsd.cpp +++ b/src/core/loader/ncsd.cpp @@ -64,5 +64,10 @@ std::optional Memory::loadNCSD(const std::filesystem::path& path) { } } + if (!ncsd.partitions[0].ncch.hasExtendedHeader()) { + printf("NCSD's CXI doesn't have exheader?\n"); + return std::nullopt; + } + return ncsd; } \ No newline at end of file