mirror of
				https://github.com/hedge-dev/XenonRecomp.git
				synced 2025-10-30 07:11:38 +00:00 
			
		
		
		
	Downgrade projects to C++17.
This commit is contained in:
		
							parent
							
								
									02d23b3463
								
							
						
					
					
						commit
						847842cd28
					
				
					 20 changed files with 250 additions and 189 deletions
				
			
		|  | @ -1,6 +1,9 @@ | |||
| cmake_minimum_required (VERSION 3.20) | ||||
| 
 | ||||
| include($ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake) | ||||
| set(THIRDPARTY_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty) | ||||
| set(CMAKE_CXX_STANDARD 23) | ||||
| 
 | ||||
| set(CMAKE_CXX_STANDARD 17) | ||||
| set(BUILD_SHARED_LIBS OFF) | ||||
| 
 | ||||
| # Enable Hot Reload for MSVC compilers if supported. | ||||
|  | @ -12,20 +15,6 @@ endif() | |||
| set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>") | ||||
| 
 | ||||
| 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) | ||||
| set(POWERANALYSE_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/PowerAnalyse) | ||||
|  |  | |||
|  | @ -5,7 +5,9 @@ project("PowerAnalyse") | |||
| add_executable(PowerAnalyse "main.cpp" "function.h"  "function.cpp") | ||||
| add_library(LibPowerAnalyse "function.h"  "function.cpp") | ||||
| 
 | ||||
| find_package(fmt CONFIG REQUIRED) | ||||
| 
 | ||||
| target_include_directories(LibPowerAnalyse PUBLIC .) | ||||
| 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 <algorithm> | ||||
| #include <cassert> | ||||
| #include <byteswap.h> | ||||
| 
 | ||||
| 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
 | ||||
|     for (; data <= dataEnd ; ++data) | ||||
|     { | ||||
|         const auto addr = base + ((data - dataStart) * sizeof(*data)); | ||||
|         const size_t addr = base + ((data - dataStart) * sizeof(*data)); | ||||
|         if (blockStack.empty()) | ||||
|         { | ||||
|             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()]; | ||||
|         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 auto xop = PPC_XOP(instruction); | ||||
|         const auto isLink = PPC_BL(instruction); // call
 | ||||
|         const uint32_t op = PPC_OP(instruction); | ||||
|         const uint32_t xop = PPC_XOP(instruction); | ||||
|         const uint32_t isLink = PPC_BL(instruction); // call
 | ||||
| 
 | ||||
|         ppc_insn 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?
 | ||||
|             assert(!PPC_BA(instruction)); | ||||
|             const auto branchDest = addr + PPC_BD(instruction); | ||||
|             const size_t branchDest = addr + PPC_BD(instruction); | ||||
| 
 | ||||
|             // true/false paths
 | ||||
|             // left block: false case
 | ||||
|             // right block: true case
 | ||||
|             const auto lBase = (addr - base) + 4; | ||||
|             const auto rBase = (addr + PPC_BD(instruction)) - base; | ||||
|             const size_t lBase = (addr - base) + 4; | ||||
|             const size_t rBase = (addr + PPC_BD(instruction)) - base; | ||||
| 
 | ||||
|             // these will be -1 if it's our first time seeing these blocks
 | ||||
|             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); | ||||
|             } | ||||
| 
 | ||||
