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,81 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Record exact local executable and installed data identities, without copying assets."""
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import plistlib
|
||||
import subprocess
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
from lift_rng import arm64_image
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
EXPECTED_BINARY = '00b014d78df07e05ab1cee853904c8f7b3814ca652c043461a9d49fbad46cdf6'
|
||||
EXPECTED_SLICE = '2cb4de127b50d54c6c5666acfef2263fae16d11a3361ad39353ecf8a66a4d9c7'
|
||||
|
||||
|
||||
def digest(path):
|
||||
result = hashlib.sha256()
|
||||
with path.open('rb') as source:
|
||||
for block in iter(lambda: source.read(1024 * 1024), b''):
|
||||
result.update(block)
|
||||
return result.hexdigest()
|
||||
|
||||
|
||||
def command(*args):
|
||||
return subprocess.check_output(args, cwd=ROOT, text=True).strip()
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('app', type=Path)
|
||||
args = parser.parse_args()
|
||||
app = args.app.resolve(strict=True)
|
||||
binary = app / 'Contents/MacOS/factorio'
|
||||
source = binary.read_bytes()
|
||||
image, offset = arm64_image(source)
|
||||
binary_hash, slice_hash = hashlib.sha256(source).hexdigest(), hashlib.sha256(image).hexdigest()
|
||||
if binary_hash != EXPECTED_BINARY or slice_hash != EXPECTED_SLICE:
|
||||
raise ValueError('Target differs from the inspected Factorio 2.0.77 build')
|
||||
info = plistlib.loads((app / 'Contents/Info.plist').read_bytes())
|
||||
assets = app / 'Contents/data'
|
||||
entries = []
|
||||
for path in sorted(assets.rglob('*')):
|
||||
if path.is_symlink():
|
||||
raise ValueError(f'Asset symlink requires explicit inventory policy: {path}')
|
||||
if path.is_file():
|
||||
entries.append({'path': path.relative_to(assets).as_posix(),
|
||||
'bytes': path.stat().st_size, 'sha256': digest(path)})
|
||||
if not entries:
|
||||
raise ValueError('No installed data files found')
|
||||
packages = []
|
||||
for path in sorted(assets.glob('*/info.json')):
|
||||
metadata = json.loads(path.read_text())
|
||||
packages.append({'directory': path.parent.name, 'name': metadata.get('name'),
|
||||
'version': metadata.get('version'), 'dependencies': metadata.get('dependencies')})
|
||||
asset_manifest = {'scope': 'all regular files under installed Contents/data; no user mods or saves',
|
||||
'files': entries, 'file_count': len(entries),
|
||||
'total_bytes': sum(e['bytes'] for e in entries), 'packages': packages,
|
||||
'gameplay_configuration': 'not selected; inventory does not prove save compatibility'}
|
||||
out = ROOT / 'build/target'
|
||||
out.mkdir(parents=True, exist_ok=True)
|
||||
asset_path = out / 'assets.json'
|
||||
asset_path.write_text(json.dumps(asset_manifest, indent=2) + '\n')
|
||||
report = {'recorded_at': datetime.now(timezone.utc).isoformat(), 'app': str(app),
|
||||
'version': info.get('CFBundleShortVersionString'), 'binary_sha256': binary_hash,
|
||||
'arm64_sha256': slice_hash, 'arm64_slice_offset': offset, 'arm64_bytes': len(image),
|
||||
'binary_uuids': command('xcrun', 'dwarfdump', '--uuid', str(binary)).splitlines(),
|
||||
'xcode': command('xcodebuild', '-version'),
|
||||
'iphoneos_sdk': command('xcrun', '--sdk', 'iphoneos', '--show-sdk-version'),
|
||||
'wabt_revision': command('git', '-C', str(ROOT / 'third_party/wabt'), 'rev-parse', 'HEAD'),
|
||||
'asset_manifest_sha256': digest(asset_path), 'asset_file_count': len(entries),
|
||||
'source_files': {str(p.relative_to(ROOT)): digest(p) for base in ('tools', 'runtime', 'platform/ios', 'tests')
|
||||
for p in sorted((ROOT / base).glob('*'))
|
||||
if p.is_file() and p.suffix in ('.py', '.mjs', '.c', '.h', '.m', '.yml')}}
|
||||
(out / 'manifest.json').write_text(json.dumps(report, indent=2) + '\n')
|
||||
print(f'PASS: pinned executable and ARM64 slice; recorded {len(entries)} asset files ({asset_manifest["total_bytes"]} bytes)')
|
||||
print(out / 'manifest.json')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in new issue
Block a user