2023-02-27  2025-03-26    1349 字  3 分钟

aos32-gb2312.tgz

一个GB2312汉字是由两个字节编码的,范围为A1A1~FEFE。A1-A9为符号区,B0到F7为汉字区。每一个区有94个字符。

点阵结构

从图片可以看出:

  • 日文编码的第一个字节为点阵的左半部分,第二个字节为点阵的右半部分。

日文EUC

  • 中文编码的第一个字节为点阵的上半部分,第二个字节为点阵的下半部分

中文GB2312

偏移

在汉字占的两个字节中,前一个字节为该汉字的区号,后一个字节为该字的位号。其中,每个区记录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)

Result

除另有声明外本博客文章均采用 知识共享 (Creative Commons) 署名 4.0 国际许可协议 进行许可转载请注明原作者与文章出处