Utilities Issue 25 Contents Mind Games

helpline



Andrew Hewson

ZX equivalents

Andrew Hewson explains how you can convert your programs to run on a different machine

PROBLEMS of converting programs written to run on one machine so that they run correctly on another are the subject of a number of queries. Correspondents who have raised the topic include Shawn Woodhouse, Chris Fowler, and Glen Lewis. Most requests concern the conversion of ZX-81 programs to run on the Spectrum but Fowler in particular asked for details on the conversion of ZX-80 programs.

Sinclair Basic is not upwards-compatible, i.e., it is not necessarily possible to transfer a program written for the ZX-80 on to the ZX-81 or Spectrum. Usually, however, only a relatively small number of alterations is required. The converse is not true, because generally a program written for a more sophisticated machine will use facilities which are not present and cannot be emulated on a predecessor. Thus I have assumed readers are interested either in converting ZX-80 programs to run on the ZX-81 or converting ZX-81 programs to run on the Spectrum.

All the software facilities available on the ZX-80 can be mimicked on the ZX81 but the latter machine is less economical of memory space as a consequence of its greater sophistication. For example:

The ZX-81 uses 85 bytes more in the systems variables area; the ZX-81 requires five bytes to hold the value of a variable, thus permitting the use of non-integer numbers, compared to the two bytes used by the integer-only ZX-80. A calculator stack therefore is required; constants in a ZX-81 program are held both in their character and in their numeric form so that an extra six bytes per constant are required; two bytes per program line are used by the ZX-81 to hold the line length.

There is no equivalent usage by the ZX-80. Hence it will often be necessary to prune a 1K ZX-80 program to load it into a ZX-81.


'Usually only a small number of alterations is required'

All ZX-80 commands and functions have exact counterparts on the ZX-81 except for the TL$ function, the DIM command, the division operator and the RND function. These are dealt with as follows:

The TL$ function is a special case of the ZX-81 slicing facility and is replaced by (2 TO). For example:

LET A$= TL$(A$) becomes LET A$=A$(2 TO).

Array indices start at 0 on the ZX-80 and 1 on the ZX-81 so that

DIM B(5)
PRINT B(0)

is meaningful only on the ZX-80. Hence one is added to every array subscript.

Numbers are converted to integers explicitly on the ZX-81 using the INT function before division. For example:

LET B=B/5 becomes LET B=INT (B)/5

The ZX-80 random number function RND (N) generates a random integer between 1 and N inclusive, whereas on the ZX-81 RND generates a random number in the range 0 to 1. Thus, for example:

LET A=RND(N) becomes LET A=I+INT(N*RND)

The character codes used by the ZX81 are listed in appendix A of the operating manual. The codes for both letters and numbers in both normal and inverse video are the same as those used by the ZX-80 but the remainder are mostly different. Table one lists the ZX-81 equivalents for the non-alphabetic or numeric codes used by the ZX-80. Reference should be made to the table when converting CHR$ or CODE commands.

