]> git.sur5r.net Git - cc65/commitdiff
Final touches to the first full version of the vector font output.
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 12 Nov 2009 18:00:17 +0000 (18:00 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 12 Nov 2009 18:00:17 +0000 (18:00 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@4464 b7a2c559-68d2-44c3-8de9-860c34a00d81

libsrc/tgi/tgi_imulround.s
libsrc/tgi/tgi_outcode.s
libsrc/tgi/tgi_outtext.s
libsrc/tgi/tgi_textheight.s
libsrc/tgi/tgi_textwidth.s
libsrc/tgi/tgi_vectorchar.s

index c1661d3dcd1238e3b3610bccfafc1c830eed4c20..238c69fc8c67a48a0b8d77c9b934e5a2cda68cc9 100644 (file)
@@ -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
+     
index 243e5c2de956dae5874bf8366af9c84aebbc21df..5c75ee0b76d53ad0f91da7ac680712829493948b 100644 (file)
@@ -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
index 3f2f365fd9a55d4ab99bdca3d7875b1c63d218b7..76fbf78adfbd18698c5577b1d8ac8fa099b6a802 100644 (file)
@@ -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
 
index 52bab4f1adcf5d76306db6135d4277eece7aa48c..7bd4216bd80ec7d552e0c7080e2e94234a90c908 100644 (file)
@@ -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
 
index 0c04ed94a50ce5b65c20cc04ac8505ae15ff7830..477510d8e40449a396afad09350d024831430977 100644 (file)
@@ -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);
 ; 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
 
+
+
index 72a5b234bb4c9fbdf16c5f9291cf7331378e1bf6..76f585dcdbfb07fc77beb16d9126c6af01069e7f 100644 (file)
@@ -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.
+; Multiplicate with the scale factor.
 
-        sta     tmp1                    ; Remember sign of vector offset
-        bpl     :+
-        eor     #$FF
-        clc
-        adc     #$01                    ; Negate
-:       ldx     #$00                    ; High byte is always zero
+        jmp     tgi_imulround           ; Multiplicate, round and scale
 
-; Multiplicate with the scale factor.
+;----------------------------------------------------------------------------
+; Add the base coordinate with offset in Y to the value in A/X
+
+.code
+.proc   AddBaseCoord
+
+        clc
+        adc     _tgi_curx+0,y
+        pha
+        txa
+        adc     _tgi_curx+1,y
+        tax
+        pla
+        rts
 
-        jsr     umul16x16r32            ; Multiplicate
+.endproc
 
-; The result is a 16.8 fixed point value. Round it.
+;----------------------------------------------------------------------------
+; 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);
 
-        jsr     RoundFix
 
-; Check the sign and negate if necessary
+.code
+.proc   SubBaseCoord
 
-        bit     tmp1                    ; Check sign
-        bpl     :+
-        jmp     negax                   ; Negate result if necessary
-:       rts
+        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);
+;
+
+        ldy     _tgi_textdir    ; Horizontal or vertical text?
+        bne     @Vertical       ; Jump if vertical
 
-        clc
-        adc     BaseX+0
-        sta     X2+0
-        txa
-        adc     BaseX+1
-        sta     X2+1
+; Process horizontal text
 
-; Process the Y value
+        ldy     #0
+        jsr     AddBaseCoord
+        sta     X2
+        stx     X2+1
 
-        lda     _tgi_textscaleh+0
-        ldx     _tgi_textscaleh+1
-        jsr     GetProcessedCoord
+; Get Y vector
 
-; Y2 = BaseY - YMag * YDelta;
-; Y2 = BaseY + (~(YMag * YDelta) + 1);
+        jsr     GetProcessedYCoord
 
-        eor     #$FF
-        sec                             ; + 1
-        adc     BaseY+0
-        sta     Y2+0
-        txa
-        eor     #$FF
-        adc     BaseY+1
-        sta     Y2+1
+; 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