Browse code

Started migrating examples to new devices setup

neauoire authored on 27/02/2021 00:38:20
Showing 12 changed files
... ...
@@ -20,5 +20,5 @@ cc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werr
20 20
 # cc uxn.c emulator.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -L/usr/local/lib -lSDL2 -o bin/emulator
21 21
 
22 22
 # run
23
-./bin/assembler examples/gui.shapes.usm bin/boot.rom
23
+./bin/assembler examples/dev.mouse.usm bin/boot.rom
24 24
 ./bin/emulator bin/boot.rom
... ...
@@ -253,30 +253,31 @@ init(void)
253 253
 }
254 254
 
255 255
 void
256
-domouse(SDL_Event *event)
256
+domouse(Uxn *u, SDL_Event *event)
257 257
 {
258 258
 	Uint8 flag = 0x00;
259
+	Uint16 addr = 0xff50; /* TODO: get dynamically */
259 260
 	Uint16 x = clamp(event->motion.x / ZOOM - PAD * 8, 0, HOR * 8 - 1);
260 261
 	Uint16 y = clamp(event->motion.y / ZOOM - PAD * 8, 0, VER * 8 - 1);
261
-	devmouse->mem[0] = (x >> 8) & 0xff;
262
-	devmouse->mem[1] = x & 0xff;
263
-	devmouse->mem[2] = (y >> 8) & 0xff;
264
-	devmouse->mem[3] = y & 0xff;
265
-	devmouse->mem[5] = 0x00;
262
+	u->ram.dat[addr + 0] = (x >> 8) & 0xff;
263
+	u->ram.dat[addr + 1] = x & 0xff;
264
+	u->ram.dat[addr + 2] = (y >> 8) & 0xff;
265
+	u->ram.dat[addr + 3] = y & 0xff;
266
+	u->ram.dat[addr + 5] = 0x00;
266 267
 	switch(event->button.button) {
267 268
 	case SDL_BUTTON_LEFT: flag = 0x01; break;
268 269
 	case SDL_BUTTON_RIGHT: flag = 0x10; break;
269 270
 	}
270 271
 	switch(event->type) {
271 272
 	case SDL_MOUSEBUTTONUP:
272
-		setflag(&devmouse->mem[4], flag, 0);
273
+		setflag(&u->ram.dat[addr + 4], flag, 0);
273 274
 		break;
274 275
 	case SDL_MOUSEBUTTONDOWN:
275
-		setflag(&devmouse->mem[4], flag, 1);
276
-		if(flag == 0x01 && getflag(&devmouse->mem[4], 0x10))
277
-			devmouse->mem[5] = 0x01;
278
-		if(flag == 0x10 && getflag(&devmouse->mem[4], 0x01))
279
-			devmouse->mem[5] = 0x10;
276
+		setflag(&u->ram.dat[addr + 4], flag, 1);
277
+		if(flag == 0x01 && getflag(&u->ram.dat[addr + 4], 0x10))
278
+			u->ram.dat[addr + 5] = 0x01;
279
+		if(flag == 0x10 && getflag(&u->ram.dat[addr + 4], 0x01))
280
+			u->ram.dat[addr + 5] = 0x10;
280 281
 		break;
281 282
 	}
282 283
 }
... ...
@@ -325,19 +326,23 @@ doctrl(SDL_Event *event, int z)
325 326
 #pragma mark - Devices
326 327
 
327 328
 Uint8
328
-console_poke(Uint8 *m, Uint8 b0, Uint8 b1)
329
+console_poke(Uint8 *m, Uint16 ptr, Uint8 b0, Uint8 b1)
329 330
 {
330 331
 	printf("%c", b1);
331 332
 	fflush(stdout);
333
+	(void)m;
334
+	(void)ptr;
335
+	(void)b0;
332 336
 	return b1;
333 337
 }
334 338
 
335 339
 Uint8
