# UTP
Unreal Tournament 99 on iPhone and iPad.
UTP hosts the original OldUnreal v469e game inside a native iOS app with
Metal rendering, touch controls, game-file setup, and classic online play.
Current UTP gameplay build, tested extensively on physical iPhone and iPad.
Status · Build · Controls · FAQ · Evidence · Report a problem
UTP brings the original Unreal Tournament 99 engine to iPhone and iPad by hosting the official [OldUnreal v469e](https://github.com/OldUnreal/UnrealTournamentPatches/releases/tag/v469e) ARM64 runtime inside a native iOS app. It is not streaming, emulation, or a remake: the original game still owns its menus, maps, bots, weapons, rules, and multiplayer protocol. UTP supplies the Apple-platform layer around it—Metal presentation, touch input, lifecycle, game-file setup, recovery, and diagnostics. UTP 0.1.2 is out: build your own copy with PadMint on an Apple Silicon Mac, or on [GitHub's free Mac](https://github.com/chrissotraidis/padmint#no-mac-build-on-githubs-mac) without one. See [Can I download and play UTP now?](#frequently-asked-questions) > [!NOTE] > **AI disclosure:** UTP uses substantial AI assistance for code, tests, > documentation, debugging and maintenance. Some support replies and maintenance > tasks are automated. There is no audited percentage of AI-generated code. > Build, test and device records describe what was checked. This disclosure > concerns UTP's workflow, not the authorship of its upstream projects. ## Release status | Surface | Current status | Meaning | |---|---|---| | Source repository | **Public** | Source is available from this repository. Release 0.1.2 publishes the recipe PadMint builds from; there is no prebuilt app. | | Physical iPhone/iPad | **Working and extensively tested** | UTP builds, signs, installs, launches, and runs the full game on real iPhone and iPad hardware with touch gameplay and audio. Controller play has also been exercised. | | iPhone/iPad Simulator | **Developer test path working** | The original engine reaches live bot and network sessions through FruCoRe/Metal with the native host and touch layer. | | TestFlight / App Store | **Not available** | No TestFlight build. The sideloadable developer previews have been retired. | | App Store / website install | **Not announced** | Distribution permission, Apple review/channel requirements, privacy work, and release operations remain open. | The authoritative gate ledger is [`docs/STATUS.md`](docs/STATUS.md). The requirement-by-requirement view is [`docs/COMPLETION_AUDIT.md`](docs/COMPLETION_AUDIT.md), and the underlying records are indexed in [`docs/evidence/`](docs/evidence/index.md). ## What works today Current repository evidence includes: - reproducible inspection of the official OldUnreal v469e Apple Silicon baseline and all eight recursively discovered native images; - build-time preparation of an iOS-platform ARM64 engine candidate without a runtime JIT; - a UIKit host with a full-bleed FruCoRe Metal surface on iPhone and iPad Simulator targets; - repeated physical-iPhone and physical-iPad builds with successful signing, installation, launch, gameplay, touch input, and audio; - usable touch combat and physical controller play on real hardware; - captured mouse/trackpad look with persistent speed presets, gameplay WASD, pointer buttons, and simultaneous Xbox controller input on physical iPad; - touch movement, aim, FIRE, ALT, USE, JUMP, DUCK, PREV/NEXT, SCORE, and the original Unreal menu; - editable touch layout, opacity, handedness, saved profiles, diagnostics, lifecycle recovery, keyboard/controller bridges, and a compact host menu; - first-run **Get Game Data** and **Import Files** flows with explicit consent, pinned verification, data-only extraction, transactional install, and temporary-file cleanup; - the original v469 online server browser, public-server join, data-only package download, combat, death/respawn, map transition, and clean disconnect in Simulator; and - a final-package iPhone Simulator session that held one engine process for more than 30 minutes and survived three Home/reopen cycles. The game itself works on physical iPhone and iPad. Hardware and virtual-keyboard text entry, Xbox controller startup/hot-connect, Gameplay-mode WASD, captured mouse/trackpad look and buttons, adjustable pointer speed, and simultaneous controller plus keyboard/pointer play are physically accepted in Preview 3. Narrower known issues, including wheel behavior, UI scaling, shadow fidelity, and audio-route interruption, are tracked in [`docs/KNOWN_ISSUES.md`](docs/KNOWN_ISSUES.md). ## Getting the game files UTP and Unreal Tournament are deliberately separate. The repository and app package contain no Epic game data, disc image, or prepared game installation. ### Where do the files come from? - **Official OldUnreal route:** the [OldUnreal full-game installer page](https://www.oldunreal.com/downloads/unrealtournament/full-game-installers/) is the recommended source of truth. OldUnreal currently makes the full game available online through free-to-download installers. Those installers download the original Unreal Tournament 99 GOTY disc image from OldUnreal's file servers, use Archive.org only as a fallback, and apply the latest OldUnreal patch. - **An existing copy:** if you already have a user-authorized GOTY installation, UTP can import its supported data from a folder or ZIP. In practical terms, this means you can obtain the game data online through the established OldUnreal route without buying a separate copy from UTP. UTP is simply using that path: it does not mirror, sell, or relicense the game. Epic's terms and OldUnreal's current instructions still apply. ### How does setup work inside UTP? The current UTP build presents two choices on first launch: 1. **Get Game Data** explains the source, approximate size, terms, and destination before consent. It verifies the exact installer image by size and SHA-256, extracts only supported data, installs it transactionally, and removes the temporary image. 2. **Import Files** accepts a folder or ZIP you already have. It rejects unsafe paths, encrypted entries, and desktop/native executables before replacing a working installation. UTP keeps only the supported `Maps`, `Music`, `Sounds`, and `Textures` data in its app container. It does not import the desktop `System` directory or run native code from imported content. This describes implemented behavior, not a finding that distribution rights have been cleared. Public previews already exist; the earlier written-permission gate remains unresolved in the public record. Review the applicable terms and any separate permission for the shipped runtime and acquisition flow; Apple review requirements depend on the selected channel. See [`docs/DATA_COMPATIBILITY.md`](docs/DATA_COMPATIBILITY.md) and [`docs/DISTRIBUTION_AND_ONBOARDING.md`](docs/DISTRIBUTION_AND_ONBOARDING.md). ## Controls and input The touch interface is designed as a full-bleed landscape overlay: - **Left thumb:** movement stick plus SCORE, USE, PREV, and NEXT utility directions. - **Right thumb:** look/aim stick, FIRE, ALT, JUMP, and DUCK. - **Menus:** a persistent `•••` button opens host settings; MENU opens the original Unreal interface. - **Customization:** opacity, scale, handedness, visibility, drag/pinch layout editing, saved profiles, and restore defaults. Touch gameplay, Xbox controller play and hot-connect, hardware-keyboard text, UTP virtual-keyboard text entry, Gameplay-mode WASD, captured mouse/trackpad look, pointer buttons, and simultaneous controller plus keyboard/pointer play have been exercised on physical hardware. The three-dot panel explicitly switches between Menu and Gameplay routing, captures/releases the system pointer, and cycles persistent 20%, 35%, 50%, 75%, and 100% speed presets. ### Input boundaries - Gameplay WASD and relative pointer look require **Gameplay Controls** mode; **Menu Controls** routes the same devices to Unreal's original UI. - Gyro aiming is not included in Preview 3. - Xbox controller startup and hot-connect are physically accepted. Other extended controllers may use the same Apple profile but are not part of the current hardware acceptance matrix. - Pointer wheel/scroll behavior has not been separately accepted on hardware. ## Known Preview 3 limitations - Original UWindow menu text remains small at the engine's maximum GUI scale. - Some projectile, shadow, or alpha effects can render as large black polygons. - Physical-device server-browser compatibility is less broadly exercised than the proven Simulator and direct-connect network paths. - Audio-route interruptions, long background/resume cycles, long-session thermals, memory pressure, battery use, and broader device/peripheral coverage remain preview validation work. - UTP requires iOS/iPadOS 17 or later. It is not available through TestFlight, the App Store, or a one-tap website install. See [`docs/KNOWN_ISSUES.md`](docs/KNOWN_ISSUES.md) for the engineering ledger. ## Build and test ### Requirements - an Apple Silicon Mac; - Xcode and its command-line tools; - enough local storage for pinned upstream inputs and generated build output; - a user-owned Unreal Tournament GOTY source for manual import testing; and - an Apple Development team plus one trusted Developer Mode device for the physical path. All proprietary inputs and generated products stay under ignored `ref/` and `build/` paths. ### Core developer workflow ```bash git clone https://github.com/chrissotraidis/utp.git cd utp make doctor make bootstrap make mac-baseline make audit-469e make test make public-check ``` Useful targets: | Command | Purpose | |---|---| | `make ios-engine-sim-package` | Build the no-audio Simulator diagnostic package | | `make ios-engine-sim-real-package` | Build the local real-FMOD Simulator experiment | | `make ios-engine-package` | Build the ad-hoc device diagnostic package | | `make ios-engine-real-package` | Build the real-FMOD device candidate | | `make diagnostics` | Collect a redacted local diagnostics archive | | `make clean-runtime` | Stop project runtimes and shut down Simulators | Simulator products are development evidence only. The device path requires a non-secret ten-character team identifier supplied at invocation time: ```bash DEVELOPMENT_TEAM=YOURTEAMID make device-check DEVELOPMENT_TEAM=YOURTEAMID make device-run DEVELOPMENT_TEAM=YOURTEAMID make verify-device ``` `device-run` uses Xcode automatic provisioning, verifies the produced app, installs it through CoreDevice, and launches the host. Set `DEVICE_UDID` only when more than one physical iPhone or iPad is connected. Do not commit either value. ## Architecture ```mermaid flowchart LR A["Official v469e ARM64 macOS input"] --> B["Deterministic Mach-O and dependency audit"] B --> C["Build-time iOS platform preparation"] C --> D["Signed native dependencies and narrow shims"] D --> E["UIKit host and SDL2 boundary"] E --> F["FruCoRe Metal renderer and original engine"] G["User-authorized game data"] --> H["Validated transactional import"] H --> F ``` The host owns scenes, sandbox paths, onboarding, diagnostics, recovery, and touch UI. The original engine remains responsible for menus, maps, game rules, bot behavior, rendering, and the UT network protocol. Imported native code is not supported. This is a bounded binary-rehosting experiment, not a browser port, streaming client, Windows compatibility layer, x86 emulator, or Unreal Engine 1 rewrite. The exact technical and stop-gate rationale is in [`docs/UT99_Apple_PRD.md`](docs/UT99_Apple_PRD.md). ## Online play Yes—UTP uses the original v469 server browser and protocol, and the current build has connected to real community Unreal Tournament servers. It has populated live listings, joined unmodified servers, downloaded data-only packages, reached player possession, exercised combat and respawn, survived a natural map transition, and disconnected through the original menu.