haribote file.c 文件读取程序阅读注释

Posted 资质平庸的程序员

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了haribote file.c 文件读取程序阅读注释相关的知识,希望对你有一定的参考价值。

[ 1] haribote ipl09.nas 引导程序阅读注释
[ 2] haribote asmhead.nas 从实模式进入保护模式程序阅读注释
[ 3] haribote dsctbl.c 设置GDT和IDT程序阅读注释
[ 4] haribote memory.c 内存管理程序阅读注释
[ 5] haribote int.c 可编程中断控制器(PIC)初始配置程序阅读注释
[ 6] haribote timer.c 定时器管理程序阅读注释
[ 7] haribote fifo.c 循环队列管理程序阅读注释
[ 8] haribote keyboard.c 键盘管理程序阅读注释
[ 9] haribote mouse.c 鼠标管理程序阅读注释
[10] haribote graphic.c 由像素点阵转换显卡画面信息程序阅读注释
[11] haribote sheet.c 窗口画面及显示管理程序阅读注释
[12] haribote window.c 自制窗口画面信息程序阅读注释

篇幅较长,可通过浏览器的搜索功能(Ctrl + f)搜索函数名了解相应函数的实现机制,如 file_loadfile。

[13]haribote file.c 文件读取程序阅读注释

file.c
/* file.c, 文件读取程序接口 */

/* 粗略理解haribote文件系统。
 * 
 * 回看ipl09.nas,FAT12格式软盘内容大体如下。
 * ---------------------------
 * |保留区域|FAT区域|数据区域|
 * ---------------------------
 * 保留区域共1个扇区(0柱面,0磁头,1扇区),包含了对FAT12总体描述和haribote启动代码;
 * FAT区域共有2个FAT(第2个是第1个的备份),每个占9个扇区(0柱面,0磁头,[2,19]扇区)。
 * 
 * 回看asmhead.nas,整个FAT12软盘被加载到内存地址空间[0x100000, 0x267fff]所对应的
 * 内存段中——软盘映像。*/

/* 根据作者在书中的提示,将FAT12格式软盘内容粗略细化。
 * --------------------------------------------
 * |保留区域|FAT区域|文件信息区域|文件内容区域
 * --------------------------------------------
 * 1        2       20           34
 * 保留区域: 1扇区;
 * FAT区域: [2, 20)扇区,用于索引文件大于512字节部分内容;
 * 文件信息区域: [20, 34)扇区,1个文件信息由 struct FILEINFO 结构体描述;
 * 文件内容: [34,...)扇区
 * 
 * 文件信息中的簇号(扇区号)clustno能够索引文件开始的512字节内容,  接下
 * 来512字节内容的索引为clustno=FAT[clustno]索引,...当clustno在FF8~FFF
 * 范围时,则表示文件内容结束。
 * 
 * 由簇号计算文件内容在软盘中偏移地址的公式可归纳为clustno*512+0x3e00h
 * 那么,文件内容在软盘映像中的地址=clustno * 512 + 0x3e00 + 0x00100000。
 *
 * FAT12各个区域所占大小跟FAT所在介质总大小有关。*/


#include "bootpack.h"

/* file_readfat,
 * 从软盘映像起始处img读取文件分配表即FAT到fat所指内存从。*/
void file_readfat(int *fat, unsigned char *img)

    int i, j = 0;

    /* FAT中的内容是经过压缩的: 用3个字节保存2个扇区号, 即
     * 1个扇区号占用1.5字节;根据FAT压缩规律将FAT中的扇区号
     * 信息读取到fat所指内存中。FAT中扇区号的压缩规律为
     * 123 456 --> 23 61 45 即
     * 将两个需4字节保存的扇区号0x123和0x456压缩后用3字节保
     * 存。以下程序按照该规律解压FAT到fat所指内存中。*/
    for (i = 0; i < 2880; i += 2) 
        fat[i + 0] = (img[j + 0]      | img[j + 1] << 8) & 0xfff;
        fat[i + 1] = (img[j + 1] >> 4 | img[j + 2] << 4) & 0xfff;
        j += 3;
    
/* 关于2880: FAT最多保存2880个扇区号(1.44Mb软盘共2880个扇区)。FAT
 * 被压缩后,FAT最多占用2880*1.5字节软盘即不到9扇区,这是在保留区域
 * (ipl09.nas)中填写FAT占9扇区的来源。*/
    return;


/* file_loadfile,
 * 从软盘映像(缓存软盘内容内存段)img中从读取size字节文件内容
 * 到buf所指内存段,clustno为文件的起始簇号,fat所指内存段为FAT。*/
void file_loadfile(int clustno, int size, char *buf, int *fat, char *img)

    int i;

    /* 文件的起始簇号clustno在文件信息中,之后簇号为
     * FAT[clustno]。第n个clustno*512将索引文件第n扇区内容。*/
    for (;;) 
        if (size <= 512) 
            for (i = 0; i < size; i++) 
               buf[i] = img[clustno * 512 + i];
            
            break;
        
        for (i = 0; i < 512; i++) 
            buf[i] = img[clustno * 512 + i];
        
        size -= 512;
        buf += 512;
        clustno = fat[clustno];
    
    return;