|             auto rBlock = fn.SearchBlock(base + rBase); | ||||
|             size_t rBlock = fn.SearchBlock(base + rBase); | ||||
|             if (rBlock == -1) | ||||
|             { | ||||
|                 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) | ||||
|                 { | ||||
|                     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 auto branchBlock = fn.SearchBlock(branchDest); | ||||
|                     const size_t branchBase = branchDest - base; | ||||
|                     const size_t branchBlock = fn.SearchBlock(branchDest); | ||||
| 
 | ||||
|                     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
 | ||||
|                     const auto isContinuous = branchBase == curBlock.base + curBlock.size; | ||||
|                     auto sizeProjection = (size_t)-1; | ||||
|                     const bool isContinuous = branchBase == curBlock.base + curBlock.size; | ||||
|                     size_t sizeProjection = (size_t)-1; | ||||
| 
 | ||||
|                     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) | ||||
|                 { | ||||
|                     // 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) | ||||
|                     { | ||||
|                         // right block's just going to return
 | ||||
|                         const auto lBase = (addr - base) + 4; | ||||
|                         auto lBlock = fn.SearchBlock(lBase); | ||||
|                         const size_t lBase = (addr - base) + 4; | ||||
|                         size_t lBlock = fn.SearchBlock(lBase); | ||||
|                         if (lBlock == -1) | ||||
|                         { | ||||
|                             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
 | ||||
|     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; | ||||
|         }); | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| #pragma once | ||||
| #include <vector> | ||||
| 
 | ||||
| #ifdef _DEBUG(X) | ||||
| #ifdef _DEBUG | ||||
| #define DEBUG(X) X | ||||
| #else | ||||
| #define DEBUG(X) | ||||
|  | @ -13,15 +13,36 @@ struct Function | |||
|     { | ||||
|         size_t base{}; | ||||
|         size_t size{}; | ||||
|         size_t projectedSize{ static_cast<size_t>(-1) }; // scratch
 | ||||
|         DEBUG(size_t parent{}); | ||||
| 
 | ||||
|         // scratch
 | ||||
|         size_t projectedSize{ static_cast<size_t>(-1) }; | ||||
|         Block()  | ||||
|         { | ||||
|         } | ||||
| 
 | ||||
|         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 size{}; | ||||
|     std::vector<Block> blocks{}; | ||||
| 
 | ||||
|     Function() | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     Function(size_t base, size_t size) | ||||
|         : base(base), size(size) | ||||
|     { | ||||
|     } | ||||
|      | ||||
|     size_t SearchBlock(size_t address) const; | ||||
|     static Function Analyze(const void* code, size_t size, size_t base); | ||||
|  |  | |||
|  | @ -1,10 +1,11 @@ | |||
| #include <cassert> | ||||
| #include <iterator> | ||||
| #include <file.h> | ||||
| #include <disasm.h> | ||||
| #include <image.h> | ||||
| #include "function.h" | ||||
| #include <print> | ||||
| #include <xbox.h> | ||||
| #include <fmt/core.h> | ||||
| #include "function.h" | ||||
| 
 | ||||
| #define SWITCH_ABSOLUTE 0 | ||||
| #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++) | ||||
|     { | ||||
|         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() | ||||
| { | ||||
|     const auto file = LoadFile("private/default.xex").value(); | ||||
|     auto image = Image::ParseImage(file.data(), file.size()).value(); | ||||
|     const auto file = LoadFile("private/default.xex"); | ||||
|     auto image = Image::ParseImage(file.data(), file.size()); | ||||
| 
 | ||||
|     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'; | ||||
|     }; | ||||
|     //for (const auto& section : image.sections)
 | ||||
|  | @ -190,7 +191,7 @@ int main() | |||
|     // MakeMask((uint32_t*)image.Find(0x82C40D84), 6);
 | ||||
| 
 | ||||
|     //auto data = "\x4D\x99\x00\x20";
 | ||||
|     //auto data2 = std::byteswap((2129));
 | ||||
|     //auto data2 = ByteSwap((2129));
 | ||||
|     //ppc_insn insn;
 | ||||
|     //ppc_insn insn2;
 | ||||
|     //ppc::Disassemble(data, 0, insn);
 | ||||
|  | @ -261,7 +262,7 @@ int main() | |||
|                         table.type = type; | ||||
|                         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) | ||||
|                         { | ||||
|                             ReadTable(image, table); | ||||
|  | @ -335,15 +336,15 @@ int main() | |||
|     fwrite(out.data(), 1, out.size(), f); | ||||
|     fclose(f); | ||||
| 
 | ||||
|     uint32_t cxxFrameHandler = std::byteswap(0x831B1C90); | ||||
|     uint32_t cSpecificFrameHandler = std::byteswap(0x8324B3BC); | ||||
|     uint32_t cxxFrameHandler = ByteSwap(0x831B1C90); | ||||
|     uint32_t cSpecificFrameHandler = ByteSwap(0x8324B3BC); | ||||
|     image.symbols.emplace("__CxxFrameHandler", 0x831B1C90, 0x38, Symbol_Function); | ||||
|     image.symbols.emplace("__C_specific_handler", 0x8324B3BC, 0x38, Symbol_Function); | ||||
|     image.symbols.emplace("memcpy", 0x831B0ED0, 0x488, Symbol_Function); | ||||
|     image.symbols.emplace("memset", 0x831B0BA0, 0xA0, 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);
 | ||||
| 
 | ||||
|  | @ -354,8 +355,8 @@ int main() | |||
|     for (size_t i = 0; i < count; i++) | ||||
|     { | ||||
|         auto fn = pf[i]; | ||||
|         fn.BeginAddress = std::byteswap(fn.BeginAddress); | ||||
|         fn.Data = std::byteswap(fn.Data); | ||||
|         fn.BeginAddress = ByteSwap(fn.BeginAddress); | ||||
|         fn.Data = ByteSwap(fn.Data); | ||||
| 
 | ||||
|         auto& f = functions.emplace_back(); | ||||
|         f.base = fn.BeginAddress; | ||||
|  | @ -366,7 +367,7 @@ int main() | |||
|             __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); | ||||
|  | @ -413,7 +414,7 @@ int main() | |||
|                 base += 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;
 | ||||
|     //uint8_t c[4] = { 0x10, 0x00, 0x59, 0xC3 };
 | ||||
|     //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); | ||||
|  | @ -432,21 +433,21 @@ int main() | |||
| 
 | ||||
|     image.symbols.emplace("_start", image.entry_point, entrySize, Symbol_Function); | ||||
| 
 | ||||
|     std::println("FUNCTIONS"); | ||||
|     fmt::println("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) | ||||
|     { | ||||
|         std::printf("Section %.8s\n", section.name.c_str()); | ||||
|         std::printf("\t%X-%X\n", section.base, section.base + section.size); | ||||
|         printf("Section %.8s\n", section.name.c_str()); | ||||
|         printf("\t%X-%X\n", section.base, section.base + section.size); | ||||
|     } | ||||
| 
 | ||||
|     std::println(""); | ||||
|     fmt::println(""); | ||||
|     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") | ||||
| 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") | ||||
|     target_compile_options(PowerRecomp PRIVATE -Wno-switch -Wno-unused-variable) | ||||
|  |  | |||
|  | @ -1,22 +1,17 @@ | |||
| #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 <charconv> | ||||
| #include <disasm.h> | ||||
| #include <file.h> | ||||
| #include <filesystem> | ||||
| #include <format> | ||||
| #include <fstream> | ||||
| #include <function.h> | ||||
| #include <image.h> | ||||
| #include <print> | ||||
| #include <toml++/toml.hpp> | ||||
| #include <unordered_map> | ||||
| #include <unordered_set> | ||||
| #include <xbox.h> | ||||
| #include <xxhash.h> | ||||
| #include <fmt/core.h> | ||||
| #include "generated/ppc_context.gen.h" | ||||
|  |  | |||
|  | @ -13,8 +13,8 @@ void Recompiler::LoadConfig(const std::string_view& configFilePath) | |||
| { | ||||
|     config.Load(configFilePath); | ||||
| 
 | ||||
|     const auto file = LoadFile((config.directoryPath + config.filePath).c_str()).value(); | ||||
|     image = Image::ParseImage(file.data(), file.size()).value(); | ||||
|     const auto file = LoadFile((config.directoryPath + config.filePath).c_str()); | ||||
|     image = Image::ParseImage(file.data(), file.size()); | ||||
| } | ||||
| 
 | ||||
| void Recompiler::Analyse() | ||||
|  | @ -26,32 +26,32 @@ void Recompiler::Analyse() | |||
|             auto& restgpr = functions.emplace_back(); | ||||
|             restgpr.base = config.restGpr14Address + (i - 14) * 4; | ||||
|             restgpr.size = (32 - i) * 4 + 12; | ||||
|             image.symbols.emplace(std::format("__restgprlr_{}", i), restgpr.base, restgpr.size, Symbol_Function); | ||||
|             image.symbols.emplace(Symbol{ fmt::format("__restgprlr_{}", i), restgpr.base, restgpr.size, Symbol_Function }); | ||||
| 
 | ||||
|             auto& savegpr = functions.emplace_back(); | ||||
|             savegpr.base = config.saveGpr14Address + (i - 14) * 4; | ||||
|             savegpr.size = (32 - i) * 4 + 8; | ||||
|             image.symbols.emplace(std::format("__savegprlr_{}", i), savegpr.base, savegpr.size, Symbol_Function); | ||||
|             image.symbols.emplace(fmt::format("__savegprlr_{}", i), savegpr.base, savegpr.size, Symbol_Function); | ||||
| 
 | ||||
|             auto& restfpr = functions.emplace_back(); | ||||
|             restfpr.base = config.restFpr14Address + (i - 14) * 4; | ||||
|             restfpr.size = (32 - i) * 4 + 4; | ||||
|             image.symbols.emplace(std::format("__restfpr_{}", i), restfpr.base, restfpr.size, Symbol_Function); | ||||
|             image.symbols.emplace(fmt::format("__restfpr_{}", i), restfpr.base, restfpr.size, Symbol_Function); | ||||
| 
 | ||||
|             auto& savefpr = functions.emplace_back(); | ||||
|             savefpr.base = config.saveFpr14Address + (i - 14) * 4; | ||||
|             savefpr.size = (32 - i) * 4 + 4; | ||||
|             image.symbols.emplace(std::format("__savefpr_{}", i), savefpr.base, savefpr.size, Symbol_Function); | ||||
|             image.symbols.emplace(fmt::format("__savefpr_{}", i), savefpr.base, savefpr.size, Symbol_Function); | ||||
| 
 | ||||
|             auto& restvmx = functions.emplace_back(); | ||||
|             restvmx.base = config.restVmx14Address + (i - 14) * 8; | ||||
|             restvmx.size = (32 - i) * 8 + 4; | ||||
|             image.symbols.emplace(std::format("__restvmx_{}", i), restvmx.base, restvmx.size, Symbol_Function); | ||||
|             image.symbols.emplace(fmt::format("__restvmx_{}", i), restvmx.base, restvmx.size, Symbol_Function); | ||||
| 
 | ||||
|             auto& savevmx = functions.emplace_back(); | ||||
|             savevmx.base = config.saveVmx14Address + (i - 14) * 8; | ||||
|             savevmx.size = (32 - i) * 8 + 4; | ||||
|             image.symbols.emplace(std::format("__savevmx_{}", i), savevmx.base, savevmx.size, Symbol_Function); | ||||
|             image.symbols.emplace(fmt::format("__savevmx_{}", i), savevmx.base, savevmx.size, Symbol_Function); | ||||
|         } | ||||
| 
 | ||||
|         if (i >= 64) | ||||
|  | @ -59,19 +59,19 @@ void Recompiler::Analyse() | |||
|             auto& restvmx = functions.emplace_back(); | ||||
|             restvmx.base = config.restVmx64Address + (i - 64) * 8; | ||||
|             restvmx.size = (128 - i) * 8 + 4; | ||||
|             image.symbols.emplace(std::format("__restvmx_{}", i), restvmx.base, restvmx.size, Symbol_Function); | ||||
|             image.symbols.emplace(fmt::format("__restvmx_{}", i), restvmx.base, restvmx.size, Symbol_Function); | ||||
| 
 | ||||
|             auto& savevmx = functions.emplace_back(); | ||||
|             savevmx.base = config.saveVmx64Address + (i - 64) * 8; | ||||
|             savevmx.size = (128 - i) * 8 + 4; | ||||
|             image.symbols.emplace(std::format("__savevmx_{}", i), savevmx.base, savevmx.size, Symbol_Function); | ||||
|             image.symbols.emplace(fmt::format("__savevmx_{}", i), savevmx.base, savevmx.size, Symbol_Function); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     for (auto& [address, size] : config.functions) | ||||
|     { | ||||
|         functions.emplace_back(address, size); | ||||
|         image.symbols.emplace(std::format("sub_{:X}", address), address, size, Symbol_Function); | ||||
|         image.symbols.emplace(fmt::format("sub_{:X}", address), address, size, Symbol_Function); | ||||
|     } | ||||
| 
 | ||||
|     auto& pdata = *image.Find(".pdata"); | ||||
|  | @ -80,8 +80,8 @@ void Recompiler::Analyse() | |||
|     for (size_t i = 0; i < count; i++) | ||||
|     { | ||||
|         auto fn = pf[i]; | ||||
|         fn.BeginAddress = std::byteswap(fn.BeginAddress); | ||||
|         fn.Data = std::byteswap(fn.Data); | ||||
|         fn.BeginAddress = ByteSwap(fn.BeginAddress); | ||||
|         fn.Data = ByteSwap(fn.Data); | ||||
| 
 | ||||
|         if (image.symbols.find(fn.BeginAddress) == image.symbols.end()) | ||||
|         { | ||||
|  | @ -89,7 +89,7 @@ void Recompiler::Analyse() | |||
|             f.base = fn.BeginAddress; | ||||
|             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) | ||||
|         { | ||||
|             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)) | ||||
|             { | ||||
|                 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& 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; | ||||
|  | @ -124,7 +124,7 @@ void Recompiler::Analyse() | |||
| 
 | ||||
|         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()) | ||||
|             { | ||||
|                 base += invalidInstr->second; | ||||
|  | @ -143,7 +143,7 @@ void Recompiler::Analyse() | |||
|             else | ||||
|             { | ||||
|                 auto& fn = functions.emplace_back(Function::Analyze(data, dataEnd - data, base)); | ||||
|                 image.symbols.emplace(std::format("sub_{:X}", fn.base), fn.base, fn.size, Symbol_Function); | ||||
|                 image.symbols.emplace(fmt::format("sub_{:X}", fn.base), fn.base, fn.size, Symbol_Function); | ||||
| 
 | ||||
|                 base += fn.size; | ||||
|                 data += fn.size; | ||||
|  | @ -172,9 +172,9 @@ bool Recompiler::Recompile( | |||
|                 (config.nonVolatileRegistersAsLocalVariables && index >= 14)) | ||||
|             { | ||||
|                 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) | ||||
|  | @ -183,9 +183,9 @@ bool Recompiler::Recompile( | |||
|                 (config.nonVolatileRegistersAsLocalVariables && index >= 14)) | ||||
|             { | ||||
|                 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) | ||||
|  | @ -194,9 +194,9 @@ bool Recompiler::Recompile( | |||
|                 (config.nonVolatileRegistersAsLocalVariables && ((index >= 14 && index <= 31) || (index >= 64 && index <= 127)))) | ||||
|             { | ||||
|                 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) | ||||
|  | @ -204,9 +204,9 @@ bool Recompiler::Recompile( | |||
|             if (config.crRegistersAsLocalVariables) | ||||
|             { | ||||
|                 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 = [&]() | ||||
|  | @ -287,7 +287,7 @@ bool Recompiler::Recompile( | |||
| 
 | ||||
|                 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
 | ||||
|                     } | ||||
|  | @ -513,7 +513,7 @@ bool Recompiler::Recompile( | |||
|                 if (label < fn.base || label >= fn.base + fn.size) | ||||
|                 { | ||||
|                     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;"); | ||||
|                 } | ||||
|                 else | ||||
|  | @ -1897,7 +1897,7 @@ bool Recompiler::Recompile( | |||
|         { | ||||
|         case 0: // D3D color
 | ||||
|             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++) | ||||
|             { | ||||
|  | @ -2145,7 +2145,7 @@ bool Recompiler::Recompile( | |||
|     { | ||||
|         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) | ||||
|             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 | ||||
|      | ||||
|  | @ -2163,7 +2163,7 @@ bool Recompiler::Recompile(const Function& fn) | |||
| 
 | ||||
|     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)) | ||||
|         { | ||||
|             const size_t op = PPC_OP(instruction); | ||||
|  | @ -2248,7 +2248,7 @@ bool Recompiler::Recompile(const Function& fn) | |||
|     } | ||||
|     else | ||||
|     { | ||||
|         name = std::format("sub_{}", fn.base); | ||||
|         name = fmt::format("sub_{}", fn.base); | ||||
|     } | ||||
| 
 | ||||
|     println("__attribute__((alias(\"__imp__{}\"))) PPC_WEAK_FUNC({});", name, name); | ||||
|  | @ -2268,7 +2268,7 @@ bool Recompiler::Recompile(const Function& fn) | |||
|     ppc_insn insn; | ||||
|     while (base < end) | ||||
|     { | ||||
|         if (labels.contains(base)) | ||||
|         if (labels.find(base) != labels.end()) | ||||
|         { | ||||
|             println("loc_{:X}:", base); | ||||
| 
 | ||||
|  | @ -2286,17 +2286,17 @@ bool Recompiler::Recompile(const Function& fn) | |||
|             println("\t// {}", insn.op_str); | ||||
| #if 1 | ||||
|             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 | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             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)) | ||||
|             { | ||||
|                 std::println("Unrecognized instruction at 0x{:X}: {}", base, insn.opcode->name); | ||||
|                 fmt::println("Unrecognized instruction at 0x{:X}: {}", base, insn.opcode->name); | ||||
|                 allRecompiled = false; | ||||
|             } | ||||
|         } | ||||
|  | @ -2307,7 +2307,7 @@ bool Recompiler::Recompile(const Function& fn) | |||
| 
 | ||||
| #if 0 | ||||
|     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 | ||||
| 
 | ||||
|     println("}}\n"); | ||||
|  | @ -2441,7 +2441,7 @@ void Recompiler::Recompile() | |||
|         } | ||||
| 
 | ||||
|         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]); | ||||
|     } | ||||
|  | @ -2457,14 +2457,14 @@ void Recompiler::SaveCurrentOutData(const std::string_view& name) | |||
| 
 | ||||
|         if (name.empty()) | ||||
|         { | ||||
|             cppName = std::format("ppc_recomp.{}.cpp", cppFileIndex); | ||||
|             cppName = fmt::format("ppc_recomp.{}.cpp", cppFileIndex); | ||||
|             ++cppFileIndex; | ||||
|         } | ||||
| 
 | ||||
|         bool shouldWrite = true; | ||||
| 
 | ||||
|         // 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"); | ||||
|         if (f) | ||||
|         { | ||||
|  |  | |||
|  | @ -38,15 +38,15 @@ struct Recompiler | |||
|     void LoadConfig(const std::string_view& configFilePath); | ||||
| 
 | ||||
|     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> | ||||
|     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'; | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -100,14 +100,14 @@ void RecompilerConfig::Load(const std::string_view& configFilePath) | |||
|                 (midAsmHook.returnOnTrue && midAsmHook.jumpAddressOnTrue != 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) && | ||||
|                 (midAsmHook.returnOnFalse != NULL || midAsmHook.returnOnTrue != 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)); | ||||
|  |  | |||
|  | @ -22,7 +22,7 @@ void TestRecompiler::Analyse(const std::string_view& testName) | |||
|             } | ||||
| 
 | ||||
|             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; | ||||
|             data += fn.size; | ||||
|  | @ -40,11 +40,11 @@ void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* ds | |||
|     { | ||||
|         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; | ||||
|             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(); | ||||
|             recompiler.Analyse(stem); | ||||
|  | @ -61,7 +61,7 @@ void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* ds | |||
|                 } | ||||
|                 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"; | ||||
|  | @ -73,7 +73,7 @@ void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* ds | |||
| 
 | ||||
|     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()) | ||||
|         { | ||||
|             std::string line; | ||||
|  | @ -86,30 +86,30 @@ void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* ds | |||
|                     size_t address = ~0; | ||||
|                     std::from_chars(&line[0], &line[spaceIndex], address, 16); | ||||
|                     address &= 0xFFFFF; | ||||
|                     if (addr.contains(address)) | ||||
|                         symbols.emplace(line.substr(spaceIndex + 2, bracketIndex - spaceIndex - 2), std::format("{}_{:X}", fn, address)); | ||||
|                     if (addr.find(address) != addr.end()) | ||||
|                         symbols.emplace(line.substr(spaceIndex + 2, bracketIndex - spaceIndex - 2), fmt::format("{}_{:X}", fn, address)); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         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::println(file, "#define PPC_CONFIG_H_INCLUDED"); | ||||
|     std::println(file, "#include <ppc_context.h>"); | ||||
|     std::println(file, "#include <Windows.h>"); | ||||
|     std::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"); | ||||
|     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_CONFIG_H_INCLUDED"); | ||||
|     fmt::println(file, "#include <ppc_context.h>"); | ||||
|     fmt::println(file, "#include <Windows.h>"); | ||||
|     fmt::println(file, "#include <print>\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"); | ||||
|     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) | ||||
|     { | ||||
|         std::ifstream in(std::format("{}/../{}.s", srcDirectoryPath, fn)); | ||||
|         std::ifstream in(fmt::format("{}/../{}.s", srcDirectoryPath, fn)); | ||||
|         if (in.is_open()) | ||||
|         { | ||||
|             std::string str; | ||||
|  | @ -135,10 +135,10 @@ void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* ds | |||
|                         auto symbol = symbols.find(name); | ||||
|                         if (symbol != symbols.end()) | ||||
|                         { | ||||
|                             std::println(file, "PPC_FUNC({});\n", symbol->second); | ||||
|                             std::println(file, "void {}(uint8_t* base) {{", name); | ||||
|                             std::println(file, "\tPPCContext ctx{{}};"); | ||||
|                             std::println(file, "\tctx.fpscr.loadFromHost();"); | ||||
|                             fmt::println(file, "PPC_FUNC({});\n", symbol->second); | ||||
|                             fmt::println(file, "void {}(uint8_t* base) {{", name); | ||||
|                             fmt::println(file, "\tPPCContext ctx{{}};"); | ||||
|                             fmt::println(file, "\tctx.fpscr.loadFromHost();"); | ||||
| 
 | ||||
|                             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 closingBracketIndex = str.find(']', commaIndex2 + 1); | ||||
| 
 | ||||
|                                             std::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)); | ||||
|                                             std::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[3] = 0x{};", reg, str.substr(openingBracketIndex + 1, commaIndex0 - openingBracketIndex - 1)); | ||||
|                                             fmt::println(file, "\tctx.{}.u32[2] = 0x{};", reg, str.substr(commaIndex0 + 2, commaIndex1 - commaIndex0 - 2)); | ||||
|                                             fmt::println(file, "\tctx.{}.u32[1] = 0x{};", reg, str.substr(commaIndex1 + 2, commaIndex2 - commaIndex1 - 2)); | ||||
|                                             fmt::println(file, "\tctx.{}.u32[0] = 0x{};", reg, str.substr(commaIndex2 + 2, closingBracketIndex - commaIndex2 - 2)); | ||||
|                                         } | ||||
|                                         else | ||||
|                                         { | ||||
|                                             std::println(file, "\tctx.{}.{}64 = {};", | ||||
|                                             fmt::println(file, "\tctx.{}.{}64 = {};", | ||||
|                                                 reg, | ||||
|                                                 str.find('.', secondSpaceIndex) != std::string::npos ? 'f' : 'u', | ||||
|                                                 str.substr(secondSpaceIndex + 1)); | ||||
|  | @ -183,7 +183,7 @@ void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* ds | |||
|                                             { | ||||
|                                                 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
 | ||||
|                                                     ++j; | ||||
|                                                 } | ||||
|  | @ -196,7 +196,7 @@ void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* ds | |||
|                             while (getline() && (str.empty() || str[0] != '#')) | ||||
|                                 ; | ||||
| 
 | ||||
|                             std::println(file, "\t{}(ctx, base);", symbol->second); | ||||
|                             fmt::println(file, "\t{}(ctx, base);", symbol->second); | ||||
| 
 | ||||
|                             do | ||||
|                             { | ||||
|  | @ -218,14 +218,14 @@ void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* ds | |||
|                                             int commaIndex2 = str.find(',', commaIndex1 + 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)); | ||||
|                                             std::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)); | ||||
|                                             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[3], 0x{});", name, reg, str.substr(openingBracketIndex + 1, commaIndex0 - openingBracketIndex - 1)); | ||||
|                                             fmt::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[1], 0x{});", name, reg, str.substr(commaIndex1 + 2, commaIndex2 - commaIndex1 - 2)); | ||||
|                                             fmt::println(file, "\tPPC_CHECK_VALUE_U({}, ctx.{}.u32[0], 0x{});", name, reg, str.substr(commaIndex2 + 2, closingBracketIndex - commaIndex2 - 2)); | ||||
|                                         } | ||||
|                                         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', | ||||
|                                                 name, | ||||
|                                                 reg, | ||||
|  | @ -245,7 +245,7 @@ void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* ds | |||
|                                             { | ||||
|                                                 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
 | ||||
|                                                     ++j; | ||||
|                                                 } | ||||
|  | @ -255,13 +255,13 @@ void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* ds | |||
|                                 } | ||||
|                             } 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 | ||||
|                         { | ||||
|                             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 | ||||
|         { | ||||
|             std::println("Unable to locate source file for {}", fn); | ||||
|             fmt::println("Unable to locate source file for {}", fn); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     std::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, "int main() {{"); | ||||
|     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); | ||||
|     std::println(file, "\treturn 0;"); | ||||
|     std::println(file, "}}"); | ||||
|     fmt::println(file, "\treturn 0;"); | ||||
|     fmt::println(file, "}}"); | ||||
| 
 | ||||
