1. 全体構成
Sector 0 : パーティション0(FAT16)。同時にMBRを兼ねる。 Sector xxx : パーティション1(FAT16)。チェーンの基準点。 Sector xxx : パーティション2以降(FAT16)。拡張チェーン本体。
- 隠し領域・MEGASCSI.PNTは存在しない。Sector0自身がそのまま使える実パーティション(パーティション0)である。
- 全パーティションが均等にFAT16。
- パーティション総数の上限は32個(MEGASCSI.TBLのレコード数制約)。実運用の上限は
MAX_PARTITIONSで別途設定(例: 16個、ファームウェアのドライブ登録テーブル上限に合わせる)。
2. パーティションのパラメータ(現在の実装値。用途に応じて変更可)
| 項目 | 値 |
|---|---|
| sectors/cluster | 16 (8KB/cluster) |
| reserved sectors | 1 |
| FATs | 2 |
| root entries | 512 |
| max clusters | 環境により変更(例: 4078=約32MB、65501=約512MB) |
| sectors/FAT | ceil(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-0x0A | OEM名(8byte、任意。例 "SFRM16 ") |
| 0x0B-0x0C | bytes/sector = 512 |
| 0x0D | sectors/cluster |
| 0x0E-0x0F | reserved sectors = 1 |
| 0x10 | FATs = 2 |
| 0x11-0x12 | root entries |
| 0x13-0x14 | total sectors(16bit) = 0 (拡張BPB使用のため常にゼロ) |
| 0x15 | media ID = 0xF0 |
| 0x16-0x17 | sectors/FAT |
| 0x18-0x19 | sectors/track = 0 |
| 0x1A-0x1B | heads = 0 |
| 0x1C-0x1D | hidden sectors(2byte) = 0 |
| 0x1E-0x1F | 18 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-0x1CD | MBRエントリ1(自分自身)。§4.1参照 |
| 0x1CE-0x1DD | MBRエントリ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と呼ぶ)。
- パーティション0: 次(パーティション1)が存在すれば
type=0x05, 開始LBA=chain_start(絶対値), サイズ=0。パーティションが1個しか無い場合は全ゼロ(type=0x00含む)。 - パーティション1以降(最後以外):
type=0x05, 開始LBA=(次パーティションの絶対LBA − chain_start), サイズ=0(=パーティション1からの相対LBA。直前のパーティションからの相対ではない点に注意)。 - 最後のパーティション: エントリ2は全ゼロ(type=0x00含む)。
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-0x19 | 0(予約/日時) |
| 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 = パーティション0(Sector0)、以降レコードNがパーティションN (隠し領域が無いため、0.09a版のような「1つずれる」ことはない)。
- 実パーティション数を N とすると、レコード N は終端マーカー(開始=デバイス総容量, サイズ=0xFFFFFF, ブロック長=0,予約=
00 00 FF FF FF FF)を1つだけ置く。 - レコード (N+1) 以降、テーブル末尾(512byte)まで
00 00 00 00 FF FF FF FFを8byte単位で繰り返して埋める。
この実データは全パーティション(パーティション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. 既知の注意点
- CP-004.COM(CP.COMへのパッチ版)には、特定条件下でパーティション番号→ファームウェアレコードの対応にオフバイワンのバグが確認されている。原因はCP-004.COM側の実装であり、本仕様のデータ構造の問題ではない。
CP.COM(パッチ無し版)は、MEGASCSI.TBLに正しいサイズ情報がある限り問題なく動作することを確認済み。 - メディアIDは全セクタを通して統一して 0xF0 を使うこと。