Up to now, this blog has mostly tracked two threads: two-game mashups that weld rival engines into a single executable, and perspective-shifting camera or VR mods that let you step inside a twenty-five-year-old world. Starting today, we're adding a third beat to the site: impossible cross-platform ports. When someone takes a game built for one generation of silicon and makes it run natively on hardware that should have no business booting it, the engineering rhymes with everything else we cover here.
Case in point: Halo 64, an open-source project by developer JackTulli that compiles Halo: Combat Evolved to run natively on a real Nintendo 64. Not a stylistic demake rebuilt in Unity, and not a GoldenEye 007 ROM hack wearing Master Chief armor—actual decompiled Halo C code running on the N64's 93.75 MHz MIPS CPU and 8 MB Expansion Pak, playable in an accurate emulator (ares) or off a flashcart (SummerCart64 or EverDrive-64 X7) on original 1996 hardware.

When Retro Dodo, Windows Central, and XDA Developers picked up the story after JackTulli posted the project to r/HaloClassicHub, the headline alone was enough to make people double-take. In the days since those initial write-ups went live, the repository has already shipped six releases (v0.1.0 through v0.3.2), adding a standalone campaign test cartridge for the second mission ("Halo" / a30.map), an optional Gearbox PC expansion builder with Banshees and Rocket Hogs, a streamed terrain megatexture, and aggressive frame-pacing optimizations.
I haven't built a ROM from my own Xbox disc yet, so everything below comes from reading the repository's architecture notes, its 1,090-line engineering history log, and the release commits. If you care about how decompilation Projects make the impossible routine, the internals of this port are fascinating.
Not a ROM Hack: Decompiled Xbox C on a 93.75 MHz MIPS CPU
Last week, when we looked at Black & White VR, we talked about how clean-room decompilations turn locked-down 2001 binaries back into malleable C and C++ source trees. Halo 64 rides that exact wave. It forks halo-ce-universal (now maintained upstream as OpenCommunityEdition/OpenCE, building on the bnunu/halo-1 and punpckhdq/halo decompilations of Xbox Halo build 2342).
Instead of rewriting Halo's gameplay by hand, Halo 64 compiles the original engine's C simulation directly for the N64's big-endian NEC VR4300 processor, pairing it with a custom renderer, menu system, HUD, and 12-voice 22 kHz VADPCM audio mixer built on the open-source libdragon SDK and tiny3d, plus Invader's Halo Editing Kit tag definitions for asset conversion.
| Subsystem | Original Xbox (Halo: CE, 2001) | Nintendo 64 (Halo 64, 2026) |
|---|---|---|
| CPU | 733 MHz Intel Pentium III (32-bit little-endian x86) | 93.75 MHz NEC VR4300 (big-endian MIPS, 32-bit pointers) |
| System Memory | 64 MB unified DDR SDRAM | 8 MB RDRAM (requires N64 Expansion Pak; 4 MB base unsupported) |
| Texture Cache | Unified system RAM | 4 KB on-chip RDP Texture Memory (TMEM) |
| Core Simulation | 30 Hz fixed tick (objects, physics, weapons, game) | Same 30 Hz C simulation compiled from halo-ce-universal |
| Renderer & Audio | Direct3D 8 + Xbox hardware MCPX audio | Custom libdragon + tiny3d RSP/RDP pipeline & 12-voice VADPCM mixer |
What stays intact from Bungie's simulation code is why the port feels like Halo rather than an approximation:
- Kept from the Xbox engine: The 30 Hz gameplay loop, object pool, rigid-body physics, BSP collision, weapon firing and projectile ballistics, vehicles, game-type rules (Slayer, CTF, Oddball, King of the Hill, Race), HUD state logic, first-person weapon animations, and
source/ai/path*.cpathfinding. - Cut or replaced for the N64: Full campaign actor AI state machines (replaced with a lightweight N64 AI controller), HaloScript (
hs), network play, Xbox Direct3D shaders, and the original sound engine.