336
-screen_poke(Uint8 *m, Uint8 b0, Uint8 b1)
340
+screen_poke(Uint8 *m, Uint16 ptr, Uint8 b0, Uint8 b1)
337 341
 {
338
-	if(b0 == 0x04) {
339
-		Uint16 x = (*(m + 2) << 8) + *(m + 3);
340
-		Uint16 y = (*m << 8) + *(m + 1);
342
+	ptr += 8;
343
+	if(b0 == 0x0c) {
344
+		Uint16 x = (m[ptr] << 8) + m[ptr + 1];
345
+		Uint16 y = (m[ptr + 2] << 8) + m[ptr + 3];
341 346
 		paintpixel(b1 >> 4 & 0xf ? screen.fg : screen.bg, x, y, b1 & 0xf);
342 347
 		screen.reqdraw = 1;
343 348
 	}
... ...
@@ -345,16 +350,30 @@ screen_poke(Uint8 *m, Uint8 b0, Uint8 b1)
345 350
 }
346 351
 
347 352
 Uint8
348
-peek1(Uint8 *m, Uint8 b0, Uint8 b1)
353
+sprite_poke(Uint8 *m, Uint16 ptr, Uint8 b0, Uint8 b1)
349 354
 {
350
-	printf("PEEK! %02x\n", b1);
355
+	ptr += 8;
356
+	if(b0 == 0x0e) {
357
+		Uint16 x = (m[ptr] << 8) + m[ptr + 1];
358
+		Uint16 y = (m[ptr + 2] << 8) + m[ptr + 3];
359
+		Uint16 a = (m[ptr + 4] << 8) + m[ptr + 5];
360
+		Uint8 source = (b1 >> 4) & 0xf;
361
+		Uint8 *layer = source % 2 ? screen.fg : screen.bg;
362
+		if(source / 2)
363
+			paintchr(layer, x, y, &m[a]);
364
+		else
365
+			painticn(layer, x, y, &m[a], b1 & 0xf);
366
+		screen.reqdraw = 1;
367
+	}
351 368
 	return b1;
352 369
 }
353 370
 
354 371
 Uint8
355
-poke1(Uint8 *m, Uint8 b0, Uint8 b1)
372
+ppnil(Uint8 *m, Uint16 ptr, Uint8 b0, Uint8 b1)
356 373
 {
357
-	printf("POKE! %02x\n", b1);
374
+	(void)m;
375
+	(void)ptr;
376
+	(void)b0;
358 377
 	return b1;
359 378
 }
360 379
 
... ...
@@ -376,37 +395,6 @@ consolew(Device *d, Memory *m, Uint8 b)
376 395
 	return 0;
377 396
 }
378 397
 
379
-Uint8
380
-screenr(Device *d, Memory *m, Uint8 b)
381
-{
382
-	loadtheme(m->dat + 0xfff0);
383
-	switch(b) {
384
-	case 0: return (HOR * 8 >> 8) & 0xff;
385
-	case 1: return HOR * 8 & 0xff;
386
-	case 2: return (VER * 8 >> 8) & 0xff;
387
-	case 3: return VER * 8 & 0xff;
388
-	}
389
-	(void)m;
390
-	return d->mem[b];
391
-}
392
-
393
-Uint8
394
-screenw(Device *d, Memory *m, Uint8 b)
395
-{
396
-	d->mem[d->ptr++] = b;
397
-	if(d->ptr > 4) {
398
-		Uint16 x = (d->mem[2] << 8) + d->mem[3];
399
-		Uint16 y = (d->mem[0] << 8) + d->mem[1];
400
-		Uint8 clr = d->mem[4] & 0xf;
401
-		Uint8 layer = d->mem[4] >> 4 & 0xf;
402
-		paintpixel(layer ? screen.fg : screen.bg, x, y, clr);
403
-		screen.reqdraw = 1;
404
-		d->ptr = 0;
405
-	}
406
-	(void)m;
407
-	return 0;
408
-}
409
-
410 398
 Uint8
411 399
 spritew(Device *d, Memory *m, Uint8 b)
