X68000 V-DISPの効果がすごい
前回のV-DISP (V-Sync)を組み込んだフリッカーレスのブロック崩しのリストです。
ぜひ、以前のものと比較してみてください。こんなにも印象が変わるのですね。
/* フリッカーレス */
#include <iocslib.h>
/* X68000の16ビットカラーコード定義 */
#define COLOR_BLACK 0x0000
#define COLOR_WHITE 0xffff
#define COLOR_BLUE 0x003f
#define COLOR_RED 0x07c1
#define COLOR_GREEN 0xf801
#define COLOR_YELLOW 0xffc1
#define COLOR_CYAN 0xf83f
#define COLOR_MAGENTA 0x07ff
/* ブロックの配置設定 */
#define BLOCK_ROWS 5
#define BLOCK_COLS 12
int main(void) {
int old_mode;
struct FILLPTR pad;
struct FILLPTR ball;
struct FILLPTR wall;
struct FILLPTR blk;
/* パドルの変数宣言 */
int pad_width;
int pad_height;
int pad_x;
int pad_y;
int speed;
int prev_pad_x;
/* ボールの変数宣言 */
int ball_size;
int ball_x;
int ball_y;
int ball_vx;
int ball_vy;
int prev_ball_x;
int prev_ball_y;
/* ブロック管理の変数宣言 */
int blocks[BLOCK_ROWS][BLOCK_COLS];
int block_width;
int block_height;
int gap_x;
int gap_y;
int start_x;
int start_y;
int row;
int col;
/* V-SYNC同期(ハードウェア直接監視)用のポインタと、スタック退避用の変数 */
volatile unsigned char *gpip;
int ssp; /* スーパーバイザ移行時のスタック退避用 */
/* 1. 現在の画面モードを保存 */
old_mode = CRTMOD(-1);
/* スーパーバイザモード(特権モード)へ移行します */
/* これにより、システムI/O領域 $e88001 への直接読み取りが許可されます */
ssp = B_SUPER(0);
/* 画面初期化 (17: グラフィック16色 / 解像度 512x512) */
CRTMOD(17);
G_CLR_ON();
/* WINDOWの解像度を設定 */
WINDOW(0, 0, 511, 511);
/* カラーパレット登録 */
GPALET(0, COLOR_BLACK);
GPALET(1, COLOR_WHITE);
GPALET(2, COLOR_BLUE);
GPALET(3, COLOR_RED);
GPALET(4, COLOR_GREEN);
GPALET(5, COLOR_YELLOW);
GPALET(6, COLOR_CYAN);
GPALET(7, COLOR_MAGENTA);
/* ハードウェアレジスタのアドレス設定 */
gpip = (volatile unsigned char *)0xe88001;
/* 外壁の描画(青) */
wall.x1 = 0; wall.y1 = 0; wall.x2 = 9; wall.y2 = 430; wall.color = 2;
FILL(&wall);
wall.x1 = 502; wall.y1 = 0; wall.x2 = 511; wall.y2 = 430; wall.color = 2;
FILL(&wall);
wall.x1 = 0; wall.y1 = 0; wall.x2 = 511; wall.y2 = 19; wall.color = 2;
FILL(&wall);
/* ブロック群の初期化と描画 */
block_width = 39;
block_height = 16;
gap_x = 2;
gap_y = 4;
start_x = 11;
start_y = 50;
for (row = 0; row < BLOCK_ROWS; row++) {
for (col = 0; col < BLOCK_COLS; col++) {
blocks[row][col] = 1;
blk.x1 = start_x + col * (block_width + gap_x);
blk.y1 = start_y + row * (block_height + gap_y);
blk.x2 = blk.x1 + block_width - 1;
blk.y2 = blk.y1 + block_height - 1;
blk.color = 3 + row;
FILL(&blk);
}
}
/* パドルの初期設定 */
pad_width = 60;
pad_height = 12;
pad_x = (512 - pad_width) / 2;
pad_y = 410;
speed = 8;
prev_pad_x = pad_x;
/* パドルの初期描画 */
pad.x1 = pad_x; pad.y1 = pad_y; pad.x2 = pad_x + pad_width - 1; pad.y2 = pad_y + pad_height - 1; pad.color = 1;
FILL(&pad);
/* ボールの初期設定 */
ball_size = 8;
ball_x = 256;
ball_y = 200;
ball_vx = 4;
ball_vy = 4;
prev_ball_x = ball_x;
prev_ball_y = ball_y;
/* ゲームのメインループ */
while (1) {
int is_moved;
int new_x;
int b_hit;
int next_ball_x;
int next_ball_y;
/* ESCキーで終了 */
if ((BITSNS(0) & 2) != 0) {
break;
}
/* --- 計算フェーズ --- */
prev_pad_x = pad_x;
prev_ball_x = ball_x;
prev_ball_y = ball_y;
/* パドルの移動先計算 */
is_moved = 0;
new_x = pad_x;
if ((BITSNS(7) & 8) != 0) {
new_x = pad_x - speed;
if (new_x < 10) { new_x = 10; }
is_moved = 1;
}
if ((BITSNS(7) & 32) != 0) {
new_x = pad_x + speed;
if (new_x > 502 - pad_width) { new_x = 502 - pad_width; }
is_moved = 1;
}
pad_x = new_x;
/* ボールの移動先を予測 */
next_ball_x = ball_x + ball_vx;
next_ball_y = ball_y + ball_vy;
/* 壁との衝突 */
if (next_ball_x < 10) {
next_ball_x = 10;
ball_vx = -ball_vx;
} else if (next_ball_x > 502 - ball_size) {
next_ball_x = 502 - ball_size;
ball_vx = -ball_vx;
}
if (next_ball_y < 20) {
next_ball_y = 20;
ball_vy = -ball_vy;
}
/* パドルとの衝突 */
if (ball_vy > 0) {
if (next_ball_y + ball_size >= pad_y && next_ball_y <= pad_y + pad_height) {
if (next_ball_x + ball_size >= pad_x && next_ball_x <= pad_x + pad_width) {
next_ball_y = pad_y - ball_size;
ball_vy = -ball_vy;
}
}
}
/* ブロックとの衝突 */
b_hit = 0;
for (row = 0; row < BLOCK_ROWS && b_hit == 0; row++) {
for (col = 0; col < BLOCK_COLS; col++) {
if (blocks[row][col] == 1) {
int blx1 = start_x + col * (block_width + gap_x);
int bly1 = start_y + row * (block_height + gap_y);
int blx2 = blx1 + block_width - 1;
int bly2 = bly1 + block_height - 1;
if (next_ball_x <= blx2 && next_ball_x + ball_size - 1 >= blx1 &&
next_ball_y <= bly2 && next_ball_y + ball_size - 1 >= bly1) {
blocks[row][col] = 0;
blk.x1 = blx1; blk.y1 = bly1; blk.x2 = blx2; blk.y2 = bly2; blk.color = 0;
FILL(&blk);
ball_vy = -ball_vy;
b_hit = 1;
break;
}
}
}
}
/* ミス判定 */
if (next_ball_y > 430) {
next_ball_x = 256;
next_ball_y = 200;
ball_vx = 4;
ball_vy = 4;
}
ball_x = next_ball_x;
ball_y = next_ball_y;
/* --- 同期フェーズ (V-SYNC) --- */
while ((*gpip & 0x10) == 0) ;
while ((*gpip & 0x10) != 0) ;
/* --- 描画フェーズ (V-Blank中に一気に行う) --- */
if (pad_x != prev_pad_x) {
pad.x1 = prev_pad_x; pad.y1 = pad_y; pad.x2 = prev_pad_x + pad_width - 1; pad.y2 = pad_y + pad_height - 1; pad.color = 0;
FILL(&pad);
pad.x1 = pad_x; pad.y1 = pad_y; pad.x2 = pad_x + pad_width - 1; pad.y2 = pad_y + pad_height - 1; pad.color = 1;
FILL(&pad);
}
ball.x1 = prev_ball_x; ball.y1 = prev_ball_y; ball.x2 = prev_ball_x + ball_size - 1; ball.y2 = prev_ball_y + ball_size - 1; ball.color = 0;
FILL(&ball);
ball.x1 = ball_x; ball.y1 = ball_y; ball.x2 = ball_x + ball_size - 1; ball.y2 = ball_y + ball_size - 1; ball.color = 1;
FILL(&ball);
}
/* 画面モードを元に戻す */
CRTMOD(old_mode);
/* ユーザーモード(通常の安全なモード)に戻してプログラムを終了します */
B_SUPER(ssp);
return 0;
}
このまま、XCでコンパイルすれば動作します。
cc /Y block.c

今回は、右を空けています。
いろいろな情報を表示できるようにです。
それでは、ヌルヌル動くようになったゲームをお楽しみください。
2026.8.8
