Storing data and/or code in the header of a disc file

This document describes how it is possible to store useful data and/or code in the header of a disc file. (This is useful especially for coding competitions where there is a limit to the file size).

The method that is described here is known to work on the standard Amstrad CPC disc operating system (AMSDOS). It may not work if a different disc operating system is installed because it relies on the structure of AMSDOS's work RAM. This method will work even if there are additional ROMs attached.

The method described here relies on these facts:

File header detection

Whenever a file is opened, AMSDOS will do the following:

If a valid header is detected, then the program data will immediatly follow the file header, otherwise the program data begins at the start of the file.

Notes:

Header usage

To load a file, AMSDOS doesn't require all the variables in the header.

This table gives a list of the variables required by AMSDOS:

OffsetLengthDescription
181Filetype (note 1)
212Load address (note 2)
242Length (note 3)
262Execution Address (note 4)
643Length (note 5)
672Checksum (note 6)

Notes:

  1. The "filetype" defines the type of the file: e.g. &00 for a unprotected BASIC file, and &02 for a unprotected binary file
  2. The "load address" is the Z80 memory address the file is loaded to. This is normally &170 for BASIC programs, and can be any value for BINARY programs.
  3. The "length" is the length of the file in bytes,
  4. If the file is binary, and the program is started with the "RUN" command, then the program will be executed starting from this address.
  5. This defines the length of the file in bytes and is the same as the length parameter described in note 3. However, this variable allows a file longer than 64K to be defined.
  6. The checksum is initialised with 0, and calculated from the sum of the data bytes in the range 0-66 inclusive. The checksum must be valid or AMSDOS will assume that the file does not have a header.

The remaining bytes are not used and can be filled with code and/or program data.

Method

The first 128 bytes of the file are stored in a 128-byte buffer.

This can be accessed immediatly after loading and will exist until another file is loaded.

The code to get the start of the stored header in AMSDOS's work RAM is:

;; get start of AMSDOS work RAM
ld hl,(&be7d)						; this variable is initialised by AMSDOS				
;; add on offset of loaded header 
ld bc,&e4
add hl,bc				
;; HL = start of record buffer

Initialising the header

The header written to the start of a file is located at offset &9f from the start of AMSDOS work RAM.

The header can't be filled with user data and/or code before the file is opened for output with "cas out open" because this function modifies the header data in the following way:

If the in-memory header is filled with user data and/or code after "cas out open" but before "cas out direct", then the following variables are changed:
OffsetLengthVariable
93Extension (note 8)
181Filetype (note 1)
19,202(note 7)
212Load address (note 2)
232(note 7)
242Length (note 3)
262Execution Address (note 4)
642Length (note 5)
672Checksum (note 6)

NOTES:

  1. This variable is set to the file type parameter (A register) of the "cas out direct" function
  2. This variable is set to the load address parameter (HL register) of the "cas out direct" function
  3. This variable is set to the length parameter (DE register) of the "cas out direct" function
  4. This variable is set to the execution address (BC register) of the "cas out direct" function
  5. If the file is less than 65535 bytes, then this variable is set to the length parameter (DE register) of the "cas in direct" function
  6. This variable is computed from the header and contains a valid checksum.
  7. These variables are set to "0".
  8. This variable is filled with the extension of the filename
  9. All other bytes are not changed

Therefore to use all the bytes that are unused during loading the following method must be used:

If "cas out char" is used, then the in-memory header will be defined as ASCII, and the header will not be written to the output file, and the user has full control over the data that will be in the output file.