NS ゲームの Apple ARM へのネイティブ移植
元のゲームコードをターゲットデバイス上で視覚的に操作・保存可能な状態にすることを目標とする。CPU が同じ ARM64 でも命令翻訳の作業は減るが、OS ABI、メモリ、スレッド、グラフィック、オーディオ、入力の互換レイヤーは省略できない。
言語とアーキテクチャの要件
- 新規移植コアは Rust(
.rs)で作成し、Cargo workspace を使ってリソース解析、共有 ABI、オフライン書き換え、シェーダー変換、ホストランタイムを分離する。既存の Rust プロジェクトはそのまま再利用する。既存の C/C++ ネイティブモジュールは明確な FFI 境界で接続し、統一言語のために検証済みモジュールを書き換えない。ユーザーが明示的に他の技術スタックを指定した場合はそれに従い、差異を記録する。 - Swift はランチャーと Apple プラットフォーム UI に使用する。Objective-C/Objective-C++、C/C++ は必要なシステムブリッジや既存ネイティブライブラリに使用する。AArch64 アセンブリはエントリポイント、レジスタ保存、コールジャンプ台に限定する。Metal Shading Language(MSL)は GPU プログラムに使用する。Python/Bash はリソース準備、ビルド、署名、診断の編集のみに使用し、フレーム単位の再生やゲストコードのホットパスには使用しない。
- ルートは、ローカルリソース解析 → AArch64 オフライン書き換え → 元ゲームのマシンコードのネイティブ実行 → Horizon/SDK 互換 → NVN コマンド記録と Metal 再生 である。ゲームロジックは変更せず、ゲームプレイの書き換え、ホストデモ画面、または API スタブのみでの移植は行わない。
- 実装開始またはクロスゲームでの再利用前に architecture-and-workflow.md を読み、モジュール境界、ゲームバージョン設定、最短の縦断的検証パスを決定する。このリファレンスは Rust/Cargo の実際の移植構造から抽出されたものであり、元プロジェクトがローカルに存在することを前提としない。
作業開始
- ユーザー指定のディレクトリまたは現在のワークスペースからターゲットリポジトリを特定する。参照リポジトリは、ユーザーから提供されるか現在のワークスペース内で発見可能な場合のみ読み取り、開発者のローカルパスを推定しない。ターゲットリポジトリの説明、ローカル AGENTS.md、Git ステータス、ビルドエントリ、最新の検証記録を読み取る。最初にユーザーが実装、診断、評価のいずれを希望するかを確認する。評価タスクは読み取り専用に留める。
- 入力マトリックスを確立する:ゲーム/Title ID、ベース/アップデート/DLC、表示バージョン、NPDM アーキテクチャ、実際の NSO モジュールの build ID、ターゲット OS/チップ、ソースバージョン、実行方法。実際に抽出したモジュールを基準とし、ファイル名やゲーム名だけで AArch64 を推定しない。
- 既定ルートを維持する。既存のネイティブ互換レイヤーがある場合は、抽出、書き換え、ホスト、Metal のアーキテクチャを再利用し、モジュールごとに比較する。他のゲームのアドレスパッチをそのまま流用しない。新しいプロジェクトではまず再利用可能な互換レイヤーがあるか確認し、工数を決定する。AArch32 入力はこの AArch64 直接実行ルートの対象外である。ユーザーに適切なバージョンを探すか、別の実行ルートを明確にする。
- まず反復可能な最短の検証パスを選択する:起動 → タイトル/メニュー → シーン → 操作 → 正常終了 → 新プロセスでのセーブデータ読み込み。段階的に実際のボトルネックを解決し、ログ、コード、画面で原因を確認する。
問題別リファレンスの読み方
- コードロード、パッチ、Horizon ABI、スレッド、プラットフォームデプロイ: runtime-and-platforms.md を読む。
- ブラックスクリーン、描画異常、地形/水色の異常、シェーダーやパフォーマンス問題: graphics-and-debugging.md を読む。
- 検証、進捗判断、振り返り、引き継ぎ: validation-and-cases.md を読む。移行可能なケースと証拠の境界が含まれている。
実装サイクル
- まず障害が発生しているレイヤーを記録する:抽出/識別 → 命令書き換え → ロード/再配置 → SDK/サービス → コマンド記録 → Metal 再生/送信 → 実際のウィンドウ → ゲーム動作。
- 毎ラウンドで反証可能な仮説を立て、最小限の必要な証拠を収集し、局所的な修正を行う。診断スイッチはデフォルトでオフ、数量/サイズの上限あり。例外にはモジュールの相対位置、リクエストまたはリソース情報を含めること。鍵情報を漏洩させてはならない。
- 低レベルの意味的修正には適切な検証方法を選択する:命令等価性、ABI レイアウト、並行性、実際の GPU リードバック。静的チェックとビルド後、ユーザーの許可範囲で実際のゲームを実行する。ユーザーがテストを禁止した場合は未検証として記録し、勝手に実行しない。
- 対応するバージョンのソースコード、ビルド、インストールパッケージ、実行 ID、ログ、スクリーンショットは関連付けられなければならない。新しいビルドを古いデバイスのログで成功と証明してはならない。
- 診断の反例を保持し、現在の結論を更新する。フレームキャプチャやシングルステップはタイミングを変える可能性がある。修正後は診断をオフにした新しいプロセスで再テストする。表面の異常を取り除くために、キャラクターの高さ、水色、衝突、ゲーム進行度をハードコードで変更しない。
- 未知のサービス、命令、フォーマットは明確な失敗情報を残す。呼び出し元がダウングレードを許容することが証明された場合のみ、意味のあるダウングレードを実装する。未実装機能を隠すために一律に成功を返さない。
リソースと成果物
- ソースパッケージ、鍵、ファームウェアはローカルに保持する。鍵値をコマンド引数、ログ、リポジトリに書き込まない。これらの内容をスキルにコピーしない。原作者のライセンスと著作権表示を保持する。
- ユーザーのソースパッケージは読み取り専用とする。抽出内容、書き換えモジュール、キャッシュ、アーカイブ、ログは独立した無視されるデータディレクトリに保存する。ゲームとバージョンで隔離し、他のエミュレータの状態を上書きしない。ソースコードのロールバックではユーザーのセーブデータを削除しない。
- キャッシュは入力の build ID、書き換えツール/変換ツールのバージョン、プラットフォーム、コンパイルオプションの変更を認識できなければならない。不明または混合バージョンはゲストコードに入る前に拒否する。
- macOS と iOS/iPadOS はそれぞれビルド、署名、検証を行う。インストールスクリプトの成功は対応する段階のみを証明する。iPhone、iPad、シミュレータ、Mac の結果はそれぞれ報告する。
- ローカル iOS ビルドには元ゲームの書き換えコードが含まれる場合がある。配信または公開前にアプリケーションパッケージの内容とライセンスを確認し、配信権限のあるものだけを配布する。ローカル派生成果物を自動アップロードしない。
完了報告では以下を説明する:何を変更したか、実際にどこまで実行されたか、証拠がどのビルドとデバイスに対応するか、まだどのような制限があるか、次にどのボトルネックを検証すべきか。検証不能な完了率や「完全互換」といった表現は避ける。