MZ-80A ROMディスク — デベロッパーズガイド
RomDisk 開発者ガイド
このガイドは、Sharp MZ-80A RomDisk PCB ファームウェアのソースコードと開発環境の詳細なウォークスルーです。アセンブリ言語に不慣れな開発者向けに Z80 アセンブリ言語の概念を説明し、RomDisk 固有のバンク切り替えメカニズムを詳しく解説し、すべてのソースモジュールをウォークスルーし、新しいコマンドの追加方法、新しい SPI ハードウェアバリアントの追加方法、実際のハードウェアで動作するファームウェアのデバッグ方法を示します。
RomDisk ファームウェアは ROM ファイリングシステム(RFS)のバリアントです。特に記載がない限り、ここでの説明はすべて
rfs_definitions.asm に BUILD_ROMDISK EQU 1 を持つビルドに適用されます。ハードウェアアーキテクチャと PCB 構築の詳細については RomDisk ハードウェアページ を参照してください。ユーザー向けの操作については RFS ユーザーマニュアル を参照してください。
アセンブリ言語を知らない開発者のための Z80 アセンブリ入門
RomDisk ファームウェア全体は Z80 アセンブリ言語で書かれています。これは Sharp MZ シリーズで使用される Zilog Z80 プロセッサのネイティブ命令言語です。高水準言語とは異なり、アセンブリはほぼ直接物理ハードウェアにマッピングされます:すべての命令は CPU が直接実行する 1 つまたは数バイトに変換されます。
レジスター
Z80 には「変数」がありません — 代わりに小さなレジスターセット(CPU 内部の高速ストレージ場所)があります。RFS で最もよく使用されるもの:
| レジスター | サイズ | 役割 |
|---|---|---|
| A | 8 ビット | アキュムレーター — 算術、論理、I/O 操作の主要レジスター。ほぼすべての命令が A を使用します。 |
| B, C | 8 ビット | 汎用目的。BC で 16 ビットペアを形成し、ループカウンターまたはバイト数として一般に使用されます。 |
| D, E | 8 ビット | 汎用目的。DE で 16 ビットペアとなり、送信元または宛先ポインターとして一般に使用されます。 |
| H, L | 8 ビット | 汎用目的。HL で主要な 16 ビットメモリポインターを形成します — ほとんどのメモリ読み書き命令が HL を使用します。 |
| IX, IY | 16 ビット | インデックスレジスター — ベース+オフセットメモリアドレス指定に使用。HL より低速ですが、構造化データには便利です。 |
| SP | 16 ビット | スタックポインター — コールスタックのトップを指します。PUSH と POP は SP を自動的に使用します。 |
| PC | 16 ビット | プログラムカウンター — 現在の命令のアドレス。自動的にインクリメントされ、ジャンプとコールで変更されます。 |
| F | 8 ビット | フラグレジスター — 算術演算によって設定される個別のビット:Z(ゼロ)、C(キャリー)、S(符号)、P/V(パリティ/オーバーフロー)。 |
LD dest, src— データのロード(コピー)。LD A, Bは B を A にコピーします。LD A, (HL)は HL が保持するメモリアドレスのバイトを A に読み込みます。LD (0x1200), Aは A をメモリアドレス 0x1200 に書き込みます。CALL addr— サブルーティンの呼び出し。戻りアドレス(次の命令)をスタックにプッシュしてaddrにジャンプします。関数呼び出しと同等です。RET— サブルーティンからの返却。スタックから戻りアドレスをポップしてそこにジャンプします。JP addr—addrへの無条件ジャンプ。JP Z, addrはゼロフラグが設定されている場合のみジャンプします(最後の操作がゼロを生成した場合)。JR offset— 短い相対ジャンプ(-128 から +127 バイト)。近くの分岐では JP より高速でコンパクトです。DJNZ offset— B をデクリメントしてゼロでない場合にジャンプ。Z80 の標準的なループ命令:LD B, 10 / LOOP: ... / DJNZ LOOPは 10 回繰り返します。ADD A, n— n を A に加算。SUB nは減算。AND n、OR n、XOR n— A に対するビット演算。IN A, (port)— I/O ポートから A に読み込み。OUT (port), A— A を I/O ポートに書き込み。これらが Z80 がハードウェア(WD1773 フロッピーコントローラー、SPI シフトレジスター、バンクラッチなど)と通信する方法です。PUSH rr / POP rr— 16 ビットレジスターペアをスタックへ保存/復元します。EI / DI— 割り込みの有効化/無効化。割り込まれてはならないコード(例:時間クリティカルなテープ操作)は DI と EI の間に包まれます。
Z80 はデータのソースまたは宛先を指定するいくつかの方法を提供します:
GLASS アセンブラー構文
- 即値:
LD A, 42— 値は命令バイト自体に埋め込まれています。 - レジスター:
LD A, B— データはレジスターから来るか、レジスターに行きます。 - 間接(HL 経由):
LD A, (HL)— HL がメモリアドレスを保持し、そのアドレスからデータが読み取られます。 - 拡張(直接アドレス):
LD A, (0x1200)— アドレスは命令内のリテラル 16 ビット定数です。 - インデックス付き:
LD A, (IX+5)— IX がベースアドレスを保持し、5 を加算して実効アドレスを得ます。RFS では固定フォーマットデータ構造内のフィールドへのアクセスに使用されます。
RFS は GLASS Z80 アセンブラー(
tools/glass.jar としてバンドル)を使用します。主な構文の特徴:
- コメントは
;で始まります — セミコロンの右側はすべて無視されます。 - ラベルは
:が続く識別子です。行の先頭のラベルは次の命令のアドレスを命名します。 EQUは定数を定義します:BELL EQU 007H— アセンブラーは BELL のすべての出現を 0x07 に置き換えます。DB(バイト定義)は生のバイトを挿入します:DB 0x41, 0x42は 2 バイトを出力します。文字列、ルックアップテーブル、コマンドテーブルエントリに使用されます。DW(ワード定義)は 16 ビットリトルエンディアン値を挿入します:DW HANDLERは HANDLER ラベルのアドレスを出力します。ORG addrはアセンブリ原点を設定します — 以降のコードはaddrに存在するかのようにアセンブルされます。INCLUDE "file.asm"は現在の位置に別のファイルをテキストとして取り込みます。IF / ENDIF条件アセンブリ:IF HW_SPI_ENA = 1 ... ENDIF— 囲まれた命令は条件が真の場合にのみアセンブルされます。これが RFS が 1 つのソースツリーからハードウェア SPI、ソフトウェア SPI、パラレルポート SPI を選択する方法です。
ソースツリー
| パス | 内容 |
|---|---|
README.md |
トップレベルのプロジェクト概要 |
README_CPM.md |
CP/M 固有の注記 |
schematics/ |
PCB v1.1、v2.0、v2.1 の KiCad 回路図 |
pcb/ |
KiCad PCB レイアウトファイル |
software/RFS/ |
RFS ファームウェアサブモジュール(/dvlp/Projects/RFS にもあります) |
software/RFS/asm/ |
すべての Z80 アセンブリソースファイル |
software/RFS/asm/include/ |
共有設定とユーティリティインクルード |
software/RFS/tools/ |
ビルドスクリプトと GLASS アセンブラー(glass.jar) |
software/RFS/build.sh |
トップレベルのビルドスクリプト |
アセンブリソースファイルとその役割:
| ファイル | バンク | 役割 |
|---|---|---|
rfs.asm |
ユーザー ROM バンク 0 | エントリーポイント、コマンドテーブル、バンク切り替えスタブ、ジャンプテーブル |
rfs_bank1.asm |
ユーザー ROM バンク 1 | フロッピーディスクコントローラー |
rfs_bank2.asm |
ユーザー ROM バンク 2 | SD カードコントローラー(SPI ドライバー、SDCFS) |
rfs_bank3.asm |
ユーザー ROM バンク 3 | メモリユーティリティ(D、M、CP、T2SD、SD2T) |
rfs_bank4.asm |
ユーザー ROM バンク 4 | CMT(カセットテープ)コントローラー |
rfs_bank5.asm |
ユーザー ROM バンク 5 | 予約済み / 未使用 |
rfs_bank6.asm |
ユーザー ROM バンク 6 | メッセージ、ヘルプ画面、ASCII ↔ Sharp 文字変換 |
rfs_bank7.asm |
ユーザー ROM バンク 7 | メモリテスト(R コマンド)、タイマーテスト(T コマンド) |
rfs_mrom.asm |
モニター ROM バンク 3 | MZF ROM スキャンとロード(ROMDIR、ROMLOAD) |
cbios.asm |
モニター ROM バンク 2 | CP/M CBIOS エントリーポイントテーブルと ROM ディスクコントローラー |
cbios_bank1–4.asm |
ユーザー ROM バンク 8–11 | CP/M CBIOS サブシステム |
monitor_sa1510.asm |
— | SA-1510 モニター ROM リファレンス |
monitor_80c_sa1510.asm |
— | SA-1510 モニター ROM(80 列バリアント) |
ipl.asm |
— | 初期プログラムローダー |
include/rfs_definitions.asm |
— | すべての設定定数 |
include/rfs_utilities.asm |
— | 共有ユーティリティマクロ |
include/macros.asm |
— | アセンブラーマクロ定義 |
include/cpm_definitions.asm |
— | CP/M CBIOS 定数 |
設定:rfs_definitions.asm
これはすべての他のソースファイルが
ビルドターゲットと SPI フラグ
INCLUDE "rfs_definitions.asm" でインクルードする中央設定ファイルです。すべてのアセンブリ時オプションはここで制御されます。主要なセクション:
; SPI ハードウェア選択 — 正確に 1 つが 1 である必要があります: HW_SPI_ENA EQU 1 ; RomDisk v2+ PCB 上のハードウェア SPI(74HCT595/165 シフトレジスター) SW_SPI_ENA EQU 0 ; Z80 I/O ポートビットを介したソフトウェアビットバン SPI PP_SPI_ENA EQU 0 ; パラレルプリンターポート SPI(v1 ボードのみ) ; プラットフォームオプション: FUSIONX_ENA EQU 1 ; tranZPUter FusionX サポートを含める KUMA80_ENA EQU 0 ; ターゲットに Kuma 40/80 アップグレードが取り付けられている VIDEOMODULE_ENA EQU 0 ; ターゲットに 40/80 列カラービデオモジュールが取り付けられている ; ビルドターゲット — 正確に 1 つが 1 である必要があります: BUILD_ROMDISK EQU 1 ; MZ-80A RomDisk カード用にビルド BUILD_SFD700 EQU 0 ; SFD-700 フロッピーインターフェイス用にビルド BUILD_PICOZ80 EQU 0 ; picoZ80 ボード用にビルド ; デバッグ: ENADEBUG EQU 0 ; アセンブリ中のデバッグ出力を有効にする(1 = 有効)
正確に 1 つの
アドレス定数
BUILD_* フラグと正確に 1 つの SPI フラグを同時に 1 に設定する必要があります。複数を設定すると、誤ったまたはあいまいなコードが生成されます — rfs_bank2.asm のいくつかの条件ブロックは相互排他を前提としたネストされた IF/ELSE/ENDIF チェーンを使用します。FUSIONX_ENA = 1 の場合、tranZPUter FusionX メモリ管理の追加コードがバンク切り替えスタブにアセンブルされます。FusionX パスは実行時に FusionX ハードウェアが検出された場合にのみ取られるため、標準の RomDisk ビルドで有効にしたままにしても安全です。
UROMADDR EQU 0E800H ; ユーザー ROM ウィンドウのベースアドレス UROMBSTBL EQU UROMADDR + 020H ; バンク切り替えテーブルエントリーポイント(0xE820) RFSJMPTABLE EQU UROMADDR + 0B0H ; ジャンプテーブル開始(0xE8B0) FDCROMADDR EQU 0F000H ; フロッピー AFI ROM アドレス ; バンク制御レジスター(コード化ラッチのロック解除後にのみアクセス可能): BNKCTRLRST EQU 0EFF8H ; 制御レジスターのロックを解除するにはここを 16 回読み取る BNKCTRLDIS EQU 0EFF9H ; 制御レジスターを再ロック(無効化)するにはここを 1 回読み取る HWSPIDATA EQU 0EFFBH ; ハードウェア SPI データレジスター(読み書き) HWSPISTART EQU 0EFFCH ; ハードウェア SPI 開始トリガー(転送を開始するために書き込む) BNKSELMROM EQU 0EFFDh ; モニター ROM バンク選択レジスター BNKSELUSER EQU 0EFFEh ; ユーザー ROM バンク選択レジスター BNKCTRL EQU 0EFFFH ; バンク制御レジスター(読み書き)
BNKCTRLRST から BNKCTRL(0xEFF8–0xEFFF)は Flash ROM ウィンドウの上位 8 バイトと同じアドレス空間を共有することに注意してください。リセット時、これらのアドレスは通常の Flash ROM 読み取りとして動作します。74HCT191 プリセット可能カウンターで構成されたコード化ラッチ回路は、BNKSELMROM、BNKSELUSER、BNKCTRL への書き込みが有効になる前にロック解除する必要があります。完全なロック解除シーケンスについては、以下のバンク切り替えセクションを参照してください。
文字と制御定義
標準の ASCII 制御文字は、ソースを自己文書化するために名前付き定数として定義されています:
BELL EQU 007H ; ターミナルベル CR EQU 00DH ; キャリッジリターン LF EQU 00AH ; ラインフィード CS EQU 00CH ; 画面クリア(FF) SPACE EQU 020H ; ASCII スペース DELETE EQU 07FH ; デリートキー
バンク切り替えの詳細
RomDisk のバンク切り替えメカニズムは TZFS で使用されるものとは根本的に異なります。TZFS は tranZPUter CPLD のメモリ管理モードを使用して、ハードウェアでアドレス範囲を再マッピングします。RomDisk は代わりに物理的なバンクラッチ(74HCT273 D タイプフリップフロップ)を使用し、ユーザー ROM アドレス空間のトップにあるメモリマップド I/O レジスターを通じてアクセスします。このメカニズムを理解することは、どのソースファイルを変更するより前に不可欠です。
バンキングが必要な理由
Sharp MZ-80A はユーザー ROM に 2KB のアドレス空間(0xE800–0xEFFF)しか与えていません。2KB には数百の命令しか入りません — ファイリングシステム、フロッピーコントローラー、SD カードドライバー、テープコントローラー、メモリユーティリティには到底足りません。解決策は、より大きな Flash チップのどの 2KB ページが 0xE800–0xEFFF に表示されるかを物理的に切り替えることです。RomDisk PCB は 2KB バンクに分割された 512KB Flash チップを保持し、一度に最大 12 バンクにアクセスできます。必要に応じてバンクを切り替えることで、SA-1510 モニターが静的な 2KB ウィンドウしか見えない中でも、RFS は実質的に 24KB の ROM コードを持てます。
コード化ラッチ(v2.0 以降のボード)
バンク選択レジスターは Flash ROM の上位 8 バイト(0xEFF8–0xEFFF)とアドレスラインを共有します。バンク選択レジスターが常時書き込み可能だった場合、そのアドレス範囲への意図しない書き込み、あるいは Z80 のリフレッシュサイクルがその範囲に当たるだけで、実行中に静かにバンクが切り替わってしまいます。RomDisk v2.0 PCB はこれを防ぐためにコード化ラッチを導入しました。
コード化ラッチは 74HCT191 プリセット可能カウンターで構成されています。デフォルト状態(カウンターがターミナルカウントに達していない)では、バンク制御レジスター I/O パスが無効化されています — BNKSELMROM、BNKSELUSER、BNKCTRL への書き込みは効果がありません。パスを有効化するには、ソフトウェアがアドレス BNKCTRLRST(0xEFF8)から正確に 16 回読み取る必要があります。各読み取りでカウンターが 1 つインクリメントされます。カウンターがターミナルカウント(16)に達すると、バンク制御レジスター書き込みパスをアクティブにする有効化信号をアサートします。
バンク切り替えが完了したら、ソフトウェアは BNKCTRLDIS(0xEFF9)から 1 回読み取ります。これにより 74HCT191 が初期値にリセットされ、制御レジスターパスが再び無効化されます。ラッチは後続のバンク切り替えシーケンスごとに再ロック解除する必要があります。
RomDisk v2.1 ボードは AND ゲート(回路図では D1/D2 と称される)を追加して、Z80 の DRAM リフレッシュサイクルがカウンターを誤ってインクリメントするのを防ぎます。このゲートがなければ、Z80 が自動的に生成する周期的なリフレッシュバスサイクルがカウンターをインクリメントし、ターミナルカウントに達して、意図的なソフトウェアアクションなしに ROM エントリーポイントが実行される前に起動時に誤ったバンク切り替えを引き起こす可能性があります。
バンク切り替えシーケンス
ユーザー ROM の完全なバンク切り替えには、以下の手順が必要です:
重要:0xEFF8–0xEFFF にわたるループを配置してはならない
- コード化ラッチのロック解除: アドレス BNKCTRLRST(0xEFF8)から正確に 16 回読み取ります。各読み取りはダミー読み取りです — 返されるデータはそのアドレスの Flash ROM バイトで、破棄できます。レジスター B のループカウンターを使用します(16 に設定)が、以下の DJNZ 配置に関する重要な警告を参照してください。
- バンク番号の書き込み: 目的のバンク番号(ユーザー ROM バンクの場合は 0–7)を BNKSELUSER(0xEFFE)に書き込みます。74HCT273 は書き込みストローブの立ち上がりエッジで値をラッチします。モニター ROM バンク選択には代わりに BNKSELMROM(0xEFFD)に書き込みます。
- ラッチの再ロック: BNKCTRLDIS(0xEFF9)から 1 回読み取ります。これにより 74HCT191 カウンターがリセットされ、次の 16 回読み取りシーケンスまで制御レジスター書き込みパスが無効化されます。
UROMBSTBL を計算するだけで)バンク 3 のスタブを常に見つけられます。
これは RomDisk コードベース全体で最も重要な実装上の制約です。Z80 はプログラムカウンターアドレスから読み取ることで命令バイトをフェッチします。命令フェッチやデータ読み取りが 0xEFF8–0xEFFF の範囲内で発生した場合、74HCT191 カウンターをインクリメントします。例えば 0xEFF7 にある
FusionX バンク切り替え(FUSIONX_ENA = 1)
DJNZ 命令は 0xEFF7(効果なし)からオペコードをフェッチし、次に 0xEFF8(カウンターをインクリメント)からオフセットバイトをフェッチし、後続のループ反復でも毎回カウンターをインクリメントし続けます。意図的なバンク切り替えの前にループが 16 回以上実行された場合、カウンターがターミナルカウントに達し、制御レジスターがアクティブになり、0xEFF8–0xEFFF の任意のアドレスへの次の書き込みが意図しないバンク切り替えを実行します — 実行中のコードを即座に別のバンクに置き換えます。
ルールはシンプルです:ループ命令(DJNZ、JR、JP)は、その分岐先または自身のオペコード/オペランドバイトが 0xEFF8–0xEFFF 内にあってはなりません。 GLASS アセンブラーはこれを自動的に検出したり警告したりしません。プログラマーの責任です。バンクにコードを追加するとき、アセンブルされたバイナリが 2KB ウィンドウのトップ近くにループ命令を配置していないことを確認してください。
FUSIONX_ENA = 1 の場合、バンク切り替えスタブには、コード化ラッチレジスターの代わりに FusionX メモリ管理ポートアドレスを代入する条件アセンブリブロックが含まれています。tranZPUter FusionX ボードでは、Flash ROM ページングメカニズムが FusionX CPLD のメモリ管理に置き換えられ、16 回読み取りロック解除シーケンスなしに別の I/O ポートスキームでバンク番号を受け付けます。RFS コマンドセット、SDCFS ファイルシステム、すべてのユーザー向け動作は FusionX でも同一です — 低レベルのバンク選択書き込みのみが異なります。
rfs.asm のモニターコマンドディスパッチャーはコンパクトなコマンドテーブルを使用します。各エントリーは 1 つのコマンドを記述し、以下のようにレイアウトされています:
; 1 つのコマンドテーブルエントリー:
;
; DB FLAGS ; 1 バイト:END|MATCH|BANK[5:3]|SIZE[2:0]
; DB "COMMAND" ; SIZE バイト:コマンド文字列(ヌルターミネーターなし)
; DW HANDLER_ADDR ; 2 バイト:指定バンク内のハンドラールーティンのアドレス
;
; フラグバイトのビットフィールド:
; ビット 7 = 1:テーブル終端マーカー(最後のエントリー)
; ビット 6 = 1:完全一致が必要(入力全体が一致する必要がある;後続の文字は不可)
; ビット 5:3 ハンドラーが存在するバンク番号(0–7 はユーザー ROM バンク 0–7 にマップ)
; ビット 2:0 コマンド文字列のバイト長(1–7)
;
; 例 — 'D'(ダンプ)コマンド、ハンドラーはバンク 3 にあり、1 文字の文字列:
DB 000H | 000H | 018H | 001H ; テーブル終端でない、完全一致でない、バンク 3(011<<3=0x18)、長さ 1
DB "D"
DW DUMPX
ディスパッチャーはモニター入力行を読み取り、テーブルを走査し、各エントリーについて:
- 入力の最初の SIZE 文字をコマンド文字列と比較します。
- EXACT フラグが設定されている場合、さらに追加の非スペース文字がないことも検証します。
- 一致した場合、テーブルエントリーからバンク番号とハンドラーアドレスを抽出します。
- UROMBSTBL のスタブを通じてターゲットバンクへのバンク切り替えを実行します。
- モニター入力バッファで利用可能な残りの入力(パラメーター)を持つハンドラーを呼び出します。
LTNX は LT の前に、LT は L の前になければなりません。そうでないと、短いエントリーが最初に一致し、長いコマンドには到達しません。
モジュールウォークスルー
rfs.asm — コマンドディスパッチャー(ユーザー ROM バンク 0)
役割: すべての RFS 機能のエントリーポイント。SA-1510 モニターがコマンドを認識しない場合、UROMADDR(0xE800)のユーザー ROM エントリーポイントに制御を渡します。このアドレスは常にバンク 0 です。
主要セクション:
rfs_bank1.asm — フロッピーディスクコントローラー(ユーザー ROM バンク 1)
- ROM エントリー(ROMFS、0xE800): NOP の後にモニター ROM バンク 0 を選択するマクロ呼び出し、次にバンク切り替えテーブルエリアをスキップする JP が続きます。コールドスタート時(ROMBK1 の値が 8 以上の不正な値であることで検出)、16 回読み取りコード化ラッチセットアップシーケンスが実行され、下位スタック領域がゼロクリアされます。初期 MROM および UROM バンクは ROMBK1/ROMBK2 に保存された状態から選択されます。
- バンク切り替えスタブ(UROMBSTBL、0xE820): 16 個のクロスバンクコールゲートウェイ(BKSW0to0 から BKSW0to7)— バンク 0→N 遷移ごとに 1 つ。各ゲートウェイは呼び出し元バンク番号とターゲットバンク番号をスタックにプッシュし、次にコード化ラッチロック解除を実行し、新しいバンクを BNKSELUSER に書き込み、ターゲットハンドラーアドレスにジャンプする共通 BKSW0_0 シーケンスを呼び出します。返却時(BKSWRET0)、元のバンクが同じシーケンスで復元されます。
- ジャンプテーブル(RFSJMPTABLE、0xE8B0): モニター ROM または SA-1510 インターセプトフックが呼び出す必要がある関数の固定アドレス JP 命令:PRTMZF、PRTDBG、CMT_RDINF、CMT_RDDATA、CMT_WRINF、CMT_WRDATA、CMT_VERIFY、CMT_DIR、CNV_ATOS。
- コマンドテーブル(CMDTABLE): RomDisk/picoZ80 ビルドのコマンドリスト。コマンドには:ドライブ選択(0–9)、40/80 列モード、B(ベルトグル)、BASIC、C(クリア)、CP、CPM、D(ダンプ)、EC(消去)、F(フロッピーブート)、f(AFI ROM)、H(ヘルプ)、IR/IC(ディレクトリ)、J(ジャンプ)、LC/LR/LT およびそれらの NX バリアント(SD/ROM/テープロード)、M(編集)、P(プリンターテスト)、R(DRAM テスト)、SD2T、SC/ST(保存)、T(タイマーテスト)、T2SD、V(検証)が含まれます。
- 初期化(MONITOR → SIGNON): CPLDINFO I/O ポートを通じて tranZPUter ボードの存在を確認します。初期 SD ドライブ番号を 0 に設定します。アクティブなモニター ROM バンクを検出して 40 列または 80 列表示モードを決定し、それに応じて表示を設定します。ビデオモジュールビルドでは、表示モードを DSPCTL ラッチに書き込みます。
- コマンドディスパッチャー(ST1X): モニターの入力バッファを読み取り、CMDTABLE を走査し、一致時にバンクとハンドラーアドレスを抽出し、バンク切り替えスタブを呼び出し、返却後に次のコマンドを待つためにループバックします。一致するエントリーがない場合、SA-1510 モニターに制御を返して "?" エラーを表示させます。
役割: フロッピーディスクブートコマンドを実装します。RomDisk ビルドでは、このバンクが完全な F(ドライブ選択ブート)と f(直接 AFI ROM ジャンプ)コマンドを提供します。
主要関数:
rfs_bank2.asm — SD カードコントローラー(ユーザー ROM バンク 2)
- FLOPPY(F コマンド): コマンドラインに指定がない場合はドライブ番号の入力を求めます。ドライブ選択とモーター有効化バイトを I/O ポート 0xDC(WD1773 FDC 制御ポート)に書き込みます。スピンドルモーターが動作速度に達するのを待ちます(通常 300〜500ms、CPU サイクルカウントの遅延ループで測定)。ブートセクターを読み取り、ブート可能ディスクのシグネチャバイトを検証し、セクターにあるブートローダーコードに制御を渡します。
- FDCK(f コマンド): FDCROMADDR(0xF000)のバイトを読み取って AFI ROM が存在し非ゼロであることを確認します。見つかった場合は 0xF000 を直接呼び出し、元の SA-1510 フロッピーブート ROM に制御を渡します。FLOPPY の WD1773 ドライブ選択ロジックが不要な場合のフォールバックとして有用です。
役割: 完全な SD カードサブシステム — SPI ドライバー初期化、SD カードコマンドプロトコル、SDCFS ディレクトリとファイル I/O ルーティン。SPI ドライバーコードはアセンブリ時に HW_SPI_ENA、SW_SPI_ENA、PP_SPI_ENA フラグで選択されます。
主要関数:
rfs_bank3.asm — メモリユーティリティ(ユーザー ROM バンク 3)
- SDINIT: SD カード SPI 初期化シーケンスを実装します。チップセレクトをデアサートし、SPIINIT を呼び出してカードを SPI クロックにトレーニングし、次にチップセレクトをアサートして最大 SD_RETRIES 回の試みで CMD0(GO_IDLE_STATE)を送信します。成功すると、SD v2 カードを検出するために CMD8(SEND_IF_COND)を送信し、次にアイドル状態から脱するために ACMD41(SD_SEND_OP_COND)を送信します。CMD58 からの OCR 応答を確認することで SD v1、SD v2、SDHC、SDXC、MMC v3 カードを処理します。
- SDREAD / SDWRITE: セクターレベルの読み取り(CMD17、READ_SINGLE_BLOCK)と書き込み(CMD24、WRITE_BLOCK)。SDREAD はデータ開始トークン(0xFE)を待ってから 512 バイトを SDBUF RAM バッファに読み込みます。SDWRITE はデータ開始トークン、512 バイトのデータ、ダミー CRC を送信し、ビジー信号がクリアされるのを待ちます。
- SDDIR: アクティブな SD ドライブイメージの最初の 8KB からディレクトリを RAM 常駐ディレクトリキャッシュに読み込みます。各ディレクトリエントリは MZF ヘッダー形式(128 バイト):ファイルタイプ、ファイル名(17 バイト、Sharp エンコーディング)、データサイズ、ロードアドレス、実行アドレス。
- SDLOAD: ディレクトリキャッシュからファイル番号を受け取り、ファイルのデータブロックの 64KB アライメントされたセクターアドレスを計算し、ファイルのデータサイズバイトを読み取り、ディレクトリエントリのロードアドレスフィールドに格納された Z80 アドレスに直接ロードします。
- SDSAVE: 新しいディレクトリスロットを割り当てるか、同じ名前の既存エントリーを上書きします。MZF ヘッダーフィールド(開始セクター、サイズ、ロードアドレス、実行アドレス)を書き込み、対応する 64KB ブロックにファイルデータを書き込みます。
- SPIINIT: SD カードを SPI クロックにトレーニングします。HW_SPI_ENA では HWSPIDATA に 0xFF を書き込み HWSPISTART を 10 回トリガーします(80 個の '1' ビットを送信)。PP_SPI_ENA(パラレルポートビットバン)では、データを高に保ちながらクロックラインを 80 回トグルします。
- SPICS: SD カードチップセレクトラインを設定します。A = 0 は CS をアクティブ(低)にし、A = 0xFF は非アクティブ(高)にします。HW_SPI_ENA では BNKCTRL の SDCS ビットと BBCLK ビットを変更してハードウェアレジスターに書き戻します。
- SPIOUT: SD カードに 1 バイト A を送信します。HW_SPI_ENA では:A を HWSPIDATA に書き込み HWSPISTART をトリガーします — 2 回のメモリ書き込み、8MHz SPI クロックで約 1µs/バイト。PP_SPI_ENA では:パラレルポートのクロックとデータラインをトグルすることで各バイトを MSB から順にビットバングします。
- SPIIN: SD カードから 1 バイトを受信します。HW_SPI_ENA では:HWSPISTART をトリガーして 8 ビットをクロックインし、HWSPIDATA を読み取ります。PP_SPI_ENA では:パラレルポートの入力レジスターを読み取ることで各ビットをクロックインします。
役割: すべてのビルドで利用可能な D(16 進ダンプ)、M(メモリ編集)、CP(メモリコピー)コマンドを実装します。T2SD(テープから SD へ)と SD2T(SD からテープへ)コマンドもこのバンクにあります。
DUMPX(D コマンド): ターゲットアドレス範囲から最大 20 行の 16 バイトを読み取ります。各行に 4 桁の 16 進アドレス、4 バイトごとにスペースを挟んだ 16 個の 16 進バイト値、対応する 16 個の ASCII 文字(印刷不能バイトはドット)を表示します。Sharp MZ は独自の文字エンコーディングを使用しているため、バンク 6 が提供する Sharp-ASCII 変換テーブルを使用します。
MCORX(M コマンド): インタラクティブなメモリエディター。アドレスと現在の 16 進値を示しながら各バイトを順に表示します。ユーザーが新しい 1 桁または 2 桁の 16 進値を入力して Enter を押すと書き込まれ、Enter だけを押すとバイトを変更せずに進みます。Ctrl+C またはエスケープキーで終了します。
MCOPY(CP コマンド): ブロックメモリコピー。コマンドラインから 4 桁の 16 進値として送信元アドレス、宛先アドレス、バイト数を受け取ります。重なり合う領域を正しく処理するために必要に応じて前方または後方コピーを実行します。
T2SD と SD2T: 双方向のテープ↔SD コピー。T2SD はバンク 4 の CMT ロードルーティンを呼び出してテープファイル(MZF ヘッダーを含む)を RAM に読み込み、次にバンク 2 の SDSAVE ルーティンを呼び出してアクティブな SD ドライブに書き込みます。SD2T はバンク 2 の SDLOAD を呼び出してファイルを RAM にロードし、次にバンク 4 の CMT セーブルーティンを呼び出してテープに書き込みます。両方のコマンドは MZF ヘッダーフィールド(ファイル名、サイズ、ロードアドレス、実行アドレス)を使用して、メディア間でディレクトリを一貫して保ちます。
rfs_bank4.asm — CMT コントローラー(ユーザー ROM バンク 4)
役割: LT/LTNX(テープロード)、ST(テープセーブ)、V(テープ検証)コマンドを実装します。
Sharp MZ-80A は 1200 ボードのカンサスシティスタンダードカセットインターフェイスを使用します。バイトは 1200Hz(ビット 0)または 2400Hz(ビット 1)のトーンのバーストとしてエンコードされます。テープルーティンは時間クリティカルで、入力トーン周波数を測定し、出力波形をマイクロ秒の精度で生成する必要があります。ビット周期を測定するために 8253 プログラマブルインターバルタイマー(またはタイマーのないプラットフォームでは CPU サイクルカウントの遅延ループ)を使用します。割り込みはすべてのテープ操作中に無効化されます(
rfs_bank5.asm — 予約済み(ユーザー ROM バンク 5)
DI)。
LOADTAPE / LOADTAPENX: テープから MZF ヘッダー(128 バイト:ファイルタイプ、ファイル名、データサイズ、ロードアドレス、実行アドレス)を読み取り、ファイル名を表示してから、データバイトをロードアドレスに読み込みます。LOADTAPE はロード成功後に実行アドレスにジャンプして自動実行します;LOADTAPENX は代わりに RFS コマンドプロンプトに返ります。
SAVEX(ST コマンド): テープに MZF ヘッダーとデータバイトを書き込みます。コマンドラインから開始アドレス、終了アドレス、実行アドレスを受け取るか、指定がない場合は入力を求めます。
VERIFYX(V コマンド): テープファイルを読み取り、元のロードアドレスの RAM と比較します。アドレスと期待値/実際の値を示しながら不一致を報告します。
テープルーティンが使用する MZF ヘッダー形式は SDCFS ディレクトリエントリー形式と同一です。これは偶然ではありません — これがテープから SD へのコピーが完全に透明で、LT でロードされたプログラムをヘッダー変換なしに SC で SD カードに再保存できる理由です。
役割: RomDisk ビルドでは現在予約済みで未使用です。バンクスロットは Flash ROM イメージに存在し、標準オフセットにバンク切り替えスタブを含んでいますが、ユーザーがアクセスできるコマンドはここにマッピングされていません。このバンクは将来の拡張に利用できます — 例えば XModem 転送プロトコル、16 進ローダー、追加のメモリマップドハードウェアドライバーの追加など。
rfs_bank6.asm — メッセージと文字テーブル(ユーザー ROM バンク 6)
役割: ヘルプ画面テキスト、すべてのエラーおよびステータスメッセージ文字列、Sharp MZ 文字セットから ASCII への変換テーブルを格納します。
HELPSCR(H コマンド): ヘルプ画面の 1 行ごとの CR で終わる文字列のシーケンス。BUILD_ROMDISK バリアントは T2SD、SD2T、F[X]、f、LC、SC、EC、IR/IC、ドライブ選択数字 0–9 を含むすべての RomDisk コマンドをリストアップします。リストは 1 バイトの 000H で終端されます。H コマンドはこのリストを走査し、終端に達するまで各文字列を表示します。
PRINTMSG / PRTFN: 文字列表示ユーティリティ。PRINTMSG は書式付き診断メッセージのために埋め込みマーカーバイト(スタックから値を挿入する 0xFF など)を処理します。PRTFN は ATBL 変換テーブルを使用して Sharp MZ ファイル名(Sharp エンコーディングの 17 バイト)を ASCII テキストとして表示します。
ATBL(ASCII-Sharp 変換テーブル): ASCII 文字コードを Sharp MZ の同等物に、またはその逆にマッピングする 256 バイトのルックアップテーブル。Sharp MZ シリーズは独自の 8 ビット文字エンコーディングを使用しており、印刷可能な文字が ASCII とは異なるコードポイントを持ちます — 多くの一般的な文字(文字、数字、句読点)がシフトまたは並べ替えられています。端末に Sharp エンコーディングで保存されたファイル名を表示するコードは、各バイトをこのテーブルに通す必要があります。
rfs_bank7.asm — 診断コマンド(ユーザー ROM バンク 7)
役割: RomDisk ビルドで R(DRAM テスト)と T(タイマーテスト)コマンドを実装します。
MEMTEST(R コマンド): 完全なユーザー RAM スペース(0x1200–0xCFFF)にわたるウォーキングビットパターンの書き込み/検証テストを実行します。8 つの単一ビットパターン(0x01、0x02、0x04、…、0x80)の各々をその範囲のすべてのバイトに書き込み、次に各バイトを読み取って検証します。不一致はアドレスと期待値/実際の値とともに報告されます。新しい RAM 常駐データ構造を追加した後にこのコマンドを実行して、新しい構造が他のコードで使用される前にアドレス指定が正しいことを確認してください。
TIMERTST(T コマンド): 8253 プログラマブルインターバルタイマーをいくつかのモードにプログラムして、期待通りにカウントおよび終了することを確認することでテストします。テープ操作が信頼できない機械の診断に有用です — 不正確な 8253 の動作は CMT ビットレート測定に系統的なタイミングエラーとして現れます。
rfs_mrom.asm — モニター ROM ユーティリティ(モニター ROM バンク 3)
役割: ユーザー ROM スペースではなくモニター ROM スペースから実行する必要がある ROM スキャンと MZF ファイルロードルーティンを提供します。
なぜ別のモニター ROM バンクが必要か? IR と LR コマンドは、上位のユーザー ROM Flash バンク(ユーザー ROM バンク 11 以上にはパックされた MZF プログラムが保存されています)に保存された MZF プログラムイメージを列挙します。これらのバンクの 1 つをスキャンするには、ファームウェアはユーザー ROM ウィンドウをそのバンクに切り替える必要があります。しかしスキャンコード自体がユーザー ROM に存在するため、ユーザー ROM バンクを切り替えると、即座に自分自身のコードを別のバンクに置き換えてクラッシュしてしまいます。
解決策はスキャンループをモニター ROM バンク 3 に配置することです。モニター ROM バンク切り替え(BNKSELMROM 経由)はユーザー ROM バンク切り替え(BNKSELUSER 経由)とは完全に独立しています。モニター ROM バンク 3 で実行されているコードは、実際に実行されているモニター ROM コードを妨げることなく、ユーザー ROM バンク 12、13、14… を自由にサイクルして MZF ヘッダーを列挙できます。
主要関数:
- ROMDIR: バンク 11 以上のすべてのユーザー ROM バンクをスキャンし、各バンクの先頭から各 128 バイトの MZF ヘッダーを読み取り、RAM 常駐 ROM ディレクトリを構築します。このディレクトリは IR コマンドが ROM 常駐プログラムのリストを表示するために使用されます。
- ROMLOAD: ROM ディレクトリからファイル番号を受け取り、ユーザー ROM ウィンドウを適切なバンクに切り替え、MZF ヘッダーを読み取ってロードアドレスとデータサイズを確認し、プログラムデータをユーザー ROM から RAM のターゲットロードアドレスにコピーし、オプションで実行アドレスにジャンプします。LRNX バリアントは自動実行の代わりに RFS コマンドプロンプトに返ります。
SPI ドライバー:ハードウェア対ソフトウェア
rfs_bank2.asm の SPI ドライバーは 3 つの方法で実装されており、完全にアセンブリ時に選択されます。選択は rfs_definitions.asm の 3 つの相互排他的なフラグで制御されます:
HW_SPI_ENA EQU 1 ; RomDisk v2+ PCB 上の 74HCT595/74HCT165 ハードウェアシフトレジスター SW_SPI_ENA EQU 0 ; RomDisk v2+ I/O ポートビットを使用したソフトウェアビットバン SPI PP_SPI_ENA EQU 0 ; Sharp MZ-80A パラレルプリンターポート経由のソフトウェアビットバン SPIハードウェア SPI(HW_SPI_ENA = 1)
RomDisk PCB v2.0 以降で利用可能です。PCB は 74HCT595 シリアルアウトシフトレジスター(MOSI/CLK)と 74HCT165 パラレルインシフトレジスター(MISO/CLK)を搭載し、Z80 の 2MHz バスクロックの 8 倍の 8MHz で動作する専用ハードウェアロジックでクロックされます。
バイトの送信は 2 回のメモリ書き込みです:バイトを HWSPIDATA(0xEFFB)に書き込み、次に任意の値を HWSPISTART(0xEFFC)に書き込みます。ハードウェアはすべての 8 ビットを約 1µs で自動的にクロックアウトします。バイトの受信も同様です:HWSPISTART に書き込んで 8 ビットをクロックインし、HWSPIDATA を読み取ります。Z80 はバイト間で 2 つのメモリ書き込み命令を実行する時間だけ必要です — ハードウェアシフトレジスターは並行して動作します。
HWSPIDATA と HWSPISTART は 0xEFF8–0xEFFF のコード化ラッチ範囲内にあるため、制御レジスターがロック解除されている間(つまり 16 回の読み取りシーケンス後)にのみアクセスできます。バンク 2 の SDINIT、SDREAD、SDWRITE ルーティンは、呼び出し時に制御レジスターがすでにロック解除されていることを前提とします。これは RFS 実行環境内では常に当てはまります。
ソフトウェア SPI(SW_SPI_ENA = 1)
ハードウェアシフトレジスターの低コスト代替として RomDisk PCB v2.0 以降で利用可能です。ファームウェアは BNKCTRL レジスター(0xEFFF)の個々のビットを手動でトグルして SPI クロック(BBCLK)と MOSI データ(BBMOSI)ラインを駆動し、着信データのために BNKCTRL から MISO ビットを読み取ります。各ビットには BNKCTRL への複数の書き込みが必要です — クロックを高に、クロックを低に — 2MHz Z80 クロック速度でバイトあたり約 20〜40µs、ハードウェア SPI より約 40 倍遅いです。
SPIOUT の SW_SPI_ENA コードブロックは、現在の BBMOSI と BBCLK 状態を読み取り、関連するビットを変更し、BNKCTRL に書き戻すループを使用して各バイトを MSB から順にビットバングします。同じコード化ラッチロック解除要件が適用されます — BNKCTRL は 16 回の読み取りシーケンス後にのみ書き込み可能です。
パラレルポート SPI(PP_SPI_ENA = 1)
Sharp MZ-80A の Centronics パラレルプリンターポートを即席の SPI バスとして使用する、元の RomDisk v1 実装です。プリンターポートのデータライン(D0–D7)が再割り当てされます:1 ビットが SPI クロック(CLOCK)を駆動し、1 ビットが MOSI データ(DOUT)を駆動し、1 ビットがチップセレクト(CS)を駆動し、1 ビットがポートのステータスレジスターから MISO データ(DIN)を読み取ります。
SPIOUT(PP_SPI_ENA パス)でバイトを送信:バイトを左に 3 回回転させてビット 7 を DOUT ピン位置に合わせ、次に 8 回反復ループでパラレルポートに対して 1 ビットあたり 3 つの
SPI バリアントの選択
OUT (SPI_OUT), A 命令を使用して DOUT とクロックの高/低を駆動します。SPIINIT はクロックとデータラインを 80 回トグルして DJNZ で 80 個の '1' ビットをクロックします。すべてのパラレルポートアクセスは、メモリマップドレジスターではなく I/O ポート命令(IN / OUT)を使用します。
PP_SPI_ENA はコード化ラッチロック解除を必要としません — パラレルポートは Z80 メモリアドレス空間ではなく I/O アドレス空間に存在するため、常にアクセス可能です。これは、コード化ラッチ回路がまだ存在しなかった v1 設計で意図的なものでした。
| HW_SPI_ENA | SW_SPI_ENA | PP_SPI_ENA | |
|---|---|---|---|
| 必要な PCB | v2.0+ | v2.0+ | v1.x |
| おおよそのバイトレート | ~1µs/バイト | ~30µs/バイト | ~50µs/バイト |
| コード化ラッチが必要 | はい | はい | いいえ |
| 追加 IC | 74HCT595、74HCT165 | なし | なし |
| 適した用途 | すべての現行ビルド | 低コスト v2 バリアント | レガシー v1 ボード |
新しいモニターコマンドの追加
次の例は、指定されたアドレスから 1 バイトを読み取って表示する PEEK コマンドを追加します。ハンドラーはバンク 3(メモリユーティリティ)に属します。
ステップ 1:rfs_bank3.asm にハンドラーを書く
; rfs_bank3.asm(バンク 3、メモリユーティリティ)内:
PEEK: CALL HLHEX ; 入力バッファから 4 桁の 16 進アドレスを HL に解析
LD A,(HL) ; そのアドレスのバイトを読み取る
CALL PRTHX ; A を 2 桁の 16 進数として表示
RET
パラメーターはコマンド文字列の直後のモニター入力バッファに利用可能です。HLHEX は(バンク 5 またはジャンプテーブル経由で利用可能な)ユーティリティルーティンで、入力バッファから 4 桁の 16 進数を読み取り、16 ビット値を HL に返します。PRTHX はアキュムレーターを 2 桁の大文字 16 進数として表示します。
ステップ 2:rfs.asm にコマンドテーブルエントリーを追加する
; rfs.asm 内、CMDTABLE ブロック内(IF BUILD_ROMDISK+BUILD_PICOZ80 = 1 内):
;
; フラグバイト:テーブル終端でない(bit7=0)、完全一致でない(bit6=0)、
; バンク 3(bits5:3 = 011 = 0x18)、長さ 4(bits2:0 = 100 = 0x04)
DB 000H | 000H | 018H | 004H
DB "PEEK"
DW PEEK
同じ先頭文字を共有する短いエントリーが最初に一致しないよう、このエントリーをそれより前に配置します。フラグバイトは次のように構築されます:
000H(テーブル終端でない)OR 000H(完全一致でない)OR 018H(バンク 3:0b011 を左に 3 シフト = 0x18)OR 004H(コマンド文字列の長さ 4)。
ステップ 3:rfs_bank6.asm にヘルプテキストを追加する
; rfs_bank6.asm 内、HELPSCR ブロック内(000H ターミネーターの前):
DB "PEEKXXXX - read byte at XXXX", 00DH
ヘルプ画面は全体を大文字で使用します(小文字文字は、バイト値を手動で計算しないと Sharp 文字エンコーディングに埋め込むことが難しいためです)。
ステップ 4:ビルドする
cd /dvlp/Projects/MZ80A_RFS/software/RFS ./build.sh
バンク 3 が 2KB を超えると、アセンブラーはエラーを報告します。その場合、そのバンクのデッドコード、未使用のメッセージ文字列、または重複したユーティリティルーティンを探して削除するか、バンク 5(現在空)に移動してください。
新しいハードウェアサポートの追加
新しい SPI バリアントの追加
新しい SPI ハードウェアバリアントを追加するには(例えば、別のビット割り当てを持つ第 2 のパラレルポート設計 PP2_SPI_ENA):
- rfs_definitions.asm にフラグを追加します:
PP2_SPI_ENA EQU 0 ; 第 2 のパラレルポート SPI バリアント(カスタムハードウェア)
- rfs_bank2.asm のトップにアサーションを追加して、意図しないデュアル有効化をキャッチします:
; ガード:一度に設定できる SPI フラグは 1 つのみです。 ; GLASS には組み込みの ASSERT ディレクティブがないため、これをビルド時の値チェックとしてエンコードします。 ; 複数のフラグが設定されている場合、合計が 1 を超え、SPI ドライバー関数に ; 誤ったコードがアセンブルされるというエラーとして現れます。 ; (SDINIT の上のコメントブロックにこの制約を明記してください。)
- rfs_bank2.asm の各 SPI 関数に条件アセンブリブロックを追加します(SPIINIT、SPICS、SPIOUT、SPIIN)。既存のネストされた IF/ELSE/ENDIF パターンに従います:
SPIOUT: IF HW_SPI_ENA = 1
; ハードウェア SPI パス(既存コード)
LD (HWSPIDATA),A
LD (HWSPISTART),A
RET
ELSE
IF SW_SPI_ENA = 1
; ソフトウェアビットバンパス(既存コード)
ELSE
IF PP2_SPI_ENA = 1
; 新しい PP2 パス:
; (新しいポートレイアウト用のビットバングをここに実装)
RET
ELSE
; 元の PP_SPI_ENA(Centronics)パス(既存コード)
ENDIF
ENDIF
ENDIF
- rfs_definitions.asm に新しいポート定数を定義し、シンボルの競合を避けるために
IF PP2_SPI_ENA = 1 ... ENDIFで囲みます。 - 新しいバリアントが異なる Flash イメージレイアウトや出力ファイル名を必要とする場合は build.sh を更新します。
RFS を新しいハードウェアプラットフォームに移植するには(例えば、新しい FPGA ベースの MZ-80A 再実装):
- rfs_definitions.asm に BUILD_* フラグを追加します:
BUILD_NEWBOARD EQU 0。 - 新しいボードが ROM ウィンドウを異なるアドレスにマッピングする場合はアドレス定数を追加します。最も一般的なバリエーションはユーザー ROM ベースアドレスとバンク制御レジスターアドレスです。
- ハードウェア動作が異なるすべての点でソース全体に条件アセンブリブロックを追加します:バンクラッチ I/O アドレス、SPI コントローラーレジスター、SD カード存在検出、表示モード切り替え、rfs.asm の MONITOR エントリーポイントプラットフォーム検出コード。
- 新しいプラットフォームのバンク選択メカニズムがコード化ラッチと FusionX ポートスキームの両方と異なる場合は、各バンクファイルに新しいバンク切り替えスタブバリアントを追加します。UROMBSTBL のスタブは、初期化実行前のコールドスタートで正しく動作する必要があります。
- 新しい Flash チップレイアウトに適した ROM イメージを生成する新しいビルドセクションで build.sh を更新します。
デバッグのヒント
デバッグ出力を有効にする: ビルド前に
rfs_definitions.asm の ENADEBUG EQU 1 を設定します。これにより、SD カード初期化シーケンス、SDCMD 応答、SDCFS ディレクトリ解析の戦略的な点に追加の診断プリント文が含まれます。追加コードは条件付きで、無効の場合は RomDisk ROM イメージサイズに影響しません。
ユーザー ROM バンク 0 のエントリーエリアをダンプする: D E800 を入力して現在のユーザー ROM バンクの最初の 320 バイトをダンプします。最初の数バイトは 0xE800 の NOP、次に HWSELROM マクロバイト、次に JP 命令を示すはずです。0xE820 のバンク切り替えスタブには認識可能な PUSH AF / LD A, n シーケンスのパターンが含まれているはずです。ダンプがランダムなデータのように見える場合、コード化ラッチが正しく初期化されておらず、間違ったバンクが選択されている可能性があります。
バンク制御レジスターを確認する: D EFF8 を入力してバンク制御レジスターエリアをダンプします。手動バンク切り替えを実行した後、0xEFFF のバイトが書き込んだバンク番号を反映しているはずです。変更されていない場合、書き込みの前に 16 回読み取りコード化ラッチロック解除シーケンスが実行されているか確認してください。
コード化ラッチロック解除カウントを確認する: バンク制御レジスターへの書き込みが効果がないように見える場合、最も一般的な原因は 16 回の読み取りシーケンスが完了していないことです。これはバンク内のループ命令が通常の実行中に 0xEFF8–0xEFFF から読み取る場合に発生する可能性があります(バンク切り替えセクションの DJNZ 警告を参照)。ロック解除シーケンスの読み取りサイクルをカウントして、ループカウンターが正確に 16 に設定されていることを確認してください。
v2.1 が + RFS プロンプトなしで SA-1510 モニターに起動する: 本体がネイティブ SA-1510 モニターに起動し、RFS の + RFS サインオン行が表示されない場合、0xE800 のユーザー ROM エントリーポイントが呼び出されていません。DRAM リフレッシュサイクルによってコード化ラッチが意図せず起動されていないか確認してください — v2.1 の AND ゲート(D1/D2)は、リフレッシュサイクルが 74HCT191 カウンターをインクリメントするのを防ぐために追加されました。このゲートを持たない v2.0 ボードでは、リフレッシュサイクルが ROM エントリーポイントが実行される前にターミナルカウントに達する可能性があります。
RAM 常駐データを追加した後に MEMTEST を実行する: 新しい RAM 常駐データ構造や変数を追加した直後に R を入力して、アドレス指定のバグを早期にキャッチします。新しい構造のサイズと相関する 0x1200–0xCFFF 範囲内の失敗アドレスは、RAM チップの障害ではなくアドレス計算の 1 つずれエラーを示します。
SD カード初期化の失敗: ENADEBUG が有効な状態で SD コマンドが予期しない応答コードを返す場合、SPI チップセレクトのタイミングが正しいことを確認してください — CS は CMD0 の前にアサート(低)されており、コマンド/応答交換全体を通じて維持されている必要があります。HW_SPI_ENA では BNKCTRL の SDCS ビットが SPICS によって正しく設定および解除されているか確認します。PP_SPI_ENA では、最初の SPIINIT 呼び出しの前にパラレルポート出力レジスターが初期化されているか確認します。
クロスバンクコールの失敗: クロスバンクコールが間違ったコードを実行するか、レジスターの破損を伴って返ってくる場合、ターゲットバンクのバンク切り替えスタブがバンク 0 のものとバイトごとに一致するか確認します。各バンクは UROMBSTBL に同一のスタブのコピーを持つ必要があります。D E820 を使用してバンク 0 のスタブをダンプし、次にターゲットバンクに手動で切り替えて同じアドレス範囲をダンプして比較します。
参考サイト
| リソース | リンク |
|---|---|
| RomDisk ハードウェアページ | /sharpmz-upgrades-romdisk/ |
| RFS プロジェクトページ | /sharpmz-upgrades-rfs/ |
| RFS ユーザーマニュアル | /sharpmz-upgrades-rfs-usermanual/ |
| RFS テクニカルガイド | /sharpmz-upgrades-rfs-technicalguide/ |
| RFS 開発者ガイド(RFS) | /rfs-developersguide/ |
| TZFS 開発者ガイド | /tzfs-developersguide/ |
| tranZPUter FusionX ページ | /tranzputer-fusionx/ |
| GLASS Z80 アセンブラー | software/RFS/tools/glass.jar にバンドル |
| Zilog Z80 CPU ユーザーマニュアル | 標準データシート — バスタイミング、命令セット、レジスターリファレンス |
| WD1773 FDC データシート | Western Digital — フロッピーディスクコントローラー I/O ポートリファレンス |
| SD カード物理層仕様 | SD 協会 — CMD0/CMD8/ACMD41/CMD17/CMD24 プロトコル |
| Sharp MZ-80A サービスマニュアル | ハードウェア回路図、SA-1510 ROM リスティング、メモリマップ |