Appearance
システム構成・エンジン設計
実装の正典は src/engine.s(全ロジック単一ファイル)。本書はその構造の解説です。
ROM / ハードウェア構成
| 項目 | 内容 |
|---|---|
| マッパー | mapper 2(UNROM)・固定バンクのみ使用 |
| PRG-ROM | 128KB(8 × 16KB、全バンク出力・$FF パディング) |
| CHR | CHR-ROM なし。CHR-RAM 8KB にリセット時転送 |
| ミラーリング | 垂直 |
| 画面 | 固定 1 画面(スクロールなし) |
| リンカ設定 | cfg/nes.cfg |
UNROM バス競合
バンク切替時は ROM 上の同アドレス値と一致する値を書き込むこと(lda banktable,x / sta banktable,x 方式)。現状は固定バンクのみで切替コードなし。詳細はビルド手順の備考。
エンジン全体構造(src/engine.s)
リセット
├─ CHR-RAM 転送(フォント / ステージBG / AIスプライト)
├─ パレット設定(BG 4本 + スプライト 4本)
└─ メインループ
├─ nmi_flag 待ち(1フレーム同期)
├─ パッド読み取り(pad_cur / pad_prev / pad_new)
├─ フェーズ進行(phrase_frame → beat_index / beat_frame)
├─ コール表示 or レスポンス判定
├─ フレーズ集計 → 観客増減 → ゲームオーバー判定
└─ 描画要求を ppu_buf に積む
NMI(vblank)
├─ OAM DMA(スプライト転送)
├─ ppu_buf フラッシュ(バッファ経由の PPU 書き込み)
└─ frame_count++ / nmi_flag セットPPU アクセス規約(重要)
初期化後、メインスレッドは $2007 に直接触らない。 すべての PPU 書き込みは ppu_buf に積み、NMI ハンドラが vblank 中にフラッシュする。
ppu_buf容量は 96 バイト — 1 フレームに積める描画量の上限。超過する更新は複数フレームに分割する
タイミング設計
音楽・譜面・判定が同一のフレームカウンタを共有するのが本エンジンの核。構造的に音とズレない。
| 定数 | 値 | 意味 |
|---|---|---|
FRAMES_PER_BEAT | 32 | 112.5 BPM(NTSC 60fps で整数割り) |
| 1 フレーズ | 256 フレーム | 8 拍 = コール 4 拍 + レスポンス 4 拍。phrase_frame(8bit)が自然にラップ |
| 16 分音符 | 8 フレーム | 将来の譜面細分化単位(仕様書 §6) |
判定システム
チューニングは engine.s 冒頭の定数のみで完結する(single point of tuning)。
| 定数 | 値 | 内容 |
|---|---|---|
JUDGE_PERFECT | 4 | 目標拍 ±4 フレーム → PERFECT +100 |
JUDGE_GOOD | 8 | 目標拍 ±8 フレーム → GOOD +50 |
AUD_INIT / AUD_MAX | 8 / 16 | 観客の初期値・上限(0 でゲームオーバー) |
- 振り ID:
MOVE_REST(0)/MOVE_L/MOVE_R/MOVE_U/MOVE_D/MOVE_A/MOVE_B— 譜面(chart)はこの ID 列 - 誤ボタン・無入力は MISS。フレーズ集計(
perfect_cnt/miss_cnt/target_cnt)で観客増減を決定
申し送り(PR #18 レビュー)
「超早入力(判定窓より前の入力)の扱い」「ppu_buf 書き込み順」の 2 件が判定チューニング時の再検討項目。
キャラアニメーション
- 全振り共通: 4 コマ ×
ANIM_STEP_LEN(5) = 20 フレーム固定(拍間 32 フレーム内に収まる) - 接地固定: 足位置は動かさない。ジャンプのみ
pose_dyで Y 方向に浮上(ユーザー確定要件) - アイのポーズ番号は
pose(0〜25 の 26 フレーム) - お手本ガールはアイのスプライトをパレット差し替え + 水平フリップで共用(CHR 節約)
主要 RAM(zeropage)
| 変数 | 役割 |
|---|---|
game_state | 0 = プレイ中 / 1 = ゲームオーバー |
phrase_frame / beat_index / beat_frame | フレーズ内位置(拍 0〜3 コール、4〜7 レスポンス) |
chart_pos / resp_index | 譜面読み取り位置 / 次に判定するレスポンス拍 |
perfect_cnt / miss_cnt / target_cnt | フレーズ集計 |
audience | 観客数 0〜16 |
pose | アイの現在ダンスフレーム(0〜25) |
サウンド設計(仕様書 §6 / 未実装部分)
- 自作最小シーケンサを実装予定(famitone2 不使用)。音楽の行カウンタを判定システムと共有
- チャンネル配分: パルス 2(メロディ + ベース)/ 三角波(キック・ベース)/ ノイズ(ハイハット・スネア)/ SE はノイズ・パルス 1 を一時借用
- 現状は拍頭ビープのみ(コール ~A4 440Hz / レスポンス ~A5 880Hz、
BEEP_*定数)
ビルド・実行
bash
make # build/engine.nes(131,088 バイト)
make run # Mesen2 で起動(要 MESEN 環境変数・GUI セッション)
make hello # 旧 Hello World ROM