Skip to content

Metadata

dfgordon edited this page Jan 15, 2024 · 3 revisions

Metadata Access

This deals with facilities for manipulating disk image metadata.

If you are looking for metadata pertaining to track layout or file system structure, see also LowLevel.

Disk Image Metadata

Some disk images are merely raw dumps of tracks, sectors, or blocks, in which case there is no metadata. Examples include DSK and NIB. Others wrap this data in a structure. Examples include 2MG, IMD, and WOZ. Some of the metadata in this structure is exposed with full read/write access, some is read only, and some is not exposed at all.

General Interface

The interface is most convenient for scripted operations. All disk image metadata is referenced using a tree structure. The tree is represented as a JSON object. For example, the following tree contains two leaf keys:

space_attack.json

{
    "2mg": {
        "creator_info": "a2kit v2.2.0 :: Script v1.0.0",
        "comment": "Space Attack, by John Doe"
    }
}

The root key always gives the type of disk image. You can save this metadata into a disk image with matching type using, e.g.,

a2kit get -f space_attack.json | a2kit put -d space_attack.2mg -t meta

To retrieve an image's metadata, use, e.g.,

a2kit get -d space_attack.2mg -t meta

This will also be in the form of a JSON string, and will contain all the keys that exist in the file (see below for how to use narrowing filters). Some images, like 2MG, support only a fixed set of metadata keys. If you try to put one that doesn't exist a2kit will return an error. Others, like WOZ, allow you to invent your own. If you put a non-standard key, there will be a warning, as a guard against typos.

Direct Entry

You can put the metadata directly, although the notation can get unwieldy. Details depend on the shell. As an example

'{"2mg": {"comment": "Space Attack, by John Doe"}}' | a2kit put -d space_attack.2mg -t meta

works for PowerShell.

Tree Structure

Each disk image type has a specific, fixed, tree structure. For example, WOZ images have info and meta branches:

{
    "woz2": {
        "info": {
            "creator": "a2kit v2.2.0 :: Script v1.0.0"
        },
        "meta": {
            "title": "Space Attack",
            "developer": "John Doe"
        }
    }
}

These branches correspond exactly to the INFO and META chunks that are part of the WOZ specification. The values in the META chunk must not contain tabs or line feeds, and | is always interpreted as a value separator.

Sometimes path notation is used to refer to a specific leaf or branch, e.g., /woz2/info/creator is a leaf, and /woz2/meta/ is a branch. See below for the full structure of the various types.

Binary Metadata and Hex Strings

Disk image metadata is often stored in binary form. The JSON for this data will be in the form of a hex string. The byte order is the same as what the disk image uses internally. For example

{
    "woz2": {
        "info": {
            "write_protected": "00",
            "largest_track": "0d00"
        }
    }
}

Notice the hex does not require, and must not have, any prefix like $ or 0x. When using a2kit put, the hex value must match to one of the allowed values for the given key, or an error is returned. The hex must be padded with leading zeros out to the appropriate length for the metadata.

Raw and Pretty Keys

When using a2kit get, some values will be broken out into the special keys _raw and _pretty. For example,

{
    "woz2": {
        "info": {
            "boot_sector_format": {
                "_raw": "01",
                "_pretty": "Boots 16-sector"
            }
        }
    }
}

The _pretty key is not part of the disk image's metadata, it is provided by a2kit. There is no problem using put with a value broken out in this way, a2kit will automatically select the _raw value for writing. You can also set the base key directly, i.e., "boot_sector_format": "01" will also work. What you cannot do is provide only the _pretty value. In fact, try not to write any code that depends on the specific value of a pretty key.

Filters

You can add a filter to narrow down the metadata that is processed by either get or put. The filter argument is given as a key path, such as -f /woz2/info/. When using get, only the keys that are in the given branch will be returned. When using put, only the keys that are in the given branch will be written. The selection works all the way down to a leaf, e.g., -f /woz2/info/creator selects just that leaf.

An important use of filters is in copying metadata from one image to another. Without the filter, the entire set of R/W metadata values would be copied over. To limit what is copied you filter the put operation (do not filter the get):

a2kit get -d disk1.woz -t meta | a2kit put -d disk2.woz -t meta -f /woz2/meta/developer

You can also use filters to select a particular image type from a master file. As an example, suppose we are distributing a WOZ and a 2MG, and we decide to keep both sets of metadata in one file:

space_attack.json

{
    "woz2": {
        "info": {
            "creator": "a2kit v2.2.0 :: Script v1.0.0"
        },
        "meta": {
            "title": "Space Attack",
            "developer": "John Doe"
        }
    },
    "2mg": {
        "creator_info": "a2kit v2.2.0 :: Script v1.0.0",
        "comment": "Space Attack, by John Doe"
    }
}

