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.
83 lines
4.4 KiB
C
83 lines
4.4 KiB
C
#include "deserialiser_bridge.h"
|
|
#include "deserialiser_host.h"
|
|
#include <string.h>
|
|
|
|
static int range(wasm_rt_memory_t *ram,uint64_t address,uint64_t size) {
|
|
return size<=ram->size && address<=ram->size-size;
|
|
}
|
|
static uint64_t get(const uint8_t *memory,uint64_t at) {
|
|
uint64_t value;memcpy(&value,memory+at,8);return value;
|
|
}
|
|
u32 w2c_deser__host_allocate(struct w2c_deser__host *env,u32 context) {
|
|
wasm_rt_memory_t *ram=w2c_factorio__deser_memory(env->module);
|
|
if (!range(ram,context,256) || env->heap.memory!=ram->data || env->heap.memory_size!=ram->size) return 2;
|
|
uint64_t pointer;int status=factorio_guest_heap_allocate(&env->heap,get(ram->data,context),&pointer);
|
|
if (status) return status==1 ? 5 : 2;
|
|
memcpy(ram->data+context,&pointer,8);return 0;
|
|
}
|
|
u32 w2c_deser__host_read_or_throw(struct w2c_deser__host *env,u64 source,u64 destination,u64 size) {
|
|
wasm_rt_memory_t *ram=w2c_factorio__deser_memory(env->module);
|
|
if (!range(ram,source,16) || !range(ram,destination,size)) return 2;
|
|
uint64_t stream=get(ram->data,source+8);
|
|
if (!range(ram,stream,24)) return 2;
|
|
uint64_t data=get(ram->data,stream),length=get(ram->data,stream+8),cursor=get(ram->data,stream+16);
|
|
if (!range(ram,data,length)) return 2;
|
|
if (cursor>length || size>length-cursor) return 1;
|
|
memmove(ram->data+destination,ram->data+data+cursor,(size_t)size);
|
|
cursor+=size;memcpy(ram->data+stream+16,&cursor,8);++env->reads;return 0;
|
|
}
|
|
u32 w2c_deser__host_zero_memory(struct w2c_deser__host *env,u64 destination,u64 size,u64 ignored) {
|
|
(void)ignored;wasm_rt_memory_t *ram=w2c_factorio__deser_memory(env->module);
|
|
if (!range(ram,destination,size)) return 2;
|
|
/* The selected bzero service may initialize live arena bytes only. */
|
|
if (destination<env->heap.begin || destination>env->heap.cursor || size>env->heap.cursor-destination) return 2;
|
|
memset(ram->data+destination,0,(size_t)size);++env->zero_calls;return 0;
|
|
}
|
|
u32 w2c_deser__host_unsupported(struct w2c_deser__host *env,u64 a,u64 b,u64 c) {
|
|
(void)a;(void)b;(void)c;++env->unsupported_calls;return 6;
|
|
}
|
|
u32 w2c_deser__host_unsupported_delete(struct w2c_deser__host *env,u64 a,u64 b,u64 c) {
|
|
return w2c_deser__host_unsupported(env,a,b,c);
|
|
}
|
|
u32 w2c_deser__host_unsupported_length(struct w2c_deser__host *env,u64 a,u64 b,u64 c) {
|
|
return w2c_deser__host_unsupported(env,a,b,c);
|
|
}
|
|
u32 w2c_deser__host_unsupported_array_length(struct w2c_deser__host *env,u64 a,u64 b,u64 c) {
|
|
return w2c_deser__host_unsupported(env,a,b,c);
|
|
}
|
|
u32 w2c_deser__host_version_error(struct w2c_deser__host *env,u64 a,u64 b,u64 c) {
|
|
(void)a;(void)b;(void)c;++env->version_errors;return 7;
|
|
}
|
|
|
|
int factorio_deserialiser_probe(const uint8_t *prefix,size_t length,FactorioDeserialiserProbe *out) {
|
|
if (!prefix || !out) return 2;
|
|
if (!wasm_rt_is_initialized()) wasm_rt_init();
|
|
w2c_factorio__deser module;
|
|
struct w2c_deser__host env={.module=&module};
|
|
wasm2c_factorio__deser_instantiate(&module,&env);
|
|
wasm_rt_memory_t *ram=w2c_factorio__deser_memory(&module);uint8_t *memory=ram->data;
|
|
memset(memory,0xa5,(size_t)ram->size);
|
|
uint64_t registers[32]={0};registers[0]=4096;registers[1]=512;registers[31]=ram->size-256;
|
|
uint64_t stream[3]={16384,length<9 ? length:9,0};
|
|
memcpy(memory,registers,sizeof(registers));memcpy(memory+512,stream,sizeof(stream));
|
|
memcpy(memory+16384,prefix,(size_t)stream[1]);
|
|
int status=factorio_guest_heap_init(&env.heap,memory,ram->size,131072,196608);
|
|
if (!status) status=(int)w2c_factorio__deser_run(&module,0,10000);
|
|
if (!status) {
|
|
FactorioDeserialiserProbe result={0};uint64_t version=get(memory,4096+24),target=get(memory,4096+40);
|
|
result.version=(FactorioMapVersion){version>>48,(version>>32)&65535,(version>>16)&65535,version&65535,memory[4096+32]};
|
|
result.allocations=env.heap.allocations;result.reads=env.reads;
|
|
result.heap_bytes=env.heap.cursor-env.heap.begin;result.stream_cursor=get(memory,528);
|
|
result.owns_target=memory[4096+0x4c6];
|
|
if (!range(ram,target,144) || target<env.heap.begin || target>env.heap.cursor-144 ||
|
|
result.allocations!=12 || result.reads!=5 || env.zero_calls!=1 || env.unsupported_calls ||
|
|
result.stream_cursor!=9 || result.owns_target!=1 || memory[4096+16]!=1 || get(memory,0)!=4096) status=8;
|
|
if (!status) {
|
|
result.target_capacity=(unsigned)get(memory,target+32);
|
|
if (result.target_capacity!=64) status=8;
|
|
else *out=result;
|
|
}
|
|
}
|
|
wasm2c_factorio__deser_free(&module);return status;
|
|
}
|