1
0

More than 5 years have passed since last update.

MSX 仮想VRAM (2)

Last updated at Posted at 2018-07-15

真面目に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);
    }
}

WebMSXテープ版

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0