Compare commits

..
Author SHA1 Message Date
Stefan MaierandClaude Opus 5.5 5530d19769 Merge fix/vr-weapon-arm: each weapon held so that its hand lands on the real one, the scope's disc with it
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 18:00:14 +02:00
Stefan MaierandClaude Opus 5.5 603ad6b543 Roadmap: each weapon held so that its hand lands on the real one
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 18:00:13 +02:00
Stefan MaierandClaude Opus 5.5 322146f3cb Scope: the disc moves with the weapon from its old fixed place in the hand
The disc was placed for the weapons at the old fixed place (7 cm above
the hand, 22 cm ahead of it): with the pistol now held 20 cm further
back it sat at the muzzle. It moves as the weapon did (forward and up;
sideways the barrel places it, as before).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 17:54:43 +02:00
Stefan MaierandClaude Opus 5.5 a31c482d5a Hold each weapon so that its hand lands on the real one
The first-person model hung from a camera at one fixed place from the
weapon hand's controller (18 cm behind, 10 cm left, 14 cm above), but
each weapon's animations hold the hand elsewhere from that camera: the
pistol's wrist came out 15 cm before the controller (22 cm before where
the free hand's wrist is, 7 cm behind its grip), the plasma pistol's 11,
the assault rifle's 8 cm aside and 10 cm low; the weapon arm looked
longer, reaching forward. Measured on the Quest 3 (2026-10-17).

