Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
FROM ubuntu:24.04

# Install LLVM 19 repo (xwin's latest MSVC STL requires Clang 19+)
RUN apt-get update && apt-get install -y --no-install-recommends \
curl ca-certificates gnupg \
&& curl -fsSL https://apt.llvm.org/llvm-snapshot.gpg.key \
> /etc/apt/trusted.gpg.d/llvm.asc \
&& echo "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-19 main" \
> /etc/apt/sources.list.d/llvm-19.list \
&& apt-get update && apt-get install -y --no-install-recommends \
cmake \
ninja-build \
clang-19 \
lld-19 \
llvm-19 \
git \
&& rm -rf /var/lib/apt/lists/*

# Create unversioned tool symlinks
# clang-cl is clang invoked by a different name (argv[0] detection)
RUN ln -sf /usr/bin/clang-19 /usr/bin/clang-cl \
&& for tool in clang clang++ lld-link llvm-lib llvm-rc llvm-mt llvm-ar; do \
ln -sf "/usr/bin/${tool}-19" "/usr/bin/$tool"; \
done

# Install xwin to download Windows SDK and MSVC CRT
ARG XWIN_VERSION=0.6.5
RUN curl -fsSL "https://github.com/Jake-Shadle/xwin/releases/download/${XWIN_VERSION}/xwin-${XWIN_VERSION}-x86_64-unknown-linux-musl.tar.gz" \
| tar xz --strip-components=1 -C /usr/local/bin "xwin-${XWIN_VERSION}-x86_64-unknown-linux-musl/xwin"

# Download Windows SDK and MSVC CRT (x64 only)
RUN xwin --accept-license --arch x86_64 splat --output /xwin \
&& rm -rf /root/.xwin-cache

# Create case-variant symlinks for .lib files.
# Linux is case-sensitive but Windows SDK headers reference libs with varying casing
# (e.g., "Version.lib" vs "version.lib"). This ensures both forms resolve.
RUN find /xwin -name '*.lib' | while read -r lib; do \
dir=$(dirname "$lib"); \
base=$(basename "$lib"); \
lower=$(echo "$base" | tr '[:upper:]' '[:lower:]'); \
title=$(echo "$lower" | sed 's/^\(.\)/\U\1/'); \
[ -e "$dir/$lower" ] || ln -sf "$base" "$dir/$lower"; \
[ -e "$dir/$title" ] || ln -sf "$base" "$dir/$title"; \
done; exit 0

# Create case-variant symlinks for commonly-mismatched CRT/SDK headers
# (e.g., #include "String.h" resolves to <string.h> on case-insensitive Windows)
RUN [ ! -e /xwin/sdk/include/ucrt/String.h ] && ln -sf string.h /xwin/sdk/include/ucrt/String.h; exit 0

ENV XWIN_DIR=/xwin
22 changes: 22 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "AlphaRing Cross-Compile (Windows x64)",
"build": {
"dockerfile": "Dockerfile",
"context": "."
},
"customizations": {
"vscode": {
"extensions": [
"ms-vscode.cpptools",
"ms-vscode.cmake-tools"
],
"settings": {
"cmake.configureArgs": [
"-DCMAKE_TOOLCHAIN_FILE=${workspaceFolder}/.devcontainer/toolchain-cross-win64.cmake"
],
"cmake.generator": "Ninja"
}
}
},
"postCreateCommand": "sh .devcontainer/fix-case.sh && echo 'Container ready. Build: cmake -B build -G Ninja -DCMAKE_TOOLCHAIN_FILE=.devcontainer/toolchain-cross-win64.cmake -DCMAKE_BUILD_TYPE=Release && cmake --build build'"
}
22 changes: 22 additions & 0 deletions .devcontainer/fix-case.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/sh
# Fix case-sensitivity mismatches for cross-compiling on Linux.
# Windows (NTFS) is case-insensitive; these symlinks emulate that for known paths.
set -e

# 1. lib build-type directories: Release -> release, Debug -> debug
for dir in lib/*/lib; do
[ -d "$dir/release" ] && [ ! -e "$dir/Release" ] && ln -sf release "$dir/Release"
[ -d "$dir/debug" ] && [ ! -e "$dir/Debug" ] && ln -sf debug "$dir/Debug"
done

