mirror of
				https://github.com/hedge-dev/XenonRecomp.git
				synced 2025-11-04 06:47:09 +00:00 
			
		
		
		
	Downgrade projects to C++17.
This commit is contained in:
		@@ -1,6 +1,9 @@
 | 
				
			|||||||
cmake_minimum_required (VERSION 3.20)
 | 
					cmake_minimum_required (VERSION 3.20)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include($ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake)
 | 
				
			||||||
set(THIRDPARTY_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty)
 | 
					set(THIRDPARTY_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty)
 | 
				
			||||||
set(CMAKE_CXX_STANDARD 23)
 | 
					
 | 
				
			||||||
 | 
					set(CMAKE_CXX_STANDARD 17)
 | 
				
			||||||
set(BUILD_SHARED_LIBS OFF)
 | 
					set(BUILD_SHARED_LIBS OFF)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Enable Hot Reload for MSVC compilers if supported.
 | 
					# Enable Hot Reload for MSVC compilers if supported.
 | 
				
			||||||
@@ -12,20 +15,6 @@ endif()
 | 
				
			|||||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
 | 
					set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
include("cmake/bin2h.cmake")
 | 
					include("cmake/bin2h.cmake")
 | 
				
			||||||
include(FetchContent)
 | 
					 | 
				
			||||||