/* file_search,
 * 在finfo所指软盘映像的文件信息区域(共max个文件信息)中搜索name所指
 * 目标命名文件,若搜索成功则返回目标文件的文件信息首地址,失败则返回0。*/
struct FILEINFO *file_search(char *name, struct FILEINFO *finfo, int max)

    int i, j;
    char s[12];

    /* s用于保存文件名,文件名不足12字符补齐空格 */
    for (j = 0; j < 11; j++) 
        s[j] = ' ';
    
    
    j = 0;
    for (i = 0; name[i] != 0; i++) 
        if (j >= 11)  return 0; /* 文件名太长则不予处理 */ 

        /* 保证文件名(不含后缀)占8字符 */
        if (name[i] == '.' && j <= 8) 
            j = 8;
        /* 将name所指文件名拷贝到s所指栈内存中 */
         else 
            s[j] = name[i];
            if ('a' <= s[j] && s[j] <= 'z') 
                /* 将文件名转为大写字符 */
                s[j] -= 0x20;
             
            j++;
        
    
    /* 软盘映像共max个文件信息 */
    for (i = 0; i < max; ) 
        /* 此处应该是finfo[i]->name == 0x00。当name第
         * 一字节为0x00时表文件信息区域再无文件信息。*/
        if (finfo->name[0] == 0x00) 
            break;
        
        /* 若当前文件信息非目录且为type低3位所表征文件,若在
         * 软盘映像中找到目标文件名则返回其文件信息首地址。*/
        if ((finfo[i].type & 0x18) == 0) 
            for (j = 0; j < 11; j++) 
                if (finfo[i].name[j] != s[j]) 
                    goto next;
                
            
            return finfo + i;
        
next:
        i++;
    
    return 0; /* 目标文件不在软盘映像中则返回0 */


/* file_loadfile2,
 * 读取起始簇号为clustno文件内容,共度*psize字节。该函数返回
 * 所读文件内容在内存中的首地址和成功读取的字节数(*psize中)。*/
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);

    /* 从软盘映像中读取指定起始簇号文件的size字节内容到buf中,clustno * 512 + 
     * ADR_DISKIMG + 0x003e00得到clustno对应512字节文件内容在软盘映像中的地址 */
    file_loadfile(clustno, size, buf, fat, (char *) (ADR_DISKIMG + 0x003e00));

    /* 为能在软盘映像中存放更多文件, haribote软盘映像支持文件压缩功能,
     * 即将文件内容压缩后存储。此处解压所读取到的文件内容, 然后释放掉
     * buf原指向的包含压缩数据的内存段,并将解压后文件大小赋给出参, 最
     * 后返回解压文件数据在内存中首地址。*/
    if (size >= 17)  /* tek压缩文件开头带17字节用于标识tek文件 */
        size2 = tek_getsize(buf);
        if (size2 > 0) 
            buf2 = (char *) memman_alloc_4k(memman, size2);
            tek_decomp(buf, buf2, size2);
            memman_free_4k(memman, (int) buf, size);
            buf = buf2;
            *psize = size2;
        
    
/* tek是作者自制的解压缩算法,对"压缩率","解压速度"以及"解压程序大小"
 * 有一定权衡。看作者对压缩特性的分析和认识,tek解压缩算法应当相当优
 * 秀,不过此文还不打算阅读该解压缩算法相关细节。*/
    return buf;

bootpack.h
/* ... */

/* file.c */
/* struct FILEINFO,
 * 描述(FAT文件系统)文件信息的结构体。 */
struct FILEINFO 
/* name, 文件名,name[0]=0x00时表无文件名,
 * name[0]=0x05时表明文件已被删除,文件名
 * 不足8字节用空格补齐;
 * ext,文件扩展名,不足3字节用空格补齐;
 * type为文件属性,0x20-普通文件,0x01-只读文件,
 * 0x02-隐藏文件,0x04-系统文件,0x10-目录。*/
    unsigned char name[8], ext[3], type;
    char reserve[10]; /* 保留未用 */
/* time,文件时间;date,文件日期;clustno,文
 * 件内容起始簇号(扇区号);size,文件大小。*/
    unsigned short time, date, clustno;
    unsigned int size;
;
void file_readfat(int *fat, unsigned char *img);
void file_loadfile(int clustno, int size, char *buf, int *fat, char *img);
struct FILEINFO *file_search(char *name, struct FILEINFO *finfo, int max);
char *file_loadfile2(int clustno, int *psize, int *fat);

/* ... */

以上是关于haribote file.c 文件读取程序阅读注释的主要内容,如果未能解决你的问题,请参考以下文章

haribote mouse.c 鼠标管理程序阅读注释

haribote bootpack.c 主任务程序代码阅读注释

haribote naskfunc.nas 汇编函数接口程序阅读注释

haribote window.c 自制窗口画面信息程序阅读注释

haribote sheet.c 窗口画面及显示管理程序阅读注释

haribote dsctbl.c 设置GDT和IDT程序阅读注释