shithub: qk1

Download patch

ref: a6ffb6a8ffefb4806f659ae05d730eaa6f486191
parent: 07d119a17d5ebc9245470fb3d16c40f31e6745e5
author: Konstantinn Bonnet <[email protected]>
date: Tue Oct 6 01:50:31 EDT 2015

fix writing pcx screenshots from the wrong data

having this superfluous code sucks, but screenshots written with rio have
tearing.

--- a/screen.c
+++ b/screen.c
@@ -45,6 +45,8 @@
 
 qboolean	block_drawing;
 
+static int writepcx;
+
 void SCR_ScreenShot_f (void);
 
 /*
@@ -503,134 +505,96 @@
  
 ============================================================================== 
 */ 
- 
 
-typedef struct
-{
-    char	manufacturer;
-    char	version;
-    char	encoding;
-    char	bits_per_pixel;
-    unsigned short	xmin,ymin,xmax,ymax;
-    unsigned short	hres,vres;
-    unsigned char	palette[48];
-    char	reserved;
-    char	color_planes;
-    unsigned short	bytes_per_line;
-    unsigned short	palette_type;
-    char	filler[58];
-    unsigned char	data;			// unbounded
-} pcx_t;
+void
+SCR_ScreenShot_f(void) 
+{ 
+	writepcx++;
+}
 
-/* 
-============== 
-WritePCXfile 
-============== 
-*/ 
-void WritePCXfile (char *filename, byte *data, int width, int height,
-	int rowbytes, byte *palette) 
+static void
+pcxout(char *path, byte *src, int dx, int dy, int xlen, byte *pal)
 {
-	int		i, j, length;
-	pcx_t	*pcx;
-	byte		*pack;
-	  
-	pcx = Hunk_TempAlloc (width*height*2+1000);
-	if (pcx == nil)
-	{
-		Con_Printf("SCR_ScreenShot_f: not enough memory\n");
+	int i, j;
+	uchar *buf, *p;
+
+	if((buf = Hunk_TempAlloc(dx * dy * 2 + 1000)) == nil){
+		Con_Printf("writepcx: not enough memory\n");
 		return;
-	} 
- 
-	pcx->manufacturer = 0x0a;	// PCX id
-	pcx->version = 5;			// 256 color
- 	pcx->encoding = 1;		// uncompressed
-	pcx->bits_per_pixel = 8;		// 256 color
-	pcx->xmin = 0;
-	pcx->ymin = 0;
-	pcx->xmax = LittleShort((short)(width-1));
-	pcx->ymax = LittleShort((short)(height-1));
-	pcx->hres = LittleShort((short)width);
-	pcx->vres = LittleShort((short)height);
-	memset(pcx->palette, 0, sizeof pcx->palette);
-	pcx->color_planes = 1;		// chunky image
-	pcx->bytes_per_line = LittleShort((short)width);
-	pcx->palette_type = LittleShort(2);		// not a grey scale
-	memset(pcx->filler, 0, sizeof pcx->filler);
+	}
+	p = buf;
 
-// pack the image
-	pack = &pcx->data;
-	
-	for (i=0 ; i<height ; i++)
-	{
-		for (j=0 ; j<width ; j++)
-		{
-			if ( (*data & 0xc0) != 0xc0)
-				*pack++ = *data++;
-			else
-			{
-				*pack++ = 0xc1;
-				*pack++ = *data++;
+	/* pcx header */
+	memset(p, 0, 128);
+	p[0] = 0x0a;
+	p[1] = 5;	/* version: 24bit pcx */
+	p[2] = 1;
+	p[3] = 8;	/* bits per pixel */
+	p[8] = dx - 1;
+	p[9] = dx - 1 >> 8;
+	p[10] = dy - 1;
+	p[11] = dy - 1 >> 8;
+	p[12] = dx;	/* HDpi and VDpi */
+	p[13] = dx >> 8;
+	p[14] = dy;
+	p[15] = dy >> 8;
+	p[65] = 1;	/* number of color planes */
+	p[66] = dx;	/* scanline length */
+	p[67] = dx >> 8;
+	p[68] = 2;	/* palette type: not-greyscale greyscale */
+
+	p = buf + 128;
+	for(i=0; i<dy; i++){
+		for(j=0; j<dx; j++){
+			if((*src & 0xc0) != 0xc0)
+				*p++ = *src++;
+			else{
+				*p++ = 0xc1;
+				*p++ = *src++;
 			}
 		}
-
-		data += rowbytes - width;
+		src += xlen - dx;
 	}
-	
-// write the palette
-	*pack++ = 0x0c;	// palette ID byte
-	for (i=0 ; i<768 ; i++)
-		*pack++ = *palette++;
-		
-// write output file 
-	length = pack - (byte *)pcx;
-	COM_WriteFile (filename, pcx, length);
+
+	/* palette */
+	*p++ = 0x0c;
+	for(i=0; i<3*256; i++)
+		*p++ = *pal++;
+
+	COM_WriteFile(path, buf, p - buf);
 } 
- 
 
+static void
+dopcx(void)
+{
+	int i; 
+	char pcxname[12], checkname[MAX_OSPATH];
 
-/* 
-================== 
-SCR_ScreenShot_f
-================== 
-*/  
-void SCR_ScreenShot_f (void) 
-{ 
-	int     i; 
-	char		pcxname[80]; 
-	char		checkname[MAX_OSPATH];
+	writepcx = 0;
 
-// 
-// find a file name to save it to 
-// 
-	strcpy(pcxname,"quake00.pcx");
-		
-	for (i=0 ; i<=99 ; i++) 
-	{ 
-		pcxname[5] = i/10 + '0'; 
-		pcxname[6] = i%10 + '0'; 
-		sprint (checkname, "%s/%s", com_gamedir, pcxname);
+	/* find a file name to save it to */
+	strcpy(pcxname, "quake00.pcx");
+	for(i=0; i<100; i++){
+		pcxname[5] = i / 10 + '0';
+		pcxname[6] = i % 10 + '0';
+		sprint(checkname, "%s/%s", com_gamedir, pcxname);
 		if(access(checkname, AEXIST) == -1)
 			break;
-	} 
-	if (i==100) 
-	{
-		Con_Printf ("SCR_ScreenShot_f: Couldn't create a PCX file\n"); 
+	}
+	if(i == 100){
+		Con_Printf("dopcx: no free slots\n"); 
 		return;
  	}
 
-// 
-// save the pcx file 
-// 
-	D_EnableBackBufferAccess ();	// enable direct drawing of console to back
-									//  buffer
+	/* save the pcx file */
+	D_EnableBackBufferAccess();
+	pcxout(pcxname, vid.buffer, vid.width, vid.height, vid.rowbytes,
+		host_basepal);
+	/* for adapters that can't stay mapped in for linear writes all the
+	 * time */
+	D_DisableBackBufferAccess();
 
-	WritePCXfile (pcxname, vid.buffer, vid.width, vid.height, vid.rowbytes,
-				  host_basepal);
-
-	D_DisableBackBufferAccess ();	// for adapters that can't stay mapped in
-									//  for linear writes all the time
-
-	Con_Printf ("Wrote %s\n", pcxname);
+	Con_Printf("Wrote %s\n", pcxname);
 } 
 
 
@@ -924,6 +888,10 @@
 	}
 
 	V_UpdatePalette ();
+
+	/* needs to be done before vid.buffer is transformed in st3_fixup */
+	if(writepcx)
+		dopcx();
 
 //
 // update one of three areas