-
Notifications
You must be signed in to change notification settings - Fork 1
Metadata
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.
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.
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.
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.
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.
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.
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.
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/
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.
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.
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.
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.
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 |
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 |