# HarkinianPad releases no app, because you are meant to compile the port yourself

> HarkinianPad packages the Ship of Harkinian source port as a native iOS app with Metal rendering, touch controls and controller support, and its release page publishes no binary at all. What it ships instead is a pinned dependency manifest, two build scripts, and a dependency list of roughly two dozen Homebrew libraries. Its documentation is also unusually candid about which devices and features have not been tested.

**chrissotraidis/harkinianpad** — Ocarina of Time native on iOS and iPadOS via Ship of Harkinian with Metal rendering, touch controls, controller support, and ROM-free reproducible builds.

- Repository: https://github.com/chrissotraidis/harkinianpad
- Stars: 388 · Forks: 29
- Language: Shell
- License: NOASSERTION
- Published: 2026-09-17 · Updated: 2026-09-17 · Language: en
- Canonical page: https://hysenlabs.com/projects/chrissotraidis-harkinianpad

## The install table has three green rows and two red ones

The status table at the top of the README is the most useful thing in it, because four of the five rows are about what is not available.

Available now: making your own package file with a separate tool, a local build signed with your own Apple development team, and the simulator.

Not available: a computer-free install path. The row explains why in one sentence, and the explanation is correct rather than evasive. The produced package is not an AltStore PAL release, and installing AltStore Classic through PAL does not remove Classic's own requirement for AltServer running on a Mac or a Windows PC. That is a property of how AltStore Classic is designed, and the project declines to pretend otherwise.

Not announced: any App Store listing or public TestFlight build.

Then the sentence that explains the whole shape of the project. Releases publish no app, because the app is compiled from the source-port decompilation, so you make your own.

The easy route is a separate tool that builds from this repository's latest release, takes about fifteen minutes, and saves an unsigned package file into your Downloads folder for a sideloading tool to install. The simulator route is described as best for development and interface testing and explicitly not a substitute for physical-device testing.

So the realistic experience is: install a build tool, compile, sign, sideload. That is a different commitment from downloading something.

## Two dozen Homebrew libraries before you compile a line

The dependency list is the honest first surprise. Before any of this project is involved you need a Mac with Xcode and its command line tools, Homebrew, an Apple ID configured inside Xcode for device signing, and your own legally acquired supported copy of the game.

The libraries are installed in one command:

```sh
brew install cmake ninja pkgconf sdl2 glew nlohmann-json libpng libzip \
  tinyxml2 libogg libvorbis opus opusfile sdl2_net
```

Fourteen packages, and the composition explains the project rather than just its size. There is the build system (CMake with Ninja and pkg-config), the windowing and rendering stack (SDL2, GLEW, and SDL2 networking), a JSON library, an image library, an archive library, an XML library, and three audio codec families plus their container format.

Those audio dependencies are the port's own requirement rather than anything iOS-specific, and they are the part that surprises anyone expecting a Metal app to be self-contained. The port is a desktop source port being cross-compiled for a mobile operating system, and it brings its audio stack with it.

Once those are in place, the automated route is to download the separate build tool, unzip it, and double-click a command file. That is the path the README leads with, and it hides all of the above behind one double-click for people on a Mac who do not want to read a build guide.

## One script, two targets, and an output path you will recognise

Building by hand is three commands and two variables.

```sh
git clone https://github.com/chrissotraidis/harkinianpad.git
cd harkinianpad

# Simulator
scripts/build-ios.sh --simulator

# Physical iPhone or iPad
DEVELOPMENT_TEAM=ABCDE12345 \
BUNDLE_ID=com.yourname.harkinianpad \
scripts/build-ios.sh --device
```

The two variables are the whole signing story. The team identifier is the ten-character string Xcode displays, and the bundle identifier has to be one you own. Neither is a value you invent; both are read out of Xcode.

The device output lands at a path that tells you how the project is arranged, because it is a source port's own build layout with an iOS suffix on the directory:

```text
build-ios-soh/soh/Release-iphoneos/HarkinianPad.app
```

If Xcode needs to register the device or create a provisioning profile, the instructions send you into the generated Xcode project, select the port's target and your device, and set the team under signing settings.

There are two build scripts worth knowing about by name beyond this one. The documentation set includes a complete guide covering simulator, signing, installation, controller and package auditing, a short installation guide for the package you just built, and a release checklist you are told to follow before sharing a build.

