Files
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

52 lines
2.8 KiB
Objective-C

// Decodes every PNG under a directory with pngdecode.c and with macOS ImageIO (which yields
// exact non-premultiplied samples on macOS) and requires byte-identical results.
// Usage: png_parity DATA_DIR
#import <Foundation/Foundation.h>
#import <ImageIO/ImageIO.h>
#import <QuartzCore/QuartzCore.h>
#include "pngdecode.h"
int main(int argc, char **argv) {
@autoreleasepool {
NSString *root = @(argv[1]);
long checked = 0, fallback = 0, mismatched = 0, skipped = 0;
double tw = 0, ti = 0; long px = 0;
for (NSString *rel in [NSFileManager.defaultManager enumeratorAtPath:root]) {
if (![rel hasSuffix:@".png"]) continue;
NSData *data = [NSData dataWithContentsOfFile:[root stringByAppendingPathComponent:rel]];
uint8_t *mine; int w, h, ch;
double t0 = CACurrentMediaTime();
int ok = fx_png_decode(data.bytes, data.length, &mine, &w, &h, &ch);
double t1 = CACurrentMediaTime();
if (!ok) { fallback++; continue; }
CGImageSourceRef src = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
CGImageRef img = CGImageSourceCreateImageAtIndex(src, 0, NULL);
CFDataRef ref = CGDataProviderCopyData(CGImageGetDataProvider(img));
double t2 = CACurrentMediaTime();
tw += t1 - t0; ti += t2 - t1; px += (long)w * h;
size_t bpp = CGImageGetBitsPerPixel(img) / 8, row = CGImageGetBytesPerRow(img);
CGImageAlphaInfo a = CGImageGetAlphaInfo(img);
if (CGImageGetBitsPerComponent(img) != 8 || (CGImageGetBitmapInfo(img) & kCGBitmapByteOrderMask) ||
a == kCGImageAlphaPremultipliedLast || a == kCGImageAlphaPremultipliedFirst || a == kCGImageAlphaFirst ||
a == kCGImageAlphaNoneSkipFirst) { skipped++; goto next; }
// Compare the channels AppKit would expose (drop ImageIO's padding byte for RGBX).
for (int y = 0; y < h && !mismatched; y++)
for (int x = 0; x < w; x++) {
const uint8_t *r = CFDataGetBytePtr(ref) + y * row + x * bpp, *m = mine + ((size_t)y * w + x) * ch;
if (memcmp(r, m, ch)) {
NSLog(@"MISMATCH %@ at %d,%d ch=%d", rel, x, y, ch);
mismatched++;
break;
}
}
checked++;
next:
CFRelease(ref); CGImageRelease(img); CFRelease(src); free(mine);
}
NSLog(@"checked %ld identical-format images, %ld mismatched, %ld skipped (ImageIO layout), %ld fallback to ImageIO",
checked, mismatched, skipped, fallback);
NSLog(@"%.0f Mpx: wuffs %.2fs (%.0f Mpx/s), ImageIO %.2fs (%.0f Mpx/s)", px / 1e6, tw, px / 1e6 / tw, ti, px / 1e6 / ti);
return mismatched ? 1 : 0;
}
}