| ... | ... |
@@ -44,6 +44,8 @@ evaluxn(u, u->vframe); /* Each frame |
| 44 | 44 |
- `+12ef`, a literal signed short. |
| 45 | 45 |
- `-1a`, a literal signed byte(negative). |
| 46 | 46 |
- `-12ef`, a literal signed short(negative). |
| 47 |
+- `.ab`, a raw byte in memory. |
|
| 48 |
+- `.abcd`, a raw short in memory. |
|
| 47 | 49 |
|
| 48 | 50 |
### Special |
| 49 | 51 |
|
| ... | ... |
@@ -81,6 +83,21 @@ BRK |
| 81 | 83 |
|FFFA .RESET .FRAME .ERROR |
| 82 | 84 |
``` |
| 83 | 85 |
|
| 86 |
+## Emulator |
|
| 87 |
+ |
|
| 88 |
+### Controller(dev/ctrl) |
|
| 89 |
+ |
|
| 90 |
+A device that works like a NES controller, each button is a bit from a single byte. |
|
| 91 |
+ |
|
| 92 |
+- Ctrl |
|
| 93 |
+- Alt |
|
| 94 |
+- Escape |
|
| 95 |
+- Return |
|
| 96 |
+- Up |
|
| 97 |
+- Down |
|
| 98 |
+- Left |
|
| 99 |
+- Right |
|
| 100 |
+ |
|
| 84 | 101 |
## TODOs |
| 85 | 102 |
|
| 86 | 103 |
- Defines? |
| ... | ... |
@@ -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/test.usm bin/boot.rom |
|
| 27 |
+./bin/assembler examples/controller.usm bin/boot.rom |
|
| 28 | 28 |
./bin/emulator bin/boot.rom |
| ... | ... |
@@ -37,7 +37,7 @@ SDL_Renderer *gRenderer; |
| 37 | 37 |
SDL_Texture *gTexture; |
| 38 | 38 |
Uint32 *pixels; |
| 39 | 39 |
|
| 40 |
-Device *devconsole, *devscreen, *devmouse, *devkey, *devsprite; |
|
| 40 |
+Device *devconsole, *devscreen, *devmouse, *devkey, *devsprite, *devctrl; |
|
| 41 | 41 |
|
| 42 | 42 |
#pragma mark - Helpers |
| 43 | 43 |
|
| ... | ... |
@@ -65,9 +65,7 @@ drawchr(Uint32 *dst, int x, int y, Uint8 *sprite) |
| 65 | 65 |
for(h = 0; h < 8; h++) {
|
| 66 | 66 |
int ch1 = ((sprite[v] >> h) & 0x1); |
| 67 | 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); |
|
| 68 |
+ putpixel(dst, x + 7 - h, y + v, ch1 + ch2); |
|
| 71 | 69 |
} |
| 72 | 70 |
} |
| 73 | 71 |
|
| ... | ... |
@@ -192,8 +190,25 @@ domouse(SDL_Event *event) |
| 192 | 190 |
void |
| 193 | 191 |
dokey(SDL_Event *event) |
| 194 | 192 |
{
|
| 195 |
- (void)event; |
|
| 196 |
- /* printf("key\n"); */
|
|
| 193 |
+} |
|
| 194 |
+ |
|
| 195 |
+void |
|
| 196 |
+doctrl(SDL_Event *event, int z) |
|
| 197 |
+{
|
|
| 198 |
+ Uint8 flag = 0x00; |
|
| 199 |
+ if(SDL_GetModState() & KMOD_LCTRL || SDL_GetModState() & KMOD_RCTRL) |
|
| 200 |
+ flag = 0x01; |
|
| 201 |
+ if(SDL_GetModState() & KMOD_LALT || SDL_GetModState() & KMOD_RALT) |
|
| 202 |
+ flag = 0x02; |
|
| 203 |
+ switch(event->key.keysym.sym) {
|
|
| 204 |
+ case SDLK_ESCAPE: flag = 0x04; break; |
|
| 205 |
+ case SDLK_RETURN: flag = 0x08; break; |
|
| 206 |
+ case SDLK_UP: flag = 0x10; break; |
|
| 207 |
+ case SDLK_DOWN: flag = 0x20; break; |
|
| 208 |
+ case SDLK_LEFT: flag = 0x40; break; |
|
| 209 |
+ case SDLK_RIGHT: flag = 0x80; break; |
|
| 210 |
+ } |
|
| 211 |
+ setflag(&devctrl->mem[0], flag, z); |
|
| 197 | 212 |
} |
| 198 | 213 |
|
| 199 | 214 |
#pragma mark - Devices |
| ... | ... |
@@ -296,6 +311,20 @@ keyw(Device *d, Memory *m, Uint8 b) |
| 296 | 311 |
return 0; |
| 297 | 312 |
} |
| 298 | 313 |
|
| 314 |
+Uint8 |
|
| 315 |
+ctrlr(Device *d, Memory *m, Uint8 b) |
|
| 316 |
+{
|
|
| 317 |
+ return d->mem[b]; |
|
| 318 |
+} |
|
| 319 |
+ |
|
| 320 |
+Uint8 |
|
| 321 |
+ctrlw(Device *d, Memory *m, Uint8 b) |
|
| 322 |
+{
|
|
| 323 |
+ (void)d; |
|
| 324 |
+ (void)b; |
|
| 325 |
+ return 0; |
|
| 326 |
+} |
|
| 327 |
+ |
|
| 299 | 328 |
#pragma mark - Generics |
| 300 | 329 |
|
| 301 | 330 |
int |
| ... | ... |
@@ -314,20 +343,21 @@ start(Uxn *u) |
| 314 | 343 |
if(tick < ticknext) |
| 315 | 344 |
SDL_Delay(ticknext - tick); |
| 316 | 345 |
ticknext = tick + (1000 / FPS); |
| 317 |
- evaluxn(u, u->vframe); |
|
| 318 | 346 |
while(SDL_PollEvent(&event) != 0) {
|
| 319 | 347 |
switch(event.type) {
|
| 320 | 348 |
case SDL_QUIT: quit(); break; |
| 321 | 349 |
case SDL_MOUSEBUTTONUP: |
| 322 | 350 |
case SDL_MOUSEBUTTONDOWN: |
| 323 | 351 |
case SDL_MOUSEMOTION: domouse(&event); break; |
| 324 |
- case SDL_KEYDOWN: dokey(&event); break; |
|
| 352 |
+ case SDL_KEYDOWN: doctrl(&event, 1); break; |
|
| 353 |
+ case SDL_KEYUP: doctrl(&event, 0); break; |
|
| 325 | 354 |
case SDL_WINDOWEVENT: |
| 326 | 355 |
if(event.window.event == SDL_WINDOWEVENT_EXPOSED) |
| 327 | 356 |
redraw(pixels); |
| 328 | 357 |
break; |
| 329 | 358 |
} |
| 330 | 359 |
} |
| 360 |
+ evaluxn(u, u->vframe); |
|
| 331 | 361 |
} |
| 332 | 362 |
} |
| 333 | 363 |
|
| ... | ... |
@@ -350,6 +380,7 @@ main(int argc, char **argv) |
| 350 | 380 |
devmouse = portuxn(&u, "mouse", mouser, mousew); |
| 351 | 381 |
devkey = portuxn(&u, "key", keyr, keyw); |
| 352 | 382 |
devsprite = portuxn(&u, "ppu-sprite", ppusr, ppusw); |
| 383 |
+ devctrl = portuxn(&u, "ctrl", ctrlr, ctrlw); |
|
| 353 | 384 |
|
| 354 | 385 |
start(&u); |
| 355 | 386 |
|
| 356 | 387 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,54 @@ |
| 1 |
+( comment ) |
|
| 2 |
+ |
|
| 3 |
+:dev/r fff8 ( const read port ) |
|
| 4 |
+:dev/w fff9 ( const write port ) |
|
| 5 |
+ |
|
| 6 |
+;x 2 ;y 2 |
|
| 7 |
+ |
|
| 8 |
+|0100 @RESET |
|
| 9 |
+ |
|
| 10 |
+ #05 ,dev/r STR ( set dev/read to ctrl ) |
|
| 11 |
+ #04 ,dev/w STR ( set dev/write to ppu-sprite ) |
|
| 12 |
+ |
|
| 13 |
+ #0080 ,x STR2 |
|
| 14 |
+ #0040 ,y STR2 |
|
| 15 |
+ #01 ,cursor_icn ,x LDR2 ,y LDR2 ,putsprite JSR |
|
| 16 |
+ |
|
| 17 |
+BRK |
|
| 18 |
+ |
|
| 19 |
+|0200 @SPRITESHEET |
|
| 20 |
+ |
|
| 21 |
+@cursor_icn .80c0 .e0f0 .f8e0 .1000 .0000 .0000 .0000 .0000 |
|
| 22 |
+@star_icn .1054 .28c6 .2854 .1000 .0000 .0000 .0000 .0000 |
|
| 23 |
+ |
|
| 24 |
+BRK |
|
| 25 |
+ |
|
| 26 |
+|c000 @FRAME |
|
| 27 |
+ |
|
| 28 |
+ #00 IOR #10 NEQ ,next0 ROT JMP? POP2 |
|
| 29 |
+ ,y LDR2 #0001 SUB2 ,y STR2 |
|
| 30 |
+ @next0 |
|
| 31 |
+ #00 IOR #20 NEQ ,next1 ROT JMP? POP2 |
|
| 32 |
+ ,y LDR2 #0001 ADD2 ,y STR2 |
|
| 33 |
+ @next1 |
|
| 34 |
+ #00 IOR #40 NEQ ,next2 ROT JMP? POP2 |
|
| 35 |
+ ,x LDR2 #0001 SUB2 ,x STR2 |
|
| 36 |
+ @next2 |
|
| 37 |
+ #00 IOR #80 NEQ ,next3 ROT JMP? POP2 |
|
| 38 |
+ ,x LDR2 #0001 ADD2 ,x STR2 |
|
| 39 |
+ @next3 |
|
| 40 |
+ ( redraw ) |
|
| 41 |
+ #01 ,cursor_icn ,x LDR2 ,y LDR2 ,putsprite JSR |
|
| 42 |
+ |
|
| 43 |
+BRK |
|
| 44 |
+ |
|
| 45 |
+@putsprite |
|
| 46 |
+ IOW2 ( y short ) |
|
| 47 |
+ IOW2 ( x short ) |
|
| 48 |
+ IOW2 ( sprite address ) |
|
| 49 |
+ IOW ( redraw byte ) |
|
| 50 |
+ RTS |
|
| 51 |
+ |
|
| 52 |
+|d000 @ERROR BRK |
|
| 53 |
+ |
|
| 54 |
+|FFFA .RESET .FRAME .ERROR |
| 0 | 55 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,46 @@ |
| 1 |
+( comment ) |
|
| 2 |
+ |
|
| 3 |
+:dev/w fff9 ( const write port ) |
|
| 4 |
+ |
|
| 5 |
+|0100 @RESET |
|
| 6 |
+ |
|
| 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 |
+ #00 ,star_icn #0031 #0021 ,putsprite JSR |
|
| 16 |
+ #00 ,cursor_icn #0021 #0016 ,putsprite JSR |
|
| 17 |
+ #00 ,star_icn #0055 #0042 ,putsprite JSR |
|
| 18 |
+ #01 ,cursor_icn #0067 #0031 ,putsprite JSR |
|
| 19 |
+ |
|
| 20 |
+BRK |
|
| 21 |
+ |
|
| 22 |
+@putsprite |
|
| 23 |
+ IOW2 ( y short ) |
|
| 24 |
+ IOW2 ( x short ) |
|
| 25 |
+ IOW2 ( sprite address ) |
|
| 26 |
+ IOW ( redraw byte ) |
|
| 27 |
+ RTS |
|
| 28 |
+ |
|
| 29 |
+@putpixel |
|
| 30 |
+ IOW2 ( y short ) |
|
| 31 |
+ IOW2 ( x short ) |
|
| 32 |
+ IOW ( color byte ) |
|
| 33 |
+ IOW ( redraw byte ) |
|
| 34 |
+ RTS |
|
| 35 |
+ |
|
| 36 |
+|0200 @SPRITESHEET |
|
| 37 |
+ |
|
| 38 |
+@cursor_icn .80c0 .e0f0 .f8e0 .1000 .0000 .0000 .0000 .0000 |
|
| 39 |
+@star_icn .1054 .28c6 .2854 .1000 .0000 .0000 .0000 .0000 |
|
| 40 |
+ |
|
| 41 |
+BRK |
|
| 42 |
+ |
|
| 43 |
+|c000 @FRAME BRK |
|
| 44 |
+|d000 @ERROR BRK |
|
| 45 |
+ |
|
| 46 |
+|FFFA .RESET .FRAME .ERROR |
| ... | ... |
@@ -1,22 +1,44 @@ |
| 1 | 1 |
( comment ) |
| 2 | 2 |
|
| 3 |
+:dev/r fff8 ( const read port ) |
|
| 3 | 4 |
:dev/w fff9 ( const write port ) |
| 4 | 5 |
|
| 6 |
+;x 2 ;y 2 |
|
| 7 |
+ |
|
| 5 | 8 |
|0100 @RESET |
| 6 | 9 |
|
| 7 |
- #01 ,dev/w STR ( set dev/write to screen ) |
|
| 10 |
+ #05 ,dev/r STR ( set dev/read to ctrl ) |
|
| 11 |
+ #04 ,dev/w STR ( set dev/write to ppu-sprite ) |
|
| 12 |
+ |
|
| 13 |
+ #0080 ,x STR2 |
|
| 14 |
+ #0040 ,y STR2 |
|
| 15 |
+ #01 ,cursor_icn ,x LDR2 ,y LDR2 ,putsprite JSR |
|
| 8 | 16 |
|
| 9 |
- ( draw 1 pixel ) |
|
| 10 |
- #00 #01 #0021 #0021 ,putpixel JSR |
|
| 17 |
+BRK |
|
| 18 |
+ |
|
| 19 |
+|0200 @SPRITESHEET |
|
| 11 | 20 |
|
| 12 |
- #04 ,dev/w STR ( set dev/write to screen ) |
|
| 21 |
+@cursor_icn .80c0 .e0f0 .f8e0 .1000 .0000 .0000 .0000 .0000 |
|
| 22 |
+@star_icn .1054 .28c6 .2854 .1000 .0000 .0000 .0000 .0000 |
|
| 13 | 23 |
|
| 14 |
- #00 ,star_icn #0001 #0001 ,putsprite JSR |
|
| 24 |
+BRK |
|
| 15 | 25 |
|
| 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 |
|
| 26 |
+|c000 @FRAME |
|
| 27 |
+ |
|
| 28 |
+ #00 IOR #10 NEQ ,next0 ROT JMP? POP2 |
|
| 29 |
+ ,y LDR2 #0001 SUB2 ,y STR2 |
|
| 30 |
+ @next0 |
|
| 31 |
+ #00 IOR #20 NEQ ,next1 ROT JMP? POP2 |
|
| 32 |
+ ,y LDR2 #0001 ADD2 ,y STR2 |
|
| 33 |
+ @next1 |
|
| 34 |
+ #00 IOR #40 NEQ ,next2 ROT JMP? POP2 |
|
| 35 |
+ ,x LDR2 #0001 SUB2 ,x STR2 |
|
| 36 |
+ @next2 |
|
| 37 |
+ #00 IOR #80 NEQ ,next3 ROT JMP? POP2 |
|
| 38 |
+ ,x LDR2 #0001 ADD2 ,x STR2 |
|
| 39 |
+ @next3 |
|
| 40 |
+ ( redraw ) |
|
| 41 |
+ #01 ,cursor_icn ,x LDR2 ,y LDR2 ,putsprite JSR |
|
| 20 | 42 |
|
| 21 | 43 |
BRK |
| 22 | 44 |
|
| ... | ... |
@@ -27,21 +49,6 @@ BRK |
| 27 | 49 |
IOW ( redraw byte ) |
| 28 | 50 |
RTS |
| 29 | 51 |
|
| 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 |
|
| 43 |
- |
|
| 44 |
-|c000 @FRAME BRK |
|
| 45 | 52 |
|d000 @ERROR BRK |
| 46 | 53 |
|
| 47 | 54 |
|FFFA .RESET .FRAME .ERROR |
| ... | ... |
@@ -30,10 +30,10 @@ void push16(St8 *s, Uint16 a) { push8(s, a >> 8); push8(s, a); }
|
| 30 | 30 |
Uint16 pop16(St8 *s) { return pop8(s) + (pop8(s) << 8); }
|
| 31 | 31 |
Uint16 peek16(St8 *s, Uint8 a) { return peek8(s, a * 2) + (peek8(s, a * 2 + 1) << 8); }
|
| 32 | 32 |
/* I/O */ |
| 33 |
-void op_brk(Uxn *u) { setflag(&u->status,FLAG_HALT, 1); }
|
|
| 33 |
+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 |
-void op_nop(Uxn *u) { printf("0x%02x ", pop8(&u->wst)); }
|
|
| 36 |
+void op_nop(Uxn *u) { printf("0x%02x \n", pop8(&u->wst)); fflush(stdout); }
|
|
| 37 | 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 | 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)); }
|