ロットロット (FC) 攻略/解析

PRG-ROM

概要

空き領域は全て 0xFF で埋められている。

アドレス内容
$8000codeRESET 割り込みハンドラ。
$802BcodeNMI 割り込みハンドラ。
$8070codeIRQ 割り込みハンドラ。無限ループする (本作では IRQ は使わない)。
$8073codeゲームを開始する。
$80A1code手番のプレイヤーについて現在の面をイントロから開始する。
$8178codeゲームプレイ中の通常のメインループ。
$8200codeミス後の再開処理。
$820Fcode面イントロからの再開処理 (ミス後または面クリア後にここに来る)。
$821Fcode面クリア処理。
$830Acode(未使用) NMI を無効化する。
$830Ecode(未使用) PPU_CTRL ($2000) およびその管理用変数 $00 に値を書き込む。
$8314code(未使用) NMI を有効化する。
$831AcodeNMI スレッドに制御を譲り、完了を待つ。
NMI が無効な場合は次の VBLANK の開始を待つ (が、本作ではブート時を除き NMI は常時有効)。
$8335codeレンダリングを無効化する (事前に NMI を待つ)。レンダリング有効状態 $02 の更新も行う。
$8337codeレンダリングを有効化または無効化する (事前に NMI を待つ)。レンダリング有効状態 $02 の更新も行う。
$8340codeレンダリングを有効化する (事前に NMI を待つ)。レンダリング有効状態 $02 の更新も行う。
$8344code(未使用) ネームテーブルアドレス計算。
$837Ecode矩形データ (塗りつぶし) 転送ルーチン。
$8384code矩形データ (ベタ) 転送ルーチン。
$8388code矩形データ転送ルーチン
$837E, $8384 下請け。
$83CCcode横長の矩形データ転送ルーチン。
$8388 下請け。
$8429code縦長の矩形データ転送ルーチン。
$8388 下請け。
$848BcodePPU データ転送キューへの要素の書き込みを開始する。
$84A0codePPU データ転送キューへ現在の要素内の 1 バイトを書き込む。
$84ACcodePPU データ転送キューへの要素の書き込みを完了する。
$84B1codePPU データ転送キューの内容を消費し、PPU へ転送する。
NMI スレッド専用。
NOTE: 60 バイト以上消費した時点で打ち切る。
$850Dcode1P/2P入力を更新する。
NMI スレッド専用。
$851Acode指定したコントローラーの入力を更新する。
$850D 下請け。
$853Acode(未使用)
$855Ecode(未使用)
$8584code(未使用)
$8591code盤面上の玉の更新処理。
既存の全ての玉に対して更新処理を行い、可能なら新しい玉を生成する。
$8775data盤面の各行の先頭を指すアドレステーブル。(下位バイト配列, 上位バイト配列) の形式。
なぜか 19 行ではなく 21 行分あるが、末尾の 2 行分は実質未使用。
$879Fdata盤面の各行に対する初期値テーブル ($87B4) 内インデックス。
なぜか 19 行ではなく 21 行分あるが、末尾の 2 行分は実質未使用。
$87B4data盤面の行の初期値テーブル。
$87BAdata盤面の行 0..=1 の初期値。
$87D4data盤面の行 2, 6, 10, 14, 18 の初期値 (右端 2 列以外全て閉じた壁)。
$87EEdata盤面の行 3..=5, 7..=9, 11..=13, 15..=17 の初期値。
$8808code盤面を初期化する。
19 行ではなく 20 行分初期化する (off-by-one)。これにより自機移動履歴が一部上書きされるが、この領域は後から改めて初期化されるので実害はない。
$8833codeswap 操作を行う。
$8853code部屋ペア内の 1 つの行に対する swap 操作を行う。
$8833 下請け。
$8874data盤面内の各部屋の左上隅を指すアドレステーブル。(下位バイト配列, 上位バイト配列) の形式。
$8894code盤面を再描画する (常に非同期)。
$89F1data盤面の各行の先頭を指すネームテーブル PPU アドレステーブル。(下位バイト配列, 上位バイト配列) の形式。
$8A1Bdata盤面セル値の下位 4bit に対応するBGタイルIDのテーブル。
$8A2Bdata盤面の各行に対応する赤玉スプライト座標yのテーブル。
$8A3Edata盤面の各列に対応する赤玉スプライト座標xのテーブル。
$8A58codeカニ部屋にある玉の数を返す。
$8A72dataカニ部屋の各マスへのオフセットテーブル (部屋の左上隅のマスを基準とする)。
$8A81code乱数を更新する。
$8A97codeNMI 待ちルーチン $831A を指定回数呼ぶ。
$8A9Ecode描画を有効化し、BGスクロールの再設定を行う。レンダリング有効状態 $02 の更新も行う。
$8AA1codeBGスクロールを再設定し、描画を有効化する。レンダリング有効状態 $02 の更新は行わない
NMI スレッドから直接呼ばれる。
$8ABEcodeレンダリングを無効化し、画面をクリアする。
ネームテーブル 0, 2 はともに空白タイル 0x2C でクリアされ、2 つのスプライトバッファはともに全スプライト非表示となる (240 で埋められる)。
$8AD9dataネームテーブル 0 を空白タイル 0x2C でクリアするための矩形データ。
$8ADEdataネームテーブル 2 を空白タイル 0x2C でクリアするための矩形データ。
$8AE3code自機/相方の回転状態を更新し、自機/相方スプライトをスプライトバッファに書き込む。
ゲームプレイ中に NMI スレッドから呼ばれる。
$8BA9data自機/相方スプライトの開始タイルID加算値テーブル。
$8BB1data自機/相方スプライトのスプライト属性テーブル (水平/垂直方向の反転指示)。
$8BB9data自機/相方スプライトの変位yテーブル。
$8BE9data自機/相方スプライトの変位xテーブル。
$8C19data自機/相方の姿勢に対応するスプライト変位テーブル内オフセットたち。
$8C21codeカニのスプライトをスプライトバッファに書き込む。
$8C7Edata$8C21 関連。
$8C82data$8C21 関連。
$8C86data$8C21 関連。
$8C8Adata$8C21 関連。
$8CB9data$8C21 関連。
$8CE8code赤玉スプライトをスプライトバッファに書き込み、盤面外の通常玉の更新処理を行う。
$8DAFdata(未使用)
$8DC3code盤面外の玉を生成する。
$8591 下請け。
$8DE9codeスプライトバッファオフセット操作: $1A を 4 進め、$1B を 4 戻す。
$8DF8codeスプライトバッファオフセット操作: $24 を 4 進める。
$8E00codeスコア/ハイスコア再描画処理。必要な場合のみ再描画する。
$8EBBcode入力処理および自機/相方の移動処理。
ゲームプレイ中に NMI スレッドから呼ばれる。
$8F73code与えられた座標に対応する部屋インデックスを返す。
$8F9Acode自機および相方の移動処理。
$9001data自機の移動方向に対応する方向キー入力のテーブル。
$9009data自機/相方が移動可能範囲の左端にいる場合の移動方向補正テーブル (座標制限用)。
$9011data自機/相方が移動可能範囲の上端にいる場合の移動方向補正テーブル (座標制限用)。
$9019data自機/相方が移動可能範囲の右端にいる場合の移動方向補正テーブル (座標制限用)。
$9021data自機/相方が移動可能範囲の下端にいる場合の移動方向補正テーブル (座標制限用)。
$9029data自機/相方の移動方向に対応する変位x (i16) のテーブル。(下位バイト配列, 上位バイト配列) の形式。
$9039data自機/相方の移動方向に対応する変位y (i16) のテーブル。(下位バイト配列, 上位バイト配列) の形式。
$9049codeスコア加算ルーチン。付随する諸々の処理も行う。
$9106data1P/2Pスコア末尾へのオフセットテーブル (アドレス $47 を基準とする)。
$9108data目標スコア到達時のBGパレット変更用データ。
便宜上、矩形データ (4x1) 形式としている。
$9110data目標スコア到達時のスプライトパレット変更用データ。便宜上、矩形データ (4x1) 形式としている。
$9118codeカニの更新処理。
$91B9code面イントロシーン。
$926Edata面イントロ: "PLAYER {n}" を消去するための矩形データ (塗りつぶし)。
$9273data面イントロ: "PLAYER 1" の矩形データ。
文字 '1' を書き換えることで "PLAYER 2" の描画にも使われる。
$927Fdata面イントロ: "ROUND " の矩形データ。
末尾 2 バイトは適宜書き換えられる。
$928Bdata面イントロ: "LET'S GET 0000 PTS." の矩形データ。
万の位以上は適宜書き換えられる。
$92A5data面イントロシーン用パレット。
便宜上、矩形データ (32x1) 形式としている。
$92C9data面イントロシーン用アトリビュートテーブル。
便宜上、矩形データ (64x1) 形式としている。
$930Dcode目標スコア更新処理。面イントロシーンから呼ばれる。
$9363data1, 2 面における目標スコア。
$9371codeミス状態の更新処理。
$9441data$9371 関連。
$944Adata$9371 関連。
$9454data$9371 関連。
$945Edata$9371 関連。
$946Cdata$9371 関連。
$947Bdata$9371 関連。
$948Acodeゲーム画面を構築する。
$9506dataゲーム画面: 手番でない側のプレイヤー番号 '1', '2' 描画用矩形データのヘッダ。
$950Adataゲーム画面: 手番の側のプレイヤー番号 '1' (大フォント) 描画用矩形データ。
$9512dataゲーム画面: 手番の側のプレイヤー番号 '2' (大フォント) 描画用矩形データ。
$951Adataゲーム画面: 手番の側のプレイヤーの残機数描画用矩形データのヘッダ。
$951Edataゲーム画面: 面ごとのパレット設定 (通常玉の色変更)。
((現在の面) - 1) mod 8 をインデックスとする。
$952Edataゲーム画面の基本パレット。便宜上、矩形データ (32x1) 形式としている。
$9552dataゲーム画面の初期 tilemap。便宜上、矩形データ (32x32) 形式としている。
$9956data(未使用)
$995Ecodeタイトルシーン。
$9A21dataタイトル: カーソルインデックスに対応する赤玉スプライト座標y。
$9A23dataタイトル: "LotLot" ロゴの左半分 "Lot" の矩形データ (先頭 1 行)。
後続の行は 0xD8..=0xFF の連番となる。
PPU アドレスを書き換えることで右半分の描画にも使われる。
$9A2Fdataタイトル: "1 PLAYER GAME" の矩形データ。
PPU アドレスおよび文字 '1' を書き換えることで "2 PLAYER GAME" の描画にも使われる。
$9A40dataタイトル: "HI-SCORE" の矩形データ。
$9A4Cdataタイトル: 著作権表示 (徳間書店) の矩形データ。
$9A7Edataタイトル: 著作権表示 (アイレム) の矩形データ。
$9A92dataタイトル: ハイスコア描画用矩形データのヘッダ。
$9A96dataタイトル画面用パレット。
便宜上、矩形データ (32x1) 形式としている。
$9ABAdataタイトル画面用アトリビュートテーブル。
便宜上、矩形データ (64x1) 形式としている。
$9AFEcodeゲームオーバーシーン。1 人のプレイヤーが残機を全て失った際に呼ばれる。
$9B70dataゲームオーバー: "GAME OVER" の矩形データ。
$9B7Edataゲームオーバー画面用パレット。
便宜上、矩形データ (32x1) 形式としている。
$9BA2dataゲームオーバー画面用アトリビュートテーブル。
便宜上、矩形データ (64x1) 形式としている。
$9BA7dataゲームオーバー: キーワード描画用矩形データのヘッダ。
$9BABdataゲームオーバー: 特定のスコア条件を満たした際に表示されるキーワードたち。
$9BCBcodewave 進行および壁の更新処理。
$9D0Dcode指定した壁の内部に赤玉があるかどうかを返す。
$9BCB 下請け。
$9D57codewave データ参照用ポインタ $1A, オフセット Y の組を 1 進める。
$9BCB 下請け。
$9D5Dcode壁と穴パターンを指定して対応する盤面セルたちを更新する。
$9BCB 下請け。
$9DA3data盤面内の各壁の左上隅を指すアドレステーブル。(下位バイト配列, 上位バイト配列) の形式。
$9E0Bdata横壁の穴パターンに対応する盤面セル配列テーブル内オフセットたち。
$9E13data横壁の穴パターンに対応する盤面セル配列テーブル。
$9E3Bdata縦壁の穴パターンに対応する盤面セル配列テーブル内オフセットたち。
$9E43data縦壁の穴パターンに対応する盤面セル配列テーブル。
$9E5Bdata交点壁の穴パターンに対応する盤面セルテーブル。
$9E5Dcode指定した壁を再描画する (常に非同期)。
$9E79code横壁の再描画処理 (常に非同期)。
$9E5D 下請け。
$9EADdata各横壁 (左上から row-major) の左端を指す PPU アドレステーブル。(下位バイト配列, 上位バイト配列) の形式。
$9ED5data横壁の穴パターンに対応する壁タイル配列テーブル内オフセットたち。
$9EDDdata横壁の穴パターンに対応する壁タイル配列テーブル。
$9F05code縦壁の再描画処理 (常に非同期)。
$9E5D 下請け。
$9F3Edata各縦壁 (左上から row-major) の上端を指す PPU アドレステーブル。(下位バイト配列, 上位バイト配列) の形式。
$9F5Edata縦壁の穴パターンに対応する壁タイル配列テーブル内オフセットたち。
$9F66data縦壁の穴パターンに対応する壁タイル配列テーブル。
$9F7Ecode交点壁の再描画処理 (常に非同期)。
$9E5D 下請け。
$9FAAdata各交点壁 (左上から row-major) を指す PPU アドレステーブル。(下位バイト配列, 上位バイト配列) の形式。
$9FCAdata交点壁の穴パターンに対応する壁タイルテーブル。
$9FCCcodeオーディオドライバを(再)初期化する。
$9FEEcodeオーディオ: 指定した効果音を再生要求する。
$A03Fdataオーディオ: 各効果音の nice 値。
$A04Edataオーディオ: 各効果音で使用するチャンネルのマスク。
$A05Ddataオーディオ: 各効果音バイトコードへのポインタテーブル。(下位バイト配列, 上位バイト配列) の形式。
$A07Bcodeオーディオ: 指定した音楽を再生要求する。(NOTE: 実際は常に音楽ID 0 が渡される)
$A0AFdataオーディオ: 各音楽バイトコードへのポインタテーブル (1 つしかないが)。(下位バイト配列, 上位バイト配列) の形式。
$A0B1codeオーディオドライバを tick する。
NMI スレッドから呼ばれる。
$A148codeオーディオ: 効果音の tick 処理。
$A14Dcodeオーディオ: 効果音バイトコード: プログラムカウンタをインクリメントし、次の命令を実行する。
$A153codeオーディオ: 効果音バイトコード: 次の命令を実行する。
$A15Bcodeオーディオ: 効果音バイトコード: オペコード 0x40..=0xFF (矩形波/三角波の発音/消音) の処理。
$A181codeオーディオ: 効果音バイトコード: オペコード分岐 (0..=0x3F)。
$A187codeオーディオ: 効果音バイトコード: オペコード 0..=0x1F (ウェイトカウンタ設定) の処理。
$A18Fcodeオーディオ: 効果音バイトコード: プログラムカウンタをインクリメントする。
$A196codeオーディオ: 効果音バイトコード: オペコード分岐 (0x20..=0x3F)。
$A19Ccodeオーディオ: 効果音バイトコード: オペコード 0x20..=0x2F (APU レジスタへの書き込み) の処理。
$A1AFcodeオーディオ: 効果音バイトコード: オペコード分岐 (0x30..=0x3F)。
$A1B5codeオーディオ: 効果音バイトコード: オペコード 0x3F (全ての矩形波/三角波チャンネルを消音) の処理。
$A1D0codeオーディオ: 効果音バイトコード: オペコード分岐 (0x30..=0x3E)。
$A1D4codeオーディオ: 効果音バイトコード: オペコード 0x33 (ジャンプ) の処理。
$A1E2codeオーディオ: 効果音バイトコード: オペコード分岐 (0x30..=0x32, 0x34..=0x3E)。
$A1E6codeオーディオ: 効果音バイトコード: オペコード 0x34 (サブルーチン呼び出し) の処理。
$A20Dcodeオーディオ: 効果音バイトコード: オペコード分岐 (0x30..=0x32, 0x35..=0x3E)。
$A211codeオーディオ: 効果音バイトコード: オペコード 0x35 (サブルーチンからの復帰) の処理。
$A224codeオーディオ: 効果音バイトコード: オペコード分岐 (0x30..=0x32, 0x36..=0x3E)。
$A228codeオーディオ: 効果音バイトコード: オペコード 0x36 (n 回のループを開始) の処理。
$A248codeオーディオ: 効果音バイトコード: オペコード分岐 (0x30..=0x32, 0x37..=0x3E)。
$A24Ccodeオーディオ: 効果音バイトコード: オペコード 0x37 (ループ継続/終了) の処理。
$A269codeオーディオ: 効果音バイトコード: オペコード 0x30..=0x32, 0x38..=0x3E (矩形波/三角波の周波数変化) の処理。
$A291codeオーディオ: 音楽の tick 処理。
$A29Bcodeオーディオ: 音楽バイトコード: プログラムカウンタをインクリメントし、次の命令を実行する。
$A29Ecodeオーディオ: 音楽バイトコード: 次の命令を実行する。
$A2A6codeオーディオ: 音楽バイトコード: オペコード 0x40..=0xFF (矩形波/三角波の発音/消音要求) の処理。
$A2CBcodeオーディオ: 音楽バイトコード: オペコード分岐 (0..=0x3F)。
$A2D1codeオーディオ: 音楽バイトコード: オペコード 0..=0x1F (ウェイトカウンタ設定) の処理。
$A2D5codeオーディオ: 音楽バイトコード: プログラムカウンタをインクリメントする。
$A2DCcodeオーディオ: 音楽バイトコード: オペコード分岐 (0x20..=0x3F)。
$A2E2codeオーディオ: 音楽バイトコード: オペコード 0x20..=0x2F (APU レジスタへの書き込み要求) の処理。
$A2F2codeオーディオ: 音楽バイトコード: オペコード分岐 (0x30..=0x3F)。
$A2F8codeオーディオ: 音楽バイトコード: オペコード 0x3F (未使用) の処理。
$A30Dcodeオーディオ: 音楽バイトコード: オペコード分岐 (0x30..=0x3E)。
$A311codeオーディオ: 音楽バイトコード: オペコード 0x33 (ジャンプ) の処理。
$A31Fcodeオーディオ: 音楽バイトコード: オペコード分岐 (0x30..=0x32, 0x34..=0x3E)。
$A323codeオーディオ: 音楽バイトコード: オペコード 0x34 (サブルーチン呼び出し) の処理。
$A34Acodeオーディオ: 音楽バイトコード: オペコード分岐 (0x30..=0x32, 0x35..=0x3E)。
$A34Ecodeオーディオ: 音楽バイトコード: オペコード 0x35 (サブルーチンからの復帰) の処理。
$A361codeオーディオ: 音楽バイトコード: オペコード分岐 (0x30..=0x32, 0x36..=0x3E)。
$A365codeオーディオ: 音楽バイトコード: オペコード 0x36 (n 回のループを開始) の処理。
$A385codeオーディオ: 音楽バイトコード: オペコード分岐 (0x30..=0x32, 0x37..=0x3E)。
$A389codeオーディオ: 音楽バイトコード: オペコード 0x37 (ループ継続/終了) の処理。
$A3A6codeオーディオ: 音楽バイトコード: オペコード 0x30..=0x32, 0x38..=0x3E (未使用、実質 nop) の処理。
$A3ADdataオーディオ: 効果音 1 バイトコード (面開始ジングル)。
$A48Cdataオーディオ: 音楽 0 バイトコード。
$A62Fdataオーディオ: 効果音 2 バイトコード (面クリアジングル)。
$A6ABdataオーディオ: 効果音 3 バイトコード (ゲームオーバージングル)。
$A753dataオーディオ: 効果音 4, 5 バイトコード (通常玉が 50pts に落下)。
$A75Bdataオーディオ: 効果音 6 バイトコード (通常玉が 50pts に落下)。
$A763dataオーディオ: 効果音 7 バイトコード (通常玉が 50pts に落下)。
$A76Bdataオーディオ: 効果音 8 バイトコード (通常玉が 50pts に落下)。
$A773dataオーディオ: 効果音 9 バイトコード (カニ警告)。
$A781dataオーディオ: 効果音 10 バイトコード (赤玉が 50pts 以外に落下)。
$A7C4dataオーディオ: 効果音 11 バイトコード (ミス)。
$A804dataオーディオ: 効果音 12 バイトコード (swap 操作)。
$A839dataオーディオ: 効果音 13 バイトコード (ポーズ)。
$A851dataオーディオ: 効果音 14 バイトコード (通常玉が 50pts 以外に落下)。
バイトコード内のバグにより無音になっている (おそらくノイズ音量を 0 にするつもりで矩形波Aの音量を 0 にしてしまっている)。
$A864dataオーディオ: 周波数タイマー値テーブル (u16be[60])。
12 平均律の F2 から半音ずつ高くなる。末尾は値 0 (消音用)。
$A8DC-$CEFF(空き領域)
$CF00data(未使用 wave テーブル)
$CF03datawave テーブル (ビッグエンディアンのポインタ配列 (0 終端))。
$CF54data(未使用 wave データ)
$D029datawave 8, 35 データ。
$D1F2datawave 6, 23, 33 データ。
$D2A9datawave 7 データ。
$D42Edatawave 24, 38 データ。
$D5C7datawave 31 データ。
$D74Adatawave 10, 26 データ。
$D90Bdatawave 19 データ。
$DAD2datawave 13, 34 データ。
$DD11datawave 12 データ。
$DE46datawave 29 データ。
$DFA5datawave 21, 32 データ。
$E1AAdatawave 22 データ。
$E375datawave 16 データ。
$E4C2datawave 17 データ。
$E5A1datawave 15, 37 データ。
$E738datawave 14, 30 データ。
$E949datawave 0 データ。
$E9D4datawave 1 データ。
$EBA3datawave 2, 27 データ。
$EDD2datawave 3 データ。
$F031datawave 4 データ。
末尾に 2 つの無効エントリがある (wave 内時間 255 に対するエントリと思われるが、実際には終端バイト 0xFF とみなされ、そこで wave が終わる)。
$F2B2datawave 5 データ。
$F491datawave 20, 36 データ。
$F672datawave 28 データ。
$F829datawave 9 データ。
$FA52datawave 11 データ。
$FBC1datawave 18, 39 データ。
$FE08datawave 25 データ。
$FFDF-$FFF9(空き領域)
$FFFA-$FFFFdata割り込みベクタ。

