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