# Halo: Combat Evolved on Anbernic RG35XX H (native Knulli port)

> A native ARM64 (AArch64) port of the Halo: Combat Evolved decompilation, halo-ce-universal, to the Anbernic RG35XX H and other Allwinner H700 handhelds running Knulli (a Batocera fork). The game runs as native code on the Cortex-A53 cores with the Mali-G31 GPU: no emulation, no xemu, no Box64, no Wine. Source code, documentation, and releases of the port's own programs built from it (no game data); players need their own copy of the original Xbox game. Released under CC0 1.0.

## Key facts

- Game: Halo: Combat Evolved, Xbox build 01.01.14.2342, decompiled to C by the upstream project https://github.com/cybersecurity/halo-ce-universal (pinned commit in UPSTREAM_COMMIT).
- Hardware: Allwinner H700, 4x Cortex-A53 at 1.5 GHz, Mali-G31 MP2, 1 GB RAM, 640x480 screen on the RG35XX H.
- Firmware: Knulli, release Gladiator II (the Knulli zip, no PortMaster needed), or PortMaster on Knulli or other firmware (the PortMaster zip). Uses the firmware's SDL2 and Arm's framebuffer Mali OpenGL ES driver. The host needs glibc 2.30 and SDL2 2.0.18 or newer.
- Game data: the original Xbox version's maps are required (from a .iso disc image or an extracted maps folder). The PC version's files do not work.

## Devices

- Tested: Anbernic RG35XX H.
- Untested, expected to work: Anbernic RG35XX Plus, RG35XX SP, RG35XX 2024, RG40XX H, RG40XX V.
- Untested: Anbernic RG CubeXX (720x720), RG34XX (720x480). muOS (2601 Jacaranda): tested with the PortMaster zip from v2026.10.07 (earlier releases crash there). ROCKNIX: reported working by a user on an Anbernic RG353M (RK3566, Mali-G52) once ROCKNIX was up to date (an older version, 20260601, needed debug.instance_models = false). dArkOSen: reported working by a user on an R36S (RK3326, Mali-G31) from v2026.10.07.
- Not supported: TrimUI handhelds and other devices without a Mali GPU.

## Frame rates (RG35XX H, last updated 2026-10-06, release v2026.10.06)

- Render scale 0.75 (default, dynamic resolution on): main menu 60 fps; c10, 343 Guilty Spark, about 57 (46-60); b30, The Silent Cartographer beach battle, about 43 (38-47); a30, Halo level opening, about 59 (39-60).
- Render scale 1.0 (640x480): main menu 60; c10 about 56; b30 about 38; a30 about 40.

## Install

1. Download halo-ce-knulli-<version>.zip from https://github.com/kirklandsig/halo-ce-anbernic-rg35xx/releases/latest and unzip it onto the SD card's share partition (the one with the roms folder). It adds roms/ports/Halo.sh and roms/ports/halo/.
2. Put your own Xbox Halo disc image (.iso) in roms/ports/halo/.
3. Launch from Ports. The first launch copies maps/ out of the disc image with its progress on the screen (about four minutes), then the game sets up its cache (about a minute, black screen).
4. Quit: hold the hotkey (MENU or SELECT) and press START. Spawn menu (vehicles, weapons, equipment, AI characters; single player and the host of a network game only): hold SELECT and press D-pad Down; L1/R1 change the page, B (bottom) spawns, A (right) closes. Bot Match: Multiplayer > BOT MATCH (Slayer and Team Slayer against up to 15 bots, offline; skill Easy to Legendary). Updates: the launcher offers a newer release before the game starts (START installs it; off with update.auto = false). Settings: halo/config.toml (display.render_scale, default 0.75). Log: halo/log.txt.
5. With PortMaster instead (Knulli or other firmware): put halo-ce-portmaster-<version>.zip in PortMaster's autoinstall folder, start PortMaster, then put the disc image in ports/halo/.

## Build

- Linux x86-64 (Ubuntu 24.04, WSL works) with python3, ninja-build, git, curl, clang 22 from apt.llvm.org (arm64_32 target), Android NDK r28c and gcc-aarch64-linux-gnu.
- Copy libSDL2-2.0.so.0* and libmali.so.0* from the handheld's /usr/lib into a folder (link time only, never committed).
- Run: ANDROID_NDK=/path/to/android-ndk-r28c SYSROOT_LIB=/path/to/libs ./build.sh
- Output in dist/: halo, halo_guest.elf, Halo.sh, halo_extract.py, halo_screen.py, sdl_mapping.py. The releases are built the same way.

## How it works

- The upstream Android port compiles the game as an ILP32 AArch64 guest image (32-bit pointers, as the game's data requires). This port adds a glibc aarch64 host for Knulli that bridges the guest's SDL3 calls to the firmware's SDL2 and runs OpenGL ES on a dedicated GL thread.
- Optimisations for the Mali-G31: the GL thread (the driver costs about 17 µs of CPU per draw call, 28 µs before the renderer's changes), program binary cache, fp16 shaders, 16-bit textures, asynchronous occlusion readback, quad batching and decal ordering (about 700 decal draws become about 20), model LOD scaling, shadows restructured to avoid render-target switches on the tile-based GPU, render scale, and CPU/GPU clock pinning.

## Legal

- Unofficial fan project, not affiliated with Microsoft, Xbox Game Studios, Halo Studios or Bungie. Halo and Xbox are trademarks of Microsoft Corporation.
- No game files, disc images, maps, XBE, extracted assets, Mali driver or device libraries are included, in the repository or in the releases. The releases hold only the port's own programs, built from this source.

## Links

- [README](https://github.com/kirklandsig/halo-ce-anbernic-rg35xx/blob/main/README.md): install, build, configuration, troubleshooting, FAQ
- [How it works](https://github.com/kirklandsig/halo-ce-anbernic-rg35xx/blob/main/docs/HOW-IT-WORKS.md): architecture
- [Performance](https://github.com/kirklandsig/halo-ce-anbernic-rg35xx/blob/main/docs/PERFORMANCE.md): optimisation history and measurements
- [FAQ](https://github.com/kirklandsig/halo-ce-anbernic-rg35xx/blob/main/docs/FAQ.md)
- [Documentation index](https://github.com/kirklandsig/halo-ce-anbernic-rg35xx/blob/main/docs/README.md): every document and a reading order for players, builders and developers
- [Install guide](https://github.com/kirklandsig/halo-ce-anbernic-rg35xx/blob/main/docs/INSTALL.md): copying the game and port to the SD card, first launch, controls, updating, uninstalling
- [Building from source](https://github.com/kirklandsig/halo-ce-anbernic-rg35xx/blob/main/docs/BUILDING.md): toolchain, Android NDK, device libraries, build.sh stages, build errors
- [Configuration reference](https://github.com/kirklandsig/halo-ce-anbernic-rg35xx/blob/main/docs/CONFIGURATION.md): every config.toml setting and HALO_* environment variable
- [Architecture](https://github.com/kirklandsig/halo-ce-anbernic-rg35xx/blob/main/docs/ARCHITECTURE.md): guest image, Knulli host, GL thread, Direct3D 8 on OpenGL ES renderer, engine changes
- [Profiling guide](https://github.com/kirklandsig/halo-ce-anbernic-rg35xx/blob/main/docs/PROFILING.md): frame-time, GL, GPU-pass and sampling tools and how to read them
- [Mali-G31 porting notes](https://github.com/kirklandsig/halo-ce-anbernic-rg35xx/blob/main/docs/MALI-G31-NOTES.md): measured costs of the Mali-G31 driver and GPU for a D3D-era renderer
- [Roadmap](https://github.com/kirklandsig/halo-ce-anbernic-rg35xx/blob/main/docs/ROADMAP.md): current limits and planned work toward 60 fps
- [Legal notice](https://github.com/kirklandsig/halo-ce-anbernic-rg35xx/blob/main/docs/LEGAL.md)
- [Port technical README](https://github.com/kirklandsig/halo-ce-anbernic-rg35xx/blob/main/port/knulli/README.md)
- [Project site](https://kirklandsig.github.io/halo-ce-anbernic-rg35xx/)
- [Upstream: halo-ce-universal](https://github.com/cybersecurity/halo-ce-universal)
