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.
52 lines
2.8 KiB
Objective-C
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;
|
|
}
|
|
}
|