たなしょのメモ

日々勉強していることをつらつらと

OS作成奮闘記day41

さらに日本語表示を改造していこうと思います。
graphic.c

void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s)
{
    extern char hankaku[4096];
    struct TASK *task = task_now();
    char *nihongo = (char *) *((int *) 0x0fe8), *font;
    int k, t;
    
    if (task->langmode == 0) {
        for (; *s != 0x00; s++) {
            putfont8(vram, xsize, x, y, c, hankaku + *s * 16);
            x += 8;
        }
    }
    if (task->langmode == 1) {
        for (; *s != 0x00; s++) {
            if (task->langbyte1 == 0) {
                if ((0x81 <= *s && *s <= 0x9f) || (0xe0 <= *s && *s <= 0xfc)) {
                    task->langbyte1 = *s;
                } else {
                    putfont8(vram, xsize, x, y, c, nihongo + *s * 16);
                }
            } else {
                if (0x81 <= task->langbyte1 && task->langbyte1 <= 0x9f) {
                    k = (task->langbyte1 - 0x81) * 2;
                } else {
                    k = (task->langbyte1 - 0xe0) * 2 + 62;
                }
                if (0x40 <= *s && *s <= 0x7e) {
                    t = *s - 0x40;
                } else if (0x80 <= *s && *s <= 0x9e) {
                    t = *s - 0x80 + 63;
                } else {
                    t = *s - 0x9f;
                    k++;
                }
                task->langbyte1 = 0;
                font = nihongo + 256 * 16 + (k * 94 + t) * 32;
                putfont8(vram, xsize, x - 8, y, c, font     ); /* 左半分 */
                putfont8(vram, xsize, x    , y, c, font + 16); /* 右半分 */
            } 
            x += 8;
        }
    }
    return;
}

bootpack.h

struct TASK {
    int sel, flags; /* selはGDTの番号のこと */
    int level, priority;
    struct FIFO32 fifo;
    struct TSS32 tss;
    struct SEGMENT_DESCRIPTOR ldt[2];
    struct CONSOLE *cons;
    int ds_base, cons_stack;
    struct FILEHANDLE *fhandle;
    int *fat;
    char *cmdline;
    unsigned char langmode, langbyte1;
};

console.c

void console_task(struct SHEET *sheet, int memtotal)
{
    struct TASK *task = task_now();
    struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
    int i, *fat = (int *) memman_alloc_4k(memman, 4 * 2880);
    struct CONSOLE cons;
    struct FILEHANDLE fhandle[8];
    char cmdline[30];
    unsigned char *nihongo = (char *) *((int *) 0x0fe8);

    cons.sht = sheet;
    cons.cur_x =  8;
    cons.cur_y = 28;
    cons.cur_c = -1;
    task->cons = &cons;
    task->cmdline = cmdline;

    if (cons.sht != 0) {
        cons.timer = timer_alloc();
        timer_init(cons.timer, &task->fifo, 1);
        timer_settime(cons.timer, 50);
    }
    file_readfat(fat, (unsigned char *) (ADR_DISKIMG + 0x000200));
    for (i = 0; i < 8; i++) {
        fhandle[i].buf = 0;    /* 未使用マーク */
    }
    task->fhandle = fhandle;
    task->fat = fat;
    if (nihongo[4096] != 0xff) {    /* 日本語フォントファイルを読み込めたか? */
        task->langmode = 1;
    } else {
        task->langmode = 0;
    }
    task->langbyte1 = 0;
void cons_newline(struct CONSOLE *cons)
{
    int x, y;
    struct SHEET *sheet = cons->sht;
    struct TASK *task = task_now();
    if (cons->cur_y < 28 + 112) {
        cons->cur_y += 16; /* 次の行へ */
    } else {
        /* スクロール */
        if (sheet != 0) {
            for (y = 28; y < 28 + 112; y++) {
                for (x = 8; x < 8 + 240; x++) {
                    sheet->buf[x + y * sheet->bxsize] = sheet->buf[x + (y + 16) * sheet->bxsize];
                }
            }
            for (y = 28 + 112; y < 28 + 128; y++) {
                for (x = 8; x < 8 + 240; x++) {
                    sheet->buf[x + y * sheet->bxsize] = COL8_000000;
                }
            }
            sheet_refresh(sheet, 8, 28, 8 + 240, 28 + 128);
        }
    }
    cons->cur_x = 8;
    if (task->langmode == 1 && task->langbyte1 != 0) {
        cons->cur_x = 16;
    }
    return;
}
int cmd_app(struct CONSOLE *cons, int *fat, char *cmdline)
{
    struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
    struct FILEINFO *finfo;
    char name[18], *p, *q;
    struct TASK *task = task_now();
    int i, segsiz, datsiz, esp, dathrb;
    struct SHTCTL *shtctl;
    struct SHEET *sht;

    /* コマンドラインからファイル名を生成 */
    for (i = 0; i < 13; i++) {
        if (cmdline[i] <= ' ') {
            break;
        }
        name[i] = cmdline[i];
    }
    name[i] = 0; /* とりあえずファイル名の後ろを0にする */

    /* ファイルを探す */
    finfo = file_search(name, (struct FILEINFO *) (ADR_DISKIMG + 0x002600), 224);
    if (finfo == 0 && name[i - 1] != '.') {
        /* 見つからなかったので後ろに".HRB"をつけてもう一度探してみる */
        name[i    ] = '.';
        name[i + 1] = 'H';
        name[i + 2] = 'R';
        name[i + 3] = 'B';
        name[i + 4] = 0;
        finfo = file_search(name, (struct FILEINFO *) (ADR_DISKIMG + 0x002600), 224);
    }

    if (finfo != 0) {
        /* ファイルが見つかった場合 */
        p = (char *) memman_alloc_4k(memman, finfo->size);
        file_loadfile(finfo->clustno, finfo->size, p, fat, (char *) (ADR_DISKIMG + 0x003e00));
        if (finfo->size >= 36 && strncmp(p + 4, "Hari", 4) == 0 && *p == 0x00) {
            segsiz = *((int *) (p + 0x0000));
            esp    = *((int *) (p + 0x000c));
            datsiz = *((int *) (p + 0x0010));
            dathrb = *((int *) (p + 0x0014));
            q = (char *) memman_alloc_4k(memman, segsiz);
            task->ds_base = (int) q;
            set_segmdesc(task->ldt + 0, finfo->size - 1, (int) p, AR_CODE32_ER + 0x60);
            set_segmdesc(task->ldt + 1, segsiz - 1,      (int) q, AR_DATA32_RW + 0x60);
            for (i = 0; i < datsiz; i++) {
                q[esp + i] = p[dathrb + i];
            }
            start_app(0x1b, 0 * 8 + 4, esp, 1 * 8 + 4, &(task->tss.esp0));
            shtctl = (struct SHTCTL *) *((int *) 0x0fe4);
            for (i = 0; i < MAX_SHEETS; i++) {
                sht = &(shtctl->sheets0[i]);
                if ((sht->flags & 0x11) == 0x11 && sht->task == task) {
                    /* アプリが開きっぱなしにした下じきを発見 */
                    sheet_free(sht);    /* 閉じる */
                }
            }
            for (i = 0; i < 8; i++) {    /* クローズしてないファイルをクローズ */
                if (task->fhandle[i].buf != 0) {
                    memman_free_4k(memman, (int) task->fhandle[i].buf, task->fhandle[i].size);
                    task->fhandle[i].buf = 0;
                }
            }
            timer_cancelall(&task->fifo);
            memman_free_4k(memman, (int) q, segsiz);
            task->langbyte1 = 0;
        } else {
            cons_putstr0(cons, ".hrb file format error.\n");
        }
        memman_free_4k(memman, (int) p, finfo->size);
        cons_newline(cons);
        return 1;
    }
    /* ファイルが見つからなかった場合 */
    return 0;
}

日本語を表示をさらにさらに改造していきます。
ipl20.nas(基本的にipl10.nasと一緒です)

CYLS    EQU       20             ; どこまで読み込むか

haribote/Makefile

OBJS_BOOTPACK = bootpack.obj naskfunc.obj hankaku.obj graphic.obj dsctbl.obj \
                int.obj fifo.obj keybord.obj mouse.obj memory.obj sheet.obj timer.obj \
                mtask.obj window.obj console.obj file.obj

TOOLPATH = ..\..\z_tools\\

INCPATH  = ..\..\z_tools\haribote\\

MAKE     = $(TOOLPATH)make.exe -r
NASK     = $(TOOLPATH)nask.exe
CC1      = $(TOOLPATH)cc1.exe -I$(INCPATH) -Os -Wall -quiet
GAS2NASK = $(TOOLPATH)gas2nask.exe -a
OBJ2BIM  = $(TOOLPATH)obj2bim.exe
MAKEFONT = $(TOOLPATH)makefont.exe
BIN2OBJ  = $(TOOLPATH)bin2obj
BIM2HRB  = $(TOOLPATH)bim2hrb.exe
RULEFILE = ..\haribote.rul
EDIMG    = $(TOOLPATH)edimg.exe
IMGTOL   = $(TOOLPATH)imgtol.com
GOLIB    = $(TOOLPATH)golib00.exe
COPY     = cmd.exe /C copy
DEL      = rm -f

# default operation

default :
    $(MAKE) ipl20.bin
    $(MAKE) haribote.sys

# file making rule

ipl20.bin : ipl20.nas Makefile
    $(NASK) ipl20.nas ipl20.bin ipl20.lst

asmhead.bin : asmhead.nas Makefile
    $(NASK) asmhead.nas asmhead.bin asmhead.lst

hankaku.bin : hankaku.txt Makefile
    $(MAKEFONT) hankaku.txt hankaku.bin

hankaku.obj : hankaku.bin Makefile
    $(BIN2OBJ) hankaku.bin hankaku.obj _hankaku

bootpack.bim : $(OBJS_BOOTPACK) Makefile
    $(OBJ2BIM) @$(RULEFILE) out:bootpack.bim stack:3136k map:bootpack.map \
        $(OBJS_BOOTPACK)
# 3MB+64KB=3136KB

bootpack.hrb : bootpack.bim Makefile
    $(BIM2HRB) bootpack.bim bootpack.hrb 0

haribote.sys : asmhead.bin bootpack.hrb Makefile
    cat asmhead.bin bootpack.hrb > haribote.sys

# rules

%.gas : %.c bootpack.h Makefile
    $(CC1) -o $*.gas $*.c

%.nas : %.gas Makefile
    $(GAS2NASK) $*.gas $*.nas

%.obj : %.nas Makefile
    $(NASK) $*.nas $*.obj $*.lst

# command

clean :
    -$(DEL) asmhead.bin
    -$(DEL) hankaku.bin
    -$(DEL) *.lst
    -$(DEL) *.obj
    -$(DEL) *.map
    -$(DEL) *.bim
    -$(DEL) *.hrb

src_only :
    $(MAKE) clean
    -$(DEL) ipl20.bin
    -$(DEL) haribote.sys

graphic.c

void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s)
{
    extern char hankaku[4096];
    struct TASK *task = task_now();
    char *nihongo = (char *) *((int *) 0x0fe8), *font;
    int k, t;
    
    if (task->langmode == 0) {
        for (; *s != 0x00; s++) {
            putfont8(vram, xsize, x, y, c, hankaku + *s * 16);
            x += 8;
        }
    }
    if (task->langmode == 1) {
        for (; *s != 0x00; s++) {
            if (task->langbyte1 == 0) {
                if ((0x81 <= *s && *s <= 0x9f) || (0xe0 <= *s && *s <= 0xfc)) {
                    task->langbyte1 = *s;
                } else {
                    putfont8(vram, xsize, x, y, c, nihongo + *s * 16);
                }
            } else {
                if (0x81 <= task->langbyte1 && task->langbyte1 <= 0x9f) {
                    k = (task->langbyte1 - 0x81) * 2;
                } else {
                    k = (task->langbyte1 - 0xe0) * 2 + 62;
                }
                if (0x40 <= *s && *s <= 0x7e) {
                    t = *s - 0x40;
                } else if (0x80 <= *s && *s <= 0x9e) {
                    t = *s - 0x80 + 63;
                } else {
                    t = *s - 0x9f;
                    k++;
                }
                task->langbyte1 = 0;
                font = nihongo + 256 * 16 + (k * 94 + t) * 32;
                putfont8(vram, xsize, x - 8, y, c, font     ); /* 左半分 */
                putfont8(vram, xsize, x    , y, c, font + 16); /* 右半分 */
            } 
            x += 8;
        }
    }
    if (task->langmode == 2) {
        for (; *s != 0x00; s++) {
            if (task->langbyte1 == 0) {
                if (0x81 <= *s && *s <= 0xfe) {
                    task->langbyte1 = *s;
                } else {
                    putfont8(vram, xsize, x, y, c, nihongo + *s * 16);
                }
            } else {
                k = task->langbyte1 - 0xa1;
                t = *s - 0xa1;
                task->langbyte1 = 0;
                font = nihongo + 256 * 16 + (k * 94 + t) * 32;
                putfont8(vram, xsize, x - 8, y, c, font     ); /* 左半分 */
                putfont8(vram, xsize, x    , y, c, font + 16); /* 右半分 */
            }
            x += 8;
        }
    }
    return;
}

console.c

void cmd_langmode(struct CONSOLE *cons, char *cmdline)
{
    struct TASK *task = task_now();
    unsigned char mode = cmdline[9] - '0';
    if (mode <= 2) {
        task->langmode = mode;
    } else {
        cons_putstr0(cons, "mode number error.\n");
    }
    cons_newline(cons);
    return;
}
 } else if (edx == 26) {
        i = 0;
        for (;;) {
            *((char *) ebx + ds_base + i) =  task->cmdline[i];
            if (task->cmdline[i] == 0) {
                break;
            }
            if (i >= ecx) {
                break;
            }
            i++;
        }
        reg[7] = i;
    } else if (edx == 27) {
        reg[7] = task->langmode;
    }
    return 0;
}

api027.nas

[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[BITS 32]
[FILE "api027.nas"]

        GLOBAL  _api_getlang

[SECTION .text]

_api_getlang:       ; int api_getlang(void);
        MOV     EDX,27
        INT     0x40
        RET

apilib/Makefile

OBJS_API =  api001.obj api002.obj api003.obj api004.obj api005.obj api006.obj \
            api007.obj api008.obj api009.obj api010.obj api011.obj api012.obj \
            api013.obj api014.obj api015.obj api016.obj api017.obj api018.obj \
            api019.obj api020.obj api021.obj api022.obj api023.obj api024.obj \
            api025.obj api026.obj api027.obj alloca.obj

apilib.h

int api_getlang(void);

chklang/Makefile

APP      = chklang
STACK    = 1k
MALLOC   = 0k

include ../app_make.txt

chklang.c

#include "apilib.h"

void HariMain(void)
{
    int langmode = api_getlang();
    static char s1[23] = {   /* 日本語シフトJISモード */
        0x93, 0xfa, 0x96, 0x7b, 0x8c, 0xea, 0x83, 0x56, 0x83, 0x74, 0x83, 0x67,
        0x4a, 0x49, 0x53, 0x83, 0x82, 0x81, 0x5b, 0x83, 0x68, 0x0a, 0x00
    };
    static char s2[17] = {   /* 日本語EUCモード */
        0xc6, 0xfc, 0xcb, 0xdc, 0xb8, 0xec, 0x45, 0x55, 0x43, 0xa5, 0xe2, 0xa1,
        0xbc, 0xa5, 0xc9, 0x0a, 0x00
    };
    if (langmode == 0) {
        api_putstr0("English ASCII mode\n");
    }
    if (langmode == 1) {
        api_putstr0(s1);
    }
    if (langmode == 2) {
        api_putstr0(s2);
    }
    api_end();
}

Makfile

TOOLPATH = ..\..\z_tools\\

INCPATH  = ..\..\z_tools\haribote\\

MAKE     = $(TOOLPATH)make.exe -r
EDIMG    = $(TOOLPATH)edimg.exe
IMGTOL   = $(TOOLPATH)imgtol.com
GOLIB    = $(TOOLPATH)golib00.exe
COPY     = cmd.exe /C copy
DEL      = rm -f

# default operation

default :
    $(MAKE) haribote.img

# file making rule

haribote.img : haribote/ipl20.bin haribote/haribote.sys Makefile \
        a/a.hrb hello3/hello3.hrb hello4/hello4.hrb hello5/hello5.hrb \
        winhelo/winhelo.hrb winhelo2/winhelo2.hrb winhelo3/winhelo3.hrb \
        star1/star1.hrb stars/stars.hrb stars2/stars2.hrb \
        lines/lines.hrb walk/walk.hrb noodle/noodle.hrb \
        beepdown/beepdown.hrb color/color.hrb color2/color2.hrb \
        sosu/sosu.hrb sosu2/sosu2.hrb sosu3/sosu3.hrb \
        typeipl/typeipl.hrb type/type.hrb iroha/iroha.hrb \
        chklang/chklang.hrb
    $(EDIMG)   imgin:../../z_tools/fdimg0at.tek \
        wbinimg src:haribote/ipl20.bin len:512 from:0 to:0 \
        copy from:haribote/haribote.sys to:@: \
        copy from:haribote/ipl20.nas to:@: \
        copy from:make.bat to:@: \
        copy from:a/a.hrb to:@: \
        copy from:hello3/hello3.hrb to:@: \
        copy from:hello4/hello4.hrb to:@: \
        copy from:hello5/hello5.hrb to:@: \
        copy from:winhelo/winhelo.hrb to:@: \
        copy from:winhelo2/winhelo2.hrb to:@: \
        copy from:winhelo3/winhelo3.hrb to:@: \
        copy from:star1/star1.hrb to:@: \
        copy from:stars/stars.hrb to:@: \
        copy from:stars2/stars2.hrb to:@: \
        copy from:lines/lines.hrb to:@: \
        copy from:walk/walk.hrb to:@: \
        copy from:noodle/noodle.hrb to:@: \
        copy from:beepdown/beepdown.hrb to:@: \
        copy from:color/color.hrb to:@: \
        copy from:color2/color2.hrb to:@: \
        copy from:sosu/sosu.hrb to:@: \
        copy from:sosu2/sosu2.hrb to:@: \
        copy from:sosu3/sosu3.hrb to:@: \
        copy from:typeipl/typeipl.hrb to:@: \
        copy from:type/type.hrb to:@: \
        copy from:iroha/iroha.hrb to:@: \
        copy from:chklang/chklang.hrb to:@: \
        copy from:euc.txt to:@: \
        copy from:nihongo/nihongo.fnt to:@: \
        imgout:haribote.img

# command

run :
    $(MAKE) haribote.img
    $(COPY) haribote.img ..\..\z_tools\qemu\fdimage0.bin
    $(MAKE) -C ..\..\z_tools\qemu

install :
    $(MAKE) haribote.img
    $(IMGTOL) w a: haribote.img

full :
    $(MAKE) -C haribote
    $(MAKE) -C apilib
    $(MAKE) -C a
    $(MAKE) -C hello3
    $(MAKE) -C hello4
    $(MAKE) -C hello5
    $(MAKE) -C winhelo
    $(MAKE) -C winhelo2
    $(MAKE) -C winhelo3
    $(MAKE) -C star1
    $(MAKE) -C stars
    $(MAKE) -C stars2
    $(MAKE) -C lines
    $(MAKE) -C walk
    $(MAKE) -C noodle
    $(MAKE) -C beepdown
    $(MAKE) -C color
    $(MAKE) -C color2
    $(MAKE) -C sosu
    $(MAKE) -C sosu2
    $(MAKE) -C sosu3
    $(MAKE) -C typeipl
    $(MAKE) -C type
    $(MAKE) -C iroha
    $(MAKE) -C chklang
    $(MAKE) haribote.img

run_full :
    $(MAKE) full
    $(COPY) haribote.img ..\..\z_tools\qemu\fdimage0.bin
    $(MAKE) -C ..\..\z_tools\qemu

install_full :
    $(MAKE) full
    $(IMGTOL) w a: haribote.img

run_os :
    $(MAKE) -C haribote
    $(MAKE) run

clean :
# 何もしない

src_only :
    $(MAKE) clean
    -$(DEL) haribote.img
    
clean_full :
    $(MAKE) -C haribote     clean
    $(MAKE) -C apilib       clean
    $(MAKE) -C a            clean
    $(MAKE) -C hello3       clean
    $(MAKE) -C hello4       clean
    $(MAKE) -C hello5       clean
    $(MAKE) -C winhelo      clean
    $(MAKE) -C winhelo2     clean
    $(MAKE) -C winhelo3     clean
    $(MAKE) -C star1        clean
    $(MAKE) -C stars        clean
    $(MAKE) -C stars2       clean
    $(MAKE) -C lines        clean
    $(MAKE) -C walk         clean   
    $(MAKE) -C noodle       clean
    $(MAKE) -C beepdown     clean
    $(MAKE) -C color        clean
    $(MAKE) -C color2       clean
    $(MAKE) -C sosu         clean
    $(MAKE) -C sosu2        clean
    $(MAKE) -C sosu3        clean
    $(MAKE) -C typeipl      clean
    $(MAKE) -C type         clean
    $(MAKE) -C iroha        clean
    $(MAKE) -C chklang      clean

src_only_full :
    $(MAKE) -C haribote     src_only
    $(MAKE) -C apilib       src_only
    $(MAKE) -C a            src_only
    $(MAKE) -C hello3       src_only
    $(MAKE) -C hello4       src_only
    $(MAKE) -C hello5       src_only
    $(MAKE) -C winhelo      src_only
    $(MAKE) -C winhelo2     src_only
    $(MAKE) -C winhelo3     src_only
    $(MAKE) -C star1        src_only
    $(MAKE) -C stars        src_only
    $(MAKE) -C stars2       src_only
    $(MAKE) -C lines        src_only
    $(MAKE) -C walk         src_only    
    $(MAKE) -C noodle       src_only
    $(MAKE) -C beepdown     src_only
    $(MAKE) -C color        src_only
    $(MAKE) -C color2       src_only
    $(MAKE) -C sosu         src_only
    $(MAKE) -C sosu2        src_only
    $(MAKE) -C sosu3        src_only
    $(MAKE) -C typeipl      src_only
    $(MAKE) -C type         src_only
    $(MAKE) -C iroha        src_only
    $(MAKE) -C chklang      src_only
    -$(DEL) haribote.img

refresh :
    $(MAKE) full
    $(MAKE) clean_full
    -$(DEL) haribote.img

実装過程
・ 890829f339cc2250a439d20258906562a52c6c0b