Skip to content

Latest commit

 

History

9 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MaskPad

Majora's Mask via 2 Ship 2 Harkinian, rebuilt for iPhone and iPad.
Native Metal rendering, customizable touch controls, Files-based setup, and support for keyboards, pointing devices, and iOS game controllers.

Buy me a coffee

MaskPad iOS build iOS 14+ Metal renderer Simulator tested Physical iPad tested ROM not included

MaskPad sword combat on a physical iPad with transparent touch controls

MaskPad packages the full 2 Ship 2 Harkinian source port as a native landscape iOS/iPadOS app. It renders through Metal, imports a user-provided supported Majora's Mask ROM through Files, and adds a phone/tablet touch controller with movable, resizable, and hideable controls.

This repository contains the mobile integration and reproducible build scripts. It does not contain Majora's Mask, a ROM, or a playable ROM-derived archive. See the scoped rights and licensing boundary; it does not relicense third-party projects or game material.

Install status

Option Status What to do
Local Simulator build Verified Best for development, import-flow checks, and UI testing.
Local iPad build Verified locally Configure your own Apple development team and bundle identifier before installation.
Unsigned .ipa Published Download the current ROM-free v0.1.2 IPA, verify its adjacent SHA-256 file, then re-sign it for your own device.
App Store / TestFlight Not announced No listing or public TestFlight currently exists.

The current source has been exercised in iPhone and iPad Simulators and on a 12.9-inch iPad Pro (6th generation) running iPadOS 26.5.2. ROM import, local archive loading, gameplay, touch input, save loading, signing, and in-place updates have been exercised on that hardware. Area-load frame pacing remains under active investigation. Physical Bluetooth, wired, and natural-sleep controller acceptance, rumble, motion, audio-route coverage, and longer thermal tests are still open.

Get started

You need:

  • an Apple Silicon Mac with Xcode and its command-line tools;
  • Homebrew, CMake, Ninja, Git, Python 3, and network access; and
  • your own legally acquired, supported Majora's Mask ROM for gameplay.

Install the host build dependencies:

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

Clone and build:

git clone https://github.com/chrissotraidis/maskpad.git
cd maskpad

scripts/clone-sources.sh
scripts/apply-patches.sh

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

# Generic unsigned iPhoneOS build
scripts/configure-ios.sh --device
scripts/build-ios.sh --device

The default products are:

build-ios-simulator/mm/Release-iphonesimulator/MaskPad.app
build-ios-device/mm/Release-iphoneos/MaskPad.app

See docs/building.md for installation, signing, packaging, and audit commands. Before sharing a build, follow the release checklist.

These commands document the maintained build process; they are not a license grant. Read RIGHTS_AND_LICENSES.md before copying, modifying, or distributing MaskPad-owned work.

First launch

MaskPad never downloads or bundles game data.

  1. Launch MaskPad once so iOS creates its Files-visible folder.
  2. Open Files → On My iPhone/iPad → MaskPad. This Files-visible MaskPad location is the app's Documents folder.
  3. Copy one supported .z64, .n64, or .v64 Majora's Mask ROM into Documents.
  4. Return to MaskPad and select Rescan. Leave it open while local extraction runs.
  5. Later launches load the generated mm.o2r directly.

When using LiveContainer, open MaskPad's application container and put the ROM in its Documents folder. Do not put it in SystemData. Return to MaskPad and select Rescan. This describes the expected file location and does not claim complete LiveContainer compatibility.

The ROM and generated archive stay inside the app's Documents container. They are ignored by Git and rejected by the repository and package audits.

Touch controls

MaskPad ports HarkinianPad's accepted landscape controller and customization model instead of approximating it from screenshots:

  • Left: separate D-pad, control stick, and Z within left-thumb reach.
  • Right: Start, L/R, and transparent A/B/C targets aligned to the native Majora's Mask HUD.
  • Menu: ••• remains available when gameplay controls are hidden.
  • Transparency: enable Touch Control Transparency to reveal a persisted 25%–100% opacity slider. It is off by default and never changes hit targets.
  • Customize: move, resize from 70%–150%, hide/show, reset, and save separate normalized phone and tablet layouts.
  • Safety: opening menus, editing, disabling controls, rebuilding the overlay, or backgrounding releases every held input.
  • Fallback: Legacy Fixed Touch Controls keeps the non-customizable UIKit presentation.

