cc65/libsrc/c64/soft80_cputc.s

522 lines
13 KiB
ArmAsm

;
; Groepaz/Hitmen, 11.10.2015
;
; high level implementation for the soft80 implementation
;
; void cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (char c);
;
.export soft80_cputcxy, soft80_cputc
.export soft80_cputdirect, soft80_putchar
.export soft80_newline, soft80_plot
.export soft80_checkchar
.import gotoxy
.import soft80_kplot
.import soft80_internal_bgcolor, soft80_internal_cellcolor
.import soft80_internal_cursorxlsb
.importzp tmp4,tmp3
.include "c64.inc"
.include "soft80.inc"
soft80_cputcxy:
pha ; Save C
jsr gotoxy ; Set cursor, drop x and y
pla ; Restore C
; Plot a character - also used as internal function
soft80_cputc:
cmp #$0A ; CR?
bne L1
lda #0
sta CURS_X
; Set cursor position, calculate RAM pointers
soft80_plot:
ldx CURS_Y
ldy CURS_X
clc
jmp soft80_kplot ; Set the new cursor
L1: cmp #$0D ; LF?
beq soft80_newline ; Recalculate pointers
; shortcut for codes < $80 ... codes $20-$7f can be printed directly,
; codes $00-$1f are control codes which are not printable and thus may
; give undefined result.
tay
bpl @L10
; codes $80-$ff must get converted like this:
; $80-$9f -> dont care (control codes)
; $a0-$bf -> $00-$1f
; $c0-$df -> $60-$7f
; $e0-$ff -> $00-$1f
ora #%01000000 ; $40
clc
adc #%00100000 ; $20
and #%01111111 ; $7f
@L10:
; entry point for direct output of a character. the value passed in
; akku must match the offset in the charset.
; - the following may not modify tmp1
soft80_cputdirect:
jsr soft80_putchar ; Write the character to the screen
; Advance cursor position
iny ; contains CURS_X
cpy #charsperline
beq @L3
sty CURS_X
tya
and #$01
sta soft80_internal_cursorxlsb
bne @L5
lda SCREEN_PTR
clc
adc #8
sta SCREEN_PTR
bcc @L4
inc SCREEN_PTR+1
@L4:
inc CRAM_PTR
bne @L5
inc CRAM_PTR+1
@L5:
rts
@L3:
inc CURS_Y ; new line
ldy #0 ; + cr
sty CURS_X
jmp soft80_plot
; - the following may not modify tmp1
soft80_newline:
lda SCREEN_PTR
clc
adc #<(40*8)
sta SCREEN_PTR
lda SCREEN_PTR+1
adc #>(40*8)
sta SCREEN_PTR+1
lda CRAM_PTR
clc
adc #40
sta CRAM_PTR
bcc @L5
inc CRAM_PTR+1
@L5:
inc CURS_Y
rts
;-------------------------------------------------------------------------------
; All following code belongs to the character output to bitmap
;
; this stuff is going to be used a lot so we unroll it a bit for speed
;-------------------------------------------------------------------------------
.if SOFT80FASTSPACE = 1
; output inverted space (odd)
draw_spaceinvers_odd:
.repeat 8,line
lda (SCREEN_PTR),y
and #$f0
sta (SCREEN_PTR),y
.if line < 7
iny
.endif
.endrepeat
jmp draw_back
; output inverted space (general entry point)
; in: y must be $00
draw_spaceinvers:
.if SOFT80COLORVOODOO = 1
jsr soft80_putcolor
.else
lda soft80_internal_cellcolor
sta (CRAM_PTR),y ; vram
.endif
lda soft80_internal_cursorxlsb
bne draw_spaceinvers_odd
; output inverted space (even)
.repeat 8,line
lda (SCREEN_PTR),y
and #$0f
sta (SCREEN_PTR),y
.if line < 7
iny
.endif
.endrepeat
jmp draw_back
; output space (odd)
draw_space_odd:
.repeat 8,line
lda (SCREEN_PTR),y
ora #$0f
sta (SCREEN_PTR),y
.if line < 7
iny
.endif
.endrepeat
jmp draw_back
; output space (general entry point)
; in: y must be $00
draw_space:
lda RVS
bne draw_spaceinvers
.if SOFT80COLORVOODOO = 1
jsr remcolor
.endif
;ldy #$00 ; is still $00
lda soft80_internal_cursorxlsb
bne draw_space_odd
; output space (even)
.repeat 8,line
lda (SCREEN_PTR),y
ora #$f0
sta (SCREEN_PTR),y
.if (line < 7)
iny
.endif
.endrepeat
jmp draw_back
.endif
;-------------------------------------------------------------------------------
; output one character in internal encoding without advancing cursor position
; generic entry point
;
; - the following may not modify tmp1
; in: A: charcode
; out: Y: CURS_X
;
soft80_putchar:
sta tmp3 ; remember charcode
sei
ldx $01
stx tmp4
ldx #$34
stx $01 ; will stay $34 for space
ldy #$00 ; will be $00 from now on
.if SOFT80FASTSPACE = 1
cmp #' ' ; space is a special (optimized) case
beq draw_space
.endif
.if SOFT80COLORVOODOO = 1
jsr soft80_putcolor
.else
lda soft80_internal_cellcolor
sta (CRAM_PTR),y ; vram
.endif
; output character
ldx tmp3 ; get charcode
lda RVS
beq @skp
jmp draw_charinvers
@skp:
lda soft80_internal_cursorxlsb
bne draw_char_even
; output character (odd)
.repeat 8,line
lda (SCREEN_PTR),y
and #$0f
ora soft80_hi_charset+(line*$80),x
sta (SCREEN_PTR),y
.if line < 7
iny
.endif
.endrepeat
jmp draw_back
; output character (even)
draw_char_even:
.repeat 8,line
lda (SCREEN_PTR),y
and #$f0
ora soft80_lo_charset+(line*$80),x
sta (SCREEN_PTR),y
.if line < 7
iny
.endif
.endrepeat
draw_back:
lda tmp4
sta $01
cli
ldy CURS_X
rts
; output inverted character (odd)
draw_charinvers_odd:
.repeat 8,line
lda (SCREEN_PTR),y
ora #$0f
eor soft80_lo_charset+(line*$80),x
sta (SCREEN_PTR),y
.if line < 7
iny
.endif
.endrepeat
jmp draw_back
; output inverted character (generic)
draw_charinvers:
lda soft80_internal_cursorxlsb
bne draw_charinvers_odd
.repeat 8,line
lda (SCREEN_PTR),y
ora #$f0
eor soft80_hi_charset+(line*$80),x
sta (SCREEN_PTR),y
.if line < 7
iny
.endif
.endrepeat
jmp draw_back
;-------------------------------------------------------------------------------
; optional "color voodoo". the problem is that each 8x8 cell can only contain
; two colors, one of which is used for the background color, so two characters
; have to share the same text color.
;
; - in a cell that contains two spaces, both the color ram and the text color
; in vram contain the background color
;
; - in a cell that contains one character, its text color goes into vram. the
; color ram contains the background color.
;
; - in a cell that contains two characters, the color of the left character goes
; to vram (and is shared by both for display). the "would be" color of the
; right character goes to color ram as a reminder and can be restored when one
; of the two characters is cleared by a space.
.if SOFT80COLORVOODOO = 1
; remove color from cell, called before putting a "space" character to the bitmap
;
; __ -> __ -
; _A -> _A -
; B_ -> B_ -
; _A -> __ vram = bgcol
; B_ -> __ vram = bgcol
; BA -> _A vram = colram, colram = bgcol
; BA -> B_ colram = bgcol
;
; in: x must be $34
; y must be $00
; out: x = $34
; y = $00
remcolor:
;ldy #$00 ; is still $00
; if the textcolor in vram is equal to the background color, then
; no (visible) character is in the current cell and we can exit
; immediately.
lda (CRAM_PTR),y ; vram (textcolor)
and #$0f
cmp soft80_internal_bgcolor
beq @sk1 ; yes, vram==bgcolor
; now check if the textcolor in color ram is equal the background color,
; if yes then there is only one (visible) character in the current cell
inc $01 ; $35
lda (CRAM_PTR),y ; colram (2nd textcolor)
stx $01 ; $34
and #$0f
cmp soft80_internal_bgcolor
beq @sk2 ; yes, colram==bgcolor
sta tmp3 ; A contains colram
; two characters in the current cell, of which one will get removed
lda soft80_internal_cursorxlsb
bne @sk3
; vram = colram
lda (CRAM_PTR),y ; vram
and #$f0
ora tmp3 ; colram value
sta (CRAM_PTR),y ; vram
@sk3:
; colram = bgcolor
lda soft80_internal_bgcolor
inc $01 ; $35
sta (CRAM_PTR),y ; colram
stx $01 ; $34
rts
@sk2:
; colram is bgcolor
; => only one char in cell used
jsr soft80_checkchar
bcs @sk1 ; space at current position
; vram (textcolor) = bgcolor
lda (CRAM_PTR),y ; vram
and #$f0
ora soft80_internal_bgcolor
sta (CRAM_PTR),y ; vram
@sk1:
rts
; put color to cell
;
; __ -> _A vram = textcol
; __ -> B_ vram = textcol
; _A -> BA colram = vram, vram = textcol
; B_ -> BA colram = textcol
;
; _A -> _C vram = textcol
; B_ -> C_ vram = textcol
; BA -> BC colram = textcol
; BA -> CA vram = textcol
;
; in: $01 is $34 (RAM under I/O) when entering
; x must be $34
; y must be $00
; out: x = $34
; y = $00
soft80_putcolor:
;ldy #$00 ; is still $00
lda (CRAM_PTR),y ; vram
and #$0f
cmp soft80_internal_bgcolor
beq @sk1 ; vram==bgcolor => first char in cell
; vram!=bgcolor => second char in cell
inc $01 ; $35
lda (CRAM_PTR),y ; colram
stx $01 ; $34
and #$0f
cmp soft80_internal_bgcolor
beq @l2s ; colram==bgcolor -> second char in cell
; botch characters in the cell are used
lda soft80_internal_cursorxlsb
bne @sk2 ; jump if odd xpos
; vram = textcol
lda soft80_internal_cellcolor
sta (CRAM_PTR),y ; vram
rts
@l2s:
; one character in cell is already used
jsr soft80_checkchar
bcc @sk1 ; char at current position => overwrite 1st
lda soft80_internal_cursorxlsb
beq @sk3 ; jump if even xpos
@sk2:
; colram = textcol
lda CHARCOLOR
inc $01 ; $35
sta (CRAM_PTR),y ; colram
stx $01 ; $34
rts
@sk3:
; colram=vram
lda (CRAM_PTR),y ; vram
inc $01 ; $35
sta (CRAM_PTR),y ; colram
stx $01 ; $34
@sk1:
; vram = textcol
lda soft80_internal_cellcolor
sta (CRAM_PTR),y ; vram
rts
;
; test if there is a space or a character at current position
;
; in: x = $34
; $01 must be $34
;
; out: SEC: space
; CLC: character
; x = $34
; y = $00
soft80_checkchar:
lda soft80_internal_cursorxlsb
bne @l1a
; check charset data from bottom up, since a lot of eg lowercase chars
; have no data in the top rows, but all of them DO have data in the
; second to bottom row, this will likely be faster in average.
ldy #7
.repeat 8,line
lda (SCREEN_PTR),y
and #$f0
cmp #$f0
bne @ischar
.if (line < 7)
dey
.endif
.endrepeat
;ldy #$00 ; is 0
;sec ; is set
rts
@ischar:
ldy #$00
;clc ; is cleared
rts
@l1a:
ldy #$07
.repeat 8,line
lda (SCREEN_PTR),y
and #$0f
cmp #$0f
bne @ischar
.if line < 7
dey
.endif
.endrepeat
;ldy #$00 ; is 0
;sec ; is set
rts
.endif