Files
factorio-ios/runtime/deserialiser_bridge.c
T
SashaGoncharov19 51d085e865 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.
2026-10-23 15:27:58 +04:00

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;
}