たなしょのメモ

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

OS作成奮闘記day48

day49

今日はinvader.cを軽くする作業をします。
ipl09.nasをダウンロードしてディレクトリに配置してから改造します。
invader.c

#include <stdio.h>        /* sprintf */
#include <string.h>      /* strlen */
#include "apilib.h"

void putstr(int win, char *winbuf, int x, int y, int col, unsigned char *s);
void wait(int i, int timer, char *keyflag);
void setdec8(char *s, int i);

static unsigned char charset[16 * 8] = {

    /* invader(0) */
    0x00, 0x00, 0x00, 0x43, 0x5f, 0x5f, 0x5f, 0x7f,
    0x1f, 0x1f, 0x1f, 0x1f, 0x00, 0x20, 0x3f, 0x00,

    /* invader(1) */
    0x00, 0x0f, 0x7f, 0xff, 0xcf, 0xcf, 0xcf, 0xff,
    0xff, 0xe0, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x00,

    /* invader(2) */
    0x00, 0xf0, 0xfe, 0xff, 0xf3, 0xf3, 0xf3, 0xff,
    0xff, 0x07, 0xff, 0xff, 0x03, 0x03, 0x03, 0x00,

    /* invader(3) */
    0x00, 0x00, 0x00, 0xc2, 0xfa, 0xfa, 0xfa, 0xfe,
    0xf8, 0xf8, 0xf8, 0xf8, 0x00, 0x04, 0xfc, 0x00,

    /* fighter(0) */
    0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
    0x01, 0x43, 0x47, 0x4f, 0x5f, 0x7f, 0x7f, 0x00,

    /* fighter(1) */
    0x18, 0x7e, 0xff, 0xc3, 0xc3, 0xc3, 0xc3, 0xff,
    0xff, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0x00,

    /* fighter(2) */
    0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    0x80, 0xc2, 0xe2, 0xf2, 0xfa, 0xfe, 0xfe, 0x00,

    /* laser */
    0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00
};
/* invader:"abcd", fighter:"efg", laser:"h" */

void HariMain(void)
{
    int win, timer, i, j, fx, laserwait, lx = 0, ly;
    int ix, iy, movewait0, movewait, idir;
    int invline, score, high, point;
    char winbuf[336 * 261], invstr[32 * 6], s[12], keyflag[4], *p;
    static char invstr0[32] = " abcd abcd abcd abcd abcd ";

    win = api_openwin(winbuf, 336, 261, -1, "invader");
    api_boxfilwin(win, 6, 27, 329, 254, 0);
    timer = api_alloctimer();
    api_inittimer(timer, 128);

    high = 0;
    putstr(win, winbuf, 22, 0, 7, "HIGH:00000000");

restart:
    score = 0;
    point = 1;
    putstr(win, winbuf,  4, 0, 7, "SCORE:00000000");
    movewait0 = 20;
    fx = 18;
    putstr(win, winbuf, fx, 13, 6, "efg");
    wait(100, timer, keyflag); 

next_group:
    wait(100, timer, keyflag);
    ix = 7;
    iy = 1;
    invline = 6;
    for (i = 0; i < 6; i++) {
        for (j = 0; j < 27; j++) {
            invstr[i * 32 + j] = invstr0[j];
        }
        putstr(win, winbuf, ix, iy + i, 2, invstr + i * 32);
    }
    keyflag[0] = 0;
    keyflag[1] = 0;
    keyflag[2] = 0;

    ly = 0; /* 非表示 */
    laserwait = 0;
    movewait = movewait0;
    idir = +1;
    wait(100, timer, keyflag);

    for (;;) {
        if (laserwait != 0) {
            laserwait--;
            keyflag[2 /* space */] = 0;
        }

        wait(4, timer, keyflag);

        /* 自機の処理 */
        if (keyflag[0 /* left */]  != 0 && fx > 0) {
            fx--;
            putstr(win, winbuf, fx, 13, 6, "efg ");
            keyflag[0 /* left */]  = 0;
        }
        if (keyflag[1 /* right */] != 0 && fx < 37) {
            putstr(win, winbuf, fx, 13, 6, " efg");
            fx++;
            keyflag[1 /* right */] = 0;
        }
        if (keyflag[2 /* space */] != 0 && laserwait == 0) {
            laserwait = 15;
            lx = fx + 1;
            ly = 13;
        }

        /* インベーダ移動 */
        if (movewait != 0) {
            movewait--;
        } else {
            movewait = movewait0;
            if (ix + idir > 14 || ix + idir < 0) {
                if (iy + invline == 13) {
                    break; /* GAME OVER */
                }
                idir = - idir;
                putstr(win, winbuf, ix + 1, iy, 0, "                         ");
                iy++;
            } else {
                ix += idir;
            }
            for (i = 0; i < invline; i++) {
                putstr(win, winbuf, ix, iy + i, 2, invstr + i * 32);
            }
        }

        /* レーザー処理 */
        if (ly > 0) {
            if (ly < 13) {
                if (ix < lx && lx < ix + 25 && iy <= ly && ly < iy + invline) {
                    putstr(win, winbuf, ix, ly, 2, invstr + (ly - iy) * 32);
                } else {
                    putstr(win, winbuf, lx, ly, 0, " ");
                }
            }
            ly--;
            if (ly > 0) {
                putstr(win, winbuf, lx, ly, 3, "h");
            } else {
                point -= 10;
                if (point <= 0) {
                    point = 1;
                }
            }
            if (ix < lx && lx < ix + 25 && iy <= ly && ly < iy + invline) {
                p = invstr + (ly - iy) * 32 + (lx - ix);
                if (*p != ' ') {
                    /* hit ! */
                    score += point;
                    point++;
                    setdec8(s, score);
                    putstr(win, winbuf, 10, 0, 7, s);
                    if (high < score) {
                        high = score;
                        putstr(win, winbuf, 27, 0, 7, s);
                    }
                    for (p--; *p != ' '; p--) { }
                    for (i = 1; i < 5; i++) {
                        p[i] = ' ';
                    }
                    putstr(win, winbuf, ix, ly, 2, invstr + (ly - iy) * 32);
                    for (; invline > 0; invline--) {
                        for (p = invstr + (invline - 1) * 32; *p != 0; p++) {
                            if (*p != ' ') {
                                goto alive;
                            }
                        }
                    }
                    /* 全部やっつけられた */
                    movewait0 -= movewait0 / 3;
                    goto next_group;
    alive:
                    ly = 0;
                }
            }
        }
    }

    /* GAME OVER */
    putstr(win, winbuf, 15, 6, 1, "GAME OVER");
    wait(0, timer, keyflag);
    for (i = 1; i < 14; i++) {
        putstr(win, winbuf, 0, i, 0, "                                        ");        
    }
    goto restart;
} 

