shithub: front

Download patch

ref: 6d53af9408f199aea5c2440cb23f2467359d0c25
parent: b7e11e6c459c75585be93fbb4823a13591c08e65
author: qwx <qwx@sciops.net>
date: Tue Aug 5 05:38:16 EDT 2025

eui: handle screen scaling ourselves

--- a/sys/src/games/2600/tia.c
+++ b/sys/src/games/2600/tia.c
@@ -51,25 +51,8 @@
 	u.c[1] = c >> 8;
 	u.c[2] = c >> 16;
 	u.c[3] = 0xff;
-	p = (u32int *)pic + ppuy * PICW * scale + ppux * 2 * scale;
-	switch(scale){
-	case 16: *p++ = u.l; *p++ = u.l;
-	case 15: *p++ = u.l; *p++ = u.l;
-	case 14: *p++ = u.l; *p++ = u.l;
-	case 13: *p++ = u.l; *p++ = u.l;
-	case 12: *p++ = u.l; *p++ = u.l;
-	case 11: *p++ = u.l; *p++ = u.l;
-	case 10: *p++ = u.l; *p++ = u.l;
-	case 9: *p++ = u.l; *p++ = u.l;
-	case 8: *p++ = u.l; *p++ = u.l;
-	case 7: *p++ = u.l; *p++ = u.l;
-	case 6: *p++ = u.l; *p++ = u.l;
-	case 5: *p++ = u.l; *p++ = u.l;
-	case 4: *p++ = u.l; *p++ = u.l;
-	case 3: *p++ = u.l; *p++ = u.l;
-	case 2: *p++ = u.l; *p++ = u.l;
-	default: *p++ = u.l; *p = u.l;
-	}
+	p = (u32int *)pic + ppuy * PICW + ppux * 2;
+	p[0] = p[1] = u.l;
 }
 
 static void
--- a/sys/src/games/c64/vic.c
+++ b/sys/src/games/c64/vic.c
@@ -100,7 +100,7 @@
 	u8int c;
 	u32int *q;
 
-	q = (u32int *)pic + picidx * scale;
+	q = (u32int *)pic + picidx;
 	for(i = 0; i < n; i++){
 		c = p >> 56;
 		p <<= 8;
@@ -108,24 +108,7 @@
 		u.c[1] = cg[c];
 		u.c[2] = cr[c];
 		u.c[3] = 0;
-		switch(scale){
-		case 16: *q++ = u.l;
-		case 15: *q++ = u.l;
-		case 14: *q++ = u.l;
-		case 13: *q++ = u.l;
-		case 12: *q++ = u.l;
-		case 11: *q++ = u.l;
-		case 10: *q++ = u.l;
-		case 9: *q++ = u.l;
-		case 8: *q++ = u.l;
-		case 7: *q++ = u.l;
-		case 6: *q++ = u.l;
-		case 5: *q++ = u.l;
-		case 4: *q++ = u.l;
-		case 3: *q++ = u.l;
-		case 2: *q++ = u.l;
-		default: *q++ = u.l;
-		}
+		*q++ = u.l;
 	}
 	picidx += n;
 }
--- a/sys/src/games/eui.c
+++ b/sys/src/games/eui.c
@@ -23,7 +23,7 @@
 static ulong vwchan;
 static Image *fb;
 static Channel *conv, *sync[2];
-static uchar *screenconv[2];
+static uchar *screenconv[2], *backfb;
 static int screenconvi;
 
 struct Kfn{
@@ -48,6 +48,16 @@
 	return v;
 }
 
+Image *
+eallocimage(Rectangle r, ulong chan, int repl, ulong col)
+{
+	Image *i;
+
+	if((i = allocimage(display, r, chan, repl, col)) == nil)
+		sysfatal("allocimage: %r");
+	return i;
+}
+
 static void
 joyproc(void *)
 {
@@ -206,14 +216,13 @@
 	picr = Rpt(subpt(p, Pt(scale * vwdx/2, scale * vwdy/2)),
 		addpt(p, Pt(scale * vwdx/2, scale * vwdy/2)));
 	freeimage(fb);
-	fb = allocimage(display, Rect(0, 0, scale * vwdx, scale > 1 ? 1 : scale * vwdy),
+	fb = eallocimage(Rect(0, 0, scale * vwdx, scale > 1 ? 1 : vwdy),
 		vwchan, scale > 1, 0);
-	free(pic);
-	pic = emalloc(vwdx * vwdy * vwbpp * scale);
-	free(screenconv[0]);
-	free(screenconv[1]);
-	screenconv[0] = emalloc(vwdx * vwdy * vwbpp * scale);
-	screenconv[1] = emalloc(vwdx * vwdy * vwbpp * scale);
+	free(backfb);
+	if(scale > 1)
+		backfb = emalloc(vwdx * vwbpp * scale);
+	else
+		backfb = nil;
 	draw(screen, screen->r, bg, nil, ZP);
 	recv(sync[1], nil);
 }
@@ -254,15 +263,44 @@
 			draw(screen, picr, fb, nil, ZP);
 		} else {
 			Rectangle r;
-			uchar *s;
-			int w;
-	
-			s = p;
+			int w, x;
+
 			r = picr;
 			w = vwdx * vwbpp * scale;
 			while(r.min.y < picr.max.y){
-				loadimage(fb, fb->r, s, w);
-				s += w;
+				switch(vwbpp){
+				case 4: {
+					u32int *d = (u32int *)backfb, *e, s;
+					for(x=0; x<vwdx; x++){
+						s = *(u32int *)p;
+						p += vwbpp;
+						e = d + scale;
+						while(d < e)
+							*d++ = s;
+					}
+					break;
+				} case 2: {
+					u16int *d = (u16int *)backfb, *e, s;
+					for(x=0; x<vwdx; x++){
+						s = *(u16int *)p;
+						p += vwbpp;
+						e = d + scale;
+						while(d < e)
+							*d++ = s;
+					}
+					break;
+				} case 1: {
+					u8int *d = (u8int *)backfb, *e, s;
+					for(x=0; x<vwdx; x++){
+						s = *(u8int *)p;
+						p += vwbpp;
+						e = d + scale;
+						while(d < e)
+							*d++ = s;
+					}
+					break;
+				}}
+				loadimage(fb, fb->r, backfb, w);
 				r.max.y = r.min.y+scale;
 				draw(screen, r, fb, nil, ZP);
 				r.min.y = r.max.y;
@@ -286,7 +324,7 @@
 void
 flushscreen(void)
 {
-	memmove(screenconv[screenconvi], pic, vwdx * vwdy * vwbpp * scale);
+	memmove(screenconv[screenconvi], pic, vwdx * vwdy * vwbpp);
 	if(sendp(conv, screenconv[screenconvi]) > 0)
 		screenconvi = (screenconvi + 1) % 2;
 	if(profile)
@@ -365,11 +403,14 @@
 		proccreate(kproc != nil ? kproc : keyproc, nil, mainstacksize);
 	if(kproc == nil)
 		proccreate(joyproc, nil, mainstacksize);
-	bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF);
+	bg = eallocimage(Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF);
 	scale = fixscale;
 	conv = chancreate(sizeof(uchar*), 0);
 	sync[0] = chancreate(1, 0);
 	sync[1] = chancreate(1, 0);
 	proccreate(screenproc, nil, mainstacksize);
+	pic = emalloc(vwdx * vwdy * vwbpp);
+	screenconv[0] = emalloc(vwdx * vwdy * vwbpp);
+	screenconv[1] = emalloc(vwdx * vwdy * vwbpp);
 	screeninit();
 }
--- a/sys/src/games/gb/ppu.c
+++ b/sys/src/games/gb/ppu.c
@@ -63,7 +63,7 @@
 			}
 		ppux = 0;
 		ppux0 = 0;
-		picp = (u32int*)pic + ppuy * PICW * scale;
+		picp = (u32int*)pic + ppuy * PICW;
 		y = ppuy + reg[SCY] << 1 & 14;
 		ta = 0x1800 | reg[LCDC] << 7 & 0x400 | ppuy + reg[SCY] << 2 & 0x3e0 | reg[SCX] >> 3;
 		x = -(reg[SCX] & 7);
@@ -197,7 +197,7 @@
 	int x, x1;
 	u16int chr;
 	
-	picp = (u32int*)pic + ppuy * PICW * scale;
+	picp = (u32int*)pic + ppuy * PICW;
 	for(q = spr; q < sprm; q++){
 		if(q->x <= ppux0 || q->x >= ppux + 8)
 			continue;
@@ -251,38 +251,6 @@
 	return t*2;
 }
 
-static void
-lineexpand(void)
-{
-	u32int *picp, *p, *q, l;
-	int i;
-
-	picp = (u32int*)pic + ppuy * PICW * scale;
-	p = picp + PICW;
-	q = picp + PICW * scale;
-	for(i = PICW; --i >= 0; ){
-		l = *--p;
-		switch(scale){
-		case 16: *--q = l;
-		case 15: *--q = l;
-		case 14: *--q = l;
-		case 13: *--q = l;
-		case 12: *--q = l;
-		case 11: *--q = l;
-		case 10: *--q = l;
-		case 9: *--q = l;
-		case 8: *--q = l;
-		case 7: *--q = l;
-		case 6: *--q = l;
-		case 5: *--q = l;
-		case 4: *--q = l;
-		case 3: *--q = l;
-		case 2: *--q = l;
-		case 1: *--q = l;
-		}
-	}
-}
-
 void
 hblanktick(void *)
 {
@@ -336,8 +304,6 @@
 		ppusync();
 		if(!done) print("not done?!\n");
 		done = 0;
-		if(scale > 1)
-			lineexpand();
 		ppustate = 0;
 		if((reg[STAT] & IRQM0) != 0)
 			reg[IF] |= IRQLCDS;
--- a/sys/src/games/gba/ppu.c
+++ b/sys/src/games/gba/ppu.c
@@ -699,7 +699,7 @@
 	union { u16int w; u8int b[2]; } u;
 	int n;
 
-	q = pic + y * 240 * 2 * scale;
+	q = pic + y * 240 * 2;
 	r = (u16int*)q;
 	n = 240;
 	while(n--){
@@ -706,24 +706,7 @@
 		v = *p++;
 		u.b[0] = v;
 		u.b[1] = v >> 8;
-		switch(scale){
-		case 16: *r++ = u.w;
-		case 15: *r++ = u.w;
-		case 14: *r++ = u.w;
-		case 13: *r++ = u.w;
-		case 12: *r++ = u.w;
-		case 11: *r++ = u.w;
-		case 10: *r++ = u.w;
-		case 9: *r++ = u.w;
-		case 8: *r++ = u.w;
-		case 7: *r++ = u.w;
-		case 6: *r++ = u.w;
-		case 5: *r++ = u.w;
-		case 4: *r++ = u.w;
-		case 3: *r++ = u.w;
-		case 2: *r++ = u.w;
-		default: *r++ = u.w;
-		}
+		*r++ = u.w;
 	}
 }
 
--- a/sys/src/games/md/vdp.c
+++ b/sys/src/games/md/vdp.c
@@ -32,29 +32,11 @@
 	u32int *p;
 	union { u32int l; u8int b[4]; } u;
 
-	p = (u32int *)pic + (x + y * 320) * scale;
 	u.b[0] = v >> 16;
 	u.b[1] = v >> 8;
 	u.b[2] = v;
 	u.b[3] = 0;
-	switch(scale){
-	case 16: *p++ = u.l;
-	case 15: *p++ = u.l;
-	case 14: *p++ = u.l;
-	case 13: *p++ = u.l;
-	case 12: *p++ = u.l;
-	case 11: *p++ = u.l;
-	case 10: *p++ = u.l;
-	case 9: *p++ = u.l;
-	case 8: *p++ = u.l;
-	case 7: *p++ = u.l;
-	case 6: *p++ = u.l;
-	case 5: *p++ = u.l;
-	case 4: *p++ = u.l;
-	case 3: *p++ = u.l;
-	case 2: *p++ = u.l;	/* intla ignored */
-	default: *p = u.l;
-	}
+	*((u32int *)pic + (x + y * 320)) = u.l;
 }
 
 static u32int
--- a/sys/src/games/nes/ppu.c
+++ b/sys/src/games/nes/ppu.c
@@ -13,7 +13,6 @@
 pixel(int x, int y, int val, int back)
 {
 	union { u8int c[4]; u32int l; } u;
-	u32int *p;
 	static u8int palred[64] = {
 		0x7C, 0x00, 0x00, 0x44, 0x94, 0xA8, 0xA8, 0x88, 
 		0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
@@ -49,31 +48,13 @@
 	u.c[1] = palgreen[val];
 	u.c[2] = palred[val];
 	u.c[3] = back ? 0 : 0xFF;
-	p = (u32int *)pic + y * 256 * scale + x * scale;
-	switch(scale){
-	case 16: *p++ = u.l;
-	case 15: *p++ = u.l;
-	case 14: *p++ = u.l;
-	case 13: *p++ = u.l;
-	case 12: *p++ = u.l;
-	case 11: *p++ = u.l;
-	case 10: *p++ = u.l;
-	case 9: *p++ = u.l;
-	case 8: *p++ = u.l;
-	case 7: *p++ = u.l;
-	case 6: *p++ = u.l;
-	case 5: *p++ = u.l;
-	case 4: *p++ = u.l;
-	case 3: *p++ = u.l;
-	case 2: *p++ = u.l;
-	default: *p = u.l;
-	}
+	*((u32int *)pic + y * 256 + x) = u.l;
 }
 
 static int
 iscolor(int x, int y)
 {
-	return pic[(scale * 4) * (y * 256 + x) + 3] != 0;
+	return pic[4 * (y * 256 + x) + 3] != 0;
 }
 
 static int
--- a/sys/src/games/snes/ppu.c
+++ b/sys/src/games/snes/ppu.c
@@ -40,32 +40,13 @@
 static void
 pixeldraw(int x, int y, u16int v, int s)
 {
-	u16int *p;
 	union { u16int w; u8int b[2]; } u;
 
 	if(bright != 0xf && s >= 0)
 		v = darken(v);
-	p = (u16int *)pic + (x + y * 256) * scale;
 	u.b[0] = v;
 	u.b[1] = v >> 8;
-	switch(scale){
-	case 16: *p++ = u.w;
-	case 15: *p++ = u.w;
-	case 14: *p++ = u.w;
-	case 13: *p++ = u.w;
-	case 12: *p++ = u.w;
-	case 11: *p++ = u.w;
-	case 10: *p++ = u.w;
-	case 9: *p++ = u.w;
-	case 8: *p++ = u.w;
-	case 7: *p++ = u.w;
-	case 6: *p++ = u.w;
-	case 5: *p++ = u.w;
-	case 4: *p++ = u.w;
-	case 3: *p++ = u.w;
-	case 2: if(s < 1) *p++ = u.w;
-	default: *p = u.w;
-	}
+	*((u16int *)pic + (x + y * 256)) = u.w;
 }
 
 static int
--