FetchContent_Declare(
 | 
					 | 
				
			||||||
    tomlplusplus
 | 
					 | 
				
			||||||
    GIT_REPOSITORY https://github.com/marzer/tomlplusplus.git
 | 
					 | 
				
			||||||
    GIT_TAG        v3.4.0
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
FetchContent_Declare(
 | 
					 | 
				
			||||||
    xxHash
 | 
					 | 
				
			||||||
    GIT_REPOSITORY https://github.com/Cyan4973/xxHash.git
 | 
					 | 
				
			||||||
    GIT_TAG        v0.8.2
 | 
					 | 
				
			||||||
    SOURCE_SUBDIR "cmake_unofficial"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
FetchContent_MakeAvailable(tomlplusplus)
 | 
					 | 
				
			||||||
FetchContent_MakeAvailable(xxHash)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
add_subdirectory(${THIRDPARTY_ROOT}/disasm)
 | 
					add_subdirectory(${THIRDPARTY_ROOT}/disasm)
 | 
				
			||||||
set(POWERANALYSE_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/PowerAnalyse)
 | 
					set(POWERANALYSE_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/PowerAnalyse)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,9 @@ project("PowerAnalyse")
 | 
				
			|||||||
add_executable(PowerAnalyse "main.cpp" "function.h"  "function.cpp")
 | 
					add_executable(PowerAnalyse "main.cpp" "function.h"  "function.cpp")
 | 
				
			||||||
add_library(LibPowerAnalyse "function.h"  "function.cpp")
 | 
					add_library(LibPowerAnalyse "function.h"  "function.cpp")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					find_package(fmt CONFIG REQUIRED)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_include_directories(LibPowerAnalyse PUBLIC .)
 | 
					target_include_directories(LibPowerAnalyse PUBLIC .)
 | 
				
			||||||
target_link_libraries(LibPowerAnalyse PUBLIC PowerUtils)
 | 
					target_link_libraries(LibPowerAnalyse PUBLIC PowerUtils)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(PowerAnalyse PRIVATE PowerUtils)
 | 
					target_link_libraries(PowerAnalyse PRIVATE PowerUtils fmt::fmt)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,6 +4,7 @@
 | 
				
			|||||||
#include <bit>
 | 
					#include <bit>
 | 
				
			||||||
#include <algorithm>
 | 
					#include <algorithm>
 | 
				
			||||||
#include <cassert>
 | 
					#include <cassert>
 | 
				
			||||||
 | 
					#include <byteswap.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
size_t Function::SearchBlock(size_t address) const
 | 
					size_t Function::SearchBlock(size_t address) const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -63,7 +64,7 @@ Function Function::Analyze(const void* code, size_t size, size_t base)
 | 
				
			|||||||
    // TODO: Branch fallthrough
 | 
					    // TODO: Branch fallthrough
 | 
				
			||||||
    for (; data <= dataEnd ; ++data)
 | 
					    for (; data <= dataEnd ; ++data)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        const auto addr = base + ((data - dataStart) * sizeof(*data));
 | 
					        const size_t addr = base + ((data - dataStart) * sizeof(*data));
 | 
				
			||||||
        if (blockStack.empty())
 | 
					        if (blockStack.empty())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            break; // it's hideover
 | 
					            break; // it's hideover
 | 
				
			||||||
@@ -71,11 +72,11 @@ Function Function::Analyze(const void* code, size_t size, size_t base)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        auto& curBlock = blocks[blockStack.back()];
 | 
					        auto& curBlock = blocks[blockStack.back()];
 | 
				
			||||||
        DEBUG(const auto blockBase = curBlock.base);
 | 
					        DEBUG(const auto blockBase = curBlock.base);
 | 
				
			||||||
        const auto instruction = std::byteswap(*data);
 | 
					        const uint32_t instruction = ByteSwap(*data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const auto op = PPC_OP(instruction);
 | 
					        const uint32_t op = PPC_OP(instruction);
 | 
				
			||||||
        const auto xop = PPC_XOP(instruction);
 | 
					        const uint32_t xop = PPC_XOP(instruction);
 | 
				
			||||||
        const auto isLink = PPC_BL(instruction); // call
 | 
					        const uint32_t isLink = PPC_BL(instruction); // call
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ppc_insn insn;
 | 
					        ppc_insn insn;
 | 
				
			||||||
        ppc::Disassemble(data, addr, insn);
 | 
					        ppc::Disassemble(data, addr, insn);
 | 
				
			||||||
@@ -103,13 +104,13 @@ Function Function::Analyze(const void* code, size_t size, size_t base)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            // TODO: Handle absolute branches?
 | 
					            // TODO: Handle absolute branches?
 | 
				
			||||||
            assert(!PPC_BA(instruction));
 | 
					            assert(!PPC_BA(instruction));
 | 
				
			||||||
            const auto branchDest = addr + PPC_BD(instruction);
 | 
					            const size_t branchDest = addr + PPC_BD(instruction);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // true/false paths
 | 
					            // true/false paths
 | 
				
			||||||
            // left block: false case
 | 
					            // left block: false case
 | 
				
			||||||
            // right block: true case
 | 
					            // right block: true case
 | 
				
			||||||
            const auto lBase = (addr - base) + 4;
 | 
					            const size_t lBase = (addr - base) + 4;
 | 
				
			||||||
            const auto rBase = (addr + PPC_BD(instruction)) - base;
 | 
					            const size_t rBase = (addr + PPC_BD(instruction)) - base;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // these will be -1 if it's our first time seeing these blocks
 | 
					            // these will be -1 if it's our first time seeing these blocks
 | 
				
			||||||
            auto lBlock = fn.SearchBlock(base + lBase);
 | 
					            auto lBlock = fn.SearchBlock(base + lBase);
 | 
				
			||||||
@@ -124,7 +125,7 @@ Function Function::Analyze(const void* code, size_t size, size_t base)
 | 
				
			|||||||
                blockStack.emplace_back(lBlock);
 | 
					                blockStack.emplace_back(lBlock);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            auto rBlock = fn.SearchBlock(base + rBase);
 | 
					            size_t rBlock = fn.SearchBlock(base + rBase);
 | 
				
			||||||
            if (rBlock == -1)
 | 
					            if (rBlock == -1)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                blocks.emplace_back(branchDest - base, 0);
 | 
					                blocks.emplace_back(branchDest - base, 0);
 | 
				
			||||||
@@ -145,10 +146,10 @@ Function Function::Analyze(const void* code, size_t size, size_t base)
 | 
				
			|||||||
                if (op == PPC_OP_B)
 | 
					                if (op == PPC_OP_B)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    assert(!PPC_BA(instruction));
 | 
					                    assert(!PPC_BA(instruction));
 | 
				
			||||||
                    const auto branchDest = addr + PPC_BI(instruction);
 | 
					                    const size_t branchDest = addr + PPC_BI(instruction);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    const auto branchBase = branchDest - base;
 | 
					                    const size_t branchBase = branchDest - base;
 | 
				
			||||||
                    const auto branchBlock = fn.SearchBlock(branchDest);
 | 
					                    const size_t branchBlock = fn.SearchBlock(branchDest);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (branchDest < base)
 | 
					                    if (branchDest < base)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
@@ -158,8 +159,8 @@ Function Function::Analyze(const void* code, size_t size, size_t base)
 | 
				
			|||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    // carry over our projection if blocks are next to each other
 | 
					                    // carry over our projection if blocks are next to each other
 | 
				
			||||||
                    const auto isContinuous = branchBase == curBlock.base + curBlock.size;
 | 
					                    const bool isContinuous = branchBase == curBlock.base + curBlock.size;
 | 
				
			||||||
                    auto sizeProjection = (size_t)-1;
 | 
					                    size_t sizeProjection = (size_t)-1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (curBlock.projectedSize != -1 && isContinuous)
 | 
					                    if (curBlock.projectedSize != -1 && isContinuous)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
@@ -180,12 +181,12 @@ Function Function::Analyze(const void* code, size_t size, size_t base)
 | 
				
			|||||||
                else if (op == PPC_OP_CTR)
 | 
					                else if (op == PPC_OP_CTR)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    // 5th bit of BO tells cpu to ignore the counter, which is a blr/bctr otherwise it's conditional
 | 
					                    // 5th bit of BO tells cpu to ignore the counter, which is a blr/bctr otherwise it's conditional
 | 
				
			||||||
                    const auto conditional = !(PPC_BO(instruction) & 0x10);
 | 
					                    const bool conditional = !(PPC_BO(instruction) & 0x10);
 | 
				
			||||||
                    if (conditional)
 | 
					                    if (conditional)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        // right block's just going to return
 | 
					                        // right block's just going to return
 | 
				
			||||||
                        const auto lBase = (addr - base) + 4;
 | 
					                        const size_t lBase = (addr - base) + 4;
 | 
				
			||||||
                        auto lBlock = fn.SearchBlock(lBase);
 | 
					                        size_t lBlock = fn.SearchBlock(lBase);
 | 
				
			||||||
                        if (lBlock == -1)
 | 
					                        if (lBlock == -1)
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            blocks.emplace_back(lBase, 0);
 | 
					                            blocks.emplace_back(lBase, 0);
 | 
				
			||||||
@@ -212,7 +213,7 @@ Function Function::Analyze(const void* code, size_t size, size_t base)
 | 
				
			|||||||
    // Sort and invalidate discontinuous blocks
 | 
					    // Sort and invalidate discontinuous blocks
 | 
				
			||||||
    if (blocks.size() > 1)
 | 
					    if (blocks.size() > 1)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::ranges::sort(blocks, [](const Block& a, const Block& b)
 | 
					        std::sort(blocks.begin(), blocks.end(), [](const Block& a, const Block& b)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return a.base < b.base;
 | 
					            return a.base < b.base;
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef _DEBUG(X)
 | 
					#ifdef _DEBUG
 | 
				
			||||||
#define DEBUG(X) X
 | 
					#define DEBUG(X) X
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
#define DEBUG(X)
 | 
					#define DEBUG(X)
 | 
				
			||||||
@@ -13,15 +13,36 @@ struct Function
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        size_t base{};
 | 
					        size_t base{};
 | 
				
			||||||
        size_t size{};
 | 
					        size_t size{};
 | 
				
			||||||
 | 
					        size_t projectedSize{ static_cast<size_t>(-1) }; // scratch
 | 
				
			||||||
        DEBUG(size_t parent{});
 | 
					        DEBUG(size_t parent{});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // scratch
 | 
					        Block() 
 | 
				
			||||||
        size_t projectedSize{ static_cast<size_t>(-1) };
 | 
					        {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Block(size_t base, size_t size)
 | 
				
			||||||
 | 
					            : base(base), size(size) 
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Block(size_t base, size_t size, size_t projectedSize) 
 | 
				
			||||||
 | 
					            : base(base), size(size), projectedSize(projectedSize)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    size_t base{};
 | 
					    size_t base{};
 | 
				
			||||||
    size_t size{};
 | 
					    size_t size{};
 | 
				
			||||||
    std::vector<Block> blocks{};
 | 
					    std::vector<Block> blocks{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Function()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Function(size_t base, size_t size)
 | 
				
			||||||
 | 
					        : base(base), size(size)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    size_t SearchBlock(size_t address) const;
 | 
					    size_t SearchBlock(size_t address) const;
 | 
				
			||||||
    static Function Analyze(const void* code, size_t size, size_t base);
 | 
					    static Function Analyze(const void* code, size_t size, size_t base);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,10 +1,11 @@
 | 
				
			|||||||
#include <cassert>
 | 
					#include <cassert>
 | 
				
			||||||
 | 
					#include <iterator>
 | 
				
			||||||
#include <file.h>
 | 
					#include <file.h>
 | 
				
			||||||
#include <disasm.h>
 | 
					#include <disasm.h>
 | 
				
			||||||
#include <image.h>
 | 
					#include <image.h>
 | 
				
			||||||
#include "function.h"
 | 
					 | 
				
			||||||
#include <print>
 | 
					 | 
				
			||||||
#include <xbox.h>
 | 
					#include <xbox.h>
 | 
				
			||||||
 | 
					#include <fmt/core.h>
 | 
				
			||||||
 | 
					#include "function.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SWITCH_ABSOLUTE 0
 | 
					#define SWITCH_ABSOLUTE 0
 | 
				
			||||||
#define SWITCH_COMPUTED 1
 | 
					#define SWITCH_COMPUTED 1
 | 
				
			||||||
@@ -139,7 +140,7 @@ void MakeMask(const uint32_t* instructions, size_t count)
 | 
				
			|||||||
    for (size_t i = 0; i < count; i++)
 | 
					    for (size_t i = 0; i < count; i++)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        ppc::Disassemble(&instructions[i], 0, insn);
 | 
					        ppc::Disassemble(&instructions[i], 0, insn);
 | 
				
			||||||
        std::println("0x{:X}, // {}", std::byteswap(insn.opcode->opcode | (insn.instruction & insn.opcode->mask)), insn.opcode->name);
 | 
					        fmt::println("0x{:X}, // {}", ByteSwap(insn.opcode->opcode | (insn.instruction & insn.opcode->mask)), insn.opcode->name);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -173,13 +174,13 @@ void* SearchMask(const void* source, const uint32_t* compare, size_t compareCoun
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
int main()
 | 
					int main()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const auto file = LoadFile("private/default.xex").value();
 | 
					    const auto file = LoadFile("private/default.xex");
 | 
				
			||||||
    auto image = Image::ParseImage(file.data(), file.size()).value();
 | 
					    auto image = Image::ParseImage(file.data(), file.size());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::string out;
 | 
					    std::string out;
 | 
				
			||||||
    auto println = [&]<class... Args>(std::format_string<Args...> fmt, Args&&... args)
 | 
					    auto println = [&]<class... Args>(fmt::format_string<Args...> fmt, Args&&... args)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::vformat_to(std::back_inserter(out), fmt.get(), std::make_format_args(args...));
 | 
					        fmt::vformat_to(std::back_inserter(out), fmt.get(), fmt::make_format_args(args...));
 | 
				
			||||||
        out += '\n';
 | 
					        out += '\n';
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    //for (const auto& section : image.sections)
 | 
					    //for (const auto& section : image.sections)
 | 
				
			||||||
@@ -190,7 +191,7 @@ int main()
 | 
				
			|||||||
    // MakeMask((uint32_t*)image.Find(0x82C40D84), 6);
 | 
					    // MakeMask((uint32_t*)image.Find(0x82C40D84), 6);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //auto data = "\x4D\x99\x00\x20";
 | 
					    //auto data = "\x4D\x99\x00\x20";
 | 
				
			||||||
    //auto data2 = std::byteswap((2129));
 | 
					    //auto data2 = ByteSwap((2129));
 | 
				
			||||||
    //ppc_insn insn;
 | 
					    //ppc_insn insn;
 | 
				
			||||||
    //ppc_insn insn2;
 | 
					    //ppc_insn insn2;
 | 
				
			||||||
    //ppc::Disassemble(data, 0, insn);
 | 
					    //ppc::Disassemble(data, 0, insn);
 | 
				
			||||||
@@ -261,7 +262,7 @@ int main()
 | 
				
			|||||||
                        table.type = type;
 | 
					                        table.type = type;
 | 
				
			||||||
                        ScanTable((uint32_t*)data, base + (data - dataStart), table);
 | 
					                        ScanTable((uint32_t*)data, base + (data - dataStart), table);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        // std::println("{:X} ; jmptable - {}", base + (data - dataStart), table.labels.size());
 | 
					                        // fmt::println("{:X} ; jmptable - {}", base + (data - dataStart), table.labels.size());
 | 
				
			||||||
                        if (table.base != 0)
 | 
					                        if (table.base != 0)
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            ReadTable(image, table);
 | 
					                            ReadTable(image, table);
 | 
				
			||||||
@@ -335,15 +336,15 @@ int main()
 | 
				
			|||||||
    fwrite(out.data(), 1, out.size(), f);
 | 
					    fwrite(out.data(), 1, out.size(), f);
 | 
				
			||||||
    fclose(f);
 | 
					    fclose(f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint32_t cxxFrameHandler = std::byteswap(0x831B1C90);
 | 
					    uint32_t cxxFrameHandler = ByteSwap(0x831B1C90);
 | 
				
			||||||
    uint32_t cSpecificFrameHandler = std::byteswap(0x8324B3BC);
 | 
					    uint32_t cSpecificFrameHandler = ByteSwap(0x8324B3BC);
 | 
				
			||||||
    image.symbols.emplace("__CxxFrameHandler", 0x831B1C90, 0x38, Symbol_Function);
 | 
					    image.symbols.emplace("__CxxFrameHandler", 0x831B1C90, 0x38, Symbol_Function);
 | 
				
			||||||
    image.symbols.emplace("__C_specific_handler", 0x8324B3BC, 0x38, Symbol_Function);
 | 
					    image.symbols.emplace("__C_specific_handler", 0x8324B3BC, 0x38, Symbol_Function);
 | 
				
			||||||
    image.symbols.emplace("memcpy", 0x831B0ED0, 0x488, Symbol_Function);
 | 
					    image.symbols.emplace("memcpy", 0x831B0ED0, 0x488, Symbol_Function);
 | 
				
			||||||
    image.symbols.emplace("memset", 0x831B0BA0, 0xA0, Symbol_Function);
 | 
					    image.symbols.emplace("memset", 0x831B0BA0, 0xA0, Symbol_Function);
 | 
				
			||||||
    image.symbols.emplace("blkmov", 0x831B1358, 0xA8, Symbol_Function);
 | 
					    image.symbols.emplace("blkmov", 0x831B1358, 0xA8, Symbol_Function);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    image.symbols.emplace(std::format("sub_{:X}", 0x82EF5D78), 0x82EF5D78, 0x3F8, Symbol_Function);
 | 
					    image.symbols.emplace(fmt::format("sub_{:X}", 0x82EF5D78), 0x82EF5D78, 0x3F8, Symbol_Function);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // auto fnd = Function::Analyze(image.Find(0x82C40D58), image.size, 0x82C40D58);
 | 
					    // auto fnd = Function::Analyze(image.Find(0x82C40D58), image.size, 0x82C40D58);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -354,8 +355,8 @@ int main()
 | 
				
			|||||||
    for (size_t i = 0; i < count; i++)
 | 
					    for (size_t i = 0; i < count; i++)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        auto fn = pf[i];
 | 
					        auto fn = pf[i];
 | 
				
			||||||
        fn.BeginAddress = std::byteswap(fn.BeginAddress);
 | 
					        fn.BeginAddress = ByteSwap(fn.BeginAddress);
 | 
				
			||||||
        fn.Data = std::byteswap(fn.Data);
 | 
					        fn.Data = ByteSwap(fn.Data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        auto& f = functions.emplace_back();
 | 
					        auto& f = functions.emplace_back();
 | 
				
			||||||
        f.base = fn.BeginAddress;
 | 
					        f.base = fn.BeginAddress;
 | 
				
			||||||
@@ -366,7 +367,7 @@ int main()
 | 
				
			|||||||
            __debugbreak();
 | 
					            __debugbreak();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        image.symbols.emplace(std::format("sub_{:X}", f.base), f.base, f.size, Symbol_Function);
 | 
					        image.symbols.emplace(fmt::format("sub_{:X}", f.base), f.base, f.size, Symbol_Function);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto sym = image.symbols.find(0x82BD7420);
 | 
					    auto sym = image.symbols.find(0x82BD7420);
 | 
				
			||||||
@@ -413,7 +414,7 @@ int main()
 | 
				
			|||||||
                base += missingFn.size;
 | 
					                base += missingFn.size;
 | 
				
			||||||
                data += missingFn.size;
 | 
					                data += missingFn.size;
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                std::println("sub_{:X}", missingFn.base);
 | 
					                fmt::println("sub_{:X}", missingFn.base);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -421,7 +422,7 @@ int main()
 | 
				
			|||||||
    //ppc_insn insn;
 | 
					    //ppc_insn insn;
 | 
				
			||||||
    //uint8_t c[4] = { 0x10, 0x00, 0x59, 0xC3 };
 | 
					    //uint8_t c[4] = { 0x10, 0x00, 0x59, 0xC3 };
 | 
				
			||||||
    //ppc::Disassemble(c, 0x831D6C64, insn);
 | 
					    //ppc::Disassemble(c, 0x831D6C64, insn);
 | 
				
			||||||
    //std::println("{:20}{}", insn.opcode->name, insn.op_str);
 | 
					    //fmt::println("{:20}{}", insn.opcode->name, insn.op_str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const auto entrySymbol = image.symbols.find(image.entry_point);
 | 
					    const auto entrySymbol = image.symbols.find(image.entry_point);
 | 
				
			||||||
@@ -432,21 +433,21 @@ int main()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    image.symbols.emplace("_start", image.entry_point, entrySize, Symbol_Function);
 | 
					    image.symbols.emplace("_start", image.entry_point, entrySize, Symbol_Function);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::println("FUNCTIONS");
 | 
					    fmt::println("FUNCTIONS");
 | 
				
			||||||
    for (const auto& fn : functions)
 | 
					    for (const auto& fn : functions)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::println("\tsub_{:X}", fn.base);
 | 
					        fmt::println("\tsub_{:X}", fn.base);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    std::println("");
 | 
					    fmt::println("");
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::println("SECTIONS");
 | 
					    fmt::println("SECTIONS");
 | 
				
			||||||
    for (const auto& section : image.sections)
 | 
					    for (const auto& section : image.sections)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::printf("Section %.8s\n", section.name.c_str());
 | 
					        printf("Section %.8s\n", section.name.c_str());
 | 
				
			||||||
        std::printf("\t%X-%X\n", section.base, section.base + section.size);
 | 
					        printf("\t%X-%X\n", section.base, section.base + section.size);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::println("");
 | 
					    fmt::println("");
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,7 +6,13 @@ BIN2H(SOURCE_FILE ${POWERUTILS_ROOT}/ppc_context.h HEADER_FILE "generated/ppc_co
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
add_executable(PowerRecomp "main.cpp" "pch.h" "recompiler.cpp" "recompiler.h" "test_recompiler.cpp" "test_recompiler.h" "recompiler_config.h" "recompiler_config.cpp")
 | 
					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_precompile_headers(PowerRecomp PUBLIC "pch.h")
 | 
				
			||||||
target_link_libraries(PowerRecomp PRIVATE LibPowerAnalyse tomlplusplus::tomlplusplus xxHash::xxhash)
 | 
					
 | 
				
			||||||
 | 
					find_package(fmt CONFIG REQUIRED)
 | 
				
			||||||
 | 
					find_package(PkgConfig REQUIRED)
 | 
				
			||||||
 | 
					pkg_check_modules(tomlplusplus REQUIRED IMPORTED_TARGET tomlplusplus)
 | 
				
			||||||
 | 
					find_package(xxHash CONFIG REQUIRED)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					target_link_libraries(PowerRecomp PRIVATE LibPowerAnalyse fmt::fmt PkgConfig::tomlplusplus xxHash::xxhash)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
 | 
					if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
 | 
				
			||||||
    target_compile_options(PowerRecomp PRIVATE -Wno-switch -Wno-unused-variable)
 | 
					    target_compile_options(PowerRecomp PRIVATE -Wno-switch -Wno-unused-variable)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,22 +1,17 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Workaround for the intellisense for some reason not seeing C++23 features
 | 
					 | 
				
			||||||
#ifdef __INTELLISENSE__
 | 
					 | 
				
			||||||
#undef __cplusplus
 | 
					 | 
				
			||||||
#define __cplusplus 202302L
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <cassert>
 | 
					#include <cassert>
 | 
				
			||||||
 | 
					#include <charconv>
 | 
				
			||||||
#include <disasm.h>
 | 
					#include <disasm.h>
 | 
				
			||||||
#include <file.h>
 | 
					#include <file.h>
 | 
				
			||||||
#include <filesystem>
 | 
					#include <filesystem>
 | 
				
			||||||
#include <format>
 | 
					#include <fstream>
 | 
				
			||||||
#include <function.h>
 | 
					#include <function.h>
 | 
				
			||||||
#include <image.h>
 | 
					#include <image.h>
 | 
				
			||||||
#include <print>
 | 
					 | 
				
			||||||
#include <toml++/toml.hpp>
 | 
					#include <toml++/toml.hpp>
 | 
				
			||||||
#include <unordered_map>
 | 
					#include <unordered_map>
 | 
				
			||||||
#include <unordered_set>
 | 
					#include <unordered_set>
 | 
				
			||||||
#include <xbox.h>
 | 
					#include <xbox.h>
 | 
				
			||||||
#include <xxhash.h>
 | 
					#include <xxhash.h>
 | 
				
			||||||
 | 
					#include <fmt/core.h>
 | 
				
			||||||
#include "generated/ppc_context.gen.h"
 | 
					#include "generated/ppc_context.gen.h"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,8 +13,8 @@ void Recompiler::LoadConfig(const std::string_view& configFilePath)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    config.Load(configFilePath);
 | 
					    config.Load(configFilePath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const auto file = LoadFile((config.directoryPath + config.filePath).c_str()).value();
 | 
					    const auto file = LoadFile((config.directoryPath + config.filePath).c_str());
 | 
				
			||||||
    image = Image::ParseImage(file.data(), file.size()).value();
 | 
					    image = Image::ParseImage(file.data(), file.size());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Recompiler::Analyse()
 | 
					void Recompiler::Analyse()
 | 
				
			||||||
@@ -26,32 +26,32 @@ void Recompiler::Analyse()
 | 
				
			|||||||
            auto& restgpr = functions.emplace_back();
 | 
					            auto& restgpr = functions.emplace_back();
 | 
				
			||||||
            restgpr.base = config.restGpr14Address + (i - 14) * 4;
 | 
					            restgpr.base = config.restGpr14Address + (i - 14) * 4;
 | 
				
			||||||
            restgpr.size = (32 - i) * 4 + 12;
 | 
					            restgpr.size = (32 - i) * 4 + 12;
 | 
				
			||||||
            image.symbols.emplace(std::format("__restgprlr_{}", i), restgpr.base, restgpr.size, Symbol_Function);
 | 
					            image.symbols.emplace(Symbol{ fmt::format("__restgprlr_{}", i), restgpr.base, restgpr.size, Symbol_Function });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            auto& savegpr = functions.emplace_back();
 | 
					            auto& savegpr = functions.emplace_back();
 | 
				
			||||||
            savegpr.base = config.saveGpr14Address + (i - 14) * 4;
 | 
					            savegpr.base = config.saveGpr14Address + (i - 14) * 4;
 | 
				
			||||||
            savegpr.size = (32 - i) * 4 + 8;
 | 
					            savegpr.size = (32 - i) * 4 + 8;
 | 
				
			||||||
            image.symbols.emplace(std::format("__savegprlr_{}", i), savegpr.base, savegpr.size, Symbol_Function);
 | 
					            image.symbols.emplace(fmt::format("__savegprlr_{}", i), savegpr.base, savegpr.size, Symbol_Function);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            auto& restfpr = functions.emplace_back();
 | 
					            auto& restfpr = functions.emplace_back();
 | 
				
			||||||
            restfpr.base = config.restFpr14Address + (i - 14) * 4;
 | 
					            restfpr.base = config.restFpr14Address + (i - 14) * 4;
 | 
				
			||||||
            restfpr.size = (32 - i) * 4 + 4;
 | 
					            restfpr.size = (32 - i) * 4 + 4;
 | 
				
			||||||
            image.symbols.emplace(std::format("__restfpr_{}", i), restfpr.base, restfpr.size, Symbol_Function);
 | 
					            image.symbols.emplace(fmt::format("__restfpr_{}", i), restfpr.base, restfpr.size, Symbol_Function);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            auto& savefpr = functions.emplace_back();
 | 
					            auto& savefpr = functions.emplace_back();
 | 
				
			||||||
            savefpr.base = config.saveFpr14Address + (i - 14) * 4;
 | 
					            savefpr.base = config.saveFpr14Address + (i - 14) * 4;
 | 
				
			||||||
            savefpr.size = (32 - i) * 4 + 4;
 | 
					            savefpr.size = (32 - i) * 4 + 4;
 | 
				
			||||||
            image.symbols.emplace(std::format("__savefpr_{}", i), savefpr.base, savefpr.size, Symbol_Function);
 | 
					            image.symbols.emplace(fmt::format("__savefpr_{}", i), savefpr.base, savefpr.size, Symbol_Function);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            auto& restvmx = functions.emplace_back();
 | 
					            auto& restvmx = functions.emplace_back();
 | 
				
			||||||
            restvmx.base = config.restVmx14Address + (i - 14) * 8;
 | 
					            restvmx.base = config.restVmx14Address + (i - 14) * 8;
 | 
				
			||||||
            restvmx.size = (32 - i) * 8 + 4;
 | 
					            restvmx.size = (32 - i) * 8 + 4;
 | 
				
			||||||
            image.symbols.emplace(std::format("__restvmx_{}", i), restvmx.base, restvmx.size, Symbol_Function);
 | 
					            image.symbols.emplace(fmt::format("__restvmx_{}", i), restvmx.base, restvmx.size, Symbol_Function);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            auto& savevmx = functions.emplace_back();
 | 
					            auto& savevmx = functions.emplace_back();
 | 
				
			||||||
            savevmx.base = config.saveVmx14Address + (i - 14) * 8;
 | 
					            savevmx.base = config.saveVmx14Address + (i - 14) * 8;
 | 
				
			||||||
            savevmx.size = (32 - i) * 8 + 4;
 | 
					            savevmx.size = (32 - i) * 8 + 4;
 | 
				
			||||||
            image.symbols.emplace(std::format("__savevmx_{}", i), savevmx.base, savevmx.size, Symbol_Function);
 | 
					            image.symbols.emplace(fmt::format("__savevmx_{}", i), savevmx.base, savevmx.size, Symbol_Function);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (i >= 64)
 | 
					        if (i >= 64)
 | 
				
			||||||
@@ -59,19 +59,19 @@ void Recompiler::Analyse()
 | 
				
			|||||||
            auto& restvmx = functions.emplace_back();
 | 
					            auto& restvmx = functions.emplace_back();
 | 
				
			||||||
            restvmx.base = config.restVmx64Address + (i - 64) * 8;
 | 
					            restvmx.base = config.restVmx64Address + (i - 64) * 8;
 | 
				
			||||||
            restvmx.size = (128 - i) * 8 + 4;
 | 
					            restvmx.size = (128 - i) * 8 + 4;
 | 
				
			||||||
            image.symbols.emplace(std::format("__restvmx_{}", i), restvmx.base, restvmx.size, Symbol_Function);
 | 
					            image.symbols.emplace(fmt::format("__restvmx_{}", i), restvmx.base, restvmx.size, Symbol_Function);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            auto& savevmx = functions.emplace_back();
 | 
					            auto& savevmx = functions.emplace_back();
 | 
				
			||||||
            savevmx.base = config.saveVmx64Address + (i - 64) * 8;
 | 
					            savevmx.base = config.saveVmx64Address + (i - 64) * 8;
 | 
				
			||||||
            savevmx.size = (128 - i) * 8 + 4;
 | 
					            savevmx.size = (128 - i) * 8 + 4;
 | 
				
			||||||
            image.symbols.emplace(std::format("__savevmx_{}", i), savevmx.base, savevmx.size, Symbol_Function);
 | 
					            image.symbols.emplace(fmt::format("__savevmx_{}", i), savevmx.base, savevmx.size, Symbol_Function);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (auto& [address, size] : config.functions)
 | 
					    for (auto& [address, size] : config.functions)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        functions.emplace_back(address, size);
 | 
					        functions.emplace_back(address, size);
 | 
				
			||||||
        image.symbols.emplace(std::format("sub_{:X}", address), address, size, Symbol_Function);
 | 
					        image.symbols.emplace(fmt::format("sub_{:X}", address), address, size, Symbol_Function);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto& pdata = *image.Find(".pdata");
 | 
					    auto& pdata = *image.Find(".pdata");
 | 
				
			||||||
@@ -80,8 +80,8 @@ void Recompiler::Analyse()
 | 
				
			|||||||
    for (size_t i = 0; i < count; i++)
 | 
					    for (size_t i = 0; i < count; i++)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        auto fn = pf[i];
 | 
					        auto fn = pf[i];
 | 
				
			||||||
        fn.BeginAddress = std::byteswap(fn.BeginAddress);
 | 
					        fn.BeginAddress = ByteSwap(fn.BeginAddress);
 | 
				
			||||||
        fn.Data = std::byteswap(fn.Data);
 | 
					        fn.Data = ByteSwap(fn.Data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (image.symbols.find(fn.BeginAddress) == image.symbols.end())
 | 
					        if (image.symbols.find(fn.BeginAddress) == image.symbols.end())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -89,7 +89,7 @@ void Recompiler::Analyse()
 | 
				
			|||||||
            f.base = fn.BeginAddress;
 | 
					            f.base = fn.BeginAddress;
 | 
				
			||||||
            f.size = fn.FunctionLength * 4;
 | 
					            f.size = fn.FunctionLength * 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            image.symbols.emplace(std::format("sub_{:X}", f.base), f.base, f.size, Symbol_Function);
 | 
					            image.symbols.emplace(fmt::format("sub_{:X}", f.base), f.base, f.size, Symbol_Function);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -105,7 +105,7 @@ void Recompiler::Analyse()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        while (data < dataEnd)
 | 
					        while (data < dataEnd)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            uint32_t insn = std::byteswap(*(uint32_t*)data);
 | 
					            uint32_t insn = ByteSwap(*(uint32_t*)data);
 | 
				
			||||||
            if (PPC_OP(insn) == PPC_OP_B && PPC_BL(insn))
 | 
					            if (PPC_OP(insn) == PPC_OP_B && PPC_BL(insn))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                size_t address = base + (data - section.data) + PPC_BI(insn);
 | 
					                size_t address = base + (data - section.data) + PPC_BI(insn);
 | 
				
			||||||
@@ -114,7 +114,7 @@ void Recompiler::Analyse()
 | 
				
			|||||||
                {
 | 
					                {
 | 
				
			||||||
                    auto data = section.data + address - section.base;
 | 
					                    auto data = section.data + address - section.base;
 | 
				
			||||||
                    auto& fn = functions.emplace_back(Function::Analyze(data, section.base + section.size - address, address));
 | 
					                    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);
 | 
					                    image.symbols.emplace(fmt::format("sub_{:X}", fn.base), fn.base, fn.size, Symbol_Function);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            data += 4;
 | 
					            data += 4;
 | 
				
			||||||
@@ -124,7 +124,7 @@ void Recompiler::Analyse()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        while (data < dataEnd)
 | 
					        while (data < dataEnd)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            auto invalidInstr = config.invalidInstructions.find(std::byteswap(*(uint32_t*)data));
 | 
					            auto invalidInstr = config.invalidInstructions.find(ByteSwap(*(uint32_t*)data));
 | 
				
			||||||
            if (invalidInstr != config.invalidInstructions.end())
 | 
					            if (invalidInstr != config.invalidInstructions.end())
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                base += invalidInstr->second;
 | 
					                base += invalidInstr->second;
 | 
				
			||||||
@@ -143,7 +143,7 @@ void Recompiler::Analyse()
 | 
				
			|||||||
            else
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                auto& fn = functions.emplace_back(Function::Analyze(data, dataEnd - data, base));
 | 
					                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);
 | 
					                image.symbols.emplace(fmt::format("sub_{:X}", fn.base), fn.base, fn.size, Symbol_Function);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                base += fn.size;
 | 
					                base += fn.size;
 | 
				
			||||||
                data += fn.size;
 | 
					                data += fn.size;
 | 
				
			||||||
@@ -172,9 +172,9 @@ bool Recompiler::Recompile(
 | 
				
			|||||||
                (config.nonVolatileRegistersAsLocalVariables && index >= 14))
 | 
					                (config.nonVolatileRegistersAsLocalVariables && index >= 14))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                localVariables.r[index] = true;
 | 
					                localVariables.r[index] = true;
 | 
				
			||||||
                return std::format("r{}", index);
 | 
					                return fmt::format("r{}", index);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return std::format("ctx.r{}", index);
 | 
					            return fmt::format("ctx.r{}", index);
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto f = [&](size_t index)
 | 
					    auto f = [&](size_t index)
 | 
				
			||||||
@@ -183,9 +183,9 @@ bool Recompiler::Recompile(
 | 
				
			|||||||
                (config.nonVolatileRegistersAsLocalVariables && index >= 14))
 | 
					                (config.nonVolatileRegistersAsLocalVariables && index >= 14))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                localVariables.f[index] = true;
 | 
					                localVariables.f[index] = true;
 | 
				
			||||||
                return std::format("f{}", index);
 | 
					                return fmt::format("f{}", index);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return std::format("ctx.f{}", index);
 | 
					            return fmt::format("ctx.f{}", index);
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto v = [&](size_t index)
 | 
					    auto v = [&](size_t index)
 | 
				
			||||||
@@ -194,9 +194,9 @@ bool Recompiler::Recompile(
 | 
				
			|||||||
                (config.nonVolatileRegistersAsLocalVariables && ((index >= 14 && index <= 31) || (index >= 64 && index <= 127))))
 | 
					                (config.nonVolatileRegistersAsLocalVariables && ((index >= 14 && index <= 31) || (index >= 64 && index <= 127))))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                localVariables.v[index] = true;
 | 
					                localVariables.v[index] = true;
 | 
				
			||||||
                return std::format("v{}", index);
 | 
					                return fmt::format("v{}", index);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return std::format("ctx.v{}", index);
 | 
					            return fmt::format("ctx.v{}", index);
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto cr = [&](size_t index)
 | 
					    auto cr = [&](size_t index)
 | 
				
			||||||
@@ -204,9 +204,9 @@ bool Recompiler::Recompile(
 | 
				
			|||||||
            if (config.crRegistersAsLocalVariables)
 | 
					            if (config.crRegistersAsLocalVariables)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                localVariables.cr[index] = true;
 | 
					                localVariables.cr[index] = true;
 | 
				
			||||||
                return std::format("cr{}", index);
 | 
					                return fmt::format("cr{}", index);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return std::format("ctx.cr{}", index);
 | 
					            return fmt::format("ctx.cr{}", index);
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto ctr = [&]()
 | 
					    auto ctr = [&]()
 | 
				
			||||||
@@ -287,7 +287,7 @@ bool Recompiler::Recompile(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                if (targetSymbol != image.symbols.end() && targetSymbol->address == address && targetSymbol->type == Symbol_Function)
 | 
					                if (targetSymbol != image.symbols.end() && targetSymbol->address == address && targetSymbol->type == Symbol_Function)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    if (config.nonVolatileRegistersAsLocalVariables && (targetSymbol->name.starts_with("__rest") || targetSymbol->name.starts_with("__save")))
 | 
					                    if (config.nonVolatileRegistersAsLocalVariables && (targetSymbol->name.find("__rest") == 0 || targetSymbol->name.find("__save") == 0))
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        // print nothing
 | 
					                        // print nothing
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
@@ -513,7 +513,7 @@ bool Recompiler::Recompile(
 | 
				
			|||||||
                if (label < fn.base || label >= fn.base + fn.size)
 | 
					                if (label < fn.base || label >= fn.base + fn.size)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    println("\t\t// ERROR: 0x{:X}", label);
 | 
					                    println("\t\t// ERROR: 0x{:X}", label);
 | 
				
			||||||
                    std::println("ERROR: Switch case at {:X} is trying to jump outside function: {:X}", base, label);
 | 
					                    fmt::println("ERROR: Switch case at {:X} is trying to jump outside function: {:X}", base, label);
 | 
				
			||||||
                    println("\t\treturn;");
 | 
					                    println("\t\treturn;");
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
@@ -1897,7 +1897,7 @@ bool Recompiler::Recompile(
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
        case 0: // D3D color
 | 
					        case 0: // D3D color
 | 
				
			||||||
            if (insn.operands[3] != 1 || insn.operands[4] != 3)
 | 
					            if (insn.operands[3] != 1 || insn.operands[4] != 3)
 | 
				
			||||||
                std::println("Unexpected D3D color pack instruction at {:X}", base);
 | 
					                fmt::println("Unexpected D3D color pack instruction at {:X}", base);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            for (size_t i = 0; i < 4; i++)
 | 
					            for (size_t i = 0; i < 4; i++)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
@@ -2145,7 +2145,7 @@ bool Recompiler::Recompile(
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        int lastLine = out.find_last_of('\n', out.size() - 2);
 | 
					        int lastLine = out.find_last_of('\n', out.size() - 2);
 | 
				
			||||||
        if (out.find("cr0", lastLine + 1) == std::string::npos && out.find("cr6", lastLine + 1) == std::string::npos)
 | 
					        if (out.find("cr0", lastLine + 1) == std::string::npos && out.find("cr6", lastLine + 1) == std::string::npos)
 | 
				
			||||||
            std::println("{} at {:X} has RC bit enabled but no comparison was generated", insn.opcode->name, base);
 | 
					            fmt::println("{} at {:X} has RC bit enabled but no comparison was generated", insn.opcode->name, base);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@@ -2163,7 +2163,7 @@ bool Recompiler::Recompile(const Function& fn)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    for (size_t addr = base; addr < end; addr += 4)
 | 
					    for (size_t addr = base; addr < end; addr += 4)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        const uint32_t instruction = std::byteswap(*(uint32_t*)((char*)data + addr - base));
 | 
					        const uint32_t instruction = ByteSwap(*(uint32_t*)((char*)data + addr - base));
 | 
				
			||||||
        if (!PPC_BL(instruction))
 | 
					        if (!PPC_BL(instruction))
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            const size_t op = PPC_OP(instruction);
 | 
					            const size_t op = PPC_OP(instruction);
 | 
				
			||||||
@@ -2248,7 +2248,7 @@ bool Recompiler::Recompile(const Function& fn)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        name = std::format("sub_{}", fn.base);
 | 
					        name = fmt::format("sub_{}", fn.base);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    println("__attribute__((alias(\"__imp__{}\"))) PPC_WEAK_FUNC({});", name, name);
 | 
					    println("__attribute__((alias(\"__imp__{}\"))) PPC_WEAK_FUNC({});", name, name);
 | 
				
			||||||
@@ -2268,7 +2268,7 @@ bool Recompiler::Recompile(const Function& fn)
 | 
				
			|||||||
    ppc_insn insn;
 | 
					    ppc_insn insn;
 | 
				
			||||||
    while (base < end)
 | 
					    while (base < end)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (labels.contains(base))
 | 
					        if (labels.find(base) != labels.end())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            println("loc_{:X}:", base);
 | 
					            println("loc_{:X}:", base);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2286,17 +2286,17 @@ bool Recompiler::Recompile(const Function& fn)
 | 
				
			|||||||
            println("\t// {}", insn.op_str);
 | 
					            println("\t// {}", insn.op_str);
 | 
				
			||||||
#if 1
 | 
					#if 1
 | 
				
			||||||
            if (*data != 0)
 | 
					            if (*data != 0)
 | 
				
			||||||
                std::println("Unable to decode instruction {:X} at {:X}", *data, base);
 | 
					                fmt::println("Unable to decode instruction {:X} at {:X}", *data, base);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (insn.opcode->id == PPC_INST_BCTR && (*(data - 1) == 0x07008038 || *(data - 1) == 0x00000060) && switchTable == config.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);
 | 
					                fmt::println("Found a switch jump table at {:X} with no switch table entry present", base);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!Recompile(fn, base, insn, data, switchTable, localVariables, csrState))
 | 
					            if (!Recompile(fn, base, insn, data, switchTable, localVariables, csrState))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                std::println("Unrecognized instruction at 0x{:X}: {}", base, insn.opcode->name);
 | 
					                fmt::println("Unrecognized instruction at 0x{:X}: {}", base, insn.opcode->name);
 | 
				
			||||||
                allRecompiled = false;
 | 
					                allRecompiled = false;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -2307,7 +2307,7 @@ bool Recompiler::Recompile(const Function& fn)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#if 0
 | 
					#if 0
 | 
				
			||||||
    if (insn.opcode == nullptr || (insn.opcode->id != PPC_INST_B && insn.opcode->id != PPC_INST_BCTR && insn.opcode->id != PPC_INST_BLR))
 | 
					    if (insn.opcode == nullptr || (insn.opcode->id != PPC_INST_B && insn.opcode->id != PPC_INST_BCTR && insn.opcode->id != PPC_INST_BLR))
 | 
				
			||||||
        std::println("Function at {:X} ends prematurely with instruction {} at {:X}", fn.base, insn.opcode != nullptr ? insn.opcode->name : "INVALID", base - 4);
 | 
					        fmt::println("Function at {:X} ends prematurely with instruction {} at {:X}", fn.base, insn.opcode != nullptr ? insn.opcode->name : "INVALID", base - 4);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    println("}}\n");
 | 
					    println("}}\n");
 | 
				
			||||||
@@ -2441,7 +2441,7 @@ void Recompiler::Recompile()
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ((i % 2048) == 0 || (i == (functions.size() - 1)))
 | 
					        if ((i % 2048) == 0 || (i == (functions.size() - 1)))
 | 
				
			||||||
            std::println("Recompiling functions... {}%", static_cast<float>(i + 1) / functions.size() * 100.0f);
 | 
					            fmt::println("Recompiling functions... {}%", static_cast<float>(i + 1) / functions.size() * 100.0f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Recompile(functions[i]);
 | 
					        Recompile(functions[i]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -2457,14 +2457,14 @@ void Recompiler::SaveCurrentOutData(const std::string_view& name)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if (name.empty())
 | 
					        if (name.empty())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            cppName = std::format("ppc_recomp.{}.cpp", cppFileIndex);
 | 
					            cppName = fmt::format("ppc_recomp.{}.cpp", cppFileIndex);
 | 
				
			||||||
            ++cppFileIndex;
 | 
					            ++cppFileIndex;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        bool shouldWrite = true;
 | 
					        bool shouldWrite = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Check if an identical file already exists first to not trigger recompilation
 | 
					        // Check if an identical file already exists first to not trigger recompilation
 | 
				
			||||||
        std::string filePath = std::format("{}/{}/{}", config.directoryPath, config.outDirectoryPath, name.empty() ? cppName : name);
 | 
					        std::string filePath = fmt::format("{}/{}/{}", config.directoryPath, config.outDirectoryPath, name.empty() ? cppName : name);
 | 
				
			||||||
        FILE* f = fopen(filePath.c_str(), "rb");
 | 
					        FILE* f = fopen(filePath.c_str(), "rb");
 | 
				
			||||||
        if (f)
 | 
					        if (f)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,15 +38,15 @@ struct Recompiler
 | 
				
			|||||||
    void LoadConfig(const std::string_view& configFilePath);
 | 
					    void LoadConfig(const std::string_view& configFilePath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    template<class... Args>
 | 
					    template<class... Args>
 | 
				
			||||||
    void print(std::format_string<Args...> fmt, Args&&... args)
 | 
					    void print(fmt::format_string<Args...> fmt, Args&&... args)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::vformat_to(std::back_inserter(out), fmt.get(), std::make_format_args(args...));
 | 
					        fmt::vformat_to(std::back_inserter(out), fmt.get(), fmt::make_format_args(args...));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    template<class... Args>
 | 
					    template<class... Args>
 | 
				
			||||||
    void println(std::format_string<Args...> fmt, Args&&... args)
 | 
					    void println(fmt::format_string<Args...> fmt, Args&&... args)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::vformat_to(std::back_inserter(out), fmt.get(), std::make_format_args(args...));
 | 
					        fmt::vformat_to(std::back_inserter(out), fmt.get(), fmt::make_format_args(args...));
 | 
				
			||||||
        out += '\n';
 | 
					        out += '\n';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -100,14 +100,14 @@ void RecompilerConfig::Load(const std::string_view& configFilePath)
 | 
				
			|||||||
                (midAsmHook.returnOnTrue && midAsmHook.jumpAddressOnTrue != NULL) ||
 | 
					                (midAsmHook.returnOnTrue && midAsmHook.jumpAddressOnTrue != NULL) ||
 | 
				
			||||||
                (midAsmHook.returnOnFalse && midAsmHook.jumpAddressOnFalse != NULL))
 | 
					                (midAsmHook.returnOnFalse && midAsmHook.jumpAddressOnFalse != NULL))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                std::println("{}: can't return and jump at the same time", midAsmHook.name);
 | 
					                fmt::println("{}: can't return and jump at the same time", midAsmHook.name);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if ((midAsmHook.ret || midAsmHook.jumpAddress != NULL) &&
 | 
					            if ((midAsmHook.ret || midAsmHook.jumpAddress != NULL) &&
 | 
				
			||||||
                (midAsmHook.returnOnFalse != NULL || midAsmHook.returnOnTrue != NULL ||
 | 
					                (midAsmHook.returnOnFalse != NULL || midAsmHook.returnOnTrue != NULL ||
 | 
				
			||||||
                    midAsmHook.jumpAddressOnFalse != NULL || midAsmHook.jumpAddressOnTrue != NULL))
 | 
					                    midAsmHook.jumpAddressOnFalse != NULL || midAsmHook.jumpAddressOnTrue != NULL))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                std::println("{}: can't mix direct and conditional return/jump", midAsmHook.name);
 | 
					                fmt::println("{}: can't mix direct and conditional return/jump", midAsmHook.name);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            midAsmHooks.emplace(*table["address"].value<uint32_t>(), std::move(midAsmHook));
 | 
					            midAsmHooks.emplace(*table["address"].value<uint32_t>(), std::move(midAsmHook));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,7 +22,7 @@ void TestRecompiler::Analyse(const std::string_view& testName)
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            auto& fn = functions.emplace_back(Function::Analyze(data, dataEnd - data, base));
 | 
					            auto& fn = functions.emplace_back(Function::Analyze(data, dataEnd - data, base));
 | 
				
			||||||
            image.symbols.emplace(std::format("{}_{:X}", testName, fn.base), fn.base, fn.size, Symbol_Function);
 | 
					            image.symbols.emplace(fmt::format("{}_{:X}", testName, fn.base), fn.base, fn.size, Symbol_Function);
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            base += fn.size;
 | 
					            base += fn.size;
 | 
				
			||||||
            data += fn.size;
 | 
					            data += fn.size;
 | 
				
			||||||
@@ -40,11 +40,11 @@ void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* ds
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        if (file.path().extension() == ".o")
 | 
					        if (file.path().extension() == ".o")
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            const auto exeFile = LoadFile(file.path().string().c_str()).value();
 | 
					            const auto exeFile = LoadFile(file.path().string().c_str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            TestRecompiler recompiler;
 | 
					            TestRecompiler recompiler;
 | 
				
			||||||
            recompiler.config.outDirectoryPath = dstDirectoryPath;
 | 
					            recompiler.config.outDirectoryPath = dstDirectoryPath;
 | 
				
			||||||
            recompiler.image = Image::ParseImage(exeFile.data(), exeFile.size()).value();
 | 
					            recompiler.image = Image::ParseImage(exeFile.data(), exeFile.size());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            auto stem = file.path().stem().string();
 | 
					            auto stem = file.path().stem().string();
 | 
				
			||||||
            recompiler.Analyse(stem);
 | 
					            recompiler.Analyse(stem);
 | 
				
			||||||
@@ -61,7 +61,7 @@ void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* ds
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    std::println("Function {:X} in {} has unimplemented instructions", fn.base, stem);
 | 
					                    fmt::println("Function {:X} in {} has unimplemented instructions", fn.base, stem);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            stem += ".cpp";
 | 
					            stem += ".cpp";
 | 
				
			||||||
@@ -73,7 +73,7 @@ void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* ds
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    for (auto& [fn, addr] : functions)
 | 
					    for (auto& [fn, addr] : functions)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::ifstream in(std::format("{}/{}.dis", srcDirectoryPath, fn));
 | 
					        std::ifstream in(fmt::format("{}/{}.dis", srcDirectoryPath, fn));
 | 
				
			||||||
        if (in.is_open())
 | 
					        if (in.is_open())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            std::string line;
 | 
					            std::string line;
 | 
				
			||||||
@@ -86,30 +86,30 @@ void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* ds
 | 
				
			|||||||
                    size_t address = ~0;
 | 
					                    size_t address = ~0;
 | 
				
			||||||
                    std::from_chars(&line[0], &line[spaceIndex], address, 16);
 | 
					                    std::from_chars(&line[0], &line[spaceIndex], address, 16);
 | 
				
			||||||
                    address &= 0xFFFFF;
 | 
					                    address &= 0xFFFFF;
 | 
				
			||||||
                    if (addr.contains(address))
 | 
					                    if (addr.find(address) != addr.end())
 | 
				
			||||||
                        symbols.emplace(line.substr(spaceIndex + 2, bracketIndex - spaceIndex - 2), std::format("{}_{:X}", fn, address));
 | 
					                        symbols.emplace(line.substr(spaceIndex + 2, bracketIndex - spaceIndex - 2), fmt::format("{}_{:X}", fn, address));
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            std::println("Unable to locate disassembly file for {}", fn);
 | 
					            fmt::println("Unable to locate disassembly file for {}", fn);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    FILE* file = fopen(std::format("{}/main.cpp", dstDirectoryPath).c_str(), "w");
 | 
					    FILE* file = fopen(fmt::format("{}/main.cpp", dstDirectoryPath).c_str(), "w");
 | 
				
			||||||
    std::string main;
 | 
					    std::string main;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::println(file, "#define PPC_CONFIG_H_INCLUDED");
 | 
					    fmt::println(file, "#define PPC_CONFIG_H_INCLUDED");
 | 
				
			||||||
    std::println(file, "#include <ppc_context.h>");
 | 
					    fmt::println(file, "#include <ppc_context.h>");
 | 
				
			||||||
    std::println(file, "#include <Windows.h>");
 | 
					    fmt::println(file, "#include <Windows.h>");
 | 
				
			||||||
    std::println(file, "#include <print>\n");
 | 
					    fmt::println(file, "#include <print>\n");
 | 
				
			||||||
    std::println(file, "#define PPC_CHECK_VALUE_U(f, lhs, rhs) if (lhs != rhs) std::println(#f \" \" #lhs \" EXPECTED \" #rhs \" ACTUAL {{:X}}\", lhs)\n");
 | 
					    fmt::println(file, "#define PPC_CHECK_VALUE_U(f, lhs, rhs) if (lhs != rhs) fmt::println(#f \" \" #lhs \" EXPECTED \" #rhs \" ACTUAL {{:X}}\", lhs)\n");
 | 
				
			||||||
    std::println(file, "#define PPC_CHECK_VALUE_F(f, lhs, rhs) if (lhs != rhs) std::println(#f \" \" #lhs \" EXPECTED \" #rhs \" ACTUAL {{}}\", lhs)\n");
 | 
					    fmt::println(file, "#define PPC_CHECK_VALUE_F(f, lhs, rhs) if (lhs != rhs) fmt::println(#f \" \" #lhs \" EXPECTED \" #rhs \" ACTUAL {{}}\", lhs)\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (auto& [fn, addr] : functions)
 | 
					    for (auto& [fn, addr] : functions)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::ifstream in(std::format("{}/../{}.s", srcDirectoryPath, fn));
 | 
					        std::ifstream in(fmt::format("{}/../{}.s", srcDirectoryPath, fn));
 | 
				
			||||||
        if (in.is_open())
 | 
					        if (in.is_open())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            std::string str;
 | 
					            std::string str;
 | 
				
			||||||
@@ -135,10 +135,10 @@ void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* ds
 | 
				
			|||||||
                        auto symbol = symbols.find(name);
 | 
					                        auto symbol = symbols.find(name);
 | 
				
			||||||
                        if (symbol != symbols.end())
 | 
					                        if (symbol != symbols.end())
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            std::println(file, "PPC_FUNC({});\n", symbol->second);
 | 
					                            fmt::println(file, "PPC_FUNC({});\n", symbol->second);
 | 
				
			||||||
                            std::println(file, "void {}(uint8_t* base) {{", name);
 | 
					                            fmt::println(file, "void {}(uint8_t* base) {{", name);
 | 
				
			||||||
                            std::println(file, "\tPPCContext ctx{{}};");
 | 
					                            fmt::println(file, "\tPPCContext ctx{{}};");
 | 
				
			||||||
                            std::println(file, "\tctx.fpscr.loadFromHost();");
 | 
					                            fmt::println(file, "\tctx.fpscr.loadFromHost();");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                            while (getline() && !str.empty() && str[0] == '#')
 | 
					                            while (getline() && !str.empty() && str[0] == '#')
 | 
				
			||||||
                            {
 | 
					                            {
 | 
				
			||||||
@@ -158,14 +158,14 @@ void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* ds
 | 
				
			|||||||
                                            int commaIndex2 = str.find(',', commaIndex1 + 1);
 | 
					                                            int commaIndex2 = str.find(',', commaIndex1 + 1);
 | 
				
			||||||
                                            int closingBracketIndex = str.find(']', commaIndex2 + 1);
 | 
					                                            int closingBracketIndex = str.find(']', commaIndex2 + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                            std::println(file, "\tctx.{}.u32[3] = 0x{};", reg, str.substr(openingBracketIndex + 1, commaIndex0 - openingBracketIndex - 1));
 | 
					                                            fmt::println(file, "\tctx.{}.u32[3] = 0x{};", reg, str.substr(openingBracketIndex + 1, commaIndex0 - openingBracketIndex - 1));
 | 
				
			||||||
                                            std::println(file, "\tctx.{}.u32[2] = 0x{};", reg, str.substr(commaIndex0 + 2, commaIndex1 - commaIndex0 - 2));
 | 
					                                            fmt::println(file, "\tctx.{}.u32[2] = 0x{};", reg, str.substr(commaIndex0 + 2, commaIndex1 - commaIndex0 - 2));
 | 
				
			||||||
                                            std::println(file, "\tctx.{}.u32[1] = 0x{};", reg, str.substr(commaIndex1 + 2, commaIndex2 - commaIndex1 - 2));
 | 
					                                            fmt::println(file, "\tctx.{}.u32[1] = 0x{};", reg, str.substr(commaIndex1 + 2, commaIndex2 - commaIndex1 - 2));
 | 
				
			||||||
                                            std::println(file, "\tctx.{}.u32[0] = 0x{};", reg, str.substr(commaIndex2 + 2, closingBracketIndex - commaIndex2 - 2));
 | 
					                                            fmt::println(file, "\tctx.{}.u32[0] = 0x{};", reg, str.substr(commaIndex2 + 2, closingBracketIndex - commaIndex2 - 2));
 | 
				
			||||||
                                        }
 | 
					                                        }
 | 
				
			||||||
                                        else
 | 
					                                        else
 | 
				
			||||||
                                        {
 | 
					                                        {
 | 
				
			||||||
                                            std::println(file, "\tctx.{}.{}64 = {};",
 | 
					                                            fmt::println(file, "\tctx.{}.{}64 = {};",
 | 
				
			||||||
                                                reg,
 | 
					                                                reg,
 | 
				
			||||||
                                                str.find('.', secondSpaceIndex) != std::string::npos ? 'f' : 'u',
 | 
					                                                str.find('.', secondSpaceIndex) != std::string::npos ? 'f' : 'u',
 | 
				
			||||||
                                                str.substr(secondSpaceIndex + 1));
 | 
					                                                str.substr(secondSpaceIndex + 1));
 | 
				
			||||||
@@ -183,7 +183,7 @@ void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* ds
 | 
				
			|||||||
                                            {
 | 
					                                            {
 | 
				
			||||||
                                                if (str[i] != ' ')
 | 
					                                                if (str[i] != ' ')
 | 
				
			||||||
                                                {
 | 
					                                                {
 | 
				
			||||||
                                                    std::println(file, "\tbase[0x{} + 0x{:X}] = 0x{}{};", address, j, str[i], str[i + 1]);
 | 
					                                                    fmt::println(file, "\tbase[0x{} + 0x{:X}] = 0x{}{};", address, j, str[i], str[i + 1]);
 | 
				
			||||||
                                                    ++i; // the loop adds another
 | 
					                                                    ++i; // the loop adds another
 | 
				
			||||||
                                                    ++j;
 | 
					                                                    ++j;
 | 
				
			||||||
                                                }
 | 
					                                                }
 | 
				
			||||||
@@ -196,7 +196,7 @@ void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* ds
 | 
				
			|||||||
                            while (getline() && (str.empty() || str[0] != '#'))
 | 
					                            while (getline() && (str.empty() || str[0] != '#'))
 | 
				
			||||||
                                ;
 | 
					                                ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                            std::println(file, "\t{}(ctx, base);", symbol->second);
 | 
					                            fmt::println(file, "\t{}(ctx, base);", symbol->second);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                            do
 | 
					                            do
 | 
				
			||||||
                            {
 | 
					                            {
 | 
				
			||||||
@@ -218,14 +218,14 @@ void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* ds
 | 
				
			|||||||
                                            int commaIndex2 = str.find(',', commaIndex1 + 1);
 | 
					                                            int commaIndex2 = str.find(',', commaIndex1 + 1);
 | 
				
			||||||
                                            int closingBracketIndex = str.find(']', commaIndex2 + 1);
 | 
					                                            int closingBracketIndex = str.find(']', commaIndex2 + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                            std::println(file, "\tPPC_CHECK_VALUE_U({}, ctx.{}.u32[3], 0x{});", name, reg, str.substr(openingBracketIndex + 1, commaIndex0 - openingBracketIndex - 1));
 | 
					                                            fmt::println(file, "\tPPC_CHECK_VALUE_U({}, ctx.{}.u32[3], 0x{});", name, reg, str.substr(openingBracketIndex + 1, commaIndex0 - openingBracketIndex - 1));
 | 
				
			||||||
                                            std::println(file, "\tPPC_CHECK_VALUE_U({}, ctx.{}.u32[2], 0x{});", name, reg, str.substr(commaIndex0 + 2, commaIndex1 - commaIndex0 - 2));
 | 
					                                            fmt::println(file, "\tPPC_CHECK_VALUE_U({}, ctx.{}.u32[2], 0x{});", name, reg, str.substr(commaIndex0 + 2, commaIndex1 - commaIndex0 - 2));
 | 
				
			||||||
                                            std::println(file, "\tPPC_CHECK_VALUE_U({}, ctx.{}.u32[1], 0x{});", name, reg, str.substr(commaIndex1 + 2, commaIndex2 - commaIndex1 - 2));
 | 
					                                            fmt::println(file, "\tPPC_CHECK_VALUE_U({}, ctx.{}.u32[1], 0x{});", name, reg, str.substr(commaIndex1 + 2, commaIndex2 - commaIndex1 - 2));
 | 
				
			||||||
                                            std::println(file, "\tPPC_CHECK_VALUE_U({}, ctx.{}.u32[0], 0x{});", name, reg, str.substr(commaIndex2 + 2, closingBracketIndex - commaIndex2 - 2));
 | 
					                                            fmt::println(file, "\tPPC_CHECK_VALUE_U({}, ctx.{}.u32[0], 0x{});", name, reg, str.substr(commaIndex2 + 2, closingBracketIndex - commaIndex2 - 2));
 | 
				
			||||||
                                        }
 | 
					                                        }
 | 
				
			||||||
                                        else
 | 
					                                        else
 | 
				
			||||||
                                        {
 | 
					                                        {
 | 
				
			||||||
                                            std::println(file, "\tPPC_CHECK_VALUE_{}({}, ctx.{}.{}64, {});",
 | 
					                                            fmt::println(file, "\tPPC_CHECK_VALUE_{}({}, ctx.{}.{}64, {});",
 | 
				
			||||||
                                                str.find('.', secondSpaceIndex) != std::string::npos ? 'F' : 'U',
 | 
					                                                str.find('.', secondSpaceIndex) != std::string::npos ? 'F' : 'U',
 | 
				
			||||||
                                                name,
 | 
					                                                name,
 | 
				
			||||||
                                                reg,
 | 
					                                                reg,
 | 
				
			||||||
@@ -245,7 +245,7 @@ void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* ds
 | 
				
			|||||||
                                            {
 | 
					                                            {
 | 
				
			||||||
                                                if (str[i] != ' ')
 | 
					                                                if (str[i] != ' ')
 | 
				
			||||||
                                                {
 | 
					                                                {
 | 
				
			||||||
                                                    std::println(file, "\tPPC_CHECK_VALUE_U({}, base[0x{} + 0x{:X}], 0x{}{});", name, address, j, str[i], str[i + 1]);
 | 
					                                                    fmt::println(file, "\tPPC_CHECK_VALUE_U({}, base[0x{} + 0x{:X}], 0x{}{});", name, address, j, str[i], str[i + 1]);
 | 
				
			||||||
                                                    ++i; // the loop adds another
 | 
					                                                    ++i; // the loop adds another
 | 
				
			||||||
                                                    ++j;
 | 
					                                                    ++j;
 | 
				
			||||||
                                                }
 | 
					                                                }
 | 
				
			||||||
@@ -255,13 +255,13 @@ void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* ds
 | 
				
			|||||||
                                }
 | 
					                                }
 | 
				
			||||||
                            } while (getline() && !str.empty() && str[0] == '#');
 | 
					                            } while (getline() && !str.empty() && str[0] == '#');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                            std::println(file, "}}\n");
 | 
					                            fmt::println(file, "}}\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                            std::format_to(std::back_inserter(main), "\t{}(base);\n", name);
 | 
					                            fmt::format_to(std::back_inserter(main), "\t{}(base);\n", name);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        else
 | 
					                        else
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            std::println("Found no symbol for {}", name);
 | 
					                            fmt::println("Found no symbol for {}", name);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@@ -269,15 +269,15 @@ void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* ds
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            std::println("Unable to locate source file for {}", fn);
 | 
					            fmt::println("Unable to locate source file for {}", fn);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::println(file, "int main() {{");
 | 
					    fmt::println(file, "int main() {{");
 | 
				
			||||||
    std::println(file, "\tuint8_t* base = reinterpret_cast<uint8_t*>(VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE));");
 | 
					    fmt::println(file, "\tuint8_t* base = reinterpret_cast<uint8_t*>(VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE));");
 | 
				
			||||||
    fwrite(main.data(), 1, main.size(), file);
 | 
					    fwrite(main.data(), 1, main.size(), file);
 | 
				
			||||||
    std::println(file, "\treturn 0;");
 | 
					    fmt::println(file, "\treturn 0;");
 | 
				
			||||||
    std::println(file, "}}");
 | 
					    fmt::println(file, "}}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fclose(file);
 | 
					    fclose(file);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
project("PowerUtils")
 | 
					project("PowerUtils")
 | 
				
			||||||
add_library(PowerUtils "disasm.h" "disasm.cpp" "file.h" "xex.cpp" "image.h" "image.cpp" "elf.h" "ppc_context.h" "symbol.h" "symbol_table.h" "section.h" "xdbf_wrapper.cpp")
 | 
					add_library(PowerUtils "disasm.h" "disasm.cpp" "file.h" "xex.cpp" "image.h" "image.cpp" "elf.h" "ppc_context.h" "symbol.h" "symbol_table.h" "section.h" "xdbf_wrapper.cpp" "byteswap.h")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_include_directories(PowerUtils PUBLIC .)
 | 
					target_include_directories(PowerUtils PUBLIC .)
 | 
				
			||||||
target_link_libraries(PowerUtils PUBLIC disasm)
 | 
					target_link_libraries(PowerUtils PUBLIC disasm)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										25
									
								
								PowerUtils/byteswap.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								PowerUtils/byteswap.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					#pragma once 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cassert>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					inline T ByteSwap(T value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if constexpr (sizeof(T) == 1)
 | 
				
			||||||
 | 
					        return value;
 | 
				
			||||||
 | 
					    else if constexpr (sizeof(T) == 2)
 | 
				
			||||||
 | 
					        return static_cast<T>(__builtin_bswap16(static_cast<uint16_t>(value)));
 | 
				
			||||||
 | 
					    else if constexpr (sizeof(T) == 4)
 | 
				
			||||||
 | 
					        return static_cast<T>(__builtin_bswap32(static_cast<uint32_t>(value)));
 | 
				
			||||||
 | 
					    else if constexpr (sizeof(T) == 8)
 | 
				
			||||||
 | 
					        return static_cast<T>(__builtin_bswap64(static_cast<uint64_t>(value)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert(false && "Unexpected byte size.");
 | 
				
			||||||
 | 
					    return value;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					inline void ByteSwapInplace(T& value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    value = ByteSwap(value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,14 +1,14 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
#include <expected>
 | 
					
 | 
				
			||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
inline static std::expected<std::vector<uint8_t>, int> LoadFile(const char* path)
 | 
					inline std::vector<uint8_t> LoadFile(const char* path)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    std::vector<uint8_t> data{};
 | 
					    std::vector<uint8_t> data{};
 | 
				
			||||||
    auto* stream = fopen(path, "rb");
 | 
					    auto* stream = fopen(path, "rb");
 | 
				
			||||||
    if (stream == nullptr)
 | 
					    if (stream == nullptr)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return std::unexpected(1);
 | 
					        return {};
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fseek(stream, 0, SEEK_END);
 | 
					    fseek(stream, 0, SEEK_END);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,8 +5,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void Image::Map(const std::string_view& name, size_t base, uint32_t size, uint8_t flags, uint8_t* data)
 | 
					void Image::Map(const std::string_view& name, size_t base, uint32_t size, uint8_t flags, uint8_t* data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    sections.emplace(std::string(name), this->base + base, 
 | 
					    sections.insert({ std::string(name), this->base + base,
 | 
				
			||||||
        size, static_cast<SectionFlags>(flags), data);
 | 
					        size, static_cast<SectionFlags>(flags), data });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const void* Image::Find(size_t address) const
 | 
					const void* Image::Find(size_t address) const
 | 
				
			||||||
@@ -28,7 +28,7 @@ const Section* Image::Find(const std::string_view& name) const
 | 
				
			|||||||
    return nullptr;
 | 
					    return nullptr;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::expected<Image, int> Image::ParseImage(const uint8_t* data, size_t size)
 | 
					Image Image::ParseImage(const uint8_t* data, size_t size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (data[0] == ELFMAG0 && data[1] == ELFMAG1 && data[2] == ELFMAG2 && data[3] == ELFMAG3)
 | 
					    if (data[0] == ELFMAG0 && data[1] == ELFMAG1 && data[2] == ELFMAG2 && data[3] == ELFMAG3)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -39,7 +39,7 @@ std::expected<Image, int> Image::ParseImage(const uint8_t* data, size_t size)
 | 
				
			|||||||
        return Xex2LoadImage(data);
 | 
					        return Xex2LoadImage(data);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return std::unexpected(1);
 | 
					    return {};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Image ElfLoadImage(const uint8_t* data, size_t size)
 | 
					Image ElfLoadImage(const uint8_t* data, size_t size)
 | 
				
			||||||
@@ -50,27 +50,27 @@ Image ElfLoadImage(const uint8_t* data, size_t size)
 | 
				
			|||||||
    Image image{};
 | 
					    Image image{};
 | 
				
			||||||
    image.size = size;
 | 
					    image.size = size;
 | 
				
			||||||
    image.data = std::make_unique<uint8_t[]>(size);
 | 
					    image.data = std::make_unique<uint8_t[]>(size);
 | 
				
			||||||
    image.entry_point = std::byteswap(header->e_entry);
 | 
					    image.entry_point = ByteSwap(header->e_entry);
 | 
				
			||||||
    memcpy(image.data.get(), data, size);
 | 
					    memcpy(image.data.get(), data, size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto stringTableIndex = std::byteswap(header->e_shstrndx);
 | 
					    auto stringTableIndex = ByteSwap(header->e_shstrndx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const auto numSections = std::byteswap(header->e_shnum);
 | 
					    const auto numSections = ByteSwap(header->e_shnum);
 | 
				
			||||||
    const auto numpSections = std::byteswap(header->e_phnum);
 | 
					    const auto numpSections = ByteSwap(header->e_phnum);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const auto* sections = (elf32_shdr*)(data + std::byteswap(header->e_shoff));
 | 
					    const auto* sections = (elf32_shdr*)(data + ByteSwap(header->e_shoff));
 | 
				
			||||||
    const auto* psections = (elf32_phdr*)(data + std::byteswap(header->e_phoff));
 | 
					    const auto* psections = (elf32_phdr*)(data + ByteSwap(header->e_phoff));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (size_t i = 0; i < numpSections; i++)
 | 
					    for (size_t i = 0; i < numpSections; i++)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (psections[i].p_type == std::byteswap((Elf32_Word)PT_LOAD))
 | 
					        if (psections[i].p_type == ByteSwap((Elf32_Word)PT_LOAD))
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            image.base = std::byteswap(psections[i].p_vaddr);
 | 
					            image.base = ByteSwap(psections[i].p_vaddr);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto* stringTable = reinterpret_cast<const char*>(data + std::byteswap(sections[stringTableIndex].sh_offset));
 | 
					    auto* stringTable = reinterpret_cast<const char*>(data + ByteSwap(sections[stringTableIndex].sh_offset));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (size_t i = 0; i < numSections; i++)
 | 
					    for (size_t i = 0; i < numSections; i++)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -82,16 +82,16 @@ Image ElfLoadImage(const uint8_t* data, size_t size)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        uint8_t flags{};
 | 
					        uint8_t flags{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (section.sh_flags & std::byteswap(SHF_EXECINSTR))
 | 
					        if (section.sh_flags & ByteSwap(SHF_EXECINSTR))
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            flags |= SectionFlags_Code;
 | 
					            flags |= SectionFlags_Code;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        auto* name = section.sh_name != 0 ? stringTable + std::byteswap(section.sh_name) : nullptr;
 | 
					        auto* name = section.sh_name != 0 ? stringTable + ByteSwap(section.sh_name) : nullptr;
 | 
				
			||||||
        const auto rva = std::byteswap(section.sh_addr) - image.base;
 | 
					        const auto rva = ByteSwap(section.sh_addr) - image.base;
 | 
				
			||||||
        const auto size = std::byteswap(section.sh_size);
 | 
					        const auto size = ByteSwap(section.sh_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        image.Map(name, rva, size, flags, image.data.get() + std::byteswap(section.sh_offset));
 | 
					        image.Map(name, rva, size, flags, image.data.get() + ByteSwap(section.sh_offset));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return image;
 | 
					    return image;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -44,7 +44,7 @@ struct Image
 | 
				
			|||||||
     * \param size Size of data
 | 
					     * \param size Size of data
 | 
				
			||||||
     * \return Parsed image
 | 
					     * \return Parsed image
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    static std::expected<Image, int> ParseImage(const uint8_t* data, size_t size);
 | 
					    static Image ParseImage(const uint8_t* data, size_t size);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Image ElfLoadImage(const uint8_t* data, size_t size);
 | 
					Image ElfLoadImage(const uint8_t* data, size_t size);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,9 +13,18 @@ enum SymbolType
 | 
				
			|||||||
struct Symbol
 | 
					struct Symbol
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    mutable std::string name{};
 | 
					    mutable std::string name{};
 | 
				
			||||||
    uint32_t address{};
 | 
					    size_t address{};
 | 
				
			||||||
    uint32_t size{};
 | 
					    size_t size{};
 | 
				
			||||||
    mutable SymbolType type{};
 | 
					    mutable SymbolType type{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Symbol()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Symbol(std::string name, size_t address, size_t size, SymbolType type)
 | 
				
			||||||
 | 
					        : name(std::move(name)), address(address), size(size), type(type)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct SymbolComparer
 | 
					struct SymbolComparer
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,7 @@
 | 
				
			|||||||
#include <type_traits>
 | 
					#include <type_traits>
 | 
				
			||||||
#include <bit>
 | 
					#include <bit>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include "byteswap.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef _WIN32
 | 
					#ifdef _WIN32
 | 
				
			||||||
    #include <windows.h>
 | 
					    #include <windows.h>
 | 
				
			||||||
@@ -81,22 +81,22 @@ struct be
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        if constexpr (std::is_same_v<T, double>)
 | 
					        if constexpr (std::is_same_v<T, double>)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            const uint64_t swapped = std::byteswap(*reinterpret_cast<uint64_t*>(&value));
 | 
					            const uint64_t swapped = ByteSwap(*reinterpret_cast<uint64_t*>(&value));
 | 
				
			||||||
            return *reinterpret_cast<const T*>(&swapped);
 | 
					            return *reinterpret_cast<const T*>(&swapped);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if constexpr (std::is_same_v<T, float>)
 | 
					        else if constexpr (std::is_same_v<T, float>)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            const uint32_t swapped = std::byteswap(*reinterpret_cast<uint32_t*>(&value));
 | 
					            const uint32_t swapped = ByteSwap(*reinterpret_cast<uint32_t*>(&value));
 | 
				
			||||||
            return *reinterpret_cast<const T*>(&swapped);
 | 
					            return *reinterpret_cast<const T*>(&swapped);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if constexpr (std::is_enum_v<T>)
 | 
					        else if constexpr (std::is_enum_v<T>)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            const std::underlying_type_t<T> swapped = std::byteswap(*reinterpret_cast<std::underlying_type_t<T>*>(&value));
 | 
					            const std::underlying_type_t<T> swapped = ByteSwap(*reinterpret_cast<std::underlying_type_t<T>*>(&value));
 | 
				
			||||||
            return *reinterpret_cast<const T*>(&swapped);
 | 
					            return *reinterpret_cast<const T*>(&swapped);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return std::byteswap(value);
 | 
					            return ByteSwap(value);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -126,7 +126,7 @@ Image Xex2LoadImage(const uint8_t* data)
 | 
				
			|||||||
            {
 | 
					            {
 | 
				
			||||||
                auto originalThunk = (XEX_THUNK_DATA*)image.Find(descriptors[im].FirstThunk);
 | 
					                auto originalThunk = (XEX_THUNK_DATA*)image.Find(descriptors[im].FirstThunk);
 | 
				
			||||||
                auto originalData = originalThunk;
 | 
					                auto originalData = originalThunk;
 | 
				
			||||||
                originalData->Data = std::byteswap(originalData->Data);
 | 
					                originalData->Data = ByteSwap(originalData->Data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (originalData->OriginalData.Type != 0)
 | 
					                if (originalData->OriginalData.Type != 0)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
@@ -134,7 +134,7 @@ Image Xex2LoadImage(const uint8_t* data)
 | 
				
			|||||||
                    auto name = names->find(originalData->OriginalData.Ordinal);
 | 
					                    auto name = names->find(originalData->OriginalData.Ordinal);
 | 
				
			||||||
                    if (name != names->end())
 | 
					                    if (name != names->end())
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        image.symbols.emplace(name->second, descriptors[im].FirstThunk, sizeof(thunk), Symbol_Function);
 | 
					                        image.symbols.insert({ name->second, descriptors[im].FirstThunk, sizeof(thunk), Symbol_Function });
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    memcpy(originalThunk, thunk, sizeof(thunk));
 | 
					                    memcpy(originalThunk, thunk, sizeof(thunk));
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										12
									
								
								vcpkg.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								vcpkg.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "builtin-baseline": "e63bd09dc0b7204467705c1c7c71d0e2a3f8860b",
 | 
				
			||||||
 | 
					    "dependencies": [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            "name": "pkgconf",
 | 
				
			||||||
 | 
					            "platform": "windows"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "fmt",
 | 
				
			||||||
 | 
					        "tomlplusplus",
 | 
				
			||||||
 | 
					        "xxhash"
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user