cpmfs is a tool for copying files in and out of CP/M disk images.
It allows you to copy any files you like from Windows onto a “disk” for an emulator or simulator. This also means you can copy files off old diskimage files and put them, in whatever combination you need, on new blank “disks”.
Version 0.03 supports a lot more disk formats. The list (from the program) is:
C:>cpmfs types CP/M File System Utility Ver 0.03 Copyright 2017 Greg Sydney-Smith Supported imagefile types are: Type : Description --------------------------------------------------------------- 8SSSD : 77Tk 1Hd 26sec128 skew06 1K 64Dir1 8DSSD : 77Tk 2Hd 26sec128 skew06 1K 64Dir1 8SSDD : 77Tk 1Hd 16sec512 skew11 2K 128Dir1 (SD T0H0) 8SSDD2 : 77Tk 1Hd 16sec512 skew11 2K 128Dir2 (SD T0H0) 8DSDD : 77Tk 2Hd 16sec512 skew04 2K 256Dir2 (SD T0H0) 5SSSD : 40Tk 1Hd 18sec128 skew05 1K 64Dir1 5DSDD : 40Tk 2Hd 10sec512 skew04 2K 128Dir1 (SD T0H0) 8 : 77Tk 1Hd 26sec128 skew06 1K 64Dir1 (shortcut) 5 : 40Tk 1Hd 18sec128 skew05 1K 64Dir1 (shortcut) Use "cpmfs -t (type) info" for more detail. C:>
That’s quite a few floppy disk types that you can read. As an example of the more detail option, here’s the 8 inch double-sided double-density floppy disk format supported:
C:>cpmfs -t 8DSDD info Name : 8DSDD Description : 77Tk 2Hd 16sec512 skew04 2K 256Dir2 (SD T0H0) Image size : 9818 records (1256704 bytes) System area size : 90 records Data area size : 9728 records Block size : 16 records (2K) Dir size : 64 records (4 blocks, 256 entries) Dir type : 2 (2 byte block numbers) Tracks : 77 Heads : 2 Reserved tracks : 2 (track*head) Records per sector: 4 (sector size 512 bytes) Sectors per track : 16 Skew table : 1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16 C:>
Of interest, this is far from the standard 8 inch single sided single density image that is fairly easy to support. Disk blocks (or Cromemco “clusters”) are 2K in size; rather than the usual 1K. There are 256 directory entries; which is unusual when compared to smaller disk capacities. It even has two byte block numbers. Originally, I suspect, those were an idea for when hard disks came around. Just about every thing you’ll see for CP/M disk formats will talk about 16 entries in the File Control Block (FCB) and 1K block sizes. Block numbers run from 00 to FF. They are a single byte and there’s room for 16 of them in each FCB extent…
Well, this one has two byte block numbers. It’s a big disk. DSDD with 77 tracks gives you about 1.2M on a disk. That was unthinkably large at the time. Even hard disks, when they arived, only stored about 10M of data. The point here is 9728 records and 2K blocks (16 records per block) is 608 blocks. Those sorts of block numbers are never going to fit in a single byte.
Anyway, the updated cpmfs program allows you to copy files to and from those style disks too.
It has the standard options:
C:>cpmfs CP/M File System Utility Ver 0.03 Copyright 2017 Greg Sydney-Smith Usage: cpmfs [-d dbg] [-t type] imagefile cmd [fn1 [fn2]] cmd: dir : list cpm files in imagefile era fn1 : erase cpm file fn1 r fn1 [fn2] : read cpm fn1 -> win fn2 w fn1 [fn2] : write cpm fn1 <- win fn2 dbg: use 1 for block info, 2 for track, sector, disk addr Default fn2 is same name as fn1. Default type is worked out from the imagefile size. Use "cpmfs types" for a list of supported types. Use "cpmfs adv" for advanced commands. C:>
These allow you to see what is on a disk (dir), read files from the disk (r), write files onto the disk (w), and to delete (“erase” in CP/M terms) files off the disk (era).
You can see a “dir” in the picture above. The read looks pretty simple:
This next one shows a sequence of copying a file onto the disk image, reading it back and comparing it, erasing the file from the image, and then trying to read the erased file:
Version 0.03 also has some advanced commands that let you examine what’s on a “disk” in more detail, create new ones, format existing ones, and copy all or parts of the system image to and from your Windows file system. The advanced options look like:
C:>cpmfs adv CP/M File System Utility Ver 0.03 Copyright 2017 Greg Sydney-Smith Usage: cpmfs [-d dbg] [-t type] imagefile cmd [fn1 [fn2]] cmd: make : create imagefile init : reset imagefile to empty info : show auto/selected imagefile format dir2 : list cpm files in raw FCB format used : show block allocations rsys fn1 : read system tracks -> win fn1 wsys fn1 : write system tracks <- win fn1 rr start len fn1 : read system records -> win fn1 wr start len fn1 : write system records <- win fn1 (boot= 0 1, bios varies) C:>
The cpmfs dir2 command produces output like this:
C:>cpmfs drivea.dsk dir2 00 43 52 4F 42 49 4F 53 20 41 53 4D 00 00 00 7C .CROBIOS ASM...| 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 ................ 00 43 52 4F 42 4F 4F 54 20 41 53 4D 00 31 00 0C .CROBOOT ASM.1.. 12 13 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 43 52 4F 42 4F 4F 54 20 50 52 4E 00 00 00 17 .CROBOOT PRN.... 14 15 16 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 43 52 4F 42 4F 4F 54 20 48 45 58 00 00 00 03 .CROBOOT HEX.... 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 43 52 4F 42 4F 4F 54 20 53 59 4D 00 00 00 03 .CROBOOT SYM.... 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 43 52 4F 42 49 4F 53 20 50 52 4E 00 00 00 80 .CROBIOS PRN.... 19 1A 1B 1C 1F 20 21 22 23 24 26 27 28 29 2A 2B ..... !"#$&'()*+ 00 43 52 4F 42 49 4F 53 20 48 45 58 00 00 00 14 .CROBIOS HEX.... 25 2E 36 00 00 00 00 00 00 00 00 00 00 00 00 00 %.6............. 00 43 52 4F 42 49 4F 53 20 50 52 4E 01 00 00 62 .CROBIOS PRN...b 2C 2D 2F 30 31 32 33 34 35 37 38 39 3C 00 00 00 ,-/012345789<... ... C:>
It understands the Cromemco CDOS label so, whilst it doesn’t adapt its behaviour according to it, it will provide information from it. Here’s a disk with a CDOS label:
C:>cpmfs itc-cpm.dsk dir2 Disk label : Userdisk Date on disk : 2000-00-00 Cluster size : 2K Directory type : 2 byte block numbers Directory size : 256 entries 81 55 73 65 72 64 69 73 6B 00 00 00 10 80 00 40 .Userdisk......@ 00 00 01 00 02 00 03 00 00 00 00 00 00 00 00 00 ................ 00 41 53 4D 20 20 20 20 20 43 4F 4D 00 00 00 40 .ASM COM...@ 04 00 05 00 06 00 07 00 00 00 00 00 00 00 00 00 ................ 00 43 42 49 4F 53 20 20 20 41 53 4D 00 00 00 17 .CBIOS ASM.... 08 00 09 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 43 44 4F 53 43 50 4D 20 43 4F 4D 00 00 00 0B .CDOSCPM COM.... 0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 43 44 4F 53 43 50 4D 20 48 4C 50 00 00 00 14 .CDOSCPM HLP.... 0B 00 0C 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 43 4F 4D 48 45 58 20 20 43 4F 4D 00 00 00 06 .COMHEX COM.... 0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ ...
You can see that the label flags the directory entries as having two byte block numbers. Had there been a date, you’d see when it was created (or maybe updated).
You may have noticed that cpmfs is automatically choosing the correct format as I choose different disk image files. It does this from the size of the disk. Double-sided ones will be larger than single-sided ones and double density also changes the sizes. Cpmfs copes with CDOS style disks that have different formatting on track 0 compared to the rest of the disk. This also affects the size of the image and so cpmfs can detect whether it is in this format or not.
You can override the choice if you want or need to. For example, there are two 8″ SSDD format choices. They are identical except for the use of two byte block numbers. The capacity of the disk exceeds what’s accessible with one byte values. You’d think that this would / should be the trigger to automatically go to two byte versions. But it doesn’t. Unless there is a CDOS label on the disk telling it to use 2, it stubbornly sticks with one. Cpmfs can cater for either case. Read the label if any (dir2) and then choose whichever applies to the disk you’ve got.
The debugging options can help you understand what’s where on the disk. Here’s debug level 1:
C:>cpmfs -d 1 itc-cpm.dsk r usq.h Read block 0000 Read block 0001 Read block 0002 Read block 0003 Read block 00F7 OK. C:>
Blocks 0, 1, 2 and 3 are the directory (for this disk format). It needs to read that to find where the file is stored. Then it discovers it’s at block 00F7 and so it copies it from there.
Here’s the same with level 2:
C:>cpmfs -d 2 itc-cpm.dsk r usq.h Read block 0000 Read record 0 (track 1, head 0, sector 1 ( 1), address 002D00) Read record 1 (track 1, head 0, sector 1 ( 1), address 002D80) Read record 2 (track 1, head 0, sector 1 ( 1), address 002E00) Read record 3 (track 1, head 0, sector 1 ( 1), address 002E80) Read record 4 (track 1, head 0, sector 2 ( 5), address 003500) Read record 5 (track 1, head 0, sector 2 ( 5), address 003580) Read record 6 (track 1, head 0, sector 2 ( 5), address 003600) Read record 7 (track 1, head 0, sector 2 ( 5), address 003680) Read record 8 (track 1, head 0, sector 3 ( 9), address 003D00) Read record 9 (track 1, head 0, sector 3 ( 9), address 003D80) Read record 10 (track 1, head 0, sector 3 ( 9), address 003E00) Read record 11 (track 1, head 0, sector 3 ( 9), address 003E80) Read record 12 (track 1, head 0, sector 4 (13), address 004500) Read record 13 (track 1, head 0, sector 4 (13), address 004580) Read record 14 (track 1, head 0, sector 4 (13), address 004600) Read record 15 (track 1, head 0, sector 4 (13), address 004680) Read block 0001 Read record 16 (track 1, head 0, sector 5 ( 2), address 002F00) ... Read block 00F7 Read record 3952 (track 31, head 1, sector 13 ( 4), address 07D300) Read record 3953 (track 31, head 1, sector 13 ( 4), address 07D380) Read record 3954 (track 31, head 1, sector 13 ( 4), address 07D400) Read record 3955 (track 31, head 1, sector 13 ( 4), address 07D480) Read record 3956 (track 31, head 1, sector 14 ( 8), address 07DB00) Read record 3957 (track 31, head 1, sector 14 ( 8), address 07DB80) Read record 3958 (track 31, head 1, sector 14 ( 8), address 07DC00) Read record 3959 (track 31, head 1, sector 14 ( 8), address 07DC80) Read record 3960 (track 31, head 1, sector 15 (12), address 07E300) Read record 3961 (track 31, head 1, sector 15 (12), address 07E380) Read record 3962 (track 31, head 1, sector 15 (12), address 07E400) Read record 3963 (track 31, head 1, sector 15 (12), address 07E480) Read record 3964 (track 31, head 1, sector 16 (16), address 07EB00) Read record 3965 (track 31, head 1, sector 16 (16), address 07EB80) Read record 3966 (track 31, head 1, sector 16 (16), address 07EC00) Read record 3967 (track 31, head 1, sector 16 (16), address 07EC80) OK. C:>
You can see which track would be selected, which head would be active, and which sector it is reading from the track. Both the logical sector number (unskewed) and the actual, physical, sector that it reads; are shown. You can see the logical progression of the read and where it actually goes to on the disk. Also present is the address within the disk image file. This can be helpful if you’re checking / looking for / making changes to the disk image with a binary / hexadecimal editor.
I hope it is useful for you. I’m certainly going to use it.
You can download it from cpm/cpmfs/cpmfs-0.03.exe.
As it’s open source software, you can also download the source code cpm/cpmfs/cpmfs-0.03.c. I built the “.exe” with gcc in MinGW on Windows 8.1.
This is part of the CP/M topic.