shithub: puzzles

Download patch

ref: 4338bb921e84cfb5186fe60950cf5704f997d2c2
parent: 6d347772d007e854bfcbdaecbb38abd7ef56ac6f
author: sirjofri <sirjofri@sirjofri.de>
date: Tue May 14 07:32:47 EDT 2024

adds timer support, adds blitter support (untested)

--- a/plan9.c
+++ b/plan9.c
@@ -13,6 +13,7 @@
 #endif
 
 //#define DIRECTDRAW
+//#define PROFILE
 
 struct frontend {
 	Image *image;
@@ -27,8 +28,16 @@
 	int timeractive;
 };
 
+struct blitter {
+	Image *blimg;
+};
+
 frontend *fe = nil;
 
+struct proftimes {
+	long draw;
+} ptimes;
+
 void
 frontend_default_colour(frontend *fe, float *output)
 {
@@ -90,7 +99,6 @@
 }
 
 char *showcmd = "c_game show";
-#define ugf chanprint(fe->cs->ctl, showcmd);
 
 static void p9_draw_text(void *handle, int x, int y, int fonttype, int fontsize, int align, int color, const char *text)
 {
@@ -99,7 +107,6 @@
 	string(screen, addpt(Pt(x, y), fe->ZP), fe->colors[color], ZP, font, text);
 #else
 	string(fe->image, Pt(x, y), fe->colors[color], ZP, font, text);
-	ugf;
 #endif
 }
 
@@ -111,7 +118,6 @@
 	draw(screen, rectaddpt(Rect(x, y, x+w, y+h), fe->ZP), fe->colors[color], nil, ZP);
 #else
 	draw(fe->image, Rect(x, y, x+w, y+h), fe->colors[color], nil, ZP);
-	ugf;
 #endif
 }
 
@@ -120,10 +126,9 @@
 {
 	frontend *fe = (frontend*)handle;
 #ifdef DIRECTDRAW
-	line(screen, addpt(Pt(x1, y1), fe->ZP), addpt(Pt(x2, y2), fe->ZP), Endsquare, Endsquare, 1, fe->colors[color], ZP);
+	line(screen, addpt(Pt(x1, y1), fe->ZP), addpt(Pt(x2, y2), fe->ZP), Endsquare, Endsquare, 0, fe->colors[color], ZP);
 #else
-	line(fe->image, Pt(x1, y1), Pt(x2, y2), Endsquare, Endsquare, 1, fe->colors[color], ZP);
-	ugf;
+	line(fe->image, Pt(x1, y1), Pt(x2, y2), Endsquare, Endsquare, 0, fe->colors[color], ZP);
 #endif
 }
 
@@ -132,10 +137,9 @@
 {
 	frontend *fe = (frontend*)handle;
 #ifdef DIRECTDRAW
-	line(screen, addpt(Pt(x1, y1), fe->ZP), addpt(Pt(x2, y2), fe->ZP), Endsquare, Endsquare, thickness, fe->colors[color], ZP);
+	line(screen, addpt(Pt(x1, y1), fe->ZP), addpt(Pt(x2, y2), fe->ZP), Endsquare, Endsquare, thickness-1, fe->colors[color], ZP);
 #else
-	line(fe->image, Pt(x1, y1), Pt(x2, y2), Endsquare, Endsquare, thickness, fe->colors[color], ZP);
-	ugf;
+	line(fe->image, Pt(x1, y1), Pt(x2, y2), Endsquare, Endsquare, thickness-1, fe->colors[color], ZP);
 #endif
 }
 
@@ -166,7 +170,6 @@
 		fillpoly(fe->image, points, npoints, 0, fe->colors[fillcolor], ZP);
 	if (outlinecolor > 0)
 		poly(fe->image, points, npoints, Endsquare, Endsquare, 1, fe->colors[outlinecolor], ZP);
-	ugf;
 #endif
 	
 	free(points);
@@ -184,7 +187,6 @@
 	Point c = Pt(cx, cy);
 	fillellipse(fe->image, c, radius, radius, fe->colors[fillcolor], ZP);
 	ellipse(fe->image, c, radius, radius, 0, fe->colors[outlinecolor], ZP);
-	ugf;
 #endif
 }
 
@@ -191,28 +193,43 @@
 static void
 p9_draw_update(void *handle, int x, int y, int w, int h)
 {
-	frontend *fe = (frontend*)handle;
-	chanprint(fe->cs->ctl, showcmd);
+	//frontend *fe = (frontend*)handle;
+	//print("draw_update\n");
+	//chanprint(fe->cs->ctl, showcmd);
 }
 
 static void
 p9_clip(void *handle, int x, int y, int w, int h)
 {
+	frontend *fe = (frontend*)handle;
+	fe->image->clipr = Rect(x, y, x + w, y + h);
 }
 
 static void
 p9_unclip(void *handle)
 {
+	frontend *fe = (frontend*)handle;
+	fe->image->clipr = fe->image->r;
 }
 
