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