The Psion organiser has many features built into its ROM, and some of these can be called from machine code using the SWI instruction. The SWI instruction is followed by a byte indicating which of the system services you want. The SWI instruction calls a routine in the ROM which performs the task required, and after that has finished the program execution continues at the instruction which follows immediately after the service byte.
Most services need some parameters. Mostly the registers (A,B and X) will contain the information required by the service, but sometimes further information is needed which is often put in the scratch registers UTW_S0 and UTW_S1, at address $41/42 and $43/44 respectively. Sometimes the runtime buffer RTT_BF ($2188-$2287 with length byte RTT_BL $2187) is needed too. Information is passed back from the system services in the same way. Unless otherwise noted, assume the contents of the registers A,B,X and the scratch registers UTW_S0-5 are trashed by the system services.
Some services can not always perform their tasks, and an error can be returned. A service shows an error has occurred by returning with the carry flag set, and with B containing the error code. The error codes are the same as those used in OPL. Some services that can never return an error may not always clear the carry flag, so the carry flag should only be tested after services that can cause errors.
The scratch registers UTW_S0 to UTW_S5 (which lie between $41 and $4C) are used by most services, so any values stored there will most likely be trashed. You can freely use these addresses yourself as long as you keep in mind that the information stored there is lost by calling the operating system. See also BT$PPRG if more scratch variables are needed.
Note that strings are usually leading byte-count strings, which will from now on be abbreviated by 'lbc string'. An lbc string is a string of (ascii) characters which is preceded by a length byte. Thus the word 'hello' would be stored in lbc form as 05,68,65,6C,6C,6F in hex. The address of an lbc string is the address of the length byte, not the address of the first character.
Here is an alphabetic list of all the operating system services. Each service has a short name. This allows us to use a slightly more descriptive way of denoting the SWI instruction. Instead of SWI 0 for example, we now write OS AL$FREE instead. A very short description is also given. Those marked with an asterisk are available on the LZ only, and those with a plus sign only on the LZ and later versions of the CM/XP.
AL$FREE | 000 | 00 | Free an allocator cell |
AL$GRAB | 001 | 01 | Grab an allocator cell |
AL$GROW | 002 | 02 | Grow an allocator cell |
AL$REPL | 003 | 03 | Change cell size for a part replacement |
AL$SHNK | 004 | 04 | Shrink an allocator cell |
AL$SIZE | 005 | 05 | Get size of an allocator cell |
AL$ZERO | 006 | 06 | Clear an allocator cell |
AM$ENTR | 158 | 9E* | Alarm entry |
BT$NMDN | 007 | 07 | Disable NMI, makes system clock invalid. |
BT$NMEN | 008 | 08 | Enable NMI which were switched off by BT$NMDN |
BT$NOF | 009 | 09 | Disable NMI, keeping track of elapsed time for the system clock |
BT$NON | 010 | 0A | Enables NMI which were switched off by BT$NOF, corrects clock |
BT$PPRG | 011 | 0B | Push or Pop system variables UTW_R0 to UTW_R6 |
BT$SWOF | 012 | 0C | Switches off the Psion, like menu option OFF |
BT$TOFF | 129 | 81* | Temporary switch off |
BZ$ALRM | 013 | 0D | Sound the alarm once |
BZ$BELL | 014 | 0E | Emits a standard beep |
BZ$TONE | 015 | 0F | Emits a beep with specified length & pitch |
CA$ENTR | 160 | A0* | Calculator entry |
DI$ENTR | 167 | A7* | Enter diary |
DP$CPRN | 132 | 84* | Redefine UDG-clock |
DP$CSET | 131 | 83* | Set UDG-clock status |
DP$EMIT | 016 | 10 | Output single character to the display |
DP$MSET | 130 | 82* | Set display mode |
DP$PRNT | 017 | 11 | Display a string |
DP$PVEW | 163 | A3* | Partial view string |
DP$REST | 018 | 12 | Restore screen to previously saved state |
DP$SAVE | 019 | 13 | Save screen state (use DP$REST to restore) |
DP$STAT | 020 | 14 | Move cursor and change its status |
DP$UDG | 133 | 85* | Read/write UDG |
DP$VIEW | 021 | 15 | Display a string, like the OPL VIEW instruction |
DP$WRDY | 022 | 16 | Wait until system variable DPW_REDY is zero |
DV$BOOT | 023 | 17 | Boot all devices |
DV$CLER | 024 | 18 | Unboot all devices |
DV$LKUP | 025 | 19 | Language lookup (checks each device) |
DV$LOAD | 026 | 1A | Load relocatable code from a pack |
DV$VECT | 027 | 1B | Find and run device code |
ED$EDIT | 028 | 1C | Calls the line editor ED$EPOS, with cursor at beginning. |
ED$EPOS | 029 | 1D | The built-in editor |
ED$VIEW | 030 | 1E | Clears screen, displays a string, like OPL command DISP |
ER$LKUP | 031 | 1F | Look up an error string, given an error number |
ER$MESS | 032 | 20 | Displays an error message given an error number |
ER$PRNT | 169 | A9* | Display string as error message |
FL$BACK | 033 | 21 | Works like OPL command BACK in ordinary files |
FL$BCAT | 034 | 22 | Like OPL function DIR$, works on all file types |
FL$BDEL | 035 | 23 | Deletes a block file with type $82 to $8F |
FL$BOPN | 036 | 24 | Opens a block file with type $82 to $8F |
FL$BSAV | 037 | 25 | Saves a block file with specified type |
FL$CATL | 038 | 26 | Like OPL function DIR$, works on ordinary files |
FL$COPY | 039 | 27 | Copy ordinary or block files (device to device) |
FL$CRET | 040 | 28 | Creates an ordinary file, like OPL command CREATE |
FL$DELN | 041 | 29 | Deletes an ordinary file, like OPL command DELETE |
FL$ERAS | 042 | 2A | Erases current record, like OPL command ERASE |
FL$FDEL | 176 | B0* | Fast delete records |
FL$FFND | 043 | 2B | Find record with given start string on current pack |
FL$FIND | 044 | 2C | Find record containing given string on current pack |
FL$FREC | 045 | 2D | Returns info on given record on current pack |
FL$GETX | 152 | 98* | Convert file extension to type |
FL$NCAT | 157 | 9D* | Catalogue Nth file with wild card |
FL$NEXT | 046 | 2E | Move to next record, like OPL command NEXT |
FL$OPEN | 047 | 2F | Open an existing ordinary file |
FL$PARS | 048 | 30 | Check given filename is legal |
FL$READ | 049 | 31 | Read current record |
FL$RECT | 050 | 32 | Set current record type |
FL$RENM | 051 | 33 | Renames an ordinary file |
FL$RSET | 052 | 34 | Make given record current, like OPL command POSITION |
FL$SETP | 053 | 35 | Select a datapack |
FL$SIZE | 054 | 36 | Returns free space on current datapack |
FL$VALX | 153 | 99* | Convert file type to extension |
FL$WCAT | 144 | 90* | Catalogue files with wild card |
FL$WCPY | 145 | 91* | Copy files with wild card |
FL$WDEL | 146 | 92* | Delete files with wild card |
FL$WFND | 147 | 93* | Find file record with given text with wild card |
FL$WPAR | 143 | 8F* | Check wild card filename |
FL$WRIT | 055 | 37 | Appends new record to current device, like APPEND |
FN$ACOS | 173 | AD* | Finds arccosine of a floating point number |
FN$ASIN | 172 | AC* | Finds arcsine of a floating point number |
FN$ATAN | 056 | 38 | Finds arctangent of a floating point number |
FN$COS | 057 | 39 | Finds cosine of a floating point number |
FN$EXP | 058 | 3A | Finds "e to power of a floating point number" |
FN$LN | 059 | 3B | Find natural logarithm of floating point number |
FN$LOG | 060 | 3C | Finds logarithm of a floating point number |
FN$MAX | 142 | 8E* | Maximum of list of numbers |
FN$MEAN | 138 | 8A* | Mean of list of numbers |
FN$MIN | 141 | 8D* | Minimum of list of numbers |
FN$POWR | 061 | 3D | Finds x**y, where x & y are floating point nums |
FN$RND | 062 | 3E | Finds a random number between 0 and 1 |
FN$SIN | 063 | 3F | Finds sine of a floating point number |
FN$SQRT | 064 | 40 | Finds square root of a floating point number |
FN$STD | 140 | 8C* | Standard deviation of list of numbers |
FN$SUM | 137 | 89* | Sum of list of numbers |
FN$TAN | 065 | 41 | Finds tangent of a floating point number |
FN$VAR | 139 | 8B* | Variance of list of numbers |
IT$GVAL | 066 | 42 | Used to get value of a byte parameter in table interpreter routine |
IT$RADD | 067 | 43 | Used to get memory address of a variable param in table interpreter routine |
IT$STRT | 068 | 44 | The table interpreter |
IT$TADD | 069 | 45 | Used to get value of a word parameter in table interpreter routine |
KB$BREK | 070 | 46 | Test if ON/CLEAR is pressed |
KB$CONK | 177 | B1* | Cursor on and get key |
KB$FLSH | 071 | 47 | Flush the keyboard buffer |
KB$GETK | 072 | 48 | Wait for a single character from keyboard |
KB$INIT | 073 | 49 | Initialises keyboard (OCI) interrupts |
KB$STAT | 074 | 4A | Set the keyboard state, similar to OPL KSTAT |
KB$TEST | 075 | 4B | Test keyboard buffer, return ASCII key if found |
KB$UGET | 076 | 4C | Put ASCII character in the 'unget' buffer |
LG$EDIT | 171 | AB* | Enter text editor |
LG$ENTR | 175 | AF* | Enter prog |
LG$NEWP | 077 | 4D | Makes a new text block file |
LG$RLED | 078 | 4E | Perform RUN/LIST/EDIT/DELETE on existing file |
LN$STRT | 079 | 4F | Runs the translator |
LN$XSTT | 154 | 9A* | LZ translate procedure or calc expression |
MN$1DSP | 135 | 87* | One line menu |
MN$DISP | 080 | 50 | Displays a menu, like OPL function MENU |
MN$TITL | 136 | 88* | Menu with icon and clock |
MN$XDSP | 134 | 86* | Titled menu |
MT$BTOF | 081 | 51 | Converts ASCII string to floating point number |
MT$FADD | 082 | 52 | Adds two floating point numbers |
MT$FBDC | 083 | 53 | Convert floating point to ASCII in fixed decimal format, like FIX$ |
MT$FBEX | 084 | 54 | Convert floating point to ASCII in exponent format, like SCI$ |
MT$FBGN | 085 | 55 | Convert floating point to ASCII in general format, like GEN$ |
MT$FBIN | 086 | 56 | Convert floating point to ASCII in integer format, like NUM$ |
MT$FDIV | 087 | 57 | Divides two floating point numbers |
MT$FMUL | 088 | 58 | Multiplies two floating point numbers |
MT$FNGT | 089 | 59 | Negates a floating point number |
MT$FSUB | 090 | 5A | Subtracts two floating point numbers |
NT$ENTR | 159 | 9F* | Notepad entry |
PK$PKOF | 091 | 5B | Turns off all packs |
PK$QADD | 092 | 5C | Returns current pack address |
PK$RBYT | 093 | 5D | Reads a byte from current position in current pack |
PK$READ | 094 | 5E | Copies bytes from current position in current pack |
PK$RWRD | 095 | 5F | Reads a word from current position in current pack |
PK$SADD | 096 | 60 | Sets current pack address |
PK$SAVE | 097 | 61 | Copies bytes to current position in current pack |
PK$SETP | 098 | 62 | Sets current pack |
PK$SKIP | 099 | 63 | Skips bytes by updating current pack address |
RM$RUNP | 100 | 64 | Loads/runs an OPL procedure or runs the calc |
TI$ENTR | 164 | A4* | Enter time |
TL$ADDI | 101 | 65 | Add an item to the top menu |
TL$CPYX | 102 | 66 | Performs the COPY function from standard menu |
TL$DELI | 103 | 67 | Delete item from the top menu |
TL$LSET | 128 | 80+ | Selects the language for menus. MULTI-LINGUAL MACHINES ONLY. |
TL$RSTR | 127 | 7F+ | Restores several top-level menu entries. VERSION 2.7+ ONLY. |
TL$XXMD | 104 | 68 | Clear screen, show prompt, enter filename |
TL$ZZMD | 155 | 9B* | Edit filename, screen not pre-cleared |
TM$DAYV | 105 | 69 | Calculate day of the week from a given date |
TM$DNAM | 151 | 97* | Get weekday name |
TM$MNAM | 170 | AA* | Get month name |
TM$NDYS | 149 | 95* | Get days since 1/1/1900 |
TM$TGET | 106 | 6A | Copies system time to a given buffer |
TM$TSET | 179 | B3* | Set system time |
TM$UPDT | 107 | 6B | Add a value to date/time held in a buffer |
TM$WAIT | 108 | 6C | Wait for a number of clock ticks |
TM$WEEK | 150 | 96* | Get week number |
UT$CDSP | 126 | 7E+ | Like UT$DISP but screen is cleared first. VERSION 2.5+ ONLY. |
UT$CMPB | 178 | B2* | Compare buffer, case dependent |
UT$CPYB | 109 | 6D | Copy bytes from one place to another in RAM |
UT$DDSP | 110 | 6E | Display a format control string from given addr |
UT$DISP | 111 | 6F | Display an 'inline' format control string |
UT$ENTR | 112 | 70 | Calls a routine at given address |
UT$FILL | 113 | 71 | Fills a number of bytes with a given value |
UT$ICPB | 114 | 72 | Compare two ASCII strings, ignoring case |
UT$ISBF | 115 | 73 | Find a string within another, like OPL function LOC |
UT$LEAV | 116 | 74 | Used to exit from a routine entered via UT$ENTR |
UT$SDIV | 117 | 75 | Divides signed integers |
UT$SMUL | 118 | 76 | Multiplies signed integers |
UT$SORT | 165 | A5* | General sort utility |
UT$SPLT | 119 | 77 | Finds address/length of a field in a string |
UT$UDIV | 120 | 78 | Divides unsigned integers |
UT$UMUL | 121 | 79 | Multiplies unsigned integers |
UT$UTOB | 122 | 7A | Convert unsigned integer to ASCII decimal |
UT$WILD | 148 | 94* | Search string for substring with wild cards |
UT$XCAT | 123 | 7B | Display all filenames of given type on current pack |
UT$XTOB | 124 | 7C | Convert unsigned integer to ASCII hex format |
UT$YSNO | 125 | 7D | Wait for Y,y,N,n or ON/CLEAR to be pressed |
WL$ENTR | 166 | A6* | Enter world |
XF$ENTR | 168 | A8* | Enter Xfiles |
XF$SORT | 174 | AE* | Sort file |
XT$BAR | 162 | A2* | Create UDG bar graph |
XT$DIRM | 156 | 9C* | Do directory on screen |
XT$ENTR | 161 | A1* | Do utility application |
Allocator errors | ||
255 | FF | NO ALLOC CELLS |
254 | FE | OUT OF MEMORY |
Calculator errors | ||
253 | FD | EXPONENT RANGE |
252 | FC | STR TO NUM ERR |
251 | FB | DIVIDE BY ZERO |
250 | FA | NUM TO STR ERR |
249 | F9 | STACK OVERFLOW |
248 | F8 | STACK UNDERFLOW |
247 | F7 | FN ARGUMENT ERR |
Pack errors | ||
246 | F6 | NO PACK |
245 | F5 | WRITE PACK ERR |
244 | F4 | READ ONLY PACK |
243 | F3 | BAD DEVICE NAME |
242 | F2 | PACK CHANGED |
241 | F1 | PACK NOT BLANK |
240 | F0 | UNKNOWN PACK |
File system errors | ||
239 | EF | PACK FULL |
238 | EE | END OF FILE |
237 | ED | BAD RECORD TYPE |
236 | EC | BAD FILE NAME |
235 | EB | FILE EXISTS |
234 | EA | FILE NOT FOUND |
233 | E9 | DIRECTORY FULL |
232 | E8 | PAK NOT COPYABLE |
Device system errors | ||
231 | E7 | BAD DEVICE CALL |
230 | E6 | DEVICE MISSING |
229 | E5 | DEVICE LOAD ERR |
Translator errors | ||
228 | E4 | SYNTAX ERR |
227 | E3 | MISMATCHED ()'s |
226 | E2 | BAD FN ARGS |
225 | E1 | SUBSCRIPT ERR |
224 | E0 | TYPE MISMATCH |
223 | DF | NAME TOO LONG |
222 | DE | BAD IDENTIFIER |
221 | DD | MISMATCHED " |
220 | DC | STRING TOO LONG |
219 | DB | BAD CHARACTER |
218 | DA | BAD NUMBER |
217 | D9 | NO PROC NAME |
216 | D8 | BAD DECLARATION |
215 | D7 | BAD ARRAY SIZE |
214 | D6 | DUPLICATE NAME |
213 | D5 | STRUCTURE ERR |
212 | D4 | TOO COMPLEX |
211 | D3 | MISSING LABEL |
210 | D2 | MISSING COMMA |
209 | D1 | BAD LOGICAL NAME |
208 | D0 | BAD ASSIGNMENT |
207 | CF | BAD FIELD LIST |
Runtime errors | ||
206 | CE | ESCAPE |
205 | CD | ARG COUNT ERR |
204 | CC | MISSING EXTERNAL |
203 | CB | MISSING PROC |
202 | CA | MENU TOO BIG |
201 | C9 | FIELD MISMATCH |
200 | C8 | READ PACK ERR |
199 | C7 | FILE IN USE |
198 | C6 | RECORD TOO BIG |
197 | C5 | BAD PROC NAME |
196 | C4 | FILE NOT OPEN |
195 | C3 | INTEGER OVERFLOW |
General errors | ||
194 | C2 | BATTERY TOO LOW |
193 | C1 | DEVICE READ ERR |
192 | C0 | DEVICE WRITE ERR |
191 | BF | Not used. ER$LKUP uses it as a marker for the end of the error table in ROM |
External errors | ||
These are not used in the ROM, so they have no standard error messages. Peripherals can cause these errors. | ||
General device errors | ||
190 | BE | Bad Parameter |
Comms link errors | ||
189 | BD | File Not Found |
188 | BC | Server Error |
187 | BB | File Already Exist |
186 | BA | Disk Full |
185 | B9 | Record Too Long |
Printer errors | ||
184 | B8 | Printer Battery Low |
183 | B7 | Printer Time Out |
182 | B6 | Printer Escape |
Here are the various file type used by the Psion, and the extensions used in filenames on the LZ. Note that these are not the extensions used by the comms link for PC filenames. The comms link uses only ODB, OPL (text only procedure) and OBx where x is in the range 2-F.
81 | ODB | Filenames of ordinary data files, including LZ diary files | |
82 | DIA | CM/XP diary files | |
83 | 00 | OPL | OPL procedures, both opl source and object code |
01 | OPO | OPL procedures, object code only. | |
02 | OPT | OPL procedures, opl source only. | |
84 | COM | Comms-link setup files | |
85 | PLN | Spreadsheet files | |
86 | PAG | Pager files | |
87 | NTS | LZ Notepad files | |
88 | TY8 | Not used | |
89 | TY9 | Not used | |
8A | TYA | Not used | |
8B | TYB | Not used | |
8C | TYC | Not used | |
8D | TYD | Not used | |
8E | TYE | Not used | |
8F | TYF | Not used |
The file type 82-8F are block files, which means that the record containing the filename is immediately followed by a single data block (which internally uses file type 80). Records of type 81 are used to store the names of ordinary data files but no further data other than the file type of its data records which lies in the range 90-FE. Since each ordinary file must have a unique data record type in that range, there can be only 111 ordinary files on a pack. The MAIN file is always assigned type 90 for its data. Note that the filetypes 00-7F are used to signify deleted records on a pack, and that FF is used for error correcting purposes.
The following character codes will, when printed, not produce a character but control the screen or cursor in some way.
0-7 | 00-07 | Prints a UDG character |
8 | 08 | Moves the cursor left 1 character |
9 | 09 | Moves the cursor to next position modulo 8 (or 10 on an LZ) |
10 | 0A | Moves the cursor down one line |
11 | 0B | Moves the cursor to top left of the screen |
12 | 0C | Clears the screen |
13 | 0D | Moves the cursor to left of the current line |
14 | 0E | Clears the 1st line, and cursor is placed on the left of that line. |
15 | 0F | Clears the 2nd line, and cursor is placed on the left of that line. |
16 | 10 | Emits a standard beep (see also BZ$BELL) |
17 | 11 | Refreshes the 1st and 2nd line of the display from the buffer |
18 | 12 | Refreshes the 1st line of the display from the buffer |
19 | 13 | Refreshes the 2nd line of the display from the buffer |
On the LZ the following are also available. | ||
20 | 14 | Refreshes the 3rd line of the display from the buffer |
21 | 15 | Refreshes the 4th line of the display from the buffer |
22 | 16 | Clears the 3rd line, and cursor is placed on the left of that line. |
23 | 17 | Clears the 4th line, and cursor is placed on the left of that line. |
24 | 18 | Puts dots on line 2, clears line 1, and moves cursor to left of 1st line. |
25 | 19 | Puts dots on line 3, clears line 4, and moves cursor to left of 4th line. |
26 | 1A | Clears till the end of the current line. |