412 400
 {
... ...
@@ -449,7 +437,7 @@ start(Uxn *u)
449 437
 			case SDL_QUIT: quit(); break;
450 438
 			case SDL_MOUSEBUTTONUP:
451 439
 			case SDL_MOUSEBUTTONDOWN:
452
-			case SDL_MOUSEMOTION: domouse(&event); break;
440
+			case SDL_MOUSEMOTION: domouse(u, &event); break;
453 441
 			case SDL_TEXTINPUT: dotext(&event); break;
454 442
 			case SDL_KEYDOWN: doctrl(&event, 1); break;
455 443
 			case SDL_KEYUP: doctrl(&event, 0); break;
... ...
@@ -479,12 +467,17 @@ main(int argc, char **argv)
479 467
 	if(!init())
480 468
 		return error("Init", "Failed");
481 469
 
482
-	devconsole = portuxn(&u, "console", defaultrw, consolew, peek1, console_poke);
483
-	devscreen = portuxn(&u, "screen", screenr, screenw, peek1, screen_poke);
484
-	devsprite = portuxn(&u, "sprite", screenr, spritew, peek1, poke1);
485
-	devcontroller = portuxn(&u, "controller", defaultrw, defaultrw, peek1, poke1);
486
-	devkey = portuxn(&u, "key", defaultrw, consolew, peek1, poke1);
487
-	devmouse = portuxn(&u, "mouse", defaultrw, defaultrw, peek1, poke1);
470
+	devconsole = portuxn(&u, "console", defaultrw, consolew, ppnil, console_poke);
471
+	devscreen = portuxn(&u, "screen", defaultrw, defaultrw, ppnil, screen_poke);
472
+	devsprite = portuxn(&u, "sprite", defaultrw, spritew, ppnil, sprite_poke);
473
+	devcontroller = portuxn(&u, "controller", defaultrw, defaultrw, ppnil, ppnil);
474
+	devkey = portuxn(&u, "key", defaultrw, consolew, ppnil, ppnil);
475
+	devmouse = portuxn(&u, "mouse", defaultrw, defaultrw, ppnil, ppnil);
476
+
477
+	u.ram.dat[0xff10] = (HOR * 8 >> 8) & 0xff;
478
+	u.ram.dat[0xff11] = HOR * 8 & 0xff;
479
+	u.ram.dat[0xff12] = (VER * 8 >> 8) & 0xff;
480
+	u.ram.dat[0xff13] = VER * 8 & 0xff;
488 481
 
489 482
 	start(&u);
490 483
 	quit();
... ...
@@ -1,11 +1,18 @@
1 1
 ( blank )
2 2
 
3
-:dev/r fff8 ( std read port )
4
-:dev/w fff9 ( std write port )
3
+&Console { pad 8 stdio 1 }
4
+&Screen  { width 2 height 2 pad 4 y 2 x 2 color 1 }
5
+&Sprite  { pad 8 y 2 x 2 addr 2 color 1 }
6
+&Mouse   { x 2 y 2 state 1 chord 1 }
5 7
 
6 8
 |0100 @RESET BRK
7 9
 |c000 @FRAME BRK 
8 10
 |d000 @ERROR BRK 
9 11
 
12
+|FF00 ;dev/console Console
13
+|FF10 ;dev/screen  Screen
14
+|FF20 ;dev/sprite  Sprite
15
+|FF50 ;dev/mouse   Mouse
16
+
10 17
 |FFF0 [ f2ac 35bb 2b53 ] ( palette )
11 18
 |FFFA .RESET .FRAME .ERROR
12 19
similarity index 100%
13 20
rename from examples/devchord.usm
14 21
rename to examples/dev.chord.usm
15 22
similarity index 91%
16 23
rename from examples/devconsole.usm
17 24
rename to examples/dev.console.usm
... ...
@@ -1,6 +1,6 @@
1 1
 ( hello world )
2 2
 
3
-&Console { stdio 1 }
3
+&Console { pad 8 stdio 1 }
4 4
 
5 5
 |0100 @RESET 
6 6
 	
7 7
similarity index 83%
8 8
rename from examples/devmouse.usm
9 9
rename to examples/dev.mouse.usm
... ...
@@ -1,45 +1,37 @@
1 1
 ( mouse )
2 2
 
3
-:dev/r fff8 ( std read port )
4
-:dev/w fff9 ( std write port )
3
+&Screen { width 2 height 2 pad 4 y 2 x 2 color 1 }
4
+&Sprite { pad 8 y 2 x 2 addr 2 color 1 }
5
+&Mouse  { x 2 y 2 state 1 chord 1 }
5 6
 
6 7
 &Point2d { x 2 y 2 }
7 8
 
8
-;mouse Point2d
9
-;cat Point2d
9
+;cat Point2d ;mouse Point2d
10 10
 
11
-;state 1 ;timer 1
11
+;timer 1
12 12
 
13 13
 |0100 @RESET 
14
-	
15
-	#01 =dev/r ( set dev/read screen )
16 14
 
17 15
 	( position cat )
18
-	#00 IOR2 #0002 DIV2 =cat.x 
19
-	#02 IOR2 #0038 SUB2 =cat.y
20
-
21
-	#05 =dev/r ( set dev/read mouse )
22
-	#02 =dev/w ( set dev/write to sprite ) 
23
-	
16
+	~dev/screen.width #0002 DIV2 =cat.x 
17
+	~dev/screen.height #0038 SUB2 =cat.y
24 18
 	( draw polycat )
25 19
 	,draw-polycat JSR
26 20
 
27 21
 BRK
28 22
 
29 23
 |c000 @FRAME
30
-
24
+	
31 25
 	( clear last cursor )
32 26
 	#10 ,clear_icn ~mouse.x ~mouse.y ,draw-sprite JSR
33 27
 	( record mouse positions )
34
-	#00 IOR2 =mouse.x #02 IOR2 =mouse.y
35
-	( record mouse state )
36
-	#04 IOR #11 ADD =state
28
+	~dev/mouse.x =mouse.x ~dev/mouse.y =mouse.y
37 29
 	( detect click )
38
-	#04 IOR #01 NEQ ,no-click ROT JMP? POP2
30
+	~dev/mouse.state #01 NEQ ,no-click ROT JMP? POP2
39 31
 		#50 =timer
40 32
 	@no-click
41 33
 	( draw mouse )
42
-	~state ,cursor_icn ~mouse.x ~mouse.y ,draw-sprite JSR
34
+	~dev/mouse.state #11 ADD ,cursor_icn ~mouse.x ~mouse.y ,draw-sprite JSR
43 35
 	( animate )
44 36
 	,animate-polycat JSR
45 37
 	( update last pos )
... ...
@@ -99,17 +91,17 @@ RTS
99 91
 RTS
100 92
 
101 93
 @draw-sprite
102
-	IOW2 ( y byte )
103
-	IOW2 ( x byte )
104
-	IOW2 ( sprite address )
105
-	IOW ( layer-color )
94
+	=dev/sprite.x
95
+	=dev/sprite.y
96
+	=dev/sprite.addr
97
+	=dev/sprite.color
106 98
 	RTS
107 99
 
108 100
 @draw-sprite-chr
109
-	IOW2 ( y byte )
110
-	IOW2 ( x byte )
111
-	IOW2 ( sprite address )
112
-	#20 IOW ( layer-color )
101
+	=dev/sprite.x
102
+	=dev/sprite.y
103
+	=dev/sprite.addr
104
+	#20 =dev/sprite.color
113 105
 	RTS
114 106
 
115 107
 @clear_icn   [ 0000 0000 0000 0000 ]
... ...
@@ -132,6 +124,10 @@ RTS
132 124
 	c0f0 f0e0 e080 8000 c0f1 faf9 fef8 b000
133 125
 ]
