1985年2月26日火曜日

[機器][TVゲーム] 任天堂ファミコンディスクシステム













2013/3/2
「ファミコン ディスクシステム RAMアダプタ 回路図」  ファミコン
(改訂 2013/03/02)
ファミコン ディスクシステムのRAMアダプタについて回路図を起こしてみた。以前、途中まで書いてRP2C33のピンアサインが分からず放置していたもの。写真1,2はHVC-023 RAMアダプタのオモテ面外観。初期のものはシボ(表面処理)がない。後になってキズが付きやすいためか、シボ付きに変更されている。なお、左上にラベルで示してある形番は、中に入っていた基板の形番。
 初期のもの :基板 HVC-FMR-01 RP2C33 搭載
 中期?のもの:基板 HVC-FMR-04 RP2C33A 搭載
HVC-FMR-03もあるらしいが所有しておらず。
こちらによるとHVC-FMR-03まではRP2C33,DRAM4つ搭載の構成だったようです。
HVC-023 初期のRAMアダプタ オモテ
基板はHVC-FMR-01
初期のRAMアダプタは筐体表面に皺(シボ)加工が入っていないので表面に傷つきまくり
HVC-023 初期のRAMアダプタ オモテ
基板はHVC-FMR-04
HVC-FMR-01
・HVC-FMR-01,HVC-FMR-04回路図 Rev.05(PDF)
○Rev.05での変更点
2013年03月01日 回路図Rev.05
・EXT-PORT(P3) 9番ピン 音声を出力に修正
(SuperTurbo さんの情報提供・指摘により修正。ありがとうございました。)
・4069UB(U5)の未使用ピンNC表示追加
○Rev.04での変更点
・Rev.03での修正をDISK DRIVE CONNECTORに反映していなかったのでピン番号を変更
・EXT7/BATT信号のバス接続先が間違っていたので修正
・「VCC +5V」を「+5V」に修正
・「CLOCK」が「CLICK」になっていたので修正
・「PHI2」が意味のないところに記載されていたので削除
・図面タイトルに「HVC-FMR-04」が抜けていたので追加
なお、RP2C33、LH2833-15ピンアサインの情報はこちらを参照。
KEYWORD:ファミリーコンピュータ ファミコン ディスクシステム HVC-023 HVC-FMR-01 HVC-FMR-04 回路図 FC CIRCUIT SCHEMATIC DISK SYSTEM RP2C33 RP2C33A LH2833-15

子機器 Junker
https://green.ap.teacup.com/applet/junker/116/trackback













