Classic Computer Magazine Archive COMPUTE! ISSUE 37 / JUNE 1983 / PAGE 256

Soft-16 For
Commodore 64

Douglas D. Nicoll

This program, "USR(PEEK)", demonstrates several interesting concepts about managing the memory of the 64. BASIC programs can be run essentially without BASIC, and you can switch between ROM and RAM during a program RUN to access an additional 16K of RAM for data storage. You'll also see how to use the USR() statement.

An inexpensive 16K RAM expansion for the Commodore 64? Run BASIC programs without BASIC or the kernal? Well, almost. The 6510 has the capability of exchanging RAM data banks with the three ROM banks (BASIC [AB] $A000-$BFFF; characters [D] $D000-$DFFF; and kernal [EF] $E000-$F000). It switches between ROM and RAM with the use of a control port located at $0001. Bit zero in $0001 controls EF, bit one controls AB, and bit two controls D. Setting the bit to one switches in ROM (the normal state), and zero switches in RAM memory.
    In normal BASIC operation, it is possible to POKE values to AB and EF locations, but PEEKing these locations will show only the ROM data. POKEs and PEEKs to D work fine, but you can't PEEK the character ROM without setting a number of switches so the system won't crash. Thus, without the ability to PEEK the hidden RAM memory, AB and EF locations are effectively eliminated from use in BASIC programs.
    USR(PEEK) is a valuable machine language utility program that opens up the hidden RAM for use in BASIC programs, giving the user 16K more memory cells for data storage. The program is loaded into $C001-$C0E4, and uses $0000 as a temporary storage cell. The vector for the USR() function is set (POKE 785,1:POKE 786,192). BASIC programs are loaded normally, and any RAM location can be PEEKed by using X = USR(N), where X is any variable and N is any number from 1 to 65535. Any number less than 0.5 will set X to -1, 0.5 to 1.9 evaluate as 1, and all other decimal numbers are truncated to the integer. If a negative number is given for N, the value returned is for ABS(N). If a number is greater than 65535, then X is -1. If N is between 53248 and 57343, X is the value of data stored in character ROM (D).

Automatic Switching
How does USR(PEEK) work? The statement X = USR(N) in a BASIC program loads N into the floating point accumulator and sends the computer to the machine language program pointed to by the USR vector. The machine language program evaluates the number in the FP accumulator, switches out BASIC and kernal ROM, loads the desired RAM data into the FP accumulator, switches BASIC and kernal ROM back in, and finally sets up the FP accumulator so that X contains the values on return to the BASIC program. When character ROM is desired, it is switched in for the manipulation.
    The techniques used to dynamically switch between RAM and ROM have many other uses for hybrid programmers (people who use both BASIC and machine language). For example, machine language programs can be loaded under BASIC or kernal ROM and run with BASIC programs - this leaves more space for BASIC programs and variable storage. It is possible to envision loading a BASIC program editor under BASIC ROM and calling it for renumbering, searching, etc.
    Type in the program and, after saving a copy, RUN it to see a demonstration of how easy it is to use. Then eliminate lines 10-540 and save it with the name USR(PEEK). To use with your programs, LOAD and RUN USR(PEEK) and then LOAD and RUN your own BASIC programs that can be constructed to utilize the additional 16K of RAM data storage.

1 GOSUB1000:REM SET UP USR(PEEK)
10 PRINT"{CLEAR}USR(PEEK) AT CHARACTER ROM"
20 V$="{HOME}(24 DOWN}"
30 H$=""+"{39 RIGHT}"
40 UC=53248:LC=55296:GC=53760
50 H=0:V=10:L=83*8+UC:GOSUB500
60 H=8:V=10:L=3*8+UC:GOSUB500
70 H=14:V=5:L=85*8+UC:GOSUB500:H=14:V=14:
    L=74*8+UC:GOSUB500
80 H=22:V=10:L=54*8+UC:GOSUB500
90 H=30:V=10:L=52*8+UC:GOSUB500
100 PRINTLEFT$(V$,5);LEFT$(H$,18);"SC{UP}U
    {02 DOWN}{LEFT}J{UP}64";LEFT$(V$,22)
