CP/Mディスクイメージ作成手順メモ
「CP/M on an AVR(avrcpm)」で公開されているディスクイメージはちょっと問題があり、動作テスト程度にしか使えないので作り直した方がよい。さらにディスクサイズが8インチ標準1ドライブでは狭すぎるので拡張する。
完成したソースをアーカイブに添付するほうが簡単だが、CP/Mに関する情報は少なくなってきており、応用が利くようにあえて作業の流れを記載しておく。アスキー出版の「応用CP/M」(1982年)から得られた情報を元にしている。(作業環境OSはWindows)
準備するもの
cpmtools
CP/Mファイルシステムのディスクイメージを作成し、CP/Mファイルの登録、取り出しができる。
http://www.cpm8680.com/cpmtools/
【2013.1.1】 GUI化したものを作成しました。 CpmtoolsGUI こちらも使ってみてください。
CP/Mのシステムバイナリ
CPM.SYS は下記サイトから入手できる。
http://www.cpm.z80.de/binary.html
http://spritesmods.com/?art=avrcpm&page=4
http://www.mikrocontroller.net/articles/AVR_CP/M
システムソースファイル
ipl.asm, bios.asmを下記から入手する。BIOSにシステムのリロードが実装されておりこちらをベースにする。
http://petersieg.bplaced.net/?AVR_CP%2FM の avrcpm_upd.zip
Z80アセンブラ
Win32用Z80アセンブラ(tniasm)は下記から入手。(ソースの終わりに改行を入れておく)
http://www.tni.nl/products/tniasm.html
連結ツール
システムバイナリをddコマンドで連結する。dd.exeは下記から入手。(cpmtoolsに既にあるdllは上書きしない)
「コンピュータ広場 CS」→リンク切れのためコピーを配置→ dd.exe
ディスクイメージをSDカードへ登録するツール
DDforWindows を使う。下記から入手。
http://blog.halpas.com/archives/1258
ディスクの設計
CP/Mは階層ディレクトリを持たないので1ドライブで容量を拡張すると扱いにくくなる。パーティションを分け以下の構成とする。
[128バイト/セクタ]×[64セクタ/トラック]×[244トラック]×4ドライブ
1ドライブ当り約2メガバイト。計8メガバイトとなる。これならば実用上問題ないだろう。
ディスクパラメータの算出
BIOSに設定するディスクパラメータを計算する。
パーティションで分ける場合、トラックは積算となるので各ドライブの諸元はそれぞれ
ドライブ | バイト | セクタ | トラック |
---|---|---|---|
A: | 128 | 64 | 244 |
B: | 128 | 64 | 488 |
C: | 128 | 64 | 732 |
D: | 128 | 64 | 976 |
CP/Mブロックサイズ(BLS)は、DSMが256以上になるので必然的に2048バイト以上となるがAVRのメモリが4KBなので2048バイトしか選択の余地は無い。システムトラックはセクタを64としたので1トラックとしている。
BLS=2048
SPT:64 BSH:4 (2048=128*(2^4)) BLM:15 (0〜15: 2048/128-1=15) EXM:0 (2048:DSM>255) DSM A:{(128*64)*(244-1)/2048} -1=971 DSM B:{(128*64)*(488-244)/2048} -1=975 DSM C:{(128*64)*(732-488)/2048} -1=975 DSM D:{(128*64)*(976-732)/2048} -1=975 DRM:127 (2bit*64-1) AL0:192 (2bit: 0b11000000=192) AL1:0 (0b00000000) CKS:(DRM+1)/4=(127+1)/4=32 OFF A:1 OFF B:244 OFF C:488 OFF D:732 CSV A:32 CSV B:32 CSV C:32 CSV D:32 ALV A:(971+1)/8=122 ALV B:(975+1)/8=122 ALV C:(975+1)/8=122 ALV D:(975+1)/8=122
パラメータ算出方法解説
- SPT(Sector Per Track)
- 1トラック当りのセクタ数
- BSH(Block SHift factor)
- 1ブロックのバイト数(BLS)を128バイト×2の乗数で表す。BLS=128*2^BSH
- BLM(BLock Mask)
- 1ブロック内のセクタ数を0〜 で表す。BLS/128 - 1
- EXM(EXtent Mask)
- 計算式は不明だが表が示されている。
BLS | DSM<256 | DSM>255 |
---|---|---|
1024 | 0 | - |
2048 | 1 | 0 |
4096 | 3 | 1 |
8192 | 7 | 3 |
16384 | 15 | 7 |
推測で、EXM=(BLS/1024/ブロックポインタのサイズ)-1
ブロックポインタは、DSM<256のとき1バイト、DSM>255のとき2バイトになる
1エクステント当り、ブロックポインタ用に16バイトの割り当てゆえに、
1エクステント当りに指示できるバイト数=BLS*16/ブロックポインタのサイズ=1024*(EXM+1)*16
STAT DSK:コマンドで表示されるRecords/Extent =(EXM+1)*128。(1Record=128バイト)
- DSM(Disk Size Max)
- ブロックの最大数 - 1。
- DRM(DiRectory entries Max)
- ディレクトリエントリーの数 - 1。(AL0,AL1のビット1の数)*BLS/32-1
- AL0,AL1
- この2バイトで1ビットを1ブロックとみなしたビットパターンでディレクトリエントリ(=1)を表す
AL0 | AL1 |
---|---|
11000000 | 00000000 |
これから分かることは、
ディレクトリーエントリとして確保できる領域は最大16ブロックまで。
AL0、AL1が意味するものは何か?これも未確認で推測だが、
CP/Mシステムはディスクから一律に16ブロックのディレクトリーエントリ領域を確保する?
AL0、AL1はマップであり、確保した領域のうちビット1の部分を使用する?
空きは、ディレクトリーエントリが物理損傷した場合のリカバリー用ではないか。
→確認してみた。ビットの位置を変更してみたが変化無し。
ディレクトリーエントリ領域はビット分しか確保していなかった。
構想のみで実装しなかったのか?
- CKS(ChecK vector Size)
- (DRM+1)/4。ディレクトリチェック用ワークエリアサイズ。
- OFF(track OFFset)
- システムトラック数。パーティションに分けるときにも利用できる。
- CSV(Check Scratchpad Vector)
- =CKS
- ALV(ALlocation scratchpad Vector)
- (DSM+1)/8。1ビット1ブロックとみなすマップを作り使用済/未使用エリアを管理するためのワークエリア。
なおこれらのパラメータはCP/Mが動作する環境があればDISKDEFマクロによって自動的に算出することもできる。→ DISKDEFマクロの使い方メモ
ソースの修正
ipl.asmの修正
予め43行を
ld a,1 ;execute DMA READ out (22),a
とし、21〜24行を削除しておく。
26行あたり。読み込むセクタ数。修正によって少し増えるので多めにとっておく。
ld b,55 ;
49行あたり。1トラック当りのセクタ数を26から64へ変更
cp 64 ;
bios.asmの修正
予め、76,77行を削除。31〜34行を削除。
32行あたり。システムのセクタ数。44。もとのコード($-ccp)の意味がわからないので修正。
67行あたり。追加。理由は後述。
ld (cdisk),a ld (odisk),a ;add neko Java jp gocpm
101行あたり。ipl同様。1トラック当りのセクタ数を26から64へ変更
cp 64 ;if sector >= 64 then change tracks.
108行あたり。トラック数が256以上(トラックのポインタが2バイト)になるのでbレジスタに正しい値を入れる。
push hl ld b,0 ;add neko Java. call settrk
home:。トラックが2バイト指定になったことによる。
home: push af ld a,0 out (16),a out (17),a ;add neko Java. pop af ret
seldsk:。4ドライブ化。前のカレントドライブをodiskに保持し、不正なドライブを選択したときは前のドライブに戻す。これをやっておかないとエラーメッセージ表示後、リブートの無限ループになる。
seldsk: ;mod for 4drive. neko Java push af ld a,c cp 0 jr nz,seldsk_1 ld hl,dph0 jr seldsk_ok seldsk_1: cp 1 jr nz,seldsk_2 ld hl,dph1 jr seldsk_ok seldsk_2: cp 2 jr nz,seldsk_3 ld hl,dph2 jr seldsk_ok seldsk_3: cp 3 jr nz,seldsk_na ld hl,dph3 seldsk_ok: ld (odisk),a pop af ret seldsk_na: ld hl,0 ld a,(odisk) ld (cdisk),a pop af ret
settrk:。トラックが2バイト指定になったことによる。
settrk: push af ld a,c out (16),a ld a,b ;add neko Java out (17),a ;add neko Java pop af ret
read:、write:。AVRがディスクエラーを返せるので取り込むようにする。
read: ld a,1 out (22),a in a,(23) ;mod neko Java ret write: ld a,2 out (22),a in a,(23) ;mod neko Java ret
ディスクパラメータヘッダ。下記を参考に、以下dph1,dph2,dph3を定義する。
;Disk Parameter Header dph0: dw trans ;XLT: Address of translation table dw 0 ;000: Scratchpad dw 0 ;000: Scratchpad dw 0 ;000: Scratchpad dw dirbuf ;DIRBUF: Address of a dirbuff scratchpad dw dpb0 ;DPB: Address of a disk parameter block dw chk0 ;CSV: Address of scratchpad area for changed disks dw all0 ;ALV: Address of an allocation info scratchpad
ディスクパラメータブロック。下記を参考に、以下dpb1,dpb2,dpb3を定義する。dpb1以降のDSM=975、OFF(積算)に注意。
dpb0: dw 64 ;SPT: sectors per track db 4 ;BSH: data allocation block shift factor db 15 ;BLM: Data Allocation Mask db 0 ;Extent mask dw 971 ;DSM: Disk storage capacity dw 127 ;DRM, no of directory entries db 192 ;AL0 db 0 ;AL1 dw 32 ;CKS, size of dir check vector dw 1 ;OFF, no of reserved tracks
スキューはかけないのでここの記述は意味なし。適当。
trans: db 0
後はdirbuf:(=128)、chk0:〜chk3:(=CSV)、all0:〜all3:(=ALV)のバイト数を算出した値に設定する。
dirbuf: ds 128 chk0: ds 32 . . all0: ds 122 . .
最後に以下を追加。前のカレントドライブ保持用。
odisk: ds 1 ;add neko Java
ファームの修正
z80cpm.hの修正。最後の方。SECT_CNTとBLOCK_SIZEを修正。
/* Disk parameters ----------------------------------------- */ #define SDC_CLST_SIZE 512 // fixed for SDC. #define SECT_SIZE 128 // fixed for CP/M. #define SECT_CNT 64 // CP/M sector size. #define BLOCK_SIZE 2048 // CP/M block size.
z80cpm.cの修正。166行。var_calc()内。トラックのハイバイトが0に固定してあるのでコメント化する。
//Track_no_h = 0; Track_no = ((WORD)Track_no_h << 8) + (WORD)Track_no_l;
アーカイブに添付のMakefileでビルドする。
diskdefsファイルの修正
cpmtoolsのdiskdefsファイルを定義する。同様にcpm_b,cpm_c,cpm_dを定義。それぞれtracksとboottrkは異なる(積算になる)ので注意。
# CP/M ドライブAアクセス用-- diskdef cpm_a seclen 128 tracks 244 sectrk 64 blocksize 2048 maxdir 128 skew 1 boottrk 1 os p2dos end
ディスクイメージを作成する。
以下作業ディレクトリを下記と仮定する
[ツール ] D:\cpmtools [ソース ] D:\cpmtools\z80 [A:ファイル] D:\cpmtools\z80\a [B:ファイル] D:\cpmtools\z80\b [C:ファイル] D:\cpmtools\z80\c [D:ファイル] D:\cpmtools\z80\d
環境設定、作業準備
コマンドプロンプトから、
set CPMTOOLS= set CPMTOOLS=D:\cpmtools set PATH=%CPMTOOLS%;%PATH% d: cd D:\cpmtools\z80
アセンブル
tniasm ipl.asm ipl.bin tniasm bios.asm bios.bin
連結
dd conv=sync bs=128 count=1 if=ipl.bin > cpm.bin dd conv=sync bs=128 count=44 if=CPM.SYS >> cpm.bin dd conv=sync bs=128 count=10 if=bios.bin >> cpm.bin
ディスクイメージ作成
mkfs.cpm -f cpm_d diskimage mkfs.cpm -f cpm_c diskimage mkfs.cpm -f cpm_b diskimage mkfs.cpm -f cpm_a -b cpm.bin -L test diskimage
ファイルコピー(a-dフォルダのファイルをイメージへ)
cpmcp -f cpm_a diskimage ./a/*.* 0: cpmls -f cpm_a diskimage cpmcp -f cpm_b diskimage ./b/*.* 0: cpmls -f cpm_b diskimage cpmcp -f cpm_c diskimage ./c/*.* 0: cpmls -f cpm_c diskimage cpmcp -f cpm_d diskimage ./d/*.* 0: cpmls -f cpm_d diskimage
イメージをSDカードに書き込む
DDforWindows を使う。読出す場合はSDCの容量一杯までやってしまうが途中でESCキーで止めることができる。
イメージからファイルを取り出す場合の例
cpmcp -f cpm_a diskimage 0:*.* コピー先ディレクトリ
AVRとZ80でCP/M へ戻る
CpmtoolsGUI へ
関連サイト
CP/M on an AVR
http://spritesmods.com/?art=avrcpm&page=1
改善版
http://petersieg.bplaced.net/?AVR_CP%2FM ←BIOSのベースにしたのはこちらのサイト。
http://www.mikrocontroller.net/articles/AVR_CP/M
- ($-ccp) の$には現在アドレス位置が入りますから(bios-ccp)と読み替えます-CCP) - samllaCircuit (2011年09月09日 23時32分07秒)
- ご指摘ありがとうございます。アセンブラは詳しくないので。修正不要ということで削除しておきます。 - 管理人 (2011年09月10日 03時12分33秒)
トップ メニュー
This web page is described in Japanese, but you can read in English by translation site.