| ... | ... |
@@ -23,7 +23,7 @@ typedef unsigned char Uint8; |
| 23 | 23 |
|
| 24 | 24 |
int WIDTH = 8 * HOR + 8 * PAD * 2; |
| 25 | 25 |
int HEIGHT = 8 * (VER + 2) + 8 * PAD * 2; |
| 26 |
-int FPS = 30, GUIDES = 1, BIGPIXEL = 0, ZOOM = 2; |
|
| 26 |
+int FPS = 30, GUIDES = 1, REQDRAW = 0, ZOOM = 2; |
|
| 27 | 27 |
|
| 28 | 28 |
Uint32 theme[] = {
|
| 29 | 29 |
0x000000, |
| ... | ... |
@@ -32,6 +32,24 @@ Uint32 theme[] = {
|
| 32 | 32 |
0x666666, |
| 33 | 33 |
0x222222}; |
| 34 | 34 |
|
| 35 |
+Uint8 icons[][8] = {
|
|
| 36 |
+ {0x00, 0x3c, 0x46, 0x4a, 0x52, 0x62, 0x3c, 0x00},
|
|
| 37 |
+ {0x00, 0x18, 0x28, 0x08, 0x08, 0x08, 0x3e, 0x00},
|
|
| 38 |
+ {0x00, 0x3c, 0x42, 0x02, 0x3c, 0x40, 0x7e, 0x00},
|
|
| 39 |
+ {0x00, 0x3c, 0x42, 0x1c, 0x02, 0x42, 0x3c, 0x00},
|
|
| 40 |
+ {0x00, 0x08, 0x18, 0x28, 0x48, 0x7e, 0x08, 0x00},
|
|
| 41 |
+ {0x00, 0x7e, 0x40, 0x7c, 0x02, 0x42, 0x3c, 0x00},
|
|
| 42 |
+ {0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0x3c, 0x00},
|
|
| 43 |
+ {0x00, 0x7e, 0x02, 0x04, 0x08, 0x10, 0x10, 0x00},
|
|
| 44 |
+ {0x00, 0x3c, 0x42, 0x3c, 0x42, 0x42, 0x3c, 0x00},
|
|
| 45 |
+ {0x00, 0x3c, 0x42, 0x42, 0x3e, 0x02, 0x3c, 0x00},
|
|
| 46 |
+ {0x00, 0x3c, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x00},
|
|
| 47 |
+ {0x00, 0x7c, 0x42, 0x7c, 0x42, 0x42, 0x7c, 0x00},
|
|
| 48 |
+ {0x00, 0x3c, 0x42, 0x40, 0x40, 0x42, 0x3c, 0x00},
|
|
| 49 |
+ {0x00, 0x78, 0x44, 0x42, 0x42, 0x44, 0x78, 0x00},
|
|
| 50 |
+ {0x00, 0x7e, 0x40, 0x7c, 0x40, 0x40, 0x7e, 0x00},
|
|
| 51 |
+ {0x00, 0x7e, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x00}};
|
|
| 52 |
+ |
|
| 35 | 53 |
SDL_Window *gWindow; |
| 36 | 54 |
SDL_Renderer *gRenderer; |
| 37 | 55 |
SDL_Texture *gTexture; |
| ... | ... |
@@ -90,12 +108,35 @@ error(char *msg, const char *err) |
| 90 | 108 |
} |
| 91 | 109 |
|
| 92 | 110 |
void |
| 93 |
-redraw(Uint32 *dst) |
|
| 111 |
+drawdebugger(Uint32 *dst, Uxn *u) |
|
| 112 |
+{
|
|
| 113 |
+ Uint8 i; |
|
| 114 |
+ for(i = 0; i < 0x10; ++i) { /* memory */
|
|
| 115 |
+ Uint8 x = (i % 8) * 3 + 1, y = i / 8 + 1, b = u->ram.dat[i]; |
|
| 116 |
+ drawicn(dst, x * 8, y * 8, icons[(b >> 4) & 0xf], 1, 0); |
|
| 117 |
+ drawicn(dst, x * 8 + 8, y * 8, icons[b & 0xf], 1, 0); |
|
| 118 |
+ } |
|
| 119 |
+ for(i = 0; i < 0x10; ++i) { /* memory */
|
|
| 120 |
+ Uint8 x = (i % 8) * 3 + 1, y = i / 8 + 0x13, b = u->wst.dat[i]; |
|
| 121 |
+ drawicn(dst, x * 8, y * 8, icons[(b >> 4) & 0xf], 1 + (u->wst.ptr == i), 0); |
|
| 122 |
+ drawicn(dst, x * 8 + 8, y * 8, icons[b & 0xf], 1 + (u->wst.ptr == i), 0); |
|
| 123 |
+ } |
|
| 124 |
+ drawicn(dst, 25 * 8, 8, icons[getflag(&u->status, FLAG_HALT) != 0], 2, 0); |
|
| 125 |
+ drawicn(dst, 26 * 8, 8, icons[getflag(&u->status, FLAG_SHORT) != 0], 2, 0); |
|
| 126 |
+ drawicn(dst, 27 * 8, 8, icons[getflag(&u->status, FLAG_SIGN) != 0], 2, 0); |
|
| 127 |
+ drawicn(dst, 28 * 8, 8, icons[getflag(&u->status, FLAG_COND) != 0], 2, 0); |
|
| 128 |
+} |
|
| 129 |
+ |
|
| 130 |
+void |
|
| 131 |
+redraw(Uint32 *dst, Uxn *u) |
|
| 94 | 132 |
{
|
| 133 |
+ if(GUIDES) |
|
| 134 |
+ drawdebugger(dst, u); |
|
| 95 | 135 |
SDL_UpdateTexture(gTexture, NULL, dst, WIDTH * sizeof(Uint32)); |
| 96 | 136 |
SDL_RenderClear(gRenderer); |
| 97 | 137 |
SDL_RenderCopy(gRenderer, gTexture, NULL, NULL); |
| 98 | 138 |
SDL_RenderPresent(gRenderer); |
| 139 |
+ REQDRAW = 0; |
|
| 99 | 140 |
} |
| 100 | 141 |
|
| 101 | 142 |
void |
| ... | ... |
@@ -132,43 +173,6 @@ init(void) |
| 132 | 173 |
return 1; |
| 133 | 174 |
} |
| 134 | 175 |
|
| 135 |
-void |
|
| 136 |
-echos(St8 *s, Uint8 len, char *name) |
|
| 137 |
-{
|
|
| 138 |
- int i; |
|
| 139 |
- printf("\n%s\n", name);
|
|
| 140 |
- for(i = 0; i < len; ++i) {
|
|
| 141 |
- if(i % 16 == 0) |
|
| 142 |
- printf("\n");
|
|
| 143 |
- printf("%02x%c", s->dat[i], s->ptr == i ? '<' : ' ');
|
|
| 144 |
- } |
|
| 145 |
- printf("\n\n");
|
|
| 146 |
-} |
|
| 147 |
- |
|
| 148 |
-void |
|
| 149 |
-echom(Memory *m, Uint8 len, char *name) |
|
| 150 |
-{
|
|
| 151 |
- int i; |
|
| 152 |
- printf("\n%s\n", name);
|
|
| 153 |
- for(i = 0; i < len; ++i) {
|
|
| 154 |
- if(i % 16 == 0) |
|
| 155 |
- printf("\n");
|
|
| 156 |
- printf("%02x ", m->dat[i]);
|
|
| 157 |
- } |
|
| 158 |
- printf("\n\n");
|
|
| 159 |
-} |
|
| 160 |
- |
|
| 161 |
-void |
|
| 162 |
-echof(Uxn *c) |
|
| 163 |
-{
|
|
| 164 |
- printf("ended @ %d steps | hf: %x sf: %x sf: %x cf: %x\n",
|
|
| 165 |
- c->counter, |
|
| 166 |
- getflag(&c->status, FLAG_HALT) != 0, |
|
| 167 |
- getflag(&c->status, FLAG_SHORT) != 0, |
|
| 168 |
- getflag(&c->status, FLAG_SIGN) != 0, |
|
| 169 |
- getflag(&c->status, FLAG_COND) != 0); |
|
| 170 |
-} |
|
| 171 |
- |
|
| 172 | 176 |
void |
| 173 | 177 |
domouse(SDL_Event *event) |
| 174 | 178 |
{
|
| ... | ... |
@@ -242,15 +246,15 @@ screenr(Device *d, Memory *m, Uint8 b) |
| 242 | 246 |
Uint8 |
| 243 | 247 |
screenw(Device *d, Memory *m, Uint8 b) |
| 244 | 248 |
{
|
| 245 |
- d->mem[d->len++] = b; |
|
| 246 |
- if(d->len > 5) {
|
|
| 249 |
+ d->mem[d->ptr++] = b; |
|
| 250 |
+ if(d->ptr > 5) {
|
|
| 247 | 251 |
putpixel(pixels, |
| 248 | 252 |
(d->mem[2] << 8) + d->mem[3], |
| 249 | 253 |
(d->mem[0] << 8) + d->mem[1], |
| 250 | 254 |
d->mem[4]); |
| 251 | 255 |
if(d->mem[5]) |
| 252 |
- redraw(pixels); |
|
| 253 |
- d->len = 0; |
|
| 256 |
+ REQDRAW = 1; |
|
| 257 |
+ d->ptr = 0; |
|
| 254 | 258 |
} |
| 255 | 259 |
(void)m; |
| 256 | 260 |
return 0; |
| ... | ... |
@@ -259,15 +263,15 @@ screenw(Device *d, Memory *m, Uint8 b) |
| 259 | 263 |
Uint8 |
| 260 | 264 |
spritew(Device *d, Memory *m, Uint8 b) |
| 261 | 265 |
{
|
| 262 |
- d->mem[d->len++] = b; |
|
| 263 |
- if(d->len > 6) {
|
|
| 266 |
+ d->mem[d->ptr++] = b; |
|
| 267 |
+ if(d->ptr > 6) {
|
|
| 264 | 268 |
Uint16 x = (d->mem[2] << 8) + d->mem[3]; |
| 265 | 269 |
Uint16 y = (d->mem[0] << 8) + d->mem[1]; |
| 266 | 270 |
Uint8 *chr = &m->dat[(d->mem[4] << 8) + d->mem[5]]; |
| 267 | 271 |
drawchr(pixels, x, y, chr); |
| 268 | 272 |
if(d->mem[6]) |
| 269 |
- redraw(pixels); |
|
| 270 |
- d->len = 0; |
|
| 273 |
+ REQDRAW = 1; |
|
| 274 |
+ d->ptr = 0; |
|
| 271 | 275 |
} |
| 272 | 276 |
return 0; |
| 273 | 277 |
} |
| ... | ... |
@@ -279,11 +283,6 @@ start(Uxn *u) |
| 279 | 283 |
{
|
| 280 | 284 |
int ticknext = 0; |
| 281 | 285 |
evaluxn(u, u->vreset); |
| 282 |
- |
|
| 283 |
- echos(&u->wst, 0x40, "stack"); |
|
| 284 |
- echom(&u->ram, 0x40, "ram"); |
|
| 285 |
- echof(u); |
|
| 286 |
- |
|
| 287 | 286 |
while(1) {
|
| 288 | 287 |
int tick = SDL_GetTicks(); |
| 289 | 288 |
SDL_Event event; |
| ... | ... |
@@ -300,11 +299,13 @@ start(Uxn *u) |
| 300 | 299 |
case SDL_KEYUP: doctrl(&event, 0); break; |
| 301 | 300 |
case SDL_WINDOWEVENT: |
| 302 | 301 |
if(event.window.event == SDL_WINDOWEVENT_EXPOSED) |
| 303 |
- redraw(pixels); |
|
| 302 |
+ redraw(pixels, u); |
|
| 304 | 303 |
break; |
| 305 | 304 |
} |
| 306 | 305 |
} |
| 307 | 306 |
evaluxn(u, u->vframe); |
| 307 |
+ if(REQDRAW) |
|
| 308 |
+ redraw(pixels, u); |
|
| 308 | 309 |
} |
| 309 | 310 |
} |
| 310 | 311 |
|
| ... | ... |
@@ -18,21 +18,19 @@ WITH REGARD TO THIS SOFTWARE. |
| 18 | 18 |
/* clang-format off */ |
| 19 | 19 |
void setflag(Uint8 *a, char flag, int b) { if(b) *a |= flag; else *a &= (~flag); }
|
| 20 | 20 |
int getflag(Uint8 *a, char flag) { return *a & flag; }
|
| 21 |
-void warn(char *s, Uint8 b) { printf("Warning: %s(%d)\n", s, b);}
|
|
| 22 | 21 |
void mempoke8(Memory *m, Uint16 a, Uint8 b) { m->dat[a] = b; }
|
| 23 | 22 |
Uint8 mempeek8(Memory *m, Uint16 a) { return m->dat[a]; }
|
| 24 | 23 |
void mempoke16(Memory *m, Uint16 a, Uint16 b) { mempoke8(m, a, b >> 8); mempoke8(m, a + 1, b); }
|
| 25 | 24 |
Uint16 mempeek16(Memory *m, Uint16 a) { return (mempeek8(m, a) << 8) + mempeek8(m, a + 1); }
|
| 26 |
-void push8(St8 *s, Uint8 a) { s->dat[s->ptr++] = a; }
|
|
| 27 |
-Uint8 pop8(St8 *s) { return s->dat[--s->ptr]; }
|
|
| 28 |
-Uint8 peek8(St8 *s, Uint8 a) { return s->dat[s->ptr - a - 1]; }
|
|
| 29 |
-void push16(St8 *s, Uint16 a) { push8(s, a >> 8); push8(s, a); }
|
|
| 30 |
-Uint16 pop16(St8 *s) { return pop8(s) + (pop8(s) << 8); }
|
|
| 31 |
-Uint16 peek16(St8 *s, Uint8 a) { return peek8(s, a * 2) + (peek8(s, a * 2 + 1) << 8); }
|
|
| 25 |
+void push8(Stack *s, Uint8 a) { s->dat[s->ptr++] = a; }
|
|
| 26 |
+Uint8 pop8(Stack *s) { return s->dat[--s->ptr]; }
|
|
| 27 |
+Uint8 peek8(Stack *s, Uint8 a) { return s->dat[s->ptr - a - 1]; }
|
|
| 28 |
+void push16(Stack *s, Uint16 a) { push8(s, a >> 8); push8(s, a); }
|
|
| 29 |
+Uint16 pop16(Stack *s) { return pop8(s) + (pop8(s) << 8); }
|
|
| 30 |
+Uint16 peek16(Stack *s, Uint8 a) { return peek8(s, a * 2) + (peek8(s, a * 2 + 1) << 8); }
|
|
| 32 | 31 |
/* I/O */ |
| 33 | 32 |
void op_brk(Uxn *u) { setflag(&u->status, FLAG_HALT, 1); }
|
| 34 | 33 |
void op_lit(Uxn *u) { u->literal += 1; }
|
| 35 |
-void op_lix(Uxn *u) { u->literal += u->ram.dat[u->ram.ptr++]; }
|
|
| 36 | 34 |
void op_nop(Uxn *u) { printf("0x%02x \n", pop8(&u->wst)); fflush(stdout); }
|
| 37 | 35 |
void op_ior(Uxn *u) { Device *dev = &u->dev[mempeek8(&u->ram, u->devr)]; if(dev) push8(&u->wst, dev->read(dev, &u->ram, pop8(&u->wst))); }
|
| 38 | 36 |
void op_iow(Uxn *u) { Uint8 a = pop8(&u->wst); Device *dev = &u->dev[mempeek8(&u->ram, u->devw)]; if(dev) dev->write(dev, &u->ram, a); }
|
| ... | ... |
@@ -40,8 +38,8 @@ void op_ldr(Uxn *u) { Uint16 a = pop16(&u->wst); push8(&u->wst, mempeek8(&u->ram
|
| 40 | 38 |
void op_str(Uxn *u) { Uint16 a = pop16(&u->wst); Uint8 b = pop8(&u->wst); mempoke8(&u->ram, a, b); }
|
| 41 | 39 |
/* Logic */ |
| 42 | 40 |
void op_jmp(Uxn *u) { u->ram.ptr = pop16(&u->wst); }
|
| 43 |
-void op_jsr(Uxn *u) { if(u->balance > 0){ warn("Stack unbalance", u->balance); } push16(&u->rst, u->ram.ptr); u->ram.ptr = pop16(&u->wst); }
|
|
| 44 |
-void op_rts(Uxn *u) { if(u->balance > 0){ warn("Stack unbalance", u->balance); } u->ram.ptr = pop16(&u->rst); }
|
|
| 41 |
+void op_jsr(Uxn *u) { push16(&u->rst, u->ram.ptr); u->ram.ptr = pop16(&u->wst); }
|
|
| 42 |
+void op_rts(Uxn *u) { u->ram.ptr = pop16(&u->rst); }
|
|
| 45 | 43 |
void op_and(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, b & a); }
|
| 46 | 44 |
void op_ora(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, b | a); }
|
| 47 | 45 |
void op_rol(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, b << a); }
|
| ... | ... |
@@ -93,13 +91,13 @@ void op_gth16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push8(&u-
|
| 93 | 91 |
void op_lth16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push8(&u->wst, getflag(&u->status, FLAG_SIGN) ? (Sint16)b < (Sint16)a : b < a); }
|
| 94 | 92 |
|
| 95 | 93 |
void (*ops[])(Uxn *u) = {
|
| 96 |
- op_brk, op_nop, op_lit, op_lix, op_ior, op_iow, op_ldr, op_str, |
|
| 94 |
+ op_brk, op_nop, op_lit, op_nop, op_ior, op_iow, op_ldr, op_str, |
|
| 97 | 95 |
op_jmp, op_jsr, op_nop, op_rts, op_and, op_ora, op_rol, op_ror, |
| 98 | 96 |
op_pop, op_dup, op_swp, op_ovr, op_rot, op_wsr, op_rsw, op_nop, |
| 99 | 97 |
op_add, op_sub, op_mul, op_div, op_equ, op_neq, op_gth, op_lth, |
| 100 | 98 |
/* 16-bit */ |
| 101 |
- op_brk, op_nop16, op_lit16, op_lix, op_ior16, op_iow16, op_ldr16, op_str16, |
|
| 102 |
- op_jmp, op_jsr, op_nop, op_rts, op_and16, op_ora16, op_rol16, op_ror16, |
|
| 99 |
+ op_brk, op_nop16, op_lit16, op_nop, op_ior16, op_iow16, op_ldr16, op_str16, |
|
| 100 |
+ op_jmp, op_jsr, op_nop, op_rts, op_and16, op_ora16, op_rol16, op_ror16, |
|
| 103 | 101 |
op_pop16, op_dup16, op_swp16, op_ovr16, op_rot16, op_wsr16, op_rsw16, op_nop, |
| 104 | 102 |
op_add16, op_sub16, op_mul16, op_div16, op_equ16, op_neq16, op_gth16, op_lth16 |
| 105 | 103 |
}; |
| ... | ... |
@@ -121,7 +119,7 @@ Uint8 opr[][2] = {
|
| 121 | 119 |
int |
| 122 | 120 |
haltuxn(Uxn *u, char *name, int id) |
| 123 | 121 |
{
|
| 124 |
- printf("Error: %s#%04x, at 0x%04x\n", name, id, u->counter);
|
|
| 122 |
+ printf("Halted: %s#%04x, at 0x%04x\n", name, id, u->counter);
|
|
| 125 | 123 |
return 0; |
| 126 | 124 |
} |
| 127 | 125 |
|
| ... | ... |
@@ -142,6 +140,8 @@ opcuxn(Uxn *u, Uint8 instr) |
| 142 | 140 |
setflag(&u->status, FLAG_SHORT, (instr >> 5) & 1); |
| 143 | 141 |
setflag(&u->status, FLAG_SIGN, (instr >> 6) & 1); |
| 144 | 142 |
setflag(&u->status, FLAG_COND, (instr >> 7) & 1); |
| 143 |
+ if((op == 0x09 || op == 0x0b) && u->balance) |
|
| 144 |
+ return haltuxn(u, "Stack unbalance", op); |
|
| 145 | 145 |
if(getflag(&u->status, FLAG_SHORT)) |
| 146 | 146 |
op += 32; |
| 147 | 147 |
if(u->wst.ptr < opr[op][0]) |
| ... | ... |
@@ -192,7 +192,7 @@ loaduxn(Uxn *u, char *filepath) |
| 192 | 192 |
{
|
| 193 | 193 |
FILE *f; |
| 194 | 194 |
if(!(f = fopen(filepath, "rb"))) |
| 195 |
- return haltuxn(u, "Missing input.", 0); |
|
| 195 |
+ return haltuxn(u, "Missing input rom.", 0); |
|
| 196 | 196 |
fread(u->ram.dat, sizeof(u->ram.dat), 1, f); |
| 197 | 197 |
u->devr = 0xfff8; |
| 198 | 198 |
u->devw = 0xfff9; |
| ... | ... |
@@ -213,7 +213,7 @@ portuxn(Uxn *u, char *name, Uint8 (*rfn)(Device *, Memory *, Uint8), Uint8 (*wfn |
| 213 | 213 |
Device *d = &u->dev[u->devices++]; |
| 214 | 214 |
d->read = rfn; |
| 215 | 215 |
d->write = wfn; |
| 216 |
- d->len = 0; |
|
| 216 |
+ d->ptr = 0; |
|
| 217 | 217 |
printf("Device #%d: %s \n", u->devices - 1, name);
|
| 218 | 218 |
return d; |
| 219 | 219 |
} |
| ... | ... |
@@ -24,7 +24,7 @@ typedef signed short Sint16; |
| 24 | 24 |
typedef struct {
|
| 25 | 25 |
Uint8 ptr; |
| 26 | 26 |
Uint8 dat[256]; |
| 27 |
-} St8; |
|
| 27 |
+} Stack; |
|
| 28 | 28 |
|
| 29 | 29 |
typedef struct {
|
| 30 | 30 |
Uint16 ptr; |
| ... | ... |
@@ -32,7 +32,7 @@ typedef struct {
|
| 32 | 32 |
} Memory; |
| 33 | 33 |
|
| 34 | 34 |
typedef struct Device {
|
| 35 |
- Uint8 len, mem[8]; |
|
| 35 |
+ Uint8 ptr, mem[8]; |
|
| 36 | 36 |
Uint8 (*read)(struct Device *, Memory *, Uint8); |
| 37 | 37 |
Uint8 (*write)(struct Device *, Memory *, Uint8); |
| 38 | 38 |
} Device; |
| ... | ... |
@@ -40,7 +40,7 @@ typedef struct Device {
|
| 40 | 40 |
typedef struct {
|
| 41 | 41 |
Uint8 literal, status, balance, devices; |
| 42 | 42 |
Uint16 counter, devr, devw, vreset, vframe, verror; |
| 43 |
- St8 wst, rst; |
|
| 43 |
+ Stack wst, rst; |
|
| 44 | 44 |
Memory ram; |
| 45 | 45 |
Device dev[256]; |
| 46 | 46 |
} Uxn; |