| ... | ... |
@@ -20,5 +20,5 @@ cc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werr |
| 20 | 20 |
# cc uxn.c emulator.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -L/usr/local/lib -lSDL2 -o bin/emulator |
| 21 | 21 |
|
| 22 | 22 |
# run |
| 23 |
-./bin/assembler examples/test.usm bin/boot.rom |
|
| 23 |
+./bin/assembler examples/paint.usm bin/boot.rom |
|
| 24 | 24 |
./bin/emulator bin/boot.rom |
| ... | ... |
@@ -20,12 +20,13 @@ WITH REGARD TO THIS SOFTWARE. |
| 20 | 20 |
#define RES (HOR * VER * 16) |
| 21 | 21 |
|
| 22 | 22 |
typedef struct {
|
| 23 |
+ Uint8 reqdraw; |
|
| 23 | 24 |
Uint8 bg[RES], fg[RES]; |
| 24 | 25 |
} Screen; |
| 25 | 26 |
|
| 26 | 27 |
int WIDTH = 8 * HOR + 8 * PAD * 2; |
| 27 | 28 |
int HEIGHT = 8 * VER + 8 * PAD * 2; |
| 28 |
-int FPS = 30, GUIDES = 1, REQDRAW = 0, ZOOM = 2; |
|
| 29 |
+int FPS = 30, GUIDES = 1, ZOOM = 2; |
|
| 29 | 30 |
|
| 30 | 31 |
Uint32 theme[] = {
|
| 31 | 32 |
0x000000, |
| ... | ... |
@@ -58,7 +59,15 @@ SDL_Texture *gTexture; |
| 58 | 59 |
Uint32 *pixels; |
| 59 | 60 |
|
| 60 | 61 |
Screen screen; |
| 61 |
-Device *devconsole, *devscreen, *devmouse, *devkey, *devsprite, *devcontroller, *devfg; |
|
| 62 |
+Device *devconsole, *devscreen, *devmouse, *devkey, *devsprite, *devcontroller; |
|
| 63 |
+ |
|
| 64 |
+#pragma mark - Helpers |
|
| 65 |
+ |
|
| 66 |
+int |
|
| 67 |
+clamp(int val, int min, int max) |
|
| 68 |
+{
|
|
| 69 |
+ return (val >= min) ? (val <= max) ? val : max : min; |
|
| 70 |
+} |
|
| 62 | 71 |
|
| 63 | 72 |
#pragma mark - Paint |
| 64 | 73 |
|
| ... | ... |
@@ -85,12 +94,27 @@ paintpixel(Uint8 *dst, Uint16 x, Uint16 y, Uint8 color) |
| 85 | 94 |
} |
| 86 | 95 |
|
| 87 | 96 |
void |
| 88 |
-painticn(Uint8 *dst, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 fg) |
|
| 97 |
+paintchr(Uint8 *dst, Uint16 x, Uint16 y, Uint8 *sprite) |
|
| 98 |
+{
|
|
| 99 |
+ Uint16 v, h; |
|
| 100 |
+ for(v = 0; v < 8; v++) |
|
| 101 |
+ for(h = 0; h < 8; h++) {
|
|
| 102 |
+ Uint8 ch1 = ((sprite[v] >> h) & 0x1); |
|
| 103 |
+ Uint8 ch2 = (((sprite[v + 8] >> h) & 0x1) << 1); |
|
| 104 |
+ paintpixel(dst, x + h, y + v, ch1 + ch2); |
|
| 105 |
+ } |
|
| 106 |
+} |
|
| 107 |
+ |
|
| 108 |
+void |
|
| 109 |
+painticn(Uint8 *dst, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 fg, Uint8 alpha) |
|
| 89 | 110 |
{
|
| 90 | 111 |
Uint16 v, h; |
| 91 | 112 |
for(v = 0; v < 8; v++) |
| 92 |
- for(h = 0; h < 8; h++) |
|
| 93 |
- paintpixel(dst, x + h, y + v, ((sprite[v] >> (7 - h)) & 0x1) ? fg : 0); |
|
| 113 |
+ for(h = 0; h < 8; h++) {
|
|
| 114 |
+ Uint8 ch1 = ((sprite[v] >> (7 - h)) & 0x1); |
|
| 115 |
+ if(!alpha || (alpha && ch1)) |
|
| 116 |
+ paintpixel(dst, x + h, y + v, ch1 ? fg : 0); |
|
| 117 |
+ } |
|
| 94 | 118 |
} |
| 95 | 119 |
|
| 96 | 120 |
#pragma mark - Helpers |
| ... | ... |
@@ -175,7 +199,7 @@ redraw(Uint32 *dst, Uxn *u) |
| 175 | 199 |
SDL_RenderClear(gRenderer); |
| 176 | 200 |
SDL_RenderCopy(gRenderer, gTexture, NULL, NULL); |
| 177 | 201 |
SDL_RenderPresent(gRenderer); |
| 178 |
- REQDRAW = 0; |
|
| 202 |
+ screen.reqdraw = 0; |
|
| 179 | 203 |
} |
| 180 | 204 |
|
| 181 | 205 |
void |
| ... | ... |
@@ -216,16 +240,8 @@ init(void) |
| 216 | 240 |
void |
| 217 | 241 |
domouse(SDL_Event *event) |
| 218 | 242 |
{
|
| 219 |
- int x = (event->motion.x - PAD * 8 * ZOOM) / ZOOM; |
|
| 220 |
- int y = (event->motion.y - PAD * 8 * ZOOM) / ZOOM; |
|
| 221 |
- if(x < 0) |
|
| 222 |
- x = 0; |
|
| 223 |
- else if(x > WIDTH) |
|
| 224 |
- x = WIDTH - 1; |
|
| 225 |
- if(y < 0) |
|
| 226 |
- y = 0; |
|
| 227 |
- else if(y > HEIGHT) |
|
| 228 |
- y = HEIGHT - 1; |
|
| 243 |
+ int x = clamp((event->motion.x - PAD * 8 * ZOOM) / ZOOM, 0, WIDTH - 1); |
|
| 244 |
+ int y = clamp((event->motion.y - PAD * 8 * ZOOM) / ZOOM, 0, HEIGHT - 1); |
|
| 229 | 245 |
devmouse->mem[0] = (x >> 8) & 0xff; |
| 230 | 246 |
devmouse->mem[1] = x & 0xff; |
| 231 | 247 |
devmouse->mem[2] = (y >> 8) & 0xff; |
| ... | ... |
@@ -300,7 +316,7 @@ screenw(Device *d, Memory *m, Uint8 b) |
| 300 | 316 |
(d->mem[0] << 8) + d->mem[1], |
| 301 | 317 |
d->mem[4]); |
| 302 | 318 |
if(d->mem[5] == 1) |
| 303 |
- REQDRAW = 1; |
|
| 319 |
+ screen.reqdraw = 1; |
|
| 304 | 320 |
d->ptr = 0; |
| 305 | 321 |
} |
| 306 | 322 |
(void)m; |
| ... | ... |
@@ -309,24 +325,6 @@ screenw(Device *d, Memory *m, Uint8 b) |
| 309 | 325 |
|
| 310 | 326 |
Uint8 |
| 311 | 327 |
spritew(Device *d, Memory *m, Uint8 b) |
| 312 |
-{
|
|
| 313 |
- d->mem[d->ptr++] = b; |
|
| 314 |
- if(d->ptr == 6) {
|
|
| 315 |
- int i; |
|
| 316 |
- Uint16 x = (d->mem[2] << 8) + d->mem[3]; |
|
| 317 |
- Uint16 y = (d->mem[0] << 8) + d->mem[1]; |
|
| 318 |
- Uint16 a = (d->mem[4] << 8) + d->mem[5]; |
|
| 319 |
- Uint16 key = (x + y * HOR) * 16; |
|
| 320 |
- for(i = 0; i < 16; ++i) |
|
| 321 |
- screen.bg[key + i] = m->dat[a + i]; |
|
| 322 |
- REQDRAW = 1; |
|
| 323 |
- d->ptr = 0; |
|
| 324 |
- } |
|
| 325 |
- return 0; |
|
| 326 |
-} |
|
| 327 |
- |
|
| 328 |
-Uint8 /* TODO: merge this device into screen/sprite */ |
|
| 329 |
-fgw(Device *d, Memory *m, Uint8 b) |
|
| 330 | 328 |
{
|
| 331 | 329 |
d->mem[d->ptr++] = b; |
| 332 | 330 |
if(d->ptr == 7) {
|
| ... | ... |
@@ -335,8 +333,11 @@ fgw(Device *d, Memory *m, Uint8 b) |
| 335 | 333 |
Uint16 a = (d->mem[4] << 8) + d->mem[5]; |
| 336 | 334 |
Uint8 clr = d->mem[6] & 0xf; |
| 337 | 335 |
Uint8 layer = d->mem[6] >> 4 & 0xf; |
| 338 |
- painticn(layer ? screen.fg : screen.bg, x, y, &m->dat[a], clr); |
|
| 339 |
- REQDRAW = 1; |
|
| 336 |
+ if(clr > 7) |
|
| 337 |
+ paintchr(layer ? screen.fg : screen.bg, x, y, &m->dat[a]); |
|
| 338 |
+ else |
|
| 339 |
+ painticn(layer ? screen.fg : screen.bg, x, y, &m->dat[a], clr % 4, clr > 3); |
|
| 340 |
+ screen.reqdraw = 1; |
|
| 340 | 341 |
d->ptr = 0; |
| 341 | 342 |
} |
| 342 | 343 |
return 0; |
| ... | ... |
@@ -349,7 +350,7 @@ start(Uxn *u) |
| 349 | 350 |
{
|
| 350 | 351 |
int ticknext = 0; |
| 351 | 352 |
evaluxn(u, u->vreset); |
| 352 |
- if(REQDRAW) |
|
| 353 |
+ if(screen.reqdraw) |
|
| 353 | 354 |
redraw(pixels, u); |
| 354 | 355 |
while(1) {
|
| 355 | 356 |
int tick = SDL_GetTicks(); |
| ... | ... |
@@ -372,7 +373,7 @@ start(Uxn *u) |
| 372 | 373 |
} |
| 373 | 374 |
} |
| 374 | 375 |
evaluxn(u, u->vframe); |
| 375 |
- if(REQDRAW) |
|
| 376 |
+ if(screen.reqdraw) |
|
| 376 | 377 |
redraw(pixels, u); |
| 377 | 378 |
} |
| 378 | 379 |
} |
| ... | ... |
@@ -397,7 +398,6 @@ main(int argc, char **argv) |
| 397 | 398 |
devcontroller = portuxn(&u, "controller", defaultrw, defaultrw); |
| 398 | 399 |
devkey = portuxn(&u, "key", defaultrw, consolew); |
| 399 | 400 |
devmouse = portuxn(&u, "mouse", defaultrw, defaultrw); |
| 400 |
- devfg = portuxn(&u, "fg", defaultrw, fgw); |
|
| 401 | 401 |
|
| 402 | 402 |
start(&u); |
| 403 | 403 |
quit(); |
| 404 | 404 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,58 @@ |
| 1 |
+( sprite ) |
|
| 2 |
+ |
|
| 3 |
+:dev/r fff8 ( std read port ) |
|
| 4 |
+:dev/w fff9 ( std write port ) |
|
| 5 |
+ |
|
| 6 |
+;mousex 2 ;mousey 2 ;lastx 2 ;lasty 2 ;color 1 |
|
| 7 |
+ |
|
| 8 |
+|0100 @RESET |
|
| 9 |
+ |
|
| 10 |
+ #05 =dev/r ( set dev/read mouse ) |
|
| 11 |
+ #02 =dev/w ( set dev/write to sprite ) |
|
| 12 |
+ |
|
| 13 |
+ #00 ,rounds_chr #0004 #0004 ,drawsprite JSR |
|
| 14 |
+ |
|
| 15 |
+BRK |
|
| 16 |
+ |
|
| 17 |
+|c000 @FRAME |
|
| 18 |
+ |
|
| 19 |
+ #02 =dev/w ( set dev/write to sprite ) |
|
| 20 |
+ |
|
| 21 |
+ ( clear last cursor ) |
|
| 22 |
+ #10 ,clear_icn ~lastx ~lasty ,drawsprite JSR |
|
| 23 |
+ |
|
| 24 |
+ ( record mouse values ) |
|
| 25 |
+ #00 IOR2 =mousex #02 IOR2 =mousey |
|
| 26 |
+ #04 IOR #11 ADD =color |
|
| 27 |
+ |
|
| 28 |
+ ~color ,cursor_icn ~mousex ~mousey ,drawsprite JSR |
|
| 29 |
+ |
|
| 30 |
+ ( check paint ) |
|
| 31 |
+ #04 IOR #00 EQU ,skip ROT JMP? POP2 |
|
| 32 |
+ #05 ,brush_large ~mousex #0004 SUB2 ~mousey #0004 SUB2 ,drawsprite JSR |
|
| 33 |
+ @skip |
|
| 34 |
+ |
|
| 35 |
+ ~mousex =lastx ~mousey =lasty |
|
| 36 |
+ |
|
| 37 |
+BRK |
|
| 38 |
+ |
|
| 39 |
+@drawsprite |
|
| 40 |
+ IOW2 ( y byte ) |
|
| 41 |
+ IOW2 ( x byte ) |
|
| 42 |
+ IOW2 ( sprite address ) |
|
| 43 |
+ IOW ( layer-color ) |
|
| 44 |
+ RTS |
|
| 45 |
+ |
|
| 46 |
+|0200 @SPRITESHEET |
|
| 47 |
+ |
|
| 48 |
+@rounds_chr [ 3844 92aa 9244 3800 0038 7c7c 7c38 0000 ] |
|
| 49 |
+@cursor_icn [ 80c0 e0f0 f8e0 1000 ] |
|
| 50 |
+@clear_icn [ 0000 0000 0000 0000 ] |
|
| 51 |
+@brush_large [ 387c fefe fe7c 3800 ] |
|
| 52 |
+@brush_small [ 0038 7c7c 7c38 0000 ] |
|
| 53 |
+ |
|
| 54 |
+BRK |
|
| 55 |
+ |
|
| 56 |
+|d000 @ERROR BRK |
|
| 57 |
+ |
|
| 58 |
+|FFFA .RESET .FRAME .ERROR |
| ... | ... |
@@ -16,7 +16,7 @@ BRK |
| 16 | 16 |
|
| 17 | 17 |
|c000 @FRAME |
| 18 | 18 |
|
| 19 |
- #06 =dev/w ( set dev/write to sprite ) |
|
| 19 |
+ #02 =dev/w ( set dev/write to sprite ) |
|
| 20 | 20 |
|
| 21 | 21 |
( clear last cursor ) |
| 22 | 22 |
#10 ,clear_icn ~lastx ~lasty ,drawsprite JSR |
| ... | ... |
@@ -26,6 +26,12 @@ BRK |
| 26 | 26 |
#04 IOR #11 ADD =color |
| 27 | 27 |
|
| 28 | 28 |
~color ,cursor_icn ~mousex ~mousey ,drawsprite JSR |
| 29 |
+ |
|
| 30 |
+ ( check paint ) |
|
| 31 |
+ #04 IOR #00 EQU ,skip ROT JMP? POP2 |
|
| 32 |
+ #05 ,brush_large ~mousex #0004 SUB2 ~mousey #0004 SUB2 ,drawsprite JSR |
|
| 33 |
+ @skip |
|
| 34 |
+ |
|
| 29 | 35 |
~mousex =lastx ~mousey =lasty |
| 30 | 36 |
|
| 31 | 37 |
BRK |
| ... | ... |
@@ -42,6 +48,8 @@ BRK |
| 42 | 48 |
@rounds_chr [ 3844 92aa 9244 3800 0038 7c7c 7c38 0000 ] |
| 43 | 49 |
@cursor_icn [ 80c0 e0f0 f8e0 1000 ] |
| 44 | 50 |
@clear_icn [ 0000 0000 0000 0000 ] |
| 51 |
+@brush_large [ 387c fefe fe7c 3800 ] |
|
| 52 |
+@brush_small [ 0038 7c7c 7c38 0000 ] |
|
| 45 | 53 |
|
| 46 | 54 |
BRK |
| 47 | 55 |
|