C64 GB2312 テキストレンダラー (han64)
A Commodore 64用のGB2312中国語テキストレンダラー、8×8ビットマップフォントを使用し、ダイナミックな文字キャッシングを採用しています.
スコープv1 (レンダリング)
- 2501+ 简体中国語文字 (GB2312行 $B0-$D7)
- 8×8ピクセルビットマップフォント (1文字あたり8バイト)
- バイナリファイルからのGB2312エンコードテキスト表示
- ダイナミックキャラクターキャッシング(256文字スロット)
- ランクベースのGB2312 → グリフID検索
- Pythonでのオフラインテーブル生成
- C64での6502アセンブリによるリアルタイムレンダリング(ACME)
スコープv1.5(現在:複数の文字集合)
- ラスターアイレプロットを使用したダブル文字集合サポート(512文字スロット)
- 8×7ピクセルビットマップフォント(1グリフあたり7バイト)でスペースを節約
スコープ v2 (将来:IME)
- ピンイン入力法と候補選択
- インタラクティブなテキスト編集
- カーソルの移動とスクロール
- 下の「将来の作業」セクションを参照
コアアーキテクチャ (v1)
GB2312 text file (chabuduo.bin)
↓
GB2312 → glyphID lookup (rank-based tables)
↓
Cache check (2502-byte cache array)
↓
Copy glyph bitmap (8×8) if not cached
↓
Write character code to screen RAM
↓
VIC-II renders using custom charset
主要な原則
- 実行時にはUnicodeを使用しない
- 密集型の内部グリフID (0..2500)
- GB2312はI/O専用に使用されます
- 重い処理はオフラインで行います
- 高速な字形コピーのための自己修復コード
字形セット
ちょうど2501個の漢字
すべては:
- GB2312でエンコード可能
- BMP Unicode(UTF-16サロゲートなし)
追加文字:
- ~70文字のASCII
- 8 GB2312 記号/記号(行 1–15)
字形ストレージ
font8.binまたはfont7.bin(v1.5向け)
レイアウト:
- glyphID × 8 バイト(または v1.5では 7 バイト)
- 1 行あたり 1 バイト、使用ビット数 8 ビット:8×8 ビットマップ(または v1.5では 8×7)
glyphID の並び順(重要)
glifIDはGB2312の行/列順序で割り当てられます
理由:
- GB2312符号化/復号を簡素化します
- 単一のglifIDの再利用を可能に→gb2312テーブル
- テキストレンダリング時の局所性を向上させます
- 2番目の逆マッピングテーブルを回避します
頻度はIME候補順序内で処理され、glifID番号付けではありません
符号化:GB2312
- ASCII:
0x00–0x7F(現在v1ではスキップされています) - Hanzi: 2バイト
- hiバイト(行):
0xB0–0xD7(40行サポートされています) - loバイト(列):
0xA1–0xFE(各行94列)
- hiバイト(行):
- 未使用/無効: 他のバイト範囲
- BOMなし
- 状態なし、ストリーミングに優しい
GB2312は厳密にI/O形式であり、内部ロジックに使用されません。
GB2312検索実装
実行時環境はランクベースの符号化を使用して、GB2312 → グリフIDのマッピングを圧縮します:
各行($B0-$D7)には、以下のテーブルがあります:
- ベースグリフID(2バイト):この行の開始グリフID
- ランク配列 (94バイト): 各列($A1-$FE)ごとにランク(0..count-1)を格納するか、欠落している場合は$FFを格納
これにより、欠落した文字を効率的に表現でき、使用されていないGB2312コードのために字形IDを割り当てる必要がなくなります
実行時テーブル(v1)
Pythonでオフラインで生成(tools/gb40.py)
gb40_rows.asm
40行テーブルを含む(gb_row_B0を通じて)gb_row_D7), 各々に:
!word baseGlyphID ; 2 bytes
!byte rank[94] ; 94 bytes: rank or $FF if missing
ポインタテーブルgb_row_ptr_loとgb_row_ptr_hiをmain.asmで参照しています.
キャラクターキャッシュ
キャッシュ (main.asmで2501+バイト)
- glyphID (0..2501)でインデックス化
- グリフがロードされた場合、キャラクタースロット(0-255)を保存し、キャッシュされていない場合は0を保存
- キャッシュが満杯になると(chrptrが256に達すると)、その後の文字はスペースとして表示されます
これにより一度に表示可能なユニークな文字は256に制限されますが、キャッシングを通じて2501文字以上のドキュメントを処理することが可能です
Pythonビルドパイプライン
入力:
gb2312_chars.txt(GB2312コード付き2501文字)- フォントビットマップデータ(8×8ビットマップ)
出力:
font8.bin(2501 × 8バイト)font7.bin(2501 × 7バイト for v1.5)gb40_rows.asm(40行のテーブル、ランクエンコーディング)
すべてのテーブルはアセンブリで!binaryおよび!sourceを使用して含まれます.
実行時 (C64 / 6502)
- UTF-8なし
- 実行時にはUnicodeなし
- 動的メモリなし
- すべてのテーブルは読み取り専用
- アセンブラ: ACME
- ビルド:
acme main.asm(または Makefile を参照)
レンダリングパス (v1):
- テキストストリームから GB2312 バイトペアを読み取る
GB2312_LookupGlyphID(ランクベース) を通じて glyphID を検索- glyphID でインデックス付けされたキャッシュ配列を確認
- キャッシュされていない場合、
CopyGlyph8を通じて 8×8 ビットマップをコピーしてカスタムチャラットセットに格納 - キャラクタースロットをスクリーンRAMに書き込む
- VIC-IIは$3000でカスタムチャラセットを使用
これは何ではない
- UTF-16ではない
- Unicode実行時環境ではない
- 辞書ベースではない(まだではない)
- 繁体字ではない
- GBK/GB18030実行時環境ではない(しかしオフラインで互換性がある)
将来の作業(v2 - IME)
Pinyin IMEの機能
- 音節解析付きPinyin入力法
- 初期バケット(b, p, m, f, d, t, n, lなど + Øで母音始まり)
- 候補選択UI
- フレーズ辞書(2~4文字)
- 簡拼省略モード
- MRU学習
- 頻度に基づく候補順位付け
レンダリング強化
- ダブル文字セットサポート(ラスターアイレントにより512文字スロット)
- 文字セット1は画面上半分用
- 文字セット2は画面下半分用
- ラスターアイレントは行13(走査線104)で切り替え
- 二番目のアイレントは行25(走査線200)で戻す
- スクロールサポート(行コピー+アイレント調整)
- カーソルの移動(色ベースまたは専用の文字)
- インタラクティブなテキスト編集
データソース
- Unihan Database for pinyin mappings
- SUBTLEX-CHまたはJun Da for frequency data
- UTF-8のインポート/エクスポートツール
デザイン哲学
- 構造は賢さを打ち負かす
- オフラインの複雑さ、実行時のシンプルさ
- 符号 ≠ 言語
- 6502 まず、現代のツールが次
テキストレンダリング (v1)
- VIC-II テキストモードでカスタム文字セット
- 40×25 文字
- カスタム文字セットは $3000 (バンク6)
- スクリーンRAMは $0400
- カラーラムは $D800 (現在は薄灰色 $0F に設定されています)
- 画面上同時に256個のユニークな文字グリフを表示可能
IMEレンダリング(v2 - 未来)
- 上部行:IME入力と候補エリア
- 最大10候補を表示:
ying 1英 2婴 3鹰 4应 5营 6蝇 7迎 8赢 9盈 0影 - 次/前ページのマーカーが候補数>10候補
- 下部24行:通常のテキスト表示エリア
- カーソルはテキストエリア内で動く、IMEエリアでは動かない