ZX-80 CodeCharacterZX-81 CodeZX-80 CodeCharacterZX-81 Code
0space0148inverse *151
1space11149inverse /152
2graphics5150inverse =148
3graphics131151inverse >146
4graphics1152inverse <147
5graphics2153inverse ;153
6graphics4154inverse ,154
7graphics135155inverse .155
8graphics6212"11
9graphics8213THEN222
10graphics9214TO223
11graphics10215;25
12£12216,26
13$13217)17
14:14218(16
15?15219NOT215
16(16220-22
17)17221+21
18-22222*23
19+21223/24
20*23224AND218
21/24225OR217
22=20226216
23>18227=20
24<19228>18
25;25229<19
26,26230LIST240
27.27231RETURN254
128graphics128232CLS251
129inverse "139233DIM233
130graphics133234SAVE248
131graphics3235FOR235
132graphics129236GOTO236
133graphics130237POKE244
134graphics132238INPUT238
135graphics7239RAND249
136graphics134240LET241
137graphics136243NEXT243
138graphics137244PRINT245
139graphics138246NEW230
140inverse £140247RUN247
141inverse $141248STOP227
142inverse :142249CONT232
143inverse ?143250IF250
144inverse (144251GOSUB237
145inverse )145252LOAD239
146inverse -150253CLEAR253
147inverse +149254REM234
Table 1. A list of ZX-80 character codes and their ZX-81 equivalents.

The ZX-80 uses fewer system variables than the ZX-81 and most of them have direct equivalents as listed in table two. Note that the variables area occurs below the display file in the ZX-80 but above it in the ZX-81 and so conversion of a program which manipulates the VARS, D-FILE and DF-CC variables is particularly difficult.

ZX-80 addressNo. of bytesZX-81 addressZX-81 name
16384116384ERR-NR
163851  
16386216391PPC
163882  
16390216394E-PPC
16392216400VARS
16394216404E-LINE
16396216396D-FILE
16398216398DF-CC
16400216400VARS
16402116418DF-SZ
164032  
16405216408X-PTR
16407216427OLDPPC
164091  
16410216432T-ADDR
16412216434SEED
16414216436FRAMES
164162  
164182  
16420116441S-POSN
16421116442 
164222  
Table 2. ZX-80 system variables and their ZX-81 equivalents.

On the ZX-80 the FRAMES counter is incremented 50 times per second, whereas on the ZX-81 it is decremented, except bit 15, and that difference should be taken into account during program conversion.

Just as the ZX-81 uses more RAM space than the ZX-80, so, in turn, the Spectrum uses more than the ZX-81. The principal reason is the high-resolution Spectrum display which uses 6,912 of the 16,384 bytes in RAM in the 16K Spectrum, compared to 792 bytes used by the 16K ZX-81. So it is unlikely that a full-size 16K ZX-81 program can be adapted to run in a 16K Spectrum.

Table three lists the ZX-81 character codes which have a direct Spectrum equivalent. In a few cases the character is different, although the function is the same, in which case both versions are shown in the table. For example, the exponentiation operator is ** on the ZX-81 - code 216 - and ^ on the Spectrum - code 94.

ZX-81 codeCharacterSpectrum codeZX-81 codeCharacterSpectrum code
0space32 or 128118NEWLINE/ENTER13
1graphics130119RUBOUT/DELETE12
2graphics129126number14
3graphics131128graphics143
4graphics136129graphics141
5graphics138130graphics142
6graphics137131graphics140
7graphics139132graphics135
11"34133graphics133
12£96134graphics134
13$36135graphics132
14:58193AT172
15?63194TAB173
16(40196CODE175
17)41197VAL176
18>62198LEN177
19<60199SIN178
20=61200COS179
21+43201TAN180
22-45202ASN181
23*42203ACS182
24/47204ATN183
25;59205LN184
26,44206EXP185
27.46207INT186
28048208SQR187
29149209SGN188
30250210ABS189
31351211PEEK190
32452212USR192
33553213STR$193
34654214CHR$194
35755215NOT195
36856216**/^94
37957217OR197
38A65218AND198
39B66219<=199
40C67220>=200
41D68221<>201
42E69222THEN203
43F70223TO204
44G71224STEP205
45H72225LPRINT224
46I73226LLIST225
47J74227STOP226
48K75230NEW230
49L76232CONT/CONTINUE232
50M77233DIM233
51N78234REM234
52O79235FOR235
53P80236GOTO/GO TO236
54Q81237GOSUB237
55R82238INPUT238
56S83239LOAD239
57T84240LIST240
58U85241LET241
59V86242PAUSE242
60W87243NEXT243
61X88244POKE244
62Y89245PRINT245
63Z90247RUN247
64RND165248SAVE248
65INKEY$166249RAND/ 
66PI167 RANDOMIZE249
112cursor up11250IF250
113cursor down12251CLS251
114cursor left8253CLEAR253
115cursor right9254RETURN254
117EDIT7255COPY255
Table 3. ZX-81 character codes and their Spectrum equivalents.

Much of the software which runs the calculator in the Spectrum has been copied straight from the ZX-81 and that is reflected in the manner in which the character codes in the two machines, although dissimilar, march in step. The ZX-81 codes for AT, TAB, CODE through to NOT are all 21 more than the codes for the same characters on the Spectrum. It is intriguing to note that the VAL$ function, which is present on the Spectrum - code 174 - but is not present on the ZX-81 logically would have had a ZX-81 code of 195, a code which is "not used" according to appendix A of the ZX-81 manual.

Bearing in mind that the ZX-81 was designed and built long before the Spectrum, the implication is that Sinclair intended that the ZX-81 should have a VAL$ function but it was omitted at the last minute.

ZX-81 graphics codeSpectrum user-defined graphic equivalent
8170,85,170,85,170,85,170,85
90,0,0,0,170,85,170,85
10170,85,170,85,0,0,0,0
13685,170,85,170,85,170,85,170
137255,255,255,255,85,170,85,170
13885,170,85,170,255,255,255,255
Table 4. Definitions of Spectrum UDG characters for ZX-81 graphics
characters not present in the standard Spectrum character set.

Six half-tone graphics characters in the ZX-81 do not appear in the Spectrum character set but it is a straightforward matter to create user-defined characters as required. The data for each of the characters is listed in table four. Five more ZX-81 characters have no Spectrum equivalent:

It is unlikely that any of the first three would be used explicitly in a program and so no substitute is given. The FAST command turns the ZX-81 display, speeding program execution by a factor of about four and the SLOW command turns it on again. Those commands can almost always be omitted when a program is transferred to the Spectrum, except when the FAST command has been included to prevent the user inspecting the display, in which case CLS can be substituted.

Finally, there are four characters which require special substitutes. They are "" - the paired double quotes character - SCROLL, PLOT and UNPLOT. They are dealt with as follows:

The paired double quotes character, which denotes a string within a string, is replaced by two successive double quotes characters.

The SCROLL command, which moves the display up by one line, is replaced by INPUT;.

PLOT X,Y is replaced by PLOT 4 * X + 2, 4 *Y + 2. The latter is not identical because the Spectrum pixel size is much smaller and the point will appear slightly off=centre but the difference is unlikely to be important.

UNPLOT X,Y is replaced by PLOT INVERSE 1;4*X + 2,4*Y + 2.


'It is essential to understand the function of the code'

Table five lists the ZX-81 system variables and the Spectrum equivalents. There are several points to be noted:

The ZX-81 system variable D-FILE at 16396 which points to the beginning of the display file has no Spectrum equivalent, because the Spectrum display lies at the bottom of RAM at address 16384.

The FRAMES counter is two bytes long on the ZX-81 - and bits 0 to 14 only are used - and three bytes long on the Spectrum.

The COORDS variables are different, reflecting the difference in the PLOT resolution in the two machines.

The ZX-81 printer buffer, PRBUFF, is 33 bytes long and lies within the system variables area starting at address 16444. The Spectrum printer buffer is 256 bytes long, so that it can hold high-resolution characters, and lies below the systems variables area.

ZX-81 addressNo. of bytesSpectrum addressSpectrum name
16384123610ERR NR
16386223613ERR SP
16388223730RAMTOP
16390123617MODE
16391223621PPC
16394223625E PPC
163962  
16398223684DF CC
16400223627VARS
16402223629D EST
16404223641E LINE
16406223645CH ADD
16408223647X PTR
16410223650STKBOT
16412223653STKEND
16414123655BREG
16415223656MEM
16418123659DF SZ
16419223660STOP
16421223560LAST K
16423123552KSTATE
16425223637NXTLIN
16427223662OLD PPC
16430223666STRLEN
16432223668T ADDR
16434223670SEED
16436223672FRAMES
16438123677COORDS
16439123678COORDS
16440123680PR CC
16441123688S POSN (col)
16442123689S POSN (lin)
164442223296PRBUFF
164773023698MEMBOT
Table 5. ZX-81 system variables and their Spectrum equivalents.

A word of warning. It is not possible to guarantee that a given program can be transferred from one machine to its successor. If the program author has made use of PEEKs or POKEs, it is essential to understand the function of his code on the original machine before designing the equivalent to run elsewhere. Usually that means entering the code into the first machine and analysing it dynamically.



Utilities Issue 25 Contents Mind Games

Sinclair User
April 1984