; All the drawing functions are simply done by sprites as the sprite
; engine is the only way to do fast graphics on a Lynx.
;
-; So the code is not really based on any algorithms done by somebody.
-; I have looked at other routines in the cc65 libs to see what kind of
-; entry points we need. And I have looked at the old cc65 libs by
-; Bastian Schick to see how things worked in the past.
-;
; This code is written by Karri Kaksonen, 2004 for the cc65 compiler.
;
.include "extzp.inc"
.include "tgi-kernel.inc"
- .include "tgi-mode.inc"
.include "tgi-error.inc"
.include "lynx.inc"
.byte 2 ; Number of screens available
.byte 8 ; System font X size
.byte 8 ; System font Y size
- .res 4, $00 ; Reserved for future extensions
+ .word $0100 ; Aspect ratio (square pixel LCD)
+ .byte TGI_BM_FONT_FINESCALE ; TGI driver flags
; 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
.addr GETPIXEL
.addr LINE
.addr BAR
- .addr CIRCLE
.addr TEXTSTYLE
.addr OUTTEXT
.addr IRQ
; Double buffer IRQ stuff
DRAWPAGE: .res 1
SWAPREQUEST: .res 1
-VBLHOOK: .res 3
text_bitmap: .res 8*(1+20+1)+1
; 8 rows with (one offset-byte plus 20 character bytes plus one fill-byte) plus one 0-offset-byte
stz BGINDEX
stz DRAWPAGE
stz SWAPREQUEST
- lda #$60 ; rts op-code
- sta VBLHOOK
rts
;
INIT:
+; Enable interrupts for VBL
+ lda #$80
+ tsb VTIMCTLA
+; Set up collision buffer to $A058
+ lda #$58
+ sta COLLBASL
+ lda #$A0
+ sta COLLBASH
+; Put collision index before sprite data
+ lda #$FE
+ sta COLLOFFL
+ lda #$FF
+ sta COLLOFFH
; Done, reset the error code
lda #TGI_ERR_OK
sta ERROR
;
; To set the frame rate for the display hardware call tgi_ioctl(3, rate)
;
-; To make a request for swapping the display buffers call tgi_ioctl(4, dataptr)
-; If the value of the char pointed to by the dataptr is 0 then fill in the
-; value of the char with the current state of the swap buffer 0 = idle, 1 = busy
-; If the value is not 0 then activate the swap function at next VBL interrupt
+; To check if the drawing engine is busy with the previous swap you can
+; call tgi_ioctl(4, 0). It returns 0 if idle and 1 if busy
+;
+; To update displays you can call tgi_ioctl(4, 1) it will wait for the
+; next VBL interrupt and swap draw and view buffers.
;
-; Set an address for a subroutine you want to call at every VBL
-; tgi_ioctl(5, hook)
+; Activate or deactivate collision detection by calling tgi_ioctl(5, 0/1).
CONTROL:
pha ; Almost all control routines succeed
lda #TGI_ERR_OK
sta ERROR
pla
+
cmp #5
- bne ControlSwapRequest
-
- lda ptr1 ; Set IRQ routine to be called at VBL
- sta VBLHOOK+1
- lda ptr1+1
- sta VBLHOOK+2
- lda #$43 ; jmp op-code
- sta VBLHOOK
+ bne ControlSwap
+ lda ptr1
+ bne @L0
+ lda __sprsys
+ ora #$20
+ bra @L1
+@L0: lda __sprsys
+ and #$df
+@L1: sta __sprsys
+ sta SPRSYS
rts
-ControlSwapRequest:
+ControlSwap:
cmp #4
bne ControlFramerate
cmp #3
bne ControlTextBG
+ lda ptr1
cmp #75 ; Set framerate
beq rate75
cmp #60
SETVIEWPAGE:
cmp #1
beq @L1 ; page == maxpages-1
- ldy #<$de20 ; page 0
- ldx #>$de20
+ ldy #<$e018 ; page 0
+ ldx #>$e018
bra @L2
@L1:
- ldy #<$be40 ; page 1
- ldx #>$be40
+ ldy #<$c038 ; page 1
+ ldx #>$c038
@L2:
sty VIEWPAGEL ; Save viewpage for getpixel
stx VIEWPAGEH
;
SETDRAWPAGE:
- cmp #1
+ cmp #1
beq @L1 ; page == maxpages-1
- lda #<$de20 ; page 0
- ldx #>$de20
+ lda #<$e018 ; page 0
+ ldx #>$e018
bra @L2
@L1:
- lda #<$be40 ; page 1
- ldx #>$be40
+ lda #<$c038 ; page 1
+ ldx #>$c038
@L2:
sta DRAWPAGEL
stx DRAWPAGEH
; IRQ: VBL interrupt handler
;
-TIMER0_INTERRUPT = $01
-TIMER1_INTERRUPT = $02
-TIMER2_INTERRUPT = $04
-TIMER3_INTERRUPT = $08
-TIMER4_INTERRUPT = $10
-TIMER5_INTERRUPT = $20
-TIMER6_INTERRUPT = $40
-TIMER7_INTERRUPT = $80
-
-HBL_INTERRUPT = TIMER0_INTERRUPT
-VBL_INTERRUPT = TIMER2_INTERRUPT
-SERIAL_INTERRUPT = TIMER4_INTERRUPT
-
IRQ:
- lda INTSET ; Poll all pending interrupts
- and #VBL_INTERRUPT
- bne IRQVBL
- clc ; Not a VBL interrupt - exit
- rts
-IRQVBL: sta INTRST ; Clear interrupt
- lda SWAPREQUEST
- bne @L0
- lda DRAWPAGE
- jsr SETVIEWPAGE
- lda DRAWPAGE
- eor #1
- sta DRAWPAGE
- jsr SETDRAWPAGE
- stz SWAPREQUEST
+ lda INTSET ; Poll all pending interrupts
+ and #VBL_INTERRUPT
+ beq IRQEND ; Exit if not a VBL interrupt
+
+ lda SWAPREQUEST
+ beq @L0
+ lda DRAWPAGE
+ jsr SETVIEWPAGE
+ lda DRAWPAGE
+ eor #1
+ sta DRAWPAGE
+ jsr SETDRAWPAGE
+ stz SWAPREQUEST
@L0:
- jsr VBLHOOK
- sec
- rts
+IRQEND:
+ clc
+ rts
; ------------------------------------------------------------------------
; SETCOLOR: Set the drawing color (in A). The new color is already checked
ldx #>bar_sprite
jmp draw_sprite
-; ------------------------------------------------------------------------
-; 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
-;
-; There is no sensible way of drawing a circle on a Lynx. As I would
-; have to use line elements to do the circle I rather do it in C than
-; create it here in the driver.
-
-; To do a circle please add this to your C program
-
-;int sintbl[9] = {
-; 0, // 0 degrees
-; 3196, // 11.25 degrees
-; 6270, // 22.5 degrees
-; 9102, // 33.75 degrees
-; 11585, // 45 degrees
-; 13623, // 56.25 degrees
-; 15137, // 67.5 degrees
-; 16069, // 78.75 degrees
-; 16384 // 90 degrees
-;};
-
-;int sin(char d)
-;{
-; char neg;
-; d = d & 31;
-; neg = d > 16;
-; d = d & 15;
-; if (d > 8)
-; d = 16 - d;
-; if (neg)
-; return -sintbl[d];
-; else
-; return sintbl[d];
-;}
-
-;void tgi_Circle(int x0, int y0, unsigned char r)
-;{
-; char i;
-; int x1, y1, x2, y2;
-;
-; x1 = ((long)sin(0) * r + 8192) / 16384 + x0;
-; y1 = ((long)sin(8) * r + 8192) / 16384 + y0;
-; for (i = 1; i <= 32; i++) {
-; x2 = ((long)sin(i) * r + 8192) / 16384 + x0;
-; y2 = ((long)sin(i+8) * r + 8192) / 16384 + y0;
-; tgi_line(x1, y1, x2, y2);
-; x1 = x2;
-; y1 = y2;
-; }
-;}
-
-;#define tgi_circle tgi_Circle
-
-CIRCLE:
- 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.
; The Font
; 96 characters from ASCII 32 to 127
; 8 pixels wide, 8 pixels high
-; bit value 0 = foreground, bit value 1 = background / transparent
+; bit value 0 = foreground, bit value 1 = background / transparent
font:
; VERSAIL
.byte $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF ;32