mirror of
https://github.com/RPCSX/rpcsx.git
synced 2025-12-06 07:12:14 +01:00
add unself tool
This commit is contained in:
parent
1497d01fed
commit
245bc31b6d
|
|
@ -1,2 +1,3 @@
|
|||
add_subdirectory(shader-tool)
|
||||
add_subdirectory(spv-gen)
|
||||
add_subdirectory(unself)
|
||||
|
|
|
|||
|
|
@ -230,7 +230,7 @@ static bool writeOutput(OutputParam &outputParam, std::ostream &out,
|
|||
} else if (outputParam.type == OutputType::SpirvHeader) {
|
||||
writeSpvHeader(outputParam, out, spv);
|
||||
} else if (outputParam.type == OutputType::SpirvAssembly) {
|
||||
out << shader::spv::disassembly(spv);
|
||||
out << shader::spv::disassembly(spv, true);
|
||||
} else if (outputParam.type == OutputType::Glsl) {
|
||||
out << shader::glsl::decompile(spv);
|
||||
} else {
|
||||
|
|
@ -301,7 +301,8 @@ static shader::ir::Region parseIsa(shader::ir::Context &context,
|
|||
}
|
||||
|
||||
if (auto converted = shader::gcn::convertToSpv(
|
||||
isaContext, ir, gcnSemanticModuleInfo, *inputParam.gcnStage, env)) {
|
||||
isaContext, ir, gcnSemanticInfo, gcnSemanticModuleInfo,
|
||||
*inputParam.gcnStage, env)) {
|
||||
if (auto result = shader::spv::deserialize(context, converted->spv, loc)) {
|
||||
return result->merge(context);
|
||||
}
|
||||
|
|
|
|||
4
tools/unself/CMakeLists.txt
Normal file
4
tools/unself/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
add_executable(unself unself.cpp)
|
||||
|
||||
set_target_properties(unself PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||
install(TARGETS unself RUNTIME DESTINATION bin)
|
||||
118
tools/unself/unself.cpp
Normal file
118
tools/unself/unself.cpp
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <elf.h>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
static std::vector<std::byte> unself(const std::byte *image, std::size_t size) {
|
||||
struct [[gnu::packed]] Header {
|
||||
std::uint32_t magic;
|
||||
std::uint32_t unk;
|
||||
std::uint8_t category;
|
||||
std::uint8_t programType;
|
||||
std::uint16_t padding;
|
||||
std::uint16_t headerSize;
|
||||
std::uint16_t signSize;
|
||||
std::uint32_t fileSize;
|
||||
std::uint32_t padding2;
|
||||
std::uint16_t segmentCount;
|
||||
std::uint16_t unk1;
|
||||
std::uint32_t padding3;
|
||||
};
|
||||
static_assert(sizeof(Header) == 0x20);
|
||||
|
||||
struct [[gnu::packed]] Segment {
|
||||
std::uint64_t flags;
|
||||
std::uint64_t offset;
|
||||
std::uint64_t encryptedSize;
|
||||
std::uint64_t decryptedSize;
|
||||
};
|
||||
static_assert(sizeof(Segment) == 0x20);
|
||||
|
||||
auto header = std::bit_cast<Header *>(image);
|
||||
auto segments = std::bit_cast<Segment *>(image + sizeof(Header));
|
||||
|
||||
auto elfOffset = sizeof(Header) + sizeof(Segment) * header->segmentCount;
|
||||
std::vector<std::byte> result;
|
||||
result.reserve(header->fileSize);
|
||||
result.resize(sizeof(Elf64_Ehdr));
|
||||
|
||||
auto ehdr = std::bit_cast<Elf64_Ehdr *>(image + elfOffset);
|
||||
auto phdrs = std::bit_cast<Elf64_Phdr *>(image + elfOffset + ehdr->e_phoff);
|
||||
std::memcpy(result.data(), ehdr, sizeof(Elf64_Ehdr));
|
||||
|
||||
auto phdrEndOffset = ehdr->e_phoff + ehdr->e_phentsize * ehdr->e_phnum;
|
||||
if (result.size() < phdrEndOffset) {
|
||||
result.resize(phdrEndOffset);
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < ehdr->e_phnum; ++i) {
|
||||
std::memcpy(result.data() + ehdr->e_phoff + ehdr->e_phentsize * i,
|
||||
image + elfOffset + ehdr->e_phoff + ehdr->e_phentsize * i,
|
||||
sizeof(Elf64_Phdr));
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < header->segmentCount; ++i) {
|
||||
auto &segment = segments[i];
|
||||
if ((segment.flags & 0x7fb) != 0 ||
|
||||
segment.decryptedSize != segment.encryptedSize) {
|
||||
std::fprintf(stderr, "Unsupported self segment (%lx)\n", segment.flags);
|
||||
std::abort();
|
||||
}
|
||||
|
||||
if (~segment.flags & 0x800) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto &phdr = phdrs[segment.flags >> 20];
|
||||
|
||||
auto endOffset = phdr.p_offset + segment.decryptedSize;
|
||||
if (result.size() < endOffset) {
|
||||
result.resize(endOffset);
|
||||
}
|
||||
|
||||
std::memcpy(result.data() + phdr.p_offset, image + segment.offset,
|
||||
segment.decryptedSize);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
if (argc != 3) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::vector<std::byte> image;
|
||||
{
|
||||
std::ifstream f(argv[1], std::ios::binary | std::ios::ate);
|
||||
|
||||
if (!f) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::size_t size = f.tellg();
|
||||
f.seekg(0, std::ios::beg);
|
||||
image.resize(size);
|
||||
f.read((char *)image.data(), image.size());
|
||||
if (!f) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
auto result = unself(image.data(), image.size());
|
||||
|
||||
{
|
||||
std::ofstream f(argv[2], std::ios::binary);
|
||||
f.write((char *)result.data(), result.size());
|
||||
if (!f) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in a new issue