一个GB2312汉字是由两个字节编码的,范围为A1A1~FEFE。A1-A9为符号区,B0到F7为汉字区。每一个区有94个字符。
点阵结构
从图片可以看出:
- 日文编码的第一个字节为点阵的左半部分,第二个字节为点阵的右半部分。
- 中文编码的第一个字节为点阵的上半部分,第二个字节为点阵的下半部分
偏移
在汉字占的两个字节中,前一个字节为该汉字的区号,后一个字节为该字的位号。其中,每个区记录94个汉字,位号为该字在该区中的位置。
- 区码:区号(汉字的第一个字节)- 0xa0 (因为汉字编码是从0xa0区开始的,所以文件最前面就是从0xa0区开始,要算出相对区码)
- 位码:位号(汉字的第二个字节)- 0xa0
由此可以得到汉字在HZK16中的绝对偏移位置:offset=(94*(区码-1)+(位码-1))*32
- 区码减1是因为数组是以0为开始而区号位号是以1为开始的
(94*(区号-1)+位号-1)
是一个汉字字模占用的字节数- 最后乘以32是因为汉字库文应从该位置起的32字节信息记录该字的字模信息(前面提到一个汉字要有32个字节显示)
代码实现
由于点阵结构不同,原先的putfont8函数并不适用于GB2312,所以重新编写一个函数来显示中文
1void putfont8_ud_rev(char *vram, int xsize, int x, int y, char c, char *font) {
2 int i, k;
3 char *p, d ;
4 for(i = 0; i < 8; i++) {
5 p = vram + (y + i) * xsize + x;
6 d = font[2 * i];
7 for(k = 0; k < 8; k++) {
8 if(d&(0x01<<k)) {
9 p[k] = c;
10 }
11 }
12 p += 8;
13 d = font[2 * i + 1];
14 for(k = 0; k < 8; k++) {
15 if(d&(0x01<<k)) {
16 p[k] = c;
17 }
18 }
19 }
20 return;
21}
在putfonts8_asc中添加新的模式用以显示中文
1if (task->langmode == 3) {
2 for (; *s != 0x00; s++) {
3 if (task->langbyte1 == 0) {
4 if (0xa1 <= *s && *s <= 0xfe) {
5 task->langbyte1 = *s;
6 } else {
7 //只要是半角就使用hankaku里面的字符
8 putfont8(vram, xsize, x, y, c, hankaku + *s * 16);
9 }
10 } else {
11 k = task->langbyte1 - 0xa1;
12 t = *s - 0xa1;
13 task->langbyte1 = 0;
14 font = chinese + (k * 94 + t) * 32;
15 putfont8_ud_rev(vram, xsize, x - 8, y , c, font );
16 putfont8_ud_rev(vram, xsize, x - 8, y + 8, c, font + 16);
17 }
18 x += 8;
19 }
20}
如果不需要日文字体,可以直接将中文字体数据读入bootpack.c中的nihongo变量(注意分配的内存大小需要修改为memman_alloc_4k(memman, 0x5d5d * 32))
。
如果想要共存则需要添加新的变量,并且增大读入的扇区数量。
在chklang.c文件中添加下列代码,用户测试中文
1static char s3[16] = { // 中文
2 0xc4, 0xe3, 0xba, 0xc3, 0xce, 0xd2, 0xca, 0xc7, 0x41, 0x6b, 0x76, 0x69,
3 0x63, 0x6f, 0x72, 0x00
4};
5if (langmode == 3) {
6 api_putstr0(s3);
7}
修改ipl.nas中读入的扇区数量
1CYLS EQU 30
修改bootpack.c
1// 定义全局变量
2unsigned char *chinese;
3unsigned char *nihongo;
4
5// 函数void HariMain(void) 中
6nihongo = (unsigned char *) memman_alloc_4k(memman, 16 * 256 + 32 * 94 * 47);
7chinese = (unsigned char *) memman_alloc_4k(memman, 0x5d5d * 32);
8fat = (int *) memman_alloc_4k(memman, 4 * 2880);
9file_readfat(fat, (unsigned char *) (ADR_DISKIMG + 0x000200));
10
11finfo = file_search("nihongo.fnt", (struct FILEINFO *) (ADR_DISKIMG + 0x002600), 224);
12if (finfo != 0) {
13 file_loadfile(finfo->clustno, finfo->size, nihongo, fat, (char *) (ADR_DISKIMG + 0x003e00));
14} else {
15 for (i = 0; i < 16 * 256; i++) {
16 nihongo[i] = hankaku[i]; // 没有字库,半角部分直接复制英文字裤
17 }
18 for (i = 16 * 256; i < 16 * 256 + 32 * 94 * 47; i++) {
19 nihongo[i] = 0xff; // 没有字库,全角部分以0xff填充
20 }
21}
22finfo = file_search("HZK16.fnt", (struct FILEINFO *) (ADR_DISKIMG + 0x002600), 224);
23if (finfo != 0) {
24 file_loadfile(finfo->clustno, finfo->size, chinese, fat, (char *) (ADR_DISKIMG + 0x003e00));
25} else {
26 for (i = 0; i < 16 * 256; i++) {
27 chinese[i] = hankaku[i]; // 没有字库,半角部分直接复制英文字裤
28 }
29 for (i = 16 * 256; i < 16 * 256 + 32 * 94 * 47; i++) {
30 chinese[i] = 0xff; // 没有字库,全角部分以0xff填充
31 }
32}
33memman_free_4k(memman, (int) fat, 4 * 2880);
修改graphic.c文件putfonts8_asc的代码,添加下面两行
1extern char *nihongo;
2extern char *chinese;
修改console.c文件cmd_langmode函数中的if (mode <= 2)
为if (mode <= 3)
除另有声明外,本博客文章均采用 知识共享 (Creative Commons) 署名 4.0 国际许可协议 进行许可。转载请注明原作者与文章出处。