; ****************************************************************************

; VDC-BG : routines for a BG screen within VDC RAM on 64K VDC RAM C128's

;

; Robert A. Knop Jr., Usenet Hacking Mag Issue #3

; ****************************************************************************

.if Pass1

.noeqin

.include geosSym

.include 128sym

.include geosMac

.eqin

.endif

FGVDCBASE = $0000 ;Address in VDC of foreground screen

BGVDCBASE = $4000 ;Address in VDC of background screen

; ***************************************************************************

; InitVDC -- Makes sure your VDC is set up for 64K. Have fun calling this one on a 16K VDC.

; If you are motivated, modify this to verify that there is in fact have 64K of VDC

; RAM, and return an error if there is only 16K.

;

; Note -- Call this BEFORE you do any drawing on the screen, otherwise you will become

; hopelessly confused. At any rate, I probably will, and I won't even be there.

; ***************************************************************************

InitVDC:

jsr TempHideMouse

ldx #28 ;Memory type register

jsr ReadVDC

ora #%00010000 ;Tell it we've got 64K

jsr WriteVDC

rts

; *****************************************************************************

; VDCImpRect -- Imprint a rectangle from FG to BG

; VDCRecRect -- Recover a rectangle from BG to FG

;

; Pass: r3 x coordinate of upper left endpoint (word)

; r2L y coordinate of upper left endpoint (byte

; r4 x coordinate of lower right endpoint (word)

; r2H y coordinate of lower right endpoint (byte)

;

; Returns: r3 and r4 processed through NormalizeX

;

; Nukes: a,x,y , r5-r8,r10L,r11

;

; Internal: r5-r8,r11 ;Used in the VDC line routines

; r10L ;Flag for which routine we're in

; *****************************************************************************

VDCImpRect:

LoadB r10L,#$80

bne contVDCrect

VDCRecRect:

LoadB r10L,#00

contVDCrect: PushB r2L

5$ sta r11L

bit r10L

bmi 10$

jsr VDCRecLine

bra 20$

10$ jsr VDCImpLine

20$ inc r2L

lda r2L

cmp r2H

bcc 5$

beq 5$

PopB r2L

rts

; *****************************************************************************

; VDCImpLine -- Imprint a horizontal line from FG to BG

; VDCRecLine -- Recover a horizontal line from BG to FG

;

; Pass: r3 x coordinate of leftmost endpoint (word)

; r4 x coordinate of rightmost endpoint (word)

; r11L y coordinate of line (byte)

;

; Returns: r3 and r4 processed through NormalizeX

;

; Nukes: a,x,y , r5-r8,r11

;

; Internal: r5 ;Starting byte of block to copy

; r6 ;Number of bytes to copy

; r7 ;Starting byte of destination block

; r8L ;Left X mask

; r8H ;Right X mask

; r11 ;Y byte offset; temp storage

; *****************************************************************************

VDCImpLine:

jsr GetDims ;Get the dimensions of these scary things

AddVW FGVDCBASE,r5

AddVW BGVDCBASE,r7

bra contVDCline

VDCRecLine:

jsr GetDims

AddVW BGVDCBASE,r5

AddVW FGVDCBASE,r7

contVDCline: jsr SetVDC ;Setup block copying

jsr DoVDC ;Do the copy of complete blocks

ldx #r5

jsr Ddec ;Point to the "partial" byte

ldx #r7

jsr Ddec

ldy r8L ;Check left mask

beq 5$ ;If it's zero, don't worry about leftmost byte

jsr Do1Byte ;Do the one byte

5$ ldy r8H ;Check right mask

beq 90$ ;If it's zero, then we're done

AddW r6,r5

clc

inc r5L

bcc 10$

inc r5H ;Point to rightmost byte (source)

10$ AddW r6,r7

clc

inc r7L

bcc 20$

inc r7H ;Point to rightmost byte (dest)

20$ jsr Do1Byte

90$ jsr RestVDC ;Restore VDC

rts

GetDims: ;Get dimensions for VDCImpLine,VDCRecLine

ldx #r3

jsr NormalizeX ;(Why someone would use BitMap

ldx #r4 ; doubling in an 80-column only application

jsr NormalizeX ; is somewhat beyond me....)

LoadB r8L,0

sta r8H

sta r11H

LoadW r5,80

ldx #r11

ldy #r5

jsr DMult ;r11 *= 80

MoveW r3,r5

ldx #$02 ;Divide by 8

10$ lsr r5H

ror r5L

ror r8L

dex

bpl 10$ ; ... so r5 has byte offset from start of line

ldx #$04

20$ lsr r8L

dex

bpl 20$

ldx r8L ;r8L has remainder of division

beq 40$

LoadB r8L,0

30$ sec

ror r8L

dex

bne 30$

lda #$ff

eor r8L

sta r8L ;Now r8L has the mask of the leftmost byte

inc r5L

;...continued on next page....

;...GetDims continued....

40$ MoveW r4,r6

inc r6L ;Point to one past last byte

bcc 45$

inc r6H

45$ ldx #$02 ;Divide by 8

50$ lsr r6H

ror r6L

ror r8H

dex

bpl 50$ ; ... so r6 has byte offset from start of line

SubB r5L,r6L ;Now r6 has byte count

ldx #$04

60$ lsr r8H

dex

bpl 60$

ldx r8H ;r8H has remainder of divisoin

beq 80$

LoadB r8H,0

70$ sec

ror r8H

dex

bne 70$ ;r8H has mask of rightmost byte

80$ AddB r11L,r5L

sta r7L

lda r11H

adc r5H

sta r5H

sta r7H ;r5, r7 have offset from screen top

rts

SetVDC: jsr TempHideMouse ;Set up VDC for block copying

ldx #24 ;Copy/fill register

jsr ReadVDC

sta VDCtemp

ora #%10000000 ;Set for block copy

sta $d601

rts

RestVDC: lda VDCtemp ;Restore original copy/fill status

ldx #24

jsr WriteVDC

rts

VDCtemp: .byte 0

DoVDC: ldx #18 ;Copy the bulk of the scanline

lda r7H ;Block copy destination

jsr WriteVDC

ldx #19

lda r7L

jsr WriteVDC

ldx #32 ;Block copy source

lda r5H

jsr WriteVDC

ldx #33

lda r5L

jsr WriteVDC

ldx #30 ;# bytes to copy

lda r6L

jsr WriteVDC ;BANGO!

rts

WriteVDC: stx $d600 ;Writes a to VDC register x

10$ bit $d600

bpl 10$

sta $d601

rts

ReadVDC: stx $d600 ;Reads a from VDC register x

10$ bit $d600

bpl 10$

lda $d601

rts

Do1Byte: sty r11H ;r11H holds the mask

ldx #18 ;Point to the source screen byte

lda r5H

jsr WriteVDC

ldx #19

lda r5L

jsr WriteVDC

ldx #31

jsr ReadVDC ;Get the value of this byte

and r11H ;Mask off bits that we don't modify

sta r11L ;save the result

lda r11H

eor #$ff ;flip the bits in the mask

sta r11H

ldx #18 ;Point to the dest screen byte

lda r7H

jsr WriteVDC

ldx #19

lda r7L

jsr WriteVDC

ldx #31

jsr ReadVDC ;Get the value of this byte

and r11H ;Mask out the bits to change

ora r11L ;...and load those bits in

pha

ldx #18 ;Point to the dest screen byte

lda r7H ; (reset the poitner because of the VDC's

jsr WriteVDC ; auto-increment)

ldx #19

lda r7L

jsr WriteVDC

ldx #31

pla

jsr WriteVDC