[機器][TVゲーム] 任天堂ファミコンディスクシステム
ファミコンディスクシステム
RAMアダプタに8KByteのROM(カスタムに内蔵)
32KByteのRAM($6000-$DFFF)、8KByteのキャラクタRAMのメモリを載せて
クィックディスク(QD)ドライブ込みで15、000円はかなり安い。
またドライブは通信アダプタの底面にあるコネクタ(ロットによっては無くなっている)でも接続可能
■RAM、拡張ポートテスト
スタートキーとセレクトーキーを押しながらリセットすると実行されます
このときにメインRAM$6000-$DFFFのチェック
次にPPU$0000-$1FFFをCPURAM$C000-$DFFFに転送してチェックを行います
エラーがあればOKと表示される所にエラーが出たアドレスが表示されます
$0000-$1FFFPPUのアドレス
$6000-$DFFFCPUのアドレス
拡張ポートのテストは左からBit0-Bit7の並びになっていて
$4026で拡張ポートにデータを書き込み、$4033で拡張ポートのデータを読み込みます
Cf=0にして$FFと左ローテイトで1つだけビットを0にして他は1にしてポートのチェックを行います
ただしBit7のBATTRY_SENCEはモータを起動していない為0(電圧NG)になります
■ROMの種類
RAMアダプタ内のROMはファミリーコンピュータ用の旧、新バージョンの2つ
ツインファミコンのデモでNintendoと出るのとFamicomとでるタイプの2つの計4つがあります
ROMのバージョンの判定方法はIコントローラのスタートキーとセレクトーキーを押しながらリセットすると、
RAM、拡張ポートテスト画面になりますが、そのテスト画面になる前に
Iコントローラの右とAを押すとメッセージがでます。
このときDEV2があれば新バージョン、数字が出ないのは旧バージョンになります
ツインファミコンの方は両方ともDEV2なので起動画面が違うだけのようです
■ROMバージョンの違いによる不都合
若干ROMエントリのアドレスが変っていますので、そこの部分をコールされると動かない可能性がでます
しかし実際に純正ソフトでは使わないようになっているようで実際問題での不都合はありません
非ライセンスソフトのDISKHACKERVer1.0では
FCBのブロックに$FFがあると新バージョンではエラーがでます(旧バージョンはそのままコピーが出来ます)
バックアップ活用研究のDISKCOPYでは
RAMアダプタのバージョンに合わせてアドレス変更して対応しています
NMI割り込み$E18B
ワークエリアの$0100のBit7-6(NMIコード)を見てジャンプするようになっています。
NMIコード
$00=RAMアダプタ用$E18B
$40=ゲーム用0JMP($DFF6)
$80=ゲーム用1JMP($DFF8)
$C0=ゲーム用2JMP($DFFA)
IRQ割り込み$E1C7
ディスクアクセスに使用
ワークエリアの$0101のBit7-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のコールを行い
ディスクシステムの基準に倣った方が良いです
$4020:(出力)IRQタイマ下位クロックは1.79MHz
$4021:(出力)IRQタイマ上位
$4022:(出力)
Bit2:1=IRQタイマカウント開始、0=IRQタイマカウント停止
$4023:(出力)2C33タイマーコントロール
Bit1:サウウンド?T/Oのアクセス1=許可、0=禁止
Bit0:ディスクI/Oのアクセス1=許可、0=禁止
$4024:(出力)ディスクライトデータ(/WRITE_DATA)
1バイトのデータをシフトレジスタによって
/WRITE_DATAにシリアルデータで転送されます
$4023Bit0=1ディスクI/Oアクセス許可
$4025Bit2=0/WRITEGATEデータライト
$4030Bit7=1リード・ライト可能
の条件がそろってないと書き込めません
$4025:(出力)ディスクコントロール
Bit7:IRQデータ転送1=実行する、0=実行しない
Bit6:CRCレジスタ1=クリアする、0=クリアしない
Bit5:不明1=、0=
Bit4:CRC-Hコントロール1=行う、0=行わない
Bit3:スクロール1=スクロール-V、0=スクロール-H
Bit2:/WRITEGATE1=データリード、0=データライト
Bit1:/MOTOR1=モーターの回転停止、0=モーターの回転開始
Bit0:/RESET1=リセットを行わない、0=リセットを行う
不明ほとんど1になっている、CRC転送の実行?0だとデータ転送が出来ない
CRC-Hコントロールを行うと書き込みの場合CRC-Hが$4024に転送され
WaitでCRC-Hをディスクに書き込む?
読み込みの場合次にロードした$4031のデータとCRC-Hの比較を行い
結果を$4030のBit4(同じなら0)に出力する?
/RESETは転送タイミングのリセット
$4026:(出力)バッテリーコントロール、背面の拡張I/Oライト
Bit7:BATTRY_SENCE1=オン、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バイトのデータに変換されます
$4023Bit0=1ディスクI/Oアクセス許可
$4025Bit2=1/WRITEGATEデータリード
$4030Bit7=1リード・ライト可能
の条件がそろってないと読み込めません
???データを書き込んでいる場合(/WRITEGATE=0)はCRC-Lの値
$4032:(入力)ドライブステータス
Bit7:不明0
Bit6:不明1
Bit5:不明0
Bit4:不明0
Bit3:不明0
Bit2:/WRITE_PROTECT1=カード書き込み禁止、0=カード書き込み可
Bit1:/READY1=内部に移動している、0=スタート位置
Bit0:/MEDIA_SET1=セットされていない、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面)/片面$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||
|-----------------------+--------|
|012A4E494E54454E|.*NINTEN|
|444F2D4856432A01|DO-HVC*.|
|4C4E4B2000000000|LNK....|
|000FFFFFFFFFFF62|.......b|
|0114496100000200|..Ia....|
|25021800620114FF|%...b...|
|FFFFFFFF00000000|........|
+--------------------------------+
’*NINTNDO-HVC’
メーカーコード$01
ゲームネーム’LNK’
ゲームバージョン$00
ディスクサイド$00A面
ボリューム$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$00KYODAKU-
$01$03MAIN-PRG
$04$01CHARA-00
$06$06SAVE-DATが一括ロードされる
一括ロード終了後、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;BootDiskDrive
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;WriteCRC
エラー
■ドライブ&ディスクセット関連
01:DISKSETERR.01ディスクが正しくセットされていない
02:BATTERYERR.02ディスクドライブの電圧が規定値以下になっている
03:WRITEPROTECTERR.03ライトプロテクトのツメが折れているのに書き込もうとした
04:GAMEMAKERERR.04違ったメーカのディスクがセットされた
05:GAMENAMEERR.05違ったゲームのディスクがセットされた
06:GAMEVERSIONERR.06違ったバージョンのディスクがセットされた
07:A.B.SIDEERR07違ったサイドのディスク(表と裏)がセットされた
08:DISKNUMBERERR.08違った順番のディスクがセットされた
09:ERR.09違ったディスクの種類がセットされた
10:ERR.10違った予備1のデータがセットされた
08はROM内ではDISKNO.ERR.08として出力
11-19はディスクライター用?
ファイルアクセス関連
20:DISKTROUBLEERR.20許諾ファイルが読み込めない
21:DISKTROUBLEERR.21ブロックコード$01の*NINTENDO-HVC*が見つからない
22:DISKTROUBLEERR.22ブロックコード$01の開始マーク$01が見つからない
23:DISKTROUBLEERR.23ブロックコード$02の開始マーク$02が見つからない
24:DISKTROUBLEERR.24ブロックコード$03の開始マーク$03が見つからない
25:DISKTROUBLEERR.25ブロックコード$04の開始マーク$04が見つからない
26:DISKTROUBLEERR.26ディスクに正しく書き込みが出来ない
27:DISKTROUBLEERR.27CRCエラーを検出
28:DISKTROUBLEERR.28ディスクの読み込みでタイミングが合っていない(読み込み途中でヘッドが最後まで行った)
29:DISKTROUBLEERR.29ディスクの書き込みでタイミングが合っていない(書き込み途中でヘッドが最後まで行った)
ユーザーセーブ関連
30:DISKTROUBLEERR.30ディスクに書き込みが出来なくなった(容量不足またはドライブ・プロテクトによる強制終了)
31:DISKTROUBLEERR.31ディスクのデータ数が合わない、または書き込もうとしたマウントファイル数がマイナスになった
35:DISKTROUBLEERR.35テストファイル(ブロックコード$05ファイル)の書き込み失敗
その他
40:DISKTROUBLEERR.40一括ロードでロード出来なかったファイルがあった(ファイル数が足りない)
41:DISKTROUBLEERR.41不明(きね子IIの説明書にERR.41~の表記あり)
*DISKTROUBLEERR.35以降はROMルーチンではなくソフトのルーチンでエラーの判断を行います
DISKROM エントリ
$E000:00
$E001-$E148:キャラクタデータ(文字)
$E149:Wait
$E153:nnミリWait
入力:Y=nnミリ
使用:X、Y
Yミリ秒のウェイトをかけます
ルーチン内で$0000をロード、コンペアの実行を行っていますが
時間稼ぎの為で内容の変更はありません
主にディスクアクセスのタイミングに使用
$E161:OBJ+BGOff
使用:A
$00FE
スプライトとBG画面を表示しません。
$E16B:OBJ+BGOn
使用:A
$00FE
スプライトとBG画面を表示します。
$E171:OBJOff
使用:A
$00FE
スプライトを表示しません。
$E178:OBJOn
使用:A
$00FE
スプライトを表示します。
$E17E:BGOff
使用:A
$00FE
BG画面を表示しません。
$E185:BGOn
使用: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=DISKSETERR.01
$02=BATTERYERR.02
$04=GAMEMAKERERR.04
$05=GAMENAMEERR.05
$06=GAMEVERSIONERR.06
$07=A.B.SIDEERR07
$08=DISKNUMBERERR.08
$09=ERR.09
$10=ERR.10
$21=DISKTROUBLEERR.21
$22=DISKTROUBLEERR.22
$23=DISKTROUBLEERR.23
$24=DISKTROUBLEERR.24
$27=DISKTROUBLEERR.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=DISKSETERR.01
$02=BATTERYERR.02
$04=GAMEMAKERERR.04
$05=GAMENAMEERR.05
$06=GAMEVERSIONERR.06
$07=A.B.SIDEERR07
$08=DISKNUMBERERR.08
$09=ERR.09
$10=ERR.10
$21=DISKTROUBLEERR.21
$22=DISKTROUBLEERR.22
$23=DISKTROUBLEERR.23
$26=DISKTROUBLEERR.26
$27=DISKTROUBLEERR.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=DISKSETERR.01
$02=BATTERYERR.02
$04=GAMEMAKERERR.04
$05=GAMENAMEERR.05
$06=GAMEVERSIONERR.06
$07=A.B.SIDEERR07
$08=DISKNUMBERERR.08
$09=ERR.09
$10=ERR.10
$21=DISKTROUBLEERR.21
$22=DISKTROUBLEERR.22
$23=DISKTROUBLEERR.23
$26=DISKTROUBLEERR.26
$27=DISKTROUBLEERR.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ファイルデータ下位,ファイルデータ上位
BNEERROR

$01-2データはメーカーコードからコールドスタートの次の$FFまで
ファイルデータはブロックコード$03のロードナンバからファイルタイプまで
ファイルデータに記されているアドレスと長さが書き込む範囲になります
$E26B:ファイルセーブ(メイン)
入力:$0000=ブロックコード$01-2比較データアドレス下位
$0001=ブロックコード$01-2比較データアドレス上位
$0002=ブロックコード$03データアドレス下位
$0003=ブロックコード$03データアドレス上位
$000E=$00から$FE$0006で指定した場所-1にセーブ
$FF最後にセーブ
出力:A=エラーコード$00=エラー無し
$01=DISKSETERR.01
$02=BATTERYERR.02
$04=GAMEMAKERERR.04
$05=GAMENAMEERR.05
$06=GAMEVERSIONERR.06
$07=A.B.SIDEERR07
$08=DISKNUMBERERR.08
$09=ERR.09
$10=ERR.10
$21=DISKTROUBLEERR.21
$22=DISKTROUBLEERR.22
$23=DISKTROUBLEERR.23
$26=DISKTROUBLEERR.26
$27=DISKTROUBLEERR.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=DISKSETERR.01
$02=BATTERYERR.02
$04=GAMEMAKERERR.04
$05=GAMENAMEERR.05
$06=GAMEVERSIONERR.06
$07=A.B.SIDEERR07
$08=DISKNUMBERERR.08
$09=ERR.09
$10=ERR.10
$21=DISKTROUBLEERR.21
$22=DISKTROUBLEERR.22
$23=DISKTROUBLEERR.23
$27=DISKTROUBLEERR.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=DISKSETERR.01
$02=BATTERYERR.02
$04=GAMEMAKERERR.04
$05=GAMENAMEERR.05
$06=GAMEVERSIONERR.06
$07=A.B.SIDEERR07
$08=DISKNUMBERERR.08
$09=ERR.09
$10=ERR.10
$21=DISKTROUBLEERR.21
$22=DISKTROUBLEERR.22
$23=DISKTROUBLEERR.23
$27=DISKTROUBLEERR.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=DISKSETERR.01
$02=BATTERYERR.02
$04=GAMEMAKERERR.04
$05=GAMENAMEERR.05
$06=GAMEVERSIONERR.06
$07=A.B.SIDEERR07
$08=DISKNUMBERERR.08
$09=ERR.09
$10=ERR.10
$21=DISKTROUBLEERR.21
$22=DISKTROUBLEERR.22
$23=DISKTROUBLEERR.23
$27=DISKTROUBLEERR.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=DISKSETERR.01
$02=BATTERYERR.02
$04=GAMEMAKERERR.04
$05=GAMENAMEERR.05
$06=GAMEVERSIONERR.06
$07=A.B.SIDEERR07
$08=DISKNUMBERERR.08
$09=ERR.09
$10=ERR.10
$21=DISKTROUBLEERR.21
$22=DISKTROUBLEERR.22
$23=DISKTROUBLEERR.23
$27=DISKTROUBLEERR.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=DISKSETERR.01
$02=BATTERYERR.02
$21=DISKTROUBLEERR.21
$22=DISKTROUBLEERR.22
$27=DISKTROUBLEERR.27
$29=DISKTROUBLEERR.29
$30=DISKTROUBLEERR.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=DISKSETERR.01
$02=BATTERYERR.02
$21=DISKTROUBLEERR.21
$22=DISKTROUBLEERR.22
$27=DISKTROUBLEERR.27
$29=DISKTROUBLEERR.29
$30=DISKTROUBLEERR.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=DISKSETERR.01
$02=BATTERYERR.02
$21=DISKTROUBLEERR.21
$22=DISKTROUBLEERR.22
$27=DISKTROUBLEERR.27
$29=DISKTROUBLEERR.29
$30=DISKTROUBLEERR.30
使用:A、X、Y
$0002
$0004
$0005
$0006
$0007
$00FA
$0101
スタック
ブロックコード$01-2のチェックを行ってから
マウントファイル数+nnを書き込みます
$E32A:ディスクインフォメーションの収得
入力:1st=ディスクインフォメーションアドレスの下位
2nd=ディスクインフォメーションアドレスの上位
出力:A=エラーコード$00=エラー無し
$01=DISKSETERR.01
$02=BATTERYERR.02
$21=DISKTROUBLEERR.21
$27=DISKTROUBLEERR.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ロードナンバー001バイトファイルの順番00のロードナンバ(ブロックコード$03のデータ)
+0Cファイルネーム008バイトファイルの順番00のファイルネーム(ブロックコード$03のデータ)

