; capabilities of the driver
.byte $74, $67, $69 ; "tgi"
- .byte $00 ; TGI version number
+ .byte TGI_API_VERSION ; TGI API version number
.word 320 ; X resolution
.word 200 ; Y resolution
.byte 2 ; Number of drawing colors
.byte 1 ; Number of screens available
- .res 6, $00 ; Reserved for future extensions
-
-; Next comes the jump table. Currently all entries must be valid and may point
-; to an RTS for test versions (function not implemented). A future version may
-; allow for emulation: In this case the vector will be zero. Emulation means
-; that the graphics kernel will emulate the function by using lower level
-; primitives - for example ploting a line by using calls to SETPIXEL.
-
- .word INSTALL
- .word DEINSTALL
- .word INIT
- .word DONE
- .word GETERROR
- .word CONTROL
- .word CLEAR
- .word SETVIEWPAGE
- .word SETDRAWPAGE
- .word SETCOLOR
- .word SETPALETTE
- .word GETPALETTE
- .word GETDEFPALETTE
- .word SETPIXEL
- .word GETPIXEL
- .word HORLINE
- .word LINE
- .word 0 ; BAR
- .word CIRCLE
-
+ .byte 8 ; System font X size
+ .byte 8 ; System font Y size
+ .word $100 ; Aspect ratio
+
+; Next comes the jump table. With the exception of IRQ, all entries must be
+; valid and may point to an RTS for test versions (function not implemented).
+
+ .addr INSTALL
+ .addr UNINSTALL
+ .addr INIT
+ .addr DONE
+ .addr GETERROR
+ .addr CONTROL
+ .addr CLEAR
+ .addr SETVIEWPAGE
+ .addr SETDRAWPAGE
+ .addr SETCOLOR
+ .addr SETPALETTE
+ .addr GETPALETTE
+ .addr GETDEFPALETTE
+ .addr SETPIXEL
+ .addr GETPIXEL
+ .addr LINE
+ .addr BAR
+ .addr TEXTSTYLE
+ .addr OUTTEXT
+ .addr 0 ; IRQ entry is unused
; ------------------------------------------------------------------------
; Data.
; Variables mapped to the zero page segment variables. Some of these are
; used for passing parameters to the driver.
-X1 = ptr1
-Y1 = ptr2
-X2 = ptr3
-Y2 = ptr4
-RADIUS = tmp1
+X1 := ptr1
+Y1 := ptr2
+X2 := ptr3
+Y2 := ptr4
-ROW = tmp2 ; Bitmap row...
-COL = tmp3 ; ...and column, both set by PLOT
-TEMP = tmp4
-TEMP2 = sreg
-POINT = regsave
+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
+CHUNK := X2 ; Used in the line routine
+OLDCHUNK := X2+1 ; Dito
; Absolute variables used in the code
; INIT/DONE
OLDD018: .res 1 ; Old register value
-; PLOT variables
-INRANGE: .res 1 ; $00 = coordinates in range
-
; Line routine stuff
DX: .res 2
DY: .res 2
-; Circle routine stuff
-CURX: .res 1
-CURY: .res 1
-BROW: .res 1 ; Bottom row
-TROW: .res 1 ; Top row
-LCOL: .res 1 ; Left column
-RCOL: .res 1 ; Right column
-CHUNK1: .res 1
-OLDCH1: .res 1
-CHUNK2: .res 1
-OLDCH2: .res 1
+; BAR variables
+X1SAVE: .res 2
+Y1SAVE: .res 2
+X2SAVE: .res 2
+Y2SAVE: .res 2
+
+; Text output stuff
+TEXTMAGX: .res 1
+TEXTMAGY: .res 1
+TEXTDIR: .res 1
; Constants and tables
; ------------------------------------------------------------------------
-; DEINSTALL routine. Is called before the driver is removed from memory. May
+; UNINSTALL routine. Is called before the driver is removed from memory. May
; clean up anything done by INSTALL but is probably empty most of the time.
;
; Must set an error code: NO
;
-DEINSTALL:
+UNINSTALL:
rts
; ------------------------------------------------------------------------
; INIT: Changes an already installed device from text mode to graphics
-; mode. The number of the graphics mode is passed to the function in A.
+; mode.
; Note that INIT/DONE may be called multiple times while the driver
; is loaded, while INSTALL is only called once, so any code that is needed
; to initializes variables and so on must go here. Setting palette and
; Must set an error code: YES
;
-INIT: cmp #TGI_MODE_320_200_2 ; Correct mode?
- beq @L1 ; Jump if yes
- lda #TGI_ERR_INV_MODE ; ## Error
- bne @L9
+INIT:
; Initialize variables
-@L1: ldx #$FF
+ ldx #$FF
stx BITMASK
; Switch into graphics mode
lda $D011 ; And turn on bitmap
ora #$20
- sta $D011
+DONE1: sta $D011
; Done, reset the error code
lda #TGI_ERR_OK
-@L9: sta ERROR
+ sta ERROR
rts
; ------------------------------------------------------------------------
; The graphics kernel will never call DONE when no graphics mode is active,
; so there is no need to protect against that.
;
-; Must set an error code: YES
+; Must set an error code: NO
;
DONE: lda $DD02 ; Set the data direction regs
sta $01
cli
-; Done
+; Done, reset the error code
+ lda #TGI_ERR_OK
+ sta ERROR
rts
; ------------------------------------------------------------------------
-; GETPALETTE: Return the current palette in A/X. Must return NULL and set an
-; error if palettes are not supported.
+; GETPALETTE: Return the current palette in A/X. Even drivers that cannot
+; set the palette should return the default palette here, so there's no
+; way for this function to fail.
;
-; Must set an error code: YES
+; Must set an error code: NO
;
GETPALETTE:
rts
; ------------------------------------------------------------------------
-; GETDEFPALETTE: Return the default palette for the driver in A/X. Must
-; return NULL and set an error of palettes are not supported.
+; GETDEFPALETTE: Return the default palette for the driver in A/X. All
+; drivers should return something reasonable here, even drivers that don't
+; support palettes, otherwise the caller has no way to determine the colors
+; of the (not changeable) palette.
;
-; Must set an error code: YES
+; Must set an error code: NO (all drivers must have a default palette)
;
GETDEFPALETTE:
ldx #$00 ; Clear high byte
rts
-; ------------------------------------------------------------------------
-; HORLINE: Draw a horizontal line from X1/Y to X2/Y, where X1 = ptr1,
-; Y = ptr2 and X2 = ptr3, using the current drawing color.
-;
-; This is a special line drawing entry used when the line is know to be
-; horizontal, for example by the BAR emulation routine. If the driver does
-; not have special code for horizontal lines, it may just copy Y to Y2 and
-; proceed with the generic line drawing code.
-;
-; Note: Line coordinates will always be sorted (Y1 <= X2) and clipped.
-;
-; Must set an error code: NO
-;
-
-HORLINE:
- lda ptr2
- sta ptr4
- lda ptr2+1
- sta ptr4+1
-; jmp LINE
-
; ------------------------------------------------------------------------
; 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.
bmi @C1 ;Skip if column is negative
cmp #39 ;End if move past end of screen
bcs EXIT
-@C1: lda POINT
+@C1: lda POINT
adc #8
sta POINT
bcc @CONT
@CONT1: inc ROW
bne @DONE
lda COL
- bmi @DONE
- lda #00
- sta INRANGE
+ bpl @CLEAR
@DONE: rts
@DECPTR: ;Okay, subtract 320 then
bne @DONE
lda COL
bmi @DONE
- lda #00
+@CLEAR: lda #00
sta INRANGE
rts
+
@TOAST: pla ;Remove old return address
pla
jmp EXIT ;Restore interrupts, etc.
; Must set an error code: NO
;
-BAR: rts
-
-; ------------------------------------------------------------------------
-; CIRCLE: Draw a circle around the center X1/Y1 (= ptr1/ptr2) with the
-; radius in tmp1 and the current drawing color.
-;
-; Must set an error code: NO
-;
+; Note: This function needs optimization. It's just a cheap translation of
+; the original C wrapper and could be written much smaller (besides that,
+; calling LINE is not a good idea either).
-CIRCLE: lda RADIUS
- sta CURY
- bne @L1
- jmp SETPIXEL ; Plot as a point
-
-@L1: clc
- adc Y1
- sta Y1
- bcc @L2
- inc Y1+1
-@L2: jsr CALC ; Compute XC, YC+R
-
- lda ROW
- sta BROW
- lda COL
- sta LCOL
- sta RCOL
-
- sty Y2 ; Y AND 07
- lda BITCHUNK,X
- sta CHUNK1 ; Forwards chunk
- sta OLDCH1
- lsr
- eor #$FF
- sta CHUNK2 ; Backwards chunk
- sta OLDCH2
- lda POINT
- sta TEMP2 ; TEMP2 = forwards high pointer
- sta X2 ; X2 = backwards high pointer
- lda POINT+1
- sta TEMP2+1
- sta X2+1
+BAR: lda Y2
+ sta Y2SAVE
+ lda Y2+1
+ sta Y2SAVE+1
-; Next compute CY-R
+ lda X2
+ sta X2SAVE
+ lda X2+1
+ sta X2SAVE+1
lda Y1
- sec
- sbc RADIUS
- bcs @C3
- dec Y1+1
- sec
-@C3: sbc RADIUS
- bcs @C4
- dec Y1+1
-@C4: sta Y1
-
- jsr CALC ; Compute new coords
- sty Y1
- lda POINT
- sta X1 ; X1 will be the backwards
- lda POINT+1 ; low-pointer
- sta X1+1 ; POINT will be forwards
- lda ROW
- sta TROW
-
- sei ; Get underneath ROM
- lda #$34
- sta $01
-
- lda RADIUS
- lsr ; A=r/2
- ldx #00
- stx CURX ; y=0
+ sta Y1SAVE
+ lda Y1+1
+ sta Y1SAVE+1
-; Main loop
+ lda X1
+ sta X1SAVE
+ lda X1+1
+ sta X1SAVE+1
-@LOOP: inc CURX ; x=x+1
+@L1: lda Y1
+ sta Y2
+ lda Y1+1
+ sta Y2+1
+ jsr LINE
- lsr CHUNK1 ; Right chunk
- bne @CONT1
- jsr UPCHUNK1 ; Update if we move past a column
-@CONT1: asl CHUNK2
- bne @CONT2
- jsr UPCHUNK2
-@CONT2: sec
- sbc CURX ; a=a-x
- bcs @LOOP
+ lda Y1SAVE
+ cmp Y2SAVE
+ bne @L2
+ lda Y1SAVE
+ cmp Y2SAVE
+ beq @L4
- adc CURY ;if a<0 then a=a+y; y=y-1
- tax
- jsr PCHUNK1
- jsr PCHUNK2
- lda CHUNK1
- sta OLDCH1
- lda CHUNK2
- sta OLDCH2
- txa
+@L2: inc Y1SAVE
+ bne @L3
+ inc Y1SAVE+1
- dec CURY ;(y=y-1)
+@L3: lda Y1SAVE
+ sta Y1
+ lda Y1SAVE+1
+ sta Y1+1
- dec Y2 ;Decrement y-offest for upper
- bpl @CONT3 ;points
- jsr DECYOFF
-@CONT3: ldy Y1
- iny
- sty Y1
- cpy #8
- bcc @CONT4
- jsr INCYOFF
-@CONT4: ldy CURX
- cpy CURY ;if y<=x then punt
- bcc @LOOP ;Now draw the other half
-;
-; Draw the other half of the circle by exactly reversing
-; the above!
-;
-NEXTHALF:
- lsr OLDCH1 ;Only plot a bit at a time
- asl OLDCH2
- lda RADIUS ;A=-R/2-1
- lsr
- eor #$FF
-@LOOP:
- tax
- jsr PCHUNK1 ;Plot points
- jsr PCHUNK2
- txa
- dec Y2 ;Y2=bottom
- bpl @CONT1
- jsr DECYOFF
-@CONT1: inc Y1
- ldy Y1
- cpy #8
- bcc @CONT2
- jsr INCYOFF
-@CONT2: ldx CURY
- beq @DONE
- clc
- adc CURY ;a=a+y
- dec CURY ;y=y-1
- bcc @LOOP
-
- inc CURX
- sbc CURX ;if a<0 then x=x+1; a=a+x
- lsr CHUNK1
- bne @CONT3
- tax
- jsr UPCH1 ;Upchunk, but no plot
-@CONT3: lsr OLDCH1 ;Only the bits...
- asl CHUNK2 ;Fix chunks
- bne @CONT4
- tax
- jsr UPCH2
-@CONT4: asl OLDCH2
- bcs @LOOP
-@DONE:
-CIRCEXIT: ;Restore interrupts
- lda #$37
- sta $01
- cli
- rts
-;
-; Decrement lower pointers
-;
-DECYOFF:
- tay
- lda #7
- sta Y2
+ lda X1SAVE
+ sta X1
+ lda X1SAVE+1
+ sta X1+1
- lda X2 ;If we pass through zero, then
- sec
- sbc #<320 ;subtract 320
+ lda X2SAVE
sta X2
- lda X2+1
- sbc #>320
+ lda X2SAVE+1
sta X2+1
- lda TEMP2
- sec
- sbc #<320
- sta TEMP2
- lda TEMP2+1
- sbc #>320
- sta TEMP2+1
+ jmp @L1
- tya
- dec BROW
- bmi EXIT2
- rts
-EXIT2: pla ;Grab return address
- pla
- jmp CIRCEXIT ;Restore interrupts, etc.
+@L4: rts
-; Increment upper pointers
-INCYOFF:
- tay
- lda #00
- sta Y1
- lda X1
- clc
- adc #<320
- sta X1
- lda X1+1
- adc #>320
- sta X1+1
- lda POINT
- clc
- adc #<320
- sta POINT
- lda POINT+1
- adc #>320
- sta POINT+1
-@ISKIP: inc TROW
- bmi @DONE
- lda TROW
- cmp #25
- bcs EXIT2
-@DONE: tya
- rts
+; ------------------------------------------------------------------------
+; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in X and Y
+; direction is passend in X/Y, the text direction is passed in A.
;
-; UPCHUNK1 -- Update right-moving chunk pointers
-; Due to passing through a column
+; Must set an error code: NO
;
-UPCHUNK1:
- tax
- jsr PCHUNK1
-UPCH1: lda #$FF ;Alternative entry point
- sta CHUNK1
- sta OLDCH1
- lda TEMP2
- clc
- adc #8
- sta TEMP2
- bcc @CONT
- inc TEMP2+1
- clc
-@CONT: lda POINT
- adc #8
- sta POINT
- bcc @DONE
- inc POINT+1
-@DONE: txa
- inc RCOL
- rts
-;
-; UPCHUNK2 -- Update left-moving chunk pointers
-;
-UPCHUNK2:
- tax
- jsr PCHUNK2
-UPCH2: lda #$FF
- sta CHUNK2
- sta OLDCH2
- lda X2
- sec
- sbc #8
- sta X2
- bcs @CONT
- dec X2+1
- sec
-@CONT: lda X1
- sbc #8
- sta X1
- bcs @DONE
- dec X1+1
-@DONE: txa
- dec LCOL
+TEXTSTYLE:
+ stx TEXTMAGX
+ sty TEXTMAGY
+ sta TEXTDIR
rts
-;
-; Plot right-moving chunk pairs for circle routine
-;
-PCHUNK1:
- lda RCOL ;Make sure we're in range
- cmp #40
- bcs @SKIP2
- lda CHUNK1 ;Otherwise plot
- eor OLDCH1
- sta TEMP
- lda TROW ;Check for underflow
- bmi @SKIP
- ldy Y1
- lda (POINT),y
- eor BITMASK
- and TEMP
- eor (POINT),y
- sta (POINT),y
-
-@SKIP: lda BROW ;If CY+Y >= 200...
- cmp #25
- bcs @SKIP2
- ldy Y2
- lda (TEMP2),y
- eor BITMASK
- and TEMP
- eor (TEMP2),y
- sta (TEMP2),y
-@SKIP2: rts
+; ------------------------------------------------------------------------
+; OUTTEXT: Output text at X/Y = ptr1/ptr2 using the current color and the
+; current text style. The text to output is given as a zero terminated
+; string with address in ptr3.
;
-; Plot left-moving chunk pairs for circle routine
+; Must set an error code: NO
;
-PCHUNK2:
- lda LCOL ;Range check in X
- cmp #40
- bcs EXIT3
- lda CHUNK2 ;Otherwise plot
- eor OLDCH2
- sta TEMP
- lda TROW ;Check for underflow
- bmi @SKIP
- ldy Y1
- lda (X1),y
- eor BITMASK
- and TEMP
- eor (X1),y
- sta (X1),y
-
-@SKIP: lda BROW ;If CY+Y >= 200...
- cmp #25
- bcs EXIT3
- ldy Y2
- lda (X2),y
- eor BITMASK
- and TEMP
- eor (X2),y
- sta (X2),y
-EXIT3: rts
+OUTTEXT:
+ rts
; ------------------------------------------------------------------------
; Calculate all variables to plot the pixel at X1/Y1. If the point is out