Browse code

(Screen) Faster sprite drawing

neauoire authored on 12/11/2023 20:38:43
Showing 3 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,141 @@
1
+|00 @System &vector $2 &wst $1 &rst $1 &pad $4 &r $2 &g $2 &b $2 &debug $1 &halt $1
2
+|20 @Screen &vector $2 &width $2 &height $2 &auto $1 &pad $1 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1
3
+|90 @Mouse &vector $2 &x $2 &y $2 &state $1 &pad $3 &scrollx $2 &scrolly $2
4
+
5
+|0100
6
+
7
+@on-reset ( -> )
8
+	#375e .System/r DEO2
9
+	#286c .System/g DEO2
10
+	#2358 .System/b DEO2
11
+	;on-mouse .Mouse/vector DEO2
12
+	<draw-guide>
13
+	BRK
14
+
15
+@on-mouse ( -> )
16
+	( | clear background )
17
+	#0000 DUP2 .Screen/x DEO2
18
+	.Screen/y DEO2
19
+	#80 .Screen/pixel DEO
20
+	<draw-guide>
21
+	( | cursor )
22
+	#41 ;cursor-icn <update-cursor>
23
+	( | draw portrait )
24
+	.Screen/x DEI2k #0008 ADD2 ROT DEO2
25
+	.Screen/y DEI2k #0020 SUB2 ROT DEO2
26
+	[ LIT2 36 -Screen/auto ] DEO
27
+	#81 <draw-portrait>
28
+	.Screen/x DEI2k #0010 SUB2 ROT DEO2
29
+	.Screen/y DEI2k #0020 SUB2 ROT DEO2
30
+	#91 <draw-portrait>
31
+	.Screen/x DEI2k #0000 SUB2 ROT DEO2
32
+	.Screen/y DEI2k #0020 ADD2 ROT DEO2
33
+	#b1 <draw-portrait>
34
+	.Screen/x DEI2k #0010 ADD2 ROT DEO2
35
+	.Screen/y DEI2k #0020 ADD2 ROT DEO2
36
+	#a1 <draw-portrait>
37
+	( <draw-box>
38
+	.Screen/y DEI2k #0060 SUB2 ROT DEO2
39
+	<draw-box> )
40
+	BRK
41
+
42
+@<draw-portrait> ( color -- )
43
+	;portrait-chr .Screen/addr DEO2
44
+	.Screen/sprite DEOk DEOk DEOk DEO
45
+	JMP2r
46
+
47
+@<draw-box> ( -- )
48
+	;box-icn .Screen/addr DEO2
49
+	#05 .Screen/sprite DEOk DEOk DEOk DEO
50
+	JMP2r
51
+
52
+@<draw-circle> ( color -- )
53
+	#01 .Screen/auto DEO
54
+	;circle-chr .Screen/addr DEO2
55
+	DUP .Screen/sprite DEO
56
+	DUP #10 ORA .Screen/sprite DEO
57
+	.Screen/y DEI2k #0008 ADD2 ROT DEO2
58
+	DUP #20 ORA .Screen/sprite DEO
59
+	#30 ORA .Screen/sprite DEO
60
+	JMP2r
61
+
62
+@<draw-guide> ( -- )
63
+	#0000 DUP2 .Screen/x DEO2 .Screen/y DEO2
64
+	#f2 .Screen/auto DEO
65
+	;guide-icn .Screen/addr DEO2
66
+	#1000
67
+	&l ( -- ) 
68
+		#01 .Screen/sprite DEO
69
+		INC GTHk ?&l 
70
+	POP2
71
+	( | circles )
72
+	#0010 DUP2 .Screen/x DEO2 .Screen/y DEO2
73
+	#02 <draw-circle>
74
+	.Screen/y DEI2k #0008 ADD2 ROT DEO2
75
+	#82 <draw-circle>
76
+	.Screen/y DEI2k #0008 ADD2 ROT DEO2
77
+	#05 <draw-circle>
78
+	.Screen/y DEI2k #0008 ADD2 ROT DEO2
79
+	#85 <draw-circle>
80
+	.Screen/y DEI2k #0008 ADD2 ROT DEO2
81
+	#03 <draw-circle>
82
+	.Screen/y DEI2k #0008 ADD2 ROT DEO2
83
+	#83 <draw-circle>
84
+	.Screen/y DEI2k #0008 ADD2 ROT DEO2
85
+	#0a <draw-circle>
86
+	.Screen/y DEI2k #0008 ADD2 ROT DEO2
87
+	#8a <draw-circle>
88
+	JMP2r
89
+
90
+@<update-cursor> ( color addr* -- )
91
+	[ LIT2 00 -Screen/auto ] DEO
92
+	;fill-icn .Screen/addr DEO2
93
+	#40 <draw-cursor>
94
+	.Mouse/x DEI2 ,<draw-cursor>/x STR2
95
+	.Mouse/y DEI2 ,<draw-cursor>/y STR2
96
+	.Screen/addr DEO2
97
+
98
+@<draw-cursor> ( color -- )
99
+	[ LIT2 &x $2 ] .Screen/x DEO2
100
+	[ LIT2 &y $2 ] .Screen/y DEO2
101
+	.Screen/sprite DEO
102
+	JMP2r
103
+
104
+@guide-icn [ 0101 0101 0101 01ff ]
105
+
106
+@fill-icn [ ffff ffff ffff ffff ]
107
+
108
+@cursor-icn [ 80c0 e0f0 f8e0 1000 ]
109
+
110
+@portrait-chr [
111
+	070f 1e1d 1b3b 3b3b f0e0 c0c0 d08b 8080
112
+	f76f cf9f 9f5f 5f5f 0000 0007 1c40 4040
113
+	fffb f975 7576 7667 0000 3164 0406 0607
114
+	efef efef eddd 9e1e 0060 8000 0000 0000
115
+	3b2b 280d 0105 0506 8080 8081 e1f1 f1f0
116
+	5f6c 639b 0f27 77ab 4060 639b 0f27 67ab
117
+	0dc8 b0e5 cded fdfc 0dc8 b0e4 ccec fcfc
118
+	5e1e 1c9c 9d1d 5d59 4000 0080 8000 4040
119
+	0607 0707 070e 0e0e f0f0 f0f0 f0e0 e0e0
120
+	fb73 7fb7 bbbf bfdd f373 7b37 3b3f 3f1c
121
+	ffff ffff ffff ffff ffff ffff ffff ff7f
122
+	dba7 97f7 f7ed dd9d c080 90f0 f0e0 c080
123
+	1e0e 0000 0000 0000 c0c0 f0ff ffff ffff
124
+	ee03 0000 0000 0000 0e12 fcff ffff ffff
125
+	fffc f30f 1f1f 1f3f 9f3c f30f dfdf dfbf
126
+	3c80 8080 80c0 c0e0 0003 3fbf bfbf dfef ]
127
+
128
+@box-icn [
129
+	001f 2050 4844 4241 00ff 0000 0000 0000
130
+	00ff 0000 0000 0000 00f8 040a 1222 4282
131
+	4040 4040 4040 4040 8040 2010 0804 0201
132
+	0102 0408 1020 4080 0202 0202 0202 0202
133
+	4040 4040 4040 4040 0102 0408 1020 4080
134
+	8040 2010 0804 0201 0202 0202 0202 0202
135
+	4142 4448 5020 1f00 0000 0000 0000 ff00
136
+	0000 0000 0000 ff00 8242 2212 0a04 f800 ]
137
+
138
+@circle-chr [
139
+	071f 3c70 60e3 c7c7 0000 030f 1f1f 3f3f ]
140
+
141
+
... ...
@@ -47,7 +47,7 @@ screen_fill(Uint8 *layer, int color)
47 47
 }
48 48
 
49 49
 void
50
-screen_rect(Uint8 *layer, int x1, int y1, int x2, int y2, int color)
50
+screen_rect(Uint8 *layer, Uint16 x1, Uint16 y1, Uint16 x2, Uint16 y2, int color)
51 51
 {
52 52
 	int x, y, width = uxn_screen.width, height = uxn_screen.height;
53 53
 	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)
56 56
 }
57 57
 
58 58
 static void
59
-screen_blit(Uint8 *layer, Uint8 *ram, Uint16 addr, int x1, int y1, int color, int flipx, int flipy, int twobpp)
59
+screen_2bpp(Uint8 *layer, Uint8 *ram, Uint16 addr, Uint16 x1, Uint16 y1, Uint16 color, int fx, int fy)
60 60
 {
61
-	int v, h, width = uxn_screen.width, height = uxn_screen.height, opaque = (color % 5);
62
-	for(v = 0; v < 8; v++) {
63
-		Uint16 c = ram[(addr + v) & 0xffff] | (twobpp ? (ram[(addr + v + 8) & 0xffff] << 8) : 0);
64
-		Uint16 y = y1 + (flipy ? 7 - v : v);
65
-		for(h = 7; h >= 0; --h, c >>= 1) {
61
+	int width = uxn_screen.width, height = uxn_screen.height, opaque = (color % 5);
62
+	Uint8 *ch1 = &ram[addr], *ch2 = ch1 + 8;
63
+	Uint16 y, ymod = (fy < 0 ? 7 : 0), ymax = y1 + ymod + fy * 8;
64
+	Uint16 x, xmod = (fx > 0 ? 7 : 0), xmax = x1 + xmod - fx * 8;
65
+	for(y = y1 + ymod; y != ymax; y += fy) {
66
+		Uint16 c = *ch1++ | (*ch2++ << 8);
67
+		for(x = x1 + xmod; x != xmax; x -= fx, c >>= 1) {
66 68
 			Uint8 ch = (c & 1) | ((c >> 7) & 2);
67
-			if(opaque || ch) {
68
-				Uint16 x = x1 + (flipx ? 7 - h : h);
69
-				if(x < width && y < height)
70
-					layer[x + y * width] = blending[ch][color];
71
-			}
69
+			if((opaque || ch) && x < width && y < height)
70
+				layer[x + y * width] = blending[ch][color];
71
+		}
72
+	}
73
+}
74
+
75
+static void
76
+screen_1bpp(Uint8 *layer, Uint8 *ram, Uint16 addr, Uint16 x1, Uint16 y1, Uint16 color, int fx, int fy)
77
+{
78
+	int width = uxn_screen.width, height = uxn_screen.height, opaque = (color % 5);
79
+	Uint8 *ch1 = &ram[addr];
80
+	Uint16 y, ymod = (fy < 0 ? 7 : 0), ymax = y1 + ymod + fy * 8;
81
+	Uint16 x, xmod = (fx > 0 ? 7 : 0), xmax = x1 + xmod - fx * 8;
82
+	for(y = y1 + ymod; y != ymax; y += fy) {
83
+		Uint16 c = *ch1++;
84
+		for(x = x1 + xmod; x != xmax; x -= fx, c >>= 1) {
85
+			Uint8 ch = c & 1;
86
+			if((opaque || ch) && x < width && y < height)
87
+				layer[x + y * width] = blending[ch][color];
72 88
 		}
73 89
 	}
74 90
 }
... ...
@@ -93,8 +109,8 @@ static Uint8 arrow[] = {
93 109
 static void
94 110
 draw_byte(Uint8 b, Uint16 x, Uint16 y, Uint8 color)
95 111
 {
96
-	screen_blit(uxn_screen.fg, icons, (b >> 4) << 3, x, y, color, 0, 0, 0);
97
-	screen_blit(uxn_screen.fg, icons, (b & 0xf) << 3, x + 8, y, color, 0, 0, 0);
112
+	screen_1bpp(uxn_screen.fg, icons, (b >> 4) << 3, x, y, color, 1, 1);
113
+	screen_1bpp(uxn_screen.fg, icons, (b & 0xf) << 3, x + 8, y, color, 1, 1);
98 114
 	screen_change(x, y, x + 0x10, y + 0x8);
99 115
 }
100 116
 
... ...
@@ -104,19 +120,19 @@ screen_debugger(Uxn *u)
104 120
 	int i;
105 121
 	for(i = 0; i < 0x08; i++) {
106 122
 		Uint8 pos = u->wst.ptr - 4 + i;
107
-		Uint8 color = i > 4 ? 0x01 : !pos ? 0xc
108
-			: i == 4                      ? 0x8
109
-										  : 0x2;
123
+		Uint8 color = i > 4 ? 0x01 : !pos ? 0xc :
124
+			i == 4                        ? 0x8 :
125
+                                            0x2;
110 126
 		draw_byte(u->wst.dat[pos], i * 0x18 + 0x8, uxn_screen.height - 0x18, color);
111 127
 	}
112 128
 	for(i = 0; i < 0x08; i++) {
113 129
 		Uint8 pos = u->rst.ptr - 4 + i;
114
-		Uint8 color = i > 4 ? 0x01 : !pos ? 0xc
115
-			: i == 4                      ? 0x8
116
-										  : 0x2;
130
+		Uint8 color = i > 4 ? 0x01 : !pos ? 0xc :
131
+			i == 4                        ? 0x8 :
132
+                                            0x2;
117 133
 		draw_byte(u->rst.dat[pos], i * 0x18 + 0x8, uxn_screen.height - 0x10, color);
118 134
 	}
119
-	screen_blit(uxn_screen.fg, arrow, 0, 0x68, uxn_screen.height - 0x20, 3, 0, 0, 0);
135
+	screen_1bpp(uxn_screen.fg, arrow, 0, 0x68, uxn_screen.height - 0x20, 3, 1, 1);
120 136
 	for(i = 0; i < 0x20; i++)
121 137
 		draw_byte(u->ram[i], (i & 0x7) * 0x18 + 0x8, ((i >> 3) << 3) + 0x8, 1 + !!u->ram[i]);
122 138
 }
... ...
@@ -252,9 +268,16 @@ screen_deo(Uint8 *ram, Uint8 *d, Uint8 port)
252 268
 		x = PEEK2(port_x), dx = (move & 0x1) << 3, dxy = dx * fy;
253 269
 		y = PEEK2(port_y), dy = (move & 0x2) << 2, dyx = dy * fx;
254 270
 		addr = PEEK2(port_addr), addr_incr = (move & 0x4) << (1 + twobpp);
255
-		for(i = 0; i <= length; i++) {
256
-			screen_blit(layer, ram, addr, x + dyx * i, y + dxy * i, color, flipx, flipy, twobpp);
257
-			addr += addr_incr;
271
+		if(twobpp) {
272
+			for(i = 0; i <= length; i++) {
273
+				screen_2bpp(layer, ram, addr, x + dyx * i, y + dxy * i, color, fx, fy);
274
+				addr += addr_incr;
275
+			}
276
+		} else {
277
+			for(i = 0; i <= length; i++) {
278
+				screen_1bpp(layer, ram, addr, x + dyx * i, y + dxy * i, color, fx, fy);
279
+				addr += addr_incr;
280
+			}
258 281
 		}
259 282
 		screen_change(x, y, x + dyx * length + 8, y + dxy * length + 8);
260 283
 		if(move & 0x1) {
... ...
@@ -23,7 +23,7 @@ extern UxnScreen uxn_screen;
23 23
 extern int emu_resize(int width, int height);
24 24
 
25 25
 void screen_fill(Uint8 *layer, int color);
26
-void screen_rect(Uint8 *layer, int x1, int y1, int x2, int y2, int color);
26
+void screen_rect(Uint8 *layer, Uint16 x1, Uint16 y1, Uint16 x2, Uint16 y2, int color);
27 27
 void screen_palette(Uint8 *addr);
28 28
 void screen_resize(Uint16 width, Uint16 height);
29 29
 void screen_change(Uint16 x1, Uint16 y1, Uint16 x2, Uint16 y2);