134 126
 
127
+|FF10 ;dev/screen Screen
128
+|FF20 ;dev/sprite Sprite
129
+|FF50 ;dev/mouse  Mouse
130
+
135 131
 |d000 @ERROR BRK 
136 132
 |FFF0 [ 0f85 0fd5 0fb5 ] ( palette )
137 133
 |FFFA .RESET .FRAME .ERROR
138 134
new file mode 100644
... ...
@@ -0,0 +1,40 @@
1
+( screen )
2
+
3
+&Screen { width 2 height 2 pad 4 x 2 y 2 color 1 }
4
+
5
+;centerx 2 ;centery 2 ;i 2
6
+
7
+|0100 @RESET 
8
+
9
+	( find screen center )
10
+	~dev/screen.width #0002 DIV2 =centerx
11
+	~dev/screen.height #0002 DIV2 =centery
12
+
13
+	( draw hor line )
14
+	#0000 =i
15
+	~centery =dev/screen.y
16
+	@draw-hor
17
+		#03 ~i =dev/screen.x =dev/screen.color
18
+		~i #0002 ADD2 =i ( increment )
19
+	~i ~dev/screen.width LTH2 ,draw-hor ROT JMP? POP2
20
+
21
+	( draw ver line )
22
+	#0000 =i
23
+	~centerx =dev/screen.x
24
+	@draw-ver
25
+		#03 ~i =dev/screen.y =dev/screen.color
26
+		~i #0002 ADD2 =i ( increment )
27
+	~i ~dev/screen.width LTH2 ,draw-ver ROT JMP? POP2
28
+
29
+	( draw pixel in the middle )
30
+	#01 ~centerx ~centery =dev/screen.y =dev/screen.x =dev/screen.color
31
+
32
+BRK
33
+
34
+|c000 @FRAME BRK
35
+|d000 @ERROR BRK 
36
+
37
+|FF10 ;dev/screen Screen
38
+
39
+|FFF0 [ f0ac f0bb f053 ] ( palette )
40
+|FFFA .RESET .FRAME .ERROR ( vectors )
0 41
deleted file mode 100644
... ...
@@ -1,45 +0,0 @@
1
-( screen )
2
-
3
-:dev/r fff8 ( std read port )
4
-:dev/w fff9 ( std write port )
5
-
6
-;centerx 2 ;centery 2 ;i 2
7
-
8
-|0100 @RESET 
9
-	
10
-	( set read/write to dev/screen )
11
-	#01 DUP =dev/r =dev/w 
12
-
13
-	( find screen center )
14
-	#00 IOR2 #0002 DIV2 =centerx
15
-	#02 IOR2 #0002 DIV2 =centery
16
-
17
-	( draw hor line )
18
-	#0000 =i
19
-	@draw-hor
20
-		#03 ~i ~centery ,draw-pixel JSR
21
-		~i #0002 ADD2 =i ( increment )
22
-	~i #00 IOR2 LTH2 ,draw-hor ROT JMP? POP2
23
-
24
-	( draw ver line )
25
-	#0000 =i
26
-	@draw-ver
27
-		#03 ~centerx ~i ,draw-pixel JSR
28
-		~i #0002 ADD2 =i ( increment )
29
-	~i #02 IOR2 LTH2 ,draw-ver ROT JMP? POP2
30
-
31
-	( draw pixel in the middle )
32
-	#01 ~centerx ~centery ,draw-pixel JSR
33
-
34
-BRK
35
-
36
-@draw-pixel 
37
-	IOW2 ( y short )
38
-	IOW2 ( x short )
39
-	IOW ( color byte )
40
-	RTS
41
-
42
-|c000 @FRAME BRK
43
-|d000 @ERROR BRK 
44
-|FFF0 [ f0ac f0bb f053 ] ( palette )
45
-|FFFA .RESET .FRAME .ERROR ( vectors )
46 0
similarity index 100%
47 1
rename from examples/blending.usm
48 2
rename to examples/gui.blending.usm
... ...
@@ -1,6 +1,6 @@
1 1
 ( draw routines )
