FPse - RetroBIOS¶
Technical notes
PlayStation emulator for Android, closed source, sold on Google Play as package com.emulator.fpse. Two builds are read here and both carry the same signing certificate, CN=FPse Team issued 2011, sha256 9af45a593faf3b522c5120fc976a03b7d82a88a9e5008162b9d6822ade7c981a: 12.1 versionCode 940, apk md5 09160e917333d546296d4fcdae7b35f9, armeabi-v7a, and 0.11.190 versionCode 720, apk md5 818ee3fe71370ac983283926234e920e, armeabi plus armeabi-v7a plus x86, taken from the OUYA store archive. The archive.org item labelled FPse 1.7.8 is package com.emulator.fpse64, signed with the Android test key and carrying an assets/hook.apk payload, and is not read here. The emulator descends from LDchen's PC FPSE and keeps its console messages, its fpse.ini keys and its bios, plugin, cfg and snaps directory names. ref: com.emulator.fpse META-INF/BNDLTOOL.RSA, META-INF/CERT.RSA, res/raw/fpse.ini
One root holds everything and it is the private files directory of the package, not shared storage. Main sets it from getFilesDir and creates bios, plugin, cfg and skin under it right after the native libraries load, then unpacks its own resources into them. Paths below are relative to that root. The plugins have no stable path of their own: 12.1 loads them from the native library directory of the package and 0.11.190 loaded them from this root, so they are recorded by name alone. ref: Main.java:32088, Main.java:29716-29719
Exactly one BIOS image is ever loaded and its full path is a setting rather than a name the code looks for. The Load Bios browser lists .bin files only, the chosen path is written to the preference com.emulator.fpse.biospath and pushed into the emulator core as string slot 6, and leaving the browser without a choice writes an empty string, which is the documented way to switch to HLE. The stored path is re-checked at every start: a file that no longer exists or is not exactly 524288 bytes clears the preference and the session runs on HLE. On the core side a path that will not open reports "Can't load biosfile '%s', switching to HLE" and emulation continues, so no image is needed on its own. fpse.ini ships with EnableHLE=on and BiosName set to the placeholder scph1001.bin_is_recommended, and the core resolves BiosName under bios/ when the setting is left alone. ref: Main.java:5917-5919, Main.java:1173, Main.java:1965-1971, Main.java:25213-25222, res/raw/fpse.ini BiosName, FPse 0.11.190 libfpse.so x86 0x5c2c8-0x5c395
Automatic detection recognises one dump and does it on content. Scanning storage, FPse keeps files whose lowercased name ends in .bin and whose length is exactly 524288, reads all 524288 bytes, sums them as signed bytes and accepts the file when the total is 85958, writing the path to the preference and turning the BIOS on. The same constant answers over NFS through isnfsbios. Reimplemented over the collection, that sum resolves to a single image, the v2.2 12/04/95 A dump listed below, and to no other. The HLE path impersonates the same revision: its identification strings sit in .rodata as ordinary C strings next to "HLE enabled.", and the library carries no 512 KB image of its own. ref: Main.java:4155-4175, Main.java:4185, Main.java:21188, FPse 0.11.190 libfpse.so armeabi-v7a .rodata 0x245828-0x2458cc
Emulation itself lives in plugins that Main names one by one before the core: uncompress, spuplugin, soft1, nfsplugin and opengl, then fpse. libfpse.so lists all of them except uncompress in DT_NEEDED, so the core will not link without them. They are distributed both ways. 0.11.190 shipped none of them, tested for each file in the private directory, stopped on an error dialog before loading the core when one was absent, and fetched plugins267.zip and its per GPU and per ABI variants from fpse.net; 12.1 carries them in the package and keeps an updater that asks getfile.php for the list matching its own versionCode and ABI, alongside plugins605 constants nothing reads. Both generations of the pack still answer: plugins605v7.zip is 1359776 bytes and holds the armeabi-v7a build of libsoft1.so, libspuplugin.so, libopengl.so, libnfsplugin.so and libuncompress.so at the same lengths as the copies inside 12.1 but not the same bytes, plus the libopenglex.so, libspuplugin1.so and libspupluginex.so variants the package does not carry, and twenty shader pairs. An OpenGL plugin picked by hand from the .so browser is copied over libopengl1.so and used in place of the packaged one. libGLESv2, libjnigraphics, liblog, libstdc++, libdl, libm and libc are the Android runtime and are not files anyone supplies. ref: Main.java:29686-29698, Main.java:20405-20406, Main.java:11010, Main.java:3417-3423, Main.java:1120-1137, FPse 0.11.190 Main.java:24126-24207, FPse 0.11.190 Main.java:860-871, FPse 12.1 libfpse.so readelf -d, fpse.net/plugins605v7.zip md5 ae5dbdc27452092af3e712448f427fd3
Resources unpack through two helpers that differ in one respect. b2 writes only when the target is absent, so bios/kanji.rom, fpse.ini and the whole skin set survive being replaced by hand. c2 truncates, so gamelist.ini is rewritten from the package at every start and a copy put there does not last. ref: Main.java:26892-26895, Main.java:26956-26957, Main.java:29721, Main.java:29755-29758, Main.java:30046
11 files | 6 required, 5 optional | 8 in repo, 3 missing | 1 with HLE fallback Categories: 2 BIOS, 9 game data
scph1001.bin optional in repo HLE fallback
SCPH-1001, DTL-H1201, DTL-H3001 (v2.2 12-04-95 A)
- Path:
bios/scph1001.bin - System: sony-playstation
- Size: 512.0 KB
- SHA1:
10155d8d6e6e... - MD5:
924e392ed055... - Validation: size
- Source:
Main.java:4159-4175,Main.java:5919,Main.java:25217,res/raw/fpse.ini BiosName - Platforms: batocera, lakka, recalbox, retroarch, retrodeck, retropie, rocknix, romm
- Config key:
BiosName - The only image the code identifies, and it identifies it by a checksum of its own rather than by a hash it spells out: the 524288 bytes summed as signed bytes, accepted at 85958. The md5 and sha1 here are the dump that reproduces that sum. Selecting a BIOS by hand takes any file ending in .bin that is exactly 524288 bytes, so the other images of the group fill the slot without being recognised by name or by sum.
LibPS.exe optional missing
PlayStation library executable loaded at startup when present
- System: sony-playstation
- Source:
FPse 0.11.190 libfpse.so x86 0x95545-0x9558a,FPse 12.1 libfpse.so .rodata 0x344634 - Loaded by bare name through the same loader as any PS-X EXE, reporting "LibPS.exe found and loaded." on success and continuing untouched when the loader returns -1. Not carried by the package, and the core never chdirs, so it resolves against the working directory of the process.
libsoft1.so required in repo game_data bundled
software renderer plugin
- Source:
Main.java:29688,FPse 0.11.190 Main.java:24148-24162 - Named by System.loadLibrary("soft1") and listed in DT_NEEDED by the core. 0.11.190 listed it the same way without shipping it, tested for the file in the private directory and stopped on an error dialog before the core when it was absent, the file coming from plugins267.zip.
libspuplugin.so required in repo game_data bundled
sound plugin
- Source:
Main.java:29687,FPse 0.11.190 Main.java:24126-24132 - Named by System.loadLibrary("spuplugin") and listed in DT_NEEDED. 0.11.190 picked libspupluginex.so, libspuplugin2.so or libspuplugin1.so by device and API level and copied the winner over this name.
libopengl.so required in repo game_data bundled
OpenGL renderer plugin
- Aliases:
libopengl1.so,libopenglex.so - Source:
Main.java:29690,Main.java:11010,FPse 0.11.190 Main.java:24178-24199 - Named by System.loadLibrary("opengl") and listed in DT_NEEDED. A plugin chosen from the .so browser is copied over libopengl1.so, which 0.11.190 in turn copied over this name, the ex variant standing in for it on the devices that ask for it.
libnfsplugin.so required in repo game_data bundled
NFS client plugin, for discs read from a network share
- Aliases:
libnfs.so - Source:
Main.java:29689,FPse 0.11.190 Main.java:24163-24177 - Named by System.loadLibrary("nfsplugin") and listed in DT_NEEDED. Called libnfs.so through the 0.11.x line.
libsdl.so required in repo game_data bundled
SDL 1.2 audio backend
- Source:
Main.java:20405,FPse 12.1 libfpse.so readelf -d - Named by System.loadLibrary("sdl") and listed in DT_NEEDED.
libneon.so required in repo game_data bundled
NEON colour conversion routines
- Source:
Main.java:20406,FPse 12.1 libfpse.so readelf -d - Named by System.loadLibrary("neon") and listed in DT_NEEDED, which resolves bgr555rgb565neon for the core.
libuncompress.so optional in repo game_data bundled
archive extractor for .zip, .rar, .7z, .ape and .ecm images
- Source:
Main.java:29686,FPse 0.11.190 Main.java:6244-6249 - Named by System.loadLibrary("uncompress") and the only one of the plugins the core does not list in DT_NEEDED. 0.11.190 loaded it on demand from the private directory.
<skin>.ini optional missing game_data
external overlay pad skin
- Path:
skin/<skin>.ini - Source:
Main.java:5936-5938,Main.java:29758 - Selected through a browser listing .ini files, which is what the External entry of the gamepad skin setting opens. The default set unpacks from the package as skin/pad.ini with its button and stick artwork.
<game>.txt optional missing game_data
cheat codes for one title
- Source:
Main.java:5965-5967,Main.java:30552 - Selected through a browser listing .txt files and parsed as titles between hashes followed by address and value pairs. Cheats apply only when a BIOS image is loaded.
Generated on 2026-08-23T16:12:06Z