Three docs are named earlier and are about the project's own maintenance rather than its use: one on mod compatibility and support priorities, one on source maintenance that records the remaining source-delivery and reproducibility boundaries, and one scoping the rights and licensing position.

## A lock file for source ports is the actual contribution

What this repository contains, stated plainly, is the mobile integration and the pinned build scripts. The port itself lives elsewhere, and this project does not relicense it, does not relicense the third-party projects underneath it, and does not relicense any game material.

What makes the builds repeatable is a single file: a lock manifest in the repository root holding the exact maintained forks and pins the build uses. That is the mechanism. A source port depends on several moving repositories, and a mobile build that pins its inputs to specific revisions is a different proposition from one that tracks the tip of a branch.

The tree supports that reading. There are submodules, a patches directory for changes applied to upstream sources, a sources directory, a version file, a manifest for the external build tool that declares this app, and a tests directory.

The rights position is handled with a dedicated document rather than a licence file, and the repository reports no recognised licence identifier. That combination is coherent for this kind of project: there is no clean licence to grant over someone else's decompilation, so what the project offers instead is a scoped statement of what it does and does not do.

The maintenance documentation takes the same tone, recording the remaining source-delivery and reproducibility boundaries as a document rather than a claim. For an adapter project whose entire job is tracking upstream, that is the right artefact to exist.

## A package audit rejects the file you just put in the folder

Setup on the device is a six-step sequence, and the reason it is manual is stated in the first line: the app never downloads or bundles game data.

You launch it once so the operating system creates the folder it will expose to the Files app. Then you open Files, go to the app on your device, and drop your copy of the game into that folder. The app's own Documents folder is the destination, and there is a specific trap for anyone using a container browser on the device: use the container's Documents folder, not the one named for system data. That single wrong folder is the usual reason a first launch finds nothing.

Back in the app you trigger a rescan, and then you leave it open while it builds a local archive from the ROM. That conversion step takes a while, which is why step five is phrased as an instruction rather than a step.

The last step is starting the game from the on-screen button or from a connected controller.

What happens to your data afterwards is the part worth stating. The original game file and the generated archive stay inside the app's container. Both are ignored by version control, and both are rejected by the repository's package audit, so a build you share cannot accidentally carry them.

That combination of a conversion step, a container-local file and a build-time audit is a coherent answer to the question every ROM-driven app eventually has to answer.

## The test matrix is written as a list of things not yet done

The status paragraphs about hardware testing are the strongest part of this README, because they distinguish what was exercised from what was assumed.

What was exercised: signed builds installed and played on a 12.9-inch iPad Pro of the sixth generation running a named iPadOS version. On that specific hardware, file import, loading the archive on device, touch gameplay, save loading, the settings menu and in-place app updates have all been run.

What has not: physical-device gameplay for the most recent preview's mod-pack changes, which has simulator startup validation only.

Audio has been heard during repeated playtests on that iPad, but headphone output, Bluetooth and recovery from interruption still need a complete device matrix. Controller sleep and reconnect ownership has deterministic regression coverage and a foreground check on physical hardware, while hands-on acceptance for Bluetooth, wired, natural sleep, button mapping, rumble, motion and two-controller use remains open.

Read as a whole, that is a list of specific gaps rather than a hedge. It tells you exactly which device the author used, which features were verified on it, and which claims rest on tests rather than on hardware.

It also tells you that a single iPad model stands behind the current release. Anyone with a phone, a different iPad generation, or a second controller is outside what has been checked, and the project says so rather than leaving you to discover it.

## Touch controls have a customiser and a fallback

The control scheme is laid out by thumb rather than by button, which is the right instinct for a game originally mapped to a controller held in two hands.

On the left of the sideways layout you get a separate directional pad, the analogue stick, and the Z button, all inside the reach of the left thumb. On the right you get Start, R and L, plus the game's own three-button arrangement rendered with transparent touch targets so the visible artwork stays uncluttered while the hit areas stay large.

There is one control that deliberately outlives the rest. The small menu button stays available even when the gameplay controls have been switched off, which is what makes disabling them a usable setting rather than a trap.

