Until now, rePIU has largely focused on basic initialization in Legacy mode and establishing the surrounding HLE (High-Level Emulation) environment. However, relying entirely on single-step traps for every original x86 instruction brings substantial overhead. To overcome this, the recent work branch heavily focused on introducing and refining a Native AOT (Ahead-of-Time) dynamic translator.
In this post, we will summarize the key changes merged into the main branch since the previous post and compare the actual performance differences these changes have achieved.
Key Progress (Commits Summary)
The major tasks completed since the last update include:
- Introduction of AOT Dynamic Translator and Code Cache
- Connected
aotandaot-dynamicexecution backends to allow DOS4GW-based code to execute directly within the Win32 native environment. - Implemented a relocatable code cache that translates runtime basic blocks into native instructions and places them into memory.
- Connected
- Dynamic Control Flow Optimization
- Improved the host worker to dynamically track and translate unmapped paths such as indirect calls, returns, conditional transfers, and fallthrough linking at runtime.
- Introduced worker-backed inline caches to minimize the cost of cache misses.
- Self-Modifying Code (SMC) Coherency Resolution
- Implemented a page-level coherency model to handle runtime code modification (e.g., import stubs) inherent to PIU game logic.
- Whenever code is modified at runtime, the active cache is immediately retired, and a new live arena snapshot is used to publish a new generation of native instructions, ensuring execution flow continues safely and without divergence.
- MAME CHD Asset Mounting and MSCDEX CD Audio Emulation
- Added functionality to mount and read PIU assets directly from MAME CHD image formats without needing individual file extraction.
- Implemented MSCDEX (Microsoft CD-ROM Extensions) emulation at the HLE layer, allowing CD audio (BGM) tracks to be played and controlled directly from the mounted CHD image.
Performance Comparison
The following performance data was measured by running the game loop (repiu_supervisor_win32.exe) for 10 seconds across different backends. (Based on Win32 x86 Debug build)
| Metric / Backend | legacy |
aot (Static Only) |
aot-dynamic |
|---|---|---|---|
| Cumulative Heartbeat (3s) | 671,524 | 645,770 | 76,601 |
| Cumulative Heartbeat (10s) | 2,248,638 | 2,085,754 | 1,919,174 |
| Cumulative Single-Step Traps (10s) | 1,124,319 times | 1,042,877 times | Under ~510,000 times |
| Trap Ratio | 1 per 2 Heartbeats | 1 per 2 Heartbeats | 1 per ~3.8 Heartbeats |
Analysis
- Reduced Emulation Overhead: The previous
legacymethod incurred heavy loads by triggering traps constantly. With the introduction of theaot-dynamicmode, translated code executes natively in the cache (direct execution), cutting the trap frequency by more than half. - Warm-up Acceleration: The
aot-dynamicmethod spends resources on code decoding, translation, and SMC handling during the initial execution, resulting in slower heartbeat progress in the first 3 seconds. However, once the cache is warmed up, the progress rate increases exponentially. By the 10-second mark, the translation cost is completely offset, demonstrating a dramatic uplift in overall performance.
With further optimizations and Release builds on the horizon, we can expect near-native execution performance in the near future.