Technical Reference
Memory Usage
Filing System
System Timing
System Board
Power Supply Board
Interface Slots
Low Level
Comms Link
Psion Link
Utility System
LZ Passwords
System Services

Technical Reference Manual














This section describes the format of file-structured datapacks, then the system services available for file and record management. System services which access datapacks directly are discussed in chapter low level pack access.

In the following sections "datapack" means (E) ')"; onMouseout="hideddrivetip()"> EPROM s, ROMs on external devices, external RAM packs, and internal RAM (the device A:). The operating system handles the different device types in the same way apart from delete operations. All device types use the same record structure. Device dependencies will be pointed out as necessary.


Datapacks contain two types of records, preceded by either a byte or word length. This is to al low long records while minimising the overhead for text files which typically contain short records. The first record is always at byte $0A in the datapack. The record structure is terminated by a byte $FF.


Short records are of the format:

Byte  0 1 2...
  length record type 1 to 254 data bytes...
Range  1 to 254 $81 to $FE  



"HELLO" saved using SAVE. Record type is $90.

$05  $90  $48  $45  $4C  $4C  $4F

Note that the length byte does not include itself or the record type. The record length can not be zero. The maximum length is $FE, because a first byte $FF is used to terminate the record structure. The record type is in the range $81 to $FE inclusive. When writing to more than one file, the record type is used to identify which file each record belongs to, since the records may be written in any order.


Long records are used primarily for saving blocks of data which will not be regularly altered, which are intended to be loaded and saved in one piece. Long records are also used to contain information which is to be hidden from the file system.

Long records have the following format:

Byte  0 1 2 3 4...
  $02 $80 length word  data...



long record "HELLO"

$02  $80  $00  $05  $48  $45  $4C  $4C  $4F

null long record

$02  $80  $00  $00

Long records do not have a length byte as such, the $02 is purely for error handling (see below). The $80 is a special record type which identifies a long record.


On ')"; onMouseout="hideddrivetip()"> EPROM datapacks, short records are marked as deleted by clearing the top bit of the record type. On ')"; onMouseout="hideddrivetip()"> EPROM s long records are never deleted - this will be discussed later. On a RAM device, the space occupied by a record is recovered when the record is deleted, so there will not be any long records with a record type < $80 on either RAM or ')"; onMouseout="hideddrivetip()"> EPROM devices.


short record "AAA" of record type $91 on an ')"; onMouseout="hideddrivetip()"> EPROM

$03  $91  $41  $41  $41

when deleted becomes:

$03  $11  $41  $41  $41


There are two kinds of files; data files accessible to OPL (of which the file "MAIN" is an example), and block files such as OPL procedures. In future we will refer to the first kind simply as 'files'.

Each file has a name, which is a short record of type $81, and a number of data records which are short records all of the same record type in the range $90 to $FE. The name and data records of a file can be interspersed by any number of other records and files. Also the name need not come before the first record of a file.

Each file has data records of a unique record type, so there can be up to 111 files on a device. An attempt to create more files will produce the error "DIRECTORY FULL". A file may contain up to $FFFE data records, given a sufficiently large pack.

Filenames have the following format:

Byte  0 1 2-9 10
  $09 $81 file name, space filled record type


Example: the file MAIN (all records of type $90 will be in MAIN)

$09  $81  $4D  $41  $49  $4E  $20  $20  $20  $20  $90

Filenames are always padded with spaces to make them eight bytes long. Byte 10 in the above diagram is the record type which will be used for all data records in the file. It can take values in the range $90 to $FE inclusive.

When a file is created, the operating system first searches through all the filenames on the datapack to find the lowest free record type and this is then allocated to the new file. The new record type is then stored in the new file name record. Since several files can be open at once, the records of a file can be mixed with any other type of records. No facilities are provided to allow reordering of records in a file, or to allow the insertion of records in the middle of a file.

When a file is deleted, all records of the appropriate type are deleted one by one, then the filename is deleted. On ')"; onMouseout="hideddrivetip()"> EPROM s the filename is deleted by overwriting the record byte (i.e. $81 in the above example) in the filename with $01.

