]> git.sur5r.net Git - cc65/blob - libsrc/apple2/apple2-280-192-6.s
New TGI driver by Stefan Haubenthal
[cc65] / libsrc / apple2 / apple2-280-192-6.s
1 ;
2 ; Graphics driver for the 280x192x6 mode on the Apple II
3 ;
4 ; Stefan Haubenthal <polluks@sdf.lonestar.org>
5 ; Based on Stephen L. Judd's GRLIB code and
6 ; Maciej Witkowiak's circle routine
7 ;
8
9         .include        "zeropage.inc"
10
11         .include        "tgi-kernel.inc"
12         .include        "tgi-mode.inc"
13         .include        "tgi-error.inc"
14         .include        "apple2.inc"
15
16         .macpack        generic
17
18 ; ------------------------------------------------------------------------
19 ; Header. Includes jump table and constants.
20
21 .segment        "JUMPTABLE"
22
23 ; First part of the header is a structure that has a magic and defines the
24 ; capabilities of the driver
25
26         .byte   $74, $67, $69           ; "tgi"
27         .byte   TGI_API_VERSION         ; TGI API version number
28 xres:   .word   280                     ; X resolution
29 yres:   .word   192                     ; Y resolution
30         .byte   8                       ; Number of drawing colors
31         .byte   2                       ; Number of screens available
32         .byte   8                       ; System font X size
33         .byte   8                       ; System font Y size
34         .res    4, $00                  ; Reserved for future extensions
35
36 ; Next comes the jump table. Currently all entries must be valid and may point
37 ; to an RTS for test versions (function not implemented).
38
39         .word   INSTALL
40         .word   UNINSTALL
41         .word   INIT
42         .word   DONE
43         .word   GETERROR
44         .word   CONTROL
45         .word   CLEAR
46         .word   SETVIEWPAGE
47         .word   SETDRAWPAGE
48         .word   SETCOLOR
49         .word   SETPALETTE
50         .word   GETPALETTE
51         .word   GETDEFPALETTE
52         .word   SETPIXEL
53         .word   GETPIXEL
54         .word   LINE
55         .word   BAR
56         .word   CIRCLE
57         .word   TEXTSTYLE
58         .word   OUTTEXT
59
60 ; ------------------------------------------------------------------------
61 ; Data.
62
63 ; Variables mapped to the zero page segment variables. Some of these are
64 ; used for passing parameters to the driver.
65
66 X1              = ptr1
67 Y1              = ptr2
68 X2              = ptr3
69 Y2              = ptr4
70 RADIUS          = tmp1
71
72 ADDR            = tmp1
73 TEMP            = tmp3
74 TEMP2           = tmp4
75 TEMP3           = sreg
76 TEMP4           = sreg+1
77
78 ; Circle stuff
79 XX              = ptr3          ; (2)   CIRCLE
80 YY              = ptr4          ; (2)   CIRCLE
81 MaxO            = sreg          ; (overwritten by TEMP3+TEMP4, but restored from OG/OU anyway)
82 XS              = regsave       ; (2)   CIRCLE
83 YS              = regsave+2     ; (2)   CIRCLE
84
85 ; Absolute variables used in the code
86
87 .bss
88
89 ERROR:          .res    1       ; Error code
90
91 ; Line routine stuff (combined with CIRCLE to save space)
92
93 OGora:          .res    2
94 OUkos:          .res    2
95 Y3:             .res    2
96
97 ; Text output stuff
98 TEXTMAGX        = $E7
99 TEXTMAGY        = $E7
100 TEXTDIR         = $F9
101
102 ; Constants and tables
103
104 .rodata
105
106 DEFPALETTE:     .byte   $00, $05, $04, $01, $00, $08, $06, $01; 6 unique colors
107 PALETTESIZE     = * - DEFPALETTE
108
109 SHAPE:  .byte   $64,$01,$d0,$00,$d5,$00,$da,$00,$e0,$00,$ef,$00,$fe,$00,$0c,$01
110         .byte   $19,$01,$1d,$01,$25,$01,$2d,$01,$3d,$01,$46,$01,$4b,$01,$52,$01
111         .byte   $56,$01,$60,$01,$70,$01,$77,$01,$83,$01,$8e,$01,$9a,$01,$a7,$01
112         .byte   $b6,$01,$bf,$01,$ce,$01,$dd,$01,$e2,$01,$e7,$01,$f9,$01,$03,$02
113         .byte   $15,$02,$1f,$02,$32,$02,$42,$02,$52,$02,$5e,$02,$6c,$02,$79,$02
114         .byte   $85,$02,$91,$02,$a1,$02,$a9,$02,$b2,$02,$bf,$02,$c5,$02,$d5,$02
115         .byte   $e5,$02,$f4,$02,$00,$03,$10,$03,$1f,$03,$2d,$03,$35,$03,$44,$03
116         .byte   $53,$03,$63,$03,$71,$03,$7b,$03,$85,$03,$91,$03,$97,$03,$a3,$03
117         .byte   $b6,$03,$bf,$03,$c3,$03,$cf,$03,$dc,$03,$e4,$03,$f3,$03,$00,$04
118         .byte   $0a,$04,$19,$04,$25,$04,$2a,$04,$32,$04,$3c,$04,$43,$04,$50,$04
119         .byte   $5a,$04,$66,$04,$72,$04,$7e,$04,$87,$04,$94,$04,$9c,$04,$a8,$04
120         .byte   $b4,$04,$c1,$04,$cc,$04,$db,$04,$e6,$04,$ee,$04,$f3,$04,$fb,$04
121         .byte   $04,$05,$1a,$05,$1f,$05,$24,$05,$29,$05,$22,$01,$00,$00,$00,$00
122         .byte   $09,$89,$92,$92,$00,$36,$36,$16,$0e,$00,$0d,$fe,$6e,$96,$52,$00
123         .byte   $69,$fe,$17,$2d,$2d,$1e,$1f,$17,$2d,$2d,$1e,$1f,$6e,$4e,$00,$09
124         .byte   $8d,$3f,$bf,$0d,$15,$3f,$0e,$0d,$1e,$3f,$77,$71,$09,$00,$6d,$11
125         .byte   $df,$77,$09,$1e,$17,$4d,$3a,$df,$4e,$29,$0e,$00,$a9,$1f,$6e,$1e
126         .byte   $17,$0d,$0d,$1e,$df,$0e,$6d,$0e,$00,$36,$96,$52,$00,$09,$1e,$17
127         .byte   $36,$15,$0e,$0e,$00,$15,$0e,$36,$1e,$17,$4e,$01,$00,$09,$8d,$1f
128         .byte   $1f,$0e,$2d,$1e,$17,$2d,$15,$1f,$1f,$4e,$4e,$01,$00,$89,$6e,$3a
129         .byte   $3f,$77,$31,$56,$09,$00,$92,$8a,$f6,$0d,$00,$52,$89,$3f,$b7,$52
130         .byte   $49,$00,$92,$92,$0e,$00,$49,$11,$17,$1e,$17,$1e,$56,$49,$01,$00
131         .byte   $29,$ad,$df,$33,$4d,$35,$1f,$1f,$2e,$4d,$fe,$1b,$0e,$2d,$4e,$00
132         .byte   $31,$77,$36,$be,$2d,$0e,$00,$29,$ad,$df,$73,$49,$1e,$bf,$1e,$2e
133         .byte   $2d,$75,$00,$2d,$2d,$be,$3e,$4e,$fe,$1b,$0e,$2d,$4e,$00,$49,$3e
134         .byte   $17,$0d,$fe,$33,$2d,$2d,$1e,$76,$01,$00,$2d,$2d,$de,$1b,$2e,$2d
135         .byte   $15,$36,$df,$73,$2d,$4e,$00,$09,$2d,$de,$bb,$4d,$3a,$3f,$6e,$09
136         .byte   $fe,$1b,$0e,$2d,$4e,$00,$2d,$2d,$be,$1e,$17,$36,$4e,$09,$00,$29
137         .byte   $ad,$df,$33,$4d,$f1,$3f,$17,$4d,$31,$df,$73,$2d,$4e,$00,$29,$ad
138         .byte   $df,$33,$4d,$31,$3f,$77,$09,$1e,$df,$2a,$75,$09,$00,$12,$16,$96
139         .byte   $01,$00,$52,$b2,$f6,$0d,$00,$49,$3e,$17,$2d,$2d,$35,$3f,$3f,$3f
140         .byte   $0e,$2d,$2d,$f5,$1b,$77,$4e,$09,$00,$12,$2d,$2d,$de,$9b,$2d,$2d
141         .byte   $96,$01,$00,$49,$15,$ff,$13,$2d,$2d,$ad,$3f,$3f,$3f,$2e,$2d,$2d
142         .byte   $1e,$37,$4e,$09,$00,$29,$ad,$df,$73,$09,$1e,$b6,$4e,$01,$00,$09
143         .byte   $2d,$3e,$37,$2d,$3e,$ff,$2a,$2d,$2d,$f5,$3f,$3f,$0e,$2d,$1e,$4d
144         .byte   $01,$00,$09,$15,$1f,$17,$4d,$31,$df,$33,$2d,$2d,$fe,$1b,$6e,$09
145         .byte   $0e,$00,$2d,$ad,$df,$33,$4d,$f1,$3f,$37,$4d,$31,$df,$33,$2d,$75
146         .byte   $01,$00,$29,$ad,$df,$33,$36,$4d,$11,$df,$73,$2d,$4e,$00,$2d,$ad
147         .byte   $df,$6e,$31,$df,$6e,$31,$df,$17,$2d,$75,$01,$00,$2d,$2d,$de,$1b
148         .byte   $6e,$11,$3f,$37,$36,$2d,$2d,$0e,$00,$2d,$2d,$de,$1b,$6e,$11,$3f
149         .byte   $37,$36,$4e,$49,$00,$29,$ad,$df,$33,$36,$4d,$35,$df,$73,$2d,$75
150         .byte   $00,$4d,$31,$df,$33,$4d,$31,$3f,$3f,$6e,$09,$fe,$1b,$6e,$09,$0e
151         .byte   $00,$2d,$1e,$36,$36,$17,$2d,$0e,$00,$49,$31,$36,$36,$df,$73,$2d
152         .byte   $4e,$00,$4d,$f1,$df,$6e,$1e,$37,$0d,$15,$df,$6e,$09,$0e,$00,$36
153         .byte   $36,$36,$2d,$75,$00,$4d,$31,$ff,$37,$0d,$0d,$fe,$1f,$6e,$09,$fe
154         .byte   $1b,$6e,$09,$0e,$00,$4d,$31,$df,$33,$6d,$31,$1f,$1f,$6e,$29,$fe
155         .byte   $1b,$6e,$09,$0e,$00,$29,$ad,$df,$33,$4d,$31,$df,$33,$4d,$31,$df
156         .byte   $73,$2d,$4e,$00,$2d,$ad,$df,$33,$4d,$f1,$3f,$37,$36,$4e,$49,$00
157         .byte   $29,$ad,$df,$33,$4d,$31,$df,$33,$0d,$0d,$1e,$df,$0e,$6d,$0e,$00
158         .byte   $2d,$ad,$df,$33,$4d,$f1,$3f,$37,$0d,$15,$df,$6e,$09,$0e,$00,$29
159         .byte   $ad,$df,$33,$4d,$3a,$77,$09,$fe,$1b,$0e,$2d,$4e,$00,$2d,$2d,$de
160         .byte   $36,$36,$76,$09,$00,$4d,$31,$df,$33,$4d,$31,$df,$33,$4d,$31,$df
161         .byte   $73,$2d,$4e,$00,$4d,$31,$df,$33,$4d,$31,$df,$33,$4d,$f1,$1f,$0e
162         .byte   $4e,$01,$00,$4d,$31,$df,$33,$4d,$31,$1f,$1f,$6e,$0d,$3e,$1f,$37
163         .byte   $4d,$71,$00,$4d,$31,$df,$73,$0d,$1e,$17,$0d,$15,$df,$33,$4d,$71
164         .byte   $00,$4d,$31,$df,$73,$0d,$1e,$36,$76,$09,$00,$2d,$2d,$be,$1e,$17
165         .byte   $1e,$2e,$2d,$75,$00,$2d,$2d,$de,$3b,$2e,$3e,$2e,$3e,$2e,$2d,$75
166         .byte   $00,$72,$15,$0e,$15,$56,$00,$2d,$2d,$3e,$2e,$3e,$2e,$3e,$df,$2a
167         .byte   $2d,$75,$00,$49,$15,$3f,$17,$2d,$2d,$15,$3f,$3f,$3f,$4e,$2d,$3e
168         .byte   $37,$2d,$3e,$6f,$49,$00,$92,$92,$49,$11,$3f,$3f,$4d,$09,$00,$76
169         .byte   $96,$52,$00,$52,$2d,$35,$df,$33,$4d,$31,$ff,$73,$6d,$0e,$00,$36
170         .byte   $2d,$ad,$df,$33,$4d,$31,$df,$33,$2d,$75,$01,$00,$52,$2d,$de,$33
171         .byte   $76,$2d,$0e,$00,$49,$31,$df,$2a,$2d,$fe,$1b,$6e,$09,$fe,$1b,$0e
172         .byte   $2d,$75,$00,$52,$2d,$15,$df,$33,$2d,$2d,$de,$1b,$0e,$2d,$75,$00
173         .byte   $09,$f5,$33,$8d,$3f,$77,$36,$4e,$01,$00,$52,$2d,$35,$df,$33,$4d
174         .byte   $31,$3f,$77,$09,$1e,$3f,$4d,$01,$00,$36,$2d,$ad,$df,$33,$4d,$31
175         .byte   $df,$33,$4d,$71,$00,$16,$36,$36,$0e,$00,$09,$9e,$35,$36,$f6,$6f
176         .byte   $01,$00,$36,$4d,$1e,$1f,$2e,$15,$1f,$6e,$71,$00,$35,$36,$36,$17
177         .byte   $2d,$0e,$00,$12,$2d,$ad,$1f,$1f,$6e,$0d,$fe,$1f,$6e,$0d,$0e,$00
178         .byte   $12,$2d,$15,$df,$6e,$31,$df,$6e,$71,$00,$52,$2d,$15,$df,$33,$4d
179         .byte   $31,$df,$73,$2d,$4e,$00,$12,$2d,$ad,$df,$33,$4d,$f1,$3f,$37,$6e
180         .byte   $49,$00,$52,$2d,$35,$df,$33,$4d,$31,$3f,$77,$09,$2e,$00,$12,$0d
181         .byte   $ad,$df,$37,$36,$4e,$49,$00,$52,$2d,$f5,$db,$0e,$2d,$15,$df,$13
182         .byte   $2d,$75,$01,$00,$31,$17,$2d,$f5,$33,$76,$75,$00,$12,$4d,$31,$df
183         .byte   $33,$4d,$31,$ff,$73,$6d,$0e,$00,$12,$4d,$31,$df,$33,$4d,$f1,$1f
184         .byte   $0e,$4e,$01,$00,$12,$4d,$31,$df,$33,$0d,$0d,$fe,$1f,$0e,$0d,$4e
185         .byte   $00,$12,$4d,$f1,$1f,$0e,$15,$1f,$17,$4d,$71,$00,$12,$4d,$31,$df
186         .byte   $33,$4d,$31,$3f,$77,$09,$1e,$3f,$4d,$01,$00,$12,$2d,$2d,$1e,$17
187         .byte   $1e,$17,$2d,$2d,$0e,$00,$09,$f5,$33,$1e,$0e,$76,$75,$00,$36,$36
188         .byte   $36,$2e,$00,$ad,$ae,$17,$fe,$2a,$4e,$01,$00,$69,$11,$1f,$1f,$4e
189         .byte   $b1,$92,$09,$00,$2d,$2d,$35,$3f,$3f,$37,$2d,$2d,$35,$3f,$3f,$37
190         .byte   $2d,$2d,$35,$3f,$3f,$37,$2d,$2d,$75,$00,$40,$c0,$40,$18,$00,$40
191         .byte   $c0,$40,$43,$00,$40,$c0,$40,$08,$00,$19,$00,$00
192
193 .code
194
195 ; ------------------------------------------------------------------------
196 ; INSTALL routine. Is called after the driver is loaded into memory. May
197 ; initialize anything that has to be done just once. Is probably empty
198 ; most of the time.
199 ;
200 ; Must set an error code: NO
201 ;
202
203 INSTALL:
204
205
206 ; ------------------------------------------------------------------------
207 ; UNINSTALL routine. Is called before the driver is removed from memory. May
208 ; clean up anything done by INSTALL but is probably empty most of the time.
209 ;
210 ; Must set an error code: NO
211 ;
212
213 UNINSTALL:
214         rts
215
216
217 ; ------------------------------------------------------------------------
218 ; INIT: Changes an already installed device from text mode to graphics
219 ; mode.
220 ; Note that INIT/DONE may be called multiple times while the driver
221 ; is loaded, while INSTALL is only called once, so any code that is needed
222 ; to initializes variables and so on must go here. Setting palette and
223 ; clearing the screen is not needed because this is called by the graphics
224 ; kernel later.
225 ; The graphics kernel will never call INIT when a graphics mode is already
226 ; active, so there is no need to protect against that.
227 ;
228 ; Must set an error code: YES
229 ;
230
231 INIT:
232
233 ; Switch into graphics mode
234
235         jsr     HGR
236         lda     MIXOFF
237
238 ; Done, reset the error code
239
240         lda     #TGI_ERR_OK
241         sta     ERROR
242         rts
243
244 ; ------------------------------------------------------------------------
245 ; DONE: Will be called to switch the graphics device back into text mode.
246 ; The graphics kernel will never call DONE when no graphics mode is active,
247 ; so there is no need to protect against that.
248 ;
249 ; Must set an error code: NO
250 ;
251
252 DONE            = TEXT
253
254 ; ------------------------------------------------------------------------
255 ; GETERROR: Return the error code in A and clear it.
256
257 GETERROR:
258         ldx     #TGI_ERR_OK
259         lda     ERROR
260         stx     ERROR
261         rts
262
263 ; ------------------------------------------------------------------------
264 ; CONTROL: Platform/driver specific entry point.
265 ;
266 ; Must set an error code: YES
267 ;
268
269 CONTROL:
270         lda     #TGI_ERR_INV_FUNC
271         sta     ERROR
272         rts
273
274 ; ------------------------------------------------------------------------
275 ; CLEAR: Clears the screen.
276 ;
277 ; Must set an error code: NO
278 ;
279
280 CLEAR           = HCLR
281
282 ; ------------------------------------------------------------------------
283 ; SETVIEWPAGE: Set the visible page. Called with the new page in A (0..n).
284 ; The page number is already checked to be valid by the graphics kernel.
285 ;
286 ; Must set an error code: NO (will only be called if page ok)
287 ;
288
289 SETVIEWPAGE:
290         tax
291         beq     @L1
292         lda     PG2ON
293         rts
294 @L1:    lda     PG2OFF
295         rts
296
297 ; ------------------------------------------------------------------------
298 ; SETDRAWPAGE: Set the drawable page. Called with the new page in A (0..n).
299 ; The page number is already checked to be valid by the graphics kernel.
300 ;
301 ; Must set an error code: NO (will only be called if page ok)
302 ;
303
304 SETDRAWPAGE:
305         tax
306         beq     @L1
307         jmp     HGR2
308 @L1:    jmp     HGR
309
310 ; ------------------------------------------------------------------------
311 ; SETCOLOR: Set the drawing color (in A). The new color is already checked
312 ; to be in a valid range (0..maxcolor-1).
313 ;
314 ; Must set an error code: NO (will only be called if color ok)
315 ;
316
317 SETCOLOR:
318         tax
319         jmp     SETHCOL
320
321 ; ------------------------------------------------------------------------
322 ; SETPALETTE: Set the palette (not available with all drivers/hardware).
323 ; A pointer to the palette is passed in ptr1. Must set an error if palettes
324 ; are not supported
325 ;
326 ; Must set an error code: YES
327 ;
328
329 SETPALETTE:
330         lda     #TGI_ERR_INV_FUNC
331         sta     ERROR
332         rts
333
334 ; ------------------------------------------------------------------------
335 ; GETPALETTE: Return the current palette in A/X. Even drivers that cannot
336 ; set the palette should return the default palette here, so there's no
337 ; way for this function to fail.
338 ;
339 ; Must set an error code: NO
340 ;
341
342 GETPALETTE:
343
344 ; ------------------------------------------------------------------------
345 ; GETDEFPALETTE: Return the default palette for the driver in A/X. All
346 ; drivers should return something reasonable here, even drivers that don't
347 ; support palettes, otherwise the caller has no way to determine the colors
348 ; of the (not changeable) palette.
349 ;
350 ; Must set an error code: NO (all drivers must have a default palette)
351 ;
352
353 GETDEFPALETTE:
354         lda     #<DEFPALETTE
355         ldx     #>DEFPALETTE
356         rts
357
358 ; ------------------------------------------------------------------------
359 ; SETPIXEL: Draw one pixel at X1/Y1 = ptr1/ptr2 with the current drawing
360 ; color. The coordinates passed to this function are never outside the
361 ; visible screen area, so there is no need for clipping inside this function.
362 ;
363 ; Must set an error code: NO
364 ;
365
366 SETPIXELCLIP:
367         lda     Y1+1
368         bmi     @finito         ; y<0
369         lda     X1+1
370         bmi     @finito         ; x<0
371         lda     X1
372         ldx     X1+1
373         sta     ADDR
374         stx     ADDR+1
375         ldx     #ADDR
376         lda     xres
377         ldy     xres+1
378         jsr     icmp            ; ( x < xres ) ...
379         bcs     @finito
380         lda     Y1
381         ldx     Y1+1
382         sta     ADDR
383         stx     ADDR+1
384         ldx     #ADDR
385         lda     yres
386         ldy     yres+1
387         jsr     icmp            ; ... && ( y < yres )
388         bcc     SETPIXEL
389 @finito:rts
390
391 SETPIXEL:
392         ldx     X1
393         ldy     X1+1
394         lda     Y1
395         jmp     HPLOT
396
397 ; ------------------------------------------------------------------------
398 ; GETPIXEL: Read the color value of a pixel and return it in A/X. The
399 ; coordinates passed to this function are never outside the visible screen
400 ; area, so there is no need for clipping inside this function.
401
402
403 GETPIXEL:
404         lda     #TGI_ERR_INV_FUNC
405         sta     ERROR
406         rts
407
408 ; ------------------------------------------------------------------------
409 ; LINE: Draw a line from X1/Y1 to X2/Y2, where X1/Y1 = ptr1/ptr2 and
410 ; X2/Y2 = ptr3/ptr4 using the current drawing color.
411 ;
412 ; Must set an error code: NO
413 ;
414
415 LINE:
416         ldx     X1
417         ldy     X1+1
418         lda     Y1
419         jsr     HPOSN
420         lda     X2
421         ldx     X2+1
422         ldy     Y2
423         jmp     HLIN
424
425 ; ------------------------------------------------------------------------
426 ; BAR: Draw a filled rectangle with the corners X1/Y1, X2/Y2, where
427 ; X1/Y1 = ptr1/ptr2 and X2/Y2 = ptr3/ptr4 using the current drawing color.
428 ; Contrary to most other functions, the graphics kernel will sort and clip
429 ; the coordinates before calling the driver, so on entry the following
430 ; conditions are valid:
431 ;       X1 <= X2
432 ;       Y1 <= Y2
433 ;       (X1 >= 0) && (X1 < XRES)
434 ;       (X2 >= 0) && (X2 < XRES)
435 ;       (Y1 >= 0) && (Y1 < YRES)
436 ;       (Y2 >= 0) && (Y2 < YRES)
437 ;
438 ; Must set an error code: NO
439 ;
440
441 BAR:
442         inc     Y2
443 @L1:    lda     Y2
444         pha
445         lda     Y1
446         sta     Y2
447         jsr     LINE
448         pla
449         sta     Y2
450         inc     Y1
451         cmp     Y1
452         bne     @L1
453         rts
454
455 ; ------------------------------------------------------------------------
456 ; CIRCLE: Draw a circle around the center X1/Y1 (= ptr1/ptr2) with the
457 ; radius in tmp1 and the current drawing color.
458 ;
459 ; Must set an error code: NO
460 ;
461
462 CIRCLE:
463         lda     RADIUS
464         bne     @L1
465         jmp     SETPIXELCLIP    ; Plot as a point
466
467 @L1:    sta     XX
468         ; x = r;
469         lda     #0
470         sta     XX+1
471         sta     YY
472         sta     YY+1
473         sta     MaxO
474         sta     MaxO+1
475         ; y =0; mo=0;
476         lda     X1
477         ldx     X1+1
478         sta     XS
479         stx     XS+1
480         lda     Y1
481         ldx     Y1+1
482         sta     YS
483         stx     YS+1            ; XS/YS to remember the center
484
485         ; while (y<x) {
486 @L013B: ldx     #YY
487         lda     XX
488         ldy     XX+1
489         jsr     icmp
490         bcc     @L12
491         rts
492 @L12:   ; plot points in 8 slices...
493         lda     XS
494         add     XX
495         sta     X1
496         lda     XS+1
497         adc     XX+1
498         sta     X1+1            ; x1 = xs+x
499         lda     YS
500         add     YY
501         sta     Y1
502         pha
503         lda     YS+1
504         adc     YY+1
505         sta     Y1+1            ; (stack)=ys+y, y1=(stack)
506         pha
507         jsr     SETPIXELCLIP    ; plot(xs+x,ys+y)
508         lda     YS
509         sub     YY
510         sta     Y1
511         sta     Y3
512         lda     YS+1
513         sbc     YY+1
514         sta     Y1+1            ; y3 = y1 = ys-y
515         sta     Y3+1
516         jsr     SETPIXELCLIP    ; plot(xs+x,ys-y)
517         pla
518         sta     Y1+1
519         pla
520         sta     Y1              ; y1 = ys+y
521         lda     XS
522         sub     XX
523         sta     X1
524         lda     XS+1
525         sbc     XX+1
526         sta     X1+1
527         jsr     SETPIXELCLIP    ; plot (xs-x,ys+y)
528         lda     Y3
529         sta     Y1
530         lda     Y3+1
531         sta     Y1+1
532         jsr     SETPIXELCLIP    ; plot (xs-x,ys-y)
533
534         lda     XS
535         add     YY
536         sta     X1
537         lda     XS+1
538         adc     YY+1
539         sta     X1+1            ; x1 = xs+y
540         lda     YS
541         add     XX
542         sta     Y1
543         pha
544         lda     YS+1
545         adc     XX+1
546         sta     Y1+1            ; (stack)=ys+x, y1=(stack)
547         pha
548         jsr     SETPIXELCLIP    ; plot(xs+y,ys+x)
549         lda     YS
550         sub     XX
551         sta     Y1
552         sta     Y3
553         lda     YS+1
554         sbc     XX+1
555         sta     Y1+1            ; y3 = y1 = ys-x
556         sta     Y3+1
557         jsr     SETPIXELCLIP    ; plot(xs+y,ys-x)
558         pla
559         sta     Y1+1
560         pla
561         sta     Y1              ; y1 = ys+x(stack)
562         lda     XS
563         sub     YY
564         sta     X1
565         lda     XS+1
566         sbc     YY+1
567         sta     X1+1
568         jsr     SETPIXELCLIP    ; plot (xs-y,ys+x)
569         lda     Y3
570         sta     Y1
571         lda     Y3+1
572         sta     Y1+1
573         jsr     SETPIXELCLIP    ; plot (xs-y,ys-x)
574
575         ; og = mo+y+y+1
576         lda     MaxO
577         ldx     MaxO+1
578         add     YY
579         tay
580         txa
581         adc     YY+1
582         tax
583         tya
584         add     YY
585         tay
586         txa
587         adc     YY+1
588         tax
589         tya
590         add     #1
591         bcc     @L0143
592         inx
593 @L0143: sta     OGora
594         stx     OGora+1
595         ; ou = og-x-x+1
596         sub     XX
597         tay
598         txa
599         sbc     XX+1
600         tax
601         tya
602         sub     XX
603         tay
604         txa
605         sbc     XX+1
606         tax
607         tya
608         add     #1
609         bcc     @L0146
610         inx
611 @L0146: sta     OUkos
612         stx     OUkos+1
613         ; ++y
614         inc     YY
615         bne     @L0148
616         inc     YY+1
617 @L0148: ; if (abs(ou)<abs(og))
618         lda     OUkos
619         ldy     OUkos+1
620         jsr     abs
621         sta     TEMP3
622         sty     TEMP4
623         lda     OGora
624         ldy     OGora+1
625         jsr     abs
626         ldx     #TEMP3
627         jsr     icmp
628         bpl     @L0149
629         ; { --x;
630         lda     XX
631         sub     #1
632         sta     XX
633         bcs     @L014E
634         dec     XX+1
635 @L014E: ; mo = ou; }
636         lda     OUkos
637         ldx     OUkos+1
638         jmp     @L014G
639         ; else { mo = og }
640 @L0149: lda     OGora
641         ldx     OGora+1
642 @L014G: sta     MaxO
643         stx     MaxO+1
644         ; }
645         jmp     @L013B
646
647 ; ------------------------------------------------------------------------
648 ; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in X and Y
649 ; direction is passend in X/Y, the text direction is passed in A.
650 ;
651 ; Must set an error code: NO
652 ;
653
654 TEXTSTYLE:
655         stx     TEXTMAGX
656         sty     TEXTMAGY
657         asl                             ; 16 <=> 90°
658         asl
659         asl
660         asl
661         sta     TEXTDIR
662         rts
663
664
665 ; ------------------------------------------------------------------------
666 ; OUTTEXT: Output text at X/Y = ptr1/ptr2 using the current color and the
667 ; current text style. The text to output is given as a zero terminated
668 ; string with address in ptr3.
669 ;
670 ; Must set an error code: NO
671 ;
672
673 OUTTEXT:
674         ldx     X1
675         ldy     X1+1
676         lda     Y1
677         jsr     HPOSN
678         lda     SHAPE+2*99
679         add     #<SHAPE
680         sta     tmp3
681         lda     SHAPE+2*99+1
682         adc     #>SHAPE
683         sta     tmp3+1
684
685         ldy     #0
686 @L1:    lda     (ptr3),y
687         beq     @end
688         sub     #31                     ; no controls
689         asl                             ; offset*2
690         tax
691         lda     SHAPE,x
692         add     #<SHAPE
693         sta     tmp1
694         lda     SHAPE+1,x
695         adc     #>SHAPE
696         sta     tmp1+1
697         tya
698         pha
699         ldx     tmp1
700         ldy     tmp1+1
701         lda     TEXTDIR
702         jsr     DRAW
703         ldx     tmp3
704         ldy     tmp3+1
705         lda     TEXTDIR
706         jsr     DRAW
707         pla
708         tay
709         iny
710         bne     @L1
711 @end:   rts
712
713 ;-------------
714 ; copies of some runtime routines
715
716 abs:
717         ; a/y := abs(a/y)
718         dey
719         iny
720         bpl     @L1
721         ; negay
722         clc
723         eor     #$ff
724         adc     #1
725         pha
726         tya
727         eor     #$ff
728         adc     #0
729         tay
730         pla
731 @L1:    rts
732
733 icmp:
734         ; compare a/y to zp,x
735         sta     TEMP            ; TEMP/TEMP2 - arg2
736         sty     TEMP2
737         lda     $0,x
738         pha
739         lda     $1,x
740         tay
741         pla
742         tax
743         tya                     ; x/a - arg1 (a=high)
744
745         sub     TEMP2
746         bne     @L4
747         cpx     TEMP
748         beq     @L3
749         adc     #$ff
750         ora     #$01
751 @L3:    rts
752 @L4:    bvc     @L3
753         eor     #$ff
754         ora     #$01
755         rts