詳細

$8388: 矩形データ転送ルーチン

PPU へ矩形データ (ベタまたは塗りつぶし) を転送する。レンダリングが有効なら非同期、無効なら同期で転送する。

引数

A
塗りつぶしかどうか (0:false, 1:true)。
$0B
呼び出し側で退避した A の値。

インライン引数

ptr
矩形データへのポインタ。

戻り値

A
引数 $0B から復元した値。

保存

X, Y

説明

$837E (塗りつぶし矩形データ転送ルーチン), $8384 (ベタ矩形データ転送ルーチン) の下請け。

ベタ矩形データの形式:

内容
u16le矩形の左上隅に対応する PPU アドレス。
u8矩形の幅 (タイル単位)。
u8矩形の高さ (タイル単位)。
u8[]矩形内のタイル配列。
(幅) >= (高さ) の場合 row-major, (幅) < (高さ) の場合 column-major

塗りつぶし矩形データの形式:

内容
u16le矩形の左上隅に対応する PPU アドレス。
u8矩形の幅 (タイル単位)。
u8矩形の高さ (タイル単位)。
u8矩形を塗りつぶすタイル。

レンダリングが有効なら非同期、無効なら同期で転送を行う。

矩形の幅/高さに応じて転送方向が変わる:

NOTE: 「同期かつ縦方向転送かつベタ」の設定で本ルーチンを呼び出すと暴走する。ただし、ゲーム内でそのような呼び出しが行われるケースはない。原因は縦方向転送ルーチン $8429 内の分岐命令のオフセットの誤り。

$9049: スコア加算ルーチン

指定されたスコアを加算し、付随する諸々の処理を行う。

引数

A
加算スコア:

戻り値

$29
呼び出し前の Y の値。

保存

A, Y

説明

現在のプレイヤーのスコアに指定された値を加算し、スコア再描画フラグを立てる。

加算結果がハイスコア以上の値ならばハイスコアを更新し、ハイスコア再描画フラグを立てる。

まだ現在の面の目標スコアを達成しておらず、かつ加算結果が目標スコア以上の値ならばボーナスタイムを開始する。