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