XE
BANKS
by Dave Schofield
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.
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