Repository navigation
Releases: theonlyasdk/MREmu
Release list
MREmu v1.0.0-beta.3 (pre-release)
Third pre-release. Two things changed since beta.2: apps that hung on startup now run, and the desktop build can be driven by an AI agent.
versionCode is now 2 and versionName is 1.0.1, so this installs over beta.2 as a normal upgrade and the artifact filenames no longer collide with beta.2's.
Everything from beta.2 still applies — see beta.1 for the full changelog against upstream XimikBoda/MREmu master.
Fixed: apps that hung on startup
Some .vxp files froze the emulator instead of loading
MreTags::read_mstring read a length-prefixed string but never advanced past it, so it returned the same bytes forever. Any VXP carrying an app-name list rather than a single name hit this: an infinite loop, then std::bad_alloc, then a fast-fail with 0xC0000409.
This is what stopped Opera Mini 6.1.vxp from loading at all. It now boots, runs stably, and unpacks its resources as expected. The read is also clamped to the bounds of the tag data.
ADS apps started 32 KB below their own code
For VRE/ADS layout apps the entry point was taken as 0, while the code segment is loaded at 0x8000. Execution therefore began in unmapped memory. The loader now derives the entry point from the actual code load offset — for Opera Mini 6.1.vxp that is 0x8000, and the reported entry point now matches the code load offset exactly. Apps using the other layout are unaffected.
Deep stepping no longer crashes the emulator
Running several thousand instructions inside a single timer or event callback faulted ADS apps with UC_ERR_FETCH_UNMAPPED or UC_ERR_WRITE_UNMAPPED at a garbage PC. The instruction budget is now spread over successive callbacks, at most 4096 each, carrying the remainder forward.
This fixes the crash as reached through the MCP server's emu_step. --inspect --steps N still spends its whole limit in one invocation and still crashes above roughly 5,000 instructions — see the known issues below.
Added: headless modes
Both are desktop-only. Neither opens a window, so both work on a machine with no display.
--inspect — one-shot report
MREmu.exe app.vxp --json report.json --steps 2000 --screen shot.png --inspect
Loads the app, writes what it found to JSON (MRE tags, memory layout, entry point), optionally runs a bounded number of instructions, optionally saves the emulated screen as a PNG, then exits. Useful for checking whether an app will load at all.
--mcp — an AI agent can drive the emulator
MREmu.exe app.vxp --mcp
MREmu starts the app and then speaks the Model Context Protocol over stdin/stdout, so an agent can start the emulator and ask it what is running, read the CPU registers, look at the screen, pause and step the app, read errors, and record every call the app makes into the MRE system.
The system-call tracer is the most useful of these for reverse engineering. Switch it on before an app boots and it captures the entire startup sequence — 464,217 calls for Opera Mini 6.1.vxp, each with its address, arguments and return value. That turns "the app will not start" into "it failed at vm_malloc after 1,200 calls".
Set it up by pointing an MCP client at the executable with the arguments ["app.vxp", "--mcp"]. See the README for the tool list and for two behaviours worth knowing: these apps idle until an event arrives, so a step can legitimately do nothing; and r9 holds the VM's symbol-table pointer, so writing to it breaks the app permanently.
Hard-reset faults used to surface only as a GUI dialog and were otherwise lost. They now reach the agent as an error with a full register dump, and pause the app, so a dead CPU is never silent.
Known issues
Both are documented in full in the README.
--inspect --stepsabove ~5,000 instructions still crashes. Undiagnosed.--mcpis unaffected because it spreads the budget across callbacks.- An app that has spent its timers cannot be resumed.
Opera Mini 6.1.vxpcreates one 10-second timer while booting and deletes it again. Once it has run out and stopped, nothing re-enters it, because the emulator only calls into the app from a timer callback or an incoming event.emu_stepreports this honestly rather than appearing to work. - VXP offsets are still not bounds-checked. Unchanged from beta.2. Treat VXP files from untrusted sources as unsafe.
- Release APKs are signed with the debug key. Unchanged from beta.2. Sideloading only.
MREmu v1.0.0-beta.2 (pre-release)
Second pre-release. Built from master and superseded by v1.0.0-beta.1 in three respects: the Android/JNI hardening fixes are in, two known issues are now documented, and the release APK is a little smaller.
Everything from beta.1 still applies — see beta.1 for the full feature changelog against upstream XimikBoda/MREmu master.
Fixed since beta.1
Crash and freeze fixes
- Opening a
.vxpfroze the main thread.nativeLoadVxpFilewas called on the UI thread, where it spin-waits forg_appManagerto be published part way through native start-up. Moved to the copy thread and the wait is now bounded. - Any VXP declaring more RAM than the shared pool could hold segfaulted.
Memory::shared_mallocreturns0on failure and the next line wasmemset(NULL, ...). Now rejected cleanly. - The options sheet could kill the process with
BadTokenException. It is posted from the native render thread onto an activity reference that is never refreshed, so after a configuration changeDialog.show()ran against a dead window. Now guarded onisFinishing/isDestroyed, single-instance, and wrapped in a try/catch. - "Clear user data" ran a full recursive delete on the main thread, which ANRs on a device with a few thousand emulated files, and reported success even when it deleted nothing. It now runs in the background and reports honestly.
- A failed vibration lookup aborted the process.
GetMethodIDfortriggerVibrationwas unchecked, so a failure left a pendingNoSuchMethodErrorand the next JNI call was undefined behaviour. All lookups are checked and exceptions are cleared. - A 0-byte or corrupt image could be booted. A null
openInputStreamstill handed a path to the emulator, and a fixed temp filename let two simultaneous opens interleave into one corrupt file. Streams are validated and each load gets a unique temp file. - The
ACTION_VIEWintent replayed on every activity recreation, silently relaunching the originally-opened app. It is now consumed, andonNewIntentcorrectly replaces the activity intent.
Leaks and lifecycle
LifecycleRegistrynever reachedDESTROYED— there was noonStart,onStoporonDestroy— and theViewModelStorewas never cleared. The options dialog leaked its window.- The native side cached an activity reference that was never released.
Performance
- Vibration no longer attaches and detaches to the JVM on every key press. The render thread is a plain pthread, so it paid a full ART thread setup and teardown per keystroke, twice more per key inside
unpress_by_source. It now attaches once and stays attached.
User interface
- Back now steps up the options page stack instead of dismissing the whole sheet, which makes the sheet's paging reachable by hand.
- Corrected a comment that described the destructive-action countdown as tap-armed. It arms on navigation to the page, which is the intended design.
Known issues (now documented in the README)
- VXP offsets are not bounds-checked. A malformed or hostile
.vxpcan cause out-of-bounds reads and writes. On Android this is reachable through theACTION_VIEWfile filter. Treat untrusted app files as unsafe. - These APKs are signed with the per-machine debug key. Sideloading only, cannot go to the Play Store, and the key is not secret.
Install
Install the APK matching your device ABI — arm64-v8a covers essentially all modern phones.
| Asset | ABI |
|---|---|
MREmu-arm64-v8a-1.0.apk |
64-bit ARM (most modern phones) |
MREmu-armeabi-v7a-1.0.apk |
32-bit ARM |
MREmu-x86_64-1.0.apk |
x86_64 (emulators) |
MREmu-x86-1.0.exe |
Windows, 32-bit |
MREmu v1.0.0-beta.1 (pre-release)
Android
- Options bottom sheet rewritten in Compose — Material 3 Expressive segmented rows (rounded groups, inset hairline dividers, section headers), typography set in Roboto Flex (variable axes pinned per instance), and the sheet opens at its content height instead of the default half-screen peek.
- Destructive actions reworked — Reset emulator state and Clear user data now use a 3→2→1 cooldown that starts when the page opens (button shows
3s/2s/1s, then "Reset"/"Clear") on a taller, roomier button, replacing the old arm-then-confirm checkbox. - Open FS folder… now hands the chosen path to the system file manager via an
ExternalStorageProviderdocument URI (ACTION_VIEW) instead of opening the SAF picker. - About page gains a "Source repository" row linking to this fork.
- Release APK is built per ABI: arm64-v8a, armeabi-v7a, x86_64.
- Release APK shrunk ~17.5 MB → ~6 MB via R8 + resource shrinking, with keep rules so the JNI entry points and the Roboto Flex font survive.
Launcher (Windows / C++)
- D-pad scroll fix — moving the selection near the top or bottom of a scrolled list now brings the row into view (the position was measured in content space and compared against the viewport).
- Frame-rate-independent scrolling — the release fling uses a fixed 100 ms time window instead of a fixed sample count, and the spring-back is integrated in closed form (critically damped), so scrolling feels the same regardless of touch report rate or frame rate.
Build / tooling
- Faster Gradle + CMake builds (daemon, parallel, build cache, configuration cache, conditional ccache); trimmed to a single ABI by default with per-ABI release builds on demand.
launch.bat: new Android menu option[6]builds a Release APK for a chosen ABI and saves it to~/DownloadsasMREmu-<abi>-<version>.apk(scriptable:launch.bat 7 6 <0-3>). A[3]install+launch path was added alongside the existing debug flow.
Install
- Android: install the APK matching your device ABI (arm64-v8a for virtually all modern phones). These are unsigned/ debug-signed release builds for sideloading — not Play Store releases.
- Windows: run
MREmu-x86-1.0.exe.
Full commit list: XimikBoda:MREmu:master...theonlyasdk:MREmu:feature/new-features