]> git.sur5r.net Git - cc65/blob - libsrc/apple2/apple2-40-48-16.s
Removed generic macpack
[cc65] / libsrc / apple2 / apple2-40-48-16.s
1 ;
2 ; Graphics driver for the 40x48x16 mode on the Apple II
3 ;
4 ; Stefan Haubenthal <polluks@sdf.lonestar.org>
5 ; Oliver Schmidt <ol.sc@web.de>
6 ;
7
8         .include        "zeropage.inc"
9
10         .include        "tgi-kernel.inc"
11         .include        "tgi-mode.inc"
12         .include        "tgi-error.inc"
13         .include        "apple2.inc"
14
15 ; ------------------------------------------------------------------------
16
17 ; Zero page stuff
18
19 H2      :=      $2C
20
21 ; ROM entry points
22
23 TEXT    :=      $F399
24 PLOT    :=      $F800
25 HLINE   :=      $F819
26 CLRSCR  :=      $F832
27 SETCOL  :=      $F864
28 SCRN    :=      $F871
29 SETGR   :=      $FB40
30 HOME    :=      $FC58
31
32 ; ------------------------------------------------------------------------
33
34 ; Variables mapped to the zero page segment variables. Some of these are
35 ; used for passing parameters to the driver.
36
37 X1      :=      ptr1
38 Y1      :=      ptr2
39 X2      :=      ptr3
40 Y2      :=      ptr4
41
42 TEMP    :=      tmp3
43 TEMP2   :=      tmp4
44 TEMP3   :=      sreg
45 TEMP4   :=      sreg+1
46
47 ; Line routine stuff (must be on zpage)
48
49 PB      :=      ptr3            ; (2)   LINE
50 UB      :=      ptr4            ; (2)   LINE
51 ERR     :=      regsave         ; (2)   LINE
52 NX      :=      regsave+2       ; (2)   LINE
53
54 ; ------------------------------------------------------------------------
55
56         .segment        "JUMPTABLE"
57
58 ; Header. Includes jump table and constants.
59
60 ; First part of the header is a structure that has a magic and defines the
61 ; capabilities of the driver
62
63         .byte   $74, $67, $69   ; "tgi"
64         .byte   TGI_API_VERSION ; TGI API version number
65 xres:   .word   40              ; X resolution
66 yres:   .word   48              ; Y resolution
67         .byte   16              ; Number of drawing colors
68         .byte   1               ; Number of screens available
69         .byte   8               ; System font X size
70         .byte   8               ; System font Y size
71         .word   $100            ; Aspect ratio
72
73 ; Next comes the jump table. With the exception of IRQ, all entries must be
74 ; valid and may point to an RTS for test versions (function not implemented).
75
76         .addr   INSTALL
77         .addr   UNINSTALL
78         .addr   INIT
79         .addr   DONE
80         .addr   GETERROR
81         .addr   CONTROL
82         .addr   CLEAR
83         .addr   SETVIEWPAGE
84         .addr   SETDRAWPAGE
85         .addr   SETCOLOR
86         .addr   SETPALETTE
87         .addr   GETPALETTE
88         .addr   GETDEFPALETTE
89         .addr   SETPIXEL
90         .addr   GETPIXEL
91         .addr   LINE
92         .addr   BAR
93         .addr   TEXTSTYLE
94         .addr   OUTTEXT
95         .addr   0               ; IRQ entry is unused
96
97 ; ------------------------------------------------------------------------
98
99         .bss
100
101 ; Absolute variables used in the code
102
103 ERROR:  .res    1               ; Error code
104
105 ; Line routine stuff (combined with circle routine stuff to save space)
106
107 OGora:
108 COUNT:  .res    2
109 OUkos:
110 NY:     .res    2
111 Y3:
112 DX:     .res    1
113 DY:     .res    1
114 AX:     .res    1
115 AY:     .res    1
116
117 ; ------------------------------------------------------------------------
118
119         .rodata
120
121 ; Constants and tables
122
123 DEFPALETTE: .byte $00, $01, $02, $03, $04, $05, $06, $07
124             .byte $08, $09, $0A, $0B, $0C, $0D, $0E, $0F
125
126 ; ------------------------------------------------------------------------
127
128         .code
129
130 ; INIT: Changes an already installed device from text mode to graphics mode.
131 ; Note that INIT/DONE may be called multiple times while the driver
132 ; is loaded, while INSTALL is only called once, so any code that is needed
133 ; to initializes variables and so on must go here. Setting palette and
134 ; clearing the screen is not needed because this is called by the graphics
135 ; kernel later.
136 ; The graphics kernel will never call INIT when a graphics mode is already
137 ; active, so there is no need to protect against that.
138 ; Must set an error code: YES
139 INIT:
140         ; Switch into graphics mode
141         bit     $C082           ; Switch in ROM
142         jsr     SETGR
143         bit     MIXCLR
144         bit     $C080           ; Switch in LC bank 2 for R/O
145
146         ; Done, reset the error code
147         lda     #TGI_ERR_OK
148         sta     ERROR
149
150         ; Fall through
151
152 ; INSTALL routine. Is called after the driver is loaded into memory. May
153 ; initialize anything that has to be done just once. Is probably empty
154 ; most of the time.
155 ; Must set an error code: NO
156 INSTALL:
157         ; Fall through
158
159 ; UNINSTALL routine. Is called before the driver is removed from memory. May
160 ; clean up anything done by INSTALL but is probably empty most of the time.
161 ; Must set an error code: NO
162 UNINSTALL:
163         ; Fall through
164
165 ; SETVIEWPAGE: Set the visible page. Called with the new page in A (0..n).
166 ; The page number is already checked to be valid by the graphics kernel.
167 ; Must set an error code: NO (will only be called if page ok)
168 SETVIEWPAGE:
169         ; Fall through
170
171 ; SETDRAWPAGE: Set the drawable page. Called with the new page in A (0..n).
172 ; The page number is already checked to be valid by the graphics kernel.
173 ; Must set an error code: NO (will only be called if page ok)
174 SETDRAWPAGE:
175         ; Fall through
176
177 ; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in X and Y
178 ; direction is passend in X/Y, the text direction is passed in A.
179 ; Must set an error code: NO
180 TEXTSTYLE:
181         ; Fall through
182
183 ; OUTTEXT: Output text at X/Y = ptr1/ptr2 using the current color and the
184 ; current text style. The text to output is given as a zero terminated
185 ; string with address in ptr3.
186 ; Must set an error code: NO
187 OUTTEXT:
188         rts
189
190 ; DONE: Will be called to switch the graphics device back into text mode.
191 ; The graphics kernel will never call DONE when no graphics mode is active,
192 ; so there is no need to protect against that.
193 ; Must set an error code: NO
194 DONE:
195         bit     $C082           ; Switch in ROM
196         jsr     TEXT
197         jsr     HOME
198         bit     $C080           ; Switch in LC bank 2 for R/O
199         rts
200
201 ; GETERROR: Return the error code in A and clear it.
202 GETERROR:
203         lda     ERROR
204         ldx     #TGI_ERR_OK
205         stx     ERROR
206         rts
207
208 ; CLEAR: Clears the screen.
209 ; Must set an error code: NO
210 CLEAR:
211         bit     $C082           ; Switch in ROM
212         jsr     CLRSCR
213         bit     $C080           ; Switch in LC bank 2 for R/O
214         rts
215
216 ; SETCOLOR: Set the drawing color (in A). The new color is already checked
217 ; to be in a valid range (0..maxcolor-1).
218 ; Must set an error code: NO (will only be called if color ok)
219 SETCOLOR:
220         bit     $C082           ; Switch in ROM
221         jsr     SETCOL
222         bit     $C080           ; Switch in LC bank 2 for R/O
223         rts
224
225 ; CONTROL: Platform/driver specific entry point.
226 ; Must set an error code: YES
227 CONTROL:
228         ; Fall through
229
230 ; SETPALETTE: Set the palette (not available with all drivers/hardware).
231 ; A pointer to the palette is passed in ptr1. Must set an error if palettes
232 ; are not supported
233 ; Must set an error code: YES
234 SETPALETTE:
235         lda     #TGI_ERR_INV_FUNC
236         sta     ERROR
237         rts
238
239 ; GETPALETTE: Return the current palette in A/X. Even drivers that cannot
240 ; set the palette should return the default palette here, so there's no
241 ; way for this function to fail.
242 ; Must set an error code: NO
243 GETPALETTE:
244         ; Fall through
245
246 ; GETDEFPALETTE: Return the default palette for the driver in A/X. All
247 ; drivers should return something reasonable here, even drivers that don't
248 ; support palettes, otherwise the caller has no way to determine the colors
249 ; of the (not changeable) palette.
250 ; Must set an error code: NO (all drivers must have a default palette)
251 GETDEFPALETTE:
252         lda     #<DEFPALETTE
253         ldx     #>DEFPALETTE
254         rts
255
256 ; SETPIXEL: Draw one pixel at X1/Y1 = ptr1/ptr2 with the current drawing
257 ; color. The coordinates passed to this function are never outside the
258 ; visible screen area, so there is no need for clipping inside this function.
259 ; Must set an error code: NO
260 SETPIXEL:
261         bit     $C082           ; Switch in ROM
262         ldy     X1
263         lda     Y1
264         jsr     PLOT
265         bit     $C080           ; Switch in LC bank 2 for R/O
266         rts
267
268 ; GETPIXEL: Read the color value of a pixel and return it in A/X. The
269 ; coordinates passed to this function are never outside the visible screen
270 ; area, so there is no need for clipping inside this function.
271 GETPIXEL:
272         bit     $C082           ; Switch in ROM
273         ldy     X1
274         lda     Y1
275         jsr     SCRN
276         ldx     #$00
277         bit     $C080           ; Switch in LC bank 2 for R/O
278         rts
279
280 ; LINE: Draw a line from X1/Y1 to X2/Y2, where X1/Y1 = ptr1/ptr2 and
281 ; X2/Y2 = ptr3/ptr4 using the current drawing color.
282 ; Must set an error code: NO
283 LINE:
284         ; nx = abs (x2 - x1)
285         sec
286         lda     X2
287         sbc     X1
288         sta     NX
289         lda     X2+1
290         sbc     X1+1
291         tay
292         lda     NX
293         jsr     abs
294         sta     NX
295         sty     NX+1
296
297         ; ny = abs (y2 - y1)
298         sec
299         lda     Y2
300         sbc     Y1
301         sta     NY
302         lda     Y2+1
303         sbc     Y1+1
304         tay
305         lda     NY
306         jsr     abs
307         sta     NY
308         sty     NY+1
309
310         ; if (x2 >= x1)
311         ldx     #X2
312         lda     X1
313         ldy     X1+1
314         jsr     icmp
315         bcc     :+
316
317         ;    dx = 1
318         lda     #$01
319         bne     :++
320
321         ; else
322         ;    dx = -1
323 :       lda     #$FF
324 :       sta     DX
325
326         ; if (y2 >= y1)
327         ldx     #Y2
328         lda     Y1
329         ldy     Y1+1
330         jsr     icmp
331         bcc     :+
332
333         ;    dy = 1
334         lda     #$01
335         bne     :++
336
337         ; else
338         ;    dy = -1
339 :       lda     #$FF
340 :       sta     DY
341
342         ; err = ax = ay = 0
343         lda     #$00
344         sta     ERR
345         sta     ERR+1
346         sta     AX
347         sta     AY
348
349         ; if (nx < ny) {
350         ldx     #NX
351         lda     NY
352         ldy     NY+1
353         jsr     icmp
354         bcs     :+
355
356         ;    nx <-> ny
357         lda     NX
358         ldx     NY
359         sta     NY
360         stx     NX
361         lda     NX+1
362         ldx     NY+1
363         sta     NY+1
364         stx     NX+1
365
366         ;    ax = dx
367         lda     DX
368         sta     AX
369
370         ;    ay = dy
371         lda     DY
372         sta     AY
373
374         ;    dx = dy = 0 }
375         lda     #$00
376         sta     DX
377         sta     DY
378
379         ; ny = - ny
380 :       lda     NY
381         ldy     NY+1
382         jsr     neg
383         sta     NY
384         sty     NY+1
385
386         ; for (count = nx; count > 0; --count) {
387         lda     NX
388         ldx     NX+1
389         sta     COUNT
390         stx     COUNT+1
391 for:    lda     COUNT           ; count > 0
392         ora     COUNT+1
393         bne     :+
394         rts
395
396         ;    setpixel (X1, Y1)
397 :       jsr     SETPIXEL
398
399         ;    pb = err + ny
400         clc
401         lda     ERR
402         adc     NY
403         sta     PB
404         lda     ERR+1
405         adc     NY+1
406         sta     PB+1
407         tax
408
409         ;    ub = pb + nx
410         clc
411         lda     PB
412         adc     NX
413         sta     UB
414         txa
415         adc     NX+1
416         sta     UB+1
417
418         ;    x1 = x1 + dx
419         ldx     #$00
420         lda     DX
421         bpl     :+
422         dex
423 :       clc
424         adc     X1
425         sta     X1
426         txa
427         adc     X1+1
428         sta     X1+1
429
430         ;    y1 = y1 + ay
431         ldx     #$00
432         lda     AY
433         bpl     :+
434         dex
435 :       clc
436         adc     Y1
437         sta     Y1
438         txa
439         adc     Y1+1
440         sta     Y1+1
441
442         ;    if (abs (pb) < abs (ub)) {
443         lda     PB
444         ldy     PB+1
445         jsr     abs
446         sta     TEMP3
447         sty     TEMP4
448         lda     UB
449         ldy     UB+1
450         jsr     abs
451         ldx     #TEMP3
452         jsr     icmp
453         bpl     :+
454
455         ;       err = pb }
456         lda     PB
457         ldx     PB+1
458         jmp     next
459
460         ;    else { x1 = x1 + ax
461 :       ldx     #$00
462         lda     AX
463         bpl     :+
464         dex
465 :       clc
466         adc     X1
467         sta     X1
468         txa
469         adc     X1+1
470         sta     X1+1
471
472         ;       y1 = y1 + dy
473         ldx     #$00
474         lda     DY
475         bpl     :+
476         dex
477 :       clc
478         adc     Y1
479         sta     Y1
480         txa
481         adc     Y1+1
482         sta     Y1+1
483
484         ;       err = ub }
485         lda     UB
486         ldx     UB+1
487 next:   sta     ERR
488         stx     ERR+1
489
490         ; } (--count)
491         lda     COUNT
492         sec
493         sbc     #$01
494         sta     COUNT
495         bcc     :+
496         jmp     for
497 :       dec     COUNT+1
498         jmp     for
499
500 ; BAR: Draw a filled rectangle with the corners X1/Y1, X2/Y2, where
501 ; X1/Y1 = ptr1/ptr2 and X2/Y2 = ptr3/ptr4 using the current drawing color.
502 ; Contrary to most other functions, the graphics kernel will sort and clip
503 ; the coordinates before calling the driver, so on entry the following
504 ; conditions are valid:
505 ;       X1 <= X2
506 ;       Y1 <= Y2
507 ;       (X1 >= 0) && (X1 < XRES)
508 ;       (X2 >= 0) && (X2 < XRES)
509 ;       (Y1 >= 0) && (Y1 < YRES)
510 ;       (Y2 >= 0) && (Y2 < YRES)
511 ; Must set an error code: NO
512 BAR:
513         bit     $C082           ; Switch in ROM
514         inc     Y2
515         ldx     X2
516         stx     H2
517 :       ldy     X1
518         lda     Y1
519         jsr     HLINE
520         inc     Y1
521         lda     Y2
522         cmp     Y1
523         bne     :-
524         bit     $C080           ; Switch in LC bank 2 for R/O
525         rts
526
527 ; Copies of some runtime routines
528
529 abs:
530         ; A/Y := abs (A/Y)
531         cpy     #$00
532         bpl     :+
533         
534         ; A/Y := neg (A/Y)
535 neg:    clc
536         eor     #$FF
537         adc     #$01
538         pha
539         tya
540         eor     #$FF
541         adc     #$00
542         tay
543         pla
544 :       rts
545
546 icmp:
547         ; Compare A/Y to zp,X
548         sta     TEMP            ; TEMP/TEMP2 - arg2
549         sty     TEMP2
550         lda     $00,x
551         pha
552         lda     $01,x
553         tay
554         pla
555         tax
556         tya                     ; X/A - arg1 (a = high)
557
558         sec
559         sbc     TEMP2
560         bne     :++
561         cpx     TEMP
562         beq     :+
563         adc     #$FF
564         ora     #$01
565 :       rts
566 :       bvc     :+
567         eor     #$FF
568         ora     #$01
569 :       rts