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


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のアドレス  拡張ポートのテストは左からBit0−Bit7の並びになっていて  $4026で拡張ポートにデータを書き込み、$4033で拡張ポートのデータを読み込みます  Cf=0にして$FFと左ローテイトで1つだけビットを0にして他は1にしてポートのチェックを行います  ただしBit7のBATTRY_SENCEはモータを起動していない為0(電圧NG)になります IPLの種類  IPL ROMはファミコン用のRAM アダプターの旧、新バージョンの2つ  ツインファミコンのデモでNintendoと出るのとFamicomとでるタイプの2つの計4つがあります  IPLのバージョンの区別方法はIコントローラのスタートキーとセレクトーキーを押しながらリセットすると、  RAM、拡張ポート テスト画面になりますが、そのチェックの画面になる前に  Iコントローラの右とAを押すとメッセージがでます。  このときDEV 2があれば新バージョンです。  数字が出ないのは旧バージョンです。  ツインファミコンの方は両方ともDEV 2なので新バージョンと同等で起動画面が違うだけのようです。 IPLのバージョンの違いによる不都合  若干ROMエントリのアドレスが変っていますので、そこの部分をコールされると動かない可能性がでます。  しかし実際に純正ソフトでは使わないようになっているようで、実際問題での不都合はありません。  非ライセンスソフトのDISK HACKER Ver1.0ではFCBのブロックが全て$FFだと  新バージョンではエラーがでます。(旧バージョンはそのままコピーが出来ます)  バックアップ活用研究のDISK COPYではRAMアダプタのバージョンに合わせて変更して  対応しています。 IPLの起動  RAMアダプタを本体にセットして、電源を入れればデモが動きます。  ディスクがセットされればディスクロードするのですが基本はFCBの内容にしたがって  ロード、メモリ$DDFCの内容(アドレス)をみてジャンプします。 NMI割り込み(エントリアドレスは$E18B)  ワークエリアの$0100のBit7−6(NMIコード)を見てジャンプするようになっています。   NMIコード    $00=RAM アダプタ用 $E18Bから$E19Dへ    $40=ゲーム用0     JMP ($DFF6)    $80=ゲーム用1     JMP ($DFF8)    $C0=ゲーム用2     JMP ($DFFA) IRQ割り込み(エントリアドレスは$E1C7)  ディスクのアクセスに使用されます。  ワークエリアの$0101のBit7−6(IRQコード)を見てジャンプするようになっています。   IRQコード    $00−$3F=IRQコード分のディスク ロード スキップ   *$40=ディスク1バイト転送(読み込みの場合A、Xにデータが読み込まれる、書き込みの場合Aレジスタにデータ)    $80=ディスク・ステータスを読む    $C0=JMP ($DFFE)     *$40だけPC−下位、PC−上位、PSRを空読みしてRTSを実行します。($E7A3の割り込みのトラップから戻る為) リセット割り込み(エントリアドレスは$EE24)  電源を入れるとオートリセットが掛かるので電源を入れるかリセットを押すとココにジャンプします。  まずPPUの設定、その他のポートの設定、スタックの設定を行います  次にNMIコードを$C0、IRQコードを$80をセットします  リセットコードがあり使用アドレスは$0102−$0103のリセットコードによって動作が変わります   まず$0102が$35かをチェック$35でなければRAMアダプタのデモへ行きます。                    $35なら$0103が$53か$ACかそれ以外のチェックを行いす   $0102が$35以外ならRAMアダプタのデモへ行きます。   $0102が$35で$0103が$53なら、スクロールセットしてJMP ($DFFC)   $0102が$35で$0103が$53でなく$ACなら$53にセット、スクロールセットしてJMP ($DFFC)   $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のコールを行い  ディスクシステムの基準に倣った方が良いです。
 $4020:(出力) IRQ タイマー下位  $4021:(出力) IRQ タイマー上位  $4022:(出力)  Bit2:1=タイマーカウント開始、0=タイマーカウント停止  $4023:(出力) 2C33 タイマーコントロール              Bit1:サウウンドT/Oのアクセス 1=許可、0=禁止              Bit0:ディスク I/Oのアクセス 1=許可、0=禁止  $4024:(出力) ディスク ライトデータ(/WRITE_DATA)              1バイトのデータをシフトレジスタによって              /WRITE_DATAにシリアルデータで転送されます               $4023 Bit0=1 ディスクI/Oアクセス許可               $4025 Bit2=0 /WRITEGATE データ ライト                $4030 Bit7=1 リード・ライト可能              の条件がそろってないと書き込めません  $4025:(出力) ディスク コントロール              Bit7:IRQデータ転送    1=実行する     、0=実行しない              Bit6:CRCレジスタ     1=クリアする    、0=クリアしない              Bit5:不明          1=         、0=              Bit4:CRC−Hコントロール 1=行う       、0=行わない              Bit3:スクロール       1=スクロール−V  、0=スクロール−H              Bit2:/WRITEGATE  1=データ リード  、0=データ ライト              Bit1:/MOTOR      1=モーターの回転停止、0=モーターの回転開始              Bit0:/RESET      1=リセットを行わない、リセットを行う               不明 ほとんど1になっている、CRC転送の実行? 0だとデータ転送が出来ない               CRC−Hコントロールを行うと書き込みの場合 CRC−Hが$4024に転送され                                      WaitでCRC−Hをディスクに書き込む?                              読み込みの場合 次にロードした$4031のデータとCRC−Hの比較を行い                                      結果を$4030のBit4(同じなら0)に出力する?               /RESETは転送タイミングのリセット  $4026:(出力) バッテリーコントロール、背面の拡張I/Oライト              Bit7:BATTRY_SENCE 1=オン、0=オフ              Bit6:背面の拡張I/O              Bit5:背面の拡張I/O              Bit4:背面の拡張I/O              Bit3:背面の拡張I/O              Bit2:背面の拡張I/O              Bit1:背面の拡張I/O              Bit0:背面の拡張I/O  $4030:(入力)ディスクI/O ステータス              Bit7:ドライブの検知       1=リード・ライト可能、0=リード・ライト不可              Bit6:ヘッド の検知       1=最後まで移動した 、0=最後まで移動していない              Bit5:              Bit4:CRC−Hチェック     1=エラー有り    、0=エラー無し              Bit3:              Bit2:              Bit1:シフトレジスタ転送 の検知 1=転送中      、0=転送終了              Bit0:IRQタイマ割り込みの検知 1=発生した     、0=発生していない               CRCチェックはCRC−HとCRC上位として読み込んだデータが同じなら0になる?  $4031:(入力) ディスク リードデータ(READ_DATA)              READ_DATAから転送されたシリアルデータをシフトレジスタによって              1バイトのデータに変換されます               $4023 Bit0=1 ディスクI/Oアクセス許可               $4025 Bit2=1 /WRITEGATE データ リード                $4030 Bit7=1 リード・ライト可能              の条件がそろってないと読み込めません             ???データを書き込んでいる場合(/WRITEGATE=0)はCRCの下位の値  $4032:(入力) ドライブ ステータス              Bit7:不明 0              Bit6:不明 1              Bit5:不明 0              Bit4:不明 0              Bit3:不明 0              Bit2:/WRITE_PROTECT 1=カード書き込み禁止  、0=カード書き込み許可              Bit1:/READY         1=スタート位置     、0=内部に移動している              Bit0:/MEDIA_SET     1=セットされていない  、0=セットされた               Bit6はほとんど1になっている               /WRITE_PROTECTはディスクカードのツメが折れていたら1、折れていなければ0               /READY        はヘッドが一番外に移動し、内に移動し読み書きのが可能な時に0になる               /MEDIA_SET    はディスクカードがセットされていなければ1、セットされれば0  $4033:(入力) バッテリーステータス、背面の拡張I/Oリード              Bit7:BATTRY_SENCE 1=電圧 OK、0=電圧 NG              Bit6:背面の拡張I/O              Bit5:背面の拡張I/O              Bit4:背面の拡張I/O              Bit3:背面の拡張I/O              Bit2:背面の拡張I/O              Bit1:背面の拡張I/O              Bit0:背面の拡張I/O