+long drawtime;
+
 static void
 p9_start_draw(void *handle)
 {
+#ifdef PROFILE
+	drawtime = times(nil);
+#endif
 }
 
 static void
 p9_end_draw(void *handle)
 {
+	frontend *fe = (frontend*)handle;
+	chanprint(fe->cs->ctl, showcmd);
+#ifdef PROFILE
+	ptimes.draw = times(nil) - drawtime;
+#endif
 }
 
 static void
@@ -226,22 +243,31 @@
 static blitter*
 p9_blitter_new(void *handle, int w, int h)
 {
-	return nil;
+	blitter *bl;
+	bl = malloc(sizeof(blitter));
+	bl->blimg = allocimage(display, Rect(0, 0, w, h), screen->chan, 0, 0);
+	return bl;
 }
 
 static void
 p9_blitter_free(void *handle, blitter *bl)
 {
+	freeimage(bl->blimg);
+	free(bl);
 }
 
 static void
 p9_blitter_save(void *handle, blitter *bl, int x, int y)
 {
+	frontend *fe = (frontend*)handle;
+	draw(bl->blimg, Rect(x, y, x + bl->blimg->r.max.x, y + bl->blimg->r.max.y), fe->image, nil, Pt(x, y)); // fix ZP if needed
 }
 
 static void
 p9_blitter_load(void *handle, blitter *bl, int x, int y)
 {
+	frontend *fe = (frontend*)handle;
+	draw(fe->image, Rect(x, y, x + bl->blimg->r.max.x, y + bl->blimg->r.max.y), bl->blimg, nil, Pt(x, y));
 }
 
 static const drawing_api p9_drawing = {
@@ -319,8 +345,9 @@
 	
 	b_settings = createtextbutton(cs, "b_settings");
 	p = stringsize(font, "settings");
-	chanprint(cs->ctl, "b_settings text settings");
+	chanprint(cs->ctl, "b_settings border 1");
 	chanprint(cs->ctl, "b_settings align center");
+	chanprint(cs->ctl, "b_settings text settings");
 	chanprint(cs->ctl, "b_settings size %d %d 500 %d", p.x, p.y, p.y);
 	c_settings = createcolumn(cs, "c_settings");
 	controlwire(c_settings, "event", c);
@@ -337,24 +364,6 @@
 }
 
 void
-timerthread(void *v)
-{
-	Channel *c;
-	long totaltime;
-	long newtime;
-	
-	c = v;
-	totaltime = times(nil);
-	
-	for (;;) {
-		sleep(100); /* minimum tick time */
-		newtime = times(nil);
-		chanprint(c, "tick: %ld\n", newtime - totaltime);
-		totaltime = newtime;
-	}
-}
-
-void
 initfe(frontend *fe)
 {
 	float *colors;
@@ -386,9 +395,6 @@
 	namectlimage(display->white, "i_white");
 	namectlimage(fe->background, "background");
 	initui(fe->cs, fe->c);
-	
-	// needs different timer option - atnotify(2) / alarm(2) ?
-	//threadcreate(timerthread, fe->c, 4096);
 }
 
 int windowset = 0;
@@ -563,6 +569,9 @@
 	case 'q':
 	case 127:
 		return 1; /* return 1 to quit */
+	case 'n':
+		midend_process_key(fe->me, 0, 0, UI_NEWGAME);
+		break;
 	default:
 		if (k >= 0 && midend_process_key(fe->me, 0, 0, k) == PKR_QUIT)
 			return 1;
@@ -573,12 +582,45 @@
 void
 tick(float delta)
 {
+	char msg[128];
+	
 	if (fe->timeractive) {
 		midend_timer(fe->me, delta);
 	}
+	
+#ifdef PROFILE
+	snprint(msg, 128, "draw: %ld", ptimes.draw);
+	chanprint(fe->cs->ctl, "l_status value %q", msg);
+#endif
 }
 
+typedef struct Tickinfo Tickinfo;
+struct Tickinfo {
+	long totaltime;
+	long lasttick;
+	float delta;
+};
+
 void