What's Actually in the Cartridge Right Now
It's easy to assume an N64 port of Halo would be a tech demo where a lone Spartan walks around an empty gray box at 9 FPS. Instead, the feature list as of v0.3.2 reads like a full party-game cartridge—plus a second experimental ROM for campaign:
- All 13 Xbox Multiplayer Maps: Battle Creek, Sidewinder, Damnation, Rat Race, Prisoner, Hang 'em High, Chill Out, Derelict, Boarding Action, Blood Gulch, Wizard, Chiron TL-34, and Longest—all supporting weapons, drivable vehicles, teleporters, and water.
- Eight Classic Modes: Slayer, Team Slayer, Slayer Pro, Team Slayer Pro, Capture the Flag, King of the Hill, Oddball, and Race.
- Up to 4-Player Local Split-Screen: One to four controllers on a single console, with no networking layer needed.
- Up to 8 AI Bots: Using Halo's native navigation pathfinding across Easy, Normal, Heroic, and Legendary difficulties. In the initial release, bots pulled from a list of 302 N64-era names (Banjo-Kazooie's
HUMBA WUMBAfamously dictated the 299-pixel scoreboard column width); as ofv0.3.0, thanks to a pull request from contributor@kaboggs, bots use Halo's authentic random profile names—Hambone, Caboose, Noodle, Sleepy—plus two 1-in-32 special Easter egg bots (ChaoticSP1on Legendary andKodeBrkr16, either of which can spawn with active camouflage). - 1–4 Player Firefight: Wave-based survival with shared lives across four difficulties against Covenant Grunts, Jackals, and Elites imported from the campaign's
a30.map. - Standalone Campaign Cartridge (
halo-campaign.z64): Added after the first wave of press articles, the ROM builder now emits a second.z64cartridge dedicated to the opening half (first structure BSP) of Halo's second mission, "Halo" (a30.map). You can walk out to the cliff overlook, grab the Warthog by the Marine base, and fight distance-streamed Covenant squads with checkpoints and four difficulty settings (Marines, cutscenes, scripts, and the second BSP transition aren't wired up yet). - Optional Gearbox PC Expansion (
halo-pc-expansion.z64): For users building from source with localInvaderandFFmpegtools,@kaboggsalso contributed a PC expansion pipeline that converts the six Gearbox PC-exclusive multiplayer maps (Danger Canyon, Death Island, Gephyrophobia, Ice Fields, Infinity, and Timberland) along with flyable Banshees and Rocket Warthogs, plus fun modifiers like Big Head Mode, Paintball, and Golden Style aiming.

