1
0
mirror of https://github.com/cc65/cc65.git synced 2024-07-07 19:29:18 +00:00
cc65/libsrc/tgi/tgi_vectorchar.s

205 lines
4.7 KiB
ArmAsm
Raw Normal View History

;
; Ullrich von Bassewitz, 2009-11-02
;
; void __fastcall__ tgi_vectorchar (const unsigned char* Ops);
; /* Draw one character of the vector font at the current graphics cursor
; * position using the current font magnification.
; */
;
.import _toascii, imul16x16r32, umul16x16r32, negax, negeax
.include "tgi-kernel.inc"
.include "tgi-vectorfont.inc"
.include "zeropage.inc"
.macpack longbranch
;----------------------------------------------------------------------------
; Data
Ops = regbank
Flag = regbank+2
.bss
X1: .res 2
Y1: .res 2
X2: .res 2
Y2: .res 2
;----------------------------------------------------------------------------
;
.code
.proc _tgi_vectorchar
; Convert the character to ASCII, multiplicate by two and save into Y
jsr _toascii
asl a
tay
; Since we will call tgi_lineto, which uses the zero page, and we do also
; need the zero page, make room in the register bank.
lda Ops
pha
lda Ops+1
pha
lda Flag
pha
; Calculate a pointer to the vector ops for the given char (now in Y).
lda _tgi_vectorfont+1
tax
ora _tgi_vectorfont
jeq Done ; Bail out if no font installed
lda _tgi_vectorfont
clc
adc #<(TGI_VECTORFONT::CHARS - 2*TGI_VF_FIRSTCHAR)
sta Ops
lda _tgi_vectorfont+1
adc #>(TGI_VECTORFONT::CHARS - 2*TGI_VF_FIRSTCHAR)
sta Ops+1
iny
lda (Ops),y
tax
dey
lda (Ops),y
sta Ops
stx Ops+1
; Main loop executing vector operations
Loop: lda _tgi_textscalew+0
ldx _tgi_textscalew+1
jsr GetProcessedCoord
; X2 = tgi_curx + XMag * XDelta.
clc
adc _tgi_curx+0
sta X2+0
txa
adc _tgi_curx+1
sta X2+1
; Process the Y value
lda _tgi_textscaleh+0
ldx _tgi_textscaleh+1
jsr GetProcessedCoord
; Y2 = tgi_cury - YMag * YDelta;
; Y2 = tgi_cury + (~(YMag * YDelta) + 1);
eor #$FF
sec ; + 1
adc _tgi_cury+0
sta Y2+0
txa
eor #$FF
adc _tgi_cury+1
sta Y2+1
; Draw, then move - or just move
bit Flag
bpl @Move ; Jump if move only
ldy #7 ; Copy start coords into zp
: lda X1,y
sta ptr1,y
dey
bpl :-
jsr tgi_line ; Call the driver
; Move the start position
@Move: ldy #3
: lda X2,y
sta X1,y
dey
bpl :-
; Loop if not done
bit Flag
bvc Loop
; Done. Restore zp and return.
Done: pla
sta Flag
pla
sta Ops+1
pla
sta Ops
rts
.endproc
;----------------------------------------------------------------------------
; Get and process one coordinate value. The scale factor is passed in a/x
.proc GetProcessedCoord
; Save scale factor as left operand for multiplication
sta ptr1
stx ptr1+1
; Load delta value
ldy #0
lda (Ops),y
inc Ops
bne :+
inc Ops+1
; Move bit 7 into Flag
: asl a ; Flag into carry
ror Flag
; Since we know that the scale factor is always positive, we will remember
; the sign of the coordinate offset, make it positive, do an unsigned mul
; and negate the result if the vector was negative. This is faster than
; relying on the signed multiplication, which will do the same, but for
; both operands.
sta tmp1 ; Remember sign of vector offset
cmp #$80 ; Sign bit into carry
ror a ; Sign extend the value
bpl :+
eor #$FF
clc
adc #$01 ; Negate
: ldx #$00 ; High byte is always zero
; Multiplicate with the scale factor.
jsr umul16x16r32 ; Multiplicate
; The result is a 16.8 fixed point value. Round it.
cmp #$80 ; frac(val) >= 0.5?
txa
adc #$00
tay
lda sreg
adc #$00
tax
tya
bit tmp1 ; Check sign
bpl :+
jmp negax ; Negate result if necessary
: rts
.endproc