mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-08 07:05:40 +12:00
We can almost load commercial carts now
This commit is contained in:
parent
36b0117ebc
commit
87bf469447
5 changed files with 50 additions and 8 deletions
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <vector>
|
||||||
#include "io_file.hpp"
|
#include "io_file.hpp"
|
||||||
#include "helpers.hpp"
|
#include "helpers.hpp"
|
||||||
|
|
||||||
|
@ -10,6 +11,20 @@ struct NCCH {
|
||||||
u64 hashRegionSize = 0;
|
u64 hashRegionSize = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Descriptions for .text, .data and .rodata sections
|
||||||
|
struct CodeSetInfo {
|
||||||
|
u32 address = 0;
|
||||||
|
u32 pageCount = 0;
|
||||||
|
u32 size = 0;
|
||||||
|
|
||||||
|
// Extract the code set info from the relevant header data
|
||||||
|
void extract(const u8* headerEntry) {
|
||||||
|
address = *(u32*)&headerEntry[0];
|
||||||
|
pageCount = *(u32*)&headerEntry[4];
|
||||||
|
size = *(u32*)&headerEntry[8];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
u64 partitionIndex = 0;
|
u64 partitionIndex = 0;
|
||||||
u64 fileOffset = 0;
|
u64 fileOffset = 0;
|
||||||
|
|
||||||
|
@ -28,6 +43,10 @@ struct NCCH {
|
||||||
|
|
||||||
FSInfo exeFS;
|
FSInfo exeFS;
|
||||||
FSInfo romFS;
|
FSInfo romFS;
|
||||||
|
CodeSetInfo text, data, rodata;
|
||||||
|
|
||||||
|
// Contents of the .code file in the ExeFS
|
||||||
|
std::vector<u8> codeFile;
|
||||||
|
|
||||||
// Header: 0x200 + 0x800 byte NCCH header + exheadr
|
// Header: 0x200 + 0x800 byte NCCH header + exheadr
|
||||||
// Returns true on success, false on failure
|
// Returns true on success, false on failure
|
||||||
|
@ -37,6 +56,7 @@ struct NCCH {
|
||||||
bool hasExtendedHeader() { return exheaderSize != 0; }
|
bool hasExtendedHeader() { return exheaderSize != 0; }
|
||||||
bool hasExeFS() { return exeFS.size != 0; }
|
bool hasExeFS() { return exeFS.size != 0; }
|
||||||
bool hasRomFS() { return romFS.size != 0; }
|
bool hasRomFS() { return romFS.size != 0; }
|
||||||
|
bool hasCode() { return codeFile.size() != 0; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::array<u8, 16> primaryKey = {}; // For exheader, ExeFS header and icons
|
std::array<u8, 16> primaryKey = {}; // For exheader, ExeFS header and icons
|
||||||
|
|
|
@ -16,4 +16,6 @@ struct NCSD {
|
||||||
IOFile file;
|
IOFile file;
|
||||||
u64 size = 0; // Image size according to the header converted to bytes
|
u64 size = 0; // Image size according to the header converted to bytes
|
||||||
std::array<Partition, 8> partitions; // NCCH partitions
|
std::array<Partition, 8> partitions; // NCCH partitions
|
||||||
|
|
||||||
|
u32 entrypoint; // Initial ARM11 PC
|
||||||
};
|
};
|
||||||
|
|
|
@ -49,6 +49,10 @@ bool NCCH::loadFromHeader(u8* header, IOFile& file) {
|
||||||
compressCode = (exheader[0xD] & 1) != 0;
|
compressCode = (exheader[0xD] & 1) != 0;
|
||||||
stackSize = *(u32*)&exheader[0x1C];
|
stackSize = *(u32*)&exheader[0x1C];
|
||||||
bssSize = *(u32*)&exheader[0x3C];
|
bssSize = *(u32*)&exheader[0x3C];
|
||||||
|
|
||||||
|
text.extract(&exheader[0x10]);
|
||||||
|
rodata.extract(&exheader[0x20]);
|
||||||
|
data.extract(&exheader[0x30]);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Stack size: %08X\nBSS size: %08X\n", stackSize, bssSize);
|
printf("Stack size: %08X\nBSS size: %08X\n", stackSize, bssSize);
|
||||||
|
@ -84,7 +88,9 @@ bool NCCH::loadFromHeader(u8* header, IOFile& file) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::strcmp(name, ".code") == 0) {
|
if (std::strcmp(name, ".code") == 0) {
|
||||||
std::vector<u8> code;
|
if (hasCode()) {
|
||||||
|
Helpers::panic("Second code file in a single NCCH partition. What should this do?\n");
|
||||||
|
}
|
||||||
|
|
||||||
if (compressCode) {
|
if (compressCode) {
|
||||||
std::vector<u8> tmp;
|
std::vector<u8> tmp;
|
||||||
|
@ -96,15 +102,14 @@ bool NCCH::loadFromHeader(u8* header, IOFile& file) {
|
||||||
file.readBytes(tmp.data(), fileSize);
|
file.readBytes(tmp.data(), fileSize);
|
||||||
|
|
||||||
// Decompress .code file from the tmp vector to the "code" vector
|
// Decompress .code file from the tmp vector to the "code" vector
|
||||||
if (!CartLZ77::decompress(code, tmp)) {
|
if (!CartLZ77::decompress(codeFile, tmp)) {
|
||||||
printf("Failed to decompress .code file\n");
|
printf("Failed to decompress .code file\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
code.resize(fileSize);
|
codeFile.resize(fileSize);
|
||||||
file.seek(exeFSOffset + exeFSHeaderSize + fileOffset);
|
file.seek(exeFSOffset + exeFSHeaderSize + fileOffset);
|
||||||
file.readBytes(code.data(), fileSize);
|
file.readBytes(codeFile.data(), fileSize);
|
||||||
Helpers::panic("Uncompressed .code file!");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,11 +67,20 @@ std::optional<NCSD> Memory::loadNCSD(const std::filesystem::path& path) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ncsd.partitions[0].ncch.hasExtendedHeader()) {
|
auto& cxi = ncsd.partitions[0].ncch;
|
||||||
printf("NCSD's CXI doesn't have exheader?\n");
|
if (!cxi.hasExtendedHeader() || !cxi.hasCode()) {
|
||||||
|
printf("NCSD with an invalid CXI in partition 0?\n");
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Map code file to memory
|
||||||
|
const auto& code = cxi.codeFile;
|
||||||
|
printf("Text address = %08X page count = %08X\n", cxi.text.address, cxi.text.size);
|
||||||
|
printf("Rodata address = %08X page count = %08X\n", cxi.rodata.address, cxi.rodata.size);
|
||||||
|
printf("Data address = %08X page count = %08X\n", cxi.data.address, cxi.data.size);
|
||||||
|
|
||||||
|
ncsd.entrypoint = cxi.text.address;
|
||||||
|
|
||||||
return ncsd;
|
return ncsd;
|
||||||
}
|
}
|
|
@ -70,6 +70,12 @@ bool Emulator::loadNCSD(const std::filesystem::path& path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
loadedNCSD = opt.value();
|
loadedNCSD = opt.value();
|
||||||
|
cpu.setReg(15, loadedNCSD.entrypoint);
|
||||||
|
|
||||||
|
if (loadedNCSD.entrypoint & 1) {
|
||||||
|
Helpers::panic("Misaligned NCSD entrypoint; should this start the CPU in Thumb mode?");
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue