← ジョン・ドウ レポート
SFORM16 · 技術資料

SFORM16 要求仕様書(SFORM-2 0.07互換方式・spec2)

MSX-DOS2 / MEGA-SCSI用、FAT16マルチパーティション・フォーマッタの完全仕様(0.09a版とは異なり、隠しFAT12領域を持たない、よりシンプルな構成)。この文書だけで sform16_007.py / write_physical_007.py と同等のプログラムを再現できることを目標にまとめている。

1. 全体構成

Sector 0    : パーティション0(FAT16)。同時にMBRを兼ねる。
Sector xxx  : パーティション1(FAT16)。チェーンの基準点。
Sector xxx  : パーティション2以降(FAT16)。拡張チェーン本体。

2. パーティションのパラメータ(現在の実装値。用途に応じて変更可)

項目値
sectors/cluster16 (8KB/cluster)
reserved sectors1
FATs2
root entries512
max clusters環境により変更(例: 4078=約32MB、65501=約512MB)
sectors/FATceil(max_clusters×2/512)
1パーティションの目標セクタ数reserved + FATs×sec/FAT + root_dir_sec + max_clusters×sec/cluster
最小パーティションセクタ数reserved + FATs×sec/FAT + root_dir_sec + 1×sec/cluster

3. ブートセクタのフィールド(全パーティション共通)

offset内容
0x00-0x02ジャンプ命令 EB FE 90
0x03-0x0AOEM名(8byte、任意。例 "SFRM16 ")
0x0B-0x0Cbytes/sector = 512
0x0Dsectors/cluster
0x0E-0x0Freserved sectors = 1
0x10FATs = 2
0x11-0x12root entries
0x13-0x14total sectors(16bit) = 0 (拡張BPB使用のため常にゼロ)
0x15media ID = 0xF0
0x16-0x17sectors/FAT
0x18-0x19sectors/track = 0
0x1A-0x1Bheads = 0
0x1C-0x1Dhidden sectors(2byte) = 0
0x1E-0x1F18 1E (JR命令、+30 → 0x3E = ブートプログラム開始位置へジャンプ)
0x20-0x23総セクタ数(32bit拡張、LE)
0x24物理ドライブ番号 = 0
0x25予約 = 0
0x26拡張ブートシグネチャ = 0x29
0x27-0x2Aボリュームシリアル(4byte、任意値)
0x2B-0x35"NO NAME "(11byte)
0x36-0x3D"FAT16 "(8byte)
0x3E-ブートプログラム(138byte、§6参照)
0x1B8-0x1BBディスクシグネチャ(4byte、任意値)。Sector0のみ。他のパーティションは全ゼロ
0x1BE-0x1CDMBRエントリ1(自分自身)。§4.1参照
0x1CE-0x1DDMBRエントリ2(次のパーティション)。§4.2参照
0x1FE-0x1FFブートシグネチャ 55 AA

MBRエントリの構造(16byte):

+0-3  : status/CHS開始(未使用、常に0)
+4    : パーティション種別(type)
+5-7  : CHS終了(未使用、常に0)
+8-11 : 開始LBA(4byte, LE)
+12-15: サイズ(4byte, LE)

4. MBRエントリの規則

4.1 エントリ1(自分自身、0x1BE-0x1CD)

全パーティション例外無く、以下の固定パターン:

type = 0x06 (FAT16)
開始LBA(0x1C6) = 0  (常に自己相対。絶対LBAを入れてはならない)
サイズ(0x1CA) = 自分自身のセクタ数

Sector0(パーティション0)も例外ではなく、開始LBA=0を使う(=「自分自身」を指す)。

4.2 エントリ2(次のパーティション、0x1CE-0x1DD)

基準点は常にパーティション1の絶対LBA(chain_startと呼ぶ)。

5. FAT・ルートディレクトリ・MEGASCSI.TBL

各パーティションは以下を持つ:

