EDITOR
from Your Computer, June 1983
(includes corrections from July 1983 letters page)

Trevor Hill dons his green eyeshade and presents a program
which stops you making wrong inputs to your Spectrum.


THIS EDITOR program provides a user-friendly set of routines that will
protect against invalid input as far as possible. The routines have been
located at the top end of RAM, just below the space reserved for user-defined
graphics. Consequently other programs on which you wish to use the routines
may be loaded in the normal manner. The listing is for a 16K Spectrum but
details to relocate the code for a 48K model are included later in the
article. The BASIC program is as program 1.

To enter the menu RUN 9999. The first 11 routines occupy just under 3K of
memory and you will see that provision has been made for a further five
routines. A particular routine is called by input of the appropriate routine
number. Should you accidentally call up one of the last five routines the
program will default to routine 00.

Whenever input is required a prompt message is displayed followed by a
flashing question mark. Any time that input is being requested the routine
may be terminated by use of BREAK (SHIFT+SPACE). Should you make a typing
error it may be corrected by use of DELETE (SHIFT+0). Once input is complete
the flashing question mark remains until you confirm input by ENTER.

In order to illustrate the use of routine 00, which is a disassembler, you
are asked for the start and finish addresses and print details. The routine
knows that addresses must be in hexadecimal and will only accept input of the
correct length. Should you type in a finish address lower than the start
address the routine will be aborted. Input 11 in order to dump to the printer
- any other input will dump to the screen. As in BASIC screen full will give
the Scroll? message. N will terminate the routine, almost any other key will
cause the display to continue.

The disassembler handles correctly all Z-80 instructions and recognises that
RST 08 and RST 28 instructions are followed by data bytes. Since labels are
not included, JR instructions give as part of the mnemonic the absolute jump
address.

Routine 01, the Print Data routine, is similar to routine 00 except that
Output is now Data. In figure 5 [not printed in magazine], routine 02 will
interpret the bytes as character codes. Codes 00 to 1F do not represent
characters and a flashing question mark will be printed whenever the routine
comes across one of these codes.

Routine 03 - Write Code - allows the input of instructions or data. It is
intended that each line of input should correspond to one instruction so the
maximum number of bytes that will be accepted is four. The program knows that
each byte occupies two hex digits, so it will not accept an odd number of
digits. Exit from this routine is by BREAK.

Routine 04 - Write CHR$ - is similar to routine 03 except the input now
represents characters. Numbers, upper and lower case letters and the symbols
in red on the keys - function shift - may be input. I have excluded the
keywords written on the keys and symbols <, <>, > = since the use of the
delete key would mess up the display; these, and the other keywords, will
have to be input using their character codes and routine 03.

Routine 05 - Insert - enables the insertion of code. The present limit is the
highest address to which code has been written. You will see that an
opportunity is given to change the limit value. As code is input, room is
made for it by moving up the existing code between the write address and
limit address. Figure 15 [not printed in magazine] shows the effect of the
input given in figure 8 [not printed in magazine]; exit from the routine is
by BREAK.

Routine 06 - Delete - deletes code from Start address to Finish address. The
purpose of the limit address is as described for routine 5. This time, code
is removed by moving the code after Finish address down memory to Limit
address. The byte immediately after Finish address will end up in Start
address and so on. In both routines 05 and 06 if the relationship between
Start, Finish and Limit addresses does not make sense then the routine will
be aborted.

Routine 07 - Move routine - transfers a block of code to some other location.
The transfer may be up or down memory; the routine will sort out the details.
The code in Start address is moved to Move address, the code in Start address
+ 1 to Move address + 1 and so on. If the move is down memory the limit
address remains unchanged but can be changed by using routine 05 (exit from
routine 05 after changing limit); if the move is up memory then the limit
address is updated automatically.

Routine 08 - Search - enables a block of memory to be searched for a
particular sequence of code. The search code may be from one to eight bytes
in length. This routine is particularly useful if you are thinking of
modifying a sub-routine and you wish to know exactly where in the program it
is being called. The addresses listed are where the start of the code occurs.
Screen full will give the opportunity to Scroll.

Routine 09 - Replace - enables a block of memory to be searched for a
particular sequence of code and wherever it is found, replaced. The code may
be from one to eight bytes in length and once the search length is decided
the routine will only accept a replacement code of the same length. This
routine will be particularly useful later for modifying the program for the
48K Spectrum.

Routine 0A - the Run routine - is used to run other machine-code programs. If
break points are not required then input an address in ROM as the break point
- say 0000. This, of course, will have no effect. The left hand registers are
the main set and the right hand registers the alternative set. You now have
the option of either: continuing to run from the break point with no further
breaks - type in a ROM address; continuing to run with a further break point;
or aborting the routine by BREAK.

There is no limit to the number of break points you use, so single stepping
through a program is possible. Just keep on changing the break point by one
instruction at a time. One word of warning - when a break point is inserted
in a program it actually changes the program by inserting a JP instruction.
As long as you hit the break point the program will be automatically returned
to its original value. If for some reason the break point is not reached you
will have to correct the program manually.

Some possibilities for additional routines that spring to mind are an
assembler, user-defined graphics generator, hex/octal/binary/decimal
conversion routines, two-pass disassembler - but I must move on to
something else.

Table 1 includes the locations where you should store the addresses of your
routines. To modify the menu to display your routine titles only requires the
addition of data starting at 7E86. The menu details start at 7E00 and consist
of the character code corresponding to the routine names. The end of a
message is signified by having bit 7 set.

I have included the first few bytes in table 2 and if you carry on you should
see what modifications to make from 7E86 onwards. You will also of course
have to amend the BASIC program to make more memory available above RAMTOP.
If you decide to have a go at understanding how the program works I would
suggest you leave the disassembler till last since it does call a couple of
complicated routines. In fact the Add String routines can call themselves up
to twice and it is possible to lose track of what is going on myself. The
machine stacks start to look a bit like Clapham Junction.

I keep details of the routines on flow charts and if any one would like a set
I am quite prepared to provide them. But please enclose 1 to cover the cost
of photocopying, postage and overdraft.

Now for the modifications to convert for the 48K model. Use routine 07 - Move
- to locate a copy of the 16K program at the top of RAM. The Start address is
F395, Finish address FF57.

Use routine 09 - Replace - to change the Call, JP, JR and absolute addressing
instructions. In each case start address is F395, finish address FBDE,
search code as in the 16K column of table 3, replace code as in the 48K
column. Next, use routine 03 - Write code - to change the bytes indicated in
table 4. Now, modify the BASIC listing. Save a copy of the program using:
	RUN 9997

To test the 48K version switch the Spectrum off and then on, and LOAD. If all
is well RUN 9999 should take you into the menu.

The 48K version does have one idiosyncrasy - that is a posh way of avoiding
the word bug. Some of the routines detect that they have finished by
comparing the next address with the Finish address. The routines actually
subtract the next address from the Finish address and Return if a Carry is
generated. In the 16K version this is acceptable since the largest address
you will need is 7FFF and when the Start address reaches 8000 the Carry is
produced.

In the 48K version, however, the largest address now possible is FFFF and so
we should stop when the start address moves from FFFF to 010000. But of
course the Z-80 only uses two bytes for addresses, therefore the Start
address actually changes to 0000 and a Carry will not be generated. So be
warned - if your Finish address is FFFF then some of the routines will never
terminate. If this feature of the program upsets you then the routine you
will need to modify is at 79E1 to 79EB.

If anyone intends to modify the ZX-81 version of this program to work in a
64K model then the same problem exists. The routine on the ZX-81 that will
require modification is at 7B81 to 7B8B.

Figure 1 lists a hex loader. RUN 100 to list code, RUN 300 to write code and
RUN 500 to execute code. RUN 9997 to save. The loader is intended to work
with CAPS LOCK on. Terminate Write by inputting S.

To enter the machine code type in the hex loader in figure 1 and then RUN
300. When the program gives the prompt "write to" type the start address in
hex - 73F5 [This should be 7395 to include the missing routine printed in the
next issue. JimG] - and press ENTER. You can now enter the code either in
blocks or an instruction at a time. After entering the instruction at address
7E00 [actually 7EFF] type S to stop, re-run the program and [enter] the two
further sections of code at 7F2B and 7F36.

