Skip to content
dfgordon edited this page Sep 10, 2023 · 5 revisions

CP/M Disks

This addresses some features that pertain specifically to CP/M disks.

CP/M Subcommand Aliases

You can use:

  • dir in place of catalog
  • era in place of delete

Disk Formats

The nature of CP/M is that each vendor's format has to be supported specially. The kinds of CP/M disks that can be operated on at the file system level, as of this writing, are as follows:

  • Apple 5.25 inch 140K (DSK or WOZ)
  • Amstrad 3 inch 184K SSDD (IMD or TD0)
  • Osborne 5.25 inch 100K SSSD (IMD or TD0)
  • Osborne 5.25 inch 200K SSDD (IMD or TD0)
  • Kaypro 5.25 inch 200K SSDD (IMD or TD0)
  • Kaypro 5.25 inch 400K DSDD (IMD or TD0)
  • Standard 8 inch 250K SSSD (IMD or TD0)
  • TRS-80-M2 8 inch 600K SSDD (IMD or TD0)
  • Nabu 8 inch 1M DSDD (IMD or TD0)

As usual, any supported disk image can be operated on at the sector level, even if the file system is not understood.

User Number

CP/M disks support up to 16 users, each with their own files. Two different users can own two distinct files with the same name. In order to specify a user number during file operations, prepend the file name with <n>: where <n> is the user number. For example, if user 9 owns a file called ITEMS.TXT you could display it with

a2kit get -f 9:items.txt -t txt -d cpmdisk.woz

If the user number is omitted, user 0 is assumed. Most CP/M floppies will have only user 0.

You can use a2kit dir to list files by user, see below.

File Image Metadata

Let us examine the file image for the TYPE.CMD program found on a CP/M v1 disk:

{
    "fimg_version": "2.0.0",
    "file_system": "cpm",
    "chunk_len": 1024,
    "eof": "80070000",
    "fs_type": "434D44",
    "aux": "",
    "access": "5459504520202020434D44",
    "created": "",
    "modified": "",
    "version": "",
    "min_version": "",
    "chunks": {
        "0": "014D0000004D0000000220000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000EB4B90EB7690434F505952494748542028432920313938332C204449474954414C2052455345415243482020434F4E43555252454E542043502F4D2D383620322E302C2030332F33312F3833209C58FA8CD98ED18D265401509DE9B002558BEC8B56048B4E06CDE0A30001891E0201890E0401891606015DC2040090909090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000558BECB00150B8000050E850FF5DC3558BECB002508A4604B40050E83FFF5DC20200558BECB00650B8FD0050E82EFF5DC3558BECB00950FF7604E820FF5DC20200558BECB00B50B8000050E80FFF5DC3558BECB00C50B8000050E800FF5DC3558BECB00B50B8000050E8F1FE5DC3558BECB00F50FF7604E8E3FE5DC20200558BECB01050FF7604E8D3FE5DC20200558BECB01450FF7604E8C3FE5DC20200558BECB01A50FF7604E8B3FE5DC20200558BECB02D508A4604B40050E8A0FE5DC20200558BECB08F50B8000050E88FFE5DC3558BECB09850B8080150E880FEA10001A30C01A10401A30E01833E0C01FF7543B8540150E83AFF833E0E01177505B86501EB22833E0E01187505B86E01EB16833E0E01197505B87A01EB0A833E0E01267507B8860150E808FFB8920150E801FFE88EFF5DC3558BECB00D50E8D1FEB00A50E8CBFE5DC3558BEC8A4604FEC88846043CFF740D8A46068B5E088807FF4608EBE75DC20600558BECE8B6FEA214013C61720E803E14017B7307A014012C205DC3A014015DC3558BECE8A9FFE8A6FFB8960150E89BFEB86C0050B02050B00850E8A3FFC606150100803E1501077756E8B4FFA216013C20720DA016018A1E1501B70088876C00803E16010D7438803E16011874C2803E160108751A803E15010172B4A01501FEC8A21501B40089C3C6876C0020EBBA803E1601037503E8C2FEFE06150175A3E839FEA216015DC3558BECE83DFEA31001A110013C307209A1100188E0A8FD7510B8A20150E804FEB000B4005050E827FDC6061B0100C6061A0100803E6D0050752C803E6E00207407803E6E00417507C6061A0118EB17A06E002C30B10AF6E18A0E6F0080E930B50003C1A21A01C70608018100C7060A015C00E8",
        "1": "4EFEC606180101803E18010B77208A1E1801B70080BF5C003F750DB8BE0150E88FFDE890FEE819FEFE06180175D9B0FE50E8FAFDB86C0050E8E3FD800E620080B85C0050E8A7FDA31201A112013CFF754FA1120188E008C0750CB8D40150E850FDE8DDFDEB3AA1120188E03C07751EE894FEE840FEB86C0050E8A2FD800E620080B85C0050E866FDA31201EB13A1120188E03C04750AE81CFEB8E40150E811FDA112013CFF7503E99400B00050E87EFDB8800050E867FDC6067C0000C6061701008A0E1701F6D151B85C0050E83FFD08C0B0FF7401405922C1D0D87361C606180100803E18017F77D88A1E1801B7008A878000A219013C1A7505C6061701FFA01701F6D0D0D8732E823E1A01007420803E19010A7519A01B01FEC0A21B013A061A01750BE859FCA21B01C6061B0100FF361901E859FCFE06180175A6EB83E800FD5DC30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000496E76616C69642046696C657370656324202864726976652924202866696C656E616D652924202866696C65747970652924202870617373776F726429242E0D0A2450617373776F7264203F2024526571756972657320436F6E63757272656E742043502F4D2D3836244E6F2077696C64636172647320616C6C6F7765642E2446696C65206E6F7420666F756E642E24496E76616C69642046696C65737065632E2400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5"
    }
}

