Nintendo Entertainment System Architecture version 1.4 [09/09/1996] by Marat Fayzullin [fms@freeflight.com] WWW: http://www.freeflight.com/fms/ IRC: RST38h 翻訳:BERO [bero@geocities.co.jp] WWW: http://www.geocities.co.jp/playtown/2004/ 次のドキュメントは、東洋(韓国、日本)でFamicom、ヨーロッパ(ロシアなど)で Dandyとしても知られているNintendo Entertainment Systemビデオゲームコンソー ルの作用について説明する。このドキュメントはいかなる公式の任天堂の情報にも 基づいていないので、多くの場所が不完全で間違っていることに注意する。 「Nintendo Entertainment System」と「Famicom」は任天堂の登録商標で る。 この情報の入手とNESエミュレータを書く際の支援、精神的支援をしてくれた次の 人々に感謝したい: (アルファベット順) Pascal Felber Pan of Anthrox John Stiles Kawasedo Patrick Lesaard Tink Marcel de Kogel Paul Robson Bas Vijfwinkel Alex Krasivsky Serge Skorobogatov このファイルの現在のバージョンは、サウンドハードウェアのような る情報が抜 けている。後のリリースでこれらの部分を加えるつもりで る。NESについて何か このマニュアルの中にない情報を持っている場合、fms@freeflight.comに自由に メールしてください。支援を評価する。 ******************************* 内容 ******************************* 1. 一般的なアーキテクチャ 2. 割り込み 3. I/Oポート 4. PPUメモリ 5. Hit/VBlankビット 6. ジョイスティック 7. スプライト 8. メモリマッパ a) シーケンシャル b) Konami c) VROMスイッチ d) 5202チップ e) 他のもの 9. サウンド(書かれていること) ************************* 一般的なアーキテクチャ ************************* NESは、6502のCPUと、PPU(ピクチャ処理ユニット)として知られているカスタムのビ デオコントローラに基づく。PPUのビデオのメモリはメインCPUメモリから分けられ ており、特別のポート経由で読み書きすることができる。カートリッジは、 $8000-$FFFFでメインCPUアドレス空間に現われるROMと、$0000-$1FFFでPPUアドレス 空間に現われて、パターンテーブル(akaタイルテーブル)を含んでいるVROMまたは VRAMの両方を含んでいることが る。より小さなカートリッジ(16kbのROMを単に持 っている)では、$C000-$FFFFに起こり、$8000-$BFFFエリアを未使用にしておく。 内部NES VRAMは、PPUメモリのアドレス$2000-$3FFFに位置する。いくつかのカート リッジは、さらに、$6000-$7FFFにRAMを持っており、バッテリーバックアップされ ることもされないことも る。 CPUメモリマップ --------------------------------------- $10000 カートリッジROM上位バンク --------------------------------------- $C000 カートリッジROM下位バンク --------------------------------------- $8000 カートリッジRAM (バッテリーバックアップの場合も る) --------------------------------------- $6000 拡張モジュール --------------------------------------- $5000 入出力 --------------------------------------- $2000 2kB内部RAM, 4回ミラー --------------------------------------- $0000 ****************************** 割り込み ****************************** NESは、各フレームの終了にPPUによって生成されたマスク不能割り込み(NMI)を使用 する(いわゆるVBlank割り込み)。カートリッジ中の回路はさらにマスク可能割り込 み(すなわちIRQ)を生成できる。しかし、ほとんどのカートリッジは生成しない。 VBlank割り込みは、$2000の第7ビットに1/0を書き込むことによって有効/無効にす ることができる。VBlank割り込みが生じる場合、CPUはリターンアドレスとステー タスレジスタをスタックに積んで、位置$FFFA(NESのROM)で格納されたアドレスへジ ャンプする。割り込みハンドラは、メインプログラム実行にCPUを返すRTIコマンド でその実行を終了することになっている。6502CPUの適正な本に割り込みハンドラ についてのより多くの情報を見つけることができる。 ****************************** I/Oポート ******************************* $2000-$2007と$4000-$4017のエリアへNES内部I/Oポートをマップする。いくつかの ポートの使用法は未知または不明瞭で る。また、いかなる情報も評価する。 I/Oポートマップ ------+-----+--------------------------------------------------------------- $2000 | RW | PPU制御レジスタ 1 | 0-1 | ネームテーブル to show: | | | | +-----------+-----------+ | | | 2 ($2800) | 3 ($2C00) | | | +-----------+-----------+ | | | 0 ($2000) | 1 ($2400) | | | +-----------+-----------+ | | | | しかし、ミラーのため、4ではなく2つの実際のネームテーブルだけが | | ることを思い出す。 | 2 | 垂直書込み, 1 = PPUメモリアドレス 32ずつインクリメント | | | | ネームテーブル, VW=0 ネームテーブル, VW=1 | | +----------------+ +----------------+ | | |----> write | | | write | | | | | | V | | | | 3 | スプライトパターンテーブルアドレス, 1 = $1000, 0 = $0000 | 4 | スクリーンパターンテーブルアドレス, 1 = $1000, 0 = $0000 | 5 | スプライトサイズ, 1 = 8x16, 0 = 8x8 | 6 | Hitスイッチ, 1 = Hit時に割り込みを生成 (違うかも ???) | 7 | VBlankスイッチ, 1 = VBlank時に割り込みを生成 ------+-----+--------------------------------------------------------------- $2001 | RW | PPU制御レジスタ 2 | 0 | 不明 (???) | 1 | イメージマスク, 0 = スクリーンの左8カラムを非表示 | 2 | スプライトマスク, 0 = スプライトの左8カラムを非表示 | 3 | スクリーンスイッチ, 1 = スクリーン表示, 0 = スクリーン非表示 | 4 | スプライトスイッチ, 1 = スプライト表示, 0 = スプライト非表示 | 5-7 | 不明 (???) ------+-----+--------------------------------------------------------------- $2002 | R | PPUステータスレジスタ | 0-5 | 不明 (???) | 6 | Hitフラグ, 1 = PPUリフレッシュがスプライト#0にヒット | | このフラグはVBlank開始またはCPUが$2002を読んだ時に0にリセット | | される(「Hit/VBlankビット」参照)。 | 7 | VBlankフラグ, 1 = PPUが垂直帰線信号を生成 | | このフラグはVBlank終了またはCPUが$2002を読んだ時に0にリセット | | される(「Hit/VBlankビット」参照)。 ------+-----+--------------------------------------------------------------- $2003 | W | スプライトメモリアドレス | | $2004でアクセスする256バイトのスプライトメモリのアドレスをセッ | | トする。このアドレスは$2004の各アクセスの後に1ずつインクリメン | | トする。スプライトメモリはスプライトの座標、色と他の属性を含ん | | でいる(「スプライト」を参照)。 ------+-----+--------------------------------------------------------------- $2004 | RW | スプライトメモリデータ | | スプライトメモリの読み書きに使用する。アドレスは$2003でセット | | され、各アクセスの後にインクリメントする。スプライトメモリはス | | プライトの座標、色と他の属性を含んでいる(「スプライト」を参照)。 ------+-----+--------------------------------------------------------------- $2005 | W | 背景スクロール | | 垂直と水平の2つのスクロールレジスタが り、両方ともこのポート | | 経由で書かれる。1番目に書かれた値は、垂直スクロールレジスタへ | | 入る(もし239より大きければ無視される)。2番目の値は水平スクロー | | ルレジスタに現われる。 | | ネームテーブルは次の方法で整えられると仮定される: | | | | +-----------+-----------+ | | | 2 ($2800) | 3 ($2C00) | | | +-----------+-----------+ | | | 0 ($2000) | 1 ($2400) | | | +-----------+-----------+ | | | | スクロール時、ピクチャは複数のネームテーブルにわたることが る。 | | しかし、ミラーのため、4ではなく2つの実際のネームテーブルだけが | | ることを思い出す。 ------+-----+--------------------------------------------------------------- $2006 | | PPUメモリアドレス | | 「PPUメモリ」参照 ------+-----+--------------------------------------------------------------- $2007 | | PPUメモリデータ | | 「PPUメモリ」参照 ------+-----+--------------------------------------------------------------- $4000-$4013 | サウンドレジスタ | 「サウンド」参照 ------+-----+--------------------------------------------------------------- $4014 | W | スプライトメモリのDMAアクセス | | このポートに値Nを書き込むと、アドレス$100*NのCPUメモリのエリア | | をスプライトメモリへ転送する。 ------+-----+--------------------------------------------------------------- $4015 | W | サウンドスイッチ | 0 | チャンネル 1, 1 = サウンド有効 | 1 | チャンネル 2, 1 = サウンド有効 | 2 | チャンネル 3, 1 = サウンド有効 | 3 | チャンネル 4, 1 = サウンド有効 | 4 | チャンネル 5, 1 = サウンド有効 | 5-7 | 未使用 (???) ------+-----+--------------------------------------------------------------- $4016 | RW | ジョイスティック 1 + ストローブ | 0 | ジョイスティック 1 データ | 1 | ジョイスティック 1 存在, 0 = 接続 | 2-5 | 未使用, set to 0 (???) | 6-7 | 不明, set to 10 (???) | | 「ジョイスティック」参照 ------+-----+--------------------------------------------------------------- $4017 | R | ジョイスティック 2 | 0 | ジョイスティック 2 データ | 1 | ジョイスティック 2 存在, 0 = 接続 | 2-5 | 未使用, set to 0 (???) | 6-7 | 不明, set to 10 (???) | | 「ジョイスティック」参照 ------+-----+--------------------------------------------------------------- ****************************** PPUメモリ ****************************** 実際のNESでは、PPUメモリの読み書きはVBlank期間にのみ試みるべきで る。多く のより小さなROMはパターンテーブル用に読み出し専用メモリ(VROM)を持っている。 この場合、このメモリに書き込むことができない。VRAMの中の$3F00と$3F10位置は 互いにミラーされ(つまり同じメモリセルで る)、ピクチャの背景色を定義する。 PPUメモリに書く: a) $2006に上位アドレスバイトを書き込む。 b) $2006に下位アドレスバイトを書き込む。 c) $2007にデータを書き込む。各書き込みの後に、アドレスは1($2000のビット 2が0の場合)または32($2000のビット2が1の場合)ずつインクリメントする。 PPUメモリから読む: a) $2006に上位アドレスバイトを書き込む。 b) $2006に下位アドレスバイトを書き込む。 c) $2007からデータを読む。$2007から読まれた最初のバイトは無効で る。 その後、各読み取りの後にアドレスは1ずつインクリメントする。 ネームテーブルは、各々32バイトの32の列へ構成されたタイル番号を含んでいる。 タイルは各々8x8ピクセルで る。したがって、全体のネームテーブルは32x32タイ ルまたは256x256ピクセルで る。NESのNTSCバージョンでは、上部と下部の16ピク セルを表示しないので、スクリーンは256x224ピクセルになる。NESのPALバージョ ンでは、上部と下部の8ピクセルを表示しないので、スクリーンは256x240ピクセル になる。 パターンテーブルは次の形式でタイルイメージを含んでいる: キャラクタ 色 パターンテーブルの内容 ...o.... 00010000 00010000 $10 +-> 00000000 $00 ..O.O... 00202000 00000000 $00 | 00101000 $28 .0...0.. 03000300 01000100 $44 | 01000100 $44 O.....O. 20000020 00000000 $00 | 10000010 $82 ooooooo. -> 11111110 11111110 $FE | 00000000 $00 O.....O. 20000020 00000000 $00 | 10000010 $82 0.....0. 30000030 10000010 $82 | 10000010 $82 ........ 00000000 00000000 $00 | 00000000 $00 +---------+ パターンテーブルにキャラクタの各ピクセルの2ビットだけを格納することに注意す る。属性テーブルから他の2ビットを得る。したがって、NESスクリーン上の同時 発色数の合計は、16で る。 属性テーブル中の各バイトは、スクリーン上でタイルの4x4グループを表わし、8x8 属性テーブルを作る。4つの2x2正方形へ以下のように各4x4タイルグループを細分 する: (0,0) (1,0) 0| (2,0) (3,0) 1 (0,1) (1,1) | (2,1) (3,1) --------------+---------------- (0,2) (1,2) 2| (2,2) (3,2) 3 (0,3) (1,3) | (2,3) (3,3) 属性バイトは、各2x2正方形のための色番号の上位2ビットを含んでいる(パターンテ ーブルに低位2ビットを格納する): ビット 機能 タイル -------------------------------------------------------------- 7,6 正方形3の上位カラービット (2,2),(3,2),(2,3),(3,3) 5,4 正方形2の上位カラービット (0,2),(1,2),(0,3),(1,3) 3,2 正方形1の上位カラービット (2,0),(3,0),(2,1),(3,1) 1,0 正方形0の上位カラービット (0,0),(1,0),(0,1),(1,1) 2つの16バイトのパレットテーブルが る:ピクチャのために使用される$3F00のもの と、スプライトパレットを含んでいる$3F10の別のもの。VRAMの中の$3F00と$3F10 位置は互いにミラーされ(つまり同じメモリセルで る)、ピクチャの背景色を定義 する。 2つのネームテーブルと属性テーブルのための十分なVRAMだけが る。2つの他のも のは最初の2つのミラー(つまり正確なコピー)で る。どのページをミラーするか はカートリッジ回路に左右される。垂直にミラーすることで、テーブル2と3は適切 に0と1ページのミラーで る。水平ミラーすることで、1と3ページは適切に0と2ペ ージのミラーで る。 PPUメモリマップ --------------------------------------- $4000 空 --------------------------------------- $3F20 スプライトパレット --------------------------------------- $3F10 Image パレット --------------------------------------- $3F00 空 --------------------------------------- $3000 属性テーブル 3 --------------------------------------- $2FC0 ネームテーブル 3 (32x25タイル) --------------------------------------- $2C00 属性テーブル 2 --------------------------------------- $2BC0 ネームテーブル 2 (32x25タイル) --------------------------------------- $2800 属性テーブル 1 --------------------------------------- $27C0 ネームテーブル 1 (32x25タイル) --------------------------------------- $2400 属性テーブル 0 --------------------------------------- $23C0 ネームテーブル 0 (32x25タイル) --------------------------------------- $2000 パターンテーブル 1 (256x2x8, VROMの場合も る) --------------------------------------- $1000 パターンテーブル 0 (256x2x8, VROMの場合も る) --------------------------------------- $0000 *************************** Hit/VBlankビット **************************** 読み出し専用の位置$2002の第7ビットにVBlankフラグを含んでいる。それは、PPU がスクリーンを走査しているか、垂直帰線信号を生成しているかを示す。各フレー ムの最後(スキャンライン232)でセットし、スキャンライン8からの次のスクリーン リフレッシュ開始まで残る。プログラムは、$2002から読むことによりこのビットを 早々にリセットできる。 読み出し専用の位置$2002の第6ビットにHitフラグを含んでいる。スプライト#0が位 置する場所で、PPUが最初のスキャンラインをリフレッシュし始める時、1になる。 例えば、スプライト#0のY座標が34で る場合、スキャンライン34でHitフラグをセッ トする。垂直帰線信号が開始する時、Hitフラグをリセットする。プログラムは、 $2002から読むことによりこのビットを早々にリセットできる。 ***************************** ジョイスティック **************************** 位置$4016と$4017によってアクセスされる2つのジョイスティックが る。ジョイ スティックをリセットするためには、$4016に最初に1、その後0を書き込む。この 方法で、ジョイスティックの回路にストローブを生成する。その後、$4016(ジョイ スティック0)または$4017(ジョイスティック1)のいずれかから読む。各読み取り は、第0ビットに単一のボタンの状態を与える(押されれば1、そうでなければ0): Read # | 1 2 3 4 5 6 7 8 -------+--------------------------------------------------------- Button | A B SELECT START UP DOWN LEFT RIGHT ビット1は、ポートにジョイスティックが接続されているかどうか示す。ジョイス ティックが接続されている場合0、そうでなければ1にセットされる。$4016/$4017 のビット6と7は、さらに る重要性を持つように見えるが、まだ明らかでない。 ビットの残りは0にセットされる。ボタンを押す場合、いくつかのゲームは $4016/$4017から*正確に*$41を得ることを予期する。それは考慮に入れる必要が る。 ******************************* スプライト ******************************** 64個のスプライトが り、8x8または8x16ピクセルのいずれかで る。スプライト パターンは、PPUメモリのパターンテーブルに格納される。256バイトのスプライト メモリ(CPUやPPUアドレス空間の一部ではない)にスプライト属性を格納する。位置 $4014を使用して、DMA転送によってスプライトメモリの全内容を書くことができる (上記参照)。スプライトメモリは、さらに、$2003へスタートアドレスを書き、次 に$2004を読み書きすることにより1バイトずつアクセスできる。(各アクセスの後に アドレスはインクリメントする) スプライト属性の形式は以下のとおりで る: スプライト属性RAM: | スプライト#0 | スプライト#1 | ... | スプライト#62 | スプライト#63 | | | +---- 4 bytes: 0: 左上隅のY座標-1 1: スプライトパターン番号 2: カラーと属性: bits 1,0: カラーの上位2ビット bits 2,3,4: 不明 (???) bit 5: 1 = スプライトを背景の後ろに表示 bit 6: 1 = 水平反転 bit 7: 1 = 垂直反転 3: 左上隅のX座標 背景ピクチャに対するタイルパターンと正確に同じ方法でスプライトパターンを取 って来る。ただ一つの違いは16x8スプライトで生じる: スプライトの上半分はポー ト$2000でセットされたスプライトパターンテーブルから取り出し、下半分はもう一 つのパターンテーブルの同じ位置から取る。したがって、PPUが16x8スプライトを 表示しており、スプライトパターンテーブルを$1000にセットする場合、$0000のパ ターンテーブルからこのスプライトの下半分を取り出し、その逆も正しい。 ****************************メモリマッパ**************************** NESカートリッジの中で使用される多くの様々なメモリマッパ(aka MMC)が る。 ROMとVROMのページを切り替え、他のいくつかの仕事を行うために使用する。よく 知っているMMCについてだけ説明する。これらと他のMMCについてのいかなる新しい 情報も高く評価する。MMC番号は.NESファイルフィールド「マッパタイプ」での用 語で る。 1. マッパ#1、シーケンシャル これは Bomberman 2, Destiny Of The Emperor, Megaman 2, Airwolf, Operation Wolf, Castlevania 2, Silk Worm, Yoshi, Break Thru のような多くの256kbのカー トリッジの中で使用されるシーケンシャルマッパで る。ROMとVROMを切り替える ために使用することが る。VROMがない場合、VRAMの8kbは$0000に現れる。 る 場合(ほとんどRPGゲーム)には、そのようなカートリッジが、さらに$6000-$7FFFで バッテリーバックアップRAMを含んでいる。マッパには4つの5ビットのレジスタが り、以下のアドレスでアクセスされる: レジスタ アドレス範囲 機能 --------------------------------------------------------------------------- 0 $8000-$9FFF ミラーとVROMページサイズを選択する。 このレジスタの第0ビットはミラータイプを選択する(水平=1、垂直=0)。 第4ビットは、VROMページのサイズを選択する。それが1で る場合、 $0000と$1000で2つの4kbのVROMページを独立して切り替えることができる。 そうでなければ、$0000に8kb VROMページが る。 1 $A000-$BFFF VROMページを選択する。 このレジスタはレジスタ0によって選択されたページサイズに依存して、 $0000に8kbまたは4kb VROMページのいずれかをセットする。 2 $C000-$DFFF セカンドVROM 4kbページで選択したページ 4kb VROMページがレジスタ0によって選択したならば、このレジスタは $1000でVROMページをセットする。そうでなければ、その値を無視する。 3 $E000-$FFFF ROMページを選択する。 このレジスタは$8000で16kb ROMページをセットする。カートリッジ中の 最後のROMページに$C000のページを常にハードワイヤする。 カートリッジは$8000でページ0で始まる。 --------------------------------------------------------------------------- マッパレジスタに書くためには、最初に位置のどこかに$80を書き込む。これはマ ッパをリセットする。その後、適切なアドレス範囲に値を少しずつ書き込む。例 えば、次のアセンブラコードはレジスタ3に$0Cを書き込む: lda #$80 ; Resetting mapper sta $8000 ; lda #$0C ; This is our value sta $EFD9 ; Writing bit 0 lsr a ; Shifting sta $EFD9 ; Writing bit 1 lsr a ; Shifting sta $EFD9 ; Writing bit 2 lsr a ; Shifting sta $EFD9 ; Writing bit 3 lsr a ; Shifting sta $EFD9 ; Writing bit 4 2. マッパ#2、Konami これは、ほとんどのKonami(Life Force, Castlevania, Metal Gear)と他のいくつか のカートリッジの中で使用される全く単純なマッパで る。それはROMを単に切り 替える。このマッパを備えたカートリッジはすべて$0000で8kbのVRAMを持っている (つまりVROMはない)。マッパには位置$8000-$FFFFによって書くことができる一つ の8ビットのレジスタが る。それは$8000で多くの16kb ROMページを含んでいる。 カートリッジ中の最後のROMページに$C000のページを常にハードワイヤする。カー トリッジは$8000でページ0で始まる。 このマッパに関して注意することがもう1つ る:マッパにアクセスするために $8000-$FFFF範囲中のいかなるアドレスも使用できるが、ほとんどのゲームは書き込 む値と等しい最後の数字を備えたアドレスの使用を好む。したがって、$9FF7へ$0 7、$9FF5へ$05を書くことができる。この理由は不明。 3. マッパ#3、VROMスイッチ Goonieシリーズと多くの日本専用のゲームの中で、VROMスイッチとして知られてい るマッパ#3を使用する。それは、VROMの8kbページを切り替えることを単に可能に する。ROMは16kbまたは32kbのいずれかで り、ページにつけない。マッパには位 置$8000-$FFFFによって書くことができる一つの8ビットのレジスタが る。それは $0000で多くの8kb VROMページを含んでいる。 マッパ#2でのように、多くのゲームは書き込む値と等しい最後の数字を備えた位置 を使用する。私はなぜか知らない。 4. マッパ#4(???)、5202チップ Batman Returns, Super Contra, Vindicators, Silver Surferなどのような多くの 最近のカートリッジの中でこのマッパ(または、私は「拡張チップ」と言うべきで るか)を使用する。それは非常に複雑な装置で り、IRQラインで独自の割り込みを 生成することができ、ROMとVROMを切り替える1セットのコマンドが る。VROMペー ジは1kbで り、ROMページは8kbで るように見える。私は、このマッパがどう動 作するか完全には理解していないので、いかなる情報も評価する。 下記の位置によってチップを制御する: アドレス 機能 --------------------------------------------------------------------------- $8000 コマンド番号(0-7)をここに書き込む。さらに、このレジスタへの書き込み は、$E000への書き込みによってされた変更をリセットするように見える。 $8001 コマンドに対する値をここに書き込む。 $A000 第0ビットがミラーを制御する。(1=水平ミラー) $A001 $8001と同じ(???) $C000 不明 $C001 不明 $E000 第5ビットが1にセットされた時、$8000-$8FFFと$A000-$AFFFでメモリを交 換する。 $E001 不明 --------------------------------------------------------------------------- マッパを使用するために、最初に$8000へコマンド番号、次に$8001へ値(ページ番 号)を書き込むべきで る。下記コマンドが存在する: Cmd 機能 --------------------------------------------------------------------------- 0 $0000の2つの必然の1kbのVROMページを選択する。$8001に書き込む値の第0ビッ トは重要ではない、つまり、5は4と5ページを常に選択する。 1 $0800の2つの必然の1kbのVROMページを選択する。$8001に書き込む値の第0ビッ トは重要ではない、つまり、5は4と5ページを常に選択する。 2 $1000の1kb VROMページを選択する。 3 $1400の1kb VROMページを選択する。 4 $1800の1kb VROMページを選択する。 5 $1C00の1kb VROMページを選択する。 6 $8000の8kb ROMページを選択する。初期値は0で るように見える。 7 $A000の8kb ROMページを選択する。初期値は1で るように見える。 --------------------------------------------------------------------------- $C000と$E000のROMページをROMの最後のページにハードワイヤし、切り替えること ができないことに注意する(しかしながら、$E000によってそれらを交換できる)。 5. 他のマッパ 他のいくつかのマッパが り、それらのうちのいくつかは非常に精巧で る。 iNESは部分的にそれらをサポートするが、このサポートとして、どちらもは正しく 動作しない。または、マッパはめったにない(100-イン-1カートリッジマッパのよ うに、私はそれらをここでカバーしない)。 ********************************サウンド********************************* 書かれていること。 ---------------------