Finally, if you are interested in the program but do not want to type in such
lengthy code, then I can supply a tape for 3 plus 50p postage and packing
from the following address [address removed].

Program 1.
9996 STOP
9997 SAVE "editor" LINE 9998: SAVE "editor" CODE 29589,3011: STOP
9998 CLEAR 29588: LOAD "editor" CODE: STOP
9999 RANDOMIZE USR 31019


Table 1. Variables

                                     -----------------------------------
                                    |         Routine addresses         |
 -------- -------- -------- -------- -------- -------- -------- --------
| Address|Contents| Address|Contents| Address|Contents| Address|Contents|
 -------- -------- -------- -------- -------- -------- -------- --------
|  7F00  |Variable|  7F28  |Break   |  7F38  | 00  6C |  7F48  | 08  EE |
|        |string  |  7F29  |Point   |  7F39  |     77 |  7F49  |     76 |
|        |        |  7F2A  |code    |  7F3A  | 01  8E |  7F4A  | 09  AE |
|        |        |  7F2B  |C3      |  7F3B  |     79 |  7F4B  |     76 |
|        |        |  7F2C  |CF      |  7F3C  | 02  7C |  7F4C  | 0A  95 |
|        |        |  7F2D  |73      |  7F3D  |     75 |  7F4D  |     73 |
|        |        |  7F2E  |Limit   |  7F3E  | 03  52 |  7F4E  | 0B     |
|  7F1F  |        |  7F2F  |address |  7F3F  |     77 |  7F4F  |        |
|  7F20  |        |  7F30  |Transfer|  7F40  | 04  B7 |  7F50  | 0C     |
|  7F21  |        |  7F31  |address |  7F41  |     75 |  7F51  |        |
|  7F22  |        |  7F32  |Finish  |  7F42  | 05  34 |  7F52  | 0D     |
|  7F23  |        |  7F33  |address |  7F43  |     76 |  7F53  |        |
|  7F24  |        |  7F34  |Start   |  7F44  | 06  09 |  7F54  | 0E     |
|  7F25  |        |  7F35  |address |  7F45  |     76 |  7F55  |        |
|  7F26  |        |  7F36  |String  |  7F46  | 07  37 |  7F56  | 0F     |
|  7F27  |        |  7F37  |address |  7F47  |     75 |  7F57  |        |
 -------- -------- -------- -------- -------- -------- -------- --------


Table 2. Print Data

 -------- -------- -------- -------- -------- --------
| Address|  Byte  |  CHR$  | Address|  Byte  |  CHR$  |
 -------- -------- -------- -------- -------- --------
|  7E00  |   20   |        |  7F00  |   30   |   0    |
|  7E01  |   20   |        |  7F01  |   30   |   0    |
|  7E02  |   20   |        |  7F02  |   20   |        |
|  7E03  |   20   |        |  7F03  |   50   |   P    |
|  7E04  |   4D   |   M    |  7F04  |   52   |   R    |
|  7E05  |   45   |   E    |  7F05  |   49   |   I    |
|  7E06  |   4E   |   N    |  7F06  |   4E   |   N    |
|  7E07  |   D5   |   U    |  7F07  |   54   |   T    |
|  7E08  |   20   |        |  7F08  |   20   |        |
|  7E09  |   20   |        |  7F09  |   43   |   C    |
|  7E0A  |   20   |        |  7F0A  |   4F   |   O    |
|  7E0B  |   20   |        |  7F0B  |   44   |   D    |
|  7E0C  |   3D   |   =    |  7F0C  |   C5   |   E    |
|  7E0D  |   3D   |   =    |  7F0D  |   30   |   0    |
|  7E0E  |   3D   |   =    |  7F0E  |   31   |   1    |
|  7E0F  |   BD   |   =    |  7F0F  |   20   |        |
 -------- -------- -------- -------- -------- --------


Table 3. 48K Changes made using Replace routine
(entries marked '*' are corrections from the July issue)

