(Screen) Faster sprite drawing

This commit is contained in:
neauoire 2023-11-12 12:38:43 -08:00
parent 99c492d385
commit d6a966e113
3 changed files with 189 additions and 25 deletions

View File

@ -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 ]

View File

@ -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) {

View File

@ -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);