ファミコン ディスクシステム


RAMアダプタに8KByteのROM(カスタムに内蔵) 32KByteのRAM($6000−$DFFF)、 8KByteのキャラクタRAMのメモリを載せて クィックディスク(QD) ドライブ込みで15、000円はかなり安い またドライブは通信アダプタの底面にあるコネクタ(ロットによっては無くなっている) でも接続可能     RAM、拡張ポート テスト スタートキーとセレクトーキーを押しながらリセットすると実行されます このときにメインRAM$6000−$DFFFのチェック 次にPPU$0000−$1FFFを CPU RAM$C000−$DFFFに転送してチェックを行います エラーがあればOKと表示される所にエラーが出たアドレスが表示されます  $0000−$1FFF PPUのアドレス  $6000−$DFFF CPUのアドレス   拡張ポートのテストは左からd0−d7の並びになっていて $4026で拡張ポートにデータを書き込み、 $4033で拡張ポートのデータを読み込みます Cf=0にして$FFと左ローテイトで 1つだけビットを0にして他は1にしてポートのチェックを行います ただしd7のBATTRY_SENCEは モータを起動していない為、0(電圧NG)になります     ROMの種類 RAMアダプタ内のROMは ファミリーコンピュータ用の旧、新バージョンの2つ ツインファミコンのデモで“Nintendo”と出るのと “Famicom”とでるタイプの2つの計4つがあります ROMのバージョンの判定方法は Iコントローラのスタートキーとセレクトーキーを押しながらリセットすると、 RAM、拡張ポート テスト画面になりますが、 そのテスト画面になる前にIコントローラの右とAを押すと メッセージがでます。 このときDEV 2があれば新バージョン、 数字が出ないのは旧バージョンになります ツインファミコンの方は両方ともDEV 2なので 起動画面が違うだけのようです   若干ROMエントリのアドレスが変っていますので、 そこの部分をコールされると動かない可能性がでます しかし実際に純正ソフトでは使わないようになっているようで 実際問題での不都合はありません 非ライセンスソフトのDISK HACKER Ver1.0では FCBのブロックに$FFがあると 新バージョンではエラーがでます(旧バージョンはそのままコピーが出来ます) バックアップ活用研究のDISK COPYでは RAMアダプタのバージョンに合わせてアドレス変更して対応しています     NMI割り込み $E18B   ワークエリアの$0100のd7−6(NMIコード)を見て ジャンプするようになっています。  NMIコード   $00=RAMアダプタ用 $E18B   $40=ゲーム用0    JMP ($DFF6)   $80=ゲーム用1    JMP ($DFF8)   $C0=ゲーム用2    JMP ($DFFA)     IRQ割り込み $E1C7 ディスク アクセスに使用 ワークエリアの$0101のd7−6を見てジャンプします    IRQコード   $00    =ディスク ロード・スキップの終了   $01〜$3F=ディスク ロード・スキップ nnバイト(nn=$01〜$3F)  *$40    =ディスク1バイト転送            読み込みの場合 A、Xにデータが読み込まれる            書き込みの場合 A  にデータをセットする   $80    =ディスク ステータスを読む   $C0    =JMP ($DFFE)      *$40だけPC−下位、PC−上位、PSRを空読みしてRTSを実行($E7A3の割り込みトラップから戻る為)     リセット割り込み $EE24   電源を入れるとオートリセットが掛かるので 電源を入れるかリセットを押すとココにジャンプします まずPPUの設定、その他のポートの設定、スタックの設定を行います 次にNMIコードを$C0、IRQコードを$80をセットします リセットコードがあり使用アドレスは $0102−$0103のリセットコードによって動作が変わります    1.$0102が$35以外  RAMアダプタのデモへ行きます。  2.$0102が$35、$0103が$53ならスクロールセット。JMP ($DFFC)  3.$0102が$35、$0103が$ACなら$53にセット、スクロールセットしてJMP ($DFFC)  4.$0102が$35、$0103が$53、$ACでなければ RAMアダプタのデモ   電源を入れると本体RAMの内容が不確定なので$0102と$0103の内容が 特定のデータかチェックして一番最初の起動の判断を行います 次にリセットしたときにRAMアダプタの起動かゲームの再起動が任意に出来ます。    $0102、$0103のデータがリセットコード以外の値(電源をOn)ならデモンストレーションへ  $0102が$35、$0103が$ACなら$0103:$53にしてゲームのリセットベクトルへ  $0102が$35、$0103が$53ならゲームのリセットベクトルへ   スクロールセットは$EAEAのサブルーチンコールを行いますので ゲームではポート$2005のセットは$00FC,$00FDと$EAEAのコールを行い ディスクシステムの基準に倣った方が良いです    
拡張I/Oポート $4020:(出力) IRQタイマ下位 クロックは1.79MHz $4021:(出力) IRQタイマ上位 $4022:(出力) 2C33 IRQタイマコントロール  d7: −  d6: −  d5: −  d4: −  d3: −  d2: −  d1:1=IRQタイマカウント開始、0=IRQタイマカウント停止  d0:1=IRQタイマ許可    、0=IRQタイマ禁止   $4023:(出力) 2C33 I/Oコントロール  d7: −  d6: −  d5: −  d4: −  d3: −  d2: −  d1:サウウンドT/Oのアクセス 1=許可、0=禁止  d0:ディスク I/Oのアクセス 1=許可、0=禁止   $4024:(出力) ディスク ライトデータ(/WRITE_DATA)       1バイトのデータをシフトレジスタによって       /WRITE_DATAにシリアルデータで転送されます         $4023 d0=1 ディスクI/Oアクセス許可       $4025 d2=0 /WRITEGATE データ ライト        $4030 d7=1 リード・ライト可能       の条件がそろってないと書き込めません     $4025:(出力) ディスク コントロール  d7:IRQデータ転送    1=実行する     、0=実行しない  d6:CRCレジスタ     1=クリアする    、0=クリアしない  d5:不明 (常に1)    1=         、0=  d4:CRC−Hコントロール 1=行う       、0=行わない  d3:スクロール       1=Vスクロール   、0=Hスクロール  d2:/WRITEGATE  1=データ リード  、0=データ ライト  d1:/MOTOR      1=モーターの回転停止、0=モーターの回転開始  d0:/RESET      1=リセットを行わない、0=リセットを行う         不明 ほとんど1になっている、CRC転送の実行? 0だとデータ転送が出来ない       CRC−Hコントロールを行うと書き込みの場合 CRC−Hが$4024に転送され                              WaitでCRC−Hをディスクに書き込む?       読み込みの場合 次にロードした$4031のデータとCRC−Hの比較を行い               結果を$4030のd4(同じなら0)に出力する?       /RESETは転送タイミングのリセット   $4026:(出力) バッテリーコントロール、背面の拡張I/Oライト  d7:BATTRY_SENCE 1=オン、0=オフ  d6:背面の拡張I/O  d5:背面の拡張I/O  d4:背面の拡張I/O  d3:背面の拡張I/O  d2:背面の拡張I/O  d1:背面の拡張I/O  d0:背面の拡張I/O   $4030:(入力)ディスクI/O ステータス  d7:ドライブの検知       1=リード・ライト可能、0=リード・ライト不可  d6:ヘッド の検知       1=最後まで移動した 、0=最後まで移動していない  d5:  d4:CRC−Hチェック     1=エラー有り    、0=エラー無し  d3:  d2:  d1:シフトレジスタ転送 の検知 1=転送中      、0=転送終了  d0:IRQタイマ割り込みの検知 1=発生した     、0=発生していない         CRCチェックはCRC−HとCRC上位として読み込んだデータが同じなら0になる?   $4031:(入力) ディスク リードデータ(READ_DATA)       READ_DATAから転送されたシリアルデータをシフトレジスタによって       1バイトのデータに変換されます         $4023 d0=1 ディスクI/Oアクセス許可       $4025 d2=1 /WRITEGATE データ リード        $4030 d7=1 リード・ライト可能       の条件がそろってないと読み込めません       ???データを書き込んでいる場合(/WRITEGATE=0)はCRC−Lの値   $4032:(入力) ドライブ ステータス  d7:不明 0  d6:不明 1  d5:不明 0  d4:不明 0  d3:不明 0  d2:/WRITE_PROTECT 1=カード書き込み禁止、0=カード書き込み可  d1:/READY         1=内部に移動している、0=スタート位置  d0:/MEDIA_SET     1=セットされていない、0=セットされた         d6はほとんど1になっている       /WRITE_PROTECTはディスクカードのツメが折れていたら1、折れていなければ0       /READY        はヘッドが一番外に移動し、内に移動し読み書きのが可能な時に0になる       /MEDIA_SET    はディスクカードがセットされていなければ1、セットされれば0   $4033:(入力) バッテリーステータス、背面の拡張I/Oリード  d7:BATTRY_SENCEの結果 1=電圧 OK、0=電圧 NG  d6:背面の拡張I/O  d5:背面の拡張I/O  d4:背面の拡張I/O  d3:背面の拡張I/O  d2:背面の拡張I/O  d1:背面の拡張I/O  d0:背面の拡張I/O       $4040〜$407F(入出力) 波形メモリ  d7:コントロール  d6:コントロール  d5:メモリd5  d4:メモリd4  d3:メモリd3  d2:メモリd2  d1:メモリd1  d0:メモリd0   $4080 ボリューム、エンベロープ(出力)  d7:エンベロープ  1=オン、0=オフ  d6:ボリューム増減 1=+1、0=−1  d5:v5 ボリュームまたはエンベロープ  d4:v4  d3:v3  d2:v2  d1:v1  d0:v0   $4082 周波数下位  d7:f7  d6:f6  d5:f5  d4:f4  d3:f3  d2:f2  d1:f1  d0:f0   $4081 周波数コントロール+上位  d7:エンベロープ×4  d6:ボリューム、スィープ  d5:  d4:  d3:f11  d2:f10  d1:f9  d0:f8   $4084 MODエンベロープ  d7:エンベロープモード 1=オフ、0=オン  d6:減算/加算     1=減算、0=加算  d5:s5 エンベロープモードオフの場合ゲイン、エンベロープスピード  d4:s4 エンベロープモードオンの場合エンベロープスピード  d3:s3  d2:s2  d1:s1  d0:s0   $4085 MODカウンタ  d7:−  d6:b  d5:b  d4:b  d3:b  d2:b  d1:b  d0:b   $4086 MOD周波数下位  d7:f7  d6:f6  d5:f5  d4:f4  d3:f3  d2:f2  d1:f1  d0:f0   $4087 MOD周波数コントロール+上位  d7:MODユニット 1=オン、0=オフ  d6:  d5:−  d4:−  d3:f11  d2:f10  d1:f9  d0:f8     $4088 MODテーブル  d7:−  d6:−  d5:−  d4:−  d3:−  d2:m2  d1:m1  d0:m0 $4089 波形メモリ、ボリューム $408A エンベロープスピード $4090 ボリュームゲイン $4091 波形Acc $4092 MODゲイン $4093 MODテーブル $4094 MODカウンタゲイン $4095 MODカウンタ $4096 波形メモリテーブル? $4097 MODカウンタ値    
ディスク フォーマット FCB部分 まず最初にブロック01、ブロック02が存在します ブロック01にそのディスクのゲーム名、両面ソフトでどの面か、 青色のディスクか黄色のディスクか等の情報が入っています ブロック02はマウントファイル数が書き込まれています     ファイル部分 ブロック03がファイル情報、ブロック04がファイルデータになります ブロック03はファイルID、ファイル名、ロードアドレス等が書かれています ブロック04はバイナリデータになります 1つのファイルはブロック03と04の対となります   ブロック コードの説明 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−  GAP             :      $00  スタートデータ         :1バイト $80  ブロックコード         :1バイト $01    チェックコード         :14バイト *NINTENDO−HVC*    メーカーコード         :1バイト  ゲーム ネーム         :4バイト  ゲーム バージョン       :1バイト  ディスク サイド        :1バイト 両面 $00=A面、$01=B面)/片面 $00のみ  ボリューム(ディスクの順番)  :1バイト 2枚以上のソフトで使用 $00から  ディスクの種類         :1バイト $00=FMC(ノーマル カード)、$01=FSC(シャッター付きカード)  予備1             :1バイト  コールドスタート        :1バイト 起動時に読み込む最大ロードナンバ    不明(予備)          :5バイト $FF、$FF、$FF、$FF、$FF  製造年月日           :3バイト  国コード            :1バイト $49=日本(バーコードと同じか?)  不明              :1バイト $61 地域?  不明              :1バイト $00 場所?  不明              :2バイト $00、$02  不明(各ゲームの情報?)    :5バイト  書換えた年月日         :3バイト 店頭販売の場合、製造年月日と同じ  不明              :1バイト  不明              :1バイト $80 書き込んだシステム?  ディスクライターのナンバ    :2バイト  不明              :1バイト $07  書換えた回数          :1バイト 10進数で書かれている(00=店頭販売のディスク)  実際のディスク サイド     :1バイト $00=A面、$01=B面  不明              :1バイト  デバグバージョンまたは、プライス:1バイト    CRC             :2バイト    ブロック コード$01は3つに分けると   $01−1 *NINTNDO−HVC*   $01−2 ディスク アクセス用(メーカーコードからコールドスタートまで)   $01−3 メーカー管理用       $01−1はディスクシステムに必要なデータでこれが無いとBIOSからのディスクアクセスが出来ません     $01−2はディスクの情報なります ディスクアクセスに必要なデータになります         ディスクサイド=$00(A面)、ボリューム=$00でないと起動出来ません         ゲーム ネームの最後の1バイトはイベント等を表し          $20=通常のディスク          $45=E イベント           ディスクファックスを使った全国トーナメント          $52=R リダクション イン プライス 広告による値引き           コールドスタートは起動時に読み込む最大ロードナンバで一括でファイルを読み込みます          $0Fの場合、ディスク内のロードナンバ$00〜$0Fまで全て読み          ロードナンバ$10以上のファイルは読み込みません     $01−3は主にメーカー管理用         実際のディスク サイドはディスクライタで両面ソフトの書き換え時にチェックされます         もしディスクA面に$01(B面)のデータだとディスクライタはA面の書き換えチェック時にエラーを出します           プライスは値段や周辺機器の対応          書き換え回数が00の場合は販売用のディスクの値段となり           $01=3400円           $03=3400円(とびだせ大作戦でメガネ同梱版と無しの両方)            01以上の場合は書き換えの値段           $00=500円           $01=600円            帰ってきたマリオブラザースの場合は500円でゲーム内の広告によって−100円なので            書き換え料金は500円扱いになる   −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−  GAP             :       $00  スタートデータ         : 1バイト $80  ブロックコード         : 1バイト $02    マウントファイル数       : 1バイト 登録されているファイル数    CRC             : 2バイト   −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−  GAP             :       $00  スタートデータ         : 1バイト $80  ブロックコード         : 1バイト $03    ファイルナンバ         : 1バイト 一番最初のファイルを$00として以降+1される  ロードナンバ          : 1バイト 一括ロードするためのグループナンバ  ファイル ネーム        : 8バイト  アドレス            : 2バイト 下位、上位の順  ファイルの長さ         : 2バイト 下位、上位の順  ファイルの種類         : 1バイト 00=プログラム、01=キャラクタ、02=許諾ファイル    CRC             : 2バイト         ファイルナンバ  最初のファイル(通常はKYODAKUファイル)を$00で次のファイルは$01になり            書き込む場合に使用されます(ファイルを追加するごとに+1)     ロードナンバ   読み込むときに使用されるナンバで他のファイルにも同じナンバがある場合があります            同じナンバだと一度にロードする事が可能になります              ブロックコード$01−2のコールドスタートではそのロードナンバ以下の値がロードされます            例えばコールドスタートが$0Fなら起動時に$00−$0Fまでの            ロードナンバのファイルが一度にロードされ$10以降のファイルはロードされません     ファイル ネーム 目安程度なので同じ名前のファイル ネームがあっても構いません     −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−  GAP             :       $00  スタートデータ         :  1バイト $80  ブロックコード         :  1バイト $04    プログラム           :       データ本体(ブロックコード$03の長さ分)    CRC             :  2バイト   −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− テスト ファイル用  スタートデータ         :  1バイト $80  ブロックコード         :  1バイト $05    データ             :  3バイト $6D、$B6、$DB                   :   |                  :   | 以降この3バイトのデータがディスクの最後まで続く                  :   |    CRC             :  2バイト   −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− CRCは16ビットでスタートデータからブロックの最後まで計算される まずデータとCRCレジスタを右シフトしてCRCレジスタ最下位が1なら CRCレジスタとXOR $8408を実行する これを8回(8ビット分)繰り返せば1バイトのCRC計算となる これを1ブロック分まで繰りかえす       起動時に必要なもの  1.ブロックコード$01−1 ’*NINTNDO−HVC’  2.ブロックコード$01−2 ディスクサイド$00、ゲームボリューム$00、コールドスタート$nn  3.ブロックコード$02のマウントファイル数、マウントファイル数分のファイル  4.$00、$00に’KYODAKU−’の許諾ファイル  5.割込み、リセットベクタ($DFFA〜$DFFF)のあるプログラムファイル   <例>リンクの冒険 A面のファイル内容 ブロックコード$01 ・−−−−−−−−−−−−−−−−−−−−・ |+0 +1 +2 +3 +4 +5 +6 +7|    | |−−−−−−−−−−−−−−−+−−−−| |01 2A 4E 49 4E 54 45 4E|.*NINTEN| |44 4F 2D 48 56 43 2A 01|DO-HVC*.| |4C 4E 4B 20 00 00 00 00|LNK ....| |00 0F FF FF FF FF FF 62|.......b| |01 14 49 61 00 00 02 00|..Ia....| |25 02 18 00 62 01 14 FF|%...b...| |FF FF FF FF 00 00 00 00|........| ・−−−−−−−−−−−−−−−−−−−−・    ’*NINTNDO−HVC’  メーカーコード  $01  ゲームネーム   ’LNK ’  ゲームバージョン $00  ディスクサイド  $00 A面  ボリューム    $00  ディスクの種類  FMC  予備1      $00  コールドスタート $0F       |     ブロックコード$02  マウントファイル数=$07     ブロックコード$03 ・−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−・ |Fnn|Lnn| ファイル名  |アドレス | 長 さ |  種 類  | |−−+−−+−−−−−−−−+−−−−−+−−−−−+−−−−−−−| |$00|$00|KYODAKU−|$2800|$00E0|$02(許 諾)| |$01|$03|MAIN−PRG|$6340|$7CC0|$00(PRG)| |$02|$28|CASTLE−L|$C000|$1FF6|$00(PRG)| |$03|$29|ENDING−P|$D660|$0996|$00(PRG)| |$04|$01|CHARA−00|$0000|$2000|$01(CHR)| |$05|$14|CHARA−05|$0E00|$09C0|$01(CHR)| |$06|$06|SAVE−DAT|$6000|$0338|$00(PRG)| ・−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−・   コールドスタート $0Fなので起動時 L$00〜$0Fのファイルをロード指定 ディスク サイドA面、ボリューム$00なので起動ディスクとみなしロード開始    $00 $00 KYODAKU−  $01 $03 MAIN−PRG  $04 $01 CHARA−00  $06 $06 SAVE−DATの4つが一括ロードされる   一括ロード終了後、VRAMの$2800−$28DFに ’KYADAKU−’ファイルがロードされたかチェックを行い 許諾ファイルがVRAMにロードされているのなら、 上スクロールで許諾画面を表示して ’MAIN−PRG’の$DFFC−$DFFDのアドレスにジャンプします       書き込む場合  CRCレジスタのリセット=0  GAP $00を書き込む  CRCレジスタのリセット=1     |     |スタートデータ$80以降を書き込む     |  CRCデータ下位の書き込み  CRCコントロール=1  CRCデータ上位の書き込み   読み込む場合  GAP $00を読み込む  CRCレジスタのリセット=1     |     |データを読み込む     |  CRCデータ下位の読み込む  CRCコントロール=1  CRCデータ上位の読み込む     ブロックコード$01の書き込み例   JSR $E64D    ;Boot Disk Drive   LDA $00FA   AND #$2B   STA $4025     LDA #$00   STA $4024   LDY #$C5   JSR $E153   LDY #$86   JSR $E153     LDA #$01     ;Write $00,$80,$01   JSR $E6B0    |    | *NINTENDO−HVC*...のデータをJSR $E7A3で書き込む    |   JSR $E729    ;Write CRC    
エラー ドライブ&ディスクセット関連   01:DISK SET ERR.01      ディスクが正しくセットされていない 02:BATTERY ERR.02       ディスクドライブの電圧が規定値以下になっている 03:WRITE PROTECT ERR.03 ライトプロテクトのツメが折れているのに書き込もうとした 04:GAME MAKER ERR.04    違うメーカのディスクがセットされた 05:GAME NAME ERR.05     違うゲームのディスクがセットされた 06:GAME VERSION ERR.06  違うバージョンのディスクがセットされた 07:A.B.SIDE ERR 07      違うサイドのディスク(表と裏)がセットされた 08:DISK NUMBER ERR.08   違う順番のディスクがセットされた 09:ERR.09               違うディスクの種類がセットされた 10:ERR.10               違う予備1のデータがセットされた    08はROM内ではDISK NO. ERR.08として出力  11−19はディスクライター用?   ファイルアクセス関連 20:DISK TROUBLE ERR.20  許諾ファイルが読み込めない 21:DISK TROUBLE ERR.21  ブロックコード$01の*NINTENDO−HVC*が見つからない 22:DISK TROUBLE ERR.22  ブロックコード$01の開始マーク$01が見つからない 23:DISK TROUBLE ERR.23  ブロックコード$02の開始マーク$02が見つからない 24:DISK TROUBLE ERR.24  ブロックコード$03の開始マーク$03が見つからない 25:DISK TROUBLE ERR.25  ブロックコード$04の開始マーク$04が見つからない 26:DISK TROUBLE ERR.26  ディスクに正しく書き込みが出来ない 27:DISK TROUBLE ERR.27  CRCエラーを検出 28:DISK TROUBLE ERR.28  ディスク読み込みでタイミングが合っていない(読み込み途中でヘッドが最後まで行った) 29:DISK TROUBLE ERR.29  ディスク書き込みでタイミングが合っていない(書き込み途中でヘッドが最後まで行った)   ユーザーセーブ関連 30:DISK TROUBLE ERR.30  ディスクに書き込みが出来なくなった(容量不足またはドライブ・プロテクトによる強制終了) 31:DISK TROUBLE ERR.31  ディスクのデータ数が合わない、または書き込もうとしたマウントファイル数がマイナスになった   35:DISK TROUBLE ERR.35  テスト ファイル(ブロックコード$05ファイル)の書き込み失敗   その他 40:DISK TROUBLE ERR.40  一括ロードでロード出来なかったファイルがあった(ファイル数が足りない) 41:DISK TROUBLE ERR.41  不明(きね子IIの説明書にERR.41〜の表記あり)   *DISK TROUBLE ERR.35以降は  ROMルーチンではなくソフトのルーチンでエラーの判断を行います     ERR40について(リンクの冒険V1.1の場合) リンクの冒険では一括ロードが出来なかった場合 ERR.40を出力するようになっています また他社のソフトでも同様になっている場合があります(きね子IIで確認)     <MAIN−PRG>  入力:Y=ロード番号 出力:A=エラーコード(0=エラー無し)   A84E8:JSR $8533   ;サウンドオフ       ※1       LDA $00FF   ;PPU R0 b2=0       AND #$FB       STA $00FF       STA $2000       TYA         ;Y保存(ロード番号)       PHA         LDA $8489,Y ;一括ロードナンバーセット ※2       STA $8507       LDA $849B,Y       STA $8507+1         JSR $E1F8   ;一括ファイル ロード   ※3       DW  #$846E  ;FCB Dataアドレス D8507:DW  #$0000  ;一括ロードナンバー         TAX         ;X=エラーコード(0=エラー無し)       STY $0000   ;0000:ロードしたファイル数           PLA         ;Y,A=ロード番号    ※4       TAY       CPX #$00    ;エラーならA851Bへ       BNE A851B ;+++++++++++++++++ ;+ 通常のエラー無しの場合   + ;+++++++++++++++++       LDA $84AD,Y ;Y=ロード番号       CMP $0000       BEQ A851B         LDX #$40    ;ERR.40 ;−−−−−−−−−−−−−−−−− ;+++++++++++++++++ ;+ サブルーチン終了      + ;+++++++++++++++++ A851B:STX #070A   ;エラーコード(0=エラー無し)       TXA         RTS   ※1.エラーメッセージ表示の為のPPU設定   ※2.ロード番号から一括ロードナンバー設定    パラメータ部分D8507を書き換える    ロード番号#00の場合は$84BFになる     8489:[BF]C3 C7 D5 D8 DC DF CA ポインタ下位        D5 D8 DC DF D0 D5 D8 DC        DF E5       849B:[84]84 84 84 84 84 84 84 ポインタ上位        84 84 84 84 84 84 84 84        84 84   ※3.ROMルーチンコールで一括ファイルロード    ロード番号#00の場合、$84BFのデータになるので    L$nnの01、03、06の3つのファイルを一括ロードする     $01=CHARA−00     $03=MAIN−PRG     $06=SAVE−DAT       846E: 01 4C 4E 4B 20 00 01 00 00 00 (ブロック$01データ)       84BF:[01 03 06 FF]     84C3: 01 28 29 FF     84C7: 10 20 FF     84CA: 10 20 15 26 24 FF     84D0: 10 15 20 26 FF     84D5: 11 21 FF     84D8: 11 21 25 FF     84DC: 12 22 FF     84DF: 12 13 22 23 FF     85E4: FF     85E5: 14 28 FF   ※4.ロードエラーがあれば各エラーコードを出してEND    エラーが無ければ実際にロードしたファイル数と    ロードするべきのファイル数を比較    数が合えばERR 0(エラー無し)としてRTS    数が合わなければERR 40としてRTS    ロード番号#00の場合    ロードするべきのファイル数は3つとなる       84AD:[03]03 02 02 03 02 04 05        02 03 02 04 04 02 03 02        04 02    
DISK ROM エントリ $E000:00 $E001−$E148:キャラクタデータ(文字)   $E149:Wait   $E153:nnミリ Wait    入力:Y=nnミリ    使用:X、Y         Yミリ秒のウェイトをかけます       ルーチン内で$0000をロード、コンペアの実行を行っていますが       時間稼ぎの為で内容の変更はありません       主にディスクアクセスのタイミングに使用   $E161:OBJ+BGオフ    使用:A       $00FE        スプライトとBG画面を表示しません。   $E16B:OBJ+BGオン    使用:A       $00FE        スプライトとBG画面を表示します。   $E171:OBJオフ    使用:A       $00FE        スプライトを表示しません。   $E178:OBJオン    使用:A       $00FE        スプライトを表示します。   $E17E:BGオフ    使用:A       $00FE        BG画面を表示しません。   $E185:BGオン    使用:A       $00FE        BG画面を表示します。   $E18B:NMIベクタ        ディスク システムのNMIベクタです。        割り込みがかかったら$0100のd7−6をみて、それぞれの処理を行ないます。         0100:11** ****で$DFFAの内容の所へジャンプ         0100:10** ****で$DFF8の内容の所へジャンプ         0100:01** ****で$DFF6の内容の所へジャンプ         0100:00** ****でRAMアダプタ内で処理(許諾画面表示中などで使用)   $E1B2:NMIがかかるのを待ちます。    使用:$00FF        まず、Aレジスタ、NMIコード($0100の内容)をスタックにセーブしてから        NMIコード$00にしてNMIがかかるのを待ちます        NMIがかかるとセーブしたNMIコード、Aレジスタを元に戻るようになっています   $E1C7:IRQベクタ    入力:$0101=IRQコード    出力:IRQコードによって異なる          ディスク システムのIRQです。        割り込みがかかったら$0101のd7−6をみて、それぞれの処理を行ないます。         0101:11** **** $DFFEの内容の所へジャンプ         0101:10** **** $4030(ディスクI/Oステータス)を読んでWaitをかけRTI         0101:01** **** ディスク1バイト転送、スタックからPC−L、PC−H、PSRを取り出してRTS                        これは1バイト転送($E7A3)をコールしたアドレスに戻る為                         ライトの場合入力:A=セーブするデータ                               出力:A=CRC下位のデータ                                  X=CRC下位のデータ(Aレジスタと同じ内容)                         リードの場合出力:A=リードデータ                                  X=リードデータ(Aレジスタと同じ内容)         0101:00** **** $0101の内容が$00なら何もせず、                              それ以外はd5−0のデータ分をAにディスクロード(スキップ)   $E1F8:ファイル ロード    入力:1st=ブロックコード$01−2 比較データアドレス下位       2nd=ブロックコード$01−2 比較データアドレス上位       3rd=ロードナンバ群 ポインタ下位       4th=ロードナンバ群 ポインタ上位    出力:X、A=エラーコード $00=エラー無し                  $01=DISK SET ERR.01                  $02=BATTERY ERR.02                  $04=GAME MAKER ERR.04                  $05=GAME NAME ERR.05                  $06=GAME VERSION ERR.06                  $07=A.B.SIDE ERR 07                  $08=DISK NUMBER ERR.08                  $09=ERR.09                  $10=ERR.10                  $21=DISK TROUBLE ERR.21                  $22=DISK TROUBLE ERR.22                  $23=DISK TROUBLE ERR.23                  $24=DISK TROUBLE ERR.24                  $27=DISK TROUBLE ERR.27       Y=ロード出来たファイル数    使用:A、X、Y       $0000       $0001       $0002       $0003       $0004       $0005       $0007       $0008       $000E       $00F8       $00F9       $00FA       $0101          ブロックコード$01のチェックを行ってから($E445を実行)        ブロックコード$02のマウントファイル数を読み込み($E484を実行)        ロードナンバデータで$FF(エンドマーク)が出るまでファイルロードを行います        ただし、ロードナンバ群の第1バイトが$FFならコールドスタートとしてロードされます          このルーチンで一括ロードを行うのですが        ファイルをロードできなくてもエラーが出ない恐れがあります        その為に幾つロード出来たかYレジスタにロードしたファイル数が入ります        ロードするファイル数とロード出来たファイル数とが合わないとERR.40として        各自で処理する必要があります(ROMルーチンでは何もしません)           ロードナンバ群 nn,mm,...,$FF(エンドマーク)            ロードするロードナンバが記されている(最大19個まで)          ロードナンバ群の第1バイト $FF=コールドスタートの値と比較する          その場合エンドマークを足して$FF,$FFになる   $E237:一番最後にファイル セーブ    入力:1st=ブロックコード$01−2 比較データアドレス下位       2nd=ブロックコード$01−2 比較データアドレス上位       3rd=ブロックコード$03 データアドレス下位       4th=ブロックコード$03 データアドレス上位    出力:A=エラーコード $00=エラー無し                $01=DISK SET ERR.01                $02=BATTERY ERR.02                $04=GAME MAKER ERR.04                $05=GAME NAME ERR.05                $06=GAME VERSION ERR.06                $07=A.B.SIDE ERR 07                $08=DISK NUMBER ERR.08                $09=ERR.09                $10=ERR.10                $21=DISK TROUBLE ERR.21                $22=DISK TROUBLE ERR.22                $23=DISK TROUBLE ERR.23                $26=DISK TROUBLE ERR.26                $27=DISK TROUBLE ERR.27       $0008=コールドスタート出来る最大ロードナンバ    使用:A、X、Y       $0004       $0005       $0006       $0007       $0009       $000A       $000B       $000C       $000D       $00F8       $00F9       $00FA       $0101          Aレジスタに$FFを入れて、下のファイルセーブを行います   $E239:ファイル セーブ    入力:A=$00から$FE $0006で指定した場所−1にセーブ(最後のファイル)         $FF      最後にセーブ(新しく作成)       1st=ブロックコード$01−2 比較データアドレス下位       2nd=ブロックコード$01−2 比較データアドレス上位       3rd=ブロックコード$03 データアドレス下位       4th=ブロックコード$03 データアドレス上位    出力:A=エラーコード $00=エラー無し                $01=DISK SET ERR.01                $02=BATTERY ERR.02                $04=GAME MAKER ERR.04                $05=GAME NAME ERR.05                $06=GAME VERSION ERR.06                $07=A.B.SIDE ERR 07                $08=DISK NUMBER ERR.08                $09=ERR.09                $10=ERR.10                $21=DISK TROUBLE ERR.21                $22=DISK TROUBLE ERR.22                $23=DISK TROUBLE ERR.23                $26=DISK TROUBLE ERR.26                $27=DISK TROUBLE ERR.27       $0008=コールドスタート出来る最大ロードナンバ    使用:A、X、Y       $0004       $0005       $0006       $0007       $0009       $000A       $000B       $000C       $000D       $00F8       $00F9       $00FA       $0101          ブロックコード$01のチェックを行ってから($E445を実行)        指定した番号のファイルをセーブを行います        またブロックコード$02にファイルナンバが書き込まれます        ロックコード$03 データアドレスはロードナンバからファイルタイプまで        書かれているアドレスを指します        セーブが成功すれば、ベリファイの実行を行います          またベリファイの前にマウントファイル数の書き込みを行います          ファイルはブロックコード$04も含む           LDA #$05         JSR #$E239         DB  $01−2データ下位,$01−2データ上位         DB  ファイル データ下位,ファイル データ上位         BNE ERROR               |           $01−2データはメーカーコードからコールドスタートの次の$FFまで         ファイルデータはブロックコード$03のロードナンバからファイルタイプまで         ファイルデータに記されているアドレスと長さが書き込む範囲になります   $E26B:ファイル セーブ (メイン)    入力:$0000=ブロックコード$01−2 比較データアドレス下位       $0001=ブロックコード$01−2 比較データアドレス上位       $0002=ブロックコード$03 データアドレス下位       $0003=ブロックコード$03 データアドレス上位       $000E=$00から$FE $0006で指定した場所−1にセーブ             $FF      最後にセーブ    出力:A=エラーコード $00=エラー無し                $01=DISK SET ERR.01                $02=BATTERY ERR.02                $04=GAME MAKER ERR.04                $05=GAME NAME ERR.05                $06=GAME VERSION ERR.06                $07=A.B.SIDE ERR 07                $08=DISK NUMBER ERR.08                $09=ERR.09                $10=ERR.10                $21=DISK TROUBLE ERR.21                $22=DISK TROUBLE ERR.22                $23=DISK TROUBLE ERR.23                $26=DISK TROUBLE ERR.26                $27=DISK TROUBLE ERR.27       $0008=コールドスタート出来る最大ロードナンバ    使用:A、X、Y       $0004       $0006       $0007       $0009       $000A       $000B       $000C       $000D       $00F8       $00F9       $00FA       $0101          ブロックコード$01のチェックを行ってから($E445を実行)        $000Eを見て$00なら$0006の場所の最後に移動してファイルをセーブ                $FFならブロックコード$02を読み込んでマウントファイル数の最後に移動してセーブ        ファイルはブロックコード$04も含む   $E2AB:マウントファイル数の書き込み    入力:$0000=ブロックコード$01−2 比較データアドレス下位       $0001=ブロックコード$01−2 比較データアドレス上位       $0006=フマウントァイル数    出力:A=エラーコード $00=エラー無し                $01=DISK SET ERR.01                $02=BATTERY ERR.02                $04=GAME MAKER ERR.04                $05=GAME NAME ERR.05                $06=GAME VERSION ERR.06                $07=A.B.SIDE ERR 07                $08=DISK NUMBER ERR.08                $09=ERR.09                $10=ERR.10                $21=DISK TROUBLE ERR.21                $22=DISK TROUBLE ERR.22                $23=DISK TROUBLE ERR.23                $27=DISK TROUBLE ERR.27       $0008=コールドスタート出来る最大ロードナンバ   使用:A、X、Y       $0002       $0004       $0005       $0006       $0007       $0009       $00F8       $00F9       $00FA       $0101          ブロックコード$01のチェックを行ってから($E445を実行)        ブロックコード$02のマウントファイル数の書き込みを行います   $E2B7:ブロックコード$01のチェック、マウントファイル数の書き込み    入力:A=マウントファイル数       $0000=ブロックコード$01−2 比較データアドレス下位       $0001=ブロックコード$01−2 比較データアドレス上位    出力:A=エラーコード $00=エラー無し                $01=DISK SET ERR.01                $02=BATTERY ERR.02                $04=GAME MAKER ERR.04                $05=GAME NAME ERR.05                $06=GAME VERSION ERR.06                $07=A.B.SIDE ERR 07                $08=DISK NUMBER ERR.08                $09=ERR.09                $10=ERR.10                $21=DISK TROUBLE ERR.21                $22=DISK TROUBLE ERR.22                $23=DISK TROUBLE ERR.23                $27=DISK TROUBLE ERR.27    使用:A、X、Y       $0002       $0004       $0005       $0006       $0007       $0009       $00F8       $00F9       $00FA       $0101          ブロックコード$01のチェックを行ってから        ブロックコード$02に指定したマウントファイル数の書き込みを行います。   $E2BB:ブロックコード$01のチェック、マウントファイル数の削除    入力:A=削除するファイル数       $0000=ブロックコード$01−2 比較データアドレス下位       $0001=ブロックコード$01−2 比較データアドレス上位    出力:A=エラーコード $00=エラー無し                $01=DISK SET ERR.01                $02=BATTERY ERR.02                $04=GAME MAKER ERR.04                $05=GAME NAME ERR.05                $06=GAME VERSION ERR.06                $07=A.B.SIDE ERR 07                $08=DISK NUMBER ERR.08                $09=ERR.09                $10=ERR.10                $21=DISK TROUBLE ERR.21                $22=DISK TROUBLE ERR.22                $23=DISK TROUBLE ERR.23                $27=DISK TROUBLE ERR.27    使用:A、X、Y       $0002       $0004       $0005       $0006       $0007       $0009       $00F8       $00F9       $00FA       $0101          ブロックコード$01のチェックを行ってから        ブロックコード$02のマウントファイル数から指定したファイル数の分だけ減らします        この時マウントファイル数がマイナスになるとERR.31となります。   $E2F7:マウントファイル数の読み込み    入力:$0000=ブロックコード$01−2 比較データアドレス下位       $0001=ブロックコード$01−2 比較データアドレス上位    出力:A=エラーコード $00=エラー無し                $01=DISK SET ERR.01                $02=BATTERY ERR.02                $04=GAME MAKER ERR.04                $05=GAME NAME ERR.05                $06=GAME VERSION ERR.06                $07=A.B.SIDE ERR 07                $08=DISK NUMBER ERR.08                $09=ERR.09                $10=ERR.10                $21=DISK TROUBLE ERR.21                $22=DISK TROUBLE ERR.22                $23=DISK TROUBLE ERR.23                $27=DISK TROUBLE ERR.27       $0006=ファイル数       $0008=コールドスタート出来る最大ロードナンバ    使用:A、X、Y       $0004       $0007       $00F8       $00F9       $00FA          ブロックコード$01のチェックを行ってから($E445を実行)        ブロックコード$02のマウントファイル数を読み込みます($E484を実行)        その為、前もってブロックコード$01の比較データを用意する必要があります。   $E301:マウントファイル数+1を書き込む    入力:A=マウントファイル数       1st=ブロックコード$01−2 比較データアドレス下位       2nd=ブロックコード$01−2 比較データアドレス上位    出力:A=エラーコード $00=エラー無し                $01=DISK SET ERR.01                $02=BATTERY ERR.02                $21=DISK TROUBLE ERR.21                $22=DISK TROUBLE ERR.22                $27=DISK TROUBLE ERR.27                $29=DISK TROUBLE ERR.29                $30=DISK TROUBLE ERR.30    使用:A、X、Y       $0002       $0004       $0005       $0006       $0007       $00FA       $0101       スタック          ブロックコード$01−2のチェックを行ってから        マウントファイル数より1つ多く書き込みます   $E305:マウントファイル数を書き込む    入力:A=マウントファイル数       1st=ブロックコード$01−2 比較データアドレス下位       2nd=ブロックコード$01−2 比較データアドレス上位    出力:A=エラーコード $00=エラー無し                $01=DISK SET ERR.01                $02=BATTERY ERR.02                $21=DISK TROUBLE ERR.21                $22=DISK TROUBLE ERR.22                $27=DISK TROUBLE ERR.27                $29=DISK TROUBLE ERR.29                $30=DISK TROUBLE ERR.30    使用:A、X、Y       $0002       $0004       $0005       $0006       $0007       $00FA       $0101       スタック          ブロックコード$01−2のチェックを行ってから        マウントファイル数を書き込みます   $E307:マウントファイル数+nnを書き込む    入力:A=マウントファイル数       X=nn(加えるファイル数)       $0000=ブロックコード$01−2 比較データアドレス下位       $0001=ブロックコード$01−2 比較データアドレス上位    出力:A=エラーコード $00=エラー無し                $01=DISK SET ERR.01                $02=BATTERY ERR.02                $21=DISK TROUBLE ERR.21                $22=DISK TROUBLE ERR.22                $27=DISK TROUBLE ERR.27                $29=DISK TROUBLE ERR.29                $30=DISK TROUBLE ERR.30    使用:A、X、Y       $0002       $0004       $0005       $0006       $0007       $00FA       $0101       スタック          ブロックコード$01−2のチェックを行ってから        マウントファイル数+nnを書き込みます     $E32A:ディスク インフォメーションの収得    入力:1st=ディスク インフォメーション アドレスの下位       2nd=ディスク インフォメーション アドレスの上位    出力:A=エラーコード $00=エラー無し                $01=DISK SET ERR.01                $02=BATTERY ERR.02                $21=DISK TROUBLE ERR.21                $27=DISK TROUBLE ERR.27       $0002−$0003=ディスクの総容量       $000A−$000B=ディスクの総容量    使用:A、X、Y       $0000       $0001       $0004       $0005       $0006       $0009       $000A       $000B       $000C       $000D          ディスクを最初から読み、指定したアドレスにディスク インフォメーションの取得を行います        新規ファイル作成やユーザディスクに使用か?          ディスク インフォメーションの内容         +00 メーカーコード   1バイト         +01 ゲーム ネーム   4バイト         +05 ゲーム バージョン 1バイト         +06 ディスク サイド  1バイト A面=00、B面=01         +07 ディスクの順番   1バイト         +08 ディスクの種類   1バイト 00=FMC(黄色の磁気カード)、01=FSC(シャッター付きカード)         +09 不明(地域?)   1バイト         +0A マウントファイル数 1バイト ブロックコード$02のデータ           +0B ロードナンバー00 1バイト ファイルの順番00のロードナンバ (ブロックコード$03のデータ)         +0C ファイルネーム00 8バイト ファイルの順番00のファイルネーム(ブロックコード$03のデータ)                  |                  | 以降ファイル数分のファイルが続き最後にディスクの総容量                  |           +nn ディスクの総容量の下位         +mm ディスクの総容量の上位          ディスクの総容量はヘッダ部分 +00〜+0A        10バイト                   ファイル部分       ファイルの順番  1バイト                       +0B    ロードナンバ   1バイト                       +0C〜+12ファイルネーム  8バイト                              ロードアドレス  2バイト                              ファイルの長さ  2バイト                              ファイルタイプ  1バイト                              GAP?   255バイト($03と$04分?)                 プログラム部分            ファイルの長さ          以降ファイル部分+プログラム部分がマウントファイル数−1分まで加算されます。        ???ディスクの総容量は$E31Fまで   $E3E7:パラメータの取得、現在のドライブの状態を見る(ロード)    入力:A=$FF(パラメータ4バイト)、$00(パラメータ2バイト)       1st,2nd       3rd、4th(パラメータ4バイトの場合)    出力:$0000=1st パラメータ       $0001=2nd パラメータ       $0002=3rd パラメータ(パラメータ4バイトの場合)       $0003=4th パラメータ(パラメータ4バイトの場合)       A=エラーコード $00=エラー無し                $01=DISK SET ERR    使用:A、X、Y       $0004       $0005       $0006       スタック          パラメータのの取得を行って$0000からそれぞれ対応するデータをセットして        メディア セットを調べます   $E3EA:パラメータの取得、現在のドライブの状態を見る(セーブ)    入力:A=$FF     パラメータ4バイト セット         $00−$FE パラメータ2バイト セット       1st,2nd       3rd、4th(パラメータ4バイトの場合)      出力:$0000=1st パラメータ       $0001=2nd パラメータ       $0002=入力したAレジスタの内容(パラメータ2バイト セットの場合)             3rd パラメータ   (パラメータ4バイト セットの場合)       $0003=4th パラメータ   (パラメータ4バイト セットの場合)       $000E=パラメータnnバイトの値(0か2 エラーの場合)       A=エラーコード $00=エラー無し                $01=DISK SET ERR                $03=WRITE PROTECT ERR      使用:A、X、Y       $0004       $0005       $0006       スタック         パラメータのの取得を行ってJSR命令の実行した後のアドレスをパラメータとして       $0000からそれぞれ対応するデータをセットして       Aレジスタにディスクの状態を送ります。         エラーが発生するとRTSする前にスタック操作を行って       このルーチンを実行したルーチンを強制終了されます   $E3EB:パラメータの取得、現在のドライブの状態を見る メイン    入力:Cf=1 ロード時のドライブ状態を見る          0 サーブ時のドライブ状態を見る       A=$FF     パラメータ4バイト セット         $00−$FE パラメータ2バイト セット       1st、2nd       3rd、4th(パラメータ4バイトの場合)      出力:$0000=1st パラメータ       $0001=2nd パラメータ       $0002=入力したAレジスタの内容(パラメータ2バイト セットの場合)             3rd パラメータ   (パラメータ4バイト セットの場合)       $0003=4th パラメータ   (パラメータ4バイト セットの場合)       $000E=パラメータnnバイトの値(0か2 エラーの場合)       A=ロードの場合 $00=エラー無し                $01=DISK SET ERR.01           セーブの場合 $00=エラー無し                $01=DISK SET ERR.01                $03=WRITE PROTECT ERR.03      使用:A、X、Y       $0004       $0005       $0006       スタック         パラメータのの取得を行って前にJSR命令の実行した後のアドレスをパラメータとして       $0000からそれぞれ対応するデータをセットして       Aレジスタにディスクの状態を送ります       セーブの状態なら$E3EAをサブルーチンコールをすれば良いのですが       ロードの状態はCf=1にしてから$E3EBをコールする事になります。         エラーが発生するとRTSする前にスタック操作を行って       このルーチンを実行したルーチンを強制終了されます   $E445:ブロックコード$01 リード、チェック    入力:$0000=ブロックコード$01−2 比較データアドレス下位       $0001=ブロックコード$01−2 比較データアドレス上位    出力:A=エラーコード $00=エラー無し                $01=DISK SET ERR.01                $02=BATTERY ERR.02                $04=GAME MAKER ERR.04                $05=GAME NAME ERR.05                $06=GAME VERSION ERR.06                $07=A.B.SIDE ERR 07                $08=DISK NUMBER ERR.08                $09=ERR.09                $10=ERR.10                $21=DISK TROUBLE ERR.21                $22=DISK TROUBLE ERR.22                $23=DISK TROUBLE ERR.23                $27=DISK TROUBLE ERR.27       $0008=コールドスタート出来る最大ロードナンバ      使用:A、X、Y       $0004       $0007       $00F8       $00F9       $00FA          ブロックコード$01−1と$01−2のチェックを行います        $01−3とCRCはスキップされる        違うメーカ、ゲームネーム、バージョン等の判断が出来ます        ブロックコード$01−2のチェックは予備1まで必要です   $E484:ブロックコード$02のマウントファイル数 リード    出力:A=エラーコード $00=エラー無し                $27=DISK TROUBLE ERR.27       $0006=マウントファイル数      使用:A、X、Y       $0004       $0007       $00F9       $00FA       $0101         マウントファイル数を読み、CRCチェックを行います。   $E492:ブロックコード$02のマウントファイル数 ライト    入力:A=マウントファイル数      使用:A、X、Y       $0004       $0007       $00FA       $0101         マウントファイル数を書き込み、CRCデータを書き込みます。   $E4A0:ファイル チェック    入力:$0002=ロードナンバ群 ポインタ下位       $0003=ロードナンバ群 ポインタ上位       $0008=コールドスタートの値      出力:$0009=ロード コントロール $00=ロード                        $FF=スキップ       $000E=ロード出来るファイル カウンタ      使用:A,X、Y       $0101         指定したファイルがロードが出来るかチェックを行います       ファイルナンバの読み込みから始まりますので       ブロックコード$03の$00、$80、$03を読んでからコールします       ロードナンバ群とブロックコード$03を読み同じなら $0009に$00、$000Eをインクリメント                            違うのなら$0009に$FF          ロードナンバ群 nn,mm,...,$FF(エンドマーク)                 ロードするロードナンバが記されている(最大19個まで)                 ロードナンバ群の第1バイト $FF=コールドスタートの値と比較する     $E4DA:全てのファイルをスキップ    入力:$0006=マウントファイル数      使用:A、X、Y       $0002       $0003       $0004       $0007       $0008       $0009       $000A       $000B       $000C       $000D       $00F9       $00FA       $0101          マウントファイル数の次の所まで移動します        新しくファイルを追加するなどにコールします   $E4E0:指定したファイル数をスキップ    入力:A=スキップするファイル数      使用:A、X、Y       $0002       $0003       $0004       $0007       $0008       $0009       $000A       $000B       $000C       $000D       $00F9       $00FA       $0101          指定したファイル数をスキップします   $E583:ブロックコード$03のデータ解析    入力:$0002=ブロックコード$03 データポインタ下位       $0003=ブロックコード$03 データポインタ上位      出力:$000A=ロード、セーブアドレス 下位       $000B=ロード、セーブアドレス 上位       $000C=ファイルの長さ 下位       $000D=ファイルの長さ 上位      使用:A、X、Y       $00FE          前もって読み書きしたブロックコード$03の内容に沿って        ブロックコード$04へ読み書きする為に        アドレス、ファイルの長さを取得し        ファイルの種類がキャラクタか許諾ファイルなら        PPUアドレスをセットします        またPPUロードの為1回$2007を空読みを行っています   $E64D:ディスク ドライブの起動    出力:A=エラーコード $00=エラー無し                $01=DISK SET ERR.01                $02=BATTERY ERR.02      使用:A、X、Y       $0004       $00F8       $00F9       $00FA          モータ・オフ        約0.512秒のウェイト        モータ・オン+バッテリーチェック        ディスクセットのチェックを行いながら        /READY=0になるまで待ちます   $E685:ディスク ドライブ モーター ストップ    出力:A=$4025の内容    使用:A       $00FA          ドライブのモーターを止めます        $4025に0010 ?110Bを出力し、その内容をAレジスタ出力されます        このAレジスタはドライブのモータ スタート($EE17)で使用します        つまり$E685と$EE17は対で使用(間にウェイトが入る場合がある)されます   $E68F:ブロックコードの読み込み    入力:A=ブロックコード    出力:A=エラーコード $00=エラー無し                $21=DISK TROUBLE ERR.21                $22=DISK TROUBLE ERR.22                $23=DISK TROUBLE ERR.23                $24=DISK TROUBLE ERR.24    使用:A、X、Y       $0004       $0007       $00F9       $00FA       $0101          CRCレジスタをリセットを行い、        1バイト読み込んだデータをブロックコードとして読みます        ヘッドが予めブロックコードのある所にいなければなりません   $E6B0:ブロックコードの書き込み    入力:A=ブロックコード      使用:A、X、Y       $0004       $0007       $00FA       $0101          $4025の設定(AND #$2Bをとる)        約0.01秒のウェイト        GAP $00を書き込む        CRCレジスタのリセット        スタートデータ $80を書き込む        指定したブロックコードを書き込みます(1バイト)        ヘッドが予めブロックコードのある所にいなければなりません   $E6D5−$E6E2:*NINTENDO−HVC* データ       '*CVH-ODNETNIN*'(逆になっています)   $E6E3:*NINTENDO−HVC*のチェック    出力:A=エラーコード $00=エラー無し                $01=DISK SET ERR.01                $02=BATTERY ERR.02                $21=DISK TROUBLE ERR.21    使用:A、X、Y       $0004       $0007       $00F8       $00F9       $00FA          ドライブを起動し        ブロックコード$01−1の'*NINTENDO-HVC*'があるかチェックを行います        '*NINTENDO-HVC*'が無ければドライブを止め        Aレジスタにエラーコード$21を返します   $E706:CRC リード    出力:A=エラーコード $00=エラー無し                $01=DISK SET ERR.01                $27=DISK TROUBLE ERR.27                $28=DISK TROUBLE ERR.28    使用:$00FA         CRC−Lデータをリード(データ自体は使用しません)       CRC−Hコントロールを1($4025のd4=1)       CRC上位バイトをリード       リードしたデータがCRC−Hコントロールによってチェックが行われ       結果が$4030のd4に現れ(1=エラー、0=エラー無し)       それの合わせてエラーコードが出力され、ドライブクローズされます   $E729:CRC ライト    入力:A=CRC−Lデータ    出力:A=エラーコード $00=エラー無し                $01=DISK SET ERR.01                $29=DISK TROUBLE ERR.29                $30=DISK TROUBLE ERR.30    使用:$00FA         *CRC−Lデータをライト       CRC−Hコントロールを1($4025のd4=1)       約0.0005秒のウェイト                      <−ここでCRC−Hが書き込まれている?       $4032の/READY=1(d1=1)ならエラー(ERR.31)                    0(d1=0)ならエラーなし         *CRC−LデータはIRQの1バイトデータ転送ルーチンでAレジスタに出力されています     $E761:2バイトロード、ドライブのクローズ    入力:$000A=ロードアドレス下位       $000B=ロードアドレス上位    出力:A=エラーコード $00=エラー無し                $01=DISK SET ERR.01                $28=DISK TROUBLE ERR.28    エラーコード$28 (エラーの場合)    使用:$00FA          2バイトロードしてドライブをクローズします        CRCチェックは行いません        エラーチェックはヘッドの検知を行います        CRCデータのロード?   $E778:ドライブのクローズ(エラー無し)    入力:    出力:A=エラーコード $00=エラー無し    使用:A、X         $00FA        X=$00(エラー無し)として        ドライブ クローズ($E786)を実行します        当然、出力でAレジスタには$00が入ります   $E77F:ディスク コンペア データ Zfチェック    入力:Zf=0 比較データと違う          1 比較データと同じ    出力:A=エラーコード(Zf=0で入力の場合)    使用:$0004       $00FA          前もってデータを比較したりしてZfの変化を見るルーチンになります         入力でZf=1なら何もせずRTS               0ならエラー        エラーでは$0004のスタックデータをスタックポインタにして        ドライブ クローズ、エラー出力して強制終了します   $E786:ドライブ クローズ    入力:X=エラーコード    出力:A=エラーコード(Xレジスタの値)    使用:A、X       $00FA                $4025 d7:0               6:0               5:1               4:0               3:*               2:1               1:1               0:*        XレジスタをAレジスタにコピーして、IRQをオンにします   $E794:IRQ 1バイト転送の開始    入力:A=ライト データ(書き込みの場合)    出力:A=CRC下位  (書き込みの場合)       X=リード データ(読み込みの場合)       A=リード データ(読み込みの場合)    使用:$00FA       $0101          IRQコードを$40(0101:40)        IRQデータ転送を1($4025のd7=1)にして        下の$E7A3(IRQ 1バイト転送)を実行します          ディスクのリード・ライトの始めに使用しますが事前に        CRCレジスタをクリアしていないとCRC計算が正しく行われません   $E7A3:IRQ 1バイト転送    入力:A=ライト データ(書き込みの場合)    出力:A=CRC下位  (書き込みの場合)       X=リード データ(読み込みの場合)       A=リード データ(読み込みの場合)          IRQをオンにして無限ループでIRQが掛かるまで待ちます          1バイトだけIRQによってディスク転送を行いますが、        ディスクドライブ起動、IRQの設定は行わないので前もって設定する必要があります        IRQのディスク1バイト転送ではスタック操作して        このルーチンをコールしたアドレスに返るようになっています・   $E7A7:ファイル アドレスのINC、プログラムの長さのDEC    入力:$000A=ファイル アドレス下位       $000B=ファイル アドレス上位       $000C=ファイルの長さ下位       $000D=ファイルの長さ上位    出力:$000A=ファイル アドレス+1下位       $000B=ファイル アドレス+1上位       $000C=ファイルの長さ−1下位       $000D=ファイルの長さ−1上位    使用:A          $000Aと$000Bを16ビットカウウンタとしてINCします        下の$E7ADへ続き        $000Cと$000Dを16ビットカウウンタとしてDECします          ブロックコード$04のデータを読み書き等に使用します        通常、入力はブブロックコード$03のデータ解析($E583)でセットされ        このルーチンで入力する事はありません   $E7AD:プログラムの長さのDEC    入力:$000C=ファイルの長さ下位       $000D=ファイルの長さ上位    出力:$000C=ファイルの長さ−1下位       $000D=ファイルの長さ−1上位    使用:A          $000Cと$000Dを16ビットカウウンタとしてDECします   $E7BB:文字列出力    入力:1st=データアドレス下位       2nd=データアドレス上位    使用:A、X、Y       $0000       $0001       $0005       $0006          PPUにデータを送ります          JSR #$E7BB        DB  データアドレス下位、データアドレス上位              |          上記の様にJSR命令の後にデータアドレスを指定します        データのフォーマットは         PPUアドレス上位またはコード         PPUアドレス下位         コマンド+表示する長さ         データ          |         コマンド+表示する長さ         データ         $FF(コード エンドマーク)            コード $80−$FFならエンドマークとみなし終了(通常は$FF)                  $60ならサブデータから戻ります                  $4Cなら次のデータをアドレス上位、下位の順でサブデータのアクセスを行います                    サブデータは通常のデータと同じフォーマットになりエンドマークが$60になります            コマンド d7  :1=Y方向+1  、0=X方向+1                6  :1=メモリを埋める、0=データレングスとして処理                5−0:長さ   $E844:パラメータの取得    入力:コールする前の1st       コールする前の2nd    出力:$0000=1st パラメータ       $0001=2nd パラメータ    使用:$0005     $0006          ROMのサブルーチンによってはJSR nnmmの後にパラメータを設定するのですが        それらのサブルーチンが使用して、パラメータを読みRTSする為のスタックを調節します        $0005から$0006の内容が壊れます   $E86A:VRAMバッファ出力    入力:$0302=バッファデータ00 VRAMアドレス上位       $0303=バッファデータ00 VRAMアドレス下位       $0304=バッファデータ00 データの長さ       $0305=バッファデータ00 VRAMに書き込むデータ                |       $03nn=エンドマーク($80から$FF)    出力:$0301=$00       $0302=エンドマーク$80から$FF(実際には$FF)    使用:A、X、Y       $00FF          PPUアクセス時のアドレスの増加をX方向($2000 d2=0)にして        VRAMバッファからアドレス、長さを取得してVRAMにバッファデータを書き込みます        バッファデータの第1バイトのVRAMアドレスが$80から$FFだとエンドマークになります          データフォーマット         バッファデータ00 VRAMアドレス上位         バッファデータ00 VRAMアドレス下位         バッファデータ00 出力データの長さ         バッファデータ00 出力データ                |         バッファデータnn VRAMアドレス上位         バッファデータnn VRAMアドレス下位         バッファデータnn 出力データの長さ         バッファデータnn 出力データ         エンドマーク($80から$FF)   $E8B3:VRAMバッファ入力    入力:X=インデックス($02から)       Y=転送するバイト数       $0302=データ00 VRAMアドレス 上位       $0303=データ00 VRAMアドレス 下位       $0305=データ01 VRAMアドレス 上位       $0306=データ01 VRAMアドレス 下位         |    出力:$0304=指定したデータ00のVRAMの内容       $0307=指定したデータ01のVRAMの内容         |    使用:A、X、Y          $0302にあるVRAMバッファにVRAMの内容を転送します        1バイトごとの転送なので3バイト1組になります        入力するXレジスタの値は$02以上になります           VRAMバッファは          +00 VRAMアドレス上位          +01 VRAMアドレス下位          +02 VRAMの内容    (3バイトで1組になっています)                |          +nn $FF(エンドマーク)          このルーチンではVRAMバッファのアドレスを読んで        その内容をVRAMの内容としてVRAMバッファに書き込みます        データの長さは3バイトで1つの長さになります   $E8D2:メモリからVRAMバッファへ1行分の転送    入力:A=VRAMアドレス上位       X=VRAMアドレス下位       Y=転送する長さ       1st=データアドレス下位、2nd=データアドレス上位       $0300=VRAMバッファ インデックスの上限       $0301=VRAMバッファ インデックス    出力:A=$01 エラー有り         $FF エラー無し       $0002=キャラクタ定義用($0002−$0003に$20足される他のルーチン用)       $0003=キャラクタ定義用       $0301=入力したVRAMバッファ インデックス+データの長さ(次のインデックス)       $0302=VRAMアドレス上位       $0303=VRAMアドレス下位       $0304=データの長さ       $0305=データ              |       $03nn=$FF エンドマーク    使用:A、X、Y       $0000       $0001       $0004       $0005       $0006          メモリからVRAMバッファ($0302−$03FF)へ1行分転送(追加)します        バッファの上限が$0300に設定され        これを超えるとバッファにエンド マーク$FFが書き込まれ        このルーチンをコールしたルーチンが強制終了されます           書き込み例          LDA #$20     ;VRAM上位          LDX #$00     ;VRAM下位          LDY #$04     ;転送する長さ          JSR $E8D2    ;VRAMバッファに転送          DB  データアドレス下位,データアドレス上位          JSR $E1B2 ;VBLANK期間になるまで待つ          JSR $E86A    ;VRAMバッファからVRAMに転送          JSR $EAEA ;スクロール(画面のクローズ)                |            DB  ’ABCD’   ;データ   $E8E1:メモリからVRAMバッファへ数行転送    入力:A=VRAMアドレス上位       X=VRAMアドレス下位       1st=データアドレス下位、2nd=データアドレス上位       $0300=VRAMバッファ インデックスの上限       $0301=VRAMバッファ インデックス    出力:A=$01 エラー有り         $FF エラー無し       $0002=キャラクタ定義用($0002−$0003に$20足される他のルーチン用)       $0003=キャラクタ定義用       $0301=入力したVRAMバッファ インデックス+データの長さ(次のインデックス)       $0302=VRAMアドレス上位       $0303=VRAMアドレス下位       $0304=データの長さ       $0305=データ              |       $03nn=$FF エンドマーク    使用:A、X、Y       $0000       $0001       $0004       $0005       $0006          メモリからVRAMバッファ($0302−$03FF)へ数行転送(追加)します        $E8D2と違うのはデータの第1バイトがPPUデータでなく         d7−4:行数で         d3−0:データの長さ        になります          バッファの上限が$0300に設定され        これを超えるとバッファにエンド マーク$FFが書き込まれ        このルーチンをコールしたルーチンが強制終了されます   $E94F:VRAMバッファ アドレスチェック、リード    入力:X=$00 (VRAMバッファ オフセット)       Y=VRAMバッファ スキップする個数(3バイトで1)       $0000=チェックするVRAMバッファ (VRAMアドレスの上位)       $0001=チェックするVRAMバッファ (VRAMアドレスの下位)    出力:<同じアドレスの場合>        A=VRAMバッファにあるVRAMの内容        Cf=0              <違うアドレスの場合>        チェックしたVRAMバッファ+0=チェックするVRAMアドレス上位($0000)        チェックしたVRAMバッファ+1=チェックするVRAMアドレス下位($0001)        Cf=1        Y=VRAMバッファ インデックス          VRAMバッファ X=インデックス(+0の位置)、Y=スキップする個数(3バイトで1)で        X=$0302+X+3*(Y−1)でチェックするアドレスを決めます        そのアドレスと$0000、$0001と比較して        同じならAレジスタに+2のデータを読み、Cf=0にしています        違う場合は+0、+1に比較した$0000、$0001のアドレスを書き込み        Cf=1にしてエラーとみなします   $E97D:座標からネームテーブル0変換    入力:$0002=Y座標(0から224)       $0003=X座標(0から255)    出力:$0000=ネームテーブル0 上位       $0001=ネームテーブル0 下位    使用:A          ドットの座標からネームテーブル0($2000−$23BF)に変換を行います     $E997:ネームテーブルから座標変換    入力:$0000=ネームテーブル 上位       $0001=ネームテーブル 下位    出力:$0002=Y座標(0から232)       $0003=X座標(0から248)    使用:A          ネームテーブルオフセット($0000−$03BF)からドットの座標に変換を行います        入力のネームテーブル上位は$0000から$03BFで計算を行っているので        どのネームテーブル、ネームテーブルオフセットでも同じ出力になります   $E9B1:乱数の発生    入力:X=インデックスデータ       Y=長さ       ゼロページ    出力:ゼロページ+入力したXレジスタからゼロページ+入力したX+Yまで    使用:A、X、Y       $0000         指定したゼロページ+Xレジスタのアドレスを起点として長さYまでを       発生レジスタとして乱数の発生を行います       指定したゼロページ+Xレジスタのd1だけマスクして$0000にストア       指定したゼロページ+1+Xレジスタのd1と$0000とEORする       0ならCf=0、1ならCf=1       全発生レジスタを右シフトする   $E9C8:仮想OBJエリア セット    使用:A         仮想OBJを$0200に設定します。   $E9D3:ロジック カウンタ    入力:X=カウンタ0のアドレス(ゼロページ内)       A=カウンタ1のアドレス(ゼロページ内)       Y=カウンタ2のアドレス(ゼロページ内)    出力:X=カウンタ0のアドレス(ゼロページ内0から9)       A=カウンタ1のアドレス(ゼロページ内0から255)       Y=カウンタ2のアドレス(ゼロページ内0から255)    使用:A、X、Y          カウンタを1つ減らします        カウンタ0が基本になり、9からカウントダウンして−1になると9に戻ります          カウンタ0が9から0の時にカウンタ1のカウントダウン(00で止まる)                −1の時にカウンタ2のカウントダウン(00で止まる)   $E9EB:リアルタイムでコントローラを読む    出力:$0000:拡張端子のI−コントローラ       $0001:拡張端子のII−コントローラ       $00F5:I−コントローラ       $00F6:II−コントローラ    使用:A、X       $00FB          本体コントローラと外部のコントローラを読んで        各ワークエリアにデータをストアします。   $EA0D:コントローラデータの合成    入力:$0000:拡張端子のI−コントローラ       $0001:拡張端子のII−コントローラ       $00F5:I−コントローラ       $00F6:II−コントローラ    出力:$00F5:I−コントローラ       $00F6:II−コントローラ    使用:A          $E9EBをコールして得たデータをIコン、IIコンの2つにまとめます   $EA1A:リアルタイムで本体コントローラを読む    出力:$00F5:I−コントローラ       $00F6:II−コントローラ       $00F7:I−コントローラを1回押した時の内容       $00F8:II−コントローラを1回押した時の内容    使用:A、X、Y       $0000       $0001          リアルタイムでントローラを読み($E9EBをコール)        ワークエリアにストアします        $00F7と$00F8は        押されたままだと1になり、離すと0になります   $EA1F:リアルタイムで本体コントローラと拡張コントローラを読む    出力:$00F5:I−コントローラ       $00F6:II−コントローラ       $00F7:I−コントローラを1回押した時の内容       $00F8:II−コントローラを1回押した時の内容    使用:A、X、Y       $0000       $0001          リアルタイムでコントローラを読み($E9EBをコール)        コントローラデータの合成($EA0Dをコール)を行い        ワークエリアにストアします        $00F7と$00F8は        押されたままだと1になり離すと0になります      使用:A、X、Y       $0000       $0001   $EA36:本体コントローラを読む    出力:$00F5:I−コントローラ       $00F6:II−コントローラ       $00F7:I−コントローラを1回押した時の内容       $00F8:II−コントローラを1回押した時の内容    使用:A、X、Y       $0000       $0001          リアルタイムでコントローラを読み($E9EBをコール)、レジスタA、Yに読む        リアルタイムでコントローラを読み($E9EBをコール)        1回目と2回目に読んだ内容が同じになるまでループ        同じになったら$00F5から$00F8までのワークに        それぞれストアします   $EA4C:本体コントローラと拡張コントローラを読む    出力:$00F5:I−コントローラ       $00F6:II−コントローラ       $00F7:I−コントローラを1回押した時の内容       $00F8:II−コントローラを1回押した時の内容    使用:A、X、Y       $0000       $0001          $EA36と同様に本体コントローラと拡張コントローラで        コントローラの読み込みを行います   $EA84:PPUメモリを埋める    入力:A=PPU アドレス上位       X=埋めるデータ       Y=パラメータ(PPUアドレスの指定によって違う)    出力:X=指定した埋めるデータ    使用:A、X、Y       $0000       $0001       $0002          指定したPPUアドレスが$2000未満(パターンテーブル)なら        XレジスタのデータをYレジスタで指定した長さ*256バイトで埋めます          指定したPPUアドレスが$2000以上なら        Xレジスタのデータ$0400バイトをネームテーブルに埋め        Yレジスタのデータ$  40バイトをネームテーブルのアトリビュートに埋めます        主に画面クリアに使用          PPUアドレスは上位のみで下位アドレスは$00になります。        転送量も上位になるので256バイト単位になります。   $EAD2:メモリを埋める    入力:A=埋めるデータ       X=スタートアドレス上位       Y=エンド アドレス下位    使用:A、X、Y       $0000       $0001          CPUメモリを特定のデータで埋めます        指定できるのはアドレス上位のみなのでページ単位$nn00−$mmFFが指定範囲になります   $EAEA:スクロールをセット    入力:$00FC=ポート$2005の内容(X座標)       $00FD=ポート$2005の内容(Y座標)       $00FF=ポート$2000の内容    使用:A          VRAMをアクセスした後スクロールセットをするのに使用します        スクロールをセット        PPU R#0を$00FFの内容でセット   $EAFD:テーブルジャンプ    入力:A=テーブジャンプNo.nn($00−$7Fまで)       1st=テーブルジャンプNo.$00 下位アドレス       2nd=テーブルジャンプNo.$00 上位アドレス       3rd=テーブルジャンプNo.$01 下位アドレス       4th=テーブルジャンプNo.$01 上位アドレス                  |    使用:A、X、Y       $0000       $0001          テーブルジャンプを行います        BASICのON A GOTOnnnn,mmmm,...に相当           使用例          JSR $EAFD          DW  ADDRESS0 ;A=$00のジャンプ          DW  ADDRESS1 ;A=$01のジャンプ          DW  ADDRESS2 ;A=$02のジャンプ                 |   $EB13:HVC−007 キーボードのキーマトリクス入力    出力:$0000=キーマトリクスP2 9の反転データ       $0001=キーマトリクスP2 8の反転データ       $0002=キーマトリクスP2 7の反転データ       $0003=キーマトリクスP2 6の反転データ       $0004=キーマトリクスP2 5の反転データ       $0005=キーマトリクスP2 4の反転データ       $0006=キーマトリクスP2 3の反転データ       $0007=キーマトリクスP2 2の反転データ       $0008=キーマトリクスP2 1の反転データ    使用:A、X、Y       $00FB          ファミリーBASICのキーボード(HVC−0007)のキーマトリクス入力を行います        出力データは反転されているので押していると1、離している0になります        P3 1がd0...P3 8がd7になります            $EB66:ポインタ+8バイト、Y=#$00、DEC ($02)    入力:$0000=ポインタ下位       $0001=ポインタ上位       $0002=ブロック(長さ)    出力:Y=$00       $0000=ポインタ下位       $0001=ポインタ上位       $0002=ブロック(長さ)−1    使用:A、Y       $0000=ポインタ下位       $0001=ポインタ上位       $0002=ブロック(長さ)          $0000から$0001をポインタとして        ポインタ+8        Y=#$00        $0002の内容を−1にします        パターンテーブル定義用   $EB69:ポインタ+Aバイト、Y=#$00、DEC ($02)    入力:A=ポインタにプラスする値       $0000=ポインタ下位       $0001=ポインタ上位       $0002=ブロック(長さ)    出力:Y=$00       $0000=ポインタ下位       $0001=ポインタ上位       $0002=ブロック(長さ)−1    使用:A、Y       $0000=ポインタ下位       $0001=ポインタ上位       $0002=ブロック(長さ)          $0000から$0001をポインタとして        ポインタ+A        Y=#$00        $0002の内容を−1にします        パターンテーブル定義用   $EBAF:パターンテーブル定義    入力:Y=PPUアドレス 上位       A=PPUアドレス 下位+コード          d7:PPUアドレス A7          d6:PPUアドレス A6          d5:PPUアドレス A5          d4:PPUアドレス A4          d3:コード D1 11=反転 通常 、10=埋める 通常          d2:コード D0 01=通常 埋める、00=通常 通常          d1:コード 1=リード モード、0=ライト モード          d0:コード 1=$FFで埋める、0=$00で埋める       X=キャラクタ数       1st=パターン データアドレス下位       2nd=パターン データアドレス上位    使用:A、X、Y       $0000       $0001       $0002       $0003       $0004       $00FF          パターンテーブル(キャラクタ)の定義を行います        アクセスするPPUアドレスを指定しますがPPUアドレス下位のd3−0は0になる($xxx0)        次にコード解析でd1−0の設定、d3−2で各キャラクタ定義を行います        キャラクタは1キャラ8バイト+8バイトの計16バイト必要で        コードによって定義のパターン(必要なパターンデータ数)が変わります           コード11(パターン データは1キャラクタ 16バイト必要)          プレーン0 パターン データを反転してVRAMに書き込む          プレーン1 ライト モード=パターン データをVRAMに書き込む                リード モード=VRAMの内容をパターン データに書き込む           コード10(パターン データは1キャラクタ  8バイト必要)          プレーン0 ライト モード=VRAMに$FFまたは$00で埋める                リード モード=VRAMのデータを読み、VRAMに書き込む          プレーン1 ライト モード=パターン データをVRAMに書き込む                リード モード=VRAMの内容をパターン データに書き込む           コード01(パターン データは1キャラクタ  8バイト必要)          プレーン0 ライト モード=パターン データをVRAMに書き込む                リード モード=VRAMの内容をパターン データに書き込む          プレーン1 ライト モード=VRAMに$FFまたは$00で埋める                リード モード=VRAMのデータを読み、VRAMに書き込む           コード00(パターン データは1キャラクタ 16バイト必要)          プレーン0 ライト モード=パターン データをVRAMに書き込む                リード モード=VRAMの内容をパターン データに書き込む          プレーン1 ライト モード=パターン データをVRAMに書き込む                リード モード=VRAMの内容をパターン データに書き込む   $ED37−$EE16:許諾画面 データ   $EE17:ドライブのモータ スタート    入力:A=$4025の内容    使用:A       $00FA         /RESET=1にして/MOTOR=0にします       前もってディスク ドライブ モーター ストップ($E685)を実行しておく必要があります   $EE24:ディスクシステム スタート(リセット ベクタ)       電源を入れたり、リセットされるとココにとびます。   $F1C3:キャラクタ定義    使用:A、X、Y       $0000       $0001       $0002       $0003       $0004       $00FF         BG(PPU$1000)に数字、英字のキャラクタ41文字の定義を行います   $F431:許諾画面の書き込みチェック    出力:Zf=0 エラーなし          1 エラーあり         キャラクタ定義、カラーの設定、BG−Aをクリア       BG−Cにロードされた許諾データとROM内にある許諾データの比較を行います   $F48C:キャラクタ定義の退避または復帰    入力:Y=$03 キャラクタデータの退避         $07 キャラクタデータの復帰    使用:A、X、Y       $0000       $0001       $0002       $0003       $0004       $0007       $0008       $0009       $000A       $000B       $00FF       PPU $2930以降          ディスクを起動したときにはキャラクタ、プログラム、許諾データが一括ロードされている場合があります        キャラクタデータがロードされていても必ずしも許諾画面を確実に表示する英数字コードとは限りません        そこで、このルーチンでロードしたPPU$1000以降のキャラクタデータを        一旦PPU$2930以降を退避用エリアとして一時退避、復帰を行います          データを退避したら英数字のキャラクタ定義を行いPPUにロードした許諾画面のチェック、表示        許諾画面の表示が終了したらデータの復帰を行いロードしたプログラムの実行となります。  
$0000:JSR文の後の第1パラメータ       データアドレス下位       ポインタ下位   $0001:JSR文の後の第2パラメータ       データアドレス上位       ポインタ上位   $0002:JSR文の後の第3パラメータ       VRAMアドレス下位       指定したマウントファイル数   $0003:JSR文の後の第4パラメータ       VRAMアドレス上位   $0004:スタックポインタ退避       データの長さ   $0005:JSRで戻るアドレス下位       ディスクアクセス リトライカウンタ       VRAMバッファの長さ   $0006:JSRで戻るアドレス上位       マウントファイル数   $0007:ブロックコード   $0008:エラーコード       最初に読み込むロードナンバー   $0009:ロード コントロール $00=ロード、$FF=スキップ       セーブ コントロール $00=セーブ、$FF=ベリファイ   $000A:ファイルの先頭アドレス 下位 $000B:ファイルの先頭アドレス 上位   $000C:ファイルの長さ     下位 $000D:ファイルの長さ     上位   $000E:パラメータnnバイトの値       ファイルカウンタ       $00F5:コントローラIの内容 1=オン、0=オフ        A、B、SELECT、START、上、下、左、右 $00F6:コントローラIIの内容 $00F7:コントローラIを1回押した時の内容 $00F8:コントローラIIを1回押した時の内容 $00F9:ポート$4026の内容 $00FA:ポート$4025の内容 $00FB:ポート$4016の内容 $00FC:ポート$2005の内容(垂直) $00FD:ポート$2005の内容(水平) $00FE:ポート$2001の内容 $00FF:ポート$2000の内容       $0100:NMI コントロール        $00=BIOS内        $40=JMP ($DFF6)        $80=JMP ($DFF8)        $C0=JMP ($DFFA)   $0101:IRQ コントロール        $00    =ロード・スキップの終了        $01−$3F=ロード・スキップ バイト        $40    =ディスク1バイト リード・ライト        $80    =ディスク ステータス        $C0    =JMP ($DFFE)   $0102−$0103:RESET コントロール        $0102:35 53=JMP ($DFFC)        $0102:35 AC=$0103を$53にしてスクロールセットの後、JMP ($DFFC)        それ以外のデータはデモ   $0200−$02FF:仮想OBJエリア $0300−$03FF:VRAMバッファ  
ディスクドライブのプロテクト 最初のドライブにはプロテクトは掛かっていませんでしたがコピープログラムの発表や発売され 一定時間(約1秒)しか書き込みが出来ないようになりました。 プロテクトの内容はドライブ内の基板でライト信号が送られたらカウントして約1秒たったら シャットダウンする方式でコレをパターンカットとバイバスを通して無効する方法があります。 最終的にはFDC自身に同等のプロテクトを掛けるのですがロジック回路で破られています。   ソフトでのプロテクト 元々QDなのでそれほどきついプロテクトは掛けられません。 特定のソフトのコピーツールに対してのプロテクトとなります。 またPCから読み書きやデュプリケータでは全くプロテクトの意味がありません。       ダミー ファイル ブロックコード$02のマウントファイル数より多くファイルを持つタイプ とびだせ大作戦、夢工場ドキドキパニック、ディープダンジョンII勇士の紋章(店頭販売、書き換え共)が該当します   主に対DISK HACKER V1.1用です DISK HACKER V1.1までではファイル数を見て必要なファイルだけをコピーしていました とびだせ大作戦のA面では実際のファイルはブロックコード$02のファイル数より1つ多く DISK HACKER V1.1でコピーすると最後の1つだけファイルが足りないものになります そのファイルが無ければコピー品と判断しています ダミーファイルとはいえ、とびだせ大作戦はダミーファイルが本当のメインプログラムになっていて ゲームスタートするとMAINPROG(警告プログラム)がロードされ、その後すぐにダミーファイル(本当のメイン)が RAMに上書きされ実行されます ダミーファイルが上書きされないと警告プログラムが動いてコピー品とみなされメッセージを出します 夢工場ドキドキパニック、ディープダンジョンII勇士の紋章では数バイトのデータが書き込まれていて このファイルがロード出来るかでコピー品の判断を行っています。    とびだせ大作戦ではコピー失敗すると作者からメッセージが出ます。       夢工場ドキドキパニックのコピー失敗       勇士の紋章のコピー失敗       新鬼ヶ島のコピー失敗          40KB ファイル コピーツールのバッファより大きいファイルを持つタイプ 麻雀家族、スーパーロードランナー、きね子IIが該当   1つのファイルがRAM容量よりも大きくなっています ファイルが40KBのファイルがあり、コピーバッファが少ないとコピー出来ないようになっています 主に対DISK HACKER V1.2用 DISK HACKER V1.3ではV1.2より大きいバッファを持ちコピー出来ます。 ファミコンのディスクはランダムアクセスが出来ないQDなのでトラックやセクタ等は無く テープと同じように最低でも一つのファイルを一気に書き込まないといけません つまり分割して一つのファイルを書き込みする事はかなり困難になります しかし、本体メモリはRAMアダプタ32KB+本体ワーク2KB+VRAM2KB+キャラクタ8K計44KBなので 4KB内でコピープログラム、最低限40KBのバッファを取ってコピー出来るツールもあります    スーパーロードランナーではSIDE Aの4番目のファイルLRMAIN01が  ロードアドレス$6000で長さ$A000になります    3番目のファイルPROTECT(ローダ)を本体内ワークRAMにローダを転送、実行  LRMAIN01は$6000から読み込まれますが  ローダによって始めの$2000バイトを空読みして  残りの$8000バイトが$6000−$DFFFにロードされます  ロード終了後、$DFE0−$DFEFのチェック  $6000−$DFFFのチェックを行い  正常ロード出来たなら$6000にジャンプします       44KB ファイル 本体内+RAMアダプタの全RAMと同じ容量のファイルを持つタイプ HACKERのソフトで途中から出てきたプロテクトです   1つのファイルの大きさが44KBで本体内の全RAMより同じになります これだとコピープログラムの入る所が無く ソフトのコピーツールではコピー出来なくなります メインプログラムが$4800からロードして BIOSの$F7FFまでロードするようになっていて 実際にはRAM領域の$6000−$DFFFに プログラムがロードされるようになります HACKERのソフトで同タイトルでも プロテクトが掛かっているのと掛かっていない2タイプがあります。     偽データ ブロックコード$03と$04が合わないプロテクトです アイツーのジンゴローが該当   ブロックコード$03にはファイル名やロードされるアドレス、長さが書き込まれています ブロックコード$04が実際のプログラムやデータとなります そのブロックコード$03で書き込まれた長さと ブロックコード$04の長さが合わないようするタイプです コピーツールでブロックコード$03を見てブロックコード$04のファイルをコピーする コピーツールに対して有効です    ジンゴローでは最後のファイルがブロックコード$03では1バイトの長さになっていますが  次のブロックコード$04では1バイトでなく7バイト×$2000=$E000バイトのデータが書き込まれており  IPLプログラムでデータをメモリとVRAMに振り分けながらロードしています     第1バイトがプログラムデータ(ストア アドレス下位の値で引く)   第2バイトがダミー   第3バイトがダミー   第4バイトがダミー   第4バイトがダミー   第6バイトがキャラクターデータ(ストア アドレス下位の値で足す)   第7バイトがダミー   このデータ群をロード(CRC計算もされているのでダミーデータも必要)する様になっています       CRCエラー ファイルにワザとCRCエラーの出るファイルが存在するタイプ トンカチエディタが該当   ディスクが起動するまでは通常のフォーマットでその後の読み込みにCRCエラーの出るファイルを ロードしてCRCエラーが出るかチェックします コピーツールによっては正しいCRCが書き込まれるので CRCエラーが出るはずのファイルがエラー無しとなり コピーされたと判断しています   オリジナルフォーマット 最後のメーン・ファイルが独自のフォーマットで書き込まれIPLプログラムでロードするプロテクトです 子育てゴッコ、クイックハンターが該当   検査システムでチェックするディスクデータがディスクの最後までデータの読み書きが出来るかチェックされる為 テストファイルが上書きされるので注意が必要なタイプです   途中まで普通のフォーマットでIPLもそのフォーマット内のファイルにあるので IPLをロードして実行、独自のフォーマットで書かれたプログラムを読む 単純なバイナリデータや、加工したデータ、プログラムとダミーデータとVRAMデータと混合等 ソフトによってデータが変わります    子育てゴッコではメインプログラムは$0200−$05FFで  通常のフォーマットの後ろに直接メインプログラムが書かれていて  IPLプログラムでこのメインプログラムを$0200からロード  ロード終了したら最初の0200:20と最後の05FF:23をチェックして  ロードされたか判断をしています  このメインプログラムのコピーに失敗すると隠しゲームのバリケードゲームが遊べます。    クイックハンターではIPLプログラムまで行くまでに自己書き換え(一部分が暗号化されている)しながら  数ヶ所にジャンプされています  最終ファイルはブロックコード$00として書き込まれており  $1000バイト空読みしてから$B000−$CFFFにロードします  $B000以降のロードデータは暗号化されておりEOR $C9(データを一部反転)しながらロードします  当然、このブロックコード$00のファイルもCRCチェックも行われています。       メーカーコード$00 HACKER製コピーツールで HACKER製ソフトをコピー出来ない為のプロテクトです 通常のソフトはメーカーコードは$01からになっており$00は使用していません そこでHACKERのソフトはここに$00を書き込みを行っています メーカーコードが$00だとHACKER製コピーツールではエラー FFを出力して コピーできないようになっています DEV1のRAMディスクとディスクハッカーVer1.0ではエラーが出ずにコピー出来ます DEV2のRAMディスクとディスクハッカーVer1.0ではエラー FFが出てコピー出来ません 他のコピーツールではコピーが出来ますが当然44KBファイルはコピーできません       プログラム書き換えチェック これはプロテクトといってもコピープロテクトでは無く プログラムの改造されたかチェックをするタイプ 改造するとチェックサムエラーのメッセージが出たり、 起動画面に飛んだり、ゲームが起動出来ない様になっています ただし完全なチェックを行っているとは限りません コピーライト表記の書き換え(海賊版)対策? コナミやカプコンのソフトに見かけます    セクションZのチェックサムエラーメッセージ          ナムコのディスクソフト プロテクトでは無いのですがナムコのディスクソフトは 非ライセンス ソフトと同じような許諾画面を出さないような事をしています 実際には許諾画面を出しているのですが RAMアダプタのプログラムで動いてなくて ゲームソフト(IPLMAIN)が割り込みで RAMアダプタからの許諾画面表示を乗っ取っていながら ゲームソフトから許諾画面を表示しています これにより任天堂が許諾画面表示の乗っ取りプログラムに対する プロテクトを掛けるのが難しくなっています つまりプロテクトを掛けるのを防ぐ為の任天堂に対する逆プロテクト(?)に思えますが 真相は不明です  
Home へ戻る