Retroman and Sufami's profile

Sufami proportional font engine (1)

Proportional font (1)


Proportional font là tên gọi chính thống, còn tên dân dã là variable width font (vwf). Khái niệm này trái ngược với monospace font hay còn gọi là fixed width font. Đối với các loại chữ tượng hình như chữ Hoa, chữ Nhật thì dùng monospace font không sao, vì bề ngang của mỗi chữ gần như tương đồng nhau. Nhưng với văn bản dùng chữ La Tinh thì dùng proportional font sẽ cho kết quả đẹp hơn.

Để tạo proportional font cho máy Sufami thì có một trong hai lựa chọn là render chữ trong thời gian thực, hoặc chứa bộ font đã được render sẵn trong Rom. Cách render chữ trong thời gian thực có ưu điểm là ít tốn Rom, nhưng có nhược điểm là tốn thời gian render, mà chủ yếu là ở bước shift bit sang phải. Cách chứa sẵn bộ chữ đã được shift sẵn trong Rom tuy tốn không gian chứa trong Rom (mỗi chữ có 8 phiên bản shift) nhưng lại không tốn thời gian render, hiển thị text tức thời. Cách này phù hợp với Rom kích thước lớn, hiển thị text ở nơi cần phản ứng tức thì, chẳng hạn như text trong menu.
Tileset và tilemap cho bộ font 2bpp, chứa trong Rom theo kiểu interleave như dưới đây.


Tilemap cho font 2bpp
Tileset cho font 2bpp

Một ví dụ cho đoạn code render font 2bpp như dưới đây.

-
    JSR read_text
    CMP #$FF
    BEQ _end
    CMP #$F0
    BCC +
    JSR control_code
    BRA -
+
    JSR draw_tile
    BRA -
    JSR draw_map
    RTS

Từ F0~FF là control code tùy ý. Ở đây FF là code kết thúc text. Điểm mấu chốt là công đoạn shift chữ sang phải nếu chữ đó dùng chung tile với chữ trước. Số lần shift bằng độ rộng của chữ đứng trước. Sau khi shift thì ORA với dữ liệu của chữ đứng trước nó.

shift_char:
    PHX
    REP #$20
    LDA.b {pixel_shift}
    AND #$00FF
    TAX
    BEQ +
    LDA.b {left_byte}
    XBA
-
    LSR
    DEX
    BNE -
    XBA
    STA.b {left_byte}
+
    SEP #$20
    PLX
    RTS

draw_tile:
    PHY
    REP #$20
    AND #$00FF
    PHA
    TAY
    SEP #$20
    JSR choose_width
    LDA.b [{font_ptr}],y
    STA.b {font_width}
    CLC
    ADC.b {total_width}
    STA.b {total_width}
    JSR choose_font
    LDA #$10
    STA.b {pix_line_count}
    REP #$20
    PLA
    ASL
    ASL
    ASL
    ASL
    ASL
    ASL
    TAY
    LDA.b {tile_num}
    AND #$00FF
    ASL
    ASL
    ASL
    ASL
    ASL
    TAX
    PHX
-
    REP #$20
    LDA.b [{font_ptr}],y
    AND #$00FF
    STA.b {left_byte}
    PHY
    TYA
    CLC
    ADC #$0020
    TAY
    SEP #$20
    LDA.b [{font_ptr}],y    
    STA.b {right_byte}
    PLY
    JSR shift_char
    LDA.b {left_byte}
    ORA {draw_font},x
    STA {draw_font},x
    LDA.b {right_byte}
    ORA {draw_font}+32,x
    STA {draw_font}+32,x
    INX
    INY
    DEC.b {pix_line_count}
    BNE -
    PLX
    LDA #$10
    STA.b {pix_line_count}
-
    REP #$20
    LDA.b [{font_ptr}],y
    AND #$00FF
    STA.b {left_byte}
    PHY
    TYA
    CLC
    ADC #$0020
    TAY
    SEP #$20
    LDA.b [{font_ptr}],y    
    STA.b {right_byte}
    PLY
    JSR shift_char
    LDA.b {left_byte}
    ORA {draw_font}+16,x
    STA {draw_font}+16,x
    LDA.b {right_byte}
    ORA {draw_font}+48,x
    STA {draw_font}+48,x
    INX
    INY
    DEC.b {pix_line_count}
    BNE -    
    JSR shift_cal
    PLY
    RTS

Shift_cal ở đây là bước tính toán phải shift chữ kế tiếp sang phải bao nhiêu lần. Phân làm 3 trường hợp: độ rộng của chữ hiện tại + số lần shift của nó so sánh với độ rộng của một tile (8 pixel). Bằng, lớn hơn, nhỏ hơn.

shift_cal:
    LDA.b {font_width}
    CLC
    ADC.b {pixel_shift}
    CMP #$08
    BNE +
    STZ.b {pixel_shift}
    INC.b {tile_num}
    RTS
+
    BCS +
    STA.b {pixel_shift}
    RTS
+
    SEC
    SBC #$08
    STA.b {pixel_shift}
    INC.b {tile_num}
    RTS


Sufami proportional font engine (1)
Published:

Sufami proportional font engine (1)

Published:

Tools

Creative Fields