川合のプログラミング言語自作のためのテキスト第三版#9a

  • (by K, 2021.03.24)

(1) HL-9a

  • 今回は、HL-9に対して、いくつかの命令を意図的に無視することにより、C言語で書かれたプログラムをそのまま実行できるようにしたいと思います。
  • しかし任意のC言語プログラムが実行できるわけではなく、HL-9aでも普通のC言語でもどちらでも動くように書かれたプログラムだけが実行可能です。HL-9aの能力を超えた内容が含まれているときはうまく動きません。
  • これは真面目な開発であるというよりは、ちょっとした遊びというか余興というか、悪ふざけというか、いたずらみたいなものです。だからこんなことはけしかん、などと怒らないでください。
  • 言語を自作しているからこその遊びです。
    //の扱い行末まで無視するこれは余興じゃなくて本来必要な機能
    #include行行末まで無視する#include <acl.c>を読み飛ばす想定
    変数宣言構文セミコロンまで無視するHL-9aは配列以外は宣言なしで使えるので
    void aMain() {中身は無視しないが、この記述そのものは無視するまだ関数に対応していないので
    上記に対応する }中身は無視しないが、この記述そのものは無視する
  • HL-9aでは、#includeを「#」と「include」に分けて認識して、#は何もしない命令として読み飛ばし、includeを//と同じ扱いとして、行末までのコメントにしています。
  • 「行末まで」の処理は、lexerを抜けてしまうと改行コードが消えてしまうので、lexerの中でやることにします。
#include <acl.c>

typedef unsigned char *String;	// こう書くと String は unsigned char * の代用になる.

int loadText(String path, String t, int siz) → HL-4と同じなので省略

///////////////////////////////////////////////////////////////////////////////

#define MAX_TC  1000 // トークンコードの最大値.
String ts[MAX_TC + 1]; // トークンの内容(文字列)を記憶.
int tl[MAX_TC + 1]; // トークンの長さ.
unsigned char tcBuf[(MAX_TC + 1) * 10]; // トークン1つ当たり平均10バイトを想定.
int tcs = 0, tcb = 0;

AInt var[MAX_TC + 1];	// 変数.

int getTc(String s, int len) → HL-8aと同じなので省略

///////////////////////////////////////////////////////////////////////////////

int isAlphabetOrNumber(unsigned char c) → HL-2と同じなので省略

int lexer(String s, int tc[])
{
    int i = 0, j = 0, len; // i:今s[]のどこを読んでいるか、j:これまでに変換したトークン列の長さ.
    for (;;) {
        (中略)
        } else {
            printf("syntax error : %.10s\n", &s[i]);
            exit(1);
        }
+       if (strncmp(&s[i], "//", 2) == 0) {	// コメント.
+comment:
+           while (s[i] != 0 && s[i] != '\n')
+               i++;
+           continue;
+       }
+       if (len == 7 && strncmp(&s[i], "include", 7) == 0) goto comment; // include をコメント扱いする(=無視する).
        tc[j] = getTc(&s[i], len);
        i += len;
        j++;
    }
}

int tc[10000];	// トークンコード.

enum { TcSemi = 0, TcDot, TcWiCard, Tc0, Tc1, Tc2, Tc3, Tc4, Tc5, Tc6, Tc7, Tc8, TcBrOpn, TcBrCls, TcSqBrOpn, TcSqBrCls, TcCrBrOpn, TcCrBrCls,
    TcEEq, TcNEq, TcLt, TcGe, TcLe, TcGt, TcPlus, TcMinus, TcAster, TcSlash, TcPerce, TcAnd, TcShr, TcPlPlus, TcEqu,
    TcComma, TcExpr, TcExpr0, TcTmp0, TcTmp1, TcTmp2, TcTmp3, TcTmp4, TcTmp5, TcTmp6, TcTmp7, TcTmp8, TcTmp9 };

char tcInit[] = "; . !!* 0 1 2 3 4 5 6 7 8 ( ) [ ] { } == != < >= <= > + - * / % & >> ++ = , !!** !!*** _t0 _t1 _t2 _t3 _t4 _t5 _t6 _t7 _t8 _t9";

///////////////////////////////////////////////////////////////////////////////

int phrCmp_tc[32 * 100], ppc1, wpc[9], wpc1[9]; // ppc1:一致したフレーズの次のトークンをさす, wpc[]:ワイルドカードのトークンの場所をさす.

int phrCmp(int pid, String phr, int pc) → HL-7と同じなので省略

