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.
3.7 KiB
Steam-free single-player target
User-directed scope: exclude Steam integration; retain basic local gameplay. Steam matchmaking, cloud saves, achievements, rich presence, overlay and Steam networking are outside this port's target. The installed macOS game is not modified.
The current translated RNG library and iOS prototype contain no Steam imports or Steam dynamic dependency. tools/build_rng.py rejects Steam undefined symbols; tools/package_ios.py checks both imports and linked libraries before packaging.
Original binary observations
REA Mach-O import inventory observed eleven direct Steam imports, including SteamAPI_Init, callbacks, shutdown and SteamInternal interface acquisition. Import coverage is not exhaustive, and virtual interface calls extend beyond these named imports.
Independent LLVM symbol inspection found SteamContextInterface, SteamContext, and DummySteamContext. REA/Hopper subsequently confirmed the factory disassembly and decompilation. The interface factory is at ARM64 VA 0x100267594 (SteamContextInterface::createContext(bool, bool)). Its observed branches are:
- Nonzero second argument (
w1) selects an object referencingDummySteamContext's vtable. - With the second argument zero, bit zero of the first argument (
w0) branches to a base-interface object at0x100267640, without entering the Steam initialization block. - The other branch contains calls into the Steam path and constructs
SteamContextif initialization succeeds.
Parameter names and caller-level meaning have not yet been established. These observations do not prove full game startup through either optional context. The correct integration point is the factory/interface boundary, not a blanket success-returning replacement for every Steam import.
REA also found that the Steam initialization stub has two observed callers: the factory and GlobalContext::init at 0x100161584. The latter contains an inlined Steam initialization block beginning at 0x100161608. Editing only the out-of-line factory would miss it. At 0x100161604, startup branches on GlobalContext::headlessMode; headless startup constructs the base context without Steam. The graphical port must select local services independently of headless mode, while preserving graphical startup. Whole-function body ranges and complete indirect-reference classification are unavailable from Hopper's public API, so these observations are not a complete reachability proof.
Retained REA evidence
Canonical bundle: evidence/factorio-functions-final.json, ARM64 slice SHA-256 2cb4de127b50d54c6c5666acfef2263fae16d11a3361ad39353ecf8a66a4d9c7.
- Factory dossier:
ev_4ebc9cbefaeb34d2e4f642c8cfa48d5035442aa80f6a438bf6481d215d1fe694. - Steam initialization stub/callers:
ev_c2713194813cae2a2677b7d73a284f9f99b4b9214e59f58cf8ee2a0ffc159f09. - Global startup dossier:
ev_7f2a2b88000ba82d85771c0f368eae9cf0a1f071beb7d73506ba6bbf3c0a22eb. - Base
isSteamApiInitialized()assembly returns zero:ev_0b47cba381075942160840ec0d392a8f05803c3c8a2ebb672bb01c4a282f4a5b.
The interface includes cloud storage, locale, networking, callbacks, on-screen keyboard, stats and achievements. Local replacements must preserve actual method contracts and object layout once lifted callers use them. Returning invented success or a fake Steam identity would hide missing behavior; the port should expose unavailable optional services and use local file storage and native text entry.
Remaining work
Replace the inlined startup integration when that engine function is lifted, audit optional-service checks, and prove no Steam-only branch is reachable from the chosen local startup. A full translated engine does not exist yet, so Steam exclusion has only been verified for the current prototype.