... | ... |
@@ -213,8 +213,8 @@ pass1(FILE *f) |
213 | 213 |
else { |
214 | 214 |
switch(w[0]) { |
215 | 215 |
case '|': addr = shex(w + 1); break; |
216 |
- case '.': addr += 2; break; |
|
217 | 216 |
case ',': addr += 3; break; |
217 |
+ case '.': addr += (slen(w + 1) == 2 ? 1 : 2); break; |
|
218 | 218 |
case '+': /* signed positive */ |
219 | 219 |
case '-': /* signed negative */ |
220 | 220 |
case '#': addr += (slen(w + 1) == 2 ? 2 : 3); break; |
... | ... |
@@ -242,8 +242,10 @@ pass2(FILE *f) |
242 | 242 |
else if((op = findopcode(w)) || scmp(w, "BRK")) pushbyte(op, 0); |
243 | 243 |
else if(w[0] == ':') fscanf(f, "%s", w); |
244 | 244 |
else if(w[0] == ';') fscanf(f, "%s", w); |
245 |
- else if(w[0] == '#' && sihx(w + 1) && slen(w + 1) == 2) pushbyte(shex(w), 1); |
|
246 |
- else if(w[0] == '#' && sihx(w + 1) && slen(w + 1) == 4) pushshort(shex(w), 1); |
|
245 |
+ else if(w[0] == '.' && sihx(w + 1) && slen(w + 1) == 2) pushbyte(shex(w + 1), 0); |
|
246 |
+ else if(w[0] == '.' && sihx(w + 1) && slen(w + 1) == 4) pushshort(shex(w + 1), 0); |
|
247 |
+ else if(w[0] == '#' && sihx(w + 1) && slen(w + 1) == 2) pushbyte(shex(w + 1), 1); |
|
248 |
+ else if(w[0] == '#' && sihx(w + 1) && slen(w + 1) == 4) pushshort(shex(w + 1), 1); |
|
247 | 249 |
else if(w[0] == '+' && sihx(w + 1) && slen(w + 1) == 2) pushbyte((Sint8)shex(w + 1), 1); |
248 | 250 |
else if(w[0] == '+' && sihx(w + 1) && slen(w + 1) == 4) pushshort((Sint16)shex(w + 1), 1); |
249 | 251 |
else if(w[0] == '-' && sihx(w + 1) && slen(w + 1) == 2) pushbyte((Sint8)(shex(w + 1) * -1), 1); |
... | ... |
@@ -24,5 +24,5 @@ rm -f ./bin/emulator |
24 | 24 |
cc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined uxn.c emulator.c -L/usr/local/lib -lSDL2 -o bin/emulator |
25 | 25 |
|
26 | 26 |
# run |
27 |
-./bin/assembler examples/line.usm bin/boot.rom |
|
27 |
+./bin/assembler examples/test.usm bin/boot.rom |
|
28 | 28 |
./bin/emulator bin/boot.rom |
... | ... |
@@ -37,14 +37,9 @@ SDL_Renderer *gRenderer; |
37 | 37 |
SDL_Texture *gTexture; |
38 | 38 |
Uint32 *pixels; |
39 | 39 |
|
40 |
-Device *devconsole, *devscreen, *devmouse, *devkey; |
|
40 |
+Device *devconsole, *devscreen, *devmouse, *devkey, *devsprite; |
|
41 | 41 |
|
42 |
-int |
|
43 |
-error(char *msg, const char *err) |
|
44 |
-{ |
|
45 |
- printf("Error %s: %s\n", msg, err); |
|
46 |
- return 0; |
|
47 |
-} |
|
42 |
+#pragma mark - Helpers |
|
48 | 43 |
|
49 | 44 |
void |
50 | 45 |
clear(Uint32 *dst) |
... | ... |
@@ -59,7 +54,41 @@ void |
59 | 54 |
putpixel(Uint32 *dst, int x, int y, int color) |
60 | 55 |
{ |
61 | 56 |
if(x >= 0 && x < WIDTH - 8 && y >= 0 && y < HEIGHT - 8) |
62 |
- dst[y * WIDTH + x] = theme[color]; |
|
57 |
+ dst[(y + PAD * 8) * WIDTH + (x + PAD * 8)] = theme[color]; |
|
58 |
+} |
|
59 |
+ |
|
60 |
+void |
|
61 |
+drawchr(Uint32 *dst, int x, int y, Uint8 *sprite) |
|
62 |
+{ |
|
63 |
+ int v, h; |
|
64 |
+ for(v = 0; v < 8; v++) |
|
65 |
+ for(h = 0; h < 8; h++) { |
|
66 |
+ int ch1 = ((sprite[v] >> h) & 0x1); |
|
67 |
+ int ch2 = (((sprite[v + 8] >> h) & 0x1) << 1); |
|
68 |
+ int clr = ch1 + ch2; |
|
69 |
+ int guides = GUIDES && !clr && ((x + y) / 8) % 2; |
|
70 |
+ putpixel(dst, x + 7 - h, y + v, guides ? 4 : clr); |
|
71 |
+ } |
|
72 |
+} |
|
73 |
+ |
|
74 |
+void |
|
75 |
+drawicn(Uint32 *dst, int x, int y, Uint8 *sprite, int fg, int bg) |
|
76 |
+{ |
|
77 |
+ int v, h; |
|
78 |
+ for(v = 0; v < 8; v++) |
|
79 |
+ for(h = 0; h < 8; h++) { |
|
80 |
+ int ch1 = (sprite[v] >> (7 - h)) & 0x1; |
|
81 |
+ putpixel(dst, x + h, y + v, ch1 ? fg : bg); |
|
82 |
+ } |
|
83 |
+} |
|
84 |
+ |
|
85 |
+#pragma mark - Core |
|
86 |
+ |
|
87 |
+int |
|
88 |
+error(char *msg, const char *err) |
|
89 |
+{ |
|
90 |
+ printf("Error %s: %s\n", msg, err); |
|
91 |
+ return 0; |
|
63 | 92 |
} |
64 | 93 |
|
65 | 94 |
void |
... | ... |
@@ -170,7 +199,7 @@ dokey(SDL_Event *event) |
170 | 199 |
#pragma mark - Devices |
171 | 200 |
|
172 | 201 |
Uint8 |
173 |
-consoler(Device *d, Uint8 b) |
|
202 |
+consoler(Device *d, Memory *m, Uint8 b) |
|
174 | 203 |
{ |
175 | 204 |
(void)b; |
176 | 205 |
(void)d; |
... | ... |
@@ -178,7 +207,7 @@ consoler(Device *d, Uint8 b) |
178 | 207 |
} |
179 | 208 |
|
180 | 209 |
Uint8 |
181 |
-consolew(Device *d, Uint8 b) |
|
210 |
+consolew(Device *d, Memory *m, Uint8 b) |
|
182 | 211 |
{ |
183 | 212 |
(void)d; |
184 | 213 |
if(b) |
... | ... |
@@ -188,7 +217,7 @@ consolew(Device *d, Uint8 b) |
188 | 217 |
} |
189 | 218 |
|
190 | 219 |
Uint8 |
191 |
-screenr(Device *d, Uint8 b) |
|
220 |
+ppur(Device *d, Memory *m, Uint8 b) |
|
192 | 221 |
{ |
193 | 222 |
switch(b) { |
194 | 223 |
case 0: return (WIDTH >> 8) & 0xff; |
... | ... |
@@ -200,7 +229,7 @@ screenr(Device *d, Uint8 b) |
200 | 229 |
} |
201 | 230 |
|
202 | 231 |
Uint8 |
203 |
-screenw(Device *d, Uint8 b) |
|
232 |
+ppuw(Device *d, Memory *m, Uint8 b) |
|
204 | 233 |
{ |
205 | 234 |
d->mem[d->len++] = b; |
206 | 235 |
if(d->len > 5) { |
... | ... |
@@ -216,13 +245,35 @@ screenw(Device *d, Uint8 b) |
216 | 245 |
} |
217 | 246 |
|
218 | 247 |
Uint8 |
219 |
-mouser(Device *d, Uint8 b) |
|
248 |
+ppusr(Device *d, Memory *m, Uint8 b) |
|
249 |
+{ |
|
250 |
+ return 0; |
|
251 |
+} |
|
252 |
+ |
|
253 |
+Uint8 |
|
254 |
+ppusw(Device *d, Memory *m, Uint8 b) |
|
255 |
+{ |
|
256 |
+ d->mem[d->len++] = b; |
|
257 |
+ if(d->len > 6) { |
|
258 |
+ Uint16 x = (d->mem[2] << 8) + d->mem[3]; |
|
259 |
+ Uint16 y = (d->mem[0] << 8) + d->mem[1]; |
|
260 |
+ Uint8 *chr = &m->dat[(d->mem[4] << 8) + d->mem[5]]; |
|
261 |
+ drawchr(pixels, x, y, chr); |
|
262 |
+ if(d->mem[6]) |
|
263 |
+ redraw(pixels); |
|
264 |
+ d->len = 0; |
|
265 |
+ } |
|
266 |
+ return 0; |
|
267 |
+} |
|
268 |
+ |
|
269 |
+Uint8 |
|
270 |
+mouser(Device *d, Memory *m, Uint8 b) |
|
220 | 271 |
{ |
221 | 272 |
return d->mem[b]; |
222 | 273 |
} |
223 | 274 |
|
224 | 275 |
Uint8 |
225 |
-mousew(Device *d, Uint8 b) |
|
276 |
+mousew(Device *d, Memory *m, Uint8 b) |
|
226 | 277 |
{ |
227 | 278 |
(void)d; |
228 | 279 |
(void)b; |
... | ... |
@@ -230,7 +281,7 @@ mousew(Device *d, Uint8 b) |
230 | 281 |
} |
231 | 282 |
|
232 | 283 |
Uint8 |
233 |
-keyr(Device *d, Uint8 b) |
|
284 |
+keyr(Device *d, Memory *m, Uint8 b) |
|
234 | 285 |
{ |
235 | 286 |
(void)d; |
236 | 287 |
(void)b; |
... | ... |
@@ -238,7 +289,7 @@ keyr(Device *d, Uint8 b) |
238 | 289 |
} |
239 | 290 |
|
240 | 291 |
Uint8 |
241 |
-keyw(Device *d, Uint8 b) |
|
292 |
+keyw(Device *d, Memory *m, Uint8 b) |
|
242 | 293 |
{ |
243 | 294 |
(void)d; |
244 | 295 |
(void)b; |
... | ... |
@@ -295,9 +346,10 @@ main(int argc, char **argv) |
295 | 346 |
return error("Init", "Failed"); |
296 | 347 |
|
297 | 348 |
devconsole = portuxn(&u, "console", consoler, consolew); |
298 |
- devscreen = portuxn(&u, "screen", screenr, screenw); |
|
349 |
+ devscreen = portuxn(&u, "ppu", ppur, ppuw); |
|
299 | 350 |
devmouse = portuxn(&u, "mouse", mouser, mousew); |
300 | 351 |
devkey = portuxn(&u, "key", keyr, keyw); |
352 |
+ devsprite = portuxn(&u, "ppu-sprite", ppusr, ppusw); |
|
301 | 353 |
|
302 | 354 |
start(&u); |
303 | 355 |
|
... | ... |
@@ -4,16 +4,42 @@ |
4 | 4 |
|
5 | 5 |
|0100 @RESET |
6 | 6 |
|
7 |
- #00 ,dev/w STR ( set dev/write to console ) |
|
8 |
- ,string ( add string pointer to stack ) |
|
9 |
- @loop |
|
10 |
- DUP2 LDR IOW ( write pointer value to console ) |
|
11 |
- #0001 ADD2 ( increment string pointer ) |
|
12 |
- DUP2 LDR #00 NEQ ,loop ROT JMP? POP2 ( while *ptr!=0 goto loop ) |
|
7 |
+ #01 ,dev/w STR ( set dev/write to screen ) |
|
8 |
+ |
|
9 |
+ ( draw 1 pixel ) |
|
10 |
+ #00 #01 #0021 #0021 ,putpixel JSR |
|
11 |
+ |
|
12 |
+ #04 ,dev/w STR ( set dev/write to screen ) |
|
13 |
+ |
|
14 |
+ #00 ,star_icn #0001 #0001 ,putsprite JSR |
|
15 |
+ |
|
16 |
+ #00 ,star_icn #0031 #0021 ,putsprite JSR |
|
17 |
+ #00 ,cursor_icn #0021 #0016 ,putsprite JSR |
|
18 |
+ #00 ,star_icn #0055 #0042 ,putsprite JSR |
|
19 |
+ #01 ,cursor_icn #0067 #0031 ,putsprite JSR |
|
13 | 20 |
|
14 | 21 |
BRK |
15 | 22 |
|
16 |
-@string " Hello World " ( add string to memory ) |
|
23 |
+@putsprite |
|
24 |
+ IOW2 ( y short ) |
|
25 |
+ IOW2 ( x short ) |
|
26 |
+ IOW2 ( sprite address ) |
|
27 |
+ IOW ( redraw byte ) |
|
28 |
+ RTS |
|
29 |
+ |
|
30 |
+@putpixel |
|
31 |
+ IOW2 ( y short ) |
|
32 |
+ IOW2 ( x short ) |
|
33 |
+ IOW ( color byte ) |
|
34 |
+ IOW ( redraw byte ) |
|
35 |
+ RTS |
|
36 |
+ |
|
37 |
+|0200 @SPRITESHEET |
|
38 |
+ |
|
39 |
+@cursor_icn .80c0 .e0f0 .f8e0 .1000 .0000 .0000 .0000 .0000 |
|
40 |
+@star_icn .1054 .28c6 .2854 .1000 .0000 .0000 .0000 .0000 |
|
41 |
+ |
|
42 |
+BRK |
|
17 | 43 |
|
18 | 44 |
|c000 @FRAME BRK |
19 | 45 |
|d000 @ERROR BRK |
... | ... |
@@ -34,8 +34,8 @@ void op_brk(Uxn *u) { setflag(&u->status,FLAG_HALT, 1); } |
34 | 34 |
void op_lit(Uxn *u) { u->literal += 1; } |
35 | 35 |
void op_lix(Uxn *u) { u->literal += u->ram.dat[u->ram.ptr++]; } |
36 | 36 |
void op_nop(Uxn *u) { printf("0x%02x ", pop8(&u->wst)); } |
37 |
-void op_ior(Uxn *u) { Device *dev = &u->dev[mempeek8(&u->ram, u->devr)]; if(dev) push8(&u->wst, dev->read(dev, pop8(&u->wst))); } |
|
38 |
-void op_iow(Uxn *u) { Uint8 a = pop8(&u->wst); Device *dev = &u->dev[mempeek8(&u->ram, u->devw)]; if(dev) dev->write(dev, a); } |
|
37 |
+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 |
+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); } |
|
39 | 39 |
void op_ldr(Uxn *u) { Uint16 a = pop16(&u->wst); push8(&u->wst, mempeek8(&u->ram, a)); } |
40 | 40 |
void op_str(Uxn *u) { Uint16 a = pop16(&u->wst); Uint8 b = pop8(&u->wst); mempoke8(&u->ram, a, b); } |
41 | 41 |
/* Logic */ |
... | ... |
@@ -63,8 +63,8 @@ void op_lth(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, |
63 | 63 |
/* --- */ |
64 | 64 |
void op_lit16(Uxn *u) { u->literal += 2; } |
65 | 65 |
void op_nop16(Uxn *u) { printf("%04x\n", pop16(&u->wst)); } |
66 |
-void op_ior16(Uxn *u) { Uint8 a = pop8(&u->wst); Device *dev = &u->dev[mempeek8(&u->ram, u->devr)]; if(dev) push16(&u->wst, (dev->read(dev, a) << 8) + dev->read(dev, a + 1)); } |
|
67 |
-void op_iow16(Uxn *u) { Uint8 a = pop8(&u->wst); Uint8 b = pop8(&u->wst); Device *dev = &u->dev[mempeek8(&u->ram, u->devw)]; if(dev) { dev->write(dev, b); dev->write(dev, a); } } |
|
66 |
+void op_ior16(Uxn *u) { Uint8 a = pop8(&u->wst); Device *dev = &u->dev[mempeek8(&u->ram, u->devr)]; if(dev) push16(&u->wst, (dev->read(dev, &u->ram, a) << 8) + dev->read(dev, &u->ram, a + 1)); } |
|
67 |
+void op_iow16(Uxn *u) { Uint8 a = pop8(&u->wst); Uint8 b = pop8(&u->wst); Device *dev = &u->dev[mempeek8(&u->ram, u->devw)]; if(dev) { dev->write(dev, &u->ram, b); dev->write(dev, &u->ram, a); } } |
|
68 | 68 |
void op_ldr16(Uxn *u) { Uint16 a = pop16(&u->wst); push16(&u->wst, mempeek16(&u->ram, a)); } |
69 | 69 |
void op_str16(Uxn *u) { Uint16 a = pop16(&u->wst); Uint16 b = pop16(&u->wst); mempoke16(&u->ram, a, b); } |
70 | 70 |
/* Stack(16-bits) */ |
... | ... |
@@ -202,7 +202,7 @@ loaduxn(Uxn *u, char *filepath) |
202 | 202 |
} |
203 | 203 |
|
204 | 204 |
Device * |
205 |
-portuxn(Uxn *u, char *name, Uint8 (*rfn)(Device *, Uint8), Uint8 (*wfn)(Device *, Uint8)) |
|
205 |
+portuxn(Uxn *u, char *name, Uint8 (*rfn)(Device *, Memory *, Uint8), Uint8 (*wfn)(Device *, Memory *, Uint8)) |
|
206 | 206 |
{ |
207 | 207 |
Device *d = &u->dev[u->devices++]; |
208 | 208 |
d->read = rfn; |
... | ... |
@@ -33,8 +33,8 @@ typedef struct { |
33 | 33 |
|
34 | 34 |
typedef struct Device { |
35 | 35 |
Uint8 len, mem[8]; |
36 |
- Uint8 (*read)(struct Device *, Uint8); |
|
37 |
- Uint8 (*write)(struct Device *, Uint8); |
|
36 |
+ Uint8 (*read)(struct Device *, Memory *, Uint8); |
|
37 |
+ Uint8 (*write)(struct Device *, Memory *, Uint8); |
|
38 | 38 |
} Device; |
39 | 39 |
|
40 | 40 |
typedef struct { |
... | ... |
@@ -50,4 +50,4 @@ int getflag(Uint8 *status, char flag); |
50 | 50 |
int loaduxn(Uxn *c, char *filepath); |
51 | 51 |
int bootuxn(Uxn *c); |
52 | 52 |
int evaluxn(Uxn *u, Uint16 vec); |
53 |
-Device *portuxn(Uxn *u, char *name, Uint8 (*rfn)(Device *, Uint8), Uint8 (*wfn)(Device *, Uint8)); |
|
53 |
+Device *portuxn(Uxn *u, char *name, Uint8 (*rfn)(Device *, Memory *, Uint8), Uint8 (*wfn)(Device *, Memory *, Uint8)); |