Classic Computer Magazine Archive A.N.A.L.O.G. ISSUE 62 / JULY 1988 / PAGE 23

130 XE only
XE
BANKS
by Dave Schofield

You'll notice, if you keep up with all the popular Atari specific publications, that the general consensus about the extra 64k in the 130XE is: BASIC programmers, keep out! This is actually pretty sound advice, but does lead one to think that the matter is an open- and-shut case, which is not necessarily true. Let's first take a look at why BASIC can't access the extra banks of RAM.

XE
Banks


BASIC and the extra RAM
    The first thing to know is that BASIC can indeed access the extra RAM. It's as simple as a single POKE statement! Hmmm, there must be more to it than that. Well, there is. Since the XE has 64K of main RAM, we can think of it as four 16K blocks. The first block goes from memory locations 0 to 16383. The second from 16384 to 32767, third 32768 to 49151, and the fourth is 49152 to 65535. The extra 64K is divisible exactly the same way. We'll call each of these divisions a "bank." The special memory management chip in the XE can let you access all four banks, but only one at a time. It does this by laying the bank you specify in place of the main RAM's second bank, from 16384 to 32767. So, whenever you execute that special POKE, the bank you specify shows up in place of the main RAM's bank.
    What happens to the main RAM's bank two? Ah, this is where the problem arises. The normal bank two section of RAM becomes completely invisible, as though it didn't exist. Now suppose you had a fairly good sized BASIC program in memory. Chances are it will extend well into the second bank of RAM. As soon as you enable an extra bank in place of the normal one, your BASIC program goes into la-la land. You can't re-enable the normal bank because you no longer have the program in RAM!

When does
the good
news come?

    Right now! Even though BASIC can't hack enabling and disabling the extra RAM banks, machine language can. Here's how: Most everyone knows that a USR statement transfers control to a machine language routine. Let's say the routine is located in Page 6, from 1536 to 1791. When the machine language program has control, it doesn't care what you do with the second bank of RAM, since it lies within the safety of the first bank. So, the secret is to give control to the machine language, let it enable the extra banks, perform the operation involving the extra RAM, then re-enable the normal bank two, and return control to BASIC. Sound simple? Actually, it really is.

Our
application

    Listing 1 is a BASIC program that will load up to eight graphics screens (in an UNcompressed, 62-sector format) and save them into the extra memory. After they are all there, you can load any one of them back into the screen area, one by one, almost instantly! Here's how to use it:

1) Round up several (up to eight) screen files on a single disk.
2) Type in Listing 1.
3) In Line 140, set the variable PICS equal to the number of picture files you have on the disk.
4) Type the picture files' names on Line 9100 as DATA elements (erasing the ones already there).
5) Lines 9201 thru 9208 are DATA statements describing the picture file. (9201 describes picture one, 9202 describes picture two, etc.) Here's what the program expects to find there:
    Data element 1: The graphics mode (plus 16) of the picture. (Can be 31, 24, 9, 10 or 11.) Data elements 2-6: The values to POKE into the color registers from 708-712.
6) Save the program before running it.
7) After you type RUN, the files will load onto the screen, and be saved into the extra RAM. The saving to extra RAM is done right after the picture loads, and you'll notice there is virtually no delay at all.
8) The last screen loaded will remain visible. Now you can press a number between one and eight instantly.
    If you only loaded five pictures, pressing 6, 7 or 8 will put garbage on the screen. No harm, it's just the data that's in the extra RAM at powerup. 9) Hit 0 to clear the screen, ESCAPE to quit the program.

Technically
speeking

    All the machine language program does is decide which hank should be enabled and at what address it will find the correct data (determined from the variable BANK in the USR calls). It then enables the correct bank. Next, it does a very simple memory move routine to move $1E00 (7680) bytes into the screen RAM area or from the screen RAM area based on the first argument in the USR call (0 means save from screen to extra RAM, 1 means from extra RAM to screen area). Lastly, it reenables the normal configuration and returns to BASIC.
    Using the machine code in your own programs is easy.

Follow these rules:

