diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp index c5a9bae2..ca6bdd19 100644 --- a/src/core/loader/3dsx.cpp +++ b/src/core/loader/3dsx.cpp @@ -7,31 +7,29 @@ #include "memory.hpp" namespace { + struct LoadInfo { + u32 codeSegSizeAligned; + u32 rodataSegSizeAligned; + u32 dataSegSizeAligned; + }; -struct LoadInfo { - u32 codeSegSizeAligned; - u32 rodataSegSizeAligned; - u32 dataSegSizeAligned; -}; + static inline u32 translateAddr(const u32 off, const u32* addrs, const u32* offsets) { + if (off < offsets[1]) { + return addrs[0] + off; + } -static inline u32 translateAddr(const u32 off, const u32* addrs, const u32* offsets) { - if (off < offsets[1]) { - return addrs[0] + off; + if (off < offsets[2]) { + return addrs[1] + off - offsets[1]; + } + return addrs[2] + off - offsets[2]; } - - if (off < offsets[2]) { - return addrs[1] + off - offsets[1]; - } - return addrs[2] + off - offsets[2]; -} - -} +} // namespace bool Memory::map3DSX(HB3DSX& hb3dsx, const HB3DSX::Header& header) { const LoadInfo hbInfo = { - .codeSegSizeAligned = (header.codeSegSize+0xFFF) &~ 0xFFF, - .rodataSegSizeAligned = (header.rodataSegSize+0xFFF) &~ 0xFFF, - .dataSegSizeAligned = (header.dataSegSize+0xFFF) &~ 0xFFF, + .codeSegSizeAligned = (header.codeSegSize + 0xFFF) & ~0xFFF, + .rodataSegSizeAligned = (header.rodataSegSize + 0xFFF) & ~0xFFF, + .dataSegSizeAligned = (header.dataSegSize + 0xFFF) & ~0xFFF, }; const u32 textSegAddr = HB3DSX::entrypoint; @@ -74,7 +72,7 @@ bool Memory::map3DSX(HB3DSX& hb3dsx, const HB3DSX::Header& header) { return false; } - const u32 dataLoadsize = header.dataSegSize - header.bssSize; // 3DSX data size in header includes bss + const u32 dataLoadsize = header.dataSegSize - header.bssSize; // 3DSX data size in header includes bss std::vector code(totalSize, 0); std::tie(success, count) = hb3dsx.file.readBytes(&code[textOffset], header.codeSegSize); @@ -90,13 +88,13 @@ bool Memory::map3DSX(HB3DSX& hb3dsx, const HB3DSX::Header& header) { } std::tie(success, count) = hb3dsx.file.readBytes(&code[dataOffset], dataLoadsize); - if (!success || count != dataLoadsize) { + if (!success || count != dataLoadsize) { Helpers::panic("Failed to read 3DSX data segment"); return false; } std::vector currentRelocs; - + const u32 segAddrs[] = { textSegAddr, rodataSegAddr, @@ -110,7 +108,7 @@ bool Memory::map3DSX(HB3DSX& hb3dsx, const HB3DSX::Header& header) { dataOffset, extraPageOffset, }; - + const u32 segSizes[] = { header.codeSegSize, header.rodataSegSize, @@ -121,7 +119,7 @@ bool Memory::map3DSX(HB3DSX& hb3dsx, const HB3DSX::Header& header) { for (const auto& relocHeader : relocHeaders) { currentRelocs.resize(relocHeader.absoluteCount + relocHeader.relativeCount); std::tie(success, count) = hb3dsx.file.read(¤tRelocs[0], currentRelocs.size(), sizeof(HB3DSX::Reloc)); - if (!success || count != currentRelocs.size()) { + if (!success || count != currentRelocs.size()) { Helpers::panic("Failed to read 3DSX relocations"); return false; } @@ -136,15 +134,15 @@ bool Memory::map3DSX(HB3DSX& hb3dsx, const HB3DSX::Header& header) { const auto RelocationAction = [&](const HB3DSX::Reloc& reloc, const HB3DSX::RelocType relocType) -> bool { if (reloc.skip) { - sectionData = sectionData.subspan(reloc.skip * sizeof(u32)); // advance by `skip` words (32-bit values) + sectionData = sectionData.subspan(reloc.skip * sizeof(u32)); // advance by `skip` words (32-bit values) } for (u32 m = 0; m < reloc.patch && !sectionData.empty(); ++m) { - const u32 inAddr = textSegAddr + (sectionData.data() - code.data()); // byte offset -> word count + const u32 inAddr = textSegAddr + (sectionData.data() - code.data()); // byte offset -> word count u32 origData = 0; std::memcpy(&origData, §ionData[0], sizeof(u32)); - const u32 subType = origData >> (32-4); - const u32 addr = translateAddr(origData &~ 0xF0000000, segAddrs, segOffs); + const u32 subType = origData >> (32 - 4); + const u32 addr = translateAddr(origData & ~0xF0000000, segAddrs, segOffs); switch (relocType) { case HB3DSX::RelocType::Absolute: { @@ -159,14 +157,12 @@ bool Memory::map3DSX(HB3DSX& hb3dsx, const HB3DSX::Header& header) { case HB3DSX::RelocType::Relative: { u32 data = addr - inAddr; switch (subType) { - case 1: // 31-bit signed offset + case 1: // 31-bit signed offset data &= ~(1u << 31); - case 0: // 32-bit signed offset + case 0: // 32-bit signed offset std::memcpy(§ionData[0], &data, sizeof(u32)); break; - default: - Helpers::panic("Unsupported relative reloc subtype"); - return false; + default: Helpers::panic("Unsupported relative reloc subtype"); return false; } break; } @@ -184,7 +180,7 @@ bool Memory::map3DSX(HB3DSX& hb3dsx, const HB3DSX::Header& header) { } } - sectionData = sectionDataStartAs; // restart from the beginning for the next part + sectionData = sectionDataStartAs; // restart from the beginning for the next part for (const auto& reloc : relativeRelocs) { if (!RelocationAction(reloc, HB3DSX::RelocType::Relative)) { return false; @@ -195,22 +191,22 @@ bool Memory::map3DSX(HB3DSX& hb3dsx, const HB3DSX::Header& header) { // Detect and fill _prm structure HB3DSX::PrmStruct pst; std::memcpy(&pst, &code[4], sizeof(pst)); - if (pst.magic[0] == '_' && pst.magic[1] == 'p' && pst.magic[2] == 'r' && pst.magic[3] == 'm' ) { + if (pst.magic[0] == '_' && pst.magic[1] == 'p' && pst.magic[2] == 'r' && pst.magic[3] == 'm') { // if there was any argv to put, it would go there // first u32: argc // remaining: continuous argv string (NUL-char separated, ofc) // std::memcpy(&code[extraPageOffset], argvBuffer, ...); - + // setting to NULL (default) = run from system. load romfs from process. // non-NULL = homebrew launcher. load romfs from 3dsx @ argv[0] // pst.pSrvOverride = extraPageAddr + 0xFFC; - + pst.pArgList = extraPageAddr; - + // RUNFLAG_APTREINIT: Reinitialize APT. // From libctru. Because there's no previously running software here pst.runFlags |= 1 << 1; - + /* s64 dummy; bool isN3DS = svcGetSystemInfo(&dummy, 0x10001, 0) == 0; if (isN3DS) @@ -228,9 +224,9 @@ bool Memory::map3DSX(HB3DSX& hb3dsx, const HB3DSX::Header& header) { const auto paddr = opt.value(); std::memcpy(&fcram[paddr], &code[0], totalSize); // Copy the 3 segments + BSS to FCRAM - allocateMemory(textSegAddr, paddr + textOffset, hbInfo.codeSegSizeAligned, true, true, false, true); // Text is R-X - allocateMemory(rodataSegAddr, paddr + rodataOffset, hbInfo.rodataSegSizeAligned, true, true, false, false); // Rodata is R-- - allocateMemory(dataSegAddr, paddr + dataOffset, hbInfo.dataSegSizeAligned + 0x1000, true, true, true, false); // Data+BSS+Extra is RW- + allocateMemory(textSegAddr, paddr + textOffset, hbInfo.codeSegSizeAligned, true, true, false, true); // Text is R-X + allocateMemory(rodataSegAddr, paddr + rodataOffset, hbInfo.rodataSegSizeAligned, true, true, false, false); // Rodata is R-- + allocateMemory(dataSegAddr, paddr + dataOffset, hbInfo.dataSegSizeAligned + 0x1000, true, true, true, false); // Data+BSS+Extra is RW- return true; } @@ -262,9 +258,8 @@ std::optional Memory::load3DSX(const std::filesystem::path& path) { } if (hbHeader.headerSize == 0x20 || hbHeader.headerSize == 0x2C) { - if (hbHeader.headerSize == 0x2C) - { - hb3dsx.file.seek(8, SEEK_CUR); // skip SMDH info + if (hbHeader.headerSize == 0x2C) { + hb3dsx.file.seek(8, SEEK_CUR); // skip SMDH info std::tie(success, bytes) = hb3dsx.file.readBytes(&hb3dsx.romFSOffset, 4); if (!success || bytes != 4) { printf("Failed to read 3DSX romFS offset\n"); @@ -278,8 +273,7 @@ std::optional Memory::load3DSX(const std::filesystem::path& path) { } hb3dsx.romFSSize = *fileSize - hb3dsx.romFSOffset; } - } - else { + } else { printf("Invalid 3DSX header size\n"); return std::nullopt; } @@ -293,17 +287,15 @@ std::optional Memory::load3DSX(const std::filesystem::path& path) { return HB3DSX::entrypoint; } -bool HB3DSX::hasRomFs() const { - return romFSSize != 0 && romFSOffset != 0; -} +bool HB3DSX::hasRomFs() const { return romFSSize != 0 && romFSOffset != 0; } -std::pair HB3DSX::readRomFSBytes(void *dst, std::size_t offset, std::size_t size) { +std::pair HB3DSX::readRomFSBytes(void* dst, std::size_t offset, std::size_t size) { if (!hasRomFs()) { - return { false, 0 }; + return {false, 0}; } if (!file.seek(romFSOffset + offset)) { - return { false, 0 }; + return {false, 0}; } return file.readBytes(dst, size);