The file image is using three metadata fields: eof, fs_type, and access. Because of the way the CP/M directory works, all of these need some explanation:

  • eof field - this is the length of the data as a little endian unsigned integer. For CP/M this is usually padded to the nearest 128-byte record boundary. The way this information is stored in the CP/M directory, however, is not straightforward, so this is a case where the metadata field is not in direct correspondence with what is stored on disk. The file system interpreter has to do some work to translate.

  • fs_type field - CP/M filenames are in the form <base>.<extension>, where the <base> is up to 8 characters and <extension> is up to 3 characters. The extension is interpreted as a file type. So what is stored in fs_type is simply <extension>. It is stored exactly the way it is stored in the CP/M directory, i.e., padded with spaces, and with the high bits dependent on other file properties.

  • access field - In CP/M v2, access flags are stored in the high bits of the filename extension. Some variants also encode information in the high bits of the base name. Therefore the access metadata is best represented by a direct copy of the filename and extension exactly as they occur in the directory. This includes padding and high bits. In the case shown above, we have a CP/M v1 file, so none of the flags are set.

As of this writing the file image does not include timestamps, but this may change in the future.

Disk Directory

Using a2kit dir on a CP/M disk will perform something like DIR for user 0. Unlike the CP/M DIR, this will show hidden files (in dimmed text) and will highlight read-only files in red. This will also display the label information if it exists.

You can use the -f option to specify CP/M wildcards and command tails. For example,

a2kit dir -d cpm.dsk -f *.com[full]

will list all the COM files in long format. The supported command tails are

  • att - show user attributes
  • dir - show directory files
  • exclude - do not show files matching the wildcard pattern
  • full - display the long directory listing
  • nosort - do not sort alphabetically
  • ro - show read only files
  • rw - show read/write files
  • size - show file sizes
  • sys - show system files
  • user - show the given users

The syntax is the same as CP/M 3. For example, to list files of users 0, 3, and 5:

a2kit dir -d cpm.dsk -f [user=(0,3,5)]

Please note that, depending on the shell, you may need to quote or escape the command tail.

Retype and Rename

The a2kit retype command works a bit differently on CP/M. Changing the type in the sense of the filename extension can be done with rename. What retype does is allow you to switch between hidden (system) and non-hidden (directory) files. It works the same as the usual retype, except the only types are sys and dir.

CP/M File Types

When working with CP/M files, you will probably be using txt, bin, or any. As usual, the any type is the most fool-proof for copying or archiving a file. Regarding bin, CP/M has no concept of a variable load address, so just specify an arbitrary one (e.g. 0). You can also use raw, but remember to get using --trunc if you want to keep the EOF (such as it is in CP/M).

As of this writing, a2kit does not comprehend Microsoft BASIC, which is the version of BASIC most likely to be found on a CP/M disk. For BASIC programs that are not tokenized, you can get them as txt. If they are tokenized you can get them as bin or any (no data is lost, it just won't be readable).

Random access text files can be copied or archived using any, but the rec type, which would allow them to be viewed and copied to other file systems, is not yet supported.