﻿# Debugging Recompiled Code
Source: https://rexglue-rexglue-sdk.mintlify.app/advanced/debugging

Debug and troubleshoot recompiled PowerPC executables

## Overview

Debugging recompiled code presents unique challenges since the generated C++ code doesn't directly correspond to the original PowerPC assembly. This guide covers tools, techniques, and common issues when debugging ReXGlue applications.

## Build Configuration

### Debug vs Release Builds

ReXGlue supports multiple build configurations via CMake:

```bash theme={null}
# Debug build (no optimization, full symbols)
cmake -B build -DCMAKE_BUILD_TYPE=Debug
cmake --build build --config Debug

# Release build (full optimization)
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --config Release

# Release with debug info
cmake -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo
cmake --build build --config RelWithDebInfo
```

**Debug flags** (from CMakeLists.txt:72-73):

* `-g`: Generate debug symbols
* `-O0`: No optimization for easier stepping

**Release flags** (from CMakeLists.txt:74-75):

* `-O3`: Maximum optimization
* `-DNDEBUG`: Disables assertions

## Runtime Assertions

### Assertion System

ReXGlue uses a comprehensive assertion system defined in `rex/assert.h`. All assertions are compiled out in Release builds when `NDEBUG` is defined.

**Available assertions**:

```cpp theme={null}
#include <rex/assert.h>

assert_true(ptr != nullptr);              // Verify condition is true
assert_false(error_occurred);             // Verify condition is false
assert_not_null(my_pointer);              // Verify pointer is not null
assert_null(freed_pointer);               // Verify pointer is null
assert_zero(error_code);                  // Verify value is 0
assert_not_zero(size);                    // Verify value is non-zero
assert_unhandled_case(variable);          // Mark unhandled switch case
assert_always();                          // Unconditional failure
```

**With custom messages**:

```cpp theme={null}
assert_true(size > 0, "Buffer size must be positive");
assert_not_null(ptr, "Failed to allocate memory");
```

### Static Assertions

```cpp theme={null}
static_assert_size(MyStruct, 64);  // Verify struct is exactly 64 bytes
```

Defined in `/home/daytona/workspace/source/include/rex/assert.h:25-26`

## Sanitizers

### Undefined Behavior Sanitizer (UBSan)

Enable UBSan to detect undefined behavior at runtime:

```bash theme={null}
cmake -B build -DREXGLUE_ENABLE_SANITIZERS=ON
cmake --build build
```

**What UBSan catches** (from CMakeLists.txt:96-101):

* Signed integer overflow
* Null pointer dereferences
* Misaligned memory access
* Division by zero
* Invalid enum values
* Out-of-bounds array access

**Note**: AddressSanitizer (ASan) is **not compatible** with ReXGlue because it conflicts with the custom memory mapping at `0x100000000`. Only UBSan is enabled.

### Running with Sanitizers

```bash theme={null}
# Build with sanitizers
cmake -B build -DREXGLUE_ENABLE_SANITIZERS=ON -DCMAKE_BUILD_TYPE=Debug
cmake --build build

# Run your recompiled executable
./build/out/linux-amd64/my_recompiled_app
```

UBSan will print detailed diagnostics when it detects issues:

```
runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int'
```

## Debugging Recompiled Functions

### Function Naming

Recompiled functions follow the naming convention:

```cpp theme={null}
sub_XXXXXXXX()  // Auto-generated name based on address
MyCustomName()  // Custom name from config.functions map
```

You can set custom names in your TOML config:

```toml theme={null}
[functions.0x82100000]
name = "GameInit"
size = 0x200
```

### Setting Breakpoints

**In GDB**:

```bash theme={null}
gdb ./my_recompiled_app
(gdb) break sub_82100000      # Break at auto-named function
(gdb) break GameInit          # Break at custom-named function
(gdb) run
```

**In LLDB**:

```bash theme={null}
lldb ./my_recompiled_app
(lldb) breakpoint set --name sub_82100000
(lldb) run
```

### Inspecting PPC State

Recompiled functions use a `PPCContext` parameter that holds the emulated PowerPC CPU state:

```cpp theme={null}
// In GDB while stopped in recompiled code:
(gdb) print ppc_ctx->r[3]     # Print GPR3
(gdb) print ppc_ctx->lr       # Print link register
(gdb) print ppc_ctx->ctr      # Print count register
(gdb) print ppc_ctx->cr       # Print condition register
```

## Common Issues

### Memory Access Violations

**Symptom**: Segmentation fault when accessing guest memory

**Cause**: Guest memory not mapped or accessed outside valid range

**Debug steps**:

1. Enable exception handlers to catch the fault address
2. Check if address is in valid guest range (typically `0x80000000 - 0x9FFFFFFF`)
3. Verify memory was initialized before access

```cpp theme={null}
// Enable exception handler to catch faults
rex::arch::ExceptionHandler::Install(MyDebugHandler, nullptr);
```

### Invalid Instruction Exceptions

**Symptom**: `SIGILL` or illegal instruction crash

**Cause**:

* Unimplemented PowerPC instruction
* Invalid opcode in source binary
* Code region executed as data

**Debug steps**:

1. Check the faulting address in exception handler
2. Disassemble the PowerPC code at that address
3. Add instruction to `invalidInstructionHints` if it's data:

```toml theme={null}
[invalid_instruction_hints]
0x82105000 = 64  # Mark 64 bytes as data, not code
```

### Assertion Failures

**Symptom**: Assertion failed messages during execution

**Debug steps**:

1. Read the assertion message and location
2. Set a breakpoint at the assertion line
3. Inspect variables when assertion fires
4. Run in Debug build for maximum information

**Example**:

```
Assertion failed: Buffer size must be positive
  Expression: size > 0
  Location: /path/to/source.cpp:42
```

### Performance Issues in Debug Builds

**Symptom**: Recompiled code runs 10-100x slower than expected

**Cause**: Debug builds use `-O0` and enable expensive assertions

**Solutions**:

* Use `RelWithDebInfo` for moderate optimization with debug symbols
* Profile in Release build, debug specific issues in Debug
* Disable specific hot-path assertions if necessary

## Logging and Tracing

### Kernel Import Tracing

Enable kernel import tracing to debug Xbox 360 kernel calls:

```cpp theme={null}
// In your code, use the logging macros
REXKRNL_IMPORT_TRACE("NtCreateFile", "path={} options={:#x}", path, opts);
REXKRNL_IMPORT_RESULT("NtCreateFile", "handle={:#x}", handle);
REXKRNL_IMPORT_WARN("NtCreateFile", "Unimplemented flag: {:#x}", flag);
```

Defined in `/home/daytona/workspace/source/include/rex/system/kernel_state.h:42-52`

### Custom Debug Output

Add debug prints in recompiled code:

```cpp theme={null}
#ifndef NDEBUG
  printf("[DEBUG] Function sub_82100000 entered, r3=%llx\n", ppc_ctx->r[3]);
#endif
```

## Debugging Tools

### GDB (Linux)

Recommended GDB settings for ReXGlue:

```bash theme={null}
# .gdbinit
set print pretty on
set pagination off
set disassembly-flavor intel

# Handle SIGSEGV in exception handlers
handle SIGSEGV nostop noprint pass
```

### LLDB (macOS/Linux)

```bash theme={null}
# .lldbinit
settings set target.process.stop-on-sharedlibrary-events false
settings set target.x86-disassembly-flavor intel
```

### Visual Studio (Windows)

1. Open the generated Visual Studio solution
2. Set the recompiled executable as the startup project
3. F5 to debug with full IDE support
4. Use Exception Settings to break on C++ exceptions

## Advanced Debugging

### Debugging the Recompiler Itself

If you suspect a code generation bug:

1. **Inspect generated code**: Check the output `.cpp` files in your output directory
2. **Compare with disassembly**: Use a PowerPC disassembler on the source binary
3. **Add code comments**: Enable verbose output in the recompiler
4. **File a bug report**: Include the problematic function address and generated code

### Memory Corruption

Use Valgrind (Linux) or Dr. Memory (Windows) to detect memory errors:

```bash theme={null}
# Valgrind (note: may conflict with custom memory mapping)
valgrind --leak-check=full --track-origins=yes ./my_app

# For best results, use UBSan instead
```

### Debugging Race Conditions

ReXGlue is multi-threaded. Use thread sanitizer carefully:

```bash theme={null}
# ThreadSanitizer (TSan) - experimental
cmake -B build -DCMAKE_CXX_FLAGS="-fsanitize=thread"
```

**Warning**: TSan may conflict with exception handlers and custom memory mapping.

## Tips and Best Practices

1. **Start with Debug builds**: Get your code working first, optimize later
2. **Use assertions liberally**: They're free in Release builds
3. **Enable exception handlers**: Catch crashes early with detailed context
4. **Test incrementally**: Recompile one function at a time when debugging
5. **Compare with emulation**: Run the same code in Xenia to verify behavior
6. **Read the generated code**: Understanding the output helps debug issues
7. **Use sanitizers in CI**: Catch bugs before they reach production

## Related Topics

* [Exception Handlers](/advanced/exception-handlers) - Catch and handle runtime exceptions
* [Optimization](/advanced/optimization) - Performance tuning and optimization flags
* [Platform Support](/advanced/platform-support) - Platform-specific debugging notes


# Exception Handlers
Source: https://rexglue-rexglue-sdk.mintlify.app/advanced/exception-handlers

Generate SEH exception handlers and handle runtime exceptions in recompiled code

## Overview

ReXGlue provides unified exception handling for recompiled PowerPC code running on AMD64 and ARM64 host architectures. The exception handler system captures access violations, illegal instructions, and other runtime exceptions that occur during execution of recompiled code.

## Exception Handler Generation

### Configuration Option

Enable exception handler generation in your recompiler config:

```cpp theme={null}
rex::codegen::RecompilerConfig config;
config.generateExceptionHandlers = true;  // Enable SEH wrapper generation
```

When enabled, the recompiler generates Structured Exception Handling (SEH) wrappers around recompiled functions, allowing you to catch and handle exceptions that occur during execution.

### How It Works

The exception handler system provides:

* **Access Violation Handling**: Captures read/write violations and determines the faulting address
* **Illegal Instruction Detection**: Catches invalid opcodes and unimplemented instructions
* **Thread Context Preservation**: Maintains full CPU state at the point of exception
* **Cross-Platform Abstraction**: Unified API across Windows (SEH) and Linux (signal handlers)

## Architecture Support

### AMD64 (x86-64)

The AMD64 implementation (`rex::arch::X64ThreadContextMembers`) captures:

* **General-purpose registers**: RAX, RCX, RDX, RBX, RSP, RBP, RSI, RDI, R8-R15
* **XMM registers**: XMM0-XMM15 (128-bit SIMD)
* **Control registers**: RIP (instruction pointer), EFLAGS

Defined in `/home/daytona/workspace/source/include/rex/exception_handler.h:186-231`

### ARM64 (AArch64)

The ARM64 implementation (`rex::arch::Arm64ThreadContextMembers`) captures:

* **General-purpose registers**: X0-X30, SP (stack pointer)
* **Vector registers**: V0-V31 (128-bit NEON)
* **Control registers**: PC (program counter), PSTATE, FPSR, FPCR
* **Special registers**: X29 (frame pointer), X30 (link register)

Defined in `/home/daytona/workspace/source/include/rex/exception_handler.h:121-129`

## Exception Types

### Access Violation

```cpp theme={null}
rex::arch::Exception::Code::kAccessViolation
```

Triggered when recompiled code attempts to read from or write to an invalid memory address.

**Properties**:

* `fault_address()`: Returns the address that caused the violation
* `access_violation_operation()`: Returns `kRead`, `kWrite`, or `kUnknown`

### Illegal Instruction

```cpp theme={null}
rex::arch::Exception::Code::kIllegalInstruction
```

Triggered when the CPU encounters an invalid opcode or unimplemented instruction.

## Using Exception Handlers

### Installing a Handler

```cpp theme={null}
#include <rex/exception_handler.h>

bool MyExceptionHandler(rex::arch::Exception* ex, void* context) {
  if (ex->code() == rex::arch::Exception::Code::kAccessViolation) {
    uint64_t fault_addr = ex->fault_address();
    bool is_write = ex->access_violation_operation() == 
                    rex::arch::Exception::AccessViolationOperation::kWrite;
    
    // Handle the violation (e.g., map memory, log error)
    printf("Access violation at 0x%llx (%s)\n", 
           fault_addr, is_write ? "write" : "read");
    
    // Return true to continue execution, false to propagate
    return false;
  }
  return false;
}

void SetupExceptionHandling() {
  rex::arch::ExceptionHandler::Install(MyExceptionHandler, nullptr);
}
```

### Inspecting Thread Context

Access CPU state at the point of exception:

```cpp theme={null}
bool DebugExceptionHandler(rex::arch::Exception* ex, void* context) {
  auto* thread_ctx = ex->thread_context();
  uint64_t pc = ex->pc();
  
#if REX_ARCH_AMD64
  uint64_t rax = thread_ctx->rax;
  uint64_t rsp = thread_ctx->rsp;
  printf("Exception at RIP=0x%llx, RAX=0x%llx, RSP=0x%llx\n", pc, rax, rsp);
#elif REX_ARCH_ARM64
  uint64_t x0 = thread_ctx->x[0];
  uint64_t sp = thread_ctx->sp;
  printf("Exception at PC=0x%llx, X0=0x%llx, SP=0x%llx\n", pc, x0, sp);
#endif
  
  return false;
}
```

### Modifying Registers

You can modify registers to recover from exceptions:

```cpp theme={null}
bool RecoveryHandler(rex::arch::Exception* ex, void* context) {
#if REX_ARCH_AMD64
  // Modify RAX and skip the faulting instruction
  ex->ModifyIntRegister(0) = 0;  // RAX is index 0
  ex->set_resume_pc(ex->pc() + 4);  // Skip instruction
  return true;  // Continue execution
#elif REX_ARCH_ARM64
  // Modify X0 and skip the faulting instruction
  ex->ModifyXRegister(0) = 0;
  ex->set_resume_pc(ex->pc() + 4);
  return true;
#endif
}
```

### Uninstalling a Handler

```cpp theme={null}
rex::arch::ExceptionHandler::Uninstall(MyExceptionHandler, nullptr);
```

## ARM64 Load/Store Decoding

For ARM64 platforms, ReXGlue includes VIXL-derived load/store instruction decoding to determine whether a faulting instruction was a load or store:

```cpp theme={null}
#if REX_ARCH_ARM64
#include <rex/exception_handler.h>

bool is_store = false;
if (rex::arch::IsArm64LoadPrefetchStore(instruction, is_store)) {
  if (is_store) {
    // Handle store operation
  } else {
    // Handle load/prefetch operation
  }
}
#endif
```

See `/home/daytona/workspace/source/include/rex/exception_handler.h:345-399` for load/store operation constants.

## Platform-Specific Notes

### Windows

* Uses Structured Exception Handling (SEH)
* Requires `/EHa` compiler flag (enabled automatically by ReXGlue)
* Handlers are called on the same thread that raised the exception

### Linux

* Uses POSIX signal handlers (SIGSEGV, SIGILL)
* Handlers run in signal context with restricted operations
* Avoid allocations and locks inside handlers

## Best Practices

1. **Keep handlers fast**: Exception handlers run in a critical context
2. **Minimal logging**: Avoid complex I/O operations
3. **Return false for unknown exceptions**: Let the OS handle what you can't
4. **Test on both architectures**: AMD64 and ARM64 have different semantics
5. **Use for debugging**: Exception handlers are invaluable for diagnosing crashes

## Common Use Cases

### Memory-Mapped I/O

Capture access violations to emulate hardware registers:

```cpp theme={null}
bool MMIOHandler(rex::arch::Exception* ex, void* context) {
  if (ex->code() != rex::arch::Exception::Code::kAccessViolation) {
    return false;
  }
  
  uint64_t addr = ex->fault_address();
  if (addr >= 0x80000000 && addr < 0x90000000) {
    // Handle MMIO read/write
    EmulateHardwareRegister(addr, ex);
    return true;
  }
  return false;
}
```

### Lazy Memory Mapping

Map pages on-demand when accessed:

```cpp theme={null}
bool LazyMapHandler(rex::arch::Exception* ex, void* context) {
  if (ex->code() == rex::arch::Exception::Code::kAccessViolation) {
    uint64_t addr = ex->fault_address();
    if (MapPageIfNeeded(addr)) {
      return true;  // Retry the instruction
    }
  }
  return false;
}
```

## Related APIs

* `rex::arch::HostThreadContext` - Thread context structure
* `rex::arch::Exception` - Exception information
* `rex::arch::ExceptionHandler` - Handler registration


# Optimization and Performance
Source: https://rexglue-rexglue-sdk.mintlify.app/advanced/optimization

Optimize recompiled code for maximum performance

## Overview

ReXGlue provides multiple optimization levels and code generation options to tune performance of recompiled Xbox 360 executables. This guide covers compiler optimization flags, code generation options, and performance tuning strategies.

## Compiler Optimization Levels

### Build Type Optimization

ReXGlue uses Clang's optimization levels via CMake build types:

| Build Type       | Optimization | Debug Info  | Use Case                         |
| ---------------- | ------------ | ----------- | -------------------------------- |
| `Debug`          | `-O0`        | Full (`-g`) | Development, debugging           |
| `Release`        | `-O3`        | None        | Production, maximum performance  |
| `RelWithDebInfo` | `-O2`        | Full (`-g`) | Profiling, performance debugging |
| `MinSizeRel`     | `-Os`        | None        | Size-constrained deployments     |

Defined in `/home/daytona/workspace/source/CMakeLists.txt:72-75`

### Setting Build Type

```bash theme={null}
# Maximum performance (recommended for production)
cmake -B build -DCMAKE_BUILD_TYPE=Release

# Development with debugging
cmake -B build -DCMAKE_BUILD_TYPE=Debug

# Performance profiling
cmake -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo
```

### Clang Compiler Requirement

ReXGlue **requires Clang 18+** for optimal code generation:

```bash theme={null}
# Verify Clang version
clang++ --version  # Must be >= 18.0

# Set Clang as compiler
cmake -B build -DCMAKE_CXX_COMPILER=clang++
```

Enforced in `/home/daytona/workspace/source/CMakeLists.txt:40-46`

## Code Generation Options

### RecompilerConfig Optimization Flags

Configure code generation in your TOML config or programmatically:

```cpp theme={null}
#include <rex/codegen/config.h>

rex::codegen::RecompilerConfig config;

// Register usage optimization
config.nonArgumentRegistersAsLocalVariables = true;
config.nonVolatileRegistersAsLocalVariables = true;
config.crRegistersAsLocalVariables = true;
config.reservedRegisterAsLocalVariable = true;

// Control flow optimization
config.skipLr = false;        // Keep link register tracking
config.skipMsr = true;        // Skip rarely-used MSR register
config.ctrAsLocalVariable = true;   // CTR as local variable
config.xerAsLocalVariable = true;   // XER as local variable

// Exception handling
config.generateExceptionHandlers = false;  // Disable for max performance
```

Defined in `/home/daytona/workspace/source/include/rex/codegen/config.h:82-91`

### Register Allocation Strategies

#### 1. Non-Argument Registers as Locals

```cpp theme={null}
config.nonArgumentRegistersAsLocalVariables = true;
```

**Effect**: Treats non-argument PowerPC registers (r4-r31) as C++ local variables instead of context members, allowing better compiler optimization and register allocation.

**Use when**: Function is self-contained and doesn't call out to other recompiled code frequently.

#### 2. Non-Volatile Registers as Locals

```cpp theme={null}
config.nonVolatileRegistersAsLocalVariables = true;
```

**Effect**: Treats callee-saved registers (r14-r31) as local variables.

**Use when**: Function follows standard calling conventions and preserves non-volatile registers.

#### 3. Condition Register Optimization

```cpp theme={null}
config.crRegistersAsLocalVariables = true;
```

**Effect**: Stores CR0-CR7 fields as local booleans instead of bitfields in the context structure.

**Use when**: Function has many condition register operations (common in branches).

### Special Register Optimization

#### Skip Link Register (LR)

```cpp theme={null}
config.skipLr = true;
```

**Effect**: Omits link register tracking if the function doesn't use `blr` or save/restore LR.

**Trade-off**: Saves overhead but breaks functions that return via LR.

#### Skip Machine State Register (MSR)

```cpp theme={null}
config.skipMsr = true;
```

**Effect**: Omits MSR tracking (rarely used in game code).

**Recommended**: Enable for most game functions.

#### CTR/XER as Local Variables

```cpp theme={null}
config.ctrAsLocalVariable = true;
config.xerAsLocalVariable = true;
```

**Effect**: Stores CTR (count register) and XER (fixed-point exception register) as local variables.

**Use when**: Function heavily uses loops (CTR) or carry/overflow flags (XER).

## Platform-Specific Optimizations

### Linux: Large Code Model

On Linux, ReXGlue uses the large code model for executables over 35MB:

```cmake theme={null}
# Automatically applied on Linux
add_compile_options(-mcmodel=large)
```

Defined in `/home/daytona/workspace/source/CMakeLists.txt:64`

**Reason**: Supports very large recompiled executables that exceed the default code model's 2GB addressing limit.

### Floating-Point Model

ReXGlue uses strict floating-point semantics to match PowerPC behavior:

```cmake theme={null}
add_compile_options(-ffp-model=strict)
```

Defined in `/home/daytona/workspace/source/CMakeLists.txt:71`

**Trade-off**: Ensures correctness but disables aggressive FP optimizations like reassociation and fused multiply-add.

### No Strict Aliasing

```cmake theme={null}
add_compile_options(-fno-strict-aliasing)
```

Defined in `/home/daytona/workspace/source/CMakeLists.txt:70`

**Reason**: Recompiled code frequently casts pointers (e.g., byte access to words), which violates C++ strict aliasing rules.

## Performance Tuning

### Analysis Thresholds

Tune analysis heuristics for your binary:

```cpp theme={null}
config.maxJumpExtension = 65536;          // Max bytes to extend function for jump tables
config.dataRegionThreshold = 16;          // Consecutive invalid instructions = data
config.largeFunctionThreshold = 1048576;  // 1MB warning threshold
```

Defined in `/home/daytona/workspace/source/include/rex/codegen/config.h:93-95`

#### Max Jump Extension

Controls how far the recompiler extends a function to include jump table targets:

```cpp theme={null}
config.maxJumpExtension = 131072;  // 128KB - for functions with large switch tables
```

**Increase**: If you see warnings about jump targets outside function bounds.

**Decrease**: If functions are incorrectly merged due to distant jumps.

#### Data Region Threshold

Number of consecutive invalid instructions before marking a region as data:

```cpp theme={null}
config.dataRegionThreshold = 8;  // More aggressive data detection
```

**Lower values**: More aggressive data detection, may split functions.

**Higher values**: More tolerant of invalid instructions in code.

### Exception Handler Overhead

Exception handlers add significant overhead:

```cpp theme={null}
// Development: Enable for debugging
config.generateExceptionHandlers = true;

// Production: Disable for maximum performance
config.generateExceptionHandlers = false;
```

**Overhead**: \~10-20% performance penalty from SEH prologues/epilogues.

**Recommendation**: Enable only when debugging or if you need to catch runtime exceptions.

## Link-Time Optimization (LTO)

Enable LTO for whole-program optimization:

```bash theme={null}
cmake -B build \
  -DCMAKE_BUILD_TYPE=Release \
  -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON
```

**Benefits**:

* Cross-module inlining
* Better dead code elimination
* Optimized calling conventions

**Trade-offs**:

* Longer build times
* Higher memory usage during linking

## Profiling and Benchmarking

### CPU Profiling

#### Linux: perf

```bash theme={null}
# Build with profiling info
cmake -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo
cmake --build build

# Profile execution
perf record -g ./my_recompiled_app
perf report
```

#### Windows: Visual Studio Profiler

1. Build with `RelWithDebInfo`
2. Open in Visual Studio
3. Debug → Performance Profiler
4. Select CPU Usage
5. Start profiling

### Hotspot Analysis

Identify performance bottlenecks:

```bash theme={null}
# Sample-based profiling (low overhead)
perf record -F 99 -g ./my_app

# Generate flamegraph
git clone https://github.com/brendangregg/FlameGraph
perf script | FlameGraph/stackcollapse-perf.pl | FlameGraph/flamegraph.pl > flame.svg
```

### Micro-Benchmarking

Benchmark specific recompiled functions:

```cpp theme={null}
#include <chrono>

void BenchmarkFunction() {
  auto start = std::chrono::high_resolution_clock::now();
  
  // Call recompiled function 1000 times
  for (int i = 0; i < 1000; i++) {
    sub_82100000(&ppc_ctx);
  }
  
  auto end = std::chrono::high_resolution_clock::now();
  auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
  printf("Average: %lld μs\n", duration.count() / 1000);
}
```

## Common Performance Issues

### Issue: Slow Memory Access

**Symptom**: Recompiled code is 5-10x slower than expected

**Cause**: Every memory access goes through indirection

**Solution**: Ensure guest memory is mapped at a fixed address (default: `0x100000000`)

### Issue: Excessive Context Switching

**Symptom**: High overhead in `PPCContext` loads/stores

**Cause**: Registers stored in context instead of local variables

**Solution**: Enable register-as-local optimizations:

```cpp theme={null}
config.nonArgumentRegistersAsLocalVariables = true;
config.crRegistersAsLocalVariables = true;
```

### Issue: Debug Assertions in Hot Paths

**Symptom**: Debug build is 100x slower than Release

**Cause**: `assert_*` macros execute expensive checks

**Solution**: Use `RelWithDebInfo` for profiling, or disable specific assertions:

```cpp theme={null}
#ifdef NDEBUG
  #define HOT_PATH_ASSERT(x) ((void)0)
#else
  #define HOT_PATH_ASSERT(x) assert_true(x)
#endif
```

### Issue: Large Function Compilation Time

**Symptom**: Clang takes minutes to compile a single function

**Cause**: Function is too large (>100KB) for effective optimization

**Solution**: Split into chunks using the `parent` field:

```toml theme={null}
[functions.0x82100000]
name = "HugeFunction_Part1"
size = 0x10000

[functions.0x82110000]
name = "HugeFunction_Part2"
parent = 0x82100000  # Chunk of parent function
size = 0x10000
```

## Optimization Checklist

For maximum performance:

* [ ] Use `Release` build type (`-O3`)
* [ ] Enable Clang 18+ with LTO
* [ ] Set `generateExceptionHandlers = false` in production
* [ ] Enable register-as-local optimizations for hot functions
* [ ] Set `skipMsr = true` for most functions
* [ ] Use `-mcmodel=large` on Linux for large executables
* [ ] Profile with `perf` or Visual Studio Profiler
* [ ] Benchmark before and after optimizations
* [ ] Consider splitting functions >1MB into chunks

## Related Topics

* [Debugging](/advanced/debugging) - Debug builds and sanitizers
* [Platform Support](/advanced/platform-support) - Platform-specific optimizations
* [Exception Handlers](/advanced/exception-handlers) - Performance impact of SEH


# Platform Support
Source: https://rexglue-rexglue-sdk.mintlify.app/advanced/platform-support

Platform-specific considerations for Windows and Linux

## Overview

ReXGlue supports Windows and Linux on AMD64 (x86-64) architecture. This guide covers platform-specific build options, runtime differences, and cross-platform considerations.

## Supported Platforms

### Windows (win-amd64)

* **OS**: Windows 10/11 (64-bit)
* **Compiler**: Clang 18+ (MSVC ABI compatible)
* **Graphics**: Direct3D 12 (default), Vulkan (optional)
* **Architecture**: x86-64 only

### Linux (linux-amd64)

* **OS**: Ubuntu 20.04+, Debian 11+, Arch Linux, or compatible
* **Compiler**: Clang 18+
* **Graphics**: Vulkan (default), Direct3D 12 not available
* **Architecture**: x86-64 only

### Unsupported Platforms

* **macOS**: Not currently supported (would require significant porting effort)
* **ARM64**: Partially supported in code but not tested
* **32-bit**: Explicitly rejected at build time

Defined in `/home/daytona/workspace/source/CMakeLists.txt:49-51`

## Platform Detection

### Build-Time Detection

ReXGlue automatically detects the platform during CMake configuration:

```cmake theme={null}
if(WIN32)
    set(REX_PLATFORM "win-amd64")
    add_compile_definitions(REX_PLATFORM_WINDOWS=1)
elseif(UNIX AND NOT APPLE)
    set(REX_PLATFORM "linux-amd64")
    add_compile_definitions(REX_PLATFORM_LINUX=1)
endif()
```

Defined in `/home/daytona/workspace/source/CMakeLists.txt:80-88`

### Runtime Platform Macros

In C++ code, use these preprocessor macros:

```cpp theme={null}
#include <rex/platform.h>

#if REX_PLATFORM_WIN32
    // Windows-specific code
#elif REX_PLATFORM_LINUX
    // Linux-specific code
#endif
```

Available macros:

* `REX_PLATFORM_WIN32` - Windows
* `REX_PLATFORM_LINUX` - Linux (generic)
* `REX_PLATFORM_GNU_LINUX` - GNU/Linux specifically
* `REX_PLATFORM_ANDROID` - Android (Linux variant)
* `REX_PLATFORM_MAC` - macOS (not supported)

Defined in `/home/daytona/workspace/source/include/rex/platform.h:31-61`

### Architecture Detection

```cpp theme={null}
#if REX_ARCH_AMD64
    // x86-64 code
#elif REX_ARCH_ARM64
    // ARM64 code (experimental)
#endif
```

Defined in `/home/daytona/workspace/source/include/rex/platform.h:77-85`

## Graphics Backend Selection

### Windows: D3D12 vs Vulkan

On Windows, you can choose between Direct3D 12 (default) and Vulkan:

```bash theme={null}
# D3D12 only (default)
cmake -B build -DREXGLUE_USE_D3D12=ON -DREXGLUE_USE_VULKAN=OFF

# Vulkan only
cmake -B build -DREXGLUE_USE_D3D12=OFF -DREXGLUE_USE_VULKAN=ON

# Both backends (for runtime selection)
cmake -B build -DREXGLUE_USE_D3D12=ON -DREXGLUE_USE_VULKAN=ON
```

**D3D12 advantages**:

* Native Windows API, better driver support
* Lower CPU overhead on Windows
* Better integration with Windows debugging tools

**Vulkan advantages**:

* Cross-platform code path (same as Linux)
* More explicit control over GPU resources
* Better for testing cross-platform behavior

### Linux: Vulkan Only

On Linux, only Vulkan is available:

```bash theme={null}
# Vulkan is ON by default on Linux
cmake -B build

# Explicitly enable
cmake -B build -DREXGLUE_USE_VULKAN=ON
```

Defined in `/home/daytona/workspace/source/CMakeLists.txt:20-30`

### Runtime Graphics Backend Check

```cpp theme={null}
#include <rex/platform.h>

#if REX_HAS_D3D12
    // D3D12 backend available
#endif

#if REX_HAS_VULKAN
    // Vulkan backend available
#endif
```

Defined in `/home/daytona/workspace/source/src/graphics/CMakeLists.txt:132-142`

## Platform-Specific Build Options

### Large Code Model (Linux Only)

Linux builds use the large code model to support executables over 35MB:

```cmake theme={null}
if(NOT WIN32)
    add_compile_options(-mcmodel=large)
    set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()
```

Defined in `/home/daytona/workspace/source/CMakeLists.txt:60-66`

**Reason**: Recompiled Xbox 360 executables can exceed 100MB, requiring 64-bit absolute addressing.

**Windows**: Uses default code model (large is implicit on Win64).

### Position-Independent Code

Linux builds use PIE (Position-Independent Executable):

```cmake theme={null}
set(CMAKE_POSITION_INDEPENDENT_CODE ON)  # Linux only
```

**Benefits**:

* ASLR (Address Space Layout Randomization) support
* Required for shared libraries
* Better security

**Windows**: PIE is handled automatically by MSVC/Clang.

## Compiler Differences

### Clang on Windows

Windows builds use Clang with MSVC ABI compatibility:

```bash theme={null}
# Use clang-cl (Clang with MSVC frontend)
cmake -B build -T ClangCL

# Or use Clang directly with MSVC ABI
cmake -B build -DCMAKE_CXX_COMPILER=clang++
```

**Note**: MinGW is **not supported**. Use Clang with MSVC runtime.

### GCC Not Supported

ReXGlue **requires Clang 18+** on all platforms:

```cmake theme={null}
if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
    message(FATAL_ERROR "ReXGlue requires Clang compiler")
endif()
```

Defined in `/home/daytona/workspace/source/CMakeLists.txt:40-42`

**Reason**: ReXGlue relies on Clang-specific code generation and C++23 features.

## Platform-Specific APIs

### Path Separators

```cpp theme={null}
#include <rex/platform.h>

const char kPathSeparator;        // '\\' on Windows, '/' on Linux
const char kGuestPathSeparator;   // Always '\\' (Xbox 360 uses Windows paths)
```

Defined in `/home/daytona/workspace/source/include/rex/platform.h:125-132`

### File System

```cpp theme={null}
#include <filesystem>

// Cross-platform path handling
std::filesystem::path gamePath = "D:\\Games\\MyGame";  // Windows
std::filesystem::path gamePath = "/mnt/games/MyGame";  // Linux

// Use rex::kPathSeparator for runtime path construction
std::string path = "game" + std::string(1, rex::kPathSeparator) + "data";
```

### Threading

ReXGlue uses C++23 `<thread>` and `<mutex>` for cross-platform threading:

```cpp theme={null}
#include <rex/thread.h>  // Platform-abstracted threading primitives

// Cross-platform event
rex::threading::Event event;
event.Set();
event.Wait();
```

## Exception Handling

### Windows: Structured Exception Handling (SEH)

Windows uses SEH for exception handlers:

```cpp theme={null}
#if REX_PLATFORM_WIN32
    __try {
        // Recompiled code
    } __except (ExceptionFilter(GetExceptionInformation())) {
        // Handle exception
    }
#endif
```

### Linux: Signal Handlers

Linux uses POSIX signals:

```cpp theme={null}
#if REX_PLATFORM_LINUX
#include <signal.h>

void SigSegvHandler(int sig, siginfo_t* info, void* context) {
    // Handle SIGSEGV
}

struct sigaction sa;
sa.sa_sigaction = SigSegvHandler;
sa.sa_flags = SA_SIGINFO;
sigaction(SIGSEGV, &sa, nullptr);
#endif
```

ReXGlue abstracts this with `rex::arch::ExceptionHandler` (see [Exception Handlers](/advanced/exception-handlers)).

## Memory Mapping

### Guest Memory Location

ReXGlue maps Xbox 360 guest memory at a fixed host address:

* **Address**: `0x100000000` (4GB boundary)
* **Size**: Up to 512MB (Xbox 360 physical memory)
* **Mapping**: Direct pointer arithmetic for fast access

```cpp theme={null}
// Guest address 0x82000000 maps to host address:
uintptr_t host_addr = 0x100000000 + 0x82000000;
```

**Platform notes**:

* **Windows**: Uses `VirtualAlloc` with `MEM_RESERVE | MEM_COMMIT`
* **Linux**: Uses `mmap` with `MAP_FIXED | MAP_ANONYMOUS`

**Conflict**: This is why AddressSanitizer (ASan) is disabled - it conflicts with the fixed mapping.

## Build Output Directories

Builds output to platform-specific directories:

```
out/
├── win-amd64/          # Windows builds
│   ├── Debug/
│   ├── Release/
│   └── RelWithDebInfo/
└── linux-amd64/        # Linux builds
    ├── Debug/
    ├── Release/
    └── RelWithDebInfo/
```

Defined in `/home/daytona/workspace/source/CMakeLists.txt:91-93`

## Cross-Platform Build Script

### Windows (PowerShell)

```powershell theme={null}
# Configure
cmake -B build -G "Visual Studio 17 2022" -T ClangCL `
    -DCMAKE_BUILD_TYPE=Release `
    -DREXGLUE_USE_D3D12=ON

# Build
cmake --build build --config Release -j

# Run
.\out\win-amd64\Release\my_recompiled_app.exe
```

### Linux (Bash)

```bash theme={null}
# Configure
cmake -B build -G Ninja \
    -DCMAKE_BUILD_TYPE=Release \
    -DCMAKE_CXX_COMPILER=clang++ \
    -DREXGLUE_USE_VULKAN=ON

# Build
cmake --build build -j$(nproc)

# Run
./out/linux-amd64/my_recompiled_app
```

## Common Platform-Specific Issues

### Windows: Missing DLLs

**Symptom**: Application fails to start with "VCRUNTIME140.dll not found"

**Solution**: Install Visual C++ Redistributable or build with static linking:

```bash theme={null}
cmake -B build -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreaded"
```

### Linux: Missing Vulkan Drivers

**Symptom**: "Failed to create Vulkan instance"

**Solution**: Install Vulkan drivers:

```bash theme={null}
# Ubuntu/Debian
sudo apt install mesa-vulkan-drivers vulkan-tools

# Arch Linux
sudo pacman -S vulkan-icd-loader vulkan-tools

# Verify
vulkaninfo
```

### Linux: Large Code Model Linking Issues

**Symptom**: Linker error "relocation truncated to fit"

**Solution**: Already handled by `-mcmodel=large`. If it persists, reduce executable size by splitting functions.

### Windows: Path Length Limits

**Symptom**: Build fails with "path too long" errors

**Solution**: Enable long paths in Windows:

```powershell theme={null}
# Run as Administrator
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" `
    -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force
```

## Platform Testing Strategy

1. **Develop on primary platform** (Windows or Linux)
2. **Test on both platforms** before release
3. **Use CI/CD** to build and test both platforms automatically
4. **Profile on target platform** (don't assume performance parity)
5. **Test graphics backends separately** (D3D12 vs Vulkan)

## CMake Configuration Summary

```bash theme={null}
# Windows (D3D12)
cmake -B build \
    -DCMAKE_BUILD_TYPE=Release \
    -DREXGLUE_USE_D3D12=ON \
    -DREXGLUE_USE_VULKAN=OFF

# Linux (Vulkan)
cmake -B build \
    -DCMAKE_BUILD_TYPE=Release \
    -DCMAKE_CXX_COMPILER=clang++ \
    -DREXGLUE_USE_VULKAN=ON

# Cross-platform (Vulkan on both)
cmake -B build \
    -DCMAKE_BUILD_TYPE=Release \
    -DREXGLUE_USE_D3D12=OFF \
    -DREXGLUE_USE_VULKAN=ON
```

## Related Topics

* [Optimization](/advanced/optimization) - Platform-specific optimization flags
* [Debugging](/advanced/debugging) - Platform-specific debugging tools
* [Exception Handlers](/advanced/exception-handlers) - SEH vs signal handlers


# IAudioSystem
Source: https://rexglue-rexglue-sdk.mintlify.app/api/audio-system

Abstract audio system interface for audio pipeline dependency injection

## Overview

`IAudioSystem` is the abstract interface for audio subsystems in ReXGlue. It provides dependency injection for different audio backends, with SDL as the primary implementation.

**Header:** `rex/system/interfaces/audio.h`

**Namespace:** `rex::system`

## Interface Methods

### Setup

```cpp theme={null}
virtual X_STATUS Setup(KernelState* kernel_state) = 0;
```

Initializes the audio system with the kernel state.

**Parameters:**

* `kernel_state` - Pointer to the kernel state manager

**Returns:** `X_STATUS` - Status code indicating success or failure

### Shutdown

```cpp theme={null}
virtual void Shutdown() = 0;
```

Cleanly shuts down the audio system and releases all resources.

## Concrete Implementation

### SDL Audio System

**Class:** `rex::audio::sdl::SDLAudioSystem`

**Header:** `rex/audio/sdl/sdl_audio_system.h`

SDL-based audio implementation providing cross-platform audio support.

```cpp theme={null}
class SDLAudioSystem : public AudioSystem {
public:
  explicit SDLAudioSystem(runtime::Processor* processor);
  ~SDLAudioSystem() override;
  
  static bool IsAvailable() { return true; }
  
  static std::unique_ptr<AudioSystem> Create(runtime::Processor* processor);
  
  X_STATUS CreateDriver(
    size_t index,
    rex::thread::Semaphore* semaphore,
    AudioDriver** out_driver
  ) override;
  
  void DestroyDriver(AudioDriver* driver) override;
  
protected:
  void Initialize() override;
};
```

## Base AudioSystem Class

The SDL implementation extends `rex::audio::AudioSystem`, which provides:

**Key Members:**

* `memory()` - Access to memory subsystem
* `processor()` - Access to CPU processor
* `xma_decoder()` - XMA audio decoder instance

**Key Methods:**

* `Setup(kernel_state)` - Initialize audio system
* `Shutdown()` - Shutdown audio system
* `RegisterClient(callback, callback_arg, out_index)` - Register audio client
* `UnregisterClient(index)` - Unregister audio client
* `SubmitFrame(index, samples_ptr)` - Submit audio frame for playback
* `Pause()` / `Resume()` - Pause and resume audio playback
* `Save(stream)` / `Restore(stream)` - Save and restore state

**Constants:**

* `kMaximumClientCount = 8` - Maximum number of simultaneous audio clients

## Example Usage

### Initializing SDL Audio System

```cpp theme={null}
#include <rex/audio/sdl/sdl_audio_system.h>
#include <rex/system/kernel_state.h>
#include <rex/runtime/processor.h>

using namespace rex;

// Check availability
if (!audio::sdl::SDLAudioSystem::IsAvailable()) {
  // Handle unavailable audio
  return;
}

// Create the audio system
auto audio = audio::sdl::SDLAudioSystem::Create(processor);

// Setup with kernel state
X_STATUS status = audio->Setup(kernel_state);

if (status != X_STATUS_SUCCESS) {
  // Handle error
}

// Use the audio system...

// Cleanup
audio->Shutdown();
```

### Registering an Audio Client

```cpp theme={null}
// Audio client callback
void AudioCallback(uint32_t arg) {
  // Handle audio callback
}

// Register client
size_t client_index;
X_STATUS status = audio->RegisterClient(
  reinterpret_cast<uint32_t>(&AudioCallback),
  user_data,
  &client_index
);

if (status == X_STATUS_SUCCESS) {
  // Submit audio frames
  audio->SubmitFrame(client_index, samples_ptr);
  
  // Later, unregister when done
  audio->UnregisterClient(client_index);
}
```

### Pausing and Resuming Audio

```cpp theme={null}
// Pause audio playback
if (!audio->is_paused()) {
  audio->Pause();
}

// Resume audio playback
if (audio->is_paused()) {
  audio->Resume();
}
```

### Using XMA Decoder

```cpp theme={null}
// Access XMA decoder for compressed audio
auto* xma = audio->xma_decoder();

// Use XMA decoder for Xbox 360 audio format decoding
// ...
```

## Audio Driver Interface

The audio system creates and manages `AudioDriver` instances for each client:

```cpp theme={null}
// Create driver for client
AudioDriver* driver = nullptr;
auto semaphore = std::make_unique<rex::thread::Semaphore>();

X_STATUS status = audio->CreateDriver(
  client_index,
  semaphore.get(),
  &driver
);

if (status == X_STATUS_SUCCESS) {
  // Use driver...
  
  // Destroy when done
  audio->DestroyDriver(driver);
}
```

## Thread Safety

The audio system uses `rex::thread::global_critical_region` for thread-safe access to client management and audio frame submission.

## See Also

* [KernelState](/api/kernel-state) - Kernel state management
* [IGraphicsSystem](/api/graphics-system) - Graphics subsystem interface
* [IInputSystem](/api/input-system) - Input subsystem interface


# FunctionConfig
Source: https://rexglue-rexglue-sdk.mintlify.app/api/function-config

Per-function configuration and related structures

## Overview

The `FunctionConfig` structure defines configuration for individual functions and code chunks in the recompiler. Related structures include `MidAsmHook` for injecting custom code, and `SectionInfo`/`FunctionEntry` for analysis output.

## FunctionConfig

Unified configuration for both standalone functions and discontinuous chunks.

```cpp theme={null}
namespace rex::codegen {
  struct FunctionConfig {
    uint32_t size;
    uint32_t end;
    std::string name;
    uint32_t parent;

    uint32_t getSize(uint32_t address) const;
    bool isChunk() const;
  };
}
```

### Fields

<ParamField type="uint32_t">
  Explicit function size in bytes. Mutually exclusive with `end`. If both are specified, `size` takes precedence.
</ParamField>

<ParamField type="uint32_t">
  End address of the function (exclusive). Mutually exclusive with `size`. Used when the function boundary is known by address rather than size.
</ParamField>

<ParamField type="std::string">
  Custom symbol name for the function. If empty, auto-generates a name in the format `sub_XXXXXXXX` where X is the hexadecimal address.
</ParamField>

<ParamField type="uint32_t">
  Parent function address. Set to 0 for standalone functions. Non-zero indicates this is a discontinuous chunk belonging to the parent function at the specified address.
</ParamField>

### Methods

#### getSize()

Get the effective size of the function.

```cpp theme={null}
uint32_t getSize(uint32_t address) const
```

<ParamField type="uint32_t">
  Starting address of the function.
</ParamField>

**Returns:** Effective size in bytes. Prefers `size` field if set, otherwise calculates `end - address`.

**Example:**

```cpp theme={null}
FunctionConfig cfg;
cfg.end = 0x82001000;
uint32_t sz = cfg.getSize(0x82000800);  // Returns 0x800 (2048 bytes)
```

#### isChunk()

Check if this configuration represents a discontinuous chunk.

```cpp theme={null}
bool isChunk() const
```

**Returns:** `true` if `parent != 0`, indicating this is a chunk belonging to another function.

**Example:**

```cpp theme={null}
FunctionConfig chunk;
chunk.parent = 0x82000100;
if (chunk.isChunk()) {
  // Handle as chunk of parent function
}
```

### Usage in RecompilerConfig

Functions are configured via the `functions` map in `RecompilerConfig`:

```cpp theme={null}
RecompilerConfig config;

// Standalone function with explicit size
FunctionConfig& fn1 = config.functions[0x82000100];
fn1.name = "GameInit";
fn1.size = 512;

// Function with end address
FunctionConfig& fn2 = config.functions[0x82000500];
fn2.name = "RenderLoop";
fn2.end = 0x82000800;

// Discontinuous chunk belonging to RenderLoop
FunctionConfig& chunk = config.functions[0x82002000];
chunk.parent = 0x82000500;
chunk.size = 256;
```

### TOML Configuration

```toml theme={null}
[functions.0x82000100]
name = "GameInit"
size = 512

[functions.0x82000500]
name = "RenderLoop"
end = 0x82000800

[functions.0x82002000]
parent = 0x82000500
size = 256
```

## MidAsmHook

Configuration for injecting custom C++ code at specific instruction addresses.

```cpp theme={null}
struct MidAsmHook {
  std::string name;
  std::vector<std::string> registers;

  bool ret;
  bool returnOnTrue;
  bool returnOnFalse;

  uint32_t jumpAddress;
  uint32_t jumpAddressOnTrue;
  uint32_t jumpAddressOnFalse;

  bool afterInstruction;
};
```

### Fields

<ParamField type="std::string">
  Name of the C++ function to call at this hook point. The function signature should match the register arguments specified.
</ParamField>

<ParamField type="std::vector<std::string>">
  List of PowerPC registers to pass as arguments to the hook function. Valid values include `"r3"`, `"r4"`, `"f1"`, `"ctx"`, etc.
</ParamField>

<ParamField type="bool">
  If `true`, the hook function's return value is used as the function's return value, and execution stops.
</ParamField>

<ParamField type="bool">
  If `true`, return from the current function when the hook function returns a truthy value.
</ParamField>

<ParamField type="bool">
  If `true`, return from the current function when the hook function returns a falsy value.
</ParamField>

<ParamField type="uint32_t">
  Unconditional jump target address. If non-zero, execution jumps to this address after the hook executes.
</ParamField>

<ParamField type="uint32_t">
  Conditional jump target when hook returns true. If non-zero, jumps to this address when the hook function returns a truthy value.
</ParamField>

<ParamField type="uint32_t">
  Conditional jump target when hook returns false. If non-zero, jumps to this address when the hook function returns a falsy value.
</ParamField>

<ParamField type="bool">
  If `true`, execute the hook after the current instruction. If `false`, execute before the instruction.
</ParamField>

### Example

```cpp theme={null}
RecompilerConfig config;

// Hook at 0x82000200 to intercept memory allocation
MidAsmHook& hook = config.midAsmHooks[0x82000200];
hook.name = "OnMemoryAlloc";
hook.registers = {"r3", "r4"};  // size, flags
hook.returnOnFalse = true;      // return if allocation fails
```

### TOML Configuration

```toml theme={null}
[midAsmHooks.0x82000200]
name = "OnMemoryAlloc"
registers = ["r3", "r4"]
returnOnFalse = true

[midAsmHooks.0x82000400]
name = "DebugLog"
registers = ["r3", "r4", "r5"]
afterInstruction = true
```

## SectionInfo

Metadata about executable sections for analysis output.

```cpp theme={null}
struct SectionInfo {
  std::string name;
  uint64_t address;
  uint64_t size;
  std::string flags;
};
```

<ParamField type="std::string">
  Section name (e.g., `.text`, `.data`, `.rdata`).
</ParamField>

<ParamField type="uint64_t">
  Starting address of the section.
</ParamField>

<ParamField type="uint64_t">
  Size of the section in bytes.
</ParamField>

<ParamField type="std::string">
  Section flags indicating permissions: `"rx"` (read+execute), `"rw"` (read+write), `"r"` (read-only), etc.
</ParamField>

## FunctionEntry

Function metadata for analysis output.

```cpp theme={null}
struct FunctionEntry {
  uint64_t address;
  uint64_t size;
  std::string name;
};
```

<ParamField type="uint64_t">
  Starting address of the function.
</ParamField>

<ParamField type="uint64_t">
  Size of the function in bytes.
</ParamField>

<ParamField type="std::string">
  Function name. Defaults to `"sub_XXXXXXXX"` if not specified.
</ParamField>

## See Also

* [RecompilerConfig](/api/recompiler-config) - Main configuration structure
* [Recompiler](/api/recompiler) - Recompiler class


# IGraphicsSystem
Source: https://rexglue-rexglue-sdk.mintlify.app/api/graphics-system

Abstract graphics system interface for rendering pipeline dependency injection

## Overview

`IGraphicsSystem` is the abstract interface for graphics subsystems in ReXGlue. It provides dependency injection for different rendering backends including Direct3D 12 and Vulkan.

**Header:** `rex/system/interfaces/graphics.h`

**Namespace:** `rex::system`

## Interface Methods

### Setup

```cpp theme={null}
virtual X_STATUS Setup(
  runtime::Processor* processor,
  KernelState* kernel_state,
  ui::WindowedAppContext* app_context,
  bool with_presentation
) = 0;
```

Initializes the graphics system with the required runtime components.

**Parameters:**

* `processor` - Pointer to the CPU processor instance
* `kernel_state` - Pointer to the kernel state manager
* `app_context` - Windowed application context for presentation
* `with_presentation` - Enable presentation layer if true

**Returns:** `X_STATUS` - Status code indicating success or failure

### Shutdown

```cpp theme={null}
virtual void Shutdown() = 0;
```

Cleanly shuts down the graphics system and releases all resources.

## Concrete Implementations

### Direct3D 12

**Class:** `rex::graphics::d3d12::D3D12GraphicsSystem`

**Header:** `rex/graphics/d3d12/graphics_system.h`

Direct3D 12 implementation providing Windows-native graphics rendering.

```cpp theme={null}
class D3D12GraphicsSystem : public GraphicsSystem {
public:
  D3D12GraphicsSystem();
  ~D3D12GraphicsSystem() override;
  
  static bool IsAvailable();
  
  std::string name() const override;
  
  X_STATUS Setup(
    runtime::Processor* processor,
    system::KernelState* kernel_state,
    ui::WindowedAppContext* app_context,
    bool with_presentation
  ) override;
  
protected:
  std::unique_ptr<CommandProcessor> CreateCommandProcessor() override;
};
```

### Vulkan

**Class:** `rex::graphics::vulkan::VulkanGraphicsSystem`

**Header:** `rex/graphics/vulkan/graphics_system.h`

Vulkan implementation providing cross-platform graphics rendering.

```cpp theme={null}
class VulkanGraphicsSystem : public GraphicsSystem {
public:
  VulkanGraphicsSystem();
  ~VulkanGraphicsSystem() override;
  
  static bool IsAvailable();
  
  std::string name() const override;
  
  X_STATUS Setup(
    runtime::Processor* processor,
    system::KernelState* kernel_state,
    ui::WindowedAppContext* app_context,
    bool with_presentation
  ) override;
  
private:
  std::unique_ptr<CommandProcessor> CreateCommandProcessor() override;
};
```

## Base GraphicsSystem Class

The concrete implementations extend `rex::graphics::GraphicsSystem`, which provides:

**Key Methods:**

* `memory()` - Access to memory subsystem
* `processor()` - Access to CPU processor
* `kernel_state()` - Access to kernel state
* `provider()` - Graphics provider instance
* `presenter()` - Presentation layer instance
* `register_file()` - GPU register file access
* `command_processor()` - Command processor instance
* `InitializeRingBuffer(ptr, size_log2)` - Initialize GPU ring buffer
* `EnableReadPointerWriteBack(ptr, block_size_log2)` - Enable read pointer writeback
* `SetInterruptCallback(callback, user_data)` - Set GPU interrupt handler
* `ClearCaches()` - Clear all GPU caches
* `Pause()` / `Resume()` - Pause and resume rendering

## Example Usage

### Initializing D3D12 Graphics System

```cpp theme={null}
#include <rex/graphics/d3d12/graphics_system.h>
#include <rex/system/kernel_state.h>
#include <rex/runtime/processor.h>
#include <rex/ui/windowed_app_context.h>

using namespace rex;

// Check availability
if (!graphics::d3d12::D3D12GraphicsSystem::IsAvailable()) {
  // Fallback to another backend
  return;
}

// Create the graphics system
auto graphics = std::make_unique<graphics::d3d12::D3D12GraphicsSystem>();

// Setup with runtime components
X_STATUS status = graphics->Setup(
  processor,
  kernel_state,
  app_context,
  true  // Enable presentation
);

if (status != X_STATUS_SUCCESS) {
  // Handle error
}

// Use the graphics system...

// Cleanup
graphics->Shutdown();
```

### Initializing Vulkan Graphics System

```cpp theme={null}
#include <rex/graphics/vulkan/graphics_system.h>

using namespace rex;

// Create Vulkan graphics system
auto graphics = std::make_unique<graphics::vulkan::VulkanGraphicsSystem>();

X_STATUS status = graphics->Setup(
  processor,
  kernel_state,
  app_context,
  true
);

if (status == X_STATUS_SUCCESS) {
  // Initialize shaders and resources
  graphics->InitializeShaderStorage(cache_path, title_id, false);
  
  // Set interrupt callback for GPU events
  graphics->SetInterruptCallback(callback_func, user_data);
}
```

## See Also

* [KernelState](/api/kernel-state) - Kernel state management
* [IAudioSystem](/api/audio-system) - Audio subsystem interface
* [IInputSystem](/api/input-system) - Input subsystem interface


# IInputSystem
Source: https://rexglue-rexglue-sdk.mintlify.app/api/input-system

Abstract input system interface for controller and input device dependency injection

## Overview

`IInputSystem` is the abstract interface for input subsystems in ReXGlue. It provides dependency injection for different input backends, with SDL as the primary implementation for game controller support.

**Header:** `rex/system/interfaces/input.h`

**Namespace:** `rex::system`

## Interface Methods

### Setup

```cpp theme={null}
virtual X_STATUS Setup() = 0;
```

Initializes the input system and input drivers.

**Returns:** `X_STATUS` - Status code indicating success or failure

### Shutdown

```cpp theme={null}
virtual void Shutdown() = 0;
```

Cleanly shuts down the input system and releases all resources.

## Concrete Implementation

### InputSystem

**Class:** `rex::input::InputSystem`

**Header:** `rex/input/input_system.h`

Input system implementation supporting multiple input drivers.

```cpp theme={null}
class InputSystem : public system::IInputSystem {
public:
  explicit InputSystem(rex::ui::Window* window);
  ~InputSystem() override;
  
  rex::ui::Window* window() const;
  
  X_STATUS Setup() override;
  void Shutdown() override;
  
  void AddDriver(std::unique_ptr<InputDriver> driver);
  
  X_RESULT GetCapabilities(
    uint32_t user_index,
    uint32_t flags,
    X_INPUT_CAPABILITIES* out_caps
  );
  
  X_RESULT GetState(
    uint32_t user_index,
    X_INPUT_STATE* out_state
  );
  
  X_RESULT SetState(
    uint32_t user_index,
    X_INPUT_VIBRATION* vibration
  );
  
  X_RESULT GetKeystroke(
    uint32_t user_index,
    uint32_t flags,
    X_INPUT_KEYSTROKE* out_keystroke
  );
};
```

### SDL Input Driver

**Class:** `rex::input::sdl::SDLInputDriver`

**Header:** `rex/input/sdl/sdl_input_driver.h`

SDL-based input driver providing game controller and keyboard support.

```cpp theme={null}
class SDLInputDriver final : public InputDriver {
public:
  explicit SDLInputDriver(rex::ui::Window* window, size_t window_z_order);
  ~SDLInputDriver() override;
  
  X_STATUS Setup() override;
  
  X_RESULT GetCapabilities(
    uint32_t user_index,
    uint32_t flags,
    X_INPUT_CAPABILITIES* out_caps
  ) override;
  
  X_RESULT GetState(
    uint32_t user_index,
    X_INPUT_STATE* out_state
  ) override;
  
  X_RESULT SetState(
    uint32_t user_index,
    X_INPUT_VIBRATION* vibration
  ) override;
  
  X_RESULT GetKeystroke(
    uint32_t user_index,
    uint32_t flags,
    X_INPUT_KEYSTROKE* out_keystroke
  ) override;
};
```

**Configuration Constants:**

* `HID_SDL_USER_COUNT = 4` - Maximum simultaneous users/controllers
* `HID_SDL_THUMB_THRES = 0x4E00` - Thumbstick deadzone threshold
* `HID_SDL_TRIGG_THRES = 0x1F` - Trigger activation threshold
* `HID_SDL_REPEAT_DELAY = 400` - Key repeat delay in milliseconds
* `HID_SDL_REPEAT_RATE = 100` - Key repeat rate in milliseconds

## Factory Function

```cpp theme={null}
std::unique_ptr<InputSystem> CreateDefaultInputSystem(bool tool_mode);
```

Creates a default `InputSystem` with appropriate drivers:

* **Normal mode:** SDL driver + NOP driver
* **Tool mode:** NOP driver only (no physical input)

**Parameters:**

* `tool_mode` - If true, creates system without SDL driver for headless operation

**Returns:** Configured input system instance

## Example Usage

### Creating Input System

```cpp theme={null}
#include <rex/input/input_system.h>
#include <rex/ui/window.h>

using namespace rex;

// Create default input system
auto input = input::CreateDefaultInputSystem(false);

// Setup the input system
X_STATUS status = input->Setup();

if (status != X_STATUS_SUCCESS) {
  // Handle error
}

// Use input system...

// Cleanup
input->Shutdown();
```

### Manual Input System Creation

```cpp theme={null}
#include <rex/input/input_system.h>
#include <rex/input/sdl/sdl_input_driver.h>

using namespace rex;

// Create input system with window
auto input = std::make_unique<input::InputSystem>(window);

// Add SDL driver
auto sdl_driver = std::make_unique<input::sdl::SDLInputDriver>(
  window,
  0  // window z-order
);
input->AddDriver(std::move(sdl_driver));

// Setup
input->Setup();
```

### Reading Controller State

```cpp theme={null}
// Get controller capabilities
X_INPUT_CAPABILITIES caps;
X_RESULT result = input->GetCapabilities(
  0,      // user_index (0-3)
  0,      // flags
  &caps
);

if (result == X_ERROR_SUCCESS) {
  // Check capabilities
  if (caps.Type == 0x01) {  // Gamepad
    // Controller is available
  }
}

// Get current state
X_INPUT_STATE state;
result = input->GetState(0, &state);

if (result == X_ERROR_SUCCESS) {
  // Process gamepad state
  auto& gamepad = state.gamepad;
  
  if (gamepad.buttons & 0x0010) {  // A button
    // Handle A button press
  }
  
  // Read analog sticks
  int16_t left_x = gamepad.thumb_lx;
  int16_t left_y = gamepad.thumb_ly;
}
```

### Setting Controller Vibration

```cpp theme={null}
X_INPUT_VIBRATION vibration;
vibration.left_motor_speed = 32768;   // 50% left motor
vibration.right_motor_speed = 65535;  // 100% right motor

X_RESULT result = input->SetState(0, &vibration);

if (result == X_ERROR_SUCCESS) {
  // Vibration applied
}

// Stop vibration
vibration.left_motor_speed = 0;
vibration.right_motor_speed = 0;
input->SetState(0, &vibration);
```

### Reading Keystrokes

```cpp theme={null}
X_INPUT_KEYSTROKE keystroke;
X_RESULT result = input->GetKeystroke(
  0,      // user_index
  0,      // flags
  &keystroke
);

if (result == X_ERROR_SUCCESS) {
  // Process keystroke
  if (keystroke.flags & 0x0001) {  // Key down
    // Handle key down event
    uint16_t virtual_key = keystroke.virtual_key;
    uint16_t unicode = keystroke.unicode;
  }
}
```

### Tool Mode (Headless)

```cpp theme={null}
// Create input system without SDL for automated testing
auto input = input::CreateDefaultInputSystem(true);

input->Setup();

// Input calls will return no devices
X_INPUT_CAPABILITIES caps;
X_RESULT result = input->GetCapabilities(0, 0, &caps);
// result == X_ERROR_DEVICE_NOT_CONNECTED
```

## Multi-User Support

The input system supports up to 4 simultaneous users (controllers):

```cpp theme={null}
// Poll all controllers
for (uint32_t user = 0; user < 4; user++) {
  X_INPUT_STATE state;
  X_RESULT result = input->GetState(user, &state);
  
  if (result == X_ERROR_SUCCESS) {
    // Process input for user
  } else if (result == X_ERROR_DEVICE_NOT_CONNECTED) {
    // No controller at this index
  }
}
```

## See Also

* [IGraphicsSystem](/api/graphics-system) - Graphics subsystem interface
* [IAudioSystem](/api/audio-system) - Audio subsystem interface
* [KernelState](/api/kernel-state) - Kernel state management


# KernelState
Source: https://rexglue-rexglue-sdk.mintlify.app/api/kernel-state

Central kernel state management for the Xbox 360 emulation environment

## Overview

`KernelState` is the central manager for the Xbox 360 kernel emulation environment. It coordinates modules, threads, notifications, and provides access to core subsystems.

**Header:** `rex/system/kernel_state.h`

**Namespace:** `rex::system`

## Class Definition

```cpp theme={null}
class KernelState {
public:
  explicit KernelState(Runtime* emulator);
  ~KernelState();
  
  static KernelState* shared();
  
  // Subsystem accessors
  Runtime* emulator() const;
  memory::Memory* memory() const;
  runtime::Processor* processor() const;
  rex::filesystem::VirtualFileSystem* file_system() const;
  
  // XAM managers
  xam::AppManager* app_manager() const;
  xam::ContentManager* content_manager() const;
  xam::UserProfile* user_profile() const;
  
  // Object management
  util::ObjectTable* object_table();
  
  // Title information
  uint32_t title_id() const;
  util::XdbfGameData title_xdbf() const;
  util::XdbfGameData module_xdbf(object_ref<UserModule> exec_module) const;
  
  // Process management
  uint32_t process_type() const;
  void set_process_type(uint32_t value);
  uint32_t process_info_block_address() const;
  
  // TLS management
  uint32_t AllocateTLS();
  void FreeTLS(uint32_t slot);
  
  // Termination notifications
  void RegisterTitleTerminateNotification(uint32_t routine, uint32_t priority);
  void RemoveTitleTerminateNotification(uint32_t routine);
  
  // Module management
  void RegisterModule(XModule* module);
  void UnregisterModule(XModule* module);
  bool RegisterUserModule(object_ref<UserModule> module);
  void UnregisterUserModule(UserModule* module);
  bool IsKernelModule(const std::string_view name);
  object_ref<XModule> GetModule(const std::string_view name, bool user_only = false);
  
  object_ref<XThread> LaunchModule(object_ref<UserModule> module);
  object_ref<UserModule> GetExecutableModule();
  void SetExecutableModule(object_ref<UserModule> module);
  object_ref<UserModule> LoadUserModule(const std::string_view name, bool call_entry = true);
  void UnloadUserModule(const object_ref<UserModule>& module, bool call_entry = true);
  
  object_ref<KernelModule> GetKernelModule(const std::string_view name);
  
  template <typename T>
  object_ref<KernelModule> LoadKernelModule();
  
  template <typename T>
  object_ref<T> GetKernelModule(const std::string_view name);
  
  void TerminateTitle();
  
  // Thread management
  void RegisterThread(XThread* thread);
  void UnregisterThread(XThread* thread);
  void OnThreadExecute(XThread* thread);
  void OnThreadExit(XThread* thread);
  object_ref<XThread> GetThreadByID(uint32_t thread_id);
  
  // Notification system
  void RegisterNotifyListener(XNotifyListener* listener);
  void UnregisterNotifyListener(XNotifyListener* listener);
  void BroadcastNotification(XNotificationID id, uint32_t data);
  
  // DPC list
  util::NativeList* dpc_list();
  
  // Overlapped I/O completion
  void CompleteOverlapped(uint32_t overlapped_ptr, X_RESULT result);
  void CompleteOverlappedEx(uint32_t overlapped_ptr, X_RESULT result,
                           uint32_t extended_error, uint32_t length);
  void CompleteOverlappedImmediate(uint32_t overlapped_ptr, X_RESULT result);
  void CompleteOverlappedImmediateEx(uint32_t overlapped_ptr, X_RESULT result,
                                    uint32_t extended_error, uint32_t length);
  
  // Deferred overlapped completion with callbacks
  void CompleteOverlappedDeferred(
    std::move_only_function<void()> completion_callback,
    uint32_t overlapped_ptr,
    X_RESULT result,
    std::move_only_function<void()> pre_callback = nullptr,
    std::move_only_function<void()> post_callback = nullptr
  );
  
  void CompleteOverlappedDeferredEx(
    std::move_only_function<void()> completion_callback,
    uint32_t overlapped_ptr,
    X_RESULT result,
    uint32_t extended_error,
    uint32_t length,
    std::move_only_function<void()> pre_callback = nullptr,
    std::move_only_function<void()> post_callback = nullptr
  );
  
  // State persistence
  bool Save(stream::ByteStream* stream);
  bool Restore(stream::ByteStream* stream);
};
```

## Process Types

Constants for process type classification:

```cpp theme={null}
constexpr uint32_t X_PROCTYPE_IDLE = 0;
constexpr uint32_t X_PROCTYPE_USER = 1;
constexpr uint32_t X_PROCTYPE_SYSTEM = 2;
```

## Global Accessors

Convenience functions for accessing kernel state:

```cpp theme={null}
// Get global kernel state instance
KernelState* kernel_state();

// Get kernel memory directly
inline memory::Memory* kernel_memory() {
  return kernel_state()->memory();
}
```

## Kernel Import Trace Macros

Utility macros for logging kernel import function calls:

```cpp theme={null}
REXKRNL_IMPORT_TRACE(name, fmt, ...)    // Trace function call
REXKRNL_IMPORT_RESULT(name, fmt, ...)   // Trace function result
REXKRNL_IMPORT_FAIL(name, fmt, ...)     // Log function failure
REXKRNL_IMPORT_WARN(name, fmt, ...)     // Log function warning
```

## Example Usage

### Accessing Kernel State

```cpp theme={null}
#include <rex/system/kernel_state.h>

using namespace rex::system;

// Get global kernel state
auto* kernel = kernel_state();

// Access subsystems
auto* memory = kernel->memory();
auto* processor = kernel->processor();
auto* vfs = kernel->file_system();

// Get title information
uint32_t title_id = kernel->title_id();
auto xdbf_data = kernel->title_xdbf();
```

### Creating Kernel State

```cpp theme={null}
#include <rex/runtime.h>
#include <rex/system/kernel_state.h>

using namespace rex;

// Create runtime
auto runtime = std::make_unique<Runtime>();

// Create kernel state
auto kernel = std::make_unique<system::KernelState>(runtime.get());

// Initialize subsystems with kernel state
graphics_system->Setup(processor, kernel.get(), app_context, true);
audio_system->Setup(kernel.get());
```

### Loading Modules

```cpp theme={null}
// Load user module (XEX)
auto module = kernel->LoadUserModule("game.xex", true);

if (module) {
  // Set as executable
  kernel->SetExecutableModule(module);
  
  // Launch the module
  auto thread = kernel->LaunchModule(module);
}

// Get loaded module
auto existing = kernel->GetModule("xam.xex");
```

### Loading Kernel Modules

```cpp theme={null}
// Load kernel module by type
auto xboxkrnl = kernel->LoadKernelModule<XboxkrnlModule>();

// Get loaded kernel module
auto module = kernel->GetKernelModule<XamModule>("xam.xex");

if (module) {
  // Use kernel module
}
```

### Thread Management

```cpp theme={null}
// Get thread by ID
auto thread = kernel->GetThreadByID(thread_id);

if (thread) {
  // Work with thread
}

// Thread lifecycle is managed automatically via:
// - RegisterThread() - called when thread is created
// - OnThreadExecute() - called when thread starts executing
// - OnThreadExit() - called when thread exits
// - UnregisterThread() - called when thread is destroyed
```

### TLS Management

```cpp theme={null}
// Allocate TLS slot
uint32_t tls_slot = kernel->AllocateTLS();

// Use TLS slot for thread-local storage
// ...

// Free TLS slot when done
kernel->FreeTLS(tls_slot);
```

### Notification System

```cpp theme={null}
// Create notification listener
class MyListener : public XNotifyListener {
public:
  void OnNotification(XNotificationID id, uint32_t data) override {
    // Handle notification
  }
};

auto listener = new MyListener();
kernel->RegisterNotifyListener(listener);

// Broadcast notification
kernel->BroadcastNotification(notification_id, data);

// Cleanup
kernel->UnregisterNotifyListener(listener);
```

### Title Termination

```cpp theme={null}
// Register termination notification
void OnTerminate(uint32_t priority) {
  // Cleanup before termination
}

kernel->RegisterTitleTerminateNotification(
  reinterpret_cast<uint32_t>(&OnTerminate),
  priority
);

// Terminate the title (unloads modules, kills threads)
kernel->TerminateTitle();  // Does not return if called from guest thread!

// Remove notification
kernel->RemoveTitleTerminateNotification(
  reinterpret_cast<uint32_t>(&OnTerminate)
);
```

### Overlapped I/O Completion

```cpp theme={null}
// Complete overlapped I/O immediately
kernel->CompleteOverlappedImmediate(overlapped_ptr, X_ERROR_SUCCESS);

// Complete with extended info
kernel->CompleteOverlappedImmediateEx(
  overlapped_ptr,
  X_ERROR_SUCCESS,
  0,      // extended_error
  length  // bytes transferred
);

// Deferred completion with callback
kernel->CompleteOverlappedDeferred(
  []() {
    // Completion work
  },
  overlapped_ptr,
  X_ERROR_SUCCESS,
  []() { /* pre-callback */ },
  []() { /* post-callback */ }
);
```

### Object Table Access

```cpp theme={null}
// Access must be guarded by global critical region
auto* object_table = kernel->object_table();

// Add object to table
uint32_t handle = 0;
object_table->AddObject(object, &handle);

// Retrieve object
auto obj = object_table->LookupObject(handle);

// Remove object
object_table->RemoveObject(handle);
```

### XAM Managers

```cpp theme={null}
// Access application manager
auto* app_mgr = kernel->app_manager();

// Access content manager
auto* content_mgr = kernel->content_manager();

// Access user profile
auto* profile = kernel->user_profile();
profile->SetName("Player1");
```

### State Persistence

```cpp theme={null}
#include <rex/stream/byte_stream.h>

// Save kernel state
auto stream = std::make_unique<stream::ByteStream>();
if (kernel->Save(stream.get())) {
  // State saved successfully
  stream->WriteToFile("save.dat");
}

// Restore kernel state
stream->ReadFromFile("save.dat");
if (kernel->Restore(stream.get())) {
  // State restored successfully
}
```

### Process Type Management

```cpp theme={null}
// Get current process type
uint32_t proc_type = kernel->process_type();

if (proc_type == X_PROCTYPE_USER) {
  // User process
} else if (proc_type == X_PROCTYPE_SYSTEM) {
  // System process
}

// Set process type
kernel->set_process_type(X_PROCTYPE_USER);

// Get process info block address
uint32_t pib_addr = kernel->process_info_block_address();
```

## Thread Safety

KernelState uses `rex::thread::global_critical_region` to protect shared data structures. Access to the object table and certain operations must be performed while holding this lock.

## See Also

* [IGraphicsSystem](/api/graphics-system) - Graphics subsystem interface
* [IAudioSystem](/api/audio-system) - Audio subsystem interface
* [IInputSystem](/api/input-system) - Input subsystem interface


# rex::memory::Memory
Source: https://rexglue-rexglue-sdk.mintlify.app/api/memory

Xbox 360 guest memory system with virtual and physical heaps

## Overview

The `Memory` class models the entire Xbox 360 guest memory system, providing interfaces to both virtual and physical memory with TLB and page table management for allocation, mapping, and protection.

<Note>
  The memory is backed by a memory-mapped file and placed at a stable fixed host address (typically `0x100000000`). This allows efficient guest-to-host address translation and easy sharing across subsystems.
</Note>

## Memory Layout

The guest memory address space is split into several ranges with varying properties:

* **Virtual Heaps**: Standard guest virtual address ranges
* **Physical Heaps**: Hardware-mapped memory for audio/graphics subsystems
* Each range has its own page size, caching strategy, and protection settings

## Class Definition

```cpp theme={null}
namespace rex::memory {
  class Memory;
}
```

## Initialization

### Memory()

Constructs a new Memory instance.

```cpp theme={null}
Memory();
```

### Initialize()

Initializes the memory system by reserving host address space and setting up the memory-mapped file.

```cpp theme={null}
bool Initialize();
```

**Returns**: `true` on success, `false` if host address space reservation or file mapping fails

### Reset()

Resets all memory to zero and clears all allocations.

```cpp theme={null}
void Reset();
```

## Address Translation

### TranslateVirtual()

Translates a guest virtual address to a host pointer.

```cpp theme={null}
template <typename T = uint8_t*>
T TranslateVirtual(uint32_t guest_address) const;
```

**Parameters**:

* `guest_address` - Guest virtual address to translate

**Returns**: Host pointer to the memory location

<Note>
  The contents at the translated host address are in **big-endian** byte order.
</Note>

### TranslatePhysical()

Translates a guest physical address to a host pointer.

```cpp theme={null}
template <typename T = uint8_t*>
T TranslatePhysical(uint32_t guest_address) const;
```

**Parameters**:

* `guest_address` - Guest physical address to translate

**Returns**: Host pointer to the memory location

### HostToGuestVirtual()

Translates a host address back to a guest virtual address.

```cpp theme={null}
uint32_t HostToGuestVirtual(const void* host_address) const;
```

**Parameters**:

* `host_address` - Host pointer to translate

**Returns**: Guest virtual address

### GetPhysicalAddress()

Returns the guest physical address for a given guest virtual address.

```cpp theme={null}
uint32_t GetPhysicalAddress(uint32_t address) const;
```

**Parameters**:

* `address` - Guest virtual address

**Returns**: Guest physical address, or `UINT32_MAX` if unavailable

## Memory Operations

### Zero()

Zeros out a range of guest memory.

```cpp theme={null}
void Zero(uint32_t address, uint32_t size);
```

**Parameters**:

* `address` - Starting guest address
* `size` - Number of bytes to zero

### Fill()

Fills a range of guest memory with a byte value.

```cpp theme={null}
void Fill(uint32_t address, uint32_t size, uint8_t value);
```

**Parameters**:

* `address` - Starting guest address
* `size` - Number of bytes to fill
* `value` - Byte value to write

### Copy()

Copies a non-overlapping range of guest memory.

```cpp theme={null}
void Copy(uint32_t dest, uint32_t src, uint32_t size);
```

**Parameters**:

* `dest` - Destination guest address
* `src` - Source guest address
* `size` - Number of bytes to copy

### SearchAligned()

Searches for a sequence of dword values in big-endian order.

```cpp theme={null}
uint32_t SearchAligned(uint32_t start, uint32_t end, 
                       const uint32_t* values, size_t value_count);
```

**Parameters**:

* `start` - Starting guest address
* `end` - Ending guest address
* `values` - Array of dword values to search for
* `value_count` - Number of values in the array

**Returns**: Guest address where the sequence was found, or 0 if not found

## System Heap Allocation

### SystemHeapAlloc()

Allocates virtual memory from the system heap for kernel structures and internal allocations.

```cpp theme={null}
uint32_t SystemHeapAlloc(uint32_t size, uint32_t alignment = 0x20,
                         uint32_t system_heap_flags = kSystemHeapDefault);
```

**Parameters**:

* `size` - Number of bytes to allocate
* `alignment` - Alignment requirement (default: 32 bytes)
* `system_heap_flags` - Allocation flags (see `SystemHeapFlag`)

**Returns**: Guest address of allocated memory, or 0 on failure

### SystemHeapFree()

Frees memory allocated with `SystemHeapAlloc()`.

```cpp theme={null}
void SystemHeapFree(uint32_t address);
```

**Parameters**:

* `address` - Guest address to free

## Heap Management

### LookupHeap()

Gets the heap containing the given address.

```cpp theme={null}
const BaseHeap* LookupHeap(uint32_t address) const;
BaseHeap* LookupHeap(uint32_t address);
```

**Parameters**:

* `address` - Guest address to lookup

**Returns**: Pointer to the heap, or `nullptr` if not found

### LookupHeapByType()

Gets a heap with specific properties.

```cpp theme={null}
BaseHeap* LookupHeapByType(bool physical, uint32_t page_size);
```

**Parameters**:

* `physical` - `true` for physical heap, `false` for virtual
* `page_size` - Required page size

**Returns**: Pointer to matching heap, or `nullptr`

### GetPhysicalHeap()

Gets the physical base heap.

```cpp theme={null}
VirtualHeap* GetPhysicalHeap();
```

**Returns**: Pointer to the physical heap

## MMIO (Memory-Mapped I/O)

### AddVirtualMappedRange()

Defines an MMIO virtual address range with read/write callbacks.

```cpp theme={null}
bool AddVirtualMappedRange(uint32_t virtual_address, uint32_t mask, uint32_t size,
                           void* context,
                           runtime::MMIOReadCallback read_callback,
                           runtime::MMIOWriteCallback write_callback);
```

**Parameters**:

* `virtual_address` - Starting virtual address
* `mask` - Address mask
* `size` - Size of the range
* `context` - User context pointer passed to callbacks
* `read_callback` - Callback for read operations
* `write_callback` - Callback for write operations

**Returns**: `true` on success

### LookupVirtualMappedRange()

Gets the MMIO range for a virtual address.

```cpp theme={null}
runtime::MMIORange* LookupVirtualMappedRange(uint32_t virtual_address);
```

**Parameters**:

* `virtual_address` - Address to lookup

**Returns**: Pointer to MMIO range, or `nullptr`

## Physical Memory Callbacks

### RegisterPhysicalMemoryInvalidationCallback()

Registers a callback for physical memory invalidation events.

```cpp theme={null}
void* RegisterPhysicalMemoryInvalidationCallback(
    PhysicalMemoryInvalidationCallback callback,
    void* callback_context);
```

**Parameters**:

* `callback` - Callback function
* `callback_context` - User context pointer

**Returns**: Handle for unregistering the callback

### UnregisterPhysicalMemoryInvalidationCallback()

Unregisters a physical memory invalidation callback.

```cpp theme={null}
void UnregisterPhysicalMemoryInvalidationCallback(void* callback_handle);
```

**Parameters**:

* `callback_handle` - Handle returned from registration

### EnablePhysicalMemoryAccessCallbacks()

Enables physical memory access callbacks for a memory range.

```cpp theme={null}
void EnablePhysicalMemoryAccessCallbacks(
    uint32_t physical_address, uint32_t length,
    bool enable_invalidation_notifications,
    bool enable_data_providers);
```

**Parameters**:

* `physical_address` - Starting physical address
* `length` - Length of the range
* `enable_invalidation_notifications` - Enable write invalidation callbacks
* `enable_data_providers` - Enable data provider callbacks

## Function Table API

<Note>
  These methods support static recompilation by providing a function dispatch table stored in guest memory at `IMAGE_BASE + IMAGE_SIZE`.
</Note>

### InitializeFunctionTable()

Initializes the function table region for recompiled code dispatch.

```cpp theme={null}
bool InitializeFunctionTable(uint32_t code_base, uint32_t code_size,
                             uint32_t image_base, uint32_t image_size);
```

**Parameters**:

* `code_base` - Base address of code section
* `code_size` - Size of code section
* `image_base` - Base address of executable image
* `image_size` - Size of executable image

**Returns**: `true` on success, `false` if allocation fails

### SetFunction()

Registers a host function for a guest address.

```cpp theme={null}
void SetFunction(uint32_t guest_address, PPCFunc* host_function);
```

**Parameters**:

* `guest_address` - Guest address to map
* `host_function` - Host function pointer

### GetFunction()

Gets the registered host function for a guest address.

```cpp theme={null}
PPCFunc* GetFunction(uint32_t guest_address) const;
```

**Parameters**:

* `guest_address` - Guest address to lookup

**Returns**: Host function pointer, or `nullptr` if not registered

### HasFunctionTable()

Checks if the function table has been initialized.

```cpp theme={null}
bool HasFunctionTable() const;
```

**Returns**: `true` if initialized

## Properties

### file\_name()

Gets the path to the memory-mapped backing file.

```cpp theme={null}
const std::filesystem::path& file_name() const;
```

### virtual\_membase()

Gets the base address of virtual memory in host address space.

```cpp theme={null}
uint8_t* virtual_membase() const;
```

<Note>
  This is typically `0x100000000` on 64-bit systems.
</Note>

### physical\_membase()

Gets the base address of physical memory in host address space.

```cpp theme={null}
uint8_t* physical_membase() const;
```

<Note>
  This is typically `0x200000000` on 64-bit systems.
</Note>

## Enumerations

### SystemHeapFlag

```cpp theme={null}
enum SystemHeapFlag : uint32_t {
  kSystemHeapVirtual = 1 << 0,
  kSystemHeapPhysical = 1 << 1,
  kSystemHeapDefault = kSystemHeapVirtual
};
```

### HeapType

```cpp theme={null}
enum class HeapType : uint8_t {
  kGuestVirtual,
  kGuestXex,
  kGuestPhysical,
  kHostPhysical
};
```

### MemoryAllocationFlag

```cpp theme={null}
enum MemoryAllocationFlag : uint32_t {
  kMemoryAllocationReserve = 1 << 0,
  kMemoryAllocationCommit = 1 << 1
};
```

### MemoryProtectFlag

```cpp theme={null}
enum MemoryProtectFlag : uint32_t {
  kMemoryProtectRead = 1 << 0,
  kMemoryProtectWrite = 1 << 1,
  kMemoryProtectNoCache = 1 << 2,
  kMemoryProtectWriteCombine = 1 << 3,
  kMemoryProtectNoAccess = 0
};
```

## See Also

* [Processor](/api/processor) - CPU emulation and execution
* [XThread](/api/thread) - Thread management


# PathConfig
Source: https://rexglue-rexglue-sdk.mintlify.app/api/path-config

Content path configuration structure

## Overview

`PathConfig` is a structure that defines the directory paths for game content, user data, and updates. It is passed to the `OnConfigurePaths()` virtual hook in `ReXApp`, allowing subclasses to customize data storage locations before the Runtime is constructed.

## Definition

```cpp theme={null}
struct PathConfig {
  std::filesystem::path game_data_root;
  std::filesystem::path user_data_root;
  std::filesystem::path update_data_root;
};
```

## Fields

<ParamField type="std::filesystem::path">
  Root directory for read-only game content (assets, original game files)
</ParamField>

<ParamField type="std::filesystem::path">
  Root directory for user-specific data (save files, settings, profiles)
</ParamField>

<ParamField type="std::filesystem::path">
  Root directory for game updates and downloadable content
</ParamField>

## Default Values

All paths start with sensible defaults derived from:

* Command-line arguments
* Console variables (cvars)
* Platform conventions

Subclasses can override any field in the `OnConfigurePaths()` hook before Runtime construction.

## Usage

Override `OnConfigurePaths()` to customize data paths:

```cpp theme={null}
class MyApp : public rex::ReXApp {
protected:
    void OnConfigurePaths(PathConfig& paths) override {
        // Use custom locations for user data
        paths.user_data_root = std::filesystem::path(std::getenv("HOME")) / ".mygame" / "saves";
        
        // Keep game data in a specific directory
        paths.game_data_root = "/opt/mygame/data";
        
        // Use default for updates (don't modify update_data_root)
    }
};
```

## Accessing Configured Paths

After configuration, the resolved paths can be accessed through `ReXApp` accessor methods:

```cpp theme={null}
void MyApp::OnPostSetup() {
    auto save_dir = user_data_root() / "savefiles";
    auto assets_dir = game_data_root() / "textures";
    
    // Use the paths...
}
```

## See Also

* [rex::ReXApp](/api/rexapp) - Base application class that uses this structure
* [ReXApp Virtual Hooks](/api/rexapp) - Virtual hook for path customization


# PPCImageInfo
Source: https://rexglue-rexglue-sdk.mintlify.app/api/ppc-image-info

PPC image layout structure passed to ReXApp

## Overview

`PPCImageInfo` is a structure that describes the PowerPC image layout for a recompiled Xbox 360 application. This structure is passed from the generated config header into the `ReXApp` constructor to configure the runtime memory layout.

## Definition

```cpp theme={null}
struct PPCImageInfo {
  uint32_t code_base;
  uint32_t code_size;
  uint32_t image_base;
  uint32_t image_size;
  const PPCFuncMapping* func_mappings;
};
```

## Fields

<ParamField type="uint32_t">
  Base address of the executable code segment in PPC address space
</ParamField>

<ParamField type="uint32_t">
  Size of the code segment in bytes
</ParamField>

<ParamField type="uint32_t">
  Base address of the entire loaded image in PPC address space
</ParamField>

<ParamField type="uint32_t">
  Total size of the loaded image in bytes
</ParamField>

<ParamField type="const PPCFuncMapping*">
  Pointer to array of function mappings between PPC addresses and recompiled native functions
</ParamField>

## Usage

This structure is typically initialized with constants from the generated configuration header:

```cpp theme={null}
class MyApp : public rex::ReXApp {
public:
    static std::unique_ptr<rex::ui::WindowedApp> Create(
        rex::ui::WindowedAppContext& ctx) {
      return std::unique_ptr<MyApp>(new MyApp(ctx, "my_app",
          {PPC_CODE_BASE, PPC_CODE_SIZE, PPC_IMAGE_BASE,
           PPC_IMAGE_SIZE, PPCFuncMappings}));
    }
};
```

The values are generated by the ReXGlue toolchain during the recompilation process and should not be modified manually.

## See Also

* [rex::ReXApp](/api/rexapp) - Base application class that uses this structure


# rex::runtime::Processor
Source: https://rexglue-rexglue-sdk.mintlify.app/api/processor

PowerPC processor emulation with IRQL and interrupt handling

## Overview

The `Processor` class manages PowerPC code execution, module loading, and interrupt request level (IRQL) handling for the Xbox 360 emulation runtime.

## Class Definition

```cpp theme={null}
namespace rex::runtime {
  class Processor;
}
```

## Construction

### Processor()

Constructs a new Processor instance.

```cpp theme={null}
Processor(memory::Memory* memory, ExportResolver* export_resolver);
```

**Parameters**:

* `memory` - Pointer to the Memory system
* `export_resolver` - Pointer to the export resolver for kernel functions

## Initialization

### PreLaunch()

Runs pre-launch logic after modules and threads are initialized.

```cpp theme={null}
void PreLaunch();
```

This prepares the processor for execution by setting up the initial execution environment.

## Module Management

### AddModule()

Adds a loaded module to the processor.

```cpp theme={null}
bool AddModule(std::unique_ptr<Module> module);
```

**Parameters**:

* `module` - Unique pointer to the module to add

**Returns**: `true` on success, `false` if the module couldn't be added

### GetModule()

Retrieves a module by name.

```cpp theme={null}
Module* GetModule(const std::string_view name);
```

**Parameters**:

* `name` - Name of the module to retrieve

**Returns**: Pointer to the module, or `nullptr` if not found

### GetModules()

Gets a list of all loaded modules.

```cpp theme={null}
std::vector<Module*> GetModules();
```

**Returns**: Vector of pointers to all loaded modules

## Code Execution

### Execute()

Executes PowerPC code at the specified address.

```cpp theme={null}
bool Execute(ThreadState* thread_state, uint32_t address);
```

**Parameters**:

* `thread_state` - Thread state for execution context
* `address` - Guest address to begin execution

**Returns**: `true` on successful execution

### ExecuteRaw()

Executes raw PowerPC code without setup overhead.

```cpp theme={null}
bool ExecuteRaw(ThreadState* thread_state, uint32_t address);
```

**Parameters**:

* `thread_state` - Thread state for execution context
* `address` - Guest address to begin execution

**Returns**: `true` on successful execution

### Execute() with Arguments

Executes a function at the specified address with arguments.

```cpp theme={null}
uint64_t Execute(ThreadState* thread_state, uint32_t address, 
                 uint64_t args[], size_t arg_count);
```

**Parameters**:

* `thread_state` - Thread state for execution context
* `address` - Guest address of function to call
* `args` - Array of arguments to pass to the function
* `arg_count` - Number of arguments in the array

**Returns**: Return value from the executed function

### ExecuteInterrupt()

Executes code as an interrupt handler.

```cpp theme={null}
uint64_t ExecuteInterrupt(ThreadState* thread_state, uint32_t address,
                          uint64_t args[], size_t arg_count);
```

**Parameters**:

* `thread_state` - Thread state for execution context
* `address` - Guest address of interrupt handler
* `args` - Array of arguments
* `arg_count` - Number of arguments

**Returns**: Return value from the interrupt handler

## Interrupt Request Level (IRQL)

<Note>
  IRQL controls interrupt priority. Higher IRQL values prevent lower-priority interrupts from firing. This matches Xbox 360 kernel behavior.
</Note>

### RaiseIrql()

Raises the processor's IRQL to a new level.

```cpp theme={null}
Irql RaiseIrql(Irql new_value);
```

**Parameters**:

* `new_value` - New IRQL level (must be >= current IRQL)

**Returns**: Previous IRQL value

**Example**:

```cpp theme={null}
auto old_irql = processor->RaiseIrql(Irql::DISPATCH);
// Critical section - no dispatching allowed
processor->LowerIrql(old_irql);
```

### LowerIrql()

Lowers the processor's IRQL to a previous level.

```cpp theme={null}
void LowerIrql(Irql old_value);
```

**Parameters**:

* `old_value` - Previous IRQL value (must be less than or equal to current IRQL)

### current\_irql()

Gets the current IRQL level.

```cpp theme={null}
Irql current_irql() const;
```

**Returns**: Current IRQL value

## Function Table Management

### InitializeFunctionTable()

Initializes the function dispatch table for recompiled code.

```cpp theme={null}
bool InitializeFunctionTable(uint32_t code_base, uint32_t code_size,
                             uint32_t image_base, uint32_t image_size);
```

**Parameters**:

* `code_base` - Base address of executable code section
* `code_size` - Size of code section
* `image_base` - Base address of loaded image
* `image_size` - Total image size

**Returns**: `true` on success

### SetFunction()

Registers a host function for a guest address in the function table.

```cpp theme={null}
void SetFunction(uint32_t guest_address, ::PPCFunc* func);
```

**Parameters**:

* `guest_address` - Guest address to map
* `func` - Host function pointer

### GetFunction()

Retrieves the registered host function for a guest address.

```cpp theme={null}
::PPCFunc* GetFunction(uint32_t guest_address);
```

**Parameters**:

* `guest_address` - Guest address to lookup

**Returns**: Host function pointer, or `nullptr` if not registered

### HasFunctionTable()

Checks if the function table has been initialized.

```cpp theme={null}
bool HasFunctionTable() const;
```

**Returns**: `true` if initialized

## Thread Management

### OnThreadCreated()

Called when a new thread is created.

```cpp theme={null}
void OnThreadCreated(uint32_t handle, ThreadState* thread_state, Thread* thread);
```

**Parameters**:

* `handle` - Thread handle
* `thread_state` - Pointer to thread state
* `thread` - Pointer to thread object

### OnThreadExit()

Called when a thread exits.

```cpp theme={null}
void OnThreadExit(uint32_t thread_id);
```

**Parameters**:

* `thread_id` - ID of exiting thread

### OnThreadDestroyed()

Called when a thread is destroyed.

```cpp theme={null}
void OnThreadDestroyed(uint32_t thread_id);
```

**Parameters**:

* `thread_id` - ID of destroyed thread

## State Management

### Save()

Saves the processor state to a byte stream.

```cpp theme={null}
bool Save(stream::ByteStream* stream);
```

**Parameters**:

* `stream` - Byte stream to write to

**Returns**: `true` on success

### Restore()

Restores the processor state from a byte stream.

```cpp theme={null}
bool Restore(stream::ByteStream* stream);
```

**Parameters**:

* `stream` - Byte stream to read from

**Returns**: `true` on success

## Properties

### memory()

Gets the associated Memory instance.

```cpp theme={null}
memory::Memory* memory() const;
```

**Returns**: Pointer to the Memory system

### export\_resolver()

Gets the associated ExportResolver.

```cpp theme={null}
ExportResolver* export_resolver() const;
```

**Returns**: Pointer to the export resolver

### execution\_state()

Gets the current execution state.

```cpp theme={null}
ExecutionState execution_state() const;
```

**Returns**: Current execution state (running, paused, stepping, or ended)

## Enumerations

### Irql

Interrupt Request Level values:

```cpp theme={null}
enum class Irql : uint32_t {
  PASSIVE = 0,  // Normal execution
  APC = 1,      // Asynchronous procedure call level
  DISPATCH = 2, // Thread dispatch level
  DPC = 3       // Deferred procedure call level
};
```

**IRQL Hierarchy**:

* `PASSIVE` - Normal execution, all interrupts allowed
* `APC` - APCs blocked
* `DISPATCH` - Thread dispatching blocked
* `DPC` - Deferred procedure calls active

### ExecutionState

Describes the debugger state:

```cpp theme={null}
enum class ExecutionState {
  kRunning,  // Target is running normally
  kStepping, // Target is single-stepping
  kPaused,   // Target is paused for debugging
  kEnded     // Target has stopped (crash, exit, etc.)
};
```

## See Also

* [Memory](/api/memory) - Memory subsystem
* [XThread](/api/thread) - Thread management


# Recompiler
Source: https://rexglue-rexglue-sdk.mintlify.app/api/recompiler

PPC to C++ recompiler interface

## Overview

The `rex::codegen::Recompiler` class is the main interface for converting PowerPC binary code to C++ source code. It manages the recompilation process, output buffering, and file generation.

## Class Definition

```cpp theme={null}
namespace rex::codegen {
  struct Recompiler {
    std::unique_ptr<rex::Runtime> runtime;
    CodegenContext* ctx_;
    std::string out;
    size_t cppFileIndex;
    std::vector<std::pair<std::string, std::string>> pendingWrites;
    bool validationFailed_;

    Recompiler();
    ~Recompiler();

    // Output methods
    template <class... Args>
    void print(fmt::format_string<Args...> fmt, Args&&... args);

    template <class... Args>
    void println(fmt::format_string<Args...> fmt, Args&&... args);

    // Recompilation methods
    bool recompile(const FunctionNode& fn, uint32_t base, const ppc_insn& insn,
                   const uint32_t* data,
                   std::unordered_map<uint32_t, JumpTable>::iterator& switchTable,
                   RecompilerLocalVariables& localVariables, CSRState& csrState);

    bool recompile(const FunctionNode& fn);
    bool recompile(bool force);

    // File management
    void SaveCurrentOutData(const std::string_view& name = std::string_view());
    void FlushPendingWrites();
  };
}
```

## Public Members

<ParamField type="std::unique_ptr<rex::Runtime>">
  Runtime environment for executing recompiled code
</ParamField>

<ParamField type="CodegenContext*">
  Non-owning pointer to the code generation context
</ParamField>

<ParamField type="std::string">
  Output buffer accumulating generated C++ code
</ParamField>

<ParamField type="size_t">
  Counter for generating unique C++ file names
</ParamField>

<ParamField type="std::vector<std::pair<std::string, std::string>>">
  Deferred file writes buffered until validation passes. Each pair contains (filename, content).
</ParamField>

<ParamField type="bool">
  Tracks if validation failed during analysis
</ParamField>

## Methods

### print()

Append formatted text to the output buffer.

```cpp theme={null}
template <class... Args>
void print(fmt::format_string<Args...> fmt, Args&&... args)
```

<ParamField type="fmt::format_string<Args...>">
  Format string using  syntax
</ParamField>

<ParamField type="Args&&...">
  Variadic arguments to format
</ParamField>

**Example:**

```cpp theme={null}
recompiler.print("uint32_t r{} = ", regNum);
```

### println()

Append formatted text with a newline to the output buffer.

```cpp theme={null}
template <class... Args>
void println(fmt::format_string<Args...> fmt, Args&&... args)
```

<ParamField type="fmt::format_string<Args...>">
  Format string using  syntax
</ParamField>

<ParamField type="Args&&...">
  Variadic arguments to format
</ParamField>

**Example:**

```cpp theme={null}
recompiler.println("  ctx.r[{}] = 0x{:08X};", reg, value);
```

### recompile() - Single Instruction

Recompile a single PowerPC instruction (internal use).

```cpp theme={null}
bool recompile(const FunctionNode& fn, uint32_t base, const ppc_insn& insn,
               const uint32_t* data,
               std::unordered_map<uint32_t, JumpTable>::iterator& switchTable,
               RecompilerLocalVariables& localVariables, CSRState& csrState)
```

<ParamField type="const FunctionNode&">
  Function node containing the instruction
</ParamField>

<ParamField type="uint32_t">
  Base address for the instruction
</ParamField>

<ParamField type="const ppc_insn&">
  PowerPC instruction to recompile
</ParamField>

<ParamField type="const uint32_t*">
  Pointer to instruction data
</ParamField>

<ParamField type="std::unordered_map<uint32_t, JumpTable>::iterator&">
  Iterator to current jump table (if any)
</ParamField>

<ParamField type="RecompilerLocalVariables&">
  Tracks which registers are used as local variables
</ParamField>

<ParamField type="CSRState&">
  Current control/status register state (FPU or VMX)
</ParamField>

**Returns:** `true` on success, `false` on error

### recompile() - Single Function

Recompile an entire function (internal use).

```cpp theme={null}
bool recompile(const FunctionNode& fn)
```

<ParamField type="const FunctionNode&">
  Function node to recompile
</ParamField>

**Returns:** `true` on success, `false` on error

### recompile() - All Functions

Recompile all functions and write output files.

```cpp theme={null}
bool recompile(bool force)
```

<ParamField type="bool">
  If `true`, generate output even if validation errors occur. If `false`, validation errors block code generation.
</ParamField>

**Returns:** `true` if output was generated, `false` if blocked due to errors

<Note>
  Generated code includes SDK headers (`rexglue/runtime/ppc_context.h`) and follows the configured code generation options from `RecompilerConfig`.
</Note>

### SaveCurrentOutData()

Save the current output buffer to pending writes.

```cpp theme={null}
void SaveCurrentOutData(const std::string_view& name = std::string_view())
```

<ParamField type="const std::string_view&">
  Optional custom filename. If empty, uses auto-generated name based on `cppFileIndex`.
</ParamField>

### FlushPendingWrites()

Write all pending files to disk. Called after validation passes.

```cpp theme={null}
void FlushPendingWrites()
```

<Warning>
  This method writes all buffered files to the output directory specified in the configuration. Ensure validation has passed before calling.
</Warning>

## Related Types

### RecompilerLocalVariables

Tracks which PowerPC registers are allocated as C++ local variables during recompilation.

```cpp theme={null}
struct RecompilerLocalVariables {
  bool ctr;        // Count register
  bool xer;        // Fixed-point exception register
  bool reserved;   // Reserved register (r13)
  bool cr[8];      // Condition register fields
  bool r[32];      // General-purpose registers
  bool f[32];      // Floating-point registers
  bool v[128];     // Vector registers
  bool env;        // Environment pointer
  bool temp;       // Temporary variable
  bool v_temp;     // Vector temporary
  bool ea;         // Effective address

  uint32_t mmio_base_regs;  // Bit mask tracking MMIO base addresses

  void set_mmio_base(size_t reg);
  void clear_mmio_base(size_t reg);
  bool is_mmio_base(size_t reg) const;
};
```

<ParamField type="uint32_t">
  Bit mask where bit N indicates rN contains an MMIO base address. Set when `lis` loads a value with upper 16 bits >= 0x7F00 (address >= 0x7F000000) or when `oris` sets upper bits >= 0xC800 (address >= 0xC8000000).
</ParamField>

### CSRState

Tracks the current control/status register mode.

```cpp theme={null}
enum class CSRState { Unknown, FPU, VMX };
```

<ParamField type="enum value">
  Status register mode is unknown
</ParamField>

<ParamField type="enum value">
  Floating-point unit mode
</ParamField>

<ParamField type="enum value">
  Vector/SIMD (AltiVec) mode
</ParamField>

## Constants

<ParamField type="static constexpr uint32_t">
  Encoded instruction value for PowerPC EIEIO (Enforce In-order Execution of I/O) instruction.
</ParamField>

## See Also

* [RecompilerConfig](/api/recompiler-config) - Configuration structure
* [FunctionConfig](/api/function-config) - Per-function configuration


# RecompilerConfig
Source: https://rexglue-rexglue-sdk.mintlify.app/api/recompiler-config

Recompiler configuration structure

## Overview

The `RecompilerConfig` structure defines all configuration options for the PowerPC to C++ recompiler, including input/output paths, code generation flags, analysis tuning parameters, and manual overrides.

## Structure Definition

```cpp theme={null}
namespace rex::codegen {
  struct RecompilerConfig {
    // Required fields
    std::string projectName;
    std::string filePath;
    std::string outDirectoryPath;

    // Patch files (TODO)
    std::string patchFilePath;
    std::string patchedFilePath;

    // Code generation options
    bool skipLr;
    bool ctrAsLocalVariable;
    bool xerAsLocalVariable;
    bool reservedRegisterAsLocalVariable;
    bool skipMsr;
    bool crRegistersAsLocalVariables;
    bool nonArgumentRegistersAsLocalVariables;
    bool nonVolatileRegistersAsLocalVariables;
    bool generateExceptionHandlers;

    // Analysis tuning
    uint32_t maxJumpExtension;
    uint32_t dataRegionThreshold;
    uint32_t largeFunctionThreshold;

    // Manual overrides
    std::unordered_map<uint32_t, FunctionConfig> functions;
    std::unordered_map<uint32_t, JumpTable> switchTables;
    std::unordered_map<uint32_t, MidAsmHook> midAsmHooks;
    uint32_t longJmpAddress;
    uint32_t setJmpAddress;

    // User hints
    std::unordered_map<uint32_t, uint32_t> invalidInstructionHints;
    std::unordered_set<uint32_t> knownIndirectCallHints;
    std::vector<uint32_t> exceptionHandlerFuncHints;

    // Methods
    void Load(const std::string_view& configFilePath);
    ValidationResult Validate() const;
  };
}
```

## Required Fields

<ParamField type="std::string">
  Project name used for output file naming. Generated files will be named `{projectName}_generated_{index}.cpp`.
</ParamField>

<ParamField type="std::string">
  Path to the input XEX or ELF binary file to recompile.
</ParamField>

<ParamField type="std::string">
  Output directory where generated C++ source files will be written.
</ParamField>

## Patch Files

<ParamField type="std::string">
  Path to binary patch file (feature not yet implemented).
</ParamField>

<ParamField type="std::string">
  Path to write patched binary (feature not yet implemented).
</ParamField>

## Code Generation Options

<ParamField type="bool">
  Skip generating link register (LR) operations.
</ParamField>

<ParamField type="bool">
  Allocate the count register (CTR) as a C++ local variable instead of using `ctx.ctr`.
</ParamField>

<ParamField type="bool">
  Allocate the fixed-point exception register (XER) as a C++ local variable.
</ParamField>

<ParamField type="bool">
  Allocate the reserved register (r13) as a C++ local variable.
</ParamField>

<ParamField type="bool">
  Skip generating machine state register (MSR) operations.
</ParamField>

<ParamField type="bool">
  Allocate condition register fields as C++ local variables.
</ParamField>

<ParamField type="bool">
  Allocate non-argument general-purpose registers as C++ local variables. Excludes r3-r10 which are used for arguments.
</ParamField>

<ParamField type="bool">
  Allocate non-volatile general-purpose registers (r14-r31) as C++ local variables.
</ParamField>

<ParamField type="bool">
  Generate SEH (Structured Exception Handling) exception handler wrapper functions.
</ParamField>

## Analysis Tuning

<ParamField type="uint32_t">
  Maximum number of bytes to extend a function boundary when resolving jump table targets. Prevents runaway function detection.
</ParamField>

<ParamField type="uint32_t">
  Number of consecutive invalid instructions required to mark a region as data (not code). Helps distinguish embedded data from code.
</ParamField>

<ParamField type="uint32_t">
  Size threshold in bytes (default 1MB). Functions exceeding this size trigger a warning as they may indicate detection errors.
</ParamField>

## Manual Overrides

<ParamField type="std::unordered_map<uint32_t, FunctionConfig>">
  Map of address to function configuration. Allows manual specification of function boundaries, names, and chunk relationships. See [FunctionConfig](/api/function-config).
</ParamField>

<ParamField type="std::unordered_map<uint32_t, JumpTable>">
  Map of address to jump table definitions for switch statement reconstruction.
</ParamField>

<ParamField type="std::unordered_map<uint32_t, MidAsmHook>">
  Map of address to mid-assembly hook configurations. Allows injecting custom C++ code at specific instruction addresses. See [FunctionConfig](/api/function-config).
</ParamField>

<ParamField type="uint32_t">
  Address of custom `longjmp` implementation (0 = use standard library).
</ParamField>

<ParamField type="uint32_t">
  Address of custom `setjmp` implementation (0 = use standard library).
</ParamField>

## User Hints

<ParamField type="std::unordered_map<uint32_t, uint32_t>">
  Map of address to size (in bytes) marking known invalid instruction regions. Merged with analysis results to improve disassembly accuracy.
</ParamField>

<ParamField type="std::unordered_set<uint32_t>">
  Set of addresses where `bctr` instructions are known to be indirect calls (vtable dispatch, computed calls) rather than tail calls.
</ParamField>

<ParamField type="std::vector<uint32_t>">
  Additional exception handler function addresses not detected by automatic analysis.
</ParamField>

## Methods

### Load()

Load configuration from a TOML file.

```cpp theme={null}
void Load(const std::string_view& configFilePath)
```

<ParamField type="const std::string_view&">
  Path to the TOML configuration file.
</ParamField>

**Example TOML:**

```toml theme={null}
projectName = "MyGame"
filePath = "/path/to/game.xex"
outDirectoryPath = "./generated"

# Code generation
nonVolatileRegistersAsLocalVariables = true
generateExceptionHandlers = true

# Analysis
maxJumpExtension = 131072
dataRegionThreshold = 32

# Manual overrides
[functions.0x82000100]
name = "InitializeEngine"
size = 1024

[functions.0x82000500]
name = "RenderFrame"
end = 0x82000800
```

### Validate()

Validate the loaded configuration.

```cpp theme={null}
ValidationResult Validate() const
```

**Returns:** `ValidationResult` containing warnings and errors

Checks performed:

* Address alignment (4-byte boundaries)
* Required fields are non-empty
* Function size/end constraints
* Path validity
* Sanity checks (e.g., `maxJumpExtension` not excessive)

**Example:**

```cpp theme={null}
auto result = config.Validate();
if (!result) {
  for (const auto& error : result.errors) {
    std::cerr << "Error: " << error << '\n';
  }
}
for (const auto& warning : result.warnings) {
  std::cout << "Warning: " << warning << '\n';
}
```

## ValidationResult

Nested structure returned by `Validate()`.

```cpp theme={null}
struct ValidationResult {
  bool valid;
  std::vector<std::string> warnings;
  std::vector<std::string> errors;

  explicit operator bool() const { return valid; }
};
```

<ParamField type="bool">
  `true` if no errors occurred (warnings are allowed). `false` if fatal errors exist.
</ParamField>

<ParamField type="std::vector<std::string>">
  Non-fatal issues that don't prevent code generation but should be reviewed.
</ParamField>

<ParamField type="std::vector<std::string>">
  Fatal issues that block code generation unless `force` is used.
</ParamField>

## See Also

* [Recompiler](/api/recompiler) - Main recompiler class
* [FunctionConfig](/api/function-config) - Per-function configuration
* [FunctionConfig](/api/function-config) - Per-function and hook configuration


# rex::ReXApp
Source: https://rexglue-rexglue-sdk.mintlify.app/api/rexapp

Base class for recompiled Xbox 360 applications

## Overview

`rex::ReXApp` is the base class for recompiled Xbox 360 applications in the ReXGlue SDK. It handles all boilerplate setup including runtime initialization, window creation, ImGui integration, module launching, and shutdown. Consumer projects inherit from this class and optionally override virtual hooks for customization.

## Constructor

```cpp theme={null}
protected:
ReXApp(ui::WindowedAppContext& ctx, 
       std::string_view name, 
       PPCImageInfo ppc_info,
       std::string_view usage = "[game_directory]");
```

<ParamField type="ui::WindowedAppContext&">
  Windowed application context
</ParamField>

<ParamField type="std::string_view">
  Application name identifier
</ParamField>

<ParamField type="PPCImageInfo">
  PPC image layout information (code base, size, function mappings)
</ParamField>

<ParamField type="std::string_view">
  Command-line usage string for help text
</ParamField>

## Virtual Hooks

These methods can be overridden in subclasses to customize application behavior:

### OnPreSetup

```cpp theme={null}
virtual void OnPreSetup(RuntimeConfig& config);
```

Called before `Runtime::Setup()`. Override to modify backend configuration.

<ParamField type="RuntimeConfig&">
  Runtime configuration that can be modified before setup
</ParamField>

### OnPostSetup

```cpp theme={null}
virtual void OnPostSetup();
```

Called after runtime is fully initialized, before window creation. Use for post-initialization setup.

### OnCreateDialogs

```cpp theme={null}
virtual void OnCreateDialogs(ui::ImGuiDrawer* drawer);
```

Called after ImGui drawer is created. Add custom dialogs and UI overlays here.

<ParamField type="ui::ImGuiDrawer*">
  ImGui drawer instance to register custom dialogs with
</ParamField>

### OnShutdown

```cpp theme={null}
virtual void OnShutdown();
```

Called before cleanup begins. Release custom resources here.

### OnConfigurePaths

```cpp theme={null}
virtual void OnConfigurePaths(PathConfig& paths);
```

Called after path defaults are computed, before Runtime is constructed. Override to adjust game/user/update data paths programmatically.

<ParamField type="PathConfig&">
  Path configuration with defaults that can be modified
</ParamField>

## Accessor Methods

These protected methods provide access to core components for subclass use:

### runtime

```cpp theme={null}
Runtime* runtime() const;
```

Returns pointer to the Runtime instance.

### window

```cpp theme={null}
ui::Window* window() const;
```

Returns pointer to the Window instance.

### imgui\_drawer

```cpp theme={null}
ui::ImGuiDrawer* imgui_drawer() const;
```

Returns pointer to the ImGuiDrawer instance.

### game\_data\_root

```cpp theme={null}
const std::filesystem::path& game_data_root() const;
```

Returns the game data root directory path.

### user\_data\_root

```cpp theme={null}
const std::filesystem::path& user_data_root() const;
```

Returns the user data root directory path.

### update\_data\_root

```cpp theme={null}
const std::filesystem::path& update_data_root() const;
```

Returns the update data root directory path.

## Example: Subclassing ReXApp

The generated `main.cpp` from `rexglue init` or `rexglue migrate` creates a subclass like this:

```cpp theme={null}
class MyApp : public rex::ReXApp {
public:
    using rex::ReXApp::ReXApp;
    
    static std::unique_ptr<rex::ui::WindowedApp> Create(
        rex::ui::WindowedAppContext& ctx) {
      return std::unique_ptr<MyApp>(new MyApp(ctx, "my_app",
          {PPC_CODE_BASE, PPC_CODE_SIZE, PPC_IMAGE_BASE,
           PPC_IMAGE_SIZE, PPCFuncMappings}));
    }
    
protected:
    // Override virtual hooks as needed
    void OnPreSetup(RuntimeConfig& config) override {
        // Customize runtime configuration
    }
    
    void OnCreateDialogs(ui::ImGuiDrawer* drawer) override {
        // Add custom UI dialogs
    }
    
    void OnConfigurePaths(PathConfig& paths) override {
        // Adjust data paths if needed
        paths.user_data_root = "/custom/save/location";
    }
};

REX_DEFINE_APP(my_app, MyApp::Create)
```

## See Also

* [PPCImageInfo](/api/ppc-image-info) - PPC image layout structure
* [PathConfig](/api/path-config) - Path configuration structure


# rex::Runtime
Source: https://rexglue-rexglue-sdk.mintlify.app/api/runtime

Main entry point for ReXGlue runtime subsystem

# Runtime

The `rex::Runtime` class is the main entry point for recompiled applications. It owns and manages all runtime subsystems including memory, virtual file system, kernel state, and backend systems (graphics, audio, input).

## Constructor

```cpp theme={null}
explicit Runtime(const std::filesystem::path& game_data_root,
                 const std::filesystem::path& user_data_root = {},
                 const std::filesystem::path& update_data_root = {})
```

Creates a new Runtime instance with the specified data paths.

<ParamField type="const std::filesystem::path&">
  Path to game data directory. Mounted as `game:` and `d:` in the virtual file system.
</ParamField>

<ParamField type="const std::filesystem::path&">
  Path to user data directory for save files and settings. Defaults to `game_data_root` if empty.
</ParamField>

<ParamField type="const std::filesystem::path&">
  Path to update/DLC data directory. Mounted as `update:` if provided and exists.
</ParamField>

## Setup Methods

### Basic Setup

```cpp theme={null}
X_STATUS Setup(RuntimeConfig config = {})
```

Initializes the runtime environment with the provided configuration. This method:

* Initializes SEH exception support
* Sets up the guest clock (50MHz tick frequency)
* Creates memory system
* Initializes processor and export resolver
* Sets up virtual file system
* Initializes backend systems (graphics, audio, input) from config
* Loads HLE kernel modules (xboxkrnl, xam)

<ParamField type="RuntimeConfig">
  Runtime configuration with backend system factories. See [RuntimeConfig](/api/runtime-config).
</ParamField>

<ResponseField name="X_STATUS" type="uint32_t">
  Returns `X_STATUS_SUCCESS` on success, or an error code:

  * `X_STATUS_UNSUCCESSFUL` - Already initialized or initialization failed
  * GPU setup errors if graphics backend fails and not in tool mode
</ResponseField>

### ReXGlue Setup (Recompiled Code)

```cpp theme={null}
X_STATUS Setup(uint32_t code_base, uint32_t code_size, uint32_t image_base, 
               uint32_t image_size, const PPCFuncMapping* func_mappings, 
               RuntimeConfig config = {})
```

Initializes runtime for recompiled code execution. Calls basic `Setup()` first, then registers the function dispatch table for recompiled code.

<ParamField type="uint32_t">
  Guest virtual address where recompiled code begins.
</ParamField>

<ParamField type="uint32_t">
  Size of the recompiled code region in bytes.
</ParamField>

<ParamField type="uint32_t">
  Guest virtual address of the loaded XEX image.
</ParamField>

<ParamField type="uint32_t">
  Size of the loaded XEX image in bytes.
</ParamField>

<ParamField type="const PPCFuncMapping*">
  Null-terminated array of `{guest_addr, host_func}` pairs mapping guest addresses to recompiled host functions.
</ParamField>

<ParamField type="RuntimeConfig">
  Runtime configuration with backend system factories. See [RuntimeConfig](/api/runtime-config).
</ParamField>

<ResponseField name="X_STATUS" type="uint32_t">
  Returns `X_STATUS_SUCCESS` on success, or error codes from basic `Setup()` or function table initialization.
</ResponseField>

<Warning>
  This method sets the global `Runtime::instance()` singleton. Only call once per process.
</Warning>

## Module Loading

### LoadXexImage

```cpp theme={null}
X_STATUS LoadXexImage(const std::string_view module_path)
```

Loads an XEX module into guest memory from the virtual file system.

<ParamField type="std::string_view">
  Path to XEX file in VFS, typically `"game:\\default.xex"`.
</ParamField>

<ResponseField name="X_STATUS" type="uint32_t">
  Returns `X_STATUS_SUCCESS` on success, or XEX loading error codes.
</ResponseField>

### LaunchModule

```cpp theme={null}
system::object_ref<system::XThread> LaunchModule()
```

Launches the previously loaded executable module and returns the main thread.

<ResponseField name="system::object_ref<system::XThread>" type="object_ref">
  Returns the main thread object, or `nullptr` if launch failed.
</ResponseField>

<Note>
  Call this after `LoadXexImage()` to begin execution. The returned thread can be waited on to detect program completion.
</Note>

## Shutdown

```cpp theme={null}
void Shutdown()
```

Shuts down all subsystems in reverse initialization order. Automatically called by destructor.

## Accessors

### Subsystem Accessors

```cpp theme={null}
memory::Memory* memory() const
rex::filesystem::VirtualFileSystem* file_system() const
system::KernelState* kernel_state() const
system::IGraphicsSystem* graphics_system() const
system::IAudioSystem* audio_system() const
system::IInputSystem* input_system() const
runtime::Processor* processor() const
runtime::ExportResolver* export_resolver() const
```

Access runtime subsystems. Returns `nullptr` if the subsystem is not initialized.

### Path Accessors

```cpp theme={null}
const std::filesystem::path& game_data_root() const
const std::filesystem::path& user_data_root() const
const std::filesystem::path& update_data_root() const
```

Returns the configured data paths.

### UI Context Accessors

```cpp theme={null}
void set_app_context(ui::WindowedAppContext* context)
ui::WindowedAppContext* app_context() const

void set_display_window(ui::Window* window)
ui::Window* display_window() const

void set_imgui_drawer(ui::ImGuiDrawer* drawer)
ui::ImGuiDrawer* imgui_drawer() const
```

Set and get UI components for presentation and dialog systems. Call setters before `Setup()`.

### Global Instance

```cpp theme={null}
static Runtime* instance()
```

Returns the global runtime instance, set after calling the ReXGlue `Setup()` overload.

<ResponseField name="Runtime*" type="Runtime*">
  Global runtime instance, or `nullptr` if not initialized.
</ResponseField>

### Tool Mode

```cpp theme={null}
bool is_tool_mode() const
```

Checks if running in tool mode (GPU initialization skipped).

### Memory Base

```cpp theme={null}
uint8_t* virtual_membase() const
```

Returns the base pointer to guest virtual memory for recompiled code access.

<ResponseField name="uint8_t*" type="uint8_t*">
  Virtual memory base pointer, or `nullptr` if memory not initialized.
</ResponseField>

## Usage Example

```cpp theme={null}
#include <rex/runtime.h>
#include <rex/graphics/vulkan/graphics_system.h>
#include <rex/audio/sdl/sdl_audio_system.h>
#include <rex/input/input_system.h>

// Typical ReXGlue application setup
int main() {
  // Create runtime with game assets path
  auto runtime = std::make_unique<rex::Runtime>(
    "path/to/game/assets",
    "path/to/user/data"
  );
  
  // Configure backends
  rex::RuntimeConfig config;
  config.graphics = REX_GRAPHICS_BACKEND(rex::graphics::vulkan::VulkanGraphicsSystem);
  config.audio_factory = REX_AUDIO_BACKEND(rex::audio::sdl::SDLAudioSystem);
  config.input_factory = REX_INPUT_BACKEND(rex::input::CreateDefaultInputSystem);
  
  // Setup for recompiled code
  auto status = runtime->Setup(
    ppc_info.code_base,
    ppc_info.code_size,
    ppc_info.image_base,
    ppc_info.image_size,
    ppc_info.func_mappings,
    std::move(config)
  );
  
  if (XFAILED(status)) {
    REXLOG_ERROR("Runtime setup failed: {:08X}", status);
    return 1;
  }
  
  // Load and launch XEX
  status = runtime->LoadXexImage("game:\\default.xex");
  if (XFAILED(status)) {
    REXLOG_ERROR("Failed to load XEX: {:08X}", status);
    return 1;
  }
  
  auto main_thread = runtime->LaunchModule();
  if (!main_thread) {
    REXLOG_ERROR("Failed to launch module");
    return 1;
  }
  
  // Wait for completion
  main_thread->Wait(0, 0, 0, nullptr);
  
  return 0;
}
```

## Real-World Example

From `src/ui/rex_app.cpp:118-148`:

```cpp theme={null}
// Create runtime
runtime_ = std::make_unique<rex::Runtime>(game_data_root_, user_data_root_, update_data_root_);
runtime_->set_app_context(&app_context());

// Build runtime config with default platform backends
rex::RuntimeConfig config;
#if REX_HAS_D3D12
config.graphics = REX_GRAPHICS_BACKEND(rex::graphics::d3d12::D3D12GraphicsSystem);
#elif REX_HAS_VULKAN
config.graphics = REX_GRAPHICS_BACKEND(rex::graphics::vulkan::VulkanGraphicsSystem);
#endif
config.audio_factory = REX_AUDIO_BACKEND(rex::audio::sdl::SDLAudioSystem);
config.input_factory = REX_INPUT_BACKEND(rex::input::CreateDefaultInputSystem);

// Allow subclass to customize config
OnPreSetup(config);

auto status = runtime_->Setup(ppc_info_.code_base, ppc_info_.code_size, ppc_info_.image_base,
                              ppc_info_.image_size, ppc_info_.func_mappings, std::move(config));
if (XFAILED(status)) {
  REXLOG_ERROR("Runtime setup failed: {:08X}", status);
  return false;
}

// Load XEX image
status = runtime_->LoadXexImage("game:\\default.xex");
if (XFAILED(status)) {
  REXLOG_ERROR("Failed to load XEX: {:08X}", status);
  return false;
}
```

## See Also

* [RuntimeConfig](/api/runtime-config) - Configuration structure and backend factories
* Memory System - Guest virtual memory management
* KernelState - Xbox 360 kernel emulation


# RuntimeConfig
Source: https://rexglue-rexglue-sdk.mintlify.app/api/runtime-config

Configuration structure for Runtime subsystem dependency injection

# RuntimeConfig

The `RuntimeConfig` structure provides dependency injection for Runtime subsystem backends. This keeps the runtime library decoupled from concrete backend implementations (graphics, audio, input).

## Structure Definition

```cpp theme={null}
struct RuntimeConfig {
  std::unique_ptr<system::IGraphicsSystem> graphics;
  std::function<std::unique_ptr<system::IAudioSystem>(runtime::Processor*)> audio_factory;
  std::function<std::unique_ptr<system::IInputSystem>(bool tool_mode)> input_factory;
  bool tool_mode = false;
};
```

## Fields

<ParamField type="std::unique_ptr<system::IGraphicsSystem>">
  Graphics backend implementation. Moved directly into Runtime during `Setup()`.

  **Available implementations:**

  * `rex::graphics::vulkan::VulkanGraphicsSystem` (cross-platform)
  * `rex::graphics::d3d12::D3D12GraphicsSystem` (Windows only)

  Use the `REX_GRAPHICS_BACKEND()` macro for easy instantiation.
</ParamField>

<ParamField type="std::function<std::unique_ptr<system::IAudioSystem>(runtime::Processor*)>">
  Factory function that creates an audio backend. Takes a `Processor*` because `IAudioSystem` requires processor access at construction time (only available during `Setup()`).

  **Available implementations:**

  * `rex::audio::sdl::SDLAudioSystem` (cross-platform, SDL2-based)

  Use the `REX_AUDIO_BACKEND()` macro for easy factory creation.
</ParamField>

<ParamField type="std::function<std::unique_ptr<system::IInputSystem>(bool tool_mode)>">
  Factory function that creates an input backend. Takes `tool_mode` parameter to allow skipping input initialization in headless tools.

  **Available implementations:**

  * `rex::input::CreateDefaultInputSystem` (platform-dependent default)

  Use the `REX_INPUT_BACKEND()` macro for easy factory creation.
</ParamField>

<ParamField type="bool">
  If `true`, skips GPU initialization for analysis tools (like codegen). Audio and input may also be skipped based on factory implementation.
</ParamField>

## Helper Macros

The SDK provides three helper macros for populating `RuntimeConfig` with concrete backends:

### REX\_GRAPHICS\_BACKEND

```cpp theme={null}
#define REX_GRAPHICS_BACKEND(Type) std::make_unique<Type>()
```

Creates a graphics backend instance.

<ParamField type="typename">
  Graphics system class name (e.g., `rex::graphics::vulkan::VulkanGraphicsSystem`).
</ParamField>

**Example:**

```cpp theme={null}
config.graphics = REX_GRAPHICS_BACKEND(rex::graphics::vulkan::VulkanGraphicsSystem);
```

### REX\_AUDIO\_BACKEND

```cpp theme={null}
#define REX_AUDIO_BACKEND(Type) \
  [](::rex::runtime::Processor* _proc) -> std::unique_ptr<::rex::system::IAudioSystem> { \
    return Type::Create(_proc); \
  }
```

Creates an audio backend factory lambda. The factory receives the `Processor*` during runtime initialization.

<ParamField type="typename">
  Audio system class name with a static `Create(Processor*)` method (e.g., `rex::audio::sdl::SDLAudioSystem`).
</ParamField>

**Example:**

```cpp theme={null}
config.audio_factory = REX_AUDIO_BACKEND(rex::audio::sdl::SDLAudioSystem);
```

### REX\_INPUT\_BACKEND

```cpp theme={null}
#define REX_INPUT_BACKEND(SetupFunc) \
  [](bool _tool_mode) -> std::unique_ptr<::rex::system::IInputSystem> { \
    return SetupFunc(_tool_mode); \
  }
```

Creates an input backend factory lambda. The factory receives the `tool_mode` flag during runtime initialization.

<ParamField type="function">
  Input system setup function with signature `std::unique_ptr<IInputSystem>(bool tool_mode)`.
</ParamField>

**Example:**

```cpp theme={null}
config.input_factory = REX_INPUT_BACKEND(rex::input::CreateDefaultInputSystem);
```

## Design Notes

### Why Factories for Audio and Input?

**Audio** uses a factory because `IAudioSystem` requires a `Processor*` at construction time. The processor is only available during `Runtime::Setup()`, so we can't construct audio backends before calling `Setup()`.

**Input** uses a factory to allow the backend to check `tool_mode` and skip initialization in headless scenarios (e.g., codegen tools).

**Graphics** is passed directly as a `unique_ptr` because it doesn't require runtime-specific parameters at construction.

## Usage Example

### Full Configuration

```cpp theme={null}
#include <rex/runtime.h>
#include <rex/graphics/vulkan/graphics_system.h>
#include <rex/audio/sdl/sdl_audio_system.h>
#include <rex/input/input_system.h>

rex::RuntimeConfig config;

// Graphics: Vulkan backend
config.graphics = REX_GRAPHICS_BACKEND(rex::graphics::vulkan::VulkanGraphicsSystem);

// Audio: SDL2 backend
config.audio_factory = REX_AUDIO_BACKEND(rex::audio::sdl::SDLAudioSystem);

// Input: Platform default
config.input_factory = REX_INPUT_BACKEND(rex::input::CreateDefaultInputSystem);

// Not tool mode (full initialization)
config.tool_mode = false;

// Pass to Runtime::Setup()
auto status = runtime->Setup(std::move(config));
```

### Tool Mode (No GPU)

```cpp theme={null}
rex::RuntimeConfig config;
config.tool_mode = true;  // Skip GPU initialization

// Optionally still configure audio/input if needed by tool
config.audio_factory = REX_AUDIO_BACKEND(rex::audio::sdl::SDLAudioSystem);
config.input_factory = REX_INPUT_BACKEND(rex::input::CreateDefaultInputSystem);

auto status = runtime->Setup(std::move(config));
```

### Platform-Specific Graphics

```cpp theme={null}
rex::RuntimeConfig config;

#if REX_HAS_D3D12
  config.graphics = REX_GRAPHICS_BACKEND(rex::graphics::d3d12::D3D12GraphicsSystem);
#elif REX_HAS_VULKAN
  config.graphics = REX_GRAPHICS_BACKEND(rex::graphics::vulkan::VulkanGraphicsSystem);
#else
  #error "No graphics backend available"
#endif

config.audio_factory = REX_AUDIO_BACKEND(rex::audio::sdl::SDLAudioSystem);
config.input_factory = REX_INPUT_BACKEND(rex::input::CreateDefaultInputSystem);

auto status = runtime->Setup(std::move(config));
```

## Real-World Example

From `src/ui/rex_app.cpp:122-133`:

```cpp theme={null}
// Build runtime config with default platform backends
rex::RuntimeConfig config;
#if REX_HAS_D3D12
config.graphics = REX_GRAPHICS_BACKEND(rex::graphics::d3d12::D3D12GraphicsSystem);
#elif REX_HAS_VULKAN
config.graphics = REX_GRAPHICS_BACKEND(rex::graphics::vulkan::VulkanGraphicsSystem);
#endif
config.audio_factory = REX_AUDIO_BACKEND(rex::audio::sdl::SDLAudioSystem);
config.input_factory = REX_INPUT_BACKEND(rex::input::CreateDefaultInputSystem);

// Allow subclass to customize config
OnPreSetup(config);

auto status = runtime_->Setup(ppc_info_.code_base, ppc_info_.code_size, ppc_info_.image_base,
                              ppc_info_.image_size, ppc_info_.func_mappings, std::move(config));
```

## Macro Expansion Example

To understand what the macros do, here's what they expand to:

```cpp theme={null}
// This:
config.graphics = REX_GRAPHICS_BACKEND(rex::graphics::vulkan::VulkanGraphicsSystem);

// Expands to:
config.graphics = std::make_unique<rex::graphics::vulkan::VulkanGraphicsSystem>();

// This:
config.audio_factory = REX_AUDIO_BACKEND(rex::audio::sdl::SDLAudioSystem);

// Expands to:
config.audio_factory = [](::rex::runtime::Processor* _proc) -> std::unique_ptr<::rex::system::IAudioSystem> {
  return rex::audio::sdl::SDLAudioSystem::Create(_proc);
};

// This:
config.input_factory = REX_INPUT_BACKEND(rex::input::CreateDefaultInputSystem);

// Expands to:
config.input_factory = [](bool _tool_mode) -> std::unique_ptr<::rex::system::IInputSystem> {
  return rex::input::CreateDefaultInputSystem(_tool_mode);
};
```

## See Also

* [rex::Runtime](/api/runtime) - Main runtime class that consumes this config
* Graphics System - GPU emulation backends
* Audio System - Audio processing backends
* Input System - Controller and keyboard input backends


# rex::system::XThread
Source: https://rexglue-rexglue-sdk.mintlify.app/api/thread

Xbox 360 guest thread creation and management

## Overview

The `XThread` class represents an Xbox 360 guest thread, managing thread state, execution, APCs (Asynchronous Procedure Calls), priority, and affinity.

<Note>
  Thread stacks are allocated in the guest address range `0x70000000` to `0x7F000000`.
</Note>

## Class Definition

```cpp theme={null}
namespace rex::system {
  class XThread : public XObject;
}
```

## Construction

### XThread()

Constructs a new guest thread.

```cpp theme={null}
XThread(KernelState* kernel_state);

XThread(KernelState* kernel_state, uint32_t stack_size, 
        uint32_t xapi_thread_startup, uint32_t start_address,
        uint32_t start_context, uint32_t creation_flags,
        bool guest_thread, bool main_thread = false);
```

**Parameters**:

* `kernel_state` - Pointer to the kernel state
* `stack_size` - Size of thread stack in bytes
* `xapi_thread_startup` - Guest address of XAPI startup routine
* `start_address` - Guest address of thread entry point
* `start_context` - Context parameter passed to thread
* `creation_flags` - Thread creation flags (see `X_CREATE_SUSPENDED`)
* `guest_thread` - `true` if created by guest code
* `main_thread` - `true` if this is the main entry point thread

## Thread Lifecycle

### Create()

Creates and initializes the thread.

```cpp theme={null}
X_STATUS Create();
```

**Returns**: Status code (`X_STATUS_SUCCESS` on success)

### Execute()

Begins thread execution.

```cpp theme={null}
virtual void Execute();
```

This method runs the thread's entry point function. Override in derived classes for custom behavior.

### Exit()

Exits the thread with an exit code.

```cpp theme={null}
X_STATUS Exit(int exit_code);
```

**Parameters**:

* `exit_code` - Thread exit code

**Returns**: Status code

### Terminate()

Forcibly terminates the thread.

```cpp theme={null}
X_STATUS Terminate(int exit_code);
```

**Parameters**:

* `exit_code` - Thread exit code

**Returns**: Status code

### Reenter()

Re-enters thread execution at a specific address.

```cpp theme={null}
virtual void Reenter(uint32_t address);
```

**Parameters**:

* `address` - Guest address to resume execution

## Thread Control

### Suspend()

Suspends the thread.

```cpp theme={null}
X_STATUS Suspend(uint32_t* out_suspend_count = nullptr);
```

**Parameters**:

* `out_suspend_count` - Optional pointer to receive previous suspend count

**Returns**: Status code

### Resume()

Resumes the thread.

```cpp theme={null}
X_STATUS Resume(uint32_t* out_suspend_count = nullptr);
```

**Parameters**:

* `out_suspend_count` - Optional pointer to receive previous suspend count

**Returns**: Status code

### Delay()

Delays thread execution for a specified interval.

```cpp theme={null}
X_STATUS Delay(uint32_t processor_mode, uint32_t alertable, uint64_t interval);
```

**Parameters**:

* `processor_mode` - Processor mode (user/kernel)
* `alertable` - Whether the delay is alertable for APCs
* `interval` - Delay interval in 100-nanosecond units

**Returns**: Status code

## Priority and Affinity

### SetPriority()

Sets the thread priority.

```cpp theme={null}
void SetPriority(int32_t increment);
```

**Parameters**:

* `increment` - Priority increment value

### QueryPriority()

Queries the current thread priority.

```cpp theme={null}
int32_t QueryPriority();
```

**Returns**: Current priority value

### priority()

Gets the thread priority.

```cpp theme={null}
int32_t priority() const;
```

**Returns**: Priority value

### SetAffinity()

Sets the processor affinity mask.

```cpp theme={null}
void SetAffinity(uint32_t affinity);
```

**Parameters**:

* `affinity` - Processor affinity bitmask

<Note>
  Xbox 360 has 3 cores with 2 hardware threads each:

  * Thread 0-1: Core 0
  * Thread 2-3: Core 1 (sometimes XContent)
  * Thread 4-5: Core 2 (often XAudio)
</Note>

### SetActiveCpu()

Sets the active CPU for the thread.

```cpp theme={null}
void SetActiveCpu(uint8_t cpu_index);
```

**Parameters**:

* `cpu_index` - CPU index (0-5)

### active\_cpu()

Gets the active CPU index.

```cpp theme={null}
uint8_t active_cpu() const;
```

**Returns**: Active CPU index

## Critical Regions and IRQL

### EnterCriticalRegion()

Enters a critical region (disables APCs).

```cpp theme={null}
void EnterCriticalRegion();
```

### LeaveCriticalRegion()

Leaves a critical region (re-enables APCs).

```cpp theme={null}
void LeaveCriticalRegion();
```

### RaiseIrql()

Raises the thread's IRQL.

```cpp theme={null}
uint32_t RaiseIrql(uint32_t new_irql);
```

**Parameters**:

* `new_irql` - New IRQL level

**Returns**: Previous IRQL value

### LowerIrql()

Lowers the thread's IRQL.

```cpp theme={null}
void LowerIrql(uint32_t new_irql);
```

**Parameters**:

* `new_irql` - IRQL level to lower to

## Asynchronous Procedure Calls (APCs)

### EnqueueApc()

Enqueues an APC for execution on this thread.

```cpp theme={null}
void EnqueueApc(uint32_t normal_routine, uint32_t normal_context,
                uint32_t arg1, uint32_t arg2);
```

**Parameters**:

* `normal_routine` - Guest address of APC routine
* `normal_context` - Context parameter
* `arg1` - First argument
* `arg2` - Second argument

### CheckApcs()

Checks and delivers pending APCs.

```cpp theme={null}
void CheckApcs();
```

### LockApc()

Locks the APC queue.

```cpp theme={null}
void LockApc();
```

### UnlockApc()

Unlocks the APC queue.

```cpp theme={null}
void UnlockApc(bool queue_delivery);
```

**Parameters**:

* `queue_delivery` - Whether to queue APC delivery after unlocking

### apc\_list()

Gets the APC list.

```cpp theme={null}
util::NativeList* apc_list();
```

**Returns**: Pointer to the APC list

## Thread Local Storage (TLS)

### GetTLSValue()

Gets a TLS value.

```cpp theme={null}
bool GetTLSValue(uint32_t slot, uint32_t* value_out);
```

**Parameters**:

* `slot` - TLS slot index
* `value_out` - Pointer to receive the value

**Returns**: `true` on success

### SetTLSValue()

Sets a TLS value.

```cpp theme={null}
bool SetTLSValue(uint32_t slot, uint32_t value);
```

**Parameters**:

* `slot` - TLS slot index
* `value` - Value to set

**Returns**: `true` on success

### tls\_ptr()

Gets the TLS base address.

```cpp theme={null}
uint32_t tls_ptr() const;
```

**Returns**: Guest address of TLS block

## Current Thread Access

### GetCurrentThread()

Gets the currently executing XThread.

```cpp theme={null}
static XThread* GetCurrentThread();
```

**Returns**: Pointer to current thread, or `nullptr`

### GetCurrentThreadHandle()

Gets the current thread's handle.

```cpp theme={null}
static uint32_t GetCurrentThreadHandle();
```

**Returns**: Current thread handle

### GetCurrentThreadId()

Gets the current thread's ID.

```cpp theme={null}
static uint32_t GetCurrentThreadId();
```

**Returns**: Current thread ID

### IsInThread()

Checks if code is executing in a specific thread.

```cpp theme={null}
static bool IsInThread(XThread* other);
static bool IsInThread();
```

**Parameters**:

* `other` - Thread to check against

**Returns**: `true` if in the specified thread

## Error Handling

### GetLastError()

Gets the last error code for the current thread.

```cpp theme={null}
static uint32_t GetLastError();
```

**Returns**: Last error code

### SetLastError()

Sets the last error code for the current thread.

```cpp theme={null}
static void SetLastError(uint32_t error_code);
```

**Parameters**:

* `error_code` - Error code to set

### last\_error()

Gets the thread's last error code.

```cpp theme={null}
uint32_t last_error();
```

**Returns**: Last error code

### set\_last\_error()

Sets the thread's last error code.

```cpp theme={null}
void set_last_error(uint32_t error_code);
```

**Parameters**:

* `error_code` - Error code to set

## Properties

### thread\_id()

Gets the thread ID.

```cpp theme={null}
uint32_t thread_id() const;
```

**Returns**: Thread ID

### pcr\_ptr()

Gets the Processor Control Region (PCR) address.

```cpp theme={null}
uint32_t pcr_ptr() const;
```

**Returns**: Guest address of PCR

### is\_guest\_thread()

Checks if the thread was created by guest code.

```cpp theme={null}
bool is_guest_thread() const;
```

**Returns**: `true` if created by guest

### main\_thread()

Checks if this is the main entry point thread.

```cpp theme={null}
bool main_thread() const;
```

**Returns**: `true` if main thread

### is\_running()

Checks if the thread is running.

```cpp theme={null}
bool is_running() const;
```

**Returns**: `true` if running

### creation\_params()

Gets the thread creation parameters.

```cpp theme={null}
const CreationParams* creation_params() const;
```

**Returns**: Pointer to creation parameters

### suspend\_count()

Gets the thread suspend count.

```cpp theme={null}
uint32_t suspend_count();
```

**Returns**: Current suspend count

### set\_name()

Sets the thread name.

```cpp theme={null}
void set_name(const std::string_view name);
```

**Parameters**:

* `name` - Thread name

### thread()

Gets the underlying host thread.

```cpp theme={null}
rex::thread::Thread* thread();
```

**Returns**: Pointer to host thread

### thread\_state()

Gets the PowerPC thread state.

```cpp theme={null}
runtime::ThreadState* thread_state();
```

**Returns**: Pointer to thread state (registers, etc.)

## State Management

### Save()

Saves thread state to a byte stream.

```cpp theme={null}
virtual bool Save(stream::ByteStream* stream) override;
```

**Parameters**:

* `stream` - Byte stream to write to

**Returns**: `true` on success

### Restore()

Restores thread state from a byte stream.

```cpp theme={null}
static object_ref<XThread> Restore(KernelState* kernel_state, 
                                    stream::ByteStream* stream);
```

**Parameters**:

* `kernel_state` - Kernel state pointer
* `stream` - Byte stream to read from

**Returns**: Restored thread object

## Constants

### Stack Address Range

```cpp theme={null}
static constexpr uint32_t kStackAddressRangeBegin = 0x70000000;
static constexpr uint32_t kStackAddressRangeEnd = 0x7F000000;
```

### Creation Flags

```cpp theme={null}
constexpr uint32_t X_CREATE_SUSPENDED = 0x00000001;
constexpr uint32_t X_TLS_OUT_OF_INDEXES = UINT32_MAX;
```

## Related Types

### CreationParams

Thread creation parameters:

```cpp theme={null}
struct CreationParams {
  uint32_t stack_size;
  uint32_t xapi_thread_startup;
  uint32_t start_address;
  uint32_t start_context;
  uint32_t creation_flags;
};
```

### X\_KPCR

Processor Control Region structure (mapped in guest memory):

```cpp theme={null}
struct X_KPCR {
  rex::be<uint32_t> tls_ptr;         // 0x0
  rex::be<uint32_t> pcr_ptr;         // 0x30
  rex::be<uint32_t> stack_base_ptr;  // 0x70
  rex::be<uint32_t> stack_end_ptr;   // 0x74
  rex::be<uint32_t> current_thread;  // 0x100
  uint8_t current_cpu;               // 0x10C
  rex::be<uint32_t> dpc_active;      // 0x150
  // ... (see source for full structure)
};
```

## See Also

* [Processor](/api/processor) - CPU emulation and execution
* [Memory](/api/memory) - Memory subsystem
* `rex::thread::Thread` - Host threading primitives


# VirtualFileSystem
Source: https://rexglue-rexglue-sdk.mintlify.app/api/vfs

Virtual file system for path-based device mounting and symbolic link resolution

The `VirtualFileSystem` class provides a unified interface for mounting devices and resolving paths in the ReXGlue runtime. It abstracts Xbox 360 file system paths like `game:/` and `d:/` to host operating system directories.

## Class Definition

```cpp theme={null}
namespace rex::filesystem {
  class VirtualFileSystem;
}
```

**Header:** `<rex/filesystem/vfs.h>`

## Overview

VirtualFileSystem manages device registration and path resolution for the runtime. It supports:

* **Device mounting** - Register filesystem devices at specific mount points
* **Symbolic links** - Map Xbox 360 paths (e.g., `game:/`, `d:/`) to device paths
* **Path resolution** - Resolve virtual paths to filesystem entries
* **File operations** - Open, create, and delete files through mounted devices

## Constructor & Destructor

### VirtualFileSystem()

```cpp theme={null}
VirtualFileSystem();
```

Constructs a new virtual file system instance.

***

### \~VirtualFileSystem()

```cpp theme={null}
~VirtualFileSystem();
```

Destructs the VFS and releases all registered devices.

## Device Management

### RegisterDevice

```cpp theme={null}
bool RegisterDevice(std::unique_ptr<Device> device);
```

Registers a filesystem device at its configured mount point.

**Parameters:**

* `device` - Unique pointer to the device to register (ownership transferred)

**Returns:** `true` if registration succeeded, `false` otherwise.

**Example:**

```cpp theme={null}
auto device = std::make_unique<HostPathDevice>(
  "\\Device\\Harddisk0\\Partition1",
  "/path/to/game/files",
  true  // read_only
);
if (vfs->RegisterDevice(std::move(device))) {
  // Device registered successfully
}
```

***

### UnregisterDevice

```cpp theme={null}
bool UnregisterDevice(const std::string_view path);
```

Unregisters a previously registered device.

**Parameters:**

* `path` - Mount path of the device to unregister

**Returns:** `true` if unregistration succeeded, `false` if device not found.

## Symbolic Link Management

### RegisterSymbolicLink

```cpp theme={null}
bool RegisterSymbolicLink(const std::string_view path,
                          const std::string_view target);
```

Registers a symbolic link that redirects one path to another.

**Parameters:**

* `path` - Virtual path (e.g., `"game:"`, `"d:"`)
* `target` - Target device path (e.g., `"\\Device\\Harddisk0\\Partition1"`)

**Returns:** `true` if registration succeeded, `false` otherwise.

**Example:**

```cpp theme={null}
// Map game: to the main partition
vfs->RegisterSymbolicLink("game:", "\\Device\\Harddisk0\\Partition1");
vfs->RegisterSymbolicLink("d:", "\\Device\\Harddisk0\\Partition1");

// Map update: to the update partition
vfs->RegisterSymbolicLink("update:", "\\Device\\Harddisk0\\PartitionUpdate");
```

***

### UnregisterSymbolicLink

```cpp theme={null}
bool UnregisterSymbolicLink(const std::string_view path);
```

Unregisters a symbolic link.

**Parameters:**

* `path` - Virtual path to unregister

**Returns:** `true` if unregistration succeeded, `false` if link not found.

***

### FindSymbolicLink

```cpp theme={null}
bool FindSymbolicLink(const std::string_view path, std::string& target);
```

Looks up a symbolic link target.

**Parameters:**

* `path` - Virtual path to look up
* `target` - Output parameter receiving the target path

**Returns:** `true` if link found, `false` otherwise.

## Path Resolution

### ResolvePath

```cpp theme={null}
Entry* ResolvePath(const std::string_view path);
```

Resolves a virtual path to a filesystem entry.

This method:

1. Resolves any symbolic links in the path
2. Finds the appropriate mounted device
3. Returns the entry from the device

**Parameters:**

* `path` - Virtual path to resolve (e.g., `"game:/default.xex"`)

**Returns:** Pointer to the resolved `Entry`, or `nullptr` if not found.

**Example:**

```cpp theme={null}
Entry* entry = vfs->ResolvePath("game:/default.xex");
if (entry) {
  // Entry found, can open file
}
```

## File Operations

### CreatePath

```cpp theme={null}
Entry* CreatePath(const std::string_view path, uint32_t attributes);
```

Creates a new file or directory at the specified path.

**Parameters:**

* `path` - Virtual path where to create the entry
* `attributes` - File attributes (e.g., directory flag)

**Returns:** Pointer to the created `Entry`, or `nullptr` on failure.

***

### DeletePath

```cpp theme={null}
bool DeletePath(const std::string_view path);
```

Deletes a file or directory at the specified path.

**Parameters:**

* `path` - Virtual path to delete

**Returns:** `true` if deletion succeeded, `false` otherwise.

***

### OpenFile

```cpp theme={null}
X_STATUS OpenFile(Entry* root_entry,
                  const std::string_view path,
                  FileDisposition creation_disposition,
                  uint32_t desired_access,
                  bool is_directory,
                  bool is_non_directory,
                  File** out_file,
                  FileAction* out_action);
```

Opens a file through the VFS.

**Parameters:**

* `root_entry` - Root entry for relative path resolution (or `nullptr` for absolute)
* `path` - Path to the file
* `creation_disposition` - How to handle existing files (open, create, etc.)
* `desired_access` - Access flags (read, write, etc.)
* `is_directory` - Must be a directory
* `is_non_directory` - Must not be a directory
* `out_file` - Output parameter receiving the opened `File` pointer
* `out_action` - Output parameter receiving the action taken (opened, created, etc.)

**Returns:** `X_STATUS` result code.

## Runtime Integration

The VFS is set up during runtime initialization in `Runtime::SetupVfs()`:

```cpp theme={null}
bool Runtime::SetupVfs() {
  // Mount game_data_root as \Device\Harddisk0\Partition1
  auto device = std::make_unique<HostPathDevice>(
    "\\Device\\Harddisk0\\Partition1",
    game_data_root_,
    true  // read_only
  );
  file_system_->RegisterDevice(std::move(device));

  // Register symbolic links for game: and d:
  file_system_->RegisterSymbolicLink("game:", "\\Device\\Harddisk0\\Partition1");
  file_system_->RegisterSymbolicLink("d:", "\\Device\\Harddisk0\\Partition1");

  // Mount update_data_root as update: if provided
  if (!update_data_root_.empty()) {
    auto update_device = std::make_unique<HostPathDevice>(
      "\\Device\\Harddisk0\\PartitionUpdate",
      update_data_root_,
      true
    );
    file_system_->RegisterDevice(std::move(update_device));
    file_system_->RegisterSymbolicLink("update:", "\\Device\\Harddisk0\\PartitionUpdate");
  }

  // Register NullDevice for cache/raw partition access
  auto null_device = std::make_unique<NullDevice>(
    "\\Device\\Harddisk0",
    {"\\Partition0", "\\Cache0", "\\Cache1"}
  );
  file_system_->RegisterDevice(std::move(null_device));
}
```

**Source:** `runtime.cpp:224-287`

## Thread Safety

VirtualFileSystem uses internal locking (`global_critical_region_`) to ensure thread-safe access to device and symbolic link registries.

## See Also

* [Runtime](/api/runtime) - Access VFS through `Runtime::file_system()`
* [XexModule](/api/xex-module) - XEX module loading using VFS


# XexModule
Source: https://rexglue-rexglue-sdk.mintlify.app/api/xex-module

XEX (Xbox Executable) module loader and runtime representation

The `XexModule` class loads and manages Xbox 360 executable (XEX) files in the ReXGlue runtime. It handles XEX decompression, PE header parsing, import resolution, and provides access to module metadata.

## Class Definition

```cpp theme={null}
namespace rex::runtime {
  class XexModule : public Module;
}
```

**Header:** `<rex/system/xex_module.h>`

## Overview

XexModule represents a loaded XEX executable in guest memory. It:

* **Loads XEX files** - Decompresses and loads XEX1/XEX2 format executables
* **Parses PE headers** - Extracts section information and exports
* **Resolves imports** - Links against kernel modules (xboxkrnl.xex, xam.xex)
* **Provides metadata** - Exposes execution info, security info, and optional headers

## Types

### XexFormat

```cpp theme={null}
enum XexFormat {
  kFormatUnknown,
  kFormatXex1,
  kFormatXex2
};
```

Identifies the XEX file format version.

***

### ImportLibrary

```cpp theme={null}
struct ImportLibrary {
  std::string name;
  uint32_t id;
  xe_xex2_version_t version;
  xe_xex2_version_t min_version;
  std::vector<ImportLibraryFn> imports;
};
```

Represents an imported library (e.g., "xboxkrnl.exe", "xam.xex").

**Fields:**

* `name` - Library name
* `id` - Library identifier
* `version` - Required library version
* `min_version` - Minimum compatible version
* `imports` - List of imported functions

***

### ImportLibraryFn

```cpp theme={null}
struct ImportLibraryFn {
  uint32_t ordinal = 0;
  uint32_t value_address = 0;
  uint32_t thunk_address = 0;
};
```

Represents a single imported function.

**Fields:**

* `ordinal` - Function ordinal in the import library
* `value_address` - Guest address where function pointer is stored
* `thunk_address` - Import thunk address

***

### SecurityInfoContext

```cpp theme={null}
struct SecurityInfoContext {
  const char* rsa_signature;
  const char* aes_key;
  uint32_t image_size;
  uint32_t image_flags;
  uint32_t export_table;
  uint32_t load_address;
  uint32_t page_descriptor_count;
  const xex2_page_descriptor* page_descriptors;
};
```

Extracted XEX security and layout information.

## Constructor & Destructor

### XexModule

```cpp theme={null}
XexModule(Processor* processor, system::KernelState* kernel_state);
```

Constructs a new XEX module loader.

**Parameters:**

* `processor` - Processor instance for code execution
* `kernel_state` - Kernel state for object management

***

### \~XexModule

```cpp theme={null}
virtual ~XexModule();
```

Destructs the module and releases allocated memory.

## Loading

### Load

```cpp theme={null}
bool Load(const std::string_view name,
          const std::string_view path,
          const void* xex_addr,
          size_t xex_length);
```

Loads a XEX module from memory.

This method:

1. Validates the XEX signature (XEX1/XEX2)
2. Reads and decrypts the XEX headers
3. Decompresses the executable image (if compressed)
4. Loads the PE image into guest memory

**Parameters:**

* `name` - Module name (e.g., "default.xex")
* `path` - Full virtual path to the module
* `xex_addr` - Pointer to XEX file data in host memory
* `xex_length` - Size of XEX file in bytes

**Returns:** `true` if load succeeded, `false` on error.

**Example:**

```cpp theme={null}
// Read XEX from file
std::vector<uint8_t> xex_data = ReadFile("game:/default.xex");

XexModule module(processor, kernel_state);
if (module.Load("default.xex", "game:/default.xex",
                xex_data.data(), xex_data.size())) {
  // XEX loaded successfully
}
```

***

### LoadContinue

```cpp theme={null}
bool LoadContinue();
```

Completes the loading process after `Load()` has succeeded.

This method:

1. Parses PE headers and sections
2. Resolves import libraries
3. Populates binary symbols for debugging

**Returns:** `true` if completion succeeded, `false` on error.

**Note:** Call `Load()` first, then `LoadContinue()` to finish initialization.

***

### Unload

```cpp theme={null}
bool Unload();
```

Unloads the module and releases guest memory.

**Returns:** `true` if unload succeeded, `false` on error.

## Module Properties

### loaded

```cpp theme={null}
bool loaded() const;
```

Returns `true` if the module has been loaded into memory.

***

### name

```cpp theme={null}
const std::string& name() const override;
```

Returns the module name.

***

### base\_address

```cpp theme={null}
uint32_t base_address() const override;
```

Returns the base address where the module is loaded in guest memory.

***

### image\_size

```cpp theme={null}
uint32_t image_size() const override;
```

Returns the total size of the loaded module image in bytes.

Calculates size from XEX page descriptors:

```cpp theme={null}
uint32_t total_size = 0;
for (uint32_t i = 0; i < xex_security_info()->page_descriptor_count; i++) {
  xex2_page_descriptor desc;
  desc.value = byte_swap(xex_security_info()->page_descriptors[i].value);
  total_size += desc.page_count * heap->page_size();
}
```

**Source:** `xex_module.h:72-86`

***

### entry\_point

```cpp theme={null}
uint32_t entry_point() const override;
```

Returns the guest address of the module's entry point.

***

### is\_executable

```cpp theme={null}
bool is_executable() const override;
```

Returns `true` if this is a title executable (has `XEX_MODULE_TITLE` flag).

***

### is\_patch

```cpp theme={null}
bool is_patch() const;
```

Returns `true` if this is a patch module (title update).

***

### is\_dev\_kit

```cpp theme={null}
bool is_dev_kit() const;
```

Returns `true` if the XEX was signed with a development key.

## XEX Headers

### xex\_header

```cpp theme={null}
const xex2_header* xex_header() const;
```

Returns pointer to the XEX header structure.

***

### xex\_security\_info

```cpp theme={null}
const SecurityInfoContext* xex_security_info() const;
```

Returns pointer to the extracted security information.

***

### GetOptHeader

```cpp theme={null}
template <typename T>
bool GetOptHeader(xex2_header_keys key, T* out_ptr) const;
```

Retrieves an optional XEX header by key.

**Parameters:**

* `key` - Header key (e.g., `XEX_HEADER_EXECUTION_INFO`)
* `out_ptr` - Output parameter receiving header pointer (or value for inline headers)

**Returns:** `true` if header exists, `false` otherwise.

**Example:**

```cpp theme={null}
const xex2_opt_execution_info* exec_info = nullptr;
if (module.GetOptHeader(XEX_HEADER_EXECUTION_INFO, &exec_info)) {
  uint32_t media_id = exec_info->media_id;
  uint32_t title_id = exec_info->title_id;
}
```

***

### opt\_execution\_info

```cpp theme={null}
const xex2_opt_execution_info* opt_execution_info() const;
```

Returns execution info header (title ID, media ID, region, etc.).

***

### opt\_file\_format\_info

```cpp theme={null}
const xex2_opt_file_format_info* opt_file_format_info() const;
```

Returns file format info header (compression type, encryption, etc.).

***

### opt\_alternate\_title\_ids

```cpp theme={null}
std::vector<uint32_t> opt_alternate_title_ids() const;
```

Returns list of alternate title IDs (for DLC compatibility).

## Import Resolution

### import\_libraries

```cpp theme={null}
const std::vector<ImportLibrary>* import_libraries() const;
```

Returns the list of imported libraries with their function imports.

**Example:**

```cpp theme={null}
for (const auto& lib : *module.import_libraries()) {
  printf("Import library: %s\n", lib.name.c_str());
  for (const auto& fn : lib.imports) {
    printf("  Ordinal %u at 0x%08X\n", fn.ordinal, fn.value_address);
  }
}
```

## PE Sections

### pe\_sections

```cpp theme={null}
const std::vector<PESection>& pe_sections() const;
```

Returns the list of PE sections (`.text`, `.data`, `.rdata`, etc.).

***

### GetPESection

```cpp theme={null}
const PESection* GetPESection(const char* name);
```

Finds a PE section by name.

**Parameters:**

* `name` - Section name (e.g., ".text")

**Returns:** Pointer to `PESection`, or `nullptr` if not found.

## Export Resolution

### export\_table\_address

```cpp theme={null}
uint32_t export_table_address() const override;
```

Returns the guest address of the export table.

***

### GetProcAddress (by ordinal)

```cpp theme={null}
uint32_t GetProcAddress(uint16_t ordinal) const;
```

Resolves an exported function by ordinal.

**Parameters:**

* `ordinal` - Function ordinal

**Returns:** Guest address of the function, or `0` if not found.

***

### GetProcAddress (by name)

```cpp theme={null}
uint32_t GetProcAddress(const std::string_view name) const;
```

Resolves an exported function by name.

**Parameters:**

* `name` - Function name

**Returns:** Guest address of the function, or `0` if not found.

## Exception Handling

### exception\_directory\_rva

```cpp theme={null}
uint32_t exception_directory_rva() const override;
```

Returns the RVA of the exception directory (PDATA table).

***

### exception\_directory\_size

```cpp theme={null}
uint32_t exception_directory_size() const override;
```

Returns the size of the exception directory in bytes.

***

### exception\_directory\_address

```cpp theme={null}
uint32_t exception_directory_address() const override;
```

Returns the guest address of the exception directory.

## Binary Introspection

### binary\_sections

```cpp theme={null}
std::span<const BinarySection> binary_sections() const override;
```

Returns all binary sections for debugging and analysis.

***

### FindSectionByName

```cpp theme={null}
const BinarySection* FindSectionByName(std::string_view name) const override;
```

Finds a binary section by name.

***

### binary\_symbols

```cpp theme={null}
std::span<const BinarySymbol> binary_symbols() const override;
```

Returns all binary symbols (functions, data) for debugging.

***

### ContainsAddress

```cpp theme={null}
bool ContainsAddress(uint32_t address) override;
```

Checks if a guest address belongs to this module.

**Parameters:**

* `address` - Guest virtual address

**Returns:** `true` if address is within module bounds.

## XEX Format Constants

```cpp theme={null}
constexpr memory::fourcc_t kXEX1Signature = memory::make_fourcc("XEX1");
constexpr memory::fourcc_t kXEX2Signature = memory::make_fourcc("XEX2");
constexpr memory::fourcc_t kElfSignature = memory::make_fourcc(0x7F, 'E', 'L', 'F');
```

**Source:** `xex_module.h:25-27`

## Usage Example

```cpp theme={null}
// Load and launch a XEX executable
Runtime runtime("/path/to/game");
runtime.Setup();

// Load the XEX image
X_STATUS status = runtime.LoadXexImage("game:/default.xex");
if (XSUCCEEDED(status)) {
  // Launch the module's main thread
  auto thread = runtime.LaunchModule();
  
  // Access module information
  auto module = runtime.kernel_state()->GetExecutableModule();
  printf("Entry point: 0x%08X\n", module->entry_point());
  printf("Base address: 0x%08X\n", module->base_address());
  printf("Image size: 0x%08X\n", module->image_size());
}
```

## See Also

* [Runtime](/api/runtime) - Load XEX modules through `Runtime::LoadXexImage()`
* [Module](/api/module) - Base class for all module types
* [UserModule](/api/user-module) - User-space module wrapper


# Custom Hooks
Source: https://rexglue-rexglue-sdk.mintlify.app/app/custom-hooks

Customizing application behavior with virtual hooks

ReXApp provides virtual hook methods that allow you to customize application behavior without modifying framework code. Override these methods in your subclass to inject custom logic at specific points in the application lifecycle.

## Available Hooks

All hooks are defined in `rex/rex_app.h:88-103`.

### OnPreSetup

```cpp theme={null}
virtual void OnPreSetup(RuntimeConfig& config)
```

Called before `Runtime::Setup()`. This is your opportunity to configure backend injection.

**Typical uses:**

* Set graphics backend (Vulkan, OpenGL)
* Set audio backend (SDL, custom)
* Set input backend (SDL, custom)
* Enable tool mode

**Example:**

```cpp theme={null}
void OnPreSetup(RuntimeConfig& config) override {
  // Inject Vulkan graphics
  config.graphics = REX_GRAPHICS_BACKEND(
      rex::graphics::vulkan::VulkanGraphicsSystem);
  
  // Inject SDL backends
  config.audio_factory = REX_AUDIO_BACKEND(
      rex::audio::sdl::SDLAudioSystem);
  config.input_factory = REX_INPUT_BACKEND(
      rex::input::sdl::SetupSDLInput);
}
```

See `rex/rex_app.h:90`

### OnPostSetup

```cpp theme={null}
virtual void OnPostSetup()
```

Called after Runtime is fully initialized, before window creation.

**Typical uses:**

* Query subsystem state
* Configure kernel objects
* Set up custom memory regions
* Initialize game-specific systems

**Example:**

```cpp theme={null}
void OnPostSetup() override {
  // Access runtime subsystems
  auto* kernel = runtime()->kernel_state();
  auto* vfs = runtime()->file_system();
  
  // Check if game data is valid
  if (!vfs->ResolvePath("game:/default.xex")) {
    REXLOG_ERROR("Failed to find game executable");
  }
  
  // Initialize custom logging
  REXLOG_INFO("Game data root: {}", game_data_root().string());
}
```

See `rex/rex_app.h:93`

### OnConfigurePaths

```cpp theme={null}
virtual void OnConfigurePaths(PathConfig& paths)
```

Called after path defaults are computed from CLI args, before Runtime is constructed.

**Typical uses:**

* Override default paths programmatically
* Apply platform-specific path logic
* Validate or create directories

**Example:**

```cpp theme={null}
void OnConfigurePaths(PathConfig& paths) override {
  // Use XDG_DATA_HOME on Linux
#ifdef __linux__
  const char* xdg_data = std::getenv("XDG_DATA_HOME");
  if (xdg_data) {
    paths.user_data_root = std::filesystem::path(xdg_data) / "my_game";
  }
#endif
  
  // Ensure user data directory exists
  std::filesystem::create_directories(paths.user_data_root);
  
  REXLOG_INFO("User data: {}", paths.user_data_root.string());
}
```

See `rex/rex_app.h:102-103`

### OnCreateDialogs

```cpp theme={null}
virtual void OnCreateDialogs(ui::ImGuiDrawer* drawer)
```

Called after ImGui drawer is created. Add custom dialogs and UI here.

**Typical uses:**

* Register custom debug overlays
* Add game-specific UI panels
* Create settings dialogs

**Example:**

```cpp theme={null}
class MyGameApp : public rex::ReXApp {
 protected:
  void OnCreateDialogs(ui::ImGuiDrawer* drawer) override {
    // Add custom debug panel
    auto* stats_dialog = new GameStatsDialog(drawer);
    drawer->AddDialog(stats_dialog);
    
    // Add custom settings
    auto* settings = new GraphicsSettingsDialog(drawer);
    drawer->AddDialog(settings);
  }
  
 private:
  class GameStatsDialog : public rex::ui::ImGuiDialog {
   public:
    using ImGuiDialog::ImGuiDialog;
   protected:
    void OnDraw(ImGuiIO& io) override {
      ImGui::Begin("Game Stats");
      ImGui::Text("FPS: %.1f", io.Framerate);
      // ... custom stats
      ImGui::End();
    }
  };
};
```

See `rex/rex_app.h:96`

### OnShutdown

```cpp theme={null}
virtual void OnShutdown()
```

Called before cleanup begins. Release custom resources here.

**Typical uses:**

* Save user data or settings
* Release custom subsystems
* Flush logs
* Clean up background threads

**Example:**

```cpp theme={null}
class MyGameApp : public rex::ReXApp {
 protected:
  void OnShutdown() override {
    // Save user preferences
    SaveUserSettings(user_data_root() / "settings.json");
    
    // Stop background tasks
    if (background_thread_.joinable()) {
      stop_flag_.store(true);
      background_thread_.join();
    }
    
    REXLOG_INFO("Application shutdown complete");
  }
  
 private:
  std::thread background_thread_;
  std::atomic<bool> stop_flag_{false};
};
```

See `rex/rex_app.h:99`

## Hook Execution Order

Hooks are called in this sequence during application startup:

<Steps>
  <Step title="OnConfigurePaths">
    Customize filesystem paths before Runtime construction.
  </Step>

  <Step title="Runtime Construction">
    Runtime is created with configured paths.
  </Step>

  <Step title="OnPreSetup">
    Configure backend injection (graphics, audio, input).
  </Step>

  <Step title="Runtime::Setup">
    All subsystems are initialized with injected backends.
  </Step>

  <Step title="OnPostSetup">
    Runtime is ready, window not yet created.
  </Step>

  <Step title="Window & ImGui Creation">
    Window and ImGui drawer are created.
  </Step>

  <Step title="OnCreateDialogs">
    Add custom UI dialogs.
  </Step>

  <Step title="Module Launch">
    PPC module starts executing on background thread.
  </Step>
</Steps>

During shutdown:

<Steps>
  <Step title="OnShutdown">
    Release custom resources before framework cleanup.
  </Step>

  <Step title="Framework Cleanup">
    ReXApp destroys Runtime, window, and UI systems.
  </Step>
</Steps>

## Complete Example

Here's a full example using all hooks:

```cpp theme={null}
#include "generated/my_game_config.h"
#include "generated/my_game_init.h"
#include <rex/rex_app.h>
#include <fstream>

class MyGameApp : public rex::ReXApp {
 public:
  using rex::ReXApp::ReXApp;

  static std::unique_ptr<rex::ui::WindowedApp> Create(
      rex::ui::WindowedAppContext& ctx) {
    return std::unique_ptr<MyGameApp>(new MyGameApp(ctx, "my_game",
        {PPC_CODE_BASE, PPC_CODE_SIZE, PPC_IMAGE_BASE,
         PPC_IMAGE_SIZE, PPCFuncMappings}));
  }

 protected:
  // 1. Configure paths first
  void OnConfigurePaths(PathConfig& paths) override {
    // Use platform-specific user data location
    auto home = std::filesystem::path(std::getenv("HOME"));
    paths.user_data_root = home / ".local" / "share" / "my_game";
    std::filesystem::create_directories(paths.user_data_root);
  }
  
  // 2. Inject backends before Runtime setup
  void OnPreSetup(RuntimeConfig& config) override {
    config.graphics = REX_GRAPHICS_BACKEND(
        rex::graphics::vulkan::VulkanGraphicsSystem);
    config.audio_factory = REX_AUDIO_BACKEND(
        rex::audio::sdl::SDLAudioSystem);
    config.input_factory = REX_INPUT_BACKEND(
        rex::input::sdl::SetupSDLInput);
    
    REXLOG_INFO("Backends configured");
  }
  
  // 3. Post-setup validation
  void OnPostSetup() override {
    // Verify game data
    auto* vfs = runtime()->file_system();
    if (!vfs->ResolvePath("game:/default.xex")) {
      REXLOG_ERROR("Game executable not found!");
    }
    
    // Load user settings
    LoadUserSettings();
  }
  
  // 4. Add custom UI
  void OnCreateDialogs(ui::ImGuiDrawer* drawer) override {
    drawer->AddDialog(new GameStatsDialog(drawer));
  }
  
  // 5. Clean shutdown
  void OnShutdown() override {
    SaveUserSettings();
    REXLOG_INFO("Saved user settings");
  }

 private:
  void LoadUserSettings() {
    auto settings_path = user_data_root() / "settings.json";
    if (std::filesystem::exists(settings_path)) {
      // Load settings...
      REXLOG_INFO("Loaded settings from {}", settings_path.string());
    }
  }
  
  void SaveUserSettings() {
    auto settings_path = user_data_root() / "settings.json";
    // Save settings...
  }
  
  class GameStatsDialog : public rex::ui::ImGuiDialog {
   public:
    using ImGuiDialog::ImGuiDialog;
   protected:
    void OnDraw(ImGuiIO& io) override {
      ImGui::Begin("Game Stats");
      ImGui::Text("FPS: %.1f", io.Framerate);
      ImGui::End();
    }
  };
};

REX_DEFINE_APP(my_game, MyGameApp::Create)
```

## Best Practices

### Do

* Override only the hooks you need
* Call base class implementation if you override and want default behavior
* Use REXLOG macros for debugging hook execution
* Keep hooks focused and minimal
* Use `OnPreSetup` for all backend configuration
* Use `OnPostSetup` to validate runtime state
* Use `OnShutdown` to save user data

### Don't

* Don't perform long-running operations in hooks (blocks startup)
* Don't access runtime() before OnPostSetup
* Don't access window() or imgui\_drawer() before OnCreateDialogs
* Don't spawn threads in OnPreSetup (runtime not ready)
* Don't forget to clean up resources created in hooks

## Thread Safety

Hooks are called on the main thread during initialization. The PPC module thread starts after all hooks complete. If you spawn additional threads in hooks, ensure proper synchronization:

```cpp theme={null}
class MyGameApp : public rex::ReXApp {
 protected:
  void OnPostSetup() override {
    // Safe - main thread, no PPC thread yet
    worker_thread_ = std::thread([this]() {
      // Background work
      // Use atomics/mutexes for shared state
    });
  }
  
  void OnShutdown() override {
    // Stop worker before shutdown
    if (worker_thread_.joinable()) {
      stop_flag_.store(true);
      worker_thread_.join();
    }
  }
  
 private:
  std::thread worker_thread_;
  std::atomic<bool> stop_flag_{false};
};
```

## Next Steps

<CardGroup>
  <Card title="ReXApp Base Class" icon="code" href="/app/rexapp">
    Learn about the application framework
  </Card>

  <Card title="Runtime Setup" icon="gear" href="/app/runtime-setup">
    Configure backend systems
  </Card>

  <Card title="UI Integration" icon="window" href="/app/ui-integration">
    Add custom ImGui dialogs
  </Card>
</CardGroup>


# ReXApp Base Class
Source: https://rexglue-rexglue-sdk.mintlify.app/app/rexapp

Base class for recompiled Xbox 360 applications

The `ReXApp` class is the foundation for building recompiled Xbox 360 applications with ReXGlue. It handles all boilerplate setup including runtime initialization, window creation, ImGui integration, module launch, and shutdown.

## Overview

`ReXApp` provides a complete application framework that:

* Initializes the Runtime subsystem with configurable backends
* Creates and manages the application window
* Sets up ImGui for debug overlays and UI
* Launches the recompiled PPC module on a background thread
* Provides virtual hooks for customization without modifying framework code

## Class Declaration

Defined in `rex/rex_app.h`:

```cpp theme={null}
class ReXApp : public ui::WindowedApp, 
               public ui::WindowListener, 
               public ui::WindowInputListener
```

## Basic Usage

The typical pattern is to subclass `ReXApp` in your `main.cpp`:

```cpp theme={null}
#include "generated/my_game_config.h"
#include "generated/my_game_init.h"
#include <rex/rex_app.h>

class MyGameApp : public rex::ReXApp {
 public:
  using rex::ReXApp::ReXApp;

  static std::unique_ptr<rex::ui::WindowedApp> Create(
      rex::ui::WindowedAppContext& ctx) {
    return std::unique_ptr<MyGameApp>(new MyGameApp(ctx, "my_game",
        {PPC_CODE_BASE, PPC_CODE_SIZE, PPC_IMAGE_BASE,
         PPC_IMAGE_SIZE, PPCFuncMappings}));
  }
};

REX_DEFINE_APP(my_game, MyGameApp::Create)
```

This minimal implementation inherits all default behavior. Customize by overriding virtual hooks.

## Constructor

```cpp theme={null}
protected:
ReXApp(ui::WindowedAppContext& ctx, 
       std::string_view name, 
       PPCImageInfo ppc_info,
       std::string_view usage = "[game_directory]");
```

### Parameters

* **ctx**: Window system context from the platform entry point
* **name**: Application name (used for window title, logging)
* **ppc\_info**: PPC image layout from generated config header
* **usage**: Optional command-line usage string

### PPCImageInfo Structure

```cpp theme={null}
struct PPCImageInfo {
  uint32_t code_base;      // PPC code section base address
  uint32_t code_size;      // PPC code section size
  uint32_t image_base;     // Full image base address
  uint32_t image_size;     // Full image size
  const PPCFuncMapping* func_mappings;  // Function dispatch table
};
```

These values come from the generated config header created by `rexglue codegen`.

## Virtual Hooks

See [Custom Hooks](/app/custom-hooks) for detailed documentation of all customization points.

## Protected Accessors

Subclasses can access framework objects through protected methods:

### Runtime Access

```cpp theme={null}
Runtime* runtime() const
```

Access the Runtime instance for subsystem queries:

```cpp theme={null}
void OnPostSetup() override {
  auto* graphics = runtime()->graphics_system();
  auto* kernel = runtime()->kernel_state();
}
```

See `rex/rex_app.h:106`

### Window Access

```cpp theme={null}
ui::Window* window() const
```

Access the application window for input, sizing, etc.

See `rex/rex_app.h:107`

### ImGui Drawer Access

```cpp theme={null}
ui::ImGuiDrawer* imgui_drawer() const
```

Access the ImGui drawer to add custom dialogs:

```cpp theme={null}
void OnCreateDialogs(ui::ImGuiDrawer* drawer) override {
  drawer->AddDialog(new MyCustomDialog(drawer));
}
```

See `rex/rex_app.h:108`

### Path Configuration

```cpp theme={null}
const std::filesystem::path& game_data_root() const
const std::filesystem::path& user_data_root() const
const std::filesystem::path& update_data_root() const
```

Access configured data paths. These are set during initialization and can be customized via `OnConfigurePaths()`.

See `rex/rex_app.h:110-112`

## Initialization Sequence

Understanding the initialization order helps you choose the right hook:

<Steps>
  <Step title="Path Configuration">
    Default paths are computed from CLI args and cvars. `OnConfigurePaths()` is called to allow customization.
  </Step>

  <Step title="Runtime Construction">
    Runtime is constructed with the configured paths.
  </Step>

  <Step title="Pre-Setup Hook">
    `OnPreSetup()` is called. This is your chance to configure backend injection before Runtime::Setup().
  </Step>

  <Step title="Runtime Setup">
    `Runtime::Setup()` initializes all subsystems (memory, VFS, kernel, graphics, audio, input).
  </Step>

  <Step title="Post-Setup Hook">
    `OnPostSetup()` is called. Runtime is fully initialized, window not yet created.
  </Step>

  <Step title="Window Creation">
    Application window is created and shown.
  </Step>

  <Step title="ImGui Initialization">
    ImGui drawer is created and default dialogs (console, debug overlay) are registered.
  </Step>

  <Step title="Custom Dialogs Hook">
    `OnCreateDialogs()` is called to add application-specific UI.
  </Step>

  <Step title="Module Launch">
    PPC module is launched on a background thread. Game code begins executing.
  </Step>
</Steps>

## Shutdown Sequence

When the application closes:

<Steps>
  <Step title="Shutdown Initiated">
    User closes window or game code calls exit.
  </Step>

  <Step title="Custom Shutdown Hook">
    `OnShutdown()` is called. Release custom resources here.
  </Step>

  <Step title="Module Thread Join">
    Background thread running PPC code is joined.
  </Step>

  <Step title="Runtime Cleanup">
    Runtime subsystems are shut down in reverse order.
  </Step>

  <Step title="Window Destruction">
    Window and UI resources are released.
  </Step>
</Steps>

## Built-in Features

ReXApp provides these features out of the box:

### Debug Overlays

* **Console**: Press `` ` `` (backtick) to toggle log console
* **Debug Overlay**: Performance stats and system info
* **Settings**: Runtime configuration UI

### Command-Line Processing

ReXApp processes standard command-line arguments:

```bash theme={null}
./my_game /path/to/game/data
```

The first positional argument sets `game_data_root`.

### Logging Integration

All log output is captured and displayed in the console overlay. Use ReXGlue's logging macros:

```cpp theme={null}
REXLOG_INFO("Initializing custom system");
REXLOG_WARN("Resource not found: {}", path);
REXLOG_ERROR("Failed to load: {}", filename);
```

## Thread Safety

The PPC module runs on a background thread. ImGui callbacks run on the main thread. Use appropriate synchronization when sharing state:

```cpp theme={null}
class MyApp : public rex::ReXApp {
  std::atomic<int> frame_count_{0};
  
  void OnCreateDialogs(ui::ImGuiDrawer* drawer) override {
    // Called on main thread - safe to add dialogs
  }
};
```

## Next Steps

<CardGroup>
  <Card title="Runtime Setup" icon="gear" href="/app/runtime-setup">
    Configure backend systems (graphics, audio, input)
  </Card>

  <Card title="Custom Hooks" icon="hook" href="/app/custom-hooks">
    Customize application behavior with virtual hooks
  </Card>

  <Card title="UI Integration" icon="window" href="/app/ui-integration">
    Add custom ImGui dialogs and overlays
  </Card>
</CardGroup>


# Runtime Setup
Source: https://rexglue-rexglue-sdk.mintlify.app/app/runtime-setup

Configuring Runtime with backend systems

The `Runtime` class is the core subsystem coordinator for recompiled applications. It manages memory, file system, kernel state, and hardware interfaces (graphics, audio, input). Backend systems are injected via `RuntimeConfig` to keep the runtime library decoupled from concrete implementations.

## RuntimeConfig Structure

Defined in `rex/runtime.h:53-58`:

```cpp theme={null}
struct RuntimeConfig {
  std::unique_ptr<system::IGraphicsSystem> graphics;
  std::function<std::unique_ptr<system::IAudioSystem>(runtime::Processor*)> audio_factory;
  std::function<std::unique_ptr<system::IInputSystem>(bool tool_mode)> input_factory;
  bool tool_mode = false;
};
```

### Fields

* **graphics**: Graphics backend instance (Vulkan, OpenGL, etc.)
* **audio\_factory**: Factory function for audio backend (requires Processor at construction)
* **input\_factory**: Factory function for input backend (depends on tool\_mode)
* **tool\_mode**: If true, skips GPU initialization for analysis tools

## Backend Injection

Backends are configured in the `OnPreSetup()` hook before `Runtime::Setup()` is called.

### Basic Configuration

```cpp theme={null}
class MyGameApp : public rex::ReXApp {
 protected:
  void OnPreSetup(RuntimeConfig& config) override {
    // Inject Vulkan graphics backend
    config.graphics = REX_GRAPHICS_BACKEND(
        rex::graphics::vulkan::VulkanGraphicsSystem);
    
    // Inject SDL audio backend
    config.audio_factory = REX_AUDIO_BACKEND(
        rex::audio::sdl::SDLAudioSystem);
    
    // Inject SDL input backend
    config.input_factory = REX_INPUT_BACKEND(
        rex::input::sdl::SetupSDLInput);
  }
};
```

See `rex/runtime.h:65-73` for helper macro definitions.

## Helper Macros

ReXGlue provides convenience macros to reduce boilerplate:

### REX\_GRAPHICS\_BACKEND

```cpp theme={null}
#define REX_GRAPHICS_BACKEND(Type) std::make_unique<Type>()
```

Expands to construct the graphics system directly:

```cpp theme={null}
config.graphics = std::make_unique<rex::graphics::vulkan::VulkanGraphicsSystem>();
```

See `rex/runtime.h:65`

### REX\_AUDIO\_BACKEND

```cpp theme={null}
#define REX_AUDIO_BACKEND(Type) \
  [](::rex::runtime::Processor* _proc) -> std::unique_ptr<::rex::system::IAudioSystem> { \
    return Type::Create(_proc); \
  }
```

Creates a lambda that captures the Processor pointer:

```cpp theme={null}
config.audio_factory = [](rex::runtime::Processor* proc) {
  return rex::audio::sdl::SDLAudioSystem::Create(proc);
};
```

See `rex/runtime.h:66-69`

### REX\_INPUT\_BACKEND

```cpp theme={null}
#define REX_INPUT_BACKEND(SetupFunc) \
  [](bool _tool_mode) -> std::unique_ptr<::rex::system::IInputSystem> { \
    return SetupFunc(_tool_mode); \
  }
```

Wraps a setup function that takes tool\_mode:

```cpp theme={null}
config.input_factory = [](bool tool_mode) {
  return rex::input::sdl::SetupSDLInput(tool_mode);
};
```

See `rex/runtime.h:70-73`

## Backend Interfaces

All backends implement abstract interfaces defined in `rex/system/interfaces/`.

### IGraphicsSystem

```cpp theme={null}
class IGraphicsSystem {
 public:
  virtual ~IGraphicsSystem() = default;
  virtual X_STATUS Setup(runtime::Processor* processor, 
                         KernelState* kernel_state,
                         ui::WindowedAppContext* app_context, 
                         bool with_presentation) = 0;
  virtual void Shutdown() = 0;
};
```

See `rex/system/interfaces/graphics.h:29-35`

### IAudioSystem

```cpp theme={null}
class IAudioSystem {
 public:
  virtual ~IAudioSystem() = default;
  virtual X_STATUS Setup(KernelState* kernel_state) = 0;
  virtual void Shutdown() = 0;
};
```

See `rex/system/interfaces/audio.h:22-27`

### IInputSystem

```cpp theme={null}
class IInputSystem {
 public:
  virtual ~IInputSystem() = default;
  virtual X_STATUS Setup() = 0;
  virtual void Shutdown() = 0;
};
```

See `rex/system/interfaces/input.h:18-23`

## Available Backends

ReXGlue SDK includes these backend implementations:

### Graphics Backends

| Backend | Class                                         | Description                          |
| ------- | --------------------------------------------- | ------------------------------------ |
| Vulkan  | `rex::graphics::vulkan::VulkanGraphicsSystem` | Modern Vulkan renderer (recommended) |
| OpenGL  | `rex::graphics::gl::GLGraphicsSystem`         | Legacy OpenGL 4.5+ renderer          |

### Audio Backends

| Backend | Class                               | Description               |
| ------- | ----------------------------------- | ------------------------- |
| SDL     | `rex::audio::sdl::SDLAudioSystem`   | Cross-platform SDL2 audio |
| Null    | `rex::audio::null::NullAudioSystem` | Silent audio (testing)    |

### Input Backends

| Backend | Function                           | Description               |
| ------- | ---------------------------------- | ------------------------- |
| SDL     | `rex::input::sdl::SetupSDLInput`   | Cross-platform SDL2 input |
| Null    | `rex::input::null::SetupNullInput` | No-op input (testing)     |

## Tool Mode

Setting `config.tool_mode = true` disables graphics initialization for headless analysis tools:

```cpp theme={null}
void OnPreSetup(RuntimeConfig& config) override {
  config.tool_mode = true;  // Skip GPU init
  config.graphics = nullptr;  // No graphics
  config.audio_factory = REX_AUDIO_BACKEND(rex::audio::null::NullAudioSystem);
  config.input_factory = REX_INPUT_BACKEND(rex::input::null::SetupNullInput);
}
```

Useful for:

* Static analysis tools
* Headless servers
* Automated testing
* CI/CD environments

## Runtime Construction

The Runtime is constructed with filesystem paths:

```cpp theme={null}
Runtime::Runtime(
    const std::filesystem::path& game_data_root,
    const std::filesystem::path& user_data_root = {},
    const std::filesystem::path& update_data_root = {})
```

See `rex/runtime.h:85-87`

### Path Configuration

Paths are configured via the `OnConfigurePaths()` hook before Runtime construction:

```cpp theme={null}
void OnConfigurePaths(PathConfig& paths) override {
  // Defaults are already set from CLI args
  // Override if needed:
  paths.game_data_root = "/opt/my_game/data";
  paths.user_data_root = std::filesystem::path(std::getenv("HOME")) / ".my_game";
}
```

### PathConfig Structure

```cpp theme={null}
struct PathConfig {
  std::filesystem::path game_data_root;    // Game assets (read-only)
  std::filesystem::path user_data_root;    // Save files, configs
  std::filesystem::path update_data_root;  // Patches, DLC
};
```

See `rex/rex_app.h:47-51`

## Runtime Setup Process

After configuration, `Runtime::Setup()` initializes subsystems in order:

<Steps>
  <Step title="Memory Initialization">
    Virtual address space is allocated for PPC guest code and data.
  </Step>

  <Step title="Processor Setup">
    PPC processor state and IRQL synchronization primitives.
  </Step>

  <Step title="Virtual File System">
    VFS mounts:

    * `game:` → game\_data\_root
    * `d:` → game\_data\_root (alias)
    * `update:` → update\_data\_root
  </Step>

  <Step title="Export Resolver">
    Import resolution for guest code variable access.
  </Step>

  <Step title="Kernel State">
    Kernel objects, threading subsystem, synchronization primitives.
  </Step>

  <Step title="Graphics System">
    Graphics backend Setup() is called (if provided and not tool\_mode).
  </Step>

  <Step title="Audio System">
    Audio factory is invoked with Processor\*, backend Setup() is called.
  </Step>

  <Step title="Input System">
    Input factory is invoked with tool\_mode flag, backend Setup() is called.
  </Step>
</Steps>

## Runtime Accessors

Access subsystems through Runtime methods:

```cpp theme={null}
void OnPostSetup() override {
  Runtime* rt = runtime();
  
  // Subsystems
  auto* memory = rt->memory();
  auto* vfs = rt->file_system();
  auto* kernel = rt->kernel_state();
  auto* graphics = rt->graphics_system();
  auto* audio = rt->audio_system();
  auto* input = rt->input_system();
  
  // Processor and export resolver
  auto* processor = rt->processor();
  auto* exports = rt->export_resolver();
  
  // Paths
  const auto& game_root = rt->game_data_root();
  const auto& user_root = rt->user_data_root();
}
```

See `rex/runtime.h:98-113`

## Advanced: Custom Backends

You can implement custom backends by inheriting the interface classes:

```cpp theme={null}
namespace my_game {

class CustomAudioSystem : public rex::system::IAudioSystem {
 public:
  static std::unique_ptr<IAudioSystem> Create(rex::runtime::Processor* proc) {
    return std::make_unique<CustomAudioSystem>(proc);
  }
  
  X_STATUS Setup(rex::system::KernelState* kernel) override {
    // Your audio setup
    return X_STATUS_SUCCESS;
  }
  
  void Shutdown() override {
    // Cleanup
  }
  
 private:
  CustomAudioSystem(rex::runtime::Processor* proc) : processor_(proc) {}
  rex::runtime::Processor* processor_;
};

}  // namespace my_game
```

Then inject it:

```cpp theme={null}
void OnPreSetup(RuntimeConfig& config) override {
  config.audio_factory = REX_AUDIO_BACKEND(my_game::CustomAudioSystem);
}
```

## Next Steps

<CardGroup>
  <Card title="ReXApp Base Class" icon="code" href="/app/rexapp">
    Learn about the application framework
  </Card>

  <Card title="Custom Hooks" icon="hook" href="/app/custom-hooks">
    Customize behavior with virtual hooks
  </Card>
</CardGroup>


# UI Integration
Source: https://rexglue-rexglue-sdk.mintlify.app/app/ui-integration

Adding custom ImGui dialogs and overlays

ReXApp provides ImGui integration out of the box, with built-in debug overlays and support for custom dialogs. This guide shows you how to add your own UI panels and integrate them with the application framework.

## ImGui Integration Overview

ReXApp creates an `ImGuiDrawer` instance that manages all ImGui rendering. Dialogs are registered with the drawer and automatically rendered each frame.

### Built-in Overlays

ReXApp includes these debug overlays:

* **Console**: Log output viewer (toggle with `` ` `` backtick key)
* **Debug Overlay**: FPS, frame time, system stats
* **Settings**: Runtime configuration UI

These are always available without additional setup.

## Creating Custom Dialogs

Custom dialogs inherit from `rex::ui::ImGuiDialog` and override the `OnDraw()` method.

### Basic Dialog

```cpp theme={null}
class GameStatsDialog : public rex::ui::ImGuiDialog {
 public:
  using ImGuiDialog::ImGuiDialog;

 protected:
  void OnDraw(ImGuiIO& io) override {
    ImGui::Begin("Game Stats", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
    ImGui::Text("FPS: %.1f", io.Framerate);
    ImGui::Text("Frame Time: %.3f ms", 1000.0f / io.Framerate);
    ImGui::End();
  }
};
```

See `rex/ui/imgui_dialog.h:27-59`

### Dialog Lifecycle Hooks

```cpp theme={null}
class MyDialog : public rex::ui::ImGuiDialog {
 protected:
  void OnShow() override {
    // Called when dialog is first shown
    REXLOG_INFO("Dialog opened");
  }
  
  void OnClose() override {
    // Called when dialog is closed
    REXLOG_INFO("Dialog closed");
  }
  
  void OnDraw(ImGuiIO& io) override {
    // Called every frame while dialog is open
    ImGui::Begin("My Dialog");
    // ... UI code
    ImGui::End();
  }
};
```

See `rex/ui/imgui_dialog.h:51-53`

## Registering Dialogs

Register dialogs in the `OnCreateDialogs()` hook:

```cpp theme={null}
class MyGameApp : public rex::ReXApp {
 protected:
  void OnCreateDialogs(ui::ImGuiDrawer* drawer) override {
    // Create and register dialog
    drawer->AddDialog(new GameStatsDialog(drawer));
    drawer->AddDialog(new DebugControlsDialog(drawer));
  }
};
```

Dialogs are owned by the ImGuiDrawer and automatically cleaned up on shutdown.

See `rex/ui/imgui_drawer.h:44`

## Accessing ImGui Drawer

Access the drawer through the protected accessor:

```cpp theme={null}
void OnPostSetup() override {
  // Available after OnCreateDialogs, but typically use OnCreateDialogs hook
  auto* drawer = imgui_drawer();
}
```

See `rex/rex_app.h:108`

## Advanced Dialog Examples

### Interactive Settings Dialog

```cpp theme={null}
class GraphicsSettingsDialog : public rex::ui::ImGuiDialog {
 public:
  GraphicsSettingsDialog(ui::ImGuiDrawer* drawer, Runtime* runtime)
      : ImGuiDialog(drawer), runtime_(runtime) {}

 protected:
  void OnDraw(ImGuiIO& io) override {
    ImGui::Begin("Graphics Settings");
    
    // Checkbox
    ImGui::Checkbox("VSync", &vsync_enabled_);
    
    // Slider
    ImGui::SliderInt("Resolution Scale", &resolution_scale_, 50, 200, "%d%%");
    
    // Combo box
    const char* items[] = { "Low", "Medium", "High", "Ultra" };
    ImGui::Combo("Quality", &quality_level_, items, 4);
    
    // Apply button
    if (ImGui::Button("Apply Settings")) {
      ApplySettings();
    }
    
    ImGui::End();
  }

 private:
  void ApplySettings() {
    // Update graphics system
    auto* graphics = runtime_->graphics_system();
    // Apply settings...
    REXLOG_INFO("Graphics settings applied");
  }
  
  Runtime* runtime_;
  bool vsync_enabled_ = true;
  int resolution_scale_ = 100;
  int quality_level_ = 2;
};
```

### Real-time Data Display

```cpp theme={null}
class MemoryMonitorDialog : public rex::ui::ImGuiDialog {
 public:
  MemoryMonitorDialog(ui::ImGuiDrawer* drawer, Runtime* runtime)
      : ImGuiDialog(drawer), runtime_(runtime) {}

 protected:
  void OnDraw(ImGuiIO& io) override {
    ImGui::Begin("Memory Monitor");
    
    auto* memory = runtime_->memory();
    
    // Display memory stats
    ImGui::Text("Virtual Memory");
    ImGui::Separator();
    
    // Get memory stats from runtime
    // (This is example - actual API may differ)
    ImGui::Text("Total: 512 MB");
    ImGui::Text("Used: %.1f MB", GetUsedMemoryMB());
    
    // Progress bar
    float used_fraction = GetUsedMemoryMB() / 512.0f;
    ImGui::ProgressBar(used_fraction, ImVec2(-1, 0));
    
    ImGui::End();
  }

 private:
  float GetUsedMemoryMB() {
    // Query runtime for memory usage
    return 123.4f;  // Placeholder
  }
  
  Runtime* runtime_;
};
```

### Modal Dialog with Callback

```cpp theme={null}
class ConfirmDialog : public rex::ui::ImGuiDialog {
 public:
  ConfirmDialog(ui::ImGuiDrawer* drawer, 
                std::string title,
                std::string message,
                std::function<void()> on_confirm)
      : ImGuiDialog(drawer),
        title_(std::move(title)),
        message_(std::move(message)),
        on_confirm_(std::move(on_confirm)) {}

 protected:
  void OnDraw(ImGuiIO& io) override {
    ImGui::OpenPopup(title_.c_str());
    
    if (ImGui::BeginPopupModal(title_.c_str(), nullptr, 
                               ImGuiWindowFlags_AlwaysAutoResize)) {
      ImGui::Text("%s", message_.c_str());
      ImGui::Separator();
      
      if (ImGui::Button("OK", ImVec2(120, 0))) {
        on_confirm_();
        Close();
      }
      ImGui::SameLine();
      if (ImGui::Button("Cancel", ImVec2(120, 0))) {
        Close();
      }
      
      ImGui::EndPopup();
    }
  }

 private:
  std::string title_;
  std::string message_;
  std::function<void()> on_confirm_;
};

// Usage:
void OnCreateDialogs(ui::ImGuiDrawer* drawer) override {
  drawer->AddDialog(new ConfirmDialog(
      drawer,
      "Reset Settings",
      "Are you sure you want to reset all settings?",
      []() { REXLOG_INFO("Settings reset"); }
  ));
}
```

## Accessing Runtime from Dialogs

Dialogs often need access to Runtime subsystems. Pass the Runtime pointer through the constructor:

```cpp theme={null}
class MyGameApp : public rex::ReXApp {
 protected:
  void OnCreateDialogs(ui::ImGuiDrawer* drawer) override {
    // Pass runtime() to dialog constructor
    drawer->AddDialog(new GameStatsDialog(drawer, runtime()));
  }
};

class GameStatsDialog : public rex::ui::ImGuiDialog {
 public:
  GameStatsDialog(ui::ImGuiDrawer* drawer, Runtime* runtime)
      : ImGuiDialog(drawer), runtime_(runtime) {}

 protected:
  void OnDraw(ImGuiIO& io) override {
    // Access runtime subsystems
    auto* kernel = runtime_->kernel_state();
    auto* graphics = runtime_->graphics_system();
    
    ImGui::Begin("Game Stats");
    // Display stats...
    ImGui::End();
  }

 private:
  Runtime* runtime_;
};
```

## Accessing ImGuiIO

The `ImGuiIO` structure provides input state and configuration:

```cpp theme={null}
void OnDraw(ImGuiIO& io) override {
  ImGui::Begin("Input Debug");
  
  // Display metrics
  ImGui::Text("FPS: %.1f", io.Framerate);
  ImGui::Text("Delta Time: %.3f ms", io.DeltaTime * 1000.0f);
  
  // Mouse position
  ImGui::Text("Mouse: (%.1f, %.1f)", io.MousePos.x, io.MousePos.y);
  
  // Keyboard state
  if (ImGui::IsKeyPressed(ImGuiKey_Space)) {
    ImGui::Text("Space pressed!");
  }
  
  ImGui::End();
}
```

See `rex/rex_app.h:96` for OnCreateDialogs signature

## Message Boxes

For simple alerts, use the built-in message box:

```cpp theme={null}
void ShowErrorMessage() {
  auto* dialog = rex::ui::ImGuiDialog::ShowMessageBox(
      imgui_drawer(),
      "Error",
      "Failed to load game data. Please check the installation."
  );
  
  // Optional: wait for dialog to close
  rex::thread::Fence fence;
  dialog->Then(&fence);
  fence.Wait();  // Blocks until user closes dialog
}
```

See `rex/ui/imgui_dialog.h:34-35`

## Removing Dialogs

Dialogs are typically removed by calling `Close()` from within the dialog:

```cpp theme={null}
void OnDraw(ImGuiIO& io) override {
  ImGui::Begin("My Dialog");
  
  if (ImGui::Button("Close")) {
    Close();  // Removes dialog from drawer
  }
  
  ImGui::End();
}
```

You can also manually remove dialogs from the drawer:

```cpp theme={null}
ui::ImGuiDialog* my_dialog = new MyDialog(drawer);
drawer->AddDialog(my_dialog);

// Later...
drawer->RemoveDialog(my_dialog);
```

See `rex/ui/imgui_drawer.h:45`

## Thread Safety

ImGui rendering happens on the main thread. The PPC module runs on a background thread. If your dialog needs to display data from the game thread, use proper synchronization:

```cpp theme={null}
class GameStatsDialog : public rex::ui::ImGuiDialog {
 public:
  void UpdateFromGameThread(int kills, int deaths) {
    std::lock_guard<std::mutex> lock(mutex_);
    kills_ = kills;
    deaths_ = deaths;
  }

 protected:
  void OnDraw(ImGuiIO& io) override {
    std::lock_guard<std::mutex> lock(mutex_);
    
    ImGui::Begin("Stats");
    ImGui::Text("Kills: %d", kills_);
    ImGui::Text("Deaths: %d", deaths_);
    ImGui::End();
  }

 private:
  std::mutex mutex_;
  int kills_ = 0;
  int deaths_ = 0;
};
```

Or use atomics for simple values:

```cpp theme={null}
std::atomic<int> frame_count_{0};

void OnDraw(ImGuiIO& io) override {
  ImGui::Text("Frames: %d", frame_count_.load());
}
```

## Complete Example

Here's a complete application with multiple custom dialogs:

```cpp theme={null}
#include "generated/my_game_config.h"
#include "generated/my_game_init.h"
#include <rex/rex_app.h>

class MyGameApp : public rex::ReXApp {
 public:
  using rex::ReXApp::ReXApp;

  static std::unique_ptr<rex::ui::WindowedApp> Create(
      rex::ui::WindowedAppContext& ctx) {
    return std::unique_ptr<MyGameApp>(new MyGameApp(ctx, "my_game",
        {PPC_CODE_BASE, PPC_CODE_SIZE, PPC_IMAGE_BASE,
         PPC_IMAGE_SIZE, PPCFuncMappings}));
  }

 protected:
  void OnCreateDialogs(ui::ImGuiDrawer* drawer) override {
    // Add custom dialogs
    drawer->AddDialog(new GameStatsDialog(drawer, runtime()));
    drawer->AddDialog(new MemoryMonitorDialog(drawer, runtime()));
    drawer->AddDialog(new GraphicsSettingsDialog(drawer, runtime()));
  }

 private:
  // Dialog implementations...
  class GameStatsDialog : public rex::ui::ImGuiDialog {
   public:
    GameStatsDialog(ui::ImGuiDrawer* drawer, Runtime* runtime)
        : ImGuiDialog(drawer), runtime_(runtime) {}
   protected:
    void OnDraw(ImGuiIO& io) override {
      ImGui::Begin("Game Stats");
      ImGui::Text("FPS: %.1f", io.Framerate);
      ImGui::End();
    }
   private:
    Runtime* runtime_;
  };
  
  class MemoryMonitorDialog : public rex::ui::ImGuiDialog {
   public:
    using ImGuiDialog::ImGuiDialog;
   protected:
    void OnDraw(ImGuiIO& io) override {
      ImGui::Begin("Memory");
      ImGui::Text("Memory usage stats here");
      ImGui::End();
    }
  };
  
  class GraphicsSettingsDialog : public rex::ui::ImGuiDialog {
   public:
    GraphicsSettingsDialog(ui::ImGuiDrawer* drawer, Runtime* runtime)
        : ImGuiDialog(drawer), runtime_(runtime) {}
   protected:
    void OnDraw(ImGuiIO& io) override {
      ImGui::Begin("Graphics Settings");
      ImGui::Checkbox("VSync", &vsync_);
      ImGui::End();
    }
   private:
    Runtime* runtime_;
    bool vsync_ = true;
  };
};

REX_DEFINE_APP(my_game, MyGameApp::Create)
```

## Best Practices

### Do

* Keep dialog logic simple and focused
* Use atomics or mutexes for shared state with game thread
* Pass Runtime pointer through constructor for subsystem access
* Use ImGui's built-in layout and styling
* Call `Close()` when dialog should be removed
* Use message boxes for simple alerts

### Don't

* Don't perform heavy computation in OnDraw (called every frame)
* Don't access UI from the PPC module thread
* Don't forget to handle window close (user clicking X)
* Don't leak memory - dialogs are owned by ImGuiDrawer
* Don't block the UI thread with long operations

## ImGui Resources

For detailed ImGui API documentation:

* [ImGui GitHub](https://github.com/ocornut/imgui)
* [ImGui Demo](https://github.com/ocornut/imgui/blob/master/imgui_demo.cpp) - comprehensive examples
* [ImGui Manual](https://github.com/ocornut/imgui/wiki)

## Next Steps

<CardGroup>
  <Card title="ReXApp Base Class" icon="code" href="/app/rexapp">
    Learn about the application framework
  </Card>

  <Card title="Custom Hooks" icon="hook" href="/app/custom-hooks">
    Customize behavior with virtual hooks
  </Card>

  <Card title="Runtime Setup" icon="gear" href="/app/runtime-setup">
    Configure backend systems
  </Card>
</CardGroup>


# Architecture Overview
Source: https://rexglue-rexglue-sdk.mintlify.app/architecture

Understanding the ReXGlue recompilation system and runtime architecture

# Architecture Overview

ReXGlue is a complete static recompilation system that transforms Xbox 360 PowerPC executables into native C++ code. This page explains the core components and how they work together.

## System Architecture

```mermaid theme={null}
graph TB
    XEX[Xbox 360 XEX] --> Analysis[Analysis Phase]
    Analysis --> CodeGen[Code Generation]
    CodeGen --> CPP[Generated C++]
    CPP --> Compiler[Clang Compiler]
    Runtime[ReXGlue Runtime] --> Compiler
    Compiler --> Native[Native Executable]
    Native --> Kernel[Kernel Layer]
    Native --> Graphics[Graphics Layer]
    Kernel --> Memory[Memory Management]
    Graphics --> D3D12[D3D12 Backend]
    Graphics --> Vulkan[Vulkan Backend]
```

## Core Components

### 1. Analysis Engine

The analysis engine (`src/codegen`) processes Xbox 360 executables to understand their structure:

* **Binary Parsing**: Reads XEX format files and extracts code sections, headers, and metadata
* **Function Discovery**: Identifies function boundaries using entry points, prologue patterns, and call analysis
* **Control Flow Analysis**: Builds control flow graphs to track jumps, branches, and switch tables
* **Data Region Detection**: Distinguishes embedded data from code using configurable thresholds

<Note>
  The analyzer can detect jump tables and switch statements automatically, but complex cases may require manual configuration via TOML hints.
</Note>

### 2. Code Generator

The code generator (`src/codegen`) translates PowerPC assembly to C++:

```cpp theme={null}
// PowerPC instruction
lis r3, 0x8000      // Load immediate shifted
addi r3, r3, 0x100  // Add immediate

// Generated C++ (simplified)
ctx->r[3] = 0x80000000;
ctx->r[3] = ctx->r[3] + 0x100;
```

**Key features:**

* **Register Mapping**: PowerPC GPRs (r0-r31), FPRs (f0-f31), and special registers (LR, CTR, CR, XER)
* **Condition Flags**: Accurate CR field tracking for conditional branches
* **Exception Handling**: Optional SEH wrapper generation for Windows structured exception handling
* **Optimization**: Dead code elimination, register allocation, and local variable promotion

### 3. Runtime System

The runtime provides Xbox 360 environment emulation:

#### Processor (`rex::runtime::Processor`)

Manages execution state and module loading:

```cpp theme={null}
class Processor {
  memory::Memory* memory() const;
  ExportResolver* export_resolver() const;
  
  bool AddModule(std::unique_ptr<Module> module);
  bool Execute(ThreadState* thread_state, uint32_t address);
  
  void SetFunction(uint32_t guest_address, PPCFunc* func);
  PPCFunc* GetFunction(uint32_t guest_address);
};
```

Location: `include/rex/system/processor.h:64-128`

#### Kernel State (`rex::system::KernelState`)

Emulates Xbox 360 kernel services:

```cpp theme={null}
class KernelState {
  memory::Memory* memory() const;
  runtime::Processor* processor() const;
  VirtualFileSystem* file_system() const;
  
  ObjectTable* object_table();
  object_ref<XThread> LaunchModule(object_ref<UserModule> module);
  void RegisterThread(XThread* thread);
};
```

Location: `include/rex/system/kernel_state.h:111-254`

**Provides:**

* Thread management (XThread)
* Synchronization primitives (XEvent, XSemaphore, XMutant)
* File I/O and virtual filesystem
* Object handle table
* Module loading and symbol resolution

#### Memory Management (`rex::memory::Memory`)

Emulates Xbox 360 memory layout:

* **Physical Memory**: 512MB base allocation at fixed address
* **Virtual Memory**: Page table management with Xbox 360 addressing
* **Memory Mapping**: Support for memory-mapped I/O (MMIO) handlers
* **Big Endian**: Automatic endianness conversion for memory operations

<Warning>
  Memory is allocated at a fixed base address (`0x100000000` on x64) to maintain Xbox 360 pointer semantics. This requires specific compiler flags and may conflict with sanitizers.
</Warning>

### 4. Graphics Backends

ReXGlue translates Xbox 360 GPU commands to modern graphics APIs:

<Tabs>
  <Tab title="D3D12 (Windows)">
    **Direct3D 12 Backend** (`src/graphics/d3d12`)

    * Command list translation
    * Resource binding compatibility
    * Shader translation (HLSL)
    * Hardware-accelerated rendering

    Enabled by default on Windows via `REXGLUE_USE_D3D12=ON`
  </Tab>

  <Tab title="Vulkan (Linux)">
    **Vulkan Backend** (`src/graphics/vulkan`)

    * Cross-platform rendering
    * SPIR-V shader compilation
    * Validation layer support
    * RenderDoc integration

    Enabled by default on Linux via `REXGLUE_USE_VULKAN=ON`
  </Tab>
</Tabs>

### 5. Platform Abstraction

Platform-specific implementations:

| Component      | Windows            | Linux           |
| -------------- | ------------------ | --------------- |
| **Window**     | Win32 API          | GTK             |
| **Input**      | XInput/DirectInput | evdev/SDL       |
| **Audio**      | XAudio2            | PulseAudio/ALSA |
| **Threading**  | Win32 Threads      | pthreads        |
| **Filesystem** | NTFS paths         | POSIX paths     |

## Module Organization

The SDK is organized into layered modules:

```
rexglue-sdk/
├── src/core/          # Core types, logging, cvars
├── src/filesystem/    # VFS and file I/O
├── src/system/        # Kernel emulation (threads, objects, memory)
├── src/kernel/        # Kernel exports (xboxkrnl.exe)
├── src/graphics/      # GPU emulation (d3d12, vulkan)
├── src/ui/            # Windowing and presentation
├── src/input/         # Controller and keyboard input
├── src/audio/         # Audio emulation
├── src/codegen/       # Analysis and code generation
└── src/rexglue/       # CLI tool (init, codegen, migrate)
```

Each module is a CMake target that can be linked independently:

```cmake theme={null}
target_link_libraries(my_recompiled_game PRIVATE
  rex::core      # Required: Logging, types, utilities
  rex::system    # Required: Processor, kernel state
  rex::kernel    # Required: Kernel exports (XThread, XFile, etc.)
  rex::graphics  # Optional: Graphics if game uses GPU
  rex::ui        # Optional: Windowing and ImGui overlays
)
```

## Configuration System

ReXGlue uses TOML configuration files for code generation:

```toml theme={null}
project_name = "my_game"
file_path = "assets/default.xex"
out_directory_path = "generated"

# Code generation options
skip_lr = false
generate_exception_handlers = true
max_jump_extension = 65536

# Manual function overrides
[[functions]]
address = 0x82000100
name = "GameMain"
size = 0x500

# Jump table hints
[[switch_tables]]
address = 0x82001000
targets = [0x82001020, 0x82001040, 0x82001060]
```

Configuration structure: `include/rex/codegen/config.h:71-134`

## Build System Integration

ReXGlue integrates with CMake for seamless builds:

```cmake theme={null}
# Find or add SDK
find_package(rexglue REQUIRED CONFIG)

# Add your sources + generated code
add_executable(my_game
  src/main.cpp
  ${GENERATED_SOURCES}  # From generated/sources.cmake
)

# Configure runtime and platform settings
rexglue_configure_target(my_game)

# Link runtime modules
target_link_libraries(my_game PRIVATE
  rex::core rex::system rex::kernel
)
```

The `rexglue_configure_target()` helper automatically:

* Links platform entry point
* Adds ReXApp framework code
* Configures graphics backend
* Sets compiler flags for Clang

## Next Steps

<CardGroup>
  <Card title="Installation" icon="download" href="/installation">
    Install the SDK and configure your toolchain
  </Card>

  <Card title="Quick Start" icon="rocket" href="/quickstart">
    Create your first recompiled project
  </Card>
</CardGroup>


# rexglue codegen
Source: https://rexglue-rexglue-sdk.mintlify.app/cli/codegen

Analyze Xbox 360 XEX files and generate recompiled C++ code

The `codegen` command analyzes Xbox 360 executable files and generates recompiled C++ code, headers, and build integration files.

## Usage

```bash theme={null}
rexglue codegen <config.toml> [flags]
```

## Arguments

<ParamField type="string">
  Path to TOML configuration file

  This file specifies the XEX input path, output directory, and codegen options. See [Configuration Reference](/configuration/overview).
</ParamField>

## Flags

### General Flags

<ParamField type="boolean">
  Generate output even if validation errors occur

  By default, codegen aborts if it detects errors during analysis. Use `--force` to generate code anyway (useful for iterative development).
</ParamField>

<ParamField type="boolean">
  Enable generation of SEH exception handler code

  Generates code for Structured Exception Handling (SEH) found in the XEX binary.
</ParamField>

### Output Control

<ParamField type="uint32">
  Number of functions per generated .cpp file

  Controls file splitting to keep compilation units manageable. Range: 1-100000.
</ParamField>

<ParamField type="uint32">
  Log progress every N functions

  Controls how often progress messages are logged during code generation. Range: 1-100000.
</ParamField>

### Analysis Parameters

<ParamField type="uint32">
  Maximum iterations for function discovery convergence

  Limits the iterative function discovery process. Range: 1-100000.
</ParamField>

<ParamField type="uint32">
  Maximum iterations for vtable discovery

  Limits the C++ vtable discovery process. Range: 1-100000.
</ParamField>

<ParamField type="uint32">
  Maximum iterations for call target resolution

  Limits the call graph resolution process. Range: 1-100000.
</ParamField>

### Exception Handling Limits

<ParamField type="uint32">
  Maximum C++ EH states before rejecting handler

  Functions with more exception states are skipped. Range: 1-100000.
</ParamField>

<ParamField type="uint32">
  Maximum try blocks before rejecting handler

  Functions with more try blocks are skipped. Range: 1-100000.
</ParamField>

<ParamField type="uint32">
  Maximum IP-to-state map entries

  Controls exception handler table size limits. Range: 1-100000.
</ParamField>

<ParamField type="uint32">
  Maximum SEH scope table entries

  Controls SEH handler table size limits. Range: 1-100000.
</ParamField>

### Jump Table Discovery

<ParamField type="uint32">
  Maximum instructions to scan backward for jump table patterns

  Controls how far to look back when detecting switch/jump tables. Range: 1-10000.
</ParamField>

<ParamField type="uint32">
  Maximum entries per detected jump table

  Prevents runaway jump table detection. Range: 1-100000.
</ParamField>

<ParamField type="uint32">
  Safety limit on basic blocks per function

  Prevents analysis of pathologically large functions. Range: 1-1000000.
</ParamField>

## Examples

### Basic Code Generation

```bash theme={null}
rexglue codegen my_game_config.toml
```

Output:

```
ReXGlue v0.1.0 - Xbox 360 Recompilation Toolkit
Generating code with config: my_game_config.toml
[Info] Loading XEX file: assets/default.xex
[Info] Discovered 4523 functions
[Info] Resolving call targets...
[Info] Generating C++ code...
[Info] Writing output files...
Operation completed successfully in 12.456s
```

### Enable Exception Handlers

```bash theme={null}
rexglue codegen my_game_config.toml --enable-exception-handlers
```

### Force Generation with Errors

```bash theme={null}
rexglue codegen my_game_config.toml --force --log-verbose
```

### Adjust Output File Size

```bash theme={null}
rexglue codegen my_game_config.toml --functions-per-file 250
```

This generates more (but smaller) `.cpp` files, which can improve parallel compilation.

### Tune Analysis for Large Binaries

```bash theme={null}
rexglue codegen my_game_config.toml \
  --max-discovery-iterations 2000 \
  --max-blocks-per-function 20000 \
  --progress-log-frequency 50
```

## Generated Output

The codegen command generates several types of files in the output directory:

### Configuration Header

```cpp theme={null}
// generated/my_game_config.h
#define PPC_IMAGE_BASE 0x82000000ull
#define PPC_IMAGE_SIZE 0x01A3C000ull
#define PPC_CODE_BASE 0x82000200ull
#define PPC_CODE_SIZE 0x019F4800ull
```

### Initialization Code

```cpp theme={null}
// generated/my_game_init.h
// Function mapping tables for runtime
extern const PPCFunctionMapping PPCFuncMappings[];
```

### Function Implementation Files

```cpp theme={null}
// generated/my_game_funcs_0.cpp
#include "my_game_config.h"
#include <rex/ppc.h>

PPC_FUNC(sub_82000200) {
  // Generated recompiled code
}
```

### CMake Integration

```cmake theme={null}
# generated/sources.cmake
set(GENERATED_SOURCES
    generated/my_game_funcs_0.cpp
    generated/my_game_funcs_1.cpp
    # ...
)
```

## Integration with CMake

After running codegen, rebuild your CMake project to include the generated code:

```bash theme={null}
cmake --build out/build/linux-amd64-debug
```

The generated `sources.cmake` is automatically included by the project's `CMakeLists.txt`.

### Custom Codegen Target

Your project includes a custom CMake target for running codegen:

```bash theme={null}
cmake --build out/build/linux-amd64-debug --target my_game_codegen
```

This runs `rexglue codegen` with the correct paths automatically.

## Common Errors

### Missing Config File

```
Missing config path. Usage: rexglue codegen <config.toml>
```

**Solution:** Provide the path to your configuration file.

### XEX File Not Found

```
Failed to load XEX file: assets/default.xex
```

**Solution:** Verify the `file_path` in your config matches the actual XEX location.

### Validation Errors

```
Operation failed: Validation errors detected (took 8.234s)
```

**Solution:** Check logs for details. Use `--force` to generate code despite errors, or fix the issues in your configuration.

## Performance Tips

1. **Use `--functions-per-file`** to balance compilation parallelism:
   * Smaller values (250-500): More files, better parallelism, slower linking
   * Larger values (1000+): Fewer files, slower compilation per file

2. **Enable verbose logging** only when debugging:
   ```bash theme={null}
   rexglue codegen config.toml --log-verbose --log-file codegen.log
   ```

3. **Tune iteration limits** for very large binaries (>10MB XEX):
   * Increase `--max-discovery-iterations` if function discovery doesn't converge
   * Increase `--max-blocks-per-function` if you have very large functions

## Next Steps

* Learn about [Configuration Options](/configuration/overview)
* Understand [Function Discovery](/concepts/analysis)
* Read about [Exception Handling](/concepts/exception-handling)


# rexglue init
Source: https://rexglue-rexglue-sdk.mintlify.app/cli/init

Initialize a new ReXGlue recompilation project

The `init` command creates a new ReXGlue project with the required directory structure, build files, and configuration templates.

## Usage

```bash theme={null}
rexglue init --app-name <name> --app-root <path> [flags]
```

## Required Flags

<ParamField type="string">
  Project name (snake\_case, PascalCase, or kebab-case)

  This name is used throughout the generated project files. ReXGlue normalizes it to:

  * `snake_case` for file names and CMake targets
  * `PascalCase` for C++ class names
  * `UPPER_CASE` for CMake variables
</ParamField>

<ParamField type="string">
  Project root directory path

  The directory will be created if it doesn't exist. Must be empty unless `--force` is used.
</ParamField>

## Optional Flags

<ParamField type="string">
  Project description (optional)
</ParamField>

<ParamField type="string">
  Project author name (optional)
</ParamField>

<ParamField type="boolean">
  Create as SDK example project (omits vcpkg.json)
</ParamField>

<ParamField type="boolean">
  Overwrite existing files in non-empty directory
</ParamField>

## Generated Project Structure

```
my_game_project/
├── CMakeLists.txt           # SDK-managed build configuration
├── CMakePresets.json        # Build presets for Windows/Linux
├── my_game_config.toml      # Codegen configuration
├── src/
│   └── main.cpp            # SDK-managed application entry point
└── generated/              # Output directory for generated code
```

## Examples

### Basic Project Initialization

```bash theme={null}
rexglue init --app-name my_game --app-root ./my_game_project
```

Output:

```
ReXGlue v0.1.0 - Xbox 360 Recompilation Toolkit
Initializing project 'my_game' at: ./my_game_project
Mode: standalone
Creating directory structure...
Generating project files...
Project 'my_game' initialized in './my_game_project' successfully!
Operation completed successfully in 0.123s
```

### Initialize with Metadata

```bash theme={null}
rexglue init \
  --app-name "Halo3" \
  --app-root ./halo3_recomp \
  --app-desc "Halo 3 Recompilation Project" \
  --app-author "Your Name"
```

### Create SDK Example

```bash theme={null}
rexglue init \
  --app-name example_minimal \
  --app-root ./examples/minimal \
  --sdk-example
```

## Generated Files

### CMakeLists.txt

The generated `CMakeLists.txt` is SDK-managed and will be overwritten by [`rexglue migrate`](/cli/migrate). It includes:

* CMake 3.25+ configuration with C++23 standard
* ReXGlue SDK integration (via `REXSDK_DIR` or `find_package`)
* Source file configuration with generated code inclusion
* Platform-specific settings via `rexglue_configure_target()`
* Custom codegen target: `cmake --build . --target <project>_codegen`

### src/main.cpp

The generated `src/main.cpp` is SDK-managed and includes:

* Application class derived from `rex::ReXApp`
* Generated configuration headers (`<project>_config.h`, `<project>_init.h`)
* `REX_DEFINE_APP` macro registration

**Note:** Customizations should go in virtual hook overrides, not in `main.cpp`.

### Configuration File

The `<project>_config.toml` file configures code generation:

```toml theme={null}
project_name = "my_game"
file_path = "assets/default.xex"
out_directory_path = "generated"
```

See [Codegen Configuration](/configuration/overview) for all available options.

### CMakePresets.json

Provides build presets for different platforms and configurations:

* `win-amd64-debug` / `win-amd64-release` (Windows with clang)
* `linux-amd64-debug` / `linux-amd64-release` (Linux with clang-20)
* `*-relwithdebinfo` variants for optimized debugging

## Next Steps

After initializing your project:

1. **Add your XEX file** to `assets/default.xex` (or update the path in the config)
2. **Configure the build:**
   ```bash theme={null}
   cmake --preset=linux-amd64-debug
   ```
3. **Run code generation:**
   ```bash theme={null}
   rexglue codegen my_game_config.toml
   ```
4. **Build the project:**
   ```bash theme={null}
   cmake --build out/build/linux-amd64-debug
   ```

See [Getting Started](/getting-started/quickstart) for a complete walkthrough.

## Common Errors

### Directory Not Empty

```
Directory is not empty. Use --force to overwrite: ./my_game_project
```

**Solution:** Add `--force` flag or use an empty directory.

### Invalid App Name

```
--app_name is required
```

**Solution:** Provide a valid project name with `--app-name`.

### Missing Required Flag

```
--app_root is required for init command
```

**Solution:** Specify the project directory with `--app-root`.


# rexglue migrate
Source: https://rexglue-rexglue-sdk.mintlify.app/cli/migrate

Migrate existing projects to the current SDK version

The `migrate` command updates SDK-managed files in an existing ReXGlue project to match the current SDK templates. This ensures projects stay compatible with SDK updates.

## Usage

```bash theme={null}
rexglue migrate --app-root <path> [flags]
```

## Required Flags

<ParamField type="string">
  Path to existing ReXGlue project root directory

  Must contain a valid ReXGlue project with `src/main.cpp` and a `*_config.toml` file.
</ParamField>

## Optional Flags

<ParamField type="boolean">
  Skip confirmation prompt and overwrite files immediately

  By default, migrate shows which files will be changed and asks for confirmation.
</ParamField>

## SDK-Managed Files

The following files are overwritten during migration:

* `CMakeLists.txt` - Build configuration and SDK integration
* `src/main.cpp` - Application entry point and ReXApp setup

These files are regenerated from current SDK templates using the project name from your configuration file.

## User-Managed Files

The following files are **never** modified by migrate:

* `*_config.toml` - Your codegen configuration
* `CMakePresets.json` - Build presets
* Custom source files in `src/`
* Generated code in `generated/`
* Any other files you've added

## Examples

### Basic Migration

```bash theme={null}
rexglue migrate --app-root ./my_game_project
```

Output:

```
ReXGlue v0.1.0 - Xbox 360 Recompilation Toolkit
The following files will be overwritten:
  CMakeLists.txt
  src/main.cpp

Any local changes to these files will be lost.
Continue? [y/N] y
Migrating project 'my_game' at: ./my_game_project
  Overwrote src/main.cpp
  Overwrote CMakeLists.txt
Migration complete. Re-run CMake configure to pick up changes.
Operation completed successfully in 0.045s
```

### Force Migration Without Prompt

```bash theme={null}
rexglue migrate --app-root ./my_game_project --force
```

Output:

```
ReXGlue v0.1.0 - Xbox 360 Recompilation Toolkit
Migrating project 'my_game' at: ./my_game_project
  Overwrote src/main.cpp
  Overwrote CMakeLists.txt
Migration complete. Re-run CMake configure to pick up changes.
Operation completed successfully in 0.038s
```

### No Changes Needed

```bash theme={null}
rexglue migrate --app-root ./my_game_project
```

Output:

```
ReXGlue v0.1.0 - Xbox 360 Recompilation Toolkit
Project 'my_game' is already up to date.
Operation completed successfully in 0.012s
```

## Migration Workflow

1. **Detects project name** from `*_config.toml` in the project root
2. **Checks existing files** against current SDK templates
3. **Lists modified files** and prompts for confirmation (unless `--force`)
4. **Overwrites SDK-managed files** with current templates
5. **Preserves customizations** in non-managed files

## After Migration

After successful migration, you must reconfigure your CMake build:

```bash theme={null}
# Reconfigure CMake
cmake --preset=linux-amd64-debug

# Rebuild the project
cmake --build out/build/linux-amd64-debug
```

This ensures CMake picks up any changes to `CMakeLists.txt`.

## When to Migrate

Run `rexglue migrate` when:

* **Updating the SDK** to a new version
* **Build errors occur** after SDK updates
* **New SDK features** require template changes (e.g., new CMake functions)
* **Prompted by SDK documentation** for breaking changes

## Preserving Customizations

### Do NOT Customize SDK-Managed Files

Files marked as "SDK-managed" in their header comments will be overwritten:

```cpp theme={null}
// src/main.cpp
// This file is SDK-managed. Customizations go in virtual hook overrides.
// Running 'rexglue migrate' will overwrite this file.
```

### Where to Add Custom Code

<CodeGroup>
  ```cpp Custom Application Hooks theme={null}
  // src/my_game_hooks.cpp
  #include "generated/my_game_config.h"
  #include <rex/rex_app.h>

  class MyGameApp : public rex::ReXApp {
   public:
    using rex::ReXApp::ReXApp;

    // Override initialization
    void OnInit() override {
      ReXApp::OnInit();
      // Your custom initialization here
    }

    // Override frame update
    void OnUpdate(float delta) override {
      // Your custom game logic here
      ReXApp::OnUpdate(delta);
    }
  };
  ```

  ```cpp Custom CMake Configuration theme={null}
  # Add a custom CMakeLists.txt.user (never overwritten)
  # my_game_project/CMakeLists.txt.user

  # Add custom source files
  target_sources(my_game PRIVATE
      src/my_game_hooks.cpp
      src/custom_logic.cpp
  )

  # Add custom compile definitions
  target_compile_definitions(my_game PRIVATE
      MY_CUSTOM_DEFINE=1
  )
  ```
</CodeGroup>

Then include the user file in `CMakeLists.txt` (this line won't be removed by migrate if you add it once):

```cmake theme={null}
# At the end of CMakeLists.txt
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt.user")
    include(CMakeLists.txt.user)
endif()
```

## Common Errors

### Project Directory Not Found

```
Project directory does not exist: ./my_game_project
```

**Solution:** Verify the path is correct and the directory exists.

### Not a ReXGlue Project

```
Not a rexglue project (no src/main.cpp): ./my_game_project
```

**Solution:** Ensure you're running migrate on a valid ReXGlue project initialized with [`rexglue init`](/cli/init).

### No Configuration File

```
No *_config.toml found in project root: ./my_game_project
```

**Solution:** Ensure your project has a configuration file (e.g., `my_game_config.toml`) in the root directory.

### Missing app\_root Flag

```
--app_root is required for migrate command
```

**Solution:** Provide the project path with `--app-root`.

## Migration Checklist

Before migrating:

* [ ] **Commit your changes** to version control
* [ ] **Review SDK changelog** for breaking changes
* [ ] **Backup custom modifications** if you edited SDK-managed files

After migrating:

* [ ] **Reconfigure CMake** with your preset
* [ ] **Rebuild the project** to verify everything compiles
* [ ] **Test your application** to ensure functionality is preserved
* [ ] **Commit migration changes** to version control

## Version Compatibility

Migration always updates to the **current SDK version** bundled with the `rexglue` binary. There is no way to migrate to a specific older version.

If you need to maintain multiple SDK versions:

1. Use separate `rexglue` binary installations
2. Pin your SDK version in your build system
3. Document the required SDK version in your project README


# CLI Overview
Source: https://rexglue-rexglue-sdk.mintlify.app/cli/overview

ReXGlue command-line interface for Xbox 360 recompilation

ReXGlue is the command-line tool for recompiling Xbox 360 executables. It provides commands for project initialization, code generation, migration, and test generation.

## Usage

```bash theme={null}
rexglue <command> [flags] [args]
```

## Commands

| Command           | Description                             |
| ----------------- | --------------------------------------- |
| `init`            | Initialize a new ReXGlue project        |
| `codegen`         | Analyze XEX and generate C++ code       |
| `migrate`         | Migrate project to current SDK version  |
| `recompile-tests` | Generate Catch2 tests from PPC assembly |

Run `rexglue --help` for detailed flag documentation.

## Common Flags

These flags work with all commands:

<ParamField type="string">
  Logging level: trace, debug, info, warn, error, fatal
</ParamField>

<ParamField type="boolean">
  Enable verbose logging (sets level to trace)
</ParamField>

<ParamField type="string">
  Log file path (empty = no file logging)
</ParamField>

<ParamField type="boolean">
  Generate output even if validation errors occur
</ParamField>

## Environment Variables

ReXGlue supports setting any flag via environment variables using the format:

```bash theme={null}
export REX_<FLAG_NAME>=<value>
```

For example:

```bash theme={null}
export REX_LOG_LEVEL=debug
export REX_FORCE=true
rexglue codegen myproject_config.toml
```

## Exit Codes

* `0` - Success
* `1` - Error (check logs for details)

## Examples

### Initialize a New Project

```bash theme={null}
rexglue init --app-name my_game --app-root ./my_game_project
```

### Generate Code from Configuration

```bash theme={null}
rexglue codegen my_game_config.toml
```

### Enable Verbose Logging

```bash theme={null}
rexglue codegen my_game_config.toml --log-verbose
```

### Force Generation Despite Errors

```bash theme={null}
rexglue codegen my_game_config.toml --force
```


# rexglue recompile-tests
Source: https://rexglue-rexglue-sdk.mintlify.app/cli/recompile-tests

Generate Catch2 unit tests from PPC assembly test cases

The `recompile-tests` command generates Catch2 test cases from PowerPC assembly source files with embedded test specifications. This is used for validating the recompiler's correctness.

<Note>
  This command is primarily for **ReXGlue SDK development** and testing the recompiler itself. End-user projects typically don't need this command.
</Note>

## Usage

```bash theme={null}
rexglue recompile-tests --bin-dir <path> --asm-dir <path> --output <path>
```

## Required Flags

<ParamField type="string">
  Directory containing linked `.bin` and `.map` files

  These are PowerPC binaries linked at address `0x82010000` (matching the `-Ttext` linker flag).
</ParamField>

<ParamField type="string">
  Directory containing `.s` assembly source files

  Assembly files must include test specification comments (`#_REGISTER_IN`, `#_REGISTER_OUT`, etc.).
</ParamField>

<ParamField type="string">
  Output directory for generated test code

  The command generates:

  * `ppc_config.h` - Test memory layout configuration
  * `ppc_test_functions.cpp` - Recompiled PPC functions
  * `ppc_test_cases.cpp` - Catch2 test cases
  * `ppc_test_decls.h` - Function declarations
</ParamField>

## Test Specification Format

Assembly files use special comments to specify test cases:

```asm theme={null}
# Test function with register inputs/outputs
test_add:
#_REGISTER_IN r3 0x10
#_REGISTER_IN r4 0x20
    add r5, r3, r4
#_REGISTER_OUT r5 0x30
    blr

# Test with vector registers
test_vector_add:
#_REGISTER_IN v0 [0x00000001, 0x00000002, 0x00000003, 0x00000004]
#_REGISTER_IN v1 [0x00000010, 0x00000020, 0x00000030, 0x00000040]
    vadduwm v2, v0, v1
#_REGISTER_OUT v2 [0x00000011, 0x00000022, 0x00000033, 0x00000044]
    blr

# Test with memory operations
test_load_store:
#_REGISTER_IN r3 0x1000
#_MEMORY_IN 0x1000 01 02 03 04
    lwz r4, 0(r3)
#_REGISTER_OUT r4 0x01020304
#_MEMORY_OUT 0x1000 01 02 03 04
    blr
```

### Supported Test Directives

* `#_REGISTER_IN <reg> <value>` - Set register before function call
* `#_REGISTER_OUT <reg> <value>` - Assert register after function call
* `#_MEMORY_IN <addr> <hex bytes>` - Initialize memory before function call
* `#_MEMORY_OUT <addr> <hex bytes>` - Assert memory after function call

### Register Types

* **General purpose:** `r0`-`r31` (64-bit integer values)
* **Floating point:** `f0`-`f31` (64-bit floating point, use decimal notation)
* **Vector:** `v0`-`v127` (128-bit, four 32-bit values in `[w3, w2, w1, w0]` order)
* **Condition register:** `cr` (32-bit combined condition flags)

## Examples

### Basic Test Generation

```bash theme={null}
rexglue recompile-tests \
  --bin-dir ./tests/ppc/bin \
  --asm-dir ./tests/ppc/asm \
  --output ./tests/generated
```

Output:

```
ReXGlue v0.1.0 - Xbox 360 Recompilation Toolkit
Recompiling PPC tests...
  Bin dir: ./tests/ppc/bin
  ASM dir: ./tests/ppc/asm
  Output dir: ./tests/generated
[Debug] Processing binary file: test_arithmetic
[Debug]   Found 24 functions
[Debug] Processing binary file: test_vector
[Debug]   Found 18 functions
Generated 42 test cases
Operation completed successfully in 1.234s
```

## Generated Output

### ppc\_config.h

Defines the memory layout for test execution:

```cpp theme={null}
// Generated by rexglue recompile-tests
#ifndef PPC_CONFIG_H_INCLUDED
#define PPC_CONFIG_H_INCLUDED

// Test code base address (matches -Ttext=0x82010000 linker option)
#define PPC_IMAGE_BASE 0x82010000ull
#define PPC_IMAGE_SIZE 0x100000ull
#define PPC_CODE_BASE 0x82010000ull
#define PPC_CODE_SIZE 0x100000ull

#endif // PPC_CONFIG_H_INCLUDED
```

### ppc\_test\_functions.cpp

Contains recompiled PPC functions:

```cpp theme={null}
// Generated by rexglue recompile-tests
#include "ppc_config.h"
#include <rex/ppc.h>
#include <rex/logging.h>

// Forward declarations
PPC_EXTERN_FUNC(test_arithmetic_82010000);
PPC_EXTERN_FUNC(test_arithmetic_82010010);
// ...

PPC_FUNC(test_arithmetic_82010000) {
  // Recompiled code
}
```

### ppc\_test\_cases.cpp

Generated Catch2 test cases:

```cpp theme={null}
// Generated by rexglue recompile-tests
#include <catch2/catch_test_macros.hpp>
#include "ppc_config.h"
#include <rex/ppc.h>
#include <rex/system/xmemory.h>
#include "ppc_test_decls.h"

TEST_CASE("test_add", "[ppc][arithmetic][test_arithmetic]") {
    auto& mem = get_memory();
    uint8_t* memory = mem.virtual_membase();
    PPCContext ctx{};
    ctx.fpscr.loadFromHost();

    ctx.r3.u64 = 0x10;
    ctx.r4.u64 = 0x20;

    test_arithmetic_82010000(ctx, memory);

    REQUIRE(ctx.r5.u64 == 0x30);
}
```

### ppc\_test\_decls.h

Function declarations for test cases:

```cpp theme={null}
// Generated by rexglue recompile-tests
#pragma once

#include "ppc_config.h"
#include <rex/ppc.h>

PPC_EXTERN_FUNC(test_arithmetic_82010000);
PPC_EXTERN_FUNC(test_vector_82010020);
// ...
```

## Building Test Binaries

The `.bin` and `.map` files are typically generated from assembly sources using a PowerPC cross-compiler:

```bash theme={null}
# Assemble and link (example using powerpc-eabi-gcc)
powerpc-eabi-gcc -c test_arithmetic.s -o test_arithmetic.o
powerpc-eabi-ld -Ttext=0x82010000 test_arithmetic.o -o test_arithmetic.elf
powerpc-eabi-objcopy -O binary test_arithmetic.elf test_arithmetic.bin
powerpc-eabi-nm test_arithmetic.elf > test_arithmetic.map
```

<Warning>
  The base address **must** be `0x82010000` to match the `TEST_BASE_ADDRESS` constant in the recompile-tests implementation.
</Warning>

## Running Generated Tests

The generated test files integrate with Catch2:

```bash theme={null}
# Build test executable (example CMake configuration)
cmake --build build --target ppc_tests

# Run all tests
./build/ppc_tests

# Run specific category
./build/ppc_tests "[arithmetic]"

# Run specific test
./build/ppc_tests "test_add"
```

## Test Categories

Tests are automatically tagged based on file naming:

| File Pattern                       | Category         | Description                   |
| ---------------------------------- | ---------------- | ----------------------------- |
| `*add*`, `*sub*`, `*mul*`, `*div*` | `arithmetic`     | Integer arithmetic            |
| `*cmp*`                            | `comparison`     | Comparison operations         |
| `*and*`, `*or*`, `*xor*`, `*rl*`   | `logical`        | Logical and rotate            |
| `f*`, `*_f*`                       | `floating_point` | Floating point operations     |
| `v*`, `*_v*`                       | `vector`         | VMX/AltiVec vector operations |
| `l*`, `st*`                        | `memory`         | Load/store operations         |
| Other                              | `misc`           | Miscellaneous instructions    |

## Common Errors

### Missing Required Flags

```
--bin-dir, --asm-dir, and --output are required
```

**Solution:** Provide all three required directory paths.

### No Symbols in Map File

```
No symbols found in map file: ./tests/ppc/bin/test_arithmetic.map
```

**Solution:** Ensure your map file is in `nm` format with symbols at the correct base address.

### Test Recompilation Failed

```
Test recompilation failed
```

**Solution:** Check logs for details about which function failed to recompile. The assembly may contain unimplemented instructions.

## Limitations

* **Fixed base address:** Tests must be linked at `0x82010000`
* **No imports:** Test functions cannot call external libraries
* **Single module:** All test functions must be self-contained
* **No OS calls:** Tests run in isolated memory without kernel/OS support

## Use Cases

1. **Recompiler validation** - Ensure instructions are recompiled correctly
2. **Regression testing** - Catch recompiler bugs during development
3. **Instruction coverage** - Track which PPC instructions are implemented
4. **Accuracy testing** - Verify edge cases and corner conditions

## Next Steps

* Review [Recompiler Architecture](/concepts/recompiler)
* Learn about [PPC Instruction Set](/reference/ppc-instructions)
* Understand [Testing Strategy](/development/testing)


# Xbox 360 Kernel Emulation
Source: https://rexglue-rexglue-sdk.mintlify.app/concepts/kernel-emulation

How ReXGlue emulates the Xbox 360 operating system and kernel services

## Overview

The Xbox 360 runs a custom operating system based on a stripped-down Windows NT kernel. ReXGlue emulates the kernel APIs (xboxkrnl.exe) and system libraries (xam.xex) to provide a compatible runtime environment for Xbox 360 games.

<Info>
  ReXGlue uses **High-Level Emulation (HLE)** for kernel calls. System functions are reimplemented in native C++ rather than recompiling the kernel itself.
</Info>

## Kernel Architecture

The `KernelState` (source:include/rex/system/kernel\_state.h:111) is the central manager for all kernel emulation:

```cpp theme={null}
class KernelState {
public:
  Runtime* emulator() const;
  memory::Memory* memory() const;
  runtime::Processor* processor() const;
  
  // Module Management
  void RegisterModule(XModule* module);
  object_ref<XModule> GetModule(const std::string_view name);
  object_ref<UserModule> LoadUserModule(const std::string_view name);
  
  // Thread Management
  void RegisterThread(XThread* thread);
  object_ref<XThread> GetThreadByID(uint32_t thread_id);
  void OnThreadExecute(XThread* thread);
  void OnThreadExit(XThread* thread);
  
  // Object Table (kernel handles)
  util::ObjectTable* object_table();
  
  // System Services
  xam::AppManager* app_manager() const;
  xam::ContentManager* content_manager() const;
  xam::UserProfile* user_profile() const;
  
  // Process Information
  uint32_t process_type() const;
  uint32_t process_info_block_address() const;
  
  // Thread-Local Storage
  uint32_t AllocateTLS();
  void FreeTLS(uint32_t slot);
  
  // Title Lifecycle
  void TerminateTitle();
  
private:
  Runtime* emulator_;
  memory::Memory* memory_;
  util::ObjectTable object_table_;  // Kernel handle table
  std::vector<object_ref<KernelModule>> kernel_modules_;
  std::vector<object_ref<UserModule>> user_modules_;
};
```

## Process Information Block

The PIB (source:include/rex/system/kernel\_state.h:81) contains process metadata:

```cpp theme={null}
struct ProcessInfoBlock {
  rex::be<uint32_t> unk_00;
  rex::be<uint32_t> unk_04;  // blink
  rex::be<uint32_t> unk_08;  // flink
  rex::be<uint32_t> thread_count;
  rex::be<uint32_t> kernel_stack_size;
  rex::be<uint32_t> tls_data_size;
  rex::be<uint32_t> tls_raw_data_size;
  rex::be<uint16_t> tls_slot_size;
  uint8_t process_type;  // X_PROCTYPE_USER, X_PROCTYPE_SYSTEM, etc.
  rex::be<uint32_t> bitmap[0x20 / 4];  // TLS allocation bitmap
};
```

Process types (source:include/rex/system/kernel\_state.h:77):

```cpp theme={null}
constexpr uint32_t X_PROCTYPE_IDLE = 0;
constexpr uint32_t X_PROCTYPE_USER = 1;    // Game process
constexpr uint32_t X_PROCTYPE_SYSTEM = 2;  // System process
```

## Kernel Modules

ReXGlue implements Xbox 360 system libraries:

### xboxkrnl.exe (Kernel)

Core OS functions:

* **Threading**: `NtCreateThread`, `KeWaitForSingleObject`, `KePulseEvent`
* **Memory**: `NtAllocateVirtualMemory`, `NtFreeVirtualMemory`, `NtProtectVirtualMemory`
* **I/O**: `NtCreateFile`, `NtReadFile`, `NtWriteFile`, `NtQueryDirectoryFile`
* **Synchronization**: Mutexes, semaphores, events, timers
* **Exceptions**: `RtlRaiseException`, `KeBugCheck`

### xam.xex (Xbox Application Manager)

High-level services:

* **User Profiles**: `XamUserGetSigninState`, `XamUserGetName`
* **Content**: `XamContentCreate`, `XamContentGetThumbnail`
* **Networking**: `XamNetGetTitleOpaqueId`, `XamNetGetEthernetLinkStatus`
* **UI**: `XamShowMessageBoxUI`, `XamShowKeyboardUI`
* **Achievements**: `XamUserWriteAchievements`, `XamUserCreateAchievementEnumerator`

### xbdm.xex (Xbox Debug Monitor)

Debugger support (usually stubbed).

## Object Table

Kernel handles are managed by the `ObjectTable` (source:include/rex/system/kernel\_state.h:132):

```cpp theme={null}
class ObjectTable {
public:
  X_STATUS AddHandle(XObject* object, X_HANDLE* out_handle);
  object_ref<XObject> LookupObject(X_HANDLE handle);
  X_STATUS RemoveHandle(X_HANDLE handle);
  
  template <typename T>
  object_ref<T> LookupObject(X_HANDLE handle) {
    auto obj = LookupObject(handle);
    return object_ref<T>(reinterpret_cast<T*>(obj.release()));
  }
};
```

**Kernel Object Types:**

* `XThread` - Guest thread
* `XEvent` - Event object (manual/auto-reset)
* `XSemaphore` - Counting semaphore
* `XMutant` - Mutex (called "mutant" in NT kernel)
* `XTimer` - Waitable timer
* `XFile` - File handle
* `XSocket` - Network socket
* `XModule` - Loaded module (DLL/XEX)

Each object has a reference count and can be waited on (some types).

## Threading Model

### XThread

Each guest thread is represented by `XThread`:

```cpp theme={null}
class XThread : public XObject {
public:
  uint32_t thread_id() const;
  uint32_t guest_thread() const;  // XTHREAD structure address
  
  bool Create();
  X_STATUS Exit(int exit_code);
  X_STATUS Terminate(int exit_code);
  
  X_STATUS Suspend(uint32_t* out_suspend_count);
  X_STATUS Resume(uint32_t* out_suspend_count);
  
  void DeliverAPCs();
  
private:
  PPCContext* context_;          // CPU state
  uint32_t guest_thread_;        // Address of XTHREAD
  uint32_t thread_state_address_; // Thread-local storage
  std::thread native_thread_;    // Host OS thread
};
```

### Thread Creation Flow

1. Game calls `NtCreateThread(entry_point, ...)`
2. ReXGlue allocates `XTHREAD` structure in guest memory
3. Creates `XThread` object and adds to object table
4. Spawns native host thread via `std::thread`
5. Host thread calls `Processor::Execute(thread_state, entry_point)`
6. Recompiled guest code executes in host thread

### Context Switching

ReXGlue uses **cooperative multithreading** via native host threads:

* Each guest thread = one host thread
* Host OS scheduler handles preemption
* No PowerPC context switches needed

**Advantages:**

* Leverages host OS scheduler
* True parallelism on multi-core systems
* No complex context save/restore

**Disadvantages:**

* Guest timing may differ from real hardware
* Race conditions if game relies on Xbox 360 scheduler quirks

## Synchronization Primitives

### Events

```cpp theme={null}
class XEvent : public XObject {
public:
  void Set();    // Signal the event
  void Pulse();  // Signal and immediately reset
  void Reset();  // Clear the event
  
  bool Wait(uint64_t timeout_ms);
  
private:
  bool manual_reset_;  // Manual or auto-reset
  std::condition_variable cond_;
  std::mutex mutex_;
};
```

### Mutexes (Mutants)

```cpp theme={null}
class XMutant : public XObject {
public:
  X_STATUS ReleaseMutant(int* out_previous_count);
  bool Wait(uint64_t timeout_ms);
  
private:
  std::recursive_mutex mutex_;
  uint32_t owner_thread_id_;
};
```

### Semaphores

```cpp theme={null}
class XSemaphore : public XObject {
public:
  X_STATUS Release(int count, int* out_previous_count);
  bool Wait(uint64_t timeout_ms);
  
private:
  std::counting_semaphore<> semaphore_;
};
```

## File I/O

ReXGlue translates Xbox 360 file paths to the host filesystem via `VirtualFileSystem`:

### Path Mapping

```cpp theme={null}
// Xbox 360 paths:
// "game:\\data\\level1.map" -> "<game_directory>/data/level1.map"
// "d:\\saves\\profile.dat" -> "<content_root>/00000001/saves/profile.dat"
// "hdd1:\\cache\\..."      -> "<cache_directory>/..."
```

### NtCreateFile

```cpp theme={null}
X_STATUS NtCreateFile(X_HANDLE* handle_out, uint32_t desired_access,
                      X_OBJECT_ATTRIBUTES* obj_attrs, X_IO_STATUS_BLOCK* io_status,
                      uint64_t* allocation_size, uint32_t file_attributes,
                      uint32_t share_access, uint32_t creation_disposition,
                      uint32_t create_options) {
  auto path = obj_attrs->name.value();  // Wide string
  auto vfs_path = vfs->ResolvePath(path);
  
  auto file = vfs->OpenFile(vfs_path, desired_access, creation_disposition);
  if (!file) {
    return X_STATUS_NO_SUCH_FILE;
  }
  
  auto xfile = object_ref<XFile>(new XFile(file));
  kernel_state()->object_table()->AddHandle(xfile, handle_out);
  return X_STATUS_SUCCESS;
}
```

### NtReadFile / NtWriteFile

```cpp theme={null}
X_STATUS NtReadFile(X_HANDLE handle, X_HANDLE event,
                    uint32_t apc_routine, uint32_t apc_context,
                    uint32_t io_status_block, uint32_t buffer,
                    uint32_t buffer_length, uint64_t* byte_offset) {
  auto file = kernel_state()->object_table()->LookupObject<XFile>(handle);
  if (!file) {
    return X_STATUS_INVALID_HANDLE;
  }
  
  auto host_buffer = memory()->TranslateVirtual(buffer);
  size_t bytes_read = file->Read(host_buffer, buffer_length, byte_offset);
  
  // Write io_status_block
  auto io_status = memory()->TranslateVirtual<X_IO_STATUS_BLOCK*>(io_status_block);
  io_status->status = X_STATUS_SUCCESS;
  io_status->information = bytes_read;
  
  return X_STATUS_SUCCESS;
}
```

## Memory Management

### NtAllocateVirtualMemory

```cpp theme={null}
X_STATUS NtAllocateVirtualMemory(uint32_t* base_address, uint32_t* region_size,
                                 uint32_t allocation_type, uint32_t protect) {
  auto heap = memory()->LookupHeap(*base_address);
  if (!heap) {
    return X_STATUS_INVALID_PARAMETER;
  }
  
  uint32_t allocated_address = 0;
  bool success = heap->Alloc(*region_size, 0x1000, allocation_type, 
                             protect, false, &allocated_address);
  
  if (!success) {
    return X_STATUS_NO_MEMORY;
  }
  
  *base_address = allocated_address;
  return X_STATUS_SUCCESS;
}
```

### NtFreeVirtualMemory

```cpp theme={null}
X_STATUS NtFreeVirtualMemory(uint32_t* base_address, uint32_t* region_size,
                             uint32_t free_type) {
  auto heap = memory()->LookupHeap(*base_address);
  if (!heap) {
    return X_STATUS_INVALID_PARAMETER;
  }
  
  if (free_type == kMemoryDecommit) {
    heap->Decommit(*base_address, *region_size);
  } else {
    heap->Release(*base_address, region_size);
  }
  
  return X_STATUS_SUCCESS;
}
```

## Interrupt Request Level (IRQL)

The Xbox 360 kernel uses **IRQL** to control interrupt priority (source:include/rex/system/processor.h:43):

```cpp theme={null}
enum class Irql : uint32_t {
  PASSIVE = 0,   // Normal execution
  APC = 1,       // Asynchronous procedure calls
  DISPATCH = 2,  // Scheduler/DPCs
  DPC = 3,       // Deferred procedure calls
};
```

ReXGlue tracks IRQL per-CPU:

```cpp theme={null}
class Processor {
public:
  Irql RaiseIrql(Irql new_value) {
    Irql old_value = current_irql();
    irql_.store(static_cast<uint32_t>(new_value));
    return old_value;
  }
  
  void LowerIrql(Irql old_value) {
    irql_.store(static_cast<uint32_t>(old_value));
  }
  
private:
  std::atomic<uint32_t> irql_{static_cast<uint32_t>(Irql::PASSIVE)};
};
```

Raising IRQL disables certain interrupts and thread switches.

## Deferred Procedure Calls (DPCs)

DPCs allow low-priority work to execute asynchronously (source:include/rex/system/kernel\_state.h:184):

```cpp theme={null}
util::NativeList* dpc_list() { return &dpc_list_; }
```

The kernel maintains a DPC queue processed by a dedicated dispatcher thread.

## Overlapped I/O

Asynchronous I/O operations use `OVERLAPPED` structures (source:include/rex/system/kernel\_state.h:186):

```cpp theme={null}
void CompleteOverlapped(uint32_t overlapped_ptr, X_RESULT result) {
  auto overlapped = memory()->TranslateVirtual<X_OVERLAPPED*>(overlapped_ptr);
  overlapped->result = result;
  overlapped->length = 0;
  
  // Signal event if specified
  if (overlapped->event) {
    auto event = object_table()->LookupObject<XEvent>(overlapped->event);
    if (event) {
      event->Set();
    }
  }
}

void CompleteOverlappedDeferred(
    std::move_only_function<void()> completion_callback,
    uint32_t overlapped_ptr, X_RESULT result) {
  // Queue work on dispatch thread
  dispatch_queue_.push_back([=, cb = std::move(completion_callback)]() {
    cb();
    CompleteOverlapped(overlapped_ptr, result);
  });
  dispatch_cond_.notify_one();
}
```

This allows network I/O, file I/O, etc. to complete asynchronously without blocking the game thread.

## Exception Handling

### Structured Exception Handling (SEH)

ReXGlue uses native SEH on Windows and signal handlers on POSIX:

```cpp theme={null}
void SetupExceptionHandlers() {
#if REX_PLATFORM_WIN32
  AddVectoredExceptionHandler(1, VectoredExceptionHandler);
#else
  struct sigaction sa = {};
  sa.sa_sigaction = SignalHandler;
  sa.sa_flags = SA_SIGINFO;
  sigaction(SIGSEGV, &sa, nullptr);
  sigaction(SIGILL, &sa, nullptr);
#endif
}
```

Access violations (e.g., writing to protected physical memory) trigger callbacks for cache invalidation.

### Guest Exceptions

PowerPC exceptions are emulated:

* **Trap instructions** (`tw`, `twi`) call `ppc_trap()`
* **Illegal instructions** throw `std::runtime_error`
* **Floating-point exceptions** controlled by FPSCR

## System Services

### App Manager

```cpp theme={null}
class AppManager {
public:
  uint32_t GetTitleId();  // Title ID from XEX
  void SetLocale(uint32_t locale);  // Language setting
};
```

### Content Manager

Manages save data, DLC, and user content:

```cpp theme={null}
class ContentManager {
public:
  X_RESULT CreateContent(const std::string& path, ContentType type);
  X_RESULT EnumerateContent(ContentType type, std::vector<ContentData>& out);
};
```

### User Profile

```cpp theme={null}
class UserProfile {
public:
  std::string GetName();
  uint64_t GetXUID();  // Xbox User ID
  X_RESULT ReadSetting(uint32_t setting_id, Setting& out);
  X_RESULT WriteSetting(uint32_t setting_id, const Setting& value);
};
```

## Import Resolution

When a game XEX imports a kernel function:

1. **Symbol lookup**: Import name (e.g., `"NtCreateFile"`) is looked up
2. **Ordinal resolution**: Alternatively, import by ordinal (e.g., `ordinal 400`)
3. **Thunk generation**: Recompiler generates a thunk:
   ```cpp theme={null}
   PPC_FUNC_IMPL(__imp_NtCreateFile) {
     PPC_FUNC_PROLOGUE();
     NtCreateFile_impl(ctx, base);  // Call native implementation
   }
   ```
4. **Function table registration**: Host function pointer stored in function table

## Kernel Tracing

ReXGlue provides logging macros for debugging kernel calls (source:include/rex/system/kernel\_state.h:40):

```cpp theme={null}
#define REXKRNL_IMPORT_TRACE(name, fmt, ...) \
  REXKRNL_TRACE("[" name "] " fmt, ##__VA_ARGS__)

#define REXKRNL_IMPORT_RESULT(name, fmt, ...) \
  REXKRNL_TRACE("[" name "] -> " fmt, ##__VA_ARGS__)

#define REXKRNL_IMPORT_FAIL(name, fmt, ...) \
  REXKRNL_WARN("[" name "] FAILED: " fmt, ##__VA_ARGS__)
```

**Example:**

```cpp theme={null}
REXKRNL_IMPORT_TRACE("NtCreateFile", "path={}", path);
// ... implementation ...
REXKRNL_IMPORT_RESULT("NtCreateFile", "handle={:#x}", handle);
```

Output:

```
[NtCreateFile] path="game:\data\level1.map"
[NtCreateFile] -> handle=0x10
```

## See Also

* [Memory Model](/concepts/memory-model) - System heap and kernel allocations
* [PowerPC Emulation](/concepts/ppc-emulation) - Context structure and execution
* [Static Recompilation](/concepts/recompilation) - Import thunk generation


# Virtual Memory Layout
Source: https://rexglue-rexglue-sdk.mintlify.app/concepts/memory-model

Xbox 360 memory architecture and ReXGlue's address translation system

## Overview

The Xbox 360 uses a **4GB virtual address space** with a complex memory layout involving multiple heaps, page sizes, and memory-mapped regions. ReXGlue emulates this layout by mapping guest addresses into the host process's address space.

## Virtual Address Space Layout

The Xbox 360 memory map (source:include/rex/system/xmemory.h:286):

```
┌──────────────────────────────────────────────────────────────┐
│ 0x00000000 - 0x3FFFFFFF  Virtual Heap (1GB)                 │  4KB pages
│                          - Game allocations                  │
│                          - XEX image loaded here             │
├──────────────────────────────────────────────────────────────┤
│ 0x40000000 - 0x7EFFFFFF  Virtual Heap (1GB - 16MB)          │  64KB pages
│                          - Rarely used                       │
├──────────────────────────────────────────────────────────────┤
│ 0x7F000000 - 0x7FFFFFFF  MMIO Range (16MB)                  │  Hardware I/O
│                          - GPU registers (0x7FC80000)        │
│                          - Audio, video, etc.                │
├──────────────────────────────────────────────────────────────┤
│ 0x80000000 - 0x8FFFFFFF  XEX Heap (256MB)                   │  64KB pages
│                          - Executable images                 │
├──────────────────────────────────────────────────────────────┤
│ 0x90000000 - 0x9FFFFFFF  System Virtual Heap (256MB)        │  64KB pages
│                          - Kernel allocations                │
├──────────────────────────────────────────────────────────────┤
│ 0xA0000000 - 0xBFFFFFFF  Physical Heap (512MB)              │  64KB pages
│                          - Direct physical memory access     │
├──────────────────────────────────────────────────────────────┤
│ 0xC0000000 - 0xDFFFFFFF  Physical Heap (512MB)              │  16MB pages
│                          - Large page allocations            │
├──────────────────────────────────────────────────────────────┤
│ 0xE0000000 - 0xFFFFFFFF  Physical Heap (512MB)              │  4KB pages
│                          - Small page allocations            │
└──────────────────────────────────────────────────────────────┘
```

<Info>
  The Xbox 360 has **512MB of physical RAM**, but the virtual address space is **4GB**. Virtual heaps are backed by physical memory through the page table.
</Info>

## Memory Class

The `Memory` class (source:include/rex/system/xmemory.h:286) manages the entire guest memory system:

```cpp theme={null}
class Memory {
public:
  bool Initialize();  // Set up memory-mapped file and heaps
  void Reset();       // Zero all memory and reset allocations
  
  // Address Translation
  template <typename T = uint8_t*>
  inline T TranslateVirtual(uint32_t guest_address) const {
    uint8_t* host_address = virtual_membase_ + guest_address;
    const auto heap = LookupHeap(guest_address);
    if (heap) {
      host_address += heap->host_address_offset();
    }
    return reinterpret_cast<T>(host_address);
  }
  
  template <typename T = uint8_t*>
  inline T TranslatePhysical(uint32_t guest_address) const {
    return reinterpret_cast<T>(physical_membase_ + (guest_address & 0x1FFFFFFF));
  }
  
  uint32_t HostToGuestVirtual(const void* host_address) const;
  uint32_t GetPhysicalAddress(uint32_t virtual_address) const;
  
  // Memory Operations
  void Zero(uint32_t address, uint32_t size);
  void Fill(uint32_t address, uint32_t size, uint8_t value);
  void Copy(uint32_t dest, uint32_t src, uint32_t size);
  
  // System Heap (kernel allocations)
  uint32_t SystemHeapAlloc(uint32_t size, uint32_t alignment = 0x20);
  void SystemHeapFree(uint32_t address);
  
private:
  std::filesystem::path file_name_;  // Memory-mapped file path
  uint8_t* virtual_membase_ = nullptr;   // Host base for virtual memory
  uint8_t* physical_membase_ = nullptr;  // Host base for physical memory
  
  struct {
    VirtualHeap v00000000;  // 0x00000000 - 4KB pages
    VirtualHeap v40000000;  // 0x40000000 - 64KB pages
    VirtualHeap v80000000;  // 0x80000000 - XEX heap
    VirtualHeap v90000000;  // 0x90000000 - System heap
    VirtualHeap physical;   // Physical backing
    PhysicalHeap vA0000000; // 0xA0000000 - 64KB pages
    PhysicalHeap vC0000000; // 0xC0000000 - 16MB pages
    PhysicalHeap vE0000000; // 0xE0000000 - 4KB pages
  } heaps_;
};
```

## Heap Architecture

### BaseHeap

All heaps derive from `BaseHeap` (source:include/rex/system/xmemory.h:103):

```cpp theme={null}
class BaseHeap {
public:
  uint32_t heap_base() const { return heap_base_; }      // Offset from membase
  uint32_t heap_size() const { return heap_size_; }      // Total size in bytes
  uint32_t page_size() const { return page_size_; }      // Page size (4KB/64KB/16MB)
  uint32_t host_address_offset() const;                  // Windows granularity fix
  
  // Allocation API
  virtual bool Alloc(uint32_t size, uint32_t alignment, 
                     uint32_t allocation_type, uint32_t protect,
                     bool top_down, uint32_t* out_address);
  
  virtual bool AllocFixed(uint32_t base_address, uint32_t size, 
                          uint32_t alignment, uint32_t allocation_type,
                          uint32_t protect);
  
  virtual bool Decommit(uint32_t address, uint32_t size);
  virtual bool Release(uint32_t address, uint32_t* out_region_size);
  virtual bool Protect(uint32_t address, uint32_t size, uint32_t protect);
  
  // Query API
  bool QueryRegionInfo(uint32_t base_address, HeapAllocationInfo* out_info);
  bool QueryProtect(uint32_t address, uint32_t* out_protect);
  
protected:
  memory::Memory* memory_;
  uint8_t* membase_;              // Base address in host memory
  uint32_t heap_base_;            // Offset from membase
  uint32_t heap_size_;            // Total heap size
  uint32_t page_size_;            // Page granularity
  uint32_t host_address_offset_;  // Platform-specific offset
  std::vector<PageEntry> page_table_;  // Page allocation tracking
};
```

### Page Table

Each heap maintains a page table with allocation metadata (source:include/rex/system/xmemory.h:83):

```cpp theme={null}
union PageEntry {
  uint64_t qword;
  struct {
    uint32_t base_address : 20;       // Base of allocated region (4K pages)
    uint32_t region_page_count : 20;  // Size in 4K pages
    uint32_t allocation_protect : 4;  // Original protection flags
    uint32_t current_protect : 4;     // Current protection flags
    uint32_t state : 2;               // Reserve/Commit/Free
    uint32_t reserved : 14;
  };
};
```

Each entry represents one **4KB page**, even if the heap uses larger pages (64KB/16MB). The `region_page_count` tracks contiguous allocations.

### Protection Flags

```cpp theme={null}
enum MemoryProtectFlag : uint32_t {
  kMemoryProtectRead = 1 << 0,
  kMemoryProtectWrite = 1 << 1,
  kMemoryProtectNoCache = 1 << 2,
  kMemoryProtectWriteCombine = 1 << 3,
  kMemoryProtectNoAccess = 0,
};
```

### VirtualHeap

Standard heap for virtual address ranges (source:include/rex/system/xmemory.h:209):

```cpp theme={null}
class VirtualHeap : public BaseHeap {
public:
  void Initialize(memory::Memory* memory, uint8_t* membase, 
                  HeapType heap_type, uint32_t heap_base,
                  uint32_t heap_size, uint32_t page_size);
};
```

Used for:

* `0x00000000` - Game allocations (4KB pages)
* `0x40000000` - Rarely used virtual heap (64KB pages)
* `0x80000000` - XEX images (64KB pages)
* `0x90000000` - System heap (64KB pages)

### PhysicalHeap

Physical heaps mirror allocations to a "parent" virtual heap (source:include/rex/system/xmemory.h:226):

```cpp theme={null}
class PhysicalHeap : public BaseHeap {
public:
  void Initialize(memory::Memory* memory, uint8_t* membase,
                  HeapType heap_type, uint32_t heap_base,
                  uint32_t heap_size, uint32_t page_size,
                  VirtualHeap* parent_heap);
  
  uint32_t GetPhysicalAddress(uint32_t virtual_address) const;
  
  // Invalidation callbacks for GPU/audio caches
  void EnableAccessCallbacks(uint32_t physical_address, uint32_t length,
                             bool enable_invalidation_notifications,
                             bool enable_data_providers);
  
  bool TriggerCallbacks(std::unique_lock<std::recursive_mutex> lock,
                        uint32_t virtual_address, uint32_t length,
                        bool is_write, bool unwatch_exact_range);
  
protected:
  VirtualHeap* parent_heap_;
  std::vector<SystemPageFlagsBlock> system_page_flags_;  // Write-watch flags
};
```

Physical allocations at `0xA0000000`, `0xC0000000`, or `0xE0000000` automatically create a 1:1 mapping in the parent virtual heap.

## Address Translation

### Virtual to Host

```cpp theme={null}
template <typename T = uint8_t*>
inline T TranslateVirtual(uint32_t guest_address) const {
  uint8_t* host_address = virtual_membase_ + guest_address;
  const auto heap = LookupHeap(guest_address);
  if (heap) {
    host_address += heap->host_address_offset();
  }
  return reinterpret_cast<T>(host_address);
}
```

**Example:**

* Guest address: `0x82E00000`
* `virtual_membase_`: `0x100000000` (host)
* Host address: `0x100000000 + 0x82E00000 = 0x182E00000`

### Physical to Host

```cpp theme={null}
template <typename T = uint8_t*>
inline T TranslatePhysical(uint32_t guest_address) const {
  return reinterpret_cast<T>(physical_membase_ + (guest_address & 0x1FFFFFFF));
}
```

Physical addresses are masked to 29 bits (512MB), then added to `physical_membase_`.

### Host to Guest

```cpp theme={null}
uint32_t HostToGuestVirtual(const void* host_address) const {
  auto addr = reinterpret_cast<uintptr_t>(host_address);
  auto base_addr = reinterpret_cast<uintptr_t>(virtual_membase_);
  if (addr < base_addr || addr >= (base_addr + 0x100000000ull)) {
    return 0;  // Out of range
  }
  return static_cast<uint32_t>(addr - base_addr);
}
```

## Memory-Mapped File

ReXGlue backs the entire 4GB guest memory with a memory-mapped file (source:include/rex/system/xmemory.h:299):

```cpp theme={null}
std::filesystem::path file_name_;  // Usually "xenia_memory.bin"
FileMappingHandle mapping_;        // OS-specific file handle
uint8_t* mapping_base_;             // Base of mapped region
```

**Benefits:**

1. **Persistence**: Memory state can be saved/restored by copying the file
2. **Swapping**: OS can page unused memory to disk
3. **Large allocations**: No need for giant `malloc()`

### Memory Views

Different address ranges are mapped to the same physical file at different offsets:

```cpp theme={null}
union {
  struct {
    uint8_t* v00000000;  // Virtual 0x00000000 - 0x3FFFFFFF
    uint8_t* v40000000;  // Virtual 0x40000000 - 0x7EFFFFFF
    uint8_t* v7F000000;  // MMIO (not backed by file)
    uint8_t* v80000000;  // XEX heap
    uint8_t* v90000000;  // System heap
    uint8_t* vA0000000;  // Physical 0x00000000 - 0x1FFFFFFF
    uint8_t* vC0000000;  // Physical (16MB pages)
    uint8_t* vE0000000;  // Physical (4KB pages)
    uint8_t* physical;   // Physical backing
  };
  uint8_t* all_views[9];
} views_;
```

## MMIO Handling

The range `0x7F000000 - 0x7FFFFFFF` is **not backed by memory**. Accesses go through the `MMIOHandler` (source:include/rex/system/xmemory.h:354):

```cpp theme={null}
bool AddVirtualMappedRange(uint32_t virtual_address, uint32_t mask,
                           uint32_t size, void* context,
                           runtime::MMIOReadCallback read_callback,
                           runtime::MMIOWriteCallback write_callback);

runtime::MMIORange* LookupVirtualMappedRange(uint32_t virtual_address);
```

**Example - GPU Register:**

```cpp theme={null}
// 0x7FC80000 - GPU command processor
memory->AddVirtualMappedRange(
  0x7FC80000, 0xFFFF0000, 0x10000, gpu_context,
  [](void* ctx, uint32_t addr, uint32_t* out_value) {
    auto gpu = static_cast<GPU*>(ctx);
    *out_value = gpu->ReadRegister(addr);
    return true;
  },
  [](void* ctx, uint32_t addr, uint32_t value) {
    auto gpu = static_cast<GPU*>(ctx);
    gpu->WriteRegister(addr, value);
    return true;
  }
);
```

## Physical Memory Callbacks

Physical heaps support **invalidation callbacks** for GPU/audio cache coherency (source:include/rex/system/xmemory.h:411):

```cpp theme={null}
typedef std::pair<uint32_t, uint32_t> (*PhysicalMemoryInvalidationCallback)(
    void* context_ptr, uint32_t physical_address_start, 
    uint32_t length, bool exact_range);

void* RegisterPhysicalMemoryInvalidationCallback(
    PhysicalMemoryInvalidationCallback callback, void* callback_context);

void UnregisterPhysicalMemoryInvalidationCallback(void* callback_handle);
```

**Use Case:**

When the CPU writes to a physical address that the GPU has cached:

1. Page protection triggers a write fault
2. ReXGlue calls all registered invalidation callbacks
3. GPU invalidates its cache for that region
4. Page is unprotected and write proceeds

## Function Table

For static recompilation, ReXGlue stores a function dispatch table in guest memory (source:include/rex/system/xmemory.h:473):

```cpp theme={null}
bool InitializeFunctionTable(uint32_t code_base, uint32_t code_size,
                             uint32_t image_base, uint32_t image_size);

void SetFunction(uint32_t guest_address, PPCFunc* host_function);
PPCFunc* GetFunction(uint32_t guest_address) const;
```

**Layout:**

```
Guest Address: IMAGE_BASE + IMAGE_SIZE + (guest_addr - CODE_BASE) * 2
Contents: 8-byte host function pointer
```

**Example:**

* `IMAGE_BASE = 0x82000000`
* `IMAGE_SIZE = 0x1000000` (16MB)
* `CODE_BASE = 0x82000000`
* Function at `0x82E00000`:
  * Table offset: `(0x82E00000 - 0x82000000) * 2 = 0x1C00000`
  * Table address: `0x82000000 + 0x1000000 + 0x1C00000 = 0x84C00000`

<Note>
  The `* 2` multiplier allows 8-byte pointers for every 4-byte-aligned address, using 2 bytes per possible function.
</Note>

## Platform-Specific Quirks

### Windows: Allocation Granularity

Windows requires memory mappings to align to **64KB boundaries**. The `0xE0000000` heap has a file offset of `0x1000`, which gets masked away. ReXGlue compensates with `host_address_offset_ = 0x1000` for that heap.

### Linux/macOS: 4KB Granularity

POSIX systems use 4KB granularity, so the file offset works correctly. `host_address_offset_ = 0`.

## Memory Operations

### Zero/Fill

```cpp theme={null}
void Zero(uint32_t address, uint32_t size) {
  std::memset(TranslateVirtual(address), 0, size);
}

void Fill(uint32_t address, uint32_t size, uint8_t value) {
  std::memset(TranslateVirtual(address), value, size);
}
```

### Copy

```cpp theme={null}
void Copy(uint32_t dest, uint32_t src, uint32_t size) {
  std::memmove(TranslateVirtual(dest), TranslateVirtual(src), size);
}
```

### Search

```cpp theme={null}
uint32_t SearchAligned(uint32_t start, uint32_t end,
                       const uint32_t* values, size_t value_count) {
  // Search for a pattern of big-endian dwords
  auto ptr = TranslateVirtual<uint32_t*>(start);
  auto end_ptr = TranslateVirtual<uint32_t*>(end);
  // ... scan and byte-swap compare ...
}
```

## System Heap

The system heap (source:include/rex/system/xmemory.h:436) is used for kernel allocations:

```cpp theme={null}
uint32_t SystemHeapAlloc(uint32_t size, uint32_t alignment = 0x20,
                         uint32_t system_heap_flags = kSystemHeapDefault);
void SystemHeapFree(uint32_t address);
```

Allocations come from the `0x90000000` heap, keeping kernel structures separate from game memory.

## See Also

* [Static Recompilation](/concepts/recompilation) - Function table initialization
* [PowerPC Emulation](/concepts/ppc-emulation) - Memory load/store macros
* [Kernel Emulation](/concepts/kernel-emulation) - System heap usage


# PowerPC Instruction Translation
Source: https://rexglue-rexglue-sdk.mintlify.app/concepts/ppc-emulation

How ReXGlue translates and executes PowerPC instructions on x86-64/ARM64

## Overview

ReXGlue translates PowerPC instructions to native C++ code that executes on x86-64 and ARM64 architectures. This page explains the instruction translation strategy, register mapping, and execution model.

## PPCContext Structure

The `PPCContext` (source:include/rex/ppc/context.h:170) represents the complete PowerPC processor state:

```cpp theme={null}
struct alignas(0x40) PPCContext {
  // Kernel state pointer
  rex::system::KernelState* kernel_state;
  
  // General Purpose Registers (GPRs)
  PPCRegister r0, r1, r2, r3, ..., r31;
  
  // Link Register and Count Register
  uint64_t lr;
  PPCRegister ctr;
  
  // Fixed-Point Exception Register
  PPCXERRegister xer;  // {so, ov, ca}
  
  // Condition Register fields
  PPCCRRegister cr0, cr1, ..., cr7;  // {lt, gt, eq, so/un}
  
  // Floating-Point Status and Control Register
  PPCFPSCRRegister fpscr;
  
  // Floating-Point Registers (FPRs)
  PPCRegister f0, f1, ..., f31;  // 64-bit doubles
  
  // Vector Registers (VMX/AltiVec)
  PPCVRegister v0, v1, ..., v127;  // 128-bit vectors
  
  // Vector Status and Control Register
  uint8_t vscr_sat;  // Saturation flag
};
```

<Info>
  The context is aligned to 64 bytes (`alignas(0x40)`) for optimal cache performance. It's passed by reference to every recompiled function.
</Info>

## Register Types

ReXGlue defines several register types (source:include/rex/ppc/types.h):

### General Purpose Register

```cpp theme={null}
union Register {
  int8_t s8;
  uint8_t u8;
  int16_t s16;
  uint16_t u16;
  int32_t s32;
  uint32_t u32;
  int64_t s64;
  uint64_t u64;
  float f32;
  double f64;
};
```

PowerPC GPRs are 64-bit, but most instructions only use the lower 32 bits. The union allows type-punning for efficient access.

### XER Register (Fixed-Point Exception)

```cpp theme={null}
struct XERRegister {
  uint8_t so;  // Summary Overflow
  uint8_t ov;  // Overflow
  uint8_t ca;  // Carry
};
```

Used by arithmetic instructions (`addc`, `subfe`, etc.).

### Condition Register Field

```cpp theme={null}
struct CRRegister {
  uint8_t lt;  // Less Than
  uint8_t gt;  // Greater Than
  uint8_t eq;  // Equal
  union {
    uint8_t so;  // Summary Overflow (integer)
    uint8_t un;  // Unordered (float - NaN)
  };
  
  template <typename T>
  inline void compare(T left, T right, const XERRegister& xer) {
    lt = left < right;
    gt = left > right;
    eq = left == right;
    so = xer.so;
  }
};
```

### Vector Register

```cpp theme={null}
union alignas(0x10) VRegister {
  int8_t s8[16];
  uint8_t u8[16];
  int16_t s16[8];
  uint16_t u16[8];
  int32_t s32[4];
  uint32_t u32[4];
  int64_t s64[2];
  uint64_t u64[2];
  float f32[4];
  double f64[2];
};
```

## Memory Access

PowerPC uses **big-endian** byte order, while x86-64 and most ARM64 systems use little-endian. ReXGlue handles byte swapping transparently.

### Load Macros

```cpp theme={null}
// Load with byte swap (source:include/rex/ppc/memory.h:54)
#define PPC_LOAD_U8(x)  (*(volatile uint8_t*)(base + (uint32_t)(x) + PPC_PHYS_HOST_OFFSET(x)))
#define PPC_LOAD_U16(x) __builtin_bswap16(*(volatile uint16_t*)(base + (uint32_t)(x) + ...))
#define PPC_LOAD_U32(x) __builtin_bswap32(*(volatile uint32_t*)(base + (uint32_t)(x) + ...))
#define PPC_LOAD_U64(x) __builtin_bswap64(*(volatile uint64_t*)(base + (uint32_t)(x) + ...))
```

### Store Macros

```cpp theme={null}
#define PPC_STORE_U8(x, y)  (*(volatile uint8_t*)(base + (uint32_t)(x) + ...) = (y))
#define PPC_STORE_U16(x, y) (*(volatile uint16_t*)(base + (uint32_t)(x) + ...) = __builtin_bswap16(y))
#define PPC_STORE_U32(x, y) (*(volatile uint32_t*)(base + (uint32_t)(x) + ...) = __builtin_bswap32(y))
#define PPC_STORE_U64(x, y) (*(volatile uint64_t*)(base + (uint32_t)(x) + ...) = __builtin_bswap64(y))
```

<Note>
  **Physical Heap Offset Workaround**

  On Windows, the allocation granularity is 64KB, so the 0x1000-byte file offset for the 0xE0000000 physical heap gets masked away. `PPC_PHYS_HOST_OFFSET()` compensates by adding 0x1000 to addresses ≥ 0xE0000000 (source:include/rex/ppc/memory.h:42).
</Note>

### MMIO (Memory-Mapped I/O)

Addresses in the range `0x7F000000 - 0x7FFFFFFF` are MMIO (GPU registers, audio, etc.). These go through the `MMIOHandler`:

```cpp theme={null}
#define PPC_MM_LOAD_U32(addr) \
  (PPC_IS_MMIO_ADDR(addr) \
    ? ({ uint32_t _v; \
         rex::runtime::MMIOHandler::global_handler()->CheckLoad(addr, &_v); \
         _v; }) \
    : __builtin_bswap32(*(volatile uint32_t*)(base + (addr) + ...)))
```

The recompiler uses MMIO macros when it detects MMIO base addresses in registers.

## Instruction Categories

### Integer Arithmetic

**Addition:**

```cpp theme={null}
// add r3, r4, r5
r3.u32 = r4.u32 + r5.u32;

// addi r3, r4, 0x10
r3.u32 = r4.u32 + 0x10;

// addic r3, r4, 0x10  (sets CA)
ctx.xer.ca = /* carry detection logic */;
r3.u32 = r4.u32 + 0x10;
```

**Comparison:**

```cpp theme={null}
// cmpw cr0, r3, r4
cr0.compare(r3.s32, r4.s32, ctx.xer);

// cmpwi cr0, r3, 0
cr0.compare(r3.s32, 0, ctx.xer);
```

### Floating-Point

**Arithmetic:**

```cpp theme={null}
// fadd f1, f2, f3
f1.f64 = f2.f64 + f3.f64;

// fmul f1, f2, f3
f1.f64 = f2.f64 * f3.f64;

// fmadd f1, f2, f3, f4  (f1 = f2*f3 + f4)
f1.f64 = std::fma(f2.f64, f3.f64, f4.f64);
```

**Rounding Mode:**

The `FPSCRRegister` manages x86-64 MXCSR or ARM64 FPCR rounding modes (source:include/rex/ppc/types.h:468):

```cpp theme={null}
struct FPSCRRegister {
  uint32_t csr;  // Host control/status register
  
  static constexpr size_t HostToGuest[] = {
    kRoundNearest,      // 0 -> 0
    kRoundDown,         // 1 -> 3
    kRoundUp,           // 2 -> 2
    kRoundTowardZero    // 3 -> 1
  };
  
  void storeFromGuest(uint32_t value) {
    csr &= ~RoundMaskVal;
    csr |= Platform::GuestToHost[value & kRoundMask];
    setcsr(csr);
  }
};
```

### Vector/SIMD (AltiVec/VMX)

ReXGlue uses [SIMDe](https://github.com/simd-everywhere/simde) for cross-platform SIMD:

```cpp theme={null}
#include <simde/x86/sse4.1.h>

// vadduwm v0, v1, v2  (add 4x uint32)
v0.v128 = simde_mm_add_epi32(v1.v128, v2.v128);

// vmaxsw v0, v1, v2  (max 4x int32)
v0.v128 = simde_mm_max_epi32(v1.v128, v2.v128);

// lvx v0, 0, r3  (load vector from memory)
v0.v128 = simde_mm_loadu_si128((simde__m128i*)(base + r3.u32));
```

**Custom Vector Helpers:**

Some AltiVec instructions require custom implementations (source:include/rex/ppc/memory.h:343):

```cpp theme={null}
// Vector Convert To Unsigned Fixed-Point Word Saturate
inline simde__m128i simde_mm_vctuxs(simde__m128 src1) {
  // Clamp to [0, UINT_MAX]
  simde__m128 clamped = simde_mm_max_ps(src1, simde_mm_setzero_ps());
  clamped = simde_mm_min_ps(clamped, simde_mm_set1_ps(4294967295.0f));
  // Convert with saturation logic...
}
```

### Branches and Calls

**Unconditional:**

```cpp theme={null}
// b 0x82E00100
PPC_CALL_FUNC(function_82E00100);

// bl 0x82E00100  (branch and link)
ctx.lr = /* return address */;
PPC_CALL_FUNC(function_82E00100);
```

**Conditional:**

```cpp theme={null}
// beq cr0, 0x82E00100
if (cr0.eq) {
  PPC_CALL_FUNC(function_82E00100);
}

// bne cr0, 0x82E00100
if (!cr0.eq) {
  PPC_CALL_FUNC(function_82E00100);
}
```

**Indirect:**

```cpp theme={null}
// bctr  (branch to count register)
PPC_CALL_INDIRECT_FUNC(ctx.ctr.u32);

// bctrl  (branch to count register and link)
ctx.lr = /* return address */;
PPC_CALL_INDIRECT_FUNC(ctx.ctr.u32);
```

### Load/Store

**Byte-swapping loads:**

```cpp theme={null}
// lwz r3, 0x10(r4)  (load word and zero)
r3.u32 = PPC_LOAD_U32(r4.u32 + 0x10);

// lhz r3, 0x10(r4)  (load halfword and zero)
r3.u32 = PPC_LOAD_U16(r4.u32 + 0x10);

// lbz r3, 0x10(r4)  (load byte and zero)
r3.u32 = PPC_LOAD_U8(r4.u32 + 0x10);
```

**Sign-extending loads:**

```cpp theme={null}
// lha r3, 0x10(r4)  (load halfword algebraic)
r3.s32 = (int32_t)(int16_t)PPC_LOAD_U16(r4.u32 + 0x10);
```

**Stores:**

```cpp theme={null}
// stw r3, 0x10(r4)
PPC_STORE_U32(r4.u32 + 0x10, r3.u32);

// sth r3, 0x10(r4)
PPC_STORE_U16(r4.u32 + 0x10, r3.u16);
```

## Special Instructions

### Timebase

```cpp theme={null}
// mftb r3  (move from time base)
r3.u64 = PPC_QUERY_TIMEBASE();

#define PPC_QUERY_TIMEBASE() rex::chrono::Clock::QueryGuestTickCount()
```

### Synchronization

```cpp theme={null}
// lwarx r3, 0, r4  (load word and reserve)
ctx.reserved.u32 = r4.u32;  // Save reservation address
r3.u32 = PPC_LOAD_U32(r4.u32);

// stwcx. r3, 0, r4  (store word conditional)
if (ctx.reserved.u32 == r4.u32) {
  PPC_STORE_U32(r4.u32, r3.u32);
  cr0.eq = 1;  // Success
} else {
  cr0.eq = 0;  // Failure
}
ctx.reserved.u32 = 0;  // Clear reservation
```

### Traps

Trap instructions generate exceptions (source:include/rex/ppc/context.h:502):

```cpp theme={null}
// twi 31, r0, 20  (unconditional trap - debug print)
inline void ppc_trap(PPCContext& ctx, uint8_t* base, uint16_t trap_type) {
  switch (trap_type) {
    case 20:
    case 26: {  // Debug print
      auto str = PPC_LOAD_STRING(ctx.r3.u32, ctx.r4.u16);
      REXCPU_DEBUG("(service trap) {}", str);
      break;
    }
    case 0:
    case 22:  // Debug break
      REXCPU_WARN("tw/td trap hit (type {})", trap_type);
      break;
  }
}
```

## Interrupt Handling

ReXGlue emulates PowerPC interrupt disable/enable via a global lock (source:include/rex/ppc/context.h:464):

```cpp theme={null}
// mfmsr r3  (move from machine state register)
r3.u64 = PPC_CHECK_GLOBAL_LOCK();  // Returns 0x8000 if unlocked

// mtmsr r13  (move to MSR from r13 - disable interrupts)
PPC_ENTER_GLOBAL_LOCK();

// mtmsr r3  (move to MSR from non-r13 - enable interrupts)
PPC_LEAVE_GLOBAL_LOCK();
```

The global lock uses `std::recursive_mutex` and atomic nesting counter.

## setjmp/longjmp

PowerPC `setjmp`/`longjmp` is tricky because the guest `jmp_buf` format is incompatible with the host. ReXGlue uses a mapping table (source:include/rex/ppc/context.h:429):

```cpp theme={null}
// Thread-local map: guest_jmp_buf_addr -> host jmp_buf
inline std::unordered_map<uint32_t, jmp_buf>& get_jmp_buf_map() {
  static thread_local std::unordered_map<uint32_t, jmp_buf> map;
  return map;
}

// setjmp(guest_buf_addr)
#define ppc_setjmp(guest_buf_addr) \
  (setjmp(::rex::get_jmp_buf_map()[(guest_buf_addr)]))

// longjmp(guest_buf_addr, val)
[[noreturn]] inline void ppc_longjmp(uint32_t guest_buf_addr, int val) {
  auto& map = get_jmp_buf_map();
  auto it = map.find(guest_buf_addr);
  if (it != map.end()) {
    longjmp(it->second, val);
  }
  std::abort();  // setjmp was never called
}
```

<Note>
  `ppc_setjmp` must be a macro (not a function) so it captures the caller's stack frame. Otherwise, `longjmp` would return to a dead frame.
</Note>

## Platform Differences

### x86-64 (SSE/AVX)

* Native support for 128-bit SIMD via SSE4.1/AVX
* `__rdtsc()` for timebase
* `_mm_getcsr()` / `_mm_setcsr()` for FPSCR

### ARM64 (NEON)

* SIMDe translates x86 intrinsics to NEON
* `mrs` instruction for timebase
* `fpcr` register for rounding mode

## Performance Tips

1. **Minimize context access**: Recompiled functions use local variables when possible
2. **MMIO detection**: The recompiler tracks MMIO base addresses to avoid runtime checks
3. **SIMD alignment**: Vector loads/stores assume 16-byte alignment when safe
4. **Inline functions**: Short recompiled functions are marked `inline` for optimization

## See Also

* [Static Recompilation](/concepts/recompilation) - Code generation pipeline
* [Memory Model](/concepts/memory-model) - Address translation details
* [Kernel Emulation](/concepts/kernel-emulation) - System calls and interrupts


# Static Recompilation
Source: https://rexglue-rexglue-sdk.mintlify.app/concepts/recompilation

How ReXGlue translates PowerPC code to native C++ at build time

## Overview

ReXGlue uses **static ahead-of-time (AOT) recompilation** to translate Xbox 360 PowerPC machine code into native C++ source code at build time. Unlike traditional emulators that use dynamic recompilation (JIT) at runtime, ReXGlue produces compilable C++ files that can be optimized by modern compilers.

<Info>
  Static recompilation happens once during build, not at runtime. The output is standard C++ code that compiles to native machine code for maximum performance.
</Info>

## The Recompilation Pipeline

The recompilation process consists of several stages:

```
XEX Binary → Analysis → Block Discovery → Code Generation → C++ Files → Native Binary
```

### Stage 1: Binary Analysis

The `BinaryView` examines the XEX executable to extract:

* Code sections and data sections
* Entry points and export tables
* `.pdata` (exception handling metadata) for function boundaries
* Relocation information

### Stage 2: Function Discovery

The `FunctionScanner` (source:include/rex/codegen/recompiled\_function.h:84) discovers function boundaries using multiple heuristics:

<Note>
  **Function Boundary Detection**

  * **Linear sweep** from known entry points
  * **Branch target tracking** to find furthest reachable instruction
  * **Prologue/epilogue patterns** (`mflr`, `stw r0`, `blr` sequences)
  * **pdata information** when available
  * **Jump table detection** for `bctr` switch statements
</Note>

Each function is decomposed into **basic blocks** (see `DiscoveredBlock` structure in source:include/rex/codegen/recompiled\_function.h:47):

```cpp theme={null}
struct DiscoveredBlock {
  rex::guest_addr_t base;       // Start address
  rex::guest_addr_t end;        // End address (exclusive)
  bool has_terminator;          // Ends with blr/bctr/branch
  int64_t projectedSize;        // Size limit for fall-through
  std::vector<rex::guest_addr_t> successors;  // Branch targets
};
```

### Stage 3: Code Generation

The `Recompiler` (source:include/rex/codegen/recompiler.h:67) translates each PowerPC instruction to C++ code:

**Instruction-by-Instruction Translation:**

```cpp theme={null}
bool recompile(const FunctionNode& fn, uint32_t base, 
               const ppc_insn& insn, const uint32_t* data,
               std::unordered_map<uint32_t, JumpTable>::iterator& switchTable,
               RecompilerLocalVariables& localVariables, 
               CSRState& csrState);
```

**Local Variable Tracking:**

The `RecompilerLocalVariables` structure (source:include/rex/codegen/recompiler.h:36) tracks which registers need to be declared as local variables:

```cpp theme={null}
struct RecompilerLocalVariables {
  bool ctr{};           // Count register
  bool xer{};           // Fixed-point exception register
  bool reserved{};      // Reservation address
  bool cr[8]{};         // Condition register fields 0-7
  bool r[32]{};         // General purpose registers
  bool f[32]{};         // Floating-point registers
  bool v[128]{};        // Vector registers
  uint32_t mmio_base_regs{0};  // Tracks MMIO base addresses
};
```

**MMIO Optimization:**

The recompiler tracks which GPRs contain memory-mapped I/O base addresses (≥ 0x7F000000):

```cpp theme={null}
// Set when lis loads a value with upper 16 bits >= 0x7F00
// or when oris sets upper bits >= 0xC800
void set_mmio_base(size_t reg) {
  if (reg < 32)
    mmio_base_regs |= (1u << reg);
}
```

This allows the recompiler to generate optimized MMIO access code using `PPC_MM_LOAD_U32`/`PPC_MM_STORE_U32` macros.

### Stage 4: Output Generation

Generated C++ functions follow this signature:

```cpp theme={null}
void function_82E00000(PPCContext& ctx, uint8_t* base) {
  PPC_FUNC_PROLOGUE();  // Assert base alignment
  
  // Local variable declarations
  PPCRegister r3, r4, r5;
  PPCCRRegister cr0;
  
  // Translated instructions
  r3.u32 = PPC_LOAD_U32(ctx.r3.u32);  // lwz r3, 0(r3)
  r4.u32 = r3.u32 + 0x10;              // addi r4, r3, 0x10
  cr0.compare(r4.s32, 0, ctx.xer);     // cmpwi cr0, r4, 0
  
  if (cr0.eq) {                        // beq target
    PPC_CALL_INDIRECT_FUNC(0x82E00100);
  }
  // ...
}
```

## Function Dispatch

Indirect calls (via CTR register) use a **function table** stored in guest memory:

```cpp theme={null}
#define PPC_LOOKUP_FUNC(base, addr) \
  (*(PPCFunc**)(base + PPC_IMAGE_BASE + PPC_IMAGE_SIZE + \
                (uint64_t(uint32_t(addr) - PPC_CODE_BASE) * 2)))

#define PPC_CALL_INDIRECT_FUNC(addr) \
  PPC_LOOKUP_FUNC(base, addr)(ctx, base);
```

<Info>
  The function table is indexed by `(guest_addr - CODE_BASE) * 2`, allowing 8-byte pointers for each 4-byte-aligned instruction. This is initialized by `Memory::InitializeFunctionTable()` (source:include/rex/system/xmemory.h:473).
</Info>

## Control Flow Handling

### Direct Branches

Unconditional branches compile to direct C++ function calls:

```cpp theme={null}
// b 0x82E00200
PPC_CALL_FUNC(function_82E00200);
```

### Conditional Branches

Conditional branches become C++ if statements:

```cpp theme={null}
// bne cr0, 0x82E00200
if (!cr0.eq) {
  PPC_CALL_FUNC(function_82E00200);
}
```

### Jump Tables

Switch statements via `bctr` are detected and converted to C++ switch:

```cpp theme={null}
switch (ctx.ctr.u32) {
  case 0x82E00100: PPC_CALL_FUNC(function_82E00100); break;
  case 0x82E00104: PPC_CALL_FUNC(function_82E00104); break;
  case 0x82E00108: PPC_CALL_FUNC(function_82E00108); break;
  default: __builtin_debugtrap();
}
```

## Validation and Optimization

**Deferred Writes:**

Generated code is buffered until validation passes (source:include/rex/codegen/recompiler.h:78):

```cpp theme={null}
std::vector<std::pair<std::string, std::string>> pendingWrites;
```

The `FlushPendingWrites()` method writes all files to disk only after successful validation.

**Force Mode:**

The `recompile(bool force)` method can bypass validation errors:

```cpp theme={null}
bool recompile(bool force);
```

This is useful for debugging malformed binaries or during development.

## Performance Characteristics

| Metric           | Static Recompilation           | Dynamic Recompilation (JIT)   |
| ---------------- | ------------------------------ | ----------------------------- |
| Translation time | Build time (one-time)          | Runtime overhead              |
| Code quality     | Full compiler optimizations    | Limited optimization window   |
| Startup time     | Instant                        | Must compile before execution |
| Memory usage     | Zero runtime overhead          | JIT cache in memory           |
| Debugging        | Source-level with native tools | Requires special JIT debugger |

<Note>
  Static recompilation trades build time for runtime performance. Once compiled, there is **zero translation overhead** at runtime.
</Note>

## Code Example

Original PowerPC assembly:

```asm theme={null}
; Function at 0x82E00000
mflr  r0          ; Save link register
stw   r0, -8(r1)  ; Store to stack
stwu  r1, -0x10(r1) ; Allocate stack frame
lis   r3, 0x8300  ; Load high address
lwz   r4, 0x100(r3) ; Load from memory
cmpwi cr0, r4, 0  ; Compare with zero
beq   exit        ; Branch if equal
addi  r3, r4, 1   ; Increment
stw   r3, 0x100(r3) ; Store back
exit:
addi  r1, r1, 0x10 ; Deallocate stack
lwz   r0, -8(r1)  ; Restore LR
mtlr  r0
blr               ; Return
```

Generated C++ code:

```cpp theme={null}
PPC_FUNC_IMPL(function_82E00000) {
  PPC_FUNC_PROLOGUE();
  
  PPCRegister r3, r4;
  PPCCRRegister cr0;
  
  // mflr r0 (LR already in ctx.lr)
  // stw r0, -8(r1) - handled by runtime
  // stwu r1, -0x10(r1) - stack management
  
  r3.u32 = 0x83000000;  // lis r3, 0x8300
  r4.u32 = PPC_LOAD_U32(r3.u32 + 0x100);  // lwz r4, 0x100(r3)
  cr0.compare(r4.s32, 0, ctx.xer);  // cmpwi cr0, r4, 0
  
  if (!cr0.eq) {  // beq exit
    r3.u32 = r4.u32 + 1;  // addi r3, r4, 1
    PPC_STORE_U32(r3.u32 + 0x100, r3.u32);  // stw r3, 0x100(r3)
  }
  
  // Stack cleanup and return handled by caller
}
```

## See Also

* [PowerPC Emulation](/concepts/ppc-emulation) - Instruction translation details
* [Memory Model](/concepts/memory-model) - Address translation and memory layout
* [Kernel Emulation](/concepts/kernel-emulation) - System call handling


# Codegen Configuration (TOML)
Source: https://rexglue-rexglue-sdk.mintlify.app/config/codegen-config

Complete reference for ReXGlue recompiler TOML configuration

The recompiler is configured via a TOML file that controls code generation behavior, analysis settings, and manual overrides.

## Required Fields

<ParamField type="string">
  Project name used for generated files and namespaces.
</ParamField>

<ParamField type="string">
  Path to the input XEX or ELF executable file to recompile.
</ParamField>

<ParamField type="string">
  Output directory for generated C++ source files.
</ParamField>

## Patch Files (Not Yet Implemented)

<ParamField type="string">
  Path to binary patch file to apply before analysis.
</ParamField>

<ParamField type="string">
  Path to save the patched executable.
</ParamField>

## Code Generation Options

These flags control register allocation and optimization behavior:

<ParamField type="boolean">
  Skip saving/restoring the Link Register (LR) when not modified. Reduces overhead for leaf functions.
</ParamField>

<ParamField type="boolean">
  Skip Machine State Register (MSR) emulation. Use only if the binary doesn't modify MSR.
</ParamField>

<ParamField type="boolean">
  Allocate Count Register (CTR) as a local variable instead of state struct field. Improves performance when CTR is used locally.
</ParamField>

<ParamField type="boolean">
  Allocate XER (Fixed-Point Exception Register) as local variable.
</ParamField>

<ParamField type="boolean">
  Allocate reserved registers (r2, r13) as local variables.
</ParamField>

<ParamField type="boolean">
  Allocate Condition Register fields as local variables.
</ParamField>

<ParamField type="boolean">
  Allocate non-argument registers (r11-r31) as local variables when not used for parameters.
</ParamField>

<ParamField type="boolean">
  Allocate non-volatile registers (r14-r31) as local variables.
</ParamField>

<ParamField type="boolean">
  Generate SEH (Structured Exception Handling) wrapper functions for Windows exception handling.
</ParamField>

## Special Addresses

<ParamField type="uint32">
  Address of `longjmp` function for setjmp/longjmp analysis. Use hex format: `0x82000100`.
</ParamField>

<ParamField type="uint32">
  Address of `setjmp` function for setjmp/longjmp analysis.
</ParamField>

## Analysis Section

Fine-tune the analysis pipeline:

```toml theme={null}
[analysis]
max_jump_extension = 65536
data_region_threshold = 16
large_function_threshold = 1048576
exception_handler_funcs = [0x82000200, 0x82000300]
```

<ParamField type="uint32">
  Maximum bytes to extend function boundaries when jump table targets are found outside initial function size.
</ParamField>

<ParamField type="uint32">
  Number of consecutive invalid instructions before marking region as data (not code). Helps detect embedded constants.
</ParamField>

<ParamField type="uint32">
  Size in bytes (1MB default) to warn about unusually large functions. May indicate analysis errors.
</ParamField>

<ParamField type="array">
  Array of exception handler function addresses for code region segmentation.

  ```toml theme={null}
  exception_handler_funcs = [0x82000200, 0x82000300]
  ```
</ParamField>

## Invalid Instructions Hints

Mark regions that contain data (not code) to prevent disassembly errors:

```toml theme={null}
[[invalid_instructions]]
data = 0x82001000
size = 0x40

[[invalid_instructions]]
data = 0x82002000
size = 0x10
```

<ParamField type="array of tables">
  Array of data regions that should not be disassembled as code.

  Each entry requires:

  * `data` (uint32): Starting address of data region
  * `size` (uint32): Size of data region in bytes
</ParamField>

## Indirect Call Hints

Mark `bctr` instructions as indirect calls (vtable dispatch, computed jumps) rather than switch tables:

```toml theme={null}
indirect_calls = [0x82000400, 0x82000800]
```

<ParamField type="array">
  Array of addresses where `bctr` instructions are vtable/computed calls, not switch table jumps.
</ParamField>

## Example Configuration

```toml theme={null}
project_name = "mygame"
file_path = "default.xex"
out_directory_path = "generated"

# Enable optimizations
skip_lr = true
ctr_as_local = true
xer_as_local = true
cr_as_local = true

# Analysis settings
[analysis]
max_jump_extension = 131072  # 128KB
data_region_threshold = 20
large_function_threshold = 2097152  # 2MB

# Mark embedded constant table as data
[[invalid_instructions]]
data = 0x82100000
size = 0x1000

# Known indirect calls
indirect_calls = [0x82000450, 0x82000890]

# Manual function override
[functions."0x82000100"]
size = 0x400
name = "GameInit"
```

## Validation Rules

The configuration is validated before code generation:

1. **Alignment**: All addresses must be 4-byte aligned (PowerPC instruction size)
2. **Required fields**: `file_path` must be provided
3. **No overlaps**: Function boundaries cannot overlap (standalone functions)
4. **Size constraints**: Cannot specify both `size` and `end` for functions
5. **End address**: If using `end`, it must be greater than the start address

## See Also

* [Functions Configuration](/config/functions) - Function and chunk definitions
* [Hooks Configuration](/config/hooks) - Mid-assembly hooks
* [Overview](/config/overview) - Configuration system overview


# Function Configuration
Source: https://rexglue-rexglue-sdk.mintlify.app/config/functions

Manually define function boundaries, names, and discontinuous chunks

The `[functions]` section allows you to manually specify function boundaries, override auto-generated names, and define discontinuous code chunks.

## Function Definition

Functions are defined using hexadecimal address keys:

```toml theme={null}
[functions."0x82000100"]
size = 0x200
name = "GameInit"

[functions."0x82000400"]
end = 0x82000800
name = "Render"
```

## FunctionConfig Structure

From `config.h:42-54`:

<ParamField type="uint32">
  Explicit size of the function in bytes. Mutually exclusive with `end`.

  ```toml theme={null}
  [functions."0x82000100"]
  size = 0x400  # Function is 1024 bytes
  ```
</ParamField>

<ParamField type="uint32">
  End address of the function (exclusive). Mutually exclusive with `size`.

  Must be greater than the start address. The function size is calculated as `end - address`.

  ```toml theme={null}
  [functions."0x82001000"]
  end = 0x82001400  # Size = 0x400
  ```
</ParamField>

<ParamField type="string">
  Custom symbol name for the function. If not specified, auto-generates `sub_XXXXXXXX` format.

  ```toml theme={null}
  [functions."0x82000100"]
  size = 0x200
  name = "PlayerUpdate"
  ```
</ParamField>

<ParamField type="uint32">
  Parent function address for discontinuous chunks. When non-zero, this entry is a chunk belonging to the parent function.

  Use this for functions with non-contiguous code regions (e.g., cold/hot path separation).

  ```toml theme={null}
  # Parent function
  [functions."0x82000100"]
  size = 0x200
  name = "MainLoop"

  # Chunk belonging to MainLoop
  [functions."0x82005000"]
  size = 0x100
  parent = 0x82000100
  ```
</ParamField>

## Size vs End

You must specify either `size` or `end`, but not both:

```toml theme={null}
# Using size (preferred)
[functions."0x82000100"]
size = 0x400

# Using end address
[functions."0x82000500"]
end = 0x82000900

# ERROR: Cannot use both
[functions."0x82000A00"]
size = 0x200
end = 0x82000C00  # This will fail validation
```

## Discontinuous Chunks

Some compilers split functions into multiple non-contiguous regions. Use the `parent` field to define chunks:

```toml theme={null}
# Main function entry point
[functions."0x82000100"]
size = 0x200
name = "ProcessInput"

# Cold path chunk (rarely executed code)
[functions."0x82010000"]
size = 0x80
parent = 0x82000100  # Belongs to ProcessInput

# Another chunk
[functions."0x82010100"]
end = 0x82010180
parent = 0x82000100
```

Key properties of chunks:

* Chunks have `parent != 0`
* Chunks are not entry points themselves
* Multiple chunks can belong to the same parent
* Chunks can overlap with other functions (parent function boundaries)
* Standalone functions cannot overlap

## Validation Rules

From `config.cpp:100-124` and `config.cpp:289-350`:

### Address Alignment

All function addresses must be 4-byte aligned (PowerPC instruction size):

```toml theme={null}
# Valid: aligned to 4 bytes
[functions."0x82000100"]
size = 0x200

# INVALID: not aligned
[functions."0x82000101"]  # Will fail validation
size = 0x200
```

### Mutual Exclusivity

Cannot specify both `size` and `end`:

```toml theme={null}
# ERROR: Validation will fail
[functions."0x82000100"]
size = 0x200
end = 0x82000300
```

### End Address Constraint

When using `end`, it must be greater than the start address:

```toml theme={null}
# INVALID: end <= start
[functions."0x82000100"]
end = 0x82000100  # Will fail

# Valid
[functions."0x82000100"]
end = 0x82000200
```

### No Overlapping Boundaries

Standalone functions (non-chunks) cannot overlap:

```toml theme={null}
# INVALID: Functions overlap
[functions."0x82000100"]
size = 0x400  # Ends at 0x82000500

[functions."0x82000300"]  # Starts before previous ends
size = 0x200  # Will fail validation
```

Chunks CAN overlap with their parent function boundaries.

## Common Patterns

### Override Auto-Detection

Force specific boundaries when analysis is incorrect:

```toml theme={null}
[functions."0x82000100"]
size = 0x800
name = "ComplexFunction"
```

### Split Functions

Handle hot/cold code splitting:

```toml theme={null}
# Hot path (frequently executed)
[functions."0x82000100"]
size = 0x400
name = "FastPath"

# Cold path (error handling)
[functions."0x82100000"]
size = 0x200
parent = 0x82000100
```

### Name Important Functions

```toml theme={null}
[functions."0x82000100"]
name = "main"

[functions."0x82000500"]
name = "Initialize"

[functions."0x82000A00"]
name = "Shutdown"
```

## Example Configuration

```toml theme={null}
project_name = "mygame"
file_path = "default.xex"
out_directory_path = "generated"

# Main entry point
[functions."0x82000000"]
size = 0x100
name = "__start"

# Game initialization
[functions."0x82000100"]
end = 0x82000500
name = "GameInit"

# Main loop with cold path
[functions."0x82001000"]
size = 0x800
name = "MainLoop"

[functions."0x82100000"]
size = 0x200
parent = 0x82001000  # Error handling chunk

# Rendering system
[functions."0x82002000"]
size = 0x1000
name = "RenderFrame"
```

## See Also

* [Codegen Config](/config/codegen-config) - Main TOML reference
* [Hooks](/config/hooks) - Mid-assembly hook configuration


# Mid-Assembly Hooks
Source: https://rexglue-rexglue-sdk.mintlify.app/config/hooks

Inject custom C++ code at specific PowerPC instruction addresses

Mid-assembly hooks allow you to inject custom C++ function calls at specific PowerPC instruction addresses during code generation. This is useful for logging, debugging, and implementing custom behavior.

## MidAsmHook Structure

From `config.h:25-38`:

```cpp theme={null}
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;
};
```

## Basic Hook Definition

Hooks are defined in an array of tables:

```toml theme={null}
[[midasm_hook]]
address = 0x82000400
name = "OnFrameStart"
registers = ["r3", "r4"]
```

## Configuration Fields

<ParamField type="uint32">
  PowerPC instruction address where the hook should be injected.

  ```toml theme={null}
  [[midasm_hook]]
  address = 0x82000400
  name = "MyHook"
  ```
</ParamField>

<ParamField type="string">
  Name of the C++ function to call. This function must be defined in your custom code.

  ```toml theme={null}
  [[midasm_hook]]
  address = 0x82000400
  name = "LogFrameStart"
  ```
</ParamField>

<ParamField type="array of strings">
  PowerPC registers to pass as arguments to the hook function.

  Registers are passed in order: `hook(r3, r4, r5)`

  ```toml theme={null}
  [[midasm_hook]]
  address = 0x82000400
  name = "ProcessData"
  registers = ["r3", "r4", "r5", "r6"]
  ```
</ParamField>

<ParamField type="boolean">
  If true, the hook function's return value is used to immediately return from the current function.

  Cannot be combined with `jump_address`, `return_on_true`, or `return_on_false`.

  ```toml theme={null}
  [[midasm_hook]]
  address = 0x82000400
  name = "CheckEarlyExit"
  registers = ["r3"]
  return = true
  ```
</ParamField>

<ParamField type="boolean">
  Return from the current function if the hook function returns true (non-zero).

  Cannot be combined with `return` or `jump_address`.

  ```toml theme={null}
  [[midasm_hook]]
  address = 0x82000400
  name = "ShouldSkipFrame"
  return_on_true = true
  ```
</ParamField>

<ParamField type="boolean">
  Return from the current function if the hook function returns false (zero).

  Cannot be combined with `return` or `jump_address`.

  ```toml theme={null}
  [[midasm_hook]]
  address = 0x82000400
  name = "ValidateInput"
  return_on_false = true  # Return if validation fails
  ```
</ParamField>

<ParamField type="uint32">
  PowerPC address to jump to unconditionally after calling the hook.

  Cannot be combined with `return`, `return_on_true`, or `return_on_false`.

  ```toml theme={null}
  [[midasm_hook]]
  address = 0x82000400
  name = "RedirectFlow"
  jump_address = 0x82001000
  ```
</ParamField>

<ParamField type="uint32">
  Jump to this address if the hook function returns true.

  Cannot be combined with `return` or `jump_address`.

  ```toml theme={null}
  [[midasm_hook]]
  address = 0x82000400
  name = "CheckCondition"
  jump_address_on_true = 0x82001000
  jump_address_on_false = 0x82002000
  ```
</ParamField>

<ParamField type="uint32">
  Jump to this address if the hook function returns false.

  Must be used with `jump_address_on_true`.
</ParamField>

<ParamField type="boolean">
  If true, inject the hook after the instruction at the address. Otherwise, inject before.

  ```toml theme={null}
  [[midasm_hook]]
  address = 0x82000400
  name = "AfterStore"
  after_instruction = true
  ```
</ParamField>

## Validation Rules

From `config.cpp:254-264`:

### Cannot Return and Jump

A hook cannot both return and jump:

```toml theme={null}
# INVALID: Cannot specify both
[[midasm_hook]]
address = 0x82000400
name = "BadHook"
return = true
jump_address = 0x82001000  # Error!
```

### Cannot Mix Direct and Conditional

Cannot mix direct return/jump with conditional return/jump:

```toml theme={null}
# INVALID: Cannot mix direct and conditional
[[midasm_hook]]
address = 0x82000400
name = "BadHook"
return = true
return_on_true = true  # Error!
```

## Hook Function Signature

Your C++ hook function must match the signature based on registers:

```cpp theme={null}
// No registers: void hook()
void LogEvent() {
  fmt::print("Event occurred\n");
}

// With registers: void hook(uint32_t r3, uint32_t r4, ...)
void ProcessData(uint32_t r3, uint32_t r4) {
  fmt::print("r3={:08X}, r4={:08X}\n", r3, r4);
}

// Returning bool for conditional behavior
bool CheckCondition(uint32_t r3) {
  return r3 > 0x100;
}

// Returning value for direct return
uint32_t ComputeValue(uint32_t r3, uint32_t r4) {
  return r3 + r4;
}
```

## Common Use Cases

### Logging and Debugging

Log function parameters:

```toml theme={null}
[[midasm_hook]]
address = 0x82000400
name = "LogFunctionEntry"
registers = ["r3", "r4", "r5"]
```

```cpp theme={null}
void LogFunctionEntry(uint32_t r3, uint32_t r4, uint32_t r5) {
  fmt::print("Function called: r3={:08X}, r4={:08X}, r5={:08X}\n", r3, r4, r5);
}
```

### Early Exit

Skip function execution based on condition:

```toml theme={null}
[[midasm_hook]]
address = 0x82000400
name = "ShouldSkipRendering"
return_on_true = true
```

```cpp theme={null}
bool ShouldSkipRendering() {
  return g_skipFrame;
}
```

### Value Injection

Replace computed values:

```toml theme={null}
[[midasm_hook]]
address = 0x82000400
name = "OverrideValue"
registers = ["r3"]
return = true
```

```cpp theme={null}
uint32_t OverrideValue(uint32_t original) {
  if (g_useOverride) {
    return g_overrideValue;
  }
  return original;
}
```

### Control Flow Redirection

Dynamically redirect execution:

```toml theme={null}
[[midasm_hook]]
address = 0x82000400
name = "CheckGameMode"
jump_address_on_true = 0x82001000   # Single player
jump_address_on_false = 0x82002000  # Multiplayer
```

```cpp theme={null}
bool CheckGameMode() {
  return g_gameMode == SINGLE_PLAYER;
}
```

## Example Configuration

```toml theme={null}
project_name = "mygame"
file_path = "default.xex"
out_directory_path = "generated"

# Log frame start
[[midasm_hook]]
address = 0x82000100
name = "OnFrameStart"
registers = ["r3"]  # Frame number

# Early exit if paused
[[midasm_hook]]
address = 0x82000200
name = "IsPaused"
return_on_true = true

# Debug memory access
[[midasm_hook]]
address = 0x82000300
name = "LogMemoryRead"
registers = ["r3", "r4"]  # Address, size
after_instruction = true

# Override random seed
[[midasm_hook]]
address = 0x82000400
name = "GetRandomSeed"
return = true

# Conditional branch redirection
[[midasm_hook]]
address = 0x82000500
name = "CheckDifficulty"
jump_address_on_true = 0x82001000   # Easy mode
jump_address_on_false = 0x82001500  # Hard mode
```

## See Also

* [Codegen Config](/config/codegen-config) - Main TOML reference
* [Functions](/config/functions) - Function configuration


# Configuration Overview
Source: https://rexglue-rexglue-sdk.mintlify.app/config/overview

Understanding ReXGlue's configuration system

ReXGlue uses a TOML-based configuration system to control code generation, analysis behavior, and manual overrides for the recompiler.

## Configuration Files

The primary configuration is stored in a `.toml` file that you pass to the recompiler. This file controls:

* **Project settings** - Project name, input/output paths
* **Code generation options** - Register allocation, optimization flags
* **Analysis tuning** - Function size limits, data region detection
* **Manual overrides** - Functions, jump tables, hooks

## Configuration Structure

```toml theme={null}
# Required: Project identification and paths
project_name = "myproject"
file_path = "game.xex"
out_directory_path = "generated"

# Optional: Code generation flags
skip_lr = false
ctr_as_local = true

# Optional: Analysis tuning
[analysis]
max_jump_extension = 65536
data_region_threshold = 16

# Optional: Manual function definitions
[functions."0x82000100"]
size = 0x200
name = "GameInit"

# Optional: Mid-assembly hooks
[[midasm_hook]]
address = 0x82000400
name = "OnFrameStart"
registers = ["r3", "r4"]
```

## Configuration Hierarchy

1. **Project-level** - vcpkg.json, CMakeLists.txt for build system
2. **Recompiler config** - TOML file for codegen behavior
3. **Source-level** - Function annotations and attributes

## Validation

The configuration is validated before code generation:

* All addresses must be 4-byte aligned (PowerPC instruction alignment)
* Function boundaries cannot overlap (except chunks)
* `size` and `end` are mutually exclusive
* Required fields (`file_path`) must be present

Validation errors will block code generation, while warnings are informational.

## Loading Configuration

In C++ code:

```cpp theme={null}
#include <rex/codegen/config.h>

rex::codegen::RecompilerConfig config;
config.Load("myproject.toml");

auto result = config.Validate();
if (!result.valid) {
  for (const auto& error : result.errors) {
    fmt::print("Error: {}\n", error);
  }
}
```

## See Also

* [Project Configuration](/config/project-config) - Build system setup
* [Codegen Config](/config/codegen-config) - TOML reference
* [Functions](/config/functions) - Function and chunk configuration
* [Hooks](/config/hooks) - Mid-assembly hook system


# Project Configuration
Source: https://rexglue-rexglue-sdk.mintlify.app/config/project-config

Setting up vcpkg and CMake for your recompilation project

ReXGlue projects use vcpkg for dependency management and CMake for building. This page covers the project-level configuration files.

## vcpkg.json

Create a `vcpkg.json` manifest in your project root:

```json theme={null}
{
  "name": "myproject",
  "version": "1.0.0",
  "dependencies": [
    "fmt",
    "spdlog"
  ],
  "builtin-baseline": "latest"
}
```

### Required Dependencies

ReXGlue requires:

* **fmt** - String formatting (used by generated code)
* **spdlog** - Logging (optional but recommended)

The recompiler itself uses additional dependencies (toml++, etc.) but these are not needed in generated projects.

## CMakeLists.txt

Minimal CMake configuration for a recompiled project:

```cmake theme={null}
cmake_minimum_required(VERSION 3.20)
project(myproject)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Find dependencies
find_package(fmt CONFIG REQUIRED)
find_package(spdlog CONFIG REQUIRED)

# Add generated source files
file(GLOB_RECURSE GENERATED_SOURCES "generated/*.cpp")

# Create executable
add_executable(myproject
  src/main.cpp
  ${GENERATED_SOURCES}
)

target_link_libraries(myproject PRIVATE
  fmt::fmt
  spdlog::spdlog
)

target_include_directories(myproject PRIVATE
  ${CMAKE_CURRENT_SOURCE_DIR}/generated
  ${CMAKE_CURRENT_SOURCE_DIR}/include
)
```

## Build System Integration

### Using vcpkg Toolchain

Configure CMake with the vcpkg toolchain:

```bash theme={null}
cmake -B build \
  -DCMAKE_TOOLCHAIN_FILE="$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake"
cmake --build build
```

### Output Directory Structure

The recompiler generates files into the directory specified by `out_directory_path` in your TOML config:

```
generated/
├── functions.cpp        # Main function implementations
├── functions.h          # Function declarations
├── imports.cpp          # Import thunks
├── ppc_state.h          # PowerPC state structure
└── ppc_context.h        # Execution context
```

## Platform-Specific Settings

### Windows (MSVC)

```cmake theme={null}
if(MSVC)
  # Enable exception handling for SEH support
  target_compile_options(myproject PRIVATE /EHsc)
  
  # Increase stack size if needed (for deeply nested calls)
  target_link_options(myproject PRIVATE /STACK:8388608)
endif()
```

### Linux/macOS (GCC/Clang)

```cmake theme={null}
if(UNIX)
  target_compile_options(myproject PRIVATE
    -Wall
    -Wextra
    -Wno-unused-parameter
  )
endif()
```

## Compiler Requirements

* **C++20** or later required
* **MSVC 2022+**, **GCC 11+**, or **Clang 14+**
* **64-bit host** architecture

## Next Steps

* [Codegen Config](/config/codegen-config) - Configure the recompiler
* [Functions](/config/functions) - Define custom function boundaries


# Installation
Source: https://rexglue-rexglue-sdk.mintlify.app/installation

Install the ReXGlue SDK and set up your development environment

# Installation

This guide walks through installing the ReXGlue SDK and configuring your development environment for static recompilation of Xbox 360 executables.

## System Requirements

<Tabs>
  <Tab title="Windows">
    **Minimum Requirements:**

    * Windows 10/11 (x64)
    * Clang 18 or newer
    * CMake 3.25+
    * Ninja build system
    * Visual Studio 2022 (for Windows SDK)

    **Graphics:**

    * DirectX 12 capable GPU
    * Latest graphics drivers
  </Tab>

  <Tab title="Linux">
    **Minimum Requirements:**

    * Linux (x64) - Ubuntu 22.04+ or equivalent
    * Clang 18 or newer (Clang 20 recommended)
    * CMake 3.25+
    * Ninja build system
    * GTK 3 development libraries

    **Graphics:**

    * Vulkan 1.2+ capable GPU
    * Latest Mesa drivers or proprietary GPU drivers
  </Tab>
</Tabs>

<Warning>
  **Architecture Requirement**: ReXGlue requires x64 architecture. 32-bit systems and ARM are not supported.
</Warning>

<Warning>
  **Compiler Requirement**: ReXGlue requires Clang 18+ and will not compile with GCC or MSVC. The build system enforces this requirement.
</Warning>

## Step 1: Install Prerequisites

<Tabs>
  <Tab title="Windows">
    ### Install Clang and Build Tools

    1. **Install LLVM/Clang 18+**:
       * Download from [LLVM releases](https://github.com/llvm/llvm-project/releases)
       * Add to PATH: `C:\Program Files\LLVM\bin`

    2. **Install CMake**:
       * Download from [cmake.org](https://cmake.org/download/)
       * Or via chocolatey: `choco install cmake`

    3. **Install Ninja**:
       ```bash theme={null}
       choco install ninja
       ```

    4. **Install Visual Studio 2022**:
       * Required for Windows SDK headers
       * Select "Desktop development with C++" workload

    ### Verify Installation

    ```bash theme={null}
    clang --version   # Should show 18.0.0 or newer
    cmake --version   # Should show 3.25 or newer
    ninja --version
    ```
  </Tab>

  <Tab title="Linux">
    ### Install Clang and Build Tools

    **Ubuntu/Debian:**

    ```bash theme={null}
    # Add LLVM repository for Clang 20
    wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc
    sudo add-apt-repository "deb http://apt.llvm.org/$(lsb_release -sc)/ llvm-toolchain-$(lsb_release -sc)-20 main"

    # Install build tools
    sudo apt update
    sudo apt install -y clang-20 clang++-20 cmake ninja-build

    # Install GTK and Vulkan development libraries
    sudo apt install -y libgtk-3-dev libvulkan-dev vulkan-validationlayers-dev

    # Set Clang as default
    sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-20 100
    sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-20 100
    ```

    **Arch Linux:**

    ```bash theme={null}
    sudo pacman -S clang cmake ninja gtk3 vulkan-devel
    ```

    ### Verify Installation

    ```bash theme={null}
    clang-20 --version  # Should show 20.0.0 or newer
    cmake --version     # Should show 3.25 or newer
    ninja --version
    vulkaninfo | head   # Verify Vulkan is available
    ```
  </Tab>
</Tabs>

## Step 2: Download ReXGlue SDK

You can either download a pre-built release or build from source.

<Tabs>
  <Tab title="Pre-built Release">
    ### Download from GitHub Releases

    1. Visit [ReXGlue SDK Releases](https://github.com/rexglue/rexglue-sdk/releases)

    2. Download the latest release for your platform:
       * `rexglue-sdk-win-amd64-vX.X.X.zip` (Windows)
       * `rexglue-sdk-linux-amd64-vX.X.X.tar.gz` (Linux)

    3. Extract to your preferred location:

    ```bash theme={null}
    # Windows (PowerShell)
    Expand-Archive rexglue-sdk-win-amd64-v0.2.2.zip -DestinationPath C:\rexglue-sdk

    # Linux
    tar -xzf rexglue-sdk-linux-amd64-v0.2.2.tar.gz -C ~/rexglue-sdk
    ```

    4. Add the SDK binaries to your PATH:

    ```bash theme={null}
    # Windows (add to environment variables)
    setx PATH "%PATH%;C:\rexglue-sdk\bin"

    # Linux (add to ~/.bashrc or ~/.zshrc)
    export PATH="$HOME/rexglue-sdk/bin:$PATH"
    ```

    <Note>
      Pre-built releases include the `rexglue` CLI tool and runtime libraries ready to use.
    </Note>
  </Tab>

  <Tab title="Build from Source">
    ### Clone and Build SDK

    1. **Clone the repository**:

    ```bash theme={null}
    git clone https://github.com/rexglue/rexglue-sdk.git
    cd rexglue-sdk
    ```

    2. **Configure build** (choose your platform preset):

    <CodeGroup>
      ```bash Windows Debug theme={null}
      cmake --preset win-amd64-debug
      ```

      ```bash Windows Release theme={null}
      cmake --preset win-amd64-release
      ```

      ```bash Linux Debug theme={null}
      cmake --preset linux-amd64-debug
      ```

      ```bash Linux Release theme={null}
      cmake --preset linux-amd64-release
      ```
    </CodeGroup>

    3. **Build the SDK**:

    ```bash theme={null}
    # Build all targets
    cmake --build out/build/<preset-name>

    # Or build specific targets
    cmake --build out/build/<preset-name> --target rexglue
    ```

    4. **Verify build output**:

    ```bash theme={null}
    # Binary output location
    ls out/win-amd64/      # Windows
    ls out/linux-amd64/    # Linux
    ```

    <Note>
      Building from source gives you the latest development version and allows you to customize build options.
    </Note>
  </Tab>
</Tabs>

## Step 3: Verify Installation

Test that the ReXGlue CLI tool is working:

```bash theme={null}
rexglue --help
```

You should see output similar to:

```
ReXGlue - Xbox 360 Recompilation Toolkit

Usage: rexglue <command> [flags] [args]

Commands:
  codegen <config.toml>   Analyze XEX and generate C++ code
  init                    Initialize a new project
  migrate                 Migrate project to current SDK version
  recompile-tests         Generate Catch2 tests from PPC assembly

Run 'rexglue --help' for flag details.
```

Location: `src/rexglue/main.cpp:44-53`

## Step 4: Configure Graphics Backend

The SDK supports multiple graphics backends depending on your platform.

<Tabs>
  <Tab title="Windows (D3D12)">
    **Direct3D 12** is the default backend on Windows.

    Enabled automatically via CMake option: `REXGLUE_USE_D3D12=ON`

    **Requirements:**

    * Windows 10/11 with DirectX 12
    * D3D12-capable GPU (most GPUs from 2015+)

    No additional configuration needed.
  </Tab>

  <Tab title="Linux (Vulkan)">
    **Vulkan** is the default backend on Linux.

    Enabled automatically via CMake option: `REXGLUE_USE_VULKAN=ON`

    **Verify Vulkan installation:**

    ```bash theme={null}
    vulkaninfo | grep "Vulkan Instance Version"
    ```

    Should show version 1.2.0 or newer.

    **Optional: Enable validation layers for debugging**

    ```bash theme={null}
    export VK_LAYER_PATH=/usr/share/vulkan/explicit_layer.d
    export VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation
    ```
  </Tab>

  <Tab title="Dual Backend">
    You can enable both backends on Windows for testing:

    ```bash theme={null}
    cmake -DREXGLUE_USE_D3D12=ON -DREXGLUE_USE_VULKAN=ON --preset win-amd64-release
    ```

    <Note>
      At least one graphics backend must be enabled. The build will fail if both are disabled.
    </Note>

    Location: `CMakeLists.txt:18-30`
  </Tab>
</Tabs>

## Optional: Enable Build Features

### Build with Tests

Enable unit tests and PPC instruction tests:

```bash theme={null}
cmake -DREXGLUE_BUILD_TESTS=ON --preset <your-preset>
cmake --build out/build/<preset-name>

# Run tests
ctest --test-dir out/build/<preset-name>
```

### Enable Sanitizers (Debug)

Enable undefined behavior sanitizer for debugging:

```bash theme={null}
cmake -DREXGLUE_ENABLE_SANITIZERS=ON --preset <debug-preset>
```

<Warning>
  Address Sanitizer (ASan) is **not compatible** with ReXGlue's memory mapping at `0x100000000`. Only UndefinedBehaviorSanitizer (UBSan) is supported.
</Warning>

Location: `CMakeLists.txt:96-101`

## Project Integration Methods

Once installed, you can use the SDK in your projects in two ways:

### Method 1: Add as Subdirectory (Recommended)

Include the SDK source tree in your project:

```cmake theme={null}
# In your CMakeLists.txt
set(REXSDK_DIR "${CMAKE_SOURCE_DIR}/thirdparty/rexglue-sdk" CACHE PATH "")
add_subdirectory("${REXSDK_DIR}" rexglue-sdk)

target_link_libraries(my_game PRIVATE rex::core rex::system)
```

### Method 2: Use Installed Package

If you installed the SDK to a system location:

```cmake theme={null}
find_package(rexglue REQUIRED CONFIG)
target_link_libraries(my_game PRIVATE rex::core rex::system)
```

## Troubleshooting

<AccordionGroup>
  <Accordion title="CMake can't find Clang 18">
    Explicitly set the compiler:

    ```bash theme={null}
    cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ --preset <preset>
    ```

    On Linux with specific version:

    ```bash theme={null}
    cmake -DCMAKE_C_COMPILER=clang-20 -DCMAKE_CXX_COMPILER=clang++-20 --preset <preset>
    ```
  </Accordion>

  <Accordion title="Build fails with 'Clang required' error">
    The SDK enforces Clang compiler. Verify:

    ```bash theme={null}
    clang --version
    ```

    Ensure it shows Clang 18.0.0 or newer. Set compiler explicitly in CMake.

    Location: `CMakeLists.txt:39-46`
  </Accordion>

  <Accordion title="Graphics backend error 'at least one backend must be enabled'">
    Check that you haven't disabled both graphics backends:

    ```bash theme={null}
    # On Windows, enable D3D12 (default)
    cmake -DREXGLUE_USE_D3D12=ON --preset win-amd64-release

    # On Linux, enable Vulkan (default)
    cmake -DREXGLUE_USE_VULKAN=ON --preset linux-amd64-release
    ```

    Location: `CMakeLists.txt:28-30`
  </Accordion>

  <Accordion title="Vulkan validation layers not found (Linux)">
    Install validation layers:

    ```bash theme={null}
    # Ubuntu/Debian
    sudo apt install vulkan-validationlayers-dev

    # Arch
    sudo pacman -S vulkan-validation-layers
    ```
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup>
  <Card title="Quick Start Guide" icon="rocket" href="/quickstart">
    Create your first recompiled project with `rexglue init`
  </Card>

  <Card title="Architecture Overview" icon="diagram-project" href="/architecture">
    Learn about the recompilation system architecture
  </Card>
</CardGroup>


# Introduction
Source: https://rexglue-rexglue-sdk.mintlify.app/introduction

Convert Xbox 360 PowerPC code into portable C++ that runs natively on modern platforms

<img alt="ReXGlue Banner" />

<img alt="ReXGlue Banner" />

# Welcome to ReXGlue SDK

ReXGlue converts Xbox 360 PowerPC code into portable C++ that runs natively on modern platforms.

<Note>
  **Early Development Notice**: This project is in early development. Expect significant changes and breaking API updates as development progresses. Contributions and feedback are welcome!
</Note>

## What is ReXGlue?

ReXGlue is a **static recompilation toolkit** for Xbox 360 executables. Rather than interpreting or JIT-compiling PowerPC instructions at runtime like traditional emulators, ReXGlue generates C++ source code ahead of time that can be compiled and run natively on Windows and Linux.

ReXGlue is heavily rooted on the foundations of [Xenia](https://github.com/xenia-project), the Xbox 360 emulator. It takes a different path inspired by [XenonRecomp](https://github.com/hedge-dev/XenonRecomp) and [rexdex's recompiler](https://github.com/rexdex/recompiler) by generating C++ source code that can be compiled with standard toolchains.

## Key Features

<CardGroup>
  <Card title="Static Recompilation" icon="code">
    Generate portable C++ code from Xbox 360 XEX executables that compiles with standard toolchains
  </Card>

  <Card title="Cross-Platform" icon="desktop">
    Run recompiled games natively on Windows (D3D12) and Linux (Vulkan) with x64 architecture
  </Card>

  <Card title="Modern C++23" icon="microchip">
    Built with modern C++23, requires Clang 18+ for optimal performance and compatibility
  </Card>

  <Card title="Complete Runtime" icon="layer-group">
    Includes kernel emulation, graphics backends, filesystem virtualization, and input handling
  </Card>
</CardGroup>

## How It Works

The ReXGlue workflow consists of three main phases:

<Steps>
  <Step title="Analysis">
    ReXGlue analyzes the Xbox 360 executable (XEX format) to identify functions, data regions, and control flow patterns
  </Step>

  <Step title="Code Generation">
    PowerPC instructions are translated to equivalent C++ code with full support for register state, condition flags, and exception handling
  </Step>

  <Step title="Compilation">
    The generated C++ is compiled with your project using CMake and Clang 18+, linking against the ReXGlue runtime libraries
  </Step>
</Steps>

## Example Projects

See ReXGlue in action with these example projects:

* [demo-iruka](https://github.com/rexglue/demo-iruka) - Demonstration project
* [reblue](https://github.com/rexglue/reblue) - Full game recompilation

## Platform Support

| Platform | Architecture | Graphics Backend | Status          |
| -------- | ------------ | ---------------- | --------------- |
| Windows  | x64          | D3D12            | ✅ Supported     |
| Linux    | x64          | Vulkan           | ✅ Supported     |
| macOS    | ARM64/x64    | Metal            | ❌ Not supported |

## Requirements

* **Compiler**: Clang 18 or newer
* **C++ Standard**: C++23
* **CMake**: 3.25 or newer
* **Architecture**: x64 (64-bit) only
* **Graphics**: D3D12 (Windows) or Vulkan (Linux)

## Next Steps

<CardGroup>
  <Card title="Architecture Overview" icon="diagram-project" href="/architecture">
    Understand the recompilation system architecture and runtime components
  </Card>

  <Card title="Installation" icon="download" href="/installation">
    Install the ReXGlue SDK and set up your development environment
  </Card>

  <Card title="Quick Start" icon="rocket" href="/quickstart">
    Create your first recompiled project in minutes
  </Card>

  <Card title="Join Discord" icon="discord" href="https://discord.gg/CNTxwSNZfT">
    Get help, share your projects, and stay updated on development
  </Card>
</CardGroup>

## Community & Support

* **Discord**: [Join our server](https://discord.gg/CNTxwSNZfT) for updates and discussions
* **GitHub**: [rexglue/rexglue-sdk](https://github.com/rexglue/rexglue-sdk)
* **Releases**: [Latest SDK builds](https://github.com/rexglue/rexglue-sdk/releases)

## Disclaimer

ReXGlue is not affiliated with nor endorsed by Microsoft or Xbox. It is an independent project created for educational and development purposes. All trademarks and copyrights belong to their respective owners.

This project is not intended to promote piracy nor unauthorized use of copyrighted material. Any misuse of this software to endorse or enable this type of activity is strictly prohibited.


# Quick Start
Source: https://rexglue-rexglue-sdk.mintlify.app/quickstart

Create your first recompiled Xbox 360 project with ReXGlue

# Quick Start Guide

This guide walks you through creating, configuring, and building your first recompiled Xbox 360 project using ReXGlue.

<Note>
  **Prerequisites**: Make sure you have [installed the ReXGlue SDK](/installation) and have a Clang 18+ toolchain configured.
</Note>

## Overview

The ReXGlue workflow consists of four main steps:

<Steps>
  <Step title="Initialize Project">
    Create a new project structure with `rexglue init`
  </Step>

  <Step title="Configure TOML">
    Configure code generation settings and provide your XEX file
  </Step>

  <Step title="Generate Code">
    Run `rexglue codegen` to analyze and generate C++ code
  </Step>

  <Step title="Build Project">
    Compile the generated code with CMake and run your recompiled executable
  </Step>
</Steps>

Let's get started!

## Step 1: Initialize a New Project

Use the `rexglue init` command to create a new project scaffold:

```bash theme={null}
rexglue init --app_name my_game --app_root ./my_game
```

**Available options:**

* `--app_name` (required): Project name (snake\_case recommended)
* `--app_root` (required): Directory where project will be created
* `--app_desc` (optional): Project description
* `--app_author` (optional): Your name or organization
* `--force`: Overwrite existing files if present

Location: `src/rexglue/main.cpp:101-119`

### Generated Project Structure

The init command creates the following structure:

```
my_game/
├── CMakeLists.txt              # Build configuration (SDK-managed)
├── CMakePresets.json           # Platform-specific build presets
├── my_game_config.toml         # Codegen configuration
├── src/
│   └── main.cpp                # Application entry point (SDK-managed)
└── assets/
    └── default.xex             # Place your XEX file here
```

<Warning>
  **SDK-Managed Files**: `CMakeLists.txt` and `src/main.cpp` are marked as SDK-managed and will be overwritten when running `rexglue migrate`. Put customizations in separate files or use virtual hook overrides.
</Warning>

### Understanding main.cpp

The generated `main.cpp` creates a minimal ReXApp:

```cpp theme={null}
#include "generated/my_game_config.h"
#include "generated/my_game_init.h"
#include <rex/rex_app.h>

class MyGameApp : public rex::ReXApp {
public:
  using rex::ReXApp::ReXApp;

  static std::unique_ptr<rex::ui::WindowedApp> Create(
      rex::ui::WindowedAppContext& ctx) {
    return std::unique_ptr<MyGameApp>(new MyGameApp(ctx, "my_game",
        {PPC_CODE_BASE, PPC_CODE_SIZE, PPC_IMAGE_BASE,
         PPC_IMAGE_SIZE, PPCFuncMappings}));
  }
};

REX_DEFINE_APP(my_game, MyGameApp::Create)
```

Location: `src/rexglue/commands/init_command.cpp:109-140`

The `REX_DEFINE_APP` macro provides the platform-specific entry point (WinMain on Windows, main on Linux).

## Step 2: Configure Code Generation

Edit the generated `my_game_config.toml` file to configure code generation:

```toml theme={null}
# my_game_config.toml - ReXGlue Codegen Configuration

project_name = "my_game"
file_path = "assets/default.xex"        # Path to your XEX file
out_directory_path = "generated"        # Output directory for generated code

# Code generation options (optional)
skip_lr = false
generate_exception_handlers = true      # Enable SEH wrappers (Windows)
max_jump_extension = 65536              # Max bytes for jump table analysis
data_region_threshold = 16              # Consecutive invalid instructions = data

# Manual function overrides (optional)
[[functions]]
address = 0x82000100
name = "GameMain"
size = 0x500

[[functions]]
address = 0x82000200
name = "RenderLoop"
end = 0x82000400  # Alternative to size

# Jump table hints for switch statements (optional)
[[switch_tables]]
address = 0x82001000
targets = [0x82001020, 0x82001040, 0x82001060, 0x82001080]

# Mid-assembly hooks (optional, advanced)
[[mid_asm_hooks]]
address = 0x82002000
name = "OnPlayerSpawn"
registers = ["r3", "r4"]
ret = true
```

Location: `src/rexglue/commands/init_command.cpp:142-155`

### Configuration Options Reference

<AccordionGroup>
  <Accordion title="Required Fields">
    * `project_name`: Project identifier used for generated file names
    * `file_path`: Path to Xbox 360 XEX executable (relative or absolute)
    * `out_directory_path`: Where to write generated C++ files
  </Accordion>

  <Accordion title="Code Generation Options">
    * `skip_lr`: Skip link register (LR) tracking (default: false)
    * `skip_msr`: Skip machine state register (MSR) (default: false)
    * `ctr_as_local_variable`: Promote CTR to local variable (default: false)
    * `xer_as_local_variable`: Promote XER to local variable (default: false)
    * `cr_registers_as_local_variables`: Promote CR fields (default: false)
    * `non_volatile_registers_as_local_variables`: Promote saved registers (default: false)
    * `generate_exception_handlers`: Wrap functions in SEH handlers (default: false)
  </Accordion>

  <Accordion title="Analysis Tuning">
    * `max_jump_extension`: Max bytes to extend function for jump targets (default: 65536)
    * `data_region_threshold`: Invalid instruction count to mark data region (default: 16)
    * `large_function_threshold`: Warn if function exceeds size (default: 1048576)
  </Accordion>

  <Accordion title="Manual Overrides">
    **Functions**: Explicitly define function boundaries and names

    ```toml theme={null}
    [[functions]]
    address = 0x82000100
    name = "CustomName"   # Optional, defaults to sub_82000100
    size = 0x500          # Use size OR end, not both
    # end = 0x82000600    # Exclusive end address
    # parent = 0x82000000 # For discontinuous chunks
    ```

    **Switch Tables**: Hint jump table locations

    ```toml theme={null}
    [[switch_tables]]
    address = 0x82001000
    targets = [0x82001020, 0x82001040]  # Jump targets
    ```
  </Accordion>
</AccordionGroup>

Configuration structure: `include/rex/codegen/config.h:71-134`

## Step 3: Place Your XEX File

Copy your Xbox 360 executable to the path specified in `file_path`:

```bash theme={null}
cp /path/to/your/game.xex my_game/assets/default.xex
```

<Note>
  XEX files are Xbox 360 executable format. You'll need to extract these from Xbox 360 game discs or downloads. ReXGlue does not provide these files.
</Note>

## Step 4: Run Code Generation

Analyze the XEX and generate C++ code:

```bash theme={null}
cd my_game
rexglue codegen my_game_config.toml
```

**Command options:**

* `--force`: Force regeneration even if output is newer than input
* `--enable_exception_handlers`: Override TOML setting to enable SEH wrappers
* `--log_level=<level>`: Set logging verbosity (trace, debug, info, warn, error)
* `--log_file=<path>`: Write logs to file

Location: `src/rexglue/main.cpp:120-130`

### Generated Output

The codegen command creates:

```
generated/
├── my_game_config.h            # Constants (code base, size, etc.)
├── my_game_init.h              # Function table initialization
├── my_game_init.cpp            # Function mappings array
├── sources.cmake               # List of generated files for CMake
├── sub_82000100.cpp            # Generated function implementations
├── sub_82000200.cpp
└── ...
```

**Example generated function:**

```cpp theme={null}
// generated/sub_82000100.cpp
#include <rex/ppc/context.h>
#include <rex/ppc/state.h>

void __fastcall sub_82000100(PPCContext* ctx) {
  // PowerPC: lis r3, 0x8000
  ctx->r[3] = 0x80000000;
  
  // PowerPC: addi r3, r3, 0x100
  ctx->r[3] = ctx->r[3] + 0x100;
  
  // PowerPC: blr
  return;
}
```

<Note>
  Code generation can take several minutes for large executables. Use `--log_level=debug` to see detailed progress.
</Note>

## Step 5: Configure CMake

Configure the build using CMake presets:

<CodeGroup>
  ```bash Windows Debug theme={null}
  cmake --preset win-amd64-debug -DREXSDK_DIR=/path/to/rexglue-sdk
  ```

  ```bash Windows Release theme={null}
  cmake --preset win-amd64-release -DREXSDK_DIR=/path/to/rexglue-sdk
  ```

  ```bash Linux Debug theme={null}
  cmake --preset linux-amd64-debug -DREXSDK_DIR=/path/to/rexglue-sdk
  ```

  ```bash Linux Release theme={null}
  cmake --preset linux-amd64-release -DREXSDK_DIR=/path/to/rexglue-sdk
  ```
</CodeGroup>

**SDK Path Options:**

1. **Subdirectory**: Set `REXSDK_DIR` to SDK source tree location
2. **Installed Package**: Omit `REXSDK_DIR` if SDK is on `CMAKE_PREFIX_PATH`

Location: `src/rexglue/commands/init_command.cpp:47-60`

## Step 6: Build Your Project

Compile the generated code and runtime:

```bash theme={null}
# Build using preset
cmake --build out/build/<preset-name>

# Or use the codegen target to regenerate + build
cmake --build out/build/<preset-name> --target my_game_codegen
cmake --build out/build/<preset-name>
```

The generated `CMakeLists.txt` includes a custom target for regenerating code:

```cmake theme={null}
add_custom_target(my_game_codegen
    COMMAND $<TARGET_FILE:rex::rexglue> codegen ${CMAKE_CURRENT_SOURCE_DIR}/my_game_config.toml
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
    COMMENT "Generating recompiled code for my_game"
    VERBATIM
)
```

Location: `src/rexglue/commands/init_command.cpp:96-103`

## Step 7: Run Your Recompiled Game

Run the built executable:

```bash theme={null}
# Windows
out\win-amd64\Debug\my_game.exe

# Linux
./out/linux-amd64/Debug/my_game
```

**Runtime command-line flags:**

```bash theme={null}
# Enable verbose logging
my_game --log_level=trace

# Write logs to file
my_game --log_file=my_game.log

# Graphics backend selection (if both compiled)
my_game --gpu_backend=vulkan  # or d3d12
```

## Customizing Your App

Extend the generated `MyGameApp` class to add custom behavior:

```cpp theme={null}
// src/my_hooks.cpp
#include "generated/my_game_config.h"
#include <rex/rex_app.h>

class MyGameApp : public rex::ReXApp {
public:
  using rex::ReXApp::ReXApp;

  // Override initialization
  bool OnInitialize() override {
    if (!ReXApp::OnInitialize()) {
      return false;
    }
    
    // Custom initialization
    REXLOG_INFO("MyGame initialized!");
    return true;
  }

  // Override frame update
  void OnUpdate(double dt) override {
    ReXApp::OnUpdate(dt);
    
    // Custom per-frame logic
  }

  static std::unique_ptr<rex::ui::WindowedApp> Create(
      rex::ui::WindowedAppContext& ctx) {
    return std::unique_ptr<MyGameApp>(new MyGameApp(ctx, "my_game",
        {PPC_CODE_BASE, PPC_CODE_SIZE, PPC_IMAGE_BASE,
         PPC_IMAGE_SIZE, PPCFuncMappings}));
  }
};

REX_DEFINE_APP(my_game, MyGameApp::Create)
```

Then update `CMakeLists.txt` to use your custom main:

```cmake theme={null}
set(MY_GAME_SOURCES
    src/my_hooks.cpp  # Your custom main
    # src/main.cpp    # Comment out SDK-managed main
)
```

## Migrating to New SDK Versions

When updating to a new SDK version, use the migrate command:

```bash theme={null}
rexglue migrate --app_root ./my_game
```

This updates SDK-managed files (CMakeLists.txt, main.cpp) while preserving your configuration and custom code.

Location: `src/rexglue/main.cpp:145-155`

<Warning>
  Migration overwrites `CMakeLists.txt` and `src/main.cpp`. Back up any customizations first or use custom files as shown above.
</Warning>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Codegen fails with 'file not found'">
    Check that `file_path` in your TOML points to a valid XEX file:

    ```bash theme={null}
    ls -lh assets/default.xex
    ```

    Use absolute paths if relative paths aren't resolving correctly.
  </Accordion>

  <Accordion title="Build fails with 'GENERATED_SOURCES not found'">
    You need to run codegen before building:

    ```bash theme={null}
    rexglue codegen my_game_config.toml
    ```

    This creates `generated/sources.cmake` which CMake includes.
  </Accordion>

  <Accordion title="Runtime crashes immediately">
    Common causes:

    1. **Missing assets**: Game may need additional data files
    2. **Invalid function boundaries**: Check TOML function definitions
    3. **Memory mapping failed**: Check system has enough virtual address space

    Enable debug logging to see details:

    ```bash theme={null}
    my_game --log_level=trace --log_file=crash.log
    ```
  </Accordion>

  <Accordion title="Game renders incorrectly">
    Graphics issues may require shader translation fixes or GPU state mapping. This is an active area of development.

    Try:

    * Different graphics backend (Vulkan vs D3D12)
    * Enable RenderDoc for frame capture analysis
    * Report issues on GitHub with screenshots
  </Accordion>
</AccordionGroup>

## Example Projects

Study these complete examples to learn more:

<CardGroup>
  <Card title="demo-iruka" icon="github" href="https://github.com/rexglue/demo-iruka">
    Simple demonstration project showing basic recompilation
  </Card>

  <Card title="reblue" icon="gamepad" href="https://github.com/rexglue/reblue">
    Full game recompilation with custom hooks and asset loading
  </Card>
</CardGroup>

## Next Steps

<CardGroup>
  <Card title="Configuration Reference" icon="gear" href="/configuration">
    Complete TOML configuration options and advanced features
  </Card>

  <Card title="API Reference" icon="book" href="/api-reference">
    ReXGlue SDK API documentation and runtime hooks
  </Card>

  <Card title="Join Discord" icon="discord" href="https://discord.gg/CNTxwSNZfT">
    Get help and share your recompiled projects
  </Card>

  <Card title="GitHub Issues" icon="bug" href="https://github.com/rexglue/rexglue-sdk/issues">
    Report bugs or request features
  </Card>
</CardGroup>