///////////////////////////////////////////////////////////////////////////////

typedef AInt *IntP; // こう書くと IntP は AInt * の代わりに使えるようになる.

enum { OpCpy = 0, OpCeq, OpCne, OpClt, OpCge, OpCle, OpCgt, OpAdd, OpSub, OpMul, OpDiv, OpMod, OpAnd, OpShr, 
    OpAdd1, OpNeg, OpGoto, OpJeq, OpJne, OpJlt, OpJge, OpJle, OpJgt, OpLop, OpPrint, OpTime, OpEnd,
    OpPrints, OpAryNew, OpAryInit, OpArySet, OpAryGet, OpOpnWin, OpSetPix0, OpM64s, OpRgb8, OpWait,
    OpXorShift, OpGetPix, OpFilRct0, OpPrm, OpF16Sin, OpF16Cos, OpInkey, OpDrwStr0, OpGprDec, OpBitBlt };

IntP ic[10000], *icq; // ic[]:内部コード、icq:ic[]への書き込み用ポインタ.

void putIc(int op, IntP p0, IntP p1, IntP p2, IntP p3) → HL-6と同じなので省略

///////////////////////////////////////////////////////////////////////////////

char tmp_flag[10]; // 一時変数の利用状況を管理.

int tmpAlloc() → HL-7と同じなので省略

void tmpFree(int i) → HL-7と同じなので省略

///////////////////////////////////////////////////////////////////////////////

int epc, epc1;	// exprのためのpcとpc1.

int exprSub(int priority);	// exprSub1()が参照するので、プロトタイプ宣言.
int expr(int j);
int phrCmpPutIc(int pid, String phr, int pc, int *pi, int lenExpr, int op, int *err);

int exprSub1(int i, int priority, int op) → HL-7と同じなので省略

int exprSub(int priority) → HL-9と同じなので省略

int expr(int j) → HL-7と同じなので省略

///////////////////////////////////////////////////////////////////////////////

enum { IfTrue = 0, IfFalse = 1 };

void ifgoto(int i, int not, int label) → HL-8と同じなので省略

int tmpLabelNo;

int tmpLabelAlloc() → HL-8と同じなので省略

#define BInfSiz		10

int binf[BInfSiz * 100], bd, lbd; // binf:block-info, bd:block-depth, lbd:loop-block-depth

enum { BlkIf = 1, BlkFor, BlkMain }; // BlkMainをHL-9aで追加.
enum { IfLabel0 = 1, IfLabel1 };
enum { ForLopBgn = 1, ForCont, ForBrk, ForLbd0, ForWpc01, ForWpc11, ForWpc02, ForWpc12 };

int phrCmpPutIc(int pid, String phr, int pc, int *pi, int lenExpr, int op, int *err) → HL-9と同じなので省略

///////////////////////////////////////////////////////////////////////////////

int compile(String s)
{
    (中略)
        } else if (phrCmpPutIc(28, "bitblt(!!***8, !!**0, !!**1, !!**2, !!**3, !!**4);",           pc, 0, 5, OpBitBlt,  &e0)) {
+       } else if (phrCmpPutIc(29, "printTime();", pc, 0, 0, OpTime, &e0)) { // time;と同じ(C言語っぽく書けるようにした)
+       } else if (phrCmp(30, "void aMain() {", pc)) {
+           bd += BInfSiz;
+           binf[bd] = BlkMain; // ただ認識しているだけで、なにもしてない.
+       } else if (phrCmp(31, "}", pc) && binf[bd] == BlkMain) {
+           bd -= BInfSiz; // ただコードブロックを閉じているだけ.
+       } else if (phrCmp(32, "#", pc)) { // 何もせずに無視.
+       } else if (phrCmp(33, "int", pc) || phrCmp(34, "AWindow", pc)) {
+           while (tc[pc] != TcSemi) // セミコロンまでを読み飛ばす.
+               pc++;
+           ppc1 = pc;
        } else if (phrCmp( 8, "!!***0;", pc)) {	// これはかなりマッチしやすいので最後にする.
            e0 = expr(0);
    (中略)
}

AWindow *win;
 
void exec() → HL-9と同じなので省略

int run(String s) → HL-6と同じなので省略

///////////////////////////////////////////////////////////////////////////////

void aMain() → HL-9と同じなので省略
  • プログラムは772行になりました。今回は少ししか増えませんでした。まあ大したことはしていない(いろいろ読み飛ばして無視しているだけ)なので、当然と言えば当然の結果です。
  • 今回は、くだらないことしかやっていないので、改造内容の説明は省略して、このHL-9a向けのサンプルプログラムを示したいと思います。

