(1)从零开始的操作系统开发日记

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_24328101/article/details/52004843

果然回家了几天加上天气热,就会变得怠惰呢【あなた、怠惰ですね】


继续阅读笔记博客的记录:

  1. 软盘中地址计算公式=clustno*512+0x003e00
  2. P406,API直接注册在IDT【中断向量表】中来固定地址 ,使用类似BIOS的方式,把功能号存到edx,然后调用底层函数
  3. P407,可修改IDT的设置禁止CPU禁止中断
  4. P418谜之偷懒的解决方案:随便找个内存的位置用来通讯,传递参数D21区分程序栈和系统栈
  5. 强制结束程序=将段寄存器全部赋值为系统用的段地址,并强制返回到startapp时的esp
  6. P519 关于色号计算,一个颜色分0-255个阶,作者取6个,所以255/5=51【整除】,这样一个色分别有0,51,102…255,6个阶,然后三色混合,排列组合得6*6*6=216色,table2里的颜色从16号开始【因为之前定义了简单的16色,0-15色号被占用】,所以色号的计算公式为:16+R/51+G/51*6+B/51*36
  7. P521-522的算法:作者这里使用了特别的技巧去扩展216色的表现力,CG界在当年也有用类似的技巧(スタープラチナ,カスタム,1996)
    (同級生2,ELF,1995)
    【以上图片引用自知乎相关问题日本 Galgame 的主流 CG 画风经历过哪几次变迁?
    真的很难想象这是16色的表现力。
    不闲扯太多,作者提供的算法的核心不难,一图流看懂:《30天自制操作系统P521》,问题在于如何优雅实现。这里我看了一下源码,大概的给一个思路:

根据作者的定义,RGB各有6阶,通过这种渐变的算法可以扩展到21阶,在128*128的画板上,作者对坐标进行(x*2)*21/256的转换,建立坐标与21阶色号的对应关系,于是可以确定128*128里任一点属于21色阶里的哪一阶。但是大家稍微留心就可以注意到,作者是以2*2的格子作为混色的基本单位的,所以在确定色阶后,还要确定坐标在这个2*2里的相对位置,以0,1两个阶的颜色混合为例,则:

00,10,10,11,11
00,00,01,01,11

所以就有了源码中的常量表,用来表示当前的坐标应该是一个混色的基本单位里的哪一个位置。
我个人猜测,其实这个算法的精华应该是常量表的确定吧,我觉得这个算法应该可以给出一个很严格很优雅的证明,从而得到这个式子来简化大量的if的,并且很有可能是计算机图形学那边的一些经典算法。我没有精力去给出严格证明,因为感觉把过多的精力投入到这些太过细节的地方不算特别好,这个算法能大致弄懂开拓一下视野就好了。
附:相关源码以及效果图

int api_openwin(char *buf, int xsiz, int ysiz, int col_inv, char *title);
void api_initmalloc(void);
char *api_malloc(int size);
void api_refreshwin(int win, int x0, int y0, int x1, int y1);
void api_linewin(int win, int x0, int y0, int x1, int y1, int col);
int api_getkey(int mode);
void api_end(void);

unsigned char rgb2pal(int r, int g, int b, int x, int y);

void HariMain(void)
{
    char *buf;
    int win, x, y;
    api_initmalloc();
    buf = api_malloc(144 * 164);
    win = api_openwin(buf, 144, 164, -1, "color2");
    for (y = 0; y < 128; y++) {
        for (x = 0; x < 128; x++) {
            buf[(x + 8) + (y + 28) * 144] = rgb2pal(x * 2, y * 2, 0, x, y);
        }
    }
    api_refreshwin(win, 8, 28, 136, 156);
    api_getkey(1); /* 等待按下任意键 */
    api_end();
}

unsigned char rgb2pal(int r, int g, int b, int x, int y)
{
    static int table[4] = { 3, 1, 0, 2 };
    int i;
    x &= 1; /* 判断奇偶性 */
    y &= 1;
    i = table[x + y * 2];   /* 查询中间色的常量表 */
    r = (r * 21) / 256; /* 返回0-20的扩展色阶 */
    g = (g * 21) / 256;
    b = (b * 21) / 256;
    r = (r + i) / 4;    /*返回0-5的原始色阶 */
    g = (g + i) / 4;    
    b = (b + i) / 4;
    return 16 + r + g * 6 + b * 36;
}

模拟器测试结果

没有更多推荐了,返回首页