The total overhead for each file is 11 bytes for the filename plus two bytes per record.


The top level commands FIND and SAVE work with short records of type $90 directly, not by opening the file MAIN. This means that if MAIN is deleted, problems can occur. SAVE will still save records of type $90, but these records can not be re-read by OPL. The record type $90 is 'reserved' for MAIN, so that no other file can have this record type. When blank packs are sized, the filename MAIN is created.

Note: User programs should never delete MAIN, since this will cause problems with certain OS versions. To create a new MAIN, delete all the records in a loop.


Block files are a special class of files with a name immediately followed by a single long data record. No records are allowed between the block filename and the long record. They are intended for storing data which will be re-saved as a whole each time the data is changed. Long records may be used alone without a preceding block filename - for example to enclose a machine code program on a datapack. Long records with no preceding block filename are ignored by the file system.

Format of a block file:

Byte  0 1 2-9 10 11 12 13 - 14 15...
  $09 TYPE file name $00 $02 $80 length data...


Example: block file ABCD of block type $83, containing four bytes of data.

$09  $83  $41  $42  $43  $44  $20  $20  $20  $20  $00  $02  $80  $00  $04 xx xx xx xx

The record type, byte 1 in the above diagram, is in the range $82-$8F inclusive. This byte is used to distinguish different classes of block files containing different kinds of information, and will be referred to as the block file type. Because block files have their data immediately after the filename they do not need a data record type, so byte 10, which was used as the data record type in ordinary filenames is not used in block files. This byte is reserved by Psion. Note also that the number of block files on a device is limited only by the space available, and there can be up to fourteen different kinds of block files with types $82 to $8F.

On ')"; onMouseout="hideddrivetip()"> EPROM S, a block file is deleted by clearing the top bit in the record type byte of the name (byte 1, the $83 in the above example). The total overhead for each block file is 15 bytes.


OPL procedures are saved as block files of type $83. The data block has the following format:

Byte  0 1 2... word        
  length of
Q-code (if any) length of
1st source line $00 2nd source line $00...


The length of the Q-code may be zero, if the procedure was saved with the SAVE option in the TRAN SAVE QUIT sub-menu or was received from PC. The length of the source may be zero if the procedure has been copied object-only. Each line of the source is terminated by a zero.

The DIR option in the PROG sub-menu works by finding all type $83 records.


These are block files of type $82. Its data block consists of a list of entries which is terminated by a zero byte. Each entry has the form:

Byte  0 1 2 3 4 5 6 7...
  length of the text year month day hour minute alarm text...
Range    0-99 0-11 0-30 0-23 0-59 0-60  


The alarm flag is 0 for no alarm, otherwise one more than the number of minutes early the alarm has to go off.


On LZ machines the diary is no longer saved as a block file of type $82, but instead as an ordinary data file. Each entry is saved as a separate record.

For example

Mon 8 May 1989 Wk19 
5:15p ABCDEF 

would be:


The first field specifies the date of the entry (1989, 05, 08, for 8th May 1989), the time (17 15, for 5:15pm), the duration (02) and the alarm byte (16, for 15 minutes before - again, 00 would mean "no alarm"). The second field is the text of the entry. The order of things in the first field, and the use of zeroes where necessary to keep things the same length (e.g. "02" for a duration of 2) make the file easy to sort in OPL, or otherwise.

Note, though, that the "Restore" option in the diary will restore entries in any order from a file. The "Xrestore" option can be used to load a CM/XP diary from a pack, in which case each entry is given a duration of 2 (=30 minutes).


These are block files of type $84. Its data block consists of 27 bytes exactly, containing the parameters:

Byte  0 1 2 3 4 5 6
  baud parity data bits stop bits handshake minute echo
Range  0-9 0-4 0-1 0-1 0-7 0-2 0-1


Byte  7 8 9-11 12-15 16-19 20-23 24-27
  width timeout REOL REOF RTRN TEOL TTRN
Range  0-254 0-255 string string string string string


All string have a maximum length of 2 and a leading length byte.


These are block files of type $87. Its data block consists of two parts, the header, and the data, both preceded by a length word.

