Native iPhone port of Factorio 2.0.77
Run the original macOS ARM64 game code on iOS: - tools/retarget.py: header-only Mach-O retargeting to an iOS dylib - platform/native: UIKit host and macOS API shims (AppKit for SDL's Cocoa backend, CoreGraphics displays, CoreAudio device, Metal device properties, Wuffs PNG decoding, Steam and peripheral stubs) - touch, overlay, iOS keyboard and hardware keyboard input - tools/build_native.py: build, sign, install, data copy, launch - docs: build guide, controls, architecture Also includes the earlier static-translation research (ARM64 -> WASM -> native) under docs/research, runtime/, tests/ and tools/. No game files are included; the build reads them from a local install.
This commit is contained in:
commit
51d085e865
89 files changed
+7999
No files matched your search
@@ -0,0 +1,59 @@
|
||||
# Original MapDeserialiser initialization (2026-10-20)
|
||||
|
||||
Build **5** initializes the original MapDeserialiser on the iPhone 15 Pro using both a controlled version header and the approved actual save's nine-byte version prefix. The original guest code performs five reads, creates its helper structures and owned TargetDeserialiser, and returns successfully. Reports record **12 allocations**, **10,712 guest heap bytes**, a target-pool capacity of **64** and a stream cursor of **9**. A controlled newer-version prefix takes the original error branch and returns the adapter's version-error status 7.
|
||||
|
||||
This is an isolated constructor probe. The module is freed after validation; its object graph is not yet connected to a persistent world loader. The rest of the save stream, object references, entities and gameplay are not loaded. The scenario-envelope probe remains a separate host-side reconstruction.
|
||||
|
||||
## Original input and evidence
|
||||
|
||||
| Code/data | Address | Bytes | Complete REA byte record |
|
||||
| --- | --- | --- | --- |
|
||||
| MapDeserialiser C2 normal CFG including version-error branches | `0x1014def40` | 1272 | `ev_904c99c8305aec9932b9bfe4c722d12a961c34e254d80c97a09db109dc390bba` |
|
||||
| Actual TargetDeserialiser C1 normal body called by that CFG | `0x1012c1044` | 116 | `ev_d0a2867c6c04389e519058440e52ecc612c2212435f9920a725fb219e27fc663` |
|
||||
| Shared TypeAwareMemoryPool C2 normal CFG | `0x10244a4bc` | 1260 | `ev_bdbccc8d7c9a58178fcb6476fcf32651ee9daa7abfd66ac2b4e39b2b8d489b3e` |
|
||||
| Pool vtable identity range | `0x102fc2d98` | 32 | `ev_ee2b757ce4a5c73c150c5cd29112e7dd6db99529211abfa59085d500e4c2cbb1` |
|
||||
|
||||
The prior C2 TargetDeserialiser input at `0x101ab7c74` also has a complete matching byte record, `ev_5c30d5ca0d76c6b2727297e08f671d59e0944c9bffadd7b58cb62f8650e32b37`. This closes the previous batch's pending byte check. The C1 constructor is a distinct body with different stack saves; it is translated at its actual call target, without substituting the earlier C2 implementation.
|
||||
|
||||
The unchanged ARM64 SHA-256 is pinned to `2cb4de127b50d54c6c5666acfef2263fae16d11a3361ad39353ecf8a66a4d9c7`. Function range hashes and all 662 translated instruction words are in `build/deserialiser/manifest.json`. Complete REA records are in `evidence/deserialiser-final.json`; the native session was snapshotted to `build/deserialiser-rea.snapshot.json` and closed. Earlier constructor assembly is retained as `ev_3143ceb6dee72f0a56235e02cd4a5ed942c3826860ea21c315847bb186053650`.
|
||||
|
||||
## Guest execution and boundaries
|
||||
|
||||
The original constructor stores the reader pointer at object offset `+8`, the packed version at `+0x18`, its flag at `+0x20`, the target pointer at `+0x28` and the target ownership byte at `+0x4c6`. The initialized-state byte at `+0x10` becomes 1. Helper allocation order and self/heap pointer relationships are compared against the original ARM64 execution.
|
||||
|
||||
The stream service is a bounded memory adapter selected for the observed readOrThrow contract; it does not implement the game's ReadStream virtual dispatch. Operator new uses the existing 16-byte-aligned per-run guest arena. The new bzero adapter validates its destination in the allocated arena prefix. All guest pointers remain offsets into the fixed 1 MiB module memory.
|
||||
|
||||
Zero-vector stores now require a MOVI-zero definition on **every** incoming path. Integer instructions preserve these facts; calls clear them, and copy loads overwrite the relevant vector fact. The supported stores include unscaled/scaled Q stores, pre/post writeback and Q-store pairs. This does not add general SIMD arithmetic, floating point or incoming vector-register state.
|
||||
|
||||
Version rejection aborts with status 7 at the original call to `__cxa_allocate_exception`. The original exception object, message and unwinding behavior are not implemented. Destruction helpers and delete return unsupported-service status 6 if reached. Ordinary constructor inputs skip those cleanup blocks; allocation failures abort with status 5 and discard the module. Static ADRP pages used for vtable/type/callback identities are declared explicitly; those addresses do not provide callable native pointers or a complete relocated image. No exception landing pads are executed.
|
||||
|
||||
The constructor's original checks accept 2.0.77.0 and reject 2.0.77.1; they also reject major zero, the tested newer versions/nonzero flag and the original 1.2.0 build-0..27 interval. This constructor-level acceptance does not establish that the rest of a save version or mod set is supported. The separate save-envelope adapter remains restricted to 2.0.77.0/flag 0/empty startup settings.
|
||||
|
||||
## Verification
|
||||
|
||||
- **512 original ARM64 object-graph comparisons** vary guest object and heap offsets, accepted headers, supplied/owned targets and stream-ownership values. They compare the complete 1,224-byte constructor output and allocated graph after normalizing reader, self, heap and vtable pointers. Register and unallocated-memory guards pass.
|
||||
- **9 short-header cases**, **8 original version-error branches**, all **12 allocation-failure boundaries**, and exact heap capacity pass. Public wrapper outputs remain unchanged on failure.
|
||||
- **4,096 native zero-vector comparisons** cover pair/single stores, v31, positive/negative offsets, pre/post writeback, branches, merges and loops; four invalid vector cases fail closed.
|
||||
- Prior **66,048 instruction comparisons**, **80,000 guest-program comparisons**, **512 TargetDeserialiser graphs** and **20,000 MapHeader comparisons** still pass.
|
||||
- All new constructor/code/data ranges match complete REA observations. The checker reports this independently of behavioral comparisons.
|
||||
- Build 5's controlled and actual-save initialization reports pass on the iPhone, alongside same-launch TargetDeserialiser, version and modern/legacy MapHeader checks. The actual save's header offset and raw tick values still match the existing desktop result, and all save reports share the same input hash and probe ID.
|
||||
- The signed binary has no Steam dependency/import and contains none of the desktop original-code oracle entry symbols.
|
||||
|
||||
The desktop oracle redirects declared BL services and relocates the pool's vtable ADRP/ADD reference. Its version-error service aborts before exception construction, matching the guest adapter's selected stopping point. Tests therefore compare original initialization and branch decisions, not native C++ exception semantics.
|
||||
|
||||
## Reproduce
|
||||
|
||||
```sh
|
||||
python3 tools/build_target_deserialiser.py build/factorio.arm64
|
||||
python3 tools/build_deserialiser.py build/factorio.arm64
|
||||
python3 tests/check_a64_zero_vectors.py
|
||||
python3 tests/check_a64_initialization.py
|
||||
python3 tests/check_a64_program.py
|
||||
python3 tools/build_map_header.py build/factorio.arm64
|
||||
python3 tools/check_initialization_rea.py build/factorio.arm64 evidence/deserialiser-final.json
|
||||
python3 tools/package_ios.py
|
||||
```
|
||||
|
||||
Generated artifacts and verification reports live under `build/deserialiser/`. After signing, installing, launching and downloading the seven `iphone-*-result.json` reports, `python3 tools/check_deserialiser_device.py` verifies build identity, common launch/probe/input identities and the signed binary, writing `device-verification.json`.
|
||||
|
||||
Next: translate MapGenSettings and the following Map::loadData dependencies, then connect these isolated verified components into a persistent loader. Full static-image mapping, indirect calls, object references, destruction/unwinding, simulation, graphics, sound and touch controls remain ahead.
|
||||
Reference in new issue
Block a user