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