ZX81の回想禄

PR

×

プロフィール

ZX81

ZX81

カレンダー

コメント新着

コメントに書き込みはありません。

キーワードサーチ

▼キーワード検索

2026.04.03
XML

前回のソースでは描画があまりにも遅かったので
まずは、画面バッファを移動方向に合わせて
-1なら1行下にコピーして最上段の1行のみを描画
+1なら1行上にコピーして最下段の1行のみを描画
としてみました。
ーーーーーmap.cpp
/*
 *      ZX81 Map Handling Module program
 */
#include <stdio.h>
#include <string.h>
#include "map.h"
unsigned char rock_tbl[19][3] = {
// screen
{0x80,0x00,0x00},{0x40,0x00,0x00},{0x20,0x00,0x00},{0x10,0x00,0x00},{0x08,0x00,0x00},
{0x04,0x00,0x00},{0x02,0x00,0x00},{0x01,0x00,0x00},{0x00,0x80,0x00},{0x00,0x40,0x00},
{0x00,0x20,0x00},{0x00,0x10,0x00},
// scroll
{0x00,0x08,0x00},{0x00,0x04,0x00},{0x00,0x02,0x00},{0x00,0x01,0x00},{0x00,0x00,0x80},
{0x00,0x00,0x40},{0x00,0x00,0x20},
};
unsigned char rock_chr[4][2] =
{
{0x81, 0x05},{0x80, 0x01},
{0x03, 0x00},{0x87, 0x04}
};
// Render buffers for smooth 2x2 tile scrolling (even/odd frames)
#define RENDER_DX 22
#define RENDER_DY 24
unsigned char render_buf_even[RENDER_DY][RENDER_DX];
unsigned char render_buf_odd[RENDER_DY][RENDER_DX];
int render_pos;
// screen address
#define D_FILE          0x400c
#define D_DX            33      // 32+1(CR)
#define D_DY            24
unsigned char* getscrnaddr(int posy, int posx)
{
#asm
    ld      ix,2
    add     ix,sp
;    push    de
    ld      d, (ix+2)       ; d=posy
    ld      e, (ix+0)       ; e=posx
    call    getscrnaddr
;    pop     de
    ret
getscrnaddr:
; IN:  D=posy, E=posx
; OUT: HL= screen address
;    push    bc
    ; HL = posy * 33
    ld      h, 0
    ld      l, d
    add     hl, hl          ; *2
    add     hl, hl          ; *4
    add     hl, hl          ; *8
    add     hl, hl          ; *16
    add     hl, hl          ; *32
    ld      b, 0
    ld      c, d
    add     hl, bc          ; +1 -> *33
    ; HL += posx
    ld      b, 0
    ld      c, e            ; c=posx
    add     hl, bc
    ; HL += D_FILE
    ld      bc,(D_FILE)
    inc     bc
    add     hl, bc
;    pop     bc
    ret
#endasm
}
void rock_render_line(int phys_y)
{
    int dx;
    unsigned char bit = 0x80;
    int rockx = 0;
    int rocky = (render_pos + phys_y * 2 + 1) / 4;
    int ptn   = (render_pos + phys_y * 2) & 0x03;   // 0 or 2
    if (render_pos & 0x01)
    {
        memset(&render_buf_odd[phys_y][1], 0, RENDER_DX - 2);
        for (dx = 1; dx <= RENDER_DX - 2; dx++)
        {
            if (rock_tbl[rocky][rockx] & bit)
                memcpy(&render_buf_odd[phys_y][dx], &rock_chr[ptn][0], 2);
            bit >>= 1;
            if (!bit) { bit = 0x80; rockx++; }
        }
    }
    else
    {
        memset(&render_buf_even[phys_y][1], 0, RENDER_DX - 2);
        for (dx = 1; dx <= RENDER_DX - 2; dx++)
        {
            if (rock_tbl[rocky][rockx] & bit)
                memcpy(&render_buf_even[phys_y][dx], &rock_chr[ptn][0], 2);
            bit >>= 1;
            if (!bit) { bit = 0x80; rockx++; }
        }
    }
}
// ----------------------------------------------------------
// 初期化
// ----------------------------------------------------------
void map_init(void)
{
    int phys_y;
    render_pos = 0;
    // -----------------------------
    // even バッファの初期化(render_pos=0)
    // -----------------------------
    for (phys_y = 0; phys_y < RENDER_DY; phys_y++)
    {
        render_buf_even[phys_y][0]             = 0x82;
        render_buf_even[phys_y][RENDER_DX-1]   = 0x81;
        rock_render_line(phys_y);
    }
    // -----------------------------
    // odd バッファの初期化(render_pos-1 にして描く)
    // -----------------------------
    render_pos--;
    for (phys_y = 0; phys_y < RENDER_DY; phys_y++)
    {
        render_buf_odd[phys_y][0]              = 0x07;
        render_buf_odd[phys_y][RENDER_DX-1]    = 0x84;
        rock_render_line(phys_y);
    }
    // 初期状態は render_pos++ に戻す
    render_pos++;
}
// ----------------------------------------------------------
// スクロール
//   dy < 0 : 上へ 1dot
//   dy > 0 : 下へ 1dot
// ----------------------------------------------------------
void map_scroll(int dy)
{
    int phys_y;
    if (dy < 0)
    {
        if (render_pos == 0) return;
        // 上へ 1dot
        render_pos--;
        // 結果が偶数ならバッファを1行上にコピー(memcpyはコピーが重なるためNG)
        if ((render_pos & 1) == 0)
        {
            memmove(&render_buf_even[1][0], &render_buf_even[0][0], RENDER_DX * (RENDER_DY - 1));
            memmove(&render_buf_odd[1][0], &render_buf_odd[0][0], RENDER_DX * (RENDER_DY - 1));
        }
        phys_y = 0;
        rock_render_line(phys_y);
    }
    else if (dy > 0)
    {
 if (render_pos == 28) return;
        // 下へ 1dot
        render_pos++;
        // 結果が奇数ならバッファ全体を1行下にコピー
        if (render_pos & 1)
        {
            memcpy(&render_buf_even[0][0], &render_buf_even[1][0], RENDER_DX * (RENDER_DY - 1));
            memcpy(&render_buf_odd[0][0], &render_buf_odd[1][0], RENDER_DX * (RENDER_DY - 1));
        }
        phys_y = RENDER_DY - 1;
        rock_render_line(phys_y);
    }
}
// ----------------------------------------------------------
// VRAM へ描画
// ----------------------------------------------------------
void map_draw(void)
{
    int phys_y;
    unsigned char *curr_bufp;
    unsigned char *pos = getscrnaddr(0, 4);
    if (render_pos & 1)
    {
        curr_bufp = &render_buf_odd[0][0];
    }
    else
    {
        curr_bufp = &render_buf_even[0][0];
    }
    for (phys_y = 0; phys_y < RENDER_DY; phys_y++)
    {
        memcpy(pos, curr_bufp, RENDER_DX);
        pos += D_DX;
        curr_bufp += RENDER_DX;
    }
}
28ドット分スクロールした結果
前回が14秒、今回が3秒程度かかってります。
約4倍高速化された事となります。






お気に入りの記事を「いいね!」で応援しよう

最終更新日  2026.04.03 16:18:50 コメントを書く
[ZX81C言語でのプログラム開発] カテゴリの最新記事


【毎日開催】
15記事にいいね!で1ポイント
10秒滞在
いいね! -- / --
おめでとうございます!
ミッションを達成しました。
※「ポイントを獲得する」ボタンを押すと広告が表示されます。
x
X

© Rakuten Group, Inc.
X
Design a Mobile Website
スマートフォン版を閲覧 | PC版を閲覧
Share by: