272 lines · 5.2 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <draw.h>#include <stdio.h>#include <ctype.h>#include "dat.h"#include "fns.h" refexport_t re;	/* exported functions from refresh DLL */int resized, dumpwin;Point center;Rectangle grabr; static int rwon;static uchar *fb, *fbs;static Image *fbi;static s32int fbpal[256];static int scale = 1;static Rectangle fbr; refexport_t GetRefAPI(refimport_t);  static voidscalefb(void){	int i, dy, *p, c, *s; 	if(scale < 2)		return;	p = (s32int *)fbs;	s = (s32int *)fb;	dy = vid.width * vid.height;	if(scale > 16){		while(dy-- > 0){			c = *s++;			for(i=0; i<scale; i++)				*p++ = c;		}		return;	}	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 voiddrawfb(void){	uchar *s;	int n, we, w8, wr, *d, dy; 	we = vid.width - 1;	w8 = vid.width + 7 >> 3;	wr = vid.width % 8;	dy = vid.height * vid.rowbytes;	while((dy -= vid.rowbytes) >= 0){		s = fb + dy;		d = ((int *)s) + we;		s += we;		n = w8;		switch(wr){		case 0:	do{	*d-- = fbpal[*s--];		case 7:		*d-- = fbpal[*s--];		case 6:		*d-- = fbpal[*s--];		case 5:		*d-- = fbpal[*s--];		case 4:		*d-- = fbpal[*s--];		case 3:		*d-- = fbpal[*s--];		case 2:		*d-- = fbpal[*s--];		case 1:		*d-- = fbpal[*s--];			}while(--n > 0);		}	}} /* only exists to allow taking tear-free screenshots ingame... */static intwritebit(void){	int n, fd;	char *s; 	mkdir(va("%s/scrnshot", ri.FS_Gamedir()));	s = va("%s/scrnshot/quake.%d.bit", ri.FS_Gamedir(), time(nil));	if(access(s, AEXIST) != -1){		fprint(2, "writebit: not overwriting %s\n", s);		return -1;	}	if(fd = create(s, OWRITE, 0644), fd < 0)		return -1;	n = writeimage(fd, fbi, 0);	close(fd);	if(n >= 0)		ri.Con_Printf(PRINT_ALL, "Wrote %s\n", s);	return n;} static voidsetscale(void){	int f;	char *s, *p; 	if(Cmd_Argc() < 2){		Com_Printf("scale f: set integer downscaling factor\n");		return;	}	s = Cmd_Argv(1);	f = strtol(s, &p, 10);	if(p == s || f <= 1 || Dx(screen->r) / f < 1 || Dy(screen->r) / f < 1){		Com_Printf("scaling disabled\n");		if(scale != 1){			resized = 1;			scale = 1;		}		return;	}	if(scale == f)		return;	scale = f;	resized = 1;} static voidresetfb(void){	Point p; 	vid.width = Dx(screen->r) / scale;	vid.height = Dy(screen->r) / scale;	vid.rowbytes = vid.width * sizeof *fbpal;	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));	free(fb);	freeimage(fbi);	if((fbi = allocimage(display,		Rect(0, 0, vid.width * scale, scale > 1 ? 1 : vid.height),		XRGB32, scale > 1, 0)) == nil)		sysfatal("resetfb: %r");	fb = emalloc(vid.rowbytes * vid.height);	if(scale > 1){		free(fbs);		fbs = emalloc(vid.rowbytes * scale * vid.height);	}	vid.buffer = fb;	draw(screen, screen->r, display->black, nil, ZP);	sw_mode->modified = true;	/* make ref_soft refresh its shit */} voidflipfb(void){	uchar *p;	Rectangle r; 	if(resized){		resized = 0;		if(getwindow(display, Refnone) < 0)			sysfatal("getwindow: %r\n");		resetfb();		return;	}	drawfb();	scalefb();	if(scale == 1){		loadimage(fbi, Rect(0,0,vid.width,vid.height), fb, vid.height * vid.rowbytes);		draw(screen, Rpt(fbr.min, Pt(fbr.max.x, fbr.max.y)), fbi, nil, ZP);	}else{		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)			ri.Con_Printf(PRINT_ALL, "Could not write screenshot\n");		dumpwin = 0;	}} voidsetpal(uchar *p){	int *fp; 	if(p == nil)        	p = (uchar *)sw_state.currentpalette;	for(fp=fbpal; fp<fbpal+nelem(fbpal); p+=4)		*fp++ = p[0] << 16 | p[1] << 8 | p[2];} voidVID_Printf(int print_level, char *fmt, ...){	va_list argptr;	char msg[4096];		va_start(argptr, fmt);	vsprintf(msg, fmt, argptr);	va_end(argptr);	if(print_level == PRINT_ALL)		Com_Printf("%s", msg);	else		Com_DPrintf("%s", msg);} voidVID_Error(int err_level, char *fmt, ...){	va_list argptr;	char msg[4096];		va_start(argptr, fmt);	vsprintf(msg, fmt, argptr);	va_end(argptr);	Com_Error(err_level, "%s", msg);} voidinitfb(void){	refimport_t ri; 	if(initdraw(nil, nil, "quake2") < 0)		sysfatal("VID_Init:initdraw: %r\n");	vidref_val = VIDREF_SOFT;	ri.Cmd_AddCommand = Cmd_AddCommand;	ri.Cmd_RemoveCommand = Cmd_RemoveCommand;	ri.Cmd_Argc = Cmd_Argc;	ri.Cmd_Argv = Cmd_Argv;	ri.Cmd_ExecuteText = Cbuf_ExecuteText;	ri.Con_Printf = VID_Printf;	ri.Sys_Error = VID_Error;	ri.FS_LoadFile = FS_LoadFile;	ri.FS_FreeFile = FS_FreeFile;	ri.FS_Gamedir = FS_Gamedir;	ri.Cvar_Get = Cvar_Get;	ri.Cvar_Set = Cvar_Set;	ri.Cvar_SetValue = Cvar_SetValue;	ri.Vid_MenuInit = VID_MenuInit; 	re = GetRefAPI(ri);	re.Init();	Cmd_AddCommand("v_scale", setscale);	resetfb();}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t