mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-09 15:45:40 +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;
|
||||
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;
|
||||
u64 size = 0; // Size of NCCH converted to bytes
|
||||
u32 stackSize = 0;
|
||||
|
|
|
@ -123,16 +123,21 @@ public:
|
|||
static constexpr u32 pageMask = pageSize - 1;
|
||||
static constexpr u32 totalPageCount = 1 << (32 - pageShift);
|
||||
|
||||
static constexpr u32 FCRAM_SIZE = u32(128_MB);
|
||||
static constexpr u32 FCRAM_APPLICATION_SIZE = u32(64_MB);
|
||||
// TODO: All of these change on N3DS
|
||||
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_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_CODE_MEMORY_OFFSET = u32(0_KB);
|
||||
static constexpr u32 DSP_DATA_MEMORY_OFFSET = u32(256_KB);
|
||||
|
||||
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::optional<u32> findPaddr(u32 size);
|
||||
u64 timeSince3DSEpoch();
|
||||
|
@ -186,9 +191,23 @@ public:
|
|||
u32 getLinearHeapVaddr();
|
||||
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)
|
||||
u32 totalSysFCRAM() {
|
||||
return FCRAM_SIZE - FCRAM_APPLICATION_SIZE;
|
||||
return FCRAM_SIZE - fcramApplicationSize;
|
||||
}
|
||||
|
||||
// Amount of OS-only FCRAM currently available
|
||||
|
@ -198,8 +217,8 @@ public:
|
|||
|
||||
// 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
|
||||
u32 sysFCRAMIndex() {
|
||||
return FCRAM_APPLICATION_SIZE;
|
||||
u32 sysFCRAMStartIndex() {
|
||||
return fcramApplicationSize;
|
||||
}
|
||||
|
||||
enum class BatteryLevel {
|
||||
|
|
|
@ -21,6 +21,9 @@ std::optional<u32> Memory::loadELF(std::ifstream& file) {
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Use 64MB of application FCRAM for ELFs by default
|
||||
setApplicationRamSize(64_MB);
|
||||
|
||||
auto segNum = reader.segments.size();
|
||||
printf("Number of segments: %d\n", segNum);
|
||||
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]);
|
||||
rodata.extract(&exheader[0x20]);
|
||||
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);
|
||||
|
|
|
@ -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" };
|
||||
|
||||
// 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
|
||||
region = cxi.region.value();
|
||||
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
|
||||
// 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(size <= FCRAM_APPLICATION_SIZE || isMap);
|
||||
assert(usedUserMemory + size <= FCRAM_APPLICATION_SIZE || isMap);
|
||||
assert(paddr + size <= FCRAM_APPLICATION_SIZE || isMap);
|
||||
assert(size <= fcramApplicationSize || isMap);
|
||||
assert(usedUserMemory + size <= fcramApplicationSize || isMap);
|
||||
assert(paddr + size <= fcramApplicationSize || isMap);
|
||||
|
||||
// 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;
|
||||
|
||||
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)
|
||||
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
|
||||
candidatePage = i + 1;
|
||||
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
|
||||
// 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
|
||||
if (size > remainingSysFCRAM()) {
|
||||
Helpers::panic("Memory::allocateSysMemory: Overflowed OS FCRAM");
|
||||
}
|
||||
|
||||
const u32 pageCount = size / pageSize; // Number of pages that will be used up
|
||||
const u32 startIndex = sysFCRAMIndex() + usedSystemMemory; // Starting FCRAM index
|
||||
const u32 pageCount = size / pageSize; // Number of pages that will be used up
|
||||
const u32 startIndex = FCRAM_SIZE - usedSystemMemory - size; // Starting FCRAM index
|
||||
const u32 startingPage = startIndex / pageSize;
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
usedFCRAMPages[startingPage + i] = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -444,6 +444,8 @@ bool Emulator::loadROM(const std::filesystem::path& path) {
|
|||
}
|
||||
|
||||
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();
|
||||
bool success; // Tracks if we loaded the ROM successfully
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue