shithub: qk1

Download patch

ref: 24fcd8e802ad06ef8863c95631e583a650d9ff1e
parent: 6b2f2bdd67732bcd7703f2d9edc9c1d9f8ca2483
author: qwx <>
date: Wed Jun 20 19:22:17 EDT 2018

vid: experimental scaling from a given resolution

--- a/dat.h
+++ b/dat.h
@@ -42,4 +42,4 @@
 };
 #define Spktatt 1.0
 
-extern int dumpwin;
+extern int dumpwin, scaleon;
--- a/qk1.c
+++ b/qk1.c
@@ -108,7 +108,7 @@
 static void
 usage(void)
 {
-	fprint(2, "usage: %s [-dl] [-g game] [-m kB]\n", argv0);
+	fprint(2, "usage: %s [-dl] [-g game] [-m kB] [-s width height]\n", argv0);
 	exits("usage");
 }
 
@@ -131,6 +131,13 @@
 		memsize = strtol(EARGF(usage()), nil, 0) * KB;
 		if(memsize <= 0)
 			sysfatal("invalid memsize");
+		break;
+	case 's':
+		scaleon = 1;
+		vid.width = strtol(EARGF(usage()), nil, 0);
+		vid.height = strtol(EARGF(usage()), nil, 0);
+		if(vid.width < 320 || vid.height < 200)
+			sysfatal("invalid scale resolution");
 		break;
 	default: usage();
 	}ARGEND
--- a/vid.c
+++ b/vid.c
@@ -7,15 +7,50 @@
 
 viddef_t vid;		/* global video state */
 int resized;
-int dumpwin;
+int dumpwin, scaleon;
 Point center;		/* of window */
 Rectangle grabr;
 
-static int fbpal[256];
-static uchar *fb;
+static int scale = 1;
+static s32int fbpal[256];
+static uchar *fb, *fbs;
 static Image *fbi;
+static Rectangle fbr;
 
 static void
+scalefb(int dy)
+{
+	int *p, c, *s;
+
+	if(scale < 2)
+		return;
+	p = (s32int *)fbs;
+	s = (s32int *)fb;
+	dy *= vid.width;
+	while(dy-- > 0){
+		c = *s++;
+		switch(scale){
+		case 16: p[15] = c;
+		case 15: p[14] = c;
+		case 14: p[13] = c;
+		case 13: p[12] = c;
+		case 12: p[11] = c;
+		case 11: p[10] = c;
+		case 10: p[9] = c;
+		case 9: p[8] = c;
+		case 8: p[7] = c;
+		case 7: p[6] = c;
+		case 6: p[5] = c;
+		case 5: p[4] = c;
+		case 4: p[3] = c;
+		case 3: p[2] = c;
+		case 2: p[1] = c; p[0] = c;
+		}
+		p += scale;
+	}
+}
+
+static void
 drawfb(int dy)
 {
 	uchar *s;
@@ -52,8 +87,16 @@
 	int hunkvbuf, scachesz;
 	Point p;
 
-	vid.width = Dx(screen->r);
-	vid.height = Dy(screen->r);
+	if(scaleon){
+		scale = Dx(screen->r) / vid.width;
+		if(scale <= 0)
+			scale = 1;
+		else if(scale > 16)
+			scale = 16;
+	}else{
+		vid.width = Dx(screen->r);
+		vid.height = Dy(screen->r);
+	}
 	if(d_pzbuffer != nil){
 		D_FlushCaches();
 		Hunk_FreeToHighMark(highhunk);
@@ -76,17 +119,26 @@
 	vid.conwidth = vid.width;
 	vid.conheight = vid.height;
 
-	center = addpt(screen->r.min, Pt(vid.width/2, vid.height/2));
+	center = divpt(addpt(screen->r.min, screen->r.max), 2);
+	p = Pt(scale * vid.width/2, scale * vid.height/2);
+	fbr = Rpt(subpt(center, p), addpt(center, p));
 	p = Pt(vid.width/4, vid.height/4);
 	grabr = Rpt(subpt(center, p), addpt(center, p));
 	freeimage(fbi);
 	free(fb);
-	fbi = allocimage(display, Rect(0,0,vid.width,vid.height), XRGB32, 0, 0);
+	fbi = allocimage(display,
+		Rect(0, 0, vid.width * scale, scale > 1 ? 1 : vid.height),
+		XRGB32, scale > 1, 0);
 	if(fbi == nil)
-		sysfatal("resetfb: %r");
-	fb = emalloc(vid.rowbytes * vid.height * sizeof *fb);
+		sysfatal("resetfb: %r (%d %d)", vid.width, vid.height);
+	fb = emalloc(vid.rowbytes * vid.height);
+	if(scaleon){
+		free(fbs);
+		fbs = emalloc(vid.rowbytes * scale * vid.height);
+	}
 	vid.buffer = fb;
 	vid.conbuffer = fb;
+	draw(screen, screen->r, display->black, nil, ZP);
 }
 
 /* only exists to allow taking tear-free screenshots ingame... */
@@ -125,12 +177,26 @@
 		vid.recalc_refdef = 1;	/* force a surface cache flush */
 		Con_CheckResize();
 		Con_Clear_f();
-		return;
 	}
 	drawfb(dy);
-	loadimage(fbi, Rect(0,0,vid.width,dy), fb, dy * vid.rowbytes);
-	draw(screen, Rpt(screen->r.min, Pt(screen->r.max.x,
-		screen->r.max.y - vid.height + dy)), fbi, nil, ZP);
+	scalefb(dy);
+	if(scale == 1){
+		loadimage(fbi, Rect(0,0,vid.width,dy), fb, dy * vid.rowbytes);
+		draw(screen, Rpt(fbr.min, Pt(fbr.max.x,
+			fbr.max.y - vid.height + dy)), fbi, nil, ZP);
+	}else{
+		Rectangle r;
+		uchar *p;
+
+		p = fbs;
+		r = fbr;
+		while(r.min.y < fbr.max.y){
+			r.max.y = r.min.y + scale;
+			p += loadimage(fbi, fbi->r, p, vid.rowbytes * scale);
+			draw(screen, r, fbi, nil, ZP);
+			r.min.y = r.max.y;
+		}
+	}
 	flushimage(display, 1);
 	if(dumpwin){
 		if(writebit() < 0)