mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-18 03:31:31 +12:00
Start handling exheader flag0
This commit is contained in:
parent
902b2032e2
commit
fe70616535
7 changed files with 74 additions and 15 deletions
|
@ -47,6 +47,9 @@ struct NCCH {
|
||||||
bool seedCrypto = false;
|
bool seedCrypto = false;
|
||||||
u8 secondaryKeySlot = 0;
|
u8 secondaryKeySlot = 0;
|
||||||
|
|
||||||
|
// Contains info such as the ideal processor for threads, affinity mask, and how much memory should be reserved for the application
|
||||||
|
u8 flag0 = 0;
|
||||||
|
|
||||||
static constexpr u64 mediaUnit = 0x200;
|
static constexpr u64 mediaUnit = 0x200;
|
||||||
u64 size = 0; // Size of NCCH converted to bytes
|
u64 size = 0; // Size of NCCH converted to bytes
|
||||||
u32 stackSize = 0;
|
u32 stackSize = 0;
|
||||||
|
|
|
@ -123,16 +123,21 @@ public:
|
||||||
static constexpr u32 pageMask = pageSize - 1;
|
static constexpr u32 pageMask = pageSize - 1;
|
||||||
static constexpr u32 totalPageCount = 1 << (32 - pageShift);
|
static constexpr u32 totalPageCount = 1 << (32 - pageShift);
|
||||||
|
|
||||||
static constexpr u32 FCRAM_SIZE = u32(128_MB);
|
// TODO: All of these change on N3DS
|
||||||
static constexpr u32 FCRAM_APPLICATION_SIZE = u32(64_MB);
|
static constexpr u32 FCRAM_SIZE = u32(128_MB); // Total amount of FCRAM
|
||||||
static constexpr u32 FCRAM_PAGE_COUNT = FCRAM_SIZE / pageSize;
|
static constexpr u32 FCRAM_PAGE_COUNT = FCRAM_SIZE / pageSize;
|
||||||
static constexpr u32 FCRAM_APPLICATION_PAGE_COUNT = FCRAM_APPLICATION_SIZE / pageSize;
|
static constexpr u32 FCRAM_MAX_APPLICATION_SIZE = u32(96_MB); // Max amount available for applications
|
||||||
|
static constexpr u32 FCRAM_APPLICATION_MAX_PAGE_COUNT = FCRAM_MAX_APPLICATION_SIZE / pageSize;
|
||||||
|
|
||||||
static constexpr u32 DSP_RAM_SIZE = u32(512_KB);
|
static constexpr u32 DSP_RAM_SIZE = u32(512_KB);
|
||||||
static constexpr u32 DSP_CODE_MEMORY_OFFSET = u32(0_KB);
|
static constexpr u32 DSP_CODE_MEMORY_OFFSET = u32(0_KB);
|
||||||
static constexpr u32 DSP_DATA_MEMORY_OFFSET = u32(256_KB);
|
static constexpr u32 DSP_DATA_MEMORY_OFFSET = u32(256_KB);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// This will get adjusted based on the cartridge exheader via setFcramApplicationSize, 64MB is just a default
|
||||||
|
u32 fcramApplicationSize = u32(64_MB);
|
||||||
|
u32 fcramApplicationPageCount = u32(64_MB) / pageSize; // Same here
|
||||||
|
|
||||||
std::bitset<FCRAM_PAGE_COUNT> usedFCRAMPages;
|
std::bitset<FCRAM_PAGE_COUNT> usedFCRAMPages;
|
||||||
std::optional<u32> findPaddr(u32 size);
|
std::optional<u32> findPaddr(u32 size);
|
||||||
u64 timeSince3DSEpoch();
|
u64 timeSince3DSEpoch();
|
||||||
|
@ -186,9 +191,23 @@ public:
|
||||||
u32 getLinearHeapVaddr();
|
u32 getLinearHeapVaddr();
|
||||||
u8* getFCRAM() { return fcram; }
|
u8* getFCRAM() { return fcram; }
|
||||||
|
|
||||||
|
// Set the amount of application FCRAM
|
||||||
|
void setApplicationRamSize(u32 size) {
|
||||||
|
fcramApplicationSize = size;
|
||||||
|
fcramApplicationPageCount = size / pageSize;
|
||||||
|
|
||||||
|
if (usedUserMemory > fcramApplicationSize) {
|
||||||
|
Helpers::panic("Set application FCRAM to a value less than the currently used application memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usedSystemMemory > totalSysFCRAM()) {
|
||||||
|
Helpers::panic("Set system FCRAM to a value less than the currently used system memory");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Total amount of OS-only FCRAM available (Can vary depending on how much FCRAM the app requests via the cart exheader)
|
// Total amount of OS-only FCRAM available (Can vary depending on how much FCRAM the app requests via the cart exheader)
|
||||||
u32 totalSysFCRAM() {
|
u32 totalSysFCRAM() {
|
||||||
return FCRAM_SIZE - FCRAM_APPLICATION_SIZE;
|
return FCRAM_SIZE - fcramApplicationSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Amount of OS-only FCRAM currently available
|
// Amount of OS-only FCRAM currently available
|
||||||
|
@ -198,8 +217,8 @@ public:
|
||||||
|
|
||||||
// Physical FCRAM index to the start of OS FCRAM
|
// Physical FCRAM index to the start of OS FCRAM
|
||||||
// We allocate the first part of physical FCRAM for the application, and the rest to the OS. So the index for the OS = application ram size
|
// We allocate the first part of physical FCRAM for the application, and the rest to the OS. So the index for the OS = application ram size
|
||||||
u32 sysFCRAMIndex() {
|
u32 sysFCRAMStartIndex() {
|
||||||
return FCRAM_APPLICATION_SIZE;
|
return fcramApplicationSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class BatteryLevel {
|
enum class BatteryLevel {
|
||||||
|
|
|
@ -21,6 +21,9 @@ std::optional<u32> Memory::loadELF(std::ifstream& file) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use 64MB of application FCRAM for ELFs by default
|
||||||
|
setApplicationRamSize(64_MB);
|
||||||
|
|
||||||
auto segNum = reader.segments.size();
|
auto segNum = reader.segments.size();
|
||||||
printf("Number of segments: %d\n", segNum);
|
printf("Number of segments: %d\n", segNum);
|
||||||
printf(" # Perms Vaddr File Size Mem Size\n");
|
printf(" # Perms Vaddr File Size Mem Size\n");
|
||||||
|
|
|
@ -160,6 +160,10 @@ bool NCCH::loadFromHeader(Crypto::AESEngine &aesEngine, IOFile& file, const FSIn
|
||||||
text.extract(&exheader[0x10]);
|
text.extract(&exheader[0x10]);
|
||||||
rodata.extract(&exheader[0x20]);
|
rodata.extract(&exheader[0x20]);
|
||||||
data.extract(&exheader[0x30]);
|
data.extract(&exheader[0x30]);
|
||||||
|
|
||||||
|
// Access Control Info section of the exheader
|
||||||
|
const u8* aci = &exheader[0x200];
|
||||||
|
flag0 = aci[0xE];
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Stack size: %08X\nBSS size: %08X\n", stackSize, bssSize);
|
printf("Stack size: %08X\nBSS size: %08X\n", stackSize, bssSize);
|
||||||
|
|
|
@ -13,6 +13,31 @@ bool Memory::mapCXI(NCSD& ncsd, NCCH& cxi) {
|
||||||
|
|
||||||
static constexpr std::array<const char*, 7> regionNames = {"Japan", "North America", "Europe", "Australia", "China", "Korea", "Taiwan" };
|
static constexpr std::array<const char*, 7> regionNames = {"Japan", "North America", "Europe", "Australia", "China", "Korea", "Taiwan" };
|
||||||
|
|
||||||
|
// The application RAM sizes for Old 3DS titles, chosen based on flag0 of the exheader
|
||||||
|
static constexpr std::array<u32, 16> applicationRamSizes_O3DS = {
|
||||||
|
64_MB, // Prod
|
||||||
|
64_MB, // Unused
|
||||||
|
96_MB, // Dev1
|
||||||
|
80_MB, // Dev2
|
||||||
|
72_MB, // Dev3
|
||||||
|
32_MB, // Dev4
|
||||||
|
64_MB, 64_MB, 64_MB, 64_MB, 64_MB, 64_MB, 64_MB, 64_MB, 64_MB, 64_MB,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Similar for New 3DS titles chosed based on flag2 from exheader. Index 0 isn't actually used, and denotes that this should use the Old3DS setting
|
||||||
|
[[maybe_unused]] static constexpr std::array<u32, 16> applicationRamSizes_New3DS = {
|
||||||
|
64_MB, // Legacy mode
|
||||||
|
124_MB, // Prod
|
||||||
|
178_MB, // Dev1
|
||||||
|
124_MB, // Dev2
|
||||||
|
124_MB, 124_MB, 124_MB, 124_MB, 124_MB, 124_MB, 124_MB, 124_MB, 124_MB, 124_MB, 124_MB, 124_MB,
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: Handle N3DS FCRAM here
|
||||||
|
const u32 memorySize = applicationRamSizes_O3DS[Helpers::getBits<4, 4>(cxi.flag0)];
|
||||||
|
setApplicationRamSize(memorySize);
|
||||||
|
printf("Set application RAM size to %dMB\n", u32(memorySize / 1_MB));
|
||||||
|
|
||||||
// Set autodetected 3DS region to one of the values allowed by the CXI's SMDH
|
// Set autodetected 3DS region to one of the values allowed by the CXI's SMDH
|
||||||
region = cxi.region.value();
|
region = cxi.region.value();
|
||||||
printf("Console region autodetected to: %s\n", regionNames[static_cast<size_t>(region)]);
|
printf("Console region autodetected to: %s\n", regionNames[static_cast<size_t>(region)]);
|
||||||
|
|
|
@ -289,12 +289,12 @@ std::optional<u32> Memory::allocateMemory(u32 vaddr, u32 paddr, u32 size, bool l
|
||||||
// Additionally assert we don't OoM and that we don't try to allocate physical FCRAM past what's available to userland
|
// Additionally assert we don't OoM and that we don't try to allocate physical FCRAM past what's available to userland
|
||||||
// If we're mapping there's no fear of OoM, because we're not really allocating memory, just binding vaddrs to specific paddrs
|
// If we're mapping there's no fear of OoM, because we're not really allocating memory, just binding vaddrs to specific paddrs
|
||||||
assert(isAligned(vaddr) && isAligned(paddr) && isAligned(size));
|
assert(isAligned(vaddr) && isAligned(paddr) && isAligned(size));
|
||||||
assert(size <= FCRAM_APPLICATION_SIZE || isMap);
|
assert(size <= fcramApplicationSize || isMap);
|
||||||
assert(usedUserMemory + size <= FCRAM_APPLICATION_SIZE || isMap);
|
assert(usedUserMemory + size <= fcramApplicationSize || isMap);
|
||||||
assert(paddr + size <= FCRAM_APPLICATION_SIZE || isMap);
|
assert(paddr + size <= fcramApplicationSize || isMap);
|
||||||
|
|
||||||
// Amount of available user FCRAM pages and FCRAM pages to allocate respectively
|
// Amount of available user FCRAM pages and FCRAM pages to allocate respectively
|
||||||
const u32 availablePageCount = (FCRAM_APPLICATION_SIZE - usedUserMemory) / pageSize;
|
const u32 availablePageCount = (fcramApplicationSize - usedUserMemory) / pageSize;
|
||||||
const u32 neededPageCount = size / pageSize;
|
const u32 neededPageCount = size / pageSize;
|
||||||
|
|
||||||
assert(availablePageCount >= neededPageCount || isMap);
|
assert(availablePageCount >= neededPageCount || isMap);
|
||||||
|
@ -367,7 +367,7 @@ std::optional<u32> Memory::findPaddr(u32 size) {
|
||||||
// If this ends up >= than neededPages then the paddr is good (ie we can use the candidate page as a base address)
|
// If this ends up >= than neededPages then the paddr is good (ie we can use the candidate page as a base address)
|
||||||
u32 counter = 0;
|
u32 counter = 0;
|
||||||
|
|
||||||
for (u32 i = 0; i < FCRAM_APPLICATION_PAGE_COUNT; i++) {
|
for (u32 i = 0; i < fcramApplicationPageCount; i++) {
|
||||||
if (usedFCRAMPages[i]) { // Page is occupied already, go to new candidate
|
if (usedFCRAMPages[i]) { // Page is occupied already, go to new candidate
|
||||||
candidatePage = i + 1;
|
candidatePage = i + 1;
|
||||||
counter = 0;
|
counter = 0;
|
||||||
|
@ -392,19 +392,22 @@ u32 Memory::allocateSysMemory(u32 size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// We use a pretty dumb allocator for OS memory since this is not really accessible to the app and is only used internally
|
// We use a pretty dumb allocator for OS memory since this is not really accessible to the app and is only used internally
|
||||||
// It works by just allocating memory linearly, starting from index 0 of OS memory and going up
|
// It works by just allocating memory linearly, starting from the end of system memory and going back
|
||||||
|
// This happens in order to allow changing the size of application FCRAM when loading a ROM, and not risking messing up our data
|
||||||
// This should also be unreachable in practice and exists as a sanity check
|
// This should also be unreachable in practice and exists as a sanity check
|
||||||
if (size > remainingSysFCRAM()) {
|
if (size > remainingSysFCRAM()) {
|
||||||
Helpers::panic("Memory::allocateSysMemory: Overflowed OS FCRAM");
|
Helpers::panic("Memory::allocateSysMemory: Overflowed OS FCRAM");
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 pageCount = size / pageSize; // Number of pages that will be used up
|
const u32 pageCount = size / pageSize; // Number of pages that will be used up
|
||||||
const u32 startIndex = sysFCRAMIndex() + usedSystemMemory; // Starting FCRAM index
|
const u32 startIndex = FCRAM_SIZE - usedSystemMemory - size; // Starting FCRAM index
|
||||||
const u32 startingPage = startIndex / pageSize;
|
const u32 startingPage = startIndex / pageSize;
|
||||||
|
|
||||||
for (u32 i = 0; i < pageCount; i++) {
|
for (u32 i = 0; i < pageCount; i++) {
|
||||||
if (usedFCRAMPages[startingPage + i]) // Also a theoretically unreachable panic for safety
|
if (usedFCRAMPages[startingPage + i]) { // Also a theoretically unreachable panic for safety
|
||||||
Helpers::panic("Memory::reserveMemory: Trying to reserve already reserved memory");
|
Helpers::panic("Memory::reserveMemory: Trying to reserve already reserved memory");
|
||||||
|
}
|
||||||
|
|
||||||
usedFCRAMPages[startingPage + i] = true;
|
usedFCRAMPages[startingPage + i] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -444,6 +444,8 @@ bool Emulator::loadROM(const std::filesystem::path& path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
kernel.initializeFS();
|
kernel.initializeFS();
|
||||||
|
memory.setApplicationRamSize(64_MB); // Set the application RAM size to a default 64MB that loaded apps can override if needed
|
||||||
|
|
||||||
auto extension = path.extension();
|
auto extension = path.extension();
|
||||||
bool success; // Tracks if we loaded the ROM successfully
|
bool success; // Tracks if we loaded the ROM successfully
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue