]> git.sur5r.net Git - cc65/blob - libsrc/nes/tgi/nes-64-56-2.s
70e23e1193bf29482d5d0f55181e6bfce38241ee
[cc65] / libsrc / nes / tgi / nes-64-56-2.s
1 ;
2 ; Graphics driver for the lores 64x56x2 mode on the NES
3 ;
4 ; Stefan Haubenthal, 2009-03-10
5 ; Based on Maciej Witkowiak's line routine.
6 ;
7
8         .include        "zeropage.inc"
9
10         .include        "tgi-kernel.inc"
11         .include        "tgi-error.inc"
12         .include        "nes.inc"
13         .include        "get_tv.inc"
14         .import         _clrscr, setcursor, putchar
15         .import         paldata
16
17         .macpack        generic
18         .macpack        module
19
20
21 ; ------------------------------------------------------------------------
22 ; Header. Includes jump table and constants.
23
24         module_header   _nes_64_56_2_tgi
25
26 ; First part of the header is a structure that has a magic and defines the
27 ; capabilities of the driver
28
29         .byte   $74, $67, $69           ; "tgi"
30         .byte   TGI_API_VERSION         ; TGI API version number
31         .addr   $0000                   ; Library reference
32 xres:   .word   charsperline*2          ; Max X resolution
33 yres:   .word   56                      ; Max Y resolution
34         .byte   2                       ; Number of drawing colors
35         .byte   1                       ; Number of screens available
36         .byte   2                       ; System font X size
37         .byte   2                       ; System font Y size
38         .word   $0100                   ; Aspect ratio
39         .byte   0                       ; TGI driver flags
40
41 ; Next comes the jump table. Currently all entries must be valid and may point
42 ; to an RTS for test versions (function not implemented).
43
44         .addr   INSTALL
45         .addr   UNINSTALL
46         .addr   INIT
47         .addr   DONE
48         .addr   GETERROR
49         .addr   CONTROL
50         .addr   CLEAR
51         .addr   SETVIEWPAGE
52         .addr   SETDRAWPAGE
53         .addr   SETCOLOR
54         .addr   SETPALETTE
55         .addr   GETPALETTE
56         .addr   GETDEFPALETTE
57         .addr   SETPIXEL
58         .addr   GETPIXEL
59         .addr   LINE
60         .addr   BAR
61         .addr   TEXTSTYLE
62         .addr   OUTTEXT
63         .addr   0                       ; IRQ entry is unused
64
65 ; ------------------------------------------------------------------------
66 ; Data.
67
68 ; Variables mapped to the zero page segment variables. Some of these are
69 ; used for passing parameters to the driver.
70
71 X1              = ptr1
72 Y1              = ptr2
73 X2              = ptr3
74 Y2              = ptr4
75 RADIUS          = tmp1
76
77 ADDR            = tmp1
78 TEMP            = tmp3
79 TEMP2           = tmp4
80 TEMP3           = sreg
81 TEMP4           = sreg+1
82
83 ; Line routine stuff (must be on zpage)
84 PB              = ptr3          ; (2)   LINE
85 UB              = ptr4          ; (2)   LINE
86 ERR             = regsave       ; (2)   LINE
87 NX              = regsave+2     ; (2)   LINE
88
89 ; Absolute variables used in the code
90
91 .bss
92
93 MEM:            .res    charsperline*2*56/4
94 MEMEND:
95 ERROR:          .res    1       ; Error code
96 COLOR:          .res    1       ; Current color
97 PALETTE:        .res    2       ; The current palette
98
99 ; Line routine stuff
100
101 OGora:
102 COUNT:          .res    2
103 OUkos:
104 NY:             .res    2
105 Y3:
106 DX:             .res    1
107 DY:             .res    1
108 AY:             .res    1
109
110 ; Constants and tables
111
112 .rodata
113
114 DEFPALETTE:     .byte   $0, $1
115 OFFSET:         .byte   8, 4, 2, 1
116 ;                       00  00  00  00  01  01  01  01
117 ;                       00  01  10  11  00  01  10  11
118 CODE:           .byte   32, 29, 26, 25, 28, 24+128, 31+128, 30+128
119 ;                       10  10  10  10  11  11  11  11
120 ;                       00  01  10  11  00  01  10  11
121                 .byte   30, 31, 24, 28+128, 25+128, 26+128, 29+128, 32+128
122
123 .code
124
125 ; ------------------------------------------------------------------------
126 ; INSTALL routine. Is called after the driver is loaded into memory. May
127 ; initialize anything that has to be done just once. Is probably empty
128 ; most of the time.
129 ;
130 ; Must set an error code: NO
131 ;
132
133 INSTALL:
134         jsr     _get_tv
135         cmp     #TV::NTSC
136         beq     ntsc
137 ; TODO ROM!
138         inc     yres
139         inc     yres
140 ntsc:;  rts
141
142 ; ------------------------------------------------------------------------
143 ; UNINSTALL routine. Is called before the driver is removed from memory. May
144 ; clean up anything done by INSTALL but is probably empty most of the time.
145 ;
146 ; Must set an error code: NO
147 ;
148
149 UNINSTALL:
150         rts
151
152 ; ------------------------------------------------------------------------
153 ; INIT: Changes an already installed device from text mode to graphics
154 ; mode.
155 ; Note that INIT/DONE may be called multiple times while the driver
156 ; is loaded, while INSTALL is only called once, so any code that is needed
157 ; to initializes variables and so on must go here. Setting palette and
158 ; clearing the screen is not needed because this is called by the graphics
159 ; kernel later.
160 ; The graphics kernel will never call INIT when a graphics mode is already
161 ; active, so there is no need to protect against that.
162 ;
163 ; Must set an error code: YES
164 ;
165
166 INIT:
167
168 ; Done, reset the error code
169
170         lda     #TGI_ERR_OK
171         sta     ERROR
172 ;       rts
173
174 ; ------------------------------------------------------------------------
175 ; DONE: Will be called to switch the graphics device back into text mode.
176 ; The graphics kernel will never call DONE when no graphics mode is active,
177 ; so there is no need to protect against that.
178 ;
179 ; Must set an error code: NO
180 ;
181
182 DONE:
183         rts
184
185 ; ------------------------------------------------------------------------
186 ; GETERROR: Return the error code in A and clear it.
187
188 GETERROR:
189         lda     ERROR
190         ldx     #TGI_ERR_OK
191         stx     ERROR
192         rts
193
194 ; ------------------------------------------------------------------------
195 ; CONTROL: Platform/driver specific entry point.
196 ;
197 ; Must set an error code: YES
198 ;
199
200 CONTROL:
201         lda     #TGI_ERR_INV_FUNC
202         sta     ERROR
203         rts
204
205 ; ------------------------------------------------------------------------
206 ; CLEAR: Clears the screen.
207 ;
208 ; Must set an error code: NO
209 ;
210
211 CLEAR:
212         ldx     #<MEM
213         stx     TEMP
214         ldx     #>MEM
215         stx     TEMP+1
216         lda     #0
217         tay
218 @L1:    sta     (TEMP),y
219         iny
220         bne     @L1
221         inc     TEMP+1
222         inx
223         cpx     #>MEMEND
224         bne     @L1
225         jmp     _clrscr
226
227 ; ------------------------------------------------------------------------
228 ; SETCOLOR: Set the drawing color (in A). The new color is already checked
229 ; to be in a valid range (0..maxcolor-1).
230 ;
231 ; Must set an error code: NO (will only be called if color ok)
232 ;
233
234 SETCOLOR:
235         sta     COLOR
236 ;       rts
237
238 ; ------------------------------------------------------------------------
239 ; SETVIEWPAGE: Set the visible page. Called with the new page in A (0..n).
240 ; The page number is already checked to be valid by the graphics kernel.
241 ;
242 ; Must set an error code: NO (will only be called if page ok)
243 ;
244
245 SETVIEWPAGE:
246
247 ; ------------------------------------------------------------------------
248 ; SETDRAWPAGE: Set the drawable page. Called with the new page in A (0..n).
249 ; The page number is already checked to be valid by the graphics kernel.
250 ;
251 ; Must set an error code: NO (will only be called if page ok)
252 ;
253
254 SETDRAWPAGE:
255         rts
256
257 ; ------------------------------------------------------------------------
258 ; SETPALETTE: Set the palette (not available with all drivers/hardware).
259 ; A pointer to the palette is passed in ptr1. Must set an error if palettes
260 ; are not supported
261 ;
262 ; Must set an error code: YES
263 ;
264
265 SETPALETTE:
266 ; Wait for v-blank
267 @wait:  lda     PPU_STATUS
268         bpl     @wait
269
270         lda     #$3F
271         sta     PPU_VRAM_ADDR2
272         lda     #$00
273         sta     PPU_VRAM_ADDR2
274
275         ldy     #0
276         lda     (ptr1),y
277         sta     PALETTE
278         tax
279         lda     paldata,x
280 ;       sta     PPU_VRAM_IO
281
282         iny
283         lda     (ptr1),y
284         sta     PALETTE+1
285         tax
286         lda     paldata,x
287         sta     PPU_VRAM_IO
288
289         lda     #TGI_ERR_OK
290         sta     ERROR
291         rts
292
293 ; ------------------------------------------------------------------------
294 ; GETPALETTE: Return the current palette in A/X. Even drivers that cannot
295 ; set the palette should return the default palette here, so there's no
296 ; way for this function to fail.
297 ;
298 ; Must set an error code: NO
299 ;
300
301 GETPALETTE:
302         lda     #<PALETTE
303         ldx     #>PALETTE
304         rts
305
306 ; ------------------------------------------------------------------------
307 ; GETDEFPALETTE: Return the default palette for the driver in A/X. All
308 ; drivers should return something reasonable here, even drivers that don't
309 ; support palettes, otherwise the caller has no way to determine the colors
310 ; of the (not changeable) palette.
311 ;
312 ; Must set an error code: NO (all drivers must have a default palette)
313 ;
314
315 GETDEFPALETTE:
316         lda     #<DEFPALETTE
317         ldx     #>DEFPALETTE
318         rts
319
320 ; ------------------------------------------------------------------------
321 ; SETPIXEL: Draw one pixel at X1/Y1 = ptr1/ptr2 with the current drawing
322 ; color. The coordinates passed to this function are never outside the
323 ; visible screen area, so there is no need for clipping inside this function.
324 ;
325 ; Must set an error code: NO
326 ;
327
328 SETPIXEL:
329         ldx     Y1              ; y+2<yres
330         inx
331         inx
332         cpx     yres
333         bcc     @L2
334         ldx     X1              ; x+2<xres
335         inx
336         inx
337         cpx     xres
338         bcc     @L2
339         rts
340 @L2:    lda     X1
341         lsr
342         tay
343         lda     Y1
344         lsr
345         tax
346         clc
347         jsr     setcursor
348         jsr     CALC
349         ldx     COLOR
350         bne     @set2
351         eor     #%00001111
352 @set2:  sta     TEMP3
353
354         lda     (TEMP),y
355         ldx     COLOR
356         bne     @set
357         and     TEMP3
358         .byte   $2c
359 @set:   ora     TEMP3
360         sta     (TEMP),y
361         tax
362         lda     CODE,x
363 @normal:jmp     putchar
364
365 ; ------------------------------------------------------------------------
366 ; GETPIXEL: Read the color value of a pixel and return it in A/X. The
367 ; coordinates passed to this function are never outside the visible screen
368 ; area, so there is no need for clipping inside this function.
369
370
371 GETPIXEL:
372         jsr     CALC
373         sta     TEMP3
374         lda     (TEMP),y
375         and     TEMP3
376         beq     @L1
377         lda     #1
378 @L1:    ldx     #0
379         rts
380
381 ; ------------------------------------------------------------------------
382 ; BAR: Draw a filled rectangle with the corners X1/Y1, X2/Y2, where
383 ; X1/Y1 = ptr1/ptr2 and X2/Y2 = ptr3/ptr4 using the current drawing color.
384 ; Contrary to most other functions, the graphics kernel will sort and clip
385 ; the coordinates before calling the driver, so on entry the following
386 ; conditions are valid:
387 ;       X1 <= X2
388 ;       Y1 <= Y2
389 ;       (X1 >= 0) && (X1 < XRES)
390 ;       (X2 >= 0) && (X2 < XRES)
391 ;       (Y1 >= 0) && (Y1 < YRES)
392 ;       (Y2 >= 0) && (Y2 < YRES)
393 ;
394 ; Must set an error code: NO
395 ;
396
397 BAR:
398         inc     Y2
399 @L1:    lda     X1
400         pha
401 @L2:    jsr     SETPIXEL
402         inc     X1
403         lda     X2
404         cmp     X1
405         bne     @L2
406         pla
407         sta     X1
408         inc     Y1
409         lda     Y2
410         cmp     Y1
411         bne     @L1
412         rts
413
414 ; ------------------------------------------------------------------------
415 ; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in X and Y
416 ; direction is passend in X/Y, the text direction is passed in A.
417 ;
418 ; Must set an error code: NO
419 ;
420
421 TEXTSTYLE:
422         rts
423
424 ; ------------------------------------------------------------------------
425 ; OUTTEXT: Output text at X/Y = ptr1/ptr2 using the current color and the
426 ; current text style. The text to output is given as a zero terminated
427 ; string with address in ptr3.
428 ;
429 ; Must set an error code: NO
430 ;
431
432 OUTTEXT:
433         lda     ptr1
434         lsr
435         tay
436         lda     ptr2
437         lsr
438         tax
439         clc
440         jsr     setcursor
441         ldy     #0
442 @L1:    lda     (ptr3),y
443         jsr     putchar
444         iny
445         cmp     #$0
446         bne     @L1
447         rts
448
449 ; ------------------------------------------------------------------------
450 ; Calculate all variables to plot the pixel at X1/Y1. If the point is out
451 ; of range, a carry is returned and INRANGE is set to a value !0 zero. If
452 ; the coordinates are valid, INRANGE is zero and the carry clear.
453
454 CALC:   lda     xres
455         sta     TEMP
456         lda     #0
457         sta     TEMP+1
458         ldy     Y1
459 @L1:    lda     TEMP
460         add     xres
461         lsr
462         sta     TEMP
463         lda     TEMP+1
464         adc     #0
465         lsr
466         sta     TEMP+1
467         dey
468         bne     @L1
469         lda     TEMP
470         add     X1
471         lsr
472         sta     TEMP
473         lda     TEMP+1
474         adc     #0
475         lsr
476         sta     TEMP+1
477         lda     TEMP
478         add     #<MEM
479         sta     TEMP
480         lda     TEMP+1
481         adc     #>MEM
482         sta     TEMP+1
483
484         lda     X1
485         and     #%00000001
486         sta     TEMP3
487         lda     Y1
488         asl
489         and     #%00000010
490         ora     TEMP3
491         tax
492         lda     OFFSET,x
493         rts
494
495 ; ------------------------------------------------------------------------
496
497 .include        "../../tgi/tgidrv_line.inc"