Crate a2kit

Source
Expand description

§a2kit main library

This library manipulates disk images suitable for emulators, with emphasis on Apple II. Manipulations can be done at a level as low as track bits, or as high as language files.

§Architecture

Disk image operations are built around three trait objects:

  • img::DiskImage encodes/decodes disk tracks, does not try to interpret a file system
  • fs::DiskFS imposes a file system on the already decoded track data
    • don’t confuse std::fs and a2kit::fs
  • fs::FileImage provides a representation of a file that can be restored to a disk image

When a DiskFS object is created it takes ownership of some DiskImage. It then uses this owned image as storage. Any changes are not permanent until the image is saved to whatever file system is hosting a2kit.

§Language Services

Language modules are designed to be complementary to the needs of language servers that use the language server protocol (LSP). Specific language services are in modules named after the language, at present:

  • lang::applesoft handles Applesoft BASIC
  • lang::integer handles Integer BASIC
  • lang::merlin handles Merlin assembly language

The language servers are in bin and compile to separate executables. The language servers and CLI both depend on lang, but do not depend on each other.

§File Systems

In order to manipulate files, a2kit must understand the file system it finds on the disk image. As of this writing a2kit supports

  • CP/M 1,2,3
  • Apple DOS 3.x
  • FAT (e.g. MS-DOS)
  • ProDOS
  • Pascal File System

A simple example follows:

// DiskFS is always mutable because the underlying image can be stateful.
let mut disk = a2kit::create_fs_from_file("disk.woz")?;
// Get a text file from the disk image as a String.
let text = disk.read_text("README")?;

§Disk Images

In order to manipulate tracks and sectors, a2kit must understand the way the track data is packed into a disk image. As of this writing a2kit supports

formatplatformsaliases
2MGApple II
D13Apple II
DOApple IIDSK
POApple IIDSK
IMDCP/M, FAT
IMGFATDSK, IMA
NIBApple II
TD0CP/M, FAT
WOZApple II

A simple example follows:

// DiskImage can be stateful and therefore is always mutable
let mut img = a2kit::create_img_from_file("disk.woz")?;
// Unlike DiskFS, we cannot access files, only tracks and sectors
let sector_data = img.read_sector(0,0,0)?;
// Disk images are *always* buffered, so writing only affects memory
img.write_sector(0,0,1,&sector_data)?;
// Save the changes to local storage
a2kit::save_img(&mut img,"disk.woz")?;

§Disk Kinds

A disk image can typically represent some number of disk kinds (defined by mechanical and encoding characteristics). The kinds a2kit supports include

  • Logical ProDOS volumes
  • 3 inch CP/M formats (Amstrad 184K)
  • 3.5 inch Apple formats (400K/800K)
  • 3.5 inch IBM formats(720K through 2880K)
  • 5.25 inch Apple formats (114K/140K)
  • 5.25 inch IBM formats (160K through 1200K)
  • 5.25 inch CP/M formats (Osborne 100K/200K, Kaypro 200K/400K)
  • 8 inch CP/M formats (IBM 250K, Nabu 1M, TRS-80 600K)

Modules§

Macros§

  • Get a byte value from the image into a JSON object as a hex string.
  • Get a byte value from the image into a JSON object, adding the _raw terminus. The _pretty terminus has to be added by hand.
  • get a multi-byte value from the image into a JSON object as hex string
  • Get a multi-byte value from the image into a JSON object, adding the _raw terminus. The _pretty terminus has to be added by hand.
  • Parse a hex string containing one byte and put value into the image using the given key path.
  • Parse a hex string containing multiple bytes and put value into the image using the given key path.
  • Put a variable length UTF8 string into the image using the given key path.
  • Put a fixed length UTF8 string into the image using the given key path.

Structs§

Functions§

  • Given a bytestream return a DiskFS, or Err if the bytestream cannot be interpreted. Optional maybe_ext restricts the image types that will be tried based on file extension.
  • Calls create_fs_from_bytestream getting the bytes from a file. The pathname must already be in the right format for the file system. File extension will be used to restrict image types that are tried, unless the extension is unknown, in which case all will be tried.
  • Calls create_fs_from_bytestream getting the bytes from stdin. All image types and file systems will be tried heuristically.
  • Given a bytestream return a disk image without any file system. Optional maybe_ext restricts the image types that will be tried based on file extension. N.b. the ordering for DSK types cannot always be determined without the file system.
  • Calls create_img_from_bytestream getting the bytes from a file. The pathname must already be in the right format for the file system. File extension will be used to restrict image types that are tried, unless the extension is unknown, in which case all will be tried.
  • Calls create_img_from_bytestream getting the bytes from stdin. All image types will be tried heuristically.
  • Display binary to stdout in columns of hex, +ascii, and -ascii
  • This takes any bytes and makes an ascii friendly string by using hex escapes, e.g., \xFF. if escape_cc is true, ascii control characters are also escaped. if inverted is true, assume we have negative ascii bytes. This is intended for directory strings, for language files use lang::bytes_to_escaped_string
  • Calls parse_escaped_ascii with caps=true
  • Interpret a UTF8 string as pure ascii and put into bytes. Non-ascii characters are omitted from the result, but arbitrary bytes can be introduced using escapes, e.g., \xFF. Literal hex escapes are created by coding the backslash, e.g., \x5CxFF. if inverted is true the sign of the non-escaped bytes is flipped. if caps is true the ascii is put in upper case. This is suitable for either languages or directory strings.
  • Save the image file (make changes permanent)