mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-20 12:39:13 +12:00
Add IVFC parser
This commit is contained in:
parent
72b45377e1
commit
f3ce29bf2d
5 changed files with 137 additions and 1 deletions
78
src/core/fs/ivfc.cpp
Normal file
78
src/core/fs/ivfc.cpp
Normal file
|
@ -0,0 +1,78 @@
|
|||
#include "fs/ivfc.hpp"
|
||||
|
||||
namespace IVFC {
|
||||
|
||||
size_t parseIVFC(uintptr_t ivfcStart, IVFC& ivfc) {
|
||||
uintptr_t ivfcPointer = ivfcStart;
|
||||
std::string magicIVFC((char*)ivfcPointer, 4);
|
||||
ivfcPointer += 4;
|
||||
|
||||
if (magicIVFC != "IVFC") {
|
||||
printf("Invalid IVFC magic: %s\n", magicIVFC.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t magicIdentifier = *(u32*)ivfcPointer;
|
||||
ivfcPointer += 4;
|
||||
|
||||
// RomFS IVFC uses 0x10000, DISA/DIFF IVFC uses 0x20000 here
|
||||
if (magicIdentifier != 0x10000 && magicIdentifier != 0x20000) {
|
||||
printf("Invalid IVFC magic identifier: %08X\n", magicIdentifier);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (magicIdentifier == 0x10000) {
|
||||
ivfc.masterHashSize = *(u32*)ivfcPointer;
|
||||
ivfcPointer += 4;
|
||||
// RomFS IVFC uses 3 levels
|
||||
ivfc.levels.resize(3);
|
||||
} else {
|
||||
ivfc.masterHashSize = *(u64*)ivfcPointer;
|
||||
ivfcPointer += 8;
|
||||
// DISA/DIFF IVFC uses 4 levels
|
||||
ivfc.levels.resize(4);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < ivfc.levels.size(); i++) {
|
||||
IVFCLevel level;
|
||||
|
||||
level.logicalOffset = *(u64*)ivfcPointer;
|
||||
ivfcPointer += 8;
|
||||
|
||||
level.size = *(u64*)ivfcPointer;
|
||||
ivfcPointer += 8;
|
||||
|
||||
// This field is in log2
|
||||
level.blockSize = 1 << *(u32*)ivfcPointer;
|
||||
ivfcPointer += 4;
|
||||
|
||||
// Skip 4 reserved bytes
|
||||
ivfcPointer += 4;
|
||||
|
||||
ivfc.levels[i] = level;
|
||||
}
|
||||
|
||||
u64 ivfcDescriptorSize = *(u64*)ivfcPointer;
|
||||
ivfcPointer += 8;
|
||||
|
||||
uintptr_t ivfcActualSize = ivfcPointer - ivfcStart;
|
||||
|
||||
// According to 3DBrew, this is usually the case but not guaranteed
|
||||
if (ivfcActualSize != ivfcDescriptorSize) {
|
||||
printf("IVFC descriptor size mismatch: %lx != %lx\n", ivfcActualSize, ivfcDescriptorSize);
|
||||
}
|
||||
|
||||
if (magicIdentifier == 0x10000 && ivfcActualSize != 0x5C) {
|
||||
// This is always 0x5C bytes long
|
||||
printf("Invalid IVFC size: %08x\n", (u32)ivfcActualSize);
|
||||
return 0;
|
||||
} else if (magicIdentifier == 0x20000 && ivfcActualSize != 0x78) {
|
||||
// This is always 0x78 bytes long
|
||||
printf("Invalid IVFC size: %08x\n", (u32)ivfcActualSize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ivfcActualSize;
|
||||
}
|
||||
|
||||
} // namespace IVFC
|
21
src/core/fs/romfs.cpp
Normal file
21
src/core/fs/romfs.cpp
Normal file
|
@ -0,0 +1,21 @@
|
|||
#include "fs/romfs.hpp"
|
||||
#include "fs/ivfc.hpp"
|
||||
#include <cstdio>
|
||||
|
||||
namespace RomFS {
|
||||
|
||||
RomFSNode parseRomFSTree(uintptr_t romFS, u64 romFSSize) {
|
||||
RomFSNode root;
|
||||
|
||||
IVFC::IVFC ivfc;
|
||||
size_t ivfcSize = IVFC::parseIVFC((uintptr_t)romFS, ivfc);
|
||||
|
||||
if (ivfcSize == 0) {
|
||||
printf("Failed to parse IVFC\n");
|
||||
return {};
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
} // namespace RomFS
|
Loading…
Add table
Add a link
Reference in a new issue