真面目にVSync処理してないのでチラつくが、チラつきの丁度いいサンプルなのでこのままにしておく。
wall.c
/*
z88dk / WebMSX
zcc +msx -lndos -create-app -bnwall wall.c
*/
#include <msx/gfx.h>
#include <stdlib.h>
#include <string.h>
#define BYTE unsigned char
#define _countof(arr) (sizeof(arr)/sizeof(arr[0]))
#define WIDTH 64
#define HEIGHT 48
const int dx[] = { 0, 0, 1, 1, 1, 0, -1, -1, -1 };
const int dy[] = { 0, -1, -1, 0, 1, 1, 1, 0, -1 };
BYTE vvr[HEIGHT][WIDTH]; // 仮想VRAM
BYTE pgblt[8*16]; // パターンジェネレータ・バッファ
BYTE pnblt[32*24]; // パターンネーム・バッファ
BYTE walls[8][2][8]; // プリレンダー・シフト壁
void gen_walls()
{
BYTE wall[] = { 0xff, 0x81, 0xbd, 0xbd, 0xbd, 0xbd, 0x81, 0xff };
for (int y = 0; y < 8; y++) {
int w = wall[y];
for (int x = 0; x < 8; x++) {
walls[x][0][y] = w & 0xff;
walls[x][1][y] = w >> 8;
w <<= 1;
}
}
}
void put_wall(int x, int y)
{
vvr[y ][x ] |= 1;
vvr[y ][x-1] |= 2;
vvr[y-1][x ] |= 4;
vvr[y-1][x-1] |= 8;
}
void gen_map()
{
int lines[][4] = {
{ 1, 1, 63, 1 },
{ 1, 23, 63, 23 },
{ 1, 47, 63, 47 },
{ 1, 1, 1, 47 },
{ 31, 1, 31, 47 },
{ 47, 24, 47, 47 },
{ 63, 1, 63, 47 },
{ 1, 23, 23, 1 }
};
for (int i = 0; i < _countof(lines); i++) {
int x0 = lines[i][0];
int y0 = lines[i][1];
int x1 = lines[i][2];
int y1 = lines[i][3];
int dx = abs(x1 - x0);
int dy = abs(y1 - y0);
int sx = (x0 < x1) ? 1 : -1;
int sy = (y0 < y1) ? 1 : -1;
int err = dx - dy;
for (;;) {
put_wall(x0, y0);
if (x0 == x1 && y0 == y1) { break; }
int e2 = 2 * err;
if (e2 > -dy) {
err -= dy;
x0 += sx;
}
if (e2 < dx) {
err += dx;
y0 += sy;
}
}
}
}
void memmerge(BYTE *dst, BYTE *src, int len)
{
for (int i = 0; i < len; i++) {
*dst++ |= *src++;
}
}
void main()
{
const BYTE *pjiffy = (BYTE *)0xfc9e;
int px = 0;
int py = 0;
set_mode(mode_1);
gen_walls();
gen_map();
while (! get_trigger(0)) {
int st = get_stick(0);
px += dx[st] * 3;
py += dy[st] * 3;
if (px < 0) px = 0;
if (px > (WIDTH-32)*8) px = (WIDTH-32)*8;
if (py < 0) py = 0;
if (py > (HEIGHT-24)*8) py = (HEIGHT-24)*8;
int xh = px >> 3;
int yh = py >> 3;
int xl = px & 7;
int yl = py & 7;
int yr = 8 - yl;
// パターンジェネレータ
memset(pgblt, 0, 8*16);
BYTE *pg = pgblt;
BYTE *w0 = &(walls[xl][0]);
BYTE *w1 = &(walls[xl][1]);
for (int i = 1; i < 16; i++) {
pg += 8;
if (i & 1) memmerge(pg, w0+yl, yr);
if (i & 2) memmerge(pg, w1+yl, yr);
if (i & 4) memmerge(pg+yr, w0, yl);
if (i & 8) memmerge(pg+yr, w1, yl);
}
// パターンネーム
BYTE *pn = pnblt;
for (int y = 0; y < 24; y++) {
memcpy(pn, &(vvr[yh+y][xh]), 32);
pn += 32;
}
// VBlank
BYTE jiffy = *pjiffy;
while (jiffy == *pjiffy) ;
// ブロック転送
vwrite(pgblt, 0, 8*16);
vwrite(pnblt, 0x1800, 32*24);
}
}