mirror of
https://github.com/hedge-dev/XenonRecomp.git
synced 2025-07-22 21:17:14 +00:00
Downgrade projects to C++17.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user