2 2
 
3
-&Screen { y 2 x 2 color 1 }
3
+&Screen { width 2 height 2 pad 4 y 2 x 2 color 1 red 1 green 1 blue 1 }
4 4
 
5 5
 ;color 1 ;x1 2 ;x2 2 ;y1 2 ;y2 2
6 6
 
... ...
@@ -53,7 +53,7 @@ RTS
53 53
 |c000 @FRAME BRK 
54 54
 |d000 @ERROR BRK 
55 55
 
56
-|FF08 ;dev/screen Screen
56
+|FF10 ;dev/screen Screen
57 57
 
58 58
 |FFF0 [ 0f0f 0fff 0ff0 ] ( palette )
59 59
 |FFFA .RESET .FRAME .ERROR ( vectors )
60 60
\ No newline at end of file
... ...
@@ -18,9 +18,9 @@ WITH REGARD TO THIS SOFTWARE.
18 18
 /* clang-format off */
19 19
 void   setflag(Uint8 *a, char flag, int b) { if(b) *a |= flag; else *a &= (~flag); }
20 20
 int    getflag(Uint8 *a, char flag) { return *a & flag; }
21
-Uint8  devpoke8(Uxn *u, Uint8 id, Uint8 b0, Uint8 b1){ return id < u->devices ? u->dev[id].poke(&u->ram.dat[0xff00 + id * 8], b0, b1) : b1; }
22
-Uint8  devpeek8(Uxn *u, Uint8 id, Uint8 b0, Uint8 b1){ return id < u->devices ? u->dev[id].peek(&u->ram.dat[0xff00 + id * 8], b0, b1) : b1; }
23
-void   mempoke8(Uxn *u, Uint16 a, Uint8 b) { u->ram.dat[a] = a >= 0xff00 ? devpoke8(u, (a & 0xff) >> 3, (a & 0xf) % 8, b) : b; }
21
+Uint8  devpoke8(Uxn *u, Uint8 id, Uint8 b0, Uint8 b1){ return id < u->devices ? u->dev[id].poke(u->ram.dat, 0xff00 + id * 0x10, b0, b1) : b1; }
22
+Uint8  devpeek8(Uxn *u, Uint8 id, Uint8 b0, Uint8 b1){ return id < u->devices ? u->dev[id].peek(u->ram.dat, 0xff00 + id * 0x10, b0, b1) : b1; }
23
+void   mempoke8(Uxn *u, Uint16 a, Uint8 b) { u->ram.dat[a] = a >= 0xff00 ? devpoke8(u, (a & 0xff) >> 4, a & 0xf, b) : b; }
24 24
 Uint8  mempeek8(Uxn *u, Uint16 a) { return a >= 0xff00 ? devpeek8(u, (a & 0xff) >> 4, a & 0xf, u->ram.dat[a]) : u->ram.dat[a]; }