|以降ファイル数分のファイルが続き最後にディスクの総容量

+nnディスクの総容量の下位
+mmディスクの総容量の上位
ディスクの総容量はヘッダ部分+00~+0A10バイト
ファイル部分ファイルの順番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=DISKSETERR
使用: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バイトセットの場合)
$000E=パラメータnnバイトの値(0か2エラーの場合)
A=エラーコード$00=エラー無し
$01=DISKSETERR
$03=WRITEPROTECTERR
$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パラメータ
3rdパラメータ(パラメータ4バイトセットの場合)
$0003=4thパラメータ(パラメータ4バイトセットの場合)
$000E=パラメータnnバイトの値(0か2エラーの場合)
A=ロードの場合$00=エラー無し
$01=DISKSETERR.01
セーブの場合$00=エラー無し
$01=DISKSETERR.01
$03=WRITEPROTECTERR.03
使用:A、X、Y
$0004
$0005
$0006
スタック
$0000からそれぞれ対応するデータをセットして
Aレジスタにディスクの状態を送ります
セーブの状態なら$E3EAをサブルーチンコールをすれば良いのですが
エラーが発生するとRTSする前にスタック操作を行って
このルーチンを実行したルーチンを強制終了されます
$E445:ブロックコード$01リード、チェック
$0001=ブロックコード$01-2比較データアドレス上位
出力:A=エラーコード$00=エラー無し
$01=DISKSETERR.01
$02=BATTERYERR.02
$04=GAMEMAKERERR.04
$05=GAMENAMEERR.05
$06=GAMEVERSIONERR.06
$07=A.B.SIDEERR07
$08=DISKNUMBERERR.08
$09=ERR.09
$10=ERR.10
$21=DISKTROUBLEERR.21
$22=DISKTROUBLEERR.22
$23=DISKTROUBLEERR.23
$27=DISKTROUBLEERR.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=DISKTROUBLEERR.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=DISKSETERR.01
$02=BATTERYERR.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=DISKTROUBLEERR.21
$22=DISKTROUBLEERR.22
$23=DISKTROUBLEERR.23
$24=DISKTROUBLEERR.24
使用:A、X、Y
$0004
$0007
$00F9
$00FA
$0101
CRCレジスタをリセットを行い、
1バイト読み込んだデータをブロックコードとして読みます
ヘッドが予めブロックコードのある所にいなければなりません
$E6B0:ブロックコードの書き込み
入力:A=ブロックコード
$3F1F-$3F1Fカラーパレット
使用: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=DISKSETERR.01
$02=BATTERYERR.02
$21=DISKTROUBLEERR.21
使用:A、X、Y
$0004
$0007
$00F8
$00F9
$00FA
ドライブを起動し
ブロックコード$01-1の'*NINTENDO-HVC*'があるかチェックを行います
*NINTENDO-HVC*'が無ければドライブを止め
Aレジスタにエラーコード$21を返します
$E706:CRCリード
出力:A=エラーコード$00=エラー無し
$01=DISKSETERR.01
$27=DISKTROUBLEERR.27
$28=DISKTROUBLEERR.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=DISKSETERR.01
$29=DISKTROUBLEERR.29
$30=DISKTROUBLEERR.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=DISKSETERR.01
$28=DISKTROUBLEERR.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
$4025Bit7:0
6:0
5:1
4:0
3:*
2:1
1:1
0:*
XレジスタをAレジスタにコピーして、IRQをオンにします
$E794:IRQ1バイト転送の開始
入力:A=ライトデータ(書き込みの場合)
出力:A=CRC下位(書き込みの場合)
X=リードデータ(読み込みの場合)
A=リードデータ(読み込みの場合)
使用:$00FA
$0101
IRQコードを$40(0101:40)
IRQデータ転送を1($4025のBit7=1)にして
下の$E7A3(IRQ1バイト転送)を実行します
ディスクのリード・ライトの始めに使用しますが事前に
CRCレジスタをクリアしていないとCRC計算が正しく行われません
$E7A3:IRQ1バイト転送
入力: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のサブルーチンによってはJSRnnmmの後にパラメータを設定するのですが
それらのサブルーチンが使用して、パラメータを読みRTSする為のスタックを調節します
$0005から$0006の内容が壊れます
$E86A:VRAMバッファ出力
入力:$0302=バッファデータ00VRAMアドレス上位
$0303=バッファデータ00VRAMアドレス下位
$0304=バッファデータ00データの長さ
$0305=バッファデータ00VRAMに書き込むデータ

