diff --git a/libsrc/tgi/tgi_imulround.s b/libsrc/tgi/tgi_imulround.s index c1661d3dc..238c69fc8 100644 --- a/libsrc/tgi/tgi_imulround.s +++ b/libsrc/tgi/tgi_imulround.s @@ -1,12 +1,16 @@ ; ; Ullrich von Bassewitz, 2009-11-05 ; -; Helper function for functions using sine/cosine: Multiply two values, one -; being an 8.8 fixed point one, and return the rounded and scaled result. +; Helper function for graphics functions: Multiply two values, one being +; an 8.8 fixed point one, and return the rounded and scaled result. +; +; The module has two entry points: One is C callable and expects the +; parameters in ax and the stack, the second is assembler callable and +; expects the parameters in ax and ptr1 ; - .export _tgi_imulround + .export _tgi_imulround, tgi_imulround .import popax, imul16x16r32 .include "zeropage.inc" @@ -16,7 +20,9 @@ ; .code -.proc _tgi_imulround + +; C callable entry point +_tgi_imulround: ; Get arguments @@ -24,6 +30,9 @@ stx ptr1+1 ; Save lhs jsr popax ; Get rhs +; ASM callable entry point +tgi_imulround: + ; Multiplicate jsr imul16x16r32 @@ -51,4 +60,4 @@ tya rts -.endproc + diff --git a/libsrc/tgi/tgi_outcode.s b/libsrc/tgi/tgi_outcode.s index 243e5c2de..5c75ee0b7 100644 --- a/libsrc/tgi/tgi_outcode.s +++ b/libsrc/tgi/tgi_outcode.s @@ -12,7 +12,7 @@ .bss -; Clipping coordinates. +; Clipping coordinates. They must be in this order! tgi_clip_x1: .res 2 tgi_clip_y1: .res 2 tgi_clip_x2: .res 2 @@ -42,7 +42,7 @@ tgi_clip_y2: .res 2 ; .code -.proc tgi_outcode +.proc tgi_outcode lda #TGI_CLIP_NONE sta tmp1 diff --git a/libsrc/tgi/tgi_outtext.s b/libsrc/tgi/tgi_outtext.s index 3f2f365fd..76fbf78ad 100644 --- a/libsrc/tgi/tgi_outtext.s +++ b/libsrc/tgi/tgi_outtext.s @@ -9,6 +9,7 @@ .include "tgi-vectorfont.inc" .include "zeropage.inc" + .import _toascii .import popax, negax @@ -16,6 +17,8 @@ ; Data text := regbank +font := regbank ; Same as text +widths := regbank+2 ;---------------------------------------------------------------------------- ; @@ -40,6 +43,10 @@ text := regbank tax pla ; Restore s jsr _tgi_textwidth ; Get width of text string + +; Move the graphics cursor by the amount in a/x + +MoveCursor: ldy _tgi_textdir ; Horizontal or vertical text? beq @L1 ; Jump if horizontal @@ -56,9 +63,10 @@ text := regbank txa adc _tgi_curx+1,y sta _tgi_curx+1,y - rts +Done: rts -; Handle vector font output +; Handle vector font output. First, check if we really have a registered +; vector font. Bail out if this is not the case. VectorFont: tay @@ -66,20 +74,58 @@ VectorFont: ora _tgi_vectorfont+1 beq Done ; Bail out if not - lda text ; Save zero page variable on stack +; Check if the font in the given size is partially out of the screen. We +; do this in vertical direction here, and in horizontal direction before +; outputting a character. + + ; (todo) + +; Save zero page variable on stack and save + + lda text pha lda text+1 pha + lda widths + pha + lda widths+1 + pha sty text stx text+1 ; Store pointer to string + lda _tgi_vectorfont + clc + adc #<(TGI_VECTORFONT::WIDTHS - TGI_VF_FIRSTCHAR) + sta widths + lda _tgi_vectorfont+1 + adc #>(TGI_VECTORFONT::WIDTHS - TGI_VF_FIRSTCHAR) + sta widths+1 + ; Output the text string @L1: ldy #0 lda (text),y ; Get next character from string beq EndOfText + jsr _toascii ; Convert to ascii + pha ; Save char in A jsr _tgi_vectorchar ; Output it + pla + +; Move the graphics cursor by the width of the char + + tay + lda (widths),y ; Get width of this char + sta ptr1 + lda #0 + sta ptr1+1 + lda _tgi_textscalew + ldx _tgi_textscalew+1 ; Get scale factor + jsr tgi_imulround ; Multiplcate and round + jsr MoveCursor ; Move the graphics cursor + +; Next char in string + inc text bne @L1 inc text+1 @@ -88,11 +134,15 @@ VectorFont: ; Done. Restore registers and return EndOfText: + pla + sta widths+1 + pla + sta widths pla sta text+1 pla sta text -Done: rts + rts .endproc diff --git a/libsrc/tgi/tgi_textheight.s b/libsrc/tgi/tgi_textheight.s index 52bab4f1a..7bd4216bd 100644 --- a/libsrc/tgi/tgi_textheight.s +++ b/libsrc/tgi/tgi_textheight.s @@ -4,20 +4,51 @@ .include "tgi-kernel.inc" + .include "tgi-vectorfont.inc" + .include "zeropage.inc" ;----------------------------------------------------------------------------- ; unsigned __fastcall__ tgi_textheight (const char* s); -; /* Calculate the width of the text in pixels according to the current text +; /* Calculate the height of the text in pixels according to the current text ; * style. ; */ ; .proc _tgi_textheight + ldy _tgi_font + bne @L2 ; Jump if vector font + +; Return the height for the bitmap font + lda _tgi_charheight ldx #0 - rts +@L1: rts + +; Return the height for the vector font + +@L2: lda _tgi_vectorfont + tax + ora _tgi_vectorfont+1 + beq @L1 ; Return zero if no font + + stx ptr1 + lda _tgi_vectorfont+1 + sta ptr1+1 + ldy #TGI_VECTORFONT::TOP + lda (ptr1),y + ldy #TGI_VECTORFONT::BOTTOM + clc + adc (ptr1),y ; Total font height is top + bottom + + sta ptr1 + lda #0 + sta ptr1+1 ; Save base height in ptr1 + + lda _tgi_textscaleh + ldx _tgi_textscaleh+1 ; Get scale factor ... + jmp tgi_imulround ; ... and return scaled result .endproc diff --git a/libsrc/tgi/tgi_textwidth.s b/libsrc/tgi/tgi_textwidth.s index 0c04ed94a..477510d8e 100644 --- a/libsrc/tgi/tgi_textwidth.s +++ b/libsrc/tgi/tgi_textwidth.s @@ -4,8 +4,20 @@ .include "tgi-kernel.inc" + .include "tgi-vectorfont.inc" + .include "zeropage.inc" + + .import _strlen, _toascii + .import umul16x16r32 + +;----------------------------------------------------------------------------- +; Aliases for zero page locations + +Width := ptr1 +WTab := ptr2 +Text := ptr3 + - .import _strlen, pushax, tosumula0 ;----------------------------------------------------------------------------- ; unsigned __fastcall__ tgi_textwidth (const char* s); @@ -16,12 +28,75 @@ ; Result is strlen (s) * tgi_textmagw * tgi_fontsizex ; +.code .proc _tgi_textwidth + ldy _tgi_font + bne @L1 ; Jump if vector font + +; Return the width of the string for the bitmap font + jsr _strlen - jsr pushax + sta ptr1 + stx ptr1+1 lda _tgi_charwidth - jmp tosumula0 + ldx #0 + jmp umul16x16r32 + +; Return the width of the string for the vector font. To save some code, we +; will add up all the character widths and then multiply by the scale factor. +; Since the output routine will scale each single character, the result may +; be slightly different. + +@L1: sta Text + stx Text+1 ; Save pointer to string + + lda _tgi_vectorfont+1 + tax + ora _tgi_vectorfont + beq @L9 ; Return zero if no font + + lda _tgi_vectorfont + clc + adc #<(TGI_VECTORFONT::WIDTHS - TGI_VF_FIRSTCHAR) + sta WTab + txa + adc #>(TGI_VECTORFONT::WIDTHS - TGI_VF_FIRSTCHAR) + sta WTab+1 + + ldy #0 + sty Width + sty Width+1 ; Zero the total width + +; Sum up the widths of the single characters + +@L2: ldy #0 + lda (Text),y ; Get next char + beq @L4 ; Bail out if end of text reached + jsr _toascii ; Convert to ascii + tay + lda (WTab),y ; Get width of this char + clc + adc Width + sta Width + bcc @L3 + inc Width+1 +@L3: inc Text + bne @L2 + inc Text+1 + bne @L2 + +; We have the total width now, scale and return it + +@L4: lda _tgi_textscalew + ldx _tgi_textscalew+1 + jmp tgi_imulround + +; Exit point if no font installed + +@L9: rts .endproc + + diff --git a/libsrc/tgi/tgi_vectorchar.s b/libsrc/tgi/tgi_vectorchar.s index 72a5b234b..76f585dcd 100644 --- a/libsrc/tgi/tgi_vectorchar.s +++ b/libsrc/tgi/tgi_vectorchar.s @@ -7,7 +7,7 @@ ; */ ; - .import _toascii, imul16x16r32, umul16x16r32, negax, negeax + .import imul16x16r32, umul16x16r32, negax, negeax .include "tgi-kernel.inc" .include "tgi-vectorfont.inc" @@ -26,13 +26,10 @@ X1: .res 2 Y1: .res 2 X2: .res 2 Y2: .res 2 -BaseX: .res 2 -BaseY: .res 2 -Char: .res 1 ;---------------------------------------------------------------------------- ; Get the next operation from the Ops pointer, remove the flag bit and sign -; extend the 8 bit value. On return, the flags are set for the value in A. +; extend the 8 bit value to 16 bits. .code .proc GetOp @@ -45,78 +42,88 @@ Char: .res 1 bne :+ inc Ops+1 -; Move bit 7 into Flag, then sign extend the value in A +; Move bit 7 into Flag, then sign extend the value in A and extend the sign +; into X. : asl a ; Flag into carry ror Flag + ldx #0 cmp #$80 ; Sign bit into carry ror a ; Sign extend the value + bpl :+ + dex ; Value is negative ; Done - rts +: rts .endproc -;---------------------------------------------------------------------------- -; Round a 16.8 fixed point value in eax - -.code -.proc RoundFix - - cmp #$80 ; frac(val) >= 0.5? - txa - ldx sreg - adc #$00 - bcc @L1 - inx -@L1: rts - -.endproc - ;---------------------------------------------------------------------------- ; Get and process one coordinate value. The scale factor is passed in a/x .code -.proc GetProcessedCoord +GetProcessedYCoord: + lda _tgi_textscaleh+0 + ldx _tgi_textscaleh+1 + +GetProcessedCoord: ; Save scale factor as left operand for multiplication sta ptr1 stx ptr1+1 -; Load next operation value. This will set the flags for the value in A. +; Load next operation value. jsr GetOp -; 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 - bpl :+ - eor #$FF - clc - adc #$01 ; Negate -: ldx #$00 ; High byte is always zero - ; Multiplicate with the scale factor. - jsr umul16x16r32 ; Multiplicate + jmp tgi_imulround ; Multiplicate, round and scale -; The result is a 16.8 fixed point value. Round it. +;---------------------------------------------------------------------------- +; Add the base coordinate with offset in Y to the value in A/X - jsr RoundFix +.code +.proc AddBaseCoord -; Check the sign and negate if necessary + clc + adc _tgi_curx+0,y + pha + txa + adc _tgi_curx+1,y + tax + pla + rts - bit tmp1 ; Check sign - bpl :+ - jmp negax ; Negate result if necessary -: rts +.endproc + +;---------------------------------------------------------------------------- +; Subtract the value in a/x from the base coordinate with offset in Y +; This is +; +; ax = _tgi_cur[xy] - ax +; +; which can be transformed to +; +; ax = _tgi_cur[xy] + (~ax + 1); + + +.code +.proc SubBaseCoord + + eor #$FF + sec ; + 1 + adc _tgi_curx+0,y + pha + txa + eor #$FF + adc _tgi_curx+1,y + tax + pla + rts .endproc @@ -126,9 +133,8 @@ Char: .res 1 .code .proc _tgi_vectorchar -; Convert the character to ASCII, multiplicate by two and save into Y +; Multiplicate the char value by two and save into Y - jsr _toascii asl a tay @@ -142,59 +148,6 @@ Char: .res 1 lda Flag pha -; Get the width of the char in question - - lda _tgi_vectorfont - clc - adc #<(TGI_VECTORFONT::WIDTHS - TGI_VF_FIRSTCHAR) - sta Ops - lda _tgi_vectorfont+1 - adc #>(TGI_VECTORFONT::WIDTHS - TGI_VF_FIRSTCHAR) - sta Ops+1 - lda (Ops),y - -; Save the character - - sty Char - -; Calculate the width of the character by multiplying with the scale -; factor for the width - - sta ptr1 - lda #0 - sta ptr1+1 - - lda _tgi_textscalew - ldx _tgi_textscalew+1 - jsr umul16x16r32 - jsr RoundFix - -; Store the current value of the graphics cursor into BaseX/BaseY, then -; move it to the next character position - - pha - ldy #3 -: lda _tgi_curx,y - sta BaseX,y - dey - bpl :- - pla - - ldy _tgi_textdir - beq :+ ; Jump if horizontal text - - jsr negax - ldy #2 ; Offset of tgi_cury - -; Advance graphics cursor - -: clc - adc _tgi_curx,y - sta _tgi_curx,y - txa - adc _tgi_curx+1,y - sta _tgi_curx+1,y - ; Calculate a pointer to the vector ops for the given char (now in Y). We ; definitely expect a font here, that has to be checked by the caller. @@ -206,7 +159,6 @@ Char: .res 1 adc #>(TGI_VECTORFONT::CHARS - 2*TGI_VF_FIRSTCHAR) sta Ops+1 - ldy Char iny lda (Ops),y tax @@ -221,38 +173,84 @@ Loop: lda _tgi_textscalew+0 ldx _tgi_textscalew+1 jsr GetProcessedCoord ; Get X vector -; X2 = BaseX + XMag * XDelta. +; Depending on the text direction, the X vector is either applied to X as +; +; X2 = _tgi_curx + XMag * XDelta +; +; or applied to Y as +; +; Y2 = _tgi_cury - XMag * XDelta +; +; which can be transformed to +; +; Y2 = _tgi_cury + (~(XMag * XDelta) + 1); +; +; +; For the Y component we have +; +; Y2 = _tgi_cury - YMag * YDelta +; +; which can be transformed to +; +; Y2 = _tgi_cury + (~(YMag * YDelta) + 1); +; +; or applied to X as +; +; X2 = _tgi_curx - YMag * YDelta +; +; which can be transformed to +; +; X2 = _tgi_curx + (~(YMag * YDelta) + 1); +; - clc - adc BaseX+0 - sta X2+0 - txa - adc BaseX+1 - sta X2+1 + ldy _tgi_textdir ; Horizontal or vertical text? + bne @Vertical ; Jump if vertical -; Process the Y value +; Process horizontal text - lda _tgi_textscaleh+0 - ldx _tgi_textscaleh+1 - jsr GetProcessedCoord + ldy #0 + jsr AddBaseCoord + sta X2 + stx X2+1 -; Y2 = BaseY - YMag * YDelta; -; Y2 = BaseY + (~(YMag * YDelta) + 1); +; Get Y vector - eor #$FF - sec ; + 1 - adc BaseY+0 - sta Y2+0 - txa - eor #$FF - adc BaseY+1 - sta Y2+1 + jsr GetProcessedYCoord + +; Apply to Y + + ldy #2 + jsr SubBaseCoord + sta Y2 + stx Y2+1 + jmp @DrawMove + +; Process vertical text + +@Vertical: + ldy #2 + jsr SubBaseCoord + sta Y2 + stx Y2+1 + +; Get Y vector + + jsr GetProcessedYCoord + +; Apply to X + + ldy #0 + jsr SubBaseCoord + sta X2 + stx X2+1 ; Draw, then move - or just move +@DrawMove: bit Flag bpl @Move ; Jump if move only +.if 0 ldy #7 ; Copy start coords into zp : lda X1,y sta ptr1,y @@ -260,6 +258,15 @@ Loop: lda _tgi_textscalew+0 bpl :- jsr tgi_line ; Call the driver +.else + ldy #7 ; Copy start coords +: lda X1,y + sta tgi_clip_x1,y + dey + bpl :- + + jsr tgi_clippedline ; Call line clipper +.endif ; Move the start position @@ -276,7 +283,7 @@ Loop: lda _tgi_textscalew+0 ; Done. Restore zp and return. -Done: pla + pla sta Flag pla sta Ops+1