diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..901036c --- /dev/null +++ b/.clang-format @@ -0,0 +1,17 @@ +BasedOnStyle: LLVM +UseTab: Never +IndentWidth: 4 +Language: Cpp +DerivePointerAlignment: false +PointerAlignment: Left +BreakBeforeBraces: Allman +LineEnding: LF +ColumnLimit: 0 +IndentCaseLabels: false +InsertNewlineAtEOF: true +Cpp11BracedListStyle: false +SpaceBeforeCpp11BracedList: true +AlignAfterOpenBracket: DontAlign +ContinuationIndentWidth: 4 +AllowAllArgumentsOnNextLine: false +SpaceAfterTemplateKeyword: false diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml new file mode 100644 index 0000000..41a866a --- /dev/null +++ b/.github/workflows/format.yml @@ -0,0 +1,25 @@ +name: Clang Format +on: + push: + paths-ignore: + - "**/*.md" + - '**/*.txt' + - 'thirdparty/*' + pull_request: + paths-ignore: + - "**/*.md" + - '**/*.txt' + - 'thirdparty/*' + workflow_dispatch: +jobs: + clang-format: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Run clang-format + uses: jidicula/clang-format-action@v4.14.0 + with: + exclude-regex: (thirdparty) + clang-format-version: 19 diff --git a/XenonAnalyse/function.cpp b/XenonAnalyse/function.cpp index 34add40..e02d366 100644 --- a/XenonAnalyse/function.cpp +++ b/XenonAnalyse/function.cpp @@ -1,10 +1,10 @@ #include "function.h" +#include +#include +#include +#include #include #include -#include -#include -#include -#include size_t Function::SearchBlock(size_t address) const { @@ -40,7 +40,7 @@ size_t Function::SearchBlock(size_t address) const Function Function::Analyze(const void* code, size_t size, size_t base) { - Function fn{ base, 0 }; + Function fn { base, 0 }; if (*((uint32_t*)code + 1) == 0x04000048) // shifted ptr tail call { @@ -55,14 +55,16 @@ Function Function::Analyze(const void* code, size_t size, size_t base) const auto* data = (uint32_t*)code; const auto* dataStart = data; const auto* dataEnd = (uint32_t*)((uint8_t*)code + size); - std::vector blockStack{}; + std::vector blockStack {}; blockStack.reserve(32); blockStack.emplace_back(); - #define RESTORE_DATA() if (!blockStack.empty()) data = (dataStart + ((blocks[blockStack.back()].base + blocks[blockStack.back()].size) / sizeof(*data))) - 1; // continue adds one +#define RESTORE_DATA() \ + if (!blockStack.empty()) \ + data = (dataStart + ((blocks[blockStack.back()].base + blocks[blockStack.back()].size) / sizeof(*data))) - 1; // continue adds one // TODO: Branch fallthrough - for (; data <= dataEnd ; ++data) + for (; data <= dataEnd; ++data) { const size_t addr = base + ((data - dataStart) * sizeof(*data)); if (blockStack.empty()) @@ -82,7 +84,7 @@ Function Function::Analyze(const void* code, size_t size, size_t base) ppc::Disassemble(data, addr, insn); // Sanity check - assert(addr == base + curBlock.base + curBlock.size); + assert(addr == base + curBlock.base + curBlock.size); if (curBlock.projectedSize != -1 && curBlock.size >= curBlock.projectedSize) // fallthrough { blockStack.pop_back(); @@ -172,7 +174,7 @@ Function Function::Analyze(const void* code, size_t size, size_t base) blocks.emplace_back(branchBase, 0, sizeProjection); blockStack.emplace_back(blocks.size() - 1); - + DEBUG(blocks.back().parent = blockBase); RESTORE_DATA(); continue; @@ -214,9 +216,7 @@ Function Function::Analyze(const void* code, size_t size, size_t base) if (blocks.size() > 1) { std::sort(blocks.begin(), blocks.end(), [](const Block& a, const Block& b) - { - return a.base < b.base; - }); + { return a.base < b.base; }); size_t discontinuity = -1; for (size_t i = 0; i < blocks.size() - 1; i++) diff --git a/XenonAnalyse/main.cpp b/XenonAnalyse/main.cpp index d08371e..cac60ae 100644 --- a/XenonAnalyse/main.cpp +++ b/XenonAnalyse/main.cpp @@ -1,11 +1,11 @@ -#include -#include -#include -#include -#include -#include -#include #include "function.h" +#include +#include +#include +#include +#include +#include +#include #define SWITCH_ABSOLUTE 0 #define SWITCH_COMPUTED 1 @@ -14,11 +14,11 @@ struct SwitchTable { - std::vector labels{}; - size_t base{}; - size_t defaultLabel{}; - uint32_t r{}; - uint32_t type{}; + std::vector labels {}; + size_t base {}; + size_t defaultLabel {}; + uint32_t r {}; + uint32_t type {}; }; void ReadTable(Image& image, SwitchTable& table) @@ -104,7 +104,7 @@ void ReadTable(Image& image, SwitchTable& table) void ScanTable(const uint32_t* code, size_t base, SwitchTable& table) { ppc_insn insn; - uint32_t cr{ (uint32_t)-1 }; + uint32_t cr { (uint32_t)-1 }; for (int i = 0; i < 32; i++) { ppc::Disassemble(&code[-i], base - (4 * i), insn); @@ -193,65 +193,64 @@ int main(int argc, char** argv) auto image = Image::ParseImage(file.data(), file.size()); auto printTable = [&](const SwitchTable& table) + { + println("[[switch]]"); + println("base = 0x{:X}", table.base); + println("r = {}", table.r); + println("default = 0x{:X}", table.defaultLabel); + println("labels = ["); + for (const auto& label : table.labels) { - println("[[switch]]"); - println("base = 0x{:X}", table.base); - println("r = {}", table.r); - println("default = 0x{:X}", table.defaultLabel); - println("labels = ["); - for (const auto& label : table.labels) - { - println(" 0x{:X},", label); - } + println(" 0x{:X},", label); + } - println("]"); - println(""); - }; + println("]"); + println(""); + }; - std::vector switches{}; + std::vector switches {}; println("# Generated by XenonAnalyse"); auto scanPattern = [&](uint32_t* pattern, size_t count, size_t type) - { - for (const auto& section : image.sections) - { - if (!(section.flags & SectionFlags_Code)) - { - continue; - } - - size_t base = section.base; - uint8_t* data = section.data; - uint8_t* dataStart = section.data; - uint8_t* dataEnd = section.data + section.size; - while (data < dataEnd && data != nullptr) - { - data = (uint8_t*)SearchMask(data, pattern, count, dataEnd - data); - - if (data != nullptr) - { - SwitchTable table{}; - table.type = type; - ScanTable((uint32_t*)data, base + (data - dataStart), table); - - // fmt::println("{:X} ; jmptable - {}", base + (data - dataStart), table.labels.size()); - if (table.base != 0) - { - ReadTable(image, table); - printTable(table); - switches.emplace_back(std::move(table)); - } - - data += 4; - } - continue; - } - } - }; - - uint32_t absoluteSwitch[] = { + for (const auto& section : image.sections) + { + if (!(section.flags & SectionFlags_Code)) + { + continue; + } + + size_t base = section.base; + uint8_t* data = section.data; + uint8_t* dataStart = section.data; + uint8_t* dataEnd = section.data + section.size; + while (data < dataEnd && data != nullptr) + { + data = (uint8_t*)SearchMask(data, pattern, count, dataEnd - data); + + if (data != nullptr) + { + SwitchTable table {}; + table.type = type; + ScanTable((uint32_t*)data, base + (data - dataStart), table); + + // fmt::println("{:X} ; jmptable - {}", base + (data - dataStart), table.labels.size()); + if (table.base != 0) + { + ReadTable(image, table); + printTable(table); + switches.emplace_back(std::move(table)); + } + + data += 4; + } + continue; + } + } + }; + + uint32_t absoluteSwitch[] = { PPC_INST_LIS, PPC_INST_ADDI, PPC_INST_RLWINM, @@ -260,8 +259,7 @@ int main(int argc, char** argv) PPC_INST_BCTR, }; - uint32_t computedSwitch[] = - { + uint32_t computedSwitch[] = { PPC_INST_LIS, PPC_INST_ADDI, PPC_INST_LBZX, @@ -272,8 +270,7 @@ int main(int argc, char** argv) PPC_INST_MTCTR, }; - uint32_t offsetSwitch[] = - { + uint32_t offsetSwitch[] = { PPC_INST_LIS, PPC_INST_ADDI, PPC_INST_LBZX, @@ -283,8 +280,7 @@ int main(int argc, char** argv) PPC_INST_MTCTR, }; - uint32_t wordOffsetSwitch[] = - { + uint32_t wordOffsetSwitch[] = { PPC_INST_LIS, PPC_INST_ADDI, PPC_INST_RLWINM, diff --git a/XenonRecomp/main.cpp b/XenonRecomp/main.cpp index 12c6d8c..157b7f2 100644 --- a/XenonRecomp/main.cpp +++ b/XenonRecomp/main.cpp @@ -11,12 +11,12 @@ int main(int argc, char* argv[]) } #endif - const char* path = - #ifdef XENON_RECOMP_CONFIG_FILE_PATH + const char* path = +#ifdef XENON_RECOMP_CONFIG_FILE_PATH XENON_RECOMP_CONFIG_FILE_PATH - #else +#else argv[1] - #endif +#endif ; if (std::filesystem::is_regular_file(path)) diff --git a/XenonRecomp/recompiler.cpp b/XenonRecomp/recompiler.cpp index 5374797..bee0666 100644 --- a/XenonRecomp/recompiler.cpp +++ b/XenonRecomp/recompiler.cpp @@ -1,5 +1,5 @@ -#include "pch.h" #include "recompiler.h" +#include "pch.h" #include static uint64_t ComputeMask(uint32_t mstart, uint32_t mstop) @@ -104,7 +104,7 @@ void Recompiler::Analyse() auto& restgpr = functions.emplace_back(); restgpr.base = config.restGpr14Address + (i - 14) * 4; restgpr.size = (32 - i) * 4 + 12; - image.symbols.emplace(Symbol{ fmt::format("__restgprlr_{}", i), restgpr.base, restgpr.size, Symbol_Function }); + image.symbols.emplace(Symbol { fmt::format("__restgprlr_{}", i), restgpr.base, restgpr.size, Symbol_Function }); } if (config.saveGpr14Address != 0) @@ -251,7 +251,8 @@ void Recompiler::Analyse() } } - std::sort(functions.begin(), functions.end(), [](auto& lhs, auto& rhs) { return lhs.base < rhs.base; }); + std::sort(functions.begin(), functions.end(), [](auto& lhs, auto& rhs) + { return lhs.base < rhs.base; }); } bool Recompiler::Recompile( @@ -267,251 +268,251 @@ bool Recompiler::Recompile( // TODO: we could cache these formats in an array auto r = [&](size_t index) + { + if ((config.nonArgumentRegistersAsLocalVariables && (index == 0 || index == 2 || index == 11 || index == 12)) || + (config.nonVolatileRegistersAsLocalVariables && index >= 14)) { - if ((config.nonArgumentRegistersAsLocalVariables && (index == 0 || index == 2 || index == 11 || index == 12)) || - (config.nonVolatileRegistersAsLocalVariables && index >= 14)) - { - localVariables.r[index] = true; - return fmt::format("r{}", index); - } - return fmt::format("ctx.r{}", index); - }; + localVariables.r[index] = true; + return fmt::format("r{}", index); + } + return fmt::format("ctx.r{}", index); + }; auto f = [&](size_t index) + { + if ((config.nonArgumentRegistersAsLocalVariables && index == 0) || + (config.nonVolatileRegistersAsLocalVariables && index >= 14)) { - if ((config.nonArgumentRegistersAsLocalVariables && index == 0) || - (config.nonVolatileRegistersAsLocalVariables && index >= 14)) - { - localVariables.f[index] = true; - return fmt::format("f{}", index); - } - return fmt::format("ctx.f{}", index); - }; + localVariables.f[index] = true; + return fmt::format("f{}", index); + } + return fmt::format("ctx.f{}", index); + }; auto v = [&](size_t index) + { + if ((config.nonArgumentRegistersAsLocalVariables && (index >= 32 && index <= 63)) || + (config.nonVolatileRegistersAsLocalVariables && ((index >= 14 && index <= 31) || (index >= 64 && index <= 127)))) { - if ((config.nonArgumentRegistersAsLocalVariables && (index >= 32 && index <= 63)) || - (config.nonVolatileRegistersAsLocalVariables && ((index >= 14 && index <= 31) || (index >= 64 && index <= 127)))) - { - localVariables.v[index] = true; - return fmt::format("v{}", index); - } - return fmt::format("ctx.v{}", index); - }; + localVariables.v[index] = true; + return fmt::format("v{}", index); + } + return fmt::format("ctx.v{}", index); + }; auto cr = [&](size_t index) + { + if (config.crRegistersAsLocalVariables) { - if (config.crRegistersAsLocalVariables) - { - localVariables.cr[index] = true; - return fmt::format("cr{}", index); - } - return fmt::format("ctx.cr{}", index); - }; + localVariables.cr[index] = true; + return fmt::format("cr{}", index); + } + return fmt::format("ctx.cr{}", index); + }; auto ctr = [&]() + { + if (config.ctrAsLocalVariable) { - if (config.ctrAsLocalVariable) - { - localVariables.ctr = true; - return "ctr"; - } - return "ctx.ctr"; - }; + localVariables.ctr = true; + return "ctr"; + } + return "ctx.ctr"; + }; auto xer = [&]() + { + if (config.xerAsLocalVariable) { - if (config.xerAsLocalVariable) - { - localVariables.xer = true; - return "xer"; - } - return "ctx.xer"; - }; + localVariables.xer = true; + return "xer"; + } + return "ctx.xer"; + }; auto reserved = [&]() + { + if (config.reservedRegisterAsLocalVariable) { - if (config.reservedRegisterAsLocalVariable) - { - localVariables.reserved = true; - return "reserved"; - } - return "ctx.reserved"; - }; + localVariables.reserved = true; + return "reserved"; + } + return "ctx.reserved"; + }; auto temp = [&]() - { - localVariables.temp = true; - return "temp"; - }; + { + localVariables.temp = true; + return "temp"; + }; auto vTemp = [&]() - { - localVariables.vTemp = true; - return "vTemp"; - }; + { + localVariables.vTemp = true; + return "vTemp"; + }; auto env = [&]() - { - localVariables.env = true; - return "env"; - }; + { + localVariables.env = true; + return "env"; + }; auto ea = [&]() - { - localVariables.ea = true; - return "ea"; - }; + { + localVariables.ea = true; + return "ea"; + }; // TODO (Sajid): Check for out of bounds access auto mmioStore = [&]() -> bool - { - return *(data + 1) == c_eieio; - }; + { + return *(data + 1) == c_eieio; + }; auto printFunctionCall = [&](uint32_t address) + { + if (address == config.longJmpAddress) { - if (address == config.longJmpAddress) - { - println("\tlongjmp(*reinterpret_cast(base + {}.u32), {}.s32);", r(3), r(4)); - } - else if (address == config.setJmpAddress) - { - println("\t{} = ctx;", env()); - println("\t{}.s64 = setjmp(*reinterpret_cast(base + {}.u32));", r(3), r(3)); - println("\tif ({}.s64 != 0) ctx = {};", r(3), env()); - } - else - { - auto targetSymbol = image.symbols.find(address); + println("\tlongjmp(*reinterpret_cast(base + {}.u32), {}.s32);", r(3), r(4)); + } + else if (address == config.setJmpAddress) + { + println("\t{} = ctx;", env()); + println("\t{}.s64 = setjmp(*reinterpret_cast(base + {}.u32));", r(3), r(3)); + println("\tif ({}.s64 != 0) ctx = {};", r(3), env()); + } + else + { + auto targetSymbol = image.symbols.find(address); - if (targetSymbol != image.symbols.end() && targetSymbol->address == address && targetSymbol->type == Symbol_Function) + if (targetSymbol != image.symbols.end() && targetSymbol->address == address && targetSymbol->type == Symbol_Function) + { + if (config.nonVolatileRegistersAsLocalVariables && (targetSymbol->name.find("__rest") == 0 || targetSymbol->name.find("__save") == 0)) { - if (config.nonVolatileRegistersAsLocalVariables && (targetSymbol->name.find("__rest") == 0 || targetSymbol->name.find("__save") == 0)) - { - // print nothing - } - else - { - println("\t{}(ctx, base);", targetSymbol->name); - } + // print nothing } else { - println("\t// ERROR {:X}", address); + println("\t{}(ctx, base);", targetSymbol->name); } } - }; - - auto printConditionalBranch = [&](bool not_, const std::string_view& cond) - { - if (insn.operands[1] < fn.base || insn.operands[1] >= fn.base + fn.size) - { - println("\tif ({}{}.{}) {{", not_ ? "!" : "", cr(insn.operands[0]), cond); - print("\t"); - printFunctionCall(insn.operands[1]); - println("\t\treturn;"); - println("\t}}"); - } else { - println("\tif ({}{}.{}) goto loc_{:X};", not_ ? "!" : "", cr(insn.operands[0]), cond, insn.operands[1]); + println("\t// ERROR {:X}", address); } - }; + } + }; + + auto printConditionalBranch = [&](bool not_, const std::string_view& cond) + { + if (insn.operands[1] < fn.base || insn.operands[1] >= fn.base + fn.size) + { + println("\tif ({}{}.{}) {{", not_ ? "!" : "", cr(insn.operands[0]), cond); + print("\t"); + printFunctionCall(insn.operands[1]); + println("\t\treturn;"); + println("\t}}"); + } + else + { + println("\tif ({}{}.{}) goto loc_{:X};", not_ ? "!" : "", cr(insn.operands[0]), cond, insn.operands[1]); + } + }; auto printSetFlushMode = [&](bool enable) + { + auto newState = enable ? CSRState::VMX : CSRState::FPU; + if (csrState != newState) { - auto newState = enable ? CSRState::VMX : CSRState::FPU; - if (csrState != newState) - { - auto prefix = enable ? "enable" : "disable"; - auto suffix = csrState != CSRState::Unknown ? "Unconditional" : ""; - println("\tctx.fpscr.{}FlushMode{}();", prefix, suffix); + auto prefix = enable ? "enable" : "disable"; + auto suffix = csrState != CSRState::Unknown ? "Unconditional" : ""; + println("\tctx.fpscr.{}FlushMode{}();", prefix, suffix); - csrState = newState; - } - }; + csrState = newState; + } + }; auto midAsmHook = config.midAsmHooks.find(base); auto printMidAsmHook = [&]() + { + bool returnsBool = midAsmHook->second.returnOnFalse || midAsmHook->second.returnOnTrue || + midAsmHook->second.jumpAddressOnFalse != NULL || midAsmHook->second.jumpAddressOnTrue != NULL; + + print("\t"); + if (returnsBool) + print("if ("); + + print("{}(", midAsmHook->second.name); + for (auto& reg : midAsmHook->second.registers) { - bool returnsBool = midAsmHook->second.returnOnFalse || midAsmHook->second.returnOnTrue || - midAsmHook->second.jumpAddressOnFalse != NULL || midAsmHook->second.jumpAddressOnTrue != NULL; + if (out.back() != '(') + out += ", "; - print("\t"); - if (returnsBool) - print("if ("); - - print("{}(", midAsmHook->second.name); - for (auto& reg : midAsmHook->second.registers) + switch (reg[0]) { - if (out.back() != '(') - out += ", "; + case 'c': + if (reg == "ctr") + out += ctr(); + else + out += cr(std::atoi(reg.c_str() + 2)); + break; - switch (reg[0]) - { - case 'c': - if (reg == "ctr") - out += ctr(); - else - out += cr(std::atoi(reg.c_str() + 2)); - break; + case 'x': + out += xer(); + break; - case 'x': - out += xer(); - break; + case 'r': + if (reg == "reserved") + out += reserved(); + else + out += r(std::atoi(reg.c_str() + 1)); + break; - case 'r': - if (reg == "reserved") - out += reserved(); - else - out += r(std::atoi(reg.c_str() + 1)); - break; + case 'f': + if (reg == "fpscr") + out += "ctx.fpscr"; + else + out += f(std::atoi(reg.c_str() + 1)); + break; - case 'f': - if (reg == "fpscr") - out += "ctx.fpscr"; - else - out += f(std::atoi(reg.c_str() + 1)); - break; - - case 'v': - out += v(std::atoi(reg.c_str() + 1)); - break; - } + case 'v': + out += v(std::atoi(reg.c_str() + 1)); + break; } + } - if (returnsBool) - { - println(")) {{"); + if (returnsBool) + { + println(")) {{"); - if (midAsmHook->second.returnOnTrue) - println("\t\treturn;"); - else if (midAsmHook->second.jumpAddressOnTrue != NULL) - println("\t\tgoto loc_{:X};", midAsmHook->second.jumpAddressOnTrue); + if (midAsmHook->second.returnOnTrue) + println("\t\treturn;"); + else if (midAsmHook->second.jumpAddressOnTrue != NULL) + println("\t\tgoto loc_{:X};", midAsmHook->second.jumpAddressOnTrue); - println("\t}}"); + println("\t}}"); - println("\telse {{"); + println("\telse {{"); - if (midAsmHook->second.returnOnFalse) - println("\t\treturn;"); - else if (midAsmHook->second.jumpAddressOnFalse != NULL) - println("\t\tgoto loc_{:X};", midAsmHook->second.jumpAddressOnFalse); + if (midAsmHook->second.returnOnFalse) + println("\t\treturn;"); + else if (midAsmHook->second.jumpAddressOnFalse != NULL) + println("\t\tgoto loc_{:X};", midAsmHook->second.jumpAddressOnFalse); - println("\t}}"); - } - else - { - println(");"); + println("\t}}"); + } + else + { + println(");"); - if (midAsmHook->second.ret) - println("\treturn;"); - else if (midAsmHook->second.jumpAddress != NULL) - println("\tgoto loc_{:X};", midAsmHook->second.jumpAddress); - } - }; + if (midAsmHook->second.ret) + println("\treturn;"); + else if (midAsmHook->second.jumpAddress != NULL) + println("\tgoto loc_{:X};", midAsmHook->second.jumpAddress); + } + }; if (midAsmHook != config.midAsmHooks.end() && !midAsmHook->second.afterInstruction) printMidAsmHook(); @@ -519,8 +520,10 @@ bool Recompiler::Recompile( int id = insn.opcode->id; // Handling instructions that don't disassemble correctly for some reason here - if (id == PPC_INST_VUPKHSB128 && insn.operands[2] == 0x60) id = PPC_INST_VUPKHSH128; - else if (id == PPC_INST_VUPKLSB128 && insn.operands[2] == 0x60) id = PPC_INST_VUPKLSH128; + if (id == PPC_INST_VUPKHSB128 && insn.operands[2] == 0x60) + id = PPC_INST_VUPKHSH128; + else if (id == PPC_INST_VUPKLSB128 && insn.operands[2] == 0x60) + id = PPC_INST_VUPKLSH128; switch (id) { @@ -2255,7 +2258,7 @@ bool Recompiler::Recompile( if (midAsmHook != config.midAsmHooks.end() && midAsmHook->second.afterInstruction) printMidAsmHook(); - + return true; } @@ -2339,9 +2342,9 @@ bool Recompiler::Recompile(const Function& fn) println(");\n"); if (midAsmHook->second.jumpAddress != NULL) - labels.emplace(midAsmHook->second.jumpAddress); + labels.emplace(midAsmHook->second.jumpAddress); if (midAsmHook->second.jumpAddressOnTrue != NULL) - labels.emplace(midAsmHook->second.jumpAddressOnTrue); + labels.emplace(midAsmHook->second.jumpAddressOnTrue); if (midAsmHook->second.jumpAddressOnFalse != NULL) labels.emplace(midAsmHook->second.jumpAddressOnFalse); } @@ -2430,7 +2433,7 @@ bool Recompiler::Recompile(const Function& fn) std::swap(out, tempString); if (localVariables.ctr) - println("\tPPCRegister ctr{{}};"); + println("\tPPCRegister ctr{{}};"); if (localVariables.xer) println("\tPPCXERRegister xer{{}};"); if (localVariables.reserved) @@ -2461,11 +2464,11 @@ bool Recompiler::Recompile(const Function& fn) } if (localVariables.env) - println("\tPPCContext env{{}};"); - + println("\tPPCContext env{{}};"); + if (localVariables.temp) - println("\tPPCRegister temp{{}};"); - + println("\tPPCRegister temp{{}};"); + if (localVariables.vTemp) println("\tPPCVRegister vTemp{{}};"); @@ -2488,19 +2491,19 @@ void Recompiler::Recompile(const std::filesystem::path& headerFilePath) println("#define PPC_CONFIG_H_INCLUDED\n"); if (config.skipLr) - println("#define PPC_CONFIG_SKIP_LR"); + println("#define PPC_CONFIG_SKIP_LR"); if (config.ctrAsLocalVariable) - println("#define PPC_CONFIG_CTR_AS_LOCAL"); + println("#define PPC_CONFIG_CTR_AS_LOCAL"); if (config.xerAsLocalVariable) - println("#define PPC_CONFIG_XER_AS_LOCAL"); + println("#define PPC_CONFIG_XER_AS_LOCAL"); if (config.reservedRegisterAsLocalVariable) - println("#define PPC_CONFIG_RESERVED_AS_LOCAL"); + println("#define PPC_CONFIG_RESERVED_AS_LOCAL"); if (config.skipMsr) - println("#define PPC_CONFIG_SKIP_MSR"); + println("#define PPC_CONFIG_SKIP_MSR"); if (config.crRegistersAsLocalVariables) - println("#define PPC_CONFIG_CR_AS_LOCAL"); + println("#define PPC_CONFIG_CR_AS_LOCAL"); if (config.nonArgumentRegistersAsLocalVariables) - println("#define PPC_CONFIG_NON_ARGUMENT_AS_LOCAL"); + println("#define PPC_CONFIG_NON_ARGUMENT_AS_LOCAL"); if (config.nonVolatileRegistersAsLocalVariables) println("#define PPC_CONFIG_NON_VOLATILE_AS_LOCAL"); @@ -2508,7 +2511,7 @@ void Recompiler::Recompile(const std::filesystem::path& headerFilePath) println("#define PPC_IMAGE_BASE 0x{:X}ull", image.base); println("#define PPC_IMAGE_SIZE 0x{:X}ull", image.size); - + // Extract the address of the minimum code segment to store the function table at. size_t codeMin = ~0; size_t codeMax = 0; @@ -2543,7 +2546,7 @@ void Recompiler::Recompile(const std::filesystem::path& headerFilePath) println("#pragma once"); println("#include \"ppc_config.h\"\n"); - + std::ifstream stream(headerFilePath); if (stream.good()) { diff --git a/XenonRecomp/recompiler_config.cpp b/XenonRecomp/recompiler_config.cpp index 81330a4..f24306d 100644 --- a/XenonRecomp/recompiler_config.cpp +++ b/XenonRecomp/recompiler_config.cpp @@ -5,7 +5,7 @@ void RecompilerConfig::Load(const std::string_view& configFilePath) directoryPath = configFilePath.substr(0, configFilePath.find_last_of("\\/") + 1); toml::table toml = toml::parse_file(configFilePath) #if !TOML_EXCEPTIONS - .table() + .table() #endif ; @@ -38,14 +38,22 @@ void RecompilerConfig::Load(const std::string_view& configFilePath) longJmpAddress = main["longjmp_address"].value_or(0u); setJmpAddress = main["setjmp_address"].value_or(0u); - if (restGpr14Address == 0) fmt::println("ERROR: __restgprlr_14 address is unspecified"); - if (saveGpr14Address == 0) fmt::println("ERROR: __savegprlr_14 address is unspecified"); - if (restFpr14Address == 0) fmt::println("ERROR: __restfpr_14 address is unspecified"); - if (saveFpr14Address == 0) fmt::println("ERROR: __savefpr_14 address is unspecified"); - if (restVmx14Address == 0) fmt::println("ERROR: __restvmx_14 address is unspecified"); - if (saveVmx14Address == 0) fmt::println("ERROR: __savevmx_14 address is unspecified"); - if (restVmx64Address == 0) fmt::println("ERROR: __restvmx_64 address is unspecified"); - if (saveVmx64Address == 0) fmt::println("ERROR: __savevmx_64 address is unspecified"); + if (restGpr14Address == 0) + fmt::println("ERROR: __restgprlr_14 address is unspecified"); + if (saveGpr14Address == 0) + fmt::println("ERROR: __savegprlr_14 address is unspecified"); + if (restFpr14Address == 0) + fmt::println("ERROR: __restfpr_14 address is unspecified"); + if (saveFpr14Address == 0) + fmt::println("ERROR: __savefpr_14 address is unspecified"); + if (restVmx14Address == 0) + fmt::println("ERROR: __restvmx_14 address is unspecified"); + if (saveVmx14Address == 0) + fmt::println("ERROR: __savevmx_14 address is unspecified"); + if (restVmx64Address == 0) + fmt::println("ERROR: __restvmx_64 address is unspecified"); + if (saveVmx64Address == 0) + fmt::println("ERROR: __savevmx_64 address is unspecified"); if (auto functionsArray = main["functions"].as_array()) { @@ -73,7 +81,7 @@ void RecompilerConfig::Load(const std::string_view& configFilePath) { toml::table switchToml = toml::parse_file(directoryPath + switchTableFilePath) #if !TOML_EXCEPTIONS - .table() + .table() #endif ; if (auto switchArray = switchToml["switch"].as_array()) diff --git a/XenonRecomp/test_recompiler.cpp b/XenonRecomp/test_recompiler.cpp index f4fcdfe..125ec31 100644 --- a/XenonRecomp/test_recompiler.cpp +++ b/XenonRecomp/test_recompiler.cpp @@ -23,13 +23,14 @@ void TestRecompiler::Analyse(const std::string_view& testName) auto& fn = functions.emplace_back(Function::Analyze(data, dataEnd - data, base)); image.symbols.emplace(fmt::format("{}_{:X}", testName, fn.base), fn.base, fn.size, Symbol_Function); - + base += fn.size; data += fn.size; } } - std::sort(functions.begin(), functions.end(), [](auto& lhs, auto& rhs) { return lhs.base < rhs.base; }); + std::sort(functions.begin(), functions.end(), [](auto& lhs, auto& rhs) + { return lhs.base < rhs.base; }); } void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* dstDirectoryPath) @@ -118,15 +119,15 @@ void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* ds { std::string str; auto getline = [&]() + { + if (std::getline(in, str)) { - if (std::getline(in, str)) - { - str.erase(str.find_last_not_of(' ') + 1); - str.erase(0, str.find_first_not_of(' ')); - return true; - } - return false; - }; + str.erase(str.find_last_not_of(' ') + 1); + str.erase(0, str.find_first_not_of(' ')); + return true; + } + return false; + }; while (getline()) { diff --git a/XenonUtils/disasm.cpp b/XenonUtils/disasm.cpp index 4610b9b..54b772f 100644 --- a/XenonUtils/disasm.cpp +++ b/XenonUtils/disasm.cpp @@ -1,6 +1,6 @@ #include "disasm.h" -thread_local ppc::DisassemblerEngine ppc::gBigEndianDisassembler{ BFD_ENDIAN_BIG, "cell 64"}; +thread_local ppc::DisassemblerEngine ppc::gBigEndianDisassembler { BFD_ENDIAN_BIG, "cell 64" }; ppc::DisassemblerEngine::DisassemblerEngine(bfd_endian endian, const char* options) { diff --git a/XenonUtils/image.cpp b/XenonUtils/image.cpp index 39afe92..9ce4372 100644 --- a/XenonUtils/image.cpp +++ b/XenonUtils/image.cpp @@ -48,7 +48,7 @@ Image ElfLoadImage(const uint8_t* data, size_t size) const auto* header = (elf32_hdr*)data; assert(header->e_ident[EI_DATA] == 2); - Image image{}; + Image image {}; image.size = size; image.data = std::make_unique(size); image.entry_point = ByteSwap(header->e_entry); @@ -81,7 +81,7 @@ Image ElfLoadImage(const uint8_t* data, size_t size) continue; } - uint8_t flags{}; + uint8_t flags {}; if (section.sh_flags & ByteSwap(SHF_EXECINSTR)) { diff --git a/XenonUtils/memory_mapped_file.cpp b/XenonUtils/memory_mapped_file.cpp index ba3c5d8..a315525 100644 --- a/XenonUtils/memory_mapped_file.cpp +++ b/XenonUtils/memory_mapped_file.cpp @@ -1,10 +1,10 @@ #include "memory_mapped_file.h" #if !defined(_WIN32) -# include -# include -# include -# include +#include +#include +#include +#include #endif MemoryMappedFile::MemoryMappedFile() @@ -12,7 +12,7 @@ MemoryMappedFile::MemoryMappedFile() // Default constructor. } -MemoryMappedFile::MemoryMappedFile(const std::filesystem::path &path) +MemoryMappedFile::MemoryMappedFile(const std::filesystem::path& path) { open(path); } @@ -22,7 +22,7 @@ MemoryMappedFile::~MemoryMappedFile() close(); } -MemoryMappedFile::MemoryMappedFile(MemoryMappedFile &&other) +MemoryMappedFile::MemoryMappedFile(MemoryMappedFile&& other) { #if defined(_WIN32) fileHandle = other.fileHandle; @@ -45,7 +45,7 @@ MemoryMappedFile::MemoryMappedFile(MemoryMappedFile &&other) #endif } -bool MemoryMappedFile::open(const std::filesystem::path &path) +bool MemoryMappedFile::open(const std::filesystem::path& path) { #if defined(_WIN32) fileHandle = CreateFileW(path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); @@ -154,9 +154,9 @@ bool MemoryMappedFile::isOpen() const #endif } -uint8_t *MemoryMappedFile::data() const +uint8_t* MemoryMappedFile::data() const { - return reinterpret_cast(fileView); + return reinterpret_cast(fileView); } size_t MemoryMappedFile::size() const diff --git a/XenonUtils/xdbf_wrapper.cpp b/XenonUtils/xdbf_wrapper.cpp index 9f6b2cd..7d73f58 100644 --- a/XenonUtils/xdbf_wrapper.cpp +++ b/XenonUtils/xdbf_wrapper.cpp @@ -36,7 +36,7 @@ XDBFBlock XDBFWrapper::GetResource(EXDBFNamespace ns, uint64_t id) const if (entry.NamespaceID == ns && entry.ResourceID == id) { - XDBFBlock block{}; + XDBFBlock block {}; block.pBuffer = pContent + entry.Offset; block.BufferSize = entry.Length; return block; @@ -89,7 +89,7 @@ std::vector XDBFWrapper::GetAchievements(EXDBFLanguage language) co seek += sizeof(XACHEntry); - Achievement achievement{}; + Achievement achievement {}; achievement.ID = entry->AchievementID; achievement.Name = GetString(language, entry->NameID); achievement.UnlockedDesc = GetString(language, entry->UnlockedDescID); @@ -112,7 +112,7 @@ std::vector XDBFWrapper::GetAchievements(EXDBFLanguage language) co Achievement XDBFWrapper::GetAchievement(EXDBFLanguage language, uint16_t id) const { - Achievement result{}; + Achievement result {}; auto achievementsBlock = GetResource(XDBF_SPA_NAMESPACE_METADATA, 0x58414348); diff --git a/XenonUtils/xex.cpp b/XenonUtils/xex.cpp index d1972c0..07af99c 100644 --- a/XenonUtils/xex.cpp +++ b/XenonUtils/xex.cpp @@ -1,125 +1,130 @@ #include "xex.h" #include "image.h" +#include #include #include -#include #include -#include +#include #define STRINGIFY(X) #X #define XE_EXPORT(MODULE, ORDINAL, NAME, TYPE) { (ORDINAL), "__imp__" STRINGIFY(NAME) } #ifndef _WIN32 -typedef struct _IMAGE_DOS_HEADER { - uint16_t e_magic; - uint16_t e_cblp; - uint16_t e_cp; - uint16_t e_crlc; - uint16_t e_cparhdr; - uint16_t e_minalloc; - uint16_t e_maxalloc; - uint16_t e_ss; - uint16_t e_sp; - uint16_t e_csum; - uint16_t e_ip; - uint16_t e_cs; - uint16_t e_lfarlc; - uint16_t e_ovno; - uint16_t e_res[4]; - uint16_t e_oemid; - uint16_t e_oeminfo; - uint16_t e_res2[10]; - uint32_t e_lfanew; -} IMAGE_DOS_HEADER, * PIMAGE_DOS_HEADER; +typedef struct _IMAGE_DOS_HEADER +{ + uint16_t e_magic; + uint16_t e_cblp; + uint16_t e_cp; + uint16_t e_crlc; + uint16_t e_cparhdr; + uint16_t e_minalloc; + uint16_t e_maxalloc; + uint16_t e_ss; + uint16_t e_sp; + uint16_t e_csum; + uint16_t e_ip; + uint16_t e_cs; + uint16_t e_lfarlc; + uint16_t e_ovno; + uint16_t e_res[4]; + uint16_t e_oemid; + uint16_t e_oeminfo; + uint16_t e_res2[10]; + uint32_t e_lfanew; +} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; -typedef struct _IMAGE_FILE_HEADER { - uint16_t Machine; - uint16_t NumberOfSections; - uint32_t TimeDateStamp; - uint32_t PointerToSymbolTable; - uint32_t NumberOfSymbols; - uint16_t SizeOfOptionalHeader; - uint16_t Characteristics; -} IMAGE_FILE_HEADER, * PIMAGE_FILE_HEADER; +typedef struct _IMAGE_FILE_HEADER +{ + uint16_t Machine; + uint16_t NumberOfSections; + uint32_t TimeDateStamp; + uint32_t PointerToSymbolTable; + uint32_t NumberOfSymbols; + uint16_t SizeOfOptionalHeader; + uint16_t Characteristics; +} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; -typedef struct _IMAGE_DATA_DIRECTORY { - uint32_t VirtualAddress; - uint32_t Size; -} IMAGE_DATA_DIRECTORY, * PIMAGE_DATA_DIRECTORY; +typedef struct _IMAGE_DATA_DIRECTORY +{ + uint32_t VirtualAddress; + uint32_t Size; +} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; -#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 +#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 -typedef struct _IMAGE_OPTIONAL_HEADER { - uint16_t Magic; - uint8_t MajorLinkerVersion; - uint8_t MinorLinkerVersion; - uint32_t SizeOfCode; - uint32_t SizeOfInitializedData; - uint32_t SizeOfUninitializedData; - uint32_t AddressOfEntryPoint; - uint32_t BaseOfCode; - uint32_t BaseOfData; - uint32_t ImageBase; - uint32_t SectionAlignment; - uint32_t FileAlignment; - uint16_t MajorOperatingSystemVersion; - uint16_t MinorOperatingSystemVersion; - uint16_t MajorImageVersion; - uint16_t MinorImageVersion; - uint16_t MajorSubsystemVersion; - uint16_t MinorSubsystemVersion; - uint32_t Win32VersionValue; - uint32_t SizeOfImage; - uint32_t SizeOfHeaders; - uint32_t CheckSum; - uint16_t Subsystem; - uint16_t DllCharacteristics; - uint32_t SizeOfStackReserve; - uint32_t SizeOfStackCommit; - uint32_t SizeOfHeapReserve; - uint32_t SizeOfHeapCommit; - uint32_t LoaderFlags; - uint32_t NumberOfRvaAndSizes; +typedef struct _IMAGE_OPTIONAL_HEADER +{ + uint16_t Magic; + uint8_t MajorLinkerVersion; + uint8_t MinorLinkerVersion; + uint32_t SizeOfCode; + uint32_t SizeOfInitializedData; + uint32_t SizeOfUninitializedData; + uint32_t AddressOfEntryPoint; + uint32_t BaseOfCode; + uint32_t BaseOfData; + uint32_t ImageBase; + uint32_t SectionAlignment; + uint32_t FileAlignment; + uint16_t MajorOperatingSystemVersion; + uint16_t MinorOperatingSystemVersion; + uint16_t MajorImageVersion; + uint16_t MinorImageVersion; + uint16_t MajorSubsystemVersion; + uint16_t MinorSubsystemVersion; + uint32_t Win32VersionValue; + uint32_t SizeOfImage; + uint32_t SizeOfHeaders; + uint32_t CheckSum; + uint16_t Subsystem; + uint16_t DllCharacteristics; + uint32_t SizeOfStackReserve; + uint32_t SizeOfStackCommit; + uint32_t SizeOfHeapReserve; + uint32_t SizeOfHeapCommit; + uint32_t LoaderFlags; + uint32_t NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; -} IMAGE_OPTIONAL_HEADER32, * PIMAGE_OPTIONAL_HEADER32; +} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32; -typedef struct _IMAGE_NT_HEADERS { +typedef struct _IMAGE_NT_HEADERS +{ uint32_t Signature; IMAGE_FILE_HEADER FileHeader; IMAGE_OPTIONAL_HEADER32 OptionalHeader; -} IMAGE_NT_HEADERS32, * PIMAGE_NT_HEADERS32; +} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32; -#define IMAGE_SIZEOF_SHORT_NAME 8 +#define IMAGE_SIZEOF_SHORT_NAME 8 -typedef struct _IMAGE_SECTION_HEADER { - uint8_t Name[IMAGE_SIZEOF_SHORT_NAME]; - union { - uint32_t PhysicalAddress; - uint32_t VirtualSize; +typedef struct _IMAGE_SECTION_HEADER +{ + uint8_t Name[IMAGE_SIZEOF_SHORT_NAME]; + union + { + uint32_t PhysicalAddress; + uint32_t VirtualSize; } Misc; - uint32_t VirtualAddress; - uint32_t SizeOfRawData; - uint32_t PointerToRawData; - uint32_t PointerToRelocations; - uint32_t PointerToLinenumbers; - uint16_t NumberOfRelocations; - uint16_t NumberOfLinenumbers; - uint32_t Characteristics; -} IMAGE_SECTION_HEADER, * PIMAGE_SECTION_HEADER; + uint32_t VirtualAddress; + uint32_t SizeOfRawData; + uint32_t PointerToRawData; + uint32_t PointerToRelocations; + uint32_t PointerToLinenumbers; + uint16_t NumberOfRelocations; + uint16_t NumberOfLinenumbers; + uint32_t Characteristics; +} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; -#define IMAGE_SCN_CNT_CODE 0x00000020 +#define IMAGE_SCN_CNT_CODE 0x00000020 #endif -std::unordered_map XamExports = -{ - #include "xbox/xam_table.inc" +std::unordered_map XamExports = { +#include "xbox/xam_table.inc" }; -std::unordered_map XboxKernelExports = -{ - #include "xbox/xboxkrnl_table.inc" +std::unordered_map XboxKernelExports = { +#include "xbox/xboxkrnl_table.inc" }; Image Xex2LoadImage(const uint8_t* data, size_t dataSize) @@ -128,8 +133,8 @@ Image Xex2LoadImage(const uint8_t* data, size_t dataSize) auto* security = reinterpret_cast(data + header->securityOffset); const auto* fileFormatInfo = reinterpret_cast(getOptHeaderPtr(data, XEX_HEADER_FILE_FORMAT_INFO)); - Image image{}; - std::unique_ptr result{}; + Image image {}; + std::unique_ptr result {}; size_t imageSize = security->imageSize; // Decompress image @@ -210,14 +215,14 @@ Image Xex2LoadImage(const uint8_t* data, size_t dataSize) for (size_t i = 0; i < numSections; i++) { const auto& section = sections[i]; - uint8_t flags{}; + uint8_t flags {}; if (section.Characteristics & IMAGE_SCN_CNT_CODE) { flags |= SectionFlags_Code; } - image.Map(reinterpret_cast(section.Name), section.VirtualAddress, + image.Map(reinterpret_cast(section.Name), section.VirtualAddress, section.Misc.VirtualSize, flags, image.data.get() + section.VirtualAddress); } diff --git a/XenonUtils/xex_patcher.cpp b/XenonUtils/xex_patcher.cpp index 18aacda..f123a29 100644 --- a/XenonUtils/xex_patcher.cpp +++ b/XenonUtils/xex_patcher.cpp @@ -17,22 +17,22 @@ #include #include +#include #include #include #include -#include #include "memory_mapped_file.h" struct mspack_memory_file { mspack_system sys; - void *buffer; + void* buffer; size_t bufferSize; size_t offset; }; -static mspack_memory_file *mspack_memory_open(mspack_system *sys, void *buffer, size_t bufferSize) +static mspack_memory_file* mspack_memory_open(mspack_system* sys, void* buffer, size_t bufferSize) { assert(bufferSize < INT_MAX); @@ -41,7 +41,7 @@ static mspack_memory_file *mspack_memory_open(mspack_system *sys, void *buffer, return nullptr; } - mspack_memory_file *memoryFile = (mspack_memory_file *)(std::calloc(1, sizeof(mspack_memory_file))); + mspack_memory_file* memoryFile = (mspack_memory_file*)(std::calloc(1, sizeof(mspack_memory_file))); if (memoryFile == nullptr) { return memoryFile; @@ -53,49 +53,49 @@ static mspack_memory_file *mspack_memory_open(mspack_system *sys, void *buffer, return memoryFile; } -static void mspack_memory_close(mspack_memory_file *file) +static void mspack_memory_close(mspack_memory_file* file) { std::free(file); } -static int mspack_memory_read(mspack_file *file, void *buffer, int chars) +static int mspack_memory_read(mspack_file* file, void* buffer, int chars) { - mspack_memory_file *memoryFile = (mspack_memory_file *)(file); + mspack_memory_file* memoryFile = (mspack_memory_file*)(file); const size_t remaining = memoryFile->bufferSize - memoryFile->offset; const size_t total = std::min(size_t(chars), remaining); - std::memcpy(buffer, (uint8_t *)(memoryFile->buffer) + memoryFile->offset, total); + std::memcpy(buffer, (uint8_t*)(memoryFile->buffer) + memoryFile->offset, total); memoryFile->offset += total; return int(total); } -static int mspack_memory_write(mspack_file *file, void *buffer, int chars) +static int mspack_memory_write(mspack_file* file, void* buffer, int chars) { - mspack_memory_file *memoryFile = (mspack_memory_file *)(file); + mspack_memory_file* memoryFile = (mspack_memory_file*)(file); const size_t remaining = memoryFile->bufferSize - memoryFile->offset; const size_t total = std::min(size_t(chars), remaining); - std::memcpy((uint8_t *)(memoryFile->buffer) + memoryFile->offset, buffer, total); + std::memcpy((uint8_t*)(memoryFile->buffer) + memoryFile->offset, buffer, total); memoryFile->offset += total; return int(total); } -static void *mspack_memory_alloc(mspack_system *sys, size_t chars) +static void* mspack_memory_alloc(mspack_system* sys, size_t chars) { return std::calloc(chars, 1); } -static void mspack_memory_free(void *ptr) +static void mspack_memory_free(void* ptr) { std::free(ptr); } -static void mspack_memory_copy(void *src, void *dest, size_t chars) +static void mspack_memory_copy(void* src, void* dest, size_t chars) { std::memcpy(dest, src, chars); } -static mspack_system *mspack_memory_sys_create() +static mspack_system* mspack_memory_sys_create() { - auto sys = (mspack_system *)(std::calloc(1, sizeof(mspack_system))); + auto sys = (mspack_system*)(std::calloc(1, sizeof(mspack_system))); if (!sys) { return nullptr; @@ -109,31 +109,31 @@ static mspack_system *mspack_memory_sys_create() return sys; } -static void mspack_memory_sys_destroy(struct mspack_system *sys) +static void mspack_memory_sys_destroy(struct mspack_system* sys) { free(sys); } #if defined(_WIN32) -inline bool bitScanForward(uint32_t v, uint32_t *outFirstSetIndex) +inline bool bitScanForward(uint32_t v, uint32_t* outFirstSetIndex) { - return _BitScanForward((unsigned long *)(outFirstSetIndex), v) != 0; + return _BitScanForward((unsigned long*)(outFirstSetIndex), v) != 0; } -inline bool bitScanForward(uint64_t v, uint32_t *outFirstSetIndex) +inline bool bitScanForward(uint64_t v, uint32_t* outFirstSetIndex) { - return _BitScanForward64((unsigned long *)(outFirstSetIndex), v) != 0; + return _BitScanForward64((unsigned long*)(outFirstSetIndex), v) != 0; } #else -inline bool bitScanForward(uint32_t v, uint32_t *outFirstSetIndex) +inline bool bitScanForward(uint32_t v, uint32_t* outFirstSetIndex) { int i = ffs(v); *outFirstSetIndex = i - 1; return i != 0; } -inline bool bitScanForward(uint64_t v, uint32_t *outFirstSetIndex) +inline bool bitScanForward(uint64_t v, uint32_t* outFirstSetIndex) { int i = __builtin_ffsll(v); *outFirstSetIndex = i - 1; @@ -141,20 +141,23 @@ inline bool bitScanForward(uint64_t v, uint32_t *outFirstSetIndex) } #endif -static int lzxDecompress(const void *lzxData, size_t lzxLength, void *dst, size_t dstLength, uint32_t windowSize, void *windowData, size_t windowDataLength) +static int lzxDecompress(const void* lzxData, size_t lzxLength, void* dst, size_t dstLength, uint32_t windowSize, void* windowData, size_t windowDataLength) { int resultCode = 1; uint32_t windowBits; - if (!bitScanForward(windowSize, &windowBits)) { + if (!bitScanForward(windowSize, &windowBits)) + { return resultCode; } - mspack_system *sys = mspack_memory_sys_create(); - mspack_memory_file *lzxSrc = mspack_memory_open(sys, (void *)(lzxData), lzxLength); - mspack_memory_file *lzxDst = mspack_memory_open(sys, dst, dstLength); - lzxd_stream *lzxd = lzxd_init(sys, (mspack_file *)(lzxSrc), (mspack_file *)(lzxDst), windowBits, 0, 0x8000, dstLength, 0); - if (lzxd != nullptr) { - if (windowData != nullptr) { + mspack_system* sys = mspack_memory_sys_create(); + mspack_memory_file* lzxSrc = mspack_memory_open(sys, (void*)(lzxData), lzxLength); + mspack_memory_file* lzxDst = mspack_memory_open(sys, dst, dstLength); + lzxd_stream* lzxd = lzxd_init(sys, (mspack_file*)(lzxSrc), (mspack_file*)(lzxDst), windowBits, 0, 0x8000, dstLength, 0); + if (lzxd != nullptr) + { + if (windowData != nullptr) + { size_t paddingLength = windowSize - windowDataLength; std::memset(&lzxd->window[0], 0, paddingLength); std::memcpy(&lzxd->window[paddingLength], windowData, windowDataLength); @@ -165,28 +168,31 @@ static int lzxDecompress(const void *lzxData, size_t lzxLength, void *dst, size_ lzxd_free(lzxd); } - if (lzxSrc) { + if (lzxSrc) + { mspack_memory_close(lzxSrc); } - if (lzxDst) { + if (lzxDst) + { mspack_memory_close(lzxDst); } - if (sys) { + if (sys) + { mspack_memory_sys_destroy(sys); } return resultCode; } -static int lzxDeltaApplyPatch(const Xex2DeltaPatch *deltaPatch, uint32_t patchLength, uint32_t windowSize, uint8_t *dstData) +static int lzxDeltaApplyPatch(const Xex2DeltaPatch* deltaPatch, uint32_t patchLength, uint32_t windowSize, uint8_t* dstData) { - const void *patchEnd = (const uint8_t *)(deltaPatch) + patchLength; - const Xex2DeltaPatch *curPatch = deltaPatch; + const void* patchEnd = (const uint8_t*)(deltaPatch) + patchLength; + const Xex2DeltaPatch* curPatch = deltaPatch; while (patchEnd > curPatch) { - int patchSize = -4; + int patchSize = -4; if (curPatch->compressedLength == 0 && curPatch->uncompressedLength == 0 && curPatch->newAddress == 0 && curPatch->oldAddress == 0) { // End of patch. @@ -216,23 +222,23 @@ static int lzxDeltaApplyPatch(const Xex2DeltaPatch *deltaPatch, uint32_t patchLe } curPatch++; - curPatch = (const Xex2DeltaPatch *)((const uint8_t *)(curPatch) + patchSize); + curPatch = (const Xex2DeltaPatch*)((const uint8_t*)(curPatch) + patchSize); } return 0; } -XexPatcher::Result XexPatcher::apply(const uint8_t* xexBytes, size_t xexBytesSize, const uint8_t* patchBytes, size_t patchBytesSize, std::vector &outBytes, bool skipData) +XexPatcher::Result XexPatcher::apply(const uint8_t* xexBytes, size_t xexBytesSize, const uint8_t* patchBytes, size_t patchBytesSize, std::vector& outBytes, bool skipData) { // Validate headers. static const char Xex2Magic[] = "XEX2"; - const Xex2Header *xexHeader = (const Xex2Header *)(xexBytes); + const Xex2Header* xexHeader = (const Xex2Header*)(xexBytes); if (memcmp(xexBytes, Xex2Magic, 4) != 0) { return Result::XexFileInvalid; } - const Xex2Header *patchHeader = (const Xex2Header *)(patchBytes); + const Xex2Header* patchHeader = (const Xex2Header*)(patchBytes); if (memcmp(patchBytes, Xex2Magic, 4) != 0) { return Result::PatchFileInvalid; @@ -244,13 +250,13 @@ XexPatcher::Result XexPatcher::apply(const uint8_t* xexBytes, size_t xexBytesSiz } // Validate patch. - const Xex2OptDeltaPatchDescriptor *patchDescriptor = (const Xex2OptDeltaPatchDescriptor *)(getOptHeaderPtr(patchBytes, XEX_HEADER_DELTA_PATCH_DESCRIPTOR)); + const Xex2OptDeltaPatchDescriptor* patchDescriptor = (const Xex2OptDeltaPatchDescriptor*)(getOptHeaderPtr(patchBytes, XEX_HEADER_DELTA_PATCH_DESCRIPTOR)); if (patchDescriptor == nullptr) { return Result::PatchFileInvalid; } - - const Xex2OptFileFormatInfo *patchFileFormatInfo = (const Xex2OptFileFormatInfo *)(getOptHeaderPtr(patchBytes, XEX_HEADER_FILE_FORMAT_INFO)); + + const Xex2OptFileFormatInfo* patchFileFormatInfo = (const Xex2OptFileFormatInfo*)(getOptHeaderPtr(patchBytes, XEX_HEADER_FILE_FORMAT_INFO)); if (patchFileFormatInfo == nullptr) { return Result::PatchFileInvalid; @@ -295,7 +301,7 @@ XexPatcher::Result XexPatcher::apply(const uint8_t* xexBytes, size_t xexBytesSiz memset(outBytes.data(), 0, newXexHeaderSize); memcpy(outBytes.data(), xexBytes, headerTargetSize); - Xex2Header *newXexHeader = (Xex2Header *)(outBytes.data()); + Xex2Header* newXexHeader = (Xex2Header*)(outBytes.data()); if (patchDescriptor->deltaHeadersSourceOffset > 0) { memcpy(&outBytes[patchDescriptor->deltaHeadersTargetOffset], &outBytes[patchDescriptor->deltaHeadersSourceOffset], patchDescriptor->deltaHeadersSourceSize); @@ -309,20 +315,20 @@ XexPatcher::Result XexPatcher::apply(const uint8_t* xexBytes, size_t xexBytesSiz // Make the header the specified size by the patch. outBytes.resize(headerTargetSize); - newXexHeader = (Xex2Header *)(outBytes.data()); + newXexHeader = (Xex2Header*)(outBytes.data()); // Copy the rest of the data. - const Xex2SecurityInfo *newSecurityInfo = (const Xex2SecurityInfo *)(&outBytes[newXexHeader->securityOffset]); + const Xex2SecurityInfo* newSecurityInfo = (const Xex2SecurityInfo*)(&outBytes[newXexHeader->securityOffset]); outBytes.resize(outBytes.size() + newSecurityInfo->imageSize); memset(&outBytes[headerTargetSize], 0, outBytes.size() - headerTargetSize); memcpy(&outBytes[headerTargetSize], &xexBytes[xexHeader->headerSize], xexBytesSize - xexHeader->headerSize); - newXexHeader = (Xex2Header *)(outBytes.data()); - newSecurityInfo = (const Xex2SecurityInfo *)(&outBytes[newXexHeader->securityOffset]); - + newXexHeader = (Xex2Header*)(outBytes.data()); + newSecurityInfo = (const Xex2SecurityInfo*)(&outBytes[newXexHeader->securityOffset]); + // Decrypt the keys and validate that the patch is compatible with the base file. constexpr uint32_t KeySize = 16; - const Xex2SecurityInfo *originalSecurityInfo = (const Xex2SecurityInfo *)(&xexBytes[xexHeader->securityOffset]); - const Xex2SecurityInfo *patchSecurityInfo = (const Xex2SecurityInfo *)(&patchBytes[patchHeader->securityOffset]); + const Xex2SecurityInfo* originalSecurityInfo = (const Xex2SecurityInfo*)(&xexBytes[xexHeader->securityOffset]); + const Xex2SecurityInfo* patchSecurityInfo = (const Xex2SecurityInfo*)(&patchBytes[patchHeader->securityOffset]); uint8_t decryptedOriginalKey[KeySize]; uint8_t decryptedNewKey[KeySize]; uint8_t decryptedPatchKey[KeySize]; @@ -356,9 +362,9 @@ XexPatcher::Result XexPatcher::apply(const uint8_t* xexBytes, size_t xexBytesSiz { return Result::Success; } - + // Decrypt base XEX if necessary. - const Xex2OptFileFormatInfo *fileFormatInfo = (const Xex2OptFileFormatInfo *)(getOptHeaderPtr(xexBytes, XEX_HEADER_FILE_FORMAT_INFO)); + const Xex2OptFileFormatInfo* fileFormatInfo = (const Xex2OptFileFormatInfo*)(getOptHeaderPtr(xexBytes, XEX_HEADER_FILE_FORMAT_INFO)); if (fileFormatInfo == nullptr) { return Result::XexFileInvalid; @@ -377,11 +383,12 @@ XexPatcher::Result XexPatcher::apply(const uint8_t* xexBytes, size_t xexBytesSiz // Decompress base XEX if necessary. if (fileFormatInfo->compressionType == XEX_COMPRESSION_BASIC) { - const Xex2FileBasicCompressionBlock *blocks = &((const Xex2FileBasicCompressionInfo*)(fileFormatInfo + 1))->firstBlock; + const Xex2FileBasicCompressionBlock* blocks = &((const Xex2FileBasicCompressionInfo*)(fileFormatInfo + 1))->firstBlock; int32_t numBlocks = (fileFormatInfo->infoSize / sizeof(Xex2FileBasicCompressionBlock)) - 1; int32_t baseCompressedSize = 0; int32_t baseImageSize = 0; - for (int32_t i = 0; i < numBlocks; i++) { + for (int32_t i = 0; i < numBlocks; i++) + { baseCompressedSize += blocks[i].dataSize; baseImageSize += blocks[i].dataSize + blocks[i].zeroSize; } @@ -390,10 +397,10 @@ XexPatcher::Result XexPatcher::apply(const uint8_t* xexBytes, size_t xexBytesSiz { return Result::XexFileInvalid; } - + // Reverse iteration allows to perform this decompression in place. - uint8_t *srcDataCursor = outBytes.data() + headerTargetSize + baseCompressedSize; - uint8_t *outDataCursor = outBytes.data() + headerTargetSize + baseImageSize; + uint8_t* srcDataCursor = outBytes.data() + headerTargetSize + baseCompressedSize; + uint8_t* outDataCursor = outBytes.data() + headerTargetSize + baseImageSize; for (int32_t i = numBlocks - 1; i >= 0; i--) { outDataCursor -= blocks[i].zeroSize; @@ -412,12 +419,12 @@ XexPatcher::Result XexPatcher::apply(const uint8_t* xexBytes, size_t xexBytesSiz return Result::XexFileInvalid; } - Xex2OptFileFormatInfo *newFileFormatInfo = (Xex2OptFileFormatInfo *)(getOptHeaderPtr(outBytes.data(), XEX_HEADER_FILE_FORMAT_INFO)); + Xex2OptFileFormatInfo* newFileFormatInfo = (Xex2OptFileFormatInfo*)(getOptHeaderPtr(outBytes.data(), XEX_HEADER_FILE_FORMAT_INFO)); if (newFileFormatInfo == nullptr) { return Result::PatchFailed; } - + // Update the header to indicate no encryption or compression is used. newFileFormatInfo->encryptionType = XEX_ENCRYPTION_NONE; newFileFormatInfo->compressionType = XEX_COMPRESSION_NONE; @@ -437,8 +444,8 @@ XexPatcher::Result XexPatcher::apply(const uint8_t* xexBytes, size_t xexBytesSiz return Result::PatchFileInvalid; } - const Xex2CompressedBlockInfo *currentBlock = &((const Xex2FileNormalCompressionInfo*)(patchFileFormatInfo + 1))->firstBlock; - uint8_t *outExe = &outBytes[newXexHeader->headerSize]; + const Xex2CompressedBlockInfo* currentBlock = &((const Xex2FileNormalCompressionInfo*)(patchFileFormatInfo + 1))->firstBlock; + uint8_t* outExe = &outBytes[newXexHeader->headerSize]; if (patchDescriptor->deltaImageSourceOffset > 0) { memcpy(&outExe[patchDescriptor->deltaImageTargetOffset], &outExe[patchDescriptor->deltaImageSourceOffset], patchDescriptor->deltaImageSourceSize); @@ -447,10 +454,10 @@ XexPatcher::Result XexPatcher::apply(const uint8_t* xexBytes, size_t xexBytesSiz static const uint32_t DigestSize = 20; uint8_t sha1Digest[DigestSize]; sha1::SHA1 sha1Context; - uint8_t *patchDataCursor = patchData.data(); + uint8_t* patchDataCursor = patchData.data(); while (currentBlock->blockSize > 0) { - const Xex2CompressedBlockInfo *nextBlock = (const Xex2CompressedBlockInfo *)(patchDataCursor); + const Xex2CompressedBlockInfo* nextBlock = (const Xex2CompressedBlockInfo*)(patchDataCursor); // Hash and validate the block. sha1Context.reset(); @@ -465,7 +472,7 @@ XexPatcher::Result XexPatcher::apply(const uint8_t* xexBytes, size_t xexBytesSiz // Apply the block's patch data. uint32_t blockDataSize = currentBlock->blockSize - 24; - if (lzxDeltaApplyPatch((const Xex2DeltaPatch *)(patchDataCursor), blockDataSize, ((const Xex2FileNormalCompressionInfo*)(patchFileFormatInfo + 1))->windowSize, outExe) != 0) + if (lzxDeltaApplyPatch((const Xex2DeltaPatch*)(patchDataCursor), blockDataSize, ((const Xex2FileNormalCompressionInfo*)(patchFileFormatInfo + 1))->windowSize, outExe) != 0) { return Result::PatchFailed; } @@ -477,7 +484,7 @@ XexPatcher::Result XexPatcher::apply(const uint8_t* xexBytes, size_t xexBytesSiz return Result::Success; } -XexPatcher::Result XexPatcher::apply(const std::filesystem::path &baseXexPath, const std::filesystem::path &patchXexPath, const std::filesystem::path &newXexPath) +XexPatcher::Result XexPatcher::apply(const std::filesystem::path& baseXexPath, const std::filesystem::path& patchXexPath, const std::filesystem::path& newXexPath) { MemoryMappedFile baseXexFile(baseXexPath); MemoryMappedFile patchFile(patchXexPath); @@ -499,7 +506,7 @@ XexPatcher::Result XexPatcher::apply(const std::filesystem::path &baseXexPath, c return Result::FileOpenFailed; } - newXexFile.write((const char *)(newXexBytes.data()), newXexBytes.size()); + newXexFile.write((const char*)(newXexBytes.data()), newXexBytes.size()); newXexFile.close(); if (newXexFile.bad())