# 2. minhook lib filename casing (CMakeLists.txt says libMinhook, file is libMinHook)
for d in release Release debug Debug; do
p="lib/minhook/lib/$d"
[ -d "$p" ] && [ ! -e "$p/libMinhook.x64.lib" ] && ln -sf libMinHook.x64.lib "$p/libMinhook.x64.lib"
done

# 3. Source directory casing: includes reference D3d11/ and Window/ but dirs are d3d11/ and window/
[ -d "src/render/d3d11" ] && [ ! -e "src/render/D3d11" ] && ln -sf d3d11 "src/render/D3d11"
[ -d "src/render/window" ] && [ ! -e "src/render/Window" ] && ln -sf window "src/render/Window"

echo "Case-sensitivity symlinks created."
48 changes: 48 additions & 0 deletions .devcontainer/toolchain-cross-win64.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Cross-compilation toolchain: Linux -> Windows x64 using clang-cl + lld-link + xwin
# Used by the AlphaRing devcontainer to build WTSAPI32.dll

set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_SYSTEM_PROCESSOR AMD64)

# --- Compilers and tools ---
set(CMAKE_C_COMPILER clang-cl)
set(CMAKE_CXX_COMPILER clang-cl)
set(CMAKE_LINKER lld-link)
set(CMAKE_AR llvm-lib)
set(CMAKE_MT llvm-mt)
set(CMAKE_RC_COMPILER llvm-rc)

# Target triple
set(CMAKE_C_COMPILER_TARGET x86_64-pc-windows-msvc)
set(CMAKE_CXX_COMPILER_TARGET x86_64-pc-windows-msvc)

# xwin only ships release CRT — force /MD for all build types
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDLL" CACHE STRING "")

# --- xwin SDK/CRT paths ---
if(DEFINED ENV{XWIN_DIR})
set(XWIN_DIR "$ENV{XWIN_DIR}" CACHE PATH "Path to xwin output directory")
else()
set(XWIN_DIR "/xwin" CACHE PATH "Path to xwin output directory")
endif()

# Include paths: MSVC CRT + Windows SDK (ucrt, um, shared)
string(CONCAT _XWIN_CL_FLAGS
"-imsvc ${XWIN_DIR}/crt/include "
"-imsvc ${XWIN_DIR}/sdk/include/ucrt "
"-imsvc ${XWIN_DIR}/sdk/include/um "
"-imsvc ${XWIN_DIR}/sdk/include/shared "
"/EHsc"
)
set(CMAKE_C_FLAGS_INIT "${_XWIN_CL_FLAGS}")
set(CMAKE_CXX_FLAGS_INIT "${_XWIN_CL_FLAGS}")

