Classic Computer Magazine Archive COMPUTE! ISSUE 23 / APRIL 1982 / PAGE 126


Brian Niessen
Chemainus, B.C.

This very useful machine language routine is well worth its weight in gold when it comes to using your PET/CBM wth ASCII devices such as MODEMS and printers. It's short length (56 bytes) and ease of use make it very easy to add to any existing programs. The assembler listing included is for BASIC 3.0 ROM's. The changes needed for BASIC 2.0 ROM's and BASIC 4.0 ROM's are listed below.

For BASIC 2.0, change COMMA to $CE11 from $CDF8, change EVAL to $CCB8 from $CC9F, and change PTR to $96 from $44. For BASIC 4.0, change COMMA to $BEF5 from $CDF8 and change EVAL to $BD98 from $CC9F. The PTR location is the same for BASIC 4.0 as it is for BASIC 3.0, as Commodore promised it would be.

The machine language program works as follows. It is invoked with a SYS(NNN),A$ statement. The (NNN) is the first location of the ML routine and the string variable A$ is the string to be converted. The ML program then jumps to the routine COMMA, which checks for – you guessed it – the comma which seperates the SYS(NNN) and the A$. The next jump is to a subroutine called EVAL which looks at the variable A$ and puts its location in PTR and PTR + 1.

CBM/PET identifies characters somewhat differently than the industry standard, the ASCII code. In ASCII, the number 65 means uppercase "A," as it does to PET BASIC. However, if you POKE 32768,65, the screen will either display a spade or lowercase "a," depending on whether you are in "text" or "graphics" mode at the time. Everything is kept straight for you by BASIC, but when you try to communicate with a device outside the computer (a MODEM or a printer), some adjustments may need to be made. This is why wordprocessors like WordPro always first ask you to indicate whether you are using a Commodore printer, an ASCII printer, etc. Mr. Niessen's machine language program does the translating. It takes the CBM/PET character codes and modifies them to conform to ASCII. Within the article, he provides the necessary changes to make the program work on all CBM models: Original (2.0), Upgrade (3.0), and BASIC (4.0).

By using an indirect indexed addressing mode, you can get the length of the string by loading the Y register with zero and executing a LDA(PTR), Y. The length of the string is then transferred into the accumulator and saved into location STRLEN. Next, the Y register is incremented so it has a value of one, and another LDA(PTR), Y is executed. This time the LO byte of the beginning of the actual string in memory is returned. This is saved in the location STRLO. Again the Y register is incremented and the LDA(PTR),Y instruction is executed again, returning the HI byte of the location of the string, which is saved in STRHI.

Now knowing the location and length of the string to be converted, the routine can convert it from PETASCII to ASCII on a character by character basis, beginning with the last one and working forward. It uses the following algorithm:

IF(A) > = 65 AND (A) < = 90 THEN (A) = (A) OR 32
ELSE I (A) > = 193 AND (A) < = 219 THEN (A) = (A) AND 127

Characters above $7B have no ASCII equivalent and are left as is.

The subroutine then returns to BASIC, with the contents of the string A$ converted to ASCII. The string can now be printed normally.

One thing to remember is that the original contents of the string are changed. If the string were dynamically declared, as in the following example, it will be changed within the program:

10 A$ = "STRING" : SYS(NNN), A$

because the PET, to save memory space, sets the pointers to the actual string in the program. Instead use:

10 A$ = "STRING" + " " : SYS(NNN), A$

which will cause the string to be stored away in high memory.

I hope this will prove as useful to others as it has been to me. It was tested on the EPSON MX-80 printer.


Commodore User's Reference Manual—PN 321604
Page E-1, Paragraph I

The PET Revealed
Nick Hampshire, Computabits Ltd, P.O. Box 13, Yeovil, Somerset, England
PET/CBM Personal Computer Guide
Adam Osborne-Carroll S. Donahue

LINE#	 LOC	 CODE           LINE
0001     0000                   ; ***************************************  0002	 0000                   ; * PETASCII TO ASCII SUBROUTINE        *
0003	 0000                   ; * BY: BRIAN NIESSEN.                  *
0004 	 0000                   ; *                                     *
0005 	 0000                   ; * BOX 571                             *
0006 	 0000                   ; * CHEMAINUS, B.C. VOR 1KO             *
0007 	 0000                   ; * (604) 246-4556                      *
0008 	 0000                   ; ***************************************
0009 	 0000                   ; *TO USE: SYS(NNN), A$                 *
0010 	 0000                   ; *WHERE (NNN) IS START LOCATION        *
0011 	 0000                   ; *A$ IS STRING TO BE CONVERTED         *
0012 	 0000                   ; ***************************************
0013 	 0000                   ; LOCATIONS FOR 2001 (BASIC 3.0)
0014 	 0000                   COMMA  =  $CDF8
0015 	 0000                   EVAL   =  $CC9F
0016 	 0000                   STRLO  =  $DA
0017	 0000                   STRHI  =  $DB
0018	 0000                   STRLEN =  $F9
0019	 0000                   PTR    =  $44           ;POINTER USED IN EVAL ROUTINE
0020	 0000                          *  =634          ;STARTING LOCATION FOR ROUTINE
0021	 027A	20  F8	CD             JSR COMMH        ;CHECK FOR COMMA
0022	 027D	20  9F	CC             JSR EVAL         ;EVALUATE EXPRESSION
0023	 0280	A0  00                 LDY #0           ;SAVE STRING LOCATION
0024	 0282	B1  44                 LDA (PTR), Y
0025	 0284	85  F9                 STA STRLEN
0026	 0286	C8                     INY
0027	 0287	B1  44                 LDA (PTR), Y
0028	 0289	85  DA                 STA STRLO
0029	 028B	C8                     INY
0030	 028C	B1  44                 LDA (PTR), Y
0031	 028E	85  DB                 STA STRHI
0032	 0290                   ;PROCESS STRING ONE CHARACTER AT A TIME.
0033	 0290	A4  F9                 LDY STRLEN       ;GET STRING LENGTH
0034	 0292	B1  DA          LOOP   LDA (STRLO), Y
0035	 0294	C9  41                 CMP #$41         ;IF $41<=A<$5A THEN A=A OR $20
0036	 0296	90  12                 BCC DONE         ;IF 'A <=A<= 'Z THEN A=A OR 32
0037	 0298	C9  5B                 CMP #$5B
0038	 029A	B0  04                 BCS SECOND
0039	 029C	09  20                 ORA #$20
0040	 029E	D0  0A                 BNE DONE         ;JUMP ALWAYS
0041	 02A0                   SECOND                  ;FIRST FAILED-TRY SECOND
0042	 02A0	C9  C1                 CMP #$C1         ;IF $C1<=A<=$DA THEN A=A AND $7F
0043	 02A2	90  06                 BCC DONE
0044	 02A4	C9  DB                 CMP #$DB
0045	 02A6	B0  02                 BCS DONE
0046	 02A8	29  7F                 AND #$7F
0047	 02AA	91  DA          DONE   STA (STRLO), Y
0048	 02AC	88                     DEY
0049	 02AD	C0  FF                 CPY #$FF
0050	 02AF	D0  E1                 BNE LOOP
0051	 02B1
0052	 02B1	60                     RTS              ;RETURN TO BASIC
0053	 02B2                          .END