summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--sources/chip8.c7
-rw-r--r--sources/main.c318
-rw-r--r--sources/meta/exec.c23
4 files changed, 211 insertions, 139 deletions
diff --git a/Makefile b/Makefile
index 4f32fb4..14b9287 100644
--- a/Makefile
+++ b/Makefile
@@ -7,7 +7,7 @@ X11FLAGS = -lm -lX11 -lxcb -lXau -lXdmcp
x11: artifacts/xip-8
-artifacts/xip-8: sources/*.c resources/icon.tga.h
+artifacts/xip-8: sources/meta/*.c sources/*.c resources/icon.tga.h
$(CC) $(CFLAGS) $(X11FLAGS) sources/main.c -o artifacts/xip-8
artifacts/bin2c: utils/bin2.c
diff --git a/sources/chip8.c b/sources/chip8.c
index 1c5f907..836b9ef 100644
--- a/sources/chip8.c
+++ b/sources/chip8.c
@@ -7,7 +7,7 @@
#define C8_RESET_VECTOR 0x200
-#define C8_CYCLES_PER_FRAME 1000
+#define C8_CYCLES_PER_FRAME 20
static const u8 fnt[] =
{
@@ -36,6 +36,7 @@ typedef struct
u8 sp;
u16 i;
+ u16 prevkeys;
u16 keys;
u64 cycles;
@@ -137,8 +138,8 @@ void c8_dump_state(chip8* c8, bool stack)
printf("V%x: %02X (%3d)\n", i+3, c8->V[i+3], c8->V[i+3]);
}
- printf(" I:%04X SP: %02X DT: %02X ST: %02X CYCLES: %llu\n",
- c8->i, c8->sp, c8->dt, c8->st, c8->cycles);
+ printf(" I:%04X SP: %02X DT: %02X ST: %02X CYCLES: %llu, KEYS: %X\n",
+ c8->i, c8->sp, c8->dt, c8->st, c8->cycles, c8->keys);
if(stack)
{
diff --git a/sources/main.c b/sources/main.c
index 4049a30..4bc972c 100644
--- a/sources/main.c
+++ b/sources/main.c
@@ -36,6 +36,9 @@
#include "meta/exec.c"
+#define IUI_TXT_CENTER bit(0)
+#define IUI_CLIP_CLEAR bit(0)
+
typedef struct
{
enum
@@ -45,12 +48,14 @@ typedef struct
IUI_FILL,
IUI_LINE,
IUI_TEXT,
+ IUI_CLIP,
} type;
u32 color;
u16 x, y, w, h;
u16 size;
+ u16 flags;
char* text;
} iui_cmd;
@@ -71,6 +76,8 @@ typedef struct
u8 pbtns;
u8 btns;
+ /* TODO: event pump */
+
usize ncmds;
iui_cmd cmds[IUI_CMDBUF_LEN]; /* TODO: arena? */
@@ -140,9 +147,10 @@ int iui_button(iui* ui, u16 x, u16 y, int w, int h, char* label)
cmd.color = x11->cols.as.fg;
ui->cmds[ui->ncmds++] = cmd;
- cmd.type = IUI_TEXT;
- cmd.size = 14;
- cmd.text = label;
+ cmd.type = IUI_TEXT;
+ cmd.size = 14;
+ cmd.text = label;
+ cmd.flags = IUI_TXT_CENTER;
if(imactive) cmd.color = x11->cols.as.bg;
else cmd.color = x11->cols.as.fg;
@@ -173,59 +181,80 @@ int iui_textbox(iui* ui, u16 x, u16 y, int w, int h, char* buf, usize buflen)
imactive = ui->active == id;
{
- XGCValues gcvals = {0};
-
- if(imhot) gcvals.line_width = 2;
- else gcvals.line_width = 1;
-
- gcvals.foreground = x11->cols.as.bg;
+ iui_cmd cmd = {0};
+ cmd.type = IUI_FILL;
- XChangeGC(x11->disp, x11->gc, GCForeground | GCLineWidth, &gcvals);
- XFillRectangle(x11->disp, x11->wnd, x11->gc, x, y, w, h);
+ cmd.x = x;
+ cmd.y = y;
+ cmd.w = w;
+ cmd.h = h;
- XSetForeground(x11->disp, x11->gc, x11->cols.as.fg);
- XDrawLine(x11->disp, x11->wnd, x11->gc, x, y, x, y + h);
- XDrawLine(x11->disp, x11->wnd, x11->gc, x + w, y, x, y);
- XDrawLine(x11->disp, x11->wnd, x11->gc, x, y + h, x + w, y + h);
- XDrawLine(x11->disp, x11->wnd, x11->gc, x + w, y + h, x + w, y);
- }
+ if(imhot) cmd.size = 2;
+ else cmd.size = 1;
- if(imactive) ui->kbdfocus = id;
- if(ui->kbdfocus == id)
- {
+ cmd.color = x11->cols.as.bg;
+ ui->cmds[ui->ncmds++] = cmd;
- XGCValues gcvals = {0};
- gcvals.foreground = x11->cols.as.fg;
+ cmd.type = IUI_BOX;
+ cmd.color = x11->cols.as.fg;
+ ui->cmds[ui->ncmds++] = cmd;
- XChangeGC(x11->disp, x11->gc, GCForeground, &gcvals);
- XFillRectangle(x11->disp, x11->wnd, x11->gc, x + 6 + (6 * len), y + 6, 10, h - 12);
- }
- else
- {
- XGCValues gcvals = {0};
- gcvals.foreground = x11->cols.as.fg;
- gcvals.line_width = 1;
+ {
+ iui_cmd clip = cmd;
+ clip.type = IUI_CLIP;
+ clip.flags = 0;
+ clip.x++;
+ clip.y++;
+ clip.w--;
+ clip.h--;
+
+ ui->cmds[ui->ncmds++] = clip;
+ }
- XChangeGC(x11->disp, x11->gc, GCForeground | GCLineWidth, &gcvals);
- XDrawRectangle(x11->disp, x11->wnd, x11->gc, x + 6 + (6 * len), y + 6, 9, h - 13);
- }
+ if(imactive) ui->kbdfocus = id;
+ if(ui->kbdfocus == id)
+ {
+ cmd.type = IUI_FILL;
+ cmd.x = x + 6 + 6 * len;
+ cmd.y = y + 6;
+ cmd.w = 10;
+ cmd.h = h - 12;
+ cmd.color = x11->cols.as.fg;
+
+ ui->cmds[ui->ncmds++] = cmd;
+ }
+ else
+ {
+ cmd.type = IUI_BOX;
+ cmd.x = x + 6 + 6 * len;
+ cmd.y = y + 6;
+ cmd.w = 9;
+ cmd.h = h - 13;
+ cmd.color = x11->cols.as.fg;
+ cmd.size = 1;
+
+ ui->cmds[ui->ncmds++] = cmd;
+ }
- {
- int xx, yy;
- int di, fa, fd;
- int width, height;
- XCharStruct chs = {0};
+ {
+ cmd.type = IUI_TEXT;
+ cmd.size = 14;
+ cmd.text = buf;
+ cmd.flags = 0;
- XTextExtents(x11->xfs, buf, buflen, &di, &fa, &fd, &chs);
- height = chs.ascent + chs.descent;
+ cmd.x = x + 6;
+ cmd.y = y;
+ cmd.w = w;
+ cmd.h = h;
- xx = x + 6;
- yy = y + h / 2 + height / 2;
+ cmd.color = x11->cols.as.fg;
+ ui->cmds[ui->ncmds++] = cmd;
+ }
- if(imactive) XSetForeground(x11->disp, x11->gc, x11->cols.as.bg);
- else XSetForeground(x11->disp, x11->gc, x11->cols.as.fg);
- XDrawString(x11->disp, x11->wnd, x11->gc, xx, yy, buf, len);
+ cmd.type = IUI_CLIP;
+ cmd.flags = IUI_CLIP_CLEAR;
+ ui->cmds[ui->ncmds++] = cmd;
}
return imhot && imactive && !(ui->btns & bit(1));
@@ -283,7 +312,10 @@ void iui_draw(iui* ui)
width = chs.rbearing - chs.lbearing;
height = chs.ascent + chs.descent;
- xx = cmd->x + cmd->w / 2 - width / 2;
+ if(cmd->flags & IUI_TXT_CENTER)
+ xx = cmd->x + cmd->w / 2 - width / 2;
+ else
+ xx = cmd->x;
yy = cmd->y + cmd->h / 2 + height / 2;
XSetForeground(x11->disp, x11->gc, cmd->color);
@@ -291,6 +323,22 @@ void iui_draw(iui* ui)
}
break;
+ case IUI_CLIP:
+ {
+ if(cmd->flags & IUI_CLIP_CLEAR) XSetClipMask(x11->disp, x11->gc, None);
+ else
+ {
+ XRectangle clip_region = {0};
+ clip_region.x = cmd->x;
+ clip_region.y = cmd->y;
+ clip_region.width = cmd->w;
+ clip_region.height = cmd->h;
+
+ XSetClipRectangles(x11->disp, x11->gc, 0, 0, &clip_region, 1, Unsorted);
+ }
+ }
+ break;
+
default:
report(WARN, "IUI: Unknown draw command %u\n", cmd->type);
break;
@@ -303,12 +351,60 @@ void iui_draw(iui* ui)
int main(int argc, char** argv)
{
+ chip8 c8 = {0};
xctx x11 = {0};
iui ui = {0};
- bool run = true;
- char txtbuf[256] = {0};
+ bool run = true, cycle = false;;
+
+ u64 sz = 0;
+ FILE* f = NULL;
+ char buf[512] = {0};
+
+ srand(time(NULL));
+
+ if(argc > 1)
+ {
+ u64 got = 0;
+
+ f = fopen(argv[1], "r");
+ if(!f) return 1;
+
+ fseek(f, 0, SEEK_END);
+ sz = (u64)ftell(f);
+ rewind(f);
+
+ if(sz >= (sizeof(c8.RAM) - 512)) return 2;
+
+ got = fread(c8.RAM + C8_RESET_VECTOR, 1, sz, f);
+ if(got != sz) return 3;
+
+ fclose(f);
+ }
+ else
+ {
+ c8.RAM[C8_RESET_VECTOR + iota] = 0x60;
+ c8.RAM[C8_RESET_VECTOR + iota] = 0x04;
+
+ c8.RAM[C8_RESET_VECTOR + iota] = 0x61;
+ c8.RAM[C8_RESET_VECTOR + iota] = 0x03;
+
+ c8.RAM[C8_RESET_VECTOR + iota] = 0x72;
+ c8.RAM[C8_RESET_VECTOR + iota] = 0x01;
+
+ c8.RAM[C8_RESET_VECTOR + iota] = 0x80;
+ c8.RAM[C8_RESET_VECTOR + iota] = 0x14;
+
+ c8.RAM[C8_RESET_VECTOR + iota] = 0x30;
+ c8.RAM[C8_RESET_VECTOR + iota] = 0x10;
+
+ c8.RAM[C8_RESET_VECTOR + iota] = 0x12;
+ c8.RAM[C8_RESET_VECTOR + iota] = 0x04;
+
+ sz = iota;
+ }
x11_init(800, 600, "xip-8", argc, argv, &x11);
+ c8_reset(&c8);
while(run)
{
@@ -337,6 +433,35 @@ int main(int argc, char** argv)
len = XLookupString(&ev.xkey, name, sizeof(name) - 1, &ks, NULL);
if(keyup && ks == XK_Escape) run = false;
+
+ if(!ui.kbdfocus)
+ {
+ u16 bits = 0;
+ switch(name[0])
+ {
+ case 'x': bits = bit(0); break;
+ case '1': bits = bit(1); break;
+ case '2': bits = bit(2); break;
+ case '3': bits = bit(3); break;
+ case 'q': bits = bit(4); break;
+ case 'w': bits = bit(5); break;
+ case 'e': bits = bit(6); break;
+ case 'd': bits = bit(7); break;
+ case 's': bits = bit(8); break;
+ case 'a': bits = bit(9); break;
+ case 'z': bits = bit(10); break;
+ case 'c': bits = bit(11); break;
+ case '4': bits = bit(12); break;
+ case 'r': bits = bit(13); break;
+ case 'f': bits = bit(14); break;
+ case 'v': bits = bit(15); break;
+ default: break;
+ }
+
+ if(keyup) c8.keys &= ~bits;
+ else c8.keys |= bits;
+ }
+
if(!keyup && len == 1)
{
if(ui.kbdfocus && (isgraph(name[0]) || name[0] == ' '))
@@ -433,95 +558,32 @@ int main(int argc, char** argv)
}
iui_start(&ui, &x11);
- if(iui_button(&ui, 25, 25, 100, 35, "Click ME!")) report(DBG, "CLICK!\n");
- if(iui_button(&ui, 150, 25, 100, 35, "NOT ME!!!")) report(DBG, "WHYYYYYY!\n");
-
- iui_textbox(&ui, 25, 75, 225, 35, txtbuf, lengthof(txtbuf));
- if(iui_button(&ui, 275, 75, 100, 35, "OK")) report(DBG, "textbox: '%s'!\n", txtbuf);
+ if(iui_button(&ui, 25, 25, 100, 35, "Cycle")) cycle = !cycle;
+ iui_textbox(&ui, 25, 75, 225, 35, buf, lengthof(buf));
iui_end(&ui);
- usleep(10000);
- }
-
- x11_cleanup(&x11);
- return 0;
-}
-
-int main2(int argc, char** argv)
-{
- u64 sz = 0;
- FILE* f = NULL;
- chip8 c8 = {0};
-
- srand(time(NULL));
-
- c8_reset(&c8);
-
- if(argc > 1)
- {
- u64 got = 0;
-
- f = fopen(argv[1], "r");
- if(!f) return 1;
-
- fseek(f, 0, SEEK_END);
- sz = (u64)ftell(f);
- rewind(f);
-
- if(sz >= (sizeof(c8.RAM) - 512)) return 2;
-
- got = fread(c8.RAM + C8_RESET_VECTOR, 1, sz, f);
- if(got != sz) return 3;
-
- fclose(f);
- }
- else
- {
- c8.RAM[C8_RESET_VECTOR + iota] = 0x60;
- c8.RAM[C8_RESET_VECTOR + iota] = 0x04;
-
- c8.RAM[C8_RESET_VECTOR + iota] = 0x61;
- c8.RAM[C8_RESET_VECTOR + iota] = 0x03;
-
- c8.RAM[C8_RESET_VECTOR + iota] = 0x72;
- c8.RAM[C8_RESET_VECTOR + iota] = 0x01;
-
- c8.RAM[C8_RESET_VECTOR + iota] = 0x80;
- c8.RAM[C8_RESET_VECTOR + iota] = 0x14;
-
- c8.RAM[C8_RESET_VECTOR + iota] = 0x30;
- c8.RAM[C8_RESET_VECTOR + iota] = 0x10;
-
- c8.RAM[C8_RESET_VECTOR + iota] = 0x12;
- c8.RAM[C8_RESET_VECTOR + iota] = 0x04;
-
- sz = iota;
- }
-
- printf("Disasm:\n");
- {
- u64 i;
- char buf[512] = {0};
- for(i = 0; i < sz; i += 2)
+ if(cycle)
{
- u16 pc = C8_RESET_VECTOR + i;
- c8_disasm(c8.RAM, pc, buf);
- printf("%04X: %s\n", pc, buf);
+ c8_disasm(c8.RAM, c8.pc, buf);
+ c8_exec(c8.RAM, c8.pc, &c8);
}
- }
- printf("\nExec:\n");
- while(c8.running)
- {
- char buf[512] = {0};
+ {
+ usize x, y, s = 4;
- c8_disasm(c8.RAM, c8.pc, buf);
- printf("%04X: %s\n", c8.pc, buf);
+ XSetForeground(x11.disp, x11.gc, x11.cols.as.fg);
+ XSetBackground(x11.disp, x11.gc, x11.cols.as.bg);
+
+ for(y = 0; y < 32; y++)
+ for(x = 0; x < 64; x++)
+ if(c8.DISPLAY[y] & bit(x))
+ XFillRectangle(x11.disp, x11.wnd, x11.gc, 25 + x*s, 128 + y*s, s, s);
+ }
- c8_exec(c8.RAM, c8.pc, &c8);
- c8_dump_state(&c8, false);
+ usleep(10000);
}
+ x11_cleanup(&x11);
return 0;
}
diff --git a/sources/meta/exec.c b/sources/meta/exec.c
index b5aaba4..4f34d1b 100644
--- a/sources/meta/exec.c
+++ b/sources/meta/exec.c
@@ -34,6 +34,7 @@ BEGIN \
if(c8->st) c8->st--; \
} \
c8->pc += 2; \
+ c8->prevkeys = c8->keys; \
END
#define X_C8_ILL \
@@ -104,12 +105,12 @@ END
#define X_C8_SKP \
BEGIN \
- if(c8->keys & c8->V[x]) c8->pc += 2; \
+ if(c8->keys & bit(c8->V[x])) c8->pc += 2; \
END
#define X_C8_SKNP \
BEGIN \
- if(!(c8->keys & c8->V[x])) c8->pc += 2; \
+ if(!(c8->keys & bit(c8->V[x]))) c8->pc += 2; \
END
#define X_C8_MVDT \
@@ -117,10 +118,19 @@ BEGIN \
c8->V[x] = c8->dt; \
END
-/* TODO: implement */
#define X_C8_LDK \
BEGIN \
- if(!c8->keys) c8->pc -= 2; \
+ int i; \
+ if(c8->keys == c8->prevkeys) c8->pc -= 2; \
+ else \
+ { \
+ for(i = 7; i >= 0; i--) \
+ if(c8->keys & bit(i)) \
+ { \
+ c8->V[x] = i; \
+ break; \
+ } \
+ } \
END
#define X_C8_LDDT \
@@ -227,8 +237,7 @@ BEGIN \
if(c8->V[x] != c8->V[y]) c8->pc += 2; \
END
-
-/* TODO: actually implement */
+/* FIXME: correct wrapping, test */
#define X_C8_DRW \
BEGIN \
u8 l; \
@@ -236,7 +245,7 @@ BEGIN \
u8 cy = c8->V[y]; \
\
for(l = 0; l < n; l++) \
- c8->DISPLAY[cy + l * cx] ^= c8->RAM[c8->i + l]; \
+ c8->DISPLAY[(cy + l) % 32] ^= ((u64)c8->RAM[c8->i + l]) << (64 - cx); \
END
c8_decode_generate(exec)