Classic Computer Magazine Archive COMPUTE! ISSUE 8 / JANUARY 1981 / PAGE 96

Hooray for SYS

Harvey B. Herman
Department of Chemistry University of North Carolina at Greensboro
Greensboro, North Carolina 27412

The PET User's Club Newsletter (Vol. 1, Issue 3) reprinted an interesting article by Karl Hildon entitled "Probing PET's Memory". PETters were encouraged to experiment with the SYS command. Many of the routines in the PET are written as subroutines which terminate with the machine language instruction, RTS (return from subroutine). When a routine is initiated by the SYS command execution of the RTS instruction returns the PET to BASIC command mode or continues with the BASIC program. Using this idea we may be able to pick and choose useful segments of PET's Code and, in effect, make a new operating system.

This article describes three examples of tape operations which are not possible with just the normal BASIC commands. I hope readers will find them useful and are encouraged to develop similar ones on their own with the information supplied here. For convenience I have summarized in the Table the SYS calls and memory locations that I refer to in this article for both original and upgrade ROMs.

Occasionally I receive a tape of a machine language program with no information on its load limits. It is not possible to make a backup copy without this data. My first example is a BASIC program (see listing for TAPE DIRECTORY) which continually reads a tape and lists the start and end (+1) addresses for each program it finds. The idea behind this program and other examples here come from an article by Jim Butterfield, "Watching a Cassette Load", PET User Notes, Vol. 2, #1. He discussed several SYS commands in the article. The TAPE DIRECTORY program uses one of the SYS calls to load a tape header, containing among other information, the start and end addresses of the tape load. The addresses PEEKed from the beginning of the first cassette buffer are then converted to hexadecimal, using another Butterfield idea, and printed out. Note the use of the dynamic keyboard in statement 10 (cf., Mike Louder, "Best of PET Gazette") and the changes necessary for upgrade ROMs in statement 9.

More than once I have received a tape which would not load into my PET. For example, the program may have been saved from $4000 up in the originating PET and the highest location in my computer is $3FFF. My second BASIC example is a program (see listing for RELOCATE) which loads a cassette program into any area of RAM memory specified by the user. The loading addresses on the tape header are bypassed. I did the same trick manually in an article I wrote for MICRO ("MOVEIT", 16:17, with update 17:18). This program described here completely automates the procedure by using the dynamic keyboard idea. It asks for input of the starting location, loads the tape header, corrects the header information in the first cassette buffer, and completes the rest of the load. Note the changes necessary for upgrade ROMs (Statements 165, 330, and 345). After relocation machine language programs will probably need some changes to reflect the new location before executing successfully.

