The operating system of the Psion uses the memory area between addresses
$0000 and about $2400 to hold all the information it needs to run properly.
These so called system variables are useful for programming, especially when
using machine code. I have collected as much information as I could from
various sources, trying to make this list as complete as possible. If you have
any information about any of the variables which is not here, please let me
() know. I do not
guarantee that this information is completely correct, nor am I responsible
for any loss of data or any other damage resulting from your use of this
The system variables of the most interest are printed in bold letters.
The addresses in the range $01 to $1F are used as internal registers
by the 6303 processor. OPL does not allow PEEK/POKE in the area 00-3F.
Extreme care should be taken with these addresses. These addresses
control/receive/send data to and from the other hardware. For example
the operating system uses these for access to packs. It is obviously
much easier to use the system routines for such tasks. Those marked W
can only be written to, and similarly those marked R should only be
read. The most useful and least dangerous is Port 5 ($15) which is used
to read the keyboard and test for low battery.
Port 2 data direction register. Bit 0 controls the direction of bit
0 of port 6 (1=output,0=input) and bit 1 control the direction of bits 1-7 of
Port 1. This is the low byte of the address bus. Do not use.
Port 2. Used as data bus to slots, i.e. to packs etc.
Port 3 data direction register of data bus. Do not use.
Port 3. This the data bus. Do not use.
Port 4. This is the high byte of the address bus. Do not use.
Timer Control/Status 1. Bit 3 (EOCI1) is used to enable or disable OCI
Timer 1 Free Running Counter, automatically incremented by processor
clock. Used for OCI interrupts.
Timer 1 output compare register. When pow_frc (Timer 1 frc) reaches this
value, pow_frc is set back to zero and an OCI interrupt is generated. The OCI
interrupt is used in the Psion as the keyboard interrupt.
Input capture register
Timer control/Status register 2
Rate, mode control register
Tx/Rx control status register
Receive data register
Transmit data register
RAM/Port 5 control register. Note that bit 7 (STBY PWR) is used to
test whether a cold or warm boot is needed on startup. If it is clear on
startup, then it is set and a cold boot is performed, but if bit 7 was already
set it only does a warm boot. If bit 6 (RAME) is cleared, it disables the
internal RAM ($40-$FF) of the processor so that these addresses refer to
external memory instead. This feature is not used on the Psion though it is
probably possible. Bits 0-3 control whether the corresponding bits read from
port 5 are the port lines or the lines IRQ1, IRQ2, MRE or HLTE respectively.
On the Psion these 4 bits normally are clear, so that the normal port 5 lines
are used. The external interrupts IRQ1 and IRQ2 are therefore ignored.
Port 5, input port only. On the Psion it is used to read the activated
keyboard lines and ON/CLEAR key. Bit 7 is clear when ON/CLEAR pressed, and
bits 2 to 6 are cleared whenever the corresponding key is pressed on one of
the active keyboard lines. (See $0340). Bit 0 is clear when the battery is
running low. Bit 1 (ACOUT) is connected to bit 12 of the clock counter (see
$0340), so that when the organiser switches on this bit will show whether it
was because the timer elapsed (e.g. an alarm or because 2048 seconds elapsed)
or whether it was because ON/CLEAR was pressed (or an external device like the
comms link caused it).
Port 6 data direction register, controlling the direction of each of
the bits of port 6 individually.
Port 6. Bits 7 to 0 are labelled PACON, CS3, CS2, CS1, OE, PGM, MR,
CLK. This port is used in the Psion to control whether the packs are on or
off, which pack is selected, and to set the pack address.
Output compare register
Timer control/Status register for timer 2. Bits 0-1 select the clock
used (if both set then bit 7 of port 2 used for timing, otherwise the internal
clock is used). Bits 2-3 selects the action is needed at bit 6 of port 2 when
time-out is reached (if bit 3 is set then bit 2 will be output, if bit 3 clear
and bit 2 set then port 2 bit 6 is toggled, if bit 2, 3 both clear then port2
bit 6 becomes an I/O port). If bit 4 cleared then timer 2 is temporarily
disabled. Bit 5 is unused. If Bit 6 is set then a timeout causes an interrupt
(CMI). Bit 7 is set whenever a timeout occurs (is not reset
Timer constant register for timer 2. The timer 2 up counter is
incremented until this value is reached at which time the action indicated by
the control register is taken.
Timer 2 Up counter.
Test register. Do not use.
The addresses in the range $40 to $FF are registers in the
processor's internal memory. The machine code instructions to access these
'zero-page' addresses are shorter, and therefore execute faster than those
accessing two-byte addresses.
JMP instruction for vector in utw_s0, used in sound routines.
General word variables S0 - S5. Can be freely used, but
some OS calls use these too.
General word/byte variables R0 - R6. Their high and low
bytes are denoted by utb_h* and utb_l*. These must be preserved. They can be
stored/ retrieved on the stack using BT$PPRG (SWI 0B).
Cleared when an NMI occurs. It can be used to check for an NMI by
setting this to non-zero, and waiting till it is cleared.
Time (in seconds) that it is planned to be switched off (until next
alarm check or end of temporary switch-off).
Address of Ramtop
Run time low battery flag
Reserved. Unused in Rom versions 4.4 and earlier. Used in version
Current cursor position (0-31 if 2 lines, 0-79 if 4 line mode on an
Cursor state (as passed in DP$STAT, i.e. bit 7 set if cursor on, bit 0
set for line cursor or clear for block)
Scrolling line position (0-1 or 0-3) when used in VIEW. Current menu
item number when used in MENU.
Number of characters to scroll when used in VIEW. Total number of menu
items when used in MENU.
Scroll direction (1=right, 2=left, 0=paused). Used in VIEW.
Saved cursor position. Used by DP$SAVE and DP$REST.
Saved cursor state. Used by DP$SAVE and DP$REST.
Horizontal scrolling rate (in 50ms intervals). Default is 4. Delay
before scrolling is four times dpw_sped.
Vertical scrolling rate (in 50ms intervals). Default is 10.
Decremented every 50ms (on keyboard interrupt) until it is zero. Used
for timing, e.g. by DP$WRDY and TM$WAIT.
Address of scrolling string. Used in VIEW.
This word controls the rate of keyboard interrupts. When an interrupt
occurs the value in kbw_tdel is stored in the Timer 1 Output Compare Register
1, and the Free Running Counter is set to zero, so that the next interrupt
will occur after kbw_tdel clock cycles. There is an overhead of 35 cycles for
each interrupt. Hence, the time between interrupts = ( kbw_tdel + 35 ) /
921600 secs. The default value for kbw_tdel is $B3DD, giving a time interval
of 0.05 secs. Note that a value of zero in kbw_tdel, will cause the machine
to lock up. It is used extensively by the operating system for timing
Offset in kbt_buff to oldest key in buffer.
Number of keys in buffer
Key pressed on last keyboard poll, used to check if same key is still
pressed for auto-repeat.
Unget key, zero if no key else the key
This byte stores the delay before auto-repeat of the keys begins in
terms of the number of keyboard interrupts. The default value is 14, so with
interrupts running at 20 times per second, the delay is 0.7 secs.
This byte stores the delay between keys when auto-repeating in terms
of keyboard interrupts. The default value is 0 which is the fastest value. A
value of 1 will repeat at half normal speed, 2 at a third normal speed
Keyboard counter, counts down from kbb_dlay at last new keypress. If
zero and still same key pressed, then auto-repeat is activated.
Offset into keyboard table
kbb_stat stores the following flags:
Set if shift is depressed.
Set if Num Lock on.
Set if Multi-lingual Key Lock. (Shift rightarrow, for accented
characters etc). Multi-lingual machines only.
Set if any lock keys were pressed. This is used by the key
translate routine to signify that a keyboard click should occur despite
returning no character.
Set if Lower Case Lock.
kbb_stat can be read directly, but system service
KB$STAT should be used to write to it.
Auto-switch-off flag. Clear to disable. This will inhibit the NMI
from decrementing tmw_tout and prevent KB$TEST testing it.
Time left before next switch off. The contents of tmw_tcnt are copied
into tmw_tout whenever a key is pressed or KB$GETK is called and tmw_tout is
decremented until zero by the NMI routine every second. If tmw_tout is found
to be zero in KB$TEST, the machine will switch off.
Maximum input length
First editable line
First editable character in first line
Current line edit
Editor cursor status
Current position within line
Offset to current line
Total buffer length
Set by PK$SETP this is the current device being looked at by the
operating system. It contains the contents of B register on the last call to
PK$SETP. If this is zero (i.e.. device A: internal RAM pack selected) then the
ports may be left selecting device B,C or D.
Set by PK$SETP and PK$PKOF. Actual current slot. Only set if the
current slot is powered up and selected. Set to $FF when packs are turned off
by PK$PKOF. If this byte is zero then device A: has been selected but the
slots will be still powered up.
Length of internal RAM pack (device A:).
Offset into RAM file. Set by all pack routines when accessing ram
High order byte of pack address. Set by all pack routines when
accessing devices B,C,D.
Pack address. Set by all pack routines when accessing devices
Pointer to current pack identifier in array pkt_id. Set by
Current record type in use - set by FL$RECT, and implicitly set by
FL$OPEN, FL$CRET etc. Returned by FL$OPEN, FL$CRET and others.
Current device used by file system, set by FL$SETP, and implicitly set
by FL$OPEN, FL$CRET etc.
Device being DIR-ed
Next directory record number
Current record number, 1 is the first record. Counts the records of
type flb_rect. Set by many routines including FL$RSET, FL$NEXT.
Address of file name
Number of records
Current record type
Current default pack (0-2)
Which option: FIND, SAVE or ERASE
Non-zero to mute buzzer
Language stack pointer. rta_sp points at the lowest byte of the stack.
So if an integer is stacked, rta_sp is decremented by 2 and the word is saved
at the address pointed to by rta_sp.
Frame (procedure) pointer. rta_fp points into the header of the
current procedure. Each procedure header has the form:
Device (zero if top procedure)
Previous rta_fp. rta_fp points to this word.
Start address of the global name table
Global name table
Indirection table for externals/parameters
This is followed by the variables, and finally by the Q code. rta_fp points
at the previous rta_fp, so it is easy to jump up through all the procedures
above. The language uses this when resolving external references and when
Program counter. rta_pc points at the current operand/operator
executed and is incremented after execution - except at the start of a
procedure or a GOTO when rta_pc is set up appropriately.
Current line being edited
Current character pointer
Maximum string size
Pointer to variable
Global O code size
Current free O code bytes
Total O code size
Structure next level
Next new label number
General language word
General language word
Run time variables, overlayed against the language
Current logical name
Current error condition
Carriage return flag
Device of top procedure
General word variables
accumulator: guard byte and mantissa. Guard byte lengthens the
mantissa for rounding purposes.
operand: guard byte and mantissa
Diary variables, overlayed against the maths
Alarm variables, overlayed against the maths
Alarm temporary area
Table program counter
Table stack pointer
Transient application area. Used by most device drivers as a temporary
scratch area. For example, the Comms link copies its variables from dv_spar
(214F) to here temporarily every time it is used so that the code is faster
and more compact. Note also that a WARM BOOT uses $F8 to $FF.
In the memory map between $180 and $3FF lie the semi-
custom chip addresses. These addresses do not point to a memory chip, but
connect to the semi-custom chip which controls all external communication for
the CPU including the LCD screen, the keyboard and the buzzer. OPL does not
allow PEEK/POKE in the area 0182-03FF. The semi-custom chip does not decode
all the address lines. For the LCD driver the even addresses $180,$182... up
to $1BE are considered identical, as are the odd ones $181 up to $1BF. For
the other addresses all of the bottom 6 bits are ignored by the semi-custom
chip (except that LZ only ignores only bottom 5 bits, see below). Simply
performing a TST instruction on any of these addresses will have the required
effect. Only the LCD addresses are such that STA or LDA instructions are
Liquid Crystal Display control register. When bit 7 of the contents
of this register is set it means that the LCD is busy and cannot take any
commands. The remaining 7 bits contain the current address pointer in the LCD
memory. Writing to this register (only when bit 7 is clear) is used to pass
a command to the LCD chip. The most important of these are $40+x which sets
the address pointer to the UDG pattern space (x in range 0 to $3F).
LCD data register. Is used to pass data to/from the LCD chip (only do
this when bit 7 of $0180 is clear). Any data written/read here is stored
at/read from the current LCD address, after which the address pointer is
automatically incremented. Therefore to store/read a new UDG pattern, pass
$40+8*u to $0180 (u betw 0 and 7), then store/read the 8 bytes of the pattern
at $0181. Before each read/write you must read $0180 to check whether the LCD
is ready. Note that in OPL this is not necessary as the ROM will do it for
Pulse enable. Enables a high voltage pulse used in writing to
datapaks. Take extreme care.
Pulse disable. Disables the high voltage pulse.
Set counter for kybd + clock to zero.
Counter for kybd + clock increment once. The keyboard has 7 lines of
5 keys (ON/Clear is separate). Bits 0 to 6 of the clock/keyboard counter
determines which of these lines are active. When reset, all lines are active.
To make only one line active, set the counter to 3F, 5F, 6F, 77, 7B, 7D or 7E
which have only one of its low bits clear. These values activate the following
mode up down left right
Which of these keys is pressed (and the ON/CLEAR key) can then be read
at pob_port5 ($15). This counter is also used to control the number of seconds
that the organiser is switched off, and the number of NMI's that were missed
if they are disabled.
Enable NMI to processor. Links the NMI's to the processor, enabling
Enable NMI to counter. Disables the NMI's to the processor but links
them to the clock counter, so that they are counted.
The LZ, P350 and multi-lingual XP need more control lines
for their memory management, and for this the following semi-custom addresses
Reset ROM and RAM to first banks (LZ/P350/M-XP).
Select next RAM bank (LZ/P350).
Select next ROM bank (LZ/M-XP).
As bit 5 of the semi-custom addresses is now tested to
distinguish the memory bank switches above, the following addresses are also
available. These probably control the program mode of the Hitachi HD6303X CPU (lines MP0 and MP1 on
the chip). The organiser uses only one of these modes, so these should not be used in any
way. In fact these are only used once by the operating system, namely at the
start of a cold or warm boot.
Select mode 1 bit (LZ/P350/M-XP).
Select mode 2 bit (LZ/P350/M-XP).
Clear mode bits (LZ/P350/M-XP).
Low RAM area. If present it is used for code/data for booted devices.
If the device code to be loaded still fits in Low RAM it will be placed here,
otherwise the permanent allocator cell is used. This area is not available on CM's and normal
XP's, but only on machines with 32k or more RAM.
Base of allocator cells. Allocator cells are parts of memory
used for storing data of variable size. These cells are held consecutively in memory and
immediately follow the system variables. 2000-203F are the so-called tags of
the cells, and hold the addresses of the start of the allocator cells or zero of a cell is not
in use. The cells are manipulated by the system calls AL$FREE (SWI 00) to AL$ZERO (SWI 06)
Permanent cell, used for code/data from booted devices. If
available, Low RAM is filled first. The first cell always starts at the same address (usually
23E9 for CM, 2413 for XP, 268D for LZ), so the device programs will not be moved about in
memory. Other cells are moved when a previous cell changes size.
Top level menu cell. Contains the main menu. Each item
consists of an lbc string containing the name, followed by a word containing the address to
jump to when that item is chosen. Inserted OPL items have a zero word, and on the LZ notepads
have a 1, files a 2. The list is terminated by a zero byte.
Diary cell. Each diary item consists of:
0: Length byte. Contains length of the text of the diary entry.
1: Year (0-99 on CM/XP, 0-255 on LZ)
2: Month (0-11)
3: Day (0-30)
4: Hour (0-23)
5: Minutes (0 or 30 on CM/XP, 0,15,30,45 on LZ)
6: Alarm, 0=no alarm, else one more than the number of minutes before the
given time it will sound.
This is followed by the text of the diary entry, its length byte is byte 0
The list of diary entries is terminated by a zero byte.
Language text cell, used for editing/translating OPL/CALC.
Symbol table cell, used when translating OPL/CALC.
Global record cell, used when translating OPL/CALC.
QCODE output cell, used when translating/running OPL/CALC.
Field name symbol tables. Contain field names for files opened in
OPL, one allocator cell for each of the logical filenames A to D. Each field variable
name is preceded by a byte that is 0 for an integer, 1 for a floating point variable and 2
for a string. Each name is followed by a TAB character to signify its end.
File buffers for files opened in OPL, one cell for each of the logical filenames
A to D. Each opened file has a cell of 256 bytes. It contains the current record, each
field separated by a TAB character.
Database cell, contains all the data on device A: on CM/XP machines. The LZ
(and P350) uses RAM banks, so this cell is used slightly differently.
Notepad cell (LZ)
Dummy cell for spreadsheet, contains only $FF. (LZ)
14 free cells for use by applications
Top of allocator area, the end of the last cell in use.
IRQ2 re-vector address, no effect.
CMI re-vector address, no effect.
TRAP re-vector address
SIO re-vector address, no effect.
TOI re-vector address, no effect.
OCI re-vector address, keyboard interrupt.
ICI re-vector address, no effect.
IRQ1 re-vector address, no effect.
SWI re-vector address
NMI re-vector address
WRM re-vector address
SWOF re-vector address
This vector points to the routine which polls the keyboard. It must return the
number of the key pressed in the A register. The ROM routine returns 0 if no key was
pressed, or a number from 1 to 36 otherwise. If the shift key is not disabled (see
kbb_shfk, $20C4) and the shift key is pressed, the routine will set the shift flag (bit
7 of bta_stat, $7B) and return the number of the second key pressed if there is
This vector points to the routine which translates the key number supplied by
bta_poll in the A register into the ascii character it represents, returned in the A
register. To decode the character, the ROM routine uses a table of characters pointed
to by bta_tabl ($205E). The routine will check the shift flag (see bta_poll, $205A)
and the other keyboard flags (see bta_stat, $7B) to decide how to translate the
character. If the shift and numlock flags make it necessary, a character from the second
half of the table is returned, which contains the numerical or 'shifted' characters. If the
caps-lock flag is set and a letter would be returned, it is first changed to lower case. This
routine also checks for the caps/numlock/multi-lingual key combinations (see kbb_capk
$20C2 and kbb_numk $20C3) and sets the keyboard flags accordingly.
This is the vector which points to a table of characters used to translate a key
press into an ascii character. The vector can be changed to point to a new set of
characters and should contain 72 characters (36 'shifted') unless, of course, the translate
routine has been changed or SHIFT has been disabled.
Frame pointer for ENTER/LEAVE
If zero, next NMI is ignored (i.e. it will do nothing but set this flag).
Save interrupt mask while off.
Save TCSR1 while off.
Language stack base.
Save stack pointer while off.
Used in SWI's to save D register.
Used in SWI's to save X register.
Used in SWI's to save return address.
Used in SWI's to save flag register.
16 byte buffer containing contents of top line of the display (on 2-line machine,
or on LZ when in 2-line mode).
16 byte buffer containing contents of bottom line of the display (on 2-line
machine, or on LZ when in 2-line mode).
dpa_scrn contains the address of the current screen buffer. When in 2-line
mode, it contains the address of dpt_tlin - the 2-line screen buffer at the same
memory location as on 2-line Organisers (for compatibility) When in 4-line mode it
contains the address of dpt_4lin - the new 80 character 4-line screen buffer. It is set
by the operating system service DP$MSET. (LZ)
dpb_nlin contains the number of screen lines in the current display mode, i.e.
2 or 4. It is set by the operating system service DP$MSET. (LZ)
dpt_wide contains the screen width in the current display mode, i.e. 16 or 20.
It is set by the operating system service DP$MSET. (LZ)
dpb_clok stores the position of the left most character of the 6 character
UDG clock, so is in the range 0-74. If bit 7 is set the clock will not be updated (i.e. it is
off). It is set by the operating system service DP$CSET. (LZ)
dpb_cred is the "clock ready" flag, it is used to time the 1/2 second flashing
of the colon. It counts down from 9 to 0 and the top bit is toggled for the flashing colon.
If bit 7 is set, the ":" is printed, otherwise just an underline character. (LZ)
Used in VIEW. Current position in scrolling string.
Minute value when clock last displayed. Used to check whether UDG clock
needs updating. (LZ)
dpb_bord contains the character used for the border when in 2-line
compatibility mode. Default is $F5 (a chequered square). (LZ)
Screen position of menu. Cleared when menu finished, so of little use.
Line of menu. Cleared when menu finished, so of little use. (LZ)
If this byte is set to 1, the entries in the menu will not be capitalized, i.e. they will
appear as they are stored. Default is 0. Once set, ALL menus will appear as they are
stored until the machine is reset or the byte restored to 0. This flag is used by the
operating system in the FORMAT menu "PACK B: PACK C:". (LZ)
Length of time in seconds that should be switched off, if there were no alarms
to be checked. Highest bit set means 'permanent' switch-off (i.e. 2048 seconds). During
the OFF X% command, this word contains X%, and afterwards the high byte is set to
Used to store editor flags, e.g. by LG$EDIT and LG$ENTR. (LZ)
Used to store allocator tag, e.g. by LG$EDIT and LG$ENTR. (LZ)
??? Temporary storage of lxa_curr. (LZ)
tmb_24f stores 2 flags: Bit 7 is set for daylight-saving ON, clear for OFF. Bit
0 is set for 24 hour mode, clear for 12 hour mode. All other bits are reserved. (LZ)
amb_wrkd is used to determine which days of the week are workdays. With
bit 0 representing Monday, bit 1 Tuesday etc. Bits are set for workdays and cleared
otherwise. The top bit is reserved. Setting amb_wrkd to 0 prevents checking for
Workday alarms and removes the option from alarm setting. Note - amb_wrkd should
not be set to $80, as this may cause the machine to lock-up. (LZ)
Old keyboard state. Used to check whether display driver needs updated cursor
These three bytes hold the boundaries between the four WEEK
VIEW "slots". They are stored in quarter-hours, so e.g. a value of 4 would mean 1:00am.
This list shows how a day is divided into 4 slots IN THE WEEK VIEW:
0 (midnight a.m.)
Slot 1 starts
Slot 1 ends/slot 2 begins
Slot 2 ends/slot 3 begins
Slot 3 ends/slot 4 begins
96 (midnight p.m.)
Slot 4 ends
The values in the left hand column must be strictly increasing, and may only be
equal when set to 96. Setting the start time of a slot to 96 disables that slot, and the
flashing arrow in the week view will not move down onto it slot. (LZ)
If this byte is not zero, alarm prompts are enabled in the diary and whenever
the user types an entry and set its time so that its date/start time is greater than the
current system time, an "Alarm? Y/N" prompt is given. If this byte is set to zero, the
prompt will not be given. This feature is provided for users who rarely or never use
alarms in the diary, and who don't want to have to type "N" after each entry. (LZ)
Incremented on every NMI. Used to check whether an NMI has occurred,
regardless of whether btb_ignm was clear. (LZ)
16 character wrap-around buffer, to hold keypresses typed ahead.
This byte stores the length of the keyboard click in ms. A value of zero will turn
off the key click altogether. The default value is 1 giving the shortest possible click.
This flag controls whether the packs are switched off by KB$TEST. If it is non-
zero, which it is by default, the packs will be switched off whenever KB$TEST is called
and there is are no keys in the keyboard buffer.
This byte contains the number of the key (1 to 36) required to be the CAP key.
It is used only by the keyboard translate routine at bta_tran. By default it is set to
32 (the up-arrow key). To disable the CAP key altogether, a number greater than 36
should be stored in kbb_capk.
This byte contains the number of the key required to be the NUM key. It works
in exactly the same way as kbb_capk.
This flag is used to disable the shift key. It is tested only in the keyboard poll
routine at bta_poll. If the flag is set, the SHIFT function is disabled and the SHIFT
key will act as a normal key. Hence, the key translate routine (see bta_tran $205C)
will return the 26th character of its lookup table which is usually a "?" character.
Current year, 0 - 99 (0 - 255 on LZ)
Current month, 0 - 11.
Current date of month, 0 - 30.
Current hour, 0 - 23.
Current minutes, 0 - 59.
Current seconds, 0 - 59. On a cold start, the clock is reset to 1 JAN 1987 (or
1989 on an LZ), 00:00:00. The real-time clock can be read or written directly from these
variables but care should be taken that no NMI occurs while doing so, because the clock
is updated by these interrupts. On the LZ, system services TM$TGET and TM$TSET
can be used to get or set a valid time. On CM/XP machines, you can use btb_nmfl
($5B) to check if an NMI occurred during reading, or use it to wait till one has just
occurred before writing.
tmw_fram is incremented by 1 on each keyboard interrupt. When $FFFF
is reached, it wraps back to $0000. It can be read at any time and used for accurate
Default number of seconds to auto-switch-off. Default is $012C, i.e. 5 mins. If it
is set to less than 15, the machine will set it to 15 secs when next switched on.
Temporary buffer, used in UT$DISP
Save interrupt mask while 'blowing' i.e. while writing to a pack.
An array of 4 elements each 10 bytes long that contain the id string of each of
the 4 devices A:,B:,C: and D: respectively. Set by PK$SETP. Note that these are copies
of the pack headers, which are stored in the first ten bytes of a pack (except for pack
A:). It consists of:
0: an ID byte:
bit 0 is clear for valid Org II pack
bit 1 is clear if it is a ram pack (else an EPROM datapack)
bit 2 is set if the pack is page counted, normally only packs of 8K or 16K
are not paged.
bit 3 is clear if the pack is write protected
bit 4 is clear if the pack is bootable
bit 5 is clear if the pack is not copyable
bit 6 is normally set (reserved for future expansion)
bit 7 is set if the pack is a Organiser I datapack, in which case following
bytes have been converted from old header format on pack.
1: a size byte: size of pack in 8K units, i.e. 8 for a 64K pack.
2-7: a 6 byte time string: indicates when pack was last sized. Has bytes
indicating year, month, date, hour, and free running counter (Timer1) at time of sizing.
If the pack wasn't sized on an organiser this may hold other information.
8/9:2 byte checksum: A word checksum of the first 4 words of the ID
If a pack (or device) is bootable, then the time string is replaced by the following
2: Device/code byte: 1 if this is a hardware device (e.g. comms link), 0 if it is
a software application with no extra hardware. Descriptive purposes only.
3: Device number byte: Non-zero number unique to this device. Used to
identify the devices. Values 1-40, and 80-C0 are reserved to Psion for software resp.
hardware devices. For example, C0 Comms link, BF Bar code reader, BE Swipe reader,
0A Concise oxford spelling checker.
4: Device version byte: Version number, for descriptive purposes only.
5: Device priority byte: Determines order in which devices are booted. Highest
priority first. Usually identical to device number byte.
6/7: Device code address word: Pack address where boot code is located.
10 memory slots for calculator. Each 8 bytes long, in standard floating point
$35 bytes reserved for I/O drivers.
The Comms Link uses this space in the following way:
Length byte. Contains 1B, which means that the next 1B bytes ($2150-6A) are
those that are saved in an .OB4 file.
Handshake. Values 0-7 denote NONE, XON, RTS, XON+RTS, DTR,
DTR+XON, DTR+RTS, ALL. Default is 0 (none).
File transfer protocol. Values 0-2 denote NONE, XMODEM, PSION. Default
is 0 (none).
Echo. Values 0-1 denote LOCAL, HOST for terminal emulation. Default is 0
Width. Values 0-250 where 0 denotes no width. Default is 0 (none).
Timeout for LPRINT in seconds. Values 0-255 where 0 denotes no
REOL string (lbc string of length <=2). Default is 02 0D 0A.
REOF string (lbc string of length <=2). Default is 01 1A.
RTRN string (lbc string of length <=2). Default is 00.
TEOL string (lbc string of length <=2). Default is 02 0D 0A.
TEOF string (lbc string of length <=2). Default is 01 1A.
TTRN string (lbc string of length <=2). Default is 00.
Time to off delay in characters, 1-255. Default is 03.
Time to off delay with XON/XOFF. 1-255. Default is 07.
Time constant value for timer 2 baud rate gen. 0-255.
No. of ticks for baud rate dependent Tx off delay, 0-255.
Time constant for single tick Tx off delay, 0-65535.
General purpose decrement to zero second timer, 0-255. Decrements every
second if non-zero. Used to implement time outs, for example by LPRINT.
Entry point for assembler programs. Contains a jump instruction to the comms
link programs. There are 12 possible function calls, and the instruction 'jsr
rst_entry_point' is followed by a byte (0-11) to indicate which function is needed.
DPB_MODE shows the display mode that is currently in operation, 0 for 2-line
mode, 1 for 4-line mode. To change it DP$MSET must be used. (LZ)
Contains flags to handle the 'special' keys.
Bit 7 - set to disable all special SHIFT keys.
Bit 1 - set to allow SHIFT-SPACE.
Bit 0 - set to allow SHIFT-EXE.
All other bits are reserved. It can be read and written to at any time but should be
preserved around applications. (LZ)
Current language. It has one of the following pre-assigned values: 0 for English
(Default), 1 for French, 2 for German, 3 for Spanish, 4 for Italian, 5 for Portuguese, 6
for Swedish, 7 for Danish, 8 for Norwegian, 9 for Dutch, 10 for Turkish. Note that LZ
machines only have 3 of these available. btb_lang can be read on ALL Organiser
models but to change its value on multi-lingual machines TL$LSET must be used.
Run time buffer length
Run time buffer ($100 long). Can be freely
used in machine code programs. Many OPL commands and functions affect this area.
Keep that in mind when using it to return data from a machine code program back
General purpose buffer for maths + overflow. XP and CM machines (from
version 2.5 onwards) will store the UDG patterns here when switched off.
Overlayed against MTT_WBUF:
Copy of current time when checking alarms
Time one week from now
Find buffer length
4 file control blocks each 4 bytes long. The first byte contains the type of that
file, between 90 and FE, or 0 if no file opened. The next byte contains the device on
which the file exists (0 for A:, 1 for B: etc) Then follows a word containing the current
Alarm table, 6 bytes for each of the 8 alarms. Each entry contains a date-time
in the usual format, i.e. year (0-99)/(0-255 LZ), month (0-11), day (0-30), hour (0-23),
minutes (0-59), followed by a flag indicating the type of alarm. On CM and XP machines
the flag has the following values: 0 means alarm not set, 1 non-repeating, 2 weekly, 3
daily, 4 hourly repeat. On the LZ machines, bits 0-2 give the repeat setting associated
with the alarm: 0 means alarm not set, 1 hourly, 2 daily, 3 workdays, 4 weekly, 5 once.
The top two bits give the associated tone to go with the alarm: 0 Normal, 1 Siren, 2
Chimes. An alarm entry is cancelled by setting the flag byte to zero. Before setting or
modifying any alarms, the flag should be cleared and then set last of all. This is to
prevent interrupts from checking that entry while it is being changed. The date-time of
a repeating alarm is updated each time it rings so an alarm entry does not contain the
LA and LZ only: lowest addr used in low RAM $0400-$1FFF
LA and LZ only: highest addr used in low RAM.
Bit 7 is set to disable the language selection menu. Bit 0 is set to disable the
'second boot' after language selection (second boot allows devices to change language if
necessary). All other bits are reserved. Default is 0. Note that if bit 7 is set, the second
boot will still take place unless bit 0 is set. xtb_cold is reset to zero after language
selection is attempted. (LZ)
Set to skip low battery check when empty keyboard buffer found. (LZ)
reserved to PSION
Disable alarm checking if non-zero.
Temporary variable used checking for alarms
If set then does alarm check on next keyboard interrupt. An NMI sets this flag
when the following conditions hold: btb_ignm is non-zero (else the NMI does
nothing), amb_ei is non-zero (else alarm checking disabled), and tmb_secs is zero
(i.e. we are on a minute boundary).
Table user vector for use with table interpreter IT$STRT.
Table registers for use with table interpreter IT$STRT.
Table stack for use with table interpreter IT$STRT.
Random number seed
Q code offset to stop at
External O code size
Global & local data sizes
Declared variables count
Current branch label number
Symbol table data pointer
End of text pointer
Start of current token
Saved token for un-lex
Saved class for un-lex
Decimal places in calculator display
Last procedure name length
Last procedure name
Set to ignore TRAN option after editing
Extension O code operator code
Return address used in UT$DDSP
Pointer to SWI vector table.
On machines with ROM version 2.4 (mostly early CM models)
this is where the system variables end. The allocator cells then immediately
Later ROM versions (2.5 onwards) also have the following:
Set to skip low battery check.
6 bytes for each of the four packs. Used to store pointers to make file handling
quicker when using files on several packs at the same time. The 6 bytes contain the following:
Current record number
Pointer into flt_cfil, for active file on current pack.
Saves Stack Pointer when LN$STRT is called.
From this point on, the various models differ in their use of
variables. First the single language XP/LA has the following variables:
Holds highest byte of a pack address.
General variables used in file handling???
Saves parameter X in DV$LKUP.
On XP/LA machines this is where the system variables end. The
allocator cells then immediately follow.
Multi-lingual XP/LA machines have the following configuration
Used for system messages/menus. A string in the current language is copied
here from a ROM bank before being used.
Used to hold error message. The error message in the current language is
copied here from a ROM bank before being displayed.
On multi-lingual XP/LA machines this is where the system variables
end. The allocator cells then immediately follow.
The P350 has the same variables as the standard XP/LA, along with
the following ones.
Current RAM bank. (LZ uses 262A instead)
Incremented on every NMI. Used to check whether an NMI has occurred,
regardless of whether btb_ignm was clear. (LZ uses 20AF instead)
On P350 machines this is where the system variables end. The
allocator cells then immediately follow.
The LZ has the same variables as the standard XP/LA, along with
the following ones.
(See P350 above.)
Length of the Paste buffer. (LZ)
Paste buffer. (LZ)
Current RAM bank. (LZ)
Current ROM bank. (LZ)
4-line screen buffer. Used instead of the 2-line buffer at dpt_tlin when in 4-line
Length of name of opened file in Xfiles menu. (LZ)
Name of opened file in Xfiles menu. (LZ)
Pack of opened file in Xfiles menu. (LZ)
Current city in world. (LZ)
Current home in world. (LZ)
Number of half hours difference with GMT. (LZ)
Used by DP$PVEW to store how many non-scrolling characters there are on
the line, so that viewing can be continued later. (LZ)
Used by DP$VIEW and DP$PVEW to store line (0-3) where viewing takes
place, so that viewing can be continued later. (LZ)
End of these system variables, and usually start of first allocator cell
of the LZ.
The LZ has some further system variables at the top of the
Area for saving UDG patterns when off. (LZ)
Area for saving screen contents, used by DP$SAVE and DP$REST, whether in
2 or 4 line mode. (LZ)
System password flag. Bit 0 is set if password exists, bit 1 is set if it is switched
on. Can poke this to zero to remove system password without knowing what it was.
9 byte system password. (LZ)
This byte contains flags for the editor (see LG$EDIT) used with the current
notepad. The following bits are used:
bit 7 - true if numbered
bit 3 - true if on/clear exits editor : do not change
bit 2 - true if prompt to be capitalized
bit 1 - true if no title required
bit 0 - true if changed (used in editor)
The default value for a new notepad is $08 (bit3 set). Note that if bit3 is cleared
then the notepad cannot be exited. This bit is 0 when using the editor with an OPL
procedure where the menu includes the item EXIT. (LZ)
This byte is 0 if the current notepad in memory has no password or the
password length if a password exists. It must not be poked or the editor may attempt to
decrypt unencrypted data or not to decrypt encrypted data etc. which will cause a crash.
9 byte password code of the current notepad. (LZ)
This word contains the current line number in the current notepad. Line 0 is the
line containing the notepad name. This defines which line the cursor is on. This variable
may be poked to change the line number but should not be given a value greater than
the last line number in the notepad. The maximum line number is 1 less than the number
of zero line-delimiters in an unencrypted notepad. (LZ)
This byte contains the cursor position in the current line in the current notepad,
and has a value between 0 and $FE. This variable may be poked to change the cursor
position but should not be given a value greater than the length of the current line.
The following addresses are in the ROM, so their contents can not
Model byte 2. See Model byte 1 (FFE8). Not used on CM/XP machines, and
on these this byte is usually $FF.
Language byte. Its value indicates which languages the organiser has available.
11 languages (English default)
3 languages (English default, French,
3 languages (English default, Spanish,
3 languages (English default, Swedish,
Note that bit 7 is set if the machine is multi-lingual. It is only implemented from
Rom versions 3.6 and later. Earlier Roms are English only, and in those version this byte
is FF. The current language used on a multi-lingual machine is held in btb_lang
Model byte 1. The bottom 3 bits indicate the basic model type.
See model byte 2.
If bits 0-2 are all set, then the basic model type is determined by the bottom three
bits of model byte 2. These further basic types and type 3 have not been produced as far
as I know.
The highest 5 bits of the model byte indicate the special model types. It seems that if bit
4 is set then the machine is a POS model with a standard keyboard, if instead bit 6 is set
then it is an alpha POS model, and bit 7 indicates a normal POS model (numeric keyboard).
If bit 3 is set then the special model type is indicated by the highest 5 bits of model byte
2. If model byte 2 is used then bit 7 indicates an LZ, and bit 6 indicates LCD type (set
for the 66780 chip which allows foreign characters, clear for the standard HD44780 in
earlier models which has Japanese katakana), and bits 3, 4 and 5 are reserved. Note that
bit 5 is set on LZ versions 4.5 onwards. I have been able to verify the following values:
ROM software version number. This is a bcd number, for example, if it contains
$46 the Rom has version number 4.6 etc. LZ machines have versions 4.2 and
Address of IRQ2 interrupt routine. See bta_2iq (2042)
Address of CMI interrupt routine. See bta_cmi (2044)
Address of TRAP interrupt routine. See bta_bug (2046)
Address of SIO interrupt routine. See bta_sio (2048)
Address of TOI interrupt routine. See bta_toi (204A)
Address of OCI interrupt routine. See bta_oci (204C)
Address of ICI interrupt routine. See bta_ici (204E)
Address of IRQ1 interrupt routine. See bta_1iq (2050)
Address of SWI interrupt routine. See bta_swi (2052)
Address of NMI interrupt routine. See bta_nmi (2054)
Address of cold boot routine (usually 8000 on CM/XP's, C000 on LZ's).