Hangs where the RSX idles were only ever visible from the RSX side, so a stall report now names every guest thread, its state, PC and function, and for SPUs adds the reservation counters -- conditional store calls, failures, notifications, and the SPURS heuristic's deliberate non-notifications -- plus where the host thread last was in cpu_task. block_counter alone cannot separate a thread livelocked retrying PUTLLC from one that is genuinely idle; both report zero blocks a second. The SPU code window prints once per process. Unguarded it re-emitted a whole function on every stall dump, measured at 538 lines a second over 31 dumps with a 690 MiB log left behind, which on Android is itself a stall -- it was degrading the hang it was meant to describe, and it buried the state lines that answered the question. do_local_task counters cover the case the profiler cannot: it reports the thread is in Local task and has been for 0.00s, which together mean it is not stuck there at all and the FIFO loop is calling it repeatedly. Which FIFO state, and whether guest GET equals PUT, separates a starved RSX from a stuck one. tools/ps3autotests drives ps3autotests on a device over adb and diffs per instruction against real-hardware output; compare-platforms.py does the three-way ARM/x86/hardware split that separates shared upstream failures from ARM-only ones. This is what found the CFLTS and FMS divergences.
ARMSX3
Uses the latest RPCS3 upstream code (the recent ARM64 improvements included).
Building
Only arm64-v8a is supported. You need the Android SDK with NDK r27 or newer, CMake 3.30 or newer, and a JDK 17. Android Studio ships all of these.
Clone with submodules, then fetch the two third party checkouts that are not submodules:
git clone --recursive https://github.com/ARMSX2/ARMSX3.git
cd ARMSX3
git clone https://github.com/SnowflakePowered/librashader 3rdparty/librashader
git clone https://github.com/bylaws/libadrenotools android/armsx3-ui/app/src/main/cpp/libadrenotools
Build the core. This is the long part and produces an unstripped library of around 1.3 GB:
export ANDROID_HOME=$HOME/Library/Android/sdk
cmake -B build-android -G Ninja \
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_HOME/ndk/<version>/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=android-31 \
-DCMAKE_BUILD_TYPE=RelWithDebInfo
cmake --build build-android --target rpcsx-android -j8
Strip it and put it where the app expects it:
llvm-strip --strip-unneeded build-android/android/libarmsx3-core.so
cp build-android/android/libarmsx3-core.so \
android/armsx3-ui/app/src/main/jniLibs/arm64-v8a/
Then build the app:
cd android/armsx3-ui
export JAVA_HOME="/Applications/Android Studio.app/Contents/jbr/Contents/Home"
./gradlew :app:assembleRelease
The apk lands in app/build/outputs/apk/release/.
Note that the core library has to be rebuilt and copied again whenever anything under rpcs3/ or android/src/ changes. Gradle does not build it for you.
The Discord Social SDK is proprietary and is not redistributed here. Get it from Discord's developer portal and drop it in app/libs/ and app/src/main/cpp/discord_sdk/ if you want that feature. The build skips it otherwise.
Running it needs PS3 firmware, which is not included. License
GPL-2.0-only, the same as RPCS3. See LICENSE. Some files may be licensed differently, check the file headers.
Based on RPCS3, https://github.com/RPCS3/rpcs3