(2) プログラム例 (HL-9aで実行できるプログラム)

  • (以下のプログラムは、aclライブラリがあれば、普通のCコンパイラでコンパイルして実行することもできるようになっています。)

  • mandel.c
    • マンデルブロー集合の描画プログラムです。上記説明にある通り、#include文はHL-9aにとってはただのコメントですので、実行に際してacl.cやtl9builtin.cが必要になったりはしません。
      #include <acl.c>
      #include "tl9builtin.c"
      
      void aMain()
      {
          AWindow *w;
          int x, y, sx, sy, cx, cy, zx, zy, xx, yy, t, n, sn, c;
          w = aOpenWin(512, 384, "mandel", 1);
          for (y = 0; y < 384; y++) {
              for (x = 0; x < 512; x++) {
                  sn = 0;
                  for (sx = 0; sx < 4; sx++) {
                      cx = (x * 4 + sx) * 56 + 4673536;
                      for (sy = 0; sy < 4; sy++) {
                          cy = (y * 4 + sy) * -56 - 124928;
                          zx = cx; zy = cy;
                          for (n = 1; n < 447; n++) {
                              xx = mul64shr(zx, zx, 24);
                              yy = mul64shr(zy, zy, 24);
                              t = xx + yy;
                              if (t > 0x4000000) break;
                              zy = mul64shr(zy, zx, 23);
                              zx = xx + cx;
                              zy = zy + cy;
                              zx = zx - yy;
                          }
                          sn = sn + n;
                      }
                  }
                  n = sn >> 4;
                  c = aRgb8(n, 0, 0);
                  if (n > 255) {
                      c = aRgb8(0, 0, 0);
                      if (n != 447) {
                          c = aRgb8(255, n - 255, 0);
                      }
                  }
                  aSetPix0(w, x, y, c);
              }
          }
          printTime();
          aWait(-1);
      }
      http://k.osask.jp/files/esb20190827b.png

  • maze.c
    • 迷路作成(穴掘り法)のプログラムです。上記説明にある通り、#include文はHL-9aにとってはただのコメントですので、実行に際してacl.cが必要になったりはしません。
    • 乱数で迷路を作っているので、実行するたびに違う迷路が出てきます。
      #include <acl.c>
      
      void aMain()
      {
          AWindow *w;
          int i, x, y, xx, yy, d0, d1, d2, d3, d, dd;
          w = aOpenWin(752, 496, "maze", 1);
          aFillRect0(w, 752, 496, 0, 0, 0x00ff00);
          aFillRect0(w, 16, 16, 16, 16, 0x000000);
          for (i = 0; i < 1000000; i++) {
              x = ((aXorShift32() & 0x7fffffff) % 23) * 2 + 1;
              y = ((aXorShift32() & 0x7fffffff) % 15) * 2 + 1;
              if (aGetPix(w, x * 16, y * 16) == 0x000000) {
                  for (;;) {
                      d0 = d1 = d2 = d3 = 0;
                      xx = x * 16;
                      yy = y * 16;
                      aFillRect0(w, 16, 16, xx, yy, 0x000000);
                      if (x != 45) { d0 = (aGetPix(w, xx + 16, yy) != 0) * (aGetPix(w, xx + 32, yy) != 0); }
                      if (x !=  1) { d1 = (aGetPix(w, xx - 16, yy) != 0) * (aGetPix(w, xx - 32, yy) != 0); }
                      if (y != 29) { d2 = (aGetPix(w, xx, yy + 16) != 0) * (aGetPix(w, xx, yy + 32) != 0); }
                      if (y !=  1) { d3 = (aGetPix(w, xx, yy - 16) != 0) * (aGetPix(w, xx, yy - 32) != 0); }
                      d = d0 + d1 + d2 + d3;
                      if (d == 0) break;
                      dd = (aXorShift32() & 0x7fffffff) % d;
                      if (d0) { if (dd == 0) { aFillRect0(w, 16, 16, xx + 16, yy, 0x000000); x = x + 2; } dd = dd - 1; }
                      if (d1) { if (dd == 0) { aFillRect0(w, 16, 16, xx - 16, yy, 0x000000); x = x - 2; } dd = dd - 1; }
                      if (d2) { if (dd == 0) { aFillRect0(w, 16, 16, xx, yy + 16, 0x000000); y = y + 2; } dd = dd - 1; }
                      if (d3) { if (dd == 0) { aFillRect0(w, 16, 16, xx, yy - 16, 0x000000); y = y - 2; } dd = dd - 1; }
                  }
              }
          }
          aWait(-1);
      }
      http://essen.osask.jp/download/esb20191120a.png

  • kcube.c
    • Kにとっては定番の、キューブ回転プログラムです。上記説明にある通り、#include文はHL-9aにとってはただのコメントですので、実行に際してacl.cやtl9builtin.cが必要になったりはしません。
      #include <acl.c>
      #include "tl9buitin.c"
      
      int vertx[8] ={ 2, 2, 2, 2, 0, 0, 0, 0 };
      int verty[8] ={ 2, 2, 0, 0, 2, 2, 0, 0 };
      int vertz[8] ={ 2, 0, 2, 0, 2, 0, 2, 0 };
      int squar[24] = { 0,4,6,2, 1,3,7,5, 0,2,3,1, 0,1,5,4, 4,5,7,6, 6,7,3,2 };
      int col[6] = { 0xff0000, 0x00ff00, 0xffff00, 0x0000ff, 0xff00ff, 0x00ffff };
      
      void aMain()
      {
          int vx[8]; int vy[8]; int vz[8];
          int centerz4[6];
          int scx[8]; int scy[8];
          int buf0[160]; int buf1[160];
          int i, j, k, l, thx, thy, thz, xp, xa, yp, ya, zp, za, xt, yt, zt, t, m;
          int k0, k1, k2, e0x, e0y, e1x, e1y, l1, p0x, p0y, p1x, p1y, ymin, ymax, x, y, c;
          int dx, *buf, y0, y1;
          AWindow *w;
          w = aOpenWin(256, 160, "kcube", 1);
          for (i = 0; i < 8; i++) {
              vertx[i] = (vertx[i] - 1) * 50;
              verty[i] = (verty[i] - 1) * 50;
              vertz[i] = (vertz[i] - 1) * 50;
          }
          thx = thy = thz = 0;
          for (;;) {
              thx = (thx + 182) & 0xffff;
              thy = (thy + 273) & 0xffff;
              thz = (thz + 364) & 0xffff;
              xp = ff16cos(thx); xa = ff16sin(thx);
              yp = ff16cos(thy); ya = ff16sin(thy);
              zp = ff16cos(thz); za = ff16sin(thz);
              for (i = 0; i < 8; i++) {
                  zt = vertz[i] * xp           + verty[i] * xa;
                  yt = verty[i] * xp           - vertz[i] * xa;
                  xt = vertx[i] * yp           + mul64shr(zt, ya, 16);
                  vz[i] = mul64shr(zt, yp, 16) - vertx[i] * ya;
                  vx[i] = mul64shr(xt, zp, 16) - mul64shr(yt, za, 16);
                  vy[i] = mul64shr(yt, zp, 16) + mul64shr(xt, za, 16);
              }
              for (l = i = 0; i < 6; i++) {
                  centerz4[i] = vz[squar[l]] + vz[squar[l + 1]] + vz[squar[l + 2]] + vz[squar[l + 3]] + 0x70000000;
                  l = l + 4;
              }
              aFillRect0(w, 160, 160, 48, 0, 0x000000);
              for (i = 0; i < 8; i++) {
                  t = (vz[i] + 13107200) >> 16;
                  t = 4915200 / t;
                  scx[i] = mul64shr(vx[i], t, 31) + 128;
                  scy[i] = mul64shr(vy[i], t, 31) +  80;
              }
              for (;;) {
                  m = j = 0;
                  for (i = 0; i < 6; i++) {
                      t = centerz4[i];
                      if (m < t) {
                          m = t;
                          j = i;
                      }
                  }
                  if (m == 0) break;
                  l = j * 4; centerz4[j] = 0;
                  k0 = squar[l];
                  k1 = squar[l + 1];
                  k2 = squar[l + 2];
                  e0x = vx[k1] - vx[k0];
                  e0y = vy[k1] - vy[k0];
                  e1x = vx[k2] - vx[k1];
                  e1y = vy[k2] - vy[k1];
                  if (mul64shr(e0x, e1y, 16) <= mul64shr(e0y, e1x, 16)) {
                      l1 = l + 4;
                      k = squar[l + 3];
                      p0x = scx[k]; p0y = scy[k];
                      ymin = 99999; ymax = 0;
                      for (; l < l1; l++) {
                          k = squar[l];
                          p1x = scx[k]; p1y = scy[k];
                          if (ymin > p1y) { ymin = p1y; }
                          if (ymax < p1y) { ymax = p1y; }
                          if (p0y != p1y) {
                              if (p0y < p1y) {
                                  buf = buf0; y0 = p0y; y1 = p1y; dx = p1x - p0x; x = p0x;
                              } else {
                                  buf = buf1; y0 = p1y; y1 = p0y; dx = p0x - p1x; x = p1x;
                              }
                              x = x * 65536;
                              dx = dx * 65536;
                              dx = dx / (y1 - y0);
                              if (dx >= 0) {
                                  x = x + 0x8000;
                              } else {
                                  x = x - 0x8000;
                              }
                              ++y1;
                              for (y = y0; y < y1; y++) {
                                  buf[y] = x >> 16;
                                  x = x + dx;
                              }
                          }
                          p0x = p1x; p0y = p1y;
                      }
                      c = col[j];
                      ++ymax;
                      for (y = ymin; y < ymax; y++) {
                          p0x = buf0[y];
                          p1x = buf1[y];
                          if (p0x <= p1x) {
                              aFillRect0(w, p1x - p0x + 1, 1, p0x, y, c);
                          } else {
                              aFillRect0(w, p0x - p1x + 1, 1, p1x, y, c);
                          }
                      }
                  }
              }
              aWait(50);
              if (aInkey(w, 1) != 0) break;
          }
      }
      http://essen.osask.jp/download/esb20191120c.png http://essen.osask.jp/download/esb20191120d.png http://essen.osask.jp/download/esb20191120e.png

  • invader.c
    • Kにとっては定番の、インベーダゲームのプログラムです。上記説明にある通り、#include文はHL-9aにとってはただのコメントですので、実行に際してacl.cやtl9builtin.cが必要になったりはしません。
      #include <acl.c>
      #include "tl9builtin.c"
      
      int fght[384] = {
          0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,
          0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,
          0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,
          0,0,0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
          0,0,0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
          0,0,0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
          0,0,0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
          0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,
          0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,
          0,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,0,
          0,1,0,0,0,1,1,1,1,1,1,0,0,1,1,1,1,1,1,0,0,0,1,0,
          0,1,0,0,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,0,0,1,0,
          0,1,0,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,0,1,0,
          0,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,0,
          0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
      };
      
      int invd[512] = {
          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
          0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,
          0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,
          0,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,0,
          0,1,0,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,0,1,0,
          0,1,0,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,0,1,0,
          0,1,0,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,0,1,0,
          0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
          0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,
          0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,
          0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,
          0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,
          0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,
          0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,
          0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,
          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
      };
      
      void aMain()
      {
          int inv[192];
          int i, j, k, score, pnt, mwt0, fx, idir, wunit, ix, iy, invlin, lx = 0, ly, lwt, mwt, high = 0;
          AWindow *w;
          w = aOpenWin(324, 228, "graphics", 1);
          for (i = 0; i < 384; i++) {
              fght[i] = fght[i] * 0x00ffff;
          }
          for (i = 0; i < 512; i++) {
              invd[i] = invd[i] * 0x00ff00;
          }
      restart:
          score = 0; pnt = 1; mwt0 = 20; fx = 18;
      nxtinv:
          ix = 7; iy = 1; invlin = 5;
          ly = 0; lwt = 0; mwt = mwt0;
          idir = 1; wunit = 1024;
          for (i = 0; i < 6; i++) {
              for (j = 0; j < 26; j++) {
                   inv[i * 32 + j] = j % 5;
              }
          }
          for(;;) {
              // 表示.
              aFillRect0(w, 324, 228, 0, 0, 0x000000);
              aDrawStr0(w,  34, 2,    0xffffff, 0x000000, "SCORE:             HIGH:");
              gprintDec(w,  82, 2, 6, 0xffffff, 0x000000, score);
              gprintDec(w, 226, 2, 6, 0xffffff, 0x000000, high);
              bitblt(w, 24, 16, fx * 8 + 2, 13 * 16 + 2, fght);
              for (i = 0; i < 6; i++) {
                  for (j = 0; j < 26; j++) {
                      if (inv[i * 32 + j] == 1) {
                          bitblt(w, 32, 16, (ix + j) * 8 + 2, (iy + i) * 16 + 2, invd);
                      }
                  }
              }
              if (ly != 0) {
                  aFillRect0(w, 2, 14, lx * 8 + 5, ly * 16 + 3, 0xffff00);
              }
      
              // インベーダ全滅判定.
              for (;;) {
                  for (i = 0; i < 26; i++) {
                      if (inv[invlin * 32 + i] != 0) goto skip0;
                  }
                  invlin = invlin - 1;
                  if (invlin < 0) {
                      mwt0 = mwt0 - mwt0 / 3;
                      aWait(1024);
                      goto nxtinv;
                  }
              }
      skip0:
      
              // wait処理.
              aWait(wunit);
              wunit = 40;
              lwt = lwt - 1;
      
              // キー入力.
              j = 0;
              for (;;) {
                  i = aInkey(w, 1);
                  if (i == 0) break;
                  if (i == 27) goto end; // esc
                  if (i == 0x1024) { j = -1; }
                  if (i == 0x1025) { j =  1; }
                  if (i == 0x1026) { i = 32; }
                  if (i == 32) {
                      if (lwt <= 0) {
                          lwt = 15;
                          lx = fx + 1;
                          ly = 13;
                      }
                  }
              }
      
              // 自機の移動.
              i = fx + j;
              if (i >= 0) {
                  if (i <= 37) {
                      fx = i;
                  }
              }
      
              // レーザ移動.
              if (ly > 0) {
                  ly = ly - 1;
                  if (ly == 0) {
                      pnt = pnt - 10;
                      if (pnt < 1) {
                          pnt = 1;
                      }
                  }
              }
      
              // あたり判定.
              j = lx - ix;
              k = ly - iy;
              if (k >= 0) {
                  if (k <= 5) {
                      if (j >= 0) {
                          if (j < 24) {
                              i = inv[k * 32 + j];
                              if (i > 0) {
                                  ly = 0;
                                  j = j - i;
                                  for (i = 0; i < 6; i++) {
                                      inv[k * 32 + j + i] = 0;
                                  }
                                  score = score + pnt;
                                  pnt++;
                                  if (high < score) {
                                      high = score;
                                  }
                              }
                          }
                      }
                  }
              }
      
              // インベーダ移動.
              if (mwt > 0) {
                  mwt = mwt - 1;
              } else {
                  mwt = mwt0;
                  ix = ix + idir;
                  if (ix >= 0) {
                      if (ix <= 14) continue;
                  }
                  if (iy + invlin == 12) {
                      aDrawStr0(w, 122, 98, 0xff0000, 0x000000, "GAME OVER");
                      for (;;) {
                          aWait(128);
                          i = aInkey(w, 1);
                          if (i == 10) break;
                          if (i == 27) goto end; // esc
                      }
                      goto restart;
                  }
                  idir = idir * -1;
                  iy++;
                  ix = ix +idir;
              }
          }
      end:
          aWait(-1);
      }
      http://k.osask.jp/files/esb20191218d.png

