Skip to content

Repository files navigation

Mass Effect Infiltrator — native ARM port

Runs the 2011 EA/IronMonkey Mass Effect Infiltrator mobile game on Linux/ARM handhelds by loading its original Android native library into a bionic/JNI compatibility layer. No emulator or Android runtime is involved.

Port and project by EapRules.

This directory targets the v1.0.58 gamepad build:

lib/armeabi/libMassEffect.so
SHA1 ea58b733d3d267ab639431b50539542faa43f0d0

Current status

The immutable harness reaches M7/7 under qemu-arm + llvmpipe. The latest run, with real-time dummy audio consumption and the ARMv8 VFP compatibility patch enabled, reported:

570 frames
84 successful content opens
151 texture uploads
35,511 draw calls
non-black framebuffer
11 synthetic JNI keys
4 measured scene changes

That proves startup, content loading, rendering and input-driven progression in the harness. The PVRTC fallback is also confirmed on the real R36S Mali-G31: the previously white characters, objects and backgrounds now render correctly. The current candidate also initializes SDL audio, uses a bounded hardware period and expands the obsolete VFP short-vector mixer operations for ARMv8. Audio output, the new cursor/camera behavior, L2/R2 accelerometer gestures, saves and a complete play-through still require device testing.

Bring your own game

This repository and its packages contain no EA binary or asset. The supported donor is the Mass Effect Infiltrator v1.0.58 gamepad build, Android package com.ea.games.meinfiltrator_gamepad. Local developer runs give the loader an already-extracted directory with:

masseffect/
├── assets/
│   ├── EAMCore.ini
│   └── published/
└── lib/
    └── armeabi/
        └── libMassEffect.so

Run locally as:

./build/masseffect /path/to/extracted/masseffect

The PortMaster release also carries eapx, a content-based transactional first-boot extractor. Release users may place the supported APK, ZIP or an extracted folder in ports/masseffect/; its filename does not matter. eapx stages and validates the complete payload before publishing it. The native library is validated by critical regions, not a whole-file hash, so any legitimate v1.0.58 gamepad-build copy is accepted; the launcher additionally size-checks the .so. A complete game tree and reduced Vita-ready donors that keep the campaign are both supported.

Build and verify

docker run --rm -v "$PWD":/src -w /src masseffect-build make -j4
timeout 400 harness/verify.sh

harness/verify.sh is the read-only arbiter. Do not modify it or lower its thresholds.

To collect the redistributable ARM dependencies and make the game-data-free PortMaster zip:

docker run --rm -v "$PWD":/src -w /src masseffect-build make libs
./package_portmaster.sh

The zip is written to build/masseffect-portmaster.zip. It intentionally contains neither libMassEffect.so nor assets/published.

PortMaster install

Use PortMaster's standard independent-autoinstall workflow:

  1. put our masseffect-portmaster.zip in PortMaster's autoinstall/ directory without renaming it;
  2. put the user's v1.0.58 gamepad-build APK/ZIP in ports/masseffect/ (or an extracted donor under ports/masseffect/gamedata/);
  3. open PortMaster and wait for the exact Finished running autoinstall dialog; acknowledge it and let PortMaster return or close normally;
  4. reboot through the firmware menu, then launch Mass Effect Infiltrator from Ports. Do not hard-power the console while PortMaster is still installing.

The first launch extracts and validates the donor automatically. Complete CFW-specific paths, the two autoinstall gotchas and accepted donor layouts are in ports/masseffect/README.md. The resulting layout is:

ports/
├── Mass Effect Infiltrator.sh
└── masseffect/
    ├── masseffect
    ├── masseffect.gptk
    ├── eapx.py
    ├── masseffect.eapx.json
    ├── libs.armhf/
    ├── assets/                # your copy
    ├── lib/armeabi/           # your copy
    └── var/                   # saves/settings

The launcher follows PortMaster's directory variable, so it works from either /roms or /roms2. It also refreshes only Mass Effect Infiltrator's normalized ArkOS artwork at ports/images/Mass Effect Infiltrator.png when a direct update left an old APK icon cached there; the canonical portable cover remains masseffect/cover.png as required by PortMaster's gameinfo.xml format.

Controls

