第29天 压缩与简单的应用程序
2020.5.10
1. 修复bug(harib26a)
-
先修复harib25g中的bug。
- 通过观察,发现harib25g中,只有全角字符的显示有问题,半角字符是正常的,而且移动窗口之后可以恢复正常,这说明图层缓冲区中是有数据的。因此,问题极有可能出现在刷新上面。
-
修改putfont8_asc_sht(window.c):
void putfonts8_asc_sht(struct SHEET *sht, int x, int y, int c, int b, char *s, int l) { struct TASK *task = task_now(); boxfill8(sht->buf, sht->bxsize, b, x, y, x + l * 8 - 1, y + 15); if (task->langmode != 0 && task->langbyte1 != 0) { putfonts8_asc(sht->buf, sht->bxsize, x, y, c, s); sheet_refresh(sht, x - 8, y, x + l * 8, y + 16); } else { putfonts8_asc(sht->buf, sht->bxsize, x, y, c, s); sheet_refresh(sht, x, y, x + l * 8, y + 16); } return; }
- 当在中文(或日文)界面下开始显示全角字符的第2个字节时,refresh的范围会从
x-8
开始,其他的部分保持不变。
- 当在中文(或日文)界面下开始显示全角字符的第2个字节时,refresh的范围会从
-
make
后用VMware运行:
- 这里没有在harib25h的基础上修改,而是在harib25g的基础上修改的,因此是日文模式。
2. 文件压缩(harib26b)
-
添加支持文件压缩的功能。
- 这里的文件压缩,指的是文件的解压缩,而不是压缩。
- 实现该功能后,压缩过的文件可以在OS内部自动解压,不需要使用压缩软件来进行解压缩。对于压缩过的文件,可以像未经压缩的文件一样直接使用。
- 之所以要增加这样的功能,是为了尽量让日文字库文件变小。nihongo.fnt的大小有142KB,但OSASK的jpn16v00.fnt只有56.7KB,这都是压缩的功能。因此,实现该功能以后,能够节省大约85KB的磁盘空间,这样可以编写更多的应用程序,以及不用使用ipl30.nas了(笑)。
-
选择何种压缩格式
- 世界上有很多种压缩格式(.zip、.cab等),有的格式压缩率很好,但是解压缩的时间长,有的格式压缩率不理想,但是解压缩速度却很快。
- 解压缩程序的大小也需要考虑。即便压缩率极好,可以将142KB的nihongo.fnt压缩到1KB,但是加压缩程序却需要150KB,这是得不偿失的。
- 这里,采用书上提供的格式
.tek
,.tek格式在压缩率和解压缩时间的平衡性不错。
-
显然,讲解tek的解压缩程序代码就跑题了,而且编写tek的程序代码不知道要写到什么时候,因此,这里直接将tek的解压缩程序整合到此OS中。
-
edimg.exe的源代码是公开的,且tek相关的部分也在edimg.exe的源代码中。tek的相关代码位于autodec_.c这个文件中。直接将这个文件复制到harib26b目录的tek/uautodec_c.c就可以了。
-
删除uautodec_c.c中没有用处的autodecomp函数,并增加必要的韩式tek_getsize和tek_decomp,同时将加工过的程序保存为tek.c(在tek/和haribote/中同时放入tek.c)。
-
tek.c中tek_getsize和tek_decomp函数:
int tek_getsize(unsigned char *p) { static char header[15] = { 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x4f, 0x53, 0x41, 0x53, 0x4b, 0x43, 0x4d, 0x50 }; int size = -1; if (memcmp(p + 1, header, 15) == 0 && (*p == 0x83 || *p == 0x85 || *p == 0x89)) { p += 16; size = tek_getnum_s7s(&p); } return size; } /* 注:memcmp和strcmp差不多,这个函数忽略字符串中的0并一直比较到指定的15个字符为止 */ int tek_decomp(unsigned char *p, char *q, int size) { int err = -1; if (*p == 0x83) { err = tek_decode1(size, p, q); } else if (*p == 0x85) { err = tek_decode2(size, p, q); } else if (*p == 0x89) { err = tek_decode5(size, p, q); } if (err != 0) { return -1; /* 失败 */ } return 0; /* 成功 */ }
- 上述代码看起来是有难度的,因为tek_getnum_s7s函数和tek_decode[123]函数具体的执行流程是未知的。
- 根据书上提示,tek_getsize是用来判断文件是否符合tek格式,如果是合法的tek格式,那么将该文件解压后的大小返回,如果不合法,返回-1。tek_decomp用来完成解压缩操作。
- 还有,就是将malloc和free分别改成了memman_alloc_4k和memman_free_4k。
-
利用tek_getsize和tek_decomp函数,编写file_loadfile2函数(file.c中):
char *file_loadfile2(int clustno, int *psize, int *fat) { int size = *psize, size2; struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR; char *buf, *buf2; buf = (char *) memman_alloc_4k(memman, size); file_loadfile(clustno, size, buf, fat, (char *) (ADR_DISKIMG + 0x003e00)); if (size >= 17) { size2 = tek_getsize(buf); if (size2 > 0) { /* 使用tek格式压缩的文件 */ buf2 = (char *) memman_alloc_4k(memman, size2); tek_decomp(buf, buf2, size2); memman_free_4k(memman, (int) buf, size); buf = buf2; *psize = size2; } } return buf; }
- tek_getsize和tek_decomp要在bootpack.h中声明。
- 首先,用memman_alloc_4k申请必要的内存空间(也就是从内存中直接读出来的文件的大小),然后用file_loadfile函数将文件的内容载入内存。如果文件的大小超过17字节则表示这个文件极有可能是tek格式的文件(tek文件必须有一个用于识别格式的头文件,这个头文件的大小至少是17字节)。然后调用tek_getsize判断该文件是否是tek格式,如果是,则为解压后的文件分配内存空间并执行解压缩操作,然后释放解压缩前的文件的内存空间。函数返回值是解压缩后的文件的内存地址。
-
修改nihonggo.fnt载入部分:
void HariMain(void) { …… /* nihongo.fnt的载入 */ 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) { i = finfo->size; nihongo = file_loadfile2(finfo->clustno, &i, fat); } else { nihongo = (unsigned char *) memman_alloc_4k(memman, 16 * 256 + 32 * 94 * 47); 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; } } *((int *) 0x0fe8) = (int) nihongo; memman_free_4k(memman, (int) fat, 4 * 2880); }
- 这里只需要注意一下变量i的作用是为了获取解压缩后文件的大小并且不改变原先finfo->size。
- 其实,从代码上看,如果nihongo.fnt不被压缩,程序照样正常运行。
-
对nihongo.fnt的压缩过程需要在Windows下进行:
- 首先,将bim2bin.exe和t5lzma.exe(这两个文件都在z_tools文件夹下)赋值到目录nihongo下,当前目录是harib26b/nihongo。
- 然后将143KB的nihongo.fnt重命名成nihongo.org。
- 然后在当前目录下打开命令行,输入命令
bim2bin -osacmp in:nihongo.org out:nihongo.fnt
。 - 然后就生成了经过压缩后的nihongo.fnt,大约59KB,不知道为啥和书上说将56.6KB有点差别,貌似对于日文显示没啥问题,所以忽略吧。
- 如果输入命令
bim2bin -osacmp in:nihongo.org out:nihongo.fnt -tek2
可以将其压缩成为tek2格式,不指定选项或者指定选项为tek5,那么压缩成为tk5格式。
-
make full
后用VMware运行:
- 成功!
-
继续