(3) "tl9builtin.c"の中身

  • tl9builtin.cは、上記プログラム例をgccなどの普通のコンパイラでコンパイルするときにのみ必要になるファイルで、HL-9aで実行するときには不要です。
  • HL-9aの組み込み関数の処理に相当する処理が書いてあります。
    static inline int mul64shr(int i,int j, int k)
    {
        return ((long long) i) * ((long long) j) >> k;
    }
    
    static inline void printTime()
    {
        printf("time: %.3f[sec]\n", clock() / (double) CLOCKS_PER_SEC);
    }
    
    static inline int ff16sin(int x)
    {
        return (int) (sin(x * (2 * 3.14159265358979323 / 65536)) * 65536);
    }
    
    static inline int ff16cos(int x)
    {
        return (int) (cos(x * (2 * 3.14159265358979323 / 65536)) * 65536);
    }
    
    void gprintDec(AWindow *w, int x, int y, int l, int c, int b, int i)
    {
        char s[100];
        sprintf(s, "%*d", l, i);
        aDrawStr0(w, x, y, c, b, s);
    }
    
    void bitblt(AWindow *w, int sx, int sy, int x, int y, int *p)
    {
        AInt32 *q = &w->buf[x + y * w->xsiz];
        int i, j;
        for (j = 0; j < sy; j++) {
            for (i = 0; i < sx; i++) {
                q[i] = p[i];
            }
            p += sx;
            q += w->xsiz;
        }
    }

次回に続く

こめんと欄


コメントお名前NameLink

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2021-03-26 (金) 17:25:24 (18d)