+reserved(1)                     : ブートセクタ
+reserved 〜 +reserved+FATs×sec/FAT-1 : FAT×2本
                                    (各FATの先頭4byteは F0 FF FF FF、残りゼロ)
+その後、root_dir_sec分           : ルートディレクトリ
                                    (先頭32byteにMEGASCSI.TBLのディレクトリ
                                     エントリ。クラスタ2、サイズは§5.1参照。
                                     残りは全ゼロ)
+さらにその後、クラスタ2(1セクタ分書き込めば十分) : MEGASCSI.TBLの実データ
                                    (§5.2参照)

MEGASCSI.PNTは存在しない。

5.1 MEGASCSI.TBLのディレクトリエントリ(32byte)

offset内容
0x00-0x0A"MEGASCSITBL"(11byte、ドット無し8.3形式)
0x0B属性 = 0x27
0x0C-0x190(予約/日時)
0x1A-0x1B先頭クラスタ = 2 (LE)
0x1C-0x1Fファイルサイズ = (パーティション総数)×16 byte (LE)

5.2 MEGASCSI.TBLの実データ(512byte)

16byteレコード×32個。0.09a版(§2.5)と同一形式。

+0    : ドライブ種別(0)
+1    : フラグ(bit6=書込禁止。このspec2では特定パーティションを
        書込禁止にする要件は無いため、通常は0のままで良い)
+2-4  : 開始LBA(3byte, ビッグエンディアン, 絶対値)
+5-7  : サイズ(3byte, ビッグエンディアン)
+8-9  : ブロック長(2byte, ビッグエンディアン) = 512
+10-15: 予約(0)

この実データは全パーティション(パーティション0含む)のクラスタ2に同一内容を複製する。

6. ブートプログラム(138byte)

全パーティションとも offset 0x3E から、以下の同一バイト列を配置する。

d0 ed 53 70 c0 32 7a c0 36 6d 23 36 c0 31 1f f5 11 b4 c0 0e 0f cd 7d f3
b7 20 28 11 00 01 0e 1a cd 7d f3 21 01 00 22 c2 c0 21 00 3f 11 b4 c0 0e
27 cd 7d f3 c3 00 01 6f c0 cd 00 00 79 e6 fe fe 02 20 06 3e 00 b7 ca 22
40 11 8e c0 0e 09 cd 7d f3 0e 07 cd 7d f3 18 b5 42 6f 6f 74 20 65 72 72
6f 72 0d 0a 50 72 65 73 73 20 61 6e 79 20 6b 65 79 20 66 6f 72 20 72 65
74 72 79 0d 0a 24 00 4d 53 58 44 4f 53 20 20 53 59 53

(SFORM-2オリジナルのIPLをそのまま流用。MSXDOS.SYSをロードする処理。)

7. パーティション計画ロジック

def plan_partitions(total_capacity_sectors):
    plan = []
    remain = total_capacity_sectors
    lba = 0
    while remain >= MIN_PART_SECTORS and len(plan) < MAX_PARTITIONS:
        size = min(TARGET_SECTORS, remain)
        plan.append((lba, size))
        lba += size
        remain -= size
    return plan  # plan[0]=パーティション0(Sector0), plan[1:]=以降

8. 0.09a版との主な違い

項目0.09a版0.07互換(spec2)版
隠しFAT12領域あり(Sector0-19)無し
MEGASCSI.PNTあり(隠し領域のみ)無し
パーティション0の実体隠し領域(空き容量ほぼ0)実際に使えるFAT16パーティション
エントリ1の開始LBA全パーティション常に0全パーティション常に0(同じ)
エントリ2の相対基準最初の拡張パーティションパーティション1
Windows接続時の見え方全パーティションが見える全パーティションが見える(★旧仕様ではSector0のエントリ1がパーティション1を指す設計だったため見えなかったが、この修正版では解消)

9. 既知の注意点