REU Programming & Border Removal

REU Programming & Border Removal
by Robin Harbron.

Note: This article originally appeared in Loadstar Letter #45, published in 1997. Thanks to the folks at Loadstar for granting permission for me to post it on my website.

This project turned out to be a real monster, but I think there are many things to be learned if you just read through this program.

My main goal was to show the basics of REU (Ram Expansion Unit) programming. But since I’m given to demo coding, I couldn’t help but show a couple of tricks while I was at it. But first, some explanation:

There are three different models of REUs: The 1700, 1764 & the 1750. They have 128K, 256K & 512K of RAM respectively. The RAM is divided into banks of 64K, although in practice you don’t even notice this. The 6510 processor in the C64 can only address 64K, so extra RAM can’t be added directly to the processor. Instead, a RAM Expansion Controller (REC) is available to the programmer in the second IO page ($DF00). This allows the Super Snapshot, as well as other cartridges, to co-exist with the REU.

The way an REU allows extra memory to be added to the computer in an ingenious way: Memory can be moved from and to (and swapped) the computer through programming the REC. Once the REC is told the source and destination addresses in both the computer & REU, and told how many bytes to move, and which direction to move them in, you can command the REU to begin the transfer. The processor is disabled while the memory is moved at the incredible rate of a byte per cycle! This is equivalent to one megabyte per second! The only possible slow down is the VIC chip grabbing some cycles to keep displaying the screen.

Now, while researching this topic, I came upon some interesting information. Let me explain:

Every cycle, the VIC chip grabs some information to display on the screen. Now, when it reaches the bottom border, instead of reading and displaying useful information, the VIC grabs whatever byte is located in the last byte of the current video bank ($3FFF is the default). This is usually not shown on screen, as the border hides it. But try this:

Enter the command POKE 53265,24 or POKE 53265,31. Notice a little bit of garbage appearing at your top or bottom border edge? Whatever you now poke into location 16383 will now appear 40 times at the top or bottom of your screen.

Now, it just so happens that your top and bottom border can be removed, rather easily. You simply wait until the raster reaches lines 248-250 (you don’t have to be too precise). Then shrink the top/bottom borders by putting a 19 into location 53265. This fools the VIC into missing the start of the border. Then a few lines later, put a 27 back into 53265, and repeat this every frame. Your top/bottom border is gone!

This reveals the $3FFF pattern over the whole screen.

         *= $4000

status   = $df00
command  = $df01
c64base  = $df02
reubase  = $df04
translen = $df07
irqmask  = $df09
control  = $df0a

delay    = $fa
count    = $ff
textp    = $fb
fontp    = $fd

text     = $0400
temp     = $2000


start    lda #127
         sta 56333
         lda 56333
         sei

         lda #<text
         sta textp
         lda #>text
         sta textp+1

         lda #1
         sta $d020
         sta $d021

main     lda #39
         sta count
loop2    ldy count
         lda (textp),y
         ldy #0
         sty fontp+1
         asl a
         rol fontp+1
         asl a
         rol fontp+1
         asl a
         rol fontp+1
         sta fontp
         clc
         lda fontp+1
         adc #$d0
         sta fontp+1
         lda #<temp
         sta self+1
         lda #>temp
         sta self+2
         lda 1
         and #251
         sta 1

         ldx count
         ldy #0

loop1
         lda (fontp),y
self     sta temp,x
         clc
         lda self+1
         adc #65
         sta self+1
         bcc ahead2
         inc self+2
ahead2   iny
         cpy #8
         bne loop1
         lda 1
         ora #4
         sta 1
         dec count
         bpl loop2

         inc delay
         lda delay
         and #%00001111
         bne ahead3

         inc textp
         bne ahead3
         inc textp+1
ahead3
         ldy #39
         lda (textp),y
         cmp #31
         bne ahead1
         lda #<text
         sta textp
         lda #>text
         sta textp+1

ahead1   lda #0
         sta temp+520
         sta control
         lda #<temp
         sta c64base
         lda #>temp
         sta c64base+1
         lda #0
         sta reubase
         sta reubase+1
         sta reubase+2
         lda #<521
         sta translen
         lda #>521
         sta translen+1
         lda #%10010000
         sta command

         lda #250 ;248 250
line1    cmp $d012
         bne line1

         lda #19 ;19 27
         sta $d011


         lda #253 ;252 
line2    cmp $d012
         bne line2

         lda #27
         sta $d011

         bit $00
         nop
         nop
         nop
         nop
         nop
         nop
         nop

         lda #%10000000
         sta control
         lda #<$3fff
         sta c64base
         lda #>$3fff
         sta c64base+1
         lda #0
         sta reubase
         sta reubase+1
         sta reubase+2
         lda #<521
         sta translen
         lda #>521
         sta translen+1
         lda #%10010001
         sta command

         jmp main
10 s=16384
20 READ a: IF a= 1THEN40
30 t=t+a:POKEs,a:s=s+1:GOTO20
40 IFt<>33593THENPRINT"data error":END
50 PRINT CHR$(147);
60 PRINT"sys16384 to start"
70 PRINT"scrolling text..."
100 DATA 169,127,141, 13,220,173, 13
110 DATA 220,120,169,  0,133,251,169
120 DATA   4,133,252,169,  1,141, 32
130 DATA 208,141, 33,208,169, 39,133
140 DATA 255,164,255,177,251,160,  0
150 DATA 132,254, 10, 38,254, 10, 38
160 DATA 254, 10, 38,254,133,253, 24
170 DATA 165,254,105,208,133,254,169
180 DATA   0,141, 78, 64,169, 32,141
190 DATA  79, 64,165,  1, 41,251,133
200 DATA   1,166,255,160,  0,177,253
210 DATA 157,  0, 32, 24,173, 78, 64
220 DATA 105, 65,141, 78, 64,144,  3
230 DATA 238, 79, 64,200,192,  8,208
240 DATA 232,165,  1,  9,  4,133,  1
250 DATA 198,255, 16,176,230,250,165
260 DATA 250, 41, 15,208,  6,230,251
270 DATA 208,  2,230,252,160, 39,177
280 DATA 251,201, 31,208,  8,169,  0
290 DATA 133,251,169,  4,133,252,169
300 DATA   0,141,  8, 34,141, 10,223
310 DATA 169,  0,141,  2,223,169, 32
320 DATA 141,  3,223,169,  0,141,  4
330 DATA 223,141,  5,223,141,  6,223
340 DATA 169,  9,141,  7,223,169,  2
350 DATA 141,  8,223,169,144,141,  1
360 DATA 223,169,250,205, 18,208,208
370 DATA 251,169, 19,141, 17,208,169
380 DATA 253,205, 18,208,208,251,169
390 DATA  27,141, 17,208, 36,  0,234
400 DATA 234,234,234,234,234,234,169
410 DATA 128,141, 10,223,169,255,141
420 DATA   2,223,169, 63,141,  3,223
430 DATA 169,  0,141,  4,223,141,  5
440 DATA 223,141,  6,223,169,  9,141
450 DATA   7,223,169,  2,141,  8,223
460 DATA 169,145,141,  1,223, 76, 25
470 DATA  64, 1