GTA V native iOS port:
how it was built
The v2699 RAGE source, compiled natively for arm64, with D3D11 running on Metal through DXMT. This is neither emulation nor the web build.
These development notes cover different implementation stages. Memory readings and frame rates reflect the workloads and thermal conditions described in each section.
Why native
The first attempt used Madeira: FEX x86 emulation, Wine ARM64EC, and DXMT on an iPhone 13 Pro. It ran after fixes for missing d3dx11, clip-distance geometry-shader asserts, save paths, streamed-file corruption from the RageSec bonder, and 10-second audio memset freezes.
Performance remained at 10–25 FPS. TSO emulation was CPU-bound on two performance cores, while memory stayed at the 4 GB limit. That led to a native build.
Native arm64 base
The macOS build came first. The PC game stayed intact, including RSG_PC, the D3D11 renderer, and PC menus. The platform underneath changed.
- Compiler and ABI: MSVC / LLP64 became clang / Itanium / LP64. Unity translation units were extracted from the
.slninto a Ninja build. Source edits are replayable patch scripts, with 55 batches recorded in these development notes. - CPU: SSE support remains through
sse2neon. Moving from the x86 to the arm64 memory model required-fms-volatile, realdmbbarriers, and full fences after interlocked operations. Without them, the job scheduler lost wake-ups and froze. - Data: Orbis clang struct padding lets PC resources load unchanged. RPF archives are decrypted offline because TransformIT is a binary-only x64 library.
- Win32 compatibility:
libgtacompatreimplements approximately 500 imports. These cover kernel32 waits, threads mapped to quality-of-service classes, virtual memory with 16 KB pages, files, and thread-local storage; a 16-bitwcharC runtime; a user32 window and message queue; DirectInput / XInput through GameController; CoreAudio; and crash / hang reports. - Graphics: DXMT runs natively with an LLVM 15 shader converter. Its window-system integration was replaced with a custom view.
- Stubbed integrations: Bink, NVIDIA / AMD libraries, Steam, and telemetry were stubbed out.
The iOS target
- The same source tree initially targeted iOS 18+ on arm64. A UIKit backend replaces Cocoa, using a Playback audio session so the silent switch does not mute the game, and Files app access to the game folder.
- DXMT on iOS: UIKit replaces AppKit; macOS-only Metal APIs are removed; shader caches live in
Library/Caches; Metal shaders targetiphoneos; and LLVM is cross-built for iOS. - An Xcode stub app uses a free signing profile with the increased-memory-limit entitlement. Deployment, execution, and log collection use scripts around
devicectl.
The iOS 18 target describes the original development stage. Later release notes document iOS 16.3+ support. See the 17 October update.
Getting a correct frame on A15
The Mac rendered correctly before the phone did. Three issues needed separate fixes.
- Triangle strips: degenerate strips with a vertex behind the camera produced streaks on A15. The CPU now rewrites them as indexed triangle lists.
- Render targets: NaN and infinity writes to
R11G11B10/RGB9E5targets are filtered and clamped. - Shader conversion: DXMT’s LLVM, through Xcode’s libc++, bound to the compatibility layer’s 16-bit
wmemchr. InstCombine silently dropped vector lanes, leaving approximately 60% of converted shaders incorrect, including black SSAO and broken water. Retagging the iOS dynamic library as macOS and loading it on the Mac exposed the issue. The fix was a private 32-bitwmemchrinside DXMT.
Memory: 3.9 GB to about 1.9 GB
- Texture conversion: A15 cannot sample BC textures. Runtime BC → ETC2 / EAC transcoding initially kept the same block sizes and saved about 1 GB. Phone archives were then converted offline, removing a CPU cost of 0.5–7 seconds per 10 seconds of play.
- GPU capture: an apparent 800 MB leak came from Apple’s GPU capture layer, loaded by an
Info.plistkey. - Low-memory profile: an automatic profile applies to devices with 4.5 GB of RAM or less.
- Shaders: DXMT shader intermediate representation is freed after compilation. DXBC stays compressed, saving about 250 MB.
- Heap reclamation: freed heap blocks return to the operating system with
madvise.
Recorded result at this stage1.91 GB peak during play
Controls and user experience
- Touch input: controls act as a virtual XInput gamepad. The game reports contexts such as on foot, vehicle, menu, weapon wheel, and phone. Each has an editable layout accessible from the pause menu. A physical controller hides the overlay.
- Settings: added MetalFX, an FPS counter, Shadows Off, extra Advanced Graphics rows, Draw Distance, first-person field of view and aim field of view, and Temporal AA using a custom resolve shader in DXMT.
- Device resets: settings requiring a reset did not apply until the compatibility layer’s
SetWindowPossentWM_WINDOWPOSCHANGED. - Launcher: a configurator inspired by the Rockstar launcher runs before the game starts.
Performance and power
- Scheduling: thread quality-of-service mapping directs the render and main threads toward the two performance cores.
- Frame delivery: unlocked 120 Hz, a 24 FPS limiter step, and Metal-paced presents. The display link stays at the top rate to keep iOS from parking the performance cores.
- Diagnostics: the overlay shows thermal state, CPU power in watts, and active cores.
- iPhone 13 Pro observation: 60 FPS while the thermal state was “fair.” Heat, rather than GPU capacity, was the limiting factor in that observation.
Install size: 29.5 GB to 21.6 GB
- Resource compression: the streamer detects zstd per resource. Recompressed resources are approximately 80% of their deflate size and decode at similar or higher speed.
- Audio: an Opus decoder was added to the engine. The phone uses a dedicated low-bitrate Opus set, which also replaces remaining ADPCM audio.
- Data preparation: one script rebuilds the phone data through decryption, ETC conversion, and zstd compression, with verification at each step.
Where it is now
- iPhone 13 Pro: approximately 30 FPS and 2.3 GB of memory in the game world in the current observations described by these notes.
- iPad: support is built and verified working.
- Minimum hardware described here: an A12-family chip (A12, A12X, or A12Z) and 4 GB of RAM.
A12 support is experimental in the 24 October evening test build and the 25 October release. Start with the lowest preset on 4 GB devices. Review the release notes for the build you install.