This binary has no AInputQueue imports. Input is delivered through its exported JNI entry points, matching the working Vita port:

  • title/menus: D-pad moves a visible software cursor, A taps it
  • L3 or R3 toggles the menu cursor after it has been dismissed
  • Start restores the cursor while opening the pause menu
  • L2 simulates the accelerometer tilt used to rotate/switch weapon fire mode
  • R2 simulates the accelerometer motion required for a Zero-G jump
  • buttons outside cursor mode → KeyboardAndroid.NativeOnKeyDown/Up
  • left stick → virtual touchscreen movement stick
  • right stick → virtual touchpad aiming stick

The original game's menus do not support gamepad navigation; the Vita port uses its physical touchscreen. The cursor is therefore a required input bridge on non-touch PortMaster handhelds, not optional decoration. Moving either analog stick dismisses it so the same controls can drive gameplay.

The pointer callback uses base AAPCS because the game is softfp and the loader is hardfp.

Graphics and real-device status

The first d4ca229 build was tested on an R36S with its Mali-G31 driver:

  • the image is correctly centred at 640x480;
  • the D-pad cursor and physical controls work and can advance through menus;
  • menu UI is visible;
  • 3D characters, objects and backgrounds render mostly white, sometimes with only an edge, shadow or silhouette visible;
  • audio is not working yet.

The interactive emulator reproduced that exact visual failure. Per-call GL diagnostics identified rejected glCompressedTexImage2D uploads: 0x8c00/0x8c02 are PVRTC1 4bpp RGB/RGBA, formats unsupported by both llvmpipe and Mali-G31. The loader now uses Imagination's MIT-licensed decoder and uploads RGBA8888 when the driver does not advertise native PVRTC.

A subsequent local capture rendered the complete menu environment with its textures, lighting and materials, and the immutable harness remained M7/7. The candidate with SHA-256 9199544a9db9113e20facac61fb518dfc892beff35f17156ff3e313924a015da was then tested on the real R36S and the user confirmed that the full 3D scene also renders correctly there.

That hardware pass exposed two isolated input issues in the otherwise working controls: the provisional cross cursor could not be recovered after analog input, and a held right stick produced only one finite camera gesture. The next candidate replaces the cross with a high-contrast arrow, restores it with L3/R3 or Start, refreshes sticks every frame and reproduces the Vita port's per-frame right-touchpad gesture.

The same candidate addresses the silent audio path. AudioTrack used to call SDL_OpenAudioDevice without ever initializing SDL_INIT_AUDIO, then silently kept device ID zero. It also confused the engine's 1 MiB producer ring with a hardware period and requested a roughly six-second buffer. Audio now has explicit initialization, device enumeration/fallback and a 1024-frame period. The game's 40 obsolete VFP short-vector mixer instructions are expanded into validated scalar A32 trampolines for the Cortex-A35, which ignores FPSCR LEN/STRIDE. A qemu register-level self-test proves all 40 expansions reproduce the original vector operations, while a disassembly audit proves the list covers all 40 arithmetic opcodes in all 20 LEN regions. The local dummy device confirms the queue is consumed in real time; audible speaker output awaits the R36S test.

Current device-test binary:

SHA256 d0ba9983a13a1cf7dbd7a7c5c26d57d544cd9e435ffe80308a03799ea20390de
size   7215740 bytes

Interactive local emulator

emulator/run.sh keeps the qemu-arm + Mesa build alive and exposes cursor, touch, controls, screenshots and logs through a shared control directory. emulator/mcp_server.py publishes the same operations as an MCP server. See emulator/README.md.

This path reproduced the real-device graphics failure locally and then verified the PVRTC software fallback visually: the same menu now has a fully textured 3D environment. The immutable M1-M7 harness remains separate and unchanged.

Diagnostics

Every device launch writes ports/masseffect/log.txt. Important lines:

TRACE: module loaded
TRACE: mounted extracted content at /published
TRACE: VFP short vectors: expanded 40/40 audio instructions
TRACE: AudioTrack: SDL audio ready driver=...
TRACE: AudioTrack: opened device=...
TRACE: AudioTrack: PCM write=...
TRACE: framebuffer non-black
TRACE: summary assets=N textures=N draws=N
FATAL: ...

Never redistribute the game .so or extracted assets.

About

Mass Effect Infiltrator (2011, IronMonkey/EA) running natively on ARM Linux via a bionic/JNI so-loader. PortMaster package — bring your own game data.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages