mirror of
				https://github.com/hedge-dev/XenonRecomp.git
				synced 2025-10-30 07:11:38 +00:00 
			
		
		
		
	Remove hardcoded recompiler, load TOML file for configuration.
This commit is contained in:
		
							parent
							
								
									54cb41c4db
								
							
						
					
					
						commit
						183027d563
					
				
					 11 changed files with 309 additions and 308 deletions
				
			
		|  | @ -40,6 +40,13 @@ size_t Function::SearchBlock(size_t address) const | ||||||
| Function Function::Analyze(const void* code, size_t size, size_t base) | Function 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
 | ||||||
|  |     { | ||||||
|  |         fn.size = 0x8; | ||||||
|  |         return fn; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     auto& blocks = fn.blocks; |     auto& blocks = fn.blocks; | ||||||
|     blocks.reserve(8); |     blocks.reserve(8); | ||||||
|     blocks.emplace_back(); |     blocks.emplace_back(); | ||||||
|  |  | ||||||
|  | @ -4,6 +4,6 @@ project("PowerRecomp") | ||||||
| 
 | 
 | ||||||
| BIN2H(SOURCE_FILE ${POWERUTILS_ROOT}/ppc_context.h HEADER_FILE "generated/ppc_context.gen.h" VARIABLE_NAME "gPPCContextText") | BIN2H(SOURCE_FILE ${POWERUTILS_ROOT}/ppc_context.h HEADER_FILE "generated/ppc_context.gen.h" VARIABLE_NAME "gPPCContextText") | ||||||
| 
 | 
 | ||||||
| add_executable(PowerRecomp "main.cpp" "pch.h" "recompiler.cpp" "recompiler.h" "swa_recompiler.cpp" "swa_recompiler.h" "test_recompiler.cpp" "test_recompiler.h") | add_executable(PowerRecomp "main.cpp" "pch.h" "recompiler.cpp" "recompiler.h" "test_recompiler.cpp" "test_recompiler.h" "recompiler_config.h" "recompiler_config.cpp") | ||||||
| target_precompile_headers(PowerRecomp PUBLIC "pch.h") | target_precompile_headers(PowerRecomp PUBLIC "pch.h") | ||||||
| target_link_libraries(PowerRecomp PRIVATE LibPowerAnalyse tomlplusplus::tomlplusplus xxHash::xxhash) | target_link_libraries(PowerRecomp PRIVATE LibPowerAnalyse tomlplusplus::tomlplusplus xxHash::xxhash) | ||||||
|  |  | ||||||
|  | @ -1,32 +1,20 @@ | ||||||
| #include "pch.h" | #include "pch.h" | ||||||
| #include "swa_recompiler.h" |  | ||||||
| #include "test_recompiler.h" | #include "test_recompiler.h" | ||||||
| 
 | 
 | ||||||
| // argv 1: xex file path
 |  | ||||||
| // argv 2: switches toml file path
 |  | ||||||
| // argv 3: output directory path
 |  | ||||||
| 
 |  | ||||||
| int main(int argc, char* argv[]) | int main(int argc, char* argv[]) | ||||||
| { | { | ||||||
|     if (strstr(argv[1], ".xex") != nullptr) |     const char* path =  | ||||||
|  |     #ifdef CONFIG_FILE_PATH | ||||||
|  |         CONFIG_FILE_PATH | ||||||
|  |     #else | ||||||
|  |         argv[1] | ||||||
|  |     #endif | ||||||
|  |         ; | ||||||
|  | 
 | ||||||
|  |     if (std::filesystem::is_regular_file(path)) | ||||||
|     { |     { | ||||||
|         SWARecompiler recompiler; |         Recompiler recompiler; | ||||||
|         //recompiler.config.skipLr = true;
 |         recompiler.LoadConfig(path); | ||||||
|         recompiler.config.ctrAsLocalVariable = true; |  | ||||||
|         recompiler.config.xerAsLocalVariable = true; |  | ||||||
|         recompiler.config.reservedRegisterAsLocalVariable = true; |  | ||||||
|         recompiler.config.skipMsr = true; |  | ||||||
|         recompiler.config.crRegistersAsLocalVariables = true; |  | ||||||
|         recompiler.config.nonArgumentRegistersAsLocalVariables = true; |  | ||||||
|         recompiler.config.nonVolatileRegistersAsLocalVariables = true; |  | ||||||
| 
 |  | ||||||
|         std::println("Loading executable..."); |  | ||||||
|         recompiler.LoadExecutable(argv[1]); |  | ||||||
| 
 |  | ||||||
|         std::println("Loading switch tables..."); |  | ||||||
|         recompiler.LoadSwitchTables(argv[2]); |  | ||||||
| 
 |  | ||||||
|         std::println("Analysing functions..."); |  | ||||||
|         recompiler.Analyse(); |         recompiler.Analyse(); | ||||||
| 
 | 
 | ||||||
|         auto entry = recompiler.image.symbols.find(recompiler.image.entry_point); |         auto entry = recompiler.image.symbols.find(recompiler.image.entry_point); | ||||||
|  | @ -35,11 +23,11 @@ int main(int argc, char* argv[]) | ||||||
|             entry->name = "_xstart"; |             entry->name = "_xstart"; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         recompiler.Recompile(argv[3]); |         recompiler.Recompile(); | ||||||
|     } |     } | ||||||
|     else |     else | ||||||
|     { |     { | ||||||
|         TestRecompiler::RecompileTests(argv[1], argv[2]); |         TestRecompiler::RecompileTests(path, argv[2]); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return 0; |     return 0; | ||||||
|  |  | ||||||
|  | @ -9,33 +9,156 @@ static uint64_t ComputeMask(uint32_t mstart, uint32_t mstop) | ||||||
|     return mstart <= mstop ? value : ~value; |     return mstart <= mstop ? value : ~value; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Recompiler::LoadSwitchTables(const char* filePath) | void Recompiler::LoadConfig(const std::string_view& configFilePath) | ||||||
| { | { | ||||||
|     toml::table toml = toml::parse_file(filePath); |     config.Load(configFilePath); | ||||||
|     for (auto& entry : *toml["switch"].as_array()) |  | ||||||
|     { |  | ||||||
|         auto& table = *entry.as_table(); |  | ||||||
| 
 | 
 | ||||||
|         SwitchTable switchTable; |     const auto file = LoadFile((config.directoryPath + config.filePath).c_str()).value(); | ||||||
|         switchTable.r = *table["r"].value<size_t>(); |     image = Image::ParseImage(file.data(), file.size()).value(); | ||||||
|         for (auto& array : *table["labels"].as_array()) |  | ||||||
|             switchTable.labels.push_back(*array.value<size_t>()); |  | ||||||
| 
 |  | ||||||
|         switchTables.emplace(*table["base"].value<size_t>(), std::move(switchTable)); |  | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Recompiler::LoadExecutable(const char* filePath) | void Recompiler::Analyse() | ||||||
| { | { | ||||||
|     const auto file = LoadFile(filePath).value(); |     for (size_t i = 14; i < 128; i++) | ||||||
|     image = Image::ParseImage(file.data(), file.size()).value(); |     { | ||||||
|  |         if (i < 32) | ||||||
|  |         { | ||||||
|  |             auto& restgpr = functions.emplace_back(); | ||||||
|  |             restgpr.base = config.restGpr14Address + (i - 14) * 4; | ||||||
|  |             restgpr.size = (32 - i) * 4 + 12; | ||||||
|  |             image.symbols.emplace(std::format("__restgprlr_{}", i), restgpr.base, restgpr.size, Symbol_Function); | ||||||
|  | 
 | ||||||
|  |             auto& savegpr = functions.emplace_back(); | ||||||
|  |             savegpr.base = config.saveGpr14Address + (i - 14) * 4; | ||||||
|  |             savegpr.size = (32 - i) * 4 + 8; | ||||||
|  |             image.symbols.emplace(std::format("__savegprlr_{}", i), savegpr.base, savegpr.size, Symbol_Function); | ||||||
|  | 
 | ||||||
|  |             auto& restfpr = functions.emplace_back(); | ||||||
|  |             restfpr.base = config.restFpr14Address + (i - 14) * 4; | ||||||
|  |             restfpr.size = (32 - i) * 4 + 4; | ||||||
|  |             image.symbols.emplace(std::format("__restfpr_{}", i), restfpr.base, restfpr.size, Symbol_Function); | ||||||
|  | 
 | ||||||
|  |             auto& savefpr = functions.emplace_back(); | ||||||
|  |             savefpr.base = config.saveFpr14Address + (i - 14) * 4; | ||||||
|  |             savefpr.size = (32 - i) * 4 + 4; | ||||||
|  |             image.symbols.emplace(std::format("__savefpr_{}", i), savefpr.base, savefpr.size, Symbol_Function); | ||||||
|  | 
 | ||||||
|  |             auto& restvmx = functions.emplace_back(); | ||||||
|  |             restvmx.base = config.restVmx14Address + (i - 14) * 8; | ||||||
|  |             restvmx.size = (32 - i) * 8 + 4; | ||||||
|  |             image.symbols.emplace(std::format("__restvmx_{}", i), restvmx.base, restvmx.size, Symbol_Function); | ||||||
|  | 
 | ||||||
|  |             auto& savevmx = functions.emplace_back(); | ||||||
|  |             savevmx.base = config.saveVmx14Address + (i - 14) * 8; | ||||||
|  |             savevmx.size = (32 - i) * 8 + 4; | ||||||
|  |             image.symbols.emplace(std::format("__savevmx_{}", i), savevmx.base, savevmx.size, Symbol_Function); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (i >= 64) | ||||||
|  |         { | ||||||
|  |             auto& restvmx = functions.emplace_back(); | ||||||
|  |             restvmx.base = config.restVmx64Address + (i - 64) * 8; | ||||||
|  |             restvmx.size = (128 - i) * 8 + 4; | ||||||
|  |             image.symbols.emplace(std::format("__restvmx_{}", i), restvmx.base, restvmx.size, Symbol_Function); | ||||||
|  | 
 | ||||||
|  |             auto& savevmx = functions.emplace_back(); | ||||||
|  |             savevmx.base = config.saveVmx64Address + (i - 64) * 8; | ||||||
|  |             savevmx.size = (128 - i) * 8 + 4; | ||||||
|  |             image.symbols.emplace(std::format("__savevmx_{}", i), savevmx.base, savevmx.size, Symbol_Function); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     for (auto& [address, size] : config.functions) | ||||||
|  |     { | ||||||
|  |         functions.emplace_back(address, size); | ||||||
|  |         image.symbols.emplace(std::format("sub_{:X}", address), address, size, Symbol_Function); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     auto& pdata = *image.Find(".pdata"); | ||||||
|  |     size_t count = pdata.size / sizeof(IMAGE_CE_RUNTIME_FUNCTION); | ||||||
|  |     auto* pf = (IMAGE_CE_RUNTIME_FUNCTION*)pdata.data; | ||||||
|  |     for (size_t i = 0; i < count; i++) | ||||||
|  |     { | ||||||
|  |         auto fn = pf[i]; | ||||||
|  |         fn.BeginAddress = std::byteswap(fn.BeginAddress); | ||||||
|  |         fn.Data = std::byteswap(fn.Data); | ||||||
|  | 
 | ||||||
|  |         if (image.symbols.find(fn.BeginAddress) == image.symbols.end()) | ||||||
|  |         { | ||||||
|  |             auto& f = functions.emplace_back(); | ||||||
|  |             f.base = fn.BeginAddress; | ||||||
|  |             f.size = fn.FunctionLength * 4; | ||||||
|  | 
 | ||||||
|  |             image.symbols.emplace(std::format("sub_{:X}", f.base), f.base, f.size, Symbol_Function); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     for (const auto& section : image.sections) | ||||||
|  |     { | ||||||
|  |         if (!(section.flags & SectionFlags_Code)) | ||||||
|  |         { | ||||||
|  |             continue; | ||||||
|  |         } | ||||||
|  |         size_t base = section.base; | ||||||
|  |         uint8_t* data = section.data; | ||||||
|  |         uint8_t* dataEnd = section.data + section.size; | ||||||
|  | 
 | ||||||
|  |         while (data < dataEnd) | ||||||
|  |         { | ||||||
|  |             uint32_t insn = std::byteswap(*(uint32_t*)data); | ||||||
|  |             if (PPC_OP(insn) == PPC_OP_B && PPC_BL(insn)) | ||||||
|  |             { | ||||||
|  |                 size_t address = base + (data - section.data) + PPC_BI(insn); | ||||||
|  | 
 | ||||||
|  |                 if (address >= section.base && address < section.base + section.size && image.symbols.find(address) == image.symbols.end()) | ||||||
|  |                 { | ||||||
|  |                     auto data = section.data + address - section.base; | ||||||
|  |                     auto& fn = functions.emplace_back(Function::Analyze(data, section.base + section.size - address, address)); | ||||||
|  |                     image.symbols.emplace(std::format("sub_{:X}", fn.base), fn.base, fn.size, Symbol_Function); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             data += 4; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         data = section.data; | ||||||
|  | 
 | ||||||
|  |         while (data < dataEnd) | ||||||
|  |         { | ||||||
|  |             auto invalidInstr = config.invalidInstructions.find(std::byteswap(*(uint32_t*)data)); | ||||||
|  |             if (invalidInstr != config.invalidInstructions.end()) | ||||||
|  |             { | ||||||
|  |                 base += invalidInstr->second; | ||||||
|  |                 data += invalidInstr->second; | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             auto fnSymbol = image.symbols.find(base); | ||||||
|  |             if (fnSymbol != image.symbols.end() && fnSymbol->address == base && fnSymbol->type == Symbol_Function) | ||||||
|  |             { | ||||||
|  |                 assert(fnSymbol->address == base); | ||||||
|  | 
 | ||||||
|  |                 base += fnSymbol->size; | ||||||
|  |                 data += fnSymbol->size; | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 auto& fn = functions.emplace_back(Function::Analyze(data, dataEnd - data, base)); | ||||||
|  |                 image.symbols.emplace(std::format("sub_{:X}", fn.base), fn.base, fn.size, Symbol_Function); | ||||||
|  | 
 | ||||||
|  |                 base += fn.size; | ||||||
|  |                 data += fn.size; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     std::sort(functions.begin(), functions.end(), [](auto& lhs, auto& rhs) { return lhs.base < rhs.base; }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool Recompiler::Recompile( | bool Recompiler::Recompile( | ||||||
|     const Function& fn, |     const Function& fn, | ||||||
|     uint32_t base, |     uint32_t base, | ||||||
|     const ppc_insn& insn, |     const ppc_insn& insn, | ||||||
|     std::unordered_map<size_t, SwitchTable>::iterator& switchTable, |     std::unordered_map<uint32_t, RecompilerSwitchTable>::iterator& switchTable, | ||||||
|     RecompilerLocalVariables& localVariables, |     RecompilerLocalVariables& localVariables, | ||||||
|     CSRState& csrState) |     CSRState& csrState) | ||||||
| { | { | ||||||
|  | @ -141,11 +264,11 @@ bool Recompiler::Recompile( | ||||||
| 
 | 
 | ||||||
|     auto printFunctionCall = [&](uint32_t address) |     auto printFunctionCall = [&](uint32_t address) | ||||||
|         { |         { | ||||||
|             if (address == longJmpAddress) |             if (address == config.longJmpAddress) | ||||||
|             { |             { | ||||||
|                 println("\tlongjmp(*reinterpret_cast<jmp_buf*>(base + {}.u32), {}.s32);", r(3), r(4)); |                 println("\tlongjmp(*reinterpret_cast<jmp_buf*>(base + {}.u32), {}.s32);", r(3), r(4)); | ||||||
|             } |             } | ||||||
|             else if (address == setJmpAddress) |             else if (address == config.setJmpAddress) | ||||||
|             { |             { | ||||||
|                 println("\t{} = ctx;", env()); |                 println("\t{} = ctx;", env()); | ||||||
|                 println("\t{}.s64 = setjmp(*reinterpret_cast<jmp_buf*>(base + {}.u32));", r(3), r(3)); |                 println("\t{}.s64 = setjmp(*reinterpret_cast<jmp_buf*>(base + {}.u32));", r(3), r(3)); | ||||||
|  | @ -292,7 +415,7 @@ bool Recompiler::Recompile( | ||||||
|         break; |         break; | ||||||
| 
 | 
 | ||||||
|     case PPC_INST_BCTR: |     case PPC_INST_BCTR: | ||||||
|         if (switchTable != switchTables.end()) |         if (switchTable != config.switchTables.end()) | ||||||
|         { |         { | ||||||
|             println("\tswitch ({}.u64) {{", r(switchTable->second.r)); |             println("\tswitch ({}.u64) {{", r(switchTable->second.r)); | ||||||
| 
 | 
 | ||||||
|  | @ -316,7 +439,7 @@ bool Recompiler::Recompile( | ||||||
|             println("\t\t__builtin_unreachable();"); |             println("\t\t__builtin_unreachable();"); | ||||||
|             println("\t}}"); |             println("\t}}"); | ||||||
| 
 | 
 | ||||||
|             switchTable = switchTables.end(); |             switchTable = config.switchTables.end(); | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
|  | @ -1963,8 +2086,8 @@ bool Recompiler::Recompile(const Function& fn) | ||||||
|                 labels.emplace(addr + PPC_BD(instruction)); |                 labels.emplace(addr + PPC_BD(instruction)); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         auto switchTable = switchTables.find(addr); |         auto switchTable = config.switchTables.find(addr); | ||||||
|         if (switchTable != switchTables.end()) |         if (switchTable != config.switchTables.end()) | ||||||
|         { |         { | ||||||
|             for (auto label : switchTable->second.labels) |             for (auto label : switchTable->second.labels) | ||||||
|                 labels.emplace(label); |                 labels.emplace(label); | ||||||
|  | @ -1986,7 +2109,7 @@ bool Recompiler::Recompile(const Function& fn) | ||||||
|     println("PPC_FUNC_IMPL(__imp__{}) {{", name); |     println("PPC_FUNC_IMPL(__imp__{}) {{", name); | ||||||
|     println("\tPPC_FUNC_PROLOGUE();"); |     println("\tPPC_FUNC_PROLOGUE();"); | ||||||
| 
 | 
 | ||||||
|     auto switchTable = switchTables.end(); |     auto switchTable = config.switchTables.end(); | ||||||
|     bool allRecompiled = true; |     bool allRecompiled = true; | ||||||
|     CSRState csrState = CSRState::Unknown; |     CSRState csrState = CSRState::Unknown; | ||||||
| 
 | 
 | ||||||
|  | @ -2010,8 +2133,8 @@ bool Recompiler::Recompile(const Function& fn) | ||||||
|             csrState = CSRState::Unknown; |             csrState = CSRState::Unknown; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (switchTable == switchTables.end()) |         if (switchTable == config.switchTables.end()) | ||||||
|             switchTable = switchTables.find(base); |             switchTable = config.switchTables.find(base); | ||||||
| 
 | 
 | ||||||
|         ppc::Disassemble(data, 4, base, insn); |         ppc::Disassemble(data, 4, base, insn); | ||||||
| 
 | 
 | ||||||
|  | @ -2025,7 +2148,7 @@ bool Recompiler::Recompile(const Function& fn) | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
|             if (insn.opcode->id == PPC_INST_BCTR && (*(data - 1) == 0x07008038 || *(data - 1) == 0x00000060) && switchTable == switchTables.end()) |             if (insn.opcode->id == PPC_INST_BCTR && (*(data - 1) == 0x07008038 || *(data - 1) == 0x00000060) && switchTable == config.switchTables.end()) | ||||||
|                 std::println("Found a switch jump table at {:X} with no switch table entry present", base); |                 std::println("Found a switch jump table at {:X} with no switch table entry present", base); | ||||||
| 
 | 
 | ||||||
|             if (!Recompile(fn, base, insn, switchTable, localVariables, csrState)) |             if (!Recompile(fn, base, insn, switchTable, localVariables, csrState)) | ||||||
|  | @ -2095,7 +2218,7 @@ bool Recompiler::Recompile(const Function& fn) | ||||||
|     return allRecompiled; |     return allRecompiled; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Recompiler::Recompile(const char* directoryPath) | void Recompiler::Recompile() | ||||||
| { | { | ||||||
|     out.reserve(10 * 1024 * 1024); |     out.reserve(10 * 1024 * 1024); | ||||||
| 
 | 
 | ||||||
|  | @ -2124,16 +2247,16 @@ void Recompiler::Recompile(const char* directoryPath) | ||||||
| 
 | 
 | ||||||
|         println("\n#endif"); |         println("\n#endif"); | ||||||
| 
 | 
 | ||||||
|         SaveCurrentOutData(directoryPath, "ppc_config.h"); |         SaveCurrentOutData("ppc_config.h"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     { |     { | ||||||
|         println("#pragma once"); |         println("#pragma once"); | ||||||
| 
 | 
 | ||||||
|         println("#include \"ppc_config.h\""); |         println("#include \"ppc_config.h\"\n"); | ||||||
|         println("{}", std::string_view{gPPCContextText, gPPCContextText_SIZE}); |         println("{}", std::string_view{gPPCContextText, gPPCContextText_SIZE}); | ||||||
| 
 | 
 | ||||||
|         SaveCurrentOutData(directoryPath, "ppc_context.h"); |         SaveCurrentOutData("ppc_context.h"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     { |     { | ||||||
|  | @ -2144,7 +2267,7 @@ void Recompiler::Recompile(const char* directoryPath) | ||||||
|         for (auto& symbol : image.symbols) |         for (auto& symbol : image.symbols) | ||||||
|             println("PPC_EXTERN_FUNC({});", symbol.name); |             println("PPC_EXTERN_FUNC({});", symbol.name); | ||||||
| 
 | 
 | ||||||
|         SaveCurrentOutData(directoryPath, "ppc_recomp_shared.h"); |         SaveCurrentOutData("ppc_recomp_shared.h"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     { |     { | ||||||
|  | @ -2157,14 +2280,14 @@ void Recompiler::Recompile(const char* directoryPath) | ||||||
|         println("\t{{ 0, nullptr }}"); |         println("\t{{ 0, nullptr }}"); | ||||||
|         println("}};"); |         println("}};"); | ||||||
| 
 | 
 | ||||||
|         SaveCurrentOutData(directoryPath, "ppc_func_mapping.cpp"); |         SaveCurrentOutData("ppc_func_mapping.cpp"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     for (size_t i = 0; i < functions.size(); i++) |     for (size_t i = 0; i < functions.size(); i++) | ||||||
|     { |     { | ||||||
|         if ((i % 256) == 0) |         if ((i % 256) == 0) | ||||||
|         { |         { | ||||||
|             SaveCurrentOutData(directoryPath); |             SaveCurrentOutData(); | ||||||
|             println("#include \"ppc_recomp_shared.h\"\n"); |             println("#include \"ppc_recomp_shared.h\"\n"); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -2174,10 +2297,10 @@ void Recompiler::Recompile(const char* directoryPath) | ||||||
|         Recompile(functions[i]); |         Recompile(functions[i]); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     SaveCurrentOutData(directoryPath); |     SaveCurrentOutData(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Recompiler::SaveCurrentOutData(const char* directoryPath, const std::string_view& name) | void Recompiler::SaveCurrentOutData(const std::string_view& name) | ||||||
| { | { | ||||||
|     if (!out.empty()) |     if (!out.empty()) | ||||||
|     { |     { | ||||||
|  | @ -2192,7 +2315,7 @@ void Recompiler::SaveCurrentOutData(const char* directoryPath, const std::string | ||||||
|         bool shouldWrite = true; |         bool shouldWrite = true; | ||||||
| 
 | 
 | ||||||
|         // Check if an identical file already exists first to not trigger recompilation
 |         // Check if an identical file already exists first to not trigger recompilation
 | ||||||
|         std::string filePath = std::format("{}/{}", directoryPath, name.empty() ? cppName : name); |         std::string filePath = std::format("{}/{}/{}", config.directoryPath, config.outDirectoryPath, name.empty() ? cppName : name); | ||||||
|         FILE* f = fopen(filePath.c_str(), "rb"); |         FILE* f = fopen(filePath.c_str(), "rb"); | ||||||
|         if (f) |         if (f) | ||||||
|         { |         { | ||||||
|  |  | ||||||
|  | @ -1,11 +1,7 @@ | ||||||
| #pragma once | #pragma once | ||||||
| #include "pch.h" |  | ||||||
| 
 | 
 | ||||||
| struct SwitchTable | #include "pch.h" | ||||||
| { | #include "recompiler_config.h" | ||||||
|     size_t r; |  | ||||||
|     std::vector<size_t> labels; |  | ||||||
| }; |  | ||||||
| 
 | 
 | ||||||
| struct RecompilerLocalVariables | struct RecompilerLocalVariables | ||||||
| { | { | ||||||
|  | @ -22,18 +18,6 @@ struct RecompilerLocalVariables | ||||||
|     bool ea{}; |     bool ea{}; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct RecompilerConfig |  | ||||||
| { |  | ||||||
|     bool skipLr = false; |  | ||||||
|     bool ctrAsLocalVariable = false; |  | ||||||
|     bool xerAsLocalVariable = false; |  | ||||||
|     bool reservedRegisterAsLocalVariable = false; |  | ||||||
|     bool skipMsr = false; |  | ||||||
|     bool crRegistersAsLocalVariables = false; |  | ||||||
|     bool nonArgumentRegistersAsLocalVariables = false; |  | ||||||
|     bool nonVolatileRegistersAsLocalVariables = false; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| enum class CSRState | enum class CSRState | ||||||
| { | { | ||||||
|     Unknown, |     Unknown, | ||||||
|  | @ -45,15 +29,11 @@ struct Recompiler | ||||||
| { | { | ||||||
|     Image image; |     Image image; | ||||||
|     std::vector<Function> functions; |     std::vector<Function> functions; | ||||||
|     std::unordered_map<size_t, SwitchTable> switchTables; |  | ||||||
|     std::string out; |     std::string out; | ||||||
|     size_t cppFileIndex = 0; |     size_t cppFileIndex = 0; | ||||||
|     uint32_t setJmpAddress = 0; |  | ||||||
|     uint32_t longJmpAddress = 0; |  | ||||||
|     RecompilerConfig config; |     RecompilerConfig config; | ||||||
| 
 | 
 | ||||||
|     void LoadSwitchTables(const char* filePath); |     void LoadConfig(const std::string_view& configFilePath); | ||||||
|     void LoadExecutable(const char* filePath); |  | ||||||
| 
 | 
 | ||||||
|     template<class... Args> |     template<class... Args> | ||||||
|     void print(std::format_string<Args...> fmt, Args&&... args) |     void print(std::format_string<Args...> fmt, Args&&... args) | ||||||
|  | @ -68,18 +48,20 @@ struct Recompiler | ||||||
|         out += '\n'; |         out += '\n'; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     void Analyse(); | ||||||
|  | 
 | ||||||
|     // TODO: make a RecompileArgs struct instead this is getting messy
 |     // TODO: make a RecompileArgs struct instead this is getting messy
 | ||||||
|     bool Recompile( |     bool Recompile( | ||||||
|         const Function& fn, |         const Function& fn, | ||||||
|         uint32_t base, |         uint32_t base, | ||||||
|         const ppc_insn& insn,  |         const ppc_insn& insn,  | ||||||
|         std::unordered_map<size_t, SwitchTable>::iterator& switchTable,  |         std::unordered_map<uint32_t, RecompilerSwitchTable>::iterator& switchTable, | ||||||
|         RecompilerLocalVariables& localVariables, |         RecompilerLocalVariables& localVariables, | ||||||
|         CSRState& csrState); |         CSRState& csrState); | ||||||
| 
 | 
 | ||||||
|     bool Recompile(const Function& fn); |     bool Recompile(const Function& fn); | ||||||
| 
 | 
 | ||||||
|     void Recompile(const char* directoryPath); |     void Recompile(); | ||||||
| 
 | 
 | ||||||
|     void SaveCurrentOutData(const char* directoryPath, const std::string_view& name = std::string_view()); |     void SaveCurrentOutData(const std::string_view& name = std::string_view()); | ||||||
| }; | }; | ||||||
|  |  | ||||||
							
								
								
									
										76
									
								
								PowerRecomp/recompiler_config.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								PowerRecomp/recompiler_config.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,76 @@ | ||||||
|  | #include "recompiler_config.h" | ||||||
|  | 
 | ||||||
|  | void RecompilerConfig::Load(const std::string_view& configFilePath) | ||||||
|  | { | ||||||
|  |     directoryPath = configFilePath.substr(0, configFilePath.find_last_of("\\/") + 1); | ||||||
|  |     toml::table toml = toml::parse_file(configFilePath); | ||||||
|  | 
 | ||||||
|  |     if (auto mainPtr = toml["main"].as_table()) | ||||||
|  |     { | ||||||
|  |         const auto& main = *mainPtr; | ||||||
|  |         filePath = main["file_path"].value_or<std::string>(""); | ||||||
|  |         outDirectoryPath = main["out_directory_path"].value_or<std::string>(""); | ||||||
|  |         switchTableFilePath = main["switch_table_file_path"].value_or<std::string>(""); | ||||||
|  | 
 | ||||||
|  |         skipLr = main["skip_lr"].value_or(false); | ||||||
|  |         skipMsr = main["skip_msr"].value_or(false); | ||||||
|  |         ctrAsLocalVariable = main["ctr_as_local"].value_or(false); | ||||||
|  |         xerAsLocalVariable = main["xer_as_local"].value_or(false); | ||||||
|  |         reservedRegisterAsLocalVariable = main["reserved_as_local"].value_or(false); | ||||||
|  |         crRegistersAsLocalVariables = main["cr_as_local"].value_or(false); | ||||||
|  |         nonArgumentRegistersAsLocalVariables = main["non_argument_as_local"].value_or(false); | ||||||
|  |         nonVolatileRegistersAsLocalVariables = main["non_volatile_as_local"].value_or(false); | ||||||
|  | 
 | ||||||
|  |         restGpr14Address = main["restgprlr_14_address"].value_or(0u); | ||||||
|  |         saveGpr14Address = main["savegprlr_14_address"].value_or(0u); | ||||||
|  |         restFpr14Address = main["restfpr_14_address"].value_or(0u); | ||||||
|  |         saveFpr14Address = main["savefpr_14_address"].value_or(0u); | ||||||
|  |         restVmx14Address = main["restvmx_14_address"].value_or(0u); | ||||||
|  |         saveVmx14Address = main["savevmx_14_address"].value_or(0u); | ||||||
|  |         restVmx64Address = main["restvmx_64_address"].value_or(0u); | ||||||
|  |         saveVmx64Address = main["savevmx_64_address"].value_or(0u); | ||||||
|  |         longJmpAddress = main["longjmp_address"].value_or(0u); | ||||||
|  |         setJmpAddress = main["setjmp_address"].value_or(0u); | ||||||
|  | 
 | ||||||
|  |         if (auto functionsArray = main["functions"].as_array()) | ||||||
|  |         { | ||||||
|  |             for (auto& func : *functionsArray) | ||||||
|  |             { | ||||||
|  |                 auto& funcTable = *func.as_table(); | ||||||
|  |                 uint32_t address = *funcTable["address"].value<uint32_t>(); | ||||||
|  |                 uint32_t size = *funcTable["size"].value<uint32_t>(); | ||||||
|  |                 functions.emplace(address, size); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (auto invalidArray = main["invalid_instructions"].as_array()) | ||||||
|  |         { | ||||||
|  |             for (auto& instr : *invalidArray) | ||||||
|  |             { | ||||||
|  |                 auto& instrTable = *instr.as_table(); | ||||||
|  |                 uint32_t data = *instrTable["data"].value<uint32_t>(); | ||||||
|  |                 uint32_t size = *instrTable["size"].value<uint32_t>(); | ||||||
|  |                 invalidInstructions.emplace(data, size); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (!switchTableFilePath.empty()) | ||||||
|  |         { | ||||||
|  |             toml::table switchToml = toml::parse_file(directoryPath + switchTableFilePath); | ||||||
|  |             if (auto switchArray = switchToml["switch"].as_array()) | ||||||
|  |             { | ||||||
|  |                 for (auto& entry : *switchArray) | ||||||
|  |                 { | ||||||
|  |                     auto& table = *entry.as_table(); | ||||||
|  |                     RecompilerSwitchTable switchTable; | ||||||
|  |                     switchTable.r = *table["r"].value<uint32_t>(); | ||||||
|  |                     for (auto& label : *table["labels"].as_array()) | ||||||
|  |                     { | ||||||
|  |                         switchTable.labels.push_back(*label.value<uint32_t>()); | ||||||
|  |                     } | ||||||
|  |                     switchTables.emplace(*table["base"].value<uint32_t>(), std::move(switchTable)); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										38
									
								
								PowerRecomp/recompiler_config.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								PowerRecomp/recompiler_config.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,38 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | struct RecompilerSwitchTable | ||||||
|  | { | ||||||
|  |     uint32_t r; | ||||||
|  |     std::vector<uint32_t> labels; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct RecompilerConfig | ||||||
|  | { | ||||||
|  |     std::string directoryPath; | ||||||
|  |     std::string filePath; | ||||||
|  |     std::string outDirectoryPath; | ||||||
|  |     std::string switchTableFilePath; | ||||||
|  |     std::unordered_map<uint32_t, RecompilerSwitchTable> switchTables; | ||||||
|  |     bool skipLr = false; | ||||||
|  |     bool ctrAsLocalVariable = false; | ||||||
|  |     bool xerAsLocalVariable = false; | ||||||
|  |     bool reservedRegisterAsLocalVariable = false; | ||||||
|  |     bool skipMsr = false; | ||||||
|  |     bool crRegistersAsLocalVariables = false; | ||||||
|  |     bool nonArgumentRegistersAsLocalVariables = false; | ||||||
|  |     bool nonVolatileRegistersAsLocalVariables = false; | ||||||
|  |     uint32_t restGpr14Address = 0; | ||||||
|  |     uint32_t saveGpr14Address = 0; | ||||||
|  |     uint32_t restFpr14Address = 0; | ||||||
|  |     uint32_t saveFpr14Address = 0; | ||||||
|  |     uint32_t restVmx14Address = 0; | ||||||
|  |     uint32_t saveVmx14Address = 0; | ||||||
|  |     uint32_t restVmx64Address = 0; | ||||||
|  |     uint32_t saveVmx64Address = 0; | ||||||
|  |     uint32_t longJmpAddress = 0; | ||||||
|  |     uint32_t setJmpAddress = 0; | ||||||
|  |     std::unordered_map<uint32_t, uint32_t> functions; | ||||||
|  |     std::unordered_map<uint32_t, uint32_t> invalidInstructions; | ||||||
|  | 
 | ||||||
|  |     void Load(const std::string_view& configFilePath); | ||||||
|  | }; | ||||||
|  | @ -1,208 +0,0 @@ | ||||||
| #include "pch.h" |  | ||||||
| #include "swa_recompiler.h" |  | ||||||
| 
 |  | ||||||
| void SWARecompiler::Analyse() |  | ||||||
| { |  | ||||||
|     constexpr uint32_t cxxFrameHandler = std::byteswap(0x831B1C90); |  | ||||||
|     constexpr uint32_t cSpecificFrameHandler = std::byteswap(0x8324B3BC); |  | ||||||
|     constexpr uint32_t yetAnotherFrameHandler = std::byteswap(0x831C8B50); |  | ||||||
| 
 |  | ||||||
|     auto& pdata = *image.Find(".pdata"); |  | ||||||
|     size_t count = pdata.size / sizeof(IMAGE_CE_RUNTIME_FUNCTION); |  | ||||||
|     auto* pf = (IMAGE_CE_RUNTIME_FUNCTION*)pdata.data; |  | ||||||
|     for (size_t i = 0; i < count; i++) |  | ||||||
|     { |  | ||||||
|         auto fn = pf[i]; |  | ||||||
|         fn.BeginAddress = std::byteswap(fn.BeginAddress); |  | ||||||
|         fn.Data = std::byteswap(fn.Data); |  | ||||||
| 
 |  | ||||||
|         auto& f = functions.emplace_back(); |  | ||||||
|         f.base = fn.BeginAddress; |  | ||||||
|         f.size = fn.FunctionLength * 4; |  | ||||||
| 
 |  | ||||||
|         std::string name; |  | ||||||
|         if (f.base == 0x831B0B40) name = "__restgprlr_14"; |  | ||||||
|         else if (f.base == 0x831B0AF0) name = "__savegprlr_14"; |  | ||||||
|         else if (f.base == 0x831B144C) name = "__restfpr_14"; |  | ||||||
|         else if (f.base == 0x831B1400) name = "__savefpr_14"; |  | ||||||
|         else if (f.base == 0x831B36E8) name = "__restvmx_14"; |  | ||||||
|         else if (f.base == 0x831B3450) name = "__savevmx_14"; |  | ||||||
|         else if (f.base == 0x831B377C) name = "__restvmx_64"; |  | ||||||
|         else if (f.base == 0x831B34E4) name = "__savevmx_64"; |  | ||||||
|         else name = std::format("sub_{:X}", f.base); |  | ||||||
| 
 |  | ||||||
|         image.symbols.emplace(name, f.base, f.size, Symbol_Function); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     for (size_t i = 15; i < 128; i++) |  | ||||||
|     { |  | ||||||
|         if (i < 32) |  | ||||||
|         { |  | ||||||
|             auto& restgpr = functions.emplace_back(); |  | ||||||
|             restgpr.base = 0x831B0B40 + (i - 14) * 4; |  | ||||||
|             restgpr.size = 0x831B0B94 - restgpr.base; |  | ||||||
|             image.symbols.emplace(std::format("__restgprlr_{}", i), restgpr.base, restgpr.size, Symbol_Function); |  | ||||||
| 
 |  | ||||||
|             auto& savegpr = functions.emplace_back(); |  | ||||||
|             savegpr.base = 0x831B0AF0 + (i - 14) * 4; |  | ||||||
|             savegpr.size = 0x831B0B40 - savegpr.base; |  | ||||||
|             image.symbols.emplace(std::format("__savegprlr_{}", i), savegpr.base, savegpr.size, Symbol_Function); |  | ||||||
| 
 |  | ||||||
|             auto& restfpr = functions.emplace_back(); |  | ||||||
|             restfpr.base = 0x831B144C + (i - 14) * 4; |  | ||||||
|             restfpr.size = 0x831B1498 - restfpr.base; |  | ||||||
|             image.symbols.emplace(std::format("__restfpr_{}", i), restfpr.base, restfpr.size, Symbol_Function); |  | ||||||
| 
 |  | ||||||
|             auto& savefpr = functions.emplace_back(); |  | ||||||
|             savefpr.base = 0x831B1400 + (i - 14) * 4; |  | ||||||
|             savefpr.size = 0x831B144C - savefpr.base; |  | ||||||
|             image.symbols.emplace(std::format("__savefpr_{}", i), savefpr.base, savefpr.size, Symbol_Function); |  | ||||||
| 
 |  | ||||||
|             auto& restvmx = functions.emplace_back(); |  | ||||||
|             restvmx.base = 0x831B36E8 + (i - 14) * 8; |  | ||||||
|             restvmx.size = 0x831B377C - restvmx.base; |  | ||||||
|             image.symbols.emplace(std::format("__restvmx_{}", i), restvmx.base, restvmx.size, Symbol_Function); |  | ||||||
| 
 |  | ||||||
|             auto& savevmx = functions.emplace_back(); |  | ||||||
|             savevmx.base = 0x831B3450 + (i - 14) * 8; |  | ||||||
|             savevmx.size = 0x831B34E4 - savevmx.base; |  | ||||||
|             image.symbols.emplace(std::format("__savevmx_{}", i), savevmx.base, savevmx.size, Symbol_Function); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if (i >= 64) |  | ||||||
|         { |  | ||||||
|             auto& restvmx = functions.emplace_back(); |  | ||||||
|             restvmx.base = 0x831B377C + (i - 64) * 8; |  | ||||||
|             restvmx.size = 0x831B3980 - restvmx.base; |  | ||||||
|             image.symbols.emplace(std::format("__restvmx_{}", i), restvmx.base, restvmx.size, Symbol_Function); |  | ||||||
| 
 |  | ||||||
|             auto& savevmx = functions.emplace_back(); |  | ||||||
|             savevmx.base = 0x831B34E4 + (i - 64) * 8; |  | ||||||
|             savevmx.size = 0x831B36E8 - savevmx.base; |  | ||||||
|             image.symbols.emplace(std::format("__savevmx_{}", i), savevmx.base, savevmx.size, Symbol_Function); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     auto hardcodedFuncCheck = [&](uint8_t* data, Function& f) |  | ||||||
|         { |  | ||||||
|             if (*(uint32_t*)(data + 4) == 0x04000048) f.size = 0x8; // shifted ptr tail call
 |  | ||||||
|             else if (f.base == 0x824E7EF0) f.size = 0x98; |  | ||||||
|             else if (f.base == 0x824E7F28) f.size = 0x60; |  | ||||||
|             else if (f.base == 0x82C980E8) f.size = 0x110; |  | ||||||
|             else if (f.base == 0x82CF7080) f.size = 0x80; |  | ||||||
|             else if (f.base == 0x82D9AC08) f.size = 0x78; |  | ||||||
|             else if (f.base == 0x82E86770) f.size = 0x98; |  | ||||||
|             else if (f.base == 0x82E97E50) f.size = 0x84; |  | ||||||
|             else if (f.base == 0x82EE2D08) f.size = 0x154; |  | ||||||
|             else if (f.base == 0x82EF5C38) f.size = 0x64; |  | ||||||
|             else if (f.base == 0x82EF5D78) f.size = 0x3F8; |  | ||||||
|             else if (f.base == 0x82F08730) f.size = 0x2B0; |  | ||||||
|             else if (f.base == 0x82F098C0) f.size = 0x19C; |  | ||||||
|             else if (f.base == 0x82F13980) f.size = 0xF4; |  | ||||||
|             else if (f.base == 0x82F1D668) f.size = 0x1E8; |  | ||||||
|             else if (f.base == 0x82F22908) f.size = 0x20C; |  | ||||||
|             else if (f.base == 0x82F25FD8) f.size = 0x240; |  | ||||||
|             else if (f.base == 0x82F852A0) f.size = 0xCC; |  | ||||||
|             else if (f.base == 0x830DADA0) f.size = 0x150; |  | ||||||
|             else if (f.base == 0x831487D0) f.size = 0xD4; |  | ||||||
|             else if (f.base == 0x831530C8) f.size = 0x258; |  | ||||||
|             else if (f.base == 0x831539E0) f.size = 0xD0; |  | ||||||
|             else if (f.base == 0x83168940) f.size = 0x100; |  | ||||||
|             else if (f.base == 0x83168A48) f.size = 0x11C; |  | ||||||
|             else if (f.base == 0x83168B70) f.size = 0x128; |  | ||||||
|             else if (f.base == 0x83168F18) f.size = 0x254; |  | ||||||
|             else if (f.base == 0x8316C678) f.size = 0x78; |  | ||||||
|             else if (f.base == 0x8317CD30) f.size = 0x50; |  | ||||||
|             else if (f.base == 0x83180700) f.size = 0x74; |  | ||||||
|             else if (f.base == 0x8319ED58) f.size = 0x98; |  | ||||||
|             else if (f.base == 0x82455E70) f.size = 0x84; |  | ||||||
|             else if (f.base == 0x82456DC8) f.size = 0xD4; |  | ||||||
|             else if (f.base == 0x826ABB70) f.size = 0x70; |  | ||||||
|             else if (f.base == 0x82893088) f.size = 0x45C; |  | ||||||
|             else if (f.base == 0x82C49540) f.size = 0x114; |  | ||||||
|             else if (f.base == 0x82DE35D8) f.size = 0x68; |  | ||||||
|             else if (f.base == 0x82DE3640) f.size = 0x64; |  | ||||||
|             else if (f.base == 0x82DE36A8) f.size = 0x5C; |  | ||||||
|             else if (f.base == 0x82DE3708) f.size = 0x198; |  | ||||||
|             else if (f.base == 0x82DE38A0) f.size = 0x16C; |  | ||||||
|             else if (f.base == 0x830B7DD0) f.size = 0x74; |  | ||||||
|             else if (f.base == 0x831B0BA0) f.size = 0xA0; |  | ||||||
|             else if (f.base == 0x8305D168) f.size = 0x278; |  | ||||||
|         }; |  | ||||||
| 
 |  | ||||||
|     for (const auto& section : image.sections) |  | ||||||
|     { |  | ||||||
|         if (!(section.flags & SectionFlags_Code)) |  | ||||||
|         { |  | ||||||
|             continue; |  | ||||||
|         } |  | ||||||
|         size_t base = section.base; |  | ||||||
|         uint8_t* data = section.data; |  | ||||||
|         uint8_t* dataEnd = section.data + section.size; |  | ||||||
| 
 |  | ||||||
|         while (data < dataEnd) |  | ||||||
|         { |  | ||||||
|             uint32_t insn = std::byteswap(*(uint32_t*)data); |  | ||||||
|             if (PPC_OP(insn) == PPC_OP_B && PPC_BL(insn)) |  | ||||||
|             { |  | ||||||
|                 size_t address = base + (data - section.data) + PPC_BI(insn); |  | ||||||
| 
 |  | ||||||
|                 if (address >= section.base && address < section.base + section.size && image.symbols.find(address) == image.symbols.end()) |  | ||||||
|                 { |  | ||||||
|                     auto data = section.data + address - section.base; |  | ||||||
|                     auto& fn = functions.emplace_back(Function::Analyze(data, section.base + section.size - address, address)); |  | ||||||
|                     hardcodedFuncCheck(data, fn); |  | ||||||
|                     image.symbols.emplace(std::format("sub_{:X}", fn.base), fn.base, fn.size, Symbol_Function); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             data += 4; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         data = section.data; |  | ||||||
| 
 |  | ||||||
|         while (data < dataEnd) |  | ||||||
|         { |  | ||||||
|             if (*(uint32_t*)data == 0) |  | ||||||
|             { |  | ||||||
|                 data += 4; |  | ||||||
|                 base += 4; |  | ||||||
|                 continue; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             if (*(uint32_t*)data == cxxFrameHandler || *(uint32_t*)data == cSpecificFrameHandler || *(uint32_t*)data == yetAnotherFrameHandler) |  | ||||||
|             { |  | ||||||
|                 data += 8; |  | ||||||
|                 base += 8; |  | ||||||
|                 continue; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             if (*(uint32_t*)data == 0x45564800) |  | ||||||
|             { |  | ||||||
|                 break; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             auto fnSymbol = image.symbols.find(base); |  | ||||||
|             if (fnSymbol != image.symbols.end() && fnSymbol->address == base && fnSymbol->type == Symbol_Function) |  | ||||||
|             { |  | ||||||
|                 assert(fnSymbol->address == base); |  | ||||||
| 
 |  | ||||||
|                 base += fnSymbol->size; |  | ||||||
|                 data += fnSymbol->size; |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 auto& fn = functions.emplace_back(Function::Analyze(data, dataEnd - data, base)); |  | ||||||
|                 hardcodedFuncCheck(data, fn); |  | ||||||
|                 image.symbols.emplace(std::format("sub_{:X}", fn.base), fn.base, fn.size, Symbol_Function); |  | ||||||
| 
 |  | ||||||
|                 base += fn.size; |  | ||||||
|                 data += fn.size; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     std::sort(functions.begin(), functions.end(), [](auto& lhs, auto& rhs) { return lhs.base < rhs.base; }); |  | ||||||
| 
 |  | ||||||
|     setJmpAddress = 0x831B6AB0; |  | ||||||
|     longJmpAddress = 0x831B6790; |  | ||||||
| } |  | ||||||
|  | @ -1,7 +0,0 @@ | ||||||
| #pragma once |  | ||||||
| #include "recompiler.h" |  | ||||||
| 
 |  | ||||||
| struct SWARecompiler : Recompiler |  | ||||||
| { |  | ||||||
|     void Analyse(); |  | ||||||
| }; |  | ||||||
|  | @ -40,8 +40,12 @@ void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* ds | ||||||
|     { |     { | ||||||
|         if (file.path().extension() == ".o") |         if (file.path().extension() == ".o") | ||||||
|         { |         { | ||||||
|  |             const auto exeFile = LoadFile(file.path().string().c_str()).value(); | ||||||
|  | 
 | ||||||
|             TestRecompiler recompiler; |             TestRecompiler recompiler; | ||||||
|             recompiler.LoadExecutable(file.path().string().c_str()); |             recompiler.config.outDirectoryPath = dstDirectoryPath; | ||||||
|  |             recompiler.image = Image::ParseImage(exeFile.data(), exeFile.size()).value(); | ||||||
|  | 
 | ||||||
|             auto stem = file.path().stem().string(); |             auto stem = file.path().stem().string(); | ||||||
|             recompiler.Analyse(stem); |             recompiler.Analyse(stem); | ||||||
| 
 | 
 | ||||||
|  | @ -61,7 +65,7 @@ void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* ds | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             stem += ".cpp"; |             stem += ".cpp"; | ||||||
|             recompiler.SaveCurrentOutData(dstDirectoryPath, stem); |             recompiler.SaveCurrentOutData(stem); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -5,12 +5,10 @@ add_compile_options( | ||||||
|     "/fp:strict" |     "/fp:strict" | ||||||
|     "/GS-" |     "/GS-" | ||||||
|     "/EHa-" |     "/EHa-" | ||||||
|     "-march=haswell" |     "-march=sandybridge" | ||||||
|     "-fno-strict-aliasing") |     "-fno-strict-aliasing") | ||||||
| 
 | 
 | ||||||
| file(GLOB RecompiledFiles *.cpp) | file(GLOB RecompiledFiles *.cpp) | ||||||
| add_library(PowerSample ${RecompiledFiles}) | add_library(PowerSample ${RecompiledFiles}) | ||||||
| 
 | 
 | ||||||
| target_precompile_headers(PowerSample PUBLIC "ppc_recomp_shared.h") | target_precompile_headers(PowerSample PUBLIC "ppc_recomp_shared.h") | ||||||
| 
 |  | ||||||
| target_link_libraries(PowerSample PUBLIC PowerUtils) |  | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Skyth
						Skyth