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,68 @@
|
||||
"""Exercise native ZIP/zlib header reading, including malformed archives."""
|
||||
import io
|
||||
import json
|
||||
import struct
|
||||
import subprocess
|
||||
import tempfile
|
||||
import zipfile
|
||||
import zlib
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
HEADER = struct.pack('<4HB', 2, 0, 77, 0, 0)
|
||||
|
||||
|
||||
def archive(entries, method=zipfile.ZIP_DEFLATED, stream=False):
|
||||
class NonSeeking(io.BytesIO):
|
||||
def seekable(self): return False
|
||||
def seek(self, *args): raise OSError('streaming archive')
|
||||
buffer = NonSeeking() if stream else io.BytesIO()
|
||||
with zipfile.ZipFile(buffer, 'w', compression=method) as output:
|
||||
for name, contents in entries:
|
||||
output.writestr(name, contents)
|
||||
return buffer.getvalue()
|
||||
|
||||
|
||||
def probe(contents, status, label):
|
||||
with tempfile.TemporaryDirectory() as folder:
|
||||
path = Path(folder) / 'save.zip'
|
||||
path.write_bytes(contents)
|
||||
result = subprocess.run([str(ROOT / 'build/version/save_probe'), str(path)], capture_output=True, text=True)
|
||||
actual = json.loads(result.stdout)
|
||||
assert actual['status'] == status, (label, actual, status, result.stderr)
|
||||
assert result.returncode == (1 if status else 0), (label, result.returncode)
|
||||
if not status:
|
||||
assert [actual[k] for k in ('major', 'minor', 'patch', 'build', 'flag')] == [2, 0, 77, 0, 0]
|
||||
print('PASS:', label)
|
||||
|
||||
|
||||
payload = zlib.compress(HEADER + bytes(10000))
|
||||
for method in (zipfile.ZIP_STORED, zipfile.ZIP_DEFLATED):
|
||||
probe(archive([('world/level.dat0', payload)], method), 0, f'outer method {method}, nested zlib')
|
||||
probe(archive([('world/level.dat0', payload)], stream=True), 0, 'ZIP data descriptor')
|
||||
probe(archive([('world/level.dat', payload)]), 0, 'legacy level.dat entry name')
|
||||
probe(archive([('world/level.dat', b'invalid'), ('world/level.dat0', payload)]), 0, 'level.dat0 preference')
|
||||
probe(b'not a zip', 2, 'invalid ZIP')
|
||||
probe(archive([('description.json', b'{}')]), 3, 'no level entry')
|
||||
probe(archive([('a/level.dat0', payload), ('b/level.dat0', payload)]), 2, 'ambiguous roots')
|
||||
probe(archive([('world/level.dat0', b'not zlib')]), 5, 'bad inner compression')
|
||||
probe(archive([('world/level.dat0', zlib.compress(HEADER[:8]))]), 6, 'short decompressed header')
|
||||
valid = archive([('world/level.dat0', payload)])
|
||||
probe(valid[:-1], 2, 'truncated end record')
|
||||
changed = bytearray(valid)
|
||||
central = changed.index(b'PK\x01\x02')
|
||||
struct.pack_into('<H', changed, 6, 1)
|
||||
struct.pack_into('<H', changed, central + 8, 1)
|
||||
probe(changed, 4, 'encrypted flag refused')
|
||||
changed = bytearray(valid)
|
||||
changed[30] ^= 1
|
||||
probe(changed, 2, 'local/central name mismatch')
|
||||
changed = bytearray(valid)
|
||||
struct.pack_into('<I', changed, central + 42, 0xfffffffe)
|
||||
probe(changed, 2, 'out-of-file local offset')
|
||||
changed = bytearray(valid)
|
||||
end = changed.rindex(b'PK\x05\x06')
|
||||
struct.pack_into('<H', changed, end + 10, 0xffff)
|
||||
struct.pack_into('<H', changed, end + 8, 0xffff)
|
||||
probe(changed, 4, 'ZIP64 sentinel refused')
|
||||
print('PASS: 15 archive cases; only the bounded version prefix is validated')
|
||||
Reference in new issue
Block a user