diff options
author | Bad Diode <bd@badd10de.dev> | 2023-04-19 17:58:04 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2023-04-19 17:58:04 +0200 |
commit | d68d16405b013967e0faa12f9dfc608e3bb3d0d4 (patch) | |
tree | f8436d01c6a9aa112cdb6ac6bd042fe2a7c0b046 | |
parent | 2e8ab813a9e4c2d908d5450e346a81d2a91a75e8 (diff) | |
download | uxngba-d68d16405b013967e0faa12f9dfc608e3bb3d0d4.tar.gz uxngba-d68d16405b013967e0faa12f9dfc608e3bb3d0d4.zip |
Update uxn core and fix some new ppu bugs
-rw-r--r-- | src/main.c | 162 | ||||
-rw-r--r-- | src/ppu.c | 162 | ||||
-rw-r--r-- | src/uxn.c | 160 | ||||
-rw-r--r-- | src/uxn.h | 8 |
4 files changed, 318 insertions, 174 deletions
@@ -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 | |||
329 | static void | ||
330 | system_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 | |||
316 | void | 352 | void |
317 | system_deo(Uxn *u, u8 *d, u8 port) { | 353 | system_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 | ||
324 | u8 | 361 | u8 |
325 | emu_dei(Uxn *u, u8 addr) { | 362 | uxn_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 | ||
340 | void | 377 | void |
341 | emu_deo(Uxn *u, u8 addr, u8 v) { | 378 | uxn_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 | ||
361 | void | 397 | void |
@@ -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); |
@@ -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 | ||
250 | IWRAM_CODE | ||
251 | void | ||
252 | ppu_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 | |||
347 | IWRAM_CODE | ||
348 | void | ||
349 | screen_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 |
251 | IWRAM_CODE | 363 | IWRAM_CODE |
252 | void | 364 | void |
@@ -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 | } |
@@ -11,87 +11,93 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |||
11 | WITH REGARD TO THIS SOFTWARE. | 11 | WITH 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]; } | 31 | u16 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)]; } | 32 | u16 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 | ||
32 | IWRAM_CODE | 45 | IWRAM_CODE |
33 | int | 46 | int |
34 | uxn_eval(Uxn *u, u16 pc) | 47 | uxn_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 | ||
97 | int | 103 | int |
@@ -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 | ||
24 | typedef struct { | 18 | typedef struct { |
@@ -35,6 +29,8 @@ typedef struct Uxn { | |||
35 | typedef u8 Dei(Uxn *u, u8 addr); | 29 | typedef u8 Dei(Uxn *u, u8 addr); |
36 | typedef void Deo(Uxn *u, u8 addr, u8 value); | 30 | typedef void Deo(Uxn *u, u8 addr, u8 value); |
37 | 31 | ||
32 | u8 uxn_dei(Uxn *u, u8 addr); | ||
33 | void uxn_deo(Uxn *u, u8 addr); | ||
38 | int uxn_halt(Uxn *u, u8 instr, u8 err, u16 addr); | 34 | int uxn_halt(Uxn *u, u8 instr, u8 err, u16 addr); |
39 | int uxn_boot(Uxn *u, u8 *ram, Dei *dei, Deo *deo); | 35 | int uxn_boot(Uxn *u, u8 *ram, Dei *dei, Deo *deo); |
40 | int uxn_eval(Uxn *u, u16 pc); | 36 | int uxn_eval(Uxn *u, u16 pc); |