POKE the data found in Lines 9005 thru 9030 into locations 1536 thru 1637

    Call it with: A=USR (1536, OPER, SCRN, BANK) where OPER equals 0 to move data from the screen to RAM, and 1 to move RAM to the screen, and SCRN equals the address of the screen, found by SCRN =PEEK (88) +PEEK (89)* 256 (after you execute your graphics command). Bank equals a number between one and eight signifying which bank (actually half-bank) to store to or load from. If you use only one or two banks, it doesn't matter which ones you choose; they are all exactly the same.
Listing 2 is the assembly source code written with Mac/65 from OSS.

Lastly . . .
    This program is simply a way to demonstrate the ability to access the extra RAM, even from BASIC (sort of). The routine in Page 6 isn't completely useless though. If you're writing a drawing program for the XE, you can easily use this routine to enable you to have eight screens in the computer at once! Switching from one to the other would be a piece of cake. Or you could set aside one of the banks for an Undo feature. This simply means that each time a new "tool" or color is chosen to draw with, you save the current screen into the extra RAM. If the user decides he liked it better before his changes, he hits the Undo key, the program loads the extra RAM back to the screen, and it looks like all the changes disappear. See if you can find some other uses, too.

XE Banks
Listing 1:
BASIC


VE 10 REM XESANKS FROM ANALOG COMPUTING
RU 15 ? CHR$(125):POKE 752,1:POSITION 2,1
   0:? "Insert disk with pictures. Hit RE
   TURN"
UF 16 IF PEEK(764)=255 THEN 16
RZ 17 POKE 764,255:POKE 752,0:? CHRS(125)
HC 20 IF PEEK(1637)<>237 THEN GOSUB 9000
PY 100 ICCOM=834:ICBADR=836:ICBLEN=840
QZ 110 CGBINR=7:X1=16
UF 120 DIM FILE$(26),T$(20)
MQ 130 GRAPHICS 0:SC=PEEK(88)+PEEK(89)*25
   6
OT 140 PICS=8:RESTORE 9100
LI 150 FOR BANK=1 TO PICS
EV 160 READ T$:FILES="D:":FILES(3)=T$
BG 170 CLOSE #1:OPEN #1,4,0,FILE$
VX 180 POKE ICCOM+X1,CGBINR
UE 190 POKE ICBADR+X1,PEEK(88):POKE ICBAD
   R+1+X1,PEEK(89)
UO 200 POKE ICBLEN+X1,0:POKE ICBLEN+1+X1,
   30
VN 205 POKE 752,1:POKE 656,1:? CHR$(156);
   CHR$(127);"Loading ";FILES;"..."
HA 210 A=USR(ADR(""),X1):CLOSE #1
QS 220 A=USR(1535,0,SC,BANK)
AG 230 NEXT BANK
XR 235 CLOSE #1:OPEN #1,4,0,"K:"
AY 240 ? CHR$(125):POKE 656,1:POKE 657,10
   :? "Hit 1-8, ESC to end";
SX 250 GET #1,BANK:BANK=BANK-48
OY 260 IF BANK=0 THEN ? #6;CHR5(125):GOTO
    250
OU 280 IF BANK=-21 THEN END
TX 290 IF BANK<1 OR BANK>8 THEN 250
FL 300 RESTORE 9200+BANK:READ MODE,C0,C1,
   C2,C3,C4:GRAPHICS MODE
TN 310 POKE 708,C0:POKE 709,C1:POKE 710,C
   2:POKE 711,C3:POKE 712,C4
OY 320 SC=PEEK(88)+PEEK(89]*256:A=USR(153
   6,1,SC,BANK)
OB 330 GOTO 250
JF 9000 FOR I=1536 TO 1637:READ D:POKE I,
   D:NEXT I:RETURN
KT 9005 DATA 104,104,104,208,18,104,133,2
   25,104,133,224,104,104,32,65,6,134,226
   ,132,227
GL 9010 DATA 76,38,6,104,133,227,104,133,
   226,104,104,32,65,6,134,224,132,225,16
   2,30
YO 9015 DATA 160,0,177,224,145,226,200,20
   8,249,202,240,7,230,225,230,227,76,40,
   6,169