Three customisation layers sit on top. A toggle in settings hides and restores the gameplay overlay. A transparency setting reveals a slider from a quarter opacity to full, and the documentation is careful to say it changes opacity and not the touch targets, which is the distinction that matters for a game where you keep mistiming jumps. And a layout customiser lets you move, resize or hide individual controls, with separate phone and tablet arrangements.

Underneath all of that is a fallback: a switch back to the previous fixed, non-customisable control layout, which is the thing to reach for when a custom layout stops being playable.

The behaviour around the menu is also deliberate. Opening it hides the gameplay controls so the settings interface stays usable, and closing it brings them back.

## Against the Android build of the same port

The comparison worth making is not with other iOS apps, because there are none of this kind. It is with the same source port built for a platform where shipping an app is routine.

On Android, a build of this port is a package you download once, install, and update. The code is the same decompilation and the emulator, the graphics API and the control layer are the same. What differs is the delivery: no Mac required, no developer team identifier, no bundle identifier to choose, and no compiler between you and the game.

On iOS that path does not exist, and this project does not pretend otherwise. The Apple toolchain requires a Mac for the build, requires your own signing identity for the device, and produces an unsigned artefact that a third-party sideloading tool has to install. Every re-sign for a new device is a build.

That is a cost, and the project pays it to get a few things the alternative route cannot give: native Metal rendering rather than a screen mirror, a sideways touch layout designed for thumbs rather than an on-screen d-pad, and a Files-based import that keeps your game file inside the app's own container instead of a shared filesystem.

On maintenance, there is one release so far, tagged at the end of September, with the last push on the repository the day before this review. A project whose value is tracking upstream pins does not need a busy release history, and this one is explicitly built around a lock file rather than around shipping binaries.

Read the gaps in the hardware notes as the reason to try it on the device you already own rather than the one you would buy.

## Conclusion

HarkinianPad suits someone with a Mac, an Apple developer team and fifteen minutes who wants Ocarina of Time running on an iPad with Metal rather than a mirrored stream or an emulator, and who is comfortable keeping a build pinned to upstream forks. It does not suit anyone hoping to sideload a download. Verify two things before you start: that the pinned source revisions in the lock file still resolve, because the whole reproducibility argument rests on them, and that the feature you actually want is on the tested list, since controller rumble, Bluetooth and audio interruption recovery are all documented as still open. The single release is v0.2.0, tagged on 2026-09-29, and the last push on the repository was on 2026-10-01.

## FAQ

### Can I play Ship of Harkinian on iOS?

Yes, by way of this repository, which packages the Ship of Harkinian source port as a native iOS and iPadOS app with Metal rendering, touch controls and controller support. It publishes no app binary, so you compile your own build and supply your own legally acquired game file.

### Why does HarkinianPad not ship a prebuilt app?

Because the app is compiled from the source-port decompilation, so you make your own. Releases publish no app. A separate build tool can compile from the latest release into an unsigned IPA in about fifteen minutes, or you can run the build script yourself with a simulator or device target.

### What do I need to build HarkinianPad from source?

A Mac with Xcode and its command line tools, Homebrew, an Apple ID configured in Xcode for signing, and your own supported game file. The library dependencies are CMake, Ninja, pkg-config, SDL2, GLEW, nlohmann-json, libpng, libzip, tinyxml2, libogg, libvorbis, opus, opusfile and SDL2 networking.

### How do I get the game file onto the device in HarkinianPad?

Launch the app once so the system creates its folder, then open the Files app, go to the app on your device and move your game file into that Documents folder. In a container browser use the Documents folder rather than the system-data one. Return to the app, rescan, and leave it open while it builds the local archive.

### Has HarkinianPad been tested on real hardware?

On one device configuration: a 12.9-inch iPad Pro of the sixth generation, where file import, on-device archive loading, touch gameplay, save loading, the settings menu and in-place updates have been exercised. Headphone and Bluetooth audio, interruption recovery, rumble, motion, button mapping and two-controller use are documented as still open.

## Sources

- [chrissotraidis/harkinianpad on GitHub](https://github.com/chrissotraidis/harkinianpad)
- [Issues](https://github.com/chrissotraidis/harkinianpad/issues)
- [README](https://github.com/chrissotraidis/harkinianpad/blob/main/README.md)
- [Releases](https://github.com/chrissotraidis/harkinianpad/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/chrissotraidis-harkinianpad
