### Build and Install ReXGlue SDK (Binary Install) Source: https://github.com/rexglue/rexglue-sdk/wiki/SDK-Install-Modes Builds and installs the SDK to the system. This is typically done once per machine or branch and allows consumer projects to discover it via `find_package`. ```bash cmake --preset win-amd64 cmake --build --preset win-amd64 --target install ``` -------------------------------- ### Configure and Build ReXGlue SDK Source: https://github.com/rexglue/rexglue-sdk/wiki/Contributing Use these CMake commands to configure the build for your platform and then build and install the SDK. Ensure you have CMake 3.25+, Clang 20+, and Ninja installed. ```bash cmake --preset win-amd64 # Windows cmake --preset linux-amd64 # Linux ``` ```bash cmake --build out/build/[preset name] --target install ``` -------------------------------- ### Simple Logging Initialization Source: https://github.com/rexglue/rexglue-sdk/wiki/Logging For quick setup without a full configuration, use the simplified `InitLogging` overloads. These provide basic console-only or console-and-file logging with default or specified levels. ```cpp rex::InitLogging(); // console-only, info level rex::InitLogging("game.log"); // console + file, info level rex::InitLogging("game.log", spdlog::level::debug); // console + file, debug level ``` -------------------------------- ### Initialize and Configure Logging Source: https://github.com/rexglue/rexglue-sdk/wiki/Logging Set up the logging system with a configuration object that specifies default log levels, output files, and category-specific settings. This example also shows how to redirect specific categories to different files. ```cpp // main.cpp #include "my_game_logging.h" int main() { rex::LogConfig config; config.default_level = spdlog::level::info; config.log_file = "game.log"; // Crank up input logging for debugging config.category_levels["game.input"] = spdlog::level::trace; // Send netplay logs to a separate file auto net_sink = std::make_shared("netplay.log", true); config.category_sinks["game.netplay"] = {net_sink}; rex::InitLogging(config); rex::RegisterLogLevelCallback(); GAME_INPUT_TRACE("polling controllers, tick {}", tick); GAME_NET_INFO("connected to lobby {}", lobby_id); GAME_SAVE_INFO("checkpoint saved"); rex::ShutdownLogging(); } ``` -------------------------------- ### ReXGlue SDK CMake Install Modes Source: https://context7.com/rexglue/rexglue-sdk/llms.txt Demonstrates three ways to consume the ReXGlue SDK in a CMake project: binary install, git submodule, and FetchContent. All modes expose the same `rex::` CMake target names. ```cmake # ── Mode 1: Binary install (recommended) ────────────────────────────────────── # Build and install once: # cmake --preset win-amd64 # cmake --build --preset win-amd64 --target install # # Consumer CMakeLists.txt (generated by rexglue init): set(REXSDK "" CACHE PATH "Path to ReXGlue SDK install prefix") set(REXSDK_VERSION "" CACHE STRING "Required SDK version, e.g. 0.7.0 (empty = any)") if(REXSDK) list(PREPEND CMAKE_PREFIX_PATH "${REXSDK}") elseif(DEFINED ENV{REXSDK}) list(PREPEND CMAKE_PREFIX_PATH "$ENV{REXSDK}") endif() find_package(rexglue ${REXSDK_VERSION} REQUIRED CONFIG) # ── Mode 2: Git submodule ────────────────────────────────────────────────────── # git submodule add https://github.com/rexglue-sdk/rexglue-sdk thirdparty/rexglue-sdk add_subdirectory(thirdparty/rexglue-sdk) # ── Mode 3: FetchContent ─────────────────────────────────────────────────────── include(FetchContent) FetchContent_Declare(rexglue GIT_REPOSITORY https://github.com/rexglue-sdk/rexglue-sdk GIT_TAG v0.7.0 ) FetchContent_MakeAvailable(rexglue) # All modes: wire the SDK to your target via rexglue_configure_target() # (this is called automatically by the generated rexglue.cmake) rexglue_configure_target(foobar) target_link_libraries(foobar PRIVATE rex::core rex::kernel rex::codegen) ``` -------------------------------- ### Consumer CMakeLists.txt for Binary Install Source: https://github.com/rexglue/rexglue-sdk/wiki/SDK-Install-Modes Configures a consumer project to find and use the ReXGlue SDK installed via the binary method. It allows overriding the auto-discovery path and version. ```cmake set(REXSDK "" CACHE PATH "Path to ReXGlue SDK install prefix (overrides auto-discovery)") set(REXSDK_VERSION "" CACHE STRING "Required ReXGlue SDK version, e.g. 0.2.0 (empty = any)") if(REXSDK) list(PREPEND CMAKE_PREFIX_PATH "${REXSDK}") elseif(DEFINED ENV{REXSDK}) list(PREPEND CMAKE_PREFIX_PATH "$ENV{REXSDK}") endif() find_package(rexglue ${REXSDK_VERSION} REQUIRED CONFIG) ``` -------------------------------- ### Consumer CMakeLists.txt for FetchContent Install Source: https://github.com/rexglue/rexglue-sdk/wiki/SDK-Install-Modes Configures the consumer project to automatically download and build the ReXGlue SDK using CMake's FetchContent module. This is suitable for CI and simplifies onboarding. ```cmake include(FetchContent) FetchContent_Declare(rexglue GIT_REPOSITORY https://github.com/rexglue-sdk/rexglue-sdk GIT_TAG v0.2.0 # pin to a tag or commit hash ) FetchContent_MakeAvailable(rexglue) # rex:: targets are now available directly ``` -------------------------------- ### Clone and Build ReXGlue SDK Source: https://github.com/rexglue/rexglue-sdk/wiki/Getting-Started Clone the SDK repository and build it using CMake presets. The install step registers the SDK with CMake for downstream projects. ```bash git clone --recursive https://github.com/rexglue/rexglue-sdk.git cd rexglue-sdk cmake --preset win-amd64 # or linux-amd64 cmake --build --preset win-amd64 --target install ``` -------------------------------- ### Configure Public Include Directories Source: https://github.com/rexglue/rexglue-sdk/blob/main/src/audio/CMakeLists.txt Sets public include directories for the rexaudio library, making its headers available during build and installation. ```cmake target_include_directories(rexaudio PUBLIC $ $ ) ``` -------------------------------- ### ReXGlue Codegen TOML Configuration Example Source: https://context7.com/rexglue/rexglue-sdk/llms.txt This TOML file configures the codegen pipeline, specifying the input binary, output directory, and other parameters. `rexglue init` generates a starter file. ```toml # foobar_config.toml # Required project_name = "foobar" file_path = "assets/default.xex" out_directory_path = "generated" ``` -------------------------------- ### Configure Include Directories for libavcodec Source: https://github.com/rexglue/rexglue-sdk/blob/main/thirdparty/CMakeLists.txt Sets up include directories for the libavcodec target, including build interface, installation, and private includes. The build interface directory is prioritized. ```cmake target_include_directories(libavcodec BEFORE PRIVATE "${FFMPEG_OVERLAY_BUILD_DIR}") target_include_directories(libavcodec PUBLIC $ $ PRIVATE ${FFMPEG_ATOMICS_INCLUDE} ) ``` -------------------------------- ### Consumer CMakeLists.txt for Git Submodule Install Source: https://github.com/rexglue/rexglue-sdk/wiki/SDK-Install-Modes Integrates the ReXGlue SDK into the consumer project by adding its source directory. This makes `rex::` targets available directly without needing `find_package`. ```cmake add_subdirectory(thirdparty/rexglue-sdk) # rex:: targets are now available directly — no find_package needed ``` -------------------------------- ### Configure Public Include Directories Source: https://github.com/rexglue/rexglue-sdk/blob/main/src/input/CMakeLists.txt Sets the public include directories for the 'rexinput' library. This ensures that headers are accessible during the build and installation process. ```cmake target_include_directories(rexinput PUBLIC $ $ ) ``` -------------------------------- ### Configure Per-Project SDK Selection with CMakeUserPresets.json Source: https://github.com/rexglue/rexglue-sdk/wiki/SDK-Install-Modes Sets the `REXSDK` cache variable in a `CMakeUserPresets.json` file to specify a particular SDK installation path for the current project. This file should be gitignored. ```json { "version": 6, "configurePresets": [ { "name": "user-env", "hidden": true, "cacheVariables": { "REXSDK": "/some/install/path" } }, { "name": "win-amd64-debug", "inherits": ["win-amd64-debug", "user-env"] }, { "name": "win-amd64-release", "inherits": ["win-amd64-release", "user-env"] }, { "name": "win-amd64-relwithdebinfo", "inherits": ["win-amd64-relwithdebinfo", "user-env"] }, { "name": "linux-amd64-debug", "inherits": ["linux-amd64-debug", "user-env"] }, { "name": "linux-amd64-release", "inherits": ["linux-amd64-release", "user-env"] }, { "name": "linux-amd64-relwithdebinfo", "inherits": ["linux-amd64-relwithdebinfo", "user-env"] } ] } ``` -------------------------------- ### Generated Code Call Site Example Source: https://github.com/rexglue/rexglue-sdk/wiki/Generated-Code-Structure Illustrates how call sites in generated code target ReXCRT functions using their prefixed names, instead of direct memory addresses. This ensures that SDK-provided host-native implementations are used. ```cpp rexcrt_RtlAllocateHeap(ctx, base); // instead of sub_820A0000 ``` -------------------------------- ### Define a Custom ReXApp for Windowed Applications Source: https://context7.com/rexglue/rexglue-sdk/llms.txt Subclass ReXApp to create windowed applications. Override virtual hooks to customize behavior during different lifecycle phases like path configuration, presentation setup, and runtime initialization. Ensure PPCImageConfig is generated by rexglue codegen. ```cpp #pragma once #include #include "generated/foobar_init.h" // PPCImageConfig class FoobarApp : public rex::ReXApp { public: using rex::ReXApp::ReXApp; static std::unique_ptr Create( rex::ui::WindowedAppContext& ctx) { // PPCImageConfig carries code_base, code_size, image_base, image_size, // PPCFuncMappings[] — all generated by rexglue codegen. return std::unique_ptr(new FoobarApp(ctx, "foobar", PPCImageConfig)); } // ── Phase 1: SetupEnvironment ────────────────────────────────────────────── void OnConfigurePaths(rex::PathConfig& paths) override { // Override path defaults before the window opens. paths.user_data_root = std::filesystem::path(getenv("HOME")) / ".foobar"; } // ── Phase 2: SetupPresentation ───────────────────────────────────────────── void OnPreSetup(rex::RuntimeConfig& cfg) override { // Swap to Vulkan, or enable tool_mode (headless, no graphics init). cfg.use_vulkan = true; } void OnCreateDialogs(rex::ui::ImGuiDrawer* drawer) override { // Register custom ImGui overlay dialogs. drawer->AddDialog(std::make_unique(drawer)); } // ── Phase 3: Path finalization ───────────────────────────────────────────── // OnFinalizePaths() can show a UI file-picker and return asynchronously. std::optional OnFinalizePaths( const rex::PathConfig& defaults, std::function resume) override { // Synchronous path: return directly. rex::PathConfig cfg = defaults; cfg.game_data_root = "./assets"; return cfg; // Async path: show dialog, call resume(cfg) from callback, return nullopt. } // ── Phase 4: ConstructRuntime ────────────────────────────────────────────── void OnPostLoadXexImage() override { // XEX data is mapped into guest memory. Patch loaded data here. auto* mem = kernel_state()->memory(); uint32_t* flag = mem->TranslateVirtual(0x82500000); *flag = 1; // big-endian patch } void OnPostSetup() override { // Runtime fully initialized. Register custom kernel exports, etc. } // ── Phase 5: LaunchModule ───────────────────────────────────────────────── void OnPreLaunchModule() override { // Last chance to patch guest memory before the main thread starts. } void OnGuestThreadExit(rex::kernel::XThread* thread) override { // Main guest thread exited. Runtime is still alive; safe to do cleanup. REXLOG_INFO("Guest thread exited with r3={:#x}", thread->context().r3.u32); } // ── Shutdown ─────────────────────────────────────────────────────────────── void OnShutdown() override { /* Release custom resources. */ } }; ``` ```cpp #include "generated/foobar_init.h" #include "foobar_app.h" REX_DEFINE_APP(foobar, FoobarApp::Create) ``` -------------------------------- ### Initialization Source (`_init.cpp`) Source: https://github.com/rexglue/rexglue-sdk/wiki/Generated-Code-Structure Defines `PPCImageConfig` and `PPCFuncMappings[]`. `Runtime::Setup()` uses `PPCFuncMappings` to populate the function dispatch table in guest memory. ```cpp #include "{project}_init.h" const rex::PPCImageInfo PPCImageConfig = { REX_CODE_BASE, // code_base REX_CODE_SIZE, // code_size REX_IMAGE_BASE, // image_base REX_IMAGE_SIZE, // image_size PPCFuncMappings, // func_mappings REXCRT_HEAP, // rexcrt_heap }; PPCFuncMapping PPCFuncMappings[] = { { 0x82020000, xstart }, { 0x82003A40, sub_82003A40 }, { 0x82010000, rexcrt_RtlAllocateHeap }, // ... all recompiled functions { 0x82100000, __imp__NtAllocateVirtualMemory }, // import thunks { 0, nullptr } // null terminator }; ``` -------------------------------- ### Configure SPIRV-Headers in CMake Source: https://github.com/rexglue/rexglue-sdk/blob/main/thirdparty/CMakeLists.txt Configures SPIRV-Headers by disabling tests and installation. Use when integrating SPIRV-Headers for Vulkan backend. ```cmake if(REXGLUE_USE_VULKAN) set(SPIRV_HEADERS_ENABLE_TESTS OFF CACHE BOOL "" FORCE) set(SPIRV_HEADERS_ENABLE_INSTALL OFF CACHE BOOL "" FORCE) add_subdirectory(spirv-headers) endif() ``` -------------------------------- ### Initialize a New ReXGlue Project Source: https://github.com/rexglue/rexglue-sdk/wiki/Getting-Started Scaffold a new project using the `rexglue init` command, specifying the application name and root directory. ```bash rexglue init --app_name "foobar" --app_root ./foobar ``` -------------------------------- ### Rexglue Init Command Structure Source: https://github.com/rexglue/rexglue-sdk/wiki/rexglue-CLI-Commands Initializes a new ReXGlue project. Requires application name and root directory. Optional flags control description, author, and overwriting existing files. ```bash rexglue init --app_name --app_root [flags] ``` -------------------------------- ### Configure SPIRV-Tools in CMake Source: https://github.com/rexglue/rexglue-sdk/blob/main/thirdparty/CMakeLists.txt Configures SPIRV-Tools by skipping executables, tests, and installation, and disabling warnings. Use when integrating SPIRV-Tools for Vulkan backend. ```cmake if(REXGLUE_USE_VULKAN) set(SPIRV_SKIP_EXECUTABLES ON CACHE BOOL "" FORCE) set(SPIRV_SKIP_TESTS ON CACHE BOOL "" FORCE) set(SPIRV_WERROR OFF CACHE BOOL "" FORCE) set(SKIP_SPIRV_TOOLS_INSTALL ON CACHE BOOL "" FORCE) add_subdirectory(spirv-tools) target_compile_options(SPIRV-Tools-static PRIVATE -w) endif() ``` -------------------------------- ### Creating Kernel Objects with KernelState Source: https://context7.com/rexglue/rexglue-sdk/llms.txt Demonstrates the process of allocating and initializing a kernel object (XSemaphore) and adding it to the object table to obtain a guest handle. ```cpp // ── Creating kernel objects in guest memory ─────────────────────────────── auto sem = object_ref::alloc(ks); sem->Initialize(/*initial_count=*/0, /*maximum_count=*/10); uint32_t handle = ks->object_table()->Add(std::move(sem)); // returns guest handle ``` -------------------------------- ### Boolean Hook Function Signature Source: https://github.com/rexglue/rexglue-sdk/wiki/rexglue-CLI-Configuration-File Example signature for a boolean hook function used for conditional control flow based on the return value. ```cpp bool MyHook(PPCRegister& r3) { if (some_condition) { r3.u64 = 42; // Modify register before jump return true; // Triggers jump_address_on_true } return false; // Continue normal execution } ``` -------------------------------- ### Accessing KernelState and Subsystems Source: https://context7.com/rexglue/rexglue-sdk/llms.txt Demonstrates how to access the global KernelState singleton and its subsystem accessors for memory, file system, and function dispatch. Include the necessary header. ```cpp #include rex::system::KernelState* ks = kernel_state(); // ── Subsystem accessors ─────────────────────────────────────────────────── rex::Memory* mem = ks->memory(); rex::VirtualFileSystem* vfs = ks->file_system(); rex::FunctionDispatcher* disp = ks->function_dispatcher(); ``` -------------------------------- ### Initialize and Run rex::Runtime Directly (Headless) Source: https://context7.com/rexglue/rexglue-sdk/llms.txt Construct and manage rex::Runtime manually for headless tools or custom windowing. Configure runtime settings, inject backends, and load/launch XEX images. The runtime blocks execution until the guest thread exits. ```cpp #include #include #include "generated/foobar_init.h" int main() { rex::RuntimeConfig cfg; cfg.game_data_root = "./assets"; cfg.user_data_root = "./userdata"; // Inject backends (nullptr = disabled) cfg.audio_factory = nullptr; cfg.input_factory = nullptr; cfg.graphics_factory = nullptr; // Kernel init callback: registers xboxkrnl/xam export tables cfg.kernel_init = [](rex::system::KernelState* ks) { ks->LoadKernelModule(); ks->LoadKernelModule(); }; rex::Runtime runtime; runtime.Setup(cfg, PPCImageConfig); // initializes all subsystems + dispatch table runtime.LoadXexImage("game:/default.xex"); auto* module = runtime.GetExecutableModule(); runtime.LaunchModule(module); // creates + resumes the main XThread runtime.Run(); // blocks until guest thread exits runtime.Shutdown(); return 0; } ``` -------------------------------- ### Configure glslang for SPIR-V in CMake Source: https://github.com/rexglue/rexglue-sdk/blob/main/thirdparty/CMakeLists.txt Configures glslang for SPIR-V code generation, disabling binaries, tests, and installation, while enabling RTTI. Use for shader translation in Vulkan backend. ```cmake if(REXGLUE_USE_VULKAN) set(ENABLE_GLSLANG_BINARIES OFF CACHE BOOL "" FORCE) set(ENABLE_SPVREMAPPER OFF CACHE BOOL "" FORCE) set(ENABLE_HLSL OFF CACHE BOOL "" FORCE) set(ENABLE_OPT OFF CACHE BOOL "" FORCE) set(BUILD_TESTING OFF CACHE BOOL "" FORCE) set(SKIP_GLSLANG_INSTALL ON CACHE BOOL "" FORCE) set(ENABLE_RTTI ON CACHE BOOL "" FORCE) set(CMAKE_POLICY_VERSION_MINIMUM 3.5 CACHE STRING "" FORCE) add_subdirectory(glslang) if(NOT TARGET glslang::SPIRV) add_library(glslang::SPIRV ALIAS SPIRV) endif() endif() ``` -------------------------------- ### Module Loading and Execution Source: https://context7.com/rexglue/rexglue-sdk/llms.txt Explains how to load a user module, set it as the executable module, and launch it, which involves creating an XThread and calling the FunctionDispatcher. ```cpp // ── Module loading ──────────────────────────────────────────────────────── // LoadUserModule maps XEX data sections; execution uses the pre-built function table. auto* module = ks->LoadUserModule("game:\\default.xex"); ks->SetExecutableModule(module); // sets kernel globals from XEX header ks->LaunchModule(module); // creates XThread → calls FunctionDispatcher ``` -------------------------------- ### Scaffold a new ReXGlue project Source: https://context7.com/rexglue/rexglue-sdk/llms.txt Use `rexglue init` to create a new project skeleton. Specify the application name and root directory. The `--force` flag overwrites an existing directory. ```bash # Create a new project called "foobar" in ./foobar/ rexglue init --app_name "foobar" --app_root ./foobar # Generated layout: # foobar/ # ⌂⌂ CMakeLists.txt # SDK discovery + rexglue_setup_target() # ⌂⌂ CMakePresets.json # win-amd64-{debug,release,relwithdebinfo}, linux-amd64-* # ⌂⌂ foobar_config.toml # Codegen config template (fill in file_path) # ⌂⌂ src/ # ⌂⌂ ⌂⌂ main.cpp # REX_DEFINE_APP(foobar, FoobarApp::Create) # ⌂⌂ ⌂⌂ foobar_app.h # ReXApp subclass with virtual hook stubs # ⌂⌂ generated/ # ⌂⌂ ⌂⌂ rexglue.cmake # SDK integration (auto-regenerated by rexglue migrate) # Overwrite an existing directory rexglue init --app_name "foobar" --app_root ./foobar --force ``` -------------------------------- ### Query and Manage Log Categories Source: https://context7.com/rexglue/rexglue-sdk/llms.txt Find specific log categories by name, retrieve all registered categories, and set their levels. This enables introspection and dynamic modification of the logging setup. ```cpp // ── Category query ──────────────────────────────────────────────────────── if (auto cat = rex::FindCategory("app.input")) { rex::SetCategoryLevel(*cat, spdlog::level::trace); } for (const auto& e : rex::GetAllCategories()) { fmt::print("{}: {} ", e.name, spdlog::level::to_string_view(e.logger->level())); } rex::ShutdownLogging(); ``` -------------------------------- ### ReXGlue SDK Configuration Options Source: https://context7.com/rexglue/rexglue-sdk/llms.txt Configure patch files, register locality, exception handlers, and jump address hints. Adjust analysis parameters like max jump extension and data region thresholds. Define manual function boundaries and switch tables. Mark invalid instructions and set up mid-ASM hooks. Map guest CRT functions to SDK native implementations. ```toml # Optional XEX patch patch_file_path = "assets/patch.xexp" patched_file_path = "assets/default_patched.xex" # Register locality — emit registers as C++ locals instead of PPCContext members. # Reduces memory traffic; Clang can allocate them to host registers. ctr_as_local = true cr_as_local = true non_volatile_as_local = true # elides __savegprlr/__restgprlr calls # Exception handler generation enable_exception_handlers = false # setjmp/longjmp address hints (required for correct non-local jump handling) setjmp_address = 0x82001000 longjmp_address = 0x82002000 # Analysis tuning [analysis] max_jump_extension = 65536 data_region_threshold = 16 large_function_threshold = 1048576 # Manual function boundary overrides (CONFIG authority — cannot be overridden) [functions] 0x82000000 = { name = "GameMain" } 0x82000100 = { size = 64 } 0x82000200 = { end = 0x82000280 } 0x82000300 = { parent = 0x82000000, size = 32 } # discontinuous chunk # Manual switch/jump table when auto-detection fails [[switch_tables]] address = 0x82005000 register = 11 labels = [0x82005100, 0x82005200, 0x82005300] # Mark embedded data patterns that look like code [[invalid_instructions]] data = 0xDEADBEEF size = 64 # Mid-ASM hook: inject a call before the instruction at 0x82000000 [[midasm_hook]] address = 0x82000000 name = "MyHook" registers = ["r3", "r4"] after_instruction = false jump_address_on_true = 0x82000004 # CRT replacement: map guest CRT functions to SDK native implementations [rexcrt] RtlAllocateHeap = "0x820A0000" RtlFreeHeap = "0x820A0100" RtlSizeHeap = "0x820A0200" RtlReAllocateHeap = "0x820A0300" memcpy = "0x820B0000" memset = "0x820B0100" ``` -------------------------------- ### ReXApp Subclass with Create Factory Source: https://github.com/rexglue/rexglue-sdk/wiki/ReXApp Defines a subclass of rex::ReXApp, including a static Create factory method that initializes the application with context and configuration. ```cpp class FoobarApp : public rex::ReXApp { public: using rex::ReXApp::ReXApp; static std::unique_ptr Create( rex::ui::WindowedAppContext& ctx) { return std::unique_ptr(new FoobarApp(ctx, "foobar", PPCImageConfig)); } // Override hooks here: OnPreSetup, OnPostSetup, OnCreateDialogs, etc. }; ``` -------------------------------- ### Recompiled Function Structure Example Source: https://github.com/rexglue/rexglue-sdk/wiki/Generated-Code-Structure Illustrates the standard C++ structure of a recompiled function, including prologue, local variable declarations, block comments with original disassembly, and control flow constructs like branches and calls. ```cpp DEFINE_REX_FUNC(sub_82003A40) { REX_FUNC_PROLOGUE(); // Local variable declarations (when register locality is enabled) PPCRegister r0{}; PPCRegister r11{}; PPCRegister r12{}; PPCCRRegister cr0{}; // Block: 0x82003A40 // stwu r1, -0x20(r1) ctx.r1.s64 = ctx.r1.s64 + -32; PPC_STORE_U32(base, ctx.r1.u32 + 4294967264, ctx.r1.u32); // mflr r0 r0.u64 = ctx.lr; // stw r0, 0x24(r1) PPC_STORE_U32(base, ctx.r1.u32 + 36, r0.u32); // bl sub_82010000 ctx.lr = 0x82003A50; sub_82010000(ctx, base); // Block: 0x82003A50 // cmpwi cr0, r3, 0 cr0.compare(ctx.r3.s32, 0, ctx.xer); // beq cr0, loc_82003A68 if (cr0.eq) goto loc_82003A68; // bl __imp__DbgPrint ctx.lr = 0x82003A5C; __imp__DbgPrint(ctx, base); loc_82003A68: // Block: 0x82003A68 // lwz r0, 0x24(r1) r0.u64 = PPC_LOAD_U32(base, ctx.r1.u32 + 36); // mtlr r0 ctx.lr = r0.u64; // addi r1, r1, 0x20 ctx.r1.s64 = ctx.r1.s64 + 32; // blr return; } ``` -------------------------------- ### Generated Project Structure Source: https://github.com/rexglue/rexglue-sdk/wiki/ReXApp Illustrates the directory structure generated by `rexglue init` and explains the key files. ```APIDOC ## Generated Project Structure `rexglue init --app_name "foobar" --app_root ./foobar` produces: ``` foobar/ ├── CMakeLists.txt # Build config with SDK discovery and platform settings ├── CMakePresets.json # Platform presets (win-amd64, linux-amd64) ├── foobar_config.toml # Codegen configuration template ├── src/ │ ├── main.cpp # Entry point: REX_DEFINE_APP macro │ └── foobar_app.h # ReXApp subclass with override stubs └── generated/ └── rexglue.cmake # SDK integration script (auto-managed by rexglue migrate) ``` **`src/main.cpp`** includes the [[generated headers|Generated Code Structure]] and defines the application entry point: ```cpp #include "generated/foobar_init.h" #include "foobar_app.h" REX_DEFINE_APP(foobar, FoobarApp::Create) ``` **`src/foobar_app.h`** contains the `ReXApp` subclass. The `Create` factory passes `PPCImageConfig` (code base, code size, image base, image size, function mappings) from the generated headers: ```cpp class FoobarApp : public rex::ReXApp { public: using rex::ReXApp::ReXApp; static std::unique_ptr Create( rex::ui::WindowedAppContext& ctx) { return std::unique_ptr(new FoobarApp(ctx, "foobar", PPCImageConfig)); } // Override hooks here: OnPreSetup, OnPostSetup, OnCreateDialogs, etc. }; ``` **`generated/rexglue.cmake`** is regenerated by `rexglue migrate` on SDK version upgrades. Do not edit it manually. ``` -------------------------------- ### Typed Callable Import with REX_IMPORT Source: https://github.com/rexglue/rexglue-sdk/wiki/Function-Overrides Use REX_IMPORT to wrap recompiled functions, allowing host code to call them with normal C++ types. This macro generates a callable that handles register setup, function invocation, and result retrieval. ```cpp #include // Declare an external recompiled function with a typed signature. REX_IMPORT(sub_82003A40, AddFunc, uint32_t(uint32_t, uint32_t)); // Call it. The macro creates an inline `AddFunc` callable that sets up // registers, invokes the function, and returns the result. uint32_t result = AddFunc(10, 20); ``` -------------------------------- ### Get Raw and Shared Loggers Source: https://github.com/rexglue/rexglue-sdk/wiki/Logging Access the spdlog logger directly for advanced use cases. Use raw pointers for zero overhead or shared pointers for managing references and sinks. The default core logger is also accessible. ```cpp // Raw pointer (zero overhead, used by macros internally) spdlog::logger* logger = rex::GetLoggerRaw(rex::log::GPU); if (logger && logger->should_log(spdlog::level::debug)) { logger->debug("custom message"); } // Shared pointer (for holding references or manipulating sinks) auto logger = rex::GetLogger(rex::log::GPU); // Default (Core) logger auto core = rex::GetLogger(); ``` -------------------------------- ### Initialization Header (`_init.h`) Source: https://github.com/rexglue/rexglue-sdk/wiki/Generated-Code-Structure Defines image layout constants, function-definition macros, and forward declarations for recompiled functions. Use `DECLARE_REX_FUNC` for public symbols and `__imp__`-prefixed implementations. ```cpp #pragma once #define REX_IMAGE_BASE 0x82000000ull #define REX_IMAGE_SIZE 0x1A00000ull #define REX_CODE_BASE 0x82020000ull #define REX_CODE_SIZE 0x190E000ull #define REXCRT_HEAP 1 // 1 if [rexcrt] contains heap functions, 0 otherwise #include #include extern const rex::PPCImageInfo PPCImageConfig; extern PPCFuncMapping PPCFuncMappings[]; // Macros used by every recompiled function below #define DECLARE_REX_FUNC(name) \ REX_EXTERN(name); \ REX_EXTERN(__imp__##name) #define DEFINE_REX_FUNC(name) \ __attribute__((alias("__imp__" #name))) REX_WEAK_FUNC(name); \ REX_EXTERN(__imp__##name) // Import function declarations DECLARE_REX_FUNC(__imp__NtAllocateVirtualMemory); DECLARE_REX_FUNC(__imp__DbgPrint); // Recompiled function declarations DECLARE_REX_FUNC(xstart); DECLARE_REX_FUNC(sub_82003A40); DECLARE_REX_FUNC(rexcrt_RtlAllocateHeap); // ... ``` -------------------------------- ### Virtual File System: Path Resolution and Device Mounting Source: https://context7.com/rexglue/rexglue-sdk/llms.txt Resolve guest paths to host directories and register custom devices or symbolic links. Understand default VFS mounts and file I/O disposition modes. ```cpp #include rex::VirtualFileSystem* vfs = kernel_state()->file_system(); // ── Path resolution ─────────────────────────────────────────────────────── // Guest path "game:\\content\\data.bin" // → symlink "game:" → "\\Device\\Harddisk0\\Partition1" // → HostPathDevice maps to game_data_root on host rex::Entry* entry = vfs->ResolvePath("game:\\content\\data.bin"); if (entry && entry->type() == rex::EntryType::kFile) { rex::File* file = nullptr; entry->Open(rex::FileAccess::kRead, &file); // ... } // ── Custom device mounts ───────────────────────────────────────────────── // Map "mods:" to a host directory (read-only) vfs->RegisterDevice(std::make_unique( "\\Device\\Mods\\Partition1", std::filesystem::path("./mods"), /*read_only=*/true)); vfs->RegisterSymbolicLink("mods:", "\\Device\\Mods\\Partition1"); // NullDevice: accept all I/O for cache paths games expect to exist vfs->RegisterDevice(std::make_unique( "\\Device\\Cache", std::vector{"\\Partition0", "\\Cache0", "\\Cache1"})); // ── Default mount table (configured by Runtime::SetupVfs) ───────────────── // \\Device\\Harddisk0\\Partition1 → game_data_root (symlinks: game:, d:) // \\Device\\Harddisk0\\PartitionUpdate → update_data_root (symlink: update:) // \\Device\\Harddisk0 → NullDevice (\\Partition0, \\Cache0, \\Cache1) // ── File I/O disposition modes ──────────────────────────────────────────── // Supersede: replace if exists, create if not // Open: open if exists, error if not // Create: error if exists, create if not // OpenIf: open if exists, create if not // Overwrite: overwrite if exists, error if not // OverwriteIf: overwrite if exists, create if not ``` -------------------------------- ### Initialize Rexglue Logging System Source: https://context7.com/rexglue/rexglue-sdk/llms.txt Configure and initialize the logging system with custom settings for levels, console output, file logging, and category-specific configurations. Allows routing specific categories to different sinks. ```cpp #include // ── Initialization ──────────────────────────────────────────────────────── rex::LogConfig config; config.default_level = spdlog::level::info; config.log_to_console = true; config.log_file = "game.log"; config.console_pattern = "[%^%l%$] [%n] %v"; config.category_levels["gpu"] = spdlog::level::trace; config.category_levels["app.input"] = spdlog::level::warn; // Route netplay logs to a separate file auto net_sink = std::make_shared("netplay.log", true); config.category_sinks["app.netplay"] = {net_sink}; rex::InitLogging(config); rex::RegisterLogLevelCallback(); // allows the log_level CVar to change level at runtime ``` -------------------------------- ### Building LogConfig from CLI and Environment Variables Source: https://github.com/rexglue/rexglue-sdk/wiki/Logging Use the `BuildLogConfig` helper to create a `LogConfig` object from command-line arguments and environment variables, respecting a defined precedence order. ```cpp // Precedence: CLI args > REX_LOG_LEVEL env var > build-type default auto config = rex::BuildLogConfig( log_file_path, // const char* or nullptr cli_log_level, // e.g. "debug" from --log_level cli_category_levels // e.g. {"gpu": "trace", "cpu": "warn"} ); rex::InitLogging(config); ``` -------------------------------- ### Define rexinput Static Library Source: https://github.com/rexglue/rexglue-sdk/blob/main/src/input/CMakeLists.txt Defines the static library 'rexinput' and its source files. This is the primary way to build the input system library. ```cmake add_library(rexinput STATIC input_system.cpp mnk/mnk_input_driver.cpp nop/nop_input_driver.cpp ) ``` -------------------------------- ### Full Logging Configuration with LogConfig Struct Source: https://github.com/rexglue/rexglue-sdk/wiki/Logging Initialize logging with detailed control by passing a `LogConfig` struct to `InitLogging()`. This allows customization of levels, sinks, patterns, and per-category settings. ```cpp rex::LogConfig config; config.default_level = spdlog::level::debug; config.log_to_console = true; config.log_file = "game.log"; config.console_pattern = "[%^%l%$] [%n] %v"; config.file_pattern = "[%Y-%m-%d %H:%M:%S.%e] [%l] [%n] [t%t] %v"; config.flush_level = spdlog::level::warn; // Per-category level overrides (by name, works for unregistered categories too) config.category_levels["gpu"] = spdlog::level::trace; config.category_levels["app.input"] = spdlog::level::warn; rex::InitLogging(config); ``` -------------------------------- ### Create and Push Release Branch Source: https://github.com/rexglue/rexglue-sdk/blob/main/docs/RELEASING.md Branch from the development tip and push the new release branch to origin. This is the first step in cutting a release. ```git git fetch origin git checkout -b release/X.Y.Z origin/development git push -u origin release/X.Y.Z ``` -------------------------------- ### Add rexaudio Static Library Source: https://github.com/rexglue/rexglue-sdk/blob/main/src/audio/CMakeLists.txt Defines the rexaudio static library and lists its source files, including NOP and SDL backends. ```cmake add_library(rexaudio STATIC audio_driver.cpp audio_system.cpp xma_context.cpp xma_decoder.cpp xma_register_file.cpp # NOP backend (always available) nop/nop_audio_system.cpp # SDL backend sdl/sdl_audio_system.cpp sdl/sdl_audio_driver.cpp ) ``` -------------------------------- ### REX_DEFINE_APP Macro Usage Source: https://github.com/rexglue/rexglue-sdk/wiki/ReXApp Defines the application entry point using the REX_DEFINE_APP macro, linking the application name and its creation function. ```cpp #include "generated/foobar_init.h" #include "foobar_app.h" REX_DEFINE_APP(foobar, FoobarApp::Create) ``` -------------------------------- ### Configure FFmpeg for XMA Decoding in CMake Source: https://github.com/rexglue/rexglue-sdk/blob/main/thirdparty/CMakeLists.txt Sets up FFmpeg by defining source and build directories, copying necessary list files, and defining common preprocessor macros. Use for WMA Pro decoding. ```cmake set(FFMPEG_DIR "${CMAKE_CURRENT_SOURCE_DIR}/FFmpeg") set(FFMPEG_OVERLAY_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ffmpeg-overlay") set(FFMPEG_OVERLAY_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/ffmpeg-overlay") file(MAKE_DIRECTORY "${FFMPEG_OVERLAY_BUILD_DIR}/libavcodec") configure_file( "${FFMPEG_OVERLAY_SRC_DIR}/codec_list.c" "${FFMPEG_OVERLAY_BUILD_DIR}/libavcodec/codec_list.c" COPYONLY ) configure_file( "${FFMPEG_OVERLAY_SRC_DIR}/parser_list.c" "${FFMPEG_OVERLAY_BUILD_DIR}/libavcodec/parser_list.c" COPYONLY ) configure_file( "${FFMPEG_OVERLAY_SRC_DIR}/bsf_list.c" "${FFMPEG_OVERLAY_BUILD_DIR}/libavcodec/bsf_list.c" COPYONLY ) set(FFMPEG_COMMON_DEFINES HAVE_AV_CONFIG_H _USE_MATH_DEFINES # For M_PI/etc ) ``` -------------------------------- ### Rexglue Recompile-Tests Command Structure Source: https://github.com/rexglue/rexglue-sdk/wiki/rexglue-CLI-Commands Generates Catch2 unit tests from PPC assembly test specifications. Requires paths to the binary directory, assembly directory, and output directory. ```bash rexglue recompile-tests --bin_dir --asm_dir --output ``` -------------------------------- ### CMake Helpers Source: https://github.com/rexglue/rexglue-sdk/wiki/ReXApp Explains the CMake helper function `rexglue_configure_target` for integrating the SDK into your project. ```APIDOC ## CMake Helpers The generated `rexglue.cmake` provides: - **`rexglue_configure_target()`**: adds the platform-specific entry point source (`windowed_app_main_win.cpp` or `_posix.cpp`) and the `ReXApp` base class source (`rex_app.cpp`) to the target. This is the primary integration point between your project and the SDK. The top-level `CMakeLists.txt` generated by `rexglue init` handles SDK discovery (via `REXSDK` cache variable or FetchContent), compiler settings, and links the generated recompiled code. See [[SDK Install Modes]] for the full discovery chain. ``` -------------------------------- ### Create Alias for rexaudio Library Source: https://github.com/rexglue/rexglue-sdk/blob/main/src/audio/CMakeLists.txt Creates an alias 'rex::audio' for the 'rexaudio' library for easier referencing. ```cmake add_library(rex::audio ALIAS rexaudio) ``` -------------------------------- ### Upgrade ReXGlue project to current SDK version Source: https://context7.com/rexglue/rexglue-sdk/llms.txt Use `rexglue migrate` to update `generated/rexglue.cmake` and optionally user files. The `--force` flag bypasses confirmation prompts. ```bash # Upgrade an existing project (prompts before touching user files) rexglue migrate --app_root ./foobar # Skip confirmation prompt (for CI pipelines) rexglue migrate --app_root ./foobar --force ``` -------------------------------- ### Rexglue Migrate Command Structure Source: https://github.com/rexglue/rexglue-sdk/wiki/rexglue-CLI-Commands Upgrades an existing ReXGlue project to the current SDK version. Requires the project root path. ```bash rexglue migrate --app_root [flags] ``` -------------------------------- ### Compile AES-128 Source: https://github.com/rexglue/rexglue-sdk/blob/main/thirdparty/aes_128/README.md Instructions on how to compile the AES-128 library. ```APIDOC ## Compile ```sh make ``` ``` -------------------------------- ### LogConfig Struct and Initialization Source: https://github.com/rexglue/rexglue-sdk/wiki/Logging Configure logging behavior using the `LogConfig` struct and `InitLogging` function. ```APIDOC ## Configuration ### LogConfig Struct Pass a `LogConfig` to `InitLogging()` for full control: ```cpp rex::LogConfig config; config.default_level = spdlog::level::debug; config.log_to_console = true; config.log_file = "game.log"; config.console_pattern = "[\%^\%l\%$\] [\%n] %v"; config.file_pattern = "[\%Y-\%m-\%d \%H:\%M:\%S.\%e] [\%l] [\%n] [t\%t] %v"; config.flush_level = spdlog::level::warn; // Per-category level overrides (by name, works for unregistered categories too) config.category_levels["gpu"] = spdlog::level::trace; config.category_levels["app.input"] = spdlog::level::warn; rex::InitLogging(config); ``` | Field | Type | Default | Description | |-------|------|---------|-------------| | `default_level` | `spdlog::level::level_enum` | `info` | Global default level | | `log_to_console` | `bool` | `true` | Create stdout sink | | `use_colors` | `bool` | `true` | ANSI color codes on console | | `log_file` | `const char*` | `nullptr` | Log file path (null = no file) | | `console_pattern` | `std::string` | `"[\%^\%l\%$\] [\%n] [t\%t] %v"` | Console format pattern | | `file_pattern` | `std::string` | `"[\%Y-\%m-\%d \%H:\%M:\%S.\%e] [\%l] [\%n] [t\%t] %v"` | File format pattern | | `flush_level` | `spdlog::level::level_enum` | `warn` | Auto-flush threshold | | `category_levels` | `std::map` | `{}` | Per-category level overrides | | `extra_sinks` | `std::vector` | `{}` | Additional sinks for all loggers | | `category_sinks` | `std::map>` | `{}` | Per-category extra sinks | | `category_sinks_exclusive` | `bool` | `false` | If true, per-category sinks replace defaults | ### Simple Initialization For quick setup without a full config: ```cpp rex::InitLogging(); // console-only, info level rex::InitLogging("game.log"); // console + file, info level rex::InitLogging("game.log", spdlog::level::debug); // console + file, debug level ``` ### BuildLogConfig Helper Build a `LogConfig` from CLI arguments and environment variables with proper precedence: ```cpp // Precedence: CLI args > REX_LOG_LEVEL env var > build-type default auto config = rex::BuildLogConfig( log_file_path, // const char* or nullptr cli_log_level, // e.g. "debug" from --log_level cli_category_levels // e.g. {"gpu": "trace", "cpu": "warn"} ); rex::InitLogging(config); ``` ```