uxn

Varvara Ordinator, written in ANSI C(SDL2)
git clone https://git.eamoncaddigan.net/uxn.git
Log | Files | Refs | README | LICENSE

commit c0d5f6820cd38bf4dabab35c02b026dc466c3abf
parent 40bbb544fe1e4cd487eb08fe430fc5416630473f
Author: Devine Lu Linvega <aliceffekt@gmail.com>
Date:   Mon, 23 Dec 2024 16:10:56 -0800

Fixed issue with screen device

Diffstat:
Msrc/devices/screen.c | 77+++++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/devices/screen.h | 6+++---
Msrc/uxnemu.c | 12+++++-------
3 files changed, 47 insertions(+), 48 deletions(-)

diff --git a/src/devices/screen.c b/src/devices/screen.c @@ -119,23 +119,22 @@ screen_resize(Uint16 width, Uint16 height, int scale) void screen_redraw(void) { - int i, x, y, k, l, s = uxn_screen.scale; - Uint8 *fg = uxn_screen.fg, *bg = uxn_screen.bg; - Uint16 w = uxn_screen.width, h = uxn_screen.height; - Uint16 x1 = uxn_screen.x1, y1 = uxn_screen.y1; - Uint16 x2 = uxn_screen.x2 > w ? w : uxn_screen.x2, y2 = uxn_screen.y2 > h ? h : uxn_screen.y2; + int i, x, y, k, l; + int x1 = uxn_screen.x1 < 0 ? 0 : uxn_screen.x1, y1 = uxn_screen.y1 < 0 ? 0 : uxn_screen.y1; + int x2 = uxn_screen.x2 > uxn_screen.width ? uxn_screen.width : uxn_screen.x2; + int y2 = uxn_screen.y2 > uxn_screen.height ? uxn_screen.height : uxn_screen.y2; Uint32 palette[16], *pixels = uxn_screen.pixels; uxn_screen.x1 = uxn_screen.y1 = 9000; uxn_screen.x2 = uxn_screen.y2 = 0; for(i = 0; i < 16; i++) palette[i] = uxn_screen.palette[(i >> 2) ? (i >> 2) : (i & 3)]; for(y = y1; y < y2; y++) { - int ys = y * s; - for(x = x1, i = MAR(x) + MAR(y) * MAR2(w); x < x2; x++, i++) { - int c = palette[fg[i] << 2 | bg[i]]; - for(k = 0; k < s; k++) { - int oo = ((ys + k) * w + x) * s; - for(l = 0; l < s; l++) + int ys = y * uxn_screen.scale; + for(x = x1, i = MAR(x) + MAR(y) * MAR2(uxn_screen.width); x < x2; x++, i++) { + int c = palette[uxn_screen.fg[i] << 2 | uxn_screen.bg[i]]; + for(k = 0; k < uxn_screen.scale; k++) { + int oo = ((ys + k) * uxn_screen.width + x) * uxn_screen.scale; + for(l = 0; l < uxn_screen.scale; l++) pixels[oo + l] = c; } } @@ -147,7 +146,7 @@ screen_redraw(void) static int rX, rY, rA, rMX, rMY, rMA, rML, rDX, rDY; Uint8 -screen_dei(Uxn *u, Uint8 addr) +screen_dei(Uint8 addr) { switch(addr) { case 0x22: return uxn_screen.width >> 8; @@ -160,25 +159,25 @@ screen_dei(Uxn *u, Uint8 addr) case 0x2b: return rY; case 0x2c: return rA >> 8; case 0x2d: return rA; - default: return u->dev[addr]; + default: return uxn.dev[addr]; } } void -screen_deo(Uxn *u, Uint8 addr) +screen_deo(Uint8 addr) { switch(addr) { case 0x23: screen_resize(PEEK2(&uxn.dev[0x22]), uxn_screen.height, uxn_screen.scale); return; case 0x25: screen_resize(uxn_screen.width, PEEK2(&uxn.dev[0x24]), uxn_screen.scale); return; - case 0x26: rMX = u->dev[0x26] & 0x1, rMY = u->dev[0x26] & 0x2, rMA = u->dev[0x26] & 0x4, rML = u->dev[0x26] >> 4, rDX = rMX << 3, rDY = rMY << 2; return; + case 0x26: rMX = uxn.dev[0x26] & 0x1, rMY = uxn.dev[0x26] & 0x2, rMA = uxn.dev[0x26] & 0x4, rML = uxn.dev[0x26] >> 4, rDX = rMX << 3, rDY = rMY << 2; return; case 0x28: - case 0x29: rX = (u->dev[0x28] << 8) | u->dev[0x29], rX = twos(rX); return; + case 0x29: rX = (uxn.dev[0x28] << 8) | uxn.dev[0x29], rX = twos(rX); return; case 0x2a: - case 0x2b: rY = (u->dev[0x2a] << 8) | u->dev[0x2b], rY = twos(rY); return; + case 0x2b: rY = (uxn.dev[0x2a] << 8) | uxn.dev[0x2b], rY = twos(rY); return; case 0x2c: - case 0x2d: rA = (u->dev[0x2c] << 8) | u->dev[0x2d]; return; + case 0x2d: rA = (uxn.dev[0x2c] << 8) | uxn.dev[0x2d]; return; case 0x2e: { - int ctrl = u->dev[0x2e]; + int ctrl = uxn.dev[0x2e]; int color = ctrl & 0x3; int len = MAR2(uxn_screen.width); Uint8 *layer = ctrl & 0x40 ? uxn_screen.fg : uxn_screen.bg; @@ -210,24 +209,25 @@ screen_deo(Uxn *u, Uint8 addr) return; } case 0x2f: { - int i; - int ctrl = u->dev[0x2f]; + int ctrl = uxn.dev[0x2f]; int twobpp = !!(ctrl & 0x80); int blend = ctrl & 0xf; int fx = ctrl & 0x10 ? -1 : 1, fy = ctrl & 0x20 ? -1 : 1; - int x1, x2, y1, y2, ax, ay, qx, qy, x = rX, y = rY; + int i, x1, x2, y1, y2, ax, ay, qx, qy, x = rX, y = rY; int dxy = rDX * fy, dyx = rDY * fx, addr_incr = rMA << (1 + twobpp); - int len = MAR2(uxn_screen.width); + int wmar = MAR(uxn_screen.width), wmar2 = MAR2(uxn_screen.width); + int hmar2 = MAR2(uxn_screen.height); Uint8 *layer = ctrl & 0x40 ? uxn_screen.fg : uxn_screen.bg; if(twobpp) for(i = 0; i <= rML; i++, x += dyx, y += dxy, rA += addr_incr) { - Uint16 xx = MAR(x), yy = MAR(y); - if(xx < MAR(uxn_screen.width) && MAR(yy) < MAR2(uxn_screen.height)) { - Uint8 *sprite = &u->ram[rA]; - int opaque = blend % 5, by = (yy + 8) * len; - for(ay = yy * len, qy = fy < 0 ? 7 : 0; ay < by; ay += len, qy += fy) { - int ch1 = sprite[qy], ch2 = sprite[qy + 8] << 1, bx = xx + 8 + ay; - for(ax = xx + ay, qx = fx > 0 ? 7 : 0; ax < bx; ax++, qx -= fx) { + Uint16 xmar = MAR(x), ymar = MAR(y); + Uint16 xmar2 = MAR2(x), ymar2 = MAR2(y); + if(xmar < wmar && ymar2 < hmar2) { + Uint8 *sprite = &uxn.ram[rA]; + int opaque = blend % 5, by = ymar2 * wmar2; + for(ay = ymar * wmar2, qy = fy < 0 ? 7 : 0; ay < by; ay += wmar2, qy += fy) { + int ch1 = sprite[qy], ch2 = sprite[qy + 8] << 1, bx = xmar2 + ay; + for(ax = xmar + ay, qx = fx > 0 ? 7 : 0; ax < bx; ax++, qx -= fx) { int color = ((ch1 >> qx) & 1) | ((ch2 >> qx) & 2); if(opaque || color) layer[ax] = blending[color][blend]; } @@ -236,13 +236,14 @@ screen_deo(Uxn *u, Uint8 addr) } else for(i = 0; i <= rML; i++, x += dyx, y += dxy, rA += addr_incr) { - Uint16 xx = MAR(x), yy = MAR(y); - if(xx < MAR(uxn_screen.width) && MAR(yy) < MAR2(uxn_screen.height)) { - Uint8 *sprite = &u->ram[rA]; - int opaque = blend % 5, by = (yy + 8) * len; - for(ay = yy * len, qy = fy < 0 ? 7 : 0; ay < by; ay += len, qy += fy) { - int ch1 = sprite[qy], bx = xx + 8 + ay; - for(ax = xx + ay, qx = fx > 0 ? 7 : 0; ax < bx; ax++, qx -= fx) { + Uint16 xmar = MAR(x), ymar = MAR(y); + Uint16 xmar2 = MAR2(x), ymar2 = MAR2(y); + if(xmar < wmar && ymar2 < hmar2) { + Uint8 *sprite = &uxn.ram[rA]; + int opaque = blend % 5, by = ymar2 * wmar2; + for(ay = ymar * wmar2, qy = fy < 0 ? 7 : 0; ay < by; ay += wmar2, qy += fy) { + int ch1 = sprite[qy], bx = xmar2 + ay; + for(ax = xmar + ay, qx = fx > 0 ? 7 : 0; ax < bx; ax++, qx -= fx) { int color = (ch1 >> qx) & 1; if(opaque || color) layer[ax] = blending[color][blend]; } @@ -257,7 +258,7 @@ screen_deo(Uxn *u, Uint8 addr) y1 = y, y2 = rY; else y1 = rY, y2 = y; - screen_change(x1, y1, x2 + 8, y2 + 8); + screen_change(x1 - 8, y1 - 8, x2 + 8, y2 + 8); if(rMX) rX += rDX * fx; if(rMY) rY += rDY * fy; return; diff --git a/src/devices/screen.h b/src/devices/screen.h @@ -22,9 +22,9 @@ void screen_change(int x1, int y1, int x2, int y2); void screen_fill(Uint8 *layer, int color); void screen_palette(void); void screen_resize(Uint16 width, Uint16 height, int scale); -void screen_redraw(void); +void screen_redraw(); -Uint8 screen_dei(Uxn *u, Uint8 addr); -void screen_deo(Uxn *u, Uint8 addr); +Uint8 screen_dei(Uint8 addr); +void screen_deo(Uint8 addr); #define twos(v) (v & 0x8000 ? (int)v - 0x10000 : (int)v) diff --git a/src/uxnemu.c b/src/uxnemu.c @@ -85,7 +85,7 @@ emu_dei(Uxn *u, Uint8 addr) Uint8 p = addr & 0x0f, d = addr & 0xf0; switch(d) { case 0x00: return system_dei(u, addr); - case 0x20: return screen_dei(u, addr); + case 0x20: return screen_dei(addr); case 0x30: return audio_dei(0, &uxn.dev[d], p); case 0x40: return audio_dei(1, &uxn.dev[d], p); case 0x50: return audio_dei(2, &uxn.dev[d], p); @@ -106,7 +106,7 @@ emu_deo(Uxn *u, Uint8 addr, Uint8 value) if(p > 0x7 && p < 0xe) screen_palette(); break; case 0x10: console_deo(u, addr); break; - case 0x20: screen_deo(u, addr); break; + case 0x20: screen_deo(addr); break; case 0x30: audio_deo(0, &uxn.dev[d], p); break; case 0x40: audio_deo(1, &uxn.dev[d], p); break; case 0x50: audio_deo(2, &uxn.dev[d], p); break; @@ -153,7 +153,6 @@ set_window_size(SDL_Window *window, int w, int h) if(w == win_old.x && h == win_old.y) return; SDL_RenderClear(emu_renderer); SDL_SetWindowSize(window, w, h); - screen_change(0, 0, uxn_screen.width, uxn_screen.height); screen_resize(uxn_screen.width, uxn_screen.height, 1); } @@ -255,15 +254,15 @@ emu_init(void) ms_interval = SDL_GetPerformanceFrequency() / 1000; deadline_interval = ms_interval * TIMEOUT_MS; exec_deadline = SDL_GetPerformanceCounter() + deadline_interval; - screen_change(0, 0, WIDTH, HEIGHT), screen_resize(WIDTH, HEIGHT, 1); SDL_PauseAudioDevice(audio_id, 1); + screen_resize(WIDTH, HEIGHT, 1); return 1; } static void emu_restart(char *drop, int soft) { - screen_change(0, 0, WIDTH, HEIGHT), screen_resize(WIDTH, HEIGHT, 1); + screen_resize(WIDTH, HEIGHT, uxn_screen.scale); screen_fill(uxn_screen.bg, 0); screen_fill(uxn_screen.fg, 0); system_reboot(soft); @@ -473,7 +472,7 @@ main(int argc, char **argv) /* flags */ if(argc > 1 && argv[i][0] == '-') { if(!strcmp(argv[i], "-v")) - return system_error("Uxn(gui) - Varvara Emulator", "27 Nov 2024."); + return system_error("Uxn(gui) - Varvara Emulator", "23 Dec 2024."); else if(!strcmp(argv[i], "-2x")) set_zoom(2, 0); else if(!strcmp(argv[i], "-3x")) @@ -491,7 +490,6 @@ main(int argc, char **argv) /* loop */ uxn.dev[0x17] = argc - i; if(uxn_eval(&uxn, PAGE_PROGRAM)) { - /* uxn_eval(&bios, PAGE_PROGRAM); */ console_listen(i, argc, argv); emu_run(rom); }