Appending one BASIC program to another is a very useful operation. The final BASIC example (see listing for APPEND) has appeared before in many different guises. For example, as a wedge (Commodore PET User's Club Newsletter, Vol. 1, #4-5, p. 24), or with a SYS call to a machine language program (PET User's Notes, Vol. 1, #7). The BASIC Programmer's Toolkit (Palo Alto ICs) also has a built in tape append function. The BASIC programs described here (APPEND and APPEND NEW PETS) uses a similar set of SYS calls as RELOCATE. The programs first determine the end of BASIC from pointers in page zero. After the header is loaded the start/end information in the tape buffer is updated to reflect a remaining load which starts at the end of the first BASIC program. The program can be run repeatedly to append as many programs as desired. However, each program should have successively higher line numbers with no overlap. The append program can be deleted manually after use or the task could be automated using the dynamic keyboard.

Several problems came up when I tried to adapt the append program for upgrade ROMs. Jim Butterfield was kind enough to send me the locations corresponding to "load next header" and "load rest of tape" However, the load next tape routine did not have exactly the same effect as in the older model PETs. The new routine did not correct the chaining (links between BASIC lines) and update various pointers (e.g., to end of BASIC program). My APPEND program for new PETs needed an additional SYS call to correct the chaining and a separate update POKE so BASIC can keep track of the larger merged program.

The examples given here were all for cassette tape operation. There is no reason why examples have to be limited to tape. In the future, I hope to read about other examples where selective parts of PET's code BASIC are utilized in BASIC programs. Most of us, including myself can understand BASIC more easily than machine language and as long as speed is not a requirement, I see no reason why we can't use the 14K bytes of code in ways never dreamed of originally.

TABLE (hex locations in parenthesis)
Function Original ROMs Upgrade ROMs
load header 62894 (F5AE) 62886 (F5A6)
pointer to end of BASIC program 124/125 (7C/7D) 42/43 (2A/2B)
Header Buffer 635-638 (27B-27E) same
load rest of tape 62403 (F3C3)* 62393 (F3B9)
correct chaining 50224 (C430) 50233 (C439)
current device # 241 (F1) 212 (D4)
LOAD/verify flag 523 (20B) 157 (9D)
# Chars, in keyboard 525 (20D) 158 (9E)
start of keyboard buffer 527 (20F) 623 (26F)

Note: With original ROMs, the chaining is corrected and end of BASIC program pointer updated automatically after BASIC program load. With upgrade ROM, chaining and pointer update must be done manually.

2 REM TAPE DIRECTORY
5 REM HARVEY B. HERMAN
8 REM SET CURRENT DEVICE NUMBER TO TAPE 1 : LOAD NEXT HEADER USING DYNAMIC KEYBOARD
9 REM NEW PET-POKE212, 1 : SYS 62886 : POKE 158, 1 : POKE 623, 13
10 POKE 241, 1 : PRINT "↓↓↓SYS 62894 : GOTO20 ↑↑↑" : POKE525, 1 : POKE527, 13 : END
19 REM 635-638 TAPE BUFFER START AND END LOCATION
20 A = PEEK (635) : B = PEEK (636)
30 GOSUB 110
35 PRINT
40 PRINT "TAPE START";
50 GOSUB 120
60 A = PEEK (637) : B = PEEK (638)
70 GOSUB 110
80 PRINT "TAPE END";
90 GOSUB 120
100 GOTO 10
109 REM CONVERT HIGH/LOW BYTES TO LOCATION
110 C = 256*B+A : RETURN
119 REM DECIMAL TO HEX CONVERSION-JIM B. IDEA
120 X = C/4096 : FOR J = 1 TO 4 : A = INT (X)
130 IFA > 9 THEN PRINT CHR$ (A + 55); : GOTO 150
140 PRINT CHR$ (A + 48);
150 X = (X-INT(X)) * 16 : NEXT J : PRINT : RETURN
100 REM RELOCATE
110 REM HARVEY B. HERMAN
120 REM INPUT START OF RELOCATION
130 INPUT "PROGRAM START LOCATION"; C
140 REM CONVERT TO HIGH/LOW BYTES : SAVE FOR LATER
150 GOSUB 400 : SL = A : SH = B : NS = C
160 REM SET CURR. DEVICE NUMBER TO TAPE 1 : LOAD NEXT HEADER USING DYNAMIC KEYBOARD
165 REM NEW PET-POKE 212, 1 : SYS 62886 : POKE 158, 1 : POKE 623, 13
170 POKE 241, 1 : PRINT "↓↓↓SYS 62894 : GOTO 200↑↑↑" : POKE 525, 1 : POKE 527, 13 : END
180 REM 635-638 TAPE BUFFER START AND END LOCATION
190 REM FIND TAPE START
200 A = PEEK(635) : B = PEEK(636)
210 REM SAVE FOR LATER
220 GOSUB 380 : S = C
230 REM FIND TAPE END + 1
240 A = PEEK (637) : B = PEEK (638)
250 REM SAVE FOR LATER
260 GOSUB 380 : F = C
270 REM CALCULATE NEW TAPE END
280 C = NS + (F-S) : GOSUB 400 : FL = A : FH = B
290 REM CORRECT TAPE BUFFER START AND END
300 POKE 635, SL : POKE 636, SH
310 POKE 637, FL : POKE 638, FH
320 REM FLAG-0/LOAD, 1/VERIFY
330 POKE 523, 0 : REM NEW PET-157
340 REM LOAD REST OF TAPE WITH DYNAMIC KEYBOARD
345 REM NEW PET-SYS 62393 : POKE 158, 1 : POKE 623, 13
350 PRINT : PRINT : PRINT "SYS 62403↑↑↑ : POKE 525, 1 : POKE 527, 13
360 END
370 REM CONVERT HIGH/LOW BYTES TO LOCATION
380 C = 256 * B + A : RETURN
390 REM CONVERT LOCATION TO HIGH/LOW BYTES
400 B = INT (C/256) : A = C-B*256 : RETURN
100 REM APPEND
110 REM HARVEY B. HERMAN
120 REM SET CURR. DEVICE NUMBER TO TAPE 1 : LOAD NEXT HEADER USING DYNAMIC KEYBOARD
130 POKE 241, 1 : PRINT "↓↓↓SYS 62894 : GOTO 150↑↑↑" : POKE 525, 1 : POKE 527, 13 : END
140 REM 635-638 TAPE BUFFER START AND END LOCATION
150 A = PEEK(635) : B = PEEK(636)
160 GOSUB 400
170 REM SAVE TAPE START
180 S = C
190 REM FIND END OF BASIC PROGRAM
200 A = PEEK(124) : B = PEEK (125)
210 GOSUB 400
220 REM CALCULATE NEW START LOAD
230 C = C-3 : T = C : IF PEEK (635) = 0 THEN C = C-1 : T = T-1
240 GOSUB 420
250 REM CORRECT LOAD POINT
260 POKE 635, A : POKE 636, B
270 REM FIND TAPE END (+1)
280 A = PEEK (637) : B = PEEK (638)
290 GOSUB 400
300 REM CALCULATE NEW TAPE END
310 C = C-S
320 C = T+C
330 GOSUB 420
340 REM CORRECT END LOAD : SET LOAD/VERIFY FLAG TO LOAD
350 POKE 637, A : POKE 638, B : POKE 523, 0
360 REM LOAD REST OF TAPE WITH DYNAMIC KEYBOARD
370 PRINT : PRINT "↓↓SYS 62403↑↑↑" : POKE 525, 1 : POKE 527, 13
380 END
390 REM CONVERT HIGH/LOW BYTES TO LOCATION
400 C = 256*B + A : RETURN
410 REM CONVERT LOCATION TO HIGH/LOW BYTES
420 B = INT(C/256) : A = C - B*256 : RETURN
100 REM APPEND NEW PETS
110 REM HARVEY B. HERMAN
120 REM SET CURR. DEVICE NUMBER TO TAPE l : LOAD NEXT HEADER USING DYNAMIC KEYBOARD
130 POKE 212, l : PRINT "↓↓↓SYS 62886 : GOTO 150 ↑↑↑" : POKE 158, l : POKE 623, 13 : END
140 REM 635-638 TAPE BUFFER START AND END LOCATION
150 A = PEEK (635) : B = PEEK(636)
160 GOSUB 400
170 REM SAVE TAPE START
180 S = C
190 REM FIND END OF BASIC PROGRAM
200 A = PEEK(42) : B = PEEK(43)
210 GOSUB 400
220 REM CALCULATE NEW START LOAD
230 C = C - 3 : T = C : IFPEEK(635) = 0THENC = C - 1 : T = T - 1
240 GOSUB 420
250 REM CORRECT LOAD POINT
260 POKE 635, A : POKE 636, B
270 REM FIND TAPE END (+1)
280 A = PEEK (637) : B = PEEK(638)
290 GOSUB 400
300 REM CALCULATE NEW TAPE END
310 C = C - S
320 C = T + C
330 GOSUB 420
340 REM CORRECT END LOAD : SET LOAD/VERIFY FLAG TO LOAD
350 POKE 637, A : POKE 638, B : POKE 157, 0
354 REM UPDATE ALL POINTERS
355 POKE 42, PEEK(637) : POKE43,PEEK(638): CLR
360 REM LOAD REST OF TAPE AND CORRECT CHAINING WITH DYNAMIC KEYBOARD
370 PRINT : PRINT "↓↓SYS 62393" : PRINT "↓↓↓SYS 50233↑↑↑↑↑↑↑"
371 POKE158,2 : POKE623, 13 : POKE624,13
380 END
390 REM CONVERT HIGH/LOW BYTES TO LOCATION
400 C = 256*B + A : RETURN
410 REM CONVERT LOCATION TO HIGH/LOW BYTES
420 B = INT(C/256) : A = C - B*256 : RETURN