]> git.sur5r.net Git - cc65/blob - libsrc/c64/soft80_cputc.s
92aa728de1f280a8f467c0e8b7cfeb67baac10e6
[cc65] / libsrc / c64 / soft80_cputc.s
1 ;
2 ; Groepaz/Hitmen, 11.10.2015
3 ;
4 ; void cputcxy (unsigned char x, unsigned char y, char c);
5 ; void cputc (char c);
6 ;
7
8         .export         soft80_cputcxy, soft80_cputc
9         .export         soft80_cputdirect, soft80_putchar
10         .export         soft80_newline, soft80_plot
11         .export         soft80_checkchar
12
13         .import         popa, _gotoxy
14
15         .import         soft80_kplot
16         .import         soft80_internal_bgcolor, soft80_internal_textcolor
17         .import         soft80_internal_cursorxlsb
18
19         .importzp       tmp4,tmp3
20
21         .include        "c64.inc"
22         .include        "soft80.inc"
23
24 soft80_cputcxy:
25         pha                     ; Save C
26         jsr     popa            ; Get Y
27         jsr     _gotoxy         ; Set cursor, drop x
28         pla                     ; Restore C
29
30 ; Plot a character - also used as internal function
31
32 soft80_cputc:
33         cmp     #$0A            ; CR?
34         bne     L1
35
36         lda     #0
37         sta     CURS_X
38
39         ; Set cursor position, calculate RAM pointers
40 soft80_plot:
41         ldx     CURS_Y
42         ldy     CURS_X
43         clc
44         jmp     soft80_kplot    ; Set the new cursor
45
46 L1:     cmp     #$0D            ; LF?
47         beq     soft80_newline  ; Recalculate pointers
48
49         ; shortcut for codes < $80 ... codes $20-$7f can be printed directly,
50         ; codes $00-$1f are control codes which are not printable and thus may
51         ; give undefined result.
52         tay
53         bpl     @L10
54
55         ; codes $80-$ff must get converted like this:
56         ; $80-$9f  ->   dont care (control codes)
57         ; $a0-$bf  ->   $00-$1f
58         ; $c0-$df  ->   $60-$7f
59         ; $e0-$ff  ->   $00-$1f
60
61         ora     #%01000000      ; $40
62         clc
63         adc     #%00100000      ; $20
64         and     #%01111111      ; $7f
65 @L10:
66
67         ; entry point for direct output of a character. the value passed in
68         ; akku must match the offset in the charset.
69         ; - the following may not modify tmp1
70 soft80_cputdirect:
71         jsr     soft80_putchar  ; Write the character to the screen
72
73         ; Advance cursor position
74         iny                     ; contains CURS_X
75         cpy     #charsperline
76         beq     @L3
77
78         sty     CURS_X
79         tya
80         and     #$01
81         sta     soft80_internal_cursorxlsb
82         bne     @L5
83
84         lda     SCREEN_PTR
85         clc
86         adc     #8
87         sta     SCREEN_PTR
88         bcc     @L4
89         inc     SCREEN_PTR+1
90 @L4:
91         inc     CRAM_PTR
92         bne     @L5
93         inc     CRAM_PTR+1
94 @L5:
95         rts
96 @L3:
97         inc     CURS_Y          ; new line
98         ldy     #0              ; + cr
99         sty     CURS_X
100         jmp     soft80_plot
101
102         ; - the following may not modify tmp1
103 soft80_newline:
104
105         lda     SCREEN_PTR
106         clc
107         adc     #<(40*8)
108         sta     SCREEN_PTR
109
110         lda     SCREEN_PTR+1
111         adc     #>(40*8)
112         sta     SCREEN_PTR+1
113
114         lda     CRAM_PTR
115         clc
116         adc     #40
117         sta     CRAM_PTR
118         bcc     @L5
119         inc     CRAM_PTR+1
120 @L5:
121         inc     CURS_Y
122         rts
123
124 ;-------------------------------------------------------------------------------
125 ; All following code belongs to the character output to bitmap
126 ;
127 ; this stuff is going to be used a lot so we unroll it a bit for speed
128 ;-------------------------------------------------------------------------------
129
130 .if SOFT80FASTSPACE = 1
131
132 ; output inverted space (odd)
133 draw_spaceinvers_odd:
134         .repeat 8,line
135         lda     (SCREEN_PTR),y
136         and     #$f0
137         sta     (SCREEN_PTR),y
138         .if line < 7
139         iny
140         .endif
141         .endrepeat
142         jmp     draw_back
143
144 ; output inverted space (general entry point)
145 ; in: y must be $00
146 draw_spaceinvers:
147
148 .if SOFT80COLORVOODOO = 1
149         jsr     soft80_putcolor
150 .else
151         lda     CHARCOLOR
152         sta     (CRAM_PTR),y    ; vram
153 .endif
154
155         lda     soft80_internal_cursorxlsb
156         bne     draw_spaceinvers_odd
157
158 ; output inverted space (even)
159         .repeat 8,line
160         lda     (SCREEN_PTR),y
161         and     #$0f
162         sta     (SCREEN_PTR),y
163         .if line < 7
164         iny
165         .endif
166         .endrepeat
167         jmp     draw_back
168
169 ; output space (odd)
170 draw_space_odd:
171         .repeat 8,line
172         lda     (SCREEN_PTR),y
173         ora     #$0f
174         sta     (SCREEN_PTR),y
175         .if line < 7
176         iny
177         .endif
178         .endrepeat
179         jmp     draw_back
180
181 ; output space (general entry point)
182 ; in: y must be $00
183 draw_space:
184
185         lda     RVS
186         bne     draw_spaceinvers
187
188 .if SOFT80COLORVOODOO = 1
189         jsr     remcolor
190 .endif
191         ;ldy     #$00            ; is still $00
192
193         lda     soft80_internal_cursorxlsb
194         bne     draw_space_odd
195
196 ; output space (even)
197         .repeat 8,line
198         lda     (SCREEN_PTR),y
199         ora     #$f0
200         sta     (SCREEN_PTR),y
201         .if (line < 7)
202         iny
203         .endif
204         .endrepeat
205         jmp     draw_back
206 .endif
207
208 ;-------------------------------------------------------------------------------
209 ; output one character in internal encoding without advancing cursor position
210 ; generic entry point
211 ;
212 ; - the following may not modify tmp1
213 ; in:   A: charcode
214 ; out:  Y: CURS_X
215 ;
216 soft80_putchar:
217         sta     tmp3            ; remember charcode
218
219         sei
220         ldx     $01
221         stx     tmp4
222         ldx     #$34
223
224         stx     $01             ; will stay $34 for space
225         ldy     #$00            ; will be $00 from now on
226
227 .if SOFT80FASTSPACE = 1
228         cmp     #' '            ; space is a special (optimized) case
229         beq     draw_space
230 .endif
231
232 .if SOFT80COLORVOODOO = 1
233         jsr     soft80_putcolor
234 .else
235         lda     CHARCOLOR
236         sta     (CRAM_PTR),y    ; vram
237 .endif
238
239 ; output character
240         ldx     tmp3            ; get charcode
241
242         lda     RVS
243         beq     @skp
244         jmp     draw_charinvers
245 @skp:
246         lda     soft80_internal_cursorxlsb
247         bne     draw_char_even
248
249 ; output character (odd)
250         .repeat 8,line
251         lda     (SCREEN_PTR),y
252         and     #$0f
253         ora     soft80_hi_charset+(line*$80),x
254         sta     (SCREEN_PTR),y
255         .if line < 7
256         iny
257         .endif
258         .endrepeat
259         jmp     draw_back
260
261 ; output character (even)
262 draw_char_even:
263         .repeat 8,line
264         lda     (SCREEN_PTR),y
265         and     #$f0
266         ora     soft80_lo_charset+(line*$80),x
267         sta     (SCREEN_PTR),y
268         .if line < 7
269         iny
270         .endif
271         .endrepeat
272
273 draw_back:
274         lda     tmp4
275         sta     $01
276         cli
277
278         ldy     CURS_X
279         rts
280
281 ; output inverted character (odd)
282 draw_charinvers_odd:
283         .repeat 8,line
284         lda     (SCREEN_PTR),y
285         ora     #$0f
286         eor     soft80_lo_charset+(line*$80),x
287         sta     (SCREEN_PTR),y
288         .if line < 7
289         iny
290         .endif
291         .endrepeat
292         jmp     draw_back
293
294 ; output inverted character (generic)
295 draw_charinvers:
296         lda     soft80_internal_cursorxlsb
297         bne     draw_charinvers_odd
298
299         .repeat 8,line
300         lda     (SCREEN_PTR),y
301         ora     #$f0
302         eor     soft80_hi_charset+(line*$80),x
303         sta     (SCREEN_PTR),y
304         .if line < 7
305         iny
306         .endif
307         .endrepeat
308         jmp     draw_back
309
310 ;-------------------------------------------------------------------------------
311 ; optional "color voodoo". the problem is that each 8x8 cell can only contain
312 ; two colors, one of which is used for the background color, so two characters
313 ; have to share the same text color.
314 ;
315 ; - in a cell that contains two spaces, both the color ram and the text color
316 ;   in vram contain the background color
317 ;
318 ; - in a cell that contains one character, its text color goes into vram. the
319 ;   color ram contains the background color.
320 ;
321 ; - in a cell that contains two characters, the color of the left character goes
322 ;   to vram (and is shared by both for display). the "would be" color of the
323 ;   right character goes to color ram as a reminder and can be restored when one
324 ;   of the two characters is cleared by a space.
325
326 .if SOFT80COLORVOODOO = 1
327
328 ; remove color from cell, called before putting a "space" character to the bitmap
329 ;
330 ; __ -> __      -
331 ; _A -> _A      -
332 ; B_ -> B_      -
333 ; _A -> __      vram = bgcol
334 ; B_ -> __      vram = bgcol
335 ; BA -> _A      vram = colram, colram = bgcol
336 ; BA -> B_      colram = bgcol
337 ;
338 ; in:  x must be $34
339 ;      y must be $00
340 ; out: x = $34
341 ;      y = $00
342 remcolor:
343
344         ;ldy     #$00            ; is still $00
345
346         ; if the textcolor in vram is equal to the background color, then
347         ; no (visible) character is in the current cell and we can exit
348         ; immediately.
349         lda     (CRAM_PTR),y    ; vram (textcolor)
350         and     #$0f
351         cmp     soft80_internal_bgcolor
352         beq     @sk1            ; yes, vram==bgcolor
353
354         ; now check if the textcolor in color ram is equal the background color,
355         ; if yes then there is only one (visible) character in the current cell
356         inc     $01             ; $35
357         lda     (CRAM_PTR),y    ; colram (2nd textcolor)
358         stx     $01             ; $34
359         and     #$0f
360         cmp     soft80_internal_bgcolor
361         beq     @sk2            ; yes, colram==bgcolor
362         sta     tmp3            ; A contains colram
363
364         ; two characters in the current cell, of which one will get removed
365
366         lda     soft80_internal_cursorxlsb
367         bne     @sk3
368
369         ; vram = colram
370         lda     (CRAM_PTR),y    ; vram
371         and     #$f0
372         ora     tmp3            ; colram value
373         sta     (CRAM_PTR),y    ; vram
374 @sk3:
375         ; colram = bgcolor
376         lda     soft80_internal_bgcolor
377         inc     $01             ; $35
378         sta     (CRAM_PTR),y    ; colram
379         stx     $01             ; $34
380
381         rts
382
383 @sk2:
384         ; colram is bgcolor
385         ; => only one char in cell used
386
387         jsr     soft80_checkchar
388         bcs     @sk1            ; space at current position
389
390         ; vram (textcolor) = bgcolor
391         lda     (CRAM_PTR),y    ; vram
392         and     #$f0
393         ora     soft80_internal_bgcolor
394         sta     (CRAM_PTR),y    ; vram
395 @sk1:
396         rts
397
398 ; put color to cell
399 ;
400 ; __ -> _A      vram = textcol
401 ; __ -> B_      vram = textcol
402 ; _A -> BA      colram = vram, vram = textcol
403 ; B_ -> BA      colram = textcol
404 ;
405 ; _A -> _C      vram = textcol
406 ; B_ -> C_      vram = textcol
407 ; BA -> BC      colram = textcol
408 ; BA -> CA      vram = textcol
409 ;
410 ; in:  $01 is $34 (RAM under I/O) when entering
411 ;      x must be $34
412 ;      y must be $00
413 ; out: x = $34
414 ;      y = $00
415 soft80_putcolor:
416
417         ;ldy     #$00            ; is still $00
418
419         lda     (CRAM_PTR),y    ; vram
420         and     #$0f
421         cmp     soft80_internal_bgcolor
422         beq     @sk1            ; vram==bgcolor => first char in cell
423
424         ; vram!=bgcolor => second char in cell
425
426         inc     $01             ; $35
427         lda     (CRAM_PTR),y    ; colram
428         stx     $01             ; $34
429         and     #$0f
430         cmp     soft80_internal_bgcolor
431         beq     @l2s            ; colram==bgcolor -> second char in cell
432
433         ; botch characters in the cell are used
434
435         lda     soft80_internal_cursorxlsb
436         bne     @sk2            ; jump if odd xpos
437
438         ; vram = textcol
439         lda     CHARCOLOR
440         sta     (CRAM_PTR),y    ; vram
441         rts
442
443 @l2s:
444         ; one character in cell is already used
445         jsr     soft80_checkchar
446         bcc     @sk1            ; char at current position => overwrite 1st
447
448         lda     soft80_internal_cursorxlsb
449         beq     @sk3            ; jump if even xpos
450 @sk2:
451         ; colram = textcol
452         lda     soft80_internal_textcolor
453         inc     $01             ; $35
454         sta     (CRAM_PTR),y    ; colram
455         stx     $01             ; $34
456         rts
457
458 @sk3:
459         ; colram=vram
460         lda     (CRAM_PTR),y    ; vram
461         inc     $01             ; $35
462         sta     (CRAM_PTR),y    ; colram
463         stx     $01             ; $34
464 @sk1:
465         ; vram = textcol
466         lda     CHARCOLOR
467         sta     (CRAM_PTR),y    ; vram
468         rts
469
470 ;
471 ; test if there is a space or a character at current position
472 ;
473 ; in:  x = $34
474 ;      $01 must be $34
475 ;
476 ; out: SEC: space
477 ;      CLC: character
478 ;      x = $34
479 ;      y = $00
480 soft80_checkchar:
481
482         lda     soft80_internal_cursorxlsb
483         bne     @l1a
484
485         ; check charset data from bottom up, since a lot of eg lowercase chars
486         ; have no data in the top rows, but all of them DO have data in the
487         ; second to bottom row, this will likely be faster in average.
488
489         ldy     #7
490         .repeat 8,line
491         lda     (SCREEN_PTR),y
492         and     #$f0
493         cmp     #$f0
494         bne     @ischar
495         .if (line < 7)
496         dey
497         .endif
498         .endrepeat
499         ;ldy     #$00                            ; is 0
500         ;sec                                     ; is set
501         rts
502 @ischar:
503         ldy     #$00
504         ;clc                                     ; is cleared
505         rts
506 @l1a:
507         ldy     #$07
508         .repeat 8,line
509         lda     (SCREEN_PTR),y
510         and     #$0f
511         cmp     #$0f
512         bne     @ischar
513         .if line < 7
514         dey
515         .endif
516         .endrepeat
517         ;ldy     #$00                            ; is 0
518         ;sec                                     ; is set
519         rts
520 .endif