+timerproc(void *v)
+{
+	Channel *c;
+	Tickinfo ti;
+	long newtime;
+	
+	c = v;
+	ti.totaltime = times(nil);
+	
+	for (;;) {
+		sleep(20);
+		newtime = times(nil);
+		ti.delta = (newtime - ti.totaltime) / 1000.;
+		ti.totaltime = newtime;
+		send(c, &ti.delta);
+	}
+}
+
+void
 threadmain(int argc, char **argv)
 {
 	int x, y, n, r;
@@ -590,6 +632,12 @@
 	Channel *c;
 	config_item *cfg;
 	int changedprefs = 0;
+	float delta;
+	Alt a[] = {
+		{ nil, &s, CHANRCV },
+		{ nil, &delta, CHANRCV },
+		{ nil, nil, CHANEND },
+	};
 	
 	fe = new_window();
 	
@@ -632,55 +680,63 @@
 	midend_new_game(fe->me);
 	resizecontrolset(fe->cs);
 	
+	a[0].c = fe->c;
+	a[1].c = chancreate(sizeof(float), 0);
+	
+	proccreate(timerproc, a[1].c, 4096);
+	
 	for (;;) {
-		s = recvp(fe->c);
-		n = tokenize(s, args, nelem(args));
-		
-		if (strcmp(args[0], "c_settings:") == 0) {
-			print("c_settings event: %s\n", args[1]);
-		} else
-		if (strcmp(args[0], "c_game:") == 0) {
-			if (strcmp(args[1], "mouse") == 0) {
-				x = atoi(args[2]+1) - fe->ZP.x; /* ignore '[' */
-				y = atoi(args[3]) - fe->ZP.y;
-				n = atoi(args[4]);
-				r = -1;
-				if ( (lastmouse&1) && !(n&1))
-					r = midend_process_key(fe->me, x, y, LEFT_RELEASE);
-				if (!(lastmouse&1) &&  (n&1))
-					r = midend_process_key(fe->me, x, y, LEFT_BUTTON);
-				if ( (lastmouse&2) && !(n&2))
-					r = midend_process_key(fe->me, x, y, MIDDLE_RELEASE);
-				if (!(lastmouse&2) &&  (n&2))
-					r = midend_process_key(fe->me, x, y, MIDDLE_BUTTON);
-				if ( (lastmouse&4) && !(n&4))
-					r = midend_process_key(fe->me, x, y, RIGHT_RELEASE);
-				if (!(lastmouse&4) &&  (n&2))
-					r = midend_process_key(fe->me, x, y, RIGHT_BUTTON);
-				if (r >= 0) {
-					chanprint(fe->cs->ctl, showcmd);
+		switch (alt(a)) {
+		case 0: /* libcontrol event channel */	
+			n = tokenize(s, args, nelem(args));
+			
+			if (strcmp(args[0], "c_settings:") == 0) {
+				print("c_settings event: %s\n", args[1]);
+			} else
+			if (strcmp(args[0], "c_game:") == 0) {
+				if (strcmp(args[1], "mouse") == 0) {
+					x = atoi(args[2]+1) - fe->ZP.x; /* ignore '[' */
+					y = atoi(args[3]) - fe->ZP.y;
+					n = atoi(args[4]);
+					r = -1;
+					if ( (lastmouse&1) && !(n&1))
+						r = midend_process_key(fe->me, x, y, LEFT_RELEASE);
+					if (!(lastmouse&1) &&  (n&1))
+						r = midend_process_key(fe->me, x, y, LEFT_BUTTON);
+					if ( (lastmouse&2) && !(n&2))
+						r = midend_process_key(fe->me, x, y, MIDDLE_RELEASE);
+					if (!(lastmouse&2) &&  (n&2))
+						r = midend_process_key(fe->me, x, y, MIDDLE_BUTTON);
+					if ( (lastmouse&4) && !(n&4))
+						r = midend_process_key(fe->me, x, y, RIGHT_RELEASE);
+					if (!(lastmouse&4) &&  (n&2))
+						r = midend_process_key(fe->me, x, y, RIGHT_BUTTON);
+					if (r >= 0) {
+						chanprint(fe->cs->ctl, showcmd);
+					}
+					lastmouse = n;
+				} else
+				if (strcmp(args[1], "key") == 0) {
+					l = strtol(args[2], nil, 0);
+					if (keyev(l))
+						goto Out;
 				}
-				lastmouse = n;
 			} else
-			if (strcmp(args[1], "key") == 0) {
-				l = strtol(args[2], nil, 0);
-				if (keyev(l))
-					break;
-			}
-		} else
-		if (strcmp(args[0], "b_game:") == 0) {
-			showframe(0);
-			chanprint(fe->cs->ctl, "b_game value 0");
-		} else
-		if (strcmp(args[0], "b_settings:") == 0) {
-			showframe(1);
-			chanprint(fe->cs->ctl, "b_settings value 0");
-		} else
-		if (strcmp(args[0], "tick:") == 0) {
-			l = strtol(args[1], nil, 0);
-			tick(l / 1000.);
-		} else
-			print("event from %s: %s\n", args[0], args[1]);
+			if (strcmp(args[0], "b_game:") == 0) {
+				showframe(0);
+				chanprint(fe->cs->ctl, "b_game value 0");
+			} else
+			if (strcmp(args[0], "b_settings:") == 0) {
+				showframe(1);
+				chanprint(fe->cs->ctl, "b_settings value 0");
+			} else
+				print("event from %s: %s\n", args[0], args[1]);
+			break;
+		case 1: /* timer */
+			tick(delta);
+			break;
+		}
 	}
+Out:
 	threadexitsall(nil);
 }