]> git.sur5r.net Git - cc65/blob - libsrc/geos-cbm/tgi/geos-tgi.s
Added library reference address to lightpen driver header.
[cc65] / libsrc / geos-cbm / tgi / geos-tgi.s
1 ;
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
5
6             .include "zeropage.inc"
7             .include "tgi-kernel.inc"
8             .include "tgi-error.inc"
9             .include "const.inc"
10             .include "jumptab.inc"
11             .include "geossym.inc"
12             .include "geossym2.inc"
13             
14             .macpack generic
15
16 ; ------------------------------------------------------------------------
17 ; Constants
18
19 VDC_ADDR_REG    := $D600        ; VDC address
20 VDC_DATA_REG    := $D601        ; VDC data
21
22 VDC_DSP_HI      = 12            ; registers used
23 VDC_DSP_LO      = 13
24 VDC_DATA_HI     = 18
25 VDC_DATA_LO     = 19
26 VDC_VSCROLL     = 24
27 VDC_HSCROLL     = 25
28 VDC_COLORS      = 26
29 VDC_CSET        = 28
30 VDC_COUNT       = 30
31 VDC_DATA        = 31
32
33 ; ------------------------------------------------------------------------
34 ; Header. Includes jump table and constants.
35
36 .segment        "JUMPTABLE"
37
38 ; First part of the header is a structure that has a magic signature,
39 ; and defines the capabilities of the driver.
40
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
52
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).
55
56         .addr INSTALL
57         .addr UNINSTALL
58         .addr INIT
59         .addr DONE
60         .addr GETERROR
61         .addr CONTROL
62         .addr CLEAR
63         .addr SETVIEWPAGE
64         .addr SETDRAWPAGE
65         .addr SETCOLOR
66         .addr SETPALETTE
67         .addr GETPALETTE
68         .addr GETDEFPALETTE
69         .addr SETPIXEL
70         .addr GETPIXEL
71         .addr LINE
72         .addr BAR
73         .addr TEXTSTYLE
74         .addr OUTTEXT
75         .addr 0                 ; IRQ entry is unused
76
77 ; ------------------------------------------------------------------------
78 ; Data.
79
80 ; Variables mapped to the zero-page segment variables. Some of these are
81 ; used for passing parameters to the driver.
82
83 X1      = ptr1
84 Y1      = ptr2
85 X2      = ptr3
86 Y2      = ptr4
87
88 ; Absolute variables used in the code
89
90 .bss
91
92 SCRBASE:
93         .res 1                  ; High byte of screen base (64k VDC only)
94
95 ERROR:  
96         .res 1                  ; Error code
97 PALETTE:
98         .res 2                  ; The current palette
99
100 BITMASK:
101         .res 1                  ; $00 = clear, $01 = set pixels
102
103 OLDCOLOR:
104         .res 1                  ; colors before entering gfx mode
105
106 ; Text output stuff
107 TEXTMAGX:
108         .res 1
109 TEXTMAGY:
110         .res 1
111 TEXTDIR:
112         .res 1
113
114 ; Constants and tables
115
116 .rodata
117
118 DEFPALETTE:
119         .byte $00, $0f          ; White on black
120 PALETTESIZE     = * - DEFPALETTE
121
122 ; color translation table (indexed by VIC color)
123 COLTRANS:
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
127
128 .code
129
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
133 ; most of the time.
134 ;
135 ; Must set an error code: NO
136 ;
137
138 INSTALL:
139         lda version             ; if GEOS 1.0...
140         and #$f0
141         cmp #$10
142         beq @L40
143         lda c128Flag            ; at least GEOS 2.0, but we're on C128?
144         bpl @L40
145         lda graphMode           ; GEOS 2.0, C128, but is 80 column screen enabled?
146         bmi @L80
147 @L40:   rts                     ; leave default values for 40 column screen
148
149         ; check for VDC version and update register $19 value
150
151 @L80:
152         ; double the x resolution and halve the aspect ratio
153
154         asl xres
155         rol xres+1
156
157         lsr aspect+1
158         ror aspect
159
160         ; update number of available screens
161
162         ldx #VDC_CSET           ; determine size of RAM...
163         jsr VDCReadReg
164         sta tmp1
165         ora #%00010000
166         jsr VDCWriteReg         ; turn on 64k
167
168         jsr settestadr1         ; save original value of test byte
169         jsr VDCReadByte
170         sta tmp2
171
172         lda #$55                ; write $55 here
173         ldy #ptr1
174         jsr test64k             ; read it here and there
175         lda #$aa                ; write $aa here
176         ldy #ptr2
177         jsr test64k             ; read it here and there
178
179         jsr settestadr1
180         lda tmp2
181         jsr VDCWriteByte        ; restore original value of test byte
182
183         lda ptr1                ; do bytes match?
184         cmp ptr1+1
185         bne @have64k
186         lda ptr2
187         cmp ptr2+1
188         bne @have64k
189
190         ldx #VDC_CSET
191         lda tmp1
192         jsr VDCWriteReg         ; restore 16/64k flag
193         jmp @endok              ; and leave default values for 16k
194
195 @have64k:
196         lda #4
197         sta pages
198 @endok:
199         lda #0
200         sta SCRBASE             ; draw page 0 as default
201         rts 
202
203 test64k:    
204         sta tmp1
205         sty ptr3
206         lda #0
207         sta ptr3+1
208         jsr settestadr1
209         lda tmp1
210         jsr VDCWriteByte        ; write $55
211         jsr settestadr1
212         jsr VDCReadByte         ; read here
213         pha
214         jsr settestadr2
215         jsr VDCReadByte         ; and there
216         ldy #1
217         sta (ptr3),y
218         pla
219         dey
220         sta (ptr3),y
221         rts
222
223 settestadr1:
224         ldy #$02                ; test page 2 (here)
225         .byte $2c
226 settestadr2:
227         ldy #$42                ; or page 64+2 (there)
228         lda #0
229         jmp VDCSetSourceAddr
230
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.
234 ;
235 ; Must set an error code: NO
236 ;
237
238 UNINSTALL:
239         rts
240
241
242 ; ------------------------------------------------------------------------
243 ; INIT: Changes an already installed device from text mode to graphics
244 ; mode.
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
249 ; kernel later.
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.
252 ;
253 ; Must set an error code: YES
254 ;
255
256 INIT:
257         ldx #$01
258         stx BITMASK             ; solid black as pattern
259         lda #1
260         jsr SetPattern
261         lda #ST_WR_FORE         ; write only on foreground
262         sta dispBufferOn
263
264         lda graphMode
265         bmi @L80
266
267 ; Remember current color value (40 columns)
268         lda screencolors
269         sta OLDCOLOR
270         jmp @L99
271
272 ; Remember current color value (80 columns)
273 @L80:   lda scr80colors
274         sta OLDCOLOR
275 @L99:   lda #0
276         jsr SETVIEWPAGE         ; switch into viewpage 0
277
278 ; Done, reset the error code
279
280         lda #TGI_ERR_OK
281         sta ERROR
282         rts
283
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.
288 ;
289 ; Must set an error code: NO
290 ;
291
292 DONE:
293         lda #0
294         jsr SETVIEWPAGE         ; switch into viewpage 0
295
296         lda graphMode
297         bmi @L80
298
299         lda OLDCOLOR
300         sta screencolors        ; restore color for 40 columns
301         ldx #0
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
306         inx
307         bne @L1
308         rts
309
310 @L80:   lda OLDCOLOR            ; restore color for 80 columns
311         ldx #VDC_COLORS
312         jmp VDCWriteReg
313
314 ; ------------------------------------------------------------------------
315 ; GETERROR: Return the error code in A and clear it.
316
317 GETERROR:
318         ldx #TGI_ERR_OK
319         lda ERROR
320         stx ERROR
321         rts
322
323 ; ------------------------------------------------------------------------
324 ; CONTROL: Platform/driver specific entry point.
325 ;
326 ; Must set an error code: YES
327 ;
328
329 CONTROL:
330         lda #TGI_ERR_INV_FUNC
331         sta ERROR
332         rts
333
334 ; ------------------------------------------------------------------------
335 ; CLEAR: Clears the screen.
336 ;
337 ; Must set an error code: NO
338 ;
339
340 CLEAR:
341         lda curPattern
342         pha
343         lda #0
344         jsr SetPattern
345         ldx #0
346         stx r3L
347         stx r3H
348         stx r2L
349         lda #199
350         sta r2H
351         lda graphMode
352         bpl @L40
353         lda #>639               ; 80 columns
354         ldx #<639
355         bne @L99
356 @L40:   lda #>319               ; 40 columns
357         ldx #<319
358 @L99:   sta r4H
359         stx r4L
360         jsr Rectangle
361         pla
362         sta curPattern
363         rts
364
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.
368 ;
369 ; Must set an error code: NO (will only be called if page ok)
370 ;
371
372 SETVIEWPAGE:
373         ldx graphMode
374         bmi @L80
375         rts
376 @L80:   clc
377         ror
378         ror
379         ror
380         ldx #VDC_DSP_HI
381         jmp VDCWriteReg
382
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.
386 ;
387 ; Must set an error code: NO (will only be called if page ok)
388 ;
389
390 SETDRAWPAGE:
391         ldx graphMode
392         bmi @L80
393         rts
394 @L80:   clc
395         ror
396         ror
397         ror
398         sta SCRBASE
399         rts
400
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).
404 ;
405 ; Must set an error code: NO (will only be called if color ok)
406 ;
407
408 SETCOLOR:
409         tax
410         beq @L1
411         lda #1
412 @L1:    sta BITMASK
413         jmp SetPattern          ; need to have either 0 or 1
414
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
418 ; are not supported
419 ;
420 ; Must set an error code: YES
421 ;
422
423 SETPALETTE:
424         jsr GETERROR            ; clear error (if any)
425
426         ldy #PALETTESIZE - 1
427 @L1:    lda (ptr1),y            ; Copy the palette
428         and #$0F                ; Make a valid color
429         sta PALETTE,y
430         dey
431         bpl @L1
432
433 ; Put colors from palette into screen
434
435         lda graphMode
436         bmi @L80
437
438         lda PALETTE+1           ; foreground
439         asl a
440         asl a
441         asl a
442         asl a
443         ora PALETTE             ; background
444         ldx #0
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
449         inx
450         bne @L2
451         rts
452
453 @L80:   ldy PALETTE+1           ; Foreground color
454         lda COLTRANS,y
455         asl a
456         asl a
457         asl a
458         asl a
459         ldy PALETTE             ; Background color
460         ora COLTRANS,y
461
462         ldx #VDC_COLORS
463         jmp VDCWriteReg
464
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.
469 ;
470 ; Must set an error code: NO
471 ;
472
473 GETPALETTE:
474         lda #<PALETTE
475         ldx #>PALETTE
476         rts
477
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.
483 ;
484 ; Must set an error code: NO (all drivers must have a default palette)
485 ;
486
487 GETDEFPALETTE:
488         lda #<DEFPALETTE
489         ldx #>DEFPALETTE
490         rts
491
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.
496 ;
497 ; Must set an error code: NO
498 ;
499
500 SETPIXEL:
501         lda X1
502         ldx X1+1
503         ldy Y1
504         sta r3L
505         stx r3H
506         sty r11L
507         sec
508         lda BITMASK             ; set or clear C flag
509         bne @L1
510         clc
511 @L1:    lda #0
512         jmp DrawPoint
513
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.
518
519
520 GETPIXEL:
521         lda X1
522         ldx X1+1
523         ldy Y1
524         sta r3L
525         stx r3H
526         sty r11L
527         jsr TestPoint
528         ldx #0
529         bcc @L1
530         inx
531 @L1:    txa
532         ldx #0
533         rts
534
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.
538 ;
539 ; Must set an error code: NO
540 ;
541
542 LINE:
543         lda X1
544         ldx X1+1
545         ldy Y1
546         sta r3L
547         stx r3H
548         sty r11L
549         lda X2
550         ldx X2+1
551         ldy Y2
552         sta r4L
553         stx r4H
554         sty r11H
555         sec
556         lda BITMASK             ; set or clear C flag
557         bne @L1
558         clc
559 @L1:    lda #0
560         jmp DrawLine
561
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:
568 ;       X1 <= X2
569 ;       Y1 <= Y2
570 ;       (X1 >= 0) && (X1 < XRES)
571 ;       (X2 >= 0) && (X2 < XRES)
572 ;       (Y1 >= 0) && (Y1 < YRES)
573 ;       (Y2 >= 0) && (Y2 < YRES)
574 ;
575 ; Must set an error code: NO
576 ;
577
578 BAR:
579         lda X1
580         ldx X1+1
581         ldy Y1
582         sta r3L
583         stx r3H
584         sty r2L
585         lda X2
586         ldx X2+1
587         ldy Y2
588         sta r4L
589         stx r4H
590         sty r2H
591         jmp Rectangle
592
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.
596 ;
597 ; Must set an error code: NO
598 ;
599
600 TEXTSTYLE:
601         stx TEXTMAGX
602         sty TEXTMAGY
603         sta TEXTDIR
604         rts
605
606
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.
611 ;
612 ; Must set an error code: NO
613 ;
614
615 OUTTEXT:
616         lda TEXTDIR
617 ;       cmp #TGI_TEXT_HORIZONTAL ; this is equal 0
618         bne @vertical
619
620         lda X1                  ; horizontal text output
621         ldx X1+1
622         ldy Y1
623         sta r11L
624         stx r11H
625         sty r1H
626         lda ptr3
627         ldx ptr3+1
628         sta r0L
629         stx r0H
630         jmp PutString
631
632 @vertical:
633         lda X1                  ; vertical text output
634         ldx X1+1
635         ldy Y1
636         sta r11L
637         stx r11H
638         sty r1H
639         ldy #0
640         lda (ptr3),y
641         beq @end
642         jsr PutChar
643         inc ptr3
644         bne @L1
645         inc ptr3+1
646 @L1:    lda Y1
647         clc
648         adc #8
649         sta Y1
650         bne @vertical
651 @end:   rts
652
653 ;-------------
654 ; VDC helpers
655
656 VDCSetSourceAddr:
657         pha
658         tya
659         ldx #VDC_DATA_HI
660         jsr VDCWriteReg
661         pla
662         ldx #VDC_DATA_LO
663         bne VDCWriteReg
664
665 VDCReadByte:
666         ldx #VDC_DATA
667 VDCReadReg:
668         stx VDC_ADDR_REG
669 @L0:    bit VDC_ADDR_REG
670         bpl @L0
671         lda VDC_DATA_REG
672         rts
673
674 VDCWriteByte:
675         ldx #VDC_DATA
676 VDCWriteReg:
677         stx VDC_ADDR_REG
678 @L0:    bit VDC_ADDR_REG
679         bpl @L0
680         sta VDC_DATA_REG
681         rts