update mult/ilo/x to support the graphica extension; some refactoring of source; allow terminal to autosize based on display window

This commit is contained in:
charles childers 2024-07-04 13:41:05 -04:00
parent 021c617339
commit bf2fe9d085

View file

@ -6,48 +6,116 @@
|_| |_| |_|\__,_|_|\__/_/ |_|_|\___/_/ /_/\_\ |_| |_| |_|\__,_|_|\__/_/ |_|_|\___/_/ /_/\_\
(c) charles childers (c) charles childers
This is a special implementation of my ilo computer, with many This is a special implementation of my ilo computer, with
copies of ilo running under a single process. Under this you multiple copies of ilo running under a single host process.
can quickly switch between ilo instances. Using this you can quickly switch between ilo instances.
User Interface
This implementation runs on X11 and provides a visual display
of the terminal with a set of buttons below the display. These
can be used to switch between ilo instances. Closing the window
will terminate the system.
Keyboard Shortcuts
+--------+-----------------------------+
| CTRL+n | Switch to the next ilo |
| CTRL+p | Switch to the previous ilo |
| CTRL+c | Restart the current ilo |
| CTRL+a | Shut down the system |
+--------+-----------------------------+
Additional Functionality
This implementation supports the basic Graphica (Level 0) and
pointer extensions. These are assigned to I/O devices 12 & 13.
Notes
- `bye` will act like `restart` on the current computer - `bye` will act like `restart` on the current computer
- ctrl+c restarts the current computer
- ctrl+n switches to the next ilo
- ctrl+p switches to the previous ilo
- ctrl+a shuts down mult/ilo
- switching can only be done when the system is waiting for - switching can only be done when the system is waiting for
input input
Building
I use this to build it:
cc -O2 -s `pkg-config --cflags --libs x11` mix.c -o mix
It'll probably also work with -O3 and might be slightly faster
**************************************************************/ **************************************************************/
/* Configuration ============================================ */
#define BLOCKS "ilo.blocks" /* default data storage */
#define ROM "ilo.rom" /* default ilo rom */
#define FONT "ilo.fnt" /* default font */
#define FONT_H 16 /* font height */
#define FONT_W 8 /* font width */
/* colors are 0xRRGGBB */
#define FG 0xFFC000 /* foreground color, amber */
#define BG 0x000000 /* background color, black */
#define CURSOR 0x663999 /* cursor color, purple */
#define FW 640 /* terminal width */
#define FH 384 /* terminal height */
#define BUTTON_HEIGHT 30 /* height for button row */
#define CENTER_WINDOW /* center window on start */
#define ILOS 3 /* number of instances */
char *ButtonLabels[ILOS] = {"Instance 0", "Instance 1",
"Instance 2"};
/* ========================================================== */
#include <fcntl.h>
#include <signal.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <fcntl.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <signal.h>
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xutil.h> #include <X11/Xutil.h>
#define BLOCKS "ilo.blocks"
#define ROM "ilo.rom"
#define FONT "ilo.fnt"
#define FG 0xFFFFFF
#define BG 0x000000
/* Orange = 0xFFAA00, Red = 0xFF0000, Cyan = 0x00FFFF */
#define CURSOR 0xFFAA00
#define FW 640
#define FH 384
#define FONT_H 16
#define FONT_W 8
#define V void #define V void
#define I int #define I int
#define C char #define C char
#define ILOS 3 #define DS v->ds /* data stack */
#define AS v->as /* address stack pointer */
#define SP v->sp /* data stack pointer */
#define RP v->rp /* address ("return") stack pointer */
#define IP v->ip /* instruction pointer */
#define M v->m /* memory */
#define T DS[SP] /* top of data stack */
#define N DS[SP-1] /* next on data stack */
#define R AS[RP] /* top of address stack */
#define A v->a /* internal use by instructions */
#define B v->b /* internal use by instructions */
#define S v->s /* internal use by instructions */
#define D v->d /* internal use by instructions */
#define L v->l /* internal use by instructions */
#define F v->f /* used to track block file pointer */
#define RESTART iof(v) /* restart ilo instance on error */
#define OK v->ok /* ok to process further instructions? */
#define FAILED if (F == -1)
#define CTRL_A 1 /* CTRL+a, shut down mult/ilo/x */
#define CTRL_C 3 /* CTRL+c, restart instance */
#define CTRL_N 14 /* CTRL+n, switch to next instance */
#define CTRL_P 16 /* CTRL+p, switch to prior instance */
#define ROWS ((FH/FONT_H) - 1)
#define COLS ((FW/FONT_W) - 1)
typedef struct ilo ilo; typedef struct ilo ilo;
struct ilo { struct ilo {
I ip, /* instruction pointer */ I ip, /* instruction pointer */
sp, /* data stack pointer */ sp, /* data stack pointer */
@ -60,9 +128,12 @@ struct ilo {
I a, b, f, s, d, l, ok; I a, b, f, s, d, l, ok;
C i[1]; C i[1];
}; };
struct ilo systems[ILOS]; /* ilo session data */
I cur; /* track current session */
#define TERM_W (FW / FONT_W) #define BUTTON_WIDTH (FW / ILOS)
#define TERM_H (FH / FONT_H) #define WINDOW_HEIGHT (FH + BUTTON_HEIGHT)
#define WINDOW_WIDTH (FW)
I frame[(FW * FH)/32]; /* frame buffer for display */ I frame[(FW * FH)/32]; /* frame buffer for display */
I font[4096]; /* font bitmap */ I font[4096]; /* font bitmap */
@ -76,73 +147,120 @@ Display *disp;
Window win; Window win;
GC gc; GC gc;
XEvent event; XEvent event;
C text[255]; Window Buttons[ILOS];
V update_labels() {
unsigned long white;
white = WhitePixel(disp, DefaultScreen(disp));
XSetForeground(disp, gc, white);
for (I i = 0; i < ILOS; i++) {
XClearWindow(disp, Buttons[i]);
XDrawString(disp, Buttons[i], gc, 20, 20, ButtonLabels[i],
strlen(ButtonLabels[i]));
if (cur == i) {
XDrawString(disp, Buttons[i], gc, 10, 20, "*", 1);
}
// XSetForeground(disp, gc, white);
XDrawLine(disp, Buttons[i], gc, 0, 0, FW, 0);
}
}
V dputc(I); V dputc(I);
V term_putc(I c);
V redraw(); V redraw();
struct ilo systems[ILOS];
I cur;
#define DS v->ds
#define AS v->as
#define SP v->sp
#define RP v->rp
#define IP v->ip
#define M v->m
#define A v->a
#define B v->b
#define S v->s
#define D v->d
#define L v->l
#define T DS[SP] /* Top of Data Stack */
#define N DS[SP-1] /* Next on Data Stack */
#define R AS[RP] /* Top of Address Stack */
#define F v->f
V iof(ilo *); V iof(ilo *);
V p(char *s) { while(*s) dputc(*s++); } V p(C *s) { while(*s) dputc(*s++); }
V e(ilo *v, char *s) { p("E:"); p(s); p("\n"); v->ok = 1; iof(v); } V e(ilo *v, C *s) { p("E:"); p(s); p("\n"); OK = 1; RESTART; }
V dso(ilo *v) { if ((SP + 1) > 32) { e(v, "DSO"); } } V dso(ilo *v) { if ((SP + 1) > 32) { e(v, "DSO"); } }
V dsu(ilo *v) { if ((SP - 1) < 0) { e(v, "DSU"); } } V dsu(ilo *v) { if ((SP - 1) < 0) { e(v, "DSU"); } }
V rso(ilo *v) { if ((RP + 1) > 256) { e(v, "RSO"); } } V rso(ilo *v) { if ((RP + 1) > 256) { e(v, "RSO"); } }
V rsu(ilo *v) { if ((RP - 1) < 0) { e(v, "RSU"); } } V rsu(ilo *v) { if ((RP - 1) < 0) { e(v, "RSU"); } }
V dbz(ilo *v) { if (T == 0) { e(v, "DBZ"); } } V dbz(ilo *v) { if (T == 0) { e(v, "DBZ"); } }
V mem(ilo *v) { if (T < 0 || T > 65535) { e(v, "MEM"); } } V mem(ilo *v) { if (T < 0 || T > 65535) { e(v, "MEM"); } }
V uli(ilo *v) { if (F == -1) { e(v, "ULI"); } } V uli(ilo *v) { e(v, "ULI"); }
V ulf(ilo *v) { if (F == -1) { e(v, "ULF"); } } V ulf(ilo *v) { e(v, "ULF"); }
V usi(ilo *v) { if (F == -1) { e(v, "URI"); } } V usi(ilo *v) { e(v, "URI"); }
V urb(ilo *v) { if (F == -1) { e(v, "URB"); } } V urb(ilo *v) { e(v, "URB"); }
V uwb(ilo *v) { if (F == -1) { e(v, "UWB"); } } V uwb(ilo *v) { e(v, "UWB"); }
V push(ilo *v, I n) { dso(v); DS[SP + 1] = n; SP += 1; } V push(ilo *v, I n) { dso(v); DS[SP + 1] = n; SP += 1; }
I pop(ilo *v) { dsu(v); SP -= 1; return DS[SP + 1]; } I pop(ilo *v) { dsu(v); SP -= 1; return DS[SP + 1]; }
/* display & terminal emulation ============================= */
V add_buttons() {
for (I i = 0; i < ILOS; i++) {
Buttons[i] = XCreateSimpleWindow(disp, win, i*BUTTON_WIDTH,
FH, BUTTON_WIDTH,
BUTTON_HEIGHT, 1, 0, 0);
XSelectInput(disp, Buttons[i],
ButtonPressMask | ExposureMask);
XMapWindow(disp, Buttons[i]);
}
}
V initialize_display() {
disp = XOpenDisplay(NULL);
win = XCreateSimpleWindow(disp, RootWindow(disp, 0),
0, 0, WINDOW_WIDTH, WINDOW_HEIGHT,
0, 0x0, 0x0);
XSelectInput(disp, win, ExposureMask | KeyPressMask |
ButtonPressMask | ButtonReleaseMask);
XStoreName(disp, win, "mult/ilo");
gc = DefaultGC(disp, DefaultScreen(disp));
add_buttons();
XMapWindow(disp, win);
XFlush(disp);
}
V cleanup_display() {
XUnmapWindow(disp, win);
XDestroyWindow(disp, win);
XCloseDisplay(disp);
}
V cursor() { V cursor() {
XSetForeground(disp, gc, CURSOR); XSetForeground(disp, gc, CURSOR);
XFillRectangle(disp, win, gc, tx, ty, FONT_W, FONT_H); XFillRectangle(disp, win, gc, tx, ty, FONT_W, FONT_H);
XFlush(disp); XFlush(disp);
} }
I wait_key() { V sel(I n) { cur = n; }
while (1) {
XNextEvent(disp, &event); I handle_keypress() {
if (event.type == KeyPress) { C text[255];
KeySym key = XLookupKeysym(&event.xkey, 0); KeySym key = XLookupKeysym(&event.xkey, 0);
XLookupString(&event.xkey, text, 255, &key, 0); XLookupString(&event.xkey, text, 255, &key, 0);
if (text[0] == 13) text[0] = 10; if (text[0] == 13) text[0] = 10;
if (text[0] != 0) return (I) text[0]; if (text[0] != 0) return (I) text[0];
return 0;
} }
if (event.type == Expose) { redraw(); cursor(); }
V handle_expose() { redraw(); update_labels(); cursor(); }
I handle_button() {
for (I i = 0; i < ILOS; i++) {
if (event.xbutton.window == Buttons[i]) { sel(i); }
} }
update_labels();
return 32;
}
I wait_key() {
I k = 0;
while (k == 0) {
XNextEvent(disp, &event);
if (event.type == KeyPress) { k = handle_keypress(); }
if (event.type == Expose) { handle_expose(); }
if (event.type == ButtonPress) { k = handle_button(); }
}
return k;
} }
V load_font(ilo *v) { V load_font(ilo *v) {
F = open(FONT, O_RDONLY, 0666); F = open(FONT, O_RDONLY, 0666); FAILED { ulf(v); return; }
ulf(v);
if (!F) { return; };
read(F, &font, 4096); read(F, &font, 4096);
close(F); close(F);
} }
@ -194,19 +312,26 @@ unsigned C reverse(unsigned C b) {
return b; return b;
} }
V handle_special_character(I c) { V special_backspace() {
if (c == 8 || c == 127) { /* BACKSPACE/DELETE */
if (tx - FONT_W >= 0) { if (tx - FONT_W >= 0) {
tx -= FONT_W ; tx -= FONT_W ; dputc(' '); tx -= FONT_W;
dputc(' ');
tx -= FONT_W;
} }
} else if (c == 9) { /* TAB */ }
V special_tab() {
I ts = tx / FONT_W; I ts = tx / FONT_W;
for (I i = ts; i < ((ts + 7) / 8) * 8; i++) { dputc(' '); } for (I i = ts; i < ((ts + 7) / 8) * 8; i++) { dputc(' '); }
} else if (c == 10 || c == 13) { /* CR or LF */ }
ty += FONT_H;
tx = 0; V special_crlf() { ty += FONT_H; tx = 0; }
V handle_special_character(I c) {
switch (c) {
case 8:
case 127: special_backspace(); break;
case 9: special_tab(); break;
case 10:
case 13: special_crlf(); break;
} }
} }
@ -226,15 +351,12 @@ V advance_cursor_and_scroll() {
if (ty > (FH - FONT_H)) { ty -= FONT_H; scroll(); } if (ty > (FH - FONT_H)) { ty -= FONT_H; scroll(); }
} }
#define NORMAL !(c < 32 || c == 127)
V dputc(I c) { V dputc(I c) {
C *bitmap = (C *)font + (c * ((FONT_H * FONT_W) / 8)); C *bitmap = (C *)font + (c * ((FONT_H * FONT_W) / 8));
handle_special_character(c); handle_special_character(c);
if (NORMAL) { handle_regular_character(bitmap); }
if (!(c == 8 || c == 127 || c == 9 || c == 10 || c == 13)) {
handle_regular_character(bitmap);
}
advance_cursor_and_scroll(); advance_cursor_and_scroll();
} }
@ -255,15 +377,15 @@ V acc_reset() {
} }
V gt_up(I n) { ty -= FONT_H; if (ty < 0) ty = 0; } V gt_up(I n) { ty -= FONT_H; if (ty < 0) ty = 0; }
V gt_down(I n) { ty += FONT_H; if (ty > 24 * FONT_H) ty = 24 * FONT_H; } V gt_down(I n) { ty += FONT_H; if (ty > ROWS * FONT_H) ty = ROWS * FONT_H; }
V gt_left(I n) { tx -= FONT_W; if (tx < 0) tx = 0; } V gt_left(I n) { tx -= FONT_W; if (tx < 0) tx = 0; }
V gt_right(I n) { tx += FONT_W; if (tx > 79 * FONT_W) ty = 79 * FONT_W; } V gt_right(I n) { tx += FONT_W; if (tx > COLS * FONT_W) ty = COLS * FONT_W; }
V gt_move_cursor() { V gt_move_cursor() {
if (acc_i >= 1) { if (acc_i >= 1) {
I a = (acc_pop() - 1) * FONT_W; I a = (acc_pop() - 1) * FONT_W;
I b = (acc_pop() - 1) * FONT_H; I b = (acc_pop() - 1) * FONT_H;
ty = b; if (ty < 0) ty = 0; if (ty > FONT_H * 24) ty = FONT_H * 24; ty = b; if (ty < 0) ty = 0; if (ty > FONT_H * ROWS) ty = FONT_H * ROWS;
tx = a; if (tx < 0) tx = 0; if (tx > FONT_W * 79) tx = FONT_W * 79; tx = a; if (tx < 0) tx = 0; if (tx > FONT_W * COLS) tx = FONT_W * COLS;
acc_reset(); acc_reset();
return; return;
} }
@ -283,10 +405,7 @@ V gt_clear() {
V gt_set_attr() { acc_reset(); } V gt_set_attr() { acc_reset(); }
V term_putc(I c) { V term_putc(I c) {
if (c == 27) { if (c == 27) { on = -2; return; }
on = -2;
return;
}
switch (on) { switch (on) {
case 0: case 0:
dputc(c); dputc(c);
@ -325,43 +444,80 @@ V term_putc(I c) {
} }
} }
/* graphica, level 0 ======================================== */
I p0, p0x, p0y, pcolor = FG;
I px(I p) { return p >> 16; }
I py(I p) { return p & 65535; }
V gra0(ilo *v) { push(v, 0); }
V gra1(ilo *v) { push(v, 2); }
V gra2(ilo *v) { push(v, FONT_H); push(v, FONT_W); }
V gra3(ilo *v) { push(v, FH); push(v, FW); }
V gra4(ilo *v) { pcolor = (pop(v) != 0) ? FG : BG; }
V gra5(ilo *v) { p0 = pop(v); p0x = px(p0); p0y = py(p0);
pixel(p0x, p0y, pcolor); }
V gra6(ilo *v) { p0 = pop(v); p0x = px(p0); p0y = py(p0);
push(v, get_pixel(p0x, p0y)); }
V gra(ilo *v) {
switch (pop(v)) {
case 0: gra0(v); break; case 1: gra1(v); break;
case 2: gra2(v); break; case 3: gra3(v); break;
case 4: gra4(v); break; case 5: gra5(v); break;
case 6: gra6(v); break;
}
}
/* pointer device =========================================== */
/* returns x, y, button state */
V ptr(ilo *v) {
I x, y, wx, wy;
unsigned I mask;
Window w;
XQueryPointer(disp, win, &w, &w, &x, &y, &wx, &wy, &mask);
push(v, x);
push(v, y);
if (mask & Button1Mask) push(v, -1); else push(v, 0);
}
/* the ilo cpu ============================================== */
V load_image(ilo *v) { V load_image(ilo *v) {
F = open(v->rom, O_RDONLY, 0666); F = open(v->rom, O_RDONLY, 0666); FAILED { uli(v); return; }
if (!F) { return; };
read(F, &M, 65536 * 4); read(F, &M, 65536 * 4);
close(F); close(F);
IP = SP = RP = 0; IP = SP = RP = 0;
} }
V save_image(ilo *v) { V save_image(ilo *v) {
v->f = open(v->rom, O_WRONLY, 0666); F = open(v->rom, O_WRONLY, 0666); FAILED { usi(v); return; }
write(v->f, &M, 65536 * 4); write(F, &M, 65536 * 4);
close(v->f); close(F);
} }
V block_common(ilo *v) { V block_common(ilo *v) {
B = pop(v); /* block buffer */ B = pop(v); /* block buffer */
A = pop(v); /* block number */ A = pop(v); /* block number */
lseek(v->f, 4096 * A, SEEK_SET); lseek(F, 4096 * A, SEEK_SET);
} }
V read_block(ilo *v) { V read_block(ilo *v) {
v->f = open(v->blocks, O_RDONLY, 0666); F = open(v->blocks, O_RDONLY, 0666); FAILED { urb(v); return; }
block_common(v); block_common(v);
read(v->f, M + B, 4096); read(F, M + B, 4096);
close(v->f); close(F);
} }
V write_block(ilo *v) { V write_block(ilo *v) {
v->f = open(v->blocks, O_WRONLY, 0666); F = open(v->blocks, O_WRONLY, 0666); FAILED { uwb(v); return; }
block_common(v); block_common(v);
write(v->f, M + B, 4096); write(F, M + B, 4096);
close(v->f); close(F);
} }
V save_ip(ilo *v) { RP += 1; R = IP; } V save_ip(ilo *v) { RP += 1; R = IP; }
V symmetric(ilo *v) { V symmetric(ilo *v) { if (B >= 0 && N < 0) { T += 1; N -= B; } }
if (B >= 0 && N < 0) { T += 1; N -= B; } }
V li(ilo *v) { IP += 1; push(v, M[IP]); } V li(ilo *v) { IP += 1; push(v, M[IP]); }
V du(ilo *v) { push(v, T); } V du(ilo *v) { push(v, T); }
@ -387,7 +543,7 @@ V ad(ilo *v) { N += T; SP -= 1; }
V su(ilo *v) { N -= T; SP -= 1; } V su(ilo *v) { N -= T; SP -= 1; }
V mu(ilo *v) { N *= T; SP -= 1; } V mu(ilo *v) { N *= T; SP -= 1; }
V di(ilo *v) { A = T; B = N; V di(ilo *v) { A = T; B = N;
if (A == 0) { v->ok = 1; iof(v); return; } if (A == 0) { dbz(v); OK = 1; RESTART; return; }
T = B / A; N = B % A; T = B / A; N = B % A;
symmetric(v); } symmetric(v); }
V an(ilo *v) { N = T & N; SP -= 1; } V an(ilo *v) { N = T & N; SP -= 1; }
@ -404,36 +560,23 @@ V cy(ilo *v) { L = pop(v); D = pop(v); S = pop(v);
M[D] = M[S]; M[D] = M[S];
L -= 1; S += 1; D += 1; } } L -= 1; S += 1; D += 1; } }
V pre(V) { cur -= 1; if (cur < 0) cur = ILOS - 1; } V pre(V) { cur -= 1; if (cur < 0) cur = ILOS - 1; update_labels(); }
V nxt(V) { cur += 1; if (cur > (ILOS - 1)) cur = 0; } V nxt(V) { cur += 1; if (cur > (ILOS - 1)) cur = 0; update_labels(); }
V msgs(V) { printf("\n*** SWITCH TO %d ***\n", cur); }
V msgx(V) { printf("\n*** SHUTDOWN REQUESTED ***\n");
exit(1); }
V msgr(V) { printf("\n*** RESTART %d ***\n", cur); }
V term_putc(I c);
V ioa(ilo *v) { term_putc(pop(v)); } V ioa(ilo *v) { term_putc(pop(v)); }
V iob(ilo *v) { redraw(); cursor(); V iob(ilo *v) { redraw(); cursor();
v->i[0] = wait_key(); push(v, v->i[0]); term_putc(T); v->i[0] = wait_key(); push(v, v->i[0]); term_putc(T);
if (v->i[0] == 14) { T = 32; nxt(); msgs(); } if (v->i[0] == CTRL_N) { T = 32; nxt(); }
if (v->i[0] == 16) { T = 32; pre(); msgs(); } if (v->i[0] == CTRL_P) { T = 32; pre(); }
if (v->i[0] == 3) { T = 32; msgr(); iof(v); if (v->i[0] == CTRL_C) { T = 32; RESTART;
v->ok = 1; } OK = 1; }
if (v->i[0] == 1) { T = 32; msgx(); } } if (v->i[0] == CTRL_A) { T = 32; exit(0); } }
V ioc(ilo *v) { read_block(v); } V ioc(ilo *v) { read_block(v); }
V iod(ilo *v) { write_block(v); } V iod(ilo *v) { write_block(v); }
V ioe(ilo *v) { save_image(v); } V ioe(ilo *v) { save_image(v); }
V iof(ilo *v) { load_image(v); IP = -1; } V iof(ilo *v) { load_image(v); IP = -1; }
V iog(ilo *v) { iof(v); } V iog(ilo *v) { RESTART; }
V ioh(ilo *v) { push(v, SP); push(v, RP); } V ioh(ilo *v) { push(v, SP); push(v, RP); }
V iox(ilo *v) { I c = pop(v); I y = pop(v); I x = pop(v);
pixel(x, y, c); }
V ioy(ilo *v) { I y = pop(v); I x = pop(v); push(v, get_pixel(x, y)); }
V ioz(ilo *v) { I x, y, wx, wy, mask; Window w;
XQueryPointer(disp, win, &w, &w, &x, &y, &wx, &wy, &mask);
push(v, x); push(v, y); if (mask & Button1Mask) push(v, -1); else push(v, 0); }
V io(ilo *v) { V io(ilo *v) {
switch (pop(v)) { switch (pop(v)) {
@ -441,8 +584,8 @@ V io(ilo *v) {
case 2: ioc(v); break; case 3: iod(v); break; case 2: ioc(v); break; case 3: iod(v); break;
case 4: ioe(v); break; case 5: iof(v); break; case 4: ioe(v); break; case 5: iof(v); break;
case 6: iog(v); break; case 7: ioh(v); break; case 6: iog(v); break; case 7: ioh(v); break;
case 33: iox(v); break; case 34: ioy(v); break; /* optional extensions after this point */
case 35: ioz(v); break; case 12: gra(v); break; case 13: ptr(v); break;
default: break; default: break;
} }
} }
@ -468,14 +611,17 @@ V process(ilo *v, I o) {
} }
} }
#define VALID(n) (v->ok == 0) && ((opcode >> n) & 0xFF) /* This is used to help skip processing NOP operations and */
/* abort on errors */
#define VALID(n) (OK == 0) && ((opcode >> n) & 0xFF)
V execute() { V execute() {
I opcode; I opcode;
ilo *v = &systems[cur]; ilo *v = &systems[cur];
while (IP < 65536) { while (IP < 65536) {
opcode = M[IP]; opcode = M[IP];
v->ok = 0; OK = 0;
if (VALID(0)) process(v, opcode & 0xFF); if (VALID(0)) process(v, opcode & 0xFF);
if (VALID(8)) process(v, (opcode >> 8) & 0xFF); if (VALID(8)) process(v, (opcode >> 8) & 0xFF);
if (VALID(16)) process(v, (opcode >> 16) & 0xFF); if (VALID(16)) process(v, (opcode >> 16) & 0xFF);
@ -485,13 +631,13 @@ V execute() {
} }
} }
V load_font(ilo *); /* main entry point ========================================= */
I main(I argc, C **argv) { I main(I argc, C **argv) {
ilo *v; ilo *v;
I i; I i;
cur = 0; /* setup each session */
for (i = 0; i < ILOS; i++) { for (i = 0; i < ILOS; i++) {
v = &systems[i]; v = &systems[i];
v->blocks = (argc > 1) ? argv[1] : BLOCKS; v->blocks = (argc > 1) ? argv[1] : BLOCKS;
@ -499,24 +645,18 @@ I main(I argc, C **argv) {
load_image(v); load_image(v);
} }
/* load the font data */
load_font(&systems[0]); load_font(&systems[0]);
initialize_display();
disp = XOpenDisplay(NULL); #ifdef CENTER_WINDOW
win = XCreateSimpleWindow(disp, RootWindow(disp, 0),
0, 0, FW, FH, 0, 0x0, 0x0);
XSelectInput(disp, win, ExposureMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask);
XStoreName(disp, win, "x/ilo");
gc = DefaultGC(disp, DefaultScreen(disp));
XMapWindow(disp, win);
XFlush(disp);
XMoveWindow(disp, win, (DisplayWidth(disp, DefaultScreen(disp)) - FW) / 2, XMoveWindow(disp, win, (DisplayWidth(disp, DefaultScreen(disp)) - FW) / 2,
(DisplayHeight(disp, DefaultScreen(disp)) - FH) / 2); (DisplayHeight(disp, DefaultScreen(disp)) - FH - BUTTON_HEIGHT) / 2);
#endif
cur = 0;
execute(); execute();
XUnmapWindow(disp, win); cleanup_display();
XDestroyWindow(disp, win);
XCloseDisplay(disp);
return 0; return 0;
} }