The workaround was gated on texture replacements being loaded. That read the
evidence backwards. Tales of the Abyss lost its text layer with a pack while NFS
Underground pushed 608 barrier draws per frame with no pack and looked fine, so
the failure was attributed to sampling a replacement. It is not: the in-pass
self-read is unreliable for ordinary blending too, it just fails subtly enough
there to pass inspection.
OutRun 2006 has no pack and renders its sea as high-contrast two-tone speckle.
Measured against the software renderer on Turnip/Adreno 650, in-tile differs from
the oracle over 4.0% of the frame by more than 16 levels; through the RT copy,
0.13%. Both in-pass shapes - the subpassLoad input attachment and the
feedback-loop-layout texelFetch sampler - are byte-identical wrong, which is what
identifies this as the driver rather than the draw.
Drop the LoadTextureReplacements term so every draw on an affected driver reads a
copy. Cost measured on device, RT copy vs in-tile, median frame time over two
runs each:
1x 3x 4x
FlatOut 2 +7.5% +10.5% +24.6% (copies/frame 23 -> 477, RPs 100 -> 538)
OutRun +20.5% +9.9% +0.5%
GoW II -3.2% +2.9%
RG lamps -1.5% +9.3%
The old note recorded +38%/+40% at 3x/4x on NFSU. Nothing here reproduces that
on the titles available now - FlatOut 2 makes a bigger structural change for a
third of the cost at 3x - so it is recorded as an upper bound on a build we can
no longer run rather than as a contradiction. OverrideTextureBarriers = 1 still
restores the in-tile path for anyone who would rather have the frames.
This depends on the preceding DATE change: turning texture barriers off also
turns framebuffer fetch off, and Adreno has no stencil buffer, which used to
leave DATE with no mechanism at all and washed the road blue.
LoadTextureReplacements leaves RestartOptionsAreEqual with it: the shader variant
now follows only OverrideTextureBarriers and the driver profile, so replacements
can be toggled in place again.
Verified on device: with default settings the water dump is now byte-identical to
the forced RT-copy run and within 0.13% of the software oracle. Non-Adreno is
untouched - 16 colour frames identical across OutRun, Katamari, MGS3, Dirge of
Cerberus and Shadow of the Colossus on Honeykrisp.
ARMSX2 — Native ARM64 JIT Fork of PCSX2
ARMSX2 is a free and open-source PlayStation 2 (PS2) emulator based on PCSX2. Its purpose is to emulate the PS2's hardware, using a combination of MIPS CPU Interpreters, Recompilers and a Virtual Machine which manages hardware states and PS2 system memory. This allows you to play PS2 games on your phone, PC, or gaming handheld, with many additional features and benefits.
Thank You
The ARMSX2 team is eternally indebted to the PCSX2 project it is based on. We are so fortunate to build on their 20 years of hardcore development.
About This Fork
The upstream PCSX2 project ships an ARM64 interpreter build for ARM, but its high-performance JIT recompilers (EE, IOP, VU0, VU1, and vtlb fast memory) are x86-64 only.
This fork exists to close that gap. The goal is to preserve the correctness features of 20 years of PCSX2 development, while generating the fastest native ARM performance possible.
Current status:
- ✅ EE (Emotion Engine) recompiler — integer, float, MMI, COP0/COP1/COP2, branches, load/store
- ✅ IOP (I/O Processor / R3000A) recompiler — full integer, load/store, branches, coprocessors
- ✅ VU (Vector Unit) recompiler — microVU skeleton + Upper FMAC vector ISA complete; Lower ISA and runtime complete
- ✅ vtlb fast memory
- ✅ Native ARM64 binary builds and boots the PS2 BIOS
- ✅ 2D games are already playable
- ✅ 3D games run
Why LLMs / AI Were Used
A word on methodology:
The x86-64 JIT code in upstream ARMSX2 is already proven correct — it has run thousands of PS2 titles for years. The challenge in this port is not emulator design or JIT theory; it is mechanical translation of a large, well-understood x86-64 assembly codebase into equivalent ARM64 assembly (via VIXL) while preserving the exact same register-allocation contracts, block lifecycle, and recompiler semantics.
Large language models (LLMs) were used as an accelerant for this translation work — pattern-matching x86 JIT boilerplate to ARM64 equivalents, scaffolding emit routines, and keeping the porting velocity high. The JIT logic (block compiler, dispatcher, analysis passes, flag pipelines, clamping rules, Tri-Ace hacks, etc.) is taken directly from the upstream x86 implementation and validated against it. Nothing was hallucinated from scratch.
In other words: the hard engineering was done by the PCSX2 team over two decades. The hard typing — translating ~50k lines of x86 emitter code into ARM64 — is what AI helped compress.
System Requirements
ARMSX2 targets ARM64 across desktop (macOS, Windows, Linux) and mobile (Android, iOS/iPadOS), all from the single shared core. Our setup documentation page contains additional details on software and hardware requirements.
Please note that a BIOS dump from a legitimately-owned PS2 console is required to use the emulator. For more information, visit this page.
Building
Check out our github actions for the latest build recipe