# Library paths: MSVC CRT + Windows SDK
string(CONCAT _XWIN_LINK_FLAGS
"/LIBPATH:${XWIN_DIR}/crt/lib/x86_64 "
"/LIBPATH:${XWIN_DIR}/sdk/lib/um/x86_64 "
"/LIBPATH:${XWIN_DIR}/sdk/lib/ucrt/x86_64"
)
set(CMAKE_EXE_LINKER_FLAGS_INIT "${_XWIN_LINK_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS_INIT "${_XWIN_LINK_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS_INIT "${_XWIN_LINK_FLAGS}")
113 changes: 113 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# Copilot Instructions for AlphaRing

## Project Overview

AlphaRing is a modding tool for Halo: The Master Chief Collection (MCC). It is compiled as a DLL (`WTSAPI32.dll`) that wraps the real Windows Terminal Services API, allowing it to be loaded by the game via DLL proxy injection. The mod provides splitscreen support for all games, a camera tool (Halo 3), and an object browser (Halo 3).

## Build System

- **CMake** (minimum 3.27), generator: Ninja
- **C++ Standard**: C++17
- **Target architecture**: x64 only (Windows)
- **Toolchain**: MSVC (`msvc_x64_x64`)
- **Configurations**: Debug and Release
- **Output**: A shared library named `WTSAPI32.dll`
- **Current game version target**: `1.3528.0.0` (set via `VERSION` in root CMakeLists.txt)
- **Compile definitions**: `WRAPPER_DLL_NAME`, `GAME_VERSION`, `_SILENCE_ALL_MS_EXT_DEPRECATION_WARNINGS`, `IMGUI_DEFINE_MATH_OPERATORS`
- **Install**: Copies the DLL to `${MCC_DIR}/mcc/binaries/win64` and resources to `${MCC_DIR}/alpha_ring`
- **Cross-compilation (Linux)**: Devcontainer in `.devcontainer/` using Clang 19 (`clang-cl`) + `lld-link` + `xwin` for Windows SDK/CRT. Toolchain file: `.devcontainer/toolchain-cross-win64.cmake`. Requires `fix-case.sh` for Linux case-sensitivity symlinks.

## Dependencies (all pre-built as static/shared libs under `lib/`)

| Library | Purpose |
|------------|--------------------------------------|
| MinHook | Function hooking (detour/trampoline) |
| ImGui | In-game overlay UI (DX11 backend) |
| Lua | Scripting engine |
| spdlog | Logging |
| tinyxml2 | XML parsing (patch.xml) |
| nlohmann/json | JSON parsing (header-only) |

## Project Structure

### `src/` — Core application code

- **`main.cpp`** — DLL entry point (`DllMain`). Spawns initialization on `DLL_PROCESS_ATTACH`.
- **`common.h`** — Precompiled-style header: includes `utils.h`, `Hook.h`, `Log.h`, `Global.h`, `Filesystem.h`.
- **`hook/`** — MinHook wrapper. Provides `Detour()`, `Offset()`, `Patch()` helpers and struct types (`DetourFunction`, `DetourOffset`, `FunctionOffset`, `PatchMCC`, `Detour_t`).
- **`log/`** — spdlog-based logging. Macros: `LOG_INFO`, `LOG_ERROR`, `LOG_WARNING`, `LOG_DEBUG`.
- **`global/`** — Global state singletons using `DefGlobal`/`ImplGlobal` macros. Holds runtime flags (wireframe, imgui visibility, splitscreen config).
- **`filesystem/`** — File I/O helpers for the `alpha_ring/` resource directory.
- **`input/`** — XInput wrapper. Intercepts controller state for menu navigation.
- **`render/`** — Rendering subsystem:
- `d3d11/` — D3D11 hook (swapchain Present), Graphics state management.
- `imgui/` — ImGui integration, game-specific UI panels (`game/halo3/`, `game/mcc/`), curve editor.
- `window/` — Window management.
- **`wrapper/`** — DLL proxy implementation. `ModuleDefinition` class loads the real `WTSAPI32.dll` and forwards exported functions (`WTSRegisterSessionNotification`, etc.).
- **`mcc/`** — MCC engine interaction:
- `CGameEngine` — Virtual function table for the game engine (pause, restart, events).
- `CGameManager` — Player profiles, controller mapping, input, game state.
- `CGameGlobal` — Game identification enum (`Halo1`..`HaloReach`), game state/events.
- `CDeviceManager` — Device/controller management.
- `CUserProfile` / `CGamepadMapping` — Player settings.
- `module/` — Per-game module loading. `CModule` manages entry hooks and patches per game DLL. `entry/` has hook entry points per game. `patch/` has XML-driven patching (`CPatch`, `CPatchSet`).
- `network/` — Network features (currently commented out / WIP).
- `splitscreen/` — Splitscreen logic and ImGui UI.

### `lib/game/` — Game-specific reverse-engineered code

- **`inc/`** — Headers per game: `halo1.h`, `halo2.h`, `halo3.h`, `halo4.h`, `haloreach.h`, `halo3odst.h`, `groundhog.h` (Halo 2 Anniversary).
- **`inc/<version>/`** — Version-specific offset headers (e.g., `offset_halo3.h`, `offset_mcc.h`) for versions `1.3385.0.0`, `1.3495.0.0`, `1.3528.0.0`.
- **`src/`** — Native function wrappers per game (e.g., `halo3/` has subdirs for `ai`, `camera`, `game`, `objects`, `physics`, `render`, `simulation`, `units`, etc.).
- **`src/ICNative.h`** — Macros: `DefNative`, `DefPtr`, `DefPPtr` for defining native game function/pointer accessors using module base + offset.

### `lib/utils/` — Shared utility code

- `FileVersion` — Parse/compare game EXE version strings.
- `String` — String utilities.
- `ThreadLocalStorage` — TLS for per-module base address storage.

### `res/` — Runtime resources (installed to `alpha_ring/`)

- `init.lua` — Lua initialization script.
- `patch.xml` — XML-defined memory patches per module/version.

## Coding Conventions

- **Namespaces**: `AlphaRing::Hook`, `AlphaRing::Render`, `AlphaRing::Input`, `AlphaRing::Log`, `AlphaRing::Filesystem`, `AlphaRing::Global`, `MCC`, `MCC::Module`, `MCC::Splitscreen`, `MCC::Network`.
- **Naming**: PascalCase for classes/structs (`CGameEngine`, `CModule`), PascalCase for namespaces, camelCase/snake_case for functions and members. Prefix `C` for major classes.
- **Hook pattern**: Use `AlphaRing::Hook::Detour()` with initializer lists of `DetourOffset` or `Detour_t`. Use `AlphaRing::Hook::Offset()` for resolving function/data pointers.
- **Offsets**: Steam and Windows Store offsets are maintained in parallel (`offset_steam`, `offset_ws`).
- **Game detection**: Based on `CGameGlobal::eGame` enum. Module DLLs are loaded dynamically.
- **Assertions**: `assertm(expr, msg)` macro used extensively during initialization.
- **Globals**: Use `DefGlobal(Name)` / `ImplGlobal(Name)` pattern for singleton global state.
- **Native calls**: Use `DefNative`, `DefPtr`, `DefPPtr` macros from `ICNative.h` to access game memory at known offsets.

## Supported Games

| Enum Value | Game | Module DLL |
|-----------|-----------------|--------------|
| 0 | Halo 1 (CE) | halo1.dll |
| 1 | Halo 2 | halo2.dll |
| 2 | Halo 3 | halo3.dll |
| 3 | Halo 4 | halo4.dll |
| 4 | Groundhog (H2A) | groundhog.dll|
| 5 | Halo 3 ODST | halo3odst.dll|
| 6 | Halo Reach | haloreach.dll|

## DLL Injection Mechanism

The project builds as `WTSAPI32.dll`. When placed in the game directory, Windows loads it instead of the system DLL. The wrapper code (`src/wrapper/`) loads the real system `WTSAPI32.dll` and forwards all original exports while simultaneously running the mod's initialization code on `DLL_PROCESS_ATTACH`.

## Key Technical Notes

- All memory offsets are relative to the game executable's base address.
- Two sets of offsets exist: one for Steam, one for Windows Store. Only Steam is actively tested.
- The mod hooks D3D11 `Present` to inject ImGui rendering.
- XInput is intercepted to allow controller-based menu navigation.
- Patches can be defined in `patch.xml` and applied at runtime via the `CPatch`/`CPatchSet` system.
- Lua scripting support is available via the embedded Lua runtime.

## Copilot Workflow Preferences

- Always save memory/knowledge files within the repository (e.g., `.github/memories.md`) rather than only in Copilot's internal memory system.
112 changes: 112 additions & 0 deletions .github/memories.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# AlphaRing Repository Knowledge

## What It Is
- Modding tool for Halo: Master Chief Collection (MCC)
- DLL proxy injection via `WTSAPI32.dll` — wraps real Windows Terminal Services API
- Provides: splitscreen (all games), camera tool (H3), object browser (H3)
- Created by WinterSquire, updated by xTrxplex

## Build
- CMake 3.27+, Ninja generator, MSVC x64, C++17
- Output: `WTSAPI32.dll` (shared library)
- Current target version: `1.3528.0.0` (set in root CMakeLists.txt `VERSION` var)
- Install dir: `${MCC_DIR}/mcc/binaries/win64` (DLL) + `${MCC_DIR}/alpha_ring` (resources)
- Two configs: Debug & Release — libs in `lib/<name>/lib/debug|release/`
- Definitions: `WRAPPER_DLL_NAME`, `GAME_VERSION`, `_SILENCE_ALL_MS_EXT_DEPRECATION_WARNINGS`, `IMGUI_DEFINE_MATH_OPERATORS`

## Dependencies (pre-built under lib/)
- MinHook: function hooking
- ImGui: in-game overlay UI (DX11)
- Lua: scripting engine
- spdlog: logging
- tinyxml2: XML parsing (patch.xml)
- nlohmann/json: JSON (header-only)

## Key Architecture
- `src/main.cpp`: DllMain → DLL_PROCESS_ATTACH → CreateThread(Initialize)
- `src/common.h`: precompiled header — utils, Hook, Log, Global, Filesystem + assertm macro
- `src/hook/`: MinHook wrapper — Detour(), Offset(), Patch() with structs DetourOffset, Detour_t, FunctionOffset, PatchMCC
- `src/log/`: spdlog — LOG_INFO, LOG_ERROR, LOG_WARNING, LOG_DEBUG macros
- `src/global/`: DefGlobal/ImplGlobal pattern for singleton state (wireframe, imgui, splitscreen config)
- `src/filesystem/`: File I/O for alpha_ring/ resource dir
- `src/input/`: XInput wrapper for controller interception
- `src/render/`: D3D11 swapchain Present hook, ImGui integration, window management
- `d3d11/`: D3d11.h/cpp, Graphics.h/cpp, Hook.cpp
- `imgui/`: ImGui.h/cpp, ICContext.h, curve_editor/, game/ (halo3, mcc UI panels)
- `window/`: Window.h/cpp
- `src/wrapper/`: ModuleDefinition loads real WTSAPI32.dll, forwards 5 exports
- `src/mcc/`: Engine interaction
- CGameEngine: vtable for engine (pause/restart/events)
- CGameManager: player profiles, controllers, input, game state
- CGameGlobal: game enum (Halo1-HaloReach), state/events
- CDeviceManager, CUserProfile, CGamepadMapping
- `module/`: CModule — per-game DLL loading, entry hooks, XML patches
- `entry/`: per-game hook entry points (halo1-haloreach subdirs)
- `patch/`: CPatch, CPatchSet — XML-driven runtime patching
- `network/`: WIP, currently commented out
- `splitscreen/`: logic + ImGui UI

## Game Library (lib/game/)
- `inc/`: Per-game headers (halo1.h-haloreach.h, groundhog.h)
- `inc/<version>/`: Offset headers per version (1.3385.0.0, 1.3495.0.0, 1.3528.0.0)
- Each version has: offset_halo1.h through offset_mcc.h
- `src/`: Native function wrappers per game
- halo3/ has deepest coverage: ai, camera, game, interface, main, networking, objects, physics, rasterizer, render, simulation, units
- `src/ICNative.h`: DefNative, DefPtr, DefPPtr macros for game memory access

## Utils (lib/utils/)
- FileVersion: parse/compare game EXE version strings
- String: string utilities
- ThreadLocalStorage: TLS for per-module base address

## Resources (res/ → installed to alpha_ring/)
- init.lua: Lua init script (sets alpha_ring['show_menu'] = true)
- patch.xml: XML memory patches per module/version (e.g., halo3.dll patches)

## Coding Conventions
- Namespaces: AlphaRing::{Hook,Render,Input,Log,Filesystem,Global}, MCC, MCC::{Module,Splitscreen,Network}
- PascalCase classes/structs with C prefix (CGameEngine, CModule)
- PascalCase namespaces, camelCase/snake_case functions/members
- Hook pattern: AlphaRing::Hook::Detour({...}) with initializer lists
- Dual offsets: Steam + Windows Store (only Steam actively tested)
- Game detection: CGameGlobal::eGame enum
- assertm(expr, msg) for init-time assertions

## Supported Games
| Enum | Game | DLL |
|------|-------------|---------------|
| 0 | Halo 1 (CE) | halo1.dll |
| 1 | Halo 2 | halo2.dll |
| 2 | Halo 3 | halo3.dll |
| 3 | Halo 4 | halo4.dll |
| 4 | H2A (Groundhog) | groundhog.dll |
| 5 | Halo 3 ODST | halo3odst.dll |
| 6 | Halo Reach | haloreach.dll |

## Distribution Detection (Hook.cpp)
- Steam: MCC-Win64-Shipping.exe
- Windows Store: MCCWinStore-Win64-Shipping.exe
- Validates file version matches GAME_VERSION at startup

## User Controls
- Toggle menu: F4 or Back+Start on controller
- Controller nav: Right Stick = mouse, RB = click
- Game input disabled when menu open

## Steam Deck / Linux
- Launch option: `WINEDLLOVERRIDES="WTSAPI32=n,b" %command%`

## Dev Container (Cross-Compilation from Linux)
- `.devcontainer/` provides a Docker-based cross-compilation environment
- Stack: Ubuntu 24.04 + Clang 19 (from LLVM apt repo) + lld-link + xwin 0.6.5
- xwin downloads Windows SDK + MSVC CRT headers/libs into /xwin
- Toolchain file: `.devcontainer/toolchain-cross-win64.cmake` — uses clang-cl targeting x86_64-pc-windows-msvc
- xwin only ships release CRT — forces `CMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL` (/MD) for all build types
- Case-sensitivity symlinks required on Linux (NTFS is case-insensitive):
- `lib/*/lib/Release` → `release`, `lib/*/lib/Debug` → `debug`
- `lib/minhook/lib/*/libMinhook.x64.lib` → `libMinHook.x64.lib` (CMakeLists.txt uses wrong casing)
- `src/render/D3d11` → `d3d11`, `src/render/Window` → `window` (includes use PascalCase dirs)
- `/xwin/sdk/include/ucrt/String.h` → `string.h` (game code includes `"String.h"` resolved case-insensitively)
- `.devcontainer/fix-case.sh` creates all workspace-level symlinks in postCreateCommand
- Build: `cmake -B build -G Ninja -DCMAKE_TOOLCHAIN_FILE=.devcontainer/toolchain-cross-win64.cmake -DCMAKE_BUILD_TYPE=Release && cmake --build build`
- Produces valid PE32+ x86-64 DLL (~1.2 MB)
18 changes: 18 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,22 @@ cmake-build-release/
cmake-build-debug/
.idea/
build/
build-*/
out/
/.vs

# Case-sensitivity symlinks created by .devcontainer/fix-case.sh
src/render/D3d11
src/render/Window
lib/imgui/lib/Release
lib/imgui/lib/Debug
lib/lua/lib/Release
lib/lua/lib/Debug
lib/minhook/lib/Release
lib/minhook/lib/Debug
lib/spdlog/lib/Release
lib/spdlog/lib/Debug
lib/tinyxml2/lib/Release
lib/tinyxml2/lib/Debug
lib/minhook/lib/release/libMinhook.x64.lib
lib/minhook/lib/debug/libMinhook.x64.lib
Loading