[1] Windowsでグラフィックを出すための雑なプログラム: a4_t0001.c
// #include <windows.h> してあることが前提.
a_class(a_Win) {
char title[256];
int xsz, ysz;
uint32_t *buf;
HWND hWin;
HINSTANCE hInst;
BITMAPINFO bmi;
};
a_static a_Win *a_Win_opened = NULL;
a_static LRESULT CALLBACK a_Win_wndProc(HWND hw, unsigned int msg, WPARAM wp, LPARAM lp)
{
if (msg == WM_CLOSE) return 0; // closeボタンを無視.
if (msg == WM_DESTROY) { PostQuitMessage(0); return 0; }
a_Win *w = a_Win_opened;
if (w == NULL || w->hWin != hw)
return DefWindowProc(hw, msg, wp, lp);
if (msg == WM_PAINT) {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hw, &ps);
SetDIBitsToDevice(hdc, 0, 0, w->xsz, w->ysz, 0, 0, 0, w->ysz, w->buf, &w->bmi, DIB_RGB_COLORS);
EndPaint(hw, &ps);
return 0;
}
return DefWindowProc(hw, msg, wp, lp);
}
a_static int a_Win_winThread(a_Win *w)
{
WNDCLASSEX wc;
RECT r;
int i;
MSG msg;
wc.cbSize = sizeof (WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = a_Win_wndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = w->hInst;
wc.hIcon = (HICON) LoadImage(NULL, MAKEINTRESOURCE(IDI_APPLICATION), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
wc.hIconSm = wc.hIcon;
wc.hCursor = (HCURSOR) LoadImage(NULL, MAKEINTRESOURCE(IDC_ARROW), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
wc.hbrBackground = (HBRUSH) COLOR_APPWORKSPACE;
wc.lpszMenuName = NULL;
wc.lpszClassName = w->title;
if (RegisterClassEx(&wc) == 0) return 1;
r.left = 0; r.top = 0;
r.right = w->xsz; r.bottom = w->ysz;
AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX, FALSE);
w->hWin = CreateWindowA(wc.lpszClassName, w->title, WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT, r.right - r.left, r.bottom - r.top, NULL, NULL, w->hInst, NULL);
if (w->hWin == NULL) return 1;
ShowWindow(w->hWin, SW_SHOW);
UpdateWindow(w->hWin);
for (;;) {
i = GetMessage(&msg, NULL, 0, 0);
if (i == 0 || i == -1) break; // エラーもしくは終了メッセージ.
// そのほかはとりあえずデフォルト処理で.
TranslateMessage(&msg);
DispatchMessage(&msg);
}
UnregisterClass(w->title, w->hInst);
return 0;
}
a_static void a_Win_ini(_argDef_ a_Win *w, int xsz, int ysz, const char *title, uint32_t c)
{
#if (a_DbgLv >= 2)
if (xsz < 192 || ysz < 64)
a_errExit("%s(%d): Win_ini: bad window size: xsz=%d, ysz=%d", a_fil, a_lin, xsz, ysz);
if (title == NULL || strlen(title) == 0 || strlen(title) >= 256)
a_errExit("%s(%d): Win_ini: bad window title", a_fil, a_lin);
#endif
w->buf = a_malloc(_arg_ xsz * ysz * sizeof (uint32_t));
int i;
for (i = 0; i < xsz * ysz; i++) { w->buf[i] = c; }
w->xsz = xsz; w->ysz = ysz;
strcpy(w->title, title);
w->bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
w->bmi.bmiHeader.biWidth = xsz;
w->bmi.bmiHeader.biHeight = - ysz;
w->bmi.bmiHeader.biPlanes = 1;
w->bmi.bmiHeader.biBitCount = 32;
w->bmi.bmiHeader.biCompression = BI_RGB;
a_Win_opened = w;
CreateThread(NULL, 0, (void *) a_Win_winThread, (void *) w, 0, (void *) &i);
Sleep(128);
}
a_static void a_Win_flushAll0(a_Win *w)
{
InvalidateRect(w->hWin, NULL, FALSE);
UpdateWindow(w->hWin);
}
[2] 上記の mandel くらいなら余裕で動かせるVM: tt0001a.c
#define a_Version 1
#include <acl4.c>
#include <windows.h>
#include "a4_t0001.c"
void myPut(Preprocessor_Put0 *w, VecChr *lin) // t0013b.cで作ったやつと同じ.
{
if (Preprocessor_isDirective(lin->p, lin->p + lin->n) != 0)
fprintf(stderr, "[err] %.*s", (int) lin->n, lin->p);
else
VecChr_puts(w->dst, lin->p, lin->p + lin->n);
}
int main(int argc, const char **argv)
{
if (argc < 2) return 1;
Preprocessor pp[1]; Preprocessor_ini(pp); // プリプロセッサの初期化.
pp->put = (void *) myPut; // 出力関数の変更.
Preprocessor_SourceFiles_addFile(pp->sfs, argv[1], strlen(argv[1])); // 入力ファイルを指定.
Preprocessor_SourceFiles_addFile(pp->sfs, "a4vm-asm-tt0001.h", 17); // 最初にこれをインクロードさせる.
VecChr vc[1]; VecChr_ini(vc); pp->put0->dst = vc; // 出力先のオブジェクトを指定.
Preprocessor_main(pp); Preprocessor_din(pp); // プリプロセッサ処理. およびメモリ開放.
Token0 t0[1]; Token0_ini1(t0);
t0->s = vc->p; t0->s1 = vc->p + vc->n;
Preprocessor_Eval ev[1]; ev->err = 0;
VecChr bin[1]; VecChr_ini(bin);
for (;;) {
intptr_t i = Preprocessor_eval(ev, t0, 0x7fff);
if (ev->err != 0) break;
VecChr_resizeDiff(_arg_ bin, sizeof (intptr_t)); ((intptr_t *) (bin->p + bin->n))[-1] = i;
Token1_get(t0);
if (t0->c != ',' && t0->c != ';') break;
}
intptr_t *bp = (intptr_t *) bin->p, bn = bin->n / sizeof (intptr_t), reg0[256], *reg, lab[256], pc;
for (pc = 0; pc < bn; pc += 4) {
if (bp[pc] == 0x01)
lab[bp[pc + 1]] = pc + 4; // Lbl_T(t)命令の次の命令を指す.
}
a_Win win[1]; win->buf = NULL;
clock_t tm0 = clock(); reg = reg0 + 256 - 16;
for (pc = 0;;) {
intptr_t op = bp[pc], a = bp[pc + 1], b = bp[pc + 2], c = bp[pc + 3], d, e, f; pc += 4;
switch (op) {
case 0x01: continue; // Lbl_T(t)
case 0x02: reg[a] = b; continue; // Lod_RI(r, i)
case 0x03: reg[a] = reg[b]; continue; // Lod_RR(r, s)
case 0x18: reg[a] <<= b; continue; // Shl_RI(r, i)
case 0x19: reg[a] <<= reg[b]; continue; // Shl_RR(r, s)
case 0x1a: reg[a] >>= b; continue; // Shr_RI(r, i)
case 0x1b: reg[a] >>= reg[b]; continue; // Shr_RR(r, s)
case 0x20: reg[a] += b; continue; // Add_RI(r, i)
case 0x21: reg[a] += reg[b]; continue; // Add_RR(r, s)
case 0x22: reg[a] -= b; continue; // Sub_RI(r, i)
case 0x23: reg[a] -= reg[b]; continue; // Sub_RR(r, s)
case 0x24: reg[a] *= b; continue; // Mul_RI(r, i)
case 0x25: reg[a] *= reg[b]; continue; // Mul_RR(r, s)
case 0x38: if (reg[b] < c) { pc = lab[a]; } continue; // Jlt_RI(r, i, t)
case 0x39: if (reg[b] < reg[c]) { pc = lab[a]; } continue; // Jlt_RR(r, s, t)
case 0x3a: if (reg[b] >= c) { pc = lab[a]; } continue; // Jge_RIT(r, i, t)
case 0x3b: if (reg[b] >= reg[c]) { pc = lab[a]; } continue; // Jge_RRT(r, s, t)
case 0x3c: if (reg[b] <= c) { pc = lab[a]; } continue; // Jle_RIT(r, i, t)
case 0x3d: if (reg[b] <= reg[c]) { pc = lab[a]; } continue; // Jle_RRT(r, s, t)
case 0x3e: if (reg[b] > c) { pc = lab[a]; } continue; // Jgt_RIT(r, i, t)
case 0x3f: if (reg[b] > reg[c]) { pc = lab[a]; } continue; // Jgt_RRT(r, s, t)
case 0x04: goto fin;
case 0x06: d = bp[pc + 1]; pc += 4; reg[a] = (intptr_t)(((int64_t)reg[b]*(int64_t)reg[c])>>d); continue;
case 0x08: a_Win_ini(_arg_ win, reg[a], reg[b], "graphic", 0); tm0 = clock(); continue;
case 0x09: win->buf[reg[b] * win->xsz + reg[a]] = reg[c]; continue;
case 0x36: reg[b]++; if (reg[b] < c) { pc = lab[a]; } continue; // IncJlt_RIT
case 0x00: case 0x05: case 0x07: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
case 0x26: case 0x27: case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x37: continue; // すべてのcaseを書くと速くなる(コンパイラの最適化の都合).
}
}
fin:
printf("tm=%d\n", clock() - tm0);
if (win->buf != NULL) {
a_Win_flushAll0(win);
for (;;) { Sleep(1000); } // Ctrl-C で終了させる.
}
VecChr_din4(vc, bin, 0, 0);
a_malloc_debugList(_arg);
return 0;
}
[3] 上記のために作った設定ファイル: a4vm-asm-tt0001.h
#define R00 0
#define R01 1
#define R02 2
#define R03 3
#define R04 4
#define R05 5
#define R06 6
#define R07 7
#define R08 8
#define R09 9
#define R0a 10
#define R0b 11
#define R0c 12
#define R0d 13
#define R0e 14
#define R0f 15
#define L0000 0
#define L0001 1
#define L0002 2
#define L0003 3
#define L0004 4
#define L0005 5
#define L0006 6
#define L0007 7
#define Lbl_T(t) 0x0001, t, 0, 0
#define Lod_RI(r, i) 0x0002, r, i, 0
#define Lod_RR(r, s) 0x0003, r, s, 0
#define Or__RI(r, i) 0x0010, r, i, 0
#define Or__RR(r, s) 0x0011, r, s, 0
#define Xor_RI(r, i) 0x0012, r, i, 0
#define Xor_RR(r, s) 0x0013, r, s, 0
#define And_RI(r, i) 0x0014, r, i, 0
#define And_RR(r, s) 0x0015, r, s, 0
#define Shl_RI(r, i) 0x0018, r, i, 0
#define Shl_RR(r, s) 0x0019, r, s, 0
#define Shr_RI(r, i) 0x001a, r, i, 0
#define Shr_RR(r, s) 0x001b, r, s, 0
#define Add_RI(r, i) 0x0020, r, i, 0
#define Add_RR(r, s) 0x0021, r, s, 0
#define Sub_RI(r, i) 0x0022, r, i, 0
#define Sub_RR(r, s) 0x0023, r, s, 0
#define Mul_RI(r, i) 0x0024, r, i, 0
#define Mul_RR(r, s) 0x0025, r, s, 0
#define Div_RI(r, i) 0x0028, r, i, 0
#define Div_RR(r, s) 0x0029, r, s, 0
#define Mod_RI(r, i) 0x002a, r, i, 0
#define Mod_RR(r, s) 0x002b, r, s, 0
#define Jeq_RIT(r, i, t) 0x0030, t, r, i
#define Jeq_RRT(r, s, t) 0x0031, t, r, s
#define Jne_RIT(r, i, t) 0x0032, t, r, i
#define Jne_RRT(r, s, t) 0x0033, t, r, s
#define Jlt_RIT(r, i, t) 0x0038, t, r, i
#define Jlt_RRT(r, s, t) 0x0039, t, r, s
#define Jge_RIT(r, i, t) 0x003a, t, r, i
#define Jge_RRT(r, s, t) 0x003b, t, r, s
#define Jle_RIT(r, i, t) 0x003c, t, r, i
#define Jle_RRT(r, s, t) 0x003d, t, r, s
#define Jgt_RIT(r, i, t) 0x003e, t, r, i
#define Jgt_RRT(r, s, t) 0x003f, t, r, s
#define Dbg_Ret_I(i) 0x0004, i, 0, 0
#define Mul64Shr_RRRI(r, s, t, i) 0x0006, r, s, t, 0x0, i, 0, 0
#define Dbg_OpenWin_RR(x, y) 0x0008, x, y, 0
#define Dbg_SetPix_RRR(x, y, c) 0x0009, x, y, c
#define IncJlt_RIT(r, i, t) 0x0036, t, r, i