uxn

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

commit d6a966e1135f5c14a948cb681806151fa24b3fc7
parent 99c492d3856e76b479ee648a79fc9fec49d1183f
Author: neauoire <aliceffekt@gmail.com>
Date:   Sun, 12 Nov 2023 12:38:43 -0800

(Screen) Faster sprite drawing

Diffstat:
Aprojects/examples/devices/screen.bounds.tal | 141+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/devices/screen.c | 71+++++++++++++++++++++++++++++++++++++++++++++++------------------------
Msrc/devices/screen.h | 2+-
3 files changed, 189 insertions(+), 25 deletions(-)

diff --git a/projects/examples/devices/screen.bounds.tal b/projects/examples/devices/screen.bounds.tal @@ -0,0 +1,141 @@ +|00 @System &vector $2 &wst $1 &rst $1 &pad $4 &r $2 &g $2 &b $2 &debug $1 &halt $1 +|20 @Screen &vector $2 &width $2 &height $2 &auto $1 &pad $1 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 +|90 @Mouse &vector $2 &x $2 &y $2 &state $1 &pad $3 &scrollx $2 &scrolly $2 + +|0100 + +@on-reset ( -> ) + #375e .System/r DEO2 + #286c .System/g DEO2 + #2358 .System/b DEO2 + ;on-mouse .Mouse/vector DEO2 + <draw-guide> + BRK + +@on-mouse ( -> ) + ( | clear background ) + #0000 DUP2 .Screen/x DEO2 + .Screen/y DEO2 + #80 .Screen/pixel DEO + <draw-guide> + ( | cursor ) + #41 ;cursor-icn <update-cursor> + ( | draw portrait ) + .Screen/x DEI2k #0008 ADD2 ROT DEO2 + .Screen/y DEI2k #0020 SUB2 ROT DEO2 + [ LIT2 36 -Screen/auto ] DEO + #81 <draw-portrait> + .Screen/x DEI2k #0010 SUB2 ROT DEO2 + .Screen/y DEI2k #0020 SUB2 ROT DEO2 + #91 <draw-portrait> + .Screen/x DEI2k #0000 SUB2 ROT DEO2 + .Screen/y DEI2k #0020 ADD2 ROT DEO2 + #b1 <draw-portrait> + .Screen/x DEI2k #0010 ADD2 ROT DEO2 + .Screen/y DEI2k #0020 ADD2 ROT DEO2 + #a1 <draw-portrait> + ( <draw-box> + .Screen/y DEI2k #0060 SUB2 ROT DEO2 + <draw-box> ) + BRK + +@<draw-portrait> ( color -- ) + ;portrait-chr .Screen/addr DEO2 + .Screen/sprite DEOk DEOk DEOk DEO + JMP2r + +@<draw-box> ( -- ) + ;box-icn .Screen/addr DEO2 + #05 .Screen/sprite DEOk DEOk DEOk DEO + JMP2r + +@<draw-circle> ( color -- ) + #01 .Screen/auto DEO + ;circle-chr .Screen/addr DEO2 + DUP .Screen/sprite DEO + DUP #10 ORA .Screen/sprite DEO + .Screen/y DEI2k #0008 ADD2 ROT DEO2 + DUP #20 ORA .Screen/sprite DEO + #30 ORA .Screen/sprite DEO + JMP2r + +@<draw-guide> ( -- ) + #0000 DUP2 .Screen/x DEO2 .Screen/y DEO2 + #f2 .Screen/auto DEO + ;guide-icn .Screen/addr DEO2 + #1000 + &l ( -- ) + #01 .Screen/sprite DEO + INC GTHk ?&l + POP2 + ( | circles ) + #0010 DUP2 .Screen/x DEO2 .Screen/y DEO2 + #02 <draw-circle> + .Screen/y DEI2k #0008 ADD2 ROT DEO2 + #82 <draw-circle> + .Screen/y DEI2k #0008 ADD2 ROT DEO2 + #05 <draw-circle> + .Screen/y DEI2k #0008 ADD2 ROT DEO2 + #85 <draw-circle> + .Screen/y DEI2k #0008 ADD2 ROT DEO2 + #03 <draw-circle> + .Screen/y DEI2k #0008 ADD2 ROT DEO2 + #83 <draw-circle> + .Screen/y DEI2k #0008 ADD2 ROT DEO2 + #0a <draw-circle> + .Screen/y DEI2k #0008 ADD2 ROT DEO2 + #8a <draw-circle> + JMP2r + +@<update-cursor> ( color addr* -- ) + [ LIT2 00 -Screen/auto ] DEO + ;fill-icn .Screen/addr DEO2 + #40 <draw-cursor> + .Mouse/x DEI2 ,<draw-cursor>/x STR2 + .Mouse/y DEI2 ,<draw-cursor>/y STR2 + .Screen/addr DEO2 + +@<draw-cursor> ( color -- ) + [ LIT2 &x $2 ] .Screen/x DEO2 + [ LIT2 &y $2 ] .Screen/y DEO2 + .Screen/sprite DEO + JMP2r + +@guide-icn [ 0101 0101 0101 01ff ] + +@fill-icn [ ffff ffff ffff ffff ] + +@cursor-icn [ 80c0 e0f0 f8e0 1000 ] + +@portrait-chr [ + 070f 1e1d 1b3b 3b3b f0e0 c0c0 d08b 8080 + f76f cf9f 9f5f 5f5f 0000 0007 1c40 4040 + fffb f975 7576 7667 0000 3164 0406 0607 + efef efef eddd 9e1e 0060 8000 0000 0000 + 3b2b 280d 0105 0506 8080 8081 e1f1 f1f0 + 5f6c 639b 0f27 77ab 4060 639b 0f27 67ab + 0dc8 b0e5 cded fdfc 0dc8 b0e4 ccec fcfc + 5e1e 1c9c 9d1d 5d59 4000 0080 8000 4040 + 0607 0707 070e 0e0e f0f0 f0f0 f0e0 e0e0 + fb73 7fb7 bbbf bfdd f373 7b37 3b3f 3f1c + ffff ffff ffff ffff ffff ffff ffff ff7f + dba7 97f7 f7ed dd9d c080 90f0 f0e0 c080 + 1e0e 0000 0000 0000 c0c0 f0ff ffff ffff + ee03 0000 0000 0000 0e12 fcff ffff ffff + fffc f30f 1f1f 1f3f 9f3c f30f dfdf dfbf + 3c80 8080 80c0 c0e0 0003 3fbf bfbf dfef ] + +@box-icn [ + 001f 2050 4844 4241 00ff 0000 0000 0000 + 00ff 0000 0000 0000 00f8 040a 1222 4282 + 4040 4040 4040 4040 8040 2010 0804 0201 + 0102 0408 1020 4080 0202 0202 0202 0202 + 4040 4040 4040 4040 0102 0408 1020 4080 + 8040 2010 0804 0201 0202 0202 0202 0202 + 4142 4448 5020 1f00 0000 0000 0000 ff00 + 0000 0000 0000 ff00 8242 2212 0a04 f800 ] + +@circle-chr [ + 071f 3c70 60e3 c7c7 0000 030f 1f1f 3f3f ] + + diff --git a/src/devices/screen.c b/src/devices/screen.c @@ -47,7 +47,7 @@ screen_fill(Uint8 *layer, int color) } void -screen_rect(Uint8 *layer, int x1, int y1, int x2, int y2, int color) +screen_rect(Uint8 *layer, Uint16 x1, Uint16 y1, Uint16 x2, Uint16 y2, int color) { int x, y, width = uxn_screen.width, height = uxn_screen.height; for(y = y1; y < y2 && y < height; y++) @@ -56,19 +56,35 @@ screen_rect(Uint8 *layer, int x1, int y1, int x2, int y2, int color) } static void -screen_blit(Uint8 *layer, Uint8 *ram, Uint16 addr, int x1, int y1, int color, int flipx, int flipy, int twobpp) +screen_2bpp(Uint8 *layer, Uint8 *ram, Uint16 addr, Uint16 x1, Uint16 y1, Uint16 color, int fx, int fy) { - int v, h, width = uxn_screen.width, height = uxn_screen.height, opaque = (color % 5); - for(v = 0; v < 8; v++) { - Uint16 c = ram[(addr + v) & 0xffff] | (twobpp ? (ram[(addr + v + 8) & 0xffff] << 8) : 0); - Uint16 y = y1 + (flipy ? 7 - v : v); - for(h = 7; h >= 0; --h, c >>= 1) { + int width = uxn_screen.width, height = uxn_screen.height, opaque = (color % 5); + Uint8 *ch1 = &ram[addr], *ch2 = ch1 + 8; + Uint16 y, ymod = (fy < 0 ? 7 : 0), ymax = y1 + ymod + fy * 8; + Uint16 x, xmod = (fx > 0 ? 7 : 0), xmax = x1 + xmod - fx * 8; + for(y = y1 + ymod; y != ymax; y += fy) { + Uint16 c = *ch1++ | (*ch2++ << 8); + for(x = x1 + xmod; x != xmax; x -= fx, c >>= 1) { Uint8 ch = (c & 1) | ((c >> 7) & 2); - if(opaque || ch) { - Uint16 x = x1 + (flipx ? 7 - h : h); - if(x < width && y < height) - layer[x + y * width] = blending[ch][color]; - } + if((opaque || ch) && x < width && y < height) + layer[x + y * width] = blending[ch][color]; + } + } +} + +static void +screen_1bpp(Uint8 *layer, Uint8 *ram, Uint16 addr, Uint16 x1, Uint16 y1, Uint16 color, int fx, int fy) +{ + int width = uxn_screen.width, height = uxn_screen.height, opaque = (color % 5); + Uint8 *ch1 = &ram[addr]; + Uint16 y, ymod = (fy < 0 ? 7 : 0), ymax = y1 + ymod + fy * 8; + Uint16 x, xmod = (fx > 0 ? 7 : 0), xmax = x1 + xmod - fx * 8; + for(y = y1 + ymod; y != ymax; y += fy) { + Uint16 c = *ch1++; + for(x = x1 + xmod; x != xmax; x -= fx, c >>= 1) { + Uint8 ch = c & 1; + if((opaque || ch) && x < width && y < height) + layer[x + y * width] = blending[ch][color]; } } } @@ -93,8 +109,8 @@ static Uint8 arrow[] = { static void draw_byte(Uint8 b, Uint16 x, Uint16 y, Uint8 color) { - screen_blit(uxn_screen.fg, icons, (b >> 4) << 3, x, y, color, 0, 0, 0); - screen_blit(uxn_screen.fg, icons, (b & 0xf) << 3, x + 8, y, color, 0, 0, 0); + screen_1bpp(uxn_screen.fg, icons, (b >> 4) << 3, x, y, color, 1, 1); + screen_1bpp(uxn_screen.fg, icons, (b & 0xf) << 3, x + 8, y, color, 1, 1); screen_change(x, y, x + 0x10, y + 0x8); } @@ -104,19 +120,19 @@ screen_debugger(Uxn *u) int i; for(i = 0; i < 0x08; i++) { Uint8 pos = u->wst.ptr - 4 + i; - Uint8 color = i > 4 ? 0x01 : !pos ? 0xc - : i == 4 ? 0x8 - : 0x2; + Uint8 color = i > 4 ? 0x01 : !pos ? 0xc : + i == 4 ? 0x8 : + 0x2; draw_byte(u->wst.dat[pos], i * 0x18 + 0x8, uxn_screen.height - 0x18, color); } for(i = 0; i < 0x08; i++) { Uint8 pos = u->rst.ptr - 4 + i; - Uint8 color = i > 4 ? 0x01 : !pos ? 0xc - : i == 4 ? 0x8 - : 0x2; + Uint8 color = i > 4 ? 0x01 : !pos ? 0xc : + i == 4 ? 0x8 : + 0x2; draw_byte(u->rst.dat[pos], i * 0x18 + 0x8, uxn_screen.height - 0x10, color); } - screen_blit(uxn_screen.fg, arrow, 0, 0x68, uxn_screen.height - 0x20, 3, 0, 0, 0); + screen_1bpp(uxn_screen.fg, arrow, 0, 0x68, uxn_screen.height - 0x20, 3, 1, 1); for(i = 0; i < 0x20; i++) draw_byte(u->ram[i], (i & 0x7) * 0x18 + 0x8, ((i >> 3) << 3) + 0x8, 1 + !!u->ram[i]); } @@ -252,9 +268,16 @@ screen_deo(Uint8 *ram, Uint8 *d, Uint8 port) x = PEEK2(port_x), dx = (move & 0x1) << 3, dxy = dx * fy; y = PEEK2(port_y), dy = (move & 0x2) << 2, dyx = dy * fx; addr = PEEK2(port_addr), addr_incr = (move & 0x4) << (1 + twobpp); - for(i = 0; i <= length; i++) { - screen_blit(layer, ram, addr, x + dyx * i, y + dxy * i, color, flipx, flipy, twobpp); - addr += addr_incr; + if(twobpp) { + for(i = 0; i <= length; i++) { + screen_2bpp(layer, ram, addr, x + dyx * i, y + dxy * i, color, fx, fy); + addr += addr_incr; + } + } else { + for(i = 0; i <= length; i++) { + screen_1bpp(layer, ram, addr, x + dyx * i, y + dxy * i, color, fx, fy); + addr += addr_incr; + } } screen_change(x, y, x + dyx * length + 8, y + dxy * length + 8); if(move & 0x1) { diff --git a/src/devices/screen.h b/src/devices/screen.h @@ -23,7 +23,7 @@ extern UxnScreen uxn_screen; extern int emu_resize(int width, int height); void screen_fill(Uint8 *layer, int color); -void screen_rect(Uint8 *layer, int x1, int y1, int x2, int y2, int color); +void screen_rect(Uint8 *layer, Uint16 x1, Uint16 y1, Uint16 x2, Uint16 y2, int color); void screen_palette(Uint8 *addr); void screen_resize(Uint16 width, Uint16 height); void screen_change(Uint16 x1, Uint16 y1, Uint16 x2, Uint16 y2);