J-3100GTSX041 OS自作入門の演習 四日目途中〜五日目

J-3100GTSX041 OS自作入門の演習 四日目途中〜五日目

OS自作入門 四日目途中〜五日目です。前回、画面描画位置がずれていたので、色々解析してみました。ベースのソースコードは、256色用なので、1ドットあたり1バイトなんだけど、相手はDCGAのプラズマディスプレイ、頑張ってもグレースケール4階調が関の山、ということは1ドット当たり2bitなので、1バイトだと4ドット分のデータが格納される。ということは、描画する部分の関数をまるっと書き換えねばならんということですな。修正はbootpack.cのみですみそう。ついでだから、四日目最後のソースコードharib00jのメンテナンスはすっとばして、五日目最終ソースharib02hまでやっつけてしまいましょう。

というわけで、harib02h内のbootpack.cのソースにございます。1Byte内に4ドット分の情報を入れ込むことで前回あった4ドット飛ばしも解決している。にしても、我ながら修正部分のソースがキチャナイ

void HariMain(void)
{
struct BOOTINFO *binfo = (struct BOOTINFO *) 0x0ff0;
char s[40], mcursor[256];
int mx, my;

init_gdtidt();
init_screen8(binfo->vram, binfo->scrnx, binfo->scrny);
mx = (binfo->scrnx – 16) / 2; /* 画面中央になるように座標計算 */
my = (binfo->scrny – 28 – 16) / 2;
init_mouse_cursor8(mcursor, 0x55);
putblock8_8(binfo->vram, binfo->scrnx, 16, 16, mx, my, mcursor, 16);
sprintf(s, “(%d, %d)”, mx, my);
putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, 0xFF, s);

for (;;) {
io_hlt();
}
}

void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1)
{
int x, y;
unsigned char color = 0;

for (y = y0; y <= y1; y++) {
for (x = x0; x <= x1; x++){ if (c == 0x00) color |= 0x00 >> ((x%4)*2);
if (c == 0x55) color |= 0x40 >> ((x%4)*2);
if (c == 0xAA) color |= 0x80 >> ((x%4)*2);
if (c == 0xFF) color |= 0xC0 >> ((x%4)*2);
if ((x+1)%4 == 0){
vram[y/2 * (xsize/4) + x/4] = color;
color = 0;
}
}
}
return;
}

void init_screen8(char *vram, int xsize, int ysize)
{
boxfill8(vram, xsize, 0x55, 0, 0, xsize – 1, ysize – 29); /* 全白で埋める */
boxfill8(vram, xsize, 0xAA, 0, ysize – 28, xsize – 1, ysize – 28);
boxfill8(vram, xsize, 0xFF, 0, ysize – 27, xsize – 1, ysize – 27);
boxfill8(vram, xsize, 0x55, 0, ysize – 26, xsize – 1, ysize – 1);

boxfill8(vram, xsize, 0xFF, 3, ysize – 24, 59, ysize – 24);
boxfill8(vram, xsize, 0xFF, 2, ysize – 24, 2, ysize – 4);
boxfill8(vram, xsize, 0x55, 3, ysize – 4, 59, ysize – 4);
boxfill8(vram, xsize, 0x55, 59, ysize – 23, 59, ysize – 5);
boxfill8(vram, xsize, 0x0, 2, ysize – 3, 59, ysize – 3);
boxfill8(vram, xsize, 0x0, 60, ysize – 24, 60, ysize – 3);

boxfill8(vram, xsize, 0x55, xsize – 47, ysize – 24, xsize – 4, ysize – 24);
boxfill8(vram, xsize, 0x55, xsize – 47, ysize – 23, xsize – 47, ysize – 4);
boxfill8(vram, xsize, 0xFF, xsize – 47, ysize – 3, xsize – 4, ysize – 3);
boxfill8(vram, xsize, 0xFF, xsize – 3, ysize – 24, xsize – 3, ysize – 3);

return;
}

void putfont8(char *vram, int xsize, int x, int y, char c, char *font)
{
int i;
char *p, d /* data */;
for (i = 0; i < 16; i++) {
p = vram + (y + i)/2 * xsize/4 + x/4;
d = font[i];
/* 色は3固定 */
if ((d & 0x80) != 0) { p[0] |= 0xC0; }
if ((d & 0x40) != 0) { p[0] |= 0x30; }
if ((d & 0x20) != 0) { p[0] |= 0x0C; }
if ((d & 0x10) != 0) { p[0] |= 0x03; }
if ((d & 0x08) != 0) { p[1] |= 0xC0; }
if ((d & 0x04) != 0) { p[1] |= 0x30; }
if ((d & 0x02) != 0) { p[1] |= 0x0C; }
if ((d & 0x01) != 0) { p[1] |= 0x03; }
}
return;
}

void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s)
{
extern char hankaku[4096];
for (; *s != 0x00; s++) {
putfont8(vram, xsize, x, y, c, hankaku + *s * 16);
x += 8; /* 右に8ドットシフト */
}
return;
}

void init_mouse_cursor8(char *mouse, char bc)
/* マウスカーソルを準備(16×16) */
{
static char cursor[16][16] = {
“**************..”,
“*OOOOOOOOOOO*…”,
“*OOOOOOOOOO*….”,
“*OOOOOOOOO*…..”,
“*OOOOOOOO*……”,
“*OOOOOOO*…….”,
“*OOOOOOO*…….”,
“*OOOOOOOO*……”,
“*OOOO**OOO*…..”,
“*OOO*..*OOO*….”,
“*OO*….*OOO*…”,
“*O*……*OOO*..”,
“**……..*OOO*.”,
“*……….*OOO*”,
“…………*OO*”,
“………….***”
};
int x, y;

for (y = 0; y < 16; y++) {
for (x = 0; x < 16; x++) {
if (cursor[y][x] == ‘*’) {
mouse[y * 16 + x] = 0x00;
}
if (cursor[y][x] == ‘O’) {
mouse[y * 16 + x] = 0xFF;
}
if (cursor[y][x] == ‘.’) {
mouse[y * 16 + x] = bc;
}
}
}
return;
}

void putblock8_8(char *vram, int vxsize, int pxsize,
int pysize, int px0, int py0, char *buf, int bxsize)
{
int x, y;
unsigned char color = 0;

for (y = 0; y < pysize; y++) {
for (x = 0; x < pxsize; x++) { if (buf[y * bxsize + x] == 0x00) color |= 0x00 >> ((x%4)*2);
if (buf[y * bxsize + x] == 0x55) color |= 0x40 >> ((x%4)*2);
if (buf[y * bxsize + x] == 0xAA) color |= 0x80 >> ((x%4)*2);
if (buf[y * bxsize + x] == 0xFF) color |= 0xC0 >> ((x%4)*2);
if ((x+1)%4 == 0){
vram[(py0 + y)/2 * vxsize/4 + (px0 + x)/4] = color;
color = 0;
}
}
}
return;
}
(以下略)

ここでまだ謎なところが残っていて、なぜかy座標を2で割らないと画面が崩れる。謎だ
んで、AT機とJ-3100で動かした時のエミュレーション結果がこちら

おお、なんかいい感じ!
よっしゃ、実機に持って行ってみるべ

五日目画面キタァ、とりあえずここまではなんとか来ました