ディスク フォーマット 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面  ディスクの順番(VOLUME) :  1バイト 2枚以上のソフトで使用  ディスクの種類         :  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はディスクシステムに必要なデータでこれが無いと起動すらできません   $01−2はシステム自体の情報なります ディスクアクセスに必要なデータになります         ゲーム ネームの最後の1バイトはイベント等を表し          $20=通常のディスク          $45=E イベント、ディスクファックスを使った全国トーナメント          $52=R リダクション イン プライス(広告による値引き)         コールドスタートは起動時に読み込む最大ロードナンバで一括でファイルを読み込みます          $0Fの場合、ディスク内のロードナンバ$00〜$0Fまで全て読み          $10以降のロードナンバは読み込みません   $01−3は主にディスクライター用         プライスは値段や周辺機器の対応          書き換え回数が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バイト 一番最初のファイルを0として以降+1される  ロードナンバ          :  1バイト 一括ロードするためのナンバ  ファイル ネーム        :  8バイト  アドレス            :  2バイト 下位、上位の順  ファイルの長さ         :  2バイト 下位、上位の順  ファイルの種類         :  1バイト 00=プログラム、01=キャラクタ、02=許諾ファイル  CRC             :  2バイト   ファイルナンバは最初のファイルを$00で次のファイルは$01になり           書き込む場合に使用されます   ロードナンバ は読み込むときに使用されるナンバで他のファイルにも同じナンバがある場合があります           同じナンバだと一度にロードする事が可能になります           ブロックコード$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ブロック分まで繰りかえす 書き込む場合  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ルーチンではなくソフトのルーチンでエラーの判断を行います
DISK ROM エントリ $E000:00 $E001−$E148:キャラクタデータ(文字) $E149:Wait $E153:nnミリ Wait    入力:Y=nnミリ    使用:X、Y       Yミリ秒のウェイトをかけます       ルーチン内で$0000をロード、コンペアの実行を行っていますが       時間稼ぎの為で内容の変更はありません       主にディスクアクセスのタイミングに使用 $E161:OBJ+BG Off    使用:A       $00FE        スプライトとBG画面を表示しません。 $E16B:OBJ+BG On    使用:A       $00FE        スプライトとBG画面を表示します。 $E171:OBJ Off    使用:A       $00FE        スプライトを表示しません。 $E178:OBJ On    使用:A       $00FE        スプライトを表示します。 $E17E:BG Off    使用:A       $00FE        BG画面を表示しません。 $E185:BG On    使用:A       $00FE        BG画面を表示します。 $E18B:NMIベクタ        ディスク システムのNMIベクタです。        割り込みがかかったら$0100のBit7−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のBit7−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なら何もせず、                              それ以外はBit5−0のデータ分をAにディスクロード(スキップ) $E1F8:ファイル ロード    入力:1st=ブロックコード$01−2 比較データアドレス下位       2nd=ブロックコード$01−2 比較データアドレス上位       3rd=ロードナンバ群 ポインタ下位       4th=ロードナンバ群 ポインタ上位    出力: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                $21=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のロードナンバ         +0C ファイルネーム00 8バイト ファイルの順番00のファイルネーム                  |                  | 以降ファイル数分のファイルが続き最後にディスクの総容量                  |         +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のBit4=1)       CRC上位バイトをリード       リードしたデータがCRC−Hコントロールによってチェックが行われ       結果が$4030のBit4に現れ(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のBit4=1)       約0.0005秒のウェイト                      <−ここでCRC−Hが書き込まれている?       $4032の/READY=1(Bit1=1)ならエラー(ERR.31)                    0(Bit1=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が入ります $E786:ドライブ クローズ    入力:X=エラーコード    出力:A=エラーコード(Xレジスタの値)    使用:A、X       $00FA                $4025 Bit7:0                 6:0                 5:1                 4:0                 3:*                 2:1                 1:1                 0:*        XレジスタをAレジスタにコピーして、IRQをオンにします $E77F:ディスク コンペア データ Zfチェック    入力:Zf=0 比較データと違う          1 比較データと同じ    出力:A=エラーコード(Zf=0で入力の場合)    使用:$0004       $00FA        前もってデータを比較したりしてZfの変化を見るルーチンになります         入力でZf=1なら何もせずRTS               0ならエラー        エラーでは$0004のスタックデータをスタックポインタにして        ドライブ クローズ、エラー出力して強制終了します         $E794:IRQ 1バイト転送の開始    入力:A=ライト データ(書き込みの場合)    出力:A=CRC下位  (書き込みの場合)       X=リード データ(読み込みの場合)       A=リード データ(読み込みの場合)    使用:$00FA       $0101        IRQコードを$40(0101:40)        IRQデータ転送を1($4025のBit7=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になります          コマンド Bit7: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 Bit2=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データでなく         Bit7−4:行数で         Bit3−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レジスタのBit1だけマスクして$0000にストア       指定したゼロページ+1+XレジスタのBit1と$0000とEORする       0ならCf=0、1ならCf=1       全発生レジスタを右シフトする $E9C8:仮想OBJエリア セット       仮想OBJを$0200に設定します。    使用:A $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で得たデータをまとめます $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の内容でセット $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がBit0...P3 8がBit7になります          $EBAF:パターンテーブル定義    入力:Y=PPUアドレス 上位       A=PPUアドレス 下位+コード          Bit7:PPUアドレス A7          Bit6:PPUアドレス A6          Bit5:PPUアドレス A5          Bit4:PPUアドレス A4          Bit3:コード D1 11=反転 通常 、10=埋める 通常          Bit2:コード D0 01=通常 埋める、00=通常 通常          Bit1:コード 1=リード モード、0=ライト モード          Bit0:コード 1=$FFで埋める、0=$00で埋める       X=キャラクタ数       1st=パターン データアドレス下位       2nd=パターン データアドレス上位    使用:A、X、Y       $0000       $0001       $0002       $0003       $0004       $00FF        パターンテーブル(キャラクタ)の定義を行います        アクセスするPPUアドレスを指定しますがPPUアドレス下位のBit3−0は0になる($xxx0)        次にコード解析でBit1−0の設定、Bit3−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の内容 $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−$3F=IRQコード分のディスク ロード スキップ        $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 ファイル   コピーツールのバッファより大きいファイルを持つタイプ   麻雀家族、スーパーロードランナーが該当    1つのファイルがRAM容量よりも大きくなっています    ファイルが40KBのファイルがあり、コピーバッファが少ないとコピー出来ないようになっています    主に対DISK HACKER V1.2用    DISK HACKER V1.3ではV1.2より大きいバッファを持ちコピー出来ます。    ファミコンのディスクはランダムアクセスが出来ないQDなのでトラックやセクタ等は無く    テープと同じように最低でも一つのファイルを一気に書き込まないといけません    つまり分割して一つのファイルを書き込みする事はかなり困難になります    しかし、本体メモリは32KB(RAMアダプタ)+2KB(ワーク)+2KB(VRAM)+キャラクタ(8K)なので    本体内の全メモリ44KBにコピープログラム+バッファを取ってコピー出来るツールもあります。     スーパーロードランナーではSIDE Aの4番目のファイルLRMAIN01が     ロードアドレス$6000で長さ$A000になります     このファイルは$6000から読み込まれますが始めの$2000バイトを空読みして     残りの$8000バイトが$6000−$DFFFにロードされます     ロード終了後、$DFE0−$DFEFのチェックと     $6000−$DFFFのチェックサムを行い、合えば$6000にジャンプします。  44KB ファイル   本体内の全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を出力して   コピーできないようになっています  プログラム書き換えチェック   これはプロテクトといってもコピープロテクトでは無くプログラムの改造されたかチェックをするタイプ   改造するとチェックサムエラーのメッセージが出たり、起動画面に飛んだり、ゲームが起動出来ない様になっています   ただし完全なチェックを行っているとは限りません(コピーライト表記の書き換えを阻止するだけの為?)   コナミやカプコンのソフトに見かけます。    セクションZのチェックサムエラーメッセージ       ナムコのディスクソフト   プロテクトでは無いのですがナムコのディスクソフトは非ライセンス ソフトと同じような   許諾画面を出さないような事をしています。   実際には許諾画面を出しているのですがRAMアダプタのプログラムで動いてなくて   ゲームソフト(IPLMAIN)が割り込みでRAMアダプタからの許諾画面表示   を乗っ取っていながらゲームソフトから許諾画面を表示しています。   これにより任天堂が許諾画面表示の乗っ取りプログラムに対する   プロテクトを掛けるのが難しくなっています   つまりプロテクトを掛けるのを防ぐ為の任天堂に対する逆プロテクト(?)に思えますが   真相は不明です。
Home へ戻る