;
; Graphics driver for the 320x200x2 mode on the C64.
;
-; Based on Stephen L. Judds GRLIB code
+; Based on Stephen L. Judd's GRLIB code.
+;
+; 2017-01-13, Greg King
+; 2018-03-13, Sven Klose
;
- .include "zeropage.inc"
+ .include "zeropage.inc"
- .include "tgi-kernel.inc"
+ .include "tgi-kernel.inc"
.include "tgi-error.inc"
-
.macpack generic
+ .macpack module
; ------------------------------------------------------------------------
; Header. Includes jump table and constants.
-.segment "JUMPTABLE"
+ module_header _c64_hi_tgi
; First part of the header is a structure that has a magic and defines the
; capabilities of the driver
.byte $74, $67, $69 ; "tgi"
.byte TGI_API_VERSION ; TGI API version number
+ .addr $0000 ; Library reference
.word 320 ; X resolution
.word 200 ; Y resolution
.byte 2 ; Number of drawing colors
.addr UNINSTALL
.addr INIT
.addr DONE
- .addr GETERROR
+ .addr GETERROR
.addr CONTROL
.addr CLEAR
.addr SETVIEWPAGE
.addr BAR
.addr TEXTSTYLE
.addr OUTTEXT
- .addr 0 ; IRQ entry is unused
; ------------------------------------------------------------------------
; Data.
Y2 := ptr4
TEXT := ptr3
-ROW := tmp2 ; Bitmap row...
-COL := tmp3 ; ...and column, both set by PLOT
TEMP := tmp4
TEMP2 := sreg
POINT := regsave
-INRANGE := regsave+2 ; PLOT variable, $00 = coordinates in range
CHUNK := X2 ; Used in the line routine
OLDCHUNK := X2+1 ; Dito
.bss
-ERROR: .res 1 ; Error code
+ERROR: .res 1 ; Error code
PALETTE: .res 2 ; The current palette
BITMASK: .res 1 ; $00 = clear, $FF = set pixels
CHARROM := $D000 ; Character rom base address
CBASE := $D000 ; Color memory base address
-VBASE := $E000 ; Video memory base address
+VBASE := $E000 ; Video memory base address
.code
;
INSTALL:
- rts
+; rts ; fall through
; ------------------------------------------------------------------------
lda $D018
sta OLDD018
- lda #$48 ; Set color map to $D000, screen to $E000
+ lda #$48 ; Set color map to $D000, screen to $E000
sta $D018
- lda $D011 ; And turn on bitmap
+ lda $D011 ; And turn on bitmap
ora #$20
DONE1: sta $D011
; GETERROR: Return the error code in A and clear it.
GETERROR:
- ldx #TGI_ERR_OK
- lda ERROR
- stx ERROR
+ ldx #TGI_ERR_OK
+ lda ERROR
+ stx ERROR
rts
; ------------------------------------------------------------------------
;
CONTROL:
- lda #TGI_ERR_INV_FUNC
- sta ERROR
+ lda #TGI_ERR_INV_FUNC
+ sta ERROR
rts
; ------------------------------------------------------------------------
sta VBASE+$1C00,y
sta VBASE+$1D00,y
sta VBASE+$1E00,y
- sta VBASE+$1F00,y
+ sta VBASE+$1E40,y ; preserve vectors
iny
bne @L1
rts
;
SETVIEWPAGE:
- rts
+; rts ; fall through
; ------------------------------------------------------------------------
; SETDRAWPAGE: Set the drawable page. Called with the new page in A (0..n).
; Initialize the color map with the new color settings (it is below the
; I/O area)
- ldy #$00
- sei
- lda $01 ; Get ROM config
- pha ; Save it
- and #%11111100 ; Clear bit 0 and 1
- sta $01
- txa ; Load color code
-@L2: sta CBASE+$0000,y
- sta CBASE+$0100,y
- sta CBASE+$0200,y
- sta CBASE+$0300,y
- iny
- bne @L2
- pla
- sta $01
- cli
+ ldy #$00
+ sei
+ lda $01 ; Get ROM config
+ pha ; Save it
+ and #%11111100 ; Clear bit 0 and 1
+ sta $01
+ txa ; Load color code
+@L2: sta CBASE+$0000,y
+ sta CBASE+$0100,y
+ sta CBASE+$0200,y
+ sta CBASE+$02e8,y
+ iny
+ bne @L2
+ pla
+ sta $01
+ cli
; Done, reset the error code
; LINE: Draw a line from X1/Y1 to X2/Y2, where X1/Y1 = ptr1/ptr2 and
; X2/Y2 = ptr3/ptr4 using the current drawing color.
;
-; To deal with off-screen coordinates, the current row
-; and column (40x25) is kept track of. These are set
-; negative when the point is off the screen, and made
-; positive when the point is within the visible screen.
-;
; X1,X2 etc. are set up above (x2=LINNUM in particular)
; Format is LINE x2,y2,x1,y1
;
stx YINCDEC
stx XINCDEC
- jsr CALC ; Set up .X,.Y,POINT, and INRANGE
+ jsr CALC ; Set up .X, .Y, and POINT
lda BITCHUNK,X
sta OLDCHUNK
sta CHUNK
eor CHUNK
sta CHUNK
txa
- bne @CONT ;If dy=0 it's just a point
- inx
+ beq YCONT2 ;If dy=0, it's just a point
@CONT: lsr ;Init counter to dy/2
;
; Main loop
;
YLOOP: sta TEMP
- lda INRANGE ;Range check
- bne @SKIP
-
- lda (POINT),y ;Otherwise plot
+ lda (POINT),y
eor BITMASK
and CHUNK
eor (POINT),y
sta (POINT),y
-@SKIP:
YINCDEC:
iny ;Advance Y coordinate
cpy #8
and CHUNK
eor (POINT),y
sta (POINT),y
-YDONE: lda #$36
+ lda #$36
sta $01
cli
rts
bne YCONT ;If we pass a column boundary...
ror CHUNK ;then reset CHUNK to $80
sta TEMP2
- lda COL
- bmi @C1 ;Skip if column is negative
- cmp #39 ;End if move past end of screen
- bcs YDONE
-@C1: lda POINT ;And add 8 to POINT
+ lda POINT ;And add 8 to POINT
adc #8
sta POINT
bcc @CONT
inc POINT+1
-@CONT: inc COL ;Increment column
- bne @C2
- lda ROW ;Range check
- cmp #25
- bcs @C2
- lda #00 ;Passed into col 0
- sta INRANGE
-@C2: lda TEMP2
+@CONT: lda TEMP2
dex
bne YLOOP
beq YCONT2
dec COUNTHI ;High bits set?
bpl XLOOP
-XDONE: lsr CHUNK ;Advance to last point
+ lsr CHUNK ;Advance to last point
jsr LINEPLOT ;Plot the last chunk
-EXIT: lda #$36
+ lda #$36
sta $01
cli
rts
lda #$FF
sta CHUNK
sta OLDCHUNK
- lda COL
- bmi @C1 ;Skip if column is negative
- cmp #39 ;End if move past end of screen
- bcs EXIT
-@C1: lda POINT
+ lda POINT
+ clc
adc #8
sta POINT
- bcc @CONT
+ lda TEMP
+ bcc XCONT1
inc POINT+1
-@CONT: inc COL
- bne @C2
- lda ROW
- cmp #25
- bcs @C2
- lda #00
- sta INRANGE
-@C2: lda TEMP
- sec
- bcs XCONT1
+ jmp XCONT1
;
; Check to make sure there isn't a high bit, plot chunk,
; and update Y-coordinate.
; room, gray hair, etc.)
;
LINEPLOT: ; Plot the line chunk
- lda INRANGE
- bne @SKIP
-
- lda (POINT),Y ; Otherwise plot
+ lda (POINT),Y
eor BITMASK
ora CHUNK
and OLDCHUNK
eor CHUNK
eor (POINT),Y
sta (POINT),Y
-@SKIP: rts
+ rts
;
; Subroutine to fix up pointer when Y decreases through
;
FIXY: cpy #255 ;Y=255 or Y=8
beq @DECPTR
+
@INCPTR: ;Add 320 to pointer
ldy #0 ;Y increased through 7
- lda ROW
- bmi @C1 ;If negative, then don't update
- cmp #24
- bcs @TOAST ;If at bottom of screen then quit
-@C1: lda POINT
+ lda POINT
adc #<320
sta POINT
lda POINT+1
adc #>320
sta POINT+1
-@CONT1: inc ROW
- bne @DONE
- lda COL
- bpl @CLEAR
-@DONE: rts
+ rts
@DECPTR: ;Okay, subtract 320 then
ldy #7 ;Y decreased through 0
lda POINT+1
sbc #>320
sta POINT+1
-@CONT2: dec ROW
- bmi @TOAST
- lda ROW
- cmp #24
- bne @DONE
- lda COL
- bmi @DONE
-@CLEAR: lda #00
- sta INRANGE
rts
-@TOAST: pla ;Remove old return address
- pla
- jmp EXIT ;Restore interrupts, etc.
-
; ------------------------------------------------------------------------
; BAR: Draw a filled rectangle with the corners X1/Y1, X2/Y2, where
; X1/Y1 = ptr1/ptr2 and X2/Y2 = ptr3/ptr4 using the current drawing color.
; the original C wrapper and could be written much smaller (besides that,
; calling LINE is not a good idea either).
-BAR: lda Y2
+BAR: lda Y2
sta Y2SAVE
lda Y2+1
sta Y2SAVE+1
lda X1+1
sta X1SAVE+1
-@L1: lda Y1
+@L1: lda Y1
sta Y2
lda Y1+1
sta Y2+1
- jsr LINE
+ jsr LINE
lda Y1SAVE
cmp Y2SAVE
OUTTEXT:
; Calculate a pointer to the representation of the character in the
-; character ROM
+; character ROM
ldx #((>(CHARROM + $0800)) >> 3)
ldy #0
rts
; ------------------------------------------------------------------------
-; Calculate all variables to plot the pixel at X1/Y1. If the point is out
-; of range, a carry is returned and INRANGE is set to a value !0 zero. If
-; the coordinates are valid, INRANGE is zero and the carry clear.
+; Calculate all variables to plot the pixel at X1/Y1.
CALC: lda Y1
- sta ROW
+ sta TEMP2
and #7
tay
lda Y1+1
lsr ; Neg is possible
- ror ROW
+ ror TEMP2
lsr
- ror ROW
+ ror TEMP2
lsr
- ror ROW
+ ror TEMP2
lda #00
sta POINT
- lda ROW
+ lda TEMP2
cmp #$80
ror
ror POINT
cmp #$80
ror
ror POINT ; row*64
- adc ROW ; +row*256
+ adc TEMP2 ; +row*256
clc
adc #>VBASE ; +bitmap base
sta POINT+1
lda X1
tax
- sta COL
- lda X1+1
- lsr
- ror COL
- lsr
- ror COL
- lsr
- ror COL
-
- txa
and #$F8
clc
adc POINT ; +(X AND #$F8)
txa
and #7
tax
-
- lda ROW
- cmp #25
- bcs @L9
- lda COL
- cmp #40
- bcs @L9
- lda #00
-@L9: sta INRANGE
rts
-
-