Byte  0 2 3 4...
  header length flags $00 title+":"


If a password was used:

Byte  0 2 3 4-13 14...
  header length flags $09 password code title+":"

Flags: The bits are set as for the LG$EDIT service, so Bit 7 is set if the notepad is numbered, bit 3 must be set, bits 1 and 2 are clear.

Byte  0 2 3...    
  data length $00 1st line $00 2nd line...


Other block file types:

$85 Spreadsheet files
$86 Pager setup files
$8E General use

PSION states that all other types are reserved. These might be used by PSION or third-party software.

Block file types are important in keeping different types of data distinct: disaster would result if OPL procedures could be loaded into the diary, for example. Applications tend to assume that block files of their own type are in the correct format, and usually perform no further checking.


This is the algorithm for scanning through the record structure of a datapack:

        SET_PACK_ADDRESS ($0A)
             LENGTH_BYTE = NEXT_BYTE
             RECORD_TYPE = NEXT_BYTE
             if LENGTH_BYTE = 0
                 ERROR (246) -- "no pack"
             if RECORD_TYPE = $80        -- if long record
                 BLOCK_LENGTH = NEXT_WORD
                 SKIP_BYTES (BLOCK_LENGTH)
                 if RECORD_TYPE <> $FF   -- if valid short record
                     SKIP_BYTES (LENGTH_BYTE)
         until LENGTH_BYTE = $FF         -- found end of pack


If a length byte of zero is seen the pack is assumed to have been pulled out, and a NO PACK error is reported. Errors can occur in various places when writing to ')"; onMouseout="hideddrivetip()"> EPROM devices, which can disrupt the record structure. The file system error handling attempts to mark the data as deleted, or creates special 'invalid' records so that the remainder of the datapack can still be used. In certain exceptional cases this mechanism can fail, and a "READ PACK" error will result when invalid record structure is detected. This error is reported whenever the last record extends beyond the end of the pack. An "END OF FILE" error will also be reported when accessing a block file if the block file name is not followed immediately by a long record.

When writing a block file, any error will cause the operating system to first delete the long record, then the block file name. This is the reason for the $02 before the $80 in a long record - if writing the length word fails, the $80 is re-written as a zero, which forms a deleted short record enclosing the bad length word. When a block file is opened, if a valid long record beginning with $02 $80 is not found, the error "END OF FILE" (238) is reported.

When writing a short record the following errors may occur:

  1. When writing the length byte fails, no further bytes are written to the record. The record is left with a second byte $ff, which is taken as a special invalid record type. If this type of record is seen the bad length byte is ignored, and the next record is assumed to begin immediately after the $FF. This prevents a record with a bad length byte from going off the end of the pack. However, the method is fallible because the length byte could be $FF, denoting the end of the datapack, or could even be zero (although zero is very unlikely).
  2. When writing the record type or a data byte fails, the operating system attempts to delete the record. If this fails, a spurious record will remain, which may become part of the wrong file since the record type is wrong.

Some of the errors such as "PACK NOT BLANK", and "WRITE PACK ERROR" may only occur when sizing a blank ')"; onMouseout="hideddrivetip()"> EPROM device. Apart from the obvious, "END OF FILE" can mean: an illegal block file (as discussed above), or more generally "not found".


Record type

00 invalid long record - ignored
01 deleted data file name
02 - 0F deleted block file name, following long record is regarded as deleted
10 - 7E deleted short records
7F deleted $FF (should not occur)
80 long record - length word follows
81 data file name
82 - 8F block file name, followed by a long record
90 record from MAIN, top level FIND/SAVE record
91 - FE data records from files
FF invalid record - length byte will be ignored