110 PRINT"PRESS ANY KEY TO CONTINUE";
120 GETA$:IFA$=""THEN120
130 PRINT"{CLEAR}USR(PEEK) INTO BASIC HIDD
    EN RAM"
140 PRINTLEFT$(V$,5);"INPUT 10 NUMERS(0-25
    5) TO STORE IN $A000TO $A00A :"
150 FORI=1TO10
160 PRINT"NUMBER ";I;": ";:INPUT"";X
170 IFINT(X)<>XORX<0ORX>255THENPRINT"INVAL
    ID ENTRY...":GOT0160
180 POKE40959+I,X:NEXT
190 PRINT"{CLEAR}USR(PEEK) INTO HIDDEN BAS
    IC RAM"
200 PRINT:PRINT:PRINT"LOCATION   PEEK   US
    R(PEEK)"
205 PRINT"---------------------------"
210 FORI=1TO10:PRINTI+40959,PEEK(I+40959),
    USR(I+40959):NEXT
220 PRINTLEFT$(V$,22);"PRESS ANY KEY TO CO
    NTINUE ";
230 GETA$:IFA$=""THEN230
240 PRINT"{CLEAR}USR(PEEK) INTO KERNAL HID
    DEN RAM"
250 PRINTLEFT$(V$,5);"INPUT 10 NUMERS(0-25
    5) TO STORE IN $F000TO $F00A :"
260 FORI=1TO10
270 PRINT"NUMBER ";I;": ";:INPUT"";X
280 IFINT(X)<>XORX<0ORX>255THENPRINT"INVAL
    ID ENTRY...":GOTO160
290 POKE61439+I,X:NEXT
300 PRINT"{CLEAR}USR(PEEK) INTO HIDDEN KER
    NAL RAM"
310 PRINT:PRINT:PRINT"LOCATION   PEEK   US
    R(PEEK)"
320 PRINT"---------------------------"
330 FORI=1TO10:PRINTI+61439,PEEK(I+61439),
    USR(I+61439):NEXT
340 END
500 FORD=LTOL+7:X$="":X=USR(J)
510 FORI=7TOHSTEP-1:IFX=>2↑tITHENX=X-2I:X$
    =X$+"{WHT}{REV} {OFF}":GOTO530
520 X$=X$+"{RIGHT}"
530 NEXTI:IFJ=LTHENPRINTLEFT$(V$,V);
540 PRINTLEFT$(H$,H);X$:NEXT:RETURN
1000 POKE785,1:POKE786,192:REM USR VECTOR
1010 FORI=49153TO49380:READX:POKEI,X:NEXT
1015 RETURN
1020 DATA173,97,0,201,144,208,3,76,188,192,
    56,201,128,176,3,76,163,192,201,145
1030 DATA144,3,76,163,192,73,128,141,97,0,5
    6,169,16,237,97,0,240,13,170,24
1040 DATA78,98,0,110,99,0,202,224,0,208,244
    ,173,98,0,141,78,192,173,99,0
1050 DATA141,77,192,173,1,0,141,0,192,120,7
    3,7,141,1,0,173,255,255,141,98,0
1060 DATA173,0,192,141,1,0,88,173,98,0,201,
    0,208,3,76,140,192,162,8,173,98,0
1070 DATA24,42,176,5,202,224,0,208,247,106,
    141,98,0,73,128,141,102,0,138
1080 DATA9,128,141,97,0,169,0,141,99,0,141,
    100,0,141,101,0,96,169,0,141,97,0
1090 DATA141,99,0,141,100,0,141,101,0,141,1
    02,0,169,128,141,98,0,96,169,129
1100 DATA141,97,0,169,128,141,98,0,141,102,
    0,169,0,141,99,0,141,100,0,141,101,0
1110 DATA96,56,173,98,0,201,224,144,3,76,22
    3,192,201,208,176,3,76,223,192,169,4
1120 DATA141,72,192,173,97,0,32,26,192,169.
    7,141,72,192,96,173,97,0,76,11,192