25 25
 void   mempoke16(Uxn *u, Uint16 a, Uint16 b) { mempoke8(u, a, b >> 8); mempoke8(u, a + 1, b); }
26 26
 Uint16 mempeek16(Uxn *u, Uint16 a) { return (mempeek8(u, a) << 8) + mempeek8(u, a + 1); }
... ...
@@ -211,7 +211,7 @@ loaduxn(Uxn *u, char *filepath)
211 211
 }
212 212
 
213 213
 Device *
214
-portuxn(Uxn *u, char *name, Uint8 (*rfn)(Device *, Memory *, Uint8), Uint8 (*wfn)(Device *, Memory *, Uint8), Uint8 (*pefn)(Uint8 *m, Uint8 b0, Uint8 b1), Uint8 (*pofn)(Uint8 *m, Uint8 b0, Uint8 b1))
214
+portuxn(Uxn *u, char *name, Uint8 (*rfn)(Device *, Memory *, Uint8), Uint8 (*wfn)(Device *, Memory *, Uint8), Uint8 (*pefn)(Uint8 *m, Uint16 ptr, Uint8 b0, Uint8 b1), Uint8 (*pofn)(Uint8 *m, Uint16 ptr, Uint8 b0, Uint8 b1))
215 215
 {
216 216
 	Device *d = &u->dev[u->devices++];
217 217
 	d->read = rfn;
... ...
@@ -35,8 +35,8 @@ typedef struct Device {
35 35
 	Uint8 ptr, mem[8];
36 36
 	Uint8 (*read)(struct Device *, Memory *, Uint8);
37 37
 	Uint8 (*write)(struct Device *, Memory *, Uint8);
38
-	Uint8 (*peek)(Uint8 *, Uint8, Uint8);
39
-	Uint8 (*poke)(Uint8 *, Uint8, Uint8);
38
+	Uint8 (*peek)(Uint8 *, Uint16, Uint8, Uint8);
39
+	Uint8 (*poke)(Uint8 *, Uint16, Uint8, Uint8);
40 40
 } Device;
41 41
 
42 42
 typedef struct {
... ...
@@ -52,4 +52,4 @@ int getflag(Uint8 *status, char flag);
52 52
 int loaduxn(Uxn *c, char *filepath);
53 53
 int bootuxn(Uxn *c);
54 54
 int evaluxn(Uxn *u, Uint16 vec);
55
-Device *portuxn(Uxn *u, char *name, Uint8 (*rfn)(Device *, Memory *, Uint8), Uint8 (*wfn)(Device *, Memory *, Uint8), Uint8 (*pefn)(Uint8 *, Uint8, Uint8), Uint8 (*pofn)(Uint8 *, Uint8, Uint8));
55
+Device *portuxn(Uxn *u, char *name, Uint8 (*rfn)(Device *, Memory *, Uint8), Uint8 (*wfn)(Device *, Memory *, Uint8), Uint8 (*pefn)(Uint8 *, Uint16, Uint8, Uint8), Uint8 (*pofn)(Uint8 *, Uint16, Uint8, Uint8));