GS 9020 DATA 253,141,1,211,96,170,24,106,
   144,8,32,86,6,162,0,160,64,96,32,86
RU 9025 DATA 6,162,0,160,94,96,202,189,94
   ,6,141 1,211,96,225,225,229,229,233,23
   3
ZG 9030 DATA 237,237
QD 9100 DATA PIC.1,PIC.2,PIC.3,PIC.4,PIC.
   5,PIC.6,PIC.7,PIC.8
ZI 9200 REM SCREEN SPECIFIC DATA
UX 9201 DATA 31,20,18,0,0,70
TP 9202 DATA 31,50,10,4,0,0
ZJ 9203 DATA 31,36,12,68,0,0
QP 9204 DATA 31,40,202,148,0,0
HO 9205 DATA 31,2,4,38,0,0
AQ 9206 DATA 31,0,10,66,0,148
BB 9207 DATA 24,0,10,2,0,2
XZ 9208 DATA 24,0,10,0,0,0


Listing 2:
Assembly


10       .OPT NO LIST
20 ;SAVE#D:XEBANKS.M65
30 ;ASM,,#D:XEBANKS.OBJ
40 ;
50 ;--------------------------------
60 ; Save up to 8 Gr.7+,8,9,10 or 11
70 ; screens into the XE's extra
80 ; RAM. Won't interfere with
90 ; BASIC!
0100 ;
0110 ; Call with:
0120 ; A=U5R(1536,oper,scrn,bank)
0130 ; Where:
0140 ; 1536 is addr of routine
0150 ; oper = 0 for save to XRAM
0160 ;        1 for load from XRAM
0170 ; scrn = address of screen RAM
0180 ; bank = a number from 1-8
0190 ;        signifying which "bank"
0200 ;        to load/save to/from.
0210 ;-------------------------------
0220 ;
0230 FROM =  $E0
0240 TO =    $E2
0250 PORTB = $D301
0260 ;
0270     *=  $0600
0280 START
0290     PLA         # of args
0300     PLA         ignore high byte
0310     PLA         this is the one
0320     BNE LOAD    make SCRN the TO
0330 ;else make SCRN the FROM
0340 SAVE
0350     PLA
0360     STA FROM+1
0370     PLA
0380     STA FROM
0390     PLA         high of BANK
0400     PLA         low of BANK
0410     JSR WHERE
0420     STX TO
0430     STY TO+1
0440     JMP ACTION
0450 LOAD
0460     PLA
0470     STA TO+1
0480     PLA
0490     STA TO
0500     PLA         high of BANK
0510     PLA         low of BANK
0520     JSR WHERE
0530     STX FROM
0540     STY FROM+1
0550 ACTION
0560 ;here we actually move the data
0570     LDX #$1E    # of pages
0580 LOOP1
0590     LDY #0
0600 LOOP2
0610     LDA (FROM),Y
0620     STA (TO),Y
0630     INY
0640     BNE LOOP2
0650     DEX
0660     BEQ DONE
0670     INC FROM+1  next page of RAM
0680     INC TO+1
0690     JMP LOOP1
0695 DONE
0700     LDA #$FD    restore it to
0710     STA PORTB   normal status.
0720     RTS         back to BASIC
0730 WHERE
0740 ; decide if the address is $4000
0750 ; or $5E00. Enable accordingly.
0760     TAX         save it for later
0770     CLC
0780     ROR A       odd or even?
0790     BCC EVEN
0800 ODD
0810 ; was an odd number, so the bank
0820 ; is 1, 3, 5 or 7. That means
0830 ; it's located at S4000.
0840     JSR ENABLE
0850     LDX #$00
0860     LDY #$40
0870     RTS
0880 EVEN
0890 ; set up for pointing to $5E00.
0900     JSR ENABLE
0910     LDX #$00
0920     LDY #$5E
0930     RTS
0940 ENABLE
0950     DEX         1-8 now 0-7
0960     LDA INSTR,X
0970     STA PORTB
0980     RTS
0990 INSTR
1000     BYTE $E1,$E1,$E5,$E5
1010     BYTE $E9,$E9,$ED,$ED