mirror of
https://github.com/hedge-dev/XenonRecomp.git
synced 2025-06-06 18:31:03 +00:00
Split recompiler code.
This commit is contained in:
parent
c0d28468d0
commit
79354a9a52
@ -2,5 +2,6 @@ cmake_minimum_required (VERSION 3.8)
|
|||||||
|
|
||||||
project("PowerRecomp")
|
project("PowerRecomp")
|
||||||
|
|
||||||
add_executable(PowerRecomp "main.cpp")
|
add_executable(PowerRecomp "main.cpp" "pch.h" "recompiler.cpp" "recompiler.h" "swa_recompiler.cpp" "swa_recompiler.h")
|
||||||
|
target_precompile_headers(PowerRecomp PUBLIC "pch.h")
|
||||||
target_link_libraries(PowerRecomp PRIVATE LibPowerAnalyse tomlplusplus::tomlplusplus xxHash::xxhash)
|
target_link_libraries(PowerRecomp PRIVATE LibPowerAnalyse tomlplusplus::tomlplusplus xxHash::xxhash)
|
||||||
|
2066
PowerRecomp/main.cpp
2066
PowerRecomp/main.cpp
File diff suppressed because it is too large
Load Diff
14
PowerRecomp/pch.h
Normal file
14
PowerRecomp/pch.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <disasm.h>
|
||||||
|
#include <file.h>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <format>
|
||||||
|
#include <function.h>
|
||||||
|
#include <image.h>
|
||||||
|
#include <print>
|
||||||
|
#include <toml++/toml.hpp>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <xbox.h>
|
||||||
|
#include <xxhash.h>
|
1863
PowerRecomp/recompiler.cpp
Normal file
1863
PowerRecomp/recompiler.cpp
Normal file
File diff suppressed because it is too large
Load Diff
42
PowerRecomp/recompiler.h
Normal file
42
PowerRecomp/recompiler.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
struct SwitchTable
|
||||||
|
{
|
||||||
|
size_t r;
|
||||||
|
std::vector<size_t> labels;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Recompiler
|
||||||
|
{
|
||||||
|
Image image;
|
||||||
|
std::vector<Function> functions;
|
||||||
|
std::unordered_map<size_t, SwitchTable> switchTables;
|
||||||
|
std::string out;
|
||||||
|
size_t cppFileIndex = 0;
|
||||||
|
std::vector<uint8_t> temp;
|
||||||
|
|
||||||
|
void LoadSwitchTables(const char* filePath);
|
||||||
|
void LoadExecutable(const char* filePath);
|
||||||
|
|
||||||
|
template<class... Args>
|
||||||
|
void print(std::format_string<Args...> fmt, Args&&... args)
|
||||||
|
{
|
||||||
|
std::vformat_to(std::back_inserter(out), fmt.get(), std::make_format_args(args...));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class... Args>
|
||||||
|
void println(std::format_string<Args...> fmt, Args&&... args)
|
||||||
|
{
|
||||||
|
std::vformat_to(std::back_inserter(out), fmt.get(), std::make_format_args(args...));
|
||||||
|
out += '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Recompile(const Function& fn, uint32_t base, const ppc_insn& insn, std::unordered_map<size_t, SwitchTable>::iterator& switchTable);
|
||||||
|
|
||||||
|
void Recompile(const Function& fn);
|
||||||
|
|
||||||
|
void Recompile(const char* directoryPath);
|
||||||
|
|
||||||
|
void SaveCurrentOutData(const char* directoryPath, const std::string_view& name = std::string_view());
|
||||||
|
};
|
188
PowerRecomp/swa_recompiler.cpp
Normal file
188
PowerRecomp/swa_recompiler.cpp
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "swa_recompiler.h"
|
||||||
|
|
||||||
|
void SWARecompiler::Analyse()
|
||||||
|
{
|
||||||
|
constexpr uint32_t cxxFrameHandler = std::byteswap(0x831B1C90);
|
||||||
|
constexpr uint32_t cSpecificFrameHandler = std::byteswap(0x8324B3BC);
|
||||||
|
constexpr uint32_t yetAnotherFrameHandler = std::byteswap(0x831C8B50);
|
||||||
|
|
||||||
|
auto& pdata = *image.Find(".pdata");
|
||||||
|
size_t count = pdata.size / sizeof(IMAGE_CE_RUNTIME_FUNCTION);
|
||||||
|
auto* pf = (IMAGE_CE_RUNTIME_FUNCTION*)pdata.data;
|
||||||
|
for (size_t i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
auto fn = pf[i];
|
||||||
|
fn.BeginAddress = std::byteswap(fn.BeginAddress);
|
||||||
|
fn.Data = std::byteswap(fn.Data);
|
||||||
|
|
||||||
|
auto& f = functions.emplace_back();
|
||||||
|
f.base = fn.BeginAddress;
|
||||||
|
f.size = fn.FunctionLength * 4;
|
||||||
|
|
||||||
|
image.symbols.emplace(std::format("sub_{:X}", f.base), f.base, f.size, Symbol_Function);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 15; i < 128; i++)
|
||||||
|
{
|
||||||
|
if (i < 32)
|
||||||
|
{
|
||||||
|
auto& restgpr = functions.emplace_back();
|
||||||
|
restgpr.base = 0x831B0B40 + (i - 14) * 4;
|
||||||
|
restgpr.size = 0x831B0B94 - restgpr.base;
|
||||||
|
image.symbols.emplace(std::format("__restgprlr_{}", i), restgpr.base, restgpr.size, Symbol_Function);
|
||||||
|
|
||||||
|
auto& savegpr = functions.emplace_back();
|
||||||
|
savegpr.base = 0x831B0AF0 + (i - 14) * 4;
|
||||||
|
savegpr.size = 0x831B0B40 - savegpr.base;
|
||||||
|
image.symbols.emplace(std::format("__savegprlr_{}", i), savegpr.base, savegpr.size, Symbol_Function);
|
||||||
|
|
||||||
|
auto& restfpr = functions.emplace_back();
|
||||||
|
restfpr.base = 0x831B144C + (i - 14) * 4;
|
||||||
|
restfpr.size = 0x831B1498 - restfpr.base;
|
||||||
|
image.symbols.emplace(std::format("__restfpr_{}", i), restfpr.base, restfpr.size, Symbol_Function);
|
||||||
|
|
||||||
|
auto& savefpr = functions.emplace_back();
|
||||||
|
savefpr.base = 0x831B1400 + (i - 14) * 4;
|
||||||
|
savefpr.size = 0x831B144C - savefpr.base;
|
||||||
|
image.symbols.emplace(std::format("__savefpr_{}", i), savefpr.base, savefpr.size, Symbol_Function);
|
||||||
|
|
||||||
|
auto& restvmx = functions.emplace_back();
|
||||||
|
restvmx.base = 0x831B36E8 + (i - 14) * 8;
|
||||||
|
restvmx.size = 0x831B377C - restvmx.base;
|
||||||
|
image.symbols.emplace(std::format("__restvmx_{}", i), restvmx.base, restvmx.size, Symbol_Function);
|
||||||
|
|
||||||
|
auto& savevmx = functions.emplace_back();
|
||||||
|
savevmx.base = 0x831B3450 + (i - 14) * 8;
|
||||||
|
savevmx.size = 0x831B34E4 - savevmx.base;
|
||||||
|
image.symbols.emplace(std::format("__savevmx_{}", i), savevmx.base, savevmx.size, Symbol_Function);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i >= 64)
|
||||||
|
{
|
||||||
|
auto& restvmx = functions.emplace_back();
|
||||||
|
restvmx.base = 0x831B377C + (i - 64) * 8;
|
||||||
|
restvmx.size = 0x831B3980 - restvmx.base;
|
||||||
|
image.symbols.emplace(std::format("__restvmx_{}", i), restvmx.base, restvmx.size, Symbol_Function);
|
||||||
|
|
||||||
|
auto& savevmx = functions.emplace_back();
|
||||||
|
savevmx.base = 0x831B34E4 + (i - 64) * 8;
|
||||||
|
savevmx.size = 0x831B36E8 - savevmx.base;
|
||||||
|
image.symbols.emplace(std::format("__savevmx_{}", i), savevmx.base, savevmx.size, Symbol_Function);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto hardcodedFuncCheck = [&](Function& f)
|
||||||
|
{
|
||||||
|
if (f.base == 0x824E7EF0) f.size = 0x98;
|
||||||
|
else if (f.base == 0x824E7F28) f.size = 0x60;
|
||||||
|
else if (f.base == 0x82C980E8) f.size = 0x110;
|
||||||
|
else if (f.base == 0x82CF7080) f.size = 0x80;
|
||||||
|
else if (f.base == 0x82D9AC08) f.size = 0x78;
|
||||||
|
else if (f.base == 0x82E86770) f.size = 0x98;
|
||||||
|
else if (f.base == 0x82E97E50) f.size = 0x84;
|
||||||
|
else if (f.base == 0x82EE2D08) f.size = 0x154;
|
||||||
|
else if (f.base == 0x82EF5C38) f.size = 0x64;
|
||||||
|
else if (f.base == 0x82EF5D78) f.size = 0x3F8;
|
||||||
|
else if (f.base == 0x82F08730) f.size = 0x2B0;
|
||||||
|
else if (f.base == 0x82F098C0) f.size = 0x19C;
|
||||||
|
else if (f.base == 0x82F13980) f.size = 0xF4;
|
||||||
|
else if (f.base == 0x82F1D668) f.size = 0x1E8;
|
||||||
|
else if (f.base == 0x82F22908) f.size = 0x20C;
|
||||||
|
else if (f.base == 0x82F25FD8) f.size = 0x240;
|
||||||
|
else if (f.base == 0x82F852A0) f.size = 0xCC;
|
||||||
|
else if (f.base == 0x830DADA0) f.size = 0x150;
|
||||||
|
else if (f.base == 0x831487D0) f.size = 0xD4;
|
||||||
|
else if (f.base == 0x831530C8) f.size = 0x258;
|
||||||
|
else if (f.base == 0x831539E0) f.size = 0xD0;
|
||||||
|
else if (f.base == 0x83168940) f.size = 0x100;
|
||||||
|
else if (f.base == 0x83168A48) f.size = 0x11C;
|
||||||
|
else if (f.base == 0x83168B70) f.size = 0x128;
|
||||||
|
else if (f.base == 0x83168F18) f.size = 0x254;
|
||||||
|
else if (f.base == 0x8316C678) f.size = 0x78;
|
||||||
|
else if (f.base == 0x8317CD30) f.size = 0x50;
|
||||||
|
else if (f.base == 0x83180700) f.size = 0x74;
|
||||||
|
else if (f.base == 0x8319ED58) f.size = 0x98;
|
||||||
|
else if (f.base == 0x82455E70) f.size = 0x84;
|
||||||
|
else if (f.base == 0x82456DC8) f.size = 0xD4;
|
||||||
|
else if (f.base == 0x826ABB70) f.size = 0x70;
|
||||||
|
else if (f.base == 0x82893088) f.size = 0x45C;
|
||||||
|
else if (f.base == 0x82C49540) f.size = 0x114;
|
||||||
|
else if (f.base == 0x82DE35D8) f.size = 0x68;
|
||||||
|
else if (f.base == 0x82DE3640) f.size = 0x64;
|
||||||
|
else if (f.base == 0x82DE36A8) f.size = 0x5C;
|
||||||
|
else if (f.base == 0x82DE3708) f.size = 0x198;
|
||||||
|
else if (f.base == 0x82DE38A0) f.size = 0x16C;
|
||||||
|
else if (f.base == 0x830B7DD0) f.size = 0x74;
|
||||||
|
else if (f.base == 0x831B0BA0) f.size = 0xA0;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto& section : image.sections)
|
||||||
|
{
|
||||||
|
if (!(section.flags & SectionFlags_Code))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
size_t base = section.base;
|
||||||
|
uint8_t* data = section.data;
|
||||||
|
uint8_t* dataEnd = section.data + section.size;
|
||||||
|
|
||||||
|
while (data < dataEnd)
|
||||||
|
{
|
||||||
|
uint32_t insn = std::byteswap(*(uint32_t*)data);
|
||||||
|
if (PPC_OP(insn) == PPC_OP_B && PPC_BL(insn))
|
||||||
|
{
|
||||||
|
size_t address = base + (data - section.data) + PPC_BI(insn);
|
||||||
|
|
||||||
|
if (address >= section.base && address < section.base + section.size && image.symbols.find(address) == image.symbols.end())
|
||||||
|
{
|
||||||
|
auto& fn = functions.emplace_back(Function::Analyze(section.data + address - section.base, section.base + section.size - address, address));
|
||||||
|
hardcodedFuncCheck(fn);
|
||||||
|
image.symbols.emplace(std::format("sub_{:X}", fn.base), fn.base, fn.size, Symbol_Function);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = section.data;
|
||||||
|
const Symbol* prevSymbol = nullptr;
|
||||||
|
|
||||||
|
while (data < dataEnd)
|
||||||
|
{
|
||||||
|
if (*(uint32_t*)data == 0)
|
||||||
|
{
|
||||||
|
data += 4;
|
||||||
|
base += 4;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*(uint32_t*)data == cxxFrameHandler || *(uint32_t*)data == cSpecificFrameHandler || *(uint32_t*)data == yetAnotherFrameHandler)
|
||||||
|
{
|
||||||
|
data += 8;
|
||||||
|
base += 8;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto fnSymbol = image.symbols.find(base);
|
||||||
|
if (fnSymbol != image.symbols.end() && fnSymbol->address == base && fnSymbol->type == Symbol_Function)
|
||||||
|
{
|
||||||
|
assert(fnSymbol->address == base);
|
||||||
|
|
||||||
|
prevSymbol = &*fnSymbol;
|
||||||
|
base += fnSymbol->size;
|
||||||
|
data += fnSymbol->size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto& fn = functions.emplace_back(Function::Analyze(data, dataEnd - data, base));
|
||||||
|
hardcodedFuncCheck(fn);
|
||||||
|
image.symbols.emplace(std::format("sub_{:X}", fn.base), fn.base, fn.size, Symbol_Function);
|
||||||
|
|
||||||
|
base += fn.size;
|
||||||
|
data += fn.size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(functions.begin(), functions.end(), [](auto& lhs, auto& rhs) { return lhs.base < rhs.base; });
|
||||||
|
}
|
7
PowerRecomp/swa_recompiler.h
Normal file
7
PowerRecomp/swa_recompiler.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "recompiler.h"
|
||||||
|
|
||||||
|
struct SWARecompiler : Recompiler
|
||||||
|
{
|
||||||
|
void Analyse();
|
||||||
|
};
|
@ -1,14 +1,12 @@
|
|||||||
project("PowerSample")
|
project("PowerSample")
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
|
||||||
set(CMAKE_CXX_COMPILER "clang-cl")
|
set(CMAKE_CXX_COMPILER "clang-cl")
|
||||||
set(CMAKE_C_COMPILER "clang-cl")
|
set(CMAKE_C_COMPILER "clang-cl")
|
||||||
add_compile_options(
|
add_compile_options(
|
||||||
"/clang:-march=x86-64-v3"
|
"/clang:-march=x86-64-v3"
|
||||||
"/clang:-Wall"
|
"/clang:-Wall"
|
||||||
"/clang:-Wno-unused-label"
|
"/clang:-Wno-unused-label"
|
||||||
"/clang:-Wno-unused-variable"
|
"/clang:-Wno-unused-variable")
|
||||||
"/clang:-Wno-c++23-extensions")
|
|
||||||
|
|
||||||
file(GLOB RecompiledFiles *.cpp)
|
file(GLOB RecompiledFiles *.cpp)
|
||||||
add_library(PowerSample ${RecompiledFiles})
|
add_library(PowerSample ${RecompiledFiles})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user