ドキュメント › SEDORIC
SEDORIC ディスク形式とツール
主要参照:SEDORIC 3.0 マニュアル(sedna3_0.pdf)。A. Chéramy「SEDORIC 3.0 à NU」および SCUMM-Oric / scoop-oric プロジェクトのツールと照合。何も創作していません:以下のオフセットはマニュアルのもので、マニュアル自身が例示する記述子ダンプに対しバイト単位で検証済み。
1. MFM_DISK コンテナ
256 バイトのヘッダ:"MFM_DISK" + sides(u32 LE)+ tracks(u32 LE)+ geometry(u32 LE)。続いて(面, トラック)ごとに 6400 バイトのトラックブロックが SIDE-MAJOR 順で:面 0 の全トラック、次に面 1 の全トラック(ブロック = side * tracks + track)。
各トラックブロック:先頭ギャップ 60×$4E、続いてセクタごとに
12×$00 | A1 A1 A1 FE [trk side sec size] CRC | 22×$4E | 12×$00 | A1 A1 A1 FB [256 data] CRC | 38×$4E、6400 バイトまで $4E で埋め。CRC-16/CCITT(poly $1021、init $FFFF)を 4 マーカーバイト + データに対して。
RAW イメージ(256 バイトセクタを連結、同じ side-major 順、フレーミングなし)は sedoric-info が受理し、oric1-emu --disk-create / tools/sedoric_inject.py が生成します。tools/dsk_raw2mfm.py が RAW → MFM_DISK を変換します。
2. システムセクタ(トラック 20)
| セクタ | 役割 | 主要フィールド |
|---|---|---|
| s1 システム | ディスク名 + autoexec | +9..+29 ディスク名(21 バイト)· +0x1E..+0x59 INIST(60 バイト:ASCII 起動コマンド、: 区切り、#00 終端) |
| s2 VTOC/ビットマップ | カウンタ | +2,+3 空きセクタ(LE)· +4,+5 ファイル数(LE) |
| s4 ディレクトリ | カタログ | +0,+1 次の dir セクタへのリンク(0=終端)· +2 high-water mark · +16 から 16 バイトのエントリ |
ディレクトリエントリ(16 バイト):name[9] ext[3] track sector nsec status(V4 有効ファイル = $40;ビット 7 = 削除)。
注意(Master ディスクで観測):VTOC の free/files カウンタは、より小さい物理イメージに押印された 80 トラックのテンプレートであることがあります — 再計算された状態ではなくテンプレートです。そのため sedoric-info は VTOC カウンタとカタログを実際に辿ったファイル数の両方を報告します。
3. ファイル記述子セクタ
ディレクトリエントリ(track,sector)が指します。マニュアルの実ダンプ(システムファイル BANQUE #7 の記述子、p.16):
0 1 2 3 4 5 6 7 8 9 A B C D E F
00 00 FF 40 00 C4 FF C7 00 00 04 00 05 0B 05 0C 05 0D 05 0E 00 00
| オフセット | フィールド | 例 |
|---|---|---|
+0,+1 | 次の記述子へのリンク(00 00 = なし) | 00 00 |
+2 | 先頭記述子マーカー | FF |
+3 | 種類:b0=AUTO、b6=データブロック、b7=BASIC → $40=ML、$41=AUTO ML | 40 |
+4,+5 | ロードアドレス(LE) | 00 C4 = $C400 |
+6,+7 | 終了アドレス(LE) | FF C7 = $C7FF |
+8,+9 | AUTO 時の実行アドレス(LE) | 00 00 |
+0xA,+0xB | データセクタ数(LE) | 04 00 = 4 |
+0xC.. | データセクタマップ (track,sector)×n、00 00 終端 | 05 0B 05 0C 05 0D 05 0E 00 00 |
このダンプは、+3=0(種類なし)のままセクタ数を +9,+10 に ビッグエンディアンで書いていた(実行アドレスと重複)旧 tap2sedoric 実装を修正します。v1.64.0 以降で修正済み。
連鎖記述子(122 セクタ超のファイル)— 検証済み
記述子セクタはマップの一部のみを含みます:1 番目の記述子はヘッダ(12 バイト)に続いて +0x0C からマップ(最大 122 組、0x0C..0xFE);後続の各記述子はリンク +0,+1 のみ、続いて +0x02 からマップ(最大 127 組)。リンク +0,+1 は次の記述子を指す(00 00 = 最後)。+0xA,+0xB(1 番目の記述子)= データセクタの総数。実機検証済み:150 セクタのファイル(2 記述子)が LOAD で完全に読み込まれます。tap2sedoric と sedoric_inject.py は v1.65.0 以降で連鎖します。
4. ツール
| ツール | 役割 |
|---|---|
tap2sedoric <in.tap> -o out.dsk -b base.dsk [-n NAME.EXT] [-a] [-e EXEC] [-i "INIST"] | CSAVE の .tap を MFM Sedoric ディスクに注入(ファイル + 準拠記述子 + dir エントリ + VTOC;-a/-e AUTO、-i 起動 autoexec) |
sedoric-info <disk.dsk> [--check FREE:FILES] | VTOC、ディスク名、INIST、カタログ、デコードした記述子を検査;--check = カウンタの回帰ガード |
tools/sedoric_inject.py … | RAW 注入(直接オフセット) |
tools/dsk_raw2mfm.py <raw> <out.dsk> … | RAW → MFM_DISK(side-major ブロック) |
典型的な RAW チェーン:oric1-emu --disk-create base.raw(続いて起動時に INIT で本物の VTOC)→ sedoric_inject.py → dsk_raw2mfm.py → oric1-emu --disk-rom microdis.rom -d。
5. マルチファイル注入(制限の解消)
従来、tap2sedoric と sedoric_inject.py は既使用セクタを参照せず常にトラック 21 セクタ 1 から確保していました:同じディスクへの2 回目の注入は 1 回目を上書きしていました。
v1.64.0 以降、両ツールは確保前にカタログ(完全な連鎖)と既存記述子のセクタマップ — 連鎖したカタログセクタ自体を含む — を辿って使用済みセクタを記録します。make test-sedoric-tools で検証。
ディレクトリセクタの連鎖(実装済み)
現在のカタログセクタが満杯(15 エントリ)のとき、ツールはリンク +0,+1 で連鎖を辿ります;連鎖全体が満杯なら、空きセクタを確保し、空のカタログとして初期化して連鎖に追加します。カタログセクタはトラック/セクタのリンクで位置づけられるため、連鎖したカタログは任意の空きセクタに置けます。実機検証済み。
6. Sedoric 下でマシンコードファイルを実行する(実機検証済みレシピ)
エミュレータで読み込み・実行を検証(bare 起動 + LOAD)。遭遇した落とし穴と解決:
| コマンド / ケース | 結果 |
|---|---|
Ready で PROBE(裸の名前)を入力 | ?SYNTAX ERROR — 裸の名前は AUTO の BASIC しか起動しない |
LOADM"PROBE" | ?TYPE MISMATCH — LOADM はカセット ROMのコマンド |
CLOAD"PROBE" | エラーは出ないが何も読み込まない(BASIC ファイル) |
LOAD"PROBE"(.BIN に対して) | ?FILE NOT FOUND — .COM が既定拡張子 |
LOAD"PROBE",J(AUTO に対して) | BREAK ON BYTE #5000 — ,J が AUTO フラグと衝突 |
LOAD"PROBE"(.COM AUTO(種類 $41)に対して) | 読み込んで実行する ✅ |
レシピ:.COM AUTO として注入(tap2sedoric … -n NAME.COM -a -e EXEC)し、Ready で LOAD"NAME"。Sedoric のコマンドは LOAD(種類バイト +3 で BASIC/バイナリを自動判別)、オプション ,A(アドレス)と ,J(ジャンプ)付き。
bare で起動可能な Sedoric マスター(決定論的)
自作 .COM を検証するには、競合アプリなしで Ready まで起動するディスクが必要です。タイミングに依らない堅牢な方法:
tools/sedoric_mkbare.py disks/SEDO40u.DSK bare.dsk # INIST を無効化
tools/sedoric_mkbare.py disks/SEDO40u.DSK auto.dsk 'LOAD"PROBE"' # または自動起動
INIST を無効化(または置換)します(トラック 20 セクタ 1、+0x1E..+0x59、MFM セクタ CRC を再計算;RAW も対応)→ ディスクは裸の SEDORIC V4.0 / Ready に落ちますが起動可能なままです。
マシンコードからファイルを読み込む(実機検証済みレシピ)
実行中の ML プログラム(LOAD で起動)からは Sedoric の RAM オーバーレイがマップされていません:DOS ルーチンを直接呼ぶ($DB2D 検索、$E0EA 読み込み)とクラッシュします。堅牢な方法は 「!」ベクタ $0467(低位 RAM、常にマップ)を経由します。これはオーバーレイに切り替え、TXTPTR($00E9/$00EA)が指す行に対し SEDORIC インタプリタ($D3AE)を実行し、その後元に戻して RTS します。
LDA #<CMD : STA $E9 ; TXTPTR = コマンド行のアドレス
LDA #>CMD : STA $EA
JSR $0467 ; "!" ベクタ:コマンドを実行(オーバーレイ処理込み)
; ... ファイル読み込み済み; 通常どおり継続 ...
RTS
CMD: .byte "LOAD\"SCDATA\"", 0 ; $00 で終端する SEDORIC 行
落とし穴:行は必ず $00 で終端し、CR($0D)では終端しないこと。CR だと $D3AE インタプリタが完了せず RTS しません。TXTPTR は先頭文字(L)を指します。
Sedoric RAM オーバーレイ ↔ BASIC ROM の切替(検証済み)
LOAD で起動した ML プログラムからは、BASIC ROM が $C000-$FFFF にマップされています:システム変数もルーチンもオーバーレイ内にあります → $C000+ にアクセスする前に切り替えます。最も簡単なのは JSR $0477(低位 RAM の Sedoric スタブ)— ドライブ/面/IRQ を $04FB シャドウで保持する ROM↔オーバーレイのトグルです:
PHP:PHA:SEI : LDA $04FB : EOR #$02 : STA $04FB : STA $0314 : PLA:PLP:RTS
$0314 の値:ビット 1(ROMDIS, $02) = 0 → RAM オーバーレイ $C000-$DFFF、= 1 → BASIC ROM;ビット 7(EPROM, $80) = 1 → RAM オーバーレイ $E000-$FFFF。$0314 は書き込み専用のため、$04FB シャドウか $0477 を経由します。
オフセット指定でファイルをセクタ単位に読む(ランダムアクセス)— 検証済み
ファイル全体を読み込まずに、あるオフセットから N バイトを読むには。オーバーレイ ON($0477)が必須。
BUFNOMを埋め +JSR $DB2D(SEARCH)→X = POSNMX、カタログセクタは BUF3。LDA $C30C,X : LDY $C30D,X : JSR $DA5D→ 記述子が BUF1($C100)に読み込まれる。- BUF1 の構成:
$C100/01次記述子リンク ·$C102=FF·$C103種類 ·$C104-05load ·$C106-07end ·$C108-09exec ·$C10A-0Bセクタ数 ·$C10Cからマップ。 sect_index = off/256、byte_in_sect = off & 255。DRIVE$C000、TRACK$C001、SECTOR$C002、RWBUF$C003/$C004を設定。JSR $DA73(XPRSEC)。バッファ + byte_in_sectからNバイトをコピー。
XRWTS/XPRSEC インターフェース(マニュアル、バイト単位):DRIVE $C000、TRACK $C001(b7=面 B)、SECTOR $C002、RWBUF $C003/$C004。$C009 = DRVDEF、$C00A = DRVSYS。
docs/SEDORIC.md から再掲(正となる最新版は GitHub、完全なレシピ付き)。