commit d6a966e1135f5c14a948cb681806151fa24b3fc7
parent 99c492d3856e76b479ee648a79fc9fec49d1183f
Author: neauoire <aliceffekt@gmail.com>
Date: Sun, 12 Nov 2023 12:38:43 -0800
(Screen) Faster sprite drawing
Diffstat:
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);