16K      48K      16K      48K      16K      48K      16K      48K
-------- -------- -------- -------- -------- -------- -------- --------
CD887A   CD88FA   C3A173   C3A1F3   CD857A   CD85FA   267D     26FD
CD987A   CD98FA   CDE474   CDE4F4   21FC7C   21FCFC   2678     26F8
CDA57A   CDA5FA   CDEE74   CDEEF4   216677   2166F7   21007E   2100FE
CDAD7A   CDADFA   CDF974   CDF9F4   DA4176   DA41F6   218C79   218CF9
CDBB7A   CDBBFA   CD0475   CD04F5   2A2E7F   2A2EFF   267F     26FF
CDC57A   CDC5FA   CD2375   CD23F5   ED532E7F ED532EFF 21107E   2110FE
CDC97A   CDC9FA   CDE075   CDE0F5   DAFD76   DAFDF6   21DF79   21DFF9
CDCA7A   CDCAFA   CD6B76   CD6BF6   21367F   2136FF   21007F   2100FF
CDE07A   CDE0FA   CD1F77   CD1FF7   ED5B347F ED5B34FF 11357F   1135FF
CDF07A   CDF0FA   CD3377   CD33F7   222E7F   222EFF   ED5B367F ED5B36FF
CDFA7A   CDFAFA   CD4277   CD42F7   21B77E   21B7FE   ED53367F ED5336FF
CD257B   CD25FB   CD8278   CD82F8   112F7F   112FFF   210F7B   210FFB
CD3B7B   CD3BFB   CD9B7A   CD9BFA   212F75   212FF5   267E     26FE
CDB57B   CDB5FB   CD9378   CD93F8   213175   2131F5   C3FD76   C3FDF6
CDB77B   CDB7FB   CDB478   CDB4F8   11187F   1118FF   ED5B2E7F ED5B2EFF
CDC07B   CDC0FB   CDF578   CDF5F8   21187F   2118FF   212F7A   212FFA
213375   2133F5   CDD478   CDD4F8   ED53347F ED5334FF CDDC78   CDDCF8
11287F   1128FF   CDBF79   CDBFF9   11107F   1110FF   267C     26FC
22307F   2230FF   CDC279   CDC2F9   212D7A   212DFA   212479   2124F9
2A347F   2A34FF   CDE179   CDE1F9   21097D   2109FD   213575   2135F5
2A307F*  2A30FF*  CDE479   CDE4F9   32367F   3236FF   CD747A   CD74FA
ED73307F ED7330FF CDE879   CDE8F9   21F67C   21F6FC   22347F   2234FF
21287F   2128FF   CDEC79   CDECF9   320B7D   320BFD   CD6B7A   CD6BFA
ED58327F ED5B32FF CDFF79   CDFFF9   210A7D   210AFD   22367F   2236FF
21B17E   21B1FE   CD027A   CD02FA   21167D   2116FD   2A327F   2A32FF
11337F   1133FF   CD157A   CD15FA   21FE7C   21FEFC   CD5B7A   CD5BFA
21DF7B   21DFFFB  CD1C7A   CD1CFA   C3C97A   C3C9FA   2A367F   2A36FF
ED5B307F ED5B30FF CD317A   CD31FA   21FD7D   21FDFD
212A75   212AF5   CD367A   CD36FA   21FE78   21FEF8


Table 4. 48K changes using Write Code routine

 -------- -------- -------- --------
| Address|  Byte  | Address|  Byte  |
 -------- -------- -------- --------
|  FF2D  |   F3   |  FF47  |   F5   |
|  FF37  |   FF   |  FF49  |   F6   |
|  FF39  |   F7   |  FF4B  |   F6   |
|  FF3B  |   F9   |  FF4D  |   F3   |
|  FF3D  |   F5   |  FF4F  |   F7   |
|  FF3F  |   F7   |  FF51  |   F7   |
|  FF41  |   F5   |  FF53  |   F7   |
|  FF43  |   F6   |  FF55  |   F7   |
|  FF45  |   F6   |  FF57  |   F7   |
 -------- -------- -------- --------