$03nn=エンドマーク($80から$FF)
出力:$0301=$00
$0302=エンドマーク$80から$FF(実際には$FF)
使用:A、X、Y
$00FF
PPUアクセス時のアドレスの増加をX方向($2000Bit2=0)にして
VRAMバッファからアドレス、長さを取得してVRAMにバッファデータを書き込みます
バッファデータの第1バイトのVRAMアドレスが$80から$FFだとエンドマークになります
データフォーマット
バッファデータ00VRAMアドレス上位
バッファデータ00VRAMアドレス下位
バッファデータ00出力データの長さ
バッファデータ00出力データ

バッファデータnnVRAMアドレス上位
バッファデータnnVRAMアドレス下位
バッファデータnn出力データの長さ
バッファデータnn出力データ
エンドマーク($80から$FF)
$E8B3:VRAMバッファ入力
入力:X=インデックス($02から)
Y=転送するバイト数
$0302=データ00VRAMアドレス上位
$0303=データ00VRAMアドレス下位
$0305=データ01VRAMアドレス上位
$0306=データ01VRAMアドレス下位

出力:$0304=指定したデータ00のVRAMの内容
$0307=指定したデータ01のVRAMの内容

使用:A、X、Y
$0302にあるVRAMバッファにVRAMの内容を転送します
1バイトごとの転送なので3バイト1組になります
入力するXレジスタの値は$02以上になります
VRAMバッファは
+00VRAMアドレス上位
+01VRAMアドレス下位
+02VRAMの内容(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
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エリアセット
使用: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をアクセスした後スクロールセットをするのに使用します
スクロールをセット
PPUR#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のONAGOTOnnnn,mmmm,...に相当
使用例
JSR$EAFD
DWADDRESS0;A=$00のジャンプ
DWADDRESS1;A=$01のジャンプ
DWADDRESS2;A=$02のジャンプ

$EB13:HVC-007キーボードのキーマトリクス入力
出力:$0000=キーマトリクスP29の反転データ
$0001=キーマトリクスP28の反転データ
$0002=キーマトリクスP27の反転データ
$0003=キーマトリクスP26の反転データ
$0004=キーマトリクスP25の反転データ
$0005=キーマトリクスP24の反転データ
$0006=キーマトリクスP23の反転データ
$0007=キーマトリクスP22の反転データ
$0008=キーマトリクスP21の反転データ
使用:A、X、Y
$00FB
ファミリーBASICのキーボード(HVC-0007)のキーマトリクス入力を行います
出力データは反転されているので押していると1、離している0になります
P31がBit0...P38がBit7になります
$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アドレス下位+コード
Bit7:PPUアドレスA7
Bit6:PPUアドレスA6
Bit5:PPUアドレスA5
Bit4:PPUアドレスA4
Bit3:コードD111=反転通常、10=埋める通常
Bit2:コードD001=通常埋める、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=ロード・スキップの終了
$01-$3F=ロード・スキップバイト
$40=ディスク1バイトリード・ライト
$80=ディスクステータス
$C0=JMP($DFFE)
$0102-$0103:RESETコントロール
$0102:3553=JMP($DFFC)
$0102:35AC=$0103を$53にしてスクロールセットの後、JMP($DFFC)
それ以外のデータはデモ
$0200-$02FF:仮想OBJエリア
$0300-$03FF:VRAMバッファ
■ディスクドライブのプロテクト
最初のドライブにはプロテクトは掛かっていませんでしたがコピープログラムの発表や発売され
一定時間(約1秒)しか書き込みが出来ないようになりました。
プロテクトの内容はドライブ内の基板でライト信号が送られたらカウントして約1秒たったら
シャットダウンする方式でコレをパターンカットとバイバスを通して無効する方法があります。
最終的にはFDC自身に同等のプロテクトを掛けるのですがロジック回路で破られています。
ソフトでのプロテクト
元々QDなのでそれほどきついプロテクトは掛けられません。
特定のソフトのコピーツールに対してのプロテクトとなります。
またPCから読み書きやデュプリケータでは全くプロテクトの意味がありません。
ダミーファイル
ブロックコード$02のマウントファイル数より多くファイルを持つタイプ
とびだせ大作戦、夢工場ドキドキパニック、ディープダンジョンII勇士の紋章(店頭販売、書き換え共)が該当します
主に対DISKHACKERV1.1用です
DISKHACKERV1.1までではファイル数を見て必要なファイルだけをコピーしていました
とびだせ大作戦のA面では実際のファイルはブロックコード$02のファイル数より1つ多く
DISKHACKERV1.1でコピーすると最後の1つだけファイルが足りないものになります
そのファイルが無ければコピー品と判断しています
ダミーファイルとはいえ、とびだせ大作戦はダミーファイルが本当のメインプログラムになっていて
ゲームスタートするとMAINPROG(警告プログラム)がロードされ、その後すぐにダミーファイル(本当のメイン)が
RAMに上書きされ実行されます
ダミーファイルが上書きされないと警告プログラムが動いてコピー品とみなされメッセージを出します
夢工場ドキドキパニック、ディープダンジョンII勇士の紋章では数バイトのデータが書き込まれていて
このファイルがロード出来るかでコピー品の判断を行っています。
とびだせ大作戦ではコピー失敗すると作者からメッセージが出ます。
夢工場ドキドキパニックのコピー失敗
勇士の紋章のコピー失敗
新鬼ヶ島のコピー失敗
40KBファイル
コピーツールのバッファより大きいファイルを持つタイプ
麻雀家族、スーパーロードランナーが該当
1つのファイルがRAM容量よりも大きくなっています
ファイルが40KBのファイルがあり、コピーバッファが少ないとコピー出来ないようになっています
主に対DISKHACKERV1.2用
DISKHACKERV1.3ではV1.2より大きいバッファを持ちコピー出来ます。
ファミコンのディスクはランダムアクセスが出来ないQDなのでトラックやセクタ等は無く
テープと同じように最低でも一つのファイルを一気に書き込まないといけません
つまり分割して一つのファイルを書き込みする事はかなり困難になります
しかし、本体メモリは32KB(RAMアダプタ)+2KB(ワーク)+2KB(VRAM)+キャラクタ(8K)計44KBなので
4KB内でコピープログラム、最低限40KBのバッファを取ってコピー出来るツールもあります
スーパーロードランナーではSIDEAの4番目のファイルLRMAIN01が
ロードアドレス$6000で長さ$A000になります
3番目のファイルPROTECT(ローダ)を本体内ワークRAMにローダを転送、実行
LRMAIN01は$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を出力して
コピーできないようになっています
DEV1のRAMディスクとディスクハッカーVer1.0ではエラーが出ずにコピー出来ます
DEV2のRAMディスクとディスクハッカーVer1.0ではエラーFFが出てコピー出来ません
他のコピーツールではコピーが出来ますが44KBファイルはコピーできません
プログラム書き換えチェック
これはプロテクトといってもコピープロテクトでは無くプログラムの改造されたかチェックをするタイプ
改造するとチェックサムエラーのメッセージが出たり、起動画面に飛んだり、ゲームが起動出来ない様になっています
ただし完全なチェックを行っているとは限りません(コピーライト表記の書き換えを阻止するだけの為?)
コナミやカプコンのソフトに見かけます
セクションZのチェックサムエラーメッセージ
ナムコのディスクソフト
プロテクトでは無いのですがナムコのディスクソフトは非ライセンスソフトと同じような
許諾画面を出さないような事をしています。
実際には許諾画面を出しているのですがRAMアダプタのプログラムで動いてなくて
ゲームソフト(IPLMAIN)が割り込みでRAMアダプタからの許諾画面表示
を乗っ取っていながらゲームソフトから許諾画面を表示しています。
これにより任天堂が許諾画面表示の乗っ取りプログラムに対する
プロテクトを掛けるのが難しくなっています
つまりプロテクトを掛けるのを防ぐ為の任天堂に対する逆プロテクト(?)に思えますが
真相は不明です。

Enri's HP
http://www43.tok2.com/home/cmpslv/














0 件のコメント:

コメントを投稿