void putstr(int win, char *winbuf, int x, int y, int col, unsigned char *s)
{
    int c, x0, i;
    char *p, *q, t[2];
    x = x * 8 + 8;
    y = y * 16 + 29;
    x0 = x;
    i = strlen(s);  /* sの文字数を数える */
    api_boxfilwin(win + 1, x, y, x + i * 8 - 1, y + 15, 0);
    q = winbuf + y * 336;
    t[1] = 0;
    for (;;) {
        c = *s;
        if (c == 0) {
            break;
        }
        if (c != ' ') {
            if ('a' <= c && c <= 'h') {
                p = charset + 16 * (c - 'a');
                q += x;
                for (i = 0; i < 16; i++) {
                    if ((p[i] & 0x80) != 0) { q[0] = col; }
                    if ((p[i] & 0x40) != 0) { q[1] = col; }
                    if ((p[i] & 0x20) != 0) { q[2] = col; }
                    if ((p[i] & 0x10) != 0) { q[3] = col; }
                    if ((p[i] & 0x08) != 0) { q[4] = col; }
                    if ((p[i] & 0x04) != 0) { q[5] = col; }
                    if ((p[i] & 0x02) != 0) { q[6] = col; }
                    if ((p[i] & 0x01) != 0) { q[7] = col; }
                    q += 336;
                }
                q -= 336 * 16 + x;
            } else {
                t[0] = *s;
                api_putstrwin(win + 1, x, y, col, 1, t);
            }
        }
        s++;
        x += 8;
    }
    api_refreshwin(win, x0, y, x, y + 16);
    return;
}

void wait(int i, int timer, char *keyflag)
{
    int j;
    if (i > 0) {
        /* 一定時間待つ */
        api_settimer(timer, i);
        i = 128;
    } else {
        i = 0x0a; /* Enter */
    }
    for (;;) {
        j = api_getkey(1);
        if (i == j) {
            break;
        }
        if (j == '4') {
            keyflag[0 /* left */]  = 1;
        }
        if (j == '6') {
            keyflag[1 /* right */] = 1;
        }
        if (j == ' ') {
            keyflag[2 /* space */] = 1;
        }
    }
    return;
}

void setdec8(char *s, int i)
/* iを10進数表記でsに格納 */
{
    int j;
    for (j = 7; j >= 0; j--) {
        s[j] = '0' + i % 10;
        i /= 10;
    }
    s[8] = 0;
    return;
}

OS開発もこれにて完了で久しぶりにこんなに大がかりのモノを作りました。
最後までやり抜けてとてもいい経験になりました。
次は何をつくろうかな。
pythonで自分だけのメモ帳をつくるかもしれないし、CでNESエミュレータをつくるかもしれないし。 C++windows用のアプリケーションをつくるかもしれない。
作りたいものはまだまだ沢山あるのでこれからが楽しみです。

実装過程
・ 555963ea7a3cbd0fac7e1cedeee387c5a0704f5b