On Loading

The program presented here creates a modified LOAD command. It moves the routines needed for the LOAD from ROM into RAM and adjusts them to work there. The routines are changed so that when the LOAD completes, machine language code from the 1 REM statement is executed. By changing statement 1, you can completely control what occurs after the LOAD.

Background Information

When a program is SAVEd, the ZX/TS computer begins by writing a lead-in of five seconds of silence. Then it writes the program name (“header”), followed by the four parts of the program: the system variables, the BASIC program, the display file (i.e. the television picture,) and the BASIC program variables. When reloading the program, the LOAD command reads the tape until it finds the header with the program name, and then loads the four parts of the program into the computer.

Two routines are used by the LOAD command. These are the load routine (locations 0340-03A1h of ROM) and the terminate routine (01FC-0206.) Every time the load routine reads a character from tape and writes it into the computer, it calls the terminate routine which checks to see if the end of the program has been reached. When it finally gets to the end, the terminate routine does not return control to the load routine; instead, the code immediately after the routine is executed. Normally this is the display routine.

The program shown here moves the terminate routine and the load routine, as well as everything between them, to the top 1K of RAM. The address of the assembler statements (the CALLs and JPs) are adjusted to work in the new location. Then, before calling the LOAD command in RAM, the program moves the machine-code in the 1 REM statement into the area of RAM immediately after the terminate routine. This code will execute after the LOAD finishes. Two possible versions of this modified LOAD command will demonstrate what can be accomplished by carefully selecting the code tht is stored in the 1 REM statement.

SAVE the UnSAVEable

Suppose you purchase a self-running program and you wish to make a back-up copy. This is difficult or impossible to do the usual way because as soon as you load the program, it executes. Verson 1 of the modified LOAD command solves this problem. We have seen that when the LOAD command in RAM completes, the code from 1 REM executes. In version 1 of the modified LOAD, this code calls the keyboard scanning routine until the “S” key is pressed. Then the address of the name of the program to be saved is set to a location in ROM that happens to contain an inverse “X.” Finally, a jump is made directly to the SAVE routine in ROM.

Type in the program of version 1. Type RUN, then ENTER. The screen will become white while the code is being moved from ROM to RAM. When the modified LOAD command begins to execute, the loading pattern will appear on the screen. Start playing the tape that you wish to back up. The loading pattern will continue until the load completes, and then the screen will turn gray. Place a blank tape in the recorder, switch the cassette lead to the MIC sockets, and press RECORD. Now press the “S” key to begin the SAVE. After five seconds, the saving pattern will begin. At the end of the save, the screen will go white with the report C/190.

You now have a backup copy just like the original. To LOAD the copy you have just made, use the command LOAD “X”. The program will run as soon as it is loaded.

   1 REM E1CDBB02EB21FDFBA7ED5220F421DB04C3FC02000000000000
10 REM SAVE A SELF-RUN PROGRAM
20 FAST
30 LET A=124
40 FOR I=508 TO 929
50 POKE I+A*256,PEEK I
60 NEXT I
70 LET B=A*256+834
80 POKE B,55
90 POKE B+7,A+3
100 POKE B+32,6
110 POKE B+33,A+2
120 POKE B+38,A+3
130 POKE B+60,A+3
140 POKE B+64,A+1
150 FOR J=1 TO 25
160 LET C=16512+J*2
170 POKE J+A*256+517,(PEEK C-28)*16+PEEK (C+1)-28
180 NEXT J
190 RAND USR B

LOAD the UnLOADable

Suppose last night you keyed in a long program and saved it on tape. Now you try to load it. The loading pattern appears for half a minute or more and suddenly the screen goes white for a few seconds and an inverse K appears at the bottom. When you try to LIST the program, you receive a report 0/0, indication that nothing was loaded. I’m sure all SyncWare News readers have encountered this frustration. There is a bad spot on the tape, resulting in a drop-out. When the LOAD command reaches a silent spot on the tape, it jumps to the NEW command which deletes whatever has already been loaded. Since you have a program listing on paper, you would like to recover the program up to the bad spot on the tape, so at least you won’t have to re-enter the entire program. Version 2 of the modified LOAD routine will load a tape up to the drop-out.

When the modified LOAD command reads a silent spot on a tape, it jumps to the area after the terminate routine which holds the code from our 1 REM statement. In version 2, this code determines how far the load has gotten. If the bad spot occurred after the system variables and the BASIC program were loaded, whatever was loaded from the display file or program variables area will be disregarded. If the drop-out occurred while the BASIC program was being loaded, then the end of the last complete BASIC line is found so you won’t get a program that is unlistable because part of the last statement is missing. Finally, a jump is made to a routine in ROM that will create an empty display file and an empty program variables area.

Type in version 2 of the program from the listing. After saving it for future use, enter RUN; the screen will turn white while the routines are moved into RAM. When the loading pattern appears, start the tape recorder in PLAY with the bad tape. The loading pattern will continue until the bad spot on the tape is reached. Then the screen will go blank for a few seconds and then display report 0/0. You can now LIST. If the program is not complete, type in the missing statements.

   1 REM EB2A0C4037ED522A0C40380AEB0100003E76EDB92323C30304
10 REM LOAD PART OF A BAD TAPE
20 FAST
30 LET A=124
40 FOR I=508 TO 929
50 POKE I+A*256,PEEK I
60 NEXT I
70 LET B=A*256+834
80 POKE B,55
90 POKE B+7,A+3
100 POKE B+32,6
110 POKE B+33,A+2
120 POKE B+38,A+3
130 POKE B+60,A+3
140 POKE B+64,A+1
150 FOR J=1 TO 25
160 LET C=16512+J*2
170 POKE J+A*256+517,(PEEK C-28)*16+PEEK (C+1)-28
180 NEXT J
190 RAND USR B

Final Words

The value in A in statement 30 determines where in RAM the routines are moved to. Readers with RAM in the 8-16K block can change the value of A so that the LOAD command is moved to an area safely outside the usual 16K RAM area. Then even the largest programs being loaded in will not overlay the routines in RAM and cause a crash.

Readers with disassemblers that reside in the top part of RAM (e.g. Bug-Byte‘s ZXDB) may also set A to a different value to avoid a conflict. Make the following changes:

30 LET A=96
Delete line 190

Run the program to move the routines to a location in RAM that won’t conflict with the disassembler. Use the disassembler to view the assembly code in locations 61FC-621E and 6242-62A2.

For a detailed explanation of the LOAD command, see “The Explorer’s Guide to the ZX81 and Timex Sinclair 1000” by Mike Lord. Another book that is valuable for anyone wanting to understand ROM routines is “The Complete Timex TS1000/ Sinclair ZX81 ROM Disassembly” by Ian Logan and Frank O’Hara. I hope that by using the program shown here, readers will discover other useful changes to the LOAD command.

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.