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.
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 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
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
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
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