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,53 @@
|
||||
// macOS-only MTLDevice properties, added to the device's concrete class before the game starts.
|
||||
// Values describe a built-in Apple GPU. Other selectors iOS lacks are logged and answer zero.
|
||||
#import <Metal/Metal.h>
|
||||
#import <objc/runtime.h>
|
||||
#import "fx.h"
|
||||
|
||||
static id fx_zero(id self, SEL _cmd, ...) { return nil; }
|
||||
static BOOL fx_no(id self, SEL _cmd) { return NO; }
|
||||
static BOOL fx_yes(id self, SEL _cmd) { return YES; }
|
||||
static NSUInteger fx_uint_zero(id self, SEL _cmd) { return 0; }
|
||||
static NSUInteger fx_uint_one(id self, SEL _cmd) { return 1; }
|
||||
|
||||
static void fx_add(Class cls, const char *name, IMP imp, const char *types) {
|
||||
SEL sel = sel_registerName(name);
|
||||
if (!class_getInstanceMethod(cls, sel)) {
|
||||
class_addMethod(cls, sel, imp, types);
|
||||
fx_log("[fx] Metal compat: -[%s %s]", class_getName(cls), name);
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL (*fx_original_resolve)(id, SEL, SEL);
|
||||
static BOOL fx_device_resolve(id cls, SEL _cmd, SEL sel) {
|
||||
if (fx_original_resolve && fx_original_resolve(cls, _cmd, sel)) return YES;
|
||||
const char *name = sel_getName(sel);
|
||||
if (name[0] == '_' || name[0] == '.') return NO;
|
||||
fx_log("[fx] Metal compat: unknown -[%s %s] -> 0", class_getName(cls), name);
|
||||
class_addMethod(cls, sel, (IMP)fx_zero, "@@:");
|
||||
return YES;
|
||||
}
|
||||
|
||||
FX_EXPORT void fx_patch_metal(void) {
|
||||
id<MTLDevice> device = MTLCreateSystemDefaultDevice();
|
||||
if (!device) { fx_log("[fx] no Metal device"); return; }
|
||||
Class cls = object_getClass(device);
|
||||
fx_log("[fx] Metal device %s (%s), unified memory %d", device.name.UTF8String, class_getName(cls), device.hasUnifiedMemory);
|
||||
fx_add(cls, "isDepth24Stencil8PixelFormatSupported", (IMP)fx_no, "B@:");
|
||||
fx_add(cls, "isLowPower", (IMP)fx_no, "B@:");
|
||||
fx_add(cls, "isHeadless", (IMP)fx_no, "B@:");
|
||||
fx_add(cls, "isRemovable", (IMP)fx_no, "B@:");
|
||||
fx_add(cls, "location", (IMP)fx_uint_zero, "Q@:"); // MTLDeviceLocationBuiltIn
|
||||
fx_add(cls, "locationNumber", (IMP)fx_uint_zero, "Q@:");
|
||||
fx_add(cls, "maxTransferRate", (IMP)fx_uint_zero, "Q@:");
|
||||
fx_add(cls, "peerGroupID", (IMP)fx_uint_zero, "Q@:");
|
||||
fx_add(cls, "peerIndex", (IMP)fx_uint_zero, "I@:");
|
||||
fx_add(cls, "peerCount", (IMP)fx_uint_one, "I@:");
|
||||
fx_add(cls, "supportsBCTextureCompression", (IMP)fx_no, "B@:");
|
||||
fx_add(cls, "areProgrammableSamplePositionsSupported", (IMP)fx_yes, "B@:");
|
||||
Method resolve = class_getClassMethod(cls, @selector(resolveInstanceMethod:));
|
||||
fx_original_resolve = (BOOL (*)(id, SEL, SEL))method_getImplementation(resolve);
|
||||
// Overrides only this concrete class; inherited NSObject behavior is kept via fx_original_resolve.
|
||||
if (!class_addMethod(object_getClass(cls), @selector(resolveInstanceMethod:), (IMP)fx_device_resolve, "B@::"))
|
||||
method_setImplementation(resolve, (IMP)fx_device_resolve);
|
||||
}
|
||||
Reference in new issue
Block a user