]> git.sur5r.net Git - cc65/blob - libsrc/apple2/apple2-280-192-8.s
ae17d77fc74b5976398d517894e18e2ee9f30b07
[cc65] / libsrc / apple2 / apple2-280-192-8.s
1 ;
2 ; Graphics driver for the 280x192x8 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 HBASL   :=      $26
20 HMASK   :=      $30
21 PAGE    :=      $E6
22 SCALE   :=      $E7
23 ROT     :=      $F9
24
25 ; Graphics entry points, by cbmnut (applenut??) cbmnut@hushmail.com
26
27 TEXT    :=      $F399   ; Return to text screen
28 HGR2    :=      $F3D8   ; Initialize and clear hi-res page 2.
29 HGR     :=      $F3E2   ; Initialize and clear hi-res page 1.
30 HCLR    :=      $F3F2   ; Clear the current hi-res screen to black.
31 BKGND   :=      $F3F6   ; Clear the current hi-res screen to the
32                         ; last plotted color (from ($1C).
33 HPOSN   :=      $F411   ; Positions the hi-res cursor without
34                         ; plotting a point.
35                         ; Enter with (A) = Y-coordinate, and
36                         ; (Y,X) = X-coordinate.
37 HPLOT   :=      $F457   ; Calls HPOSN and tries to plot a dot at
38                         ; the cursor's position.  If you are
39                         ; trying to plot a non-white color at
40                         ; a complementary color position, no
41                         ; dot will be plotted.
42 HLIN    :=      $F53A   ; Draws a line from the last plotted
43                         ; point or line destination to:
44                         ; (X,A) = X-coordinate, and
45                         ; (Y) = Y-coordinate.
46 HFIND   :=      $F5CB   ; Converts the hi-res coursor's position
47                         ; back to X- and Y-coordinates; stores
48                         ; X-coordinate at $E0,E1 and Y-coordinate
49                         ; at $E2.
50 DRAW    :=      $F601   ; Draws a shape.  Enter with (Y,X) = the
51                         ; address of the shape table, and (A) =
52                         ; the rotation factor.  Uses the current
53                         ; color.
54 XDRAW   :=      $F65D   ; Draws a shape by inverting the existing
55                         ; color of the dots the shape draws over.
56                         ; Same entry parameters as DRAW.
57 SETHCOL :=      $F6EC   ; Set the hi-res color to (X), where (X)
58                         ; must be between 0 and 7.
59
60 ; ------------------------------------------------------------------------
61
62 ; Variables mapped to the zero page segment variables. Some of these are
63 ; used for passing parameters to the driver.
64
65 X1      :=      ptr1
66 Y1      :=      ptr2
67 X2      :=      ptr3
68 Y2      :=      ptr4
69
70 ; ------------------------------------------------------------------------
71
72         .segment        "JUMPTABLE"
73
74 ; Header. Includes jump table and constants.
75
76 ; First part of the header is a structure that has a magic and defines the
77 ; capabilities of the driver
78
79         .byte   $74, $67, $69   ; "tgi"
80         .byte   TGI_API_VERSION ; TGI API version number
81         .word   280             ; X resolution
82         .word   192             ; Y resolution
83         .byte   8               ; Number of drawing colors
84         .byte   2               ; Number of screens available
85         .byte   7               ; System font X size
86         .byte   8               ; System font Y size
87         .word   $100            ; Aspect ratio
88
89 ; Next comes the jump table. With the exception of IRQ, all entries must be
90 ; valid and may point to an RTS for test versions (function not implemented).
91
92         .addr   INSTALL
93         .addr   UNINSTALL
94         .addr   INIT
95         .addr   DONE
96         .addr   GETERROR
97         .addr   CONTROL
98         .addr   CLEAR
99         .addr   SETVIEWPAGE
100         .addr   SETDRAWPAGE
101         .addr   SETCOLOR
102         .addr   SETPALETTE
103         .addr   GETPALETTE
104         .addr   GETDEFPALETTE
105         .addr   SETPIXEL
106         .addr   GETPIXEL
107         .addr   LINE
108         .addr   BAR
109         .addr   TEXTSTYLE
110         .addr   OUTTEXT
111         .addr   0               ; IRQ entry is unused
112
113 ; ------------------------------------------------------------------------
114
115         .bss
116
117 ; Absolute variables used in the code
118
119 ERROR:  .res    1               ; Error code
120
121         .ifdef  __APPLE2ENH__
122 Set80:  .res    1               ; Set 80 column store
123         .endif
124
125 ; ------------------------------------------------------------------------
126
127         .rodata
128
129 ; Constants and tables
130
131 DEFPALETTE: .byte $00, $01, $02, $03, $04, $05, $06, $07
132
133 FONT:
134         ; Beagle Bros Shape Mechanic font F.ASCII.SMALL
135         ; modified to exactly reproduce the text glyphs
136         .incbin "../apple2/apple2-280-192-8.fnt"
137
138 ; ------------------------------------------------------------------------
139
140         .code
141
142 ; INIT: Changes an already installed device from text mode to graphics mode.
143 ; Note that INIT/DONE may be called multiple times while the driver
144 ; is loaded, while INSTALL is only called once, so any code that is needed
145 ; to initializes variables and so on must go here. Setting palette and
146 ; clearing the screen is not needed because this is called by the graphics
147 ; kernel later.
148 ; The graphics kernel will never call INIT when a graphics mode is already
149 ; active, so there is no need to protect against that.
150 ; Must set an error code: YES
151 INIT:
152         .ifdef  __APPLE2ENH__
153         ; Save and clear 80 column store
154         lda     RD80COL
155         sta     Set80
156         sta     CLR80COL
157         .endif
158
159         ; Switch into graphics mode
160         bit     HIRES
161         bit     MIXCLR
162         bit     TXTCLR
163
164         ; Beagle Bros Shape Mechanic fonts don't
165         ; scale well so use fixed scaling factor
166         lda     #1
167         sta     SCALE
168
169         ; Done, reset the error code
170         lda     #TGI_ERR_OK
171         sta     ERROR
172
173         ; Fall through
174
175 ; INSTALL routine. Is called after the driver is loaded into memory. May
176 ; initialize anything that has to be done just once. Is probably empty
177 ; most of the time.
178 ; Must set an error code: NO
179 INSTALL:
180         ; Fall through
181
182 ; UNINSTALL routine. Is called before the driver is removed from memory. May
183 ; clean up anything done by INSTALL but is probably empty most of the time.
184 ; Must set an error code: NO
185 UNINSTALL:
186         rts
187
188 ; DONE: Will be called to switch the graphics device back into text mode.
189 ; The graphics kernel will never call DONE when no graphics mode is active,
190 ; so there is no need to protect against that.
191 ; Must set an error code: NO
192 DONE:
193         ; Switch into text mode
194         bit     TXTSET
195         bit     LOWSCR
196
197         .ifdef  __APPLE2ENH__
198         ; Restore 80 column store
199         lda     Set80
200         bpl     :+
201         sta     SET80COL
202 :       bit     LORES           ; Limit SET80COL-HISCR to text
203         .endif
204         rts
205
206 ; GETERROR: Return the error code in A and clear it.
207 GETERROR:
208         lda     ERROR
209         ldx     #TGI_ERR_OK
210         stx     ERROR
211         rts
212
213 ; CLEAR: Clears the screen.
214 ; Must set an error code: NO
215 CLEAR:
216         bit     $C082           ; Switch in ROM
217         jsr     HCLR
218         bit     $C080           ; Switch in LC bank 2 for R/O
219         rts
220
221 ; SETVIEWPAGE: Set the visible page. Called with the new page in A (0..n).
222 ; The page number is already checked to be valid by the graphics kernel.
223 ; Must set an error code: NO (will only be called if page ok)
224 SETVIEWPAGE:
225         tax
226         .assert LOWSCR + 1 = HISCR, error
227         lda     LOWSCR,x        ; No BIT absolute,X available
228         rts
229
230 ; SETDRAWPAGE: Set the drawable page. Called with the new page in A (0..n).
231 ; The page number is already checked to be valid by the graphics kernel.
232 ; Must set an error code: NO (will only be called if page ok)
233 SETDRAWPAGE:
234         tax
235         beq     :+
236         lda     #>$4000         ; Page 2
237         .byte   $2C             ; BIT absolute
238 :       lda     #>$2000         ; Page 1
239         sta     PAGE
240         rts
241
242 ; SETCOLOR: Set the drawing color (in A). The new color is already checked
243 ; to be in a valid range (0..maxcolor-1).
244 ; Must set an error code: NO (will only be called if color ok)
245 SETCOLOR:
246         bit     $C082           ; Switch in ROM
247         tax
248         jsr     SETHCOL
249         bit     $C080           ; Switch in LC bank 2 for R/O
250         rts
251
252 ; CONTROL: Platform/driver specific entry point.
253 ; Must set an error code: YES
254 CONTROL:
255         ; Fall through
256
257 ; SETPALETTE: Set the palette (not available with all drivers/hardware).
258 ; A pointer to the palette is passed in ptr1. Must set an error if palettes
259 ; are not supported
260 ; Must set an error code: YES
261 SETPALETTE:
262         lda     #TGI_ERR_INV_FUNC
263         sta     ERROR
264         rts
265
266 ; GETPALETTE: Return the current palette in A/X. Even drivers that cannot
267 ; set the palette should return the default palette here, so there's no
268 ; way for this function to fail.
269 ; Must set an error code: NO
270 GETPALETTE:
271         ; Fall through
272
273 ; GETDEFPALETTE: Return the default palette for the driver in A/X. All
274 ; drivers should return something reasonable here, even drivers that don't
275 ; support palettes, otherwise the caller has no way to determine the colors
276 ; of the (not changeable) palette.
277 ; Must set an error code: NO (all drivers must have a default palette)
278 GETDEFPALETTE:
279         lda     #<DEFPALETTE
280         ldx     #>DEFPALETTE
281         rts
282
283 ; SETPIXEL: Draw one pixel at X1/Y1 = ptr1/ptr2 with the current drawing
284 ; color. The coordinates passed to this function are never outside the
285 ; visible screen area, so there is no need for clipping inside this function.
286 ; Must set an error code: NO
287 SETPIXEL:
288         bit     $C082           ; Switch in ROM
289         ldx     X1
290         ldy     X1+1
291         lda     Y1
292         jsr     HPLOT
293         bit     $C080           ; Switch in LC bank 2 for R/O
294         rts
295
296 ; GETPIXEL: Read the color value of a pixel and return it in A/X. The
297 ; coordinates passed to this function are never outside the visible screen
298 ; area, so there is no need for clipping inside this function.
299 GETPIXEL:
300         bit     $C082           ; Switch in ROM
301         ldx     X1
302         ldy     X1+1
303         lda     Y1
304         jsr     HPOSN
305         lda     (HBASL),y
306         and     HMASK
307         asl
308         beq     :+              ; 0 (black)
309         lda     #$03            ; 3 (white)
310 :       bcc     :+
311         adc     #$03            ; += 4 (black -> black2, white -> white2)
312 :       ldx     #$00
313         bit     $C080           ; Switch in LC bank 2 for R/O
314         rts
315
316 ; LINE: Draw a line from X1/Y1 to X2/Y2, where X1/Y1 = ptr1/ptr2 and
317 ; X2/Y2 = ptr3/ptr4 using the current drawing color.
318 ; Must set an error code: NO
319 LINE:
320         bit     $C082           ; Switch in ROM
321         ldx     X1
322         ldy     X1+1
323         lda     Y1
324         jsr     HPOSN
325         lda     X2
326         ldx     X2+1
327         ldy     Y2
328         jsr     HLIN
329         bit     $C080           ; Switch in LC bank 2 for R/O
330         rts
331
332 ; BAR: Draw a filled rectangle with the corners X1/Y1, X2/Y2, where
333 ; X1/Y1 = ptr1/ptr2 and X2/Y2 = ptr3/ptr4 using the current drawing color.
334 ; Contrary to most other functions, the graphics kernel will sort and clip
335 ; the coordinates before calling the driver, so on entry the following
336 ; conditions are valid:
337 ;       X1 <= X2
338 ;       Y1 <= Y2
339 ;       (X1 >= 0) && (X1 < XRES)
340 ;       (X2 >= 0) && (X2 < XRES)
341 ;       (Y1 >= 0) && (Y1 < YRES)
342 ;       (Y2 >= 0) && (Y2 < YRES)
343 ; Must set an error code: NO
344 BAR:
345         inc     Y2
346 :       lda     Y2
347         pha
348         lda     Y1
349         sta     Y2
350         jsr     LINE
351         pla
352         sta     Y2
353         inc     Y1
354         cmp     Y1
355         bne     :-
356         rts
357
358 ; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in X and Y
359 ; direction is passend in X/Y, the text direction is passed in A.
360 ; Must set an error code: NO
361 TEXTSTYLE:
362         cmp     #TGI_TEXT_VERTICAL
363         bne     :+
364         lda     #48
365 :       sta     ROT
366         rts
367
368 ; OUTTEXT: Output text at X/Y = ptr1/ptr2 using the current color and the
369 ; current text style. The text to output is given as a zero terminated
370 ; string with address in ptr3.
371 ; Must set an error code: NO
372 OUTTEXT:
373         bit     $C082           ; Switch in ROM
374         lda     X1
375         ldy     X1+1
376         ldx     ROT
377         php                     ; Save Z flag
378         beq     :+              ; Not horizontal
379         sec
380         sbc     #7              ; Adjust X
381         bcs     :+
382         dey
383 :       tax
384         lda     Y1
385         plp                     ; Restore Z flag
386         bne     :+              ; Not vertical
387         sec
388         sbc     #7              ; Adjust Y
389 :       jsr     HPOSN
390         clc
391         lda     FONT+2*99       ; "connection char"
392         adc     #<FONT
393         sta     ptr4
394         lda     FONT+2*99+1     ; "connection char"
395         adc     #>FONT
396         sta     ptr4+1
397         ldy     #$00
398 :       lda     (ptr3),y
399         beq     :+
400         sty     tmp1            ; Save string index
401         sec
402         sbc     #$1F            ; No control chars
403         asl                     ; Offset * 2
404         tay
405         clc
406         lda     FONT,y
407         adc     #<FONT
408         tax
409         lda     FONT+1,y
410         adc     #>FONT
411         tay
412         lda     ROT
413         jsr     DRAW            ; Draw char from string
414         ldx     ptr4
415         ldy     ptr4+1
416         lda     ROT
417         jsr     DRAW            ; Draw "connection char"
418         ldy     tmp1            ; Restore string index
419         iny
420         bne     :-              ; Branch always
421 :       bit     $C080           ; Switch in LC bank 2 for R/O
422         rts