Squeezing a 64 MB Xbox Engine Into 8 MB of RDRAM (and 4 KB of TMEM)
How do you shrink a game designed for 64 MB of unified RAM down to an 8 MB N64—where the operating system, code, stack, audio buffers, framebuffers, game state, and loaded map all have to coexist without fragmenting the heap?
The port/n64/NOTES.md and port/n64/HISTORY.md files lay out a series of brutal, clever compromises:
1. The 2.8 MB "Map Home" Arena and Borrowed Menu Buffers
On Xbox, a compiled .map cache file is tens of megabytes. Halo 64's asset pipeline (repack_map.py) strips each map down to its essential gameplay tags and converts every struct in-place from little-endian x86 to big-endian MIPS. Because loading and unloading maps repeatedly across matches was fragmenting malloc until large maps like Sidewinder (2.63 MB repacked) crashed with out-of-memory errors, the port claims a permanent 2.8 MB "map home" arena at the very bottom of the heap on boot.
Here's the clever part: the main menu runs in crisp 640×480i interlaced high-resolution, which needs 1.8 MB of framebuffers and Z-buffer. While you're in the menu, no map is loaded—so the menu borrows the bottom of the 2.8 MB map arena for its 480i framebuffers, then hands that memory right back when a match begins. Meanwhile, the engine's runtime game-state allocation was trimmed from 1 MB down to ~404 KB actually used, leaving ~1.7 MB of heap headroom for 3D meshes and audio.
2. Surviving the N64's 4 KB Texture Cache
The Nintendo 64's Reality Display Processor (RDP) has no texture cache in main RAM; every texture must fit inside 4,096 bytes of on-chip TMEM.
- Map and model textures are downsampled to 4-bit indexed (
CI4) or intensity (I4) formats at 32×32 or 64×32 resolution so a single tile load fits comfortably in TMEM. - For Spartan armor, where player color tinting normally requires a two-cycle RDP combiner pass,
build_models.pysplits each 16-colorCI4palette in half: indices0–7hold un-tinted base grays and visor colors, while indices8–15hold pre-multiplied armor shades swapped per player in C before upload—keeping Spartan rendering at one RDP cycle per pixel. - First-person weapon textures (originally 512×512 atlases) are diced into 64×64 windows and remapped per triangle; if a triangle straddles a window boundary, the offline converter splits the triangle along the seam so it never wraps in TMEM.
- For outdoor maps like Blood Gulch,
v0.2.0introduced a streamed RGBA16 terrain "megatexture" alongside a four-tier Terrain Detail toggle (Full,High,Medium,Low) and a four-tier 3D Resolution selector (Chunky160w,Medium256w,Standard320×240, andHigh Detail, which runs at 480i or 640×240 at 240p—twice the horizontal pixels of Perfect Dark's famous hi-res mode).

3. Single-Precision Math, Throttled Idle Props, and NaN Traps
The VR4300 CPU can execute single-precision float math fast, but C's default double promotion costs extra cycles on every call. The port sweeps the hot simulation loops to replace sqrt, sin, cos, and double literals with single-precision equivalents (sqrtf, sinf, cosf), and even shortcuts atan2(0, 0) in objects.c, which was eating roughly 2.8% of total CPU time just computing zero angles for stationary objects.
To keep the 30 Hz simulation from drowning the CPU on maps with vehicles and bots:
- Unheld weapons, flags, oddballs, and parked vehicles skip physics on 3 out of every 4 ticks (
(id + tick) & 3). - Active vehicle suspension and collision run every 2nd tick.
- Faraway or off-screen bots and Covenant throttle their pathfinding and animation updates based on distance and PVS visibility (
v0.2.0–v0.3.2).
And because the N64 uses strict MIPS floating-point traps where x86 silently shrugs, testing uncovered classic console-port landmines: a 0.0f / 0.0f division in units.c whenever a player crouched while stationary, and an fmod(x, 0.0f) exception in the HUD weapon bar whenever a player climbed into a Warthog turret (which has a reload time of zero). Both caused hard SIGFPE crashes on N64 hardware until squashed.
"Four-bit textures, a 4 KB texture cache, 8 MB of RAM with the Expansion Pak, and one small fan-less CPU: Halo has no business being here, and yet." — JackTulli, Halo 64 README

"The User Tests": What the Commit History Reveals About AI-Assisted Porting
There's a second story inside the repository that Retro Dodo and XDA Developers both highlighted: Halo 64 was co-developed with Anthropic's Claude.
You don't have to guess how that workflow operated, because port/n64/HISTORY.md preserves the coding agent's running lab notebook across dozens of sessions from October 8 to October 16. Throughout the file, the narrator refers to JackTulli in the third person as "the user":
- "Built, not run here: the user tests."
- "The user asked for a night of optimisations and fixes, every map tested each time; runs in ares on a hidden display."
- "First real-console test (SummerCart64) crashed immediately on picking any map... Root cause:
rspq_init()allocates a 16-segment × 512-word (32 KB) default ring buffer. For a heavy frame (terrain + BSP + skinned models + HUD), our RSP command stream overruns this before the RSP drains it."
Reading HISTORY.md end-to-end is one of the clearest public artifacts we have of what serious human-plus-agent systems engineering looks like right now. It wasn't "type a prompt, get a finished N64 ROM." Instead, it was a tight, relentless feedback loop:
- Automated headless emulator harnesses: The agent booted ROM builds inside the cycle-accurate
aresemulator on a virtual X11 display (Xvfb :97), injecting controller inputs viaxdotoolto navigate menus, spawn into each of the 13 maps, and scrape the on-screen FPS counter over 45-second soaking runs. - PC-side sampling profilers: Using a custom script (
tools/n64_profile.py), the setup sampled the emulated VR4300 Program Counter at 60 Hz viaprocess_vm_readvand resolved addresses againsthalo.elf's symbol table to find exact C functions burning frame time. - Hardware ground-truthing by a human: Whenever the emulator let something slide—like an RSP command buffer overrun that only manifested on a physical SummerCart64, or a controller stick curve that felt wrong on a real N64 trident controller—JackTulli tested on hardware, diagnosed the feel or crash, and directed the next engineering pass.
Why Cross-Platform Ports Belong Here
Whether someone is putting a VR tether onto Lionhead's Black & White, stitching Ocarina of Time and Majora's Mask into a single randomizer, or squeezing a 2001 Xbox launch titan backward in time onto a 1996 cartridge with 4 KB of texture memory, the impulse is identical: refusing to accept that a classic game is frozen forever in the hardware assumptions of the month it shipped.
Even down to the little details—like translating the Xbox controller's dual variable-speed rumble motors into frame-by-frame duty cycles on the N64 Rumble Pak's single on/off motor, or mapping crouch and reload onto GoldenEye-style C-buttons—Halo 64 treats the Nintendo 64 as if Bungie had quietly shipped a sister cartridge in late 2001. We'll be covering plenty more ambitious ports like this alongside our usual mashups and mods.
Links & Resources
- GitHub Repository: JackTulli/halo-64
- Latest Release & Windows ROM Builder (
v0.3.2): GitHub Releases - Engineering Deep Dives:
port/n64/NOTES.md·port/n64/HISTORY.md·tools/n64/ROMBUILDER_PC.md - Upstream Xbox Decompilation: OpenCommunityEdition/OpenCE (
halo-ce-universal) - Press Coverage: Retro Dodo · Windows Central · XDA Developers