|     fclose(file); | ||||
| } | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| 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_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 | ||||
| #include <expected> | ||||
| 
 | ||||
| #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{}; | ||||
|     auto* stream = fopen(path, "rb"); | ||||
|     if (stream == nullptr) | ||||
|     { | ||||
|         return std::unexpected(1); | ||||
|         return {}; | ||||
|     } | ||||
| 
 | ||||
|     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) | ||||
| { | ||||
|     sections.emplace(std::string(name), this->base + base,  | ||||
|         size, static_cast<SectionFlags>(flags), data); | ||||
|     sections.insert({ std::string(name), this->base + base, | ||||
|         size, static_cast<SectionFlags>(flags), data }); | ||||
| } | ||||
| 
 | ||||
| const void* Image::Find(size_t address) const | ||||
|  | @ -28,7 +28,7 @@ const Section* Image::Find(const std::string_view& name) const | |||
|     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) | ||||
|     { | ||||
|  | @ -39,7 +39,7 @@ std::expected<Image, int> Image::ParseImage(const uint8_t* data, size_t size) | |||
|         return Xex2LoadImage(data); | ||||
|     } | ||||
| 
 | ||||
|     return std::unexpected(1); | ||||
|     return {}; | ||||
| } | ||||
| 
 | ||||
| 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.size = 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); | ||||
| 
 | ||||
