248 OpenCE commits (network version 25): touch controls and touch menus for phones, single-player in-game Settings, opt-in FOV/viewmodel settings, voice chat and votes to kick, lens flare culling, memory leak fixes (render targets, gamepads, the Android audio stream), profiling builds, the HALO_ANDROID split into HALO_ARM64_GUEST / HALO_GLES / HALO_ANDROID. Conflicts and how they were resolved: - README.md: ours kept whole. Upstream's README changes (portable build, profiling builds) went into docs/OPENCE_README.md: upstream's new text with our header note, links rewritten to ../ and our "made from your own copy" wording. - port/android/README.md: both merged; upstream's touch, WSL and save notes taken, with our application id in every adb path; our VR section, signing.properties and wording kept; the stale "How it works" list dropped as upstream dropped it. - Launcher icons (mipmap-*/ic_launcher_foreground.png, art/android-icon.png): ours (the Ringfall art). Upstream's helmet monochrome layers, drawable/ic_launcher_background.xml and its ic_launcher.xml were left out; our ic_launcher.xml, values/ic_launcher_background.xml and tools/android_icon.py stay. (port/assets/icon and tools/app_icon.py come in for the desktop builds' window icon only; do not run app_icon.py, it would write the helmet into the Android resources.) - port/android/host/host_main.c: both config helpers kept, and upstream's emulator write tracking (native_bridge_active); upstream's display width block dropped in favour of ours (640 in VR) and its display density for the touch controls moved into our flat (non-VR) branch. - port/linux/game/menu_functions.c: platform_text_field(typing, password) from upstream; the VR keyboard launch for text fields kept after it. - port/linux/game/network_distributed.c: upstream's profile_scope wrappers, with network_vr_tick and bots_tick kept in their places. - port/linux/src/dsound_sdl.c: both (our debug.audio_log, upstream's audio.output_device). - port/linux/src/port_config.c: our temp-and-rename config write kept, under upstream's HALO_ARM64_GUEST (it is guest file I/O). - port/linux/src/sdl_platform.c/.h: upstream's (Android menu pointer from the touchscreen, Steam keyboard, scoreboard pointer); our quit marker for the Steam Frame launcher, clipboard_seen and VR frame hooks kept. Our flat-mouse menu pointer (an emulator aid) is replaced by upstream's touch pointer, which also drives the menus on the emulator. - port/linux/src/d3d8_gl.c: halo_ui_pointer_update is upstream's, with the VR controller ray taking over while VR is active (the touchscreen then is not the pointer); our persistent-buffer writes kept for stream and index uploads, now writing upstream's exact length and under HALO_GLES like the code around them (stream_reserve, index_upload, mirror_refresh too); multiview uniforms stay under HALO_ANDROID, the counter binding under HALO_GLES. Visibility counters: ours kept (the snapshot ring with multiview views, host_gl_counters_snapshot) over upstream's per-frame glCopyBufferSubData into counter_snapshots: ours reads finished frames without stalling and counts both eyes' samples once; upstream's desktop query batches come in unchanged. - port/linux/src/xinput_sdl.c: both (VR controllers and touch controls). In VR the touch controls neither show nor act (touch_input_gamepad, touch_input_controls, touch move/look skipped); rumble goes to the controllers in VR, to the phone otherwise. - source/interface/first_person_weapons.c: both (VR scope pass check and display.viewmodel_visible). - source/interface/ui_widget.c: upstream's reworked menu targets taken (ui_mouse_fit_button_targets, merged rows, widened values), which do what our icon_x0 key picking and the 12-unit value arrows did; our VR label distance (25) kept, and a VR ray counts as a coarse pointer, so it gets the taller legend areas and the widened values (not the merged rows: a row's label still presses A). Our join code and VR options panels kept; their early return now forgets the frame's targets too. The on-screen keyboard: upstream's virtual_keyboard_click for taps and the mouse, ours (hover highlights the key) for the VR ray only. - source/main/main.c: both (VR phases around upstream's profile scopes). VR guards for new upstream features: - view_fov.c: display.fov, display.viewmodel_fov and display.viewmodel_visible do nothing while VR is active (the headset gives each eye's frustum; the weapon is in the hand). - Touch controls: off in VR (xinput_sdl.c), the menus' touch pointer too (d3d8_gl.c); the overlay stays hidden as the game never reports a scene. - Lens flare culling (744040c8,b1a71709) uses global_window_parameters' frustum, which in VR is each eye's (per-eye passes) or the union frustum of the multiview centre camera: no change needed. - In-game Settings: VR options still open with Y on the main and pause menus (checked flat with debug.vr_options). - The back button change (enableOnBackInvokedCallback=false) keeps the legacy KEYCODE_BACK path, which targetSdk 35 already had: no change on Quest or Frame. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8.2 KiB
This is the README of OpenCE, the port Ringfall: Mjolnir VR is built on, kept for its build and development notes. Its download links are OpenCE's. For the VR mod, see the main README.
Halo: Combat Evolved for Linux, Windows and Android
This project is a port of the Halo: Combat Evolved decompilation to Linux,
Windows and Android. The decompilation is of the Xbox build 2342
(cachebeta.exe, SHA-256
4cc87b45f721270392a96f1674ed2b5cd4a7bb4355faeab4531d1cf1884d9520).
The port starts from the decompilation of bnunu/halo-1. That project is a fork of punpckhdq/halo.
Download
GitHub Actions builds the game for each commit. These links download the builds of the latest release:
| Platform | Release | Debug |
|---|---|---|
| Linux | halo-linux-release.zip | halo-linux-debug.zip |
| Windows | halo-windows-release.zip | halo-windows-debug.zip |
| Android | halo-android-release.zip | halo-android-debug.zip |
Use the release build to play. The debug build stops at the first failed assertion and writes it to the log. Use the debug build to find and report problems.
The game updates itself. At start-up it looks for a newer release, and asks if you want to install it. Refer to "Updates" in port/linux/README.md.
Each build of the main branch that passes on all three platforms is a new
release. The Releases
page keeps the last five releases. If the latest build has a problem, get
an older build from that page.
Game data
The port does not include the game data. It needs an Xbox disc image
(.xiso or .iso) made from your own copy of Halo: Combat Evolved. All versions of the game
operate. The maps of the European (PAL) version were made for a slower
console. The port changes them to play as the North American (NTSC) maps do,
so players of the two versions can play together.
- Start the game.
- At the first start, the game asks for the disc image. Select it.
- The game extracts the
maps/folder. Then the game starts.
On Linux and Windows, the game puts maps/ next to the executable. On
Android, copy the disc image to the phone first. The app puts maps/ in its
data folder. Refer to port/android/README.md.
Platforms
Each platform has its own instructions:
| Platform | Instructions |
|---|---|
| Linux (32-bit x86 executable, OpenGL 4.5, SDL3) | port/linux/README.md |
| Windows (32-bit x86 executable, OpenGL 4.5, SDL3) | port/windows/README.md |
| Android (arm64 app, OpenGL ES 3, SDL3) | port/android/README.md |
The Linux README also gives the controls, the settings and the multiplayer functions. These are almost the same on all platforms.
Multiplayer
The game can play system link games on a local network and on the internet:
- A system link game can have up to 128 players on up to 128 machines.
- Linux, Windows and Android machines can play in the same game.
- An invite link lets a machine join a game on the internet. No server of this project is necessary.
- The netcode is new. Each machine moves its own player at once, and the host makes the decisions for the game. Refer to port/linux/NETCODE.md.
Build the game
You do not need the Xbox SDK. The port supplies the SDK declarations that the game uses. Refer to port/include/xdk.
To build the game:
- Install Python and ninja.
- Install the tools for your platform. Refer to the README for the platform.
- In the root folder of the repository, enter
python configure.py. - Enter
ninjawith the target for the platform:
| Target | Result |
|---|---|
ninja linux |
build/linux/halo |
ninja windows (on Windows) |
build/windows/halo.exe and SDL3.dll |
ninja android_apk |
port/android/app/build/outputs/apk/debug/app-debug.apk |
If you enter ninja without a target, ninja builds the game for the
computer that you use.
tools/ci_build.py makes the same builds as GitHub Actions. For example,
enter python tools/ci_build.py linux release.
Build options
Give these options to configure.py:
| Option | Result |
|---|---|
| (none) | A debug build. A failed assertion stops the game. |
--release |
A release build. The game does not examine assertions, as in the retail game. |
--portable |
The Linux and Windows builds operate on all x86-64 processors. The Linux build also operates on older distributions and on SteamOS: refer to "Portable build" in port/linux/README.md. Use this option for builds that you give to other persons. |
--lto=thin, --lto=off |
Less link-time optimization. The link is faster. |
--pgo=off |
No profile-guided optimization. |
--pgo=train |
Records a new optimization profile. Refer to "Optimization profiles". |
--profile |
A profiling build. It records CPU times. Refer to "Profiling builds". |
Without --portable, the Linux and Windows builds use all the instructions
of the processor that builds them (-march=native). Such a build does not
always start on a different computer.
Optimization profiles
The builds use profiles of the game to optimize the code:
pgo/halo_linux.profdatafor Linux and Android.pgo/halo_windows.profdatafor Windows.
The profiles need clang 22 or later. With an older clang, the builds do not use the profiles.
To record a new profile:
- Delete the profile.
- Enter
python configure.py --pgo=train. - Enter
ninja linuxorninja windows.
The build then plays the main menu and the first minute of each campaign
level. This procedure continues for approximately 15 minutes. The game
data must be in assets/.
Profiling builds
A profiling build records where the game spends its time.
- Enter
python configure.py --profile, then build as usual. - Start a recording. Enter
profile_recordin the console (or the telnet console), or setdebug.profile_record = trueinconfig.toml. To record each game of a session, also setdebug.profile_record_when = "game". - Stop the recording. Enter
profile_stop, load another map, or quit.
The game writes numbered .part<n>.json files under profiles/ in its data root
and logs their paths. Parts are retained after the recording stops. Logs go to
standard error; a Windows release build without standard error writes them to
halo.log next to halo.exe.
tools/net_report.py is a helper for developers. Enter
python tools/net_report.py <recording.part1.json> to read a recording
as tables. The command also writes <recording>.summary.txt, a short text
file.
| Command | Result |
|---|---|
profile_record [seconds] |
Starts a recording. With a number of seconds, the recording stops after that time. |
profile_stop |
Stops the recording. |
debug.profile_memory sets the memory of a recording in MB (default 256,
from 4 to 1024). A recording has no length limit:
the game writes a part each time the memory is full. Refer to "Settings" in
port/linux/README.md.
On Android, the files are in /sdcard/Android/data/com.halo.decomp/files/profiles/.
Enter adb pull to copy the recording parts to a computer.
A profiling build plays with normal builds. It does not use
--pgo=train.