Example of record structure:

      09 81 4D 41 49 4E 20 20 20 20 90  filename "MAIN"
      04 90 41 41 41 41                 record "AAAA" in MAIN
      09 81 41 42 43 20 20 20 20 20 91  filename "ABC",
                                        data records are type $91
      03 91 42 42 42                    record "BBB" in ABC
      01 10 41                          deleted record "A" in MAIN
      09 85 42 4C 4F 43 4B 20 20 20 00  block file "BLOCK", type $85 
      02 80 00 05 01 02 03 04 05        contains 5 bytes of data
      09 02 4F 4C 44 20 20 20 20 20 00  deleted block file "OLD", 
      02 80 00 01 FF                    of type $82 (diary),
                                        contained 1 byte of data
      F7 FF                             invalid short record
      09 03 42 41 44 20 20 20 20 20 00  invalid block file "BAD" 
      02 00 00 FF                       of type $83 (OPL proc), 
                                        deleted when length word 

      FF                                end of datapack


Some of the file system's variables can be usefully read by the user, but these variables should be treated as read only. Writing to these variables may produce unpredictable results, and will cause incompatibility with future OS versions.

$96 FLB_RECT Current record type in use.
Set by FL$RECT, and implicitly set by FL$OPEN, FL$CRET etc.

Current device used by file system
Set by FL$SETP, and implicitly set by FL$OPEN, FL$CRET etc.

$9B FLW_CREC Current record number - 1 is the first record.
Set by many routines including FL$RSET, FL$NEXT.


Organiser I datapacks are structured differently to Organiser II datapacks - the details will not be discussed here. The main differences are:

  1. Organiser I datapacks have a first byte $FC - a value not used by the Organiser II. These packs are treated as read-only by the Organiser II.
  2. Organiser I program packs have a first byte of $03; these packs are not supported by the organiser II.
  3. Records saved on Organiser I datapacks with SAVE are stored in a packed six-bit format, which can be read by the Organiser II. These records are treated as part of an imaginary file "MAIN". All read-only file system operations on "MAIN" will work on an Organiser I datapack, including COPY. Other types of records, such as POPL programs are not supported.

The Organiser I datapacks themselves are all compatible with the Organiser II, and can be used on the Organiser II after UV-erasure. Also there is no reason why a special user program could not read an Organiser I datapack, by accessing the datapack directly. If some special data other than SAVEd records is to be transferred, the easiest method is to use two RS232 leads.


This section briefly describes the system services used by OPL to handle files, records and block files. The names of these services are prefixed by FL$. A detailed explanation is given on the system services page.

It is more efficient to use record types directly to access several files at once, rather than opening one file, then the other. This is the equivalent of the OPL command USE. The services FL$OPEN, and FL$CRET return the record type in use by a file. FL$FREC will provide details of a record including its address in the pack for any user wishing to perform direct pack accessing, however such programs may not be compatible with future OS versions.

Programmers should note that calls to the FL$ services may be interspersed with PK$ calls - which may change currently selected device or change the current pack address - provided that PK$SETP is called to re-select the correct device for the file system before calling any further FL$ services. As always, any programs directly accessing the datapack hardware should notify the OS by calling PK$SETP.


Sets the current file position back to the previous record.


When called repeatedly, returns each filename of a given record type on a device.


Delete a named block file. On RAM devices the block file name and the following long record is deleted and the space is freed. On ')"; onMouseout="hideddrivetip()"> EPROM s the long record is not affected.


Finds a named block file of the given block file type. It returns the length of the data, and the pack address is set to the start of the data, ready for PK$READ to load the data into RAM.


Called in preparation for saving a block file, FL$BSAV saves a block filename followed by the first four bytes of a long record: $0280 and the length word. Then a call to PK$SAVE must be made to save the data. FL$BSAV checks that there is sufficient room on the pack for both the filename and the long record before writing to the datapack.


When called repeatedly, returns each the name of each file on a device.

Calling FL$CATL is equivalent to calling FL$BCAT for file type $81.


Copies files or block files from one device to another, as in the top level COPY or PROG COPY menu options. The copy-from device must not be the same as the copy-to device. A file may be copied to a different name on the target device. If a device only is specified in the copy-to string, the file is copied with the same name.

If the file already exists on the TO device then the records will be appended to the file otherwise a new file of the appropriate name will be created.


Creates a file. If the file already exists then FL$CRET returns error "FILE EXISTS", otherwise the file is created and the record type to be used by the data records in the file is returned


Delete a named file.


Erase the current record in the current file. On