For controller gyro aiming, first add the controller's motion sensor under Settings → Controls → Gyro. Majora's Mask also requires Enhancements → Camera → First Person → Gyro Aiming to be enabled.

MaskPad keeps 2S2H/libultraship's SDL2 controller manager and per-port mapping model. It now reconciles SDL instance IDs and handles at startup, controller add/remove/remap events, foreground resume, and a bounded active check. Valid controllers keep their port; stale handles are closed and cannot be polled; the sole returning controller reclaims port 1; and additional controllers take the next free port without moving port 1. The deterministic regression covers missed removal with held button/axis state and foreground recovery. Physical Bluetooth, wired, natural-sleep, full-mapping, and two-controller acceptance remain hardware gates.

Touch control 2S2H binding
Control stick W/A/S/D, including diagonals
D-pad T/F/G/H
A / B X / C
L / Z / R E / Z / R
Start Space
C buttons Arrow keys
Menu Escape

The ROM-free UI suite verifies every UIKit press/release path and the complete layout editor. A separate user-data-gated suite observes the real PlayState.state.input[0].cur state consumed by 2S2H gameplay. Both suites pass on the representative iPhone and iPad Simulators.

See docs/controls.md for the full behavior contract and docs/touch-control-transparency.md for the opacity behavior. docs/testing.md records the exact test evidence.

Current screenshots

MaskPad exploration on a physical iPad with the complete touch controller MaskPad Clock Town character scene on a physical iPad
Touch-first exploration
The complete landscape controller stays within thumb reach.
Story and minigames
Transparent targets preserve the original HUD and scene.
MaskPad Clock Town gameplay on a physical iPad MaskPad Stock Pot Inn dialogue on a physical iPad
Clock Town
Native Metal rendering across busy outdoor areas.
Full adventure
Dialogue, items, saves, and touch input in the signed iPad build.

The hero and gallery were captured from the current signed build on a physical 12.9-inch iPad Pro (6th generation) running iPadOS 26.5.2, using ignored, user-owned game data. No ROM or generated game archive is present in this repository. Capture provenance is recorded in docs/readme/README.md.

What works

Area Current result
Native app Full 2S2H app builds for arm64 iOS/iPadOS 14+
Rendering Metal gameplay renders in Simulator and on physical iPad
Game setup Files-visible ROM discovery and local mm.o2r generation work
Touch Stick, D-pad, A/B/Z, C buttons, shoulders, Start, persistent menu, and adjustable opacity
Layout editor Move, resize, hide/show, reset, safe-area clamp, and device-class persistence
Lifecycle Input, game simulation, audio, rendering, and configuration pause while iOS is inactive and restore on return
Input options Touch plus existing keyboard, pointer, and SDL controller paths
Packaging ROM, generated game data, signing material, and dependency-license audits

For detailed evidence and remaining hardware checks, see docs/remaining-work.md.

Supported game

Game Engine Status
The Legend of Zelda: Majora's Mask 2 Ship 2 Harkinian Supported with a compatible user-owned ROM
The Legend of Zelda: Ocarina of Time Ship of Harkinian Not supported by this app; see HarkinianPad

MaskPad is a native source-port integration, not a general Nintendo 64 emulator.

Reproducible and ROM-free

flowchart LR
    A["MaskPad scripts"] --> B["Pinned official source"]
    B --> C["Maintained iOS patches"]
    C --> D["ROM-free app or unsigned IPA"]
    E["Your supported ROM"] --> F["Files-visible app folder"]
    D --> G["Local extraction"]
    F --> G
    G --> H["Local mm.o2r and gameplay"]
Loading

The compile never reads your ROM. MaskPad pins 2S2H and each relevant submodule, disables upstream push URLs, applies maintained patches, and generates the ROM-free 2ship.o2r. Your ROM is introduced only after app installation.

Create and audit the unsigned package with:

scripts/package-unsigned-ipa.sh
scripts/verify-release.sh artifacts/MaskPad-0.1.2-unsigned.ipa

Alternatively, download the current audited v0.1.2 unsigned IPA and its SHA-256 file. See the installation guide before sideloading it.

The IPA contains the project rights notice and discovered third-party license files. It contains no maintainer certificate, provisioning profile, ROM, or generated mm.o2r, and must be re-signed before standard-device installation.

Frequently asked questions

Where is the IPA?

Download the current ROM-free v0.1.2 unsigned IPA and its SHA-256 file, or build the same package locally with the commands above. It must be re-signed using your own Apple account. See docs/install-ipa.md.

Does this repository include Majora's Mask?

No. You must provide your own legally acquired supported ROM. Do not open issues requesting game data or download links.

Does audio work?

Speaker audio works on the tested physical iPad, although occasional music skips remain under investigation. Headphone, Bluetooth, interruption, and route-change acceptance still need physical-device coverage.

Can I hide touch controls and get them back?

Yes. The persistent ••• button keeps the menu reachable. Open Settings → Controls and toggle Touch Controls.

Does it support controllers?

2S2H's SDL2 controller path is compiled into the app. Automated stale-handle, slot, held-input, and foreground reconciliation tests pass. Physical Bluetooth, wired, natural-sleep, full-mapping, rumble, motion, and two-controller checks remain device-specific verification gates.

Is this an App Store or TestFlight release?

No. App Store, TestFlight, AltStore PAL, and other distribution channels have different signing, review, account, and regional requirements.

What is the licensing status?

Each upstream component retains its own license and copyright. MaskPad-owned integration code, scripts, documentation, artwork, and original patch content are publicly readable but currently carry no license grant. MaskPad is therefore source-available, not broadly redistributable open source. See RIGHTS_AND_LICENSES.md.

Project map

Path Purpose
scripts/clone-sources.sh Fetch and assert pinned upstream revisions
scripts/build-ios.sh Build the configured Simulator or device target
scripts/package-unsigned-ipa.sh Unsigned IPA plus game-data and license audit
scripts/check-repo-safety.sh Fast tracked-asset, history, script, patch, link, and credential gate
patches/ MaskPad changes replayed onto pinned upstream source
docs/building.md Full build, installation, signing, and packaging guide
docs/install-ipa.md Personal re-signing and installation guide
docs/controls.md Touch mapping, editor, Z latch, and native HUD contract
docs/touch-control-transparency.md Persisted opacity setting and visual behavior
docs/testing.md Exact Simulator, gameplay, build, and package evidence
docs/release-checklist.md Source and IPA publication gates
docs/remaining-work.md Evidence ledger and remaining physical gates
docs/readme/ Approved screenshot slots and capture guidance

Generated source trees, builds, artifacts, ROMs, and ROM-derived archives are ignored and must never be committed.

Contributing and support

Use the structured bug report for reproducible platform defects. Read CONTRIBUTING.md before proposing a change and SECURITY.md before reporting a sensitive vulnerability. Never attach or request game data.

Legal and acknowledgements

MaskPad is an unofficial community project and is not affiliated with or endorsed by Nintendo or Harbour Masters. It does not provide the game, ROM downloads, or playable ROM-derived data.

This project builds on 2 Ship 2 Harkinian, libultraship, ZAPDTR, OTRExporter, the Majora's Mask decompilation project, SDL, and their contributors. All projects, copyrights, and trademarks belong to their respective owners.

About

The Legend of Zelda: Majora's Mask via 2 Ship 2 Harkinian, rebuilt for iPhone and iPad.

Topics

Resources

Contributing

Security policy

Stars

46 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages