たなしょのメモ

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

OS作成奮闘記day36

xボタンを押したらウィンドウを閉じれるように改造します。
bootpack.c

else if (512 <= i && i <= 767) { /* マウスデータ */
                    if (mouse_decode(&mdec, i - 512) != 0) {
                        /* マウスカーソルの移動 */
                        mx += mdec.x;
                        my += mdec.y;
                        if (mx < 0) {
                            mx = 0;
                        }
                        if (my < 0) {
                            my = 0;
                        }
                        if (mx > binfo->scrnx - 1) {
                            mx = binfo->scrnx - 1;
                        }
                        if (my > binfo->scrny - 1) {
                            my = binfo->scrny - 1;
                        }
                        new_mx = mx;
                        new_my = my;
                        if ((mdec.btn & 0x01) != 0) {
                            /* 左ボタンを押している */
                            if (mmx < 0) {
                                /* 通常モードの場合 */
                                /* 上の下じきから順番にマウスが指している下じきを探す */
                                for (j = shtctl->top - 1; j > 0; j--) {
                                    sht = shtctl->sheets[j];
                                    x = mx - sht->vx0;
                                    y = my - sht->vy0;
                                    if (0 <= x && x < sht->bxsize && 0 <= y && y < sht->bysize) {
                                        if (sht->buf[y * sht->bxsize + x] != sht->col_inv) {
                                            sheet_updown(sht, shtctl->top - 1);
                                            if (sht != key_win) {
                                                keywin_off(key_win);
                                                key_win = sht;
                                                keywin_on(key_win);
                                            }
                                            if (3 <= x && x < sht->bxsize - 3 && 3 <= y && y < 21) {
                                                mmx = mx;   /* ウィンドウ移動モードへ */
                                                mmy = my;
                                                mmx2 = sht->vx0;
                                                new_wy = sht->vy0;
                                            }
                                            if (sht->bxsize - 21 <= x && x < sht->bxsize - 5 && 5 <= y && y < 19) {
                                                /* 「×」ボタンクリック */
                                                if ((sht->flags & 0x10) != 0) {      /* アプリが作ったウィンドウか? */
                                                    task = sht->task;
                                                    cons_putstr0(task->cons, "\nBreak(mouse) :\n");
                                                    io_cli();   /* 強制終了処理中にタスクが変わると困るから */
                                                    task->tss.eax = (int) &(task->tss.esp0);
                                                    task->tss.eip = (int) asm_end_app;
                                                    io_sti();
                                                } else {  /* コンソール */
                                                    task = sht->task;
                                                    io_cli();
                                                    fifo32_put(&task->fifo, 4);
                                                    io_sti();
                                                }
                                            }
                                            break;
                                    }
                                }
                            }
                        } else {

console.c

else {
            i = fifo32_get(&task->fifo);
            io_sti();
            if (i <= 1) { /* カーソル用タイマ */
                if (i != 0) {
                    timer_init(cons.timer, &task->fifo, 0); /* 次は0を */
                    if (cons.cur_c >= 0) {
                        cons.cur_c = COL8_FFFFFF;
                    }
                } else {
                    timer_init(cons.timer, &task->fifo, 1); /* 次は1を */
                    if (cons.cur_c >= 0) {
                        cons.cur_c = COL8_000000;
                    }
                }
                timer_settime(cons.timer, 50);
            }
            if (i == 2) {    /* カーソルON */
                cons.cur_c = COL8_FFFFFF;
            }
            if (i == 3) {    /* カーソルOFF */
                boxfill8(sheet->buf, sheet->bxsize, COL8_000000, cons.cur_x, cons.cur_y, cons.cur_x + 7, cons.cur_y + 15);
                cons.cur_c = -1;
            }
            if (i == 4) {    /* コンソールの「×」ボタンクリック */
                cmd_exit(&cons, fat);
            }

新しいコンソールを開いて実行してくれる「start」コマンドを実装してみます。
console.c

void cons_runcmd(char *cmdline, struct CONSOLE *cons, int *fat, int memtotal)
{
    if (strcmp(cmdline, "mem") == 0) {
        cmd_mem(cons, memtotal);
    } else if (strcmp(cmdline, "cls") == 0) {
        cmd_cls(cons);
    } else if (strcmp(cmdline, "dir") == 0) {
        cmd_dir(cons);
    } else if (strncmp(cmdline, "type ", 5) == 0) {
        cmd_type(cons, fat, cmdline);
    } else if (strcmp(cmdline, "exit") == 0) {
        cmd_exit(cons, fat);
    } else if (strncmp(cmdline, "start ", 6) == 0) {
        cmd_start(cons, cmdline, memtotal);
    } else if (cmdline[0] != 0) {
        if (cmd_app(cons, fat, cmdline) == 0) {
            /* コマンドではなく、アプリでもなく、さらに空行でもない */
            cons_putstr0(cons, "Bad command.\n\n");
        }
    }
    return;
}
void cmd_start(struct CONSOLE *cons, char *cmdline, int memtotal)
{
    struct SHTCTL *shtctl = (struct SHTCTL *) *((int *) 0x0fe4);
    struct SHEET *sht = open_console(shtctl, memtotal);
    struct FIFO32 *fifo = &sht->task->fifo;
    int i;
    sheet_slide(sht, 32, 4);
    sheet_updown(sht, shtctl->top);
    /* コマンドラインに入力された文字列を、一文字ずつ新しいコンソールに入力 */
    for (i = 6; cmdline[i] != 0; i++) {
        fifo32_put(fifo, cmdline[i] + 256);
    }
    fifo32_put(fifo, 10 + 256);   /* Enter */
    cons_newline(cons);
    return;
}

新しいコンソールはいらないのでstartコマンドを出力できるようにするncstコマンドを実装していきます。
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;
    char cmdline[30];
    cons.sht = sheet;
    cons.cur_x =  8;
    cons.cur_y = 28;
    cons.cur_c = -1;
    task->cons = &cons;

    if (sheet != 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));

    /* プロンプト表示 */
    cons_putchar(&cons, '>', 1);

    for (;;) {
        io_cli();
        if (fifo32_status(&task->fifo) == 0) {
            task_sleep(task);
            io_sti();
        } else {
            i = fifo32_get(&task->fifo);
            io_sti();
            if (i <= 1) { /* カーソル用タイマ */
                if (i != 0) {
                    timer_init(cons.timer, &task->fifo, 0); /* 次は0を */
                    if (cons.cur_c >= 0) {
                        cons.cur_c = COL8_FFFFFF;
                    }
                } else {
                    timer_init(cons.timer, &task->fifo, 1); /* 次は1を */
                    if (cons.cur_c >= 0) {
                        cons.cur_c = COL8_000000;
                    }
                }
                timer_settime(cons.timer, 50);
            }
            if (i == 2) {    /* カーソルON */
                cons.cur_c = COL8_FFFFFF;
            }
            if (i == 3) {    /* カーソルOFF */
                if (sheet != 0) {
                    boxfill8(sheet->buf, sheet->bxsize, COL8_000000,
                        cons.cur_x, cons.cur_y, cons.cur_x + 7, cons.cur_y + 15);
                }
                cons.cur_c = -1;
            }
            if (i == 4) {    /* コンソールの「×」ボタンクリック */
                cmd_exit(&cons, fat);
            }
            if (256 <= i && i <= 511) { /* キーボードデータ(タスクA経由) */
                if (i == 8 + 256) {
                    /* バックスペース */
                    if (cons.cur_x > 16) {
                        /* カーソルをスペースで消してから、カーソルを1つ戻す */
                        cons_putchar(&cons, ' ', 0);
                        cons.cur_x -= 8;
                    }
                } else if (i == 10 + 256) {
                    /* Enter */
                    /* カーソルをスペースで消してから改行する */
                    cons_putchar(&cons, ' ', 0);
                    cmdline[cons.cur_x / 8 - 2] = 0;
                    cons_newline(&cons);
                    cons_runcmd(cmdline, &cons, fat, memtotal); /* コマンド実行 */
                    if (sheet == 0) {
                        cmd_exit(&cons, fat);
                    }
                    /* プロンプト表示 */
                    cons_putchar(&cons, '>', 1);
                } else {
                    /* 一般文字 */
                    if (cons.cur_x < 240) {
                        /* 一文字表示してから、カーソルを1つ進める */
                        cmdline[cons.cur_x / 8 - 2] = i - 256;
                        cons_putchar(&cons, i - 256, 1);
                    }
                }
            }
            /* カーソル再表示 */
            if (sheet != 0) {
                if (cons.cur_c >= 0) {
                    boxfill8(sheet->buf, sheet->bxsize, cons.cur_c,
                        cons.cur_x, cons.cur_y, cons.cur_x + 7, cons.cur_y + 15);
                }
                sheet_refresh(sheet, cons.cur_x, cons.cur_y, cons.cur_x + 8, cons.cur_y + 16);
            }
        }
    }
}
void cons_putchar(struct CONSOLE *cons, int chr, char move)
{
    char s[2];
    s[0] = chr;
    s[1] = 0;
    if (s[0] == 0x09) { /* タブ */
        for (;;) {
            if (cons->sht != 0) {
                putfonts8_asc_sht(cons->sht, cons->cur_x, cons->cur_y, COL8_FFFFFF, COL8_000000, " ", 1);
            }
            cons->cur_x += 8;
            if (cons->cur_x == 8 + 240) {
                cons_newline(cons);
            }
            if (((cons->cur_x - 8) & 0x1f) == 0) {
                break;  /* 32で割り切れたらbreak */
            }
        }
    } else if (s[0] == 0x0a) {  /* 改行 */
        cons_newline(cons);
     } else if (s[0] == 0x0d) { /* 復帰 */
        /* とりあえずなにもしない */
     } else {   /* 普通の文字 */
        if (cons->sht != 0) { 
            putfonts8_asc_sht(cons->sht, cons->cur_x, cons->cur_y, COL8_FFFFFF, COL8_000000, s, 1);
         }
        if (move != 0) {
            /* moveが0のときはカーソルを進めない */
            cons->cur_x += 8;
            if (cons->cur_x == 8 + 240) {
                cons_newline(cons);
            }
        }
     }
     return;
}

void cons_newline(struct CONSOLE *cons)
{
    int x, y;
    struct SHEET *sheet = cons->sht;
    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;
    return;
}
void cons_runcmd(char *cmdline, struct CONSOLE *cons, int *fat, int memtotal)
{
    if (strcmp(cmdline, "mem") == 0 && cons->sht != 0) {
        cmd_mem(cons, memtotal);
    } else if (strcmp(cmdline, "cls") == 0 && cons->sht != 0) {
        cmd_cls(cons);
    } else if (strcmp(cmdline, "dir") == 0 && cons->sht != 0) {
        cmd_dir(cons);
    } else if (strncmp(cmdline, "type ", 5) == 0 && cons->sht != 0) {
        cmd_type(cons, fat, cmdline);
    } else if (strcmp(cmdline, "exit") == 0) {
        cmd_exit(cons, fat);
    } else if (strncmp(cmdline, "start ", 6) == 0) {
        cmd_start(cons, cmdline, memtotal);
    } else if (strncmp(cmdline, "ncst ", 5) == 0) {
        cmd_ncst(cons, cmdline, memtotal);
    } else if (cmdline[0] != 0) {
        if (cmd_app(cons, fat, cmdline) == 0) {
            /* コマンドではなく、アプリでもなく、さらに空行でもない */
            cons_putstr0(cons, "Bad command.\n\n");
        }
    }
    return;
}
void cmd_exit(struct CONSOLE *cons, int *fat)
{
    struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
    struct TASK *task = task_now();
    struct SHTCTL *shtctl = (struct SHTCTL *) *((int *) 0x0fe4);
    struct FIFO32 *fifo = (struct FIFO32 *) *((int *) 0x0fec);
    if (cons->sht != 0) {
        timer_cancel(cons->timer);
    }
    memman_free_4k(memman, (int) fat, 4 * 2880);
    io_cli();
    if (cons->sht != 0) {
        fifo32_put(fifo, cons->sht - shtctl->sheets0 + 768); /* 768~1023 */
    } else {
        fifo32_put(fifo, task - taskctl->tasks0 + 1024);    /* 1024~2023 */
    }
    io_sti();
    for (;;) {
        task_sleep(task);
    }
}
void cmd_ncst(struct CONSOLE *cons, char *cmdline, int memtotal)
{
    struct TASK *task = open_constask(0, memtotal);
    struct FIFO32 *fifo = &task->fifo;
    int i;
    /* コマンドラインに入力された文字列を、一文字ずつ新しいコンソールに入力 */
    for (i = 5; cmdline[i] != 0; i++) {
        fifo32_put(fifo, cmdline[i] + 256);
    }
    fifo32_put(fifo, 10 + 256);   /* Enter */
    cons_newline(cons);
    return;
}

bootpack.c

void keywin_off(struct SHEET *key_win);
void keywin_on(struct SHEET *key_win);
void close_console(struct SHEET *sht);
void close_constask(struct TASK *task);
         } else if (768 <= i && i <= 1023) { /* コンソール終了処理 */
                close_console(shtctl->sheets0 + (i - 768));
            } else if (1024 <= i && i <= 2023) {
                close_constask(taskctl->tasks0 + (i - 1024));
            }
struct TASK *open_constask(struct SHEET *sht, unsigned int memtotal)
{
    struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
    struct TASK *task = task_alloc();
    int *cons_fifo = (int *) memman_alloc_4k(memman, 128 * 4);
    task->cons_stack = memman_alloc_4k(memman, 64 * 1024);
    task->tss.esp = task->cons_stack + 64 * 1024 - 12;
    task->tss.eip = (int) &console_task;
    task->tss.es = 1 * 8;
    task->tss.cs = 2 * 8;
    task->tss.ss = 1 * 8;
    task->tss.ds = 1 * 8;
    task->tss.fs = 1 * 8;
    task->tss.gs = 1 * 8;
    *((int *) (task->tss.esp + 4)) = (int) sht;
    *((int *) (task->tss.esp + 8)) = memtotal;
    task_run(task, 2, 2); /* level=2, priority=2 */
    fifo32_init(&task->fifo, 128, cons_fifo, task);
    return task;
}

struct SHEET *open_console(struct SHTCTL *shtctl, unsigned int memtotal)
{
    struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
    struct SHEET *sht = sheet_alloc(shtctl);
    unsigned char *buf = (unsigned char *) memman_alloc_4k(memman, 256 * 165);
    sheet_setbuf(sht, buf, 256, 165, -1); /* 透明色なし */
    make_window8(buf, 256, 165, "console", 0);
    make_textbox8(sht, 8, 28, 240, 128, COL8_000000);
    sht->task = open_constask(sht, memtotal);
    sht->flags |= 0x20; /* カーソルあり */
    return sht;
}

bootpack.h

extern struct TASKCTL *taskctl;
/* console.c */
struct CONSOLE {
    struct SHEET *sht;
    int cur_x, cur_y, cur_c;
    struct TIMER *timer;
};
void console_task(struct SHEET *sheet, int memtotal);
void cons_putchar(struct CONSOLE *cons, int chr, char move);
void cons_newline(struct CONSOLE *cons);
void cons_putstr0(struct CONSOLE *cons, char *s);
void cons_putstr1(struct CONSOLE *cons, char *s, int l);
void cons_runcmd(char *cmdline, struct CONSOLE *cons, int *fat, int memtotal);
void cmd_mem(struct CONSOLE *cons, int memtotal);
void cmd_cls(struct CONSOLE *cons);
void cmd_dir(struct CONSOLE *cons);
void cmd_type(struct CONSOLE *cons, int *fat, char *cmdline);
void cmd_exit(struct CONSOLE *cons, int *fat);
void cmd_start(struct CONSOLE *cons, char *cmdline, int memtotal);
void cmd_ncst(struct CONSOLE *cons, char *cmdline, int memtotal);
int cmd_app(struct CONSOLE *cons, int *fat, char *cmdline);
int *hrb_api(int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax);
int *inthandler0d(int *esp);
int *inthandler0c(int *esp);
void hrb_api_linewin(struct SHEET *sht, int x0, int y0, int x1, int y1, int col);
/* bootpack.c */
struct TASK *open_constask(struct SHEET *sht, unsigned int memtotal);
struct SHEET *open_console(struct SHTCTL *shtctl, unsigned int memtotal);

本では27日目に突入しました。
まず最初にxボタンを押しても処理が終了しないバグを修正していきます。

bootpack.c

if (i == 256 + 0x3b && key_shift != 0 && key_win != 0) {   /* Shift+F1 */
                    task = key_win->task;
                    if (task != 0 && task->tss.ss0 != 0) {
                        cons_putstr0(task->cons, "\nBreak(key) :\n");
                        io_cli();   /* 強制終了処理中にタスクが変わると困るから */
                        task->tss.eax = (int) &(task->tss.esp0);
                        task->tss.eip = (int) asm_end_app;
                        io_sti();
                        task_run(task, -1, 0);    /* 終了処理を確実にやらせるために、寝ていたら起こす */
                    }
                }
                if (i == 256 + 0x3c && key_shift != 0) {   /* Shift+F2 */
                    /* 新しく作ったコンソールを入力選択状態にする(そのほうが親切だよね?) */
                    if (key_win != 0) {
                        keywin_off(key_win);
                    }
                    key_win = open_console(shtctl, memtotal);
                    sheet_slide(key_win, 32, 4);
                    sheet_updown(key_win, shtctl->top);
                    keywin_on(key_win);
                }
                if (i == 256 + 0x57) {  /* F11 */
                    sheet_updown(shtctl->sheets[1], shtctl->top - 1);
                }
                if (i == 256 + 0xfa) {  /* キーボードがデータを無事に受け取った */
                    keycmd_wait = -1;
                }
                if (i == 256 + 0xfe) {  /* キーボードがデータを無事に受け取れなかった */
                    wait_KBC_sendready();
                    io_out8(PORT_KEYDAT, keycmd_wait);
                }
            } else if (512 <= i && i <= 767) { /* マウスデータ */
                    if (mouse_decode(&mdec, i - 512) != 0) {
                        /* マウスカーソルの移動 */
                        mx += mdec.x;
                        my += mdec.y;
                        if (mx < 0) {
                            mx = 0;
                        }
                        if (my < 0) {
                            my = 0;
                        }
                        if (mx > binfo->scrnx - 1) {
                            mx = binfo->scrnx - 1;
                        }
                        if (my > binfo->scrny - 1) {
                            my = binfo->scrny - 1;
                        }
                        new_mx = mx;
                        new_my = my;
                        if ((mdec.btn & 0x01) != 0) {
                            /* 左ボタンを押している */
                            if (mmx < 0) {
                                /* 通常モードの場合 */
                                /* 上の下じきから順番にマウスが指している下じきを探す */
                                for (j = shtctl->top - 1; j > 0; j--) {
                                    sht = shtctl->sheets[j];
                                    x = mx - sht->vx0;
                                    y = my - sht->vy0;
                                    if (0 <= x && x < sht->bxsize && 0 <= y && y < sht->bysize) {
                                        if (sht->buf[y * sht->bxsize + x] != sht->col_inv) {
                                            sheet_updown(sht, shtctl->top - 1);
                                            if (sht != key_win) {
                                                keywin_off(key_win);
                                                key_win = sht;
                                                keywin_on(key_win);
                                            }
                                            if (3 <= x && x < sht->bxsize - 3 && 3 <= y && y < 21) {
                                                mmx = mx;   /* ウィンドウ移動モードへ */
                                                mmy = my;
                                                mmx2 = sht->vx0;
                                                new_wy = sht->vy0;
                                            }
                                            if (sht->bxsize - 21 <= x && x < sht->bxsize - 5 && 5 <= y && y < 19) {
                                                /* 「×」ボタンクリック */
                                                if ((sht->flags & 0x10) != 0) {      /* アプリが作ったウィンドウか? */
                                                    task = sht->task;
                                                    cons_putstr0(task->cons, "\nBreak(mouse) :\n");
                                                    io_cli();   /* 強制終了処理中にタスクが変わると困るから */
                                                    task->tss.eax = (int) &(task->tss.esp0);
                                                    task->tss.eip = (int) asm_end_app;
                                                    io_sti();
                                                    task_run(task, -1, 0);
                                                } else {  /* コンソール */
                                                    task = sht->task;
                                                    io_cli();
                                                    fifo32_put(&task->fifo, 4);
                                                    io_sti();
                                                }
                                            }
                                            break;
                                    }
                                }
                            }
                        } 

実装過程
・ 9a70ea94ede0e7ab7cfb80c694ebae1ddc3ccdb6