aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2023-04-19 17:58:04 +0200
committerBad Diode <bd@badd10de.dev>2023-04-19 17:58:04 +0200
commitd68d16405b013967e0faa12f9dfc608e3bb3d0d4 (patch)
treef8436d01c6a9aa112cdb6ac6bd042fe2a7c0b046
parent2e8ab813a9e4c2d908d5450e346a81d2a91a75e8 (diff)
downloaduxngba-d68d16405b013967e0faa12f9dfc608e3bb3d0d4.tar.gz
uxngba-d68d16405b013967e0faa12f9dfc608e3bb3d0d4.zip
Update uxn core and fix some new ppu bugs
-rw-r--r--src/main.c162
-rw-r--r--src/ppu.c162
-rw-r--r--src/uxn.c160
-rw-r--r--src/uxn.h8
4 files changed, 318 insertions, 174 deletions
diff --git a/src/main.c b/src/main.c
index 1193e9e..ba835ff 100644
--- a/src/main.c
+++ b/src/main.c
@@ -13,16 +13,16 @@
13#include <time.h> 13#include <time.h>
14 14
15#include "common.h" 15#include "common.h"
16#include "bitmap.h"
17#include "filesystem.c" 16#include "filesystem.c"
18 17
19#include "rom.c"
20#include "uxn.c" 18#include "uxn.c"
21#include "ppu.c" 19#include "ppu.c"
22#include "apu.c" 20#include "apu.c"
23#include "file.c" 21#include "file.c"
24#include "text.h" 22#include "text.h"
25 23
24#include "rom.c"
25
26// 26//
27// Config parameters. 27// Config parameters.
28// 28//
@@ -37,6 +37,8 @@
37#define CONTROL_METHODS CONTROL_CONTROLLER,CONTROL_MOUSE,CONTROL_KEYBOARD 37#define CONTROL_METHODS CONTROL_CONTROLLER,CONTROL_MOUSE,CONTROL_KEYBOARD
38#endif 38#endif
39 39
40#define PROF_ENABLE 1
41
40#ifdef PROF_ENABLE 42#ifdef PROF_ENABLE
41#if PROF_ENABLE == 0 43#if PROF_ENABLE == 0
42#define TEXT_ENABLE 1 44#define TEXT_ENABLE 1
@@ -148,20 +150,29 @@ screen_deo(u8 *ram, u8 *d, u8 port) {
148 switch(port) { 150 switch(port) {
149 case 0xe: { 151 case 0xe: {
150 u16 x, y; 152 u16 x, y;
151 u8 layer = d[0xe] & 0x40; 153 u8 *layer = (d[0xe] & 0x40) ? ppu.fg : ppu.bg;
152 PEKDEV(x, 0x8); 154 x = PEEK2(d + 0x8);
153 PEKDEV(y, 0xa); 155 y = PEEK2(d + 0xa);
154 PROF(ppu_pixel(layer ? ppu.fg : ppu.bg, x, y, d[0xe] & 0x3), ppu_pixel_cycles); 156 if(d[0xe] & 0x80) {
155 if(d[0x6] & 0x01) POKDEV(0x8, x + 1); /* auto x+1 */ 157 screen_fill(layer,
156 if(d[0x6] & 0x02) POKDEV(0xa, y + 1); /* auto y+1 */ 158 (d[0xe] & 0x10) ? 0 : x,
159 (d[0xe] & 0x20) ? 0 : y,
160 (d[0xe] & 0x10) ? x : SCREEN_WIDTH,
161 (d[0xe] & 0x20) ? y : SCREEN_HEIGHT,
162 (d[0xe] & 0x03));
163 } else {
164 PROF(ppu_pixel(layer, x, y, d[0xe] & 0x3), ppu_pixel_cycles);
165 if(d[0x6] & 0x01) POKE2(d + 0x8, x + 1); /* auto x+1 */
166 if(d[0x6] & 0x02) POKE2(d + 0xa, y + 1); /* auto y+1 */
167 }
157 break; 168 break;
158 } 169 }
159 case 0xf: { 170 case 0xf: {
160 u16 x, y, dx, dy, addr; 171 u16 x, y, dx, dy, addr;
161 u8 n, twobpp = !!(d[0xf] & 0x80); 172 u8 n, twobpp = !!(d[0xf] & 0x80);
162 PEKDEV(x, 0x8); 173 x = PEEK2(d + 0x8);
163 PEKDEV(y, 0xa); 174 y = PEEK2(d + 0xa);
164 PEKDEV(addr, 0xc); 175 addr = PEEK2(d + 0xc);
165 n = d[0x6] >> 4; 176 n = d[0x6] >> 4;
166 dx = (d[0x6] & 0x01) << 3; 177 dx = (d[0x6] & 0x01) << 3;
167 dy = (d[0x6] & 0x02) << 2; 178 dy = (d[0x6] & 0x02) << 2;
@@ -181,9 +192,9 @@ screen_deo(u8 *ram, u8 *d, u8 port) {
181 } 192 }
182 addr += (d[0x6] & 0x04) << (1 + twobpp); 193 addr += (d[0x6] & 0x04) << (1 + twobpp);
183 } 194 }
184 POKDEV(0xc, addr); /* auto addr+length */ 195 POKE2(d + 0xc, addr); /* auto addr+length */
185 POKDEV(0x8, x + dx); /* auto x+8 */ 196 POKE2(d + 0x8, x + dx); /* auto x+8 */
186 POKDEV(0xa, y + dy); /* auto y+8 */ 197 POKE2(d + 0xa, y + dy); /* auto y+8 */
187 break; 198 break;
188 } 199 }
189 } 200 }
@@ -195,7 +206,7 @@ audio_dei(int instance, u8 *d, u8 port) {
195 switch(port) { 206 switch(port) {
196 // case 0x4: return apu_get_vu(instance); 207 // case 0x4: return apu_get_vu(instance);
197 case 0x2: { 208 case 0x2: {
198 POKDEV(0x2, c->pos); 209 POKE2(d + 0x2, c->pos);
199 c->pos <<= 12; // fixed point. 210 c->pos <<= 12; // fixed point.
200 break; 211 break;
201 } 212 }
@@ -211,9 +222,9 @@ audio_deo(int instance, u8 *d, u8 port, Uxn *u) {
211 u16 adsr = 0; 222 u16 adsr = 0;
212 u16 addr = 0; 223 u16 addr = 0;
213 u8 pitch = d[0xf] & 0x7f; 224 u8 pitch = d[0xf] & 0x7f;
214 PEKDEV(adsr, 0x8); 225 adsr = PEEK2(d + 0x8);
215 PEKDEV(length, 0xa); 226 length = PEEK2(d + 0xa);
216 PEKDEV(addr, 0xc); 227 addr = PEEK2(d + 0xc);
217 u8 *data = &u->ram[addr]; 228 u8 *data = &u->ram[addr];
218 u32 vol = MAX(d[0xe] >> 4, d[0xe] & 0xf) * 4 / 3; 229 u32 vol = MAX(d[0xe] >> 4, d[0xe] & 0xf) * 4 / 3;
219 bool loop = !(d[0xf] & 0x80); 230 bool loop = !(d[0xf] & 0x80);
@@ -248,7 +259,7 @@ file_dei(u8 id, u8 *d, u8 port) {
248 case 0xc: 259 case 0xc:
249 case 0xd: { 260 case 0xd: {
250 res = file_read(c, &d[port], 1); 261 res = file_read(c, &d[port], 1);
251 POKDEV(0x2, res); 262 POKE2(d + 0x2, res);
252 break; 263 break;
253 } 264 }
254 } 265 }
@@ -261,41 +272,41 @@ file_deo(u8 id, u8 *ram, u8 *d, u8 port) {
261 UxnFile *f = &uxn_file[id]; 272 UxnFile *f = &uxn_file[id];
262 switch(port) { 273 switch(port) {
263 case 0x5: { 274 case 0x5: {
264 PEKDEV(a, 0x4); 275 a = PEEK2(d + 0x4);
265 PEKDEV(b, 0xa); 276 b = PEEK2(d + 0xa);
266 if(b > 0x10000 - a) { 277 if(b > 0x10000 - a) {
267 b = 0x10000 - a; 278 b = 0x10000 - a;
268 } 279 }
269 res = file_stat(f, &ram[a], b); 280 res = file_stat(f, &ram[a], b);
270 POKDEV(0x2, res); 281 POKE2(d + 0x2, res);
271 } break; 282 } break;
272 case 0x6: { 283 case 0x6: {
273 // TODO: no file deletion for now 284 // TODO: no file deletion for now
274 // res = file_delete(); 285 // res = file_delete();
275 // POKDEV(0x2, res); 286 // POKE2(d + 0x2, res);
276 } break; 287 } break;
277 case 0x9: { 288 case 0x9: {
278 PEKDEV(a, 0x8); 289 a = PEEK2(d + 0x8);
279 res = file_init(f, &ram[a]); 290 res = file_init(f, &ram[a]);
280 POKDEV(0x2, res); 291 POKE2(d + 0x2, res);
281 } break; 292 } break;
282 case 0xd: { 293 case 0xd: {
283 PEKDEV(a, 0xc); 294 a = PEEK2(d + 0xc);
284 PEKDEV(b, 0xa); 295 b = PEEK2(d + 0xa);
285 if(b > 0x10000 - a) { 296 if(b > 0x10000 - a) {
286 b = 0x10000 - a; 297 b = 0x10000 - a;
287 } 298 }
288 res = file_read(f, &ram[a], b); 299 res = file_read(f, &ram[a], b);
289 POKDEV(0x2, res); 300 POKE2(d + 0x2, res);
290 } break; 301 } break;
291 case 0xf: { 302 case 0xf: {
292 PEKDEV(a, 0xe); 303 a = PEEK2(d + 0xe);
293 PEKDEV(b, 0xa); 304 b = PEEK2(d + 0xa);
294 if(b > 0x10000 - a) { 305 if(b > 0x10000 - a) {
295 b = 0x10000 - a; 306 b = 0x10000 - a;
296 } 307 }
297 res = file_write(f, &ram[a], b, d[0x7]); 308 res = file_write(f, &ram[a], b, d[0x7]);
298 POKDEV(0x2, res); 309 POKE2(d + 0x2, res);
299 } break; 310 } break;
300 } 311 }
301} 312}
@@ -313,16 +324,42 @@ console_deo(u8 *d, u8 port) {
313 } 324 }
314} 325}
315 326
327#define RAM_PAGES 0x10
328
329static void
330system_cmd(u8 *ram, u16 addr) {
331 // if(ram[addr] == 0x01) {
332 // u16 i, length = PEEK2(ram + addr + 1);
333 // u16 a_page = PEEK2(ram + addr + 1 + 2);
334 // u16 a_addr = PEEK2(ram + addr + 1 + 4);
335 // u16 b_addr = PEEK2(ram + addr + 1 + 8);
336 // u8 *rom = uxn_rom;
337 // for(i = 0; i < length; i++) {
338 // switch (a_page % RAM_PAGES) {
339 // case 0: { rom = uxn_rom; } break;
340 // case 1: { rom = uxn_rom_2; } break;
341 // case 2: { rom = uxn_rom_3; } break;
342 // case 3: { rom = uxn_rom_4; } break;
343 // case 4: { rom = uxn_rom_5; } break;
344 // case 5: { rom = uxn_rom_6; } break;
345 // case 6: { rom = uxn_rom_7; } break;
346 // }
347 // ram[(u16)(b_addr + i)] = rom[(u16)(a_addr + i)];
348 // }
349 // }
350}
351
316void 352void
317system_deo(Uxn *u, u8 *d, u8 port) { 353system_deo(Uxn *u, u8 *d, u8 port) {
318 switch(port) { 354 switch(port) {
319 case 0x2: u->wst = (Stack *)(u->ram + (d[port] ? (d[port] * 0x100) : 0x10000)); break; 355 case 0x3: {
320 case 0x3: u->rst = (Stack *)(u->ram + (d[port] ? (d[port] * 0x100) : 0x10100)); break; 356 system_cmd(u->ram, PEEK2(d + 2));
357 } break;
321 } 358 }
322} 359}
323 360
324u8 361u8
325emu_dei(Uxn *u, u8 addr) { 362uxn_dei(Uxn *u, u8 addr) {
326 u8 p = addr & 0x0f, d = addr & 0xf0; 363 u8 p = addr & 0x0f, d = addr & 0xf0;
327 switch(d) { 364 switch(d) {
328 case 0x20: return screen_dei(&u->dev[d], p); 365 case 0x20: return screen_dei(&u->dev[d], p);
@@ -338,24 +375,23 @@ emu_dei(Uxn *u, u8 addr) {
338} 375}
339 376
340void 377void
341emu_deo(Uxn *u, u8 addr, u8 v) { 378uxn_deo(Uxn *u, u8 addr) {
342 u8 p = addr & 0x0f, d = addr & 0xf0; 379 u8 p = addr & 0x0f, d = addr & 0xf0;
343 u->dev[addr] = v; 380 switch(d) {
344 switch(d) { 381 case 0x00:
345 case 0x00: 382 system_deo(u, &u->dev[d], p);
346 system_deo(u, &u->dev[d], p); 383 if(p > 0x7 && p < 0xe)
347 if(p > 0x7 && p < 0xe) 384 putcolors(&u->dev[0x8]);
348 putcolors(&u->dev[0x8]); 385 break;
349 break; 386 case 0x10: console_deo(&u->dev[d], p); break;
350 case 0x10: console_deo(&u->dev[d], p); break; 387 case 0x20: screen_deo(u->ram, &u->dev[d], p); break;
351 case 0x20: screen_deo(u->ram, &u->dev[d], p); break; 388 case 0x30: audio_deo(0, &u->dev[d], p, u); break;
352 case 0x30: audio_deo(0, &u->dev[d], p, u); break; 389 case 0x40: audio_deo(1, &u->dev[d], p, u); break;
353 case 0x40: audio_deo(1, &u->dev[d], p, u); break; 390 case 0x50: audio_deo(2, &u->dev[d], p, u); break;
354 case 0x50: audio_deo(2, &u->dev[d], p, u); break; 391 case 0x60: audio_deo(3, &u->dev[d], p, u); break;
355 case 0x60: audio_deo(3, &u->dev[d], p, u); break; 392 case 0xa0: file_deo(0, u->ram, &u->dev[d], p); break;
356 case 0xa0: file_deo(0, u->ram, &u->dev[d], p); break; 393 case 0xb0: file_deo(1, u->ram, &u->dev[d], p); break;
357 case 0xb0: file_deo(1, u->ram, &u->dev[d], p); break; 394 }
358 }
359} 395}
360 396
361void 397void
@@ -363,7 +399,7 @@ init_uxn(Uxn *u) {
363 // Initialize uxn. 399 // Initialize uxn.
364 u32 fill = 0; 400 u32 fill = 0;
365 dma_fill(umem, fill, 0x10300, 3); 401 dma_fill(umem, fill, 0x10300, 3);
366 uxn_boot(u, umem, emu_dei, emu_deo); 402 uxn_boot(u, umem, uxn_dei, uxn_deo);
367 403
368 // Copy rom to VM. 404 // Copy rom to VM.
369 memcpy(u->ram + PAGE_PROGRAM, uxn_rom, sizeof(uxn_rom)); 405 memcpy(u->ram + PAGE_PROGRAM, uxn_rom, sizeof(uxn_rom));
@@ -379,16 +415,16 @@ handle_input(Uxn *u) {
379 case CONTROL_CONTROLLER: { 415 case CONTROL_CONTROLLER: {
380 u8 *d = &u->dev[0x80]; 416 u8 *d = &u->dev[0x80];
381 d[2] = 0; 417 d[2] = 0;
382 uxn_eval(u, GETVEC(d)); 418 uxn_eval(u, PEEK2(d));
383 d[3] = 0; 419 d[3] = 0;
384 } break; 420 } break;
385 case CONTROL_MOUSE: { 421 case CONTROL_MOUSE: {
386 u8 *d = &u->dev[0x90]; 422 u8 *d = &u->dev[0x90];
387 d[6] = 0; 423 d[6] = 0;
388 d[7] = 0; 424 d[7] = 0;
389 POKDEV(0x2, -10); 425 POKE2(d + 0x2, -10);
390 POKDEV(0x4, -10); 426 POKE2(d + 0x4, -10);
391 uxn_eval(u, GETVEC(d)); 427 uxn_eval(u, PEEK2(d));
392 } break; 428 } break;
393 case CONTROL_KEYBOARD: { 429 case CONTROL_KEYBOARD: {
394 toggle_keyboard(); 430 toggle_keyboard();
@@ -451,7 +487,7 @@ handle_input(Uxn *u) {
451 } 487 }
452 488
453 if (key_prev != key_curr) { 489 if (key_prev != key_curr) {
454 uxn_eval(u, GETVEC(d)); 490 uxn_eval(u, PEEK2(d));
455 } 491 }
456 d[3] = 0; 492 d[3] = 0;
457 } else if (ctrl_methods[ctrl_idx] == CONTROL_MOUSE) { 493 } else if (ctrl_methods[ctrl_idx] == CONTROL_MOUSE) {
@@ -500,10 +536,10 @@ handle_input(Uxn *u) {
500 } 536 }
501 537
502 // Eval mouse. 538 // Eval mouse.
503 POKDEV(0x2, mouse.x); 539 POKE2(d + 0x2, mouse.x);
504 POKDEV(0x4, mouse.y); 540 POKE2(d + 0x4, mouse.y);
505 if (event) { 541 if (event) {
506 uxn_eval(u, GETVEC(d)); 542 uxn_eval(u, PEEK2(d));
507 } 543 }
508 } else if (ctrl_methods[ctrl_idx] == CONTROL_KEYBOARD) { 544 } else if (ctrl_methods[ctrl_idx] == CONTROL_KEYBOARD) {
509 u8 *d = &u->dev[0x80]; 545 u8 *d = &u->dev[0x80];
@@ -549,7 +585,7 @@ handle_input(Uxn *u) {
549 d[3] = symbol; 585 d[3] = symbol;
550 } break; 586 } break;
551 } 587 }
552 uxn_eval(u, GETVEC(d)); 588 uxn_eval(u, PEEK2(d));
553 d[3] = 0; 589 d[3] = 0;
554 } 590 }
555 } 591 }
@@ -588,7 +624,7 @@ main(void) {
588 while(true) { 624 while(true) {
589 bios_vblank_wait(); 625 bios_vblank_wait();
590 PROF(handle_input(&u), input_cycles); 626 PROF(handle_input(&u), input_cycles);
591 PROF(uxn_eval(&u, GETVEC(&u.dev[0x20])), eval_cycles); 627 PROF(uxn_eval(&u, PEEK2(&u.dev[0x20])), eval_cycles);
592 PROF(sound_mix(), mix_cycles); 628 PROF(sound_mix(), mix_cycles);
593 PROF_SHOW(); 629 PROF_SHOW();
594 PROF(flipbuf(&ppu), flip_cycles); 630 PROF(flipbuf(&ppu), flip_cycles);
diff --git a/src/ppu.c b/src/ppu.c
index c258fe2..afde963 100644
--- a/src/ppu.c
+++ b/src/ppu.c
@@ -247,6 +247,118 @@ ppu_pixel(u32 *layer, u16 x, u16 y, u8 clr) {
247 dirty_tiles[tile_y] |= 1 << tile_x; 247 dirty_tiles[tile_y] |= 1 << tile_x;
248} 248}
249 249
250IWRAM_CODE
251void
252ppu_rect(u32 *layer, size_t x0, size_t y0, size_t x1, size_t y1, u8 clr) {
253 BOUNDCHECK_SCREEN(x0, y0);
254 BOUNDCHECK_SCREEN(x1, y1);
255
256 // Find row positions for the given x/y coordinates.
257 size_t tile_x0 = x0 / 8;
258 size_t tile_y0 = y0 / 8;
259 size_t tile_x1 = x1 / 8;
260 size_t tile_y1 = y1 / 8;
261 size_t start_col0 = x0 % 8;
262 size_t start_col1 = x1 % 8;
263 size_t start_row0 = y0 % 8;
264 size_t start_row1 = y1 % 8;
265
266 // Get a pointer to the backbuffer and the tile row.
267 u32 *buf_top = &layer[start_row0 + (tile_x0 + tile_y0 * 32) * 8];
268 u32 *buf_bot = &layer[start_row1 + (tile_x0 + tile_y1 * 32) * 8];
269
270 size_t dx = tile_x1 - tile_x0;
271 size_t dy = tile_y1 - tile_y0;
272
273 // We can update two lines at a time, which is faster than calling draw_line
274 // four times.
275 if (dx < 1) {
276 u32 row_mask = 0xFFFFFFFF;
277 row_mask >>= (7 - start_col1 - dx) * 4;
278 row_mask &= 0xFFFFFFFF << start_col0 * 4;
279 u32 row = (0x11111111 * clr) & row_mask;
280 buf_top[0] = (buf_top[0] & ~row_mask) | row;
281 buf_bot[0] = (buf_bot[0] & ~row_mask) | row;
282 dirty_tiles[tile_y0] |= 1 << tile_x0;
283 dirty_tiles[tile_y1] |= 1 << tile_x0;
284 } else {
285 size_t shift_left = start_col0 * 4;
286 size_t shift_right = (7 - start_col1) * 4;
287 u32 row_mask = 0xFFFFFFFF;
288 u32 row = 0x11111111 * clr;
289 buf_top[0] = buf_top[0] & ~(row_mask << shift_left);
290 buf_top[0] |= row << shift_left;
291 buf_bot[0] = buf_bot[0] & ~(row_mask << shift_left);
292 buf_bot[0] |= row << shift_left;
293 dirty_tiles[tile_y0] |= 1 << tile_x0;
294 dirty_tiles[tile_y1] |= 1 << tile_x0;
295 for (size_t i = 1; i < dx; i++) {
296 buf_top[i * 8] = row;
297 buf_bot[i * 8] = row;
298 dirty_tiles[tile_y0] |= 1 << (tile_x0 + i);
299 dirty_tiles[tile_y1] |= 1 << (tile_x0 + i);
300 }
301 buf_top[dx * 8] = buf_top[dx * 8] & ~(row_mask >> shift_right);
302 buf_top[dx * 8] |= row >> shift_right;
303 buf_bot[dx * 8] = buf_bot[dx * 8] & ~(row_mask >> shift_right);
304 buf_bot[dx * 8] |= row >> shift_right;
305 dirty_tiles[tile_y0] |= 1 << (tile_x0 + dx);
306 dirty_tiles[tile_y1] |= 1 << (tile_x0 + dx);
307 }
308 u32 row_mask_left = 0xF << start_col0 * 4;
309 u32 row_mask_right = 0xF << start_col1 * 4;
310 u32 row_left = (0x11111111 * clr) & row_mask_left;
311 u32 row_right = (0x11111111 * clr) & row_mask_right;
312 if (dy < 1) {
313 for (size_t i = 1; i < y1 - y0; i++, buf_top++) {
314 buf_top[1] = buf_top[1] & ~row_mask_left;
315 buf_top[1] |= row_left;
316 buf_top[1 + 8 * dx] = buf_top[1 + 8 * dx] & ~row_mask_right;
317 buf_top[1 + 8 * dx] |= row_right;
318 }
319 } else {
320 for (size_t i = 1; i < (8 - start_row0); i++, buf_top++) {
321 buf_top[1] = buf_top[1] & ~row_mask_left;
322 buf_top[1] |= row_left;
323 buf_top[1 + 8 * dx] = buf_top[1 + 8 * dx] & ~row_mask_right;
324 buf_top[1 + 8 * dx] |= row_right;
325 }
326 buf_top += 8 * 31;
327 for (size_t j = 1; j < dy; j++) {
328 for (size_t i = 0; i < 8; i++, buf_top++) {
329 buf_top[1] = buf_top[1] & ~row_mask_left;
330 buf_top[1] |= row_left;
331 buf_top[1 + 8 * dx] = buf_top[1 + 8 * dx] & ~row_mask_right;
332 buf_top[1 + 8 * dx] |= row_right;
333 }
334 buf_top += 8 * 31;
335 dirty_tiles[tile_y0 + j] |= 1 << tile_x0;
336 dirty_tiles[tile_y0 + j] |= 1 << (tile_x0 + dx);
337 }
338 for (size_t i = 0; i < start_row1; i++, buf_top++) {
339 buf_top[1] = buf_top[1] & ~row_mask_left;
340 buf_top[1] |= row_left;
341 buf_top[1 + 8 * dx] = buf_top[1 + 8 * dx] & ~row_mask_right;
342 buf_top[1 + 8 * dx] |= row_right;
343 }
344 }
345}
346
347IWRAM_CODE
348void
349screen_fill(u32 *layer, u16 x0, u16 y0, u16 x1, u16 y1, u8 clr) {
350 BOUNDCHECK_SCREEN(x0, y0);
351 BOUNDCHECK_SCREEN(x1, y1);
352
353 size_t dx = x1 - x0;
354 size_t dy = y1 - y0;
355 size_t n_rect = MIN(dx, dy);
356 n_rect = n_rect / 2 + 1;
357 for (size_t i = 0; i < n_rect; i++) {
358 ppu_rect(layer, x0 + i, y0 + i, x1 - i, y1 - i, clr);
359 }
360}
361
250#if NEW_PPU == 0 362#if NEW_PPU == 0
251IWRAM_CODE 363IWRAM_CODE
252void 364void
@@ -315,34 +427,28 @@ ppu_1bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 clr, u8 flip_x, u8 flip_y) {
315 u32 *dst = &layer[start_row + (tile_x + tile_y * 32) * 8]; 427 u32 *dst = &layer[start_row + (tile_x + tile_y * 32) * 8];
316 u32 *lut = flip_x ? dec_byte_flip_x : dec_byte; 428 u32 *lut = flip_x ? dec_byte_flip_x : dec_byte;
317 if (blending[4][clr]) { 429 if (blending[4][clr]) {
318 u64 mask = ~((u64)0xFFFFFFFF); 430 u32 mask = 0xFFFFFFFF;
319 if (!flip_y) { 431 if (!flip_y) {
320 for(size_t v = 0; v < 8; v++, dst++) { 432 for(size_t v = 0; v < 8; v++, dst++) {
321 if ((y + v) >= SCREEN_HEIGHT) break; 433 if ((y + v) >= SCREEN_HEIGHT) break;
322 u8 ch1 = sprite[v]; 434 u8 ch1 = sprite[v];
323 u32 color_1 = lut[ch1]; 435 u32 color_1 = lut[ch1];
324 u32 color_2 = (color_1 ^ 0xffffffff) & 0x11111111; 436 u32 color_2 = (color_1 ^ 0xFFFFFFFF) & 0x11111111;
325 u32 color = (color_1 * (clr & 3)) | (color_2 * (clr >> 2)); 437 u32 color = (color_1 * (clr & 3)) | (color_2 * (clr >> 2));
326 if (start_col == 0) { 438 dst[0] = (dst[0] & ~(mask << shift_left)) | (color << shift_left);
327 dst[0] = (dst[0] & mask) | color; 439 dst[8] = (dst[8] & ~(mask >> shift_right)) | (color >> shift_right);
328 } else { 440 if ((start_row + v) == 7) dst += (32 - 1) * 8;
329 dst[0] = (dst[0] & (mask << shift_left)) | color;
330 dst[8] = (dst[8] & (mask >> shift_right)) | (color >> shift_right);
331 }
332 } 441 }
333 } else { 442 } else {
334 for(size_t v = 0; v < 8; v++, dst++) { 443 for(size_t v = 0; v < 8; v++, dst++) {
335 if ((y + v) >= SCREEN_HEIGHT) break; 444 if ((y + v) >= SCREEN_HEIGHT) break;
336 u8 ch1 = sprite[(7 - v)]; 445 u8 ch1 = sprite[(7 - v)];
337 u32 color_1 = lut[ch1]; 446 u32 color_1 = lut[ch1];
338 u32 color_2 = (color_1 ^ 0xffffffff) & 0x11111111; 447 u32 color_2 = (color_1 ^ 0xFFFFFFFF) & 0x11111111;
339 u32 color = (color_1 * (clr & 3)) | (color_2 * (clr >> 2)); 448 u32 color = (color_1 * (clr & 3)) | (color_2 * (clr >> 2));
340 if (start_col == 0) { 449 dst[0] = (dst[0] & ~(mask << shift_left)) | (color << shift_left);
341 dst[0] = (dst[0] & mask) | color; 450 dst[8] = (dst[8] & ~(mask >> shift_right)) | (color >> shift_right);
342 } else { 451 if ((start_row + v) == 7) dst += (32 - 1) * 8;
343 dst[0] = (dst[0] & (mask << shift_left)) | color;
344 dst[8] = (dst[8] & (mask >> shift_right)) | (color >> shift_right);
345 }
346 } 452 }
347 } 453 }
348 } else { 454 } else {
@@ -359,6 +465,7 @@ ppu_1bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 clr, u8 flip_x, u8 flip_y) {
359 dst[0] = (dst[0] & ~(mask << shift_left)) | (color << shift_left); 465 dst[0] = (dst[0] & ~(mask << shift_left)) | (color << shift_left);
360 dst[8] = (dst[8] & ~(mask >> shift_right)) | (color >> shift_right); 466 dst[8] = (dst[8] & ~(mask >> shift_right)) | (color >> shift_right);
361 } 467 }
468 if ((start_row + v) == 7) dst += (32 - 1) * 8;
362 } 469 }
363 } else { 470 } else {
364 for(size_t v = 0; v < 8; v++, dst++) { 471 for(size_t v = 0; v < 8; v++, dst++) {
@@ -373,6 +480,7 @@ ppu_1bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 clr, u8 flip_x, u8 flip_y) {
373 dst[0] = (dst[0] & ~(mask << shift_left)) | (color << shift_left); 480 dst[0] = (dst[0] & ~(mask << shift_left)) | (color << shift_left);
374 dst[8] = (dst[8] & ~(mask >> shift_right)) | (color >> shift_right); 481 dst[8] = (dst[8] & ~(mask >> shift_right)) | (color >> shift_right);
375 } 482 }
483 if ((start_row + v) == 7) dst += (32 - 1) * 8;
376 } 484 }
377 } 485 }
378 } 486 }
@@ -529,6 +637,7 @@ ppu_2bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 clr, u8 flip_x, u8 flip_y) {
529 dst[0] = (dst[0] & (mask << shift_left)) | color; 637 dst[0] = (dst[0] & (mask << shift_left)) | color;
530 dst[8] = (dst[8] & (mask >> shift_right)) | (color >> shift_right); 638 dst[8] = (dst[8] & (mask >> shift_right)) | (color >> shift_right);
531 } 639 }
640 if ((start_row + v) == 7) dst += (32 - 1) * 8;
532 } 641 }
533 } else { 642 } else {
534 for(size_t v = 0; v < 8; v++, dst++) { 643 for(size_t v = 0; v < 8; v++, dst++) {
@@ -542,10 +651,11 @@ ppu_2bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 clr, u8 flip_x, u8 flip_y) {
542 dst[0] = (dst[0] & (mask << shift_left)) | color; 651 dst[0] = (dst[0] & (mask << shift_left)) | color;
543 dst[8] = (dst[8] & (mask >> shift_right)) | (color >> shift_right); 652 dst[8] = (dst[8] & (mask >> shift_right)) | (color >> shift_right);
544 } 653 }
654 if ((start_row + v) == 7) dst += (32 - 1) * 8;
545 } 655 }
546 } 656 }
547 } else if (blending[4][clr]) { 657 } else if (blending[4][clr]) {
548 u64 mask = ~((u64)0xFFFFFFFF << shift_left); 658 u32 mask = 0xFFFFFFFF;
549 u8 clr0 = blending[0][clr]; 659 u8 clr0 = blending[0][clr];
550 u8 clr1 = blending[1][clr]; 660 u8 clr1 = blending[1][clr];
551 u8 clr2 = blending[2][clr]; 661 u8 clr2 = blending[2][clr];
@@ -567,12 +677,9 @@ ppu_2bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 clr, u8 flip_x, u8 flip_y) {
567 (clr1 * col1mask) | 677 (clr1 * col1mask) |
568 (clr2 * col2mask) | 678 (clr2 * col2mask) |
569 (clr3 * col3mask); 679 (clr3 * col3mask);
570 if (start_col == 0) { 680 dst[0] = (dst[0] & ~(mask << shift_left)) | (color << shift_left);
571 dst[0] = (dst[0] & mask) | color; 681 dst[8] = (dst[8] & ~(mask >> shift_right)) | (color >> shift_right);
572 } else { 682 if ((start_row + v) == 7) dst += (32 - 1) * 8;
573 dst[0] = (dst[0] & (mask << shift_left)) | color;
574 dst[8] = (dst[8] & (mask >> shift_right)) | (color >> shift_right);
575 }
576 } 683 }
577 } else { 684 } else {
578 for(size_t v = 0; v < 8; v++, dst++) { 685 for(size_t v = 0; v < 8; v++, dst++) {
@@ -591,12 +698,9 @@ ppu_2bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 clr, u8 flip_x, u8 flip_y) {
591 (clr1 * col1mask) | 698 (clr1 * col1mask) |
592 (clr2 * col2mask) | 699 (clr2 * col2mask) |
593 (clr3 * col3mask); 700 (clr3 * col3mask);
594 if (start_col == 0) { 701 dst[0] = (dst[0] & ~(mask << shift_left)) | (color << shift_left);
595 dst[0] = (dst[0] & mask) | color; 702 dst[8] = (dst[8] & ~(mask >> shift_right)) | (color >> shift_right);
596 } else { 703 if ((start_row + v) == 7) dst += (32 - 1) * 8;
597 dst[0] = (dst[0] & (mask << shift_left)) | color;
598 dst[8] = (dst[8] & (mask >> shift_right)) | (color >> shift_right);
599 }
600 } 704 }
601 } 705 }
602 } else { 706 } else {
@@ -625,6 +729,7 @@ ppu_2bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 clr, u8 flip_x, u8 flip_y) {
625 dst[0] = (dst[0] & (mask << shift_left)) | color; 729 dst[0] = (dst[0] & (mask << shift_left)) | color;
626 dst[8] = (dst[8] & (mask >> shift_right)) | (color >> shift_right); 730 dst[8] = (dst[8] & (mask >> shift_right)) | (color >> shift_right);
627 } 731 }
732 if ((start_row + v) == 7) dst += (32 - 1) * 8;
628 } 733 }
629 } else { 734 } else {
630 for(size_t v = 0; v < 8; v++, dst++) { 735 for(size_t v = 0; v < 8; v++, dst++) {
@@ -648,6 +753,7 @@ ppu_2bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 clr, u8 flip_x, u8 flip_y) {
648 dst[0] = (dst[0] & (mask << shift_left)) | color; 753 dst[0] = (dst[0] & (mask << shift_left)) | color;
649 dst[8] = (dst[8] & (mask >> shift_right)) | (color >> shift_right); 754 dst[8] = (dst[8] & (mask >> shift_right)) | (color >> shift_right);
650 } 755 }
756 if ((start_row + v) == 7) dst += (32 - 1) * 8;
651 } 757 }
652 } 758 }
653 } 759 }
diff --git a/src/uxn.c b/src/uxn.c
index 5c39803..d525ff1 100644
--- a/src/uxn.c
+++ b/src/uxn.c
@@ -11,87 +11,93 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11WITH REGARD TO THIS SOFTWARE. 11WITH REGARD TO THIS SOFTWARE.
12*/ 12*/
13 13
14/* a,b,c: general use. bs: byte/short bool. src, dst: stack ptrs, swapped in return mode. 14#define T s->dat[s->ptr - 1]
15 pc: program counter. sp: ptr to src stack ptr. kptr: "keep" mode copy of src stack ptr. 15#define N s->dat[s->ptr - 2]
16 x,y: macro in params. d: macro in device. j: macro temp variables. o: macro out param. */ 16#define L s->dat[s->ptr - 3]
17#define H2 PEEK2(s->dat + s->ptr - 3)
18#define T2 PEEK2(s->dat + s->ptr - 2)
19#define N2 PEEK2(s->dat + s->ptr - 4)
20#define L2 PEEK2(s->dat + s->ptr - 6)
17 21
18#define HALT(c) { return uxn_halt(u, instr, (c), pc - 1); } 22/* Registers
19#define JUMP(x) { if(bs) pc = (x); else pc += (s8)(x); } 23
20#define PUSH8(s, x) { if(s->ptr == 0xff) HALT(2) s->dat[s->ptr++] = (x); } 24[ . ][ . ][ . ][ L ][ N ][ T ] <
21#define PUSH16(s, x) { if((j = s->ptr) >= 0xfe) HALT(2) k = (x); s->dat[j] = k >> 8; s->dat[j + 1] = k; s->ptr = j + 2; } 25[ . ][ . ][ . ][ H2 ][ T ] <
22#define PUSH(s, x) { if(bs) { PUSH16(s, (x)) } else { PUSH8(s, (x)) } } 26[ L2 ][ N2 ][ T2 ] <
23#define POP8(o) { if(!(j = *sp)) HALT(1) o = (u16)src->dat[--j]; *sp = j; } 27
24#define POP16(o) { if((j = *sp) <= 1) HALT(1) o = (src->dat[j - 2] << 8) + src->dat[j - 1]; *sp = j - 2; } 28*/
25#define POP(o) { if(bs) { POP16(o) } else { POP8(o) } } 29
26#define POKE(x, y) { if(bs) { u->ram[(x)] = (y) >> 8; u->ram[(x) + 1] = (y); } else { u->ram[(x)] = y; } } 30
27#define PEEK16(o, x) { o = (u->ram[(x)] << 8) + u->ram[(x) + 1]; } 31u16 deo_mask[] = {0xff08, 0x0300, 0xc028, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0x0000, 0x0000, 0xa260, 0xa260, 0x0000, 0x0000, 0x0000, 0x0000};
28#define PEEK(o, x) { if(bs) PEEK16(o, x) else o = u->ram[(x)]; } 32u16 dei_mask[] = {0x0000, 0x0000, 0x003c, 0x0014, 0x0014, 0x0014, 0x0014, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x07ff, 0x0000, 0x0000, 0x0000};
29#define DEVR(o, x) { o = u->dei(u, x); if (bs) o = (o << 8) + u->dei(u, (x) + 1); } 33
30#define DEVW(x, y) { if (bs) { u->deo(u, (x), (y) >> 8); u->deo(u, (x) + 1, (y)); } else { u->deo(u, x, (y)); } } 34#define POKE2(d, v) { (d)[0] = (v) >> 8; (d)[1] = (v); }
35#define PEEK2(d) ((d)[0] << 8 | (d)[1])
36#define HALT(c) { return uxn_halt(u, ins, (c), pc - 1); }
37#define SET(mul, add) { if(mul > s->ptr) HALT(1) tmp = s->ptr + k * mul + add; if(tmp > 254) HALT(2) s->ptr = tmp; }
38#define PUT(o, v) { s->dat[(u8)(s->ptr - 1 - (o))] = (v); }
39#define PUT2(o, v) { tmp = (v); s->dat[(u8)(s->ptr - o - 2)] = tmp >> 8; s->dat[(u8)(s->ptr - o - 1)] = tmp; }
40#define PUSH(stack, v) { if(s->ptr > 254) HALT(2) stack->dat[stack->ptr++] = (v); }
41#define PUSH2(stack, v) { if(s->ptr > 253) HALT(2) tmp = (v); stack->dat[stack->ptr] = tmp >> 8; stack->dat[stack->ptr + 1] = tmp; stack->ptr += 2; }
42#define DEO(a, b) { u->dev[(a)] = (b); if((deo_mask[(a) >> 4] >> ((a) & 0xf)) & 0x1) uxn_deo(u, (a)); }
43#define DEI(a, b) { PUT((a), ((dei_mask[(b) >> 4] >> ((b) & 0xf)) & 0x1) ? uxn_dei(u, (b)) : u->dev[(b)]) }
31 44
32IWRAM_CODE 45IWRAM_CODE
33int 46int
34uxn_eval(Uxn *u, u16 pc) 47uxn_eval(Uxn *u, u16 pc) {
35{ 48 u8 ins, opc, k;
36 u8 kptr, *sp; 49 u16 t, n, l, tmp;
37 u16 a, b, c, j, k, bs, instr, opcode; 50 Stack *s;
38 Stack *src, *dst; 51 if(!pc || u->dev[0x0f]) return 0;
39 if(!pc || u->dev[0x0f]) return 0; 52 for(;;) {
40 for(;;) { 53 ins = u->ram[pc++];
41 instr = u->ram[pc++]; 54 k = !!(ins & 0x80);
42 /* Return Mode */ 55 s = ins & 0x40 ? u->rst : u->wst;
43 if(instr & 0x40) { src = u->rst; dst = u->wst; } 56 opc = !(ins & 0x1f) ? 0 - (ins >> 5) : ins & 0x3f;
44 else { src = u->wst; dst = u->rst; } 57 switch(opc) {
45 /* Keep Mode */ 58 /* IMM */
46 if(instr & 0x80) { kptr = src->ptr; sp = &kptr; } 59 case 0x00: /* BRK */ return 1;
47 else sp = &src->ptr; 60 case 0xff: /* JCI */ pc += !!s->dat[--s->ptr] * PEEK2(u->ram + pc) + 2; break;
48 /* Short Mode */ 61 case 0xfe: /* JMI */ pc += PEEK2(u->ram + pc) + 2; break;
49 bs = instr & 0x20; 62 case 0xfd: /* JSI */ PUSH2(u->rst, pc + 2) pc += PEEK2(u->ram + pc) + 2; break;
50 opcode = instr & 0x1f; 63 case 0xfc: /* LIT */ PUSH(s, u->ram[pc++]) break;
51 switch(opcode - (!opcode * (instr >> 5))) { 64 case 0xfb: /* LIT2 */ PUSH2(s, PEEK2(u->ram + pc)) pc += 2; break;
52 /* Literals/Calls */ 65 case 0xfa: /* LITr */ PUSH(s, u->ram[pc++]) break;
53 case -0x0: /* BRK */ return 1; 66 case 0xf9: /* LIT2r */ PUSH2(s, PEEK2(u->ram + pc)) pc += 2; break;
54 case -0x1: /* JCI */ POP8(b) if(!b) { pc += 2; break; } // fallthrough 67 /* ALU */
55 case -0x2: /* JMI */ PEEK16(a, pc) pc += a + 2; break; 68 case 0x01: /* INC */ t=T; SET(1, 0) PUT(0, t + 1) break; case 0x21: t=T2; SET(2, 0) PUT2(0, t + 1) break;
56 case -0x3: /* JSI */ PUSH16(u->rst, pc + 2) PEEK16(a, pc) pc += a + 2; break; 69 case 0x02: /* POP */ SET(1,-1) break; case 0x22: SET(2,-2) break;
57 case -0x4: /* LIT */ 70 case 0x03: /* NIP */ t=T; SET(2,-1) PUT(0, t) break; case 0x23: t=T2; SET(4,-2) PUT2(0, t) break;
58 case -0x6: /* LITr */ a = u->ram[pc++]; PUSH8(src, a) break; 71 case 0x04: /* SWP */ t=T;n=N; SET(2, 0) PUT(0, n) PUT(1, t) break; case 0x24: t=T2;n=N2; SET(4, 0) PUT2(0, n) PUT2(2, t) break;
59 case -0x5: /* LIT2 */ 72 case 0x05: /* ROT */ t=T;n=N;l=L; SET(3, 0) PUT(0, l) PUT(1, t) PUT(2, n) break; case 0x25: t=T2;n=N2;l=L2; SET(6, 0) PUT2(0, l) PUT2(2, t) PUT2(4, n) break;
60 case -0x7: /* LIT2r */ PEEK16(a, pc) PUSH16(src, a) pc += 2; break; 73 case 0x06: /* DUP */ t=T; SET(1, 1) PUT(0, t) PUT(1, t) break; case 0x26: t=T2; SET(2, 2) PUT2(0, t) PUT2(2, t) break;
61 /* ALU */ 74 case 0x07: /* OVR */ t=T;n=N; SET(2, 1) PUT(0, n) PUT(1, t) PUT(2, n) break; case 0x27: t=T2;n=N2; SET(4, 2) PUT2(0, n) PUT2(2, t) PUT2(4, n) break;
62 case 0x01: /* INC */ POP(a) PUSH(src, a + 1) break; 75 case 0x08: /* EQU */ t=T;n=N; SET(2,-1) PUT(0, n == t) break; case 0x28: t=T2;n=N2; SET(4,-3) PUT(0, n == t) break;
63 case 0x02: /* POP */ POP(a) break; 76 case 0x09: /* NEQ */ t=T;n=N; SET(2,-1) PUT(0, n != t) break; case 0x29: t=T2;n=N2; SET(4,-3) PUT(0, n != t) break;
64 case 0x03: /* NIP */ POP(a) POP(b) PUSH(src, a) break; 77 case 0x0a: /* GTH */ t=T;n=N; SET(2,-1) PUT(0, n > t) break; case 0x2a: t=T2;n=N2; SET(4,-3) PUT(0, n > t) break;
65 case 0x04: /* SWP */ POP(a) POP(b) PUSH(src, a) PUSH(src, b) break; 78 case 0x0b: /* LTH */ t=T;n=N; SET(2,-1) PUT(0, n < t) break; case 0x2b: t=T2;n=N2; SET(4,-3) PUT(0, n < t) break;
66 case 0x05: /* ROT */ POP(a) POP(b) POP(c) PUSH(src, b) PUSH(src, a) PUSH(src, c) break; 79 case 0x0c: /* JMP */ t=T; SET(1,-1) pc += (s8)t; break; case 0x2c: t=T2; SET(2,-2) pc = t; break;
67 case 0x06: /* DUP */ POP(a) PUSH(src, a) PUSH(src, a) break; 80 case 0x0d: /* JCN */ t=T;n=N; SET(2,-2) pc += !!n * (s8)t; break; case 0x2d: t=T2;n=L; SET(3,-3) if(n) pc = t; break;
68 case 0x07: /* OVR */ POP(a) POP(b) PUSH(src, b) PUSH(src, a) PUSH(src, b) break; 81 case 0x0e: /* JSR */ t=T; SET(1,-1) PUSH2(u->rst, pc) pc += (s8)t; break; case 0x2e: t=T2; SET(2,-2) PUSH2(u->rst, pc) pc = t; break;
69 case 0x08: /* EQU */ POP(a) POP(b) PUSH8(src, b == a) break; 82 case 0x0f: /* STH */ t=T; SET(1,-1) PUSH((ins & 0x40 ? u->wst : u->rst), t) break; case 0x2f: t=T2; SET(2,-2) PUSH2((ins & 0x40 ? u->wst : u->rst), t) break;
70 case 0x09: /* NEQ */ POP(a) POP(b) PUSH8(src, b != a) break; 83 case 0x10: /* LDZ */ t=T; SET(1, 0) PUT(0, u->ram[t]) break; case 0x30: t=T; SET(1, 1) PUT2(0, PEEK2(u->ram + t)) break;
71 case 0x0a: /* GTH */ POP(a) POP(b) PUSH8(src, b > a) break; 84 case 0x11: /* STZ */ t=T;n=N; SET(2,-2) u->ram[t] = n; break; case 0x31: t=T;n=H2; SET(3,-3) POKE2(u->ram + t, n) break;
72 case 0x0b: /* LTH */ POP(a) POP(b) PUSH8(src, b < a) break; 85 case 0x12: /* LDR */ t=T; SET(1, 0) PUT(0, u->ram[pc + (s8)t]) break; case 0x32: t=T; SET(1, 1) PUT2(0, PEEK2(u->ram + pc + (s8)t)) break;
73 case 0x0c: /* JMP */ POP(a) JUMP(a) break; 86 case 0x13: /* STR */ t=T;n=N; SET(2,-2) u->ram[pc + (s8)t] = n; break; case 0x33: t=T;n=H2; SET(3,-3) POKE2(u->ram + pc + (s8)t, n) break;
74 case 0x0d: /* JCN */ POP(a) POP8(b) if(b) JUMP(a) break; 87 case 0x14: /* LDA */ t=T2; SET(2,-1) PUT(0, u->ram[t]) break; case 0x34: t=T2; SET(2, 0) PUT2(0, PEEK2(u->ram + t)) break;
75 case 0x0e: /* JSR */ POP(a) PUSH16(dst, pc) JUMP(a) break; 88 case 0x15: /* STA */ t=T2;n=L; SET(3,-3) u->ram[t] = n; break; case 0x35: t=T2;n=N2; SET(4,-4) POKE2(u->ram + t, n) break;
76 case 0x0f: /* STH */ POP(a) PUSH(dst, a) break; 89 case 0x16: /* DEI */ t=T; SET(1, 0) DEI(0, t) break; case 0x36: t=T; SET(1, 1) DEI(1, t) DEI(0, t + 1) break;
77 case 0x10: /* LDZ */ POP8(a) PEEK(b, a) PUSH(src, b) break; 90 case 0x17: /* DEO */ t=T;n=N; SET(2,-2) DEO(t, n) break; case 0x37: t=T;n=N;l=L; SET(3,-3) DEO(t, l) DEO(t + 1, n) break;
78 case 0x11: /* STZ */ POP8(a) POP(b) POKE(a, b) break; 91 case 0x18: /* ADD */ t=T;n=N; SET(2,-1) PUT(0, n + t) break; case 0x38: t=T2;n=N2; SET(4,-2) PUT2(0, n + t) break;
79 case 0x12: /* LDR */ POP8(a) b = pc + (s8)a; PEEK(c, b) PUSH(src, c) break; 92 case 0x19: /* SUB */ t=T;n=N; SET(2,-1) PUT(0, n - t) break; case 0x39: t=T2;n=N2; SET(4,-2) PUT2(0, n - t) break;
80 case 0x13: /* STR */ POP8(a) POP(b) c = pc + (s8)a; POKE(c, b) break; 93 case 0x1a: /* MUL */ t=T;n=N; SET(2,-1) PUT(0, n * t) break; case 0x3a: t=T2;n=N2; SET(4,-2) PUT2(0, n * t) break;
81 case 0x14: /* LDA */ POP16(a) PEEK(b, a) PUSH(src, b) break; 94 case 0x1b: /* DIV */ t=T;n=N; SET(2,-1) PUT(0, n / t) break; case 0x3b: t=T2;n=N2; SET(4,-2) PUT2(0, n / t) break;
82 case 0x15: /* STA */ POP16(a) POP(b) POKE(a, b) break; 95 case 0x1c: /* AND */ t=T;n=N; SET(2,-1) PUT(0, n & t) break; case 0x3c: t=T2;n=N2; SET(4,-2) PUT2(0, n & t) break;
83 case 0x16: /* DEI */ POP8(a) DEVR(b, a) PUSH(src, b) break; 96 case 0x1d: /* ORA */ t=T;n=N; SET(2,-1) PUT(0, n | t) break; case 0x3d: t=T2;n=N2; SET(4,-2) PUT2(0, n | t) break;
84 case 0x17: /* DEO */ POP8(a) POP(b) DEVW(a, b) break; 97 case 0x1e: /* EOR */ t=T;n=N; SET(2,-1) PUT(0, n ^ t) break; case 0x3e: t=T2;n=N2; SET(4,-2) PUT2(0, n ^ t) break;
85 case 0x18: /* ADD */ POP(a) POP(b) PUSH(src, b + a) break; 98 case 0x1f: /* SFT */ t=T;n=N; SET(2,-1) PUT(0, n >> (t & 0xf) << (t >> 4)) break; case 0x3f: t=T;n=H2; SET(3,-1) PUT2(0, n >> (t & 0xf) << (t >> 4)) break;
86 case 0x19: /* SUB */ POP(a) POP(b) PUSH(src, b - a) break; 99 }
87 case 0x1a: /* MUL */ POP(a) POP(b) PUSH(src, (u32)b * a) break; 100 }
88 case 0x1b: /* DIV */ POP(a) POP(b) if(!a) HALT(3) PUSH(src, b / a) break;
89 case 0x1c: /* AND */ POP(a) POP(b) PUSH(src, b & a) break;
90 case 0x1d: /* ORA */ POP(a) POP(b) PUSH(src, b | a) break;
91 case 0x1e: /* EOR */ POP(a) POP(b) PUSH(src, b ^ a) break;
92 case 0x1f: /* SFT */ POP8(a) POP(b) PUSH(src, b >> (a & 0x0f) << ((a & 0xf0) >> 4)) break;
93 }
94 }
95} 101}
96 102
97int 103int
diff --git a/src/uxn.h b/src/uxn.h
index f9bee16..04aba84 100644
--- a/src/uxn.h
+++ b/src/uxn.h
@@ -13,12 +13,6 @@ WITH REGARD TO THIS SOFTWARE.
13 13
14#define PAGE_PROGRAM 0x0100 14#define PAGE_PROGRAM 0x0100
15 15
16/* clang-format off */
17
18#define GETVEC(d) ((d)[0] << 8 | (d)[1])
19#define POKDEV(x, y) { d[(x)] = (y) >> 8; d[(x) + 1] = (y); }
20#define PEKDEV(o, x) { (o) = (d[(x)] << 8) + d[(x) + 1]; }
21
22/* clang-format on */ 16/* clang-format on */
23 17
24typedef struct { 18typedef struct {
@@ -35,6 +29,8 @@ typedef struct Uxn {
35typedef u8 Dei(Uxn *u, u8 addr); 29typedef u8 Dei(Uxn *u, u8 addr);
36typedef void Deo(Uxn *u, u8 addr, u8 value); 30typedef void Deo(Uxn *u, u8 addr, u8 value);
37 31
32u8 uxn_dei(Uxn *u, u8 addr);
33void uxn_deo(Uxn *u, u8 addr);
38int uxn_halt(Uxn *u, u8 instr, u8 err, u16 addr); 34int uxn_halt(Uxn *u, u8 instr, u8 err, u16 addr);
39int uxn_boot(Uxn *u, u8 *ram, Dei *dei, Deo *deo); 35int uxn_boot(Uxn *u, u8 *ram, Dei *dei, Deo *deo);
40int uxn_eval(Uxn *u, u16 pc); 36int uxn_eval(Uxn *u, u16 pc);