第29天 压缩与简单的应用程序

本文介绍了在操作系统中实现文件压缩、修复bug、标准函数、非矩形窗口、bball游戏、外形人游戏和Snake游戏的过程。重点是文件的tek压缩格式,用于节省磁盘空间。同时,修复了全角字符显示问题,并实现了tek解压缩功能,使得应用程序可以直接运行。最后,文章提到了一些未解决的问题和未来计划。
摘要由CSDN通过智能技术生成

第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开始,其他的部分保持不变。
  • 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运行:

    • 成功!
  • 继续

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值