-
Notifications
You must be signed in to change notification settings - Fork 129
Generated Code Structure
The rexglue codegen command produces a self-contained directory of C++ source files that implement the recompiled game logic. This page documents the output layout, file roles, function structure, and integration points. See Codegen Pipeline Overview for how the analysis and recompilation phases produce this output.
All files are written to the out_directory_path specified in the TOML config. Old generated files are cleaned before each run. The naming prefix is the project_name from the config.
output_dir/
{project}_init.h # Image constants, function-definition macros, forward declarations
{project}_init.cpp # PPCImageConfig + PPCFuncMappings[]
{project}_recomp.0.cpp # Recompiled functions (batch 0)
{project}_recomp.1.cpp # Recompiled functions (batch 1)
{project}_recomp.N.cpp # ... split for parallel compilation
sources.cmake # Source file list for CMake inclusion
The number of _recomp.N.cpp files depends on the function count and the functions_per_file CVar. Splitting keeps individual translation units small enough for reasonable compile times.
Defines image layout constants, the function-definition macros that recompiled code uses, and forward declarations for every function in the graph:
#pragma once
#define REX_IMAGE_BASE 0x82000000ull
#define REX_IMAGE_SIZE 0x1A00000ull
#define REX_CODE_BASE 0x82020000ull
#define REX_CODE_SIZE 0x190E000ull
#define REXCRT_HEAP 1 // 1 if [rexcrt] contains heap functions, 0 otherwise
#include <rex/ppc.h>
#include <rex/image_info.h>
extern const rex::PPCImageInfo PPCImageConfig;
extern PPCFuncMapping PPCFuncMappings[];
// Macros used by every recompiled function below
#define DECLARE_REX_FUNC(name) \
REX_EXTERN(name); \
REX_EXTERN(__imp__##name)
#define DEFINE_REX_FUNC(name) \
__attribute__((alias("__imp__" #name))) REX_WEAK_FUNC(name); \
REX_EXTERN(__imp__##name)
// Import function declarations
DECLARE_REX_FUNC(__imp__NtAllocateVirtualMemory);
DECLARE_REX_FUNC(__imp__DbgPrint);
// Recompiled function declarations
DECLARE_REX_FUNC(xstart);
DECLARE_REX_FUNC(sub_82003A40);
DECLARE_REX_FUNC(rexcrt_RtlAllocateHeap);
// ...DECLARE_REX_FUNC(name) declares both the public symbol and the __imp__-prefixed strong implementation. Functions mapped to [rexcrt] entries in the rexglue CLI Configuration File use the rexcrt_ prefix.
#define flags are emitted for each register locality option enabled in the TOML config:
| Define | Corresponding Config Flag |
|---|---|
REX_CONFIG_SKIP_LR |
skip_lr |
REX_CONFIG_CTR_AS_LOCAL |
ctr_as_local_variable |
REX_CONFIG_XER_AS_LOCAL |
xer_as_local_variable |
REX_CONFIG_RESERVED_AS_LOCAL |
reserved_register_as_local_variable |
REX_CONFIG_SKIP_MSR |
skip_msr |
REX_CONFIG_CR_AS_LOCAL |
cr_registers_as_local_variables |
REX_CONFIG_NON_ARGUMENT_AS_LOCAL |
non_argument_registers_as_local_variables |
REX_CONFIG_NON_VOLATILE_AS_LOCAL |
non_volatile_registers_as_local_variables |
Defines PPCImageConfig (passed to the SDK runtime to set up the guest memory layout and function table) and PPCFuncMappings[] (the guest-to-host address table consumed by FunctionDispatcher during Runtime::Setup()):
#include "{project}_init.h"
const rex::PPCImageInfo PPCImageConfig = {
REX_CODE_BASE, // code_base
REX_CODE_SIZE, // code_size
REX_IMAGE_BASE, // image_base
REX_IMAGE_SIZE, // image_size
PPCFuncMappings, // func_mappings
REXCRT_HEAP, // rexcrt_heap
};
PPCFuncMapping PPCFuncMappings[] = {
{ 0x82020000, xstart },
{ 0x82003A40, sub_82003A40 },
{ 0x82010000, rexcrt_RtlAllocateHeap },
// ... all recompiled functions
{ 0x82100000, __imp__NtAllocateVirtualMemory }, // import thunks
{ 0, nullptr } // null terminator
};Runtime::Setup() walks PPCFuncMappings[] and calls function_dispatcher->SetFunction(guest_addr, host_func_ptr) for each entry. This populates the function dispatch table stored at IMAGE_BASE + IMAGE_SIZE in guest memory, indexed by (guest_addr - CODE_BASE) * 2 (8-byte function pointers).
Each recompiled function follows a consistent pattern. Here is a representative example showing the key structural elements:
DEFINE_REX_FUNC(sub_82003A40) {
REX_FUNC_PROLOGUE();
// Local variable declarations (when register locality is enabled)
PPCRegister r0{};
PPCRegister r11{};
PPCRegister r12{};
PPCCRRegister cr0{};
// Block: 0x82003A40
// stwu r1, -0x20(r1)
ctx.r1.s64 = ctx.r1.s64 + -32;
PPC_STORE_U32(base, ctx.r1.u32 + 4294967264, ctx.r1.u32);
// mflr r0
r0.u64 = ctx.lr;
// stw r0, 0x24(r1)
PPC_STORE_U32(base, ctx.r1.u32 + 36, r0.u32);
// bl sub_82010000
ctx.lr = 0x82003A50;
sub_82010000(ctx, base);
// Block: 0x82003A50
// cmpwi cr0, r3, 0
cr0.compare<int32_t>(ctx.r3.s32, 0, ctx.xer);
// beq cr0, loc_82003A68
if (cr0.eq) goto loc_82003A68;
// bl __imp__DbgPrint
ctx.lr = 0x82003A5C;
__imp__DbgPrint(ctx, base);
loc_82003A68:
// Block: 0x82003A68
// lwz r0, 0x24(r1)
r0.u64 = PPC_LOAD_U32(base, ctx.r1.u32 + 36);
// mtlr r0
ctx.lr = r0.u64;
// addi r1, r1, 0x20
ctx.r1.s64 = ctx.r1.s64 + 32;
// blr
return;
}Key structural elements:
-
DEFINE_REX_FUNC(name): emits a weak alias fromnameto a strong__imp__nameimplementation, and opens the function body with the standard recompiled-function signaturevoid(PPCContext& ctx, uint8_t* base). The weak alias lets user code override any recompiled function by defining a strong symbol with the same name. -
REX_FUNC_PROLOGUE(): per-function prologue. Currently asserts membase alignment and (when profiling is enabled) opens a Tracy zone. - Local variable declarations: Only registers actually used in the function are declared, sized by the locality flags in rexglue CLI Configuration File.
- Block comments: Each basic block is annotated with its guest address. The original PPC disassembly appears as comments alongside each emitted C++ statement.
-
Labels: Internal branch targets use
loc_XXXXXXXX:labels. Conditional branches emitgoto loc_XXXXXXXX;for intra-function targets. -
Function calls: Set
ctx.lrto the return address, then call the target directly. -
Return:
blrtranslates toreturn;.
Functions with SEH scope tables (when --enable_exception_handlers is used) wrap their body in platform SEH macros:
DEFINE_REX_FUNC(sub_82050000) {
REX_FUNC_PROLOGUE();
// ... local declarations ...
SEH_TRY {
// ... function body ...
} SEH_CATCH_ALL {
REXLOG_WARN("SEH exception caught in sub_82050000");
// Run __finally handlers in reverse order
sub_82050100(ctx, base); // __finally handler
__restgprlr_14(ctx, base); // Restore caller registers
SEH_RETHROW;
} SEH_END
}Functions imported from Xbox 360 kernel modules (xboxkrnl.exe, xam.xex) are declared in {project}_init.h and appear in the mapping table. The SDK runtime provides implementations for these through its kernel module system.
Import thunks are included in PPCFuncMappings[] so that indirect calls (via function pointers stored in guest memory) can resolve to the correct host implementation at the import's original thunk address.
When the analysis pipeline cannot resolve a bl target to any function in the graph or import table, it reports a validation error:
UnresolvedCall (3):
0x82100000 from 0x82003A48: bl 0x82100000 from 0x82003A48 - target not in any function
With --force, code generation proceeds and the unresolved call site emits a fatal abort:
// FATAL: unresolved function 0x82100000
REX_FATAL("Unresolved call from 0x82003A48 to 0x82100000");Warning
Unresolved calls will abort at runtime if reached. Always investigate them.
Common causes and resolutions:
| Cause | Resolution |
|---|---|
| Function not discovered by analysis | Add the address with size under [functions] in the rexglue CLI Configuration File (e.g., 0x82000000 = { size = 64 }) |
| Target is in a data section | Verify the binary actually contains code at that address |
| Import not in the SDK's export tables | Implement the import in your project or add it to the SDK |
| Tail call to mid-function address | Specify the containing function with correct boundaries in config |
The [rexcrt] section in the rexglue CLI Configuration File maps C runtime function names to guest addresses. These functions are renamed to rexcrt_ prefixed names and excluded from recompilation; the SDK provides host-native implementations instead. See Memory for the ReXCRT allocator implementation.
[rexcrt]
RtlAllocateHeap = "0x820A0000"
RtlFreeHeap = "0x820A0100"
memcpy = "0x820B0000"In generated code, all call sites targeting these addresses emit the rexcrt_ name:
rexcrt_RtlAllocateHeap(ctx, base); // instead of sub_820A0000The sources.cmake file defines GENERATED_SOURCES which you add to your build target. See Function Overrides for REX_HOOK / REX_HOOK_RAW and the stub family, and Mid-ASM Hooks for in-function injection.
Mid-ASM hook configuration is documented in rexglue CLI Configuration File.
ReXGlue SDK
CLI Reference
Recompilation Pipeline
Runtime Architecture
Technical Reference