Now the wrist as the weapon is held ready is kept for each weapon
(eased, the last eight weapons), and the camera put so that it lands
where the free hand's does: 7 cm behind the grip, along the aim. The
model, its barrel, the laser and the shots move with the camera, as
before. A weapon not yet seen is held at the old place for its first
frame. vr.weapon_hand_forward/_right/_down (0 by default) move the hand
on the weapon; vr.weapon_forward/_right/_down, the old fixed place, are
gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 17:41:48 +02:00
Stefan MaierandClaude Opus 5.5 e543fe53e0 Merge merge/upstream-oct18: OpenCE's high-resolution Xbox HUD, pause menu artwork, client-side mods, resampler, unsteered vehicles
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 16:31:03 +02:00
Stefan MaierandClaude Opus 5.5 76fbf67334 Merge OpenCE upstream: the high-resolution Xbox HUD completed, pause menu artwork, client-side mods, the resampler setting, unsteered vehicles' netcode
README.md keeps Ringfall's; OpenCE's README is copied to
docs/OPENCE_README.md as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 14:54:00 +02:00
MrBruh 7524ba6168 Merge pull request #391 from OpenCommunityEdition/testing
Testing
2026-10-18 00:53:59 +13:00
MrBruh 5a1b8a4094 Set the resampler from a Sound Processing screen of Audio Setup (#245)
Audio Setup had no room for another row (nine on the desktop, as Video and
Network Setup), so Reverb moves with the new Resampler row (SINC, the
default, or LINEAR) to a SOUND PROCESSING screen opened from Audio Setup,
as Video Setup's categories are; the devices and volumes stay on Audio
Setup. The setting is read again when it changes, so the TODO saying it
could only be set in config.toml goes, and the help, the setting's comment
and the README say what linear does: it lets more of the images above a
sound's rate through, which is what sounds brighter.

The mixer's harness test takes the resampler from dsound_sdl.c, which now
calls config_string: it stubs it, and a new case checks linear mode against
linear interpolation worked out in double precision at every rate (with a
negative control). Checked: the harness and touch menu tests, test_web_build,
ninja linux, android and web, and both screens drawn on Xvfb with
HALO_AUDIO_RESAMPLER=linear; the menus regenerated with tools/ce_menus.py
change only the two audio screens.
2026-10-18 00:13:26 +13:00
MrBruh b718ad8468 Merge pull request #245 from WhiteI3ulL/resampler-linear-interpolation
Add linear resampler for brighter global audio
2026-10-18 00:03:17 +13:00
MrBruh af07c05d21 Say which shaders a mod's models can be drawn with
A mod's model can name a shader of any group the map has, but
shader_transparent_chicago_extended is Gearbox's addition for Halo PC and
the Xbox game has none: the note says to use a transparent chicago shader
instead, and that a Custom Edition map's chicago extended shaders are
converted to chicago shaders as the map loads.
2026-10-17 23:53:28 +13:00
MrBruh 9a8382f1ae Let mods replace models whose nodes, markers and regions match the map's 2026-10-17 23:49:30 +13:00
Stefan MaierandClaude Opus 5.5 7da699b035 Merge feature/disc-languages: the European disc in Spanish and Italian imported, in the headset's language
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 10:39:31 +02:00
Stefan MaierandClaude Opus 5.5 c5c604bb95 Import the European disc in Spanish and Italian, in the headset's language
That disc has no maps folder but one for each language, maps_es and
maps_it, and the disc image setup stopped: "The disc image has no maps
folder: it is not a Halo disc." The Quest's (XisoExtractor.java) and
the Steam Frame's (steam_frame_xiso.py, RINGFALL_LANGUAGE or the
system's) now take the folder of the device's language, else English's,
else the first, and write its language into maps/language.txt. The game
takes that as the Xbox's language (XGetLanguage) while game.language is
unset, so the menus speak it too. (Reported for ChupathingyCE, another
OpenCE fork, in its issue 145; written anew here.)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 10:39:30 +02:00
MrBruh 01797c0434 Merge pull request #388 from OpenCommunityEdition/testing
Merge testing
2026-10-17 17:54:12 +13:00
MrBruh 7059096e1b Merge main into testing, bringing in the pause menu and HUD fixes of #378 2026-10-17 17:43:40 +13:00
MrBruh 54c2d31c97 Show the Mods list as a resource pack list, the top mod winning 2026-10-17 16:19:49 +13:00
MrBruh dd16971b6c Add client-side mods with a Mods menu, load order and incompatibility checks 2026-10-17 16:19:49 +13:00
Guven 7c942e9a57 Merge pull request #384 from lukerb52/main
Added reference to AUR version to the README
2026-10-17 00:40:26 +01:00
bnunu 25697bbaa1 Merge pull request #378 from chestahh/opence-ui-fixes
Fix regression in pause menu & The Maw timer, restoring legacy Xbox behaviour. Fix incorrect Edit Gametypes positioning
2026-10-16 17:49:30 -04:00
bnunu a5e6102413 Merge pull request #372 from innerhat-dev/unsteered-vehicle-path
Carry a vehicle no player drives along the host's positions
2026-10-16 17:49:16 -04:00
chestahh b9e393c00c Apply high-resolution HUD and text settings without reloading maps
Recheck committed font settings before cached font selection, including when
high-resolution text was disabled at first use. At each frame boundary,
invalidate only cached HUD/title bitmaps affected by a changed setting so
both enabling and disabling rebuild the appropriate texture on next use.
Keep decoded replacements, font atlases, world textures and menu Apply/Cancel
semantics intact. This corrects shared cache behavior; it adds no MCC data,
map-family routing or networking/simulation changes.

Validation: Windows portable release build and 370 focused production-code,
HUD, menu and MCC checks passed. Tests cover repeated toggles, disabled text
at startup, font scale/cache reuse, selective bitmap refresh and Apply/Cancel.
Android and Web targets were attempted but are unavailable in this Windows
build graph. Live Custom Edition validation is limited by unavailable maps.

(cherry picked from commit ddeb650d82a73b570e182ff2bfd87e3cc3daa98d)
2026-10-16 21:42:21 +01:00
Constantine Luke Matthew Bubar c54185c088 punctuation 2026-10-16 16:30:26 -04:00
Constantine Luke Matthew Bubar 6b214c63a7 added reference to AUR version to the README 2026-10-16 16:27:22 -04:00
bnunu 19d84ce775 Merge pull request #383 from chestahh/opence-hud-fixes-2
Fixes to latest high-res HUD commit
2026-10-16 15:56:39 -04:00
chestahh 5f4beed534 Match high-resolution controller glyphs to the Xbox HUD
Match visible A/B/X/Y and supplied trigger/thumbstick artwork to the Xbox
bitmap bounds and center prompts around the visible glyph. Keep Black and
White unchanged. Preserve all three stick press frames and rename the
Menu Gems display label to Dark Gems without changing saved values.

Use the original HUD ONE/INVSRCALPHA blend for sticks and triggers, with
premultiplied asset edges, to avoid dimming them by prompt alpha twice.
Increase the existing high-res texture table so every new frame loads.
All changes remain in the existing high-res feature and menu wiring;
low-res fallbacks and unrelated icon indices retain their existing paths.

Checked: 358 focused HUD/menu/MCC tests on testing, Windows portable release
builds on testing and a clean upstream checkout, and hidden Xbox a10
captures for size, spacing and brightness. Android/Web targets are absent
from this Windows build graph. No protocol or simulation changes.

(cherry picked from commit c21ec87e6fbc6eb3370597dbdbc92cbe5464bb61)
2026-10-16 20:45:36 +01:00
bnunu 17a4c84a0a Merge pull request #326 from innerhat-dev/screen-fog-fov-testing
Screen fog stays on the canopy when the field of view is widened
2026-10-16 15:29:45 -04:00
bnunu 2c849ca30c Merge pull request #380 from chestahh/opence-hud-fixes
Fix low-res bitmaps overlap issue with High-Res HUD, as well as general high-res bitmap issues
2026-10-16 15:25:40 -04:00
chestahh c794406c20 Restore authored opacity for high-resolution HUD buttons (#380)
Xbox button definitions override prompt text with full-opacity colors.
Honor that existing override for Classic, Gems and Menu Gems while
retaining text alpha for icons without it. Embedded artwork supplies RGB.

Validated original Xbox a10/Blood Gulch definitions, opaque asset
interiors, Windows portable release compilation, and production-function
checks for all three styles, full/partial alpha, fallback, and cleanup.
Android/Web targets were unavailable in the Windows configuration.
No MCC/fork code, tests, documentation, assets or workflow changes included.

(cherry picked from commit ce6cf74623912bf442efcfb2e0d6849a84f86011)
2026-10-16 20:08:22 +01:00
Stefan MaierandClaude Opus 5.5 8662777f11 Merge feature/frame-updater: the Steam Frame's launcher updates the game
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 20:53:11 +02:00
chestahh f80bd15210 Add supplied Xbox Gems and retain Menu Gems as a third style (#380)
Use the supplied transparent A/B/X/Y artwork for Gems, fitted within the existing button bounds. Preserve the original menu redraws as Menu Gems and share their Black/White glyphs between both gem styles. Classic remains the default. Keep the source PNGs and deterministic asset conversion, and reserve enough placeholder entries for all styles across map changes.

Validated the Windows release build and 269 focused checks, including generated texture bounds, centering, repeatable output, all three native/MCC style transitions, disposal, and menu row spacing. Existing menu glyph PNGs remain unchanged.

(cherry picked from commit 5f66c51927f09c31095e224b0cbfbeb8aeef0bb8)
2026-10-16 19:44:57 +01:00
chestahh 4773c351d2 Add Classic and Gems high-resolution HUD button styles (#380)
Default high-resolution gameplay A/B/X/Y/Black/White buttons to plain Xbox faces made from the existing redraws. Retain the shaded faces as Gems and keep glyph geometry unchanged. Show Button Style below High-Res HUD only while enabled, following pending edits and closing the row gap when hidden. Recreate owned glyph placeholders on style changes and dispose them on map unload.

Validated the Windows release build, hidden menu captures with both styles and HUD off, isolated Xbox gameplay, and 268 focused production-code and menu checks including repeated visibility/focus and glyph lifecycle changes. Android and Web builds were attempted but their targets are unavailable in this Windows configuration.

(cherry picked from commit e8f36b8aa2b906a738856ac198efbd591cc9bcc0)
2026-10-16 19:44:33 +01:00
Stefan MaierandClaude Opus 5.5 e24df8ead9 The Steam Frame's launcher updates the game
The game's own updater (the Quest's) cannot on the Steam Frame: Lepton
installs the APK in the game's folder there at every start. So the
launcher does it: while the game runs it asks GitHub for the latest
release, fetches a newer one's Steam Frame bundle into update/, checks
it (its build.txt is the release's number), and puts the APK and the
launcher in place as the next start begins, before Lepton runs the APK.
update.auto = false in config.toml stops it, as on the Quest; a build
with no number (build.txt, which the bundle now carries and the
installer copies; 0 for local builds) never looks; without the internet,
or when anything fails, nothing changes. The in-game updater no longer
starts there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 20:40:26 +02:00
Stefan MaierandClaude Opus 5.5 7a10a413c8 Merge feature/vr-refresh-auto: the eyes drawn one by one (multiview's doubled pictures online), the refresh rate stepped down while frames come late
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 18:57:18 +02:00
Stefan MaierandClaude Opus 5.5 5ce39c27a7 Roadmap: multiview to look into later; refresh rate steps in main
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 18:57:17 +02:00
Stefan MaierandClaude Opus 5.5 67d738451c Draw the eyes one by one by default; multiview only with debug.multiview
On the Quest 3, in big online games (26-35 players), the picture was
doubled and shifted from the start as the head turned, nauseating; with
48 bots it was not, and with the eyes drawn one by one it was not online
either. Not the frame rate: one by one, online at 72 Hz, the compositor
repeated as many frames and nothing was seen. The Steam Frame had the
same doubling with multiview (2026-10-05) and draws them one by one
since. So both now do by default; debug.multiview (was vr.multiview, and
debug.multiview_steamvr) draws them at once, for finding what the shared
pass draws wrongly. The refresh rate's steps take up the extra cost.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 18:48:27 +02:00
Stefan MaierandClaude Opus 5.5 91bdb7e67c Refresh rate: step down at one late frame in 32, show the rate it runs at
The first try stepped 90 to 80 Hz a few seconds into a 30-player game,
and no doubled picture was seen, but 2-5 stale frames a second were left
at 80: one late frame in 32 (was 16) takes it on to 72. The VR options
show the rate chosen and the one it runs at while lowered.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 17:44:18 +02:00
Stefan MaierandClaude Opus 5.5 bf778b6d60 Step the refresh rate down while frames come late (vr.refresh_rate_auto)
In big online games a client's ticks cost 3 to 5 ms (twice what bots or
smaller games do), and the frames with a tick missed 90 Hz's 11.1 ms:
the headset showed them twice, a doubled picture when turning, with the
GPU at 60-80 %. While more than one frame in sixteen comes late, two
two-second windows running, the rate now steps down to the next the
headset offers (90 to 72 Hz); after ten windows in which hardly any
would be late at the rate above, it steps back up, never above
vr.refresh_rate. A load's long frames count for neither. On by default,
"Lower it when frames are late" on the VR options' MORE page; nothing
where the headset offers one rate (SteamVR).

Also the BUTTONS page's notes below its ten rows (the push to talk row
pushed the last one onto them).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 17:38:59 +02:00
Stefan MaierandClaude Opus 5.5 d8a786f5a1 Merge merge/upstream-oct16: OpenCE's string conversion fix, voice packets checked, the postgame host screen's menu
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 17:34:03 +02:00
chestahh e7d334c66a Match the legacy size and spacing of gameplay button glyphs
Increase the existing Xbox faces from 20 to 26 HUD units, centre them on the text capital midpoint and compensate for the text renderer's following-run inset. Preserve their original artwork and split-screen scale. Checked the portable Windows OpenCE build and hidden 1280x720 gameplay captures; the Press X to prompt has balanced visible gaps. Retain the repository's rocket reticle unchanged at the user's request.
2026-10-16 16:17:40 +01:00
chestahh f8b3eecb37 Complete the high-resolution Xbox HUD
Upscale the original vehicle/passenger labels, warnings, reload dots and
messaging sheets without changing their glyph layout or sprite coordinates.
Use the existing Xbox controller redraws for A/B/X/Y/Black/White prompts;
other controller symbols retain the original Xbox art through upscaling.
Match the existing high-resolution vehicle meter contour to remove the
double wrench. Restore the rounded diamond sniper reticle, contain the
flashlight fill and assign discrete thresholds to whole ammunition bullets.

The HUD module owns interpolation and tag selection. A narrow texture-cache
hook is needed to obtain decoded original pixels and invalidate generated
textures with their source; the messaging hook selects the existing button
art. Both respect the High-Res HUD setting. MCC's separate draw/texture
paths remain intact. No MCC bitmap data is embedded; label interpolation
was retained at the user's request, with its limited sharpness acknowledged.

Validated Windows portable release build; 246 focused HUD tests; 15,360
real GPU ammunition checks; hidden Xbox HUD captures enabled/disabled;
Xbox/MCC/Xbox transitions at 30 and 120 FPS with no exceptions. Player health
and sniper zoom-label pixels outside the targeted regions are unchanged.
Android/web targets are unavailable in this Windows build configuration;
Custom Edition gameplay data is unavailable, so that path was inspected.
No simulation or network format changes; network version stays unchanged.

(cherry picked from commit 5398553e4a95d7d68376acf023e6ca671066a614)
2026-10-16 16:07:49 +01:00
chestahh adccd47fe0 Restore online pause gradients and campaign Settings
Apply the existing campaign gradient to the three- and four-button online
pause artwork, retaining the translucent footer. Admit full-screen Xbox
network campaigns to the existing Settings insertion while keeping local
split-screen unchanged and preventing network Settings from pausing time.

Checked Windows release build, pause-art and campaign-context harnesses,
and hidden two-peer Xbox multiplayer and co-op sessions. The co-op client
can select and open Settings. Android/web builds are unavailable in this
Windows configuration; no wire-format or simulation contract changed.

(cherry picked from commit 04cd1e25e910c5234fee323033b1efb8c71e8e0a)
2026-10-16 14:35:52 +01:00
Stefan MaierandClaude Opus 5.5 7c294c9c39 Merge OpenCE upstream: its fix of the string conversion (taken over ours), voice packets checked, the postgame host screen's menu
Upstream fixed the Android asm conversion's string bug independently
(d9669f6ee, also from a Steam Frame crash); its converter and tests
replace ours (c85cf8ece), which they cover and extend (quoted names
honour escapes).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 09:05:24 +02:00
bnunu f90d955527 Merge pull request #374 from chestahh/opence-multiplayer-menu-fix
Restore the main menu when leaving the postgame host screen
2026-10-16 00:13:42 -04:00
chestahh 5e228ea9db Restore pause menu artwork, timer digits and multiplayer menu spacing
Restore the pause header and footer bands while retaining Settings, the
campaign body gradient, and the Xbox footer alpha of 191/255. Initialize
the scripted timer scaling flags so stack data cannot shrink its digits.
Move Edit Gametypes and its divider inside the connected panel.

This implementation-only upstream contribution excludes MCC, regression
tests, documentation, optional regeneration commands and workflows. The
complete fixes and tests remain on GulchCE testing and the local validation
branch. Original cherry-picked changes below were combined and scoped to
OpenCE; authorship is retained.

Validated: portable release Windows builds on both bases; 25 upstream
art/timer tests and 52 GulchCE tests before upstream test exclusion; hidden
Xbox and MCC pause captures, both timer HUD settings, and multiplayer menu
captures. Final generator matches all committed pause SVGs. Android/web
targets are unavailable in this Windows configuration; online co-op was
not replayed.

(cherry picked from commit a0c20572f8bfa6af0d2f94c57abef32357750bf0)
(cherry picked from commit c76a3a596f7dbe8ced581b2e6c759aae0baababb)
(cherry picked from commit f0804e1e5c857db6dc84ff16c72d3f8b8abf95a2)
(cherry picked from commit bff920f6a5ec614caf98ff5e8555a0320b0a29f1)
(cherry picked from commit b1b59eb7237d901dba10aa0b5187b184f3f44a7b)
2026-10-16 04:43:57 +01:00
bnunu 085676d827 Merge pull request #346 from startupfoundry/arm64-guest-strings
arm64 and Android guests: string literals kept byte for byte (fixes a voice chat crash)
2026-10-15 23:37:14 -04:00
chestahh 4301ca88d6 Restore the main menu when leaving the postgame host screen
The postgame host map picker opens without menu history. Give it the
existing main_menu_if_no_history flag used by the lobby so leaving the
last screen restores the main menu instead of leaving only the background.
Update the generator and generated XML together. Preserve OpenCE's
existing handlers; no MCC code or regression-test files are included.
This local menu change does not require a network version bump.

Resolved the fork cherry-pick against OpenCE main 8102e711 by adding only
the flag override. Windows portable release build passed. Existing menu
teardown, touch and web checks returned 28 passes and 6 failures: missing
m.lib/pthread.h and Windows path separators in POSIX-oriented tests.
Android and web build targets were unavailable locally. Checked generator
round-trip stability and git diff --check. The two simple wrappers were
regenerated through ce_menus.widget_xml from their exported XML fields;
the original PC tag inputs were unavailable. No upstream runtime game
session or Linux build was run. Earlier scripted runtime verification
was performed on the GulchCE implementation, not this upstream revision.

(cherry picked from commit c811c7f527d70d5476578ed88ea0edcef2269967)
2026-10-16 02:51:54 +01:00
justinfilip 7cf24ae589 Stop carrying an unsteered vehicle once the host says it has stopped. 2026-10-15 12:35:57 -05:00
justinfilip e5e97c0526 Carry a vehicle no player drives along the host's positions. 2026-10-15 11:08:46 -05:00
Stefan MaierandClaude Opus 5.5 b5cdd9268c Merge merge/upstream-net29: OpenCE network version 29
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 13:26:16 +02:00
Stefan MaierandClaude Opus 5.5 34b61fba31 Roadmap: OpenCE network version 29
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 13:06:41 +02:00
Stefan MaierandClaude Opus 5.5 87fe9fc1ad Merge OpenCE upstream: network version 29, Custom Edition maps keep their names, map sharing hardened
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 13:04:54 +02:00
MrBruh 8102e711c3 Merge pull request #353 from OpenCommunityEdition/testing
Merge testing into main
2026-10-14 23:21:30 +13:00
MrBruh 3e0ba55111 Keep Custom Edition maps' own names: the version goes in the game record
A game's level name is the map's own (custom_maps\hugeass), so no screen or
server browser listing shows a hash, and the game record's map version is
the map's hash's first 32 bits, which a client finds its file by. Maps are
no longer renamed; a download beside another version of its name is named
<name>_<hash>.map and listed as "(2)"; maps the last build renamed get
their names back. Network version 29: the level name and the map version
mean something else.
2026-10-14 23:08:39 +13:00
MrBruh 37ded3287c Fix harness tests for clang 23 2026-10-14 21:17:03 +13:00
Paul Hontz 9c70f5f5e3 Voice chat: a packet that is not one 20 ms frame is dropped before decoding
Every build sends one 20 ms frame per packet (voice_audio_encode). A packet
whose table of contents says otherwise, or that Opus cannot parse, is
damaged: voice_audio_play now drops it before the decoder sees it
(opus_packet_get_nb_samples), and the next frame makes up for it as lost.
Cheap defence in depth: Opus's decoder already refuses such packets, and the
crash in decode_pulses came from a valid packet and the guest's garbled
pulse cache, fixed in the assembly conversion.
2026-10-13 22:13:44 -04:00
Paul Hontz d9669f6eef The guest's assembly conversion keeps string literals byte for byte
The arm64 and Android guests are compiled for arm64_32-apple-watchos and
their Darwin assembly converted to ELF (tools/android_asm_convert.py). The
converter took a quoted .ascii/.asciz operand for a quoted symbol name and
dropped a leading "_" from it, as it does from symbols; and its quoted-name
pattern ended at an escaped quote (\"), so the "_" of a word after one was
dropped too. Clang writes byte tables as .ascii strings, so a table holding
95 ("_") lost that byte and everything after it moved down by one.

In Opus that table was CELT's pulse cache (modes.c, cache_bits50): the bits
a band may have are read off it, and shifted by a byte it lets a band have
more pulses than the PVQ tables hold. Decoding a frame from another player
then read past CELT_PVQ_U_ROW in decode_pulses (n 32, k 240) and crashed: a
client on the Steam Frame, in a CTF game on the internet. The guest's own
encoder could crash likewise in encode_pulses. The same build of Opus,
driven with the game's settings and with clean, corrupt, truncated and
random packets and voice_audio_play's loss handling, crashed within a few
thousand frames (and identically at -O0); with the fix it ran 4.8 million
decodes clean, and its encoded bytes and decoded samples are identical to a
native 64-bit build's.

The same loss hit other strings and tables of the guest: musl's iswalpha,
iswpunct and towctrans tables and iconv's charmaps; tomlc17's "_0123..."
digit sets (TOML numbers with "_"); the attract mode's "_de"/"_fr" names,
"_lan_", "_lit" and "_%s"; the progress bar's compressed monk tone and the
DirectSound effects image; and assertion and error texts. All are now
assembled as compiled.

String directives now go through unchanged, and quoted names honour
escapes. tools/test_android_asm_convert.py checks both, and a table of
every byte value through clang, the conversion and the assembler.
2026-10-13 22:13:44 -04:00
Stefan MaierandClaude Opus 5.5 238f3e2391 Merge fix/frame-voice-crash: the Android asm conversion keeps string data (the Steam Frame's voice chat crash), push to talk on any button
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:45:46 +02:00
Stefan MaierandClaude Opus 5.5 e18c2b37d6 Push to talk on any button, never sent by a grip reaching for the weapon
Push to talk becomes an action of the BUTTONS page (vr.button_talk),
on an eighth button there, the free hand's grip (its default): it can
trade places with any other action (the move stick's click, say, so
that a player holding a weapon in both hands can talk).

The free hand's grip as a button is pressed once held 0.15 s, at the
threshold halo_vr_two_hand takes the foregrip at, and not at all while
it holds the weapon's foregrip or the Warthog's wheel: taken in that
time, the press is theirs until the grip opens. Before, the runtime's
grip button (which closes before the foregrip's threshold) could open
the microphone for a frame or two as the hand took the weapon.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:45:40 +02:00
Stefan MaierandClaude Opus 5.5 c85cf8ece1 Keep string data as it is in the Android asm conversion
android_asm_convert.py renamed identifiers in every directive's operands,
string data included: a string starting with "_" was taken for a quoted
symbol and lost the "_", and one with \" in it was split wrongly, so a
"_" starting a word in it was dropped too. 26 of the guest's objects had
strings or tables cut short. Among them Opus's pulse cache (cache_bits50,
one byte short from entry 338): its encoder picked more pulses than its
tables hold for some bands and crashed (the Steam Frame's crashes in
online games, with push to talk). Also musl's wide character tables,
map sharing's hashed names ("_%s"), the "_lan_" menu check, libtiff's
and the sound code's tables.

.ascii, .asciz and .string are now passed on unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:06:59 +02:00
justinfilip 521c44f862 Keep screen fog on the canopy when the field of view is widened. 2026-10-12 20:50:57 -05:00
Stefan MaierandClaude Opus 5.5 01076509dd Merge fix/vr-frame-hitches: OpenCE network version 28, a shader worker and cache, graphics "medium" by default
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 23:04:19 +02:00
MrBruh 6d64abdb42 Fix map sharing restart overflow and harden map validation 2026-10-13 07:43:41 +13:00
MrBruh 52e33a391e Harden map sharing and Custom Edition map loading 2026-10-12 22:26:25 +13:00
WhiteBulL 0f3ceb9eab refactor: worked on comments a little bit more 2026-10-10 19:39:39 +03:00
WhiteBulL 39fcfdafaf feat: resampler linear mode
Fixed read past a buffer issue and
untied previous solution from reverb.
Also added config variable audio.resampler
(but no UI implementation since currently
there is no more space for that option).
2026-10-10 17:21:08 +03:00
WhiteBulL 4afb59660a Disable global audio muffling when reverb is false
previous incorrect implementation
2026-10-10 14:20:09 +03:00
222 changed files with 14514 additions and 1447 deletions

No files matched your search

+1 -1
View File
@@ -99,7 +99,7 @@ jobs:
- name: Test
run: |
python -m pytest -q tools/test_linux_port.py tools/test_host_watch_hash.py tools/test_touch_menu.py tools/harness tools/test_profile.py
python -m pytest -q tools/test_linux_port.py tools/test_android_asm_convert.py tools/test_host_watch_hash.py tools/test_touch_menu.py tools/harness tools/test_profile.py
python tools/test_light_storage.py
- name: Compile cache
+5 -3
View File
@@ -15,8 +15,8 @@ end.
| Path | Contents |
| --- | --- |
| `source/` | The game: 466 C files of the decompilation, compiled as they are with few changes (each marked, below) |
| `port/linux/src/` | The platform layer the three ports share: Direct3D 8 on OpenGL (`d3d8_gl.c`), DirectSound and XInput on SDL3, files, threads, memory, sockets, settings (`port_config.c`), internet play (`p2p*.c`) |
| `port/linux/game/` | The port's game-side code, compiled as the game's sources are: the distributed netcode (`network_*.c`), co-op, map sharing (`map_share*.c`), the menus (`menu_tags.c`, `menu_functions.c`), Custom Edition maps (`custom_edition_*.c`, `cache_file_formats.c`), the tag validator (`tag_validate.c`, `tag_schema_*.c`), touch, FOV and more |
| `port/linux/src/` | The platform layer the three ports share: Direct3D 8 on OpenGL (`d3d8_gl.c`), DirectSound and XInput on SDL3, files, threads, memory, sockets, settings (`port_config.c`), the mods folder (`port_mods.c`), internet play (`p2p*.c`) |
| `port/linux/game/` | The port's game-side code, compiled as the game's sources are: the distributed netcode (`network_*.c`), co-op, map sharing (`map_share*.c`), the menus (`menu_tags.c`, `menu_functions.c`), Custom Edition maps (`custom_edition_*.c`, `cache_file_formats.c`), the tag validator (`tag_validate.c`, `tag_schema_*.c`), mods (`mods.c`, `mod_*.c`), touch, FOV and more |
| `port/linux/include/` | The port's headers: the limits (`halo_port_limits.h`, with `HALO_PORT_NETWORK_VERSION`), capacities (`halo_port_capacity.h`), the prefix header, `halo_linux_source_fixups.h` (port functions the game's sources call) |
| `port/include/xdk/` | Stand-ins for the Xbox SDK's headers (declarations only) |
| `port/windows/` | The Windows build's own files (`win32_*.c`, headers) |
@@ -26,7 +26,7 @@ end.
| `port/third_party/` | Vendored libraries, each with a README naming its upstream, version and checksum |
| `port/tools/` | Stand-alone tools (`cache_file_report.c`) |
| `tools/` | Build scripts (`linux_build.py`, `windows_build.py`, `android_build.py`, `web_build.py`, `ci_build.py`, `web_serve.py`), generators (`ce_menus.py`, `port_settings.py`, `hud_assets.py`, `title_assets.py`, `embed_assets.py`, `xdk_headers.py`) and tests |
| `docs/` | Longer design notes (`custom_edition_caches.md`) |
| `docs/` | Longer design notes (`custom_edition_caches.md`, `mods.md`) |
| `pgo/` | Profile-guided optimisation profiles |
| `assets/` | Game data for local runs (gitignored: `maps/`, `custom_maps/`) |
| `.github/workflows/` | CI: builds every platform on each push, publishes releases from `main` |
@@ -84,6 +84,7 @@ setting (`game.custom_edition`), checked at run time with
```sh
python -m pytest -q tools/harness tools/test_touch_menu.py # the engine's functions in a fake world
python -m pytest -q tools/test_linux_port.py # the build, the maps' checks (needs assets/maps)
python -m pytest -q tools/test_mods.py # mods played over a map (needs assets/maps)
python -m pytest -q tools/test_cache_file_formats.py tools/test_bmp_files.py tools/test_profile.py
python tools/test_touch_layout.py # the Android touch layout (JDK 17+)
python tools/test_light_storage.py
@@ -216,6 +217,7 @@ as documentation of file formats, never copied.
| [port/web/README.md](port/web/README.md) | The web build, the page, the game data in the browser, limits, how it operates, hosting on GitHub Pages |
| [port/include/xdk/README.md](port/include/xdk/README.md) | How the SDK declarations were written and are checked |
| [docs/custom_edition_caches.md](docs/custom_edition_caches.md) | Loading and converting Custom Edition maps, and the evidence for each layout |
| [docs/mods.md](docs/mods.md) | Mods: folders of Halo PC tag files whose sounds, bitmaps, text and models play over a map's on one machine |
| [port/assets/menus/README.md](port/assets/menus/README.md) | The menu files' format and how to write them again |
| [port/assets/menus/NON_HANDDRAWN.md](port/assets/menus/NON_HANDDRAWN.md) | Menu pictures that are not redraws |
| [port/assets/menus/UNWIRED.md](port/assets/menus/UNWIRED.md) | Menu functions that do nothing yet |
+3
View File
@@ -18,3 +18,6 @@
[Lucide](https://lucide.dev) 1.53.0, copyright (c) 2026 Lucide Icons and
Contributors, under the ISC licence
(`port/assets/icons/lucide/LICENSE`).
- **The Mods menu's warning icons** (a mod out of its requested order, and
a mod that cannot be played): `triangle-alert` and `circle-x` from
[Lucide](https://lucide.dev) 1.53.0, under the same licence.
+8 -3
View File
@@ -68,7 +68,8 @@ of the game.
- A **Meta Quest 3 / 3S** or a **Steam Frame**.
- A **disc image** (`.iso` or `.xiso`) of **Halo: Combat Evolved for the
original Xbox**, made from **a disc you own**. Any region and version
works.
works. The game plays in the disc's language; on the European disc in
Spanish and Italian it takes your headset's language (else the first).
This project does not include, link to or help find game files. Please
do not ask for or share disc images in issues or discussions; such posts
@@ -116,8 +117,9 @@ No computer and no keyboard needed.
library and offers to switch back to Gaming Mode.
6. Start **Ringfall: Mjolnir VR** from your library (under *Non-Steam*).
To update, open the same file in Desktop Mode again; your settings,
saves and game data stay. More about the Steam Frame:
The game updates itself: when a new version is out, it is downloaded
while you play and used from the next start on. Your settings, saves and
game data stay. More about the Steam Frame:
[port/android/STEAM_FRAME.md](port/android/STEAM_FRAME.md).
## Playing
@@ -127,6 +129,9 @@ saves and game data stay. More about the Steam Frame:
*Quit the game* is on its last page.
- In the menus, point with a controller and pull the trigger to click.
- The controller layout is on the VR options' *Controller buttons* page.
- **Voice chat** in network games: hold the grip of the hand without the
weapon to talk (not while it holds the weapon or the Warthog's wheel).
The *BUTTONS* page can put push to talk on another button.
## Problems and questions
+27 -14
View File
@@ -35,7 +35,7 @@ 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](../port/linux/README.md#updates). The web site offers
[port/linux/README.md](port/linux/README.md#updates). The web site offers
each new build when it is out.
Each build of the `main` branch that passes on all four platforms is a new
@@ -43,9 +43,13 @@ release, and the web site then plays it. The [Releases](https://github.com/OpenC
page keeps the last five releases. If the latest build has a problem, get
an older build from that page.
### Arch-based Linux Distributions
The above Linux binary release is available on the [AUR](https://aur.archlinux.org/packages/opence-bin).
## Game data
The port does not include the game data. Make an Xbox disc image from your own copy
The port does not include the game data. Download an Xbox disc image
(`.xiso` or `.iso`) 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,
@@ -57,10 +61,19 @@ so players of the two versions can play together.
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](../port/android/README.md). On
data folder. Refer to [port/android/README.md](port/android/README.md). On
the web, the page copies `maps/` out of the disc image into the browser's
storage for the site; nothing is uploaded. Refer to
[port/web/README.md](../port/web/README.md).
[port/web/README.md](port/web/README.md).
## Mods
Mods are folders of Halo PC tag files, as the Halo Editing Kit and Invader
write them, in `mods/` next to `maps/`: texture, sound, text and model packs
that play over the maps' on your machine only, in any game. Each has a
`mod.toml`. Every mod in the folder is on; the main menu's Mods turns them
off and on and sets the order they load in.
Refer to [docs/mods.md](docs/mods.md).
## Platforms
@@ -68,10 +81,10 @@ Each platform has its own instructions:
| Platform | Instructions |
| --- | --- |
| Linux (32-bit x86 executable, OpenGL 4.5, SDL3) | [port/linux/README.md](../port/linux/README.md) |
| Windows (32-bit x86 executable, OpenGL 4.5, SDL3) | [port/windows/README.md](../port/windows/README.md) |
| Android (arm64 app, OpenGL ES 3, SDL3) | [port/android/README.md](../port/android/README.md) |
| Web (WebAssembly, WebGL 2, SDL3; desktop Chrome, Edge and Firefox) | [port/web/README.md](../port/web/README.md) |
| Linux (32-bit x86 executable, OpenGL 4.5, SDL3) | [port/linux/README.md](port/linux/README.md) |
| Windows (32-bit x86 executable, OpenGL 4.5, SDL3) | [port/windows/README.md](port/windows/README.md) |
| Android (arm64 app, OpenGL ES 3, SDL3) | [port/android/README.md](port/android/README.md) |
| Web (WebAssembly, WebGL 2, SDL3; desktop Chrome, Edge and Firefox) | [port/web/README.md](port/web/README.md) |
The Linux README also gives the controls, the settings and the multiplayer
functions. These are almost the same on all platforms.
@@ -84,19 +97,19 @@ The game can play system link games on a local network and on the internet:
- Linux, Windows and Android machines and browsers can play in the same
game. On a local network, the native builds play system link; browsers
play each other in rooms, over WebRTC
([port/web/README.md](../port/web/README.md)).
([port/web/README.md](port/web/README.md)).
- An invite link, or the server browser, lets a machine join a game on the
internet, browsers too: a native build takes a browser's WebRTC
([port/linux/README.md](../port/linux/README.md), "Browsers"). No server of
([port/linux/README.md](port/linux/README.md), "Browsers"). 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](../port/linux/NETCODE.md).
[port/linux/NETCODE.md](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](../port/include/xdk/README.md).
the game uses. Refer to [port/include/xdk](port/include/xdk/README.md).
To build the game:
@@ -127,7 +140,7 @@ Give these options to `configure.py`:
| --- | --- |
| (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](../port/linux/README.md#portable-build). Use this option for builds that you give to other persons. |
| `--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](port/linux/README.md#portable-build). 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". |
@@ -187,7 +200,7 @@ file.
`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](../port/linux/README.md).
[port/linux/README.md](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.
+27 -22
View File
@@ -33,17 +33,18 @@ network games, and is never taken for one of the campaign's levels (saved
games, progress, the next level). The game engine keeps 63 characters of a
level name, so a map whose file name is longer than 51 is not listed.
A map in `custom_maps` is named for its contents once the map lists (or a
host picking it) find it: `hugeass.map` becomes `hugeass_0e2b3ee4.map`, the
first 8 hexadecimal digits of its hash after `_`, its `.bmp` and `.txt`
renamed with it (`port/linux/game/map_share_files.c`; the name is cut short
to keep the level name within 63 characters). A network game's level name
then says which version of the map it is on, a player without it downloads
it under that name (`port/linux/NETCODE.md`, "Map sharing"), and two
versions of a map keep apart. A level name without the hash (a saved last
map, a test's) finds the one map of that name in `custom_maps`. The menus
show a map without its hash, unless two versions of it are listed. Maps in
a Custom Edition install's folder keep their names.
Maps keep their names. A network game's level name is the map's own
(`custom_maps\hugeass`), and its game record's map version is the first 32
bits of the map's hash (`port/linux/game/map_share_files.c`), so a client
plays its file of that name and version, whatever else it has of the name
(`custom_edition_map_find_version`); a player without it downloads it
(`port/linux/NETCODE.md`, "Map sharing"). A download beside another version
of its name is named `hugeass_0e2b3ee4.map`, the first 8 hexadecimal digits
of its hash after `_`, and the menus show it as "Hugeass (2)". A level name
without the hash (a saved last map, a test's) finds the one map of that
name in `custom_maps`, and one with it (an earlier build's, which named
every map so) the map given its name back. Maps in a Custom Edition
install's folder are found and shared as `custom_maps`' are.
A map needs only the resource maps that hold its tags: its tag index says
which (`cache_file_resource_maps_needed`, `cache_file_formats.c`: a tag
@@ -96,7 +97,7 @@ than the damaged disc error precaching a missing map gives
the map cannot run there (Custom Edition maps turned off, the file not a
Custom Edition cache, or `bitmaps.map`, `sounds.map` and `loc.map` missing),
when its copy of a Custom Edition map is another version than the host's
(the host sends its file's header checksum as the game record's map
(the host sends its map's hash's first 32 bits as the game record's map
version, which the Xbox left 0: `cache_files_map_version`; a host that sends
0 is not checked), and when the host names a Custom Edition map as other
versions of this port do (`levels\test\<name>\<name>`) and the file is in
@@ -191,9 +192,11 @@ Loading, step by step (`custom_edition_cache_load`):
its lightmaps and their materials: every block within the BSP and aligned,
every material's uncompressed environment vertices (56 bytes) and
lightmap vertices (20 bytes) within the BSP and of the size their counts
give, lightmap vertices exactly when the lightmap has a bitmap, and every
normal, binormal, tangent and incident radiosity within ±1.005 (the game's
vertex compressor asserts on anything further out).
give, at most 64000 of each (the game's limit, to which the validator
cuts a material's counts), lightmap vertices exactly when the lightmap
has a bitmap, and every normal, binormal, tangent and incident radiosity
within ±1.005 (the game's vertex compressor asserts on anything further
out).
5. The header checksum is computed as OpenSauce computes it, before anything
changes the tag data; a mismatch is reported, not refused.
6. The tags held by resource maps are read into the tag cache after the tag
@@ -384,9 +387,11 @@ every tag as it checks an Xbox map's (`tag_validate_custom_edition_tags`,
called by `custom_edition_cache_tags_load`): every block and data within
the loaded tags and overlapping no other's, counts cut to the game's
capacities, indices, enums and tag references corrected, runtime values
reset, then the graph checks (collision BSPs, node trees, scripts' syntax).
A map whose pointers cannot be trusted is refused; what can be corrected is,
and logged. What differs from an Xbox map:
reset, then the graph checks (collision BSPs, node trees, scripts' syntax),
and a tag name that lies in any tag's block or data is emptied (what the
game writes there could take away its end). A map whose pointers cannot be
trusted is refused; what can be corrected is, and logged. What differs
from an Xbox map:
- the tag header has no vertex or index buffers, and the tag cache is the
Custom Edition one (23 MB);
@@ -563,10 +568,10 @@ every layout used was then checked against the sample maps.
- **What the validator corrects is lost.** A community map's data that the
validator corrects (an index past its block, an enum past its values) is
what the game then runs; Halo PC read past such data unchecked.
- **Ogg Vorbis sounds** are decoded when the map loads (stb_vorbis, public
domain) and encoded again as Xbox ADPCM in memory
(`port/linux/game/custom_edition_sounds.c`); one that cannot be decoded is
silenced, and still logs when played.
- **Ogg Vorbis sounds** are decoded when the map loads (stb_vorbis, with
added bounds checks: `port/third_party/stb_vorbis`) and encoded again as
Xbox ADPCM in memory (`port/linux/game/custom_edition_sounds.c`); one that
cannot be decoded is silenced, and still logs when played.
- **Models of 44 nodes or more** are drawn a part's nodes at a time, given
local nodes when they have none; one whose part's vertices name more
nodes than a part holds is refused.
+329
View File
@@ -0,0 +1,329 @@
# Mods
A mod is a folder of Halo PC tag files that the game plays over a map's own
tags on your machine, as a resource pack does: sounds (a high-res audio
pack), bitmaps (a texture pack, a HUD redraw), text (a translation) and
models (higher-detail weapons, vehicles and scenery). Only the machine that
has a mod plays it. Nothing of a mod is sent to another machine, and a mod
changes nothing that the machines of a network game must agree on, so you
can play with mods in any game, with players who have other mods or none. (A host's mod sounds of other lengths change how long
the host's scripts and AI wait for dialogue to end; the host decides those
for every machine, so they still agree.)
The game's code is `port/linux/game/mods.c` (with `mod_sounds.c`,
`mod_bitmaps.c`, `mod_strings.c` and `mod_models.c`, one for each kind of
tag) and `port/linux/src/port_mods.c` (the mods folder and its files).
## A mod's folder
The mods are in the `mods` folder of the data root (the folder with
`maps/`; on Android the app's data folder, on the web the browser's storage
for the site). Each mod is a folder in it, with a `mod.toml` and a `tags`
folder:
```
mods/
hd_audio/
mod.toml
tags/
sound/sfx/weapons/assault rifle/fire.sound
sound/dialog/...
german/
mod.toml
tags/
ui/hud/hud_item_messages.unicode_string_list
```
The files in `tags` have the paths of the tags they replace: a tag's name,
then its group's extension, as the Halo Editing Kit and Invader keep them.
`tags/sound/sfx/weapons/assault rifle/fire.sound` replaces the sound tag
`sound\sfx\weapons\assault rifle\fire` of every map that has one. Names are
not case-sensitive. The game only looks up the names of the map's tags among
a mod's files: a mod cannot add tags, and no tag name of a map makes a path
outside the mod.
`mod.toml` says what the mod is. Every key is optional:
```toml
name = "High-res audio" # what the Mods menu shows (else the folder's name)
id = "hd_audio" # what other mods name it by (else the folder's name)
version = "1.0"
authors = ["Someone", "Someone else"] # or one string
description = "The game's sounds at 44 kHz"
maps = ["a10", "bloodgulch"] # the maps it is for, by their files' names (else every map)
load_after = ["hd_textures"] # mods it plays over: they load before it
load_before = ["fixes"] # mods that play over it: they load after it
incompatible = ["other_audio"] # mods it cannot be played with
format = 1 # the mods' format it is made for
```
`load_after`, `load_before` and `incompatible` name other mods by their `id`
or their folder's name, not case-sensitive. A mod they name that is not in
the mods folder is passed over. `maps = []` is every map.
A folder without `mod.toml` is not a mod. A mod made for a later `format`
than the build's, or whose `maps` names no map, is not played. The game
logs anything else wrong in `mod.toml` (an unknown key, a value of the
wrong type) and uses the rest; a `mod.toml` that is not TOML at all is
logged, and the mod played without what it says.
The game's log is its output: the terminal on Linux, `halo.log` beside
`halo.exe` on Windows, logcat on Android, and the page's log on the web.
Limits: 256 mods, folder names of 63 bytes at most, 262144 files in all, 24
folders deep under `tags`, and 64 maps in a mod's `maps`.
## The load order
Every mod in the mods folder is on until you turn it off. The mods load in
an order, and where two mods have a file for the same tag, the one loaded
later plays.
- The default order is the folders' names in alphabetical order (not
case-sensitive), except that the mods a mod must load after (those it
asks to load after, and those that ask to load before it) are taken to
just before it. Mods that ask in a ring (a after b, b after a) load
alphabetically, and the game's log says so.
- The main menu's **Mods** (in the PC version's menus, `display.menus =
"pc"`, the default) is laid out as the game lobby is: the mods on the
left as a resource pack list has them, the one at the top playing over
all those below it (the load order upside down: the mod loaded last is at
the top), and the chosen mod's details in the frame on the right (its
name, what is wrong with it, whether it is on, its priority, 1 the top,
and its version, authors, folder, maps and description). Choosing a mod
(A, or a click on the chosen one: the first click chooses it) turns it on
or off (ON, OFF); left and right, or **Move up** and **Move down**, move
the chosen mod (up: over one more mod). **OK** keeps the order and plays
it at once (on a map that is loaded, too); **Cancel** leaves it as it was.
- A warning sign beside a mod means it is on the wrong side of a mod it
asks to load before or after (both on): a mod that loads after another is
above it in the menu. A red cross means a mod that is on says it cannot be
played with this one, or that it cannot be played at all (made for a later
build, or its `maps` names none): it stays off. The details say which.
The menu keeps the order, and the mods turned off, in `mods/load_order.toml`,
by the mods' folders' names:
```toml
order = ["german", "hd_audio", "hd_textures"]
disabled = ["hd_textures"]
```
A mod added to the folder later is put where the default order puts it,
after the mod before it there (but on the side it asks for of the mods it
names), and is on. A mod gone from the folder is left out. When the file
cannot be written, the game says so in its log and keeps the order until it
quits.
### Mods that cannot be played together
When a mod that is on names another that is on as `incompatible`, the game
asks as it starts, before the window opens:
- **Play anyway** plays them all (closing the box does too);
- **Turn off ...** turns off the mods named as incompatible (if mod A says
it cannot be played with mod B, B is turned off), and keeps that in
`load_order.toml`;
- **Quit** closes the game.
The Mods menu turns them on again. On the web, **Quit** starts the page
again. A run nobody watches (`debug.hidden_window`, `debug.null_renderer`,
`debug.exit_after` or `debug.network_test`) is not asked: it plays them all,
and the game's log says which conflict.
At the console:
| Command | What it does |
| --- | --- |
| `mods_list` | Lists the mods in the mods folder in their load order, and which are on, then how many of the map's string lists, bitmaps, sounds and models the mods play. |
| `mods_reload` | Finds the mods again and reads their files again: a changed file is read again (one that now fails a check leaves what was played before), a new one is played, and the map's tag comes back for a file that is gone. If a sound changed, all sounds stop. It does nothing while `mods_enable false`. |
| `mods_enable false` | Plays the map's own tags until `mods_enable true` or the next map. |
These commands work in any game, a client's too: they change nothing of the
game.
### Getting a mod onto each platform
- **Linux, Windows**: put the mod's folder in `mods/` next to `maps/`.
- **Android**: put it in `mods/` in the app's data folder,
`/sdcard/Android/data/com.halo.decomp/files/mods`, for example with
`adb push hd_audio /sdcard/Android/data/com.halo.decomp/files/mods/`.
- **Web**: on the page, **Mods**, **Add a mod folder…** copies a mod's
`mod.toml` and `tags` folder into the browser's storage for the site.
**Remove** deletes it again.
## What a mod can replace
The game plays these groups from a mod. It does not read the files of any
other group (a `.weapon`, `.vehicle`, `.model_collision_geometry` or
`.scenario`, for example): they would change what the machines of a network
game must agree on.
| Group | Extension | What it is |
| --- | --- | --- |
| Sound | `.sound` | Sounds, music and dialogue |
| Bitmap | `.bitmap` | Textures, sprites, the HUD's pictures |
| Unicode string list | `.unicode_string_list` | The text the game shows |
| String list | `.string_list` | Other text |
| Model | `.gbxmodel` (Halo PC's), `.model` (the Xbox's) | What objects look like: weapons, first-person weapons and arms, vehicles, scenery, characters |
A file must be a Halo PC tag file of its group, as the Halo Editing Kit's
tools and Invader write them (a model also as `invader-extract` writes an
Xbox map's: `.model`). The game checks every count, size and offset
in it against the file, and every value against what the game reads, before
it uses the file. A file that fails a check is left out (the map's tag
plays), and `debug.txt` and the console say why.
### Sounds
- The samples can be 16-bit PCM, Xbox ADPCM or Ogg Vorbis, mono or stereo,
at 22 or 44 kHz. The game converts them to the Xbox ADPCM that it plays,
as it does for Custom Edition maps: mono at 22 kHz, stereo at its own rate.
- Empty values are filled in as a map's build fills them in: the defaults
of the sound's class, the playback rates and the bend.
- A sound must have permutations: a file with an empty pitch range (some
Halo PC translations have them) is left out.
- A permutation must fit in a block of the sound cache (one sound's samples:
`MAXIMUM_SOUND_DATA_SIZE`).
### Bitmaps
- A bitmap's types and formats are those the game draws: 2D, 3D and cube
maps; A8, Y8, AY8, A8Y8, R5G6B5, A1R5G5B5, A4R4G4B4, X8R8G8B8, A8R8G8B8,
DXT1, DXT3, DXT5 and P8 bump. Sides are 4096 at most (512 for a 3D
bitmap). A bitmap that is not a power of two on each side is drawn
linear, as a Custom Edition map's is: it must be an uncompressed 2D
bitmap.
- One bitmap's pixels may take a quarter of the texture cache: 64 MB on
Linux and Windows, 5.5 MB on Android and the web (a 2048 x 2048 DXT5 with
its mipmaps fits on all of them).
- A bitmap replaces the map's bitmap of its name, and the map's other tags
use it as the map's: it must have at least as many bitmaps, of the same
types, and as many sequences, each with at least as many sprites. It can
be larger: a redraw at twice the size is drawn at the map's size, sharper.
- The HUD draws a bitmap at its own size. So for each HUD element that draws
a mod's bitmap, the game scales the element by the map's size of what it
draws (its sprite, or with no sprites its bitmap) to the mod's, when that
is the same ratio for all of them. A bitmap the HUD draws that is not the
map's redrawn so (Halo PC's HUD bitmaps lay their sprites out to other
sizes) is left out. The HUD's digits can be the map's size or twice it.
- The menus draw a bitmap in their widgets' bounds, whatever its size.
- Halo PC keeps the channels of a model shader's multipurpose maps and of
the HUD's meters in another order than the Xbox. The game finds those
bitmaps among the mod's and draws them in the Xbox's order, as it does for
Custom Edition maps (`custom_edition_bitmaps.c`).
- The pixels are read from the file when the texture cache loads them, not
kept in memory.
### Text
- A list keeps the map's number of strings: a mod's strings past it are
left out, and the map's own strings stay where the mod's list is shorter.
- The game uses many strings as the format of what it prints
(`%s was killed by %s`). A mod's string replaces the map's only if it has
the same conversions in the same order (`%s`, `%d`, ...); otherwise the
map's string stays. A translation keeps the conversions of the original.
- Unicode strings are UTF-16, as the tool writes them.
- The main menu is the port's own (the PC version's menus, `port/assets/menus`),
whose text is in tags named `pc\...`. A mod's `ui\shell` lists change the
Xbox's menus (`display.menus = "xbox"`) and the text shown while playing
(HUD messages, the multiplayer messages, the pause menu).
### Models
A model is more than what is drawn: its nodes (its skeleton) are what its
animations move, its markers are where projectiles leave a weapon, where a
unit sits and where things attach, and its regions and permutations are what
damage and an object's variant choose among. The machines of a network game
agree on those, so a mod's model must have the map's:
- the same nodes: their names, hierarchy and default positions;
- the same markers: their names, regions, permutations, nodes, positions
and rotations (on the model's permutations, as the Halo Editing Kit keeps
them, or on the model, as a map does);
- the same regions and permutations: their names and flags.
Positions and rotations may differ from the map's by 0.001 at most (a model
exported again is not always bit for bit the map's). Only what is drawn is
the mod's: the geometries, their parts and vertices, which geometry each
permutation draws at each detail level, the detail levels' cutoffs, the
base map's scale, and which shaders each part is drawn with. A detail level
the map draws must draw one of the mod's geometries, and one the map draws
nothing at stays so. Every shader must be one the map has (a mod cannot add
tags); a mod's bitmaps can redraw them.
The model is checked against each map's own model of its name as that map
loads. On a map whose model of that name has other nodes, markers or
regions (a custom map's own assault rifle, say), or lacks a shader the mod
names, the mod's model is left out and the map's drawn; the mod's other
files still play there. `maps` in `mod.toml` keeps a mod to the maps it is
made for.
- Where a mod has both, its `.gbxmodel` plays; otherwise the file of the mod
loaded later, whichever its format.
- What the tool works out as it builds a map is worked out as it does: a
part's strip is its triangles block, its centroid's nodes are its most
weighted, its links of 0 to the parts drawn before and after it are none,
a base map scale of 0 is 1, and a model whose tag asks for it has the
normals of its vertices that share a position blended. The vertices are
compressed as the game draws them.
- A part's links to the parts drawn before and after it (for transparency)
must not go round.
- A model of 44 nodes or more (the renderer skins 43 at once; only Custom
Edition maps' have so many) is drawn a part's own nodes at a time, as a
Custom Edition map's is: a part's vertices may name 22 nodes at most.
- The collision geometry, the animations and the object's tag are the map's:
a larger weapon still hits and is hit where the map's does, and an object
is still left undrawn by the map's bounds of it (a much larger model may
vanish at the screen's edges).
- Every model made from a file is kept until the map changes, a file edited
and read again by `mods_reload` too, and counts against the mods' memory.
### Shaders
A model's parts can be drawn with a shader of every group Halo PC has but
one: `shader_transparent_chicago_extended`, which Gearbox added for Halo PC.
The Xbox game does not have it, so do not use it: use a
`shader_transparent_chicago` shader instead. (A Custom Edition map's
chicago extended shaders become chicago shaders as the map loads, keeping
only their four-stage maps: see
[custom_edition_caches.md](custom_edition_caches.md).) As for every
shader, it must be one the map has.
## Making a mod
1. Get the tags you want to change as tag files. `invader-extract` extracts
them from a map, and the Halo Editing Kit's tags are Halo PC's own.
2. Change them with the Halo Editing Kit or Invader (`invader-bitmap`,
`invader-sound` and `invader-model` build bitmaps, sounds and models from
images, audio files and JMS files). Keep each tag's name.
3. Put them in `tags/` of a folder in `mods/`, with a `mod.toml`.
4. Load a map (a new mod is on). `mods_reload` at the console reads the
files again as you change them, without loading the map again.
`debug.txt` has a line for every file the game leaves out, and why, and a
summary of what each kind of tag plays from the mods:
```
mods: 9 string lists from their files (9 new), 0 given back, 0 left out
mods: 66 HUD placements scaled to draw larger bitmaps at the map's size
mods: 354 bitmaps from their files (354 new), 0 given back, 6 left out
mods: 313 sounds from their files (313 new), 0 given back, 2 left out
mods: 4 models from their files (4 new), 0 given back, 1 left out
```
## How it operates
- When a map's tags load, at `mods_reload` and at the Mods menu's **OK**,
the game lists the files of the mods that are on, once, in a table of
their tag paths. Each of the map's sound, bitmap, string list and model
tags is looked up in it.
- A tag replaced by a mod takes the file's values in place, so everything
that holds the tag keeps it, and the map's own values come back when the
file goes. A sound playing or a texture in the cache is never changed
under the game: before a reload changes anything, the sounds stop and the
caches let go of what they hold.
- The mods' tags keep at most 512 MB in memory (192 MB on Android and the
web): their files, their sounds' samples, their bitmaps' tags and their
models' geometry.
- A Custom Edition map takes mods as an Xbox map does.
+4 -1
View File
@@ -98,6 +98,7 @@ To install the data from a computer:
| Item | Location in `/sdcard/Android/data/io.github.cesarus85.ringfall/files` |
| --- | --- |
| Saved games (`z:\` and `u:\`) | `save` |
| Mods (`docs/mods.md`) | `mods`: `adb push <mod folder> /sdcard/Android/data/com.halo.decomp/files/mods/`; the main menu's Mods orders them and turns them off |
| Log | `debug.txt` |
| Settings | `config.toml` |
@@ -388,7 +389,9 @@ The guest is the game, the platform layer and a small runtime:
AArch64 target of clang. The options `-U__APPLE__` and
`-fno-define-target-os-macros` hide the Darwin environment.
2. `tools/android_asm_convert.py` changes the Mach-O assembly to ELF
assembly.
assembly. It renames symbols, but keeps string literals (`.ascii`,
`.asciz`) byte for byte: they hold tables as well as text
(`tools/test_android_asm_convert.py`).
3. The AArch64 assembler makes the objects.
4. `ld.lld` links the objects with `guest/guest.ld` to a static image,
`build/android/halo_guest.elf`, at a fixed address above the Xbox memory
+5 -2
View File
@@ -16,8 +16,11 @@ On the Frame, in Desktop Mode (Steam menu > Power > Switch to Desktop):
copies the game data out of it, adds "Ringfall: Mjolnir VR" to the Steam library
and switches back to Gaming Mode. Start it from the library there.
Opening the same file again updates the game (settings, saves and game data
stay).
The game updates itself: while it runs, its launcher looks for a newer
release, fetches it and puts it in place as the next start begins
(`steam_frame_launch.sh`; `update.auto = false` in `config.toml` stops it;
`launcher.log` says what it did). Opening the same file again updates it
too (settings, saves and game data stay).
The desktop file (`steam_frame_installer.desktop`) downloads the latest
release's `ringfall-mjolnir-vr-steam-frame.zip` (`tools/steam_frame_bundle.py`, made by
+46 -8
View File
@@ -17,14 +17,17 @@ named where code is taken over.
| Area | What |
| --- | --- |
| Headsets | Quest 3; Steam Frame (Lepton): its controllers' layout, a Steam library tile that installs, starts, updates and quits the game, data kept in `~/Documents/RingfallMjolnirVR` |
| Rendering | Both eyes in one pass (multiview) on the Quest; one by one on SteamVR, where multiview's eyes did not fuse; lens flares at their depth in stereo; HUD, menus, scope, crosshair and names as layers of their own |
| Aiming | The weapon in the hand, its shots from the muzzle, laser and crosshair options |
| Rendering | The eyes drawn one by one (both at once, multiview, only with `debug.multiview`: its eyes did not always fuse, see the open points); lens flares at their depth in stereo; HUD, menus, scope, crosshair and names as layers of their own |
| Aiming | The weapon in the hand, its shots from the muzzle, laser and crosshair options; each weapon held so that its model's hand lands on the real one, as the free hand's (it learns where each weapon's animations hold the hand; the pistol's had been 15 cm before the real hand, the assault rifle's 8 cm aside), the scope's disc moved with it; `vr.weapon_hand_*` to adjust (2026-10-17) |
| Body | Physical crouch (`vr.crouch_limit`) beside the crouch button, leaning (`vr.lean_limit`), melee by swinging, grenades thrown with the left hand, two-handed weapons |
| Vehicles | The Warthog's wheel turned with the hands, right trigger throttle, left brake; first-person seats; turrets with handles |
| Comfort | Snap or smooth turning, a comfort vignette in vehicles, VR options in the main and pause menus (Y), a page of every controller button |
| Menus | The PC version's menus in VR (`vr.menus`), clicked with a laser; text typed on the on-screen keyboard |
| Multiplayer | Up to date with OpenCE (network version 28, 2026-10-12): cross-play, its server browser, co-op campaign, password lobbies; join codes and the VR online list |
| Multiplayer | Up to date with OpenCE (network version 29, 2026-10-14): cross-play, its server browser, co-op campaign, password lobbies; join codes and the VR online list |
| Bots | Bots in multiplayer: on foot (paths, items, objectives), in vehicles and at turrets; they make room for a joining person |
| Voice chat | Push to talk on any button (`vr.button_talk`, BUTTONS page; the free hand's grip by default, sending nothing while it reaches for the foregrip or the wheel), open mic, off (2026-10-13) |
| Builds | The Android build's assembly conversion (`tools/android_asm_convert.py`) keeps string data as it is: strings and tables starting with "_" or holding \" lost a "_" (Opus's pulse cache among them: the Steam Frame's crashes in online games while talking), 2026-10-13 |
| Languages | The European disc in Spanish and Italian (a maps folder for each, `maps_es` and `maps_it`, none called `maps`) imported on the Quest and the Steam Frame: the headset's language's, its language the game's and the menus' (`maps/language.txt`, unless `game.language` is set), 2026-10-17; not yet tried with that disc |
| Controls | Left-handed mode (`vr.handedness`): the weapon in the left hand, the arms and grips mirrored, sticks and buttons mirrored on both controllers (`vr.mirror_controls`), the assault rifle's counter read the right way round (2026-10-06) |
| Graphics | Presets low / medium / high / max (`vr.graphics`), refresh rate and resolution in the VR options, all kept over a restart (2026-10-06) |
| Arms and hands | Both arms by IK from shoulders that follow the torso, the elbow led by the hand's roll; fingers from trigger, grip and touch; `vr.body` arms / hands / off, `vr.fingers` (2026-10-06) |
@@ -40,6 +43,7 @@ named where code is taken over.
| 3c | Weapons held physically, holsters at shoulder and hip (the buttons stay) | |
| 3d | Other VR players shown with their heads, hands and bodies (today their bodies move as flat players' do: only their aim and throws come from their hands) | |
| 4 | Later: disc image import in the launcher; moving by swinging the arms (in place of the stick, never faster than it: online too), and a sprint by swinging them harder (faster than the game allows: offline only) | import **done** (in `main` 2026-10-06): the app's import (tried on the Quest 3: all 24 maps; on the Frame kept in `~/Documents/RingfallMjolnirVR`), a Steam Frame installer from Desktop Mode (`STEAM_FRAME.md`; tried on the Frame: the old folder renamed, the shortcut added by Steam), a release signing key (CI and local builds the same). Arm swinging and its offline sprint still open |
| 5 | Later: multiview again (both eyes in one pass, half the drawing's CPU cost): find why its eyes do not fuse in big online games on the Quest 3 (and now and then on the Steam Frame), then turn it back on | open: off by default since 2026-10-16 (`debug.multiview`); findings in the open points |
| R | Release as **Ringfall: Mjolnir VR** (no "Halo" in the product's name): app name, id `io.github.cesarus85.ringfall`, icon and library pictures (`tools/ringfall_art.py`), Frame folder and installer, release assets, README; the repository renamed | **done** (in `main` 2026-10-06; Quest 3 and Steam Frame good) |
## Step 2, first part (done)
@@ -150,11 +154,15 @@ COMFORT (turning, the vignettes), BUTTONS (the actions' buttons,
Buttons remapped (BUTTONS page; `vr.c` `controls_remapped`):
- Jump, the flashlight (held: switch grenades), action/reload, switch
weapon, crouch, zoom and melee each go on one of seven buttons: A, B,
X, Y, the move stick's click, the turning stick's, the weapon hand's
grip. Moving an action to a button swaps it with the action there, so
none is ever left without one.
- The triggers, the free hand's grip, the menu button, the Steam Frame's
weapon, crouch, zoom, melee and push to talk each go on one of eight
buttons: A, B, X, Y, the move stick's click, the turning stick's, the
weapon hand's grip, the free hand's grip. Moving an action to a button
swaps it with the action there, so none is ever left without one.
- The free hand's grip as a button (`free_grip_down`): pressed once held
0.15 s at the foregrip's threshold, and not at all while it holds the
weapon's foregrip or the Warthog's wheel (taken in that time, the press
is theirs until the grip opens).
- The triggers, the menu button, the Steam Frame's
bumpers, D-pad and View button keep theirs; the menus keep the buttons
as they are.
- Applied after the left-handed mirroring, on the gamepad's sides: the
@@ -512,6 +520,34 @@ see that nothing is missing or slower.
## Open points outside the order
- Multiview's doubled pictures (2026-10-16): on the developer's Quest 3,
doubled and shifted pictures from the start of big online games (26-35
players) as the head turned, nauseating; none in a local game with 48
bots; none online either with the eyes drawn one by one. Not the frame
rate: one by one, online at 72 Hz, the compositor repeated as many
frames (about 4 a second) and nothing was seen. Not the facing jumps
(respawns only) nor the camera (it moves every frame). Before: the
Steam Frame's (2026-10-05), each eye alone sharp. So the eyes are drawn
one by one by default now (`debug.multiview` for both at once). To do:
find what the shared pass draws wrongly online, e.g. by saving both
eyes' pictures in a big online game and comparing what is doubled
(sprites and effects projected by the game itself, `mv_depth`; programs
made on the shader worker; the sky rows), then turn it back on: it
halves the drawing's CPU cost.
- Big online games (2026-10-16): doubled pictures on a 32-player server,
none in a local game with 48 bots. Not the GPU (60–80 %): the ticks cost
3.3–4.6 ms as a client there (1.3–1.9 ms with bots or 16 players), so
47–70 of 150 frames with a tick missed 90 Hz's 11.1 ms (the doubling
itself was multiview's, above). In `main` 2026-10-16 (Quest 3 good):
`vr.refresh_rate_auto`
(VR options MORE, "Lower it when frames are late", on by default) steps
the rate down a step (90, 80, 72 Hz) while more than one frame in 32
comes late, and back up once they would keep up; "VR: refresh rate" in
the log. First try: 90 to 80 Hz a few seconds into a 30-player game, no
doubled picture seen; 2-5 stale frames a second left at 80, hence one
in 32 (was 16). Later:
why a client's ticks cost that much per remote player.
- Doubled pictures when turning on the developer's Quest 3 (2026-10-12):
with every build tried, back to 2026-10-06's, at 90 and at 72 Hz, even
in seconds the compositor reported no stale frame. That Quest runs
@@ -520,6 +556,8 @@ see that nothing is missing or slower.
default (smooth there). To do: try this and later builds with "high" on
a Quest 3 outside PTC (the developer's wife's), and set the default
back to "high" or "auto" if it holds.
Resolved 2026-10-16: multiview (above), not the Horizon OS PTC.
- Multiview on the Steam Frame: why the eyes do not fuse there (suspected
Mesa zink/Turnip); tools in branch `frame/doubled-images` (86335828),
not merged.
@@ -35,7 +35,7 @@ import java.nio.channels.FileChannel;
*/
public class LauncherActivity extends Activity {
private static final int PICK_IMAGE = 1;
private static final String SHARED_DATA_ROOT = "/home/steamos/Documents/RingfallMjolnirVR";
static final String SHARED_DATA_ROOT = "/home/steamos/Documents/RingfallMjolnirVR";
private File dataRoot;
private TextView status;
@@ -36,7 +36,8 @@ import java.util.zip.ZipInputStream;
* the latest release when it starts, on a thread of its own, and if it is
* newer asks the player whether to update:
*
* - Yes: the release's app (halo-android-release.zip or -debug.zip) is
* - Yes: the release's app (ringfall-mjolnir-vr-android-release.zip or
* -debug.zip) is
* downloaded and handed to Android's package installer, which replaces the
* game (closing it) and offers to open the new version.
* - No: nothing, until the next start.
@@ -45,6 +46,9 @@ import java.util.zip.ZipInputStream;
*
* Every build of main is signed with the same key (the workflow's), which an
* app must keep for Android to install a new version over it.
*
* Not on the Steam Frame: Lepton installs the APK in the game's folder there
* at every start, so its launcher updates that (steam_frame_launch.sh).
*/
final class Updater {
/* the VR port's own releases: the original's, made without VR, must
@@ -63,7 +67,8 @@ final class Updater {
static void start(Activity activity) {
File config = configFile(activity);
if (BuildConfig.HALO_BUILD_NUMBER <= 0 || config == null || !autoUpdate(config))
if (BuildConfig.HALO_BUILD_NUMBER <= 0 || config == null || !autoUpdate(config) ||
new File(LauncherActivity.SHARED_DATA_ROOT).isDirectory())
return;
new Thread(() -> {
int latest = latestRelease();
@@ -9,6 +9,7 @@ import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
/**
* Copies the maps folder out of an Xbox disc image (an "xiso", or a whole
@@ -29,6 +30,12 @@ import java.util.List;
* The files are written to maps.partial first and moved into maps once they
* all are, so an interrupted extraction never leaves maps/ui.map behind.
*
* A European disc in two languages (Spanish and Italian) has no maps folder
* but one for each, maps_es and maps_it: the device's language's is taken,
* else English's, else the first, and its language written to
* maps/language.txt, which the game asks the Xbox for (game.language unset,
* port/linux/src/xbox_xapi.c): the menus in it too.
*
* Some parts of this code are copyright in@fishtank.com. This product
* includes software developed by in &lt;in@fishtank.com&gt;.
*
@@ -225,6 +232,28 @@ final class XisoExtractor {
if (entry.name.equalsIgnoreCase("maps"))
maps = entry;
}
String language = null;
if (maps == null) {
String wanted = Locale.getDefault().getLanguage();
Entry english = null, first = null;
for (Entry entry : directories) {
String code = mapsLanguage(entry.name);
if (code == null)
continue;
if (code.equals(wanted))
maps = entry;
if (code.equals("en"))
english = entry;
if (first == null)
first = entry;
}
if (maps == null)
maps = english != null ? english : first;
if (maps != null)
language = mapsLanguage(maps.name);
}
if (maps == null)
throw new ExtractException("The disc image has no maps folder: it is not a Halo disc.");
@@ -286,5 +315,22 @@ final class XisoExtractor {
throw new ExtractException("Could not move " + file.name + " into " + finished + ".");
}
partial.delete();
File languageFile = new File(finished, "language.txt");
languageFile.delete();
if (language != null) {
try (FileOutputStream out = new FileOutputStream(languageFile)) {
out.write((language + "\n").getBytes(StandardCharsets.US_ASCII));
} catch (IOException e) {
throw new ExtractException("Could not write " + languageFile + " (is the storage full?).");
}
}
}
/** a language's maps folder's language ("maps_it": "it"), else null */
static String mapsLanguage(String name) {
if (name.length() != 7 || !name.regionMatches(true, 0, "maps_", 0, 5))
return null;
String code = name.substring(5).toLowerCase(Locale.ROOT);
return Character.isLetter(code.charAt(0)) && Character.isLetter(code.charAt(1)) ? code : null;
}
}
+4
View File
@@ -75,6 +75,10 @@ void host_sdl_scancode_name(int scancode, char *buffer, unsigned int size);
int host_sdl_scancode_from_name(const char *name);
int host_sdl_show_toast(const char *message, int duration, int gravity, int x, int y);
int host_sdl_show_simple_message_box(unsigned int flags, const char *title, const char *message);
/* SDL_ShowMessageBox of up to three buttons (SDL_MessageBoxData has not the
guest's layout): the index of the one chosen, else -1 */
int host_sdl_show_message_box(unsigned int flags, const char *title, const char *message, int default_index,
const char *button0, const char *button1, const char *button2);
int host_sdl_get_gamepads(unsigned int *ids, int capacity);
unsigned int host_sdl_open_gamepad(unsigned int id);
unsigned int host_sdl_gamepad_from_id(unsigned int id);
+25
View File
@@ -95,6 +95,31 @@ bool SDL_ShowSimpleMessageBox(SDL_MessageBoxFlags flags, const char *title, cons
return host_sdl_show_simple_message_box((unsigned int)flags, title, message) != 0;
}
/* (up to three buttons, their ids those of the guest's) */
bool SDL_ShowMessageBox(const SDL_MessageBoxData *data, int *buttonid)
{
const char *labels[3] = { NULL, NULL, NULL };
int default_index = -1;
int index;
int chosen;
if (!data || data->numbuttons < 1 || data->numbuttons > 3)
return false;
for (index = 0; index < data->numbuttons; index++)
{
labels[index] = data->buttons[index].text;
if (data->buttons[index].flags & SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT)
default_index = index;
}
chosen = host_sdl_show_message_box((unsigned int)data->flags, data->title, data->message, default_index,
labels[0], labels[1], labels[2]);
if (chosen < 0 || chosen >= data->numbuttons)
return false;
if (buttonid)
*buttonid = data->buttons[chosen].buttonID;
return true;
}
void SDL_Delay(Uint32 milliseconds)
{
struct timespec duration;
+32
View File
@@ -514,3 +514,35 @@ int host_sdl_show_simple_message_box(uint32_t flags, const char *title, const ch
{
return SDL_ShowSimpleMessageBox((SDL_MessageBoxFlags)flags, title, message, NULL) ? 1 : 0;
}
/* ---------- a question for the player (the mods at startup: port_mods.c) */
int host_sdl_show_message_box(uint32_t flags, const char *title, const char *message, int default_index,
const char *button0, const char *button1, const char *button2)
{
const char *labels[3] = { button0, button1, button2 };
SDL_MessageBoxButtonData buttons[3];
SDL_MessageBoxData question;
int count = 0;
int answer = -1;
int index;
for (index = 0; index < 3; index++)
{
if (!labels[index])
continue;
buttons[count].flags = index == default_index ?
SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT | SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT : 0;
buttons[count].buttonID = index;
buttons[count].text = labels[index];
count++;
}
question.flags = (SDL_MessageBoxFlags)flags;
question.window = NULL;
question.title = title;
question.message = message;
question.numbuttons = count;
question.buttons = buttons;
question.colorScheme = NULL;
return SDL_ShowMessageBox(&question, &answer) ? answer : -1;
}
+1
View File
@@ -32,6 +32,7 @@ host_sdl_set_clipboard_text
host_sdl_get_clipboard_text
host_sdl_show_toast
host_sdl_show_simple_message_box
host_sdl_show_message_box
host_sdl_get_gamepads
host_sdl_open_gamepad
host_sdl_gamepad_from_id
+4
View File
@@ -237,6 +237,10 @@ cp "$BUNDLE/$LAUNCHER" "$GAME_DIR/$LAUNCHER.tmp" && chmod 755 "$GAME_DIR/$LAUNCH
cp "$BUNDLE/$APK_NAME" "$GAME_DIR/$APK_NAME.tmp" && chmod 666 "$GAME_DIR/$APK_NAME.tmp" &&
mv -f "$GAME_DIR/$APK_NAME.tmp" "$GAME_DIR/$APK_NAME" && touch "$GAME_DIR/$APK_NAME" ||
fail "Could not write $GAME_DIR/$APK_NAME (is the storage full?)."
# (the build's number: the launcher updates from it, steam_frame_launch.sh;
# an update fetched for an older build is dropped)
cp "$BUNDLE/build.txt" "$GAME_DIR/build.txt" 2>/dev/null || rm -f "$GAME_DIR/build.txt"
rm -rf "$GAME_DIR/update"
# --- the game data
+72
View File
@@ -70,6 +70,75 @@ run()
child=0
}
# Updates (update.auto in config.toml; the game's own updater, the Quest's,
# does nothing here: Lepton installs the APK in this folder each start).
# While the game runs, the latest release is looked for; a newer one's
# bundle is fetched into update/, checked, and put in place as the next
# start begins, before Lepton runs the APK (it installs the newer one).
# A build that knows no number of its own (build.txt: a local one) never
# looks. Nothing changes without the internet, or when anything fails.
REPOSITORY="@REPOSITORY@"
UPDATE="$DATA/update"
BUILD_FILE="$DATA/build.txt"
SELF="$DATA/ringfall-mjolnir-vr.sh"
update_apply()
{
local new="$UPDATE/bundle" build
[ -f "$UPDATE/ready" ] || { rm -rf "$UPDATE"; return 0; }
build=$(cat "$new/build.txt" 2>/dev/null)
# (the launcher renamed over this one: bash goes on reading its own copy)
if cp "$new/ringfall-mjolnir-vr.sh" "$SELF.tmp" && chmod 755 "$SELF.tmp" &&
cp "$new/RingfallMjolnirVR.apk" "$APK.tmp" && chmod 666 "$APK.tmp" &&
mv -f "$SELF.tmp" "$SELF" && mv -f "$APK.tmp" "$APK" && touch "$APK" &&
cp "$new/build.txt" "$BUILD_FILE"
then
log "update: build $build put in place"
else
log "update: build $build could not be put in place"
rm -f "$SELF.tmp" "$APK.tmp"
fi
rm -rf "$UPDATE"
}
update_wanted()
{
# (update.auto = false in config.toml's [update]: never)
! awk '/^\[/ { section = $0 } section == "[update]" && /^[ \t]*auto[ \t]*=/ { print $3 }' \
"$DATA/config.toml" 2>/dev/null | grep -q false
}
update_check()
{
local installed latest
installed=$(cat "$BUILD_FILE" 2>/dev/null)
[[ "$installed" =~ ^[0-9]+$ ]] && (( installed > 0 )) || return 0
update_wanted || return 0
latest=$(curl -fsSL --max-time 20 -H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/$REPOSITORY/releases/latest" |
python3 -I -c 'import json, sys; print(json.load(sys.stdin)["tag_name"].rpartition("-")[2])' 2>/dev/null)
[[ "$latest" =~ ^[0-9]+$ ]] && (( latest > installed )) || return 0
log "update: build $latest found (this is $installed), fetching it"
rm -rf "$UPDATE" && mkdir -p "$UPDATE" || return 0
if curl -fsSL --retry 2 --max-time 900 -o "$UPDATE/bundle.zip" \
"https://github.com/$REPOSITORY/releases/download/build-$latest/ringfall-mjolnir-vr-steam-frame.zip" &&
python3 -I -m zipfile -e "$UPDATE/bundle.zip" "$UPDATE/bundle" &&
[ "$(cat "$UPDATE/bundle/build.txt" 2>/dev/null)" = "$latest" ] &&
[ -s "$UPDATE/bundle/RingfallMjolnirVR.apk" ] && [ -s "$UPDATE/bundle/ringfall-mjolnir-vr.sh" ]
then
rm -f "$UPDATE/bundle.zip"
touch "$UPDATE/ready"
log "update: build $latest fetched, put in place at the next start"
else
log "update: build $latest could not be fetched"
rm -rf "$UPDATE"
fi
}
update_apply
update_check </dev/null >/dev/null 2>&1 &
updater=$!
# (a new APK is only installed on its first start, not started; and a start
# right after a game that was ended hard can fail in SteamVR, which then
# needs a moment: again, up to three times, while it ends within 30 s)
@@ -83,4 +152,7 @@ for attempt in 1 2 3; do
sleep 5
done
rm -f "$QUIT"
# (a fetch still under way is given up: the next start looks again)
pkill -P "$updater" 2>/dev/null
kill "$updater" 2>/dev/null
log "end"
+31
View File
@@ -138,6 +138,13 @@ def walk(table, offset, depth, directories, out, visited):
walk(table, right, depth + 1, directories, out, visited)
def maps_language(name):
"""a language's maps folder's language ("maps_it": "it"), else None"""
if len(name) == 7 and name[:5].lower() == "maps_" and name[5:].isalpha():
return name[5:].lower()
return None
def extract(image_path, destination):
with open(image_path, "rb") as image:
partition, root_sector, root_size = find_volume(image)
@@ -148,6 +155,24 @@ def extract(image_path, destination):
directories = []
walk(table, 0, 0, True, directories, [0])
maps = [entry for entry in directories if entry[0].lower() == "maps"]
# (a European disc in two languages, Spanish and Italian, has a maps
# folder for each, maps_es and maps_it: the one for the language
# asked for (RINGFALL_LANGUAGE, else the system's), else English's,
# else the first; its language goes into maps/language.txt, which the
# game takes as game.language's when that is unset)
language = None
if not maps:
languages = [(maps_language(entry[0]), entry) for entry in directories if maps_language(entry[0])]
wanted = (os.environ.get("RINGFALL_LANGUAGE") or os.environ.get("LC_ALL") or
os.environ.get("LC_MESSAGES") or os.environ.get("LANG") or "")[:2].lower()
for preferred in (wanted, "en"):
chosen = [pair for pair in languages if pair[0] == preferred]
if chosen:
break
chosen = chosen or languages[:1]
if chosen:
language, entry = chosen[0]
maps = [entry]
if not maps:
raise ExtractError("The disc image has no maps folder: it is not a Halo disc.")
@@ -197,6 +222,12 @@ def extract(image_path, destination):
for name, _, _ in files:
os.replace(os.path.join(partial, name), os.path.join(finished, name))
os.rmdir(partial)
language_file = os.path.join(finished, "language.txt")
if os.path.exists(language_file):
os.remove(language_file)
if language:
with open(language_file, "w") as out:
out.write(language + "\n")
except OSError as error:
raise ExtractError("Could not move the maps into %s (%s)." % (finished, error.strerror))
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

+314
View File
@@ -207,6 +207,320 @@
]
}
]
},
{
"name": "black_butn__0",
"tag": "ui\\shell\\bitmaps\\black_butn",
"bitmap": 0,
"width": 32,
"height": 32,
"format": "dxt3",
"scale": 8,
"crc": 0,
"svg": "black_butn.svg",
"place": [
1,
0,
0
]
},
{
"name": "white_butn__0",
"tag": "ui\\shell\\bitmaps\\white_butn",
"bitmap": 0,
"width": 32,
"height": 32,
"format": "dxt3",
"scale": 8,
"crc": 0,
"svg": "white_butn.svg",
"place": [
1,
0,
0
]
},
{
"name": "classic_a__0",
"tag": "ui\\hud\\buttons\\classic_a",
"bitmap": 0,
"width": 32,
"height": 32,
"format": "dxt3",
"scale": 8,
"crc": 0,
"svg": "a_butn.svg",
"place": [
1,
0,
0
],
"classic": "#40eb40",
"letter": [
0.1685,
0.1119
]
},
{
"name": "classic_b__0",
"tag": "ui\\hud\\buttons\\classic_b",
"bitmap": 0,
"width": 32,
"height": 32,
"format": "dxt3",
"scale": 8,
"crc": 0,
"svg": "b_butn.svg",
"place": [
1,
0,
0
],
"classic": "#fa5946",
"letter": [
0.696,
0.1204
]
},
{
"name": "classic_x__0",
"tag": "ui\\hud\\buttons\\classic_x",
"bitmap": 0,
"width": 32,
"height": 32,
"format": "dxt3",
"scale": 8,
"crc": 0,
"svg": "x_butn.svg",
"place": [
1,
0,
0
],
"classic": "#3998fa",
"letter": [
0.3363,
2.4589
]
},
{
"name": "classic_y__0",
"tag": "ui\\hud\\buttons\\classic_y",
"bitmap": 0,
"width": 32,
"height": 32,
"format": "dxt3",
"scale": 8,
"crc": 0,
"svg": "y_butn.svg",
"place": [
1,
0,
0
],
"classic": "#f9e928",
"letter": [
-0.4376,
2.2898
]
},
{
"name": "classic_black__0",
"tag": "ui\\hud\\buttons\\classic_black",
"bitmap": 0,
"width": 32,
"height": 32,
"format": "dxt3",
"scale": 8,
"crc": 0,
"svg": "black_butn.svg",
"place": [
1,
0,
0
],
"classic": "#000000"
},
{
"name": "classic_white__0",
"tag": "ui\\hud\\buttons\\classic_white",
"bitmap": 0,
"width": 32,
"height": 32,
"format": "dxt3",
"scale": 8,
"crc": 0,
"svg": "white_butn.svg",
"place": [
1,
0,
0
],
"classic": "#ffffff"
},
{
"name": "gem_a__0",
"tag": "ui\\hud\\buttons\\gem_a",
"bitmap": 0,
"width": 32,
"height": 32,
"format": "dxt3",
"scale": 8,
"crc": 0,
"source_png": "source/a_gem.png"
},
{
"name": "gem_b__0",
"tag": "ui\\hud\\buttons\\gem_b",
"bitmap": 0,
"width": 32,
"height": 32,
"format": "dxt3",
"scale": 8,
"crc": 0,
"source_png": "source/b_gem.png"
},
{
"name": "gem_x__0",
"tag": "ui\\hud\\buttons\\gem_x",
"bitmap": 0,
"width": 32,
"height": 32,
"format": "dxt3",
"scale": 8,
"crc": 0,
"source_png": "source/x_gem.png"
},
{
"name": "gem_y__0",
"tag": "ui\\hud\\buttons\\gem_y",
"bitmap": 0,
"width": 32,
"height": 32,
"format": "dxt3",
"scale": 8,
"crc": 0,
"source_png": "source/y_gem.png"
},
{
"name": "trigger_left__0",
"tag": "ui\\hud\\buttons\\trigger_left",
"bitmap": 0,
"width": 64,
"height": 64,
"format": "a8r8g8b8",
"scale": 8,
"crc": 0,
"source_png": "source/trigger_left.png",
"control_cell": [
50,
35
]
},
{
"name": "trigger_right__0",
"tag": "ui\\hud\\buttons\\trigger_right",
"bitmap": 0,
"width": 64,
"height": 64,
"format": "a8r8g8b8",
"scale": 8,
"crc": 0,
"source_png": "source/trigger_right.png",
"control_cell": [
50,
35
]
},
{
"name": "thumbstick_left__0",
"tag": "ui\\hud\\buttons\\thumbstick_left",
"bitmap": 0,
"width": 64,
"height": 64,
"format": "a8r8g8b8",
"scale": 8,
"crc": 0,
"source_png": "source/thumbstick_left.png",
"control_cell": [
36,
40
]
},
{
"name": "thumbstick_right__0",
"tag": "ui\\hud\\buttons\\thumbstick_right",
"bitmap": 0,
"width": 64,
"height": 64,
"format": "a8r8g8b8",
"scale": 8,
"crc": 0,
"source_png": "source/thumbstick_right.png",
"control_cell": [
36,
40
]
},
{
"name": "thumbstick-halfway_left__0",
"tag": "ui\\hud\\buttons\\thumbstick-halfway_left",
"bitmap": 0,
"width": 64,
"height": 64,
"format": "a8r8g8b8",
"scale": 8,
"crc": 0,
"source_png": "source/thumbstick-halfway_left.png",
"control_cell": [
36,
40
]
},
{
"name": "thumbstick-halfway_right__0",
"tag": "ui\\hud\\buttons\\thumbstick-halfway_right",
"bitmap": 0,
"width": 64,
"height": 64,
"format": "a8r8g8b8",
"scale": 8,
"crc": 0,
"source_png": "source/thumbstick-halfway_right.png",
"control_cell": [
36,
40
]
},
{
"name": "thumbstick-full_left__0",
"tag": "ui\\hud\\buttons\\thumbstick-full_left",
"bitmap": 0,
"width": 64,
"height": 64,
"format": "a8r8g8b8",
"scale": 8,
"crc": 0,
"source_png": "source/thumbstick-full_left.png",
"control_cell": [
36,
40
]
},
{
"name": "thumbstick-full_right__0",
"tag": "ui\\hud\\buttons\\thumbstick-full_right",
"bitmap": 0,
"width": 64,
"height": 64,
"format": "a8r8g8b8",
"scale": 8,
"crc": 0,
"source_png": "source/thumbstick-full_right.png",
"control_cell": [
36,
40
]
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 420 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 393 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 523 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 522 KiB

+21
View File
@@ -0,0 +1,21 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<!-- Original Xbox black button, derived from the OpenCE button redraw. -->
<defs>
<linearGradient id="body" gradientUnits="userSpaceOnUse" x1="0" y1="-12.932" x2="0" y2="12.932">
<stop offset="0" stop-color="#050505"/>
<stop offset="0.5" stop-color="#202020"/>
<stop offset="1" stop-color="#454545"/>
</linearGradient>
<linearGradient id="rim" gradientUnits="userSpaceOnUse" x1="0" y1="-12.932" x2="0" y2="12.932">
<stop offset="0" stop-color="#ffffff" stop-opacity="0.74"/>
<stop offset="1" stop-color="#ffffff" stop-opacity="0.73"/>
</linearGradient>
</defs>
<g transform="translate(10.341 12.879) rotate(-26.459)">
<ellipse id="oval" rx="8.659" ry="12.932" fill="url(#body)"/>
<ellipse rx="8.082" ry="12.355" fill="none" stroke="url(#rim)" stroke-width="1.154"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 866 B

+21
View File
@@ -0,0 +1,21 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<!-- Original Xbox white button, derived from the OpenCE button redraw. -->
<defs>
<linearGradient id="body" gradientUnits="userSpaceOnUse" x1="0" y1="-12.932" x2="0" y2="12.932">
<stop offset="0" stop-color="#999999"/>
<stop offset="0.5" stop-color="#dddddd"/>
<stop offset="1" stop-color="#ffffff"/>
</linearGradient>
<linearGradient id="rim" gradientUnits="userSpaceOnUse" x1="0" y1="-12.932" x2="0" y2="12.932">
<stop offset="0" stop-color="#ffffff" stop-opacity="0.74"/>
<stop offset="1" stop-color="#ffffff" stop-opacity="0.73"/>
</linearGradient>
</defs>
<g transform="translate(10.341 12.879) rotate(-26.459)">
<ellipse id="oval" rx="8.659" ry="12.932" fill="url(#body)"/>
<ellipse rx="8.082" ry="12.355" fill="none" stroke="url(#rim)" stroke-width="1.154"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 866 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 369 KiB

After

Width:  |  Height:  |  Size: 330 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 183 KiB

After

Width:  |  Height:  |  Size: 170 KiB

+201 -7
View File
@@ -302,7 +302,70 @@
108
],
"kind": "meter",
"score": 0.683
"score": 0.683,
"thresholds": [
4,
8,
12,
16,
20,
24,
28,
32,
36,
40,
44,
48,
52,
56,
60,
64,
68,
72,
76,
80,
84,
88,
92,
96,
100,
104,
108,
112,
116,
120,
124,
128,
132,
136,
140,
144,
148,
152,
156,
160,
164,
168,
172,
176,
180,
184,
188,
192,
196,
200,
204,
208,
212,
216,
220,
224,
228,
232,
236,
240
],
"quantize_thresholds": true
},
{
"xbox": [
@@ -324,7 +387,22 @@
180
],
"kind": "meter",
"score": 0.676
"score": 0.676,
"thresholds": [
10,
30,
50,
70,
90,
110,
130,
150,
170,
190,
210,
230
],
"quantize_thresholds": true
},
{
"xbox": [
@@ -346,7 +424,22 @@
248
],
"kind": "meter",
"score": 0.747
"score": 0.747,
"thresholds": [
10,
30,
50,
70,
90,
110,
130,
150,
170,
190,
210,
230
],
"quantize_thresholds": true
},
{
"xbox": [
@@ -434,7 +527,30 @@
248
],
"kind": "meter",
"score": 0.721
"score": 0.721,
"thresholds": [
12,
24,
36,
48,
60,
72,
84,
96,
108,
120,
132,
144,
156,
168,
180,
192,
204,
216,
228,
240
],
"quantize_thresholds": true
},
{
"xbox": [
@@ -456,7 +572,14 @@
88
],
"kind": "meter",
"score": 0.852
"score": 0.852,
"thresholds": [
60,
120,
180,
240
],
"quantize_thresholds": true
},
{
"xbox": [
@@ -478,7 +601,12 @@
180
],
"kind": "meter",
"score": 0.82
"score": 0.82,
"thresholds": [
120,
240
],
"quantize_thresholds": true
}
]
},
@@ -3237,7 +3365,7 @@
50,
18
],
"svg": "hud2_left_reticles__reticle_18.svg",
"svg": "sniper_diamond.svg",
"source_scale": 1.365,
"source": [
-3.5831,
@@ -3355,6 +3483,72 @@
"score": 0.996
}
]
},
{
"name": "vehicle_wrench_outline__0",
"tag": "ui\\hud\\redraws\\vehicle_wrench_outline",
"bitmap": 0,
"width": 128,
"height": 32,
"format": "ay8",
"scale": 4,
"crc": 0,
"cells": [
{
"xbox": [
0,
0,
128,
32
],
"svg": "vehicle_wrench_outline.svg",
"source_scale": 1,
"source": [
0,
0
],
"clip": [
0,
0,
128,
32
],
"kind": "alpha"
}
]
},
{
"name": "passenger_health_outline__0",
"tag": "ui\\hud\\redraws\\passenger_health_outline",
"bitmap": 0,
"width": 128,
"height": 32,
"format": "ay8",
"scale": 4,
"crc": 0,
"cells": [
{
"xbox": [
0,
0,
128,
32
],
"svg": "passenger_health_outline.svg",
"source_scale": 1,
"source": [
0,
0
],
"clip": [
0,
0,
128,
32
],
"kind": "alpha"
}
]
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

@@ -28,12 +28,12 @@
<stop offset="0" stop-color="#ffffff"/><stop offset="1" stop-color="#000000"/>
</linearGradient>
<linearGradient id="ab0" gradientUnits="userSpaceOnUse" x1="0" y1="322.996" x2="0" y2="339.002"><stop offset="0" stop-color="#b9b9b9"/><stop offset="1" stop-color="#b3b3b3"/></linearGradient>
<mask id="mbx0" maskUnits="userSpaceOnUse" x="0" y="0" width="1024" height="512"><path d="M48.13,323 L416.49,323 L423.87,339 L55.51,339 Z" fill="url(#ab0)"/></mask>
<mask id="mbx0" maskUnits="userSpaceOnUse" x="0" y="0" width="1024" height="512"><path d="M53.5,327 L408.5,327 L412.2,335 L57.2,335 Z" fill="url(#ab0)"/></mask>
<linearGradient id="cb1" gradientUnits="userSpaceOnUse" x1="-88.616" y1="40.907" x2="242.068" y2="-111.744">
<stop offset="0" stop-color="#ffffff"/><stop offset="1" stop-color="#000000"/>
</linearGradient>
<linearGradient id="ab1" gradientUnits="userSpaceOnUse" x1="0" y1="363.996" x2="0" y2="392.003"><stop offset="0" stop-color="#b9b9b9"/><stop offset="1" stop-color="#aeaeae"/></linearGradient>
<mask id="mbx1" maskUnits="userSpaceOnUse" x="0" y="0" width="1024" height="512"><path d="M63.33,364 L459.69,364 L472.66,392 L76.29,392 Z" fill="url(#ab1)"/></mask>
<mask id="mbx1" maskUnits="userSpaceOnUse" x="0" y="0" width="1024" height="512"><path d="M68,368 L454,368 L463.3,388 L77.3,388 Z" fill="url(#ab1)"/></mask>
</defs>
<g transform="translate(0,0)" mask="url(#m1)"><rect x="564.89" y="6" width="393.11" height="60.03" fill="url(#c1)"/></g>
<g transform="translate(0,-1)" mask="url(#m4)"><rect x="49.21" y="143" width="435.41" height="112.02" fill="url(#c4)"/></g>

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="32" viewBox="0 0 128 32"><!-- Existing meter contour, aligned by the Xbox HUD tag offsets. --><path transform="translate(-.25,-55) scale(.25)" d="M327.21,274.16 L339.43,274.16 L334.08,285.74 L345.32,285.74 L340.46,296.25 L329.23,296.25 L323.88,307.82 L311.66,307.82 L317.01,296.25 L305.77,296.25 L310.63,285.74 L321.86,285.74 Z" fill="none" stroke="#fff" stroke-width="3.34"/></svg>

After

Width:  |  Height:  |  Size: 443 B

+3
View File
@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path d="M8 2.7 C9.5 2.7 10.1 3.6 11.7 5.2 C13.8 7.3 13.8 8.7 11.7 10.8 C10.1 12.4 9.5 13.3 8 13.3 C6.5 13.3 5.9 12.4 4.3 10.8 C2.2 8.7 2.2 7.3 4.3 5.2 C5.9 3.6 6.5 2.7 8 2.7 Z" fill="none" stroke="#fff" stroke-width="1.3"/><circle cx="8" cy="8" r=".65" fill="#fff"/>
</svg>

After

Width:  |  Height:  |  Size: 359 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="32" viewBox="0 0 128 32"><!-- Existing meter contour, aligned by the Xbox HUD tag offsets. --><path transform="translate(-1.25,0) scale(.25)" d="M328.14,53.64 C327.98,53.7 327.27,53.81 326.57,53.89 C324.82,54.06 324.04,54.24 323.36,54.57 C323.04,54.74 322.43,54.92 322,54.99 C321.54,55.06 321,55.26 320.64,55.47 C320.32,55.69 319.77,55.91 319.41,56 C319.06,56.07 318.59,56.29 318.35,56.46 C318.12,56.62 317.66,56.91 317.31,57.07 C316.4,57.52 315.11,58.26 314.55,58.66 C313.98,59.07 313.38,59.49 312.69,59.95 C311.82,60.54 309.75,62.41 308.05,64.14 C305.23,67.03 304.94,66.88 313.35,66.88 C320.88,66.88 320.89,66.88 321.69,67.78 C322.69,68.88 322.07,70.7 320.11,72.45 C318.82,73.6 318.44,73.88 317.94,74 C317.66,74.08 317.21,74.21 316.94,74.31 C316.51,74.47 315.23,74.5 309.1,74.5 L301.76,74.5 L301.41,74.8 L301.06,75.1 L301.06,80.78 C301.06,86 301.07,86.47 301.29,86.76 C301.4,86.92 301.65,87.29 301.84,87.56 C302.36,88.36 303.52,89.61 303.99,89.91 C304.23,90.05 304.6,90.33 304.8,90.51 C305.01,90.69 305.41,90.91 305.69,91 C305.96,91.09 306.44,91.31 306.75,91.51 C307.14,91.75 307.61,91.91 308.25,92 C308.76,92.08 309.52,92.22 309.95,92.33 C310.85,92.56 315.31,92.53 315.9,92.28 C316.09,92.2 316.8,92.08 317.5,92.01 C318.32,91.92 319.09,91.75 319.73,91.51 C320.25,91.31 321.02,91.05 321.44,90.94 C321.85,90.83 322.32,90.62 322.5,90.51 C322.68,90.39 323.15,90.17 323.56,90.04 C323.98,89.9 324.59,89.61 324.93,89.39 C325.27,89.17 325.61,89 325.7,89 C325.77,89 326.12,88.81 326.46,88.58 C326.79,88.35 327.19,88.12 327.35,88.08 C327.5,88.03 327.85,87.79 328.14,87.55 C328.43,87.31 328.86,87.03 329.1,86.94 C329.34,86.84 329.71,86.6 329.94,86.41 C330.16,86.21 330.7,85.78 331.12,85.44 C331.55,85.09 332.27,84.5 332.73,84.11 C333.19,83.72 333.69,83.35 333.84,83.28 C334.29,83.03 356.52,83.06 357,83.31 C357.52,83.59 357.85,84.08 357.94,84.72 C358.05,85.56 358.25,86.14 358.56,86.56 C358.73,86.76 358.96,87.16 359.1,87.44 C359.59,88.41 362.02,90.66 362.93,90.96 C363.2,91.06 363.73,91.31 364.07,91.51 C364.48,91.74 365.02,91.91 365.59,92 C366.06,92.06 366.82,92.2 367.26,92.31 C368.39,92.58 372.21,92.58 373.09,92.31 C373.45,92.2 374.31,92.06 375.01,92 C375.98,91.91 376.49,91.79 377.11,91.5 C377.56,91.3 378.21,91.08 378.56,91 C378.9,90.92 379.46,90.7 379.81,90.5 C380.15,90.31 380.68,90.09 380.95,90.01 C381.24,89.94 381.69,89.72 381.95,89.54 C382.23,89.36 382.73,89.1 383.06,88.97 C383.41,88.84 383.8,88.62 383.94,88.5 C384.07,88.38 384.41,88.16 384.69,88.03 C385.29,87.72 386.39,87.03 387.06,86.5 C387.34,86.29 387.93,85.84 388.38,85.5 C390.16,84.12 390.45,83.89 391.68,82.69 C392.38,82 393.1,81.24 393.27,81 C393.45,80.76 393.9,80.21 394.26,79.79 C395.91,77.88 396.15,77.44 395.73,77.16 C395.64,77.11 392.55,77.09 388.88,77.1 C380.81,77.15 381.38,77.22 379.48,75.75 C378.15,74.72 380.57,71.14 383.59,69.69 L384.75,69.12 L392.12,69.12 C400.81,69.12 399.93,69.31 400.06,67.42 C400.29,64.56 400,61.07 399.49,60.36 C399.36,60.19 399.16,59.79 399.04,59.49 C398.38,57.86 396.06,55.59 394.45,54.96 C394.1,54.84 393.69,54.64 393.51,54.51 C393.05,54.19 392.45,54.04 391.35,53.94 C390.81,53.9 390.15,53.79 389.86,53.69 C389.12,53.42 385.86,53.42 385.11,53.69 C384.81,53.8 383.94,53.94 383.15,54 C382.01,54.09 381.56,54.19 380.9,54.49 C380.44,54.69 379.69,54.94 379.23,55.04 C378.76,55.15 378.16,55.39 377.88,55.56 C377.6,55.74 377.19,55.91 376.96,55.96 C376.5,56.05 375.94,56.31 375.51,56.64 C375.35,56.77 375,56.94 374.74,57 C374.48,57.07 374.1,57.27 373.9,57.44 C373.7,57.61 373.26,57.86 372.94,58 C372.6,58.14 372.15,58.42 371.91,58.62 C371.69,58.84 371.44,59 371.38,59 C371.3,59 371.04,59.2 370.76,59.44 C370.5,59.67 370.01,60 369.68,60.15 L369.06,60.44 L355.8,60.47 L342.54,60.5 L342.31,60.24 C342.18,60.1 341.96,59.8 341.81,59.56 C341.15,58.47 340.79,58 340.07,57.26 C339.18,56.34 337.55,55 337.31,55 C337.23,55 336.74,54.8 336.24,54.56 C335.55,54.24 334.98,54.09 334,53.95 C333.27,53.85 332.43,53.7 332.12,53.64 C331.43,53.47 328.54,53.47 328.14,53.64 Z M327.19,57.01 C326.71,57.07 326.04,57.21 325.69,57.3 C323.85,57.82 322.59,58.25 322.23,58.47 C322,58.61 321.48,58.82 321.06,58.94 C320.65,59.06 320,59.34 319.62,59.56 C319.25,59.79 318.51,60.21 318,60.5 C315.26,62.07 314.46,62.82 314.99,63.3 C315.18,63.48 315.61,63.5 317.89,63.5 C321.77,63.5 322.84,63.8 324.21,65.22 C325.81,66.88 325.89,70.24 324.4,72.69 C323.9,73.5 321.79,75.65 321.19,75.96 C320.99,76.08 320.61,76.31 320.38,76.5 C320.14,76.69 319.71,76.91 319.44,77 C319.16,77.09 318.6,77.3 318.19,77.49 L317.44,77.81 L310.88,77.84 C304.71,77.86 304.3,77.88 304,78.1 C302.6,79.12 303.02,83.61 304.74,85.89 C305.91,87.45 307.93,88.69 309.79,89.01 C311.21,89.25 316.19,89.09 317.31,88.78 C319.38,88.19 320.96,87.66 321.25,87.46 C321.43,87.35 321.81,87.17 322.12,87.06 C322.43,86.95 322.94,86.71 323.25,86.51 C323.56,86.33 324.01,86.09 324.25,86 C324.49,85.9 324.85,85.69 325.05,85.53 C325.26,85.36 325.71,85.1 326.07,84.94 C326.43,84.79 326.76,84.59 326.81,84.51 C326.85,84.42 327.11,84Line truncated

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

+10 -4
View File
@@ -1,11 +1,17 @@
# Lucide icons
Two icons of [Lucide](https://lucide.dev) 1.53.0 (ISC licence: `LICENSE`),
Four icons of [Lucide](https://lucide.dev) 1.53.0 (ISC licence: `LICENSE`),
as `icons/` has them at the `1.53.0` tag of
https://github.com/lucide-icons/lucide:
- `volume-2.svg`: voice chat's speaker, of a player who talks;
- `volume-x.svg`: ... of a player muted.
- `volume-x.svg`: ... of a player muted;
- `triangle-alert.svg`: the Mods menu's sign of a mod that loads on the
wrong side of a mod it asks to load before or after;
- `circle-x.svg`: ... of a mod that cannot be played, or that another mod
says it cannot be played with.
`tools/ce_menus.py` draws them, white, as the menus' bitmap `voice/speaker`
(port/linux/game/network_voice.c tints it). Credited in `AUTHORS.md`.
`tools/ce_menus.py` draws the first two, white, as the menus' bitmap
`voice/speaker` (port/linux/game/network_voice.c tints it), and the others,
amber and red, as `mods/status` and the smaller `mods/status_small`
(`tools/port_settings.py`). Credited in `AUTHORS.md`.
+15
View File
@@ -0,0 +1,15 @@
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<circle cx="12" cy="12" r="10" />
<path d="m15 9-6 6" />
<path d="m9 9 6 6" />
</svg>

After

Width:  |  Height:  |  Size: 293 B

@@ -0,0 +1,15 @@
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" />
<path d="M12 9v4" />
<path d="M12 17h.01" />
</svg>

After

Width:  |  Height:  |  Size: 345 B

+1 -1
View File
@@ -62,7 +62,7 @@ until it is redrawn.
| `ce/shell/main_menu/settings_select/player_setup/player_profile_edit/profile_options__6.png` | 512x256 | `shell/main_menu/settings_select/player_setup/player_profile_edit/profile_options__6.png` |
| `ce/shell/main_menu/settings_select/player_setup/player_profile_edit/profile_options__8.png` | 512x256 | `shell/main_menu/settings_select/player_setup/player_profile_edit/profile_options__8.png` |
13 of 164 frames are placeholders.
13 of 177 frames are placeholders.
The PC version's `ui\gamespy` and `ui\ticker` fonts are drawn with `ui\small_ui`, which
the Xbox's map has.
+2 -2
View File
@@ -10,7 +10,7 @@ do (save a setting, join a game) does not happen; the screens open and close as
| Function | Uses | |
| --- | --- | --- |
| `common button bar update` | 27 | PC function |
| `common button bar update` | 28 | PC function |
| `direct ip connect init` | 1 | PC function |
| `direct ip connect update` | 1 | PC function |
| `direct ip edit field` | 4 | PC function |
@@ -21,7 +21,7 @@ do (save a setting, join a game) does not happen; the screens open and close as
| `gamespy update filter settings` | 2 | PC function |
| `gt edit list update` | 1 | PC function |
| `gt select list update` | 1 | PC function |
| `mouse spinner 1wide click` | 82 | PC function |
| `mouse spinner 1wide click` | 84 | PC function |
| `mp map list update` | 1 | PC function |
| `mp prof init teamplay options` | 1 | PC function |
| `mp prof init vehicle options` | 1 | PC function |
+26
View File
@@ -314,6 +314,9 @@
<bitmap name="main_menu/solo_level_select/header_load_level">
<frame png="ce/shell/main_menu/solo_level_select/header_load_level__0.png" width="512" height="64"/>
</bitmap>
<bitmap name="main_menu/mods/header_mods">
<frame png="ce/port/main_menu/mods/header_mods.png" width="512" height="64"/>
</bitmap>
<bitmap name="main_menu/multiplayer_type_select/coop/header_player_2">
<frame png="ce/port/main_menu/multiplayer_type_select/coop/header_player_2.png" width="512" height="64"/>
</bitmap>
@@ -356,10 +359,33 @@
<frame png="ce/port/pause/pausebox_right__1.png" width="16" height="256"/>
<frame png="ce/port/pause/pausebox_right__2.png" width="16" height="256"/>
</bitmap>
<bitmap name="pause/objectives_left">
<frame png="ce/port/pause/objectives_left__0.png" width="16" height="256"/>
</bitmap>
<bitmap name="pause/objectives_center">
<frame png="ce/port/pause/objectives_center__0.png" width="4" height="256"/>
</bitmap>
<bitmap name="pause/objectives_right">
<frame png="ce/port/pause/objectives_right__0.png" width="16" height="256"/>
</bitmap>
<bitmap name="voice/speaker">
<frame png="ce/port/voice/speaker__0.png" width="24" height="24"/>
<frame png="ce/port/voice/speaker__1.png" width="24" height="24"/>
</bitmap>
<bitmap name="main_menu/menu_mods">
<frame png="ce/port/main_menu/menu_mods__0.png" width="256" height="64"/>
<frame png="ce/port/main_menu/menu_mods__1.png" width="256" height="64"/>
</bitmap>
<bitmap name="mods/status">
<frame png="ce/port/mods/status__0.png" width="24" height="24"/>
<frame png="ce/port/mods/status__1.png" width="24" height="24"/>
<frame png="ce/port/mods/status__2.png" width="24" height="24"/>
</bitmap>
<bitmap name="mods/status_small">
<frame png="ce/port/mods/status_small__0.png" width="16" height="16"/>
<frame png="ce/port/mods/status_small__1.png" width="16" height="16"/>
<frame png="ce/port/mods/status_small__2.png" width="16" height="16"/>
</bitmap>
<bitmap name="blank">
<frame png="ce/port/blank__0.png" width="4" height="4"/>
</bitmap>
+183
View File
@@ -0,0 +1,183 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- The port's Mods screen, in the PC version's style (tools/port_settings.py) -->
<menus>
<widget name="main_menu/main_menu_item_mods" type="text" width="256" height="33" bitmap="main_menu/menu_mods">
<on event="a" open="main_menu/mods/mods_screen"/>
<on event="start" open="main_menu/mods/mods_screen"/>
<on event="left_mouse" run="mouse emit accept event"/>
</widget>
<widget name="main_menu/mods/mods_screen" width="640" height="480" flags="pass_unhandled_to_focused_child pause_game" bitmap="bitmaps/gradient">
<on event="b" back="true"/>
<on event="back" back="true"/>
<child widget="main_menu/new_select/sel_list_desc_bkd"/>
<child widget="main_menu/mods/mods_list"/>
<child widget="main_menu/mods/header_mods"/>
</widget>
<widget name="main_menu/mods/header_mods" controller="1" left="35" top="11" width="363" height="59" bitmap="main_menu/mods/header_mods">
</widget>
<widget name="main_menu/mods/mods_list" type="column_list" width="640" height="480" flags="pass_unhandled_to_focused_child up_down_tabs_children" description="main_menu/mods/mod_details">
<data input="port mods update"/>
<on event="created" run="port mods init"/>
<on event="deleted" run="port mods close"/>
<child widget="main_menu/mods/op_mod_1" x="20" y="73"/>
<child widget="main_menu/mods/op_mod_2" x="20" y="103"/>
<child widget="main_menu/mods/op_mod_3" x="20" y="133"/>
<child widget="main_menu/mods/op_mod_4" x="20" y="163"/>
<child widget="main_menu/mods/op_mod_5" x="20" y="193"/>
<child widget="main_menu/mods/op_mod_6" x="20" y="223"/>
<child widget="main_menu/mods/op_mod_7" x="20" y="253"/>
<child widget="main_menu/mods/op_mod_8" x="20" y="283"/>
<child widget="main_menu/mods/op_mod_9" x="20" y="313"/>
<child widget="main_menu/mods/op_mod_10" x="20" y="343"/>
<child widget="main_menu/mods/op_mod_11" x="20" y="373"/>
<child widget="main_menu/mods/button_bar" y="414"/>
</widget>
<widget name="main_menu/mods/op_mod_1" width="390" height="28" flags="pass_unhandled_to_focused_child" bitmap="bitmaps/sel_list_item_bkd_top" color="#FF2896FF">
<on event="a" run="port mods toggle"/>
<on event="start" run="port mods toggle"/>
<on event="left" run="port mods move up"/>
<on event="right" run="port mods move down"/>
<on event="left_mouse" run="mouse emit accept event"/>
<child widget="main_menu/mods/mod_status" x="8" y="2"/>
<child widget="main_menu/mods/mod_name" x="34"/>
<child widget="main_menu/mods/mod_state" x="318"/>
</widget>
<widget name="main_menu/mods/op_mod_2" width="390" height="28" flags="pass_unhandled_to_focused_child" bitmap="bitmaps/sel_list_item_bkd" color="#FF2896FF">
<on event="a" run="port mods toggle"/>
<on event="start" run="port mods toggle"/>
<on event="left" run="port mods move up"/>
<on event="right" run="port mods move down"/>
<on event="left_mouse" run="mouse emit accept event"/>
<child widget="main_menu/mods/mod_status" x="8" y="2"/>
<child widget="main_menu/mods/mod_name" x="34"/>
<child widget="main_menu/mods/mod_state" x="318"/>
</widget>
<widget name="main_menu/mods/op_mod_3" width="390" height="28" flags="pass_unhandled_to_focused_child" bitmap="bitmaps/sel_list_item_bkd" color="#FF2896FF">
<on event="a" run="port mods toggle"/>
<on event="start" run="port mods toggle"/>
<on event="left" run="port mods move up"/>
<on event="right" run="port mods move down"/>
<on event="left_mouse" run="mouse emit accept event"/>
<child widget="main_menu/mods/mod_status" x="8" y="2"/>
<child widget="main_menu/mods/mod_name" x="34"/>
<child widget="main_menu/mods/mod_state" x="318"/>
</widget>
<widget name="main_menu/mods/op_mod_4" width="390" height="28" flags="pass_unhandled_to_focused_child" bitmap="bitmaps/sel_list_item_bkd" color="#FF2896FF">
<on event="a" run="port mods toggle"/>
<on event="start" run="port mods toggle"/>
<on event="left" run="port mods move up"/>
<on event="right" run="port mods move down"/>
<on event="left_mouse" run="mouse emit accept event"/>
<child widget="main_menu/mods/mod_status" x="8" y="2"/>
<child widget="main_menu/mods/mod_name" x="34"/>
<child widget="main_menu/mods/mod_state" x="318"/>
</widget>
<widget name="main_menu/mods/op_mod_5" width="390" height="28" flags="pass_unhandled_to_focused_child" bitmap="bitmaps/sel_list_item_bkd" color="#FF2896FF">
<on event="a" run="port mods toggle"/>
<on event="start" run="port mods toggle"/>
<on event="left" run="port mods move up"/>
<on event="right" run="port mods move down"/>
<on event="left_mouse" run="mouse emit accept event"/>
<child widget="main_menu/mods/mod_status" x="8" y="2"/>
<child widget="main_menu/mods/mod_name" x="34"/>
<child widget="main_menu/mods/mod_state" x="318"/>
</widget>
<widget name="main_menu/mods/op_mod_6" width="390" height="28" flags="pass_unhandled_to_focused_child" bitmap="bitmaps/sel_list_item_bkd" color="#FF2896FF">
<on event="a" run="port mods toggle"/>
<on event="start" run="port mods toggle"/>
<on event="left" run="port mods move up"/>
<on event="right" run="port mods move down"/>
<on event="left_mouse" run="mouse emit accept event"/>
<child widget="main_menu/mods/mod_status" x="8" y="2"/>
<child widget="main_menu/mods/mod_name" x="34"/>
<child widget="main_menu/mods/mod_state" x="318"/>
</widget>
<widget name="main_menu/mods/op_mod_7" width="390" height="28" flags="pass_unhandled_to_focused_child" bitmap="bitmaps/sel_list_item_bkd" color="#FF2896FF">
<on event="a" run="port mods toggle"/>
<on event="start" run="port mods toggle"/>
<on event="left" run="port mods move up"/>
<on event="right" run="port mods move down"/>
<on event="left_mouse" run="mouse emit accept event"/>
<child widget="main_menu/mods/mod_status" x="8" y="2"/>
<child widget="main_menu/mods/mod_name" x="34"/>
<child widget="main_menu/mods/mod_state" x="318"/>
</widget>
<widget name="main_menu/mods/op_mod_8" width="390" height="28" flags="pass_unhandled_to_focused_child" bitmap="bitmaps/sel_list_item_bkd" color="#FF2896FF">
<on event="a" run="port mods toggle"/>
<on event="start" run="port mods toggle"/>
<on event="left" run="port mods move up"/>
<on event="right" run="port mods move down"/>
<on event="left_mouse" run="mouse emit accept event"/>
<child widget="main_menu/mods/mod_status" x="8" y="2"/>
<child widget="main_menu/mods/mod_name" x="34"/>
<child widget="main_menu/mods/mod_state" x="318"/>
</widget>
<widget name="main_menu/mods/op_mod_9" width="390" height="28" flags="pass_unhandled_to_focused_child" bitmap="bitmaps/sel_list_item_bkd" color="#FF2896FF">
<on event="a" run="port mods toggle"/>
<on event="start" run="port mods toggle"/>
<on event="left" run="port mods move up"/>
<on event="right" run="port mods move down"/>
<on event="left_mouse" run="mouse emit accept event"/>
<child widget="main_menu/mods/mod_status" x="8" y="2"/>
<child widget="main_menu/mods/mod_name" x="34"/>
<child widget="main_menu/mods/mod_state" x="318"/>
</widget>
<widget name="main_menu/mods/op_mod_10" width="390" height="28" flags="pass_unhandled_to_focused_child" bitmap="bitmaps/sel_list_item_bkd" color="#FF2896FF">
<on event="a" run="port mods toggle"/>
<on event="start" run="port mods toggle"/>
<on event="left" run="port mods move up"/>
<on event="right" run="port mods move down"/>
<on event="left_mouse" run="mouse emit accept event"/>
<child widget="main_menu/mods/mod_status" x="8" y="2"/>
<child widget="main_menu/mods/mod_name" x="34"/>
<child widget="main_menu/mods/mod_state" x="318"/>
</widget>
<widget name="main_menu/mods/op_mod_11" width="390" height="28" flags="pass_unhandled_to_focused_child" bitmap="bitmaps/sel_list_item_bkd" color="#FF2896FF">
<on event="a" run="port mods toggle"/>
<on event="start" run="port mods toggle"/>
<on event="left" run="port mods move up"/>
<on event="right" run="port mods move down"/>
<on event="left_mouse" run="mouse emit accept event"/>
<child widget="main_menu/mods/mod_status" x="8" y="2"/>
<child widget="main_menu/mods/mod_name" x="34"/>
<child widget="main_menu/mods/mod_state" x="318"/>
</widget>
<widget name="main_menu/mods/mod_status" controller="1" width="24" height="24" bitmap="mods/status">
</widget>
<widget name="main_menu/mods/mod_name" type="text" controller="1" width="284" height="22" font="ui\large_ui" color="#FF2896FF" text_y="4">
</widget>
<widget name="main_menu/mods/mod_state" type="text" controller="1" width="66" height="22" font="ui\large_ui" color="#FF2896FF" align="center" text_y="4" text_flags="no_focus_test">
</widget>
<widget name="main_menu/mods/mod_details" width="640" height="480">
<child widget="main_menu/mods/mod_details_name"/>
<child widget="main_menu/mods/mod_details_status"/>
<child widget="main_menu/mods/mod_details_text"/>
</widget>
<widget name="main_menu/mods/mod_details_name" type="text" controller="1" left="412" top="84" width="200" height="44" font="ui\large_ui" color="#FFFFFFFF">
</widget>
<widget name="main_menu/mods/mod_details_status" controller="1" left="411" top="132" width="16" height="16" bitmap="mods/status_small">
</widget>
<widget name="main_menu/mods/mod_details_text" type="text" controller="1" left="412" top="130" width="200" height="272" font="ui\small_ui" color="#FF2896FF">
</widget>
<widget name="main_menu/mods/button_bar" type="column_list" width="640" height="28" flags="pass_unhandled_to_focused_child left_right_tabs_items">
<child widget="main_menu/mods/button_up" y="1"/>
<child widget="main_menu/mods/button_down" x="130" y="1"/>
<child widget="main_menu/mods/button_ok" x="380" y="1"/>
<child widget="common_button_cancel" x="510" y="1"/>
</widget>
<widget name="main_menu/mods/button_up" type="text" width="128" height="24" bitmap="bitmaps/text_button_background" text="MOVE UP" font="ui\small_ui" color="#FFFFFFFF" align="center" text_y="2">
<on event="a" run="port mods move up"/>
<on event="start" run="port mods move up"/>
<on event="left_mouse" run="mouse emit accept event"/>
</widget>
<widget name="main_menu/mods/button_down" type="text" width="128" height="24" bitmap="bitmaps/text_button_background" text="MOVE DOWN" font="ui\small_ui" color="#FFFFFFFF" align="center" text_y="2">
<on event="a" run="port mods move down"/>
<on event="start" run="port mods move down"/>
<on event="left_mouse" run="mouse emit accept event"/>
</widget>
<widget name="main_menu/mods/button_ok" type="text" width="128" height="24" bitmap="bitmaps/text_button_background" string_list="strings/common_button_captions" string_index="1" font="ui\small_ui" color="#FFFFFFFF" align="center" text_y="2">
<on event="a" run="port mods save" back="true"/>
<on event="start" run="port mods save" back="true"/>
<on event="left_mouse" run="mouse emit accept event"/>
</widget>
</menus>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- The PC version's menus: ui\shell\main_menu\multiplayer_type_select\connected (tools/ce_menus.py) -->
<menus>
<widget name="main_menu/multiplayer_type_select/connected/connected_map_select_wrapper" width="640" height="480" flags="pass_unhandled_to_focused_child pause_game tag_controller_index force_handle_mouse">
<widget name="main_menu/multiplayer_type_select/connected/connected_map_select_wrapper" width="640" height="480" flags="pass_unhandled_to_focused_child pause_game main_menu_if_no_history tag_controller_index force_handle_mouse">
<child widget="main_menu/multiplayer_type_select/mp_map_select/mp_map_select_screen"/>
</widget>
<widget name="main_menu/multiplayer_type_select/connected/gametype_select_screen_wrapper" width="640" height="480" flags="pass_unhandled_to_focused_child pause_game">
@@ -60,13 +60,13 @@
<child widget="main_menu/multiplayer_type_select/multiplayer_type_create_internet_item" y="243"/>
<child widget="main_menu/multiplayer_type_select/multiplayer_type_create_lan_item" y="276"/>
<child widget="main_menu/multiplayer_type_select/multiplayer_type_coop_item" y="309"/>
<child widget="main_menu/multiplayer_type_select/multiplayer_type_gametypes_item" y="375"/>
<child widget="main_menu/multiplayer_type_select/multiplayer_type_gametypes_item" y="358"/>
<child widget="main_menu/multiplayer_type_select/multiplayer_type_button_bar" y="414"/>
</widget>
<widget name="main_menu/multiplayer_type_select/multiplayer_type_select_screen" width="640" height="480" flags="pass_unhandled_to_focused_child" bitmap="bitmaps/gradient">
<on event="created" run="mp type menu initialize"/>
<child widget="main_menu/multiplayer_type_select/header_multiplayer"/>
<child widget="main_menu/multiplayer_type_select/multiplayer_type_select_list"/>
<child widget="main_menu/blueline" x="64" y="358"/>
<child widget="main_menu/blueline" x="64" y="349"/>
</widget>
</menus>
@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- The port's settings screen, in the PC version's style (tools/port_settings.py) -->
<menus>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/sound_processing_settings_screen" width="640" height="480" flags="pass_unhandled_to_focused_child pause_game" bitmap="bitmaps/gradient">
<on event="b" back="true"/>
<on event="back" back="true"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/header_profile_audio_settings"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/options_menu"/>
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/header_profile_audio_settings" controller="1" left="35" top="11" width="605" height="59" bitmap="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/header_profile_audio_settings">
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/help" type="text" controller="1" left="68" top="350" width="482" height="60" string_list="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/help_strings" font="ui\large_ui" color="#FFFFFFFF">
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/options_menu" type="column_list" width="640" height="480" flags="pass_unhandled_to_focused_child up_down_tabs_children" description="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/help">
<data input="port settings help"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/op_reverb" x="54" y="73"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/op_resampler" x="54" y="103"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/button_bar" y="414"/>
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/button_bar" type="column_list" width="640" height="28" flags="pass_unhandled_to_focused_child left_right_tabs_items">
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/button_defaults" y="1"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/button_ok" x="380" y="1"/>
<child widget="common_button_cancel" x="510" y="1"/>
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/op_reverb" width="512" height="28" flags="pass_unhandled_to_focused_child" bitmap="bitmaps/option_bkds" color="#FF2896FF">
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/reverb_label"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/reverb_spinner" x="320" y="1"/>
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/reverb_label" type="text" controller="1" width="300" height="22" string_list="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/labels" string_index="0" font="ui\large_ui" color="#FF2896FF" text_x="13" text_y="4">
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/reverb_spinner" type="spinner" left="3" top="2" width="147" height="20" flags="pass_unhandled_to_focused_child left_right_tabs_items" strings="ON|OFF" setting="audio.reverb" values="true|false" font="ui\large_ui" color="#FF2896FF" align="center" text_y="1" header_bitmap="bitmaps/arrow_sm_left" footer_bitmap="bitmaps/arrow_sm_right" header_bounds="7 -6 19 0" footer_bounds="7 150 19 156">
<on event="created" run="port setting load"/>
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/op_resampler" width="512" height="28" flags="pass_unhandled_to_focused_child" bitmap="bitmaps/option_bkds" color="#FF2896FF">
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/resampler_label"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/resampler_spinner" x="320" y="1"/>
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/resampler_label" type="text" controller="1" width="300" height="22" string_list="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/labels" string_index="1" font="ui\large_ui" color="#FF2896FF" text_x="13" text_y="4">
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/resampler_spinner" type="spinner" left="3" top="2" width="147" height="20" flags="pass_unhandled_to_focused_child left_right_tabs_items" strings="SINC|LINEAR" setting="audio.resampler" values="sinc|linear" font="ui\large_ui" color="#FF2896FF" align="center" text_y="1" header_bitmap="bitmaps/arrow_sm_left" footer_bitmap="bitmaps/arrow_sm_right" header_bounds="7 -6 19 0" footer_bounds="7 150 19 156">
<on event="created" run="port setting load"/>
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/button_defaults" type="text" width="128" height="24" bitmap="bitmaps/text_button_background" string_list="strings/common_button_captions" string_index="3" font="ui\small_ui" color="#FFFFFFFF" align="center" text_y="2">
<on event="a" run="port settings defaults"/>
<on event="start" run="port settings defaults"/>
<on event="left_mouse" run="mouse emit accept event"/>
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/button_ok" type="text" width="128" height="24" bitmap="bitmaps/text_button_background" string_list="strings/common_button_captions" string_index="1" font="ui\small_ui" color="#FFFFFFFF" align="center" text_y="2">
<on event="a" run="port settings save" back="true"/>
<on event="start" run="port settings save" back="true"/>
<on event="left_mouse" run="mouse emit accept event"/>
</widget>
<strings name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/labels">
<string text="REVERB:"/>
<string text="RESAMPLER:"/>
</strings>
<strings name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/help_strings">
<string text=""/>
<string text="Echo sounds as the place you are in does, and\nmuffle those behind walls, as the Xbox did."/>
<string text="How sounds are converted to the output's rate:\nsinc is clean; linear is brighter, with aliasing."/>
</strings>
</menus>
@@ -21,14 +21,14 @@
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/op_music_volume" x="54" y="103" platform="android web"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/op_effects_volume" x="54" y="193" platform="desktop"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/op_effects_volume" x="54" y="133" platform="android web"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/op_reverb" x="54" y="223" platform="desktop"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/op_reverb" x="54" y="163" platform="android web"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/op_enabled" x="54" y="253" platform="desktop"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/op_enabled" x="54" y="193" platform="android web"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/op_voice_chat" x="54" y="283" platform="desktop"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/op_voice_chat" x="54" y="223" platform="android web"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/op_voice_volume" x="54" y="313" platform="desktop"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/op_voice_volume" x="54" y="253" platform="android web"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/op_enabled" x="54" y="223" platform="desktop"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/op_enabled" x="54" y="163" platform="android web"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/op_voice_chat" x="54" y="253" platform="desktop"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/op_voice_chat" x="54" y="193" platform="android web"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/op_voice_volume" x="54" y="283" platform="desktop"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/op_voice_volume" x="54" y="223" platform="android web"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/op_sound_processing" x="54" y="313" platform="desktop"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/op_sound_processing" x="54" y="253" platform="android web"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/button_bar" y="414"/>
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/button_bar" type="column_list" width="640" height="28" flags="pass_unhandled_to_focused_child left_right_tabs_items">
@@ -81,20 +81,11 @@
<widget name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/effects_volume_spinner" type="spinner" left="3" top="2" width="147" height="20" flags="pass_unhandled_to_focused_child left_right_tabs_items" strings="0|1|2|3|4|5|6|7|8|9|10" setting="audio.effects_volume" values="0|0.1|0.2|0.3|0.4|0.5|0.6|0.7|0.8|0.9|1" font="ui\large_ui" color="#FF2896FF" align="center" text_y="1" header_bitmap="bitmaps/arrow_sm_left" footer_bitmap="bitmaps/arrow_sm_right" header_bounds="7 -6 19 0" footer_bounds="7 150 19 156">
<on event="created" run="port setting load"/>
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/op_reverb" width="512" height="28" flags="pass_unhandled_to_focused_child" bitmap="bitmaps/option_bkds" color="#FF2896FF">
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/reverb_label"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/reverb_spinner" x="320" y="1"/>
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/reverb_label" type="text" controller="1" width="300" height="22" string_list="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/labels" string_index="5" font="ui\large_ui" color="#FF2896FF" text_x="13" text_y="4">
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/reverb_spinner" type="spinner" left="3" top="2" width="147" height="20" flags="pass_unhandled_to_focused_child left_right_tabs_items" strings="ON|OFF" setting="audio.reverb" values="true|false" font="ui\large_ui" color="#FF2896FF" align="center" text_y="1" header_bitmap="bitmaps/arrow_sm_left" footer_bitmap="bitmaps/arrow_sm_right" header_bounds="7 -6 19 0" footer_bounds="7 150 19 156">
<on event="created" run="port setting load"/>
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/op_enabled" width="512" height="28" flags="pass_unhandled_to_focused_child" bitmap="bitmaps/option_bkds" color="#FF2896FF">
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/enabled_label"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/enabled_spinner" x="320" y="1"/>
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/enabled_label" type="text" controller="1" width="300" height="22" string_list="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/labels" string_index="6" font="ui\large_ui" color="#FF2896FF" text_x="13" text_y="4">
<widget name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/enabled_label" type="text" controller="1" width="300" height="22" string_list="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/labels" string_index="5" font="ui\large_ui" color="#FF2896FF" text_x="13" text_y="4">
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/enabled_spinner" type="spinner" left="3" top="2" width="147" height="20" flags="pass_unhandled_to_focused_child left_right_tabs_items" strings="ON|OFF" setting="audio.enabled" values="true|false" font="ui\large_ui" color="#FF2896FF" align="center" text_y="1" header_bitmap="bitmaps/arrow_sm_left" footer_bitmap="bitmaps/arrow_sm_right" header_bounds="7 -6 19 0" footer_bounds="7 150 19 156">
<on event="created" run="port setting load"/>
@@ -103,7 +94,7 @@
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/voice_chat_label"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/voice_chat_spinner" x="320" y="1"/>
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/voice_chat_label" type="text" controller="1" width="300" height="22" string_list="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/labels" string_index="7" font="ui\large_ui" color="#FF2896FF" text_x="13" text_y="4">
<widget name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/voice_chat_label" type="text" controller="1" width="300" height="22" string_list="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/labels" string_index="6" font="ui\large_ui" color="#FF2896FF" text_x="13" text_y="4">
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/voice_chat_spinner" type="spinner" left="3" top="2" width="147" height="20" flags="pass_unhandled_to_focused_child left_right_tabs_items" strings="PUSH TO TALK|OPEN MIC|OFF" setting="audio.voice_chat" values="push_to_talk|open_mic|off" font="ui\large_ui" color="#FF2896FF" align="center" text_y="1" header_bitmap="bitmaps/arrow_sm_left" footer_bitmap="bitmaps/arrow_sm_right" header_bounds="7 -6 19 0" footer_bounds="7 150 19 156">
<on event="created" run="port setting load"/>
@@ -112,11 +103,19 @@
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/voice_volume_label"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/voice_volume_spinner" x="320" y="1"/>
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/voice_volume_label" type="text" controller="1" width="300" height="22" string_list="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/labels" string_index="8" font="ui\large_ui" color="#FF2896FF" text_x="13" text_y="4">
<widget name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/voice_volume_label" type="text" controller="1" width="300" height="22" string_list="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/labels" string_index="7" font="ui\large_ui" color="#FF2896FF" text_x="13" text_y="4">
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/voice_volume_spinner" type="spinner" left="3" top="2" width="147" height="20" flags="pass_unhandled_to_focused_child left_right_tabs_items" strings="0|1|2|3|4|5|6|7|8|9|10" setting="audio.voice_volume" values="0|0.1|0.2|0.3|0.4|0.5|0.6|0.7|0.8|0.9|1" font="ui\large_ui" color="#FF2896FF" align="center" text_y="1" header_bitmap="bitmaps/arrow_sm_left" footer_bitmap="bitmaps/arrow_sm_right" header_bounds="7 -6 19 0" footer_bounds="7 150 19 156">
<on event="created" run="port setting load"/>
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/op_sound_processing" width="512" height="28" flags="pass_unhandled_to_focused_child" bitmap="bitmaps/option_bkds" color="#FF2896FF">
<on event="a" open="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/sound_processing_settings_screen"/>
<on event="start" open="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing/sound_processing_settings_screen"/>
<on event="left_mouse" run="mouse emit accept event"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing_label"/>
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/sound_processing_label" type="text" controller="1" width="512" height="22" string_list="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/labels" string_index="8" font="ui\large_ui" color="#FF2896FF" text_x="13" text_y="4">
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/button_defaults" type="text" width="128" height="24" bitmap="bitmaps/text_button_background" string_list="strings/common_button_captions" string_index="3" font="ui\small_ui" color="#FFFFFFFF" align="center" text_y="2">
<on event="a" run="port settings defaults"/>
<on event="start" run="port settings defaults"/>
@@ -133,10 +132,10 @@
<string text="MASTER VOLUME:"/>
<string text="MUSIC VOLUME:"/>
<string text="EFFECTS VOLUME:"/>
<string text="REVERB:"/>
<string text="SOUND:"/>
<string text="VOICE CHAT:"/>
<string text="VOICE VOLUME:"/>
<string text="SOUND PROCESSING:"/>
</strings>
<strings name="main_menu/settings_select/player_setup/player_profile_edit/audio_settings/help_strings">
<string text=""/>
@@ -145,9 +144,9 @@
<string text="The volume of everything."/>
<string text="The music's volume."/>
<string text="The volume of every other sound: effects and\nspeech."/>
<string text="Echo sounds as the place you are in does, and\nmuffle those behind walls, as the Xbox did."/>
<string text="Play sound at all; from the next time the game\nstarts."/>
<string text="Talk in network games: while PUSH TO TALK is held\n(Controls), whenever you speak, or never."/>
<string text="The other players' voices."/>
<string text="The reverb, and how sounds are converted to the\noutput's rate."/>
</strings>
</menus>
@@ -14,13 +14,14 @@
<widget name="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/options_menu" type="column_list" width="640" height="480" flags="pass_unhandled_to_focused_child up_down_tabs_children" description="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/help">
<data input="port settings help"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/op_high_res_hud" x="54" y="73"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/op_high_res_text" x="54" y="103"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/op_anti_aliasing" x="54" y="133" platform="desktop"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/op_anti_aliasing_android" x="54" y="133" platform="android web"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/op_shadow_resolution" x="54" y="163"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/op_per_pixel_lighting" x="54" y="193"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/op_shield_glow" x="54" y="223"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/op_shield_glow_intensity" x="54" y="253"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/op_hud_button_style" x="54" y="103"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/op_high_res_text" x="54" y="133"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/op_anti_aliasing" x="54" y="163" platform="desktop"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/op_anti_aliasing_android" x="54" y="163" platform="android web"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/op_shadow_resolution" x="54" y="193"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/op_per_pixel_lighting" x="54" y="223"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/op_shield_glow" x="54" y="253"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/op_shield_glow_intensity" x="54" y="283"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/button_bar" y="414"/>
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/button_bar" type="column_list" width="640" height="28" flags="pass_unhandled_to_focused_child left_right_tabs_items">
@@ -37,11 +38,20 @@
<widget name="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/high_res_hud_spinner" type="spinner" left="3" top="2" width="147" height="20" flags="pass_unhandled_to_focused_child left_right_tabs_items" strings="ON|OFF" setting="display.high_res_hud" values="true|false" font="ui\large_ui" color="#FF2896FF" align="center" text_y="1" header_bitmap="bitmaps/arrow_sm_left" footer_bitmap="bitmaps/arrow_sm_right" header_bounds="7 -6 19 0" footer_bounds="7 150 19 156">
<on event="created" run="port setting load"/>
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/op_hud_button_style" width="512" height="28" flags="pass_unhandled_to_focused_child" bitmap="bitmaps/option_bkds" color="#FF2896FF">
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/hud_button_style_label"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/hud_button_style_spinner" x="320" y="1"/>
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/hud_button_style_label" type="text" controller="1" width="300" height="22" string_list="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/labels" string_index="1" font="ui\large_ui" color="#FF2896FF" text_x="13" text_y="4">
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/hud_button_style_spinner" type="spinner" left="3" top="2" width="147" height="20" flags="pass_unhandled_to_focused_child left_right_tabs_items" strings="CLASSIC|GEMS|DARK GEMS" setting="display.hud_button_style" values="classic|gems|menu_gems" font="ui\large_ui" color="#FF2896FF" align="center" text_y="1" header_bitmap="bitmaps/arrow_sm_left" footer_bitmap="bitmaps/arrow_sm_right" header_bounds="7 -6 19 0" footer_bounds="7 150 19 156">
<on event="created" run="port setting load"/>
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/op_high_res_text" width="512" height="28" flags="pass_unhandled_to_focused_child" bitmap="bitmaps/option_bkds" color="#FF2896FF">
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/high_res_text_label"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/high_res_text_spinner" x="320" y="1"/>
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/high_res_text_label" type="text" controller="1" width="300" height="22" string_list="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/labels" string_index="1" font="ui\large_ui" color="#FF2896FF" text_x="13" text_y="4">
<widget name="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/high_res_text_label" type="text" controller="1" width="300" height="22" string_list="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/labels" string_index="2" font="ui\large_ui" color="#FF2896FF" text_x="13" text_y="4">
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/high_res_text_spinner" type="spinner" left="3" top="2" width="147" height="20" flags="pass_unhandled_to_focused_child left_right_tabs_items" strings="ON|OFF" setting="display.high_res_text" values="true|false" font="ui\large_ui" color="#FF2896FF" align="center" text_y="1" header_bitmap="bitmaps/arrow_sm_left" footer_bitmap="bitmaps/arrow_sm_right" header_bounds="7 -6 19 0" footer_bounds="7 150 19 156">
<on event="created" run="port setting load"/>
@@ -50,7 +60,7 @@
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/anti_aliasing_label"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/anti_aliasing_spinner" x="320" y="1"/>
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/anti_aliasing_label" type="text" controller="1" width="300" height="22" string_list="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/labels" string_index="2" font="ui\large_ui" color="#FF2896FF" text_x="13" text_y="4">
<widget name="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/anti_aliasing_label" type="text" controller="1" width="300" height="22" string_list="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/labels" string_index="3" font="ui\large_ui" color="#FF2896FF" text_x="13" text_y="4">
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/anti_aliasing_spinner" type="spinner" left="3" top="2" width="147" height="20" flags="pass_unhandled_to_focused_child left_right_tabs_items" strings="OFF|FXAA|SMAA|SSAA 2X|MSAA 2X|MSAA 4X|MSAA 8X" setting="display.anti_aliasing" values="off|fxaa|smaa|ssaa2x|msaa2x|msaa4x|msaa8x" font="ui\large_ui" color="#FF2896FF" align="center" text_y="1" header_bitmap="bitmaps/arrow_sm_left" footer_bitmap="bitmaps/arrow_sm_right" header_bounds="7 -6 19 0" footer_bounds="7 150 19 156">
<on event="created" run="port setting load"/>
@@ -59,7 +69,7 @@
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/anti_aliasing_android_label"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/anti_aliasing_android_spinner" x="320" y="1"/>
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/anti_aliasing_android_label" type="text" controller="1" width="300" height="22" string_list="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/labels" string_index="3" font="ui\large_ui" color="#FF2896FF" text_x="13" text_y="4">
<widget name="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/anti_aliasing_android_label" type="text" controller="1" width="300" height="22" string_list="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/labels" string_index="4" font="ui\large_ui" color="#FF2896FF" text_x="13" text_y="4">
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/anti_aliasing_android_spinner" type="spinner" left="3" top="2" width="147" height="20" flags="pass_unhandled_to_focused_child left_right_tabs_items" strings="OFF|FXAA|MSAA 2X|MSAA 4X" setting="display.anti_aliasing" values="off|fxaa|msaa2x|msaa4x" font="ui\large_ui" color="#FF2896FF" align="center" text_y="1" header_bitmap="bitmaps/arrow_sm_left" footer_bitmap="bitmaps/arrow_sm_right" header_bounds="7 -6 19 0" footer_bounds="7 150 19 156">
<on event="created" run="port setting load"/>
@@ -68,7 +78,7 @@
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/shadow_resolution_label"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/shadow_resolution_spinner" x="320" y="1"/>
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/shadow_resolution_label" type="text" controller="1" width="300" height="22" string_list="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/labels" string_index="4" font="ui\large_ui" color="#FF2896FF" text_x="13" text_y="4">
<widget name="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/shadow_resolution_label" type="text" controller="1" width="300" height="22" string_list="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/labels" string_index="5" font="ui\large_ui" color="#FF2896FF" text_x="13" text_y="4">
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/shadow_resolution_spinner" type="spinner" left="3" top="2" width="147" height="20" flags="pass_unhandled_to_focused_child left_right_tabs_items" strings="128|256|512|1024" setting="display.shadow_resolution" values="128|256|512|1024" font="ui\large_ui" color="#FF2896FF" align="center" text_y="1" header_bitmap="bitmaps/arrow_sm_left" footer_bitmap="bitmaps/arrow_sm_right" header_bounds="7 -6 19 0" footer_bounds="7 150 19 156">
<on event="created" run="port setting load"/>
@@ -77,7 +87,7 @@
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/per_pixel_lighting_label"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/per_pixel_lighting_spinner" x="320" y="1"/>
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/per_pixel_lighting_label" type="text" controller="1" width="300" height="22" string_list="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/labels" string_index="5" font="ui\large_ui" color="#FF2896FF" text_x="13" text_y="4">
<widget name="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/per_pixel_lighting_label" type="text" controller="1" width="300" height="22" string_list="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/labels" string_index="6" font="ui\large_ui" color="#FF2896FF" text_x="13" text_y="4">
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/per_pixel_lighting_spinner" type="spinner" left="3" top="2" width="147" height="20" flags="pass_unhandled_to_focused_child left_right_tabs_items" strings="ON|OFF" setting="display.per_pixel_lighting" values="true|false" font="ui\large_ui" color="#FF2896FF" align="center" text_y="1" header_bitmap="bitmaps/arrow_sm_left" footer_bitmap="bitmaps/arrow_sm_right" header_bounds="7 -6 19 0" footer_bounds="7 150 19 156">
<on event="created" run="port setting load"/>
@@ -86,7 +96,7 @@
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/shield_glow_label"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/shield_glow_spinner" x="320" y="1"/>
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/shield_glow_label" type="text" controller="1" width="300" height="22" string_list="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/labels" string_index="6" font="ui\large_ui" color="#FF2896FF" text_x="13" text_y="4">
<widget name="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/shield_glow_label" type="text" controller="1" width="300" height="22" string_list="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/labels" string_index="7" font="ui\large_ui" color="#FF2896FF" text_x="13" text_y="4">
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/shield_glow_spinner" type="spinner" left="3" top="2" width="147" height="20" flags="pass_unhandled_to_focused_child left_right_tabs_items" strings="ON|OFF" setting="display.shield_glow" values="true|false" font="ui\large_ui" color="#FF2896FF" align="center" text_y="1" header_bitmap="bitmaps/arrow_sm_left" footer_bitmap="bitmaps/arrow_sm_right" header_bounds="7 -6 19 0" footer_bounds="7 150 19 156">
<on event="created" run="port setting load"/>
@@ -95,7 +105,7 @@
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/shield_glow_intensity_label"/>
<child widget="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/shield_glow_intensity_spinner" x="320" y="1"/>
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/shield_glow_intensity_label" type="text" controller="1" width="300" height="22" string_list="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/labels" string_index="7" font="ui\large_ui" color="#FF2896FF" text_x="13" text_y="4">
<widget name="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/shield_glow_intensity_label" type="text" controller="1" width="300" height="22" string_list="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/labels" string_index="8" font="ui\large_ui" color="#FF2896FF" text_x="13" text_y="4">
</widget>
<widget name="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/shield_glow_intensity_spinner" type="spinner" left="3" top="2" width="147" height="20" flags="pass_unhandled_to_focused_child left_right_tabs_items" strings="DEFAULT|LIGHT SHOW" setting="display.shield_glow_intensity" values="default|light_show" font="ui\large_ui" color="#FF2896FF" align="center" text_y="1" header_bitmap="bitmaps/arrow_sm_left" footer_bitmap="bitmaps/arrow_sm_right" header_bounds="7 -6 19 0" footer_bounds="7 150 19 156">
<on event="created" run="port setting load"/>
@@ -112,6 +122,7 @@
</widget>
<strings name="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/labels">
<string text="HIGH-RES HUD:"/>
<string text="BUTTON STYLE:"/>
<string text="HIGH-RES TEXT:"/>
<string text="ANTI-ALIASING:"/>
<string text="ANTI-ALIASING:"/>
@@ -123,6 +134,7 @@
<strings name="main_menu/settings_select/player_setup/player_profile_edit/video_settings/graphics/help_strings">
<string text=""/>
<string text="Draw the HUD from the high-res redraws; off\ndraws the game's own pictures."/>
<string text="Classic: plain Xbox buttons. Gems: shaded Xbox\nbuttons. Dark Gems: the menu's button artwork."/>
<string text="Draw text and titles with high-res fonts; off\ndraws the game's own."/>
<string text="Smooth jagged edges, which the Xbox did not. FXAA\nand SMAA are cheap; SSAA and MSAA are sharper."/>
<string text="Smooth jagged edges, which the Xbox did not. FXAA\nis cheap; MSAA is sharper."/>
+2 -1
View File
@@ -56,7 +56,8 @@
<child widget="main_menu/main_menu_item_multiplayer" x="192" y="283"/>
<child widget="main_menu/main_menu_item_profile" x="192" y="319"/>
<child widget="main_menu/main_menu_item_settings" x="192" y="355"/>
<child widget="main_menu/main_menu_item_quit_game" x="192" y="391"/>
<child widget="main_menu/main_menu_item_mods" x="192" y="391"/>
<child widget="main_menu/main_menu_item_quit_game" x="192" y="427"/>
</widget>
<widget name="main_menu/new_campaign_creating_profile" width="640" height="480" flags="pass_unhandled_to_focused_child no_history" auto_close="1">
<on event="deleted" run="new campaign decision" open="main_menu/new_campaign_saving_profile"/>
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 305 B

After

Width:  |  Height:  |  Size: 413 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 323 B

After

Width:  |  Height:  |  Size: 435 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 305 B

After

Width:  |  Height:  |  Size: 411 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

+14
View File
@@ -6,6 +6,7 @@
"ce/main_menu.campaign_select.xml",
"ce/main_menu.difficulty_select.xml",
"ce/main_menu.gametype_select.xml",
"ce/main_menu.mods.xml",
"ce/main_menu.multiplayer_type_select.connected.4way_profile_select.xml",
"ce/main_menu.multiplayer_type_select.connected.xml",
"ce/main_menu.multiplayer_type_select.coop.xml",
@@ -39,6 +40,7 @@
"ce/main_menu.settings_select.multiplayer_setup.teamplay_options_edit.xml",
"ce/main_menu.settings_select.multiplayer_setup.vehicle_options_edit.xml",
"ce/main_menu.settings_select.multiplayer_setup.xml",
"ce/main_menu.settings_select.player_setup.player_profile_edit.audio_settings.sound_processing.xml",
"ce/main_menu.settings_select.player_setup.player_profile_edit.audio_settings.xml",
"ce/main_menu.settings_select.player_setup.player_profile_edit.color_edit.xml",
"ce/main_menu.settings_select.player_setup.player_profile_edit.controls_setup.xml",
@@ -56,6 +58,9 @@
"ce/shell.xml",
"ce/strings.xml",
"ce/port/blank__0.png",
"ce/port/main_menu/menu_mods__0.png",
"ce/port/main_menu/menu_mods__1.png",
"ce/port/main_menu/mods/header_mods.png",
"ce/port/main_menu/multiplayer_type_select/coop/header_player_2.png",
"ce/port/main_menu/multiplayer_type_select/join_game/header_direct_link.png",
"ce/port/main_menu/multiplayer_type_select/join_game/header_password.png",
@@ -65,6 +70,15 @@
"ce/port/main_menu/multiplayer_type_select/server_settings/coop_options/header_coop_options.png",
"ce/port/main_menu/multiplayer_type_select/server_settings/map_share_options/header_map_share_options.png",
"ce/port/main_menu/multiplayer_type_select/server_settings/voice_options/header_voice_options.png",
"ce/port/mods/status__0.png",
"ce/port/mods/status__1.png",
"ce/port/mods/status__2.png",
"ce/port/mods/status_small__0.png",
"ce/port/mods/status_small__1.png",
"ce/port/mods/status_small__2.png",
"ce/port/pause/objectives_center__0.png",
"ce/port/pause/objectives_left__0.png",
"ce/port/pause/objectives_right__0.png",
"ce/port/pause/pausebox_center__0.png",
"ce/port/pause/pausebox_center__1.png",
"ce/port/pause/pausebox_center__2.png",
Loaded 100 of 222 files, more files were not shown because too many files have changed in this diff. Show more