iOS developer.Apps, tools, and open‑source software.
I build apps, make tools for creative projects, and contribute to Godot. Sometimes that involves ferry schedules. Sometimes it involves making a Nintendo Switch draw pictures.
Prismark
Listening app for iPhone, iPad and iPhone Duo. On the App Store.
Listen to any text like a podcast. You can share an article from Safari into Prismark and listen to it. A real, seekable timeline, background playback, and lock-screen controls. Speech is rendered up to ten minutes ahead of where you’re listening, so a long sentence or a locked screen doesn’t interrupt it. On iPhone Duo it opens into a two-page reader, with its own layout for the cover screen.
Washington State Ferries for iPhone and Apple Watch. On the App Store.
Know which ferry to catch on the largest ferry system in the US. Live schedules, vessel positions, and capacity, organized around the trip you’re making. The watch interface is tested across screen sizes and the situations riders actually meet: delays, cancellations, low tides, changing capacity, and the last sailing of the day.
A live four-color camera inspired by the Game Boy Camera. Make your own palettes, apply the same dithering to photos you already have, and export pixel-perfect images for Game Boy projects.
Uses feels-like temperature, rain, and air quality to decide when opening the windows will cool your home. One decision engine powers the iPhone and Apple Watch apps, plus nine widget and complication families that update from a cached forecast.
A compass that points to places you choose, with saved locations synced between iPhone and Apple Watch. Built as a personal tool, it is also used by the Northeast Rail Feed Association to align radio antennas.
Draws imported images in Tomodachi Life: Living the Dream on Switch 1 and 2, without modifying the console. A desktop converter matches the game’s palette and plans brush strokes and fills. A Raspberry Pi Pico then draws the picture by sending controller inputs over USB.
Live vessel positions and complete schedules for every Washington State Ferries route, designed for an e-ink display. Each screen is rendered remotely with no client runtime and kept under 100 KiB. The experiment that grew into Aweigh.
Draws the live marine layer over a full-screen map of San Francisco Bay using the HRRR weather model. Optional terrain, neighborhood conditions, and warmest and coolest spots turn changing weather into e-ink cartography.
Godot Engine is a free and open-source engine used to ship 2D and 3D games on every major platform. I have 10 merged pull requests in its core engine, primarily improving Apple platform support across both current and legacy releases.
120Hz support for iPhone and iPad
Godot capped iOS exports at 60 frames per second even on ProMotion devices. Added a project setting that lets games use 120Hz without maintaining a custom engine build.
Technical detail
Added display/window/ios/allow_high_refresh_rate, used it to configure CADisplayLink for 120fps, and added CADisableMinimumFrameDurationOnPhone to the exported app’s property list. Apple requires both the display-link configuration and property-list opt-in.
Godot games on iOS did not receive the pause and resume events needed to save state when the app entered the background. Added those signals on iOS and consistent focus events across iOS and Android.
Technical detail
Wired Godot’s MainLoop to UIKit’s applicationDidEnterBackground and applicationWillEnterForeground delegates, emitting NOTIFICATION_APPLICATION_PAUSED and NOTIFICATION_APPLICATION_RESUMED. Also added matching focus notifications on iOS and Android. The documentation warns developers that iOS allows roughly five seconds to finish work triggered by the pause signal.
For eight years, Godot’s Windows port reported that daylight saving time was always off. Its timezone API could also return an offset one hour wrong while daylight saving time was active.
Technical detail
OS.get_date() hard-coded its dst field to false on Windows, while OS.get_time_zone_info() ignored the Windows API’s separate daylight and standard bias values. Mountain Daylight Time, for example, reported -420 minutes (UTC-7) instead of -360 (UTC-6). The fix selects the active Windows timezone state and applies its corresponding bias.