mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-07-12 18:28:30 +12:00
Long overdue clang-format pass on most of the project (#773)
Some checks are pending
Android Build / x64 (release) (push) Waiting to run
Android Build / arm64 (release) (push) Waiting to run
HTTP Server Build / build (push) Waiting to run
Hydra Core Build / Windows (push) Waiting to run
Hydra Core Build / MacOS (push) Waiting to run
Hydra Core Build / Linux (push) Waiting to run
Hydra Core Build / Android-x64 (push) Waiting to run
Hydra Core Build / ARM-Libretro (push) Waiting to run
Linux AppImage Build / build (push) Waiting to run
Linux Build / build (push) Waiting to run
MacOS Build / MacOS-arm64 (push) Waiting to run
MacOS Build / MacOS-x86_64 (push) Waiting to run
MacOS Build / MacOS-Universal (push) Blocked by required conditions
Qt Build / Windows (push) Waiting to run
Qt Build / MacOS-arm64 (push) Waiting to run
Qt Build / MacOS-x86_64 (push) Waiting to run
Qt Build / MacOS-Universal (push) Blocked by required conditions
Qt Build / Linux (push) Waiting to run
Windows Build / build (push) Waiting to run
iOS Simulator Build / build (push) Waiting to run
Some checks are pending
Android Build / x64 (release) (push) Waiting to run
Android Build / arm64 (release) (push) Waiting to run
HTTP Server Build / build (push) Waiting to run
Hydra Core Build / Windows (push) Waiting to run
Hydra Core Build / MacOS (push) Waiting to run
Hydra Core Build / Linux (push) Waiting to run
Hydra Core Build / Android-x64 (push) Waiting to run
Hydra Core Build / ARM-Libretro (push) Waiting to run
Linux AppImage Build / build (push) Waiting to run
Linux Build / build (push) Waiting to run
MacOS Build / MacOS-arm64 (push) Waiting to run
MacOS Build / MacOS-x86_64 (push) Waiting to run
MacOS Build / MacOS-Universal (push) Blocked by required conditions
Qt Build / Windows (push) Waiting to run
Qt Build / MacOS-arm64 (push) Waiting to run
Qt Build / MacOS-x86_64 (push) Waiting to run
Qt Build / MacOS-Universal (push) Blocked by required conditions
Qt Build / Linux (push) Waiting to run
Windows Build / build (push) Waiting to run
iOS Simulator Build / build (push) Waiting to run
This commit is contained in:
parent
d1f4ae2911
commit
8e20bd6220
65 changed files with 13445 additions and 26224 deletions
|
@ -1,12 +1,12 @@
|
|||
#include "memory.hpp"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "elfio/elfio.hpp"
|
||||
#include "memory.hpp"
|
||||
|
||||
using namespace ELFIO;
|
||||
|
||||
std::optional<u32> Memory::loadELF(std::ifstream& file) {
|
||||
loadedCXI = std::nullopt; // ELF files don't have a CXI, so set this to null
|
||||
loadedCXI = std::nullopt; // ELF files don't have a CXI, so set this to null
|
||||
|
||||
elfio reader;
|
||||
if (!file.good() || !reader.load(file)) {
|
||||
|
@ -14,56 +14,56 @@ std::optional<u32> Memory::loadELF(std::ifstream& file) {
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Allocate stack space. For ELFs we use the default stack size, which is 16KB
|
||||
// Allocate stack space. For ELFs we use the default stack size, which is 16KB
|
||||
if (!allocateMainThreadStack(VirtualAddrs::DefaultStackSize)) {
|
||||
// Should be unreachable
|
||||
printf("Failed to allocate stack space for ELF file\n");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto segNum = reader.segments.size();
|
||||
printf("Number of segments: %d\n", segNum);
|
||||
printf(" # Perms Vaddr File Size Mem Size\n");
|
||||
for (int i = 0; i < segNum; ++i) {
|
||||
const auto seg = reader.segments[i];
|
||||
const auto flags = seg->get_flags();
|
||||
const u32 vaddr = static_cast<u32>(seg->get_virtual_address()); // Vaddr the segment is loaded in
|
||||
u32 fileSize = static_cast<u32>(seg->get_file_size()); // Size of segment in file
|
||||
u32 memorySize = static_cast<u32>(seg->get_memory_size()); // Size of segment in memory
|
||||
u8* data = (u8*)seg->get_data();
|
||||
auto segNum = reader.segments.size();
|
||||
printf("Number of segments: %d\n", segNum);
|
||||
printf(" # Perms Vaddr File Size Mem Size\n");
|
||||
for (int i = 0; i < segNum; ++i) {
|
||||
const auto seg = reader.segments[i];
|
||||
const auto flags = seg->get_flags();
|
||||
const u32 vaddr = static_cast<u32>(seg->get_virtual_address()); // Vaddr the segment is loaded in
|
||||
u32 fileSize = static_cast<u32>(seg->get_file_size()); // Size of segment in file
|
||||
u32 memorySize = static_cast<u32>(seg->get_memory_size()); // Size of segment in memory
|
||||
u8* data = (u8*)seg->get_data();
|
||||
|
||||
// Get read/write/execute permissions for segment
|
||||
const bool r = (flags & 0b100) != 0;
|
||||
const bool w = (flags & 0b010) != 0;
|
||||
const bool x = (flags & 0b001) != 0;
|
||||
// Get read/write/execute permissions for segment
|
||||
const bool r = (flags & 0b100) != 0;
|
||||
const bool w = (flags & 0b010) != 0;
|
||||
const bool x = (flags & 0b001) != 0;
|
||||
|
||||
printf("[%d] (%c%c%c)\t%08X\t%08X\t%08X\n", i, r ? 'r' : '-', w ? 'w' : '-', x ? 'x' : '-', vaddr, fileSize, memorySize);
|
||||
|
||||
// Assert that the segment will be loaded in the executable region. If it isn't then panic.
|
||||
// The executable region starts at 0x00100000 and has a maximum size of 0x03F00000
|
||||
u64 endAddress = (u64)vaddr + (u64)fileSize;
|
||||
const bool isGood = vaddr >= VirtualAddrs::ExecutableStart && endAddress < VirtualAddrs::ExecutableEnd;
|
||||
if (!isGood) {
|
||||
// We're ignoring this for now because some ELFs define a segment at the vaddr for IPC buffer mapping
|
||||
// Helpers::panic("ELF is loaded at invalid place");
|
||||
// return std::nullopt;
|
||||
}
|
||||
printf("[%d] (%c%c%c)\t%08X\t%08X\t%08X\n", i, r ? 'r' : '-', w ? 'w' : '-', x ? 'x' : '-', vaddr, fileSize, memorySize);
|
||||
|
||||
if (memorySize & pageMask) {
|
||||
// Round up the size of the ELF segment to a page (4KB) boundary, as the OS can only alloc this way
|
||||
memorySize = (memorySize + pageSize - 1) & -pageSize;
|
||||
Helpers::warn("Rounding ELF segment size to %08X\n", memorySize);
|
||||
}
|
||||
// Assert that the segment will be loaded in the executable region. If it isn't then panic.
|
||||
// The executable region starts at 0x00100000 and has a maximum size of 0x03F00000
|
||||
u64 endAddress = (u64)vaddr + (u64)fileSize;
|
||||
const bool isGood = vaddr >= VirtualAddrs::ExecutableStart && endAddress < VirtualAddrs::ExecutableEnd;
|
||||
if (!isGood) {
|
||||
// We're ignoring this for now because some ELFs define a segment at the vaddr for IPC buffer mapping
|
||||
// Helpers::panic("ELF is loaded at invalid place");
|
||||
// return std::nullopt;
|
||||
}
|
||||
|
||||
// This should also assert that findPaddr doesn't fail
|
||||
u32 fcramAddr = findPaddr(memorySize).value();
|
||||
std::memcpy(&fcram[fcramAddr], data, fileSize);
|
||||
if (memorySize & pageMask) {
|
||||
// Round up the size of the ELF segment to a page (4KB) boundary, as the OS can only alloc this way
|
||||
memorySize = (memorySize + pageSize - 1) & -pageSize;
|
||||
Helpers::warn("Rounding ELF segment size to %08X\n", memorySize);
|
||||
}
|
||||
|
||||
// Allocate the segment on the OS side
|
||||
allocateMemory(vaddr, fcramAddr, memorySize, true, r, w, x);
|
||||
}
|
||||
// This should also assert that findPaddr doesn't fail
|
||||
u32 fcramAddr = findPaddr(memorySize).value();
|
||||
std::memcpy(&fcram[fcramAddr], data, fileSize);
|
||||
|
||||
// ELF can't specify a region, make it default to USA
|
||||
region = Regions::USA;
|
||||
return static_cast<u32>(reader.get_entry());
|
||||
// Allocate the segment on the OS side
|
||||
allocateMemory(vaddr, fcramAddr, memorySize, true, r, w, x);
|
||||
}
|
||||
|
||||
// ELF can't specify a region, make it default to USA
|
||||
region = Regions::USA;
|
||||
return static_cast<u32>(reader.get_entry());
|
||||
}
|
|
@ -1,79 +1,76 @@
|
|||
#include "loader/lz77.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include "loader/lz77.hpp"
|
||||
|
||||
// The difference in size between the compressed and decompressed file is stored
|
||||
// As a footer in the compressed file. To get the decompressed size, we extract the diff
|
||||
// And add it to the compressed size
|
||||
u32 CartLZ77::decompressedSize(const u8* buffer, u32 compressedSize) {
|
||||
u32 sizeDiff;
|
||||
std::memcpy(&sizeDiff, buffer + compressedSize - 4, sizeof(u32));
|
||||
return sizeDiff + compressedSize;
|
||||
u32 sizeDiff;
|
||||
std::memcpy(&sizeDiff, buffer + compressedSize - 4, sizeof(u32));
|
||||
return sizeDiff + compressedSize;
|
||||
}
|
||||
|
||||
bool CartLZ77::decompress(std::vector<u8>& output, const std::vector<u8>& input) {
|
||||
u32 sizeCompressed = u32(input.size() * sizeof(u8));
|
||||
u32 sizeDecompressed = decompressedSize(input);
|
||||
output.resize(sizeDecompressed);
|
||||
u32 sizeCompressed = u32(input.size() * sizeof(u8));
|
||||
u32 sizeDecompressed = decompressedSize(input);
|
||||
output.resize(sizeDecompressed);
|
||||
|
||||
const u8* compressed = (u8*)input.data();
|
||||
const u8* footer = compressed + sizeCompressed - 8;
|
||||
const u8* compressed = (u8*)input.data();
|
||||
const u8* footer = compressed + sizeCompressed - 8;
|
||||
|
||||
u32 bufferTopAndBottom;
|
||||
std::memcpy(&bufferTopAndBottom, footer, sizeof(u32));
|
||||
u32 bufferTopAndBottom;
|
||||
std::memcpy(&bufferTopAndBottom, footer, sizeof(u32));
|
||||
|
||||
u32 out = sizeDecompressed; // TODO: Is this meant to be u32 or s32?
|
||||
u32 index = sizeCompressed - (Helpers::getBits<24, 8>(bufferTopAndBottom));
|
||||
u32 stopIndex = sizeCompressed - (bufferTopAndBottom & 0xffffff);
|
||||
u32 out = sizeDecompressed; // TODO: Is this meant to be u32 or s32?
|
||||
u32 index = sizeCompressed - (Helpers::getBits<24, 8>(bufferTopAndBottom));
|
||||
u32 stopIndex = sizeCompressed - (bufferTopAndBottom & 0xffffff);
|
||||
|
||||
// Set all of the decompressed buffer to 0 and copy the compressed buffer to the start of it
|
||||
std::fill(output.begin(), output.end(), 0);
|
||||
std::copy(input.begin(), input.end(), output.begin());
|
||||
// Set all of the decompressed buffer to 0 and copy the compressed buffer to the start of it
|
||||
std::fill(output.begin(), output.end(), 0);
|
||||
std::copy(input.begin(), input.end(), output.begin());
|
||||
|
||||
while (index > stopIndex) {
|
||||
u8 control = compressed[--index];
|
||||
while (index > stopIndex) {
|
||||
u8 control = compressed[--index];
|
||||
|
||||
for (uint i = 0; i < 8; i++) {
|
||||
if (index <= stopIndex)
|
||||
break;
|
||||
if (index <= 0)
|
||||
break;
|
||||
if (out <= 0)
|
||||
break;
|
||||
for (uint i = 0; i < 8; i++) {
|
||||
if (index <= stopIndex) break;
|
||||
if (index <= 0) break;
|
||||
if (out <= 0) break;
|
||||
|
||||
if (control & 0x80) {
|
||||
// Check if compression is out of bounds
|
||||
if (index < 2)
|
||||
return false;
|
||||
index -= 2;
|
||||
if (control & 0x80) {
|
||||
// Check if compression is out of bounds
|
||||
if (index < 2) {
|
||||
return false;
|
||||
}
|
||||
index -= 2;
|
||||
|
||||
u32 segmentOffset = compressed[index] | (compressed[index + 1] << 8);
|
||||
u32 segment_size = (Helpers::getBits<12, 4>(segmentOffset)) + 3;
|
||||
segmentOffset &= 0x0FFF;
|
||||
segmentOffset += 2;
|
||||
u32 segmentOffset = compressed[index] | (compressed[index + 1] << 8);
|
||||
u32 segment_size = (Helpers::getBits<12, 4>(segmentOffset)) + 3;
|
||||
segmentOffset &= 0x0FFF;
|
||||
segmentOffset += 2;
|
||||
|
||||
// Check if compression is out of bounds
|
||||
if (out < segment_size)
|
||||
return false;
|
||||
// Check if compression is out of bounds
|
||||
if (out < segment_size) return false;
|
||||
|
||||
for (uint j = 0; j < segment_size; j++) {
|
||||
// Check if compression is out of bounds
|
||||
if (out + segmentOffset >= sizeDecompressed)
|
||||
return false;
|
||||
for (uint j = 0; j < segment_size; j++) {
|
||||
// Check if compression is out of bounds
|
||||
if (out + segmentOffset >= sizeDecompressed) return false;
|
||||
|
||||
u8 data = output[out + segmentOffset];
|
||||
output[--out] = data;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Check if compression is out of bounds
|
||||
if (out < 1)
|
||||
return false;
|
||||
output[--out] = compressed[--index];
|
||||
}
|
||||
control <<= 1;
|
||||
}
|
||||
}
|
||||
u8 data = output[out + segmentOffset];
|
||||
output[--out] = data;
|
||||
}
|
||||
} else {
|
||||
// Check if compression is out of bounds
|
||||
if (out < 1) {
|
||||
return false;
|
||||
}
|
||||
output[--out] = compressed[--index];
|
||||
}
|
||||
control <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
|
@ -11,7 +11,7 @@ bool Memory::mapCXI(NCSD& ncsd, NCCH& cxi) {
|
|||
printf("Data address = %08X, size = %08X\n", cxi.data.address, cxi.data.size);
|
||||
printf("Stack size: %08X\n", cxi.stackSize);
|
||||
|
||||
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"};
|
||||
|
||||
// Set autodetected 3DS region to one of the values allowed by the CXI's SMDH
|
||||
region = cxi.region.value();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue