一个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,所以重新编写一个函数来显示中文
c ▽void putfont8_ud_rev(char *vram, int xsize, int x, int y, char c, char *font) {
int i, k;
char *p, d ;
for(i = 0; i < 8; i++) {
p = vram + (y + i) * xsize + x;
d = font[2 * i];
for(k = 0; k < 8; k++) {
if(d&(0x01<<k)) {
p[k] = c;
}
}
p += 8;
d = font[2 * i + 1];
for(k = 0; k < 8; k++) {
if(d&(0x01<<k)) {
p[k] = c;
}
}
}
return;
}
在putfonts8_asc中添加新的模式用以显示中文
c ▽if (task->langmode == 3) {
for (; *s != 0x00; s++) {
if (task->langbyte1 == 0) {
if (0xa1 <= *s && *s <= 0xfe) {
task->langbyte1 = *s;
} else {
//只要是半角就使用hankaku里面的字符
putfont8(vram, xsize, x, y, c, hankaku + *s * 16);
}
} else {
k = task->langbyte1 - 0xa1;
t = *s - 0xa1;
task->langbyte1 = 0;
font = chinese + (k * 94 + t) * 32;
putfont8_ud_rev(vram, xsize, x - 8, y , c, font );
putfont8_ud_rev(vram, xsize, x - 8, y + 8, c, font + 16);
}
x += 8;
}
}
如果不需要日文字体,可以直接将中文字体数据读入bootpack.c中的nihongo变量(注意分配的内存大小需要修改为memman_alloc_4k(memman, 0x5d5d * 32))
。
如果想要共存则需要添加新的变量,并且增大读入的扇区数量。
在chklang.c文件中添加下列代码,用户测试中文
c ▽static char s3[16] = { // 中文
0xc4, 0xe3, 0xba, 0xc3, 0xce, 0xd2, 0xca, 0xc7, 0x41, 0x6b, 0x76, 0x69,
0x63, 0x6f, 0x72, 0x00
};
if (langmode == 3) {
api_putstr0(s3);
}
修改ipl.nas中读入的扇区数量
c ▽CYLS EQU 30
修改bootpack.c
c ▽// 定义全局变量
unsigned char *chinese;
unsigned char *nihongo;
// 函数void HariMain(void) 中
nihongo = (unsigned char *) memman_alloc_4k(memman, 16 * 256 + 32 * 94 * 47);
chinese = (unsigned char *) memman_alloc_4k(memman, 0x5d5d * 32);
fat = (int *) memman_alloc_4k(memman, 4 * 2880);
file_readfat(fat, (unsigned char *) (ADR_DISKIMG + 0x000200));
finfo = file_search("nihongo.fnt", (struct FILEINFO *) (ADR_DISKIMG + 0x002600), 224);
if (finfo != 0) {
file_loadfile(finfo->clustno, finfo->size, nihongo, fat, (char *) (ADR_DISKIMG + 0x003e00));
} else {
for (i = 0; i < 16 * 256; i++) {
nihongo[i] = hankaku[i]; // 没有字库,半角部分直接复制英文字裤
}
for (i = 16 * 256; i < 16 * 256 + 32 * 94 * 47; i++) {
nihongo[i] = 0xff; // 没有字库,全角部分以0xff填充
}
}
finfo = file_search("HZK16.fnt", (struct FILEINFO *) (ADR_DISKIMG + 0x002600), 224);
if (finfo != 0) {
file_loadfile(finfo->clustno, finfo->size, chinese, fat, (char *) (ADR_DISKIMG + 0x003e00));
} else {
for (i = 0; i < 16 * 256; i++) {
chinese[i] = hankaku[i]; // 没有字库,半角部分直接复制英文字裤
}
for (i = 16 * 256; i < 16 * 256 + 32 * 94 * 47; i++) {
chinese[i] = 0xff; // 没有字库,全角部分以0xff填充
}
}
memman_free_4k(memman, (int) fat, 4 * 2880);
修改graphic.c文件putfonts8_asc的代码,添加下面两行
c ▽extern char *nihongo;
extern char *chinese;
修改console.c文件cmd_langmode函数中的if (mode <= 2)
为if (mode <= 3)