mirror of
				https://github.com/hedge-dev/XenonRecomp.git
				synced 2025-11-04 06:47:09 +00:00 
			
		
		
		
	Remove hardcoded recompiler, load TOML file for configuration.
This commit is contained in:
		@@ -40,6 +40,13 @@ size_t Function::SearchBlock(size_t address) const
 | 
			
		||||
Function Function::Analyze(const void* code, size_t size, size_t base)
 | 
			
		||||
{
 | 
			
		||||
    Function fn{ base, 0 };
 | 
			
		||||
 | 
			
		||||
    if (*((uint32_t*)code + 1) == 0x04000048) // shifted ptr tail call
 | 
			
		||||
    {
 | 
			
		||||
        fn.size = 0x8;
 | 
			
		||||
        return fn;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto& blocks = fn.blocks;
 | 
			
		||||
    blocks.reserve(8);
 | 
			
		||||
    blocks.emplace_back();
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,6 @@ project("PowerRecomp")
 | 
			
		||||
 | 
			
		||||
BIN2H(SOURCE_FILE ${POWERUTILS_ROOT}/ppc_context.h HEADER_FILE "generated/ppc_context.gen.h" VARIABLE_NAME "gPPCContextText")
 | 
			
		||||
 | 
			
		||||
add_executable(PowerRecomp "main.cpp" "pch.h" "recompiler.cpp" "recompiler.h" "swa_recompiler.cpp" "swa_recompiler.h" "test_recompiler.cpp" "test_recompiler.h")
 | 
			
		||||
add_executable(PowerRecomp "main.cpp" "pch.h" "recompiler.cpp" "recompiler.h" "test_recompiler.cpp" "test_recompiler.h" "recompiler_config.h" "recompiler_config.cpp")
 | 
			
		||||
target_precompile_headers(PowerRecomp PUBLIC "pch.h")
 | 
			
		||||
target_link_libraries(PowerRecomp PRIVATE LibPowerAnalyse tomlplusplus::tomlplusplus xxHash::xxhash)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,32 +1,20 @@
 | 
			
		||||
#include "pch.h"
 | 
			
		||||
#include "swa_recompiler.h"
 | 
			
		||||
#include "test_recompiler.h"
 | 
			
		||||
 | 
			
		||||
// argv 1: xex file path
 | 
			
		||||
// argv 2: switches toml file path
 | 
			
		||||
// argv 3: output directory path
 | 
			
		||||
 | 
			
		||||
int main(int argc, char* argv[])
 | 
			
		||||
{
 | 
			
		||||
    if (strstr(argv[1], ".xex") != nullptr)
 | 
			
		||||
    const char* path = 
 | 
			
		||||
    #ifdef CONFIG_FILE_PATH
 | 
			
		||||
        CONFIG_FILE_PATH
 | 
			
		||||
    #else
 | 
			
		||||
        argv[1]
 | 
			
		||||
    #endif
 | 
			
		||||
        ;
 | 
			
		||||
 | 
			
		||||
    if (std::filesystem::is_regular_file(path))
 | 
			
		||||
    {
 | 
			
		||||
        SWARecompiler recompiler;
 | 
			
		||||
        //recompiler.config.skipLr = true;
 | 
			
		||||
        recompiler.config.ctrAsLocalVariable = true;
 | 
			
		||||
        recompiler.config.xerAsLocalVariable = true;
 | 
			
		||||
        recompiler.config.reservedRegisterAsLocalVariable = true;
 | 
			
		||||
        recompiler.config.skipMsr = true;
 | 
			
		||||
        recompiler.config.crRegistersAsLocalVariables = true;
 | 
			
		||||
        recompiler.config.nonArgumentRegistersAsLocalVariables = true;
 | 
			
		||||
        recompiler.config.nonVolatileRegistersAsLocalVariables = true;
 | 
			
		||||
 | 
			
		||||
        std::println("Loading executable...");
 | 
			
		||||
        recompiler.LoadExecutable(argv[1]);
 | 
			
		||||
 | 
			
		||||
        std::println("Loading switch tables...");
 | 
			
		||||
        recompiler.LoadSwitchTables(argv[2]);
 | 
			
		||||
 | 
			
		||||
        std::println("Analysing functions...");
 | 
			
		||||
        Recompiler recompiler;
 | 
			
		||||
        recompiler.LoadConfig(path);
 | 
			
		||||
        recompiler.Analyse();
 | 
			
		||||
 | 
			
		||||
        auto entry = recompiler.image.symbols.find(recompiler.image.entry_point);
 | 
			
		||||
@@ -35,11 +23,11 @@ int main(int argc, char* argv[])
 | 
			
		||||
            entry->name = "_xstart";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        recompiler.Recompile(argv[3]);
 | 
			
		||||
        recompiler.Recompile();
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        TestRecompiler::RecompileTests(argv[1], argv[2]);
 | 
			
		||||
        TestRecompiler::RecompileTests(path, argv[2]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -9,33 +9,156 @@ static uint64_t ComputeMask(uint32_t mstart, uint32_t mstop)
 | 
			
		||||
    return mstart <= mstop ? value : ~value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Recompiler::LoadSwitchTables(const char* filePath)
 | 
			
		||||
void Recompiler::LoadConfig(const std::string_view& configFilePath)
 | 
			
		||||
{
 | 
			
		||||
    toml::table toml = toml::parse_file(filePath);
 | 
			
		||||
    for (auto& entry : *toml["switch"].as_array())
 | 
			
		||||
    {
 | 
			
		||||
        auto& table = *entry.as_table();
 | 
			
		||||
    config.Load(configFilePath);
 | 
			
		||||
 | 
			
		||||
        SwitchTable switchTable;
 | 
			
		||||
        switchTable.r = *table["r"].value<size_t>();
 | 
			
		||||
        for (auto& array : *table["labels"].as_array())
 | 
			
		||||
            switchTable.labels.push_back(*array.value<size_t>());
 | 
			
		||||
 | 
			
		||||
        switchTables.emplace(*table["base"].value<size_t>(), std::move(switchTable));
 | 
			
		||||
    }
 | 
			
		||||
    const auto file = LoadFile((config.directoryPath + config.filePath).c_str()).value();
 | 
			
		||||
    image = Image::ParseImage(file.data(), file.size()).value();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Recompiler::LoadExecutable(const char* filePath)
 | 
			
		||||
void Recompiler::Analyse()
 | 
			
		||||
{
 | 
			
		||||
    const auto file = LoadFile(filePath).value();
 | 
			
		||||
    image = Image::ParseImage(file.data(), file.size()).value();
 | 
			
		||||
    for (size_t i = 14; i < 128; i++)
 | 
			
		||||
    {
 | 
			
		||||
        if (i < 32)
 | 
			
		||||
        {
 | 
			
		||||
            auto& restgpr = functions.emplace_back();
 | 
			
		||||
            restgpr.base = config.restGpr14Address + (i - 14) * 4;
 | 
			
		||||
            restgpr.size = (32 - i) * 4 + 12;
 | 
			
		||||
            image.symbols.emplace(std::format("__restgprlr_{}", i), restgpr.base, restgpr.size, Symbol_Function);
 | 
			
		||||
 | 
			
		||||
            auto& savegpr = functions.emplace_back();
 | 
			
		||||
            savegpr.base = config.saveGpr14Address + (i - 14) * 4;
 | 
			
		||||
            savegpr.size = (32 - i) * 4 + 8;
 | 
			
		||||
            image.symbols.emplace(std::format("__savegprlr_{}", i), savegpr.base, savegpr.size, Symbol_Function);
 | 
			
		||||
 | 
			
		||||
            auto& restfpr = functions.emplace_back();
 | 
			
		||||
            restfpr.base = config.restFpr14Address + (i - 14) * 4;
 | 
			
		||||
            restfpr.size = (32 - i) * 4 + 4;
 | 
			
		||||
            image.symbols.emplace(std::format("__restfpr_{}", i), restfpr.base, restfpr.size, Symbol_Function);
 | 
			
		||||
 | 
			
		||||
            auto& savefpr = functions.emplace_back();
 | 
			
		||||
            savefpr.base = config.saveFpr14Address + (i - 14) * 4;
 | 
			
		||||
            savefpr.size = (32 - i) * 4 + 4;
 | 
			
		||||
            image.symbols.emplace(std::format("__savefpr_{}", i), savefpr.base, savefpr.size, Symbol_Function);
 | 
			
		||||
 | 
			
		||||
            auto& restvmx = functions.emplace_back();
 | 
			
		||||
            restvmx.base = config.restVmx14Address + (i - 14) * 8;
 | 
			
		||||
            restvmx.size = (32 - i) * 8 + 4;
 | 
			
		||||
            image.symbols.emplace(std::format("__restvmx_{}", i), restvmx.base, restvmx.size, Symbol_Function);
 | 
			
		||||
 | 
			
		||||
            auto& savevmx = functions.emplace_back();
 | 
			
		||||
            savevmx.base = config.saveVmx14Address + (i - 14) * 8;
 | 
			
		||||
            savevmx.size = (32 - i) * 8 + 4;
 | 
			
		||||
            image.symbols.emplace(std::format("__savevmx_{}", i), savevmx.base, savevmx.size, Symbol_Function);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (i >= 64)
 | 
			
		||||
        {
 | 
			
		||||
            auto& restvmx = functions.emplace_back();
 | 
			
		||||
            restvmx.base = config.restVmx64Address + (i - 64) * 8;
 | 
			
		||||
            restvmx.size = (128 - i) * 8 + 4;
 | 
			
		||||
            image.symbols.emplace(std::format("__restvmx_{}", i), restvmx.base, restvmx.size, Symbol_Function);
 | 
			
		||||
 | 
			
		||||
            auto& savevmx = functions.emplace_back();
 | 
			
		||||
            savevmx.base = config.saveVmx64Address + (i - 64) * 8;
 | 
			
		||||
            savevmx.size = (128 - i) * 8 + 4;
 | 
			
		||||
            image.symbols.emplace(std::format("__savevmx_{}", i), savevmx.base, savevmx.size, Symbol_Function);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (auto& [address, size] : config.functions)
 | 
			
		||||
    {
 | 
			
		||||
        functions.emplace_back(address, size);
 | 
			
		||||
        image.symbols.emplace(std::format("sub_{:X}", address), address, size, Symbol_Function);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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);
 | 
			
		||||
 | 
			
		||||
        if (image.symbols.find(fn.BeginAddress) == image.symbols.end())
 | 
			
		||||
        {
 | 
			
		||||
            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 (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 data = section.data + address - section.base;
 | 
			
		||||
                    auto& fn = functions.emplace_back(Function::Analyze(data, section.base + section.size - address, address));
 | 
			
		||||
                    image.symbols.emplace(std::format("sub_{:X}", fn.base), fn.base, fn.size, Symbol_Function);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            data += 4;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        data = section.data;
 | 
			
		||||
 | 
			
		||||
        while (data < dataEnd)
 | 
			
		||||
        {
 | 
			
		||||
            auto invalidInstr = config.invalidInstructions.find(std::byteswap(*(uint32_t*)data));
 | 
			
		||||
            if (invalidInstr != config.invalidInstructions.end())
 | 
			
		||||
            {
 | 
			
		||||
                base += invalidInstr->second;
 | 
			
		||||
                data += invalidInstr->second;
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            auto fnSymbol = image.symbols.find(base);
 | 
			
		||||
            if (fnSymbol != image.symbols.end() && fnSymbol->address == base && fnSymbol->type == Symbol_Function)
 | 
			
		||||
            {
 | 
			
		||||
                assert(fnSymbol->address == base);
 | 
			
		||||
 | 
			
		||||
                base += fnSymbol->size;
 | 
			
		||||
                data += fnSymbol->size;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                auto& fn = functions.emplace_back(Function::Analyze(data, dataEnd - data, base));
 | 
			
		||||
                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; });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Recompiler::Recompile(
 | 
			
		||||
    const Function& fn,
 | 
			
		||||
    uint32_t base,
 | 
			
		||||
    const ppc_insn& insn,
 | 
			
		||||
    std::unordered_map<size_t, SwitchTable>::iterator& switchTable,
 | 
			
		||||
    std::unordered_map<uint32_t, RecompilerSwitchTable>::iterator& switchTable,
 | 
			
		||||
    RecompilerLocalVariables& localVariables,
 | 
			
		||||
    CSRState& csrState)
 | 
			
		||||
{
 | 
			
		||||
@@ -141,11 +264,11 @@ bool Recompiler::Recompile(
 | 
			
		||||
 | 
			
		||||
    auto printFunctionCall = [&](uint32_t address)
 | 
			
		||||
        {
 | 
			
		||||
            if (address == longJmpAddress)
 | 
			
		||||
            if (address == config.longJmpAddress)
 | 
			
		||||
            {
 | 
			
		||||
                println("\tlongjmp(*reinterpret_cast<jmp_buf*>(base + {}.u32), {}.s32);", r(3), r(4));
 | 
			
		||||
            }
 | 
			
		||||
            else if (address == setJmpAddress)
 | 
			
		||||
            else if (address == config.setJmpAddress)
 | 
			
		||||
            {
 | 
			
		||||
                println("\t{} = ctx;", env());
 | 
			
		||||
                println("\t{}.s64 = setjmp(*reinterpret_cast<jmp_buf*>(base + {}.u32));", r(3), r(3));
 | 
			
		||||
@@ -292,7 +415,7 @@ bool Recompiler::Recompile(
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case PPC_INST_BCTR:
 | 
			
		||||
        if (switchTable != switchTables.end())
 | 
			
		||||
        if (switchTable != config.switchTables.end())
 | 
			
		||||
        {
 | 
			
		||||
            println("\tswitch ({}.u64) {{", r(switchTable->second.r));
 | 
			
		||||
 | 
			
		||||
@@ -316,7 +439,7 @@ bool Recompiler::Recompile(
 | 
			
		||||
            println("\t\t__builtin_unreachable();");
 | 
			
		||||
            println("\t}}");
 | 
			
		||||
 | 
			
		||||
            switchTable = switchTables.end();
 | 
			
		||||
            switchTable = config.switchTables.end();
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
@@ -1963,8 +2086,8 @@ bool Recompiler::Recompile(const Function& fn)
 | 
			
		||||
                labels.emplace(addr + PPC_BD(instruction));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        auto switchTable = switchTables.find(addr);
 | 
			
		||||
        if (switchTable != switchTables.end())
 | 
			
		||||
        auto switchTable = config.switchTables.find(addr);
 | 
			
		||||
        if (switchTable != config.switchTables.end())
 | 
			
		||||
        {
 | 
			
		||||
            for (auto label : switchTable->second.labels)
 | 
			
		||||
                labels.emplace(label);
 | 
			
		||||
@@ -1986,7 +2109,7 @@ bool Recompiler::Recompile(const Function& fn)
 | 
			
		||||
    println("PPC_FUNC_IMPL(__imp__{}) {{", name);
 | 
			
		||||
    println("\tPPC_FUNC_PROLOGUE();");
 | 
			
		||||
 | 
			
		||||
    auto switchTable = switchTables.end();
 | 
			
		||||
    auto switchTable = config.switchTables.end();
 | 
			
		||||
    bool allRecompiled = true;
 | 
			
		||||
    CSRState csrState = CSRState::Unknown;
 | 
			
		||||
 | 
			
		||||
@@ -2010,8 +2133,8 @@ bool Recompiler::Recompile(const Function& fn)
 | 
			
		||||
            csrState = CSRState::Unknown;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (switchTable == switchTables.end())
 | 
			
		||||
            switchTable = switchTables.find(base);
 | 
			
		||||
        if (switchTable == config.switchTables.end())
 | 
			
		||||
            switchTable = config.switchTables.find(base);
 | 
			
		||||
 | 
			
		||||
        ppc::Disassemble(data, 4, base, insn);
 | 
			
		||||
 | 
			
		||||
@@ -2025,7 +2148,7 @@ bool Recompiler::Recompile(const Function& fn)
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            if (insn.opcode->id == PPC_INST_BCTR && (*(data - 1) == 0x07008038 || *(data - 1) == 0x00000060) && switchTable == switchTables.end())
 | 
			
		||||
            if (insn.opcode->id == PPC_INST_BCTR && (*(data - 1) == 0x07008038 || *(data - 1) == 0x00000060) && switchTable == config.switchTables.end())
 | 
			
		||||
                std::println("Found a switch jump table at {:X} with no switch table entry present", base);
 | 
			
		||||
 | 
			
		||||
            if (!Recompile(fn, base, insn, switchTable, localVariables, csrState))
 | 
			
		||||
@@ -2095,7 +2218,7 @@ bool Recompiler::Recompile(const Function& fn)
 | 
			
		||||
    return allRecompiled;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Recompiler::Recompile(const char* directoryPath)
 | 
			
		||||
void Recompiler::Recompile()
 | 
			
		||||
{
 | 
			
		||||
    out.reserve(10 * 1024 * 1024);
 | 
			
		||||
 | 
			
		||||
@@ -2124,16 +2247,16 @@ void Recompiler::Recompile(const char* directoryPath)
 | 
			
		||||
 | 
			
		||||
        println("\n#endif");
 | 
			
		||||
 | 
			
		||||
        SaveCurrentOutData(directoryPath, "ppc_config.h");
 | 
			
		||||
        SaveCurrentOutData("ppc_config.h");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        println("#pragma once");
 | 
			
		||||
 | 
			
		||||
        println("#include \"ppc_config.h\"");
 | 
			
		||||
        println("#include \"ppc_config.h\"\n");
 | 
			
		||||
        println("{}", std::string_view{gPPCContextText, gPPCContextText_SIZE});
 | 
			
		||||
 | 
			
		||||
        SaveCurrentOutData(directoryPath, "ppc_context.h");
 | 
			
		||||
        SaveCurrentOutData("ppc_context.h");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
@@ -2144,7 +2267,7 @@ void Recompiler::Recompile(const char* directoryPath)
 | 
			
		||||
        for (auto& symbol : image.symbols)
 | 
			
		||||
            println("PPC_EXTERN_FUNC({});", symbol.name);
 | 
			
		||||
 | 
			
		||||
        SaveCurrentOutData(directoryPath, "ppc_recomp_shared.h");
 | 
			
		||||
        SaveCurrentOutData("ppc_recomp_shared.h");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
@@ -2157,14 +2280,14 @@ void Recompiler::Recompile(const char* directoryPath)
 | 
			
		||||
        println("\t{{ 0, nullptr }}");
 | 
			
		||||
        println("}};");
 | 
			
		||||
 | 
			
		||||
        SaveCurrentOutData(directoryPath, "ppc_func_mapping.cpp");
 | 
			
		||||
        SaveCurrentOutData("ppc_func_mapping.cpp");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (size_t i = 0; i < functions.size(); i++)
 | 
			
		||||
    {
 | 
			
		||||
        if ((i % 256) == 0)
 | 
			
		||||
        {
 | 
			
		||||
            SaveCurrentOutData(directoryPath);
 | 
			
		||||
            SaveCurrentOutData();
 | 
			
		||||
            println("#include \"ppc_recomp_shared.h\"\n");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -2174,10 +2297,10 @@ void Recompiler::Recompile(const char* directoryPath)
 | 
			
		||||
        Recompile(functions[i]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SaveCurrentOutData(directoryPath);
 | 
			
		||||
    SaveCurrentOutData();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Recompiler::SaveCurrentOutData(const char* directoryPath, const std::string_view& name)
 | 
			
		||||
void Recompiler::SaveCurrentOutData(const std::string_view& name)
 | 
			
		||||
{
 | 
			
		||||
    if (!out.empty())
 | 
			
		||||
    {
 | 
			
		||||
@@ -2192,7 +2315,7 @@ void Recompiler::SaveCurrentOutData(const char* directoryPath, const std::string
 | 
			
		||||
        bool shouldWrite = true;
 | 
			
		||||
 | 
			
		||||
        // Check if an identical file already exists first to not trigger recompilation
 | 
			
		||||
        std::string filePath = std::format("{}/{}", directoryPath, name.empty() ? cppName : name);
 | 
			
		||||
        std::string filePath = std::format("{}/{}/{}", config.directoryPath, config.outDirectoryPath, name.empty() ? cppName : name);
 | 
			
		||||
        FILE* f = fopen(filePath.c_str(), "rb");
 | 
			
		||||
        if (f)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,7 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include "pch.h"
 | 
			
		||||
 | 
			
		||||
struct SwitchTable
 | 
			
		||||
{
 | 
			
		||||
    size_t r;
 | 
			
		||||
    std::vector<size_t> labels;
 | 
			
		||||
};
 | 
			
		||||
#include "pch.h"
 | 
			
		||||
#include "recompiler_config.h"
 | 
			
		||||
 | 
			
		||||
struct RecompilerLocalVariables
 | 
			
		||||
{
 | 
			
		||||
@@ -22,18 +18,6 @@ struct RecompilerLocalVariables
 | 
			
		||||
    bool ea{};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct RecompilerConfig
 | 
			
		||||
{
 | 
			
		||||
    bool skipLr = false;
 | 
			
		||||
    bool ctrAsLocalVariable = false;
 | 
			
		||||
    bool xerAsLocalVariable = false;
 | 
			
		||||
    bool reservedRegisterAsLocalVariable = false;
 | 
			
		||||
    bool skipMsr = false;
 | 
			
		||||
    bool crRegistersAsLocalVariables = false;
 | 
			
		||||
    bool nonArgumentRegistersAsLocalVariables = false;
 | 
			
		||||
    bool nonVolatileRegistersAsLocalVariables = false;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum class CSRState
 | 
			
		||||
{
 | 
			
		||||
    Unknown,
 | 
			
		||||
@@ -45,15 +29,11 @@ struct Recompiler
 | 
			
		||||
{
 | 
			
		||||
    Image image;
 | 
			
		||||
    std::vector<Function> functions;
 | 
			
		||||
    std::unordered_map<size_t, SwitchTable> switchTables;
 | 
			
		||||
    std::string out;
 | 
			
		||||
    size_t cppFileIndex = 0;
 | 
			
		||||
    uint32_t setJmpAddress = 0;
 | 
			
		||||
    uint32_t longJmpAddress = 0;
 | 
			
		||||
    RecompilerConfig config;
 | 
			
		||||
 | 
			
		||||
    void LoadSwitchTables(const char* filePath);
 | 
			
		||||
    void LoadExecutable(const char* filePath);
 | 
			
		||||
    void LoadConfig(const std::string_view& configFilePath);
 | 
			
		||||
 | 
			
		||||
    template<class... Args>
 | 
			
		||||
    void print(std::format_string<Args...> fmt, Args&&... args)
 | 
			
		||||
@@ -68,18 +48,20 @@ struct Recompiler
 | 
			
		||||
        out += '\n';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Analyse();
 | 
			
		||||
 | 
			
		||||
    // TODO: make a RecompileArgs struct instead this is getting messy
 | 
			
		||||
    bool Recompile(
 | 
			
		||||
        const Function& fn,
 | 
			
		||||
        uint32_t base,
 | 
			
		||||
        const ppc_insn& insn, 
 | 
			
		||||
        std::unordered_map<size_t, SwitchTable>::iterator& switchTable, 
 | 
			
		||||
        std::unordered_map<uint32_t, RecompilerSwitchTable>::iterator& switchTable,
 | 
			
		||||
        RecompilerLocalVariables& localVariables,
 | 
			
		||||
        CSRState& csrState);
 | 
			
		||||
 | 
			
		||||
    bool Recompile(const Function& fn);
 | 
			
		||||
 | 
			
		||||
    void Recompile(const char* directoryPath);
 | 
			
		||||
    void Recompile();
 | 
			
		||||
 | 
			
		||||
    void SaveCurrentOutData(const char* directoryPath, const std::string_view& name = std::string_view());
 | 
			
		||||
    void SaveCurrentOutData(const std::string_view& name = std::string_view());
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										76
									
								
								PowerRecomp/recompiler_config.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								PowerRecomp/recompiler_config.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,76 @@
 | 
			
		||||
#include "recompiler_config.h"
 | 
			
		||||
 | 
			
		||||
void RecompilerConfig::Load(const std::string_view& configFilePath)
 | 
			
		||||
{
 | 
			
		||||
    directoryPath = configFilePath.substr(0, configFilePath.find_last_of("\\/") + 1);
 | 
			
		||||
    toml::table toml = toml::parse_file(configFilePath);
 | 
			
		||||
 | 
			
		||||
    if (auto mainPtr = toml["main"].as_table())
 | 
			
		||||
    {
 | 
			
		||||
        const auto& main = *mainPtr;
 | 
			
		||||
        filePath = main["file_path"].value_or<std::string>("");
 | 
			
		||||
        outDirectoryPath = main["out_directory_path"].value_or<std::string>("");
 | 
			
		||||
        switchTableFilePath = main["switch_table_file_path"].value_or<std::string>("");
 | 
			
		||||
 | 
			
		||||
        skipLr = main["skip_lr"].value_or(false);
 | 
			
		||||
        skipMsr = main["skip_msr"].value_or(false);
 | 
			
		||||
        ctrAsLocalVariable = main["ctr_as_local"].value_or(false);
 | 
			
		||||
        xerAsLocalVariable = main["xer_as_local"].value_or(false);
 | 
			
		||||
        reservedRegisterAsLocalVariable = main["reserved_as_local"].value_or(false);
 | 
			
		||||
        crRegistersAsLocalVariables = main["cr_as_local"].value_or(false);
 | 
			
		||||
        nonArgumentRegistersAsLocalVariables = main["non_argument_as_local"].value_or(false);
 | 
			
		||||
        nonVolatileRegistersAsLocalVariables = main["non_volatile_as_local"].value_or(false);
 | 
			
		||||
 | 
			
		||||
        restGpr14Address = main["restgprlr_14_address"].value_or(0u);
 | 
			
		||||
        saveGpr14Address = main["savegprlr_14_address"].value_or(0u);
 | 
			
		||||
        restFpr14Address = main["restfpr_14_address"].value_or(0u);
 | 
			
		||||
        saveFpr14Address = main["savefpr_14_address"].value_or(0u);
 | 
			
		||||
        restVmx14Address = main["restvmx_14_address"].value_or(0u);
 | 
			
		||||
        saveVmx14Address = main["savevmx_14_address"].value_or(0u);
 | 
			
		||||
        restVmx64Address = main["restvmx_64_address"].value_or(0u);
 | 
			
		||||
        saveVmx64Address = main["savevmx_64_address"].value_or(0u);
 | 
			
		||||
        longJmpAddress = main["longjmp_address"].value_or(0u);
 | 
			
		||||
        setJmpAddress = main["setjmp_address"].value_or(0u);
 | 
			
		||||
 | 
			
		||||
        if (auto functionsArray = main["functions"].as_array())
 | 
			
		||||
        {
 | 
			
		||||
            for (auto& func : *functionsArray)
 | 
			
		||||
            {
 | 
			
		||||
                auto& funcTable = *func.as_table();
 | 
			
		||||
                uint32_t address = *funcTable["address"].value<uint32_t>();
 | 
			
		||||
                uint32_t size = *funcTable["size"].value<uint32_t>();
 | 
			
		||||
                functions.emplace(address, size);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (auto invalidArray = main["invalid_instructions"].as_array())
 | 
			
		||||
        {
 | 
			
		||||
            for (auto& instr : *invalidArray)
 | 
			
		||||
            {
 | 
			
		||||
                auto& instrTable = *instr.as_table();
 | 
			
		||||
                uint32_t data = *instrTable["data"].value<uint32_t>();
 | 
			
		||||
                uint32_t size = *instrTable["size"].value<uint32_t>();
 | 
			
		||||
                invalidInstructions.emplace(data, size);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!switchTableFilePath.empty())
 | 
			
		||||
        {
 | 
			
		||||
            toml::table switchToml = toml::parse_file(directoryPath + switchTableFilePath);
 | 
			
		||||
            if (auto switchArray = switchToml["switch"].as_array())
 | 
			
		||||
            {
 | 
			
		||||
                for (auto& entry : *switchArray)
 | 
			
		||||
                {
 | 
			
		||||
                    auto& table = *entry.as_table();
 | 
			
		||||
                    RecompilerSwitchTable switchTable;
 | 
			
		||||
                    switchTable.r = *table["r"].value<uint32_t>();
 | 
			
		||||
                    for (auto& label : *table["labels"].as_array())
 | 
			
		||||
                    {
 | 
			
		||||
                        switchTable.labels.push_back(*label.value<uint32_t>());
 | 
			
		||||
                    }
 | 
			
		||||
                    switchTables.emplace(*table["base"].value<uint32_t>(), std::move(switchTable));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										38
									
								
								PowerRecomp/recompiler_config.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								PowerRecomp/recompiler_config.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
struct RecompilerSwitchTable
 | 
			
		||||
{
 | 
			
		||||
    uint32_t r;
 | 
			
		||||
    std::vector<uint32_t> labels;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct RecompilerConfig
 | 
			
		||||
{
 | 
			
		||||
    std::string directoryPath;
 | 
			
		||||
    std::string filePath;
 | 
			
		||||
    std::string outDirectoryPath;
 | 
			
		||||
    std::string switchTableFilePath;
 | 
			
		||||
    std::unordered_map<uint32_t, RecompilerSwitchTable> switchTables;
 | 
			
		||||
    bool skipLr = false;
 | 
			
		||||
    bool ctrAsLocalVariable = false;
 | 
			
		||||
    bool xerAsLocalVariable = false;
 | 
			
		||||
    bool reservedRegisterAsLocalVariable = false;
 | 
			
		||||
    bool skipMsr = false;
 | 
			
		||||
    bool crRegistersAsLocalVariables = false;
 | 
			
		||||
    bool nonArgumentRegistersAsLocalVariables = false;
 | 
			
		||||
    bool nonVolatileRegistersAsLocalVariables = false;
 | 
			
		||||
    uint32_t restGpr14Address = 0;
 | 
			
		||||
    uint32_t saveGpr14Address = 0;
 | 
			
		||||
    uint32_t restFpr14Address = 0;
 | 
			
		||||
    uint32_t saveFpr14Address = 0;
 | 
			
		||||
    uint32_t restVmx14Address = 0;
 | 
			
		||||
    uint32_t saveVmx14Address = 0;
 | 
			
		||||
    uint32_t restVmx64Address = 0;
 | 
			
		||||
    uint32_t saveVmx64Address = 0;
 | 
			
		||||
    uint32_t longJmpAddress = 0;
 | 
			
		||||
    uint32_t setJmpAddress = 0;
 | 
			
		||||
    std::unordered_map<uint32_t, uint32_t> functions;
 | 
			
		||||
    std::unordered_map<uint32_t, uint32_t> invalidInstructions;
 | 
			
		||||
 | 
			
		||||
    void Load(const std::string_view& configFilePath);
 | 
			
		||||
};
 | 
			
		||||
@@ -1,208 +0,0 @@
 | 
			
		||||
#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;
 | 
			
		||||
 | 
			
		||||
        std::string name;
 | 
			
		||||
        if (f.base == 0x831B0B40) name = "__restgprlr_14";
 | 
			
		||||
        else if (f.base == 0x831B0AF0) name = "__savegprlr_14";
 | 
			
		||||
        else if (f.base == 0x831B144C) name = "__restfpr_14";
 | 
			
		||||
        else if (f.base == 0x831B1400) name = "__savefpr_14";
 | 
			
		||||
        else if (f.base == 0x831B36E8) name = "__restvmx_14";
 | 
			
		||||
        else if (f.base == 0x831B3450) name = "__savevmx_14";
 | 
			
		||||
        else if (f.base == 0x831B377C) name = "__restvmx_64";
 | 
			
		||||
        else if (f.base == 0x831B34E4) name = "__savevmx_64";
 | 
			
		||||
        else name = std::format("sub_{:X}", f.base);
 | 
			
		||||
 | 
			
		||||
        image.symbols.emplace(name, 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 = [&](uint8_t* data, Function& f)
 | 
			
		||||
        {
 | 
			
		||||
            if (*(uint32_t*)(data + 4) == 0x04000048) f.size = 0x8; // shifted ptr tail call
 | 
			
		||||
            else 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;
 | 
			
		||||
            else if (f.base == 0x8305D168) f.size = 0x278;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
    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 data = section.data + address - section.base;
 | 
			
		||||
                    auto& fn = functions.emplace_back(Function::Analyze(data, section.base + section.size - address, address));
 | 
			
		||||
                    hardcodedFuncCheck(data, fn);
 | 
			
		||||
                    image.symbols.emplace(std::format("sub_{:X}", fn.base), fn.base, fn.size, Symbol_Function);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            data += 4;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        data = section.data;
 | 
			
		||||
 | 
			
		||||
        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;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (*(uint32_t*)data == 0x45564800)
 | 
			
		||||
            {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            auto fnSymbol = image.symbols.find(base);
 | 
			
		||||
            if (fnSymbol != image.symbols.end() && fnSymbol->address == base && fnSymbol->type == Symbol_Function)
 | 
			
		||||
            {
 | 
			
		||||
                assert(fnSymbol->address == base);
 | 
			
		||||
 | 
			
		||||
                base += fnSymbol->size;
 | 
			
		||||
                data += fnSymbol->size;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                auto& fn = functions.emplace_back(Function::Analyze(data, dataEnd - data, base));
 | 
			
		||||
                hardcodedFuncCheck(data, 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; });
 | 
			
		||||
 | 
			
		||||
    setJmpAddress = 0x831B6AB0;
 | 
			
		||||
    longJmpAddress = 0x831B6790;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,7 +0,0 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include "recompiler.h"
 | 
			
		||||
 | 
			
		||||
struct SWARecompiler : Recompiler
 | 
			
		||||
{
 | 
			
		||||
    void Analyse();
 | 
			
		||||
};
 | 
			
		||||
@@ -40,8 +40,12 @@ void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* ds
 | 
			
		||||
    {
 | 
			
		||||
        if (file.path().extension() == ".o")
 | 
			
		||||
        {
 | 
			
		||||
            const auto exeFile = LoadFile(file.path().string().c_str()).value();
 | 
			
		||||
 | 
			
		||||
            TestRecompiler recompiler;
 | 
			
		||||
            recompiler.LoadExecutable(file.path().string().c_str());
 | 
			
		||||
            recompiler.config.outDirectoryPath = dstDirectoryPath;
 | 
			
		||||
            recompiler.image = Image::ParseImage(exeFile.data(), exeFile.size()).value();
 | 
			
		||||
 | 
			
		||||
            auto stem = file.path().stem().string();
 | 
			
		||||
            recompiler.Analyse(stem);
 | 
			
		||||
 | 
			
		||||
@@ -61,7 +65,7 @@ void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* ds
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            stem += ".cpp";
 | 
			
		||||
            recompiler.SaveCurrentOutData(dstDirectoryPath, stem);
 | 
			
		||||
            recompiler.SaveCurrentOutData(stem);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,12 +5,10 @@ add_compile_options(
 | 
			
		||||
    "/fp:strict"
 | 
			
		||||
    "/GS-"
 | 
			
		||||
    "/EHa-"
 | 
			
		||||
    "-march=haswell"
 | 
			
		||||
    "-march=sandybridge"
 | 
			
		||||
    "-fno-strict-aliasing")
 | 
			
		||||
 | 
			
		||||
file(GLOB RecompiledFiles *.cpp)
 | 
			
		||||
add_library(PowerSample ${RecompiledFiles})
 | 
			
		||||
 | 
			
		||||
target_precompile_headers(PowerSample PUBLIC "ppc_recomp_shared.h")
 | 
			
		||||
 | 
			
		||||
target_link_libraries(PowerSample PUBLIC PowerUtils)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user