mirror of
https://github.com/sal063/AC6_recomp
synced 2026-05-28 16:32:21 -04:00
148 lines
5.2 KiB
C++
148 lines
5.2 KiB
C++
/**
|
|
* @file rexcodegen/internal/config.h
|
|
* @brief Recompiler configuration types
|
|
*
|
|
* @copyright Copyright (c) 2026 Tom Clay <tomc@tctechstuff.com>
|
|
* All rights reserved.
|
|
*
|
|
* @license BSD 3-Clause License
|
|
* See LICENSE file in the project root for full license text.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <cstdint>
|
|
#include <filesystem>
|
|
#include <string>
|
|
#include <unordered_map>
|
|
#include <unordered_set>
|
|
#include <vector>
|
|
|
|
#include <rex/codegen/function_graph.h> // For JumpTable
|
|
|
|
namespace rex::codegen {
|
|
|
|
struct MidAsmHook {
|
|
std::string name;
|
|
std::vector<std::string> registers;
|
|
|
|
bool ret = false;
|
|
bool returnOnTrue = false;
|
|
bool returnOnFalse = false;
|
|
|
|
uint32_t jumpAddress = 0;
|
|
uint32_t jumpAddressOnTrue = 0;
|
|
uint32_t jumpAddressOnFalse = 0;
|
|
|
|
bool afterInstruction = false;
|
|
};
|
|
|
|
// Unified function/chunk configuration
|
|
// A "chunk" is simply a function entry with a non-zero parent field
|
|
struct FunctionConfig {
|
|
uint32_t size = 0; // Explicit size in bytes (mutually exclusive with end)
|
|
uint32_t end = 0; // End address, exclusive (mutually exclusive with size)
|
|
std::string name; // Custom symbol name (empty = auto-generate sub_XXXXXXXX)
|
|
uint32_t parent = 0; // Parent function address (0 = standalone, non-zero = chunk)
|
|
|
|
// Get effective size (prefers size over end)
|
|
uint32_t getSize(uint32_t address) const {
|
|
return size ? size : (end > address ? end - address : 0);
|
|
}
|
|
// Returns true if this is a discontinuous chunk belonging to a parent function
|
|
bool isChunk() const { return parent != 0; }
|
|
};
|
|
|
|
// Section info for analysis output
|
|
struct SectionInfo {
|
|
std::string name;
|
|
uint64_t address = 0;
|
|
uint64_t size = 0;
|
|
std::string flags; // "rx", "rw", "r" etc.
|
|
};
|
|
|
|
// Function entry for analysis output
|
|
struct FunctionEntry {
|
|
uint64_t address = 0;
|
|
uint64_t size = 0;
|
|
std::string name; // optional, defaults to "sub_XXXXXXXX"
|
|
};
|
|
|
|
struct RecompilerConfig {
|
|
// === Required user-provided fields ===
|
|
std::string projectName = "rex"; ///< Project name for output files
|
|
std::string filePath; ///< Path to XEX/ELF file
|
|
std::string outDirectoryPath; ///< Output directory for generated code
|
|
std::string templateDir; ///< Optional custom template directory for overrides
|
|
|
|
// Patch file paths (TODO: implement patching workflow)
|
|
std::string patchFilePath;
|
|
std::string patchedFilePath;
|
|
|
|
// === Code generation options (optional) ===
|
|
bool skipLr = false;
|
|
bool ctrAsLocalVariable = false;
|
|
bool xerAsLocalVariable = false;
|
|
bool reservedRegisterAsLocalVariable = false;
|
|
bool skipMsr = false;
|
|
bool crRegistersAsLocalVariables = false;
|
|
bool nonArgumentRegistersAsLocalVariables = false;
|
|
bool nonVolatileRegistersAsLocalVariables = false;
|
|
bool generateExceptionHandlers = false; ///< Generate SEH exception handler wrappers
|
|
|
|
// === Analysis tuning (optional) ===
|
|
uint32_t maxJumpExtension = 65536; ///< Max bytes to extend function for jump table targets
|
|
uint32_t dataRegionThreshold = 16; ///< Consecutive invalid instructions to mark as data region
|
|
uint32_t largeFunctionThreshold = 1048576; ///< 1MB - warn if function exceeds this size
|
|
|
|
// === Manual overrides ===
|
|
std::unordered_map<uint32_t, FunctionConfig> functions; ///< Function/chunk configuration
|
|
std::unordered_map<uint32_t, JumpTable> switchTables;
|
|
std::unordered_map<uint32_t, MidAsmHook> midAsmHooks;
|
|
uint32_t longJmpAddress = 0;
|
|
uint32_t setJmpAddress = 0;
|
|
|
|
// === rexcrt: CRT function address overrides ===
|
|
// Maps function name -> guest address (e.g. "CreateFileA" -> 0x8248B780)
|
|
// Parsed from [rexcrt] TOML table. Codegen generates rexcrt_<Name> entries.
|
|
std::unordered_map<std::string, uint32_t> rexcrtFunctions;
|
|
|
|
// === User hints (merged with analysis results in AnalysisState) ===
|
|
std::unordered_map<uint32_t, uint32_t> invalidInstructionHints; ///< addr -> size
|
|
std::unordered_set<uint32_t>
|
|
knownIndirectCallHints; ///< bctr addresses that are vtable/computed calls
|
|
std::vector<uint32_t> exceptionHandlerFuncHints; ///< Additional exception handler addresses
|
|
|
|
/**
|
|
* Load configuration from a TOML file.
|
|
*
|
|
* Supports an optional `includes` array for layered config. Paths in
|
|
* `includes` resolve relative to the including file's directory. Merge
|
|
* semantics: scalars last-wins, keyed tables additive (same key = last
|
|
* wins), arrays-of-tables deduplicated by primary key, sets additive.
|
|
*
|
|
* @param configFilePath Path to the TOML config file
|
|
* @return true on success, false on error (parse failure, circular
|
|
* include, depth exceeded)
|
|
*/
|
|
bool Load(const std::string_view& configFilePath);
|
|
|
|
/// Validation result containing warnings and errors.
|
|
struct ValidationResult {
|
|
bool valid = true; ///< true if no errors (warnings OK)
|
|
std::vector<std::string> warnings; ///< Non-fatal issues
|
|
std::vector<std::string> errors; ///< Fatal issues that block codegen
|
|
|
|
explicit operator bool() const { return valid; }
|
|
};
|
|
|
|
/**
|
|
* Validate the loaded configuration.
|
|
* Checks address alignment, required fields, and sanity constraints.
|
|
* @return ValidationResult with warnings and errors
|
|
*/
|
|
ValidationResult Validate() const;
|
|
};
|
|
|
|
} // namespace rex::codegen
|