非専門的シンギュラリティー研究所

無限に動き続けるシステムを表す方法を AI なども使って考えていきます。

X68000(33)

インラインアセンブラから参照するグローバル変数とそれを設定する関数を追加しました。これらの変数は

  • スーパーバイザーモードで参照するとき
  • IOCS コールでアドレスを渡すとき

に使います。このような場合、グローバル変数で渡す以外の方法がわからないのでこのようにしています。

グローバル変数の定義

// インラインアセンブラで使うためのグローバル変数の定義
int16_t g_color;
int32_t g_x1, g_y1, g_x2, g_y2, g_x3, g_y3, g_w, g_h, g_w2, g_rx, g_ry;
int32_t g_start_angle, g_sweep_angle;
int32_t g_r, g_hbyw, g_end_angle, g_sc1, g_sc2, g_sc3, g_sc4, g_page;
uint8_t g_mx, g_my, g_font_size, g_rotation;
char g_text[MAX_DRAW_TEXT];
int32_t g_gsize = 0;        // グラフィックス領域の幅 0: 512x512, 1: 1024x1024
int32_t g_gaddr = 0xc00000; // グラフィックス用メモリーの先頭のアドレス
uint16_t g_xargs[MAX_XARGS];
void global_copy_args(uint16_t* args, int argsize) {
    for (int i = 0; i < argsize; ++i) {
        g_xargs[i] = args[i];
    }
}
void global_copy_args(int16_t* args, int argsize) {
    for (int i = 0; i < argsize; ++i) {
        g_xargs[i] = args[i];
    }
}
uint16_t global_get_arg(int index) {
    if (index < 0 || index >= MAX_XARGS) {
        return 0; // 範囲外のインデックスは0を返す
    }
    return g_xargs[index];
}
void global_set_crtmode(int mode) {
    if (mode >= 4 && mode <= 15) {
        g_gsize = 0;
    }
    else {
        g_gsize = 1;
    }
}
void global_set_apage(int page) {
    g_gaddr = 0xc00000 + (page * 0x80000); // ページごとにアドレスを設定
}
#ifdef PACKED_STRUCT
struct __attribute__((packed)) PaintStruct {
#else
struct PaintStruct {
#endif
    uint16_t x;
    uint16_t y;
    uint16_t color;
    char* start_work;
    char* end_work;
};
PaintStruct g_paint = { 0, 0, 0, nullptr, nullptr };
PaintStruct* p_paint = &g_paint;
#ifdef PACKED_STRUCT
struct __attribute__((packed)) DrawStringStruct {
#else
struct DrawStringStruct {
#endif
    uint16_t x;
    uint16_t y;
    const char* str;
    uint8_t mx;
    uint8_t my;
    uint16_t color;
    uint8_t font_size;
    uint8_t rotation;
};
DrawStringStruct g_draw_string = { 0, 0, nullptr, 0, 0, 0, 0, 0 };
DrawStringStruct* p_draw_string = &g_draw_string;

以下の関数もグローバル変数を参照するように変更しました。

長方形を描画する関数

void drawboxx(int x1, int y1, int w, int h, COLORREF color)
{
    asm(
        "move.l   %0, %%d1\n\t"
        "move.l   %1, %%d2\n\t"
        "move.l   %2, %%d3\n\t"
        "move.l   %3, %%d4\n\t"
        "move.l   %4, %%d5\n\t"
        "clr.l	  -(%%sp)\n\t"
        "dc.w	  0xff20\n\t"      // _SUPER (スーパーバイザーモードへ)
        "move.l   %%d0, (%%sp)\n\t"

        "movea.l  %%d1, %%a0\n\t"
        "adda.l   %%d1, %%a0\n\t"  // a0 = x1 * 2
        "moveq.l  #10, %%d0\n\t"
        "add.l    g_gsize, %%d0\n\t"
        "lsl.l    %%d0, %%d2\n\t"  // d2 = y1 * (1024 << g_gsize)
        "adda.l   %%d2, %%a0\n\t"  // a0 = x1 * 2 + y1 * (1024 << g_gsize)
        "adda.l   g_gaddr, %%a0\n\t" // a0 = g_gaddr + x1 * 2 + y1 * (1024 << g_gsize)
        "move.l   %%a0, %%a1\n\t"

        "move.l   %%a0, -(%%sp)\n\t"

        "move.l   %%d4, %%d2\n\t"
        "lsl.l    %%d0, %%d2\n\t"  // d2 = h * (1024 << g_gsize)
        "adda.l   %%d2, %%a1\n\t"  // a1 = x1 * 2 + (y1 + h) * (1024 << g_gsize)

        "move.l   %%d3, %%d6\n\t"  // d6 = w (x方向のカウンター)
        "boxxxlp:\n\t"
        "move.w   %%d5, (%%a0)+\n\t"
        "move.w   %%d5, (%%a1)+\n\t"
        "dbra     %%d6, boxxxlp\n\t" // x方向のループ

        "move.l   (%%sp)+, %%a0\n\t" // a0 = g_gaddr + x1 * 2 + y1 * (1024 << g_gsize)
        "move.l   %%a0, %%a1\n\t"
        "adda.l   %%d3, %%a1\n\t"
        "adda.l   %%d3, %%a1\n\t"  // a1 = g_gaddr + (x1 + w) * 2 + y1 * (1024 << g_gsize)

        "moveq.l  #1, %%d2\n\t"
        "lsl.l    %%d0, %%d2\n\t"  // d2 = (1024 << g_gsize) (y方向の差分)

        "move.l   %%d4, %%d7\n\t"  // d7 = h (y方向のカウンター)
        "boxxylp:\n\t"
        "move.w   %%d5, (%%a0)\n\t"
        "adda.l   %%d2, %%a0\n\t"
        "move.w   %%d5, (%%a1)\n\t"
        "adda.l   %%d2, %%a1\n\t"
        "dbra     %%d7, boxxylp\n\t" // y方向のループ

        "dc.w	  0xff20\n\t"      // _SUPER (スーパーバイザーモードから戻る)
        "addq.l   #4,%%sp\n\t"
        :
        : "r"(x1), "r"(y1), "r"(w), "r"(h), "r"(color) // 入力
        : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "a0", "a1" // 使用するレジスタ
    );
}

塗りつぶした長方形を描画する関数

void fillboxx(int x1, int y1, int w, int h, COLORREF color)
{
    asm(
        "move.l   %0, %%d1\n\t"
        "move.l   %1, %%d2\n\t"
        "move.l   %2, %%d3\n\t"
        "move.l   %3, %%d4\n\t"
        "move.l   %4, %%d5\n\t"

        "clr.l	  -(%%sp)\n\t"
        "dc.w	  0xff20\n\t"      // _SUPER (スーパーバイザーモードへ)
        "move.l   %%d0, (%%sp)\n\t"

        "movea.l  %%d1, %%a0\n\t"
        "adda.l   %%d1, %%a0\n\t"  // a0 = x1 * 2
        "moveq.l  #10, %%d0\n\t"
        "add.l    g_gsize, %%d0\n\t"
        "lsl.l    %%d0, %%d2\n\t"  // d2 = y1 * (1024 << g_gsize)
        "adda.l   %%d2, %%a0\n\t"  // a0 = x1 * 2 + y1 * (1024 << g_gsize)
        "adda.l   g_gaddr, %%a0\n\t" // a0 = g_gaddr + x1 * 2 + y1 * (1024 << g_gsize)
        "move.l   %%a0, %%a1\n\t"

        "moveq.l  #1, %%d2\n\t"
        "lsl.l    %%d0, %%d2\n\t"  // d2 = (1024 << g_gsize) (y方向の差分)

        "move.l   %%d4, %%d7\n\t"  // d7 = h (y方向のカウンター)
        "fillxylp:\n\t"
        "move.l   %%d3, %%d6\n\t"  // d6 = w (x方向のカウンター)
        "fillxxlp:\n\t"

        "move.w   %%d5, (%%a0)+\n\t"

        "dbra     %%d6, fillxxlp\n\t" // x方向のループ
        "adda.l   %%d2, %%a1\n\t"
        "move.l   %%a1, %%a0\n\t"
        "dbra     %%d7, fillxylp\n\t" // y方向のループ

        "dc.w	  0xff20\n\t"      // _SUPER (スーパーバイザーモードから戻る)
        "addq.l   #4,%%sp\n\t"
        :
        : "r"(x1), "r"(y1), "r"(w), "r"(h), "r"(color) // 入力
        : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "a0", "a1" // 使用するレジスタ
    );
}