Classic Computer Magazine Archive COMPUTE! ISSUE 25 / JUNE 1982 / PAGE 52

Some Similarities Between Applesoft And PET BASIC

Garry Kiziak
Burlington, Ontario

I wonder how often a PET owner will pick up a magazine article and seeing that it applies to the Apple say "Oh! This isn't of any use to me.". Similarly, how many Apple owners will pick up a PET article and say the same thing? In fact, there is much to be learned about the PET from Apple articles and vice-versa. In many cases translating a useful utility or idea from the one computer to the other simply involves chaining a few addresses or some simple modification.

For example, a very useful idea appeared in Volume 3 Issue #1 of The Transactor dealing with the idea of reading data from a particular DATA statement. The following short PET program demonstrates how it works.

10 DATA FIRST, SECOND, THIRD
20 DATA FOURTH
30 READ A$, B$
40 POKE 62, PEEK(119) : POKE63, PEEK(120)
50 READ A, B
60 DATA 1, 2, 3, 4
70 PRINT A$, B$, A, B

In this program, line 40 causes the READ statement in line 50 to get its data from the next DATA statement (i.e. line 60) instead of from the next data item which would have been in line 10.

To get this program to work on an Apple, it is only necessary to change the addresses in line 40. The following will do the trick.

40 POKE 125, PEEK(184) : POKE 126, PEEK(185)

In COMPUTE!, May, 1981, #12, Craig Peterson offered an elegant routine for the Apple that would allow you to input anything into a string (including commas, colons, etc.) without getting the EXTRA IGNORED error message. That routine is reproduced here.

1000 CALL 54572
1010 FOR B = 512 TO 751 : IF PEEK(B) <> 0 THEN NEXT
1020 IN$ = "" : POKE PEEK(131) + 256 * PEEK(132) + 1, 0 : POKE PEEK(131) + 256 *
        PEEK(132 + 2, 2 : POKE PEEK(131) + 256 * PEEK(132), B - 512 : IN$ = MID$(IN$, 1) : RETURN

Once again, to get this to work on the PET, certain addresses will have to be changed. The necessary changes are as follows:

1000 SYS 48117
1010 FOR B = 512 TO 592 : IF PEEK(B) <> 0 THEN NEXT
1020 IN$ = "" : POKE PEEK(68) + 256 * PEEK(69) + 1, 0 : POKE PEEK(68) + 256 * PEEK(69) + 2, 2
1030 POKE PEEK(68) + 256 * PEEK(69), B - 512 : IN$ = MID$(IN$, 1) : RETURN

Notice that line 1020 had to be split into two lines. This is because the maximum length of a line in PET BASIC (including line numbers) is 80 characters. On the Apple, it is 239 characters.

The use of this subroutine instead of the traditional INPUT statement on the PET has an additional advantage – an empty response (i.e. simply pressing <RETURN>) does not break out of the program. Instead, the program continues and IN$ = "".

The above routine will prompt with a question mark and then a flashing cursor just like the regular INPUT statement. If you would rather that the question mark did not appear, then simply change line 1000 to:

1000 SYS 46306

Of course, not all programs will be as easy to change, but many will – even machine language programs. The trick is to find the correct change of addresses.

Recently, while writing a program for the Apple to draw the graph of practically any curve, I found it necessary to write a short machine language program which would change a line in the program to whatever you wanted. Specifically, it would be used to enter the equation of the curve to be graphed without going through the process of stopping the program, entering a new line, then typing in GOTO 550 or some similar process. This CHANGE routine would allow you to enter the equation just like in a regular INPUT statement. An assembly listing of the program is given below (Program 1). Here is an example of a machine language program that can be easily modified for the PET. The modified assembly listing is given in Program 2. Notice that the only changes required are in the addresses to the external ROM routines or zero page locations and to the IOSAVE and IOREST ore routines of the Apple which had to be simulated on the PET.

To illustrate how this routine works on the PET, get into the monitor (i.e. SYS 4) and type in .M 033A 0399. Then use the cursor to edit the displayed screen as indicated in the memory dump in Program 3. Get back inth BASIC and type in the short program in Program 4. RUN it, type in anything that you want, and watch line 100 change. RUN it again as often as you like and line 100 changes to whatever you dictate.

Now RUN the program again, but this time type in X = T : Y = SIN(T) in response to the prompt. Notice the momentary display of the message EXTRA IGNORED. In the listing you will see that line 100 has been changed correctly, but IN$ is only equal to X = T. If you happen to need the correct value of IN$ later on in the program, this would be totally unacceptable.

Now type in Program 5, RUN it, and type in your responses as before. This time, when you type in X = T : Y = SIN (T), you will notice that line 100 gets changed correctly as does variable IN$.

A good question would be: "How do you know what to change the various addresses to?". Personally, I have found two excellent sources. The first is the article "Applesoft Internal Entry Points" which appeared in the original Apple Orchard. The second source is the PET/CBM Personal Computer Guide (second edition). Page 476-493 have Hex Addresses and Label References for most of the zero page addresses and ROM routines in the new BASIC 4.0 (and BASIC 3.0) ROMs. Even most of the names of the routines from these two sources are the same. So, the next time you see an Apple article or a PET article, don't put it off as not applying to you, make it work for you and learn by the experiences of others.

Program 1.

SOURCE FILE : CHANGE - APPLE
----- NEXT OBJECT FILE NAME IS CHANGE -
      APPLE.OBJ0
0341:             1          ORG  $341
009B:             2 LOWTR    EQU  $9B
00B8:             3 TXTPTR   EQU  $B8
DEBE:             4 CHKCOM   EQU  $DEBE
DD7B:             5 FRMEVL   EQU  $DD7B
E752:             6 GETADR   EQU  $DD7B
FF4A:             7 IOSAVE   EQU  $FF4A
FF3F:             8 IOREST   EQU  $FF3F
D56C:             9 CRUNCH   EQU  $D56C
D61A:            10 FNDLIN   EQU  $D61A
D412:            11 ERROR    EQU  $D41A
0341:            12 ;
0341:            13 ; SAVE REGISTERS
0341:            14 ;
0341:  20 4A FF  15          JSR  IOSAVE
0344:            16 ;
0344:            17 ; GET THE LINE NUMBER
0344: 20 BE DE   19          JSR  CHKCOM
0347: 20 7B DD   20          JSR  FRMEVL
034A: 20 52 E7   21          JSR  GETADR
034D:            22 ;
034D;            23 ;  SAVE TEXT POINTER
                       TEMPORARILY
034D:            24 ;
034D:A5 B8       25         LDA  TXTPTR
034F:8D 9A 03    26         STA  TEMPTXT
0352:A5 B9       27         LDA  TXTPTR + 1
0354:8D 9B 03    28         STA  TEMPTXT + 1
0357:            29 ;
0357:            30 ;  TOKENIZE THE INPUT
                       BUFFER
0357:            31 ;
0357: A9 00      32         LDA #$00
0359: 85 B8      33         STA TXTPTR
035B: A9 02      34         LDA #$2
035D: 85 B9      35         STA TXTPTR + 1
035F: A2 FF      36         LDX #$FF
0361: A0 04      37         LDY #$4
0363: 20 6C D5   38         JSR CRUNCH
0366:            39 ;
0366:            40 ;  FIND THE LINE IN THE
                       BASIC PROGRAM
0366:            41 ;
0366: 20 1A D6   42         JSR FNDLIN
0366: 90 2A      43         BCC NOPE
036B:            44 ;
036B:            45 ;  CHANGE IT TO THE NEW
                       LINE STORED IN THE
                       INPUT BUFFER
036B:            46 ;
036B: A0 04      47         LDY #$04
036D: B9 FC 01   48 BEGIN   LDA $1FC,Y
0370: F0 09      49         BEQ DONE
0372: 91 9B      50         STA (LOWTR),Y
0374: C8         51         INY
0375: D0 F6      52         BNE  BEGIN
0377: A2 B0      53         LDX  #$B0
0379: D0 1C      54         BNE  ERR
037B:            55 ;
037B:            56 ;  FILL UP THE LINE WITH COLONS
037B:            57 ;
037B: A2 3A      58 DONE   LDX  #$3A
037D: B1 9B      59 START  LDA  (LOWRE), Y
037F: F0 06      60        BEQ  LAST
0381: 8A         61        TXA
0382: 91 9B      62        STA (LOWTR),Y
0384: C8         63        INY
0385: D0 F6      64        BNE START
0387:            65 ;
0387:            66 ;  RESTORE TEXT POINTER
0387:            67 ;
0387: AD 9A 03   68 LAST   LDA TEMPTXT
038A: 85 B8      69        STA TXTPTR
038C: AD 9B 03   70        LDA TEMPTXT + 1
038F: 85 B9      71        STA TXTPTR + 1
0391:            72 ;
0391:            73 ;  RESTORE REGISTERS
0391:            74 ;
0391:20 3F FF    75         JSR IOREST
0394:60          76         RTS
0395:A2 5A       77 NOPE    LDX #$5A
0397:4C 12 D4    78 ERR     JMP ERROR
039A:            79 TEMPTXT DS  $2

Program 2.

SOURCE FILE: CHANGE - PET
----  NEXT OBJECT FILE NAME IS CHANGE - PET. OBJO
033A:           1                 ORG   $33A
005C:           2 LOWTR           EQU   $5C
0077:           3 TXTPTR          EQU   $77
BEF5:           4 CHKCOM          EQU   $BEF5
BD98:           5 FRMEVL          EQU   $BD98
C92D:           6 GETADR          EQU   $C92D
B4FB:           7 CRUNCH          EQU   $B4FB
B5A3:           8 FNDLIN          EQU   $B5A3
B3CF:           9 ERROR           EQU   $B3CF
033A:          10 ;
03AA:          11 ; SAVE REGISTERS
033A:          12 ;
033A: 48       13                 PHA
033B: 08       14                 PHB
033C: 8A       15                 TXA
033D: 48       16                 PHA
033E: 98       17                 TYA
033F: 48       18                 PHA
0340:          19 ;
0340:          20 ; GET THE LINE NUMBER
0340:          21 ;
0340: 20 F5 BE 22                 JSR CHKCOM
0343: 20 98 BD 23                 JSR FRMEVL
0346: 20 2D C9 24                 JSR GETADR
0349:          25 ;
0349:          26 ; SAVE TEXT POINTER TEMPORARILY
0349:          27 ;
0349: A5 77    28                 LDA TXTPTR
034B: 8D 99 03 29                 STA TEMPTXT
034E: A5 78    30                 LDA TXTPTR + 1
0350: 8D 9A 03 31                 STA TEMPTXT + 1
0353:          32 ;
0353:          33 ; TOKENIZE THE INPUT BUFFER
0353:          34 ;
0353: A9 00    35                 LDA #$00
0355: 85 77    36                 STA TXTPTR
0357: A9 02    37                 LDA #$2
0359: 85 78    38                 STA TXTPTR + 1
035B: A2 FF    39                 LDX #$FF
035D: A0 04    40                 LDY #$4
035F: 20 FB B4 41                 JSR CRUNCH
0362:          42 ;
0362:          43 ; FIND THE LINE IN THE BASIC PROGRAM
0362: 20 A3 BG 45                 JSR FNDLIN
0365: 90 2D    46                 BCC NOPE
0367:          47 ;
0367:          48 ; CHANGE IT TO THE NEW LINE STORED IN THE INPUT BUFFER
0367:          49 ;
0367: A0 04    50                 LDY #$04
0369: B9 FC 01 51 BEGIN           LDA $1FC, Y
036C: F0 09    52                 BEQ DONE
036E: 91 5C    53                 STA (LOWTR), Y
0370: C8       54                 INY
0371: D0 F6    55                 BNE BEGIN
0373: A2 B0    56                 LDX #$B0
0375: D0 1F    57                 BNE ERR
0377:          58 ;
0377:          59 ; FILL UP THE LINE WITH COLONS
0377:          60 ;
0377: A2 3A    61 DONE            LDX #$3A
0379: B1 5C    62 START           LDA (LOWTR), Y
037B: F0 06    63		  BEQ  LAST
037D: 8A       64                 TXA
037E: 91 5C    65                 STA (LOWTR), Y
0380: C8       66                 INY
0381: D0 F6    67                 BNE START
0383:          68 ;
0383:          69 ; RESTORE TEXT POINTER
0383:          70 ;
0383: AD 99 03 71 LAST            LDA TEMPTXT
0386: 85 77    72                 STA TXTPTR
0388: AD 9A 03 73                 LDA TEMPTXT + 1
038B: 85 78    74                 STA TXTPTR + 1
038D:          75 ;
038D:          76 ; RESTORE REGISTERS
038D:          77 ;
038D: 68       78                 PLA
038E: A8       79                 TAY
038F: 68       80                 PLA
0390: AA       81                 TAX
0391: 28       82                 PLP
0392: 68       83                 PLA
0393: 60       84                 RTS
0394: A2 5A    85 NOPE            LDX #$5A
0396: 4C CF B3 86 ERR             JMP ERROR
0399:          87 TEMPTXT         DS $2

Program 3.

" : 033A 48 08 8A 48 98 48 20 F5
" : 0342 BE 20 98 BD 20 2D C9 A5
" : 034A 77 8D 99 03 A5 78 8D 9A
" : 0352 03 A9 00 85 77 A9 02 85
" : 035A 78 A2 FF A0 04 20 FB B4
" : 0362 20 A3 B5 90 2D A0 04 B9
" : 036A FC 01 F0 09 91 5C C8 D0
" : 0372 F6 A2 B0 D0 1F A2 3A B1
" : 037A 5C F0 06 8A 91 5C C8 D0
" : 0382 F6 AD 99 03 85 77 AD 9A
" : 038A 03 85 78 68 A8 68 AA 28
" : 0392 68 60 A2 5A 4C CF B3 EF

Program 4.

10 INPUT" {CLEAR} CHANGE TO"; IN$
20 CHANGE = 826: LINE = 100
30 SYSCHANGE, LINE
40 PRINT" {CLEAR} IN$ EQUALS :" IN$ : LIST
100 :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

Program 5.

10 PRINT" {CLEAR} CHANGE TO "; : GOSUB 1000
20 CHANGE = 826 : LINE = 100
30 SYSCHANGE, LINE
40 PRINT" {CLEAR} IN$ EQUALS : "IN$: LIST
100 :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
        :::::::::::::::::::::::::::::::::::::::
1000 SYS48117
1010 FOR B = 512 TO 592 : IF PEEK (b) <> 0 THEN NEXT
1020 IN$ = "" : POKE PEEK (68) + 256 * PEEK (69) + 1, 0 : [POKE PEEK (68) + 256 * PEEK (69) + 2, 2
1030 POKE PEEK (68) + 256* PEEK (69), B - 512 : IN$ = MID$ (IN$,1) : RETURN