2 ; Graphics driver for the 320x200x2 and 640x200x2 modes on GEOS 64/128
3 ; 2010-08-17, Maciej 'YTM/Elysium' Witkowiak <ytm@elysium.pl>
4 ; 2010-08-18, Greg King
6 .include "zeropage.inc"
7 .include "tgi-kernel.inc"
8 .include "tgi-error.inc"
10 .include "jumptab.inc"
11 .include "geossym.inc"
12 .include "geossym2.inc"
16 ; ------------------------------------------------------------------------
19 VDC_ADDR_REG := $D600 ; VDC address
20 VDC_DATA_REG := $D601 ; VDC data
22 VDC_DSP_HI = 12 ; registers used
33 ; ------------------------------------------------------------------------
34 ; Header. Includes jump table and constants.
38 ; First part of the header is a structure that has a magic signature,
39 ; and defines the capabilities of the driver.
41 .byte $74, $67, $69 ; "tgi"
42 .byte TGI_API_VERSION ; TGI API version number
43 .addr $0000 ; Library reference
44 xres: .word 320 ; X resolution
45 yres: .word 200 ; Y resolution
46 .byte 2 ; Number of drawing colors
47 pages: .byte 1 ; Number of screens available
48 .byte 8 ; System font X size
49 .byte 8 ; System font Y size
50 aspect: .word $00D4 ; Aspect ratio (based on 4/3 display)
51 .byte 0 ; TGI driver flags
53 ; Next comes the jump table. With the exception of IRQ, all entries must be
54 ; valid, and may point to an RTS for test versions (function not implemented).
75 .addr 0 ; IRQ entry is unused
77 ; ------------------------------------------------------------------------
80 ; Variables mapped to the zero-page segment variables. Some of these are
81 ; used for passing parameters to the driver.
88 ; Absolute variables used in the code
93 .res 1 ; High byte of screen base (64k VDC only)
98 .res 2 ; The current palette
101 .res 1 ; $00 = clear, $01 = set pixels
104 .res 1 ; colors before entering gfx mode
114 ; Constants and tables
119 .byte $00, $0f ; White on black
120 PALETTESIZE = * - DEFPALETTE
122 ; color translation table (indexed by VIC color)
124 .byte $00, $0f, $08, $06, $0a, $04, $02, $0c
125 .byte $0d, $0b, $09, $01, $0e, $05, $03, $07
126 ; colors BROWN and GRAY3 are wrong
130 ; ------------------------------------------------------------------------
131 ; INSTALL routine. Is called after the driver is loaded into memory. May
132 ; initialize anything that has to be done just once. Is probably empty
135 ; Must set an error code: NO
139 lda version ; if GEOS 1.0...
143 lda c128Flag ; at least GEOS 2.0, but we're on C128?
145 lda graphMode ; GEOS 2.0, C128, but is 80 column screen enabled?
147 @L40: rts ; leave default values for 40 column screen
149 ; check for VDC version and update register $19 value
152 ; double the x resolution and halve the aspect ratio
160 ; update number of available screens
162 ldx #VDC_CSET ; determine size of RAM...
166 jsr VDCWriteReg ; turn on 64k
168 jsr settestadr1 ; save original value of test byte
172 lda #$55 ; write $55 here
174 jsr test64k ; read it here and there
175 lda #$aa ; write $aa here
177 jsr test64k ; read it here and there
181 jsr VDCWriteByte ; restore original value of test byte
183 lda ptr1 ; do bytes match?
192 jsr VDCWriteReg ; restore 16/64k flag
193 jmp @endok ; and leave default values for 16k
200 sta SCRBASE ; draw page 0 as default
210 jsr VDCWriteByte ; write $55
212 jsr VDCReadByte ; read here
215 jsr VDCReadByte ; and there
224 ldy #$02 ; test page 2 (here)
227 ldy #$42 ; or page 64+2 (there)
231 ; ------------------------------------------------------------------------
232 ; UNINSTALL routine. Is called before the driver is removed from memory. May
233 ; clean up anything done by INSTALL but is probably empty most of the time.
235 ; Must set an error code: NO
242 ; ------------------------------------------------------------------------
243 ; INIT: Changes an already installed device from text mode to graphics
245 ; Note that INIT/DONE may be called multiple times while the driver
246 ; is loaded, while INSTALL is only called once, so any code that is needed
247 ; to initializes variables and so on must go here. Setting palette and
248 ; clearing the screen is not needed because this is called by the graphics
250 ; The graphics kernel will never call INIT when a graphics mode is already
251 ; active, so there is no need to protect against that.
253 ; Must set an error code: YES
258 stx BITMASK ; solid black as pattern
261 lda #ST_WR_FORE ; write only on foreground
267 ; Remember current color value (40 columns)
272 ; Remember current color value (80 columns)
273 @L80: lda scr80colors
276 jsr SETVIEWPAGE ; switch into viewpage 0
278 ; Done, reset the error code
284 ; ------------------------------------------------------------------------
285 ; DONE: Will be called to switch the graphics device back into text mode.
286 ; The graphics kernel will never call DONE when no graphics mode is active,
287 ; so there is no need to protect against that.
289 ; Must set an error code: NO
294 jsr SETVIEWPAGE ; switch into viewpage 0
300 sta screencolors ; restore color for 40 columns
302 @L1: sta COLOR_MATRIX,x
303 sta COLOR_MATRIX+$0100,x
304 sta COLOR_MATRIX+$0200,x
305 sta COLOR_MATRIX+1000-256,x
310 @L80: lda OLDCOLOR ; restore color for 80 columns
314 ; ------------------------------------------------------------------------
315 ; GETERROR: Return the error code in A and clear it.
323 ; ------------------------------------------------------------------------
324 ; CONTROL: Platform/driver specific entry point.
326 ; Must set an error code: YES
330 lda #TGI_ERR_INV_FUNC
334 ; ------------------------------------------------------------------------
335 ; CLEAR: Clears the screen.
337 ; Must set an error code: NO
353 lda #>639 ; 80 columns
356 @L40: lda #>319 ; 40 columns
365 ; ------------------------------------------------------------------------
366 ; SETVIEWPAGE: Set the visible page. Called with the new page in A (0..n).
367 ; The page number is already checked to be valid by the graphics kernel.
369 ; Must set an error code: NO (will only be called if page ok)
383 ; ------------------------------------------------------------------------
384 ; SETDRAWPAGE: Set the drawable page. Called with the new page in A (0..n).
385 ; The page number is already checked to be valid by the graphics kernel.
387 ; Must set an error code: NO (will only be called if page ok)
401 ; ------------------------------------------------------------------------
402 ; SETCOLOR: Set the drawing color (in A). The new color is already checked
403 ; to be in a valid range (0..maxcolor-1).
405 ; Must set an error code: NO (will only be called if color ok)
413 jmp SetPattern ; need to have either 0 or 1
415 ; ------------------------------------------------------------------------
416 ; SETPALETTE: Set the palette (not available with all drivers/hardware).
417 ; A pointer to the palette is passed in ptr1. Must set an error if palettes
420 ; Must set an error code: YES
424 jsr GETERROR ; clear error (if any)
427 @L1: lda (ptr1),y ; Copy the palette
428 and #$0F ; Make a valid color
433 ; Put colors from palette into screen
438 lda PALETTE+1 ; foreground
443 ora PALETTE ; background
445 @L2: sta COLOR_MATRIX,x
446 sta COLOR_MATRIX+$0100,x
447 sta COLOR_MATRIX+$0200,x
448 sta COLOR_MATRIX+1000-256,x
453 @L80: ldy PALETTE+1 ; Foreground color
459 ldy PALETTE ; Background color
465 ; ------------------------------------------------------------------------
466 ; GETPALETTE: Return the current palette in A/X. Even drivers that cannot
467 ; set the palette should return the default palette here, so there's no
468 ; way for this function to fail.
470 ; Must set an error code: NO
478 ; ------------------------------------------------------------------------
479 ; GETDEFPALETTE: Return the default palette for the driver in A/X. All
480 ; drivers should return something reasonable here, even drivers that don't
481 ; support palettes, otherwise the caller has no way to determine the colors
482 ; of the (not changeable) palette.
484 ; Must set an error code: NO (all drivers must have a default palette)
492 ; ------------------------------------------------------------------------
493 ; SETPIXEL: Draw one pixel at X1/Y1 = ptr1/ptr2 with the current drawing
494 ; color. The coordinates passed to this function are never outside the
495 ; visible screen area, so there is no need for clipping inside this function.
497 ; Must set an error code: NO
508 lda BITMASK ; set or clear C flag
514 ; ------------------------------------------------------------------------
515 ; GETPIXEL: Read the color value of a pixel and return it in A/X. The
516 ; coordinates passed to this function are never outside the visible screen
517 ; area, so there is no need for clipping inside this function.
535 ; ------------------------------------------------------------------------
536 ; LINE: Draw a line from X1/Y1 to X2/Y2, where X1/Y1 = ptr1/ptr2 and
537 ; X2/Y2 = ptr3/ptr4 using the current drawing color.
539 ; Must set an error code: NO
556 lda BITMASK ; set or clear C flag
562 ; ------------------------------------------------------------------------
563 ; BAR: Draw a filled rectangle with the corners X1/Y1, X2/Y2, where
564 ; X1/Y1 = ptr1/ptr2 and X2/Y2 = ptr3/ptr4 using the current drawing color.
565 ; Contrary to most other functions, the graphics kernel will sort and clip
566 ; the coordinates before calling the driver, so on entry the following
567 ; conditions are valid:
570 ; (X1 >= 0) && (X1 < XRES)
571 ; (X2 >= 0) && (X2 < XRES)
572 ; (Y1 >= 0) && (Y1 < YRES)
573 ; (Y2 >= 0) && (Y2 < YRES)
575 ; Must set an error code: NO
593 ; ------------------------------------------------------------------------
594 ; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in X and Y
595 ; direction is passend in X/Y, the text direction is passed in A.
597 ; Must set an error code: NO
607 ; ------------------------------------------------------------------------
608 ; OUTTEXT: Output text at X/Y = ptr1/ptr2 using the current color and the
609 ; current text style. The text to output is given as a zero terminated
610 ; string with address in ptr3.
612 ; Must set an error code: NO
617 ; cmp #TGI_TEXT_HORIZONTAL ; this is equal 0
620 lda X1 ; horizontal text output
633 lda X1 ; vertical text output
669 @L0: bit VDC_ADDR_REG
678 @L0: bit VDC_ADDR_REG