|     auto stringTableIndex = std::byteswap(header->e_shstrndx); | ||||
|     auto stringTableIndex = ByteSwap(header->e_shstrndx); | ||||
| 
 | ||||
|     const auto numSections = std::byteswap(header->e_shnum); | ||||
|     const auto numpSections = std::byteswap(header->e_phnum); | ||||
|     const auto numSections = ByteSwap(header->e_shnum); | ||||
|     const auto numpSections = ByteSwap(header->e_phnum); | ||||
| 
 | ||||
|     const auto* sections = (elf32_shdr*)(data + std::byteswap(header->e_shoff)); | ||||
|     const auto* psections = (elf32_phdr*)(data + std::byteswap(header->e_phoff)); | ||||
|     const auto* sections = (elf32_shdr*)(data + ByteSwap(header->e_shoff)); | ||||
|     const auto* psections = (elf32_phdr*)(data + ByteSwap(header->e_phoff)); | ||||
| 
 | ||||
|     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; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     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++) | ||||
|     { | ||||
|  | @ -82,16 +82,16 @@ Image ElfLoadImage(const uint8_t* data, size_t size) | |||
| 
 | ||||
|         uint8_t flags{}; | ||||
| 
 | ||||
|         if (section.sh_flags & std::byteswap(SHF_EXECINSTR)) | ||||
|         if (section.sh_flags & ByteSwap(SHF_EXECINSTR)) | ||||
|         { | ||||
|             flags |= SectionFlags_Code; | ||||
|         } | ||||
| 
 | ||||
|         auto* name = section.sh_name != 0 ? stringTable + std::byteswap(section.sh_name) : nullptr; | ||||
|         const auto rva = std::byteswap(section.sh_addr) - image.base; | ||||
|         const auto size = std::byteswap(section.sh_size); | ||||
|         auto* name = section.sh_name != 0 ? stringTable + ByteSwap(section.sh_name) : nullptr; | ||||
|         const auto rva = ByteSwap(section.sh_addr) - image.base; | ||||
|         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; | ||||
|  |  | |||
|  | @ -44,7 +44,7 @@ struct Image | |||
|      * \param size Size of data | ||||
|      * \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); | ||||
|  |  | |||
|  | @ -13,9 +13,18 @@ enum SymbolType | |||
| struct Symbol | ||||
| { | ||||
|     mutable std::string name{}; | ||||
|     uint32_t address{}; | ||||
|     uint32_t size{}; | ||||
|     size_t address{}; | ||||
|     size_t size{}; | ||||
|     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 | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ | |||
| #include <type_traits> | ||||
| #include <bit> | ||||
| #include <string> | ||||
| 
 | ||||
| #include "byteswap.h" | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
|     #include <windows.h> | ||||
|  | @ -81,22 +81,22 @@ struct be | |||
|     { | ||||
|         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); | ||||
|         } | ||||
|         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); | ||||
|         } | ||||
|         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); | ||||
|         } | ||||
|         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 originalData = originalThunk; | ||||
|                 originalData->Data = std::byteswap(originalData->Data); | ||||
|                 originalData->Data = ByteSwap(originalData->Data); | ||||
| 
 | ||||
|                 if (originalData->OriginalData.Type != 0) | ||||
|                 { | ||||
|  | @ -134,7 +134,7 @@ Image Xex2LoadImage(const uint8_t* data) | |||
|                     auto name = names->find(originalData->OriginalData.Ordinal); | ||||
|                     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)); | ||||
|  |  | |||
							
								
								
									
										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" | ||||
|     ] | ||||
| } | ||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Skyth
						Skyth