Panda3DS/include/loader/3dsx.hpp
2023-09-03 10:36:54 +03:00

80 lines
2.4 KiB
C++

#pragma once
#include <array>
#include "helpers.hpp"
#include "io_file.hpp"
#include "loader/ncch.hpp"
struct HB3DSX {
// File layout:
// - File header
// - Code, rodata and data relocation table headers
// - Code segment
// - Rodata segment
// - Loadable (non-BSS) part of the data segment
// - Code relocation table
// - Rodata relocation table
// - Data relocation table
// Memory layout before relocations are applied:
// [0..codeSegSize) -> code segment
// [codeSegSize..rodataSegSize) -> rodata segment
// [rodataSegSize..dataSegSize) -> data segment
// Memory layout after relocations are applied: well, however the loader sets it up :)
// The entrypoint is always the start of the code segment.
// The BSS section must be cleared manually by the application.
// File header
struct Header {
// minus char magic[4]
u16 headerSize;
u16 relocHeaderSize;
u32 formatVer;
u32 flags;
// Sizes of the code, rodata and data segments +
// size of the BSS section (uninitialized latter half of the data segment)
u32 codeSegSize, rodataSegSize, dataSegSize, bssSize;
};
// Relocation header: all fields (even extra unknown fields) are guaranteed to be relocation counts.
struct RelocHeader {
u32 absoluteCount; // # of absolute relocations (that is, fix address to post-relocation memory layout)
u32 relativeCount; // # of cross-segment relative relocations (that is, 32bit signed offsets that need to be patched)
// more?
// Relocations are written in this order:
// - Absolute relocs
// - Relative relocs
};
enum class RelocType {
Absolute,
Relative,
};
// Relocation entry: from the current pointer, skip X words and patch Y words
struct Reloc {
u16 skip, patch;
};
// _prm structure
static constexpr std::array<char, 4> PRM_MAGIC = {'_', 'P', 'R', 'M'};
struct PrmStruct {
char magic[4];
u32 pSrvOverride;
u32 aptAppId;
u32 heapSize, linearHeapSize;
u32 pArgList;
u32 runFlags;
};
IOFile file;
static constexpr u32 entrypoint = 0x00100000; // Initial ARM11 PC
u32 romFSSize = 0;
u32 romFSOffset = 0;
bool hasRomFs() const;
std::pair<bool, std::size_t> readRomFSBytes(void *dst, std::size_t offset, std::size_t size);
};