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:
SashaGoncharov19 committed 2026-10-23 15:27:58 +04:00
commit 51d085e865
89 files changed
+7999

No files matched your search

+42
View File
@@ -0,0 +1,42 @@
# Factorio iPhone port: initial investigation
Status: two RNG functions, the map-version constructor, and a branching map-header constructor statically translated to WASM and compiled into a native, Steam-free iOS prototype. The prototype reads save-version headers and runs on the connected iPhone 15 Pro. No playable game port implemented. See static-translation.md, world-loading.md and translation-progress.md for reproduction and exact validation scope.
## Installed target
- Steam installation: `~/Library/Application Support/Steam/steamapps/common/Factorio/factorio.app`.
- Version: 2.0.77, read from the installed Info.plist.
- Executable SHA-256: `00b014d78df07e05ab1cee853904c8f7b3814ca652c043461a9d49fbad46cdf6`.
- REA identifies a universal Mach-O with x86_64 and arm64 slices.
- Selected ARM64 slice: offset 106659840, size 101261968 bytes; build platform MACOS, minimum OS 11.0, SDK 11.0.
- Adjacent `factorio.dSYM/Contents/Resources/DWARF/factorio` exists. Its ARM64 UUID matches the inspected executable: `EBA8DC1C-9981-3657-8656-16F6A8424198`. Full type/source metadata recovery has not been performed.
## Porting implications
The ARM64 slice is a macOS executable, not an iOS executable. Its dependency inventory includes AppKit, Cocoa, Carbon, ForceFeedback, desktop OpenGL/OpenCL/OpenAL, and `@loader_path/libsteam_api.dylib`. A platform marker change or IPA wrapper alone cannot replace these interfaces.
Metal and GameController are also linked. This is evidence of dependencies only; it does not establish the renderer's architecture, active execution paths, or reusable source availability.
A source-based port needs an iOS build of the simulation engine plus platform adapters for application lifecycle, graphics presentation, audio, touch/controller input, writable storage, threading and networking. Dependencies must be built for iOS. The existing Lua/data files do not by themselves provide a replacement for the native engine.
A binary-based reconstruction first needs focused recovered interfaces and behavior specifications. Pseudocode is not original C++ and does not by itself produce a buildable engine. Save compatibility, multiplayer determinism, mod support and performance remain unverified.
## Implementation milestones
1. Binary reconstruction is the selected path. The RNG prototype establishes a bounded translation pipeline; recover startup and simulation dependencies next.
2. Build an iOS application hosting an engine boundary, with Metal presentation and touch commands. A shell alone must not be presented as a Factorio port.
3. Implement and validate one vertical slice: load a small world, advance simulation, display entities, place a miner and transport its output.
4. Validate save/load, deterministic behavior where required, device memory, sustained frame rate and thermal behavior on a specified iPhone.
5. Expand features only after the vertical slice works.
## Evidence and checks
`rea-evidence.json` is the exported REA bundle. Mach-O inspection parent: `ev_83862cd660d0d09fdefd22e0fe60f714fd098b266c655142eb1a30a812ebbefc`. Architecture, build metadata and dependency pages were inspected. Import/export completeness is explicitly not guaranteed by REA; symbol counts do not prove recovered functions or complete source.
`xcodebuild -showsdks` lists iOS 26.5 and iOS Simulator 26.5 SDKs. Unsigned and locally signed device builds compile. The app is installed and running on the iPhone 15 Pro. The macOS native equivalence harness passes 876,544 RNG calls, 1,024 RNG seed constructor calls and 20,000 map-version constructor comparisons; unsupported code and changed source bytes are rejected. The phone's native map-version self-test and generated ZIP probe also pass.
The initial REA procedure search failed because the Hopper launcher relies on Spotlight. A reversible `/Applications/Hopper Disassembler.app` symlink to the existing user-installed app resolves vendor-helper discovery. No indexing settings or saved MCP client or REA configuration were changed. Full analysis took 5m27s, exceeding the original MCP session's 120s startup timeout and leaving retained cleanup state; the generated document was manually closed. The Hopper demo cannot save databases. A separate MCP client with a 600s timeout uses a locally extracted, unmodified ARM64 slice (`build/factorio.arm64`, SHA-256 `2cb4de127b50d54c6c5666acfef2263fae16d11a3361ad39353ecf8a66a4d9c7`) for focused function evidence. See evidence files for the actual success/failure of each operation.
Steam integration is excluded from the target. Current artifact import and dependency checks pass. Whole-game Steam exclusion remains dependent on lifting the engine and verifying the local startup graph; see [steam-boundary.md](steam-boundary.md).
The longer isolated REA run succeeded. Canonical function Evidence is retained in `evidence/factorio-functions-final.json`; `tools/check_rea_rng.py` confirms all three code/constant ranges match the original installed binary's ARM64 slice. The successful isolated session was saved to `build/factorio-rea.snapshot.json` and closed. Its results identify an inlined Steam startup path in `GlobalContext::init`, so omitting only the standalone Steam factory would be incomplete.