(1)從零開始的操作系統開發日記

果然回家了幾天加上天氣熱,就會變得怠惰呢【あなた、怠惰ですね】


繼續閱讀筆記博客的記錄:

  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;
}

模擬器測試結果

發佈了28 篇原創文章 · 獲贊 12 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章