Native Porting of NS Games to Apple ARM
Aim to make the original game code produce visible, interactive, and savable results on the target device. While both share ARM64 CPUs, reducing the need for instruction translation, OS ABI, memory, threading, graphics, audio, and input compatibility layers are still required.
Language and Architecture Requirements
- New porting cores must be written in Rust (
.rs), using a Cargo workspace to separate resource parsing, shared ABI, offline rewriting, shader conversion, and host runtime. Reuse existing Rust projects directly; integrate existing C/C++ native modules through explicit FFI boundaries—do not rewrite verified modules just for language uniformity. Follow and document any differences when the user explicitly specifies a different technology stack. - Swift is used for launchers and Apple platform UI; Objective-C/Objective-C++, C/C++ for essential system bridging or existing native libraries; AArch64 assembly is limited to entry points, register saving, and call trampolines; Metal Shading Language (MSL) for GPU programs. Python/Bash are only for orchestrating resource preparation, building, signing, and diagnostics—they must not carry frame-by-frame playback or guest execution hot paths.
- The roadmap is: local resource parsing → AArch64 offline rewriting → native execution of original game machine code → Horizon/SDK compatibility → NVN command recording and Metal playback. Preserve the original game logic; do not replace porting with gameplay rewrites, host demo scenes, or mere API stubs.
- Before starting implementation or reusing across games, read architecture-and-workflow.md to determine module boundaries, game version configuration, and the shortest vertical validation path. This reference is distilled from an actual Rust/Cargo-based porting structure and does not require the original project to exist locally.
Getting Started
- Locate the target repository from the user-specified directory or current workspace; reference repositories are only read if provided or discovered in the current workspace—do not assume any developer's local path. Read the target repository's description, local AGENTS.md, Git status, build entry points, and latest validation records. First confirm whether the user wants to implement, diagnose, or just assess; keep assessment tasks read-only.
- Establish an input matrix: game/Title ID, base/update/DLC, display version, NPDM architecture, actual NSO module build IDs, target OS/chip, source version, and execution method. Base this on actually extracted modules—do not infer AArch64 from file names or game names.
- Stick to the defined roadmap. When an existing native compatibility layer is available, reuse the extraction, rewriting, host, and Metal architecture, comparing module-by-module; do not directly copy address patches from other games. For new projects, first check for reusable compatibility layers before estimating the workload. AArch32 input is not suitable for this AArch64 direct execution path; look for an appropriate existing version from the user or clarify that a different execution path is needed.
- First select a repeatable minimal validation path: boot → title/menu → scene → interaction → normal exit → new process loading a save. Progressively address one real blocker at a time, using logs, code, and visuals to determine the cause.
Read References by Issue Type
- Code loading, patching, Horizon ABI, threading, and platform deployment: read runtime-and-platforms.md.
- Black screen, graphical artifacts, abnormal terrain/water color, shader, or performance issues: read graphics-and-debugging.md.
- Validation, progress assessment, review, and handover: read validation-and-cases.md. Includes transferable cases and evidence boundaries.
Implementation Closed Loop
- First record the layer where the fault occurs: extraction/identification → instruction rewriting → loading/relocation → SDK/services → command recording → Metal playback/submission → actual window → game behavior.
- Use one falsifiable hypothesis per round, collect minimally necessary evidence, then perform localized fixes. Diagnostic switches are off by default with quantity/size limits; exceptions must include module relative positions, request, or resource information—never leak keys.
- Choose appropriate verification for low-level semantic fixes: instruction equivalence, ABI layout, concurrency, real GPU readback. After static checks and builds, run the actual game as authorized by the user; if the user prohibits testing, only document "not yet verified"—do not run without permission.
- The source code, build, installation package, run ID, logs, and screenshots for a given version must be linkable. A new build cannot use logs from an old device to prove success.
- Keep diagnostic counterexamples; update current conclusions. Frame-capturing or single-stepping may change timing; after a fix, re-test with a new process where diagnostics are turned off and re-enabled. Do not hardcode character height, water color, collision, or game progress just to eliminate superficial anomalies.
- For unknown services, instructions, or formats, leave clear failure information; only implement semantic degradation when it is proven that the caller allows degradation. Do not universally return success to mask unimplemented functionality.
Resources and Delivery
- Keep source packages, keys, and firmware local; do not write key values into command arguments, logs, or repositories. Do not copy these into the skill. Retain original author licenses and copyright notices.
- User source packages are read-only; extracted content, rewritten modules, caches, saves, and logs use a separate, ignored data directory. Isolate by game and version—do not overwrite other emulator states; source rollback must not delete user saves.
- Caches must recognize changes in input build IDs, rewriter/converter versions, platform, and compilation options. Reject unknown or mixed versions before entering guest code.
- Build, sign, and validate separately for macOS and iOS/iPadOS. A successful install script only proves that phase succeeded; report results for iPhone, iPad, simulator, and Mac separately.
- A local iOS build may contain rewritten game code; before delivery or release, check the app bundle contents and licenses, and only distribute content you have the rights to distribute. Do not automatically upload local derivative builds.
Completion report explains: what was modified, what step was actually executed, which build and device the evidence corresponds to, what limitations remain, and which blocker should be verified next. Avoid unverifiable completion percentages or claims of "full compatibility."