]> git.sur5r.net Git - cc65/blob - libsrc/geos-cbm/tgi/geos-tgi.s
Merge pull request #7 from cvemu/master
[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             .macpack module
16
17
18 ; ------------------------------------------------------------------------
19 ; Constants
20
21 VDC_ADDR_REG    := $D600        ; VDC address
22 VDC_DATA_REG    := $D601        ; VDC data
23
24 VDC_DSP_HI      = 12            ; registers used
25 VDC_DSP_LO      = 13
26 VDC_DATA_HI     = 18
27 VDC_DATA_LO     = 19
28 VDC_VSCROLL     = 24
29 VDC_HSCROLL     = 25
30 VDC_COLORS      = 26
31 VDC_CSET        = 28
32 VDC_COUNT       = 30
33 VDC_DATA        = 31
34
35 ; ------------------------------------------------------------------------
36 ; Header. Includes jump table and constants.
37
38         module_header   _geos_tgi_tgi
39
40 ; First part of the header is a structure that has a magic signature,
41 ; and defines the capabilities of the driver.
42
43         .byte $74, $67, $69     ; "tgi"
44         .byte TGI_API_VERSION   ; TGI API version number
45         .addr $0000             ; Library reference
46 xres:   .word 320               ; X resolution
47 yres:   .word 200               ; Y resolution
48         .byte 2                 ; Number of drawing colors
49 pages:  .byte 1                 ; Number of screens available
50         .byte 8                 ; System font X size
51         .byte 8                 ; System font Y size
52 aspect: .word $00D4             ; Aspect ratio (based on 4/3 display)
53         .byte 0                 ; TGI driver flags
54
55 ; Next comes the jump table. With the exception of IRQ, all entries must be
56 ; valid, and may point to an RTS for test versions (function not implemented).
57
58         .addr INSTALL
59         .addr UNINSTALL
60         .addr INIT
61         .addr DONE
62         .addr GETERROR
63         .addr CONTROL
64         .addr CLEAR
65         .addr SETVIEWPAGE
66         .addr SETDRAWPAGE
67         .addr SETCOLOR
68         .addr SETPALETTE
69         .addr GETPALETTE
70         .addr GETDEFPALETTE
71         .addr SETPIXEL
72         .addr GETPIXEL
73         .addr LINE
74         .addr BAR
75         .addr TEXTSTYLE
76         .addr OUTTEXT
77         .addr 0                 ; IRQ entry is unused
78
79 ; ------------------------------------------------------------------------
80 ; Data.
81
82 ; Variables mapped to the zero-page segment variables. Some of these are
83 ; used for passing parameters to the driver.
84
85 X1      = ptr1
86 Y1      = ptr2
87 X2      = ptr3
88 Y2      = ptr4
89
90 ; Absolute variables used in the code
91
92 .bss
93
94 SCRBASE:
95         .res 1                  ; High byte of screen base (64k VDC only)
96
97 ERROR:  
98         .res 1                  ; Error code
99 PALETTE:
100         .res 2                  ; The current palette
101
102 BITMASK:
103         .res 1                  ; $00 = clear, $01 = set pixels
104
105 OLDCOLOR:
106         .res 1                  ; colors before entering gfx mode
107
108 ; Text output stuff
109 TEXTMAGX:
110         .res 1
111 TEXTMAGY:
112         .res 1
113 TEXTDIR:
114         .res 1
115
116 ; Constants and tables
117
118 .rodata
119
120 DEFPALETTE:
121         .byte $00, $0f          ; White on black
122 PALETTESIZE     = * - DEFPALETTE
123
124 ; color translation table (indexed by VIC color)
125 COLTRANS:
126         .byte $00, $0f, $08, $06, $0a, $04, $02, $0c
127         .byte $0d, $0b, $09, $01, $0e, $05, $03, $07
128         ; colors BROWN and GRAY3 are wrong
129
130 .code
131
132 ; ------------------------------------------------------------------------
133 ; INSTALL routine. Is called after the driver is loaded into memory. May
134 ; initialize anything that has to be done just once. Is probably empty
135 ; most of the time.
136 ;
137 ; Must set an error code: NO
138 ;
139
140 INSTALL:
141         lda version             ; if GEOS 1.0...
142         and #$f0
143         cmp #$10
144         beq @L40
145         lda c128Flag            ; at least GEOS 2.0, but we're on C128?
146         bpl @L40
147         lda graphMode           ; GEOS 2.0, C128, but is 80 column screen enabled?
148         bmi @L80
149 @L40:   rts                     ; leave default values for 40 column screen
150
151         ; check for VDC version and update register $19 value
152
153 @L80:
154         ; double the x resolution and halve the aspect ratio
155
156         asl xres
157         rol xres+1
158
159         lsr aspect+1
160         ror aspect
161
162         ; update number of available screens
163
164         ldx #VDC_CSET           ; determine size of RAM...
165         jsr VDCReadReg
166         sta tmp1
167         ora #%00010000
168         jsr VDCWriteReg         ; turn on 64k
169
170         jsr settestadr1         ; save original value of test byte
171         jsr VDCReadByte
172         sta tmp2
173
174         lda #$55                ; write $55 here
175         ldy #ptr1
176         jsr test64k             ; read it here and there
177         lda #$aa                ; write $aa here
178         ldy #ptr2
179         jsr test64k             ; read it here and there
180
181         jsr settestadr1
182         lda tmp2
183         jsr VDCWriteByte        ; restore original value of test byte
184
185         lda ptr1                ; do bytes match?
186         cmp ptr1+1
187         bne @have64k
188         lda ptr2
189         cmp ptr2+1
190         bne @have64k
191
192         ldx #VDC_CSET
193         lda tmp1
194         jsr VDCWriteReg         ; restore 16/64k flag
195         jmp @endok              ; and leave default values for 16k
196
197 @have64k:
198         lda #4
199         sta pages
200 @endok:
201         lda #0
202         sta SCRBASE             ; draw page 0 as default
203         rts 
204
205 test64k:    
206         sta tmp1
207         sty ptr3
208         lda #0
209         sta ptr3+1
210         jsr settestadr1
211         lda tmp1
212         jsr VDCWriteByte        ; write $55
213         jsr settestadr1
214         jsr VDCReadByte         ; read here
215         pha
216         jsr settestadr2
217         jsr VDCReadByte         ; and there
218         ldy #1
219         sta (ptr3),y
220         pla
221         dey
222         sta (ptr3),y
223         rts
224
225 settestadr1:
226         ldy #$02                ; test page 2 (here)
227         .byte $2c
228 settestadr2:
229         ldy #$42                ; or page 64+2 (there)
230         lda #0
231         jmp VDCSetSourceAddr
232
233 ; ------------------------------------------------------------------------
234 ; UNINSTALL routine. Is called before the driver is removed from memory. May
235 ; clean up anything done by INSTALL but is probably empty most of the time.
236 ;
237 ; Must set an error code: NO
238 ;
239
240 UNINSTALL:
241         rts
242
243
244 ; ------------------------------------------------------------------------
245 ; INIT: Changes an already installed device from text mode to graphics
246 ; mode.
247 ; Note that INIT/DONE may be called multiple times while the driver
248 ; is loaded, while INSTALL is only called once, so any code that is needed
249 ; to initializes variables and so on must go here. Setting palette and
250 ; clearing the screen is not needed because this is called by the graphics
251 ; kernel later.
252 ; The graphics kernel will never call INIT when a graphics mode is already
253 ; active, so there is no need to protect against that.
254 ;
255 ; Must set an error code: YES
256 ;
257
258 INIT:
259         ldx #$01
260         stx BITMASK             ; solid black as pattern
261         lda #1
262         jsr SetPattern
263         lda #ST_WR_FORE         ; write only on foreground
264         sta dispBufferOn
265
266         lda graphMode
267         bmi @L80
268
269 ; Remember current color value (40 columns)
270         lda screencolors
271         sta OLDCOLOR
272         jmp @L99
273
274 ; Remember current color value (80 columns)
275 @L80:   lda scr80colors
276         sta OLDCOLOR
277 @L99:   lda #0
278         jsr SETVIEWPAGE         ; switch into viewpage 0
279
280 ; Done, reset the error code
281
282         lda #TGI_ERR_OK
283         sta ERROR
284         rts
285
286 ; ------------------------------------------------------------------------
287 ; DONE: Will be called to switch the graphics device back into text mode.
288 ; The graphics kernel will never call DONE when no graphics mode is active,
289 ; so there is no need to protect against that.
290 ;
291 ; Must set an error code: NO
292 ;
293
294 DONE:
295         lda #0
296         jsr SETVIEWPAGE         ; switch into viewpage 0
297
298         lda graphMode
299         bmi @L80
300
301         lda OLDCOLOR
302         sta screencolors        ; restore color for 40 columns
303         ldx #0
304 @L1:    sta COLOR_MATRIX,x
305         sta COLOR_MATRIX+$0100,x
306         sta COLOR_MATRIX+$0200,x
307         sta COLOR_MATRIX+1000-256,x
308         inx
309         bne @L1
310         rts
311
312 @L80:   lda OLDCOLOR            ; restore color for 80 columns
313         ldx #VDC_COLORS
314         jmp VDCWriteReg
315
316 ; ------------------------------------------------------------------------
317 ; GETERROR: Return the error code in A and clear it.
318
319 GETERROR:
320         ldx #TGI_ERR_OK
321         lda ERROR
322         stx ERROR
323         rts
324
325 ; ------------------------------------------------------------------------
326 ; CONTROL: Platform/driver specific entry point.
327 ;
328 ; Must set an error code: YES
329 ;
330
331 CONTROL:
332         lda #TGI_ERR_INV_FUNC
333         sta ERROR
334         rts
335
336 ; ------------------------------------------------------------------------
337 ; CLEAR: Clears the screen.
338 ;
339 ; Must set an error code: NO
340 ;
341
342 CLEAR:
343         lda curPattern
344         pha
345         lda #0
346         jsr SetPattern
347         ldx #0
348         stx r3L
349         stx r3H
350         stx r2L
351         lda #199
352         sta r2H
353         lda graphMode
354         bpl @L40
355         lda #>639               ; 80 columns
356         ldx #<639
357         bne @L99
358 @L40:   lda #>319               ; 40 columns
359         ldx #<319
360 @L99:   sta r4H
361         stx r4L
362         jsr Rectangle
363         pla
364         sta curPattern
365         rts
366
367 ; ------------------------------------------------------------------------
368 ; SETVIEWPAGE: Set the visible page. Called with the new page in A (0..n).
369 ; The page number is already checked to be valid by the graphics kernel.
370 ;
371 ; Must set an error code: NO (will only be called if page ok)
372 ;
373
374 SETVIEWPAGE:
375         ldx graphMode
376         bmi @L80
377         rts
378 @L80:   clc
379         ror
380         ror
381         ror
382         ldx #VDC_DSP_HI
383         jmp VDCWriteReg
384
385 ; ------------------------------------------------------------------------
386 ; SETDRAWPAGE: Set the drawable page. Called with the new page in A (0..n).
387 ; The page number is already checked to be valid by the graphics kernel.
388 ;
389 ; Must set an error code: NO (will only be called if page ok)
390 ;
391
392 SETDRAWPAGE:
393         ldx graphMode
394         bmi @L80
395         rts
396 @L80:   clc
397         ror
398         ror
399         ror
400         sta SCRBASE
401         rts
402
403 ; ------------------------------------------------------------------------
404 ; SETCOLOR: Set the drawing color (in A). The new color is already checked
405 ; to be in a valid range (0..maxcolor-1).
406 ;
407 ; Must set an error code: NO (will only be called if color ok)
408 ;
409
410 SETCOLOR:
411         tax
412         beq @L1
413         lda #1
414 @L1:    sta BITMASK
415         jmp SetPattern          ; need to have either 0 or 1
416
417 ; ------------------------------------------------------------------------
418 ; SETPALETTE: Set the palette (not available with all drivers/hardware).
419 ; A pointer to the palette is passed in ptr1. Must set an error if palettes
420 ; are not supported
421 ;
422 ; Must set an error code: YES
423 ;
424
425 SETPALETTE:
426         jsr GETERROR            ; clear error (if any)
427
428         ldy #PALETTESIZE - 1
429 @L1:    lda (ptr1),y            ; Copy the palette
430         and #$0F                ; Make a valid color
431         sta PALETTE,y
432         dey
433         bpl @L1
434
435 ; Put colors from palette into screen
436
437         lda graphMode
438         bmi @L80
439
440         lda PALETTE+1           ; foreground
441         asl a
442         asl a
443         asl a
444         asl a
445         ora PALETTE             ; background
446         ldx #0
447 @L2:    sta COLOR_MATRIX,x
448         sta COLOR_MATRIX+$0100,x
449         sta COLOR_MATRIX+$0200,x
450         sta COLOR_MATRIX+1000-256,x
451         inx
452         bne @L2
453         rts
454
455 @L80:   ldy PALETTE+1           ; Foreground color
456         lda COLTRANS,y
457         asl a
458         asl a
459         asl a
460         asl a
461         ldy PALETTE             ; Background color
462         ora COLTRANS,y
463
464         ldx #VDC_COLORS
465         jmp VDCWriteReg
466
467 ; ------------------------------------------------------------------------
468 ; GETPALETTE: Return the current palette in A/X. Even drivers that cannot
469 ; set the palette should return the default palette here, so there's no
470 ; way for this function to fail.
471 ;
472 ; Must set an error code: NO
473 ;
474
475 GETPALETTE:
476         lda #<PALETTE
477         ldx #>PALETTE
478         rts
479
480 ; ------------------------------------------------------------------------
481 ; GETDEFPALETTE: Return the default palette for the driver in A/X. All
482 ; drivers should return something reasonable here, even drivers that don't
483 ; support palettes, otherwise the caller has no way to determine the colors
484 ; of the (not changeable) palette.
485 ;
486 ; Must set an error code: NO (all drivers must have a default palette)
487 ;
488
489 GETDEFPALETTE:
490         lda #<DEFPALETTE
491         ldx #>DEFPALETTE
492         rts
493
494 ; ------------------------------------------------------------------------
495 ; SETPIXEL: Draw one pixel at X1/Y1 = ptr1/ptr2 with the current drawing
496 ; color. The coordinates passed to this function are never outside the
497 ; visible screen area, so there is no need for clipping inside this function.
498 ;
499 ; Must set an error code: NO
500 ;
501
502 SETPIXEL:
503         lda X1
504         ldx X1+1
505         ldy Y1
506         sta r3L
507         stx r3H
508         sty r11L
509         sec
510         lda BITMASK             ; set or clear C flag
511         bne @L1
512         clc
513 @L1:    lda #0
514         jmp DrawPoint
515
516 ; ------------------------------------------------------------------------
517 ; GETPIXEL: Read the color value of a pixel and return it in A/X. The
518 ; coordinates passed to this function are never outside the visible screen
519 ; area, so there is no need for clipping inside this function.
520
521
522 GETPIXEL:
523         lda X1
524         ldx X1+1
525         ldy Y1
526         sta r3L
527         stx r3H
528         sty r11L
529         jsr TestPoint
530         ldx #0
531         bcc @L1
532         inx
533 @L1:    txa
534         ldx #0
535         rts
536
537 ; ------------------------------------------------------------------------
538 ; LINE: Draw a line from X1/Y1 to X2/Y2, where X1/Y1 = ptr1/ptr2 and
539 ; X2/Y2 = ptr3/ptr4 using the current drawing color.
540 ;
541 ; Must set an error code: NO
542 ;
543
544 LINE:
545         lda X1
546         ldx X1+1
547         ldy Y1
548         sta r3L
549         stx r3H
550         sty r11L
551         lda X2
552         ldx X2+1
553         ldy Y2
554         sta r4L
555         stx r4H
556         sty r11H
557         sec
558         lda BITMASK             ; set or clear C flag
559         bne @L1
560         clc
561 @L1:    lda #0
562         jmp DrawLine
563
564 ; ------------------------------------------------------------------------
565 ; BAR: Draw a filled rectangle with the corners X1/Y1, X2/Y2, where
566 ; X1/Y1 = ptr1/ptr2 and X2/Y2 = ptr3/ptr4 using the current drawing color.
567 ; Contrary to most other functions, the graphics kernel will sort and clip
568 ; the coordinates before calling the driver, so on entry the following
569 ; conditions are valid:
570 ;       X1 <= X2
571 ;       Y1 <= Y2
572 ;       (X1 >= 0) && (X1 < XRES)
573 ;       (X2 >= 0) && (X2 < XRES)
574 ;       (Y1 >= 0) && (Y1 < YRES)
575 ;       (Y2 >= 0) && (Y2 < YRES)
576 ;
577 ; Must set an error code: NO
578 ;
579
580 BAR:
581         lda X1
582         ldx X1+1
583         ldy Y1
584         sta r3L
585         stx r3H
586         sty r2L
587         lda X2
588         ldx X2+1
589         ldy Y2
590         sta r4L
591         stx r4H
592         sty r2H
593         jmp Rectangle
594
595 ; ------------------------------------------------------------------------
596 ; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in X and Y
597 ; direction is passend in X/Y, the text direction is passed in A.
598 ;
599 ; Must set an error code: NO
600 ;
601
602 TEXTSTYLE:
603         stx TEXTMAGX
604         sty TEXTMAGY
605         sta TEXTDIR
606         rts
607
608
609 ; ------------------------------------------------------------------------
610 ; OUTTEXT: Output text at X/Y = ptr1/ptr2 using the current color and the
611 ; current text style. The text to output is given as a zero terminated
612 ; string with address in ptr3.
613 ;
614 ; Must set an error code: NO
615 ;
616
617 OUTTEXT:
618         lda TEXTDIR
619 ;       cmp #TGI_TEXT_HORIZONTAL ; this is equal 0
620         bne @vertical
621
622         lda X1                  ; horizontal text output
623         ldx X1+1
624         ldy Y1
625         sta r11L
626         stx r11H
627         sty r1H
628         lda ptr3
629         ldx ptr3+1
630         sta r0L
631         stx r0H
632         jmp PutString
633
634 @vertical:
635         lda X1                  ; vertical text output
636         ldx X1+1
637         ldy Y1
638         sta r11L
639         stx r11H
640         sty r1H
641         ldy #0
642         lda (ptr3),y
643         beq @end
644         jsr PutChar
645         inc ptr3
646         bne @L1
647         inc ptr3+1
648 @L1:    lda Y1
649         clc
650         adc #8
651         sta Y1
652         bne @vertical
653 @end:   rts
654
655 ;-------------
656 ; VDC helpers
657
658 VDCSetSourceAddr:
659         pha
660         tya
661         ldx #VDC_DATA_HI
662         jsr VDCWriteReg
663         pla
664         ldx #VDC_DATA_LO
665         bne VDCWriteReg
666
667 VDCReadByte:
668         ldx #VDC_DATA
669 VDCReadReg:
670         stx VDC_ADDR_REG
671 @L0:    bit VDC_ADDR_REG
672         bpl @L0
673         lda VDC_DATA_REG
674         rts
675
676 VDCWriteByte:
677         ldx #VDC_DATA
678 VDCWriteReg:
679         stx VDC_ADDR_REG
680 @L0:    bit VDC_ADDR_REG
681         bpl @L0
682         sta VDC_DATA_REG
683         rts