When writing to the WOZ we would use

a2kit get -f space_attack.json | a2kit put -d space_attack.woz -t meta -f /woz2/

When writing to the 2MG we would use

a2kit get -f space_attack.json | a2kit put -d space_attack.2mg -t meta -f /2mg/

Deleting Keys

You can delete a key from the WOZ META chunk by setting it to "", e.g.,

'{"woz2":{"meta":{"some_key":""}}}' | a2kit put -d some_img.woz -t meta

will delete the some_key record if it exists. If the record does not exist it will be created, i.e., setting the value to "" can be thought of as a toggle that creates or deletes the key.

As of this writing WOZ META keys are the only ones that can be deleted.

2MG Tree

For 2MG all the metadata is exposed. Some values will be automatically recalculated after any changes. For example, if you change the comment string, all of the offsets and lengths in the header will be automatically updated.

Key Path Value Type Bytes Access
/2mg/header/creator_id binary 4 RW
/2mg/header/header_len LE u16 2 R
/2mg/header/version LE u16 2 R
/2mg/header/img_fmt LE u32 4 R
/2mg/header/flags binary 4 RW
/2mg/header/blocks LE u32 4 RW
/2mg/header/data_offset LE u32 4 R
/2mg/header/data_len LE u32 4 R
/2mg/header/comment_offset LE u32 4 R
/2mg/header/comment_len LE u32 4 R
/2mg/header/creator_offset LE u32 4 R
/2mg/header/creator_len LE u32 4 R
/2mg/comment string variable RW
/2mg/creator_info string variable RW

Write access is provided for blocks in case other software rejects the value chosen by a2kit. In particular, disks created by a2kit will have blocks set to the disk capacity divided by the ProDOS block size. Some guidance suggests it should be zero in certain cases.

IMD Tree

The exposed IMD metadata is just the header and comment:

Key Path Value Type Bytes Access
/imd/header string 29 R
/imd/comment string variable RW

IMD images contain information about the track layout that is not exposed by get. Instead it is exposed by geometry, see LowLevel.

TD0 Tree

The exposed TD0 metadata includes the image header and the comment area. Wide latitude is allowed in writing owing to the circumstance that the meaning of the fields is not perfectly known.

Key Path Value Type Bytes Access
/td0/header/sequence byte 1 RW
/td0/header/check_sequence byte 1 RW
/td0/header/version byte 1 RW
/td0/header/data_rate byte 1 RW
/td0/header/drive_type byte 1 RW
/td0/header/stepping byte 1 RW
/td0/header/dos_alloc_flag byte 1 RW
/td0/header/sides byte 1 RW
/td0/comment/timestamp binary 6 RW
/td0/comment/notes string variable RW

TD0 images contain information about the track layout that is not exposed by get. Instead it is exposed by geometry, see LowLevel.

WOZ v1 Tree

For WOZ version 1 we expose only the INFO chunk.

Key Path Value Type Bytes Access
/woz1/info/disk_type byte 1 R
/woz1/info/write_protected byte 1 RW
/woz1/info/synchronized byte 1 RW
/woz1/info/cleaned byte 1 RW
/woz1/info/creator string 32 RW

WOZ v2 Tree

For WOZ version 2 we expose the INFO chunk and the META chunk. You are allowed to make up your own keys for the META chunk, but there are also several standard ones, with standard allowed values. If you write to a non-standard key it will be created, and a warning message will appear in the log.

Key Path Value Type Bytes Access
/woz2/info/disk_type byte 1 R
/woz2/info/write_protected byte 1 RW
/woz2/info/synchronized byte 1 RW
/woz2/info/cleaned byte 1 RW
/woz2/info/creator string 32 RW
/woz2/info/disk_sides byte 1 R
/woz2/info/boot_sector_format byte 1 RW
/woz2/info/optimal_bit_timing byte 1 RW
/woz2/info/compatible_hardware binary 2 RW
/woz2/info/required_ram LE u16 2 RW
/woz2/info/largest_track LE u16 2 R
/woz2/info/flux_block LE u16 2 R
/woz2/info/largest_flux_track LE u16 2 R
/woz2/meta/title string variable RW
/woz2/meta/subtitle string variable RW
/woz2/meta/publisher string variable RW
/woz2/meta/developer string variable RW
/woz2/meta/copyright string variable RW
/woz2/meta/version string variable RW
/woz2/meta/language string variable RW
/woz2/meta/requires_ram string variable RW
/woz2/meta/requires_rom string variable RW
/woz2/meta/requires_machine string variable RW
/woz2/meta/apple2_requires string variable RW
/woz2/meta/notes string variable RW
/woz2/meta/side string variable RW
/woz2/meta/side_name string variable RW
/woz2/meta/contributor string variable RW
/woz2/meta/image_date string variable RW