.po support for qc.

rewrote messagemode to support utf8 properly, as well as left-arrow etc keys.
support for mouse-over images on console links and stuff.
added r_lerpmuzzlehack for certain viewmodels.
use libtool's dlopen stuff on cygwin to try to cover some cygwin path differences.
try to support utf-8 in filenames even in windows (only in nt, 9x is still ascii only).
added certificate validation for gnutls. gnutls now enabled by default in linux.
d3d11 tweaks. shadowmapping works.
tweaks for updated terrain format, to try to fix some inefficiencies/limitations.
xmpp plugin can now display avatars (xmpp /set avatars 1)
xmpp file transfers supported by default, but capability is disabled by default (can be enabled by hacking config).

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4523 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2013-11-21 23:02:28 +00:00
parent 84315e641d
commit f08489f141
104 changed files with 8039 additions and 4088 deletions

View File

@ -226,13 +226,13 @@ endif
ifeq ($(FTE_TARGET),) #user didn't specify prefered target
ifneq ($(shell $(CC) -v 2>&1 | grep mingw),)
FTE_TARGET=win32
endif
ifneq ($(shell $(CC) -v 2>&1 | grep cygwin),)
ifneq ($(shell uname 2>&1 | grep CYGWIN),)
FTE_TARGET=cygwin
ANDROID_SCRIPT=android.bat
endif
ifneq ($(shell $(CC) -v 2>&1 | grep mingw),)
FTE_TARGET=win32
endif
ifeq ($(FTE_TARGET),) #still not set
ifeq ($(shell uname),Linux)
@ -256,7 +256,7 @@ ifeq ($(FTE_TARGET),) #user didn't specify prefered target
#else I've no idea what it is you're running
endif
FTE_TARGET ?= sdl #so go for sdl.
FTE_TARGET ?= unk #so go for sdl.
endif
ifneq ($(shell ls|grep config.h),)
@ -323,22 +323,22 @@ ifeq ($(FTE_TARGET),macosx)
endif
BASELDFLAGS ?= -lm -ldl -lpthread
ifeq ($(shell echo $(FTE_TARGET)|grep -v win),)
BASELDFLAGS=-lm
MINGW_LIBS_DIR=$(LIBS_DIR)/mingw-libs
ifeq ($(shell echo $(FTE_TARGET)|grep -v win64),)
MINGW_LIBS_DIR=$(LIBS_DIR)/mingw64-libs
endif
IMAGELDFLAGS=$(MINGW_LIBS_DIR)/libpng.a $(MINGW_LIBS_DIR)/libz.a $(MINGW_LIBS_DIR)/libjpeg.a
OGGVORBISLDFLAGS=$(MINGW_LIBS_DIR)/libvorbisfile.a $(MINGW_LIBS_DIR)/libvorbis.a $(MINGW_LIBS_DIR)/libogg.a
ifeq ($(shell echo $(FTE_TARGET)|grep -v -i _SDL),)
RELEASE_CFLAGS+= -D_SDL
SDL_LDFLAGS=$(MINGW_LIBS_DIR)/libSDL.a $(MINGW_LIBS_DIR)/libSDLmain.a -L./libs/mingw64-libs
endif
endif
#ifeq ($(shell echo $(FTE_TARGET)|grep -v win),)
# BASELDFLAGS=-lm
# MINGW_LIBS_DIR=$(LIBS_DIR)/mingw-libs
#
# ifeq ($(shell echo $(FTE_TARGET)|grep -v win64),)
# MINGW_LIBS_DIR=$(LIBS_DIR)/mingw64-libs
# endif
#
# IMAGELDFLAGS=$(MINGW_LIBS_DIR)/libpng.a $(MINGW_LIBS_DIR)/libz.a $(MINGW_LIBS_DIR)/libjpeg.a
# OGGVORBISLDFLAGS=$(MINGW_LIBS_DIR)/libvorbisfile.a $(MINGW_LIBS_DIR)/libvorbis.a $(MINGW_LIBS_DIR)/libogg.a
#
# ifeq ($(shell echo $(FTE_TARGET)|grep -v -i _SDL),)
# RELEASE_CFLAGS+= -D_SDL
# SDL_LDFLAGS=$(MINGW_LIBS_DIR)/libSDL.a $(MINGW_LIBS_DIR)/libSDLmain.a -L./libs/mingw64-libs
# endif
#endif
IMAGELDFLAGS ?= -lpng -ljpeg
OGGVORBISLDFLAGS ?= -lvorbisfile -lvorbis -logg
@ -617,6 +617,7 @@ COMMON_OBJS = \
log.o \
net_chan.o \
net_wins.o \
net_ice.o \
zone.o \
qvm.o \
r_d3.o \
@ -1101,20 +1102,20 @@ ifeq ($(FTE_TARGET),cygwin)
GLCL_OBJS=$(GL_OBJS) $(D3DGL_OBJS) $(GLQUAKE_OBJS) $(BOTLIB_OBJS) $(SPEEX_OBJS) gl_vidlinuxglx.o snd_linux.o cd_null.o sys_linux.o sys_linux_threads.o
GL_EXE_NAME=../fteqwglcyg$(EXEPOSTFIX)
GLCL_EXE_NAME=../fteqwclglcyg$(EXEPOSTFIX)
GL_LDFLAGS=$(GLLDFLAGS) $(XLDFLAGS) $(OGGVORBISLDFLAGS)
GL_CFLAGS=$(GLCFLAGS) -I/usr/X11R6/include $(SPEEXCFLAGS) -DLIBVORBISFILE_STATIC
GL_LDFLAGS=$(GLLDFLAGS) $(XLDFLAGS) $(OGGVORBISLDFLAGS) -lz -lltdl
GL_CFLAGS=$(GLCFLAGS) -I/usr/X11R6/include $(SPEEXCFLAGS) -DLIBVORBISFILE_STATIC -DUSE_LIBTOOL
GLB_DIR=gl_cygwin
GLCL_DIR=glcl_cygwin
MCL_OBJS=$(D3DGL_OBJS) $(GLQUAKE_OBJS) $(SOFTWARE_OBJS) $(BOTLIB_OBJS) $(SPEEX_OBJS) gl_vidlinuxglx.o snd_linux.o cd_null.o sys_linux.o sys_linux_threads.o
M_EXE_NAME=../fteqwcyg$(EXEPOSTFIX)
MCL_EXE_NAME=../fteqwclcyg$(EXEPOSTFIX)
M_LDFLAGS=$(GLLDFLAGS) $(XLDFLAGS) $(OGGVORBISLDFLAGS)
M_CFLAGS=$(GLCFLAGS) $(SPEEXCFLAGS) -DLIBVORBISFILE_STATIC
M_LDFLAGS=$(GLLDFLAGS) $(XLDFLAGS) $(OGGVORBISLDFLAGS) -lz -lltdl
M_CFLAGS=$(GLCFLAGS) $(SPEEXCFLAGS) -DLIBVORBISFILE_STATIC -DUSE_LIBTOOL
MB_DIR=m_cygwin
MCL_DIR=mcl_cygwin
LIBS_DIR = $(BASE_DIR)/libs
MINGL_EXE_NAME=../fteqwminglcyg$(EXEPOSTFIX)
MINGL_DIR=mingl_cygwin

View File

@ -81,7 +81,7 @@ int CDAudio_GetAudioDiskInfo(void)
qboolean CDAudio_Startup(void)
{
DWORD dwReturn;
static MCI_OPEN_PARMS mciOpenParms;
static MCI_OPEN_PARMSA mciOpenParms;
static MCI_SET_PARMS mciSetParms;
if (initializefailed)
@ -269,6 +269,9 @@ void CDAudio_Pause(void)
DWORD dwReturn;
static MCI_GENERIC_PARMS mciGenericParms;
if (!pollneeded)
return;
mciGenericParms.dwCallback = (DWORD_PTR)mainwindow;
dwReturn = mciSendCommand(wDeviceID, MCI_PAUSE, 0, (DWORD_PTR)(LPVOID) &mciGenericParms);
if (dwReturn)

View File

@ -1797,7 +1797,7 @@ void CL_SendCmd (double frametime, qboolean mainloop)
if (cls.demorecording)
CL_WriteDemoCmd(cmd);
Con_DPrintf("generated sequence %i\n", cl.movesequence);
// Con_DPrintf("generated sequence %i\n", cl.movesequence);
cl.movesequence++;
#ifdef IRCCONNECT

View File

@ -1804,7 +1804,7 @@ void CL_FullInfo_f (void)
if (!*s)
{
Con_TPrintf (TL_KEYHASNOVALUE);
Con_Printf ("key %s has no value\n", key);
return;
}
@ -1899,7 +1899,7 @@ void CL_SetInfo_f (void)
return;
}
Con_TPrintf (TL_STARKEYPROTECTED);
Con_Printf ("Can't set * keys\n");
return;
}
@ -3458,7 +3458,7 @@ void VARGS Host_EndGame (char *message, ...)
vsnprintf (string,sizeof(string)-1, message,argptr);
va_end (argptr);
Con_TPrintf (TLC_CLIENTCON_ERROR_ENDGAME, string);
Con_TPrintf (TL_NL);
Con_Printf ("\n");
SCR_EndLoadingPlaque();
@ -4349,9 +4349,7 @@ void Host_FinishLoading(void)
CL_ArgumentOverrides();
Con_TPrintf (TL_NL);
Con_Printf ("%s", version_string());
Con_TPrintf (TL_NL);
Con_Printf ("\n%s\n", version_string());
Con_DPrintf("This program is free software; you can redistribute it and/or "
"modify it under the terms of the GNU General Public License "

View File

@ -3308,6 +3308,7 @@ void CL_ParseModellist (qboolean lots)
Host_EndGame ("Server sent too many model_precache");
strcpy (cl.model_name[nummodels], str);
//qw has a special network protocol for spikes.
if (!strcmp(cl.model_name[nummodels],"progs/spike.mdl"))
cl_spikeindex = nummodels;
if (!strcmp(cl.model_name[nummodels],"progs/player.mdl"))
@ -3319,12 +3320,13 @@ void CL_ParseModellist (qboolean lots)
if (!strcmp(cl.model_name[nummodels],"progs/flag.mdl"))
cl_flagindex = nummodels;
//rocket to grenade
if (!strcmp(cl.model_name[nummodels],"progs/missile.mdl"))
cl_rocketindex = nummodels;
if (!strcmp(cl.model_name[nummodels],"progs/grenade.mdl"))
cl_grenadeindex = nummodels;
//cl_gibfilter
if (!strcmp(cl.model_name[nummodels],"progs/gib1.mdl"))
cl_gib1index = nummodels;
if (!strcmp(cl.model_name[nummodels],"progs/gib2.mdl"))
@ -5271,7 +5273,7 @@ void CL_ParsePrecache(void)
if (!model)
Con_Printf("svc_precache: Mod_ForName(\"%s\") failed\n", s);
cl.model_precache[i] = model;
strcpy (cl.model_name[i], s);
Q_strncpyz (cl.model_name[i], s, sizeof(cl.model_name[i]));
cl.model_precaches_added = true;
}
@ -5290,7 +5292,7 @@ void CL_ParsePrecache(void)
if (!sfx)
Con_Printf("svc_precache: S_PrecacheSound(\"%s\") failed\n", s);
cl.sound_precache[i] = sfx;
strcpy (cl.sound_name[i], s);
Q_strncpyz (cl.sound_name[i], s, sizeof(cl.sound_name[i]));
}
else
Con_Printf("svc_precache: sound index %i outside range %i...%i\n", i, 1, MAX_SOUNDS);
@ -5817,10 +5819,7 @@ void CLQW_ParseServerMessage (void)
case svc_setpause:
cl.paused = MSG_ReadByte ();
if (cl.paused)
CDAudio_Pause ();
else
CDAudio_Resume ();
// Media_SetPauseTrack(!!cl.paused);
break;
// case svc_ftesetclientpersist:

View File

@ -70,16 +70,17 @@ typedef struct {
//Make SURE that the engine has resolved all cvar pointers into globals before this happens.
plugin_t *plugin;
char name[64];
qboolean picfromwad;
int type;
char *script;
mpic_t *pic;
} pluginimagearray_t;
int pluginimagearraylen;
pluginimagearray_t *pluginimagearray;
qintptr_t VARGS Plug_Draw_LoadImage(void *offset, quintptr_t mask, const qintptr_t *arg)
#include "shader.h"
qintptr_t VARGS Plug_Draw_LoadImage(char *name, int type, char *script)
{
char *name = VM_POINTER(arg[0]);
qboolean fromwad = arg[1];
int i;
mpic_t *pic;
@ -109,7 +110,11 @@ qintptr_t VARGS Plug_Draw_LoadImage(void *offset, quintptr_t mask, const qintptr
if (qrenderer != QR_NONE)
{
if (fromwad)
if (type == 3)
pic = NULL;
else if (type == 2)
pic = R_RegisterShader(name, SUF_NONE, script);
else if (type)
pic = R2D_SafePicFromWad(name);
else
pic = R2D_SafeCachePic(name);
@ -118,12 +123,59 @@ qintptr_t VARGS Plug_Draw_LoadImage(void *offset, quintptr_t mask, const qintptr
pic = NULL;
Q_strncpyz(pluginimagearray[i].name, name, sizeof(pluginimagearray[i].name));
pluginimagearray[i].picfromwad = fromwad;
pluginimagearray[i].type = type;
pluginimagearray[i].pic = pic;
pluginimagearray[i].plugin = currentplug;
pluginimagearray[i].script = script?Z_StrDup(script):NULL;
return i + 1;
}
qbyte *Read32BitImageFile(qbyte *buf, int len, int *width, int *height, qboolean *hasalpha, char *fname);
qintptr_t VARGS Plug_Draw_LoadImageData(void *offset, quintptr_t mask, const qintptr_t *arg)
{
qintptr_t ret = 0;
char *name = VM_POINTER(arg[0]);
char *mimetype = VM_POINTER(arg[1]);
void *codeddata = VM_POINTER(arg[2]);
unsigned int datalength = VM_LONG(arg[3]);
texid_t t;
qbyte *rgbdata;
unsigned int width, height;
if (VM_OOB(arg[2], arg[3]))
return 0;
if ((rgbdata = Read32BitImageFile(codeddata, datalength, &width, &height, NULL, name)))
{
name = va("%s/", name);
t = R_FindTexture(name, IF_NOMIPMAP|IF_UIPIC|IF_CLAMP);
if (!TEXVALID(t))
t = R_AllocNewTexture(name, width, height, IF_NOMIPMAP|IF_UIPIC|IF_CLAMP);
if (TEXVALID(t))
{
R_Upload(t, name, TF_RGBA32, rgbdata, NULL, width, height, IF_NOMIPMAP|IF_UIPIC|IF_CLAMP);
ret = Plug_Draw_LoadImage(name, 3, NULL);
}
BZ_Free(rgbdata);
}
return ret;
}
qintptr_t VARGS Plug_Draw_LoadImageShader(void *offset, quintptr_t mask, const qintptr_t *arg)
{
char *name = VM_POINTER(arg[0]);
char *script = VM_POINTER(arg[1]);
return Plug_Draw_LoadImage(name, 2, script);
}
qintptr_t VARGS Plug_Draw_LoadImagePic(void *offset, quintptr_t mask, const qintptr_t *arg)
{
char *name = VM_POINTER(arg[0]);
int type = arg[1];
if (type != 0 && type != 1)
return 0;
return Plug_Draw_LoadImage(name, type, NULL);
}
void Plug_DrawReloadImages(void)
{
int i;
@ -172,7 +224,7 @@ qintptr_t VARGS Plug_Draw_Image(void *offset, quintptr_t mask, const qintptr_t *
if (pluginimagearray[i].pic)
pic = pluginimagearray[i].pic;
else if (pluginimagearray[i].picfromwad)
else if (pluginimagearray[i].type == 1)
return 0; //wasn't loaded.
else
{
@ -214,6 +266,29 @@ qintptr_t VARGS Plug_Draw_Character(void *offset, quintptr_t mask, const qintptr
Font_EndString(font_conchar);
return 0;
}
qintptr_t VARGS Plug_Draw_String(void *offset, quintptr_t mask, const qintptr_t *arg)
{
int ipx, px, py;
conchar_t buffer[2048], *str;
if (qrenderer == QR_NONE)
return 0;
COM_ParseFunString(CON_WHITEMASK, VM_POINTER(arg[2]), buffer, sizeof(buffer), false);
str = buffer;
Font_BeginString(font_conchar, VM_FLOAT(arg[0]), VM_FLOAT(arg[1]), &px, &py);
ipx = px;
while(*str)
{
if ((*str & CON_CHARMASK) == '\n')
py += Font_CharHeight();
else if ((*str & CON_CHARMASK) == '\r')
px = ipx;
else
px = Font_DrawChar(px, py, *str);
str++;
}
Font_EndString(font_conchar);
return 0;
}
qintptr_t VARGS Plug_Draw_Fill(void *offset, quintptr_t mask, const qintptr_t *arg)
{
@ -525,9 +600,12 @@ void Plug_Client_Init(void)
Plug_RegisterBuiltin("Menu_Control", Plug_Menu_Control, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("Key_GetKeyCode", Plug_Key_GetKeyCode, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("Draw_LoadImage", Plug_Draw_LoadImage, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("Draw_LoadImageData", Plug_Draw_LoadImageData, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("Draw_LoadImageShader", Plug_Draw_LoadImageShader, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("Draw_LoadImage", Plug_Draw_LoadImagePic, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("Draw_Image", Plug_Draw_Image, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("Draw_Character", Plug_Draw_Character, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("Draw_String", Plug_Draw_String, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("Draw_Fill", Plug_Draw_Fill, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("Draw_Line", Plug_Draw_Line, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("Draw_Colourp", Plug_Draw_ColourP, PLUG_BIF_NEEDSRENDERER);

View File

@ -747,7 +747,7 @@ static void CL_EntStateToPlayerCommand(usercmd_t *cmd, entity_state_t *state, fl
// extra += realtime - cl.inframes[cl.validsequence&UPDATE_MASK].receivedtime;
// extra += (cl.inframes[cl.validsequence&UPDATE_MASK].receivedtime - cl.inframes[cl.oldvalidsequence&UPDATE_MASK].receivedtime)*4;
msec = 1000*extra;
Con_DPrintf("%i: age = %i, stale=%i\n", state->number, msec, state->u.q1.msec);
// Con_DPrintf("%i: age = %i, stale=%i\n", state->number, msec, state->u.q1.msec);
msec += state->u.q1.msec; //this is the age on the server
cmd->msec = bound(0, msec, 250);

View File

@ -83,6 +83,9 @@ void Con_Finit (console_t *con)
con->selstartline = NULL;
con->selendline = NULL;
con->defaultcharbits = CON_WHITEMASK;
con->parseflags = 0;
}
/*returns a bitmask:
@ -636,7 +639,7 @@ void Con_PrintCon (console_t *con, char *txt)
conline_t *oc;
conline_t *reuse;
COM_ParseFunString(CON_WHITEMASK, txt, expanded, sizeof(expanded), false);
COM_ParseFunString(con->defaultcharbits, txt, expanded, sizeof(expanded), con->parseflags);
c = expanded;
if (*c)
@ -645,7 +648,7 @@ void Con_PrintCon (console_t *con, char *txt)
{
conchar_t *o;
switch (*c & (CON_CHARMASK))
switch (*c & (CON_CHARMASK|CON_HIDDEN))
{
case '\r':
con->cr = true;
@ -1239,13 +1242,32 @@ void Con_DrawNotify (void)
conchar_t *starts[8];
conchar_t *ends[8];
conchar_t markup[MAXCMDLINE+64];
conchar_t *c;
int lines, i;
conchar_t *c, *end;
char *foo = va(chat_team?"say_team: %s":"say: %s", chat_buffer?chat_buffer:"");
int lines, i, pos;
Font_BeginString(font_conchar, 0, 0, &x, &y);
y = con_main.notif_l * Font_CharHeight();
c = COM_ParseFunString(CON_WHITEMASK, va(chat_team?"say_team: %s":"say: %s", chat_buffer), markup, sizeof(markup), true);
*c++ = (0xe00a+((int)(realtime*con_cursorspeed)&1))|CON_WHITEMASK;
lines = Font_LineBreaks(markup, c, Font_ScreenWidth(), 8, starts, ends);
i = chat_team?10:5;
pos = strlen(foo)+i;
pos = min(pos, chat_bufferpos + i);
//figure out where the cursor is, if its safe
i = foo[pos];
foo[pos] = 0;
c = COM_ParseFunString(CON_WHITEMASK, foo, markup, sizeof(markup), PFS_KEEPMARKUP|PFS_FORCEUTF8);
foo[pos] = i;
//k, build the string properly.
end = COM_ParseFunString(CON_WHITEMASK, foo, markup, sizeof(markup) - sizeof(markup[0]), PFS_KEEPMARKUP | PFS_FORCEUTF8);
//and overwrite the cursor so that it blinks.
if (((int)(realtime*con_cursorspeed)&1))
*c = 0xe00b|CON_WHITEMASK;
if (c == end)
end++;
lines = Font_LineBreaks(markup, end, Font_ScreenWidth(), 8, starts, ends);
for (i = 0; i < lines; i++)
{
x = 0;
@ -1444,7 +1466,7 @@ int Con_DrawAlternateConsoles(int lines)
consshown++;
}
if (lines == scr_conlines && consshown > 1)
if (lines == (int)scr_conlines && consshown > 1)
{
int mx, my, h;
Font_BeginString(font_conchar, mousecursor_x, mousecursor_y, &mx, &my);
@ -1507,6 +1529,9 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in
x = (Font_DrawChar (x, y, '^'|CON_WHITEMASK)-x)*4+x;
}
if (!selactive)
selactive = 2;
//deactivate the selection if the start and end is outside
if (
(selsx < sx && selex < sx) ||
@ -1671,9 +1696,9 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in
if (y >= seley)
{
send = sstart;
for (i = 0; i < linelength; i++)
for (i = 0; i < linelength; )
{
send += Font_CharWidth(s[i]);
send += Font_CharWidth(s[i++]);
if (send > selex)
break;
@ -1681,7 +1706,7 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in
con->selendline = l;
if (s)
con->selendoffset = (s+i+1) - (conchar_t*)(l+1);
con->selendoffset = (s+i) - (conchar_t*)(l+1);
else
con->selendoffset = 0;
}
@ -1701,8 +1726,11 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in
else
con->selstartoffset = 0;
}
R2D_ImagePaletteColour(0, 1.0);
R2D_FillBlock((sstart*vid.width)/vid.rotpixelwidth, (y*vid.height)/vid.rotpixelheight, ((send - sstart)*vid.width)/vid.rotpixelwidth, (Font_CharHeight()*vid.height)/vid.rotpixelheight);
if (selactive == 1)
{
R2D_ImagePaletteColour(0, 1.0);
R2D_FillBlock((sstart*vid.width)/(float)vid.rotpixelwidth, (y*vid.height)/(float)vid.rotpixelheight, ((send - sstart)*vid.width)/(float)vid.rotpixelwidth, (Font_CharHeight()*vid.height)/(float)vid.rotpixelheight);
}
}
}
}
@ -1721,6 +1749,8 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in
return y;
}
void Draw_ExpandedString(float x, float y, conchar_t *str);
/*
================
Con_DrawConsole
@ -1795,6 +1825,57 @@ void Con_DrawConsole (int lines, qboolean noback)
}
Font_EndString(font_conchar);
if (con_current->selstartline)
{
char *mouseover = Con_CopyConsole(false, true);
if (mouseover)
{
char *end = strstr(mouseover, "^]");
char *info = strchr(mouseover, '\\');
char *key;
if (!info)
info = "";
*end = 0;
if (!Plug_ConsoleLinkMouseOver(mousecursor_x, mousecursor_y, mouseover+2, info))
{
float x = mousecursor_x+8;
float y = mousecursor_y+8;
float ih = 0;
key = Info_ValueForKey(info, "tipimg");
if (*key)
{
shader_t *s = R2D_SafeCachePic(key);
if (s)
{
R2D_Image(x, y, s->width, s->height, 0, 0, 1, 1, s);
ih = s->height;
x += s->width + 8;
}
}
key = Info_ValueForKey(info, "tip");
if (*key)
{
//FIXME: draw a proper background.
//FIXME: support line breaks.
conchar_t buffer[2048], *starts[8], *ends[8];
int lines, i, px, py;
Font_BeginString(font_conchar, x, y, &px, &py);
lines = Font_LineBreaks(buffer, COM_ParseFunString(CON_WHITEMASK|CON_NONCLEARBG, key, buffer, sizeof(buffer), false), 256, 8, starts, ends);
ih = max(Font_CharHeight()*lines, ih)/2;
y += ih - (Font_CharHeight()*lines)/2;
Font_BeginString(font_conchar, x, y, &px, &py);
for (i = 0; i < lines; i++)
{
Font_LineDraw(px, py, starts[i], ends[i]);
py += Font_CharHeight();
}
Font_EndString(font_conchar);
}
}
}
Z_Free(mouseover);
}
}
void Con_DrawOneConsole(console_t *con, struct font_s *font, float fx, float fy, float fsx, float fsy)
@ -1833,7 +1914,7 @@ void Con_DrawOneConsole(console_t *con, struct font_s *font, float fx, float fy,
}
char *Con_CopyConsole(qboolean nomarkup)
char *Con_CopyConsole(qboolean nomarkup, qboolean onlyiflink)
{
console_t *con = con_current;
conchar_t *cur;
@ -1846,9 +1927,6 @@ char *Con_CopyConsole(qboolean nomarkup)
if (!con->selstartline || !con->selendline)
return NULL;
maxlen = 1024*1024;
result = Z_Malloc(maxlen+1);
// for (cur = (conchar_t*)(selstartline+1), finalendoffset = 0; cur < (conchar_t*)(selstartline+1) + selstartline->length; cur++, finalendoffset++)
// result[finalendoffset] = *cur & 0xffff;
@ -1908,6 +1986,15 @@ char *Con_CopyConsole(qboolean nomarkup)
}
}
if (onlyiflink)
{
if (*cur != CON_LINKSTART)
return NULL;
}
maxlen = 1024*1024;
result = Z_Malloc(maxlen+1);
outlen = 0;
for (;;)
{

View File

@ -163,7 +163,7 @@ qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, qboolean *
tgaheader_t tgaheader;
if (buf[16] != 8 && buf[16] != 16 && buf[16] != 24 && buf[16] != 32)
if (length < 18 || buf[16] != 8 && buf[16] != 16 && buf[16] != 24 && buf[16] != 32)
return NULL; //BUMMER!
tgaheader.id_len = buf[0];
@ -1631,6 +1631,9 @@ qbyte *ReadPCXFile(qbyte *buf, int length, int *width, int *height)
// parse the PCX file
//
if (length < sizeof(*pcx))
return NULL;
pcx = (pcx_t *)buf;
xmin = LittleShort(pcx->xmin);
@ -2462,7 +2465,7 @@ qbyte *Read32BitImageFile(qbyte *buf, int len, int *width, int *height, qboolean
}
#ifdef AVAIL_PNGLIB
if ((buf[0] == 137 && buf[1] == 'P' && buf[2] == 'N' && buf[3] == 'G') && (data = ReadPNGFile(buf, com_filesize, width, height, fname)))
if (len > 4 && (buf[0] == 137 && buf[1] == 'P' && buf[2] == 'N' && buf[3] == 'G') && (data = ReadPNGFile(buf, len, width, height, fname)))
{
TRACE(("dbg: Read32BitImageFile: png\n"));
return data;
@ -2470,19 +2473,19 @@ qbyte *Read32BitImageFile(qbyte *buf, int len, int *width, int *height, qboolean
#endif
#ifdef AVAIL_JPEGLIB
//jpeg jfif only.
if ((buf[0] == 0xff && buf[1] == 0xd8 && buf[2] == 0xff && buf[3] == 0xe0) && (data = ReadJPEGFile(buf, com_filesize, width, height)))
if (len > 4 && (buf[0] == 0xff && buf[1] == 0xd8 && buf[2] == 0xff && buf[3] == 0xe0) && (data = ReadJPEGFile(buf, len, width, height)))
{
TRACE(("dbg: Read32BitImageFile: jpeg\n"));
return data;
}
#endif
if ((data = ReadPCXFile(buf, com_filesize, width, height)))
if ((data = ReadPCXFile(buf, len, width, height)))
{
TRACE(("dbg: Read32BitImageFile: pcx\n"));
return data;
}
if ((buf[0] == 'B' && buf[1] == 'M') && (data = ReadBMPFile(buf, com_filesize, width, height)))
if (len > 2 && (buf[0] == 'B' && buf[1] == 'M') && (data = ReadBMPFile(buf, len, width, height)))
{
TRACE(("dbg: Read32BitImageFile: bitmap\n"));
return data;
@ -2610,22 +2613,28 @@ texid_t R_LoadHiResTexture(char *name, char *subpath, unsigned int flags)
image_width = 0;
image_height = 0;
COM_StripExtension(name, nicename, sizeof(nicename));
if (flags & IF_EXACTEXTENSION)
Q_strncpyz(nicename, name, sizeof(nicename));
else
COM_StripExtension(name, nicename, sizeof(nicename));
while((data = strchr(nicename, '*')))
{
*data = '#';
}
snprintf(fname, sizeof(fname)-1, "%s/%s", subpath, name); /*should be safe if its null*/
if (subpath && *subpath && !(flags & IF_REPLACE))
if (subpath)
{
tex = R_FindTexture(fname, flags);
if (TEXVALID(tex)) //don't bother if it already exists.
snprintf(fname, sizeof(fname)-1, "%s/%s", subpath, name); /*should be safe if its null*/
if (*subpath && !(flags & IF_REPLACE))
{
image_width = tex.ref->width;
image_height = tex.ref->height;
return tex;
tex = R_FindTexture(fname, flags);
if (TEXVALID(tex)) //don't bother if it already exists.
{
image_width = tex.ref->width;
image_height = tex.ref->height;
return tex;
}
}
}
if (!(flags & IF_SUBDIRONLY) && !(flags & IF_REPLACE))
@ -2675,7 +2684,7 @@ texid_t R_LoadHiResTexture(char *name, char *subpath, unsigned int flags)
for (i = 0; i < 6; i++)
{
tex = r_nulltex;
for (e = sizeof(tex_extensions)/sizeof(tex_extensions[0])-1; e >=0 ; e--)
for (e = (flags & IF_EXACTEXTENSION)?0:sizeof(tex_extensions)/sizeof(tex_extensions[0])-1; e >=0 ; e--)
{
if (!tex_extensions[e].enabled)
continue;
@ -2751,7 +2760,7 @@ texid_t R_LoadHiResTexture(char *name, char *subpath, unsigned int flags)
{
if (!tex_path[i].enabled)
continue;
for (e = sizeof(tex_extensions)/sizeof(tex_extensions[0])-1; e >=0 ; e--)
for (e = (flags & IF_EXACTEXTENSION)?0:sizeof(tex_extensions)/sizeof(tex_extensions[0])-1; e >=0 ; e--)
{
if (!tex_extensions[e].enabled)
continue;
@ -2856,7 +2865,10 @@ texid_t R_LoadHiResTexture(char *name, char *subpath, unsigned int flags)
if (!(flags & IF_SUBDIRONLY))
{
/*still failed? attempt to load quake lmp files, which have no real format id*/
snprintf(fname, sizeof(fname)-1, "%s%s", nicename, ".lmp");
if (flags & IF_EXACTEXTENSION)
Q_strncpyz(fname, nicename, sizeof(fname));
else
snprintf(fname, sizeof(fname)-1, "%s%s", nicename, ".lmp");
if ((buf = COM_LoadFile (fname, 5)))
{
extern cvar_t vid_hardwaregamma;
@ -2865,7 +2877,7 @@ texid_t R_LoadHiResTexture(char *name, char *subpath, unsigned int flags)
{
image_width = LittleLong(((int*)buf)[0]);
image_height = LittleLong(((int*)buf)[1]);
if (image_width*image_height+8 == com_filesize)
if (image_width >= 4 && image_height >= 4 && image_width*image_height+8 == com_filesize)
{
tex = R_LoadTexture8(name, image_width, image_height, buf+8, flags, 1);
}

View File

@ -1142,7 +1142,7 @@ void INS_Init (void)
Cmd_AddCommand ("force_centerview", Force_CenterView_f);
Cmd_AddCommand ("joyadvancedupdate", Joy_AdvancedUpdate_f);
uiWheelMessage = RegisterWindowMessage ( "MSWHEEL_ROLLMSG" );
uiWheelMessage = RegisterWindowMessageA ( "MSWHEEL_ROLLMSG" );
#ifdef USINGRAWINPUT
Cvar_Register (&in_rawinput, "Input Controls");

View File

@ -457,6 +457,8 @@ qboolean Key_GetConsoleSelectionBox(console_t *con, int *sx, int *sy, int *ex, i
if (con->mousedown[2] == 1)
{
//left-mouse.
//scroll the console with the mouse. trigger links on release.
while (con->mousecursor[1] - con->mousedown[1] > 8 && con->display->older)
{
con->mousedown[1] += 8;
@ -476,13 +478,22 @@ qboolean Key_GetConsoleSelectionBox(console_t *con, int *sx, int *sy, int *ex, i
}
else if (con->mousedown[2] == 2)
{
//right-mouse
//select. copy-to-clipboard on release.
*sx = con->mousedown[0];
*sy = con->mousedown[1];
*ex = con->mousecursor[0];
*ey = con->mousecursor[1];
return true;
}
return false;
else
{
*sx = con->mousecursor[0];
*sy = con->mousecursor[1];
*ex = con->mousecursor[0];
*ey = con->mousecursor[1];
return false;
}
}
/*insert the given text at the console input line at the current cursor pos*/
@ -745,7 +756,7 @@ void Key_ConsoleRelease(console_t *con, int key, int unicode)
con->mousedown[2] = 0;
if (abs(con->mousedown[0] - con->mousecursor[0]) < 5 && abs(con->mousedown[1] - con->mousecursor[1]) < 5)
{
buffer = Con_CopyConsole(false);
buffer = Con_CopyConsole(false, false);
Con_Footerf(false, "");
if (!buffer)
return;
@ -821,7 +832,7 @@ void Key_ConsoleRelease(console_t *con, int key, int unicode)
if (key == K_MOUSE2 && con->mousedown[2] == 2)
{
con->mousedown[2] = 0;
buffer = Con_CopyConsole(true); //don't keep markup if we're copying to the clipboard
buffer = Con_CopyConsole(true, false); //don't keep markup if we're copying to the clipboard
if (!buffer)
return;
Sys_SaveClipboard(buffer);
@ -925,6 +936,210 @@ static unsigned char *utf_right(unsigned char *start, unsigned char *cursor)
return cursor;
}
void Key_EntryInsert(unsigned char **line, int *linepos, char *instext)
{
int i;
int len, olen;
char *old;
if (!*instext)
return;
old = (*line);
len = strlen(instext);
olen = strlen(old);
*line = BZ_Malloc(olen + len + 1);
memcpy(*line, old, *linepos);
memcpy(*line+*linepos, instext, len);
memcpy(*line+*linepos+len, old+*linepos, olen - *linepos+1);
Z_Free(old);
for (i = *linepos; i < *linepos+len; i++)
{
if ((*line)[i] == '\r')
(*line)[i] = ' ';
else if ((*line)[i] == '\n')
(*line)[i] = ';';
}
*linepos += len;
}
qboolean Key_EntryLine(unsigned char **line, int lineoffset, int *linepos, int key, unsigned int unicode)
{
qboolean ctrl = keydown[K_LCTRL] || keydown[K_RCTRL];
qboolean shift = keydown[K_LSHIFT] || keydown[K_RSHIFT];
char utf8[8];
if (key == K_LEFTARROW || key == K_KP_LEFTARROW)
{
if (ctrl)
{
//ignore whitespace if we're at the end of the word
while (*linepos > 0 && (*line)[*linepos-1] == ' ')
*linepos = utf_left((*line)+lineoffset, (*line) + *linepos) - (*line);
//keep skipping until we find the start of that word
while (ctrl && *linepos > lineoffset && (*line)[*linepos-1] != ' ')
*linepos = utf_left((*line)+lineoffset, (*line) + *linepos) - (*line);
}
else
*linepos = utf_left((*line)+lineoffset, (*line) + *linepos) - (*line);
return true;
}
if (key == K_RIGHTARROW || key == K_KP_RIGHTARROW)
{
if ((*line)[*linepos])
{
*linepos = utf_right((*line)+lineoffset, (*line) + *linepos) - (*line);
if (ctrl)
{
//skip over the word
while ((*line)[*linepos] && (*line)[*linepos] != ' ')
*linepos = utf_right((*line)+lineoffset, (*line) + *linepos) - (*line);
//as well as any trailing whitespace
while ((*line)[*linepos] == ' ')
*linepos = utf_right((*line)+lineoffset, (*line) + *linepos) - (*line);
}
return true;
}
else
unicode = ' ';
}
if (key == K_DEL || key == K_KP_DEL)
{
if ((*line)[*linepos])
{
int charlen = utf_right((*line)+lineoffset, (*line) + *linepos) - ((*line) + *linepos);
memmove((*line)+*linepos, (*line)+*linepos+charlen, strlen((*line)+*linepos+charlen)+1);
return true;
}
else
key = K_BACKSPACE;
}
if (key == K_BACKSPACE)
{
if (*linepos > lineoffset)
{
int charlen = ((*line)+*linepos) - utf_left((*line)+lineoffset, (*line) + *linepos);
memmove((*line)+*linepos-charlen, (*line)+*linepos, strlen((*line)+*linepos)+1);
*linepos -= charlen;
}
if (!(*line)[lineoffset]) //oops?
con_commandmatch = 0;
return true;
}
if (key == K_HOME || key == K_KP_HOME)
{
*linepos = lineoffset;
return true;
}
if (key == K_END || key == K_KP_END)
{
*linepos = strlen(*line);
return true;
}
//beware that windows translates ctrl+c and ctrl+v to a control char
if (((unicode=='C' || unicode=='c' || unicode==3) && ctrl) || (ctrl && key == K_INS))
{
Sys_SaveClipboard(*line);
return true;
}
if (((unicode=='V' || unicode=='v' || unicode==22) && ctrl) || (shift && key == K_INS))
{
char *clipText = Sys_GetClipboard();
if (clipText)
{
Key_EntryInsert(line, linepos, clipText);
Sys_CloseClipboard(clipText);
}
return true;
}
if (unicode < ' ')
{
//if the user is entering control codes, then the ctrl+foo mechanism is probably unsupported by the unicode input stuff, so give best-effort replacements.
switch(unicode)
{
case 27/*'['*/: unicode = 0xe010; break;
case 29/*']'*/: unicode = 0xe011; break;
case 7/*'g'*/: unicode = 0xe086; break;
case 18/*'r'*/: unicode = 0xe087; break;
case 25/*'y'*/: unicode = 0xe088; break;
case 2/*'b'*/: unicode = 0xe089; break;
case 19/*'s'*/: unicode = 0xe080; break;
case 4/*'d'*/: unicode = 0xe081; break;
case 6/*'f'*/: unicode = 0xe082; break;
case 1/*'a'*/: unicode = 0xe083; break;
case 21/*'u'*/: unicode = 0xe01d; break;
case 9/*'i'*/: unicode = 0xe01e; break;
case 15/*'o'*/: unicode = 0xe01f; break;
case 10/*'j'*/: unicode = 0xe01c; break;
case 16/*'p'*/: unicode = 0xe09c; break;
case 13/*'m'*/: unicode = 0xe08b; break;
case 11/*'k'*/: unicode = 0xe08d; break;
case 14/*'n'*/: unicode = '\r'; break;
default:
// if (unicode)
// Con_Printf("escape code %i\n", unicode);
//even if we don't print these, we still need to cancel them in the caller.
if (key == K_LALT || key == K_RALT ||
key == K_LCTRL || key == K_RCTRL ||
key == K_LSHIFT || key == K_RSHIFT)
return true;
return false;
}
}
else if (com_parseutf8.ival >= 0) //don't do this for iso8859-1. the major user of that is hexen2 which doesn't have these chars.
{
if (ctrl && !keydown[K_RALT])
{
if (unicode >= '0' && unicode <= '9')
unicode = unicode - '0' + 0xe012; // yellow number
else switch (unicode)
{
case '[': unicode = 0xe010; break;
case ']': unicode = 0xe011; break;
case 'g': unicode = 0xe086; break;
case 'r': unicode = 0xe087; break;
case 'y': unicode = 0xe088; break;
case 'b': unicode = 0xe089; break;
case '(': unicode = 0xe080; break;
case '=': unicode = 0xe081; break;
case ')': unicode = 0xe082; break;
case 'a': unicode = 0xe083; break;
case '<': unicode = 0xe01d; break;
case '-': unicode = 0xe01e; break;
case '>': unicode = 0xe01f; break;
case ',': unicode = 0xe01c; break;
case '.': unicode = 0xe09c; break;
case 'B': unicode = 0xe08b; break;
case 'C': unicode = 0xe08d; break;
case 'n': unicode = '\r'; break;
}
}
if (keydown[K_LALT] && unicode > 32 && unicode < 128)
unicode |= 0xe080; // red char
}
unicode = utf8_encode(utf8, unicode, sizeof(utf8)-1);
if (unicode)
{
utf8[unicode] = 0;
Key_EntryInsert(line, linepos, utf8);
return true;
}
return false;
}
/*
====================
Key_Console
@ -936,8 +1151,6 @@ qboolean Key_Console (console_t *con, unsigned int unicode, int key)
{
qboolean ctrl = keydown[K_LCTRL] || keydown[K_RCTRL];
qboolean shift = keydown[K_LSHIFT] || keydown[K_RSHIFT];
char *clipText;
char utf8[8];
//weirdness for the keypad.
if ((unicode >= '0' && unicode <= '9') || unicode == '.')
@ -959,9 +1172,8 @@ qboolean Key_Console (console_t *con, unsigned int unicode, int key)
if ((key == K_MOUSE1 || key == K_MOUSE2))
{
int xpos, ypos;
xpos = (int)((con->mousecursor[0]*vid.width)/(vid.pixelwidth*8));
ypos = (int)((con->mousecursor[1]*vid.height)/(vid.pixelheight*8));
// int xpos = (int)((con->mousecursor[0]*vid.width)/(vid.pixelwidth*8));
int ypos = (int)((con->mousecursor[1]*vid.height)/(vid.pixelheight*8));
con->mousedown[0] = con->mousecursor[0];
con->mousedown[1] = con->mousecursor[1];
if (ypos == 0 && con_mouseover)
@ -1024,66 +1236,6 @@ qboolean Key_Console (console_t *con, unsigned int unicode, int key)
if (key != K_CTRL && key != K_SHIFT && con_commandmatch)
con_commandmatch=1;
if (key == K_LEFTARROW || key == K_KP_LEFTARROW)
{
if (ctrl)
{
//ignore whitespace if we're at the end of the word
while (key_linepos > 0 && key_lines[edit_line][key_linepos-1] == ' ')
key_linepos = utf_left(key_lines[edit_line]+1, key_lines[edit_line] + key_linepos) - key_lines[edit_line];
//keep skipping until we find the start of that word
while (ctrl && key_linepos > 1 && key_lines[edit_line][key_linepos-1] != ' ')
key_linepos = utf_left(key_lines[edit_line]+1, key_lines[edit_line] + key_linepos) - key_lines[edit_line];
}
else
key_linepos = utf_left(key_lines[edit_line]+1, key_lines[edit_line] + key_linepos) - key_lines[edit_line];
return true;
}
if (key == K_RIGHTARROW || key == K_KP_RIGHTARROW)
{
if (key_lines[edit_line][key_linepos])
{
key_linepos = utf_right(key_lines[edit_line]+1, key_lines[edit_line] + key_linepos) - key_lines[edit_line];
if (ctrl)
{
//skip over the word
while (key_lines[edit_line][key_linepos] && key_lines[edit_line][key_linepos] != ' ')
key_linepos = utf_right(key_lines[edit_line]+1, key_lines[edit_line] + key_linepos) - key_lines[edit_line];
//as well as any trailing whitespace
while (key_lines[edit_line][key_linepos] == ' ')
key_linepos = utf_right(key_lines[edit_line]+1, key_lines[edit_line] + key_linepos) - key_lines[edit_line];
}
return true;
}
else
unicode = ' ';
}
if (key == K_DEL || key == K_KP_DEL)
{
if (key_lines[edit_line][key_linepos])
{
int charlen = utf_right(key_lines[edit_line]+1, key_lines[edit_line] + key_linepos) - (key_lines[edit_line] + key_linepos);
memmove(key_lines[edit_line]+key_linepos, key_lines[edit_line]+key_linepos+charlen, strlen(key_lines[edit_line]+key_linepos+charlen)+1);
return true;
}
else
key = K_BACKSPACE;
}
if (key == K_BACKSPACE)
{
if (key_linepos > 1)
{
int charlen = (key_lines[edit_line]+key_linepos) - utf_left(key_lines[edit_line]+1, key_lines[edit_line] + key_linepos);
memmove(key_lines[edit_line]+key_linepos-charlen, key_lines[edit_line]+key_linepos, strlen(key_lines[edit_line]+key_linepos)+1);
key_linepos -= charlen;
}
if (!key_lines[edit_line][1])
con_commandmatch = 0;
return true;
}
if (key == K_UPARROW || key == K_KP_UPARROW)
{
do
@ -1169,140 +1321,65 @@ qboolean Key_Console (console_t *con, unsigned int unicode, int key)
return true;
}
if (key == K_HOME || key == K_KP_HOME)
if ((key == K_HOME || key == K_KP_HOME) && ctrl)
{
if (ctrl)
con->display = con->oldest;
else
key_linepos = 1;
con->display = con->oldest;
return true;
}
if (key == K_END || key == K_KP_END)
if ((key == K_END || key == K_KP_END) && ctrl)
{
if (ctrl)
con->display = con->current;
else
key_linepos = strlen(key_lines[edit_line]);
con->display = con->current;
return true;
}
//beware that windows translates ctrl+c and ctrl+v to a control char
if (((unicode=='C' || unicode=='c' || unicode==3) && ctrl) || (ctrl && key == K_INS))
{
Sys_SaveClipboard(key_lines[edit_line]+1);
return true;
}
if (((unicode=='V' || unicode=='v' || unicode==22) && ctrl) || (shift && key == K_INS))
{
clipText = Sys_GetClipboard();
if (clipText)
{
Key_ConsoleInsert(clipText);
Sys_CloseClipboard(clipText);
}
return true;
}
if (unicode < ' ')
{
//if the user is entering control codes, then the ctrl+foo mechanism is probably unsupported by the unicode input stuff, so give best-effort replacements.
switch(unicode)
{
case 27/*'['*/: unicode = 0xe010; break;
case 29/*']'*/: unicode = 0xe011; break;
case 7/*'g'*/: unicode = 0xe086; break;
case 18/*'r'*/: unicode = 0xe087; break;
case 25/*'y'*/: unicode = 0xe088; break;
case 2/*'b'*/: unicode = 0xe089; break;
case 19/*'s'*/: unicode = 0xe080; break;
case 4/*'d'*/: unicode = 0xe081; break;
case 6/*'f'*/: unicode = 0xe082; break;
case 1/*'a'*/: unicode = 0xe083; break;
case 21/*'u'*/: unicode = 0xe01d; break;
case 9/*'i'*/: unicode = 0xe01e; break;
case 15/*'o'*/: unicode = 0xe01f; break;
case 10/*'j'*/: unicode = 0xe01c; break;
case 16/*'p'*/: unicode = 0xe09c; break;
case 13/*'m'*/: unicode = 0xe08b; break;
case 11/*'k'*/: unicode = 0xe08d; break;
case 14/*'n'*/: unicode = '\r'; break;
default:
// if (unicode)
// Con_Printf("escape code %i\n", unicode);
//even if we don't print these, we still need to cancel them in the caller.
if (key == K_LALT || key == K_RALT ||
key == K_LCTRL || key == K_RCTRL ||
key == K_LSHIFT || key == K_RSHIFT)
return true;
return false;
}
}
else if (com_parseutf8.ival >= 0) //don't do this for iso8859-1. the major user of that is hexen2 which doesn't have these chars.
{
if (ctrl && !keydown[K_RALT])
{
if (unicode >= '0' && unicode <= '9')
unicode = unicode - '0' + 0xe012; // yellow number
else switch (unicode)
{
case '[': unicode = 0xe010; break;
case ']': unicode = 0xe011; break;
case 'g': unicode = 0xe086; break;
case 'r': unicode = 0xe087; break;
case 'y': unicode = 0xe088; break;
case 'b': unicode = 0xe089; break;
case '(': unicode = 0xe080; break;
case '=': unicode = 0xe081; break;
case ')': unicode = 0xe082; break;
case 'a': unicode = 0xe083; break;
case '<': unicode = 0xe01d; break;
case '-': unicode = 0xe01e; break;
case '>': unicode = 0xe01f; break;
case ',': unicode = 0xe01c; break;
case '.': unicode = 0xe09c; break;
case 'B': unicode = 0xe08b; break;
case 'C': unicode = 0xe08d; break;
case 'n': unicode = '\r'; break;
}
}
if (keydown[K_LALT] && unicode > 32 && unicode < 128)
unicode |= 0xe080; // red char
}
unicode = utf8_encode(utf8, unicode, sizeof(utf8)-1);
if (unicode)
{
utf8[unicode] = 0;
Key_ConsoleInsert(utf8);
return true;
}
return false;
return Key_EntryLine(&key_lines[edit_line], 1, &key_linepos, key, unicode);
}
//============================================================================
qboolean chat_team;
char chat_buffer[MAXCMDLINE];
int chat_bufferlen = 0;
unsigned char *chat_buffer;
int chat_bufferpos;
void Key_Message (int key, int unicode)
{
if (!chat_buffer)
{
chat_buffer = BZ_Malloc(1);
chat_buffer[0] = 0;
chat_bufferpos = 0;
}
if (key == K_ENTER || key == K_KP_ENTER)
{
if (chat_buffer[0])
if (chat_buffer && chat_buffer[0])
{ //send it straight into the command.
Cmd_TokenizeString(va("%s %s", chat_team?"say_team":"say", chat_buffer), true, false);
char *line = chat_buffer;
char deutf8[8192];
if (com_parseutf8.ival <= 0)
{
unsigned int unicode;
int err;
int len = 0;
while(*line)
{
unicode = utf8_decode(&err, line, &line);
if (com_parseutf8.ival < 0)
len += iso88591_encode(deutf8+len, unicode, sizeof(deutf8)-1 - len);
else
len += qchar_encode(deutf8+len, unicode, sizeof(deutf8)-1 - len);
}
deutf8[len] = 0;
line = deutf8;
}
Cmd_TokenizeString(va("%s %s", chat_team?"say_team":"say", line), true, false);
CL_Say(chat_team, "");
}
Key_Dest_Remove(kdm_message);
chat_bufferlen = 0;
chat_bufferpos = 0;
chat_buffer[0] = 0;
return;
}
@ -1310,29 +1387,12 @@ void Key_Message (int key, int unicode)
if (key == K_ESCAPE)
{
Key_Dest_Remove(kdm_message);
chat_bufferlen = 0;
chat_bufferpos = 0;
chat_buffer[0] = 0;
return;
}
if (key < 32 || key > 127)
return; // non printable
if (key == K_BACKSPACE)
{
if (chat_bufferlen)
{
chat_bufferlen--;
chat_buffer[chat_bufferlen] = 0;
}
return;
}
if (chat_bufferlen == sizeof(chat_buffer)-1)
return; // all full
chat_buffer[chat_bufferlen++] = unicode;
chat_buffer[chat_bufferlen] = 0;
Key_EntryLine(&chat_buffer, 0, &chat_bufferpos, key, unicode);
}
//============================================================================

View File

@ -192,8 +192,8 @@ extern int key_repeats[K_MAX];
extern int key_count; // incremented every key event
extern int key_lastpress;
extern char chat_buffer[];
extern int chat_bufferlen;
extern unsigned char *chat_buffer;
extern int chat_bufferpos;
extern qboolean chat_team;
void Key_Event (int devid, int key, unsigned int unicode, qboolean down);

View File

@ -402,12 +402,16 @@ void Media_SetPauseTrack(qboolean paused)
{
if (paused)
{
if (!cdplayingtrack)
return;
cdpausedtrack = cdplayingtrack;
cdplayingtrack = 0;
CDAudio_Pause();
}
else
{
if (!cdpausedtrack)
return;
cdplayingtrack = cdpausedtrack;
cdpausedtrack = 0;
CDAudio_Resume();

View File

@ -553,6 +553,8 @@ const char *presetexec[] =
"r_waterwarp 0;"
"r_lightstylesmooth 0;"
"r_part_density 0.25;"
"cl_nolerp 1;"
"r_lerpmuzzlehack 0;"
, // fast options
"gl_texturemode ln;"
@ -583,6 +585,8 @@ const char *presetexec[] =
"r_waterwarp 1;"
"r_drawflame 1;"
"r_coronas 1;"
"cl_nolerp 0;"
"r_lerpmuzzlehack 1;"
, // nice options
"r_stains 0.75;"

View File

@ -408,7 +408,7 @@ void M_MenuS_Combos_f (void)
/*
menuclear
menualias menucallback
conmenu menucallback
menubox 0 0 320 8
menutext 0 0 "GO GO GO!!!" "radio21"

View File

@ -7,7 +7,7 @@
//returns a valid effect if its existance is known.
static int PNULL_FindParticleType(char *name)
{
Con_DPrintf("P_FindParticleType %s\n", name);
// Con_DPrintf("P_FindParticleType %s\n", name);
return P_INVALID;
}

View File

@ -1342,31 +1342,31 @@ static void QCBUILTIN PF_R_GetViewFlag(pubprogfuncs_t *prinst, struct globalvars
break;
case VF_VIEWPORT:
r[0] = r_refdef.vrect.width;
r[1] = r_refdef.vrect.height;
r[0] = r_refdef.grect.width;
r[1] = r_refdef.grect.height;
break;
case VF_SIZE_X:
*r = r_refdef.vrect.width;
*r = r_refdef.grect.width;
break;
case VF_SIZE_Y:
*r = r_refdef.vrect.height;
*r = r_refdef.grect.height;
break;
case VF_SIZE:
r[0] = r_refdef.vrect.width;
r[1] = r_refdef.vrect.height;
r[0] = r_refdef.grect.width;
r[1] = r_refdef.grect.height;
r[2] = 0;
break;
case VF_MIN_X:
*r = r_refdef.vrect.x;
*r = r_refdef.grect.x;
break;
case VF_MIN_Y:
*r = r_refdef.vrect.y;
*r = r_refdef.grect.y;
break;
case VF_MIN:
r[0] = r_refdef.vrect.x;
r[1] = r_refdef.vrect.y;
r[0] = r_refdef.grect.x;
r[1] = r_refdef.grect.y;
break;
case VF_DRAWWORLD:
@ -3415,7 +3415,7 @@ static void QCBUILTIN PF_cs_addprogs (pubprogfuncs_t *prinst, struct globalvars_
{
newp = PR_LoadProgs(prinst, s, 0, NULL, 0);
if (newp >= 0)
PR_AutoCvarSetup(csqcprogs);
PR_ProgsAdded(csqcprogs, newp, s);
}
G_FLOAT(OFS_RETURN) = newp;
}
@ -5298,6 +5298,8 @@ qboolean CSQC_Init (qboolean anycsqc, qboolean csdatenabled, unsigned int checks
csqctime = Sys_DoubleTime();
if (!csqcprogs)
{
int csprogsnum = -1;
int csaddonnum = -1;
in_sensitivityscale = 1;
csqcmapentitydataloaded = true;
csqcprogs = InitProgs(&csqcprogparms);
@ -5324,45 +5326,39 @@ qboolean CSQC_Init (qboolean anycsqc, qboolean csdatenabled, unsigned int checks
csqc_isdarkplaces = false;
if (csdatenabled || csqc_singlecheats || anycsqc)
{
if (PR_LoadProgs(csqcprogs, "csprogs.dat", 22390, NULL, 0) >= 0)
loaded = true;
else
csprogsnum = PR_LoadProgs(csqcprogs, "csprogs.dat", 22390, NULL, 0);
if (csprogsnum == -1)
{
if (PR_LoadProgs(csqcprogs, "csprogs.dat", 52195, NULL, 0) >= 0)
{
csprogsnum = PR_LoadProgs(csqcprogs, "csprogs.dat", 52195, NULL, 0);
if (csprogsnum >= 0)
csqc_isdarkplaces = true;
loaded = true;
}
else if (PR_LoadProgs(csqcprogs, "csprogs.dat", 0, NULL, 0) >= 0)
loaded = true;
else
loaded = false;
csprogsnum = PR_LoadProgs(csqcprogs, "csprogs.dat", 0, NULL, 0);
if (loaded)
if (csprogsnum != -1)
Con_Printf(CON_WARNING "Running outdated or unknown csprogs.dat version\n");
}
}
if (csqc_singlecheats || anycsqc)
{
if (PR_LoadProgs(csqcprogs, "csaddon.dat", 0, NULL, 0) >= 0)
{
csaddonnum = PR_LoadProgs(csqcprogs, "csaddon.dat", 0, NULL, 0);
if (csaddonnum >= 0)
Con_DPrintf("loaded csaddon.dat...\n");
loaded = true;
}
else
Con_DPrintf("unable to find csaddon.dat.\n");
}
else
Con_DPrintf("skipping csaddon.dat due to cheat restrictions\n");
if (!loaded)
if (csprogsnum == -1 && csaddonnum == -1)
{
CSQC_Shutdown();
return false;
}
PR_AutoCvarSetup(csqcprogs);
PR_ProgsAdded(csqcprogs, csprogsnum, "csprogs.dat");
PR_ProgsAdded(csqcprogs, csaddonnum, "csaddon.dat");
PF_InitTempStrings(csqcprogs);

View File

@ -626,6 +626,36 @@ void QCBUILTIN PF_SubConGetSet (pubprogfuncs_t *prinst, struct globalvars_s *pr_
if (value)
con->unseentext = atoi(value);
}
else if (!strcmp(field, "markup"))
{
int cur;
if (con->parseflags & PFS_NOMARKUP)
cur = 0;
else if (con->parseflags & PFS_KEEPMARKUP)
cur = 2;
else
cur = 1;
RETURN_TSTRING(va("%i", cur));
if (value)
{
cur = atoi(value);
con->parseflags &= ~(PFS_NOMARKUP|PFS_KEEPMARKUP);
if (cur == 0)
con->parseflags |= PFS_NOMARKUP;
else if (cur == 2)
con->parseflags |= PFS_KEEPMARKUP;
}
}
else if (!strcmp(field, "forceutf8"))
{
RETURN_TSTRING((con->parseflags&PFS_FORCEUTF8)?"1":"0");
if (value)
{
con->parseflags &= ~PFS_FORCEUTF8;
if (atoi(value))
con->parseflags |= PFS_FORCEUTF8;
}
}
else if (!strcmp(field, "hidden"))
{
RETURN_TSTRING((con->flags & CON_HIDDEN)?"1":"0");
@ -1799,10 +1829,12 @@ qboolean MP_Init (void)
menutime = Sys_DoubleTime();
if (!menu_world.progs)
{
int mprogs;
Con_DPrintf("Initializing menu.dat\n");
menu_world.progs = InitProgs(&menuprogparms);
PR_Configure(menu_world.progs, 64*1024*1024, 1);
if (PR_LoadProgs(menu_world.progs, "menu.dat", 10020, NULL, 0) < 0) //no per-progs builtins.
mprogs = PR_LoadProgs(menu_world.progs, "menu.dat", 10020, NULL, 0);
if (mprogs < 0) //no per-progs builtins.
{
//failed to load or something
// CloseProgs(menu_world.progs);
@ -1826,7 +1858,7 @@ qboolean MP_Init (void)
menu_world.g.drawfont = (float*)PR_FindGlobal(menu_world.progs, "drawfont", 0, NULL);
menu_world.g.drawfontscale = (float*)PR_FindGlobal(menu_world.progs, "drawfontscale", 0, NULL);
PR_AutoCvarSetup(menu_world.progs);
PR_ProgsAdded(menu_world.progs, mprogs, "menu.dat");
menuentsize = PR_InitEnts(menu_world.progs, 8192);

View File

@ -1038,7 +1038,7 @@ static skelobject_t *skel_create(pubprogfuncs_t *prinst, int bonecount)
if (!skelobjects[skelidx].numbones)
{
skelobjects[skelidx].numbones = bonecount;
skelobjects[skelidx].bonematrix = (float*)PR_AddString(prinst, "", sizeof(float)*12*bonecount);
skelobjects[skelidx].bonematrix = (float*)PR_AddString(prinst, "", sizeof(float)*12*bonecount, false);
}
skelobjects[skelidx].world = prinst->parms->user;
if (numskelobjectsused <= skelidx)

View File

@ -3,7 +3,7 @@
#include "shader.h"
#include "gl_draw.h"
qboolean r2d_noshadergamma; //says the video code has successfully activated hardware gamma
qboolean r2d_canhwgamma; //says the video code has successfully activated hardware gamma
texid_t missing_texture;
texid_t missing_texture_gloss;
texid_t missing_texture_normal;
@ -629,7 +629,7 @@ void R2D_Font_Callback(struct cvar_s *var, char *oldvalue)
};
qboolean MyRegGetStringValue(HKEY base, char *keyname, char *valuename, void *data, int datalen);
LOGFONT lf = {0};
CHOOSEFONT cf = {sizeof(cf)};
CHOOSEFONTA cf = {sizeof(cf)};
extern HWND mainwindow;
extern qboolean WinNT;
font_conchar = Font_LoadFont(8, "");
@ -831,7 +831,7 @@ void R2D_BrightenScreen (void)
if (fabs(v_contrast.value - 1.0) < 0.05 && fabs(v_brightness.value - 0) < 0.05 && fabs(v_gamma.value - 1) < 0.05)
return;
if (r2d_noshadergamma)
if (r2d_canhwgamma)
return;
if (v_gamma.value != 1 && shader_gammacb->prog)

View File

@ -152,8 +152,8 @@ typedef struct mplane_s
#define RDFD_FOV 1
typedef struct
{
vrect_t grect; // game rectangle. fullscreen except for csqc/splitscreen.
vrect_t vrect; // subwindow in grect for 3d view
vrect_t grect; // game rectangle. fullscreen except for csqc/splitscreen/hud.
vrect_t vrect; // subwindow in grect for 3d view. equal to grect if no hud.
vec3_t pvsorigin; /*render the view using this point for pvs (useful for mirror views)*/
vec3_t vieworg; /*logical view center*/
@ -180,7 +180,7 @@ typedef struct
vec4_t gfog_rgbd;
vrect_t pxrect; /*vrect, but in pixels rather than virtual coords*/
pxrect_t pxrect; /*vrect, but in pixels rather than virtual coords*/
qboolean externalview; /*draw external models and not viewmodels*/
qboolean recurse; /*in a mirror/portal/half way through drawing something else*/
qboolean forcevis; /*if true, vis comes from the forcedvis field instead of recalculated*/
@ -308,6 +308,7 @@ enum imageflags
IF_TEXTYPE = (1<<6) | (1<<7) | (1<<8), /*0=2d, 1=3d, 2-7=cubeface*/
IF_TEXTYPESHIFT = 6, /*0=2d, 1=3d, 2-7=cubeface*/
IF_MIPCAP = 1<<9,
IF_EXACTEXTENSION = 1<<29,
IF_REPLACE = 1<<30,
IF_SUBDIRONLY = 1<<31
};

View File

@ -119,6 +119,7 @@ cvar_t r_loadlits = CVARF ("r_loadlit", "1", CVAR_ARCHIVE);
cvar_t r_menutint = SCVARF ("r_menutint", "0.68 0.4 0.13",
CVAR_RENDERERCALLBACK);
cvar_t r_netgraph = SCVAR ("r_netgraph", "0");
cvar_t r_lerpmuzzlehack = CVARF ("r_lerpmuzzlehack", "1", CVAR_ARCHIVE);
cvar_t r_nolerp = CVARF ("r_nolerp", "0", CVAR_ARCHIVE);
cvar_t r_noframegrouplerp = CVARF ("r_noframegrouplerp", "0", CVAR_ARCHIVE);
cvar_t r_nolightdir = CVARF ("r_nolightdir", "0", CVAR_ARCHIVE);
@ -402,6 +403,7 @@ void GLRenderer_Init(void)
Cvar_Register (&r_postprocshader, GLRENDEREROPTIONS);
Cvar_Register (&dpcompat_psa_ungroup, GLRENDEREROPTIONS);
Cvar_Register (&r_lerpmuzzlehack, GLRENDEREROPTIONS);
Cvar_Register (&r_noframegrouplerp, GLRENDEREROPTIONS);
Cvar_Register (&r_noportals, GLRENDEREROPTIONS);
Cvar_Register (&r_noaliasshadows, GLRENDEREROPTIONS);
@ -426,8 +428,6 @@ void GLRenderer_Init(void)
#ifdef R_XFLIP
Cvar_Register (&r_xflip, GLRENDEREROPTIONS);
#endif
Cvar_Register (&gl_specular, GRAPHICALNICETIES);
Cvar_Register (&gl_specular_fallback, GRAPHICALNICETIES);
// Cvar_Register (&gl_lightmapmode, GLRENDEREROPTIONS);
@ -611,6 +611,8 @@ void Renderer_Init(void)
Cvar_Register (&r_coronas, GRAPHICALNICETIES);
Cvar_Register (&r_flashblend, GRAPHICALNICETIES);
Cvar_Register (&r_flashblendscale, GRAPHICALNICETIES);
Cvar_Register (&gl_specular, GRAPHICALNICETIES);
Cvar_Register (&gl_specular_fallback, GRAPHICALNICETIES);
Sh_RegisterCvars();
@ -1335,44 +1337,31 @@ void R_ReloadRenderer_f (void)
#define DEFAULT_HEIGHT 480
#define DEFAULT_BPP 32
void R_RestartRenderer_f (void)
//use Cvar_ApplyLatches(CVAR_RENDERERLATCH) beforehand.
qboolean R_BuildRenderstate(rendererstate_t *newr, char *rendererstring)
{
int i, j;
rendererstate_t oldr;
rendererstate_t newr;
if (r_blockvidrestart)
{
Con_Printf("Ignoring vid_restart from config\n");
return;
}
M_Shutdown();
memset(&newr, 0, sizeof(newr));
memset(newr, 0, sizeof(*newr));
TRACE(("dbg: R_RestartRenderer_f\n"));
newr->width = vid_width.value;
newr->height = vid_height.value;
Media_CaptureDemoEnd();
Cvar_ApplyLatches(CVAR_RENDERERLATCH);
newr.width = vid_width.value;
newr.height = vid_height.value;
newr.triplebuffer = vid_triplebuffer.value;
newr.multisample = vid_multisample.value;
newr.bpp = vid_bpp.value;
newr.fullscreen = vid_fullscreen.value;
newr.rate = vid_refreshrate.value;
newr.stereo = (r_stereo_method.ival == 1);
newr->triplebuffer = vid_triplebuffer.value;
newr->multisample = vid_multisample.value;
newr->bpp = vid_bpp.value;
newr->fullscreen = vid_fullscreen.value;
newr->rate = vid_refreshrate.value;
newr->stereo = (r_stereo_method.ival == 1);
if (!*_vid_wait_override.string || _vid_wait_override.value < 0)
newr.wait = -1;
newr->wait = -1;
else
newr.wait = _vid_wait_override.value;
newr->wait = _vid_wait_override.value;
Q_strncpyz(newr.glrenderer, gl_driver.string, sizeof(newr.glrenderer));
newr->renderer = NULL;
newr.renderer = NULL;
rendererstring = COM_Parse(rendererstring);
for (i = 0; i < sizeof(rendererinfo)/sizeof(rendererinfo[0]); i++)
{
if (!rendererinfo[i]->description)
@ -1381,14 +1370,82 @@ TRACE(("dbg: R_RestartRenderer_f\n"));
{
if (!rendererinfo[i]->name[j])
continue;
if (!stricmp(rendererinfo[i]->name[j], vid_renderer.string))
if (!stricmp(rendererinfo[i]->name[j], com_token))
{
newr.renderer = rendererinfo[i];
newr->renderer = rendererinfo[i];
break;
}
}
}
if (!newr.renderer)
rendererstring = COM_Parse(rendererstring);
if (*com_token)
Q_strncpyz(newr->subrenderer, com_token, sizeof(newr->subrenderer));
else if (newr->renderer && newr->renderer->rtype == QR_OPENGL)
Q_strncpyz(newr->subrenderer, gl_driver.string, sizeof(newr->subrenderer));
// use desktop settings if set to 0 and not dedicated
if (newr->renderer && newr->renderer->rtype != QR_NONE)
{
int dbpp, dheight, dwidth, drate;
extern qboolean isPlugin;
if ((!newr->fullscreen && !vid_desktopsettings.value && !isPlugin) || !Sys_GetDesktopParameters(&dwidth, &dheight, &dbpp, &drate))
{
// force default values for systems not supporting desktop parameters
dwidth = DEFAULT_WIDTH;
dheight = DEFAULT_HEIGHT;
dbpp = DEFAULT_BPP;
drate = 0;
}
if (vid_desktopsettings.value)
{
newr->width = dwidth;
newr->height = dheight;
newr->bpp = dbpp;
newr->rate = drate;
}
else
{
if (newr->width <= 0 || newr->height <= 0)
{
newr->width = dwidth;
newr->height = dheight;
}
if (newr->bpp <= 0)
newr->bpp = dbpp;
}
}
#ifdef CLIENTONLY
if (newr->renderer && newr->renderer->rtype == QR_NONE)
{
Con_Printf("Client-only builds cannot use dedicated modes.\n");
return NULL;
}
#endif
return newr->renderer != NULL;
}
void R_RestartRenderer_f (void)
{
rendererstate_t oldr;
rendererstate_t newr;
if (r_blockvidrestart)
{
Con_Printf("Ignoring vid_restart from config\n");
return;
}
memset(&newr, 0, sizeof(newr));
TRACE(("dbg: R_RestartRenderer_f\n"));
Cvar_ApplyLatches(CVAR_RENDERERLATCH);
if (!R_BuildRenderstate(&newr, vid_renderer.string))
{
int i;
if (*vid_renderer.string)
@ -1408,40 +1465,8 @@ TRACE(("dbg: R_RestartRenderer_f\n"));
return;
}
// use desktop settings if set to 0 and not dedicated
if (newr.renderer->rtype != QR_NONE)
{
int dbpp, dheight, dwidth, drate;
extern qboolean isPlugin;
if ((!newr.fullscreen && !vid_desktopsettings.value && !isPlugin) || !Sys_GetDesktopParameters(&dwidth, &dheight, &dbpp, &drate))
{
// force default values for systems not supporting desktop parameters
dwidth = DEFAULT_WIDTH;
dheight = DEFAULT_HEIGHT;
dbpp = DEFAULT_BPP;
drate = 0;
}
if (vid_desktopsettings.value)
{
newr.width = dwidth;
newr.height = dheight;
newr.bpp = dbpp;
newr.rate = drate;
}
else
{
if (newr.width <= 0 || newr.height <= 0)
{
newr.width = dwidth;
newr.height = dheight;
}
if (newr.bpp <= 0)
newr.bpp = dbpp;
}
}
M_Shutdown();
Media_CaptureDemoEnd();
TRACE(("dbg: R_RestartRenderer_f renderer %i\n", newr.renderer));
@ -1502,9 +1527,10 @@ TRACE(("dbg: R_RestartRenderer_f\n"));
void R_SetRenderer_f (void)
{
int i, j;
int best;
int i;
char *param = Cmd_Argv(1);
rendererstate_t newr;
if (Cmd_Argc() == 1 || !stricmp(param, "help"))
{
Con_Printf ("\nValid setrenderer parameters are:\n");
@ -1516,32 +1542,7 @@ void R_SetRenderer_f (void)
return;
}
best = -1;
for (i = 0; i < sizeof(rendererinfo)/sizeof(rendererinfo[0]); i++)
{
if (!rendererinfo[i]->description)
continue; //not valid in this build. :(
for (j = 4-1; j >= 0; j--)
{
if (!rendererinfo[i]->name[j])
continue;
if (!stricmp(rendererinfo[i]->name[j], param))
{
best = i;
break;
}
}
}
#ifdef CLIENTONLY
if (best == 0)
{
Con_Printf("Client-only builds cannot use dedicated modes.\n");
return;
}
#endif
if (best == -1)
if (!R_BuildRenderstate(&newr, param))
{
Con_Printf("setrenderer: parameter not supported (%s)\n", param);
return;

View File

@ -1266,17 +1266,20 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
}
#ifdef SUPPORT_ICE
switch(s_voip.enccodec)
if (rtpstream)
{
case VOIP_SPEEX_NARROW:
case VOIP_SPEEX_WIDE:
case VOIP_SPEEX_ULTRAWIDE:
case VOIP_SPEEX_OLD:
NET_RTP_Transmit(initseq, inittimestamp, va("speex@%i", s_voip.encsamplerate), outbuf, outpos);
break;
case VOIP_OPUS:
NET_RTP_Transmit(initseq, inittimestamp, "opus", outbuf, outpos);
break;
switch(s_voip.enccodec)
{
case VOIP_SPEEX_NARROW:
case VOIP_SPEEX_WIDE:
case VOIP_SPEEX_ULTRAWIDE:
case VOIP_SPEEX_OLD:
NET_RTP_Transmit(initseq, inittimestamp, va("speex@%i", s_voip.encsamplerate), outbuf, outpos);
break;
case VOIP_OPUS:
NET_RTP_Transmit(initseq, inittimestamp, "opus", outbuf, outpos);
break;
}
}
#endif

View File

@ -51,6 +51,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <pthread.h>
#endif
#define USE_LIBTOOL
#ifdef USE_LIBTOOL
#include <ltdl.h>
#endif
#include "quakedef.h"
#undef malloc
@ -67,7 +72,7 @@ long sys_parentwindow;
qboolean X11_GetDesktopParameters(int *width, int *height, int *bpp, int *refreshrate);
char *basedir = ".";
char *basedir = "./";
qboolean Sys_InitTerminal (void) //we either have one or we don't.
{
@ -244,6 +249,10 @@ void Sys_Quit (void)
{
Host_Shutdown();
fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
#ifdef USE_LIBTOOL
lt_dlexit();
#endif
exit(0);
}
@ -268,6 +277,9 @@ void Sys_Error (const char *error, ...)
fprintf(stderr, "Error: %s\n", string);
Host_Shutdown ();
#ifdef USE_LIBTOOL
lt_dlexit();
#endif
exit (1);
}
@ -454,6 +466,7 @@ int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const
if (!func(file, st.st_size, parm, spath))
{
Con_DPrintf("giving up on search after finding %s\n", file);
closedir(dir);
return false;
}
@ -492,6 +505,52 @@ unsigned int Sys_Milliseconds (void)
return Sys_DoubleTime() * 1000;
}
#ifdef USE_LIBTOOL
void Sys_CloseLibrary(dllhandle_t *lib)
{
lt_dlclose((void*)lib);
}
dllhandle_t *Sys_LoadLibrary(const char *name, dllfunction_t *funcs)
{
int i;
dllhandle_t lib;
lib = NULL;
if (!lib)
lib = lt_dlopenext (name);
if (!lib)
{
Con_DPrintf("%s: %s\n", name, lt_dlerror());
return NULL;
}
if (funcs)
{
for (i = 0; funcs[i].name; i++)
{
*funcs[i].funcptr = lt_dlsym(lib, funcs[i].name);
if (!*funcs[i].funcptr)
break;
}
if (funcs[i].name)
{
Con_DPrintf("Unable to find symbol \"%s\" in \"%s\"\n", funcs[i].name, name);
Sys_CloseLibrary((dllhandle_t*)lib);
lib = NULL;
}
}
return (dllhandle_t*)lib;
}
void *Sys_GetAddressForName(dllhandle_t *module, const char *exportname)
{
if (!module)
return NULL;
return lt_dlsym(module, exportname);
}
#else
void Sys_CloseLibrary(dllhandle_t *lib)
{
dlclose((void*)lib);
@ -538,6 +597,7 @@ void *Sys_GetAddressForName(dllhandle_t *module, const char *exportname)
return NULL;
return dlsym(module, exportname);
}
#endif
// =======================================================================
//friendly way to crash, including stack traces. should help reduce gdb use.
@ -671,14 +731,18 @@ int main (int c, const char **v)
quakeparms_t parms;
int j;
// static char cwd[1024];
static char bindir[1024];
// char cwd[1024];
char bindir[1024];
signal(SIGFPE, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
memset(&parms, 0, sizeof(parms));
#ifdef USE_LIBTOOL
lt_dlinit();
#endif
parms.argc = c;
parms.argv = v;
COM_InitArgv(parms.argc, parms.argv);

View File

@ -456,7 +456,7 @@ int QDECL main(int argc, char **argv)
memset(&parms, 0, sizeof(parms));
parms.basedir = ".";
parms.basedir = "./";
parms.argc = argc;
parms.argv = (const char**)argv;

View File

@ -198,7 +198,7 @@ char *Sys_GetNameForAddress(dllhandle_t *module, void *address)
int starttime;
qboolean ActiveApp, Minimized;
qboolean WinNT;
qboolean WinNT; //NT has a) proper unicode support that does not unconditionally result in errors. b) a few different registry paths.
static HANDLE hinput, houtput;
@ -445,7 +445,7 @@ DWORD CrashExceptionHandler (qboolean iswatchdog, DWORD exceptionCode, LPEXCEPTI
}
Sys_SaveClipboard(stacklog+logstart);
#ifdef _MSC_VER
if (MessageBox(0, stacklog, "KABOOM!", MB_ICONSTOP|MB_YESNO) != IDYES)
if (MessageBoxA(0, stacklog, "KABOOM!", MB_ICONSTOP|MB_YESNO) != IDYES)
return EXCEPTION_EXECUTE_HANDLER;
#else
MessageBox(0, stacklog, "KABOOM!", MB_ICONSTOP);
@ -454,7 +454,7 @@ DWORD CrashExceptionHandler (qboolean iswatchdog, DWORD exceptionCode, LPEXCEPTI
}
else
{
if (MessageBox(NULL, "KABOOM! We crashed!\nBlame the monkey in the corner.\nI hope you saved your work.\nWould you like to take a dump now?", DISTRIBUTION " Sucks", MB_ICONSTOP|MB_YESNO) != IDYES)
if (MessageBoxA(NULL, "KABOOM! We crashed!\nBlame the monkey in the corner.\nI hope you saved your work.\nWould you like to take a dump now?", DISTRIBUTION " Sucks", MB_ICONSTOP|MB_YESNO) != IDYES)
return EXCEPTION_EXECUTE_HANDLER;
}
}
@ -471,7 +471,7 @@ DWORD CrashExceptionHandler (qboolean iswatchdog, DWORD exceptionCode, LPEXCEPTI
{
if (iswatchdog)
{
switch (MessageBox(NULL, "Fizzle... We hit an infinite loop! Or something is just really slow.\nBlame the monkey in the corner.\nI hope you saved your work.\nWould you like to take a dump now?", DISTRIBUTION " Sucks", MB_ICONSTOP|MB_YESNOCANCEL))
switch (MessageBoxA(NULL, "Fizzle... We hit an infinite loop! Or something is just really slow.\nBlame the monkey in the corner.\nI hope you saved your work.\nWould you like to take a dump now?", DISTRIBUTION " Sucks", MB_ICONSTOP|MB_YESNOCANCEL))
{
case IDYES:
break; //take a dump.
@ -675,133 +675,343 @@ FILE IO
===============================================================================
*/
wchar_t *widen(wchar_t *out, size_t outlen, const char *utf8)
{
wchar_t *ret = out;
//utf-8 to utf-16, not ucs-2.
unsigned int codepoint;
int error;
if (!outlen)
return L"";
outlen /= sizeof(wchar_t);
outlen--;
while (*utf8)
{
codepoint = utf8_decode(&error, utf8, (void*)&utf8);
if (error)
codepoint = 0xFFFDu;
if (codepoint > 0xffff)
{
if (outlen < 2)
break;
outlen -= 2;
codepoint -= 0x10000u;
*out++ = 0xD800 | (codepoint>>10);
*out++ = 0xDC00 | (codepoint&0x3ff);
}
else
{
if (outlen < 1)
break;
outlen -= 1;
*out++ = codepoint;
}
}
*out = 0;
return ret;
}
char *narrowen(char *out, size_t outlen, wchar_t *wide)
{
char *ret = out;
int bytes;
unsigned int codepoint;
if (!outlen)
return "";
outlen--;
//utf-8 to utf-16, not ucs-2.
while (*wide)
{
codepoint = *wide++;
if (codepoint >= 0xD800u && codepoint <= 0xDBFFu)
{ //handle utf-16 surrogates
if (*wide >= 0xDC00u && *wide <= 0xDFFFu)
{
codepoint = (codepoint&0x3ff)<<10;
codepoint |= *wide++ & 0x3ff;
}
else
codepoint = 0xFFFDu;
}
bytes = utf8_encode(out, codepoint, outlen);
if (bytes <= 0)
break;
out += bytes;
outlen -= bytes;
}
*out = 0;
return ret;
}
void Sys_mkdir (char *path)
{
_mkdir (path);
if (WinNT)
{
wchar_t wide[MAX_OSPATH];
widen(wide, sizeof(wide), path);
CreateDirectoryW(wide, NULL);
}
else
_mkdir (path);
}
qboolean Sys_remove (char *path)
{
if (remove (path) != 0)
if (WinNT)
{
int e = errno;
if (e == ENOENT)
return true; //return success if it doesn't already exist.
return false;
wchar_t wide[MAX_OSPATH];
widen(wide, sizeof(wide), path);
if (DeleteFileW(wide))
return true; //success
if (GetLastError() == ERROR_FILE_NOT_FOUND)
return true; //succeed when the file already didn't exist
return false; //other errors? panic
}
else
{
if (remove (path) != 0)
{
int e = errno;
if (e == ENOENT)
return true; //return success if it doesn't already exist.
return false;
}
return true;
}
return true;
}
qboolean Sys_Rename (char *oldfname, char *newfname)
{
return !rename(oldfname, newfname);
if (WinNT)
{
wchar_t oldwide[MAX_OSPATH];
wchar_t newwide[MAX_OSPATH];
widen(oldwide, sizeof(oldwide), oldfname);
widen(newwide, sizeof(newwide), newfname);
return MoveFileW(oldwide, newwide);
}
else
return !rename(oldfname, newfname);
}
static int Sys_EnumerateFiles2 (const char *match, int matchstart, int neststart, int (QDECL *func)(const char *fname, int fsize, void *parm, searchpathfuncs_t *spath), void *parm, searchpathfuncs_t *spath)
{
HANDLE r;
WIN32_FIND_DATA fd;
int nest = neststart; //neststart refers to just after a /
qboolean go;
qboolean wild = false;
while(match[nest] && match[nest] != '/')
if (!WinNT)
{
if (match[nest] == '?' || match[nest] == '*')
wild = true;
nest++;
}
if (match[nest] == '/')
{
char submatch[MAX_OSPATH];
char tmproot[MAX_OSPATH];
char file[MAX_OSPATH];
HANDLE r;
WIN32_FIND_DATAA fd;
int nest = neststart; //neststart refers to just after a /
qboolean wild = false;
if (!wild)
return Sys_EnumerateFiles2(match, matchstart, nest+1, func, parm, spath);
if (nest-neststart+1> MAX_OSPATH)
return 1;
memcpy(submatch, match+neststart, nest - neststart);
submatch[nest - neststart] = 0;
nest++;
if (neststart+4 > MAX_OSPATH)
return 1;
memcpy(tmproot, match, neststart);
strcpy(tmproot+neststart, "*.*");
r = FindFirstFile(tmproot, &fd);
strcpy(tmproot+neststart, "");
if (r==(HANDLE)-1)
return 1;
go = true;
do
while(match[nest] && match[nest] != '/')
{
if (*fd.cFileName == '.'); //don't ever find files with a name starting with '.'
else if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) //is a directory
if (match[nest] == '?' || match[nest] == '*')
wild = true;
nest++;
}
if (match[nest] == '/')
{
char submatch[MAX_OSPATH];
char tmproot[MAX_OSPATH];
char file[MAX_OSPATH];
if (!wild)
return Sys_EnumerateFiles2(match, matchstart, nest+1, func, parm, spath);
if (nest-neststart+1> MAX_OSPATH)
return 1;
memcpy(submatch, match+neststart, nest - neststart);
submatch[nest - neststart] = 0;
nest++;
if (neststart+4 > MAX_OSPATH)
return 1;
memcpy(tmproot, match, neststart);
strcpy(tmproot+neststart, "*.*");
r = FindFirstFile(tmproot, &fd);
strcpy(tmproot+neststart, "");
if (r==(HANDLE)-1)
return 1;
go = true;
do
{
if (wildcmp(submatch, fd.cFileName))
if (*fd.cFileName == '.'); //don't ever find files with a name starting with '.'
else if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) //is a directory
{
int newnest;
if (strlen(tmproot) + strlen(fd.cFileName) + strlen(match+nest) + 2 < MAX_OSPATH)
if (wildcmp(submatch, fd.cFileName))
{
Q_snprintfz(file, sizeof(file), "%s%s/", tmproot, fd.cFileName);
newnest = strlen(file);
strcpy(file+newnest, match+nest);
go = Sys_EnumerateFiles2(file, matchstart, newnest, func, parm, spath);
int newnest;
if (strlen(tmproot) + strlen(fd.cFileName) + strlen(match+nest) + 2 < MAX_OSPATH)
{
Q_snprintfz(file, sizeof(file), "%s%s/", tmproot, fd.cFileName);
newnest = strlen(file);
strcpy(file+newnest, match+nest);
go = Sys_EnumerateFiles2(file, matchstart, newnest, func, parm, spath);
}
}
}
}
} while(FindNextFile(r, &fd) && go);
FindClose(r);
} while(FindNextFile(r, &fd) && go);
FindClose(r);
}
else
{
const char *submatch = match + neststart;
char tmproot[MAX_OSPATH];
char file[MAX_OSPATH];
if (neststart+4 > MAX_OSPATH)
return 1;
memcpy(tmproot, match, neststart);
strcpy(tmproot+neststart, "*.*");
r = FindFirstFile(tmproot, &fd);
strcpy(tmproot+neststart, "");
if (r==(HANDLE)-1)
return 1;
go = true;
do
{
if (*fd.cFileName == '.')
; //don't ever find files with a name starting with '.' (includes .. and . directories, and unix hidden files)
else if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) //is a directory
{
if (wildcmp(submatch, fd.cFileName))
{
if (strlen(tmproot+matchstart) + strlen(fd.cFileName) + 2 < MAX_OSPATH)
{
Q_snprintfz(file, sizeof(file), "%s%s/", tmproot+matchstart, fd.cFileName);
go = func(file, fd.nFileSizeLow, parm, spath);
}
}
}
else
{
if (wildcmp(submatch, fd.cFileName))
{
if (strlen(tmproot+matchstart) + strlen(fd.cFileName) + 1 < MAX_OSPATH)
{
Q_snprintfz(file, sizeof(file), "%s%s", tmproot+matchstart, fd.cFileName);
go = func(file, fd.nFileSizeLow, parm, spath);
}
}
}
} while(FindNextFile(r, &fd) && go);
FindClose(r);
}
}
else
{
const char *submatch = match + neststart;
char tmproot[MAX_OSPATH];
char file[MAX_OSPATH];
HANDLE r;
WIN32_FIND_DATAW fd;
int nest = neststart; //neststart refers to just after a /
qboolean wild = false;
if (neststart+4 > MAX_OSPATH)
return 1;
memcpy(tmproot, match, neststart);
strcpy(tmproot+neststart, "*.*");
r = FindFirstFile(tmproot, &fd);
strcpy(tmproot+neststart, "");
if (r==(HANDLE)-1)
return 1;
go = true;
do
while(match[nest] && match[nest] != '/')
{
if (*fd.cFileName == '.'); //don't ever find files with a name starting with '.'
else if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) //is a directory
{
if (wildcmp(submatch, fd.cFileName))
{
if (strlen(tmproot+matchstart) + strlen(fd.cFileName) + 2 < MAX_OSPATH)
{
Q_snprintfz(file, sizeof(file), "%s%s/", tmproot+matchstart, fd.cFileName);
go = func(file, fd.nFileSizeLow, parm, spath);
}
}
}
else
{
if (wildcmp(submatch, fd.cFileName))
{
if (strlen(tmproot+matchstart) + strlen(fd.cFileName) + 1 < MAX_OSPATH)
{
Q_snprintfz(file, sizeof(file), "%s%s", tmproot+matchstart, fd.cFileName);
go = func(file, fd.nFileSizeLow, parm, spath);
}
}
}
} while(FindNextFile(r, &fd) && go);
FindClose(r);
}
if (match[nest] == '?' || match[nest] == '*')
wild = true;
nest++;
}
if (match[nest] == '/')
{
char utf8[MAX_OSPATH];
wchar_t wroot[MAX_OSPATH];
char submatch[MAX_OSPATH];
char tmproot[MAX_OSPATH];
char file[MAX_OSPATH];
if (!wild)
return Sys_EnumerateFiles2(match, matchstart, nest+1, func, parm, spath);
if (nest-neststart+1> MAX_OSPATH)
return 1;
memcpy(submatch, match+neststart, nest - neststart);
submatch[nest - neststart] = 0;
nest++;
if (neststart+4 > MAX_OSPATH)
return 1;
memcpy(tmproot, match, neststart);
strcpy(tmproot+neststart, "*.*");
r = FindFirstFileW(widen(wroot, sizeof(wroot), tmproot), &fd);
strcpy(tmproot+neststart, "");
if (r==(HANDLE)-1)
return 1;
go = true;
do
{
narrowen(utf8, sizeof(utf8), fd.cFileName);
if (*utf8 == '.'); //don't ever find files with a name starting with '.'
else if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) //is a directory
{
if (wildcmp(submatch, utf8))
{
int newnest;
if (strlen(tmproot) + strlen(utf8) + strlen(match+nest) + 2 < MAX_OSPATH)
{
Q_snprintfz(file, sizeof(file), "%s%s/", tmproot, utf8);
newnest = strlen(file);
strcpy(file+newnest, match+nest);
go = Sys_EnumerateFiles2(file, matchstart, newnest, func, parm, spath);
}
}
}
} while(FindNextFileW(r, &fd) && go);
FindClose(r);
}
else
{
const char *submatch = match + neststart;
char tmproot[MAX_OSPATH];
wchar_t wroot[MAX_OSPATH];
char utf8[MAX_OSPATH];
char file[MAX_OSPATH];
if (neststart+4 > MAX_OSPATH)
return 1;
memcpy(tmproot, match, neststart);
strcpy(tmproot+neststart, "*.*");
r = FindFirstFileW(widen(wroot, sizeof(wroot), tmproot), &fd);
strcpy(tmproot+neststart, "");
if (r==(HANDLE)-1)
return 1;
go = true;
do
{
narrowen(utf8, sizeof(utf8), fd.cFileName);
if (*utf8 == '.')
; //don't ever find files with a name starting with '.' (includes .. and . directories, and unix hidden files)
else if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) //is a directory
{
if (wildcmp(submatch, utf8))
{
if (strlen(tmproot+matchstart) + strlen(utf8) + 2 < MAX_OSPATH)
{
Q_snprintfz(file, sizeof(file), "%s%s/", tmproot+matchstart, utf8);
go = func(file, fd.nFileSizeLow, parm, spath);
}
}
}
else
{
if (wildcmp(submatch, utf8))
{
if (strlen(tmproot+matchstart) + strlen(utf8) + 1 < MAX_OSPATH)
{
Q_snprintfz(file, sizeof(file), "%s%s", tmproot+matchstart, utf8);
go = func(file, fd.nFileSizeLow, parm, spath);
}
}
}
} while(FindNextFileW(r, &fd) && go);
FindClose(r);
}
}
return go;
}
int Sys_EnumerateFiles (const char *gpath, const char *match, int (QDECL *func)(const char *fname, int fsize, void *parm, searchpathfuncs_t *spath), void *parm, searchpathfuncs_t *spath)
@ -937,7 +1147,7 @@ void Sys_Init (void)
if ((vinfo.dwMajorVersion < 4) ||
(vinfo.dwPlatformId == VER_PLATFORM_WIN32s))
{
Sys_Error ("QuakeWorld requires at least Win95 or NT 4.0");
Sys_Error (FULLENGINENAME " requires at least Win95 or NT 4.0");
}
if (vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
@ -2401,6 +2611,8 @@ void VARGS Signal_Error_Handler(int i)
#endif
*/
extern char sys_language[64];
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// MSG msg;
@ -2409,6 +2621,8 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
char cwd[1024], bindir[1024];
const char *qtvfile = NULL;
int delay = 0;
char lang[32];
char ctry[32];
/* previous instances do not exist in Win32 */
if (hPrevInstance)
@ -2618,6 +2832,15 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
}
}
//98+/nt4+
if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, lang, sizeof(lang)) > 0)
{
if (GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SISO3166CTRYNAME, ctry, sizeof(ctry)) > 0)
Q_snprintfz(sys_language, sizeof(sys_language), "%s_%s", lang, ctry);
else
Q_snprintfz(sys_language, sizeof(sys_language), "%s", lang);
}
TL_InitLanguages();
//tprints are now allowed

View File

@ -38,7 +38,7 @@ typedef struct {
int wait; //-1 = default, 0 = off, 1 = on, 2 = every other
int multisample; //for opengl antialiasing (which requires context stuff)
int triplebuffer;
char glrenderer[MAX_QPATH];
char subrenderer[MAX_QPATH];
struct rendererinfo_s *renderer;
} rendererstate_t;
extern rendererstate_t currentrendererstate;
@ -47,6 +47,14 @@ typedef struct vrect_s
{
float x,y,width,height;
} vrect_t;
typedef struct
{
int x;
int y;
int width;
int height;
int maxheight; //vid.pixelheight or so
} pxrect_t;
typedef struct
{

View File

@ -298,9 +298,9 @@ cshift_t cshift_lava = { {255,80,0}, 150 };
cshift_t cshift_server = { {130,80,50}, 0 };
cvar_t v_gamma = SCVARF("gamma", "0.8", CVAR_ARCHIVE|CVAR_RENDERERCALLBACK);
cvar_t v_contrast = SCVARF("contrast", "1.3", CVAR_ARCHIVE);
cvar_t v_brightness = SCVARF("brightness", "0.0", CVAR_ARCHIVE);
cvar_t v_gamma = CVARFD("gamma", "1.0", CVAR_ARCHIVE|CVAR_RENDERERCALLBACK, "Controls how bright the screen is. Setting this to anything but 1 without hardware gamma requires glsl support and can noticably harm your framerate.");
cvar_t v_contrast = CVARFD("contrast", "1.0", CVAR_ARCHIVE, "Scales colour values linearly to make your screen easier to see. Setting this to anything but 1 without hardware gamma will reduce your framerates a little.");
cvar_t v_brightness = CVARFD("brightness", "0.0", CVAR_ARCHIVE, "Brightness is how much 'white' to add to each and every pixel on the screen.");
qbyte gammatable[256]; // palette is sent through this
@ -394,6 +394,7 @@ void V_ParseDamage (playerview_t *pv)
count = 10;
#ifdef ANDROID
//later versions of android might support strength values, but the simple standard interface is duration only.
Sys_Vibrate(count);
#endif
@ -638,7 +639,7 @@ V_CalcBlend
*/
void V_CalcBlend (float *hw_blend)
{
extern qboolean r2d_noshadergamma;
extern qboolean r2d_canhwgamma;
float a2;
int j;
float *blend;
@ -671,7 +672,7 @@ void V_CalcBlend (float *hw_blend)
}
else
{
if (j == CSHIFT_BONUS || j == CSHIFT_DAMAGE || gl_nohwblend.ival || r2d_noshadergamma)
if (j == CSHIFT_BONUS || j == CSHIFT_DAMAGE || gl_nohwblend.ival || !r2d_canhwgamma)
blend = sw_blend;
else //powerup or contents?
blend = hw_blend;
@ -701,7 +702,7 @@ V_UpdatePalette
*/
void V_UpdatePalette (qboolean force)
{
extern qboolean r2d_noshadergamma;
extern qboolean r2d_canhwgamma;
int i;
float newhw_blend[4];
int ir, ig, ib;
@ -758,9 +759,9 @@ void V_UpdatePalette (qboolean force)
}
applied = rf->VID_ApplyGammaRamps ((unsigned short*)ramps);
if (!applied && r2d_noshadergamma)
if (!applied && r2d_canhwgamma)
rf->VID_ApplyGammaRamps (NULL);
r2d_noshadergamma = applied;
r2d_canhwgamma = applied;
}
RSpeedEnd(RSPEED_PALETTEFLASHES);

View File

@ -27,10 +27,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//#define VERSION 2.56
#ifndef DISTRIBUTION
#define DISTRIBUTION "FTE"
#define DISTRIBUTIONLONG "Forethought Entertainment"
#define FULLENGINENAME "FTE QuakeWorld"
#define ENGINEWEBSITE "http://www.fteqw.com"
#define DISTRIBUTION "FTE" //short name used to identify this engine. must be a single word
#define DISTRIBUTIONLONG "Forethought Entertainment" //effectively the 'company' name
#define FULLENGINENAME "FTE QuakeWorld" //the posh name for the engine
#define ENGINEWEBSITE "http://www.fteqw.com" //url for program
#endif
@ -87,25 +87,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#endif
#define AVAIL_OGGVORBIS
#if !defined(__CYGWIN__) && !defined(MINGW) && !defined(MACOSX)
#if defined(__CYGWIN__)
#define AVAIL_ZLIB
#else
#define AVAIL_PNGLIB
#define AVAIL_JPEGLIB
#define AVAIL_ZLIB
#define AVAIL_OGGVORBIS
/* Jogi's OpenAL support */
#define AVAIL_OPENAL
#endif
#if defined(MINGW) || defined(MACOSX)
#define AVAIL_PNGLIB
#define AVAIL_ZLIB
#define AVAIL_JPEGLIB
#define AVAIL_OGGVORBIS
#endif
#define AVAIL_OPENAL
#if !defined(NO_DIRECTX) && !defined(NODIRECTX)
#if !defined(NO_DIRECTX) && !defined(NODIRECTX) && defined(_WIN32)
#define AVAIL_DINPUT
#define AVAIL_DDRAW
#define AVAIL_DSOUND
@ -114,8 +107,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#if defined(_WIN32) && !defined(_SDL)
#define HAVE_WINSSPI //built in component, checks against windows' root ca database and revocations etc.
#elif defined(__linux__)
// #define HAVE_GNUTLS //currently disabled as it does not validate the server's certificate, beware the mitm attack.
#elif defined(__linux__) || defined(__CYGWIN__)
#define HAVE_GNUTLS //currently disabled as it does not validate the server's certificate, beware the mitm attack.
#endif
#if defined(HAVE_WINSSPI) || defined(HAVE_GNUTLS)
#define HAVE_SSL
@ -358,6 +351,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#undef WEBSERVER
#endif
#ifndef AVAIL_ZLIB
#undef SUPPORT_ICE
#endif
#ifdef SERVERONLY //remove options that don't make sense on only a server
#undef Q2CLIENT
#undef Q3CLIENT
@ -447,6 +444,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define PLATFORM "Win32"
#endif
#define ARCH_DL_POSTFIX ".dll"
#elif defined(__CYGWIN__)
#define PLATFORM "Cygwin" /*technically also windows*/
#define ARCH_DL_POSTFIX ".dll"
#elif defined(ANDROID)
#define PLATFORM "Android" /*technically also linux*/
#elif defined(__linux__)

View File

@ -7,6 +7,7 @@ extern char loadname[];
qboolean r_loadbumpmapping;
extern cvar_t dpcompat_psa_ungroup;
extern cvar_t r_noframegrouplerp;
extern cvar_t r_lerpmuzzlehack;
//Common loader function.
void Mod_DoCRC(model_t *mod, char *buffer, int buffersize)
@ -1259,7 +1260,7 @@ void R_LightArrays(const entity_t *entity, vecV_t *coords, avec4_t *colours, int
}
}
static void R_LerpFrames(mesh_t *mesh, galiaspose_t *p1, galiaspose_t *p2, float lerp, float expand)
static void R_LerpFrames(mesh_t *mesh, galiaspose_t *p1, galiaspose_t *p2, float lerp, float expand, float lerpcutoff)
{
extern cvar_t r_nolerp; // r_nolightdir is unused
float blerp = 1-lerp;
@ -1293,11 +1294,12 @@ static void R_LerpFrames(mesh_t *mesh, galiaspose_t *p1, galiaspose_t *p2, float
if (expand)
{
vecV_t *oxyz = mesh->xyz_array;
for (i = 0; i < mesh->numvertexes; i++)
{
mesh->xyz_array[i][0] = p1v[i][0] + p1n[i][0]*expand;
mesh->xyz_array[i][1] = p1v[i][1] + p1n[i][1]*expand;
mesh->xyz_array[i][2] = p1v[i][2] + p1n[i][2]*expand;
oxyz[i][0] = p1v[i][0] + p1n[i][0]*expand;
oxyz[i][1] = p1v[i][1] + p1n[i][1]*expand;
oxyz[i][2] = p1v[i][2] + p1n[i][2]*expand;
}
return;
}
@ -1306,24 +1308,60 @@ static void R_LerpFrames(mesh_t *mesh, galiaspose_t *p1, galiaspose_t *p2, float
}
else
{
for (i = 0; i < mesh->numvertexes; i++)
vecV_t *oxyz = mesh->xyz_array;
vec3_t *onorm = mesh->normals_array;
if (lerpcutoff)
{
mesh->normals_array[i][0] = p1n[i][0]*lerp + p2n[i][0]*blerp;
mesh->normals_array[i][1] = p1n[i][1]*lerp + p2n[i][1]*blerp;
mesh->normals_array[i][2] = p1n[i][2]*lerp + p2n[i][2]*blerp;
vec3_t d;
lerpcutoff *= lerpcutoff;
for (i = 0; i < mesh->numvertexes; i++)
{
VectorSubtract(p2v[i], p1v[i], d);
if (DotProduct(d, d) > lerpcutoff)
{
//just use the current frame if we're over the lerp threshold.
//these verts are considered to have teleported.
onorm[i][0] = p2n[i][0];
onorm[i][1] = p2n[i][1];
onorm[i][2] = p2n[i][2];
mesh->xyz_array[i][0] = p1v[i][0]*lerp + p2v[i][0]*blerp;
mesh->xyz_array[i][1] = p1v[i][1]*lerp + p2v[i][1]*blerp;
mesh->xyz_array[i][2] = p1v[i][2]*lerp + p2v[i][2]*blerp;
oxyz[i][0] = p2v[i][0];
oxyz[i][1] = p2v[i][1];
oxyz[i][2] = p2v[i][2];
}
else
{
onorm[i][0] = p1n[i][0]*lerp + p2n[i][0]*blerp;
onorm[i][1] = p1n[i][1]*lerp + p2n[i][1]*blerp;
onorm[i][2] = p1n[i][2]*lerp + p2n[i][2]*blerp;
oxyz[i][0] = p1v[i][0]*lerp + p2v[i][0]*blerp;
oxyz[i][1] = p1v[i][1]*lerp + p2v[i][1]*blerp;
oxyz[i][2] = p1v[i][2]*lerp + p2v[i][2]*blerp;
}
}
}
else
{
for (i = 0; i < mesh->numvertexes; i++)
{
onorm[i][0] = p1n[i][0]*lerp + p2n[i][0]*blerp;
onorm[i][1] = p1n[i][1]*lerp + p2n[i][1]*blerp;
onorm[i][2] = p1n[i][2]*lerp + p2n[i][2]*blerp;
oxyz[i][0] = p1v[i][0]*lerp + p2v[i][0]*blerp;
oxyz[i][1] = p1v[i][1]*lerp + p2v[i][1]*blerp;
oxyz[i][2] = p1v[i][2]*lerp + p2v[i][2]*blerp;
}
}
if (expand)
{
for (i = 0; i < mesh->numvertexes; i++)
{
mesh->xyz_array[i][0] += mesh->normals_array[i][0]*expand;
mesh->xyz_array[i][1] += mesh->normals_array[i][1]*expand;
mesh->xyz_array[i][2] += mesh->normals_array[i][2]*expand;
oxyz[i][0] += onorm[i][0]*expand;
oxyz[i][1] += onorm[i][1]*expand;
oxyz[i][2] += onorm[i][2]*expand;
}
}
}
@ -1450,6 +1488,7 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, vbo_t **vbop, galiasinfo_t *inf, in
{
extern cvar_t r_nolerp;
galiasgroup_t *g1, *g2;
float lerpcutoff;
int frame1;
int frame2;
@ -1674,13 +1713,14 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, vbo_t **vbop, galiasinfo_t *inf, in
frame2=0;
}
lerpcutoff = inf->lerpcutoff * r_lerpmuzzlehack.value;
if (Sh_StencilShadowsActive() || qrenderer != QR_OPENGL)
if (Sh_StencilShadowsActive() || qrenderer != QR_OPENGL || e->fatness || lerpcutoff)
{
mesh->xyz2_array = NULL;
mesh->xyz_blendw[0] = 1;
mesh->xyz_blendw[1] = 0;
R_LerpFrames(mesh, &g1->poseofs[frame1], &g2->poseofs[frame2], 1-lerp, e->fatness);
R_LerpFrames(mesh, &g1->poseofs[frame1], &g2->poseofs[frame2], 1-lerp, e->fatness, lerpcutoff);
}
else
{
@ -2610,7 +2650,7 @@ static void *Alias_LoadFrameGroup (daliasframetype_t *pframetype, int *seamremap
//greatly reduced version of Q1_LoadSkins
//just skips over the data
static void *Q1_LoadSkins_SV (daliasskintype_t *pskintype, qboolean alpha)
static void *Q1_LoadSkins_SV (daliasskintype_t *pskintype, unsigned int skintranstype)
{
int i;
int s;
@ -3176,6 +3216,21 @@ qboolean QDECL Mod_LoadQ1Model (model_t *mod, void *buffer)
mod->funcs.NativeTrace = Mod_Trace;
if (!strcmp(mod->name, "progs/v_shot.mdl"))
galias->lerpcutoff = 20;
else if (!strcmp(mod->name, "progs/v_shot2.mdl"))
galias->lerpcutoff = 20;
else if (!strcmp(mod->name, "progs/v_nail.mdl"))
galias->lerpcutoff = 7;
else if (!strcmp(mod->name, "progs/v_nail2.mdl"))
galias->lerpcutoff = 6;
else if (!strcmp(mod->name, "progs/v_rock.mdl"))
galias->lerpcutoff = 30;
else if (!strcmp(mod->name, "progs/v_rock2.mdl"))
galias->lerpcutoff = 30;
else if (!strcmp(mod->name, "progs/v_light.mdl"))
galias->lerpcutoff = 30;
return true;
}
#endif
@ -6185,7 +6240,7 @@ qboolean Mod_ParseIQMAnim(char *buffer, galiasinfo_t *prototype, void**poseofs,
qboolean Mod_LoadInterQuakeModel(model_t *mod, void *buffer)
qboolean QDECL Mod_LoadInterQuakeModel(model_t *mod, void *buffer)
{
int i;
galiasinfo_t *root;

View File

@ -104,6 +104,7 @@ typedef struct galiasinfo_s
int numindexes;
int *ofs_trineighbours;
float lerpcutoff; //hack. should probably be part of the entity structure, but I really don't want new models (and thus code) to have access to this ugly inefficient hack. make your models properly in the first place.
int numskins;
#ifndef SERVERONLY

View File

@ -419,12 +419,14 @@ int wildcmp(const char *wild, const char *string)
{
if (*wild == '*')
{
if (wild[1] == *string || *string == '/' || *string == '\\')
if (*string == '/' || *string == '\\')
{
//* terminates if we get a match on the char following it, or if its a \ or / char
wild++;
continue;
}
if (wildcmp(wild+1, string))
return true;
string++;
}
else if ((*wild == *string) || (*wild == '?'))
@ -2916,6 +2918,8 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t
}
else if (str[0] == '=' && str[1] == '`' && str[2] == 'k' && str[3] == '8' && str[4] == ':' && !keepmarkup)
{
//ezquake compat: koi8 compat for crazy russian people.
//we parse for compat but don't generate (they'll see utf-8 from us).
//this code can just recurse. saves affecting the rest of the code with weird encodings.
int l;
char temp[1024];
@ -3315,7 +3319,7 @@ skipwhite:
if (c == '\\' && data[1] == '\"')
{
return COM_ParseCString(data+1, token, tokenlen);
return COM_ParseCString(data+1, token, tokenlen, NULL);
}
// handle quoted strings specially
@ -3600,6 +3604,10 @@ const char *COM_QuotedString(const char *string, char *buf, int buflen)
*buf++ = '\\';
*buf++ = 'r';
break;
case '\t':
*buf++ = '\\';
*buf++ = 't';
break;
case '\'':
*buf++ = '\\';
*buf++ = '\'';
@ -3640,14 +3648,17 @@ const char *COM_QuotedString(const char *string, char *buf, int buflen)
}
}
char *COM_ParseCString (const char *data, char *token, int tokenlen)
char *COM_ParseCString (const char *data, char *token, size_t sizeoftoken, size_t *lengthwritten)
{
int c;
int len;
size_t len;
len = 0;
token[0] = 0;
if (lengthwritten)
*lengthwritten = 0;
if (!data)
return NULL;
@ -3678,9 +3689,11 @@ skipwhite:
data++;
while (1)
{
if (len >= tokenlen-2)
if (len >= sizeoftoken-2)
{
token[len] = '\0';
if (lengthwritten)
*lengthwritten = len;
return (char*)data;
}
@ -3688,6 +3701,8 @@ skipwhite:
if (!c)
{
token[len] = 0;
if (lengthwritten)
*lengthwritten = len;
return (char*)data-1;
}
if (c == '\\')
@ -3703,6 +3718,9 @@ skipwhite:
case 'n':
c = '\n';
break;
case 't':
c = '\t';
break;
case 'r':
c = '\r';
break;
@ -3723,6 +3741,8 @@ skipwhite:
if (c=='\"' || !c)
{
token[len] = 0;
if (lengthwritten)
*lengthwritten = len;
return (char*)data;
}
token[len] = c;
@ -3733,7 +3753,7 @@ skipwhite:
// parse a regular word
do
{
if (len >= tokenlen-1)
if (len >= sizeoftoken-1)
break;
token[len] = c;
data++;
@ -3742,6 +3762,8 @@ skipwhite:
} while (c>32);
token[len] = 0;
if (lengthwritten)
*lengthwritten = len;
return (char*)data;
}
@ -4633,7 +4655,7 @@ void Info_RemoveKey (char *s, const char *key)
if (strstr (key, "\\"))
{
Con_TPrintf (TL_KEYHASSLASH);
Con_Printf ("Can't use a key with a \\\n");
return;
}
@ -4775,19 +4797,19 @@ void Info_SetValueForStarKey (char *s, const char *key, const char *value, int m
if (strstr (key, "\\") || strstr (value, "\\") )
{
Con_TPrintf (TL_KEYHASSLASH);
Con_Printf ("Can't use a key with a \\\n");
return;
}
if (strstr (key, "\"") || strstr (value, "\"") )
{
Con_TPrintf (TL_KEYHASQUOTE);
Con_Printf ("Can't use a key with a \"\n");
return;
}
if (strlen(key) >= MAX_INFO_KEY)// || strlen(value) >= MAX_INFO_KEY)
{
Con_TPrintf (TL_KEYTOOLONG);
Con_Printf ("Keys and values must be < %i characters.\n", MAX_INFO_KEY);
return;
}
@ -4804,7 +4826,7 @@ void Info_SetValueForStarKey (char *s, const char *key, const char *value, int m
Info_SetValueForStarKey (s, key, value, maxsize);
return;
}
Con_TPrintf (TL_INFOSTRINGTOOLONG);
Con_Printf ("Info string length exceeded on addition of %s\n", key);
return;
}
}
@ -4816,7 +4838,7 @@ void Info_SetValueForStarKey (char *s, const char *key, const char *value, int m
if ((int)(strlen(newv) + strlen(s) + 1) > maxsize)
{
Con_TPrintf (TL_INFOSTRINGTOOLONG);
Con_Printf ("Info string length exceeded on addition of %s\n", key);
return;
}
@ -4854,7 +4876,7 @@ void Info_SetValueForKey (char *s, const char *key, const char *value, int maxsi
{
if (key[0] == '*')
{
Con_TPrintf (TL_STARKEYPROTECTED);
Con_Printf ("Can't set * keys\n");
return;
}
@ -4888,7 +4910,8 @@ void Info_Print (char *s, char *lineprefix)
if (!*s)
{
Con_TPrintf (TL_KEYHASNOVALUE);
//should never happen.
Con_Printf ("<no value>\n");
return;
}

View File

@ -273,7 +273,7 @@ extern qboolean com_eof;
#define COM_Parse(d) COM_ParseOut(d,com_token, sizeof(com_token))
char *COM_ParseOut (const char *data, char *out, int outlen);
char *COM_ParseStringSet (const char *data);
char *COM_ParseCString (const char *data, char *out, int outlen);
char *COM_ParseCString (const char *data, char *out, size_t maxoutlen, size_t *writtenlen);
char *COM_StringParse (const char *data, char *token, unsigned int tokenlen, qboolean expandmacros, qboolean qctokenize);
char *COM_ParseToken (const char *data, const char *punctuation);
char *COM_TrimString(char *str);
@ -527,6 +527,11 @@ char *T_GetString(int num);
void T_FreeInfoStrings(void);
char *T_GetInfoString(int num);
struct po_s;
const char *PO_GetText(struct po_s *po, const char *msg);
struct po_s *PO_Load(vfsfile_t *file);
void PO_Close(struct po_s *po);
//
// log.c
//

View File

@ -38,7 +38,7 @@ extern conchar_t q3codemasks[MAXQ3COLOURS];
#define CON_HIDDEN 0x00080000
#define CON_BLINKTEXT 0x00040000
#define CON_2NDCHARSETTEXT 0x00020000
#define CON_RICHFORECOLOUR 0x00010000 //
#define CON_RICHFORECOLOUR 0x00010000 //if set, the upper 3 nibbles are r4g4b4. background is clear, halfalpha is ignored.
//#define CON_HIGHCHARSMASK 0x00000080 // Quake's alternative mask
#define CON_FLAGSMASK 0xFFFF0000
@ -134,6 +134,8 @@ typedef struct console_s
int vislines; // pixel lines
int linesprinted; // for notify times
qboolean unseentext;
unsigned parseflags;
conchar_t defaultcharbits;
int commandcompletion; //allows tab completion of quake console commands
void (*linebuffered) (struct console_s *con, char *line); //if present, called on enter, causes the standard console input to appear.
void (*redirect) (struct console_s *con, int key); //if present, called every character.
@ -178,7 +180,7 @@ void Con_History_Load(void);
struct font_s;
void Con_DrawOneConsole(console_t *con, struct font_s *font, float fx, float fy, float fsx, float fsy);
void Con_DrawConsole (int lines, qboolean noback);
char *Con_CopyConsole(qboolean nomarkup);
char *Con_CopyConsole(qboolean nomarkup, qboolean onlyiflink);
void Con_Print (char *txt);
void VARGS Con_Printf (const char *fmt, ...) LIKEPRINTF(1);
void VARGS Con_TPrintf (translation_t text, ...);
@ -211,3 +213,4 @@ void Con_NotifyBox (char *text); // during startup for sound / cd warnings
#else
#define TRACE(x)
#endif

View File

@ -1296,6 +1296,10 @@ void Cvar_WriteVariables (vfsfile_t *f, qboolean all)
for (var = grp->cvars ; var ; var = var->next)
if (var->flags & CVAR_ARCHIVE || (all && var != &cl_warncmd))
{
//yeah, don't force-save readonly cvars.
if (var->flags & CVAR_NOSET)
continue;
if (!writtengroupheader)
{
writtengroupheader = true;

View File

@ -1,6 +1,6 @@
#include "quakedef.h"
#include "fs.h"
#include <windows.h>
#include "winquake.h"
#ifndef INVALID_SET_FILE_POINTER
#define INVALID_SET_FILE_POINTER ~0
@ -8,6 +8,7 @@
//read-only memory mapped files.
//for write access, we use the stdio module as a fallback.
//do you think anyone will ever notice that utf8 filenames work even in windows? probably not. oh well, worth a try.
#define VFSW32_Open VFSOS_Open
#define VFSW32_OpenPath VFSOS_OpenPath
@ -26,6 +27,11 @@ typedef struct {
unsigned int length;
unsigned int offset;
} vfsw32file_t;
wchar_t *widen(wchar_t *out, size_t outlen, const char *utf8);
char *narrowen(char *out, size_t outlen, const wchar_t *wide);
static int QDECL VFSW32_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread)
{
DWORD read;
@ -127,14 +133,30 @@ vfsfile_t *QDECL VFSW32_Open(const char *osname, const char *mode)
if (strchr(mode, '+'))
read = write = true;
if ((write && read) || append)
h = CreateFileA(osname, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
else if (write)
h = CreateFileA(osname, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
else if (read)
h = CreateFileA(osname, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (!WinNT)
{
if ((write && read) || append)
h = CreateFileA(osname, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
else if (write)
h = CreateFileA(osname, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
else if (read)
h = CreateFileA(osname, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
else
h = INVALID_HANDLE_VALUE;
}
else
h = INVALID_HANDLE_VALUE;
{
wchar_t wide[MAX_OSPATH];
widen(wide, sizeof(wide), osname);
if ((write && read) || append)
h = CreateFileW(wide, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
else if (write)
h = CreateFileW(wide, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
else if (read)
h = CreateFileW(wide, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
else
h = INVALID_HANDLE_VALUE;
}
if (h == INVALID_HANDLE_VALUE)
return NULL;
@ -251,6 +273,7 @@ static qboolean QDECL VFSW32_FLocate(searchpathfuncs_t *handle, flocation_t *loc
FILE *f;
int len;
char netpath[MAX_OSPATH];
wchar_t wide[MAX_OSPATH];
if (hashedresult && (void *)hashedresult != wp)
@ -267,7 +290,10 @@ static qboolean QDECL VFSW32_FLocate(searchpathfuncs_t *handle, flocation_t *loc
// check a file in the directory tree
snprintf (netpath, sizeof(netpath)-1, "%s/%s", wp->rootpath, filename);
f = fopen(netpath, "rb");
if (!WinNT)
f = fopen(netpath, "rb");
else
f = _wfopen(widen(wide, sizeof(wide), netpath), L"rb");
if (!f)
return false;
@ -289,7 +315,11 @@ static void QDECL VFSW32_ReadFile(searchpathfuncs_t *handle, flocation_t *loc, c
// vfsw32path_t *wp = handle;
FILE *f;
f = fopen(loc->rawname, "rb");
wchar_t wide[MAX_OSPATH];
if (!WinNT)
f = fopen(loc->rawname, "rb");
else
f = _wfopen(widen(wide, sizeof(wide), loc->rawname), L"rb");
if (!f) //err...
return;
fseek(f, loc->offset, SEEK_SET);
@ -302,6 +332,30 @@ static int QDECL VFSW32_EnumerateFiles (searchpathfuncs_t *handle, const char *m
return Sys_EnumerateFiles(wp->rootpath, match, func, parm, handle);
}
qboolean QDECL VFSW32_RenameFile(searchpathfuncs_t *handle, const char *oldfname, const char *newfname)
{
vfsw32path_t *wp = (vfsw32path_t*)handle;
char oldsyspath[MAX_OSPATH];
char newsyspath[MAX_OSPATH];
snprintf (oldsyspath, sizeof(oldsyspath)-1, "%s/%s", wp->rootpath, oldfname);
snprintf (newsyspath, sizeof(newsyspath)-1, "%s/%s", wp->rootpath, newfname);
return Sys_Rename(oldsyspath, newsyspath);
}
qboolean QDECL VFSW32_RemoveFile(searchpathfuncs_t *handle, const char *filename)
{
vfsw32path_t *wp = (vfsw32path_t*)handle;
char syspath[MAX_OSPATH];
snprintf (syspath, sizeof(syspath)-1, "%s/%s", wp->rootpath, filename);
return Sys_remove(syspath);
}
qboolean QDECL VFSW32_MkDir(searchpathfuncs_t *handle, const char *filename)
{
vfsw32path_t *wp = (vfsw32path_t*)handle;
char syspath[MAX_OSPATH];
snprintf (syspath, sizeof(syspath)-1, "%s/%s", wp->rootpath, filename);
Sys_mkdir(syspath);
return true;
}
searchpathfuncs_t *QDECL VFSW32_OpenPath(vfsfile_t *mustbenull, const char *desc)
{
@ -312,9 +366,12 @@ searchpathfuncs_t *QDECL VFSW32_OpenPath(vfsfile_t *mustbenull, const char *desc
np = Z_Malloc(sizeof(*np) + dlen);
if (np)
{
wchar_t wide[MAX_OSPATH];
memcpy(np->rootpath, desc, dlen+1);
np->changenotification = FindFirstChangeNotification(np->rootpath, true, FILE_NOTIFY_CHANGE_FILE_NAME);
if (!WinNT)
np->changenotification = FindFirstChangeNotificationA(np->rootpath, true, FILE_NOTIFY_CHANGE_FILE_NAME);
else
np->changenotification = FindFirstChangeNotificationW(widen(wide, sizeof(wide), np->rootpath), true, FILE_NOTIFY_CHANGE_FILE_NAME);
}
np->pub.fsver = FSVER;
@ -325,5 +382,10 @@ searchpathfuncs_t *QDECL VFSW32_OpenPath(vfsfile_t *mustbenull, const char *desc
np->pub.EnumerateFiles = VFSW32_EnumerateFiles;
np->pub.OpenVFS = VFSW32_OpenVFS;
np->pub.PollChanges = VFSW32_PollChanges;
np->pub.RenameFile = VFSW32_RenameFile;
np->pub.RemoveFile = VFSW32_RemoveFile;
np->pub.MkDir = VFSW32_MkDir;
return &np->pub;
}

1317
engine/common/net_ice.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -3,13 +3,19 @@
//named functions, this makes it *really* easy to port plugins from one engine to annother.
#include "quakedef.h"
#ifdef HAVE_GNUTLS
cvar_t *tls_ignorecertificateerrors;
#if 1//defined(_WIN32) && !defined(MINGW)
#ifdef _MSC_VER
#if SIZE_MAX == ULONG_MAX
#define ssize_t long
#else
#define ssize_t int
#endif
#endif
//lets rip stuff out of the header and supply a seperate dll.
//gnutls is huge.
//also this helps get around the whole msvc/mingw thing.
@ -21,13 +27,44 @@ typedef struct DSTRUCT* gnutls_anon_client_credentials;
struct gnutls_session_int;
typedef struct gnutls_session_int* gnutls_session_t;
typedef void * gnutls_transport_ptr_t;
struct gnutls_x509_crt_int;
typedef struct gnutls_x509_crt_int *gnutls_x509_crt_t;
typedef struct
{
unsigned char *data;
unsigned int size;
} gnutls_datum_t;
typedef enum gnutls_kx_algorithm { GNUTLS_KX_RSA=1, GNUTLS_KX_DHE_DSS,
GNUTLS_KX_DHE_RSA, GNUTLS_KX_ANON_DH, GNUTLS_KX_SRP,
GNUTLS_KX_RSA_EXPORT, GNUTLS_KX_SRP_RSA, GNUTLS_KX_SRP_DSS
} gnutls_kx_algorithm;
typedef enum gnutls_certificate_type { GNUTLS_CRT_X509=1, GNUTLS_CRT_OPENPGP
} gnutls_certificate_type;
typedef enum {
GNUTLS_CRT_UNKNOWN = 0,
GNUTLS_CRT_X509 = 1,
GNUTLS_CRT_OPENPGP = 2,
GNUTLS_CRT_RAW = 3
} gnutls_certificate_type_t;
typedef enum {
GNUTLS_X509_FMT_DER = 0,
GNUTLS_X509_FMT_PEM = 1
} gnutls_x509_crt_fmt_t;
typedef enum
{
GNUTLS_CERT_INVALID = 1<<1,
GNUTLS_CERT_REVOKED = 1<<5,
GNUTLS_CERT_SIGNER_NOT_FOUND = 1<<6,
GNUTLS_CERT_SIGNER_NOT_CA = 1<<7,
GNUTLS_CERT_INSECURE_ALGORITHM = 1<<8,
GNUTLS_CERT_NOT_ACTIVATED = 1<<9,
GNUTLS_CERT_EXPIRED = 1<<10,
GNUTLS_CERT_SIGNATURE_FAILURE = 1<<11,
GNUTLS_CERT_REVOCATION_DATA_SUPERSEDED = 1<<12,
GNUTLS_CERT_UNEXPECTED_OWNER = 1<<14,
GNUTLS_CERT_REVOCATION_DATA_ISSUED_IN_FUTURE = 1<<15,
GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE = 1<<16,
GNUTLS_CERT_MISMATCH = 1<<17,
} gnutls_certificate_status_t;
typedef enum gnutls_connection_end { GNUTLS_SERVER=1, GNUTLS_CLIENT } gnutls_connection_end;
typedef enum gnutls_credentials_type { GNUTLS_CRD_CERTIFICATE=1, GNUTLS_CRD_ANON, GNUTLS_CRD_SRP } gnutls_credentials_type;
typedef enum gnutls_close_request { GNUTLS_SHUT_RDWR=0, GNUTLS_SHUT_WR=1 } gnutls_close_request;
@ -35,6 +72,7 @@ typedef ssize_t (*gnutls_pull_func) (gnutls_transport_ptr_t, void *, size_t);
typedef ssize_t (*gnutls_push_func) (gnutls_transport_ptr_t, const void *, size_t);
#define GNUTLS_E_AGAIN -28
#define GNUTLS_E_CERTIFICATE_ERROR -43
#define GNUTLS_E_INTERRUPTED -52
static int (VARGS *gnutls_bye)(gnutls_session_t session, gnutls_close_request how);
@ -45,17 +83,38 @@ static void (VARGS *gnutls_transport_set_push_function)(gnutls_session_t session
static void (VARGS *gnutls_transport_set_pull_function)(gnutls_session_t session, gnutls_pull_func pull_func);
static void (VARGS *gnutls_transport_set_errno)(gnutls_session_t session, int err);
static int (VARGS *gnutls_error_is_fatal)(int error);
static int (VARGS *gnutls_certificate_type_set_priority)(gnutls_session_t session, const int*);
static int (VARGS *gnutls_credentials_set)(gnutls_session_t, gnutls_credentials_type type, void* cred);
static int (VARGS *gnutls_kx_set_priority)(gnutls_session_t session, const int*);
static int (VARGS *gnutls_init)(gnutls_session_t * session, gnutls_connection_end con_end);
static int (VARGS *gnutls_set_default_priority)(gnutls_session_t session);
static int (VARGS *gnutls_certificate_allocate_credentials)(gnutls_certificate_credentials *sc);
static int (VARGS *gnutls_certificate_type_set_priority)(gnutls_session_t session, const int*);
static int (VARGS *gnutls_anon_allocate_client_credentials)(gnutls_anon_client_credentials *sc);
static int (VARGS *gnutls_global_init)(void);
static int (VARGS *gnutls_record_send)(gnutls_session_t session, const void *data, size_t sizeofdata);
static int (VARGS *gnutls_record_recv)(gnutls_session_t session, void *data, size_t sizeofdata);
static int (VARGS *gnutls_certificate_set_verify_function)();
static void *(VARGS *gnutls_session_get_ptr)(gnutls_session_t session);
static void (VARGS *gnutls_session_set_ptr)(gnutls_session_t session, void *ptr);
#if GNUTLS_VERSION_3_0_0_PLUS
static int (VARGS *gnutls_certificate_set_x509_system_trust)(gnutls_certificate_credentials cred);
#else
static int (VARGS *gnutls_certificate_set_x509_trust_file)(gnutls_certificate_credentials cred, const char * cafile, gnutls_x509_crt_fmt_t type);
#endif
#if GNUTLS_VERSION_3_1_4_PLUS
static int (VARGS *gnutls_certificate_verify_peers3)(gnutls_session_t session, const char* hostname, unsigned int * status);
static int (VARGS *gnutls_certificate_verification_status_print)(unsigned int status, gnutls_certificate_type_t type, gnutls_datum_t * out, unsigned int flags);
#else
static int (VARGS *gnutls_certificate_verify_peers2)(gnutls_session_t session, unsigned int * status);
static int (VARGS *gnutls_x509_crt_check_hostname)(gnutls_x509_crt_t cert, const char * hostname);
static int (VARGS *gnutls_x509_crt_init)(gnutls_x509_crt_t * cert);
static int (VARGS *gnutls_x509_crt_import)(gnutls_x509_crt_t cert, const gnutls_datum_t *data, gnutls_x509_crt_fmt_t format);
static const gnutls_datum_t *(VARGS *gnutls_certificate_get_peers)(gnutls_session_t session, unsigned int * list_size);
#endif
static gnutls_certificate_type_t (VARGS *gnutls_certificate_type_get)(gnutls_session_t session);
static void (VARGS *gnutls_free)(void * ptr);
static qboolean Init_GNUTLS(void)
{
dllhandle_t hmod;
@ -80,10 +139,35 @@ static qboolean Init_GNUTLS(void)
{(void**)&gnutls_global_init, "gnutls_global_init"},
{(void**)&gnutls_record_send, "gnutls_record_send"},
{(void**)&gnutls_record_recv, "gnutls_record_recv"},
{(void**)&gnutls_certificate_set_verify_function, "gnutls_certificate_set_verify_function"},
{(void**)&gnutls_session_get_ptr, "gnutls_session_get_ptr"},
{(void**)&gnutls_session_set_ptr, "gnutls_session_set_ptr"},
#if GNUTLS_VERSION_3_0_0_PLUS
{(void**)&gnutls_certificate_set_x509_system_trust, "gnutls_certificate_set_x509_system_trust"},
#else
{(void**)&gnutls_certificate_set_x509_trust_file, "gnutls_certificate_set_x509_trust_file"},
#endif
#if GNUTLS_VERSION_3_1_4_PLUS
{(void**)&gnutls_certificate_verify_peers3, "gnutls_certificate_verify_peers3"},
{(void**)&gnutls_certificate_verification_status_print, "gnutls_certificate_verification_status_print"},
#else
{(void**)&gnutls_certificate_verify_peers2, "gnutls_certificate_verify_peers2"},
{(void**)&gnutls_x509_crt_init, "gnutls_x509_crt_init"},
{(void**)&gnutls_x509_crt_import, "gnutls_x509_crt_import"},
{(void**)&gnutls_certificate_get_peers, "gnutls_certificate_get_peers"},
{(void**)&gnutls_x509_crt_check_hostname, "gnutls_x509_crt_check_hostname"},
#endif
{(void**)&gnutls_certificate_type_get, "gnutls_certificate_type_get"},
{(void**)&gnutls_free, "gnutls_free"},
{NULL, NULL}
};
#ifdef __CYGWIN__
hmod = Sys_LoadLibrary("cyggnutls-26.dll", functable);
#else
hmod = Sys_LoadLibrary("libgnutls.so.26", functable);
#endif
if (!hmod)
return false;
return true;
@ -104,6 +188,7 @@ typedef struct
vfsfile_t funcs;
vfsfile_t *stream;
char certname[512];
gnutls_session_t session;
qboolean handshaking;
@ -114,26 +199,121 @@ typedef struct
struct sslbuf incrypt;
} gnutlsfile_t;
static void SSL_Close(vfsfile_t *vfs)
#define CAFILE "/etc/ssl/certs/ca-certificates.crt"
static void QDECL SSL_Close(vfsfile_t *vfs)
{
gnutlsfile_t *file = (void*)vfs;
gnutls_bye (file->session, GNUTLS_SHUT_RDWR);
VFS_CLOSE(file->stream);
file->handshaking = true;
if (file->session)
gnutls_bye (file->session, GNUTLS_SHUT_RDWR);
file->session = NULL;
if (file->stream)
VFS_CLOSE(file->stream);
file->stream = NULL;
}
static int SSL_Read(struct vfsfile_s *f, void *buffer, int bytestoread)
static int QDECL SSL_CheckCert(gnutls_session_t session)
{
gnutlsfile_t *file = gnutls_session_get_ptr (session);
unsigned int certstatus;
cvar_t *tls_ignorecertificateerrors;
#if GNUTLS_VERSION_3_1_4_PLUS
if (gnutls_certificate_verify_peers3(session, file->certname, &certstatus) >= 0)
{
{
gnutls_datum_t out;
gnutls_certificate_type_t type;
if (certstatus == 0)
return 0;
type = gnutls_certificate_type_get (session);
if (gnutls_certificate_verification_status_print(certstatus, type, &out, 0) >= 0)
{
Con_Printf("%s: %s\n", file->certname, out.data);
gnutls_free(out.data);
#else
if (gnutls_certificate_verify_peers2(session, &certstatus) >= 0)
{
int certslen;
//grab the certificate
const gnutls_datum_t *const certlist = gnutls_certificate_get_peers(session, &certslen);
if (certlist && certslen)
{
//and make sure the hostname on it actually makes sense.
gnutls_x509_crt_t cert;
gnutls_x509_crt_init(&cert);
gnutls_x509_crt_import(cert, certlist, GNUTLS_X509_FMT_DER);
if (gnutls_x509_crt_check_hostname(cert, file->certname))
{
if (certstatus == 0)
return 0;
if (certstatus & GNUTLS_CERT_SIGNER_NOT_FOUND)
Con_Printf("%s: Certificate authority is not recognised\n", file->certname);
else if (certstatus & GNUTLS_CERT_INSECURE_ALGORITHM)
Con_Printf("%s: Certificate uses insecure algorithm\n", file->certname);
else if (certstatus & (GNUTLS_CERT_REVOCATION_DATA_ISSUED_IN_FUTURE|GNUTLS_CERT_REVOCATION_DATA_SUPERSEDED|GNUTLS_CERT_EXPIRED|GNUTLS_CERT_REVOKED|GNUTLS_CERT_NOT_ACTIVATED))
Con_Printf("%s: Certificate has expired or was revoked or not yet valid\n", file->certname);
else if (certstatus & GNUTLS_CERT_SIGNATURE_FAILURE)
Con_Printf("%s: Certificate signature failure\n", file->certname);
else
Con_Printf("%s: Certificate error\n", file->certname);
#endif
tls_ignorecertificateerrors = Cvar_Get("tls_ignorecertificateerrors", "0", CVAR_NOTFROMSERVER, "TLS");
if (tls_ignorecertificateerrors && tls_ignorecertificateerrors->ival)
{
Con_Printf("%s: Ignoring certificate errors (tls_ignorecertificateerrors is %i)\n", file->certname, tls_ignorecertificateerrors->ival);
return 0;
}
}
}
}
Con_DPrintf("%s: rejecting certificate\n", file->certname);
return GNUTLS_E_CERTIFICATE_ERROR;
}
//return 1 to read data.
//-1 or 0 for error or not ready
int SSL_DoHandshake(gnutlsfile_t *file)
{
int err;
//session was previously closed = error
if (!file->session)
return -1;
err = gnutls_handshake (file->session);
if (err < 0)
{ //non-fatal errors can just handshake again the next time the caller checks to see if there's any data yet
//(e_again or e_intr)
if (!gnutls_error_is_fatal(err))
return 0;
//certificate errors etc
// gnutls_perror (err);
SSL_Close(&file->funcs);
// Con_Printf("%s: abort\n", file->certname);
return -1;
}
file->handshaking = false;
return 1;
}
static int QDECL SSL_Read(struct vfsfile_s *f, void *buffer, int bytestoread)
{
gnutlsfile_t *file = (void*)f;
int read;
if (file->handshaking)
{
read = gnutls_handshake (file->session);
if (read == GNUTLS_E_AGAIN || read == GNUTLS_E_INTERRUPTED)
return 0;
if (read < 0)
gnutls_perror (read);
file->handshaking = false;
read = SSL_DoHandshake(file);
if (read <= 0)
return read;
}
read = gnutls_record_recv(file->session, buffer, bytestoread);
@ -151,19 +331,16 @@ static int SSL_Read(struct vfsfile_s *f, void *buffer, int bytestoread)
return -1; //closed by remote connection.
return read;
}
static int SSL_Write(struct vfsfile_s *f, const void *buffer, int bytestowrite)
static int QDECL SSL_Write(struct vfsfile_s *f, const void *buffer, int bytestowrite)
{
gnutlsfile_t *file = (void*)f;
int written;
if (file->handshaking)
{
written = gnutls_handshake (file->session);
if (written == GNUTLS_E_AGAIN || written == GNUTLS_E_INTERRUPTED)
return 0;
if (written < 0)
gnutls_perror (written);
file->handshaking = false;
written = SSL_DoHandshake(file);
if (written <= 0)
return written;
}
written = gnutls_record_send(file->session, buffer, bytestowrite);
@ -265,7 +442,7 @@ vfsfile_t *FS_OpenSSL(const char *hostname, vfsfile_t *source, qboolean server)
/* Need to enable anonymous KX specifically. */
const int kx_prio[] = {GNUTLS_KX_ANON_DH, 0};
const int cert_type_priority[3] = {GNUTLS_CRT_X509, GNUTLS_CRT_OPENPGP, 0};
const int cert_type_priority[3] = {GNUTLS_CRT_X509, 0};
{
@ -282,7 +459,13 @@ vfsfile_t *FS_OpenSSL(const char *hostname, vfsfile_t *source, qboolean server)
gnutls_anon_allocate_client_credentials (&anoncred);
gnutls_certificate_allocate_credentials (&xcred);
// gnutls_certificate_set_x509_trust_file (xcred, "ca.pem", GNUTLS_X509_FMT_PEM);
#ifdef GNUTLS_VERSION_3_0_0_PLUS
gnutls_certificate_set_x509_system_trust (xcred);
#else
gnutls_certificate_set_x509_trust_file (xcred, CAFILE, GNUTLS_X509_FMT_PEM);
#endif
gnutls_certificate_set_verify_function (xcred, SSL_CheckCert);
needinit = false;
}
@ -304,9 +487,13 @@ vfsfile_t *FS_OpenSSL(const char *hostname, vfsfile_t *source, qboolean server)
newf->funcs.Tell = SSL_Tell;
newf->funcs.seekingisabadplan = true;
Q_strncpyz(newf->certname, hostname, sizeof(newf->certname));
// Initialize TLS session
gnutls_init (&newf->session, GNUTLS_CLIENT);
gnutls_session_set_ptr(newf->session, newf);
// Use default priorities
gnutls_set_default_priority (newf->session);
if (anon)

File diff suppressed because it is too large Load Diff

View File

@ -65,7 +65,7 @@
};
};
#if !(_MSC_VER >= 1500)
#if !defined(in_addr6)
struct in6_addr
{
u_char s6_addr[16]; /* IPv6 address */
@ -206,8 +206,8 @@ struct icecandinfo_s
enum
{
ICE_HOST=0,
ICE_SRFLX=1,
ICE_PRFLX=2,
ICE_SRFLX=1, //Server Reflexive (from stun, etc)
ICE_PRFLX=2, //Peer Reflexive
ICE_RELAY=3,
} type; //says what sort of proxy is used.
char reladdr[64]; //when proxied, this is our local info
@ -220,7 +220,8 @@ enum iceproto_e
ICEP_INVALID, //not allowed..
ICEP_QWSERVER, //we're server side
ICEP_QWCLIENT, //we're client side
ICEP_VOICE //speex. requires client.
ICEP_VOICE, //speex. requires client.
ICEP_VIDEO //err... REALLY?!?!?
};
enum icemode_e
{
@ -248,3 +249,43 @@ typedef struct
} icefuncs_t;
extern icefuncs_t iceapi;
#endif
#define FTENET_ADDRTYPES 2
typedef struct ftenet_generic_connection_s {
char name[MAX_QPATH];
int (*GetLocalAddress)(struct ftenet_generic_connection_s *con, netadr_t *local, int adridx);
qboolean (*ChangeLocalAddress)(struct ftenet_generic_connection_s *con, const char *newaddress);
qboolean (*GetPacket)(struct ftenet_generic_connection_s *con);
qboolean (*SendPacket)(struct ftenet_generic_connection_s *con, int length, void *data, netadr_t *to);
void (*Close)(struct ftenet_generic_connection_s *con);
#ifdef HAVE_PACKET
int (*SetReceiveFDSet) (struct ftenet_generic_connection_s *con, fd_set *fdset); /*set for connections which have multiple sockets (ie: listening tcp connections)*/
#endif
netadrtype_t addrtype[FTENET_ADDRTYPES];
qboolean islisten;
#ifdef HAVE_PACKET
SOCKET thesocket;
#else
int thesocket;
#endif
} ftenet_generic_connection_t;
#define MAX_CONNECTIONS 8
typedef struct ftenet_connections_s
{
qboolean islisten;
ftenet_generic_connection_t *conn[MAX_CONNECTIONS];
} ftenet_connections_t;
void ICE_Tick(void);
qboolean ICE_WasStun(netsrc_t netsrc);
void QDECL ICE_AddLCandidateConn(ftenet_connections_t *col, netadr_t *addr, int type);
void QDECL ICE_AddLCandidateInfo(struct icestate_s *con, netadr_t *adr, int adrno, int type);
ftenet_connections_t *FTENET_CreateCollection(qboolean listen);
void FTENET_CloseCollection(ftenet_connections_t *col);
qboolean FTENET_AddToCollection(struct ftenet_connections_s *col, const char *name, const char *address, netadrtype_t addrtype, qboolean islisten);

View File

@ -41,6 +41,7 @@ typedef struct plugin_s {
int executestring;
#ifndef SERVERONLY
int consolelink;
int consolelinkmouseover;
int conexecutecommand;
int menufunction;
int sbarlevel[3]; //0 - main sbar, 1 - supplementry sbar sections (make sure these can be switched off), 2 - overlays (scoreboard). menus kill all.
@ -341,6 +342,8 @@ static qintptr_t VARGS Plug_ExportToEngine(void *offset, quintptr_t mask, const
#ifndef SERVERONLY
else if (!strcmp(name, "ConsoleLink"))
currentplug->consolelink = functionid;
else if (!strcmp(name, "ConsoleLinkMouseOver"))
currentplug->consolelinkmouseover = functionid;
else if (!strcmp(name, "ConExecuteCommand"))
currentplug->conexecutecommand = functionid;
else if (!strcmp(name, "MenuEvent"))
@ -950,6 +953,8 @@ qintptr_t VARGS Plug_FS_Open(void *offset, quintptr_t mask, const qintptr_t *arg
}
if (!strcmp(fname, "**plugconfig"))
f = FS_OpenVFS(va("%s.cfg", currentplug->name), mode, FS_ROOT);
else if (arg[2] == 2)
f = FS_OpenVFS(fname, mode, FS_GAMEONLY);
else
f = FS_OpenVFS(fname, mode, FS_GAME);
if (!f)
@ -1210,8 +1215,8 @@ void Plug_Load_f(void)
{
Con_Printf("Loads a plugin\n");
Con_Printf("plug_load [pluginpath]\n");
Con_Printf("example pluginpath: plugins/blah\n");
Con_Printf("will load blahx86.dll or blah.so\n");
Con_Printf("example pluginpath: blah\n");
Con_Printf("will load fteplug_blah"ARCH_CPU_POSTFIX ARCH_DL_POSTFIX" or $gamedir/plugins/blah.qvm\n");
return;
}
if (!Plug_Load(plugin, PLUG_EITHER))
@ -1321,7 +1326,8 @@ void Plug_Initialise(qboolean fromgamedir)
if (!fromgamedir)
{
FS_NativePath("", FS_BINARYPATH, nat, sizeof(nat));
Sys_EnumerateFiles(nat, "fteplug_*"ARCH_DL_POSTFIX, Plug_EnumeratedRoot, NULL, NULL);
Con_Printf("Loading plugins from %s\n", nat);
Sys_EnumerateFiles(nat, "fteplug_*" ARCH_CPU_POSTFIX ARCH_DL_POSTFIX, Plug_EnumeratedRoot, NULL, NULL);
}
if (fromgamedir)
{
@ -1380,8 +1386,28 @@ qboolean Plugin_ExecuteString(void)
}
#ifndef SERVERONLY
qboolean Plug_ConsoleLinkMouseOver(float x, float y, char *text, char *info)
{
qboolean result = false;
plugin_t *oldplug = currentplug;
for (currentplug = plugs; currentplug; currentplug = currentplug->next)
{
if (currentplug->consolelinkmouseover)
{
char buffer[2048];
Q_strncpyz(buffer, va("\"%s\" \"%s\"", text, info), sizeof(buffer));
Cmd_TokenizeString(buffer, false, false);
result = VM_Call(currentplug->vm, currentplug->consolelinkmouseover, *(int*)&(x), *(int*)&(y));
if (result)
break;
}
}
currentplug = oldplug;
return result;
}
qboolean Plug_ConsoleLink(char *text, char *info)
{
qboolean result = false;
plugin_t *oldplug = currentplug;
for (currentplug = plugs; currentplug; currentplug = currentplug->next)
{
@ -1390,11 +1416,13 @@ qboolean Plug_ConsoleLink(char *text, char *info)
char buffer[2048];
Q_strncpyz(buffer, va("\"%s\" \"%s\"", text, info), sizeof(buffer));
Cmd_TokenizeString(buffer, false, false);
VM_Call(currentplug->vm, currentplug->consolelink);
result = VM_Call(currentplug->vm, currentplug->consolelink);
if (result)
break;
}
}
currentplug = oldplug;
return false;
return result;
}
void Plug_SubConsoleCommand(console_t *con, char *line)

View File

@ -146,7 +146,7 @@ void PF_InitTempStrings(pubprogfuncs_t *prinst)
pr_tempstringsize.flags |= CVAR_NOSET;
if (pr_tempstringcount.value >= 2)
prinst->tempstringbase = prinst->AddString(prinst, "", MAXTEMPBUFFERLEN*MAX_TEMPSTRS);
prinst->tempstringbase = prinst->AddString(prinst, "", MAXTEMPBUFFERLEN*MAX_TEMPSTRS, false);
else
prinst->tempstringbase = 0;
prinst->tempstringnum = 0;
@ -4566,7 +4566,7 @@ void PR_AutoCvar(pubprogfuncs_t *prinst, cvar_t *var)
}
}
void PDECL PR_FoundAutoCvarGlobal(pubprogfuncs_t *progfuncs, char *name, eval_t *val, etype_t type)
void PDECL PR_FoundAutoCvarGlobal(pubprogfuncs_t *progfuncs, char *name, eval_t *val, etype_t type, void *ctx)
{
cvar_t *var;
char *vals;
@ -4605,9 +4605,54 @@ void PDECL PR_FoundAutoCvarGlobal(pubprogfuncs_t *progfuncs, char *name, eval_t
PR_AutoCvarApply(progfuncs, val, type, var);
}
void PR_AutoCvarSetup(pubprogfuncs_t *prinst)
void PDECL PR_FoundDoTranslateGlobal(pubprogfuncs_t *progfuncs, char *name, eval_t *val, etype_t type, void *ctx)
{
prinst->FindPrefixGlobals (prinst, "autocvar_", PR_FoundAutoCvarGlobal);
const char *olds;
const char *news;
if ((type & ~DEF_SAVEGLOBAL) != ev_string)
return;
olds = PR_GetString(progfuncs, val->string);
news = PO_GetText(ctx, olds);
if (news != olds)
val->string = PR_NewString(progfuncs, news, 0);
}
//called after each progs is loaded
void PR_ProgsAdded(pubprogfuncs_t *prinst, int newprogs, const char *modulename)
{
vfsfile_t *f = NULL;
char lang[64], *h;
extern cvar_t language;
if (newprogs == -1)
return;
if (*language.string)
{
Q_strncpyz(lang, language.string, sizeof(lang));
while ((h = strchr(lang, '-')))
*h = '_';
for(;;)
{
if (!*lang)
break;
f = FS_OpenVFS(va("%s.%s.po", modulename, lang), "rb", FS_GAME);
if (f)
break;
h = strchr(lang, '_');
if (h)
*h = 0;
else
break;
}
}
if (f)
{
void *pofile = PO_Load(f);
prinst->FindPrefixGlobals (prinst, newprogs, "dotranslate_", PR_FoundDoTranslateGlobal, pofile);
PO_Close(pofile);
}
prinst->FindPrefixGlobals (prinst, newprogs, "autocvar_", PR_FoundAutoCvarGlobal, NULL);
}
lh_extension_t QSG_Extensions[] = {

View File

@ -174,7 +174,7 @@ void QCBUILTIN PF_stoh (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
void QCBUILTIN PF_htos (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void PR_fclose_progs (pubprogfuncs_t *prinst);
char *PF_VarString (pubprogfuncs_t *prinst, int first, struct globalvars_s *pr_globals);
void PR_AutoCvarSetup(pubprogfuncs_t *prinst);
void PR_ProgsAdded(pubprogfuncs_t *prinst, int newprogs, const char *modulename);
void PR_AutoCvar(pubprogfuncs_t *prinst, cvar_t *var);
void QCBUILTIN PF_numentityfields (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_entityfieldname (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);

View File

@ -2,7 +2,6 @@
static char *defaultlanguagetext =
"STL_LANGUAGENAME \"English\"\n"
"TL_NL \"\\n\"\n"
"TL_STNL \"%s\\n\"\n"
"STL_CLIENTCONNECTED \"client %s connected\\n\"\n"
"STL_SPECTATORCONNECTED \"spectator %s connected\\n\"\n"
@ -262,7 +261,8 @@ static char *defaultlanguagetext =
cvar_t language = SCVAR("language", "en-gb");
char sys_language[64] = "";
cvar_t language = SCVAR("language", sys_language);
char lastlang[9];
typedef struct trans_s {
@ -551,7 +551,7 @@ void TL_ParseLanguage (char *name, char *data, int num) //this is one of the fir
break;
}
s = COM_ParseCString(s, com_token, sizeof(com_token));
s = COM_ParseCString(s, com_token, sizeof(com_token), NULL);
if (i == STL_MAXSTL) //silently ignore - allow other servers or clients to add stuff
continue;
@ -850,6 +850,7 @@ char *T_GetString(int num)
//#endif
#ifndef SERVERONLY
//for hexen2's objectives and stuff.
static char *info_strings_list;
static char **info_strings_table;
static int info_strings_count;
@ -915,3 +916,128 @@ char *T_GetInfoString(int num)
}
#endif
struct poline_s
{
bucket_t buck;
struct poline_s *next;
char *orig;
char *translated;
};
struct po_s
{
hashtable_t hash;
struct poline_s *lines;
};
const char *PO_GetText(struct po_s *po, const char *msg)
{
struct poline_s *line;
line = Hash_Get(&po->hash, msg);
if (line)
return line->translated;
return msg;
}
static void PO_AddText(struct po_s *po, const char *orig, const char *trans)
{
size_t olen = strlen(orig)+1;
size_t tlen = strlen(trans)+1;
struct poline_s *line = Z_Malloc(sizeof(*line)+olen+tlen);
memcpy(line+1, orig, olen);
orig = (const char*)(line+1);
line->translated = (char*)(line+1)+olen;
memcpy(line->translated, trans, tlen);
trans = (const char*)(line->translated);
Hash_Add(&po->hash, orig, line, &line->buck);
}
struct po_s *PO_Load(vfsfile_t *file)
{
struct po_s *po;
unsigned int buckets = 1024;
char *in, *end;
int inlen;
char msgid[32768];
char msgstr[32768];
po = Z_Malloc(sizeof(*po) + Hash_BytesForBuckets(buckets));
Hash_InitTable(&po->hash, buckets, po+1);
inlen = file?VFS_GETLEN(file):0;
in = BZ_Malloc(inlen+1);
if (file)
VFS_READ(file, in, inlen);
in[inlen] = 0;
if (file)
VFS_CLOSE(file);
end = in + inlen;
while(in < end)
{
while(*in == ' ' || *in == '\n' || *in == '\r' || *in == '\t')
in++;
if (*in == '#')
{
while (*in && *in != '\n')
in++;
}
else if (!strncmp(in, "msgid", 5) && (in[5] == ' ' || in[5] == '\t' || in[5] == '\r' || in[5] == '\n'))
{
size_t start = 0;
size_t ofs = 0;
in += 5;
while(1)
{
while(*in == ' ' || *in == '\n' || *in == '\r' || *in == '\t')
in++;
if (*in == '\"')
{
in = COM_ParseCString(in, msgid+start, sizeof(msgid) - start, &ofs);
start += ofs;
}
else
break;
}
}
else if (!strncmp(in, "msgstr", 6) && (in[6] == ' ' || in[6] == '\t' || in[6] == '\r' || in[6] == '\n'))
{
size_t start = 0;
size_t ofs = 0;
in += 6;
while(1)
{
while(*in == ' ' || *in == '\n' || *in == '\r' || *in == '\t')
in++;
if (*in == '\"')
{
in = COM_ParseCString(in, msgstr+start, sizeof(msgstr) - start, &ofs);
start += ofs;
}
else
break;
}
// if (*msgid && start)
PO_AddText(po, msgid, msgstr);
}
else
{
//some sort of junk?
in++;
while (*in && *in != '\n')
in++;
}
}
return po;
}
void PO_Close(struct po_s *po)
{
while(po->lines)
{
struct poline_s *r = po->lines;
po->lines = r->next;
Z_Free(r);
}
Z_Free(po);
}

View File

@ -1,16 +1,12 @@
#ifdef TRANSLATE_H
NAME(STL_LANGUAGENAME)
NAME(TL_NL)
NAME(TL_STNL)
NAME(STL_CLIENTCONNECTED)
NAME(STL_SPECTATORCONNECTED)
NAME(STL_RECORDEDCLIENTCONNECTED)
NAME(STL_RECORDEDSPECTATORCONNECTED)
NAME(STL_CLIENTWASBANNED)
NAME(STL_YOUWEREBANNED)
NAME(STL_YOUAREBANNED)
NAME(STL_CLIENTTIMEDOUT)
NAME(STL_LOADZOMIBETIMEDOUT)
NAME(STL_CLIENTWASKICKED)
@ -25,13 +21,11 @@
NAME(STL_CLIENTISCUFFEDPERMANENTLY)
NAME(STL_CLIENTISCUFFED)
NAME(STL_CLIENTISSTILLCUFFED)
NAME(STL_YOUWERECUFFED)
NAME(STL_YOUARNTCUFFED)
NAME(STL_CLIENTISCRIPPLEDPERMANENTLY)
NAME(STL_CLIENTISCRIPPLED)
NAME(STL_CLIENTISSTILLCRIPPLED)
NAME(STL_YOUWERECLIPPLED)
NAME(STL_YOUARNTCRIPPLED)
NAME(STL_CLIENTISMUTEDPERMANENTLY)
@ -42,7 +36,6 @@
NAME(STL_NONAMEASMUTE)
NAME(STL_MUTEDVOTE)
NAME(STL_MUTEDCHAT)
NAME(STL_FLOODPROTACTIVE)
NAME(STL_FLOODPROTTIME)
NAME(STL_BUFFERPROTECTION)
@ -54,7 +47,6 @@
NAME(STL_POSSIBLEMODELCHEAT)
NAME(STL_MAPCHEAT)
NAME(STL_INVALIDTRACKCLIENT)
NAME(STL_BADNAME)
NAME(STL_CLIENTNAMECHANGE)
NAME(STL_SERVERPAUSED)
NAME(STL_UPLOADDENIED)
@ -65,11 +57,9 @@
NAME(STL_CLIENTPAUSED)
NAME(STL_CLIENTUNPAUSED)
NAME(STL_CLIENTLESSUNPAUSE)
NAME(STL_CURRENTRATE)
NAME(STL_RATESETTO)
NAME(STL_CURRENTMSGLEVEL)
NAME(STL_MSGLEVELSET)
NAME(STL_GAMESAVED)
NAME(STL_CLIENTDROPPED)
NAME(STL_SNAPREFUSED)
@ -80,7 +70,6 @@
NAME(STL_SPEEDCHEATPOSSIBLE)
NAME(STL_INITED)
NAME(STL_BACKBUFSET)
NAME(STL_MESSAGEOVERFLOW)
@ -88,14 +77,12 @@
NAME(STL_BUILDINGPHS)
NAME(STL_PHSINFO)
NAME(STL_BREAKSTATEMENT)
NAME(STL_BADSPRINT)
NAME(STL_NOPRECACHE)
NAME(STL_CANTFREEWORLD)
NAME(STL_CANTFREEPLAYERS)
NAME(STL_COMPILEROVER)
NAME(STL_EDICTWASFREE)
NAME(STL_NOFREEEDICTS)
NAME(STL_NEEDCHEATPARM)
NAME(STL_USERDOESNTEXIST)
@ -143,25 +130,13 @@
NAME(TL_SHAREWAREVERSION)
NAME(TL_REGISTEREDVERSION)
NAME(TL_CURRENTSEARCHPATH)
NAME(TL_SERACHPATHISPACK)
NAME(TL_SERACHPATHISZIP)
NAME(TL_COMPRESSEDFILEOPENFAILED)
NAME(TL_ADDEDPACKFILE)
NAME(TL_COULDNTOPENZIP)
NAME(TL_ADDEDZIPFILE)
NAME(TL_GAMEDIRAINTPATH)
NAME(TL_KEYHASSLASH)
NAME(TL_KEYHASQUOTE)
NAME(TL_KEYTOOLONG)
NAME(TL_INFOSTRINGTOOLONG)
NAME(TL_STARKEYPROTECTED)
NAME(TL_KEYHASNOVALUE)
NAME(TL_OVERSIZEPACKETFROM)
@ -180,28 +155,16 @@
NAME(STL_SERVERSPAWNED)
NAME(TL_EXEDATETIME)
NAME(TL_HEAPSIZE)
NAME(TL_VERSION)
//savegame.c
NAME(STL_SAVESYNTAX)
NAME(STL_NORELATIVEPATHS)
NAME(STL_SAVEGAMETO)
NAME(STL_ERRORCOULDNTOPEN)
NAME(STL_SAVEDONE)
NAME(STL_LOADSYNTAX)
NAME(STL_LOADGAMEFROM)
NAME(STL_BADSAVEVERSION)
NAME(STL_LOADFAILED)
//sv_ccmds.c
NAME(STL_NOMASTERMODE)
NAME(STL_MASTERAT)
NAME(STL_SENDINGPING)
NAME(STL_SHUTTINGDOWN)
NAME(STL_LOGGINGOFF)
NAME(STL_LOGGINGTO)
NAME(STL_FLOGGINGOFF)
NAME(STL_FLOGGINGFAILED)
NAME(STL_FLOGGINGTO)
@ -212,7 +175,6 @@
NAME(STL_LOCALINFOSETTINGS)
NAME(STL_LOCALINFOSYNTAX)
NAME(STL_USERINFOSYNTAX)
NAME(STL_NONEGATIVEVALUES)
NAME(STL_CURRENTGAMEDIR)
NAME(STL_SVGAMEDIRUSAGE)
NAME(STL_GAMEDIRCANTBEPATH)
@ -221,9 +183,6 @@
NAME(STL_SNAPREQUEST)
NAME(STL_SNAPUSAGE)
NAME(TLC_VERSIONST)
NAME(TLC_BADSERVERADDRESS)
NAME(TLC_ILLEGALSERVERADDRESS)
NAME(TLC_CONNECTINGTO)
@ -243,7 +202,6 @@
NAME(TLC_SYNTAX_FULLINFO)
NAME(TLC_SYNTAX_SETINFO)
NAME(TLC_PACKET_SYNTAX)
NAME(TLC_BADADDRESS)
NAME(TLC_CHANGINGMAP)
NAME(TLC_RECONNECTING)
NAME(TLC_RECONNECT_NOSERVER)
@ -256,18 +214,15 @@
NAME(TLC_LOCALID_NOTSET)
NAME(TLC_LOCALID_BAD)
NAME(TLC_A2C_PRINT)
NAME(TLC_A2A_PING)
NAME(TLC_S2C_CHALLENGE)
NAME(TLC_CONLESSPACKET_UNKNOWN)
NAME(TL_RUNTPACKET)
NAME(TLC_SERVERTIMEOUT)
NAME(TLC_CONNECTFIRST)
NAME(TLC_SYNTAX_DOWNLOAD)
NAME(TLC_REQUIRESSERVERMOD)
NAME(TLC_CLIENTCON_ERROR_ENDGAME)
NAME(TLC_HOSTFATALERROR)
NAME(TLC_CONFIGCFG_WRITEFAILED)
NAME(TLC_HOSTSPEEDSOUTPUT)
NAME(TLC_QUAKEWORLD_INITED)
NAME(TLC_DEDICATEDCANNOTCONNECT)
NAME(TLC_Q2CONLESSPACKET_UNKNOWN)
@ -275,23 +230,17 @@
NAME(TL_NORELATIVEPATHS)
NAME(TL_NODOWNLOADINDEMO)
NAME(TL_DOWNLOADINGFILE)
NAME(TLC_CHECKINGMODELS)
NAME(TLC_CHECKINGSOUNDS)
NAME(TL_FILENOTFOUND)
NAME(TL_CLS_DOWNLOAD_ISSET)
NAME(TL_FAILEDTOOPEN)
NAME(TL_RENAMEFAILED)
NAME(TL_UPLOADCOMPLEATE)
NAME(TL_FTEEXTENSIONS)
NAME(TLC_LINEBREAK_NEWLEVEL)
NAME(TLC_PC_PS_NL)
NAME(TLC_GOTSVDATAPACKET)
NAME(TLC_BAD_MAXCLIENTS)
NAME(TLC_TOOMANYMODELPRECACHES)
NAME(TLC_TOOMANYSOUNDPRECACHES)
NAME(TLC_PARSESTATICWITHNOMAP)
NAME(TL_FILE_X_MISSING)
NAME(TL_GETACLIENTPACK)
NAME(TLC_LINEBREAK_MINUS)
NAME(TL_INT_SPACE)

View File

@ -70,6 +70,7 @@ qboolean Plug_ChatMessage(char *buffer, int talkernum, int tpflags);
void Plug_Command_f(void);
int Plug_ConnectionlessClientPacket(char *buffer, int size);
qboolean Plug_ConsoleLink(char *text, char *info);
qboolean Plug_ConsoleLinkMouseOver(float x, float y, char *text, char *info);
void Plug_DrawReloadImages(void);
void Plug_Initialise(qboolean fromgamedir);
void Plug_Shutdown(qboolean preliminary);

File diff suppressed because it is too large Load Diff

View File

@ -6,6 +6,8 @@
extern ID3D11Device *pD3DDev11;
extern ID3D11DeviceContext *d3ddevctx;
//FIXME: need support for cubemaps.
typedef struct d3dtexture_s
{
texcom_t com;
@ -535,6 +537,53 @@ void D3D11_UploadLightmap(lightmapinfo_t *lm)
lm->lightmap_texture = ToTexID(tex);
}
static void genNormalMap(unsigned int *nmap, qbyte *pixels, int w, int h, float scale)
{
int i, j, wr, hr;
unsigned char r, g, b;
float sqlen, reciplen, nx, ny, nz;
const float oneOver255 = 1.0f/255.0f;
float c, cx, cy, dcx, dcy;
wr = w;
hr = h;
for (i=0; i<h; i++)
{
for (j=0; j<w; j++)
{
/* Expand [0,255] texel values to the [0,1] range. */
c = pixels[i*wr + j] * oneOver255;
/* Expand the texel to its right. */
cx = pixels[i*wr + (j+1)%wr] * oneOver255;
/* Expand the texel one up. */
cy = pixels[((i+1)%hr)*wr + j] * oneOver255;
dcx = scale * (c - cx);
dcy = scale * (c - cy);
/* Normalize the vector. */
sqlen = dcx*dcx + dcy*dcy + 1;
reciplen = 1.0f/(float)sqrt(sqlen);
nx = dcx*reciplen;
ny = -dcy*reciplen;
nz = reciplen;
/* Repack the normalized vector into an RGB unsigned qbyte
vector in the normal map image. */
r = (qbyte) (128 + 127*nx);
g = (qbyte) (128 + 127*ny);
b = (qbyte) (128 + 127*nz);
/* The highest resolution mipmap level always has a
unit length magnitude. */
nmap[i*w+j] = LittleLong ((pixels[i*wr + j] << 24)|(b << 16)|(g << 8)|(r)); // <AWE> Added support for big endian.
}
}
}
texid_t D3D11_LoadTexture (char *identifier, int width, int height, enum uploadfmt fmt, void *data, unsigned int flags)
{
d3d11texture_t *tex;
@ -579,6 +628,24 @@ texid_t D3D11_LoadTexture (char *identifier, int width, int height, enum uploadf
switch (fmt)
{
case TF_HEIGHT8PAL:
{
extern cvar_t r_shadow_bumpscale_basetexture;
unsigned int *norm = malloc(width*height*4);
genNormalMap(norm, data, width, height, r_shadow_bumpscale_basetexture.value);
D3D11_LoadTexture_32(tex, norm, width, height, flags);
free(norm);
return ToTexID(tex);
}
case TF_HEIGHT8:
{
extern cvar_t r_shadow_bumpscale_basetexture;
unsigned int *norm = malloc(width*height*4);
genNormalMap(norm, data, width, height, r_shadow_bumpscale_basetexture.value);
D3D11_LoadTexture_32(tex, norm, width, height, flags);
free(norm);
return ToTexID(tex);
}
case TF_SOLID8:
case TF_TRANS8:
case TF_H2_T7G1:
@ -592,9 +659,6 @@ texid_t D3D11_LoadTexture (char *identifier, int width, int height, enum uploadf
case TF_RGBA32:
D3D11_LoadTexture_32(tex, data, width, height, flags);
return ToTexID(tex);
case TF_HEIGHT8PAL:
OutputDebugString(va("D3D11_LoadTexture doesn't support fmt TF_HEIGHT8PAL (%s)\n", identifier));
return r_nulltex;
default:
OutputDebugString(va("D3D11_LoadTexture doesn't support fmt %i (%s)\n", fmt, identifier));
return r_nulltex;
@ -634,4 +698,115 @@ texid_t D3D11_LoadTexture8Pal24 (char *identifier, int width, int height, qbyte
return D3D11_LoadTexture8Pal32(identifier, width, height, data, (qbyte*)pal32, flags);
}
#ifdef RTLIGHTS
static const int shadowfmt = 1;
static const int shadowfmts[][3] =
{
//sampler, creation, render
{DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_D24_UNORM_S8_UINT},
{DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_D16_UNORM},
{DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM}
};
d3d11texture_t shadowmap_texture[2];
ID3D11DepthStencilView *shadowmap_dsview[2];
ID3D11RenderTargetView *shadowmap_rtview[2];
texid_t D3D11_GetShadowMap(int id)
{
d3d11texture_t *tex = &shadowmap_texture[id];
texid_t tid;
tid.ref = &tex->com;
if (!tex->view)
{
D3D11_SHADER_RESOURCE_VIEW_DESC desc;
desc.Format = shadowfmts[shadowfmt][0];
desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
desc.Texture2D.MostDetailedMip = 0;
desc.Texture2D.MipLevels = -1;
ID3D11Device_CreateShaderResourceView(pD3DDev11, (ID3D11Resource *)tex->tex2d, &desc, &tex->view);
}
tid.ptr = NULL;
return tid;
}
void D3D11_TerminateShadowMap(void)
{
int i;
for (i = 0; i < sizeof(shadowmap_texture)/sizeof(shadowmap_texture[0]); i++)
{
if (shadowmap_dsview[i])
ID3D11DepthStencilView_Release(shadowmap_dsview[i]);
shadowmap_dsview[i] = NULL;
if (shadowmap_texture[i].tex2d)
ID3D11DepthStencilView_Release(shadowmap_texture[i].tex2d);
shadowmap_texture[i].tex2d = NULL;
}
}
void D3D11_BeginShadowMap(int id, int w, int h)
{
D3D11_TEXTURE2D_DESC texdesc;
HRESULT hr;
if (!shadowmap_dsview[id] && !shadowmap_rtview[id])
{
memset(&texdesc, 0, sizeof(texdesc));
texdesc.Width = w;
texdesc.Height = h;
texdesc.MipLevels = 1;
texdesc.ArraySize = 1;
texdesc.Format = shadowfmts[shadowfmt][1];
texdesc.SampleDesc.Count = 1;
texdesc.SampleDesc.Quality = 0;
texdesc.Usage = D3D11_USAGE_DEFAULT;
texdesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
texdesc.CPUAccessFlags = 0;
texdesc.MiscFlags = 0;
if (shadowfmt == 2)
texdesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
// Create the texture
hr = ID3D11Device_CreateTexture2D(pD3DDev11, &texdesc, NULL, &shadowmap_texture[id].tex2d);
if (FAILED(hr))
Sys_Error("Failed to create depth texture\n");
if (shadowfmt == 2)
{
hr = ID3D11Device_CreateRenderTargetView(pD3DDev11, (ID3D11Resource *)shadowmap_texture[id].tex2d, NULL, &shadowmap_rtview[id]);
}
else
{
D3D11_DEPTH_STENCIL_VIEW_DESC rtdesc;
rtdesc.Format = shadowfmts[shadowfmt][2];
rtdesc.Flags = 0;
rtdesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
rtdesc.Texture2D.MipSlice = 0;
hr = ID3D11Device_CreateDepthStencilView(pD3DDev11, (ID3D11Resource *)shadowmap_texture[id].tex2d, &rtdesc, &shadowmap_dsview[id]);
}
if (FAILED(hr))
Sys_Error("ID3D11Device_CreateDepthStencilView failed\n");
}
if (shadowfmt == 2)
{
float colours[4] = {0, 1, 0, 0};
colours[0] = frandom();
colours[1] = frandom();
colours[2] = frandom();
ID3D11DeviceContext_OMSetRenderTargets(d3ddevctx, 1, &shadowmap_rtview[id], shadowmap_dsview[id]);
ID3D11DeviceContext_ClearRenderTargetView(d3ddevctx, shadowmap_rtview[id], colours);
}
else
{
ID3D11DeviceContext_OMSetRenderTargets(d3ddevctx, 0, NULL, shadowmap_dsview[id]);
ID3D11DeviceContext_ClearDepthStencilView(d3ddevctx, shadowmap_dsview[id], D3D11_CLEAR_DEPTH, 1.0f, 0);
}
}
void D3D11_EndShadowMap(void)
{
extern ID3D11RenderTargetView *fb_backbuffer;
extern ID3D11DepthStencilView *fb_backdepthstencil;
ID3D11DeviceContext_OMSetRenderTargets(d3ddevctx, 1, &fb_backbuffer, fb_backdepthstencil);
}
#endif
#endif

View File

@ -31,7 +31,6 @@ DECLARE_INTERFACE_(INTERFACE, IUnknown)
#undef INTERFACE
#define INTERFACE ID3DBlob
DECLARE_INTERFACE_(INTERFACE, IUnknown)
{
STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE;
@ -40,6 +39,10 @@ DECLARE_INTERFACE_(INTERFACE, IUnknown)
STDMETHOD_(LPVOID, GetBufferPointer)(THIS) PURE;
STDMETHOD_(SIZE_T, GetBufferSize)(THIS) PURE;
};
#define ID3DBlob_GetBufferPointer(b) b->lpVtbl->GetBufferPointer(b)
#define ID3DBlob_Release(b) b->lpVtbl->Release(b)
#define ID3DBlob_GetBufferSize(b) b->lpVtbl->GetBufferSize(b)
#undef INTERFACE
HRESULT (WINAPI *pD3DCompile) (
LPCVOID pSrcData,
@ -57,20 +60,34 @@ HRESULT (WINAPI *pD3DCompile) (
static dllhandle_t *shaderlib;
void D3D11Shader_Init(void)
D3D_FEATURE_LEVEL d3dfeaturelevel;
qboolean D3D11Shader_Init(unsigned int flevel)
{
dllfunction_t funcs[] =
//FIXME: if the feature level is below 10, make sure the compiler supports all the right targets etc
int ver;
dllfunction_t funcsold[] =
{
{(void**)&pD3DCompile, "D3DCompileFromMemory"},
{NULL,NULL}
};
dllfunction_t funcsnew[] =
{
{(void**)&pD3DCompile, "D3DCompile"},
{NULL,NULL}
};
for (ver = 43; ver >= 33; ver--)
{
shaderlib = Sys_LoadLibrary(va("D3dcompiler_%i.dll", ver), (ver>=40)?funcsnew:funcsold);
if (shaderlib)
break;
}
if (!shaderlib)
shaderlib = Sys_LoadLibrary("D3dcompiler_34.dll", funcs);
return false;
if (!shaderlib)
return;
d3dfeaturelevel = flevel;
return true;
}
HRESULT STDMETHODCALLTYPE d3dinclude_Close(ID3DInclude *this, LPCVOID pData)
@ -92,6 +109,7 @@ HRESULT STDMETHODCALLTYPE d3dinclude_Open(ID3DInclude *this, D3D_INCLUDE_TYPE In
"float3 e_light_ambient; float pad1;\n"
"float3 e_light_dir; float pad2;\n"
"float3 e_light_mul; float pad3;\n"
"float4 e_lmscale[4];\n"
"};\n"
"cbuffer fteviewdefs : register(b1)\n"
"{\n"
@ -99,6 +117,24 @@ HRESULT STDMETHODCALLTYPE d3dinclude_Open(ID3DInclude *this, D3D_INCLUDE_TYPE In
"matrix m_projection;\n"
"float3 v_eyepos; float v_time;\n"
"};\n"
"cbuffer ftelightdefs : register(b2)\n"
"{\n"
"matrix l_cubematrix;\n"
"float3 l_lightposition; float padl1;\n"
"float3 l_colour; float padl2;\n"
"float3 l_lightcolourscale;float l_lightradius;\n"
"float4 l_shadowmapproj;\n"
"float2 l_shadowmapscale; float2 padl3;\n"
"};\n"
;
*ppData = strdup(defstruct);
*pBytes = strlen(*ppData);
return S_OK;
}
if (!strcmp(pFileName, "sys/skeletal.h"))
{
static const char *defstruct =
""
;
*ppData = strdup(defstruct);
*pBytes = strlen(*ppData);
@ -132,12 +168,60 @@ typedef struct
byte_vec4_t colorsb;
} vbovdata_t;
void D3D11Shader_DeleteProgram(program_t *prog)
{
ID3D11InputLayout *layout;
ID3D11PixelShader *frag;
ID3D11VertexShader *vert;
int permu;
for (permu = 0; permu < PERMUTATIONS; permu++)
{
vert = prog->permu[permu].handle.hlsl.vert;
frag = prog->permu[permu].handle.hlsl.frag;
layout = prog->permu[permu].handle.hlsl.layout;
if (vert)
ID3D11VertexShader_Release(vert);
if (frag)
ID3D11PixelShader_Release(frag);
if (layout)
ID3D11InputLayout_Release(layout);
}
}
qboolean D3D11Shader_CreateProgram (program_t *prog, const char *name, int permu, char **precompilerconstants, char *vert, char *frag)
{
char *vsformat;
char *fsformat;
D3D_SHADER_MACRO defines[64];
ID3DBlob *vcode = NULL, *fcode = NULL, *errors = NULL;
qboolean success = false;
if (d3dfeaturelevel >= D3D_FEATURE_LEVEL_11_0) //and 11.1
{
vsformat = "vs_5_0";
fsformat = "ps_5_0";
}
else if (d3dfeaturelevel >= D3D_FEATURE_LEVEL_10_1)
{
vsformat = "vs_4_1";
fsformat = "ps_4_1";
}
else if (d3dfeaturelevel >= D3D_FEATURE_LEVEL_10_0)
{
vsformat = "vs_4_0";
fsformat = "ps_4_0";
}
else if (d3dfeaturelevel >= D3D_FEATURE_LEVEL_9_3)
{ //dx10-compatible output for 9.3 hardware
vsformat = "vs_4_0_level_9_3";
fsformat = "ps_4_0_level_9_3";
}
else
{ //dx10-compatible output for 9.1|9.2 hardware
vsformat = "vs_4_0_level_9_1";
fsformat = "ps_4_0_level_9_1";
}
prog->permu[permu].handle.hlsl.vert = NULL;
prog->permu[permu].handle.hlsl.frag = NULL;
prog->permu[permu].handle.hlsl.layout = NULL;
@ -159,10 +243,17 @@ qboolean D3D11Shader_CreateProgram (program_t *prog, const char *name, int permu
defines[consts].Definition = __DATE__;
consts++;
defines[consts].Name = Z_StrDup("LEVEL");
defines[consts].Definition = Z_StrDup(va("0x%x", d3dfeaturelevel));
consts++;
for (; *precompilerconstants; precompilerconstants++)
{
defines[consts].Name = NULL;
defines[consts].Definition = NULL;
char *t = *precompilerconstants;
t = COM_Parse(t);
t = COM_Parse(t);
defines[consts].Name = Z_StrDup(com_token);
defines[consts].Definition = t?Z_StrDup(t):NULL;
consts++;
}
@ -172,36 +263,40 @@ qboolean D3D11Shader_CreateProgram (program_t *prog, const char *name, int permu
success = true;
defines[0].Name = "VERTEX_SHADER";
if (FAILED(pD3DCompile(vert, strlen(vert), name, defines, &myd3dinclude, "main", "vs_4_0", 0, 0, &vcode, &errors)))
if (FAILED(pD3DCompile(vert, strlen(vert), name, defines, &myd3dinclude, "main", vsformat, 0, 0, &vcode, &errors)))
success = false;
else
{
if (FAILED(ID3D11Device_CreateVertexShader(pD3DDev11, vcode->lpVtbl->GetBufferPointer(vcode), vcode->lpVtbl->GetBufferSize(vcode), NULL, (ID3D11VertexShader**)&prog->permu[permu].handle.hlsl.vert)))
if (FAILED(ID3D11Device_CreateVertexShader(pD3DDev11, ID3DBlob_GetBufferPointer(vcode), ID3DBlob_GetBufferSize(vcode), NULL, (ID3D11VertexShader**)&prog->permu[permu].handle.hlsl.vert)))
success = false;
}
if (errors)
{
char *messages = errors->lpVtbl->GetBufferPointer(errors);
Con_Printf("%s", messages);
errors->lpVtbl->Release(errors);
char *messages = ID3DBlob_GetBufferPointer(errors);
Con_Printf("vertex shader:\n%s", messages);
ID3DBlob_Release(errors);
}
defines[0].Name = "FRAGMENT_SHADER";
if (FAILED(pD3DCompile(frag, strlen(frag), name, defines, &myd3dinclude, "main", "ps_4_0", 0, 0, &fcode, &errors)))
if (FAILED(pD3DCompile(frag, strlen(frag), name, defines, &myd3dinclude, "main", fsformat, 0, 0, &fcode, &errors)))
success = false;
else
{
if (FAILED(ID3D11Device_CreatePixelShader(pD3DDev11, fcode->lpVtbl->GetBufferPointer(fcode), fcode->lpVtbl->GetBufferSize(fcode), NULL, (ID3D11PixelShader**)&prog->permu[permu].handle.hlsl.frag)))
if (FAILED(ID3D11Device_CreatePixelShader(pD3DDev11, ID3DBlob_GetBufferPointer(fcode), ID3DBlob_GetBufferSize(fcode), NULL, (ID3D11PixelShader**)&prog->permu[permu].handle.hlsl.frag)))
success = false;
}
if (errors)
{
char *messages = errors->lpVtbl->GetBufferPointer(errors);
Con_Printf("%s", messages);
errors->lpVtbl->Release(errors);
char *messages = ID3DBlob_GetBufferPointer(errors);
Con_Printf("fragment shader:\n%s", messages);
ID3DBlob_Release(errors);
}
while(consts-->2)
{
Z_Free((void*)defines[consts].Name);
Z_Free((void*)defines[consts].Definition);
}
if (success)
{
@ -291,7 +386,7 @@ qboolean D3D11Shader_CreateProgram (program_t *prog, const char *name, int permu
decl[elements].InstanceDataStepRate = 0;
elements++;
*/
if (FAILED(ID3D11Device_CreateInputLayout(pD3DDev11, decl, elements, vcode->lpVtbl->GetBufferPointer(vcode), vcode->lpVtbl->GetBufferSize(vcode), (ID3D11InputLayout**)&prog->permu[permu].handle.hlsl.layout)))
if (FAILED(ID3D11Device_CreateInputLayout(pD3DDev11, decl, elements, ID3DBlob_GetBufferPointer(vcode), ID3DBlob_GetBufferSize(vcode), (ID3D11InputLayout**)&prog->permu[permu].handle.hlsl.layout)))
{
Con_Printf("HLSL Shader %s requires unsupported inputs\n", name);
success = false;
@ -299,43 +394,14 @@ qboolean D3D11Shader_CreateProgram (program_t *prog, const char *name, int permu
}
if (vcode)
vcode->lpVtbl->Release(vcode);
ID3DBlob_Release(vcode);
if (fcode)
fcode->lpVtbl->Release(fcode);
ID3DBlob_Release(fcode);
}
return success;
}
/*
static int D3D11Shader_FindUniform_(LPD3DXCONSTANTTABLE ct, char *name)
{
if (ct)
{
UINT dc = 1;
D3DXCONSTANT_DESC d;
if (!FAILED(ct->lpVtbl->GetConstantDesc(ct, name, &d, &dc)))
return d.RegisterIndex;
}
return -1;
}
*/
int D3D11Shader_FindUniform(union programhandle_u *h, int type, char *name)
{
#if 0
int offs;
if (!type || type == 1)
{
offs = D3D11Shader_FindUniform_(h->hlsl.ctabv, name);
if (offs >= 0)
return offs;
}
if (!type || type == 2)
{
offs = D3D11Shader_FindUniform_(h->hlsl.ctabf, name);
if (offs >= 0)
return offs;
}
#endif
return -1;
}
#endif

View File

@ -365,6 +365,52 @@ static void D3D9_LoadTexture_8(d3dtexture_t *tex, unsigned char *data, unsigned
D3D9_LoadTexture_32(tex, trans, width, height, flags);
}
static void genNormalMap(unsigned int *nmap, qbyte *pixels, int w, int h, float scale)
{
int i, j, wr, hr;
unsigned char r, g, b;
float sqlen, reciplen, nx, ny, nz;
const float oneOver255 = 1.0f/255.0f;
float c, cx, cy, dcx, dcy;
wr = w;
hr = h;
for (i=0; i<h; i++)
{
for (j=0; j<w; j++)
{
/* Expand [0,255] texel values to the [0,1] range. */
c = pixels[i*wr + j] * oneOver255;
/* Expand the texel to its right. */
cx = pixels[i*wr + (j+1)%wr] * oneOver255;
/* Expand the texel one up. */
cy = pixels[((i+1)%hr)*wr + j] * oneOver255;
dcx = scale * (c - cx);
dcy = scale * (c - cy);
/* Normalize the vector. */
sqlen = dcx*dcx + dcy*dcy + 1;
reciplen = 1.0f/(float)sqrt(sqlen);
nx = dcx*reciplen;
ny = -dcy*reciplen;
nz = reciplen;
/* Repack the normalized vector into an RGB unsigned qbyte
vector in the normal map image. */
r = (qbyte) (128 + 127*nx);
g = (qbyte) (128 + 127*ny);
b = (qbyte) (128 + 127*nz);
/* The highest resolution mipmap level always has a
unit length magnitude. */
nmap[i*w+j] = LittleLong ((pixels[i*wr + j] << 24)|(b << 16)|(g << 8)|(r)); // <AWE> Added support for big endian.
}
}
}
void D3D9_Upload (texid_t tex, char *name, enum uploadfmt fmt, void *data, void *palette, int width, int height, unsigned int flags)
{
switch (fmt)
@ -419,12 +465,30 @@ texid_t D3D9_LoadTexture (char *identifier, int width, int height, enum uploadfm
case TF_8PAL24:
case TF_8PAL32:
break;
}
tex = d3d_lookup_texture(identifier);
switch (fmt)
{
case TF_HEIGHT8PAL:
{
texid_t t;
extern cvar_t r_shadow_bumpscale_basetexture;
unsigned int *norm = malloc(width*height*4);
genNormalMap(norm, data, width, height, r_shadow_bumpscale_basetexture.value);
t = D3D9_LoadTexture(identifier, width, height, TF_RGBA32, data, flags);
free(norm);
return t;
}
case TF_HEIGHT8:
{
extern cvar_t r_shadow_bumpscale_basetexture;
unsigned int *norm = malloc(width*height*4);
genNormalMap(norm, data, width, height, r_shadow_bumpscale_basetexture.value);
D3D9_LoadTexture_32(tex, norm, width, height, flags);
free(norm);
return tex->tex;
}
case TF_SOLID8:
case TF_TRANS8:
case TF_H2_T7G1:
@ -439,7 +503,7 @@ texid_t D3D9_LoadTexture (char *identifier, int width, int height, enum uploadfm
D3D9_LoadTexture_32(tex, data, width, height, flags);
return tex->tex;
default:
OutputDebugString(va("D3D9_LoadTexture doesn't support fmt %i", fmt));
OutputDebugString(va("D3D9_LoadTexture doesn't support fmt %i (%s)\n", fmt, identifier));
return r_nulltex;
}
}

View File

@ -76,7 +76,7 @@ RECT window_rect;
int window_x, window_y;
void BuildGammaTable (float g, float c);
/*void BuildGammaTable (float g, float c);
static void D3D9_VID_GenPaletteTables (unsigned char *palette)
{
extern unsigned short ramps[3][256];
@ -146,7 +146,7 @@ static void D3D9_VID_GenPaletteTables (unsigned char *palette)
if (pD3DDev9)
IDirect3DDevice9_SetGammaRamp(pD3DDev9, 0, D3DSGR_NO_CALIBRATION, (D3DGAMMARAMP *)ramps);
}
*/
typedef enum {MS_WINDOWED, MS_FULLSCREEN, MS_FULLDIB, MS_UNINIT} modestate_t;
static modestate_t modestate;
@ -719,7 +719,7 @@ static qboolean D3D9_VID_Init(rendererstate_t *info, unsigned char *palette)
GetWindowRect(mainwindow, &window_rect);
D3D9_VID_GenPaletteTables(palette);
// D3D9_VID_GenPaletteTables(palette);
{
extern qboolean mouseactive;
@ -864,8 +864,6 @@ static void (D3D9_VID_SetWindowCaption) (char *msg)
SetWindowText(mainwindow, msg);
}
void d3dx_ortho(float *m);
void D3D9_Set2D (void)
{
float m[16];

View File

@ -47,9 +47,6 @@
DEFINE_QGUID(qIID_ID3D11Texture2D,0x6f15aaf2,0xd208,0x4e89,0x9a,0xb4,0x48,0x95,0x35,0xd3,0x4f,0x9c);
//static void D3D11_GetBufferSize(int *width, int *height); //not defined
static void resetD3D11(void);
//static LPDIRECT3D11 pD3D;
ID3D11Device *pD3DDev11;
ID3D11DeviceContext *d3ddevctx;
IDXGISwapChain *d3dswapchain;
@ -58,7 +55,6 @@ ID3D11RenderTargetView *fb_backbuffer;
ID3D11DepthStencilView *fb_backdepthstencil;
void *d3d11mod;
float d3d_trueprojection[16];
qboolean vid_initializing;
@ -81,77 +77,59 @@ int window_x, window_y;
static void released3dbackbuffer(void);
static qboolean resetd3dbackbuffer(int width, int height);
void BuildGammaTable (float g, float c);
static void D3D11_VID_GenPaletteTables (unsigned char *palette)
#if 0//def _DEBUG
#include <dxgidebug.h>
const GUID IID_IDXGIDebug = { 0x119E7452,0xDE9E,0x40fe, { 0x88,0x06,0x88,0xF9,0x0C,0x12,0xB4,0x41 } };
const GUID DXGI_DEBUG_ALL = { 0xe48ae283, 0xda80, 0x490b, {0x87, 0xe6, 0x43, 0xe9, 0xa9, 0xcf, 0xda, 0x8 }};
void DoDXGIDebug(void)
{
extern unsigned short ramps[3][256];
qbyte *pal;
unsigned r,g,b;
unsigned v;
unsigned short i;
unsigned *table;
extern qbyte gammatable[256];
IDXGIDebug *dbg = NULL;
if (palette)
HRESULT (WINAPI *pDXGIGetDebugInterface)(REFIID riid, void **ppDebug);
dllfunction_t dxdidebugfuncs[] =
{
extern cvar_t v_contrast;
BuildGammaTable(v_gamma.value, v_contrast.value);
//
// 8 8 8 encoding
//
if (1)//vid_hardwaregamma.value)
{
// don't built in the gamma table
pal = palette;
table = d_8to24rgbtable;
for (i=0 ; i<256 ; i++)
{
r = pal[0];
g = pal[1];
b = pal[2];
pal += 3;
// v = (255<<24) + (r<<16) + (g<<8) + (b<<0);
// v = (255<<0) + (r<<8) + (g<<16) + (b<<24);
v = (255<<24) + (r<<0) + (g<<8) + (b<<16);
*table++ = v;
}
d_8to24rgbtable[255] &= 0xffffff; // 255 is transparent
}
else
{
//computer has no hardware gamma (poor suckers) increase table accordingly
pal = palette;
table = d_8to24rgbtable;
for (i=0 ; i<256 ; i++)
{
r = gammatable[pal[0]];
g = gammatable[pal[1]];
b = gammatable[pal[2]];
pal += 3;
// v = (255<<24) + (r<<16) + (g<<8) + (b<<0);
// v = (255<<0) + (r<<8) + (g<<16) + (b<<24);
v = (255<<24) + (r<<0) + (g<<8) + (b<<16);
*table++ = v;
}
d_8to24rgbtable[255] &= 0xffffff; // 255 is transparent
}
if (LittleLong(1) != 1)
{
for (i=0 ; i<256 ; i++)
d_8to24rgbtable[i] = LittleLong(d_8to24rgbtable[i]);
}
{(void**)&pDXGIGetDebugInterface, "DXGIGetDebugInterface"},
{NULL}
};
pDXGIGetDebugInterface = NULL;
Sys_LoadLibrary("dxgidebug", dxdidebugfuncs);
pDXGIGetDebugInterface(&IID_IDXGIDebug, &dbg);
if (dbg)
{
IDXGIDebug_ReportLiveObjects(dbg, DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_ALL);
IDXGIDebug_Release(dbg);
}
}
#else
#define DoDXGIDebug()
#endif
// if (pD3DDev11)
// d3dswapchain->Set
//IDirect3DDevice11_SetGammaRamp();
// IDirect3DDevice9_SetGammaRamp(pD3DDev9, 0, D3DSGR_NO_CALIBRATION, (D3DGAMMARAMP *)ramps);
char *D3D_NameForResult(HRESULT hr)
{
if (hr == DXGI_ERROR_DEVICE_REMOVED && pD3DDev11)
hr = ID3D11Device_GetDeviceRemovedReason(pD3DDev11);
switch(hr)
{
case E_OUTOFMEMORY: return "E_OUTOFMEMORY";
case E_NOINTERFACE: return "E_NOINTERFACE";
case DXGI_ERROR_DEVICE_HUNG: return "DXGI_ERROR_DEVICE_HUNG";
case DXGI_ERROR_DEVICE_REMOVED: return "DXGI_ERROR_DEVICE_REMOVED";
case DXGI_ERROR_DEVICE_RESET: return "DXGI_ERROR_DEVICE_RESET";
case DXGI_ERROR_DRIVER_INTERNAL_ERROR: return "DXGI_ERROR_DRIVER_INTERNAL_ERROR";
case DXGI_ERROR_INVALID_CALL: return "DXGI_ERROR_INVALID_CALL";
default: return va("%x", hr);
}
}
static void D3D11_PresentOrCrash(void)
{
extern cvar_t _vid_wait_override;
HRESULT hr = IDXGISwapChain_Present(d3dswapchain, _vid_wait_override.ival, 0);
if (FAILED(hr))
Sys_Error("IDXGISwapChain_Present: %s\n", D3D_NameForResult(hr));
}
typedef enum {MS_WINDOWED, MS_FULLSCREEN, MS_FULLDIB, MS_UNINIT} modestate_t;
@ -422,7 +400,6 @@ static LRESULT WINAPI D3D11_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
vid.pixelwidth = window_rect.right - window_rect.left;
vid.pixelheight = window_rect.bottom - window_rect.top;
resetd3dbackbuffer(vid.pixelwidth, vid.pixelheight);
resetD3D11();
D3D11BE_Reset(false);
lRet = DefWindowProc (hWnd, uMsg, wParam, lParam);
break;
@ -477,36 +454,6 @@ static LRESULT WINAPI D3D11_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
/* return 1 if handled message, 0 if not */
return lRet;
}
static void resetD3D11(void)
{
#if 0
HRESULT res;
res = IDirect3DDevice9_Reset(pD3DDev9, &d3dpp);
if (FAILED(res))
{
Con_Printf("IDirect3DDevice9_Reset failed (%u)\n", res&0xffff);
return;
}
/*clear the screen to black as soon as we start up, so there's no lingering framebuffer state*/
IDirect3DDevice9_BeginScene(pD3DDev9);
IDirect3DDevice9_Clear(pD3DDev9, 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
IDirect3DDevice9_EndScene(pD3DDev9);
IDirect3DDevice9_Present(pD3DDev9, NULL, NULL, NULL, NULL);
//IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRENDERSTATE_DITHERENABLE, FALSE);
//IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRENDERSTATE_SPECULARENABLE, FALSE);
//IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRENDERSTATE_TEXTUREPERSPECTIVE, TRUE);
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_LIGHTING, FALSE);
#endif
}
#if (WINVER < 0x500) && !defined(__GNUC__)
typedef struct tagMONITORINFO
@ -576,23 +523,46 @@ static qboolean resetd3dbackbuffer(int width, int height)
static qboolean initD3D11Device(HWND hWnd, rendererstate_t *info, PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN func, IDXGIAdapter *adapt)
{
int flags = D3D11_CREATE_DEVICE_SINGLETHREADED;
D3D_DRIVER_TYPE drivertype;
DXGI_SWAP_CHAIN_DESC scd;
D3D_FEATURE_LEVEL flevel, flevels[] =
{
//D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_3,
D3D_FEATURE_LEVEL_9_2,
D3D_FEATURE_LEVEL_9_1
//FIXME: need npot.
// D3D_FEATURE_LEVEL_9_3,
// D3D_FEATURE_LEVEL_9_2,
// D3D_FEATURE_LEVEL_9_1
};
memset(&scd, 0, sizeof(scd));
if (!stricmp(info->subrenderer, "debug"))
flags |= D3D11_CREATE_DEVICE_DEBUG;
if (!stricmp(info->subrenderer, "warp"))
drivertype = D3D_DRIVER_TYPE_WARP;
else if (!stricmp(info->subrenderer, "ref"))
drivertype = D3D_DRIVER_TYPE_REFERENCE;
else if (!stricmp(info->subrenderer, "hw"))
drivertype = D3D_DRIVER_TYPE_HARDWARE;
else if (!stricmp(info->subrenderer, "null"))
drivertype = D3D_DRIVER_TYPE_NULL;
else if (!stricmp(info->subrenderer, "software"))
drivertype = D3D_DRIVER_TYPE_SOFTWARE;
else if (!stricmp(info->subrenderer, "unknown"))
drivertype = D3D_DRIVER_TYPE_UNKNOWN;
else
drivertype = adapt?D3D_DRIVER_TYPE_UNKNOWN:D3D_DRIVER_TYPE_HARDWARE;
//for stereo support, we would have to rewrite all of this in a way that would make us dependant upon windows 8 or 7+platform update, which would exclude vista.
scd.BufferDesc.Width = info->width;
scd.BufferDesc.Height = info->height;
scd.BufferDesc.RefreshRate.Numerator = 0;
scd.BufferDesc.RefreshRate.Denominator = 0;
scd.BufferCount = 1; //back buffer count
scd.BufferCount = 1+info->triplebuffer; //back buffer count
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; //32bit colour
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
scd.OutputWindow = hWnd;
@ -604,14 +574,16 @@ static qboolean initD3D11Device(HWND hWnd, rendererstate_t *info, PFN_D3D11_CREA
// flags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
if (adapt)
if (drivertype == D3D_DRIVER_TYPE_UNKNOWN && adapt)
{
DXGI_ADAPTER_DESC adesc;
adapt->lpVtbl->GetDesc(adapt, &adesc);
IDXGIAdapter_GetDesc(adapt, &adesc);
Con_Printf("D3D11 Adaptor: %S\n", adesc.Description);
}
else
adapt = NULL;
if (FAILED(func(adapt, adapt?D3D_DRIVER_TYPE_UNKNOWN:D3D_DRIVER_TYPE_HARDWARE, NULL, flags,
if (FAILED(func(adapt, drivertype, NULL, flags,
flevels, sizeof(flevels)/sizeof(flevels[0]),
D3D11_SDK_VERSION,
&scd,
@ -634,7 +606,11 @@ static qboolean initD3D11Device(HWND hWnd, rendererstate_t *info, PFN_D3D11_CREA
}
vid.numpages = scd.BufferCount;
D3D11Shader_Init();
if (!D3D11Shader_Init(flevel))
{
Con_Printf("Unable to intialise a suitable HLSL compiler, please install the DirectX runtime.\n");
return false;
}
return true;
}
@ -643,8 +619,8 @@ static void initD3D11(HWND hWnd, rendererstate_t *info)
static dllhandle_t *d3d11dll;
static dllhandle_t *dxgi;
static PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN fnc;
static HRESULT (*pCreateDXGIFactory1)(REFIID riid, void **ppFactory);
IID factiid = {0x770aae78, 0xf26f, 0x4dba, 0xa8, 0x29, 0x25, 0x3c, 0x83, 0xd1, 0xb3, 0x87};
static HRESULT (WINAPI *pCreateDXGIFactory1)(IID *riid, void **ppFactory);
static IID factiid = {0x770aae78, 0xf26f, 0x4dba, 0xa8, 0x29, 0x25, 0x3c, 0x83, 0xd1, 0xb3, 0x87};
IDXGIFactory1 *fact = NULL;
IDXGIAdapter *adapt = NULL;
dllfunction_t d3d11funcs[] =
@ -658,32 +634,37 @@ static void initD3D11(HWND hWnd, rendererstate_t *info)
{NULL}
};
if (!d3d11mod)
d3d11mod = Sys_LoadLibrary("d3d11", d3d11funcs);
if (!dxgi)
dxgi = Sys_LoadLibrary("dxgi", dxgifuncs);
if (!d3d11mod)
d3d11mod = Sys_LoadLibrary("d3d11", d3d11funcs);
if (!d3d11mod)
return;
if (pCreateDXGIFactory1)
{
pCreateDXGIFactory1(&factiid, &fact);
HRESULT hr;
hr = pCreateDXGIFactory1(&factiid, &fact);
if (FAILED(hr))
Con_Printf("CreateDXGIFactory1 failed: %s\n", D3D_NameForResult(hr));
if (fact)
{
fact->lpVtbl->EnumAdapters(fact, 0, &adapt);
IDXGIFactory1_EnumAdapters(fact, 0, &adapt);
}
}
initD3D11Device(hWnd, info, fnc, adapt);
if (adapt)
IDXGIAdapter_Release(adapt);
if (fact)
{
//DXGI SUCKS and fucks up alt+tab every single time. its pointless to go from fullscreen to fullscreen-with-taskbar-obscuring-half-the-window.
//I'm just going to handle that stuff myself.
fact->lpVtbl->MakeWindowAssociation(fact, hWnd, DXGI_MWA_NO_WINDOW_CHANGES|DXGI_MWA_NO_ALT_ENTER|DXGI_MWA_NO_PRINT_SCREEN);
fact->lpVtbl->Release(fact);
IDXGIFactory1_MakeWindowAssociation(fact, hWnd, DXGI_MWA_NO_WINDOW_CHANGES|DXGI_MWA_NO_ALT_ENTER|DXGI_MWA_NO_PRINT_SCREEN);
IDXGIFactory1_Release(fact);
}
}
@ -739,9 +720,12 @@ static qboolean D3D11_VID_Init(rendererstate_t *info, unsigned char *palette)
// Try as specified.
DoDXGIDebug();
initD3D11(mainwindow, info);
if (!pD3DDev11)
{
DoDXGIDebug();
Con_Printf("No suitable D3D11 device found\n");
return false;
}
@ -749,6 +733,8 @@ static qboolean D3D11_VID_Init(rendererstate_t *info, unsigned char *palette)
if (info->fullscreen)
IDXGISwapChain_SetFullscreenState(d3dswapchain, true, NULL);
vid.pixelwidth = width;
vid.pixelheight = height;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
@ -760,29 +746,13 @@ static qboolean D3D11_VID_Init(rendererstate_t *info, unsigned char *palette)
ShowWindow(mainwindow, SW_SHOWNORMAL);
// IDirect3DDevice9_Clear(pD3DDev9, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
// IDirect3DDevice9_BeginScene(pD3DDev9);
// IDirect3DDevice9_EndScene(pD3DDev9);
// IDirect3DDevice9_Present(pD3DDev9, NULL, NULL, NULL, NULL);
// pD3DX->lpVtbl->GetBufferSize((void*)pD3DX, &width, &height);
vid.pixelwidth = width;
vid.pixelheight = height;
vid.width = width;
vid.height = height;
vid.width = vid.pixelwidth;
vid.height = vid.pixelheight;
vid_initializing = false;
// IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_LIGHTING, FALSE);
GetWindowRect(mainwindow, &window_rect);
D3D11_VID_GenPaletteTables(palette);
{
extern qboolean mouseactive;
mouseactive = false;
@ -843,10 +813,15 @@ static void (D3D11_VID_DeInit) (void)
IDXGISwapChain_Release(d3dswapchain);
d3dswapchain = NULL;
if (pD3DDev11)
pD3DDev11->lpVtbl->Release(pD3DDev11);
ID3D11Device_Release(pD3DDev11);
pD3DDev11 = NULL;
if (d3ddevctx)
d3ddevctx->lpVtbl->Release(d3ddevctx);
{
ID3D11DeviceContext_ClearState(d3ddevctx);
ID3D11DeviceContext_Flush(d3ddevctx);
ID3D11DeviceContext_Release(d3ddevctx);
}
d3ddevctx = NULL;
if (mainwindow)
@ -854,98 +829,77 @@ static void (D3D11_VID_DeInit) (void)
DestroyWindow(mainwindow);
mainwindow = NULL;
}
DoDXGIDebug();
}
static qboolean D3D11_VID_ApplyGammaRamps(unsigned short *ramps)
{
return false;
}
static char *(D3D11_VID_GetRGBInfo) (int prepad, int *truevidwidth, int *truevidheight)
static char *D3D11_VID_GetRGBInfo(int prepad, int *truevidwidth, int *truevidheight)
{
return NULL;
#if 0
IDirect3DSurface9 *backbuf, *surf;
D3DLOCKED_RECT rect;
D3DSURFACE_DESC desc;
int i, j, c;
qbyte *ret = NULL;
qbyte *p;
/*DON'T read the front buffer.
this function can be used by the quakeworld remote screenshot 'snap' feature,
so DO NOT read the frontbuffer because it can show other information than just quake to third parties*/
if (!FAILED(IDirect3DDevice9_GetRenderTarget(pD3DDev9, 0, &backbuf)))
//don't directly map the frontbuffer, as that can hold other things.
//create a texture, copy the (gpu)backbuffer to that (cpu)texture
//then map the (cpu)texture and copy out the parts we need, reordering as needed.
D3D11_MAPPED_SUBRESOURCE lock;
qbyte *rgb, *in, *r = NULL;
unsigned int x,y;
D3D11_TEXTURE2D_DESC texDesc;
ID3D11Texture2D *texture;
ID3D11Resource *backbuffer;
texDesc.ArraySize = 1;
texDesc.BindFlags = 0;
texDesc.CPUAccessFlags = 0;
texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
texDesc.Width = vid.pixelwidth;
texDesc.Height = vid.pixelheight;
texDesc.MipLevels = 1;
texDesc.MiscFlags = 0;
texDesc.SampleDesc.Count = 1;
texDesc.SampleDesc.Quality = 0;
texDesc.Usage = D3D11_USAGE_STAGING;
texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
if (FAILED(ID3D11Device_CreateTexture2D(pD3DDev11, &texDesc, 0, &texture)))
return NULL;
ID3D11RenderTargetView_GetResource(fb_backbuffer, &backbuffer);
ID3D11DeviceContext_CopyResource(d3ddevctx, (ID3D11Resource*)texture, backbuffer);
ID3D11Resource_Release(backbuffer);
if (!FAILED(ID3D11DeviceContext_Map(d3ddevctx, (ID3D11Resource*)texture, 0, D3D11_MAP_READ, 0, &lock)))
{
if (!FAILED(IDirect3DSurface9_GetDesc(backbuf, &desc)))
if (desc.Format == D3DFMT_X8R8G8B8 || desc.Format == D3DFMT_A8R8G8B8)
if (!FAILED(IDirect3DDevice9_CreateOffscreenPlainSurface(pD3DDev9,
desc.Width, desc.Height, desc.Format,
D3DPOOL_SYSTEMMEM, &surf, NULL))
)
r = rgb = BZ_Malloc(prepad + 3 * vid.pixelwidth * vid.pixelheight);
r += prepad;
for (y = vid.pixelheight; y-- > 0; )
{
if (!FAILED(IDirect3DDevice9_GetRenderTargetData(pD3DDev9, backbuf, surf)))
if (!FAILED(IDirect3DSurface9_LockRect(surf, &rect, NULL, D3DLOCK_NO_DIRTY_UPDATE|D3DLOCK_READONLY|D3DLOCK_NOSYSLOCK)))
in = lock.pData;
in += y * lock.RowPitch;
for (x = 0; x < vid.pixelwidth; x++, rgb+=3, in+=4)
{
ret = BZ_Malloc(prepad + desc.Width*desc.Height*3);
if (ret)
{
// read surface rect and convert 32 bgra to 24 rgb and flip
c = prepad+desc.Width*desc.Height*3;
p = (qbyte *)rect.pBits;
for (i=c-(3*desc.Width); i>=prepad; i-=(3*desc.Width))
{
for (j=0; j<desc.Width; j++)
{
ret[i+j*3+0] = p[j*4+2];
ret[i+j*3+1] = p[j*4+1];
ret[i+j*3+2] = p[j*4+0];
}
p += rect.Pitch;
}
*truevidwidth = desc.Width;
*truevidheight = desc.Height;
}
IDirect3DSurface9_UnlockRect(surf);
rgb[0] = in[0];
rgb[1] = in[1];
rgb[2] = in[2];
}
IDirect3DSurface9_Release(surf);
}
IDirect3DSurface9_Release(backbuf);
ID3D11DeviceContext_Unmap(d3ddevctx, (ID3D11Resource*)texture, 0);
}
return ret;
#endif
ID3D11Texture2D_Release(texture);
*truevidwidth = vid.pixelwidth;
*truevidheight = vid.pixelheight;
return r;
}
static void (D3D11_VID_SetWindowCaption) (char *msg)
{
SetWindowText(mainwindow, msg);
}
void d3dx_ortho(float *m);
void D3D11_Set2D (void)
{
D3D11_VIEWPORT vport;
Matrix4x4_CM_OrthographicD3D(r_refdef.m_projection, 0 + (0.5*vid.width/vid.pixelwidth), vid.width + (0.5*vid.width/vid.pixelwidth), 0 + (0.5*vid.height/vid.pixelheight), vid.height + (0.5*vid.height/vid.pixelheight), 0, 100);
memcpy(d3d_trueprojection, r_refdef.m_projection, sizeof(d3d_trueprojection));
// Matrix4x4_CM_Orthographic(r_refdef.m_projection, 0 + (0.5*vid.width/vid.pixelwidth), vid.width + (0.5*vid.width/vid.pixelwidth), 0 + (0.5*vid.height/vid.pixelheight), vid.height + (0.5*vid.height/vid.pixelheight), 0, 100);
Matrix4x4_CM_Orthographic(r_refdef.m_projection, 0, vid.width, vid.height, 0, 0, 99999);
Matrix4x4_Identity(r_refdef.m_view);
#if 0
float m[16];
Matrix4x4_CM_OrthographicD3D(m, 0 + (0.5*vid.width/vid.pixelwidth), vid.width + (0.5*vid.width/vid.pixelwidth), 0 + (0.5*vid.height/vid.pixelheight), vid.height + (0.5*vid.height/vid.pixelheight), 0, 100);
IDirect3DDevice9_SetTransform(pD3DDev9, D3DTS_PROJECTION, (D3DMATRIX*)m);
Matrix4x4_Identity(m);
IDirect3DDevice9_SetTransform(pD3DDev9, D3DTS_WORLD, (D3DMATRIX*)m);
Matrix4x4_Identity(m);
IDirect3DDevice9_SetTransform(pD3DDev9, D3DTS_VIEW, (D3DMATRIX*)m);
#endif
vport.TopLeftX = 0;
vport.TopLeftY = 0;
vport.Width = vid.pixelwidth;
@ -953,21 +907,12 @@ void D3D11_Set2D (void)
vport.MinDepth = 0;
vport.MaxDepth = 1;
d3ddevctx->lpVtbl->RSSetViewports(d3ddevctx, 1, &vport);
ID3D11DeviceContext_RSSetViewports(d3ddevctx, 1, &vport);
D3D11BE_SetupViewCBuffer();
}
/*
static int d3d11error(int i)
{
if (FAILED(i))// != D3D_OK)
Con_Printf("D3D error: %i\n", i);
return i;
}
*/
static void (D3D11_SCR_UpdateScreen) (void)
{
extern cvar_t _vid_wait_override;
//extern int keydown[];
//extern cvar_t vid_conheight;
int uimenu;
@ -983,7 +928,6 @@ static void (D3D11_SCR_UpdateScreen) (void)
ID3D11DeviceContext_ClearRenderTargetView(d3ddevctx, fb_backbuffer, colours);
}
#if 1
if (d3d_resized)
{
extern cvar_t vid_conautoscale, vid_conwidth;
@ -992,22 +936,9 @@ static void (D3D11_SCR_UpdateScreen) (void)
// force width/height to be updated
//vid.pixelwidth = window_rect.right - window_rect.left;
//vid.pixelheight = window_rect.bottom - window_rect.top;
/* D3DVID_UpdateWindowStatus(mainwindow);
released3dbackbuffer();
IDXGISwapChain_ResizeBuffers(d3dswapchain, 0, 0, 0, DXGI_FORMAT_UNKNOWN, 0);
D3D11BE_Reset(true);
vid.pixelwidth = window_rect.right - window_rect.left;
vid.pixelheight = window_rect.bottom - window_rect.top;
resetd3dbackbuffer(vid.pixelwidth, vid.pixelheight);
resetD3D11();
D3D11BE_Reset(false);
*/
Cvar_ForceCallback(&vid_conautoscale);
Cvar_ForceCallback(&vid_conwidth);
}
#endif
if (scr_disabled_for_loading)
{
@ -1023,7 +954,7 @@ static void (D3D11_SCR_UpdateScreen) (void)
SCR_DrawLoading ();
scr_drawloading = false;
// IDirect3DDevice9_EndScene(pD3DDev9);
IDXGISwapChain_Present(d3dswapchain, _vid_wait_override.ival, 0);
D3D11_PresentOrCrash();
RSpeedEnd(RSPEED_TOTALREFRESH);
return;
}
@ -1073,7 +1004,7 @@ static void (D3D11_SCR_UpdateScreen) (void)
#endif
// R2D_BrightenScreen();
// IDirect3DDevice9_EndScene(pD3DDev9);
IDXGISwapChain_Present(d3dswapchain, _vid_wait_override.ival, 0);
D3D11_PresentOrCrash();
RSpeedEnd(RSPEED_TOTALREFRESH);
return;
}
@ -1141,10 +1072,7 @@ static void (D3D11_SCR_UpdateScreen) (void)
RSpeedEnd(RSPEED_TOTALREFRESH);
RSpeedShow();
// d3d11error(IDirect3DDevice9_EndScene(pD3DDev9));
IDXGISwapChain_Present(d3dswapchain, _vid_wait_override.ival, 0);
D3D11_PresentOrCrash();
window_center_x = (window_rect.left + window_rect.right)/2;
window_center_y = (window_rect.top + window_rect.bottom)/2;
@ -1214,14 +1142,6 @@ static void D3D11_SetupViewPort(void)
w = x2 - x;
h = y2 - y;
// vport.X = x;
// vport.Y = y;
// vport.Width = w;
// vport.Height = h;
// vport.MinZ = 0;
// vport.MaxZ = 1;
// IDirect3DDevice9_SetViewport(pD3DDev9, &vport);
fov_x = r_refdef.fov_x;//+sin(cl.time)*5;
fov_y = r_refdef.fov_y;//-sin(cl.time+1)*5;
@ -1235,57 +1155,50 @@ static void D3D11_SetupViewPort(void)
/*view matrix*/
Matrix4x4_CM_ModelViewMatrixFromAxis(r_refdef.m_view, vpn, vright, vup, r_refdef.vieworg);
// d3d11error(IDirect3DDevice9_SetTransform(pD3DDev9, D3DTS_VIEW, (D3DMATRIX*)r_refdef.m_view));
/*d3d projection matricies scale depth to 0 to 1*/
Matrix4x4_CM_Projection_Inf(d3d_trueprojection, fov_x, fov_y, gl_mindist.value/2);
// d3d11error(IDirect3DDevice9_SetTransform(pD3DDev9, D3DTS_PROJECTION, (D3DMATRIX*)d3d_trueprojection));
/*ogl projection matricies scale depth to -1 to 1, and I would rather my code used consistant culling*/
Matrix4x4_CM_Projection_Inf(r_refdef.m_projection, fov_x, fov_y, gl_mindist.value);
}
static void (D3D11_R_RenderView) (void)
{
float x, x2, y, y2;
D3D11_SetupViewPort();
//unlike gl, we clear colour beforehand, because that seems more sane.
//always clear depth
ID3D11DeviceContext_ClearDepthStencilView(d3ddevctx, fb_backdepthstencil, D3D11_CLEAR_DEPTH, 1, 0); //is it faster to clear the stencil too?
x = (r_refdef.vrect.x * (int)vid.pixelwidth)/(int)vid.width;
x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * (int)vid.pixelwidth/(int)vid.width;
y = (r_refdef.vrect.y * (int)vid.pixelheight)/(int)vid.height;
y2 = (r_refdef.vrect.y + r_refdef.vrect.height) * (int)vid.pixelheight/(int)vid.height;
r_refdef.pxrect.x = floor(x);
r_refdef.pxrect.y = floor(y);
r_refdef.pxrect.width = (int)ceil(x2) - r_refdef.pxrect.x;
r_refdef.pxrect.height = (int)ceil(y2) - r_refdef.pxrect.y;
R_SetFrustum (r_refdef.m_projection, r_refdef.m_view);
RQ_BeginFrame();
// if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL))
// {
// if (cl.worldmodel)
// P_DrawParticles ();
// }
if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL))
{
if (cl.worldmodel)
P_DrawParticles ();
}
if (!r_worldentity.model || r_worldentity.model->needload || !cl.worldmodel)
{
D3D11_Set2D ();
R2D_ImageColours(0, 0, 0, 1);
R2D_FillBlock(r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height);
R2D_ImageColours(1, 1, 1, 1);
return;
}
Surf_DrawWorld();
RQ_RenderBatchClear();
D3D11_Set2D ();
}
void (D3D11_R_NewMap) (void);
void (D3D11_R_PreNewMap) (void);
void (D3D11_R_PushDlights) (void);
void (D3D11_R_AddStain) (vec3_t org, float red, float green, float blue, float radius);
void (D3D11_R_LessenStains) (void);
qboolean (D3D11_VID_Init) (rendererstate_t *info, unsigned char *palette);
void (D3D11_VID_DeInit) (void);
void (D3D11_VID_SetPalette) (unsigned char *palette);
void (D3D11_VID_ShiftPalette) (unsigned char *palette);
char *(D3D11_VID_GetRGBInfo) (int prepad, int *truevidwidth, int *truevidheight);
void (D3D11_VID_SetWindowCaption) (char *msg);
void (D3D11_SCR_UpdateScreen) (void);
rendererinfo_t d3d11rendererinfo =
{
"Direct3D11",

View File

@ -8,6 +8,9 @@ EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "botlib", "botlib.vcproj", "{0018E098-B12A-4E4D-9B22-6772DA287080}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fteqcc", "..\qclib\dotnet2005\qcc.vcproj", "{2866F783-6B44-4655-A38D-D53874037454}"
ProjectSection(ProjectDependencies) = postProject
{9767E236-8454-44E9-8999-CD5BDAFBE9BA} = {9767E236-8454-44E9-8999-CD5BDAFBE9BA}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qtvprox", "..\..\fteqtv\dotnet2005\qtvprox.vcproj", "{62669E6C-7E18-4E4D-BA54-DFBE29E7D24E}"
EndProject
@ -314,7 +317,6 @@ Global
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.D3DDebug|Win32.ActiveCfg = Debug|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.D3DDebug|x64.ActiveCfg = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.D3DRelease|Win32.ActiveCfg = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.D3DRelease|Win32.Build.0 = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.D3DRelease|x64.ActiveCfg = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.Debug Dedicated Server|Win32.ActiveCfg = Debug|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.Debug Dedicated Server|x64.ActiveCfg = Debug|Win32

View File

@ -279,6 +279,7 @@
LinkIncremental="2"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="../libs/dxsdk7/lib"
GenerateManifest="false"
IgnoreDefaultLibraryNames="libc.lib;msvcrt.lib"
GenerateDebugInformation="true"
GenerateMapFile="true"
@ -635,6 +636,7 @@
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="0"
>
<Tool
Name="VCPreBuildEventTool"
@ -661,7 +663,7 @@
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../libs/speex,..\client,../libs/freetype2/include,../common,../server,../gl,../sw,../qclib,../libs,../libs/dxsdk7/include"
PreprocessorDefinitions="_DEBUG;GLQUAKE;WIN32;_WINDOWS;MULTITHREAD;BOTLIB_STATIC;USE_MSVCRT_DEBUG;RTLIGHTS"
PreprocessorDefinitions="_DEBUG;GLQUAKE;WIN32;_WINDOWS;MULTITHREAD;BOTLIB_STATIC;USE_MSVCRT_DEBUG"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
EnableFunctionLevelLinking="true"
@ -1897,12 +1899,14 @@
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="2"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1"
OmitFramePointers="true"
WholeProgramOptimization="true"
AdditionalIncludeDirectories="../libs/speex;..\client;../libs/freetype2/include;../common;../server;../gl;../sw;../qclib;../libs;../d3d9;../libs/dxsdk9/include;../libs/dxsdk7/include"
PreprocessorDefinitions="NDEBUG;D3DQUAKE;WIN32;_WINDOWS"
PreprocessorDefinitions="NDEBUG;D3D9QUAKE;D3D11QUAKE;WIN32;_WINDOWS"
StringPooling="true"
ExceptionHandling="0"
RuntimeLibrary="0"
@ -1914,7 +1918,7 @@
BrowseInformationFile="$(IntDir)\"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="0"
DebugInformationFormat="3"
CallingConvention="1"
CompileAs="0"
DisableSpecificWarnings="4996"
@ -1934,6 +1938,7 @@
Name="VCLinkerTool"
AdditionalDependencies="comctl32.lib wsock32.lib winmm.lib odbc32.lib odbccp32.lib"
OutputFile="../../fted3dqw.exe"
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="../libs/dxsdk7/lib"
GenerateManifest="false"
@ -1943,7 +1948,9 @@
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
SetChecksum="true"
TargetMachine="1"
FixedBaseAddress="1"
/>
<Tool
Name="VCALinkTool"
@ -18882,6 +18889,169 @@
/>
</FileConfiguration>
</File>
<File
RelativePath="..\common\net_ssl_gnutls.c"
>
<FileConfiguration
Name="MinGLDebug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="MinGLDebug|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="D3DDebug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="D3DDebug|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="MinGLRelease|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="MinGLRelease|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="GLDebug|Win32"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="GLDebug|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release Dedicated Server|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release Dedicated Server|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="MRelease|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="MRelease|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug Dedicated Server|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug Dedicated Server|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="MDebug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="MDebug|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="GLRelease|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="GLRelease|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="D3DRelease|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="D3DRelease|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\client\snd_alsa.c"
>
@ -29465,6 +29635,23 @@
/>
</FileConfiguration>
</File>
<File
RelativePath="..\common\net_ice.c"
>
</File>
<File
RelativePath="..\common\net_sellingmysoultothedevil.cpp"
>
<FileConfiguration
Name="GLDebug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
CompileAs="2"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\common\net_ssl_winsspi.c"
>

View File

@ -963,14 +963,17 @@ int GLBE_SetupForShadowMap(texid_t shadowmaptex, int texwidth, int texheight, fl
{
extern cvar_t r_shadow_shadowmapping_bias;
extern cvar_t r_shadow_shadowmapping_nearclip;
float n = r_shadow_shadowmapping_nearclip.value;
float f = shaderstate.lightradius;
float b = r_shadow_shadowmapping_bias.value;
//FIXME: this is used for rendering, not for shadow generation!
#define SHADOWMAP_SIZE 512
//projection frustum, slots 10+11. scaled by 0.5
//lightshadowmapproj is a projection matrix packed into a vec4, with various texture scaling stuff built in.
shaderstate.lightshadowmapproj[0] = shadowscale * (1.0-(1.0/texwidth)) * 0.5/3.0;
shaderstate.lightshadowmapproj[1] = shadowscale * (1.0-(1.0/texheight)) * 0.5/2.0;
shaderstate.lightshadowmapproj[2] = 0.5*(shaderstate.lightradius+r_shadow_shadowmapping_nearclip.value)/(r_shadow_shadowmapping_nearclip.value-shaderstate.lightradius);
shaderstate.lightshadowmapproj[3] = (shaderstate.lightradius*r_shadow_shadowmapping_nearclip.value)/(r_shadow_shadowmapping_nearclip.value-shaderstate.lightradius) - 0.5*r_shadow_shadowmapping_bias.value*r_shadow_shadowmapping_nearclip.value*(1024/texheight);
shaderstate.lightshadowmapproj[2] = 0.5*(f+n)/(n-f);
shaderstate.lightshadowmapproj[3] = (f*n)/(n-f) - b*n*(1024/texheight);
shaderstate.lightshadowmapscale[0] = 1.0/(SHADOWMAP_SIZE*3);
shaderstate.lightshadowmapscale[1] = 1.0/(SHADOWMAP_SIZE*2);
@ -1252,6 +1255,7 @@ void GenerateFogTexture(texid_t *tex, float density, float zscale)
f = 0;
if (f > 1)
f = 1;
f *= (float)t / (FOGT-1);
fogdata[t*FOGS + s][0] = 255;
fogdata[t*FOGS + s][1] = 255;
@ -1319,6 +1323,7 @@ void GLBE_Init(void)
shaderstate.dummybatch.lightmap[i] = -1;
#ifdef RTLIGHTS
Sh_CheckSettings();
if (r_shadow_realtime_dlight.ival || r_shadow_realtime_world.ival)
{
if (r_shadow_shadowmapping.ival)
@ -1420,6 +1425,7 @@ static void tcgen_fog(float *st, unsigned int numverts, float *xyz, mfog_t *fog)
int i;
float z;
float eye, point;
vec4_t zmat;
//generate a simple matrix to calc only the projected z coord
@ -1430,11 +1436,29 @@ static void tcgen_fog(float *st, unsigned int numverts, float *xyz, mfog_t *fog)
Vector4Scale(zmat, shaderstate.fogfar, zmat);
if (fog->visibleplane)
eye = (DotProduct(r_refdef.vieworg, fog->visibleplane->normal) - fog->visibleplane->dist);
else
eye = 1;
// if (eye < 1)
// eye = 1;
for (i = 0 ; i < numverts ; i++, xyz += sizeof(vecV_t)/sizeof(vec_t), st += 2 )
{
z = DotProduct(xyz, zmat) + zmat[3];
st[0] = z;
st[1] = realtime - (int)realtime;
if (fog->visibleplane)
point = (DotProduct(xyz, fog->visibleplane->normal) - fog->visibleplane->dist);
else
point = 1;
if (eye < 0)
st[1] = (point < 0)?1:0;
else
st[1] = point / (point - eye);
if (st[1] > 31/32.0)
st[1] = 31/32.0;
}
}
@ -3443,10 +3467,10 @@ void GLBE_Scissor(srect_t *rect)
{
qglScissor(
floor(r_refdef.pxrect.x + rect->x*r_refdef.pxrect.width),
floor((r_refdef.pxrect.y + rect->y*r_refdef.pxrect.height) - r_refdef.pxrect.height),
floor((r_refdef.pxrect.y + rect->y*r_refdef.pxrect.height) - r_refdef.pxrect.maxheight),
ceil(rect->width * r_refdef.pxrect.width),
ceil(rect->height * r_refdef.pxrect.height));
qglEnable(GL_SCISSOR_TEST);
// qglEnable(GL_SCISSOR_TEST);
if (qglDepthBoundsEXT)
{
@ -4156,6 +4180,9 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
if (batch->shader->flags & SHADER_NODLIGHT)
if (shaderstate.mode == BEM_LIGHT)
continue;
if (batch->shader->flags & SHADER_NOSHADOWS)
if (shaderstate.mode == BEM_DEPTHONLY)
continue;
if (batch->shader->flags & SHADER_SKY)
{
if (shaderstate.mode == BEM_STANDARD || shaderstate.mode == BEM_DEPTHDARK)
@ -4182,7 +4209,8 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
if ((batch->shader->flags & SHADER_HASREFLECT) && gl_config.ext_framebuffer_objects)
{
vrect_t orect = r_refdef.vrect, oprect = r_refdef.pxrect;
vrect_t orect = r_refdef.vrect;
pxrect_t oprect = r_refdef.pxrect;
if (!shaderstate.tex_reflection.num)
{
shaderstate.tex_reflection = GL_AllocNewTexture("***tex_reflection***", vid.pixelwidth/2, vid.pixelheight/2, 0);
@ -4200,10 +4228,11 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
r_refdef.vrect.width = vid.width/2;
r_refdef.vrect.height = vid.height/2;
r_refdef.pxrect.x = 0;
r_refdef.pxrect.y = 0;
r_refdef.pxrect.width = vid.pixelwidth/2;
r_refdef.pxrect.height = vid.pixelheight/2;
r_refdef.pxrect.y = r_refdef.pxrect.height;
qglViewport (r_refdef.pxrect.x, r_refdef.pxrect.height-r_refdef.pxrect.y, r_refdef.pxrect.width, r_refdef.pxrect.height);
r_refdef.pxrect.maxheight = vid.pixelheight/2;
GL_ViewportUpdate();
GL_ForceDepthWritable();
qglClearColor(0, 0, 0, 0);
qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@ -4211,13 +4240,14 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
GLBE_RenderToTexture(r_nulltex, r_nulltex, r_nulltex, r_nulltex, false);
r_refdef.vrect = orect;
r_refdef.pxrect = oprect;
qglViewport (r_refdef.pxrect.x, r_refdef.pxrect.height-r_refdef.pxrect.y, r_refdef.pxrect.width, r_refdef.pxrect.height);
GL_ViewportUpdate();
}
if (batch->shader->flags & (SHADER_HASREFRACT|SHADER_HASREFRACTDEPTH))
{
if (r_refract_fboival)
{
vrect_t ovrect = r_refdef.vrect, oprect = r_refdef.pxrect;
vrect_t ovrect = r_refdef.vrect;
pxrect_t oprect = r_refdef.pxrect;
GL_ForceDepthWritable();
if (!shaderstate.tex_refraction.num)
@ -4252,10 +4282,11 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
r_refdef.vrect.width = vid.width/2;
r_refdef.vrect.height = vid.height/2;
r_refdef.pxrect.x = 0;
r_refdef.pxrect.y = 0;
r_refdef.pxrect.width = vid.pixelwidth/2;
r_refdef.pxrect.height = vid.pixelheight/2;
r_refdef.pxrect.y = r_refdef.pxrect.height;
qglViewport (r_refdef.pxrect.x, r_refdef.pxrect.height-r_refdef.pxrect.y, r_refdef.pxrect.width, r_refdef.pxrect.height);
r_refdef.pxrect.maxheight = vid.pixelheight/2;
GL_ViewportUpdate();
GL_ForceDepthWritable();
qglClearColor(0, 0, 0, 0);
@ -4265,14 +4296,15 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
r_refdef.vrect = ovrect;
r_refdef.pxrect = oprect;
qglViewport (r_refdef.pxrect.x, r_refdef.pxrect.height-r_refdef.pxrect.y, r_refdef.pxrect.width, r_refdef.pxrect.height);
GL_ViewportUpdate();
}
else
GLR_DrawPortal(batch, cl.worldmodel->batches, 3);
}
if ((batch->shader->flags & SHADER_HASRIPPLEMAP) && gl_config.ext_framebuffer_objects)
{
vrect_t orect = r_refdef.vrect, oprect = r_refdef.pxrect;
vrect_t orect = r_refdef.vrect;
pxrect_t oprect = r_refdef.pxrect;
if (!shaderstate.tex_ripplemap.num)
{
//FIXME: can we use RGB8 instead?
@ -4290,10 +4322,11 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
r_refdef.vrect.width = vid.width/2;
r_refdef.vrect.height = vid.height/2;
r_refdef.pxrect.x = 0;
r_refdef.pxrect.y = 0;
r_refdef.pxrect.width = vid.pixelwidth/2;
r_refdef.pxrect.height = vid.pixelheight/2;
r_refdef.pxrect.y = r_refdef.pxrect.height;
qglViewport (r_refdef.pxrect.x, r_refdef.pxrect.height-r_refdef.pxrect.y, r_refdef.pxrect.width, r_refdef.pxrect.height);
r_refdef.pxrect.maxheight = vid.pixelheight/2;
GL_ViewportUpdate();
qglClearColor(0, 0, 0, 0);
qglClear(GL_COLOR_BUFFER_BIT);
@ -4307,7 +4340,7 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
r_refdef.vrect = orect;
r_refdef.pxrect = oprect;
qglViewport (r_refdef.pxrect.x, r_refdef.pxrect.height-r_refdef.pxrect.y, r_refdef.pxrect.width, r_refdef.pxrect.height);
GL_ViewportUpdate();
}
BE_SelectMode(oldbem);
}
@ -4705,7 +4738,7 @@ void GLBE_DrawWorld (qboolean drawworld, qbyte *vis)
}
#ifdef RTLIGHTS
if (vis && r_shadow_realtime_world.ival)
if (drawworld && r_shadow_realtime_world.ival)
shaderstate.identitylighting = r_shadow_realtime_world_lightmaps.value;
else
#endif

View File

@ -189,7 +189,7 @@ void R_BloomBlend (void)
/*grab the screen, because we failed to do it earlier*/
GL_MTBind(0, GL_TEXTURE_2D, scrtex);
qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.pxrect.x, r_refdef.pxrect.y - r_refdef.pxrect.height, r_refdef.pxrect.width, r_refdef.pxrect.height);
qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.pxrect.x, r_refdef.pxrect.maxheight - (r_refdef.pxrect.y+r_refdef.pxrect.height), r_refdef.pxrect.width, r_refdef.pxrect.height);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@ -228,6 +228,8 @@ void R_BloomBlend (void)
qglViewport (0, 0, texwidth[i], texheight[i]);
R2D_ScalePic(0, vid.height, vid.width, -(int)vid.height, bloomblur);
}
r_worldentity.glowmod[0] = 0;
r_worldentity.glowmod[1] = 0;
GL_Set2D(false);

View File

@ -166,7 +166,7 @@ typedef struct gltexture_s
{
texcom_t com;
texid_t texnum;
char identifier[64];
char identifier[MAX_QPATH];
int bpp;
unsigned int flags;
struct gltexture_s *next;
@ -595,12 +595,13 @@ void GL_Set2D (qboolean flipped)
Matrix4x4_Identity(r_refdef.m_view);
}
r_refdef.pxrect.x = 0;
r_refdef.pxrect.y = 0;
r_refdef.pxrect.width = vid.pixelwidth;
r_refdef.pxrect.height = vid.pixelheight;
r_refdef.pxrect.y = r_refdef.pxrect.height;
r_refdef.pxrect.maxheight = vid.pixelheight;
r_refdef.time = realtime;
/*flush that gl state*/
qglViewport (0, 0, vid.pixelwidth, vid.pixelheight);
GL_ViewportUpdate();
if (qglLoadMatrixf)
{

View File

@ -1370,7 +1370,7 @@ int Font_LineBreaks(conchar_t *start, conchar_t *end, int maxpixelwidth, int max
for (px=0, l=0 ; px <= maxpixelwidth; )
{
l++;
if (start+l >= end || (start[l-1]&CON_CHARMASK) == '\n')
if (start+l >= end || (start[l-1]&(CON_CHARMASK|CON_HIDDEN)) == '\n')
break;
px = Font_CharEndCoord(font, px, start[l]);
}
@ -1397,7 +1397,7 @@ int Font_LineBreaks(conchar_t *start, conchar_t *end, int maxpixelwidth, int max
if (start == end)
break;
if ((*start&CON_CHARMASK) == '\n'||!l)
if ((*start&(CON_CHARMASK|CON_HIDDEN)) == '\n'||!l)
start++; // skip the \n
}

File diff suppressed because it is too large Load Diff

View File

@ -654,6 +654,8 @@ model_t *Mod_FindName (char *name)
{
if (mod_numknown == MAX_MOD_KNOWN)
Sys_Error ("mod_numknown == MAX_MOD_KNOWN");
if (strlen(name) >= sizeof(mod->name))
Sys_Error ("model name is too long: %s", name);
memset(mod, 0, sizeof(model_t)); //clear the old model as the renderers use the same globals
strcpy (mod->name, name);
mod->needload = true;

View File

@ -860,6 +860,7 @@ void R_SaveRTLights_f(void)
vfsfile_t *f;
unsigned int i;
char fname[MAX_QPATH];
char sysname[MAX_OSPATH];
vec3_t ang;
COM_StripExtension(cl.worldmodel->name, fname, sizeof(fname));
strncat(fname, ".rtlights", MAX_QPATH-1);
@ -896,7 +897,9 @@ void R_SaveRTLights_f(void)
));
}
VFS_CLOSE(f);
Con_Printf("rtlights saved to %s\n", fname);
FS_NativePath(fname, FS_GAMEONLY, sysname, sizeof(sysname));
Con_Printf("rtlights saved to %s\n", sysname);
}
void R_ReloadRTLights_f(void)

View File

@ -383,21 +383,21 @@ void R_SetupGL (float stereooffset)
//
x = r_refdef.vrect.x * (int)vid.pixelwidth/(int)vid.width;
x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * (int)vid.pixelwidth/(int)vid.width;
y = (vid.height-r_refdef.vrect.y) * (int)vid.pixelheight/(int)vid.height;
y2 = ((int)vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)) * (int)vid.pixelheight/(int)vid.height;
y = (r_refdef.vrect.y) * (int)vid.pixelheight/(int)vid.height;
y2 = (r_refdef.vrect.y + r_refdef.vrect.height) * (int)vid.pixelheight/(int)vid.height;
// fudge around because of frac screen scale
if (x > 0)
x--;
if (x2 < vid.pixelwidth)
x2++;
if (y2 < 0)
y2--;
if (y < vid.pixelheight)
y++;
if (y2 < vid.pixelheight)
y2++;
if (y > 0)
y--;
w = x2 - x;
h = y - y2;
h = y2 - y;
fov_x = r_refdef.fov_x;//+sin(cl.time)*5;
fov_y = r_refdef.fov_y;//-sin(cl.time+1)*5;
@ -413,8 +413,9 @@ void R_SetupGL (float stereooffset)
r_refdef.pxrect.y = y;
r_refdef.pxrect.width = w;
r_refdef.pxrect.height = h;
r_refdef.pxrect.maxheight = vid.pixelheight;
qglViewport (x, y2, w, h);
GL_ViewportUpdate();
if (r_waterwarp.value<0 && (r_viewcontents & FTECONTENTS_FLUID))
{
@ -1140,7 +1141,7 @@ qboolean R_RenderScene_Cubemap(void)
vec3_t saveang;
vrect_t vrect;
vrect_t prect;
pxrect_t prect;
shader_t *shader;
int facemask;
@ -1274,27 +1275,28 @@ qboolean R_RenderScene_Cubemap(void)
}
r_refdef.vrect = vrect;
r_refdef.pxrect = prect;
qglViewport (prect.x, vid.pixelheight - (prect.y+prect.height), prect.width, prect.height);
//GL_ViewportUpdate();
GL_Set2D(false);
// go 2d
qglMatrixMode(GL_PROJECTION);
/* qglMatrixMode(GL_PROJECTION);
qglPushMatrix();
qglLoadIdentity ();
qglOrtho (0, vid.width, vid.height, 0, -99999, 99999);
qglMatrixMode(GL_MODELVIEW);
qglPushMatrix();
qglLoadIdentity ();
*/
// draw it through the shader
R2D_Image(0, 0, vid.width, vid.height, -0.5, 0.5, 0.5, -0.5, shader);
//revert the matricies
qglMatrixMode(GL_PROJECTION);
/* qglMatrixMode(GL_PROJECTION);
qglPopMatrix();
qglMatrixMode(GL_MODELVIEW);
qglPopMatrix();
*/
return true;
}
@ -1318,7 +1320,7 @@ void GLR_RenderView (void)
}
if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL))
if (!r_worldentity.model || !cl.worldmodel)
if (!r_worldentity.model || r_worldentity.model->needload || !cl.worldmodel)
{
GL_DoSwap();

View File

@ -67,6 +67,8 @@ void GLSCR_UpdateScreen (void)
qboolean noworld;
RSpeedMark();
r_refdef.pxrect.maxheight = vid.pixelheight;
vid.numpages = 2 + vid_triplebuffer.value;
if (scr_disabled_for_loading)

View File

@ -830,6 +830,8 @@ static void Shader_FogParms ( shader_t *shader, shaderpass_t *pass, char **ptr )
shader->fog_dist = 128.0f;
}
shader->fog_dist = 1.0f / shader->fog_dist;
shader->flags |= SHADER_NODLIGHT|SHADER_NOSHADOWS;
}
static void Shader_SurfaceParm ( shader_t *shader, shaderpass_t *pass, char **ptr )
@ -1143,10 +1145,10 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
}
typedef struct sgeneric_s
{
program_t prog;
struct sgeneric_s *next;
char *name;
qboolean failed;
program_t prog;
} sgeneric_t;
static sgeneric_t *sgenerics;
struct sbuiltin_s
@ -1435,6 +1437,10 @@ void Shader_UnloadProg(program_t *prog)
// D3DShader_DeleteProgram(&prog->handle[p].hlsl);
}
}
#endif
#ifdef D3D11QUAKE
if (qrenderer == QR_DIRECT3D11)
D3D11Shader_DeleteProgram(prog);
#endif
free(prog);
}
@ -1449,7 +1455,7 @@ static void Shader_FlushGenerics(void)
if (g->prog.refs == 1)
{
g->prog.refs--;
free(g);
Shader_UnloadProg(&g->prog);
}
else
Con_Printf("generic shader still used\n");
@ -1963,10 +1969,14 @@ static void Shader_ProgramName (shader_t *shader, shaderpass_t *pass, char **ptr
{
Shader_SLProgramName(shader,pass,ptr,qrenderer);
}
static void Shader_HLSLProgramName (shader_t *shader, shaderpass_t *pass, char **ptr)
static void Shader_HLSL9ProgramName (shader_t *shader, shaderpass_t *pass, char **ptr)
{
Shader_SLProgramName(shader,pass,ptr,QR_DIRECT3D9);
}
static void Shader_HLSL11ProgramName (shader_t *shader, shaderpass_t *pass, char **ptr)
{
Shader_SLProgramName(shader,pass,ptr,QR_DIRECT3D11);
}
static void Shader_ProgramParam ( shader_t *shader, shaderpass_t *pass, char **ptr )
{
@ -2242,7 +2252,8 @@ static shaderkey_t shaderkeys[] =
{"lpp_light", Shader_Prelight},
{"glslprogram", Shader_GLSLProgramName},
{"program", Shader_ProgramName}, //gl or d3d
{"hlslprogram", Shader_HLSLProgramName}, //for d3d
{"hlslprogram", Shader_HLSL9ProgramName}, //for d3d
{"hlsl11program", Shader_HLSL11ProgramName}, //for d3d
{"param", Shader_ProgramParam}, //legacy
{"bemode", Shader_BEMode},
@ -2334,6 +2345,7 @@ static qboolean Shaderpass_MapGen (shader_t *shader, shaderpass_t *pass, char *t
{
pass->texgen = T_GEN_SHADOWMAP;
pass->tcgen = TC_GEN_BASE; //FIXME: moo!
pass->flags |= SHADER_PASS_DEPTHCMP;
}
else if (!Q_stricmp (tname, "$lightcubemap"))
{
@ -4581,6 +4593,10 @@ char *Shader_DefaultBSPWater(char *shortname)
}
}
void Shader_DefaultWaterShader(char *shortname, shader_t *s, const void *args)
{
Shader_DefaultScript(shortname, s, Shader_DefaultBSPWater(shortname));
}
void Shader_DefaultBSPQ2(char *shortname, shader_t *s, const void *args)
{
if (!strncmp(shortname, "sky/", 4))

View File

@ -25,6 +25,12 @@ extern LPDIRECT3DDEVICE9 pD3DDev9;
void D3D9BE_Cull(unsigned int sflags);
void D3D9BE_RenderShadowBuffer(unsigned int numverts, IDirect3DVertexBuffer9 *vbuf, unsigned int numindicies, IDirect3DIndexBuffer9 *ibuf);
#endif
#ifdef D3D11QUAKE
void D3D11BE_GenerateShadowBuffer(void **vbuf, vecV_t *verts, int numverts, void **ibuf, index_t *indicies, int numindicies);
void D3D11BE_RenderShadowBuffer(unsigned int numverts, void *vbuf, unsigned int numindicies, void *ibuf);
void D3D11_DestroyShadowBuffer(void *vbuf, void *ibuf);
void D3D11BE_DoneShadows(void);
#endif
void GLBE_RenderShadowBuffer(unsigned int numverts, int vbo, vecV_t *verts, unsigned numindicies, int ibo, index_t *indicies);
static void SHM_Shutdown(void);
@ -149,8 +155,12 @@ typedef struct shadowmesh_s
GLuint vebo[2];
#endif
#ifdef D3D9QUAKE
IDirect3DVertexBuffer9 *d3d_vbuffer;
IDirect3DIndexBuffer9 *d3d_ibuffer;
IDirect3DVertexBuffer9 *d3d9_vbuffer;
IDirect3DIndexBuffer9 *d3d9_ibuffer;
#endif
#ifdef D3D11QUAKE
void *d3d11_vbuffer;
void *d3d11_ibuffer;
#endif
} shadowmesh_t;
@ -356,28 +366,34 @@ static void SH_FreeShadowMesh_(shadowmesh_t *sm)
{
case QR_NONE:
case QR_SOFTWARE:
case QR_DIRECT3D11:
default:
break;
case QR_OPENGL:
#ifdef GLQUAKE
case QR_OPENGL:
if (qglDeleteBuffersARB)
qglDeleteBuffersARB(2, sm->vebo);
sm->vebo[0] = 0;
sm->vebo[1] = 0;
#endif
break;
case QR_DIRECT3D9:
#endif
#ifdef D3D9QUAKE
if (sm->d3d_ibuffer)
IDirect3DIndexBuffer9_Release(sm->d3d_ibuffer);
sm->d3d_ibuffer = NULL;
if (sm->d3d_vbuffer)
IDirect3DVertexBuffer9_Release(sm->d3d_vbuffer);
sm->d3d_vbuffer = NULL;
#endif
case QR_DIRECT3D9:
if (sm->d3d9_ibuffer)
IDirect3DIndexBuffer9_Release(sm->d3d9_ibuffer);
sm->d3d9_ibuffer = NULL;
if (sm->d3d9_vbuffer)
IDirect3DVertexBuffer9_Release(sm->d3d9_vbuffer);
sm->d3d9_vbuffer = NULL;
break;
#endif
#ifdef D3D11QUAKE
case QR_DIRECT3D11:
D3D11_DestroyShadowBuffer(sm->d3d11_vbuffer, sm->d3d11_ibuffer);
sm->d3d11_vbuffer = NULL;
sm->d3d11_ibuffer = NULL;
break;
#endif
}
}
void SH_FreeShadowMesh(shadowmesh_t *sm)
@ -501,12 +517,13 @@ static struct shadowmesh_s *SHM_FinishShadowMesh(dlight_t *dl)
{
case QR_NONE:
case QR_SOFTWARE:
case QR_DIRECT3D11:
default:
break;
case QR_OPENGL:
#ifdef GLQUAKE
if (!qglGenBuffersARB)
return sh_shmesh;
qglGenBuffersARB(2, sh_shmesh->vebo);
GL_DeselectVAO();
@ -522,19 +539,24 @@ static struct shadowmesh_s *SHM_FinishShadowMesh(dlight_t *dl)
if (sh_shmesh->numindicies && sh_shmesh->numverts)
{
void *map;
IDirect3DDevice9_CreateIndexBuffer(pD3DDev9, sizeof(index_t) * sh_shmesh->numindicies, 0, D3DFMT_QINDEX, D3DPOOL_MANAGED, &sh_shmesh->d3d_ibuffer, NULL);
IDirect3DIndexBuffer9_Lock(sh_shmesh->d3d_ibuffer, 0, sizeof(index_t) * sh_shmesh->numindicies, &map, D3DLOCK_DISCARD);
IDirect3DDevice9_CreateIndexBuffer(pD3DDev9, sizeof(index_t) * sh_shmesh->numindicies, 0, D3DFMT_QINDEX, D3DPOOL_MANAGED, &sh_shmesh->d3d9_ibuffer, NULL);
IDirect3DIndexBuffer9_Lock(sh_shmesh->d3d9_ibuffer, 0, sizeof(index_t) * sh_shmesh->numindicies, &map, D3DLOCK_DISCARD);
memcpy(map, sh_shmesh->indicies, sizeof(index_t) * sh_shmesh->numindicies);
IDirect3DIndexBuffer9_Unlock(sh_shmesh->d3d_ibuffer);
IDirect3DIndexBuffer9_Unlock(sh_shmesh->d3d9_ibuffer);
IDirect3DDevice9_CreateVertexBuffer(pD3DDev9, sizeof(vecV_t) * sh_shmesh->numverts, D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &sh_shmesh->d3d_vbuffer, NULL);
IDirect3DVertexBuffer9_Lock(sh_shmesh->d3d_vbuffer, 0, sizeof(vecV_t) * sh_shmesh->numverts, &map, D3DLOCK_DISCARD);
IDirect3DDevice9_CreateVertexBuffer(pD3DDev9, sizeof(vecV_t) * sh_shmesh->numverts, D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &sh_shmesh->d3d9_vbuffer, NULL);
IDirect3DVertexBuffer9_Lock(sh_shmesh->d3d9_vbuffer, 0, sizeof(vecV_t) * sh_shmesh->numverts, &map, D3DLOCK_DISCARD);
memcpy(map, sh_shmesh->verts, sizeof(vecV_t) * sh_shmesh->numverts);
IDirect3DVertexBuffer9_Unlock(sh_shmesh->d3d_vbuffer);
IDirect3DVertexBuffer9_Unlock(sh_shmesh->d3d9_vbuffer);
}
#endif
break;
#ifdef D3D11QUAKE
case QR_DIRECT3D11:
D3D11BE_GenerateShadowBuffer(&sh_shmesh->d3d11_vbuffer, sh_shmesh->verts, sh_shmesh->numverts, &sh_shmesh->d3d11_ibuffer, sh_shmesh->indicies, sh_shmesh->numindicies);
break;
#endif
}
Z_Free(sh_shmesh->verts);
@ -2059,6 +2081,9 @@ void GL_EndRenderBuffer_DepthOnly(int restorefbo, texid_t depthtexture, int texs
qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize);
}
}
#endif
void D3D11BE_BeginShadowmapFace(void);
//determine the 5 bounding points of a shadowmap light projection side
//needs to match Sh_GenShadowFace
@ -2098,6 +2123,11 @@ static void Sh_GenShadowFace(dlight_t *l, shadowmesh_t *smesh, int face, int sms
texture_t *tex;
int tno;
/* if (face >= 3)
face -= 3;
else
face += 3;
*/
switch(face)
{
case 0:
@ -2155,21 +2185,21 @@ static void Sh_GenShadowFace(dlight_t *l, shadowmesh_t *smesh, int face, int sms
if (l->fov)
{
r_refdef.pxrect.x = 0;
r_refdef.pxrect.x = (SHADOWMAP_SIZE-smsize)/2;
r_refdef.pxrect.width = smsize;
r_refdef.pxrect.height = smsize;
r_refdef.pxrect.y = 0;
r_refdef.pxrect.y = (SHADOWMAP_SIZE-smsize)/2;
r_refdef.pxrect.maxheight = SHADOWMAP_SIZE;
}
else
{
r_refdef.pxrect.x = (face%3 * SHADOWMAP_SIZE) + (SHADOWMAP_SIZE-smsize)/2;
r_refdef.pxrect.width = smsize;
r_refdef.pxrect.height = smsize;
r_refdef.pxrect.y = r_refdef.pxrect.height - (((face>=3)*SHADOWMAP_SIZE) + (SHADOWMAP_SIZE-smsize)/2);
r_refdef.pxrect.y = (((face<3)*SHADOWMAP_SIZE) + (SHADOWMAP_SIZE-smsize)/2);
r_refdef.pxrect.maxheight = SHADOWMAP_SIZE*2;
}
qglViewport (r_refdef.pxrect.x, r_refdef.pxrect.height-r_refdef.pxrect.y, r_refdef.pxrect.width, r_refdef.pxrect.height);
R_SetFrustum(proj, r_refdef.m_view);
#ifdef DBG_COLOURNOTDEPTH
@ -2180,16 +2210,25 @@ static void Sh_GenShadowFace(dlight_t *l, shadowmesh_t *smesh, int face, int sms
BE_SelectEntity(&r_worldentity);
GL_CullFace(SHADER_CULL_FRONT);
switch(qrenderer)
{
#ifdef GLQUAKE
if (qrenderer == QR_OPENGL)
{
case QR_OPENGL:
GL_ViewportUpdate();
GL_CullFace(SHADER_CULL_FRONT);
GLBE_RenderShadowBuffer(smesh->numverts, smesh->vebo[0], smesh->verts, smesh->numindicies, smesh->vebo[1], smesh->indicies);
}
else
break;
#endif
{
#ifdef D3D11QUAKE
case QR_DIRECT3D11:
//d3d render targets are upside down
r_refdef.pxrect.y = r_refdef.pxrect.maxheight -(r_refdef.pxrect.y+r_refdef.pxrect.height);
D3D11BE_BeginShadowmapFace();
D3D11BE_RenderShadowBuffer(smesh->numverts, smesh->d3d11_vbuffer, smesh->numindicies, smesh->d3d11_ibuffer);
break;
#endif
default:
//FIXME: should be able to merge batches between textures+lightmaps.
for (tno = 0; tno < smesh->numbatches; tno++)
{
@ -2200,6 +2239,7 @@ static void Sh_GenShadowFace(dlight_t *l, shadowmesh_t *smesh, int face, int sms
continue;
BE_DrawMesh_List(tex->shader, smesh->batches[tno].count, smesh->batches[tno].s, cl.worldmodel->shadowbatches[tno].vbo, &tex->shader->defaulttextures, 0);
}
break;
}
//fixme: this walks through the entity lists up to 6 times per frame.
@ -2207,16 +2247,21 @@ static void Sh_GenShadowFace(dlight_t *l, shadowmesh_t *smesh, int face, int sms
{
default:
break;
case QR_OPENGL:
#ifdef GLQUAKE
case QR_OPENGL:
GLBE_BaseEntTextures();
#endif
break;
case QR_DIRECT3D9:
#endif
#ifdef D3D9QUAKE
case QR_DIRECT3D9:
D3D9BE_BaseEntTextures();
#endif
break;
#endif
#ifdef D3D11QUAKE
case QR_DIRECT3D11:
D3D11BE_BaseEntTextures();
break;
#endif
}
/*
@ -2245,12 +2290,17 @@ static void Sh_GenShadowFace(dlight_t *l, shadowmesh_t *smesh, int face, int sms
*/
}
void D3D11_BeginShadowMap(int id, int w, int h);
void D3D11_EndShadowMap(void);
void D3D11BE_SetupForShadowMap(dlight_t *dl, qboolean isspot, int texwidth, int texheight, float shadowscale);
qboolean Sh_GenShadowMap (dlight_t *l, qbyte *lvis, int smsize)
{
int restorefbo;
int restorefbo = 0;
int f;
float oproj[16], oview[16];
vrect_t oprect;
pxrect_t oprect;
shadowmesh_t *smesh;
int isspot = (l->fov != 0);
extern cvar_t r_shadow_shadowmapping_precision;
@ -2299,69 +2349,83 @@ qboolean Sh_GenShadowMap (dlight_t *l, qbyte *lvis, int smsize)
if (!sidevisible)
return false;
if (!TEXVALID(shadowmap[isspot]))
{
if (isspot)
{
shadowmap[isspot] = GL_AllocNewTexture("***shadowmap2dspot***", SHADOWMAP_SIZE, SHADOWMAP_SIZE, 0);
GL_MTBind(0, GL_TEXTURE_2D, shadowmap[isspot]);
#ifdef DBG_COLOURNOTDEPTH
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SHADOWMAP_SIZE, SHADOWMAP_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
#else
qglTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16_ARB, SHADOWMAP_SIZE, SHADOWMAP_SIZE, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
#endif
}
else
{
shadowmap[isspot] = GL_AllocNewTexture("***shadowmap2dcube***", SHADOWMAP_SIZE*3, SHADOWMAP_SIZE*2, 0);
GL_MTBind(0, GL_TEXTURE_2D, shadowmap[isspot]);
#ifdef DBG_COLOURNOTDEPTH
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SHADOWMAP_SIZE*3, SHADOWMAP_SIZE*2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
#else
qglTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16_ARB, SHADOWMAP_SIZE*3, SHADOWMAP_SIZE*2, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
#endif
}
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
#if 1//def DBG_COLOURNOTDEPTH
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
#else
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
#endif
//in case we're using shadow samplers
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
qglTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
}
smesh = SHM_BuildShadowMesh(l, lvis, NULL, SMT_SHADOWMAP);
/*set framebuffer*/
GL_BeginRenderBuffer_DepthOnly(shadowmap[isspot]);
restorefbo = GLBE_SetupForShadowMap(shadowmap[isspot], isspot?smsize:smsize*3, isspot?smsize:smsize*2, (smsize-4) / (float)SHADOWMAP_SIZE);
BE_Scissor(NULL);
qglViewport(0, 0, smsize*3, smsize*2);
qglClear (GL_DEPTH_BUFFER_BIT);
#ifdef DBG_COLOURNOTDEPTH
qglClearColor(0,1,0,1);
qglClear (GL_COLOR_BUFFER_BIT);
#endif
memcpy(oproj, r_refdef.m_projection, sizeof(oproj));
memcpy(oview, r_refdef.m_view, sizeof(oview));
oprect = r_refdef.pxrect;
smesh = SHM_BuildShadowMesh(l, lvis, NULL, SMT_SHADOWMAP);
Matrix4x4_CM_Projection_Far(r_refdef.m_projection, l->fov?l->fov:90, l->fov?l->fov:90, r_shadow_shadowmapping_nearclip.value, l->radius);
if (!gl_config.nofixedfunc)
switch(qrenderer)
{
qglMatrixMode(GL_PROJECTION);
qglLoadMatrixf(r_refdef.m_projection);
qglMatrixMode(GL_MODELVIEW);
#ifdef GLQUAKE
case QR_OPENGL:
if (!TEXVALID(shadowmap[isspot]))
{
if (isspot)
{
shadowmap[isspot] = GL_AllocNewTexture("***shadowmap2dspot***", SHADOWMAP_SIZE, SHADOWMAP_SIZE, 0);
GL_MTBind(0, GL_TEXTURE_2D, shadowmap[isspot]);
#ifdef DBG_COLOURNOTDEPTH
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SHADOWMAP_SIZE, SHADOWMAP_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
#else
qglTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16_ARB, SHADOWMAP_SIZE, SHADOWMAP_SIZE, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
#endif
}
else
{
shadowmap[isspot] = GL_AllocNewTexture("***shadowmap2dcube***", SHADOWMAP_SIZE*3, SHADOWMAP_SIZE*2, 0);
GL_MTBind(0, GL_TEXTURE_2D, shadowmap[isspot]);
#ifdef DBG_COLOURNOTDEPTH
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SHADOWMAP_SIZE*3, SHADOWMAP_SIZE*2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
#else
qglTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16_ARB, SHADOWMAP_SIZE*3, SHADOWMAP_SIZE*2, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
#endif
}
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
#if 1//def DBG_COLOURNOTDEPTH
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
#else
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
#endif
//in case we're using shadow samplers
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
qglTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
}
/*set framebuffer*/
GL_BeginRenderBuffer_DepthOnly(shadowmap[isspot]);
restorefbo = GLBE_SetupForShadowMap(shadowmap[isspot], isspot?smsize:smsize*3, isspot?smsize:smsize*2, (smsize-4) / (float)SHADOWMAP_SIZE);
BE_Scissor(NULL);
qglViewport(0, 0, smsize*3, smsize*2);
qglClear (GL_DEPTH_BUFFER_BIT);
#ifdef DBG_COLOURNOTDEPTH
qglClearColor(0,1,0,1);
qglClear (GL_COLOR_BUFFER_BIT);
#endif
if (!gl_config.nofixedfunc)
{
qglMatrixMode(GL_PROJECTION);
qglLoadMatrixf(r_refdef.m_projection);
qglMatrixMode(GL_MODELVIEW);
}
break;
#endif
#ifdef D3D11QUAKE
case QR_DIRECT3D11:
D3D11_BeginShadowMap(isspot, (isspot?SHADOWMAP_SIZE:(SHADOWMAP_SIZE*3)), (isspot?SHADOWMAP_SIZE:(SHADOWMAP_SIZE*2)));
// BE_Scissor(&rect);
break;
#endif
}
r_refdef.externalview = true; //never any viewmodels
@ -2376,27 +2440,39 @@ qboolean Sh_GenShadowMap (dlight_t *l, qbyte *lvis, int smsize)
}
}
/*end framebuffer*/
GL_EndRenderBuffer_DepthOnly(restorefbo, shadowmap[isspot], smsize);
memcpy(r_refdef.m_view, oview, sizeof(r_refdef.m_view));
memcpy(r_refdef.m_projection, oproj, sizeof(r_refdef.m_projection));
r_refdef.pxrect = oprect;
if (!gl_config.nofixedfunc)
{
qglMatrixMode(GL_PROJECTION);
qglLoadMatrixf(r_refdef.m_projection);
qglMatrixMode(GL_MODELVIEW);
qglLoadMatrixf(r_refdef.m_view);
}
qglViewport(r_refdef.pxrect.x, r_refdef.pxrect.y-r_refdef.pxrect.height, r_refdef.pxrect.width, r_refdef.pxrect.height);
r_refdef.flipcull = oldflip;
r_refdef.externalview = oldexternalview;
R_SetFrustum(r_refdef.m_projection, r_refdef.m_view);
switch(qrenderer)
{
#ifdef GLQUAKE
case QR_OPENGL:
/*end framebuffer*/
GL_EndRenderBuffer_DepthOnly(restorefbo, shadowmap[isspot], smsize);
if (!gl_config.nofixedfunc)
{
qglMatrixMode(GL_PROJECTION);
qglLoadMatrixf(r_refdef.m_projection);
qglMatrixMode(GL_MODELVIEW);
qglLoadMatrixf(r_refdef.m_view);
}
GL_ViewportUpdate();
break;
#endif
#ifdef D3D11QUAKE
case QR_DIRECT3D11:
D3D11_EndShadowMap();
D3D11BE_DoneShadows();
break;
#endif
}
return true;
}
@ -2406,6 +2482,7 @@ static void Sh_DrawShadowMapLight(dlight_t *l, vec3_t colour, qbyte *vvis)
qbyte *lvis;
srect_t rect;
int smsize;
qboolean isspot;
if (R_CullSphere(l->origin, l->radius))
{
@ -2455,7 +2532,8 @@ static void Sh_DrawShadowMapLight(dlight_t *l, vec3_t colour, qbyte *vvis)
lvis = NULL;
if (l->fov != 0)
isspot = l->fov != 0;
if (isspot)
smsize = SHADOWMAP_SIZE;
else
{
@ -2472,8 +2550,13 @@ static void Sh_DrawShadowMapLight(dlight_t *l, vec3_t colour, qbyte *vvis)
smsize = bound(16, lodlinear, SHADOWMAP_SIZE);
}
if (!BE_SelectDLight(l, colour, l->fov?LSHADER_SPOT:LSHADER_SMAP))
return; //can't get a shader loaded
#ifdef D3D11QUAKE
if (qrenderer == QR_DIRECT3D11)
D3D11BE_SetupForShadowMap(l, isspot, isspot?smsize:smsize*3, isspot?smsize:smsize*2, (smsize-4) / (float)SHADOWMAP_SIZE);
#endif
if (!BE_SelectDLight(l, colour, isspot?LSHADER_SPOT:LSHADER_SMAP))
return;
if (!Sh_GenShadowMap(l, lvis, smsize))
return;
@ -2488,40 +2571,8 @@ static void Sh_DrawShadowMapLight(dlight_t *l, vec3_t colour, qbyte *vvis)
Sh_DrawEntLighting(l, colour);
}
#endif
// warning: Sh_WorldLightingPass defined but not used
/*
static void Sh_WorldLightingPass(void)
{
msurface_t *s;
int i;
int ve;
ve = 0;
for (i = 0; i < cl.worldmodel->numsurfaces; i++)
{
s = &cl.worldmodel->surfaces[i];
if(s->visframe != r_framecount)
continue;
if (ve != s->texinfo->texture->vbo.vboe)
{
ve = s->texinfo->texture->vbo.vboe;
GL_SelectVBO(s->texinfo->texture->vbo.vbocoord);
GL_SelectEBO(s->texinfo->texture->vbo.vboe);
qglVertexPointer(3, GL_FLOAT, sizeof(vecV_t), s->texinfo->texture->vbo.coord);
}
qglDrawRangeElements(GL_TRIANGLES, s->mesh->vbofirstvert, s->mesh->numvertexes, s->mesh->numindexes, GL_INDEX_TYPE, (index_t*)(s->mesh->vbofirstelement*sizeof(index_t)));
RQuantAdd(RQUANT_LITFACES, s->mesh->numindexes);
}
}
*/
/*
draws faces facing the light
Note: Backend mode must have been selected in advance, as must the light to light from
@ -2553,16 +2604,21 @@ static void Sh_DrawEntLighting(dlight_t *light, vec3_t colour)
{
default:
break;
case QR_OPENGL:
#ifdef GLQUAKE
case QR_OPENGL:
GLBE_BaseEntTextures();
#endif
break;
case QR_DIRECT3D9:
#endif
#ifdef D3D9QUAKE
case QR_DIRECT3D9:
D3D9BE_BaseEntTextures();
#endif
break;
#endif
#ifdef D3D11QUAKE
case QR_DIRECT3D11:
D3D11BE_BaseEntTextures();
break;
#endif
}
}
}
@ -2696,25 +2752,31 @@ static void Sh_DrawStencilLightShadows(dlight_t *dl, qbyte *lvis, qbyte *vvis, q
{
case QR_NONE:
case QR_SOFTWARE:
case QR_DIRECT3D11:
default:
break;
case QR_DIRECT3D9:
#ifdef D3D11QUAKE
case QR_DIRECT3D11:
D3D11BE_RenderShadowBuffer(sm->numverts, sm->d3d11_vbuffer, sm->numindicies, sm->d3d11_ibuffer);
break;
#endif
#ifdef D3D9QUAKE
D3D9BE_RenderShadowBuffer(sm->numverts, sm->d3d_vbuffer, sm->numindicies, sm->d3d_ibuffer);
#endif
case QR_DIRECT3D9:
D3D9BE_RenderShadowBuffer(sm->numverts, sm->d3d9_vbuffer, sm->numindicies, sm->d3d9_ibuffer);
break;
case QR_OPENGL:
#endif
#ifdef GLQUAKE
case QR_OPENGL:
GLBE_RenderShadowBuffer(sm->numverts, sm->vebo[0], sm->verts, sm->numindicies, sm->vebo[1], sm->indicies);
#endif
break;
#endif
}
}
if (!r_drawentities.value)
return;
if (qrenderer == QR_DIRECT3D11)
return;
#ifdef GLQUAKE
if (gl_config.nofixedfunc)
return; /*hackzone*/
@ -3230,6 +3292,65 @@ void Com_ParseVector(char *str, vec3_t out)
out[2] = atof(com_token);
}
void Sh_CheckSettings(void)
{
qboolean canstencil = false, cansmap = false;
r_shadow_shadowmapping.ival = r_shadow_shadowmapping.value;
r_shadow_realtime_world.ival = r_shadow_realtime_world.value;
r_shadow_realtime_dlight.ival = r_shadow_realtime_dlight.value;
switch(qrenderer)
{
#ifdef GLQUAKE
case QR_OPENGL:
if (gl_config.arb_shader_objects && gl_config.ext_framebuffer_objects && gl_config.arb_shadow)
cansmap = true;
if (gl_stencilbits)
canstencil = true;
break;
#endif
#ifdef D3D9QUAKE
case QR_DIRECT3D9:
#ifndef GLQUAKE
//the code still has a lot of ifdefs, so will crash if you try it in a merged build.
//its not really usable in d3d-only builds either, so no great loss.
canstencil = true;
#endif
break;
#endif
#ifdef D3D11QUAKE
case QR_DIRECT3D11:
cansmap = true;
break;
#endif
default:
r_shadow_realtime_world.ival = 0;
r_shadow_realtime_dlight.ival = 0;
return;
}
if (!canstencil && !cansmap)
{
//no shadow methods available at all.
Con_Printf("Missing GL extensions: realtime lighting is not possible.\n");
r_shadow_realtime_world.ival = 0;
r_shadow_realtime_dlight.ival = 0;
}
else if (!canstencil || !cansmap)
{
//only one shadow method
if (!!r_shadow_shadowmapping.ival != cansmap)
{
Con_Printf("Missing GL extensions: forcing shadowmapping %s.\n", cansmap?"on":"off");
r_shadow_shadowmapping.ival = cansmap;
}
}
else
{
//both shadow methods available.
}
}
void Sh_DrawLights(qbyte *vis)
{
vec3_t colour;
@ -3237,44 +3358,6 @@ void Sh_DrawLights(qbyte *vis)
int i;
unsigned int ignoreflags;
switch(qrenderer)
{
#ifdef GLQUAKE
case QR_OPENGL:
if (r_shadow_shadowmapping.ival)
{ //if we've no glsl or fbos, shadowmapping ain't possible, so don't use it.
if (!gl_config.arb_shader_objects || !gl_config.ext_framebuffer_objects || !gl_config.arb_shadow)
{
//disable stuff if we can't cope with it
Con_Printf("Missing GL extensions: switching off shadowmapping.\n");
r_shadow_shadowmapping.ival = 0;
}
}
if (!r_shadow_shadowmapping.ival)
{ //if we're using stencil shadows, give up if there's no stencil buffer
if (!gl_stencilbits)
{
Con_Printf("Missing GL extensions: switching off realtime lighting.\n");
r_shadow_realtime_world.ival = 0;
r_shadow_realtime_dlight.ival = 0;
}
}
break;
#endif
#ifdef D3D9QUAKE
case QR_DIRECT3D9:
r_shadow_shadowmapping.ival = 0;
#ifdef GLQUAKE
//the code still has a lot of ifdefs, so will crash if you try it in a merged build.
//its not really usable in d3d-only builds either, so no great loss.
return;
#endif
break;
#endif
default:
return;
}
if (r_shadow_realtime_world.modified ||
r_shadow_realtime_world_shadows.modified ||
r_shadow_realtime_dlight.modified ||
@ -3287,6 +3370,7 @@ void Sh_DrawLights(qbyte *vis)
r_shadow_realtime_dlight_shadows.modified =
r_shadow_shadowmapping.modified =
false;
Sh_CheckSettings();
//make sure the lighting is reloaded
Sh_PreGenerateLights();
}
@ -3337,9 +3421,7 @@ void Sh_DrawLights(qbyte *vis)
}
else if ((dl->flags & LFLAG_SHADOWMAP) || r_shadow_shadowmapping.ival)
{
#ifdef GLQUAKE
Sh_DrawShadowMapLight(dl, colour, vis);
#endif
}
else
{

View File

@ -726,8 +726,8 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
gl_config.arb_texture_cube_map = GL_CheckExtension("GL_ARB_texture_cube_map");
#if !defined(GL_STATIC)
/*vbos*/
if (gl_config.gles && gl_config.glversion >= 2)
/*vbos, were made core in gl1.5 or gles2.0*/
if ((gl_config.gles && gl_config.glversion >= 2) || (!gl_config.gles && (gl_major_version > 1 || (gl_major_version == 1 && gl_minor_version >= 5))))
{
qglGenBuffersARB = (void *)getglext("glGenBuffers");
qglDeleteBuffersARB = (void *)getglext("glDeleteBuffers");

View File

@ -203,7 +203,11 @@ static qboolean x11_initlib(void)
if (!x11.lib)
{
#ifdef __CYGWIN__
x11.lib = Sys_LoadLibrary("cygX11-6.dll", x11_functable);
#else
x11.lib = Sys_LoadLibrary("libX11.so.6", x11_functable);
#endif
if (!x11.lib)
x11.lib = Sys_LoadLibrary("libX11", x11_functable);
@ -472,7 +476,7 @@ char clipboard_buffer[SYS_CLIPBOARD_SIZE];
/*-----------------------------------------------------------------------*/
static void *gllibrary;
static dllhandle_t *gllibrary;
XVisualInfo* (*qglXChooseVisual) (Display *dpy, int screen, int *attribList);
void (*qglXSwapBuffers) (Display *dpy, GLXDrawable drawable);
@ -483,34 +487,36 @@ void *(*qglXGetProcAddress) (char *name);
void GLX_CloseLibrary(void)
{
dlclose(gllibrary);
Sys_CloseLibrary(gllibrary);
gllibrary = NULL;
}
qboolean GLX_InitLibrary(char *driver)
{
dllfunction_t funcs[] =
{
{(void*)&qglXChooseVisual, "glXChooseVisual"},
{(void*)&qglXSwapBuffers, "glXSwapBuffers"},
{(void*)&qglXMakeCurrent, "glXMakeCurrent"},
{(void*)&qglXCreateContext, "glXCreateContext"},
{(void*)&qglXDestroyContext, "glXDestroyContext"},
{NULL, NULL}
};
if (driver && *driver)
gllibrary = dlopen(driver, RTLD_LAZY);
gllibrary = Sys_LoadLibrary(driver, funcs);
else
gllibrary = NULL;
if (!gllibrary) //I hate this.
gllibrary = dlopen("libGL.so.1", RTLD_LAZY);
gllibrary = Sys_LoadLibrary("libGL.so.1", funcs);
if (!gllibrary)
gllibrary = dlopen("libGL.so", RTLD_LAZY);
gllibrary = Sys_LoadLibrary("libGL", funcs);
if (!gllibrary)
return false;
qglXChooseVisual = dlsym(gllibrary, "glXChooseVisual");
qglXSwapBuffers = dlsym(gllibrary, "glXSwapBuffers");
qglXMakeCurrent = dlsym(gllibrary, "glXMakeCurrent");
qglXCreateContext = dlsym(gllibrary, "glXCreateContext");
qglXDestroyContext = dlsym(gllibrary, "glXDestroyContext");
qglXGetProcAddress = dlsym(gllibrary, "glXGetProcAddress");
qglXGetProcAddress = Sys_GetAddressForName(gllibrary, "glXGetProcAddress");
if (!qglXGetProcAddress)
qglXGetProcAddress = dlsym(gllibrary, "glXGetProcAddressARB");
if (!qglXSwapBuffers && !qglXDestroyContext && !qglXCreateContext && !qglXMakeCurrent && !qglXChooseVisual)
return false;
qglXGetProcAddress = Sys_GetAddressForName(gllibrary, "glXGetProcAddressARB");
return true;
}
@ -525,7 +531,7 @@ void *GLX_GetSymbol(char *name)
symb = NULL;
if (!symb)
symb = dlsym(gllibrary, name);
symb = Sys_GetAddressForName(gllibrary, name);
return symb;
}
@ -1431,7 +1437,7 @@ qboolean X11VID_Init (rendererstate_t *info, unsigned char *palette, int psl)
{
#ifdef USE_EGL
case PSL_EGL:
if (!EGL_LoadLibrary(info->glrenderer))
if (!EGL_LoadLibrary(info->subrenderer))
{
Con_Printf("couldn't load EGL library\n");
return false;
@ -1439,7 +1445,7 @@ qboolean X11VID_Init (rendererstate_t *info, unsigned char *palette, int psl)
break;
#endif
case PSL_GLX:
if (!GLX_InitLibrary(info->glrenderer))
if (!GLX_InitLibrary(info->subrenderer))
{
Con_Printf("Couldn't intialise GLX\nEither your drivers are not installed or you need to specify the library name with the gl_driver cvar\n");
return false;
@ -1526,7 +1532,7 @@ qboolean X11VID_Init (rendererstate_t *info, unsigned char *palette, int psl)
if ((!(fullscreenflags & FULLSCREEN_VMODE) || vm.usemode <= 0) && X_CheckWMFullscreenAvailable())
fullscreenflags |= FULLSCREEN_WM;
else
fullscreenflags |= FULLSCREEN_LEGACY;
fullscreenflags |= FULLSCREEN_LEGACY;
}
else if (sys_parentwindow)
{
@ -1573,7 +1579,7 @@ qboolean X11VID_Init (rendererstate_t *info, unsigned char *palette, int psl)
CL_UpdateWindowTitle();
/*make it visible*/
if (fullscreen & FULLSCREEN_VMODE)
if (fullscreenflags & FULLSCREEN_VMODE)
{
x11.pXRaiseWindow(vid_dpy, vid_window);
x11.pXWarpPointer(vid_dpy, None, vid_window, 0, 0, 0, 0, 0, 0);

View File

@ -1081,7 +1081,7 @@ qboolean VID_AttachGL (rendererstate_t *info)
do
{
TRACE(("dbg: VID_AttachGL: GLInitialise\n"));
if (GLInitialise(info->glrenderer))
if (GLInitialise(info->subrenderer))
{
maindc = GetDC(mainwindow);
TRACE(("dbg: VID_AttachGL: bSetupPixelFormat\n"));
@ -1090,13 +1090,13 @@ qboolean VID_AttachGL (rendererstate_t *info)
ReleaseDC(mainwindow, maindc);
}
if (!*info->glrenderer || !stricmp(info->glrenderer, "opengl32.dll") || !stricmp(info->glrenderer, "opengl32")) //go for windows system dir if we failed with the default. Should help to avoid the 3dfx problem.
if (!*info->subrenderer || !stricmp(info->subrenderer, "opengl32.dll") || !stricmp(info->subrenderer, "opengl32")) //go for windows system dir if we failed with the default. Should help to avoid the 3dfx problem.
{
char systemgl[MAX_OSPATH+1];
GetSystemDirectory(systemgl, sizeof(systemgl)-1);
strncat(systemgl, "\\", sizeof(systemgl)-1);
if (*info->glrenderer)
strncat(systemgl, info->glrenderer, sizeof(systemgl)-1);
if (*info->subrenderer)
strncat(systemgl, info->subrenderer, sizeof(systemgl)-1);
else
strncat(systemgl, "opengl32.dll", sizeof(systemgl)-1);
TRACE(("dbg: VID_AttachGL: GLInitialise (system dir specific)\n"));

View File

@ -420,14 +420,6 @@ void R_BloomBlend(void);
void R_InitBloomTextures(void);
#endif
//
// gl_rsurf.c
//
#ifdef GLQUAKE
void GL_LoadShaders(void);
#endif
//
// gl_ngraph.c
//
@ -436,6 +428,12 @@ void R_NetGraph (void);
#if defined(GLQUAKE)
//updates the viewport correctly.
//pxrect.y is relative to the top.
//gl requires viewports specified relative to the bottom.
//so we need to do a little extra maths, which keeps confusing me, so one macro to ensure consistancy.
#define GL_ViewportUpdate() qglViewport(r_refdef.pxrect.x, r_refdef.pxrect.maxheight-(r_refdef.pxrect.y+r_refdef.pxrect.height), r_refdef.pxrect.width, r_refdef.pxrect.height)
#ifdef GL_STATIC
//these are the functions that are valid in gles2.
//other functions should never actually be used.

View File

@ -278,16 +278,21 @@ typedef struct shaderpass_s {
enum {
SHADER_PASS_CLAMP = 1<<0, //needed for d3d's sampler states, infects image flags
SHADER_PASS_NEAREST = 1<<1, //needed for d3d's sampler states, infects image flags
SHADER_PASS_NOMIPMAP = 1<<2, //infects image flags
SHADER_PASS_NOCOLORARRAY = 1<< 3,
SHADER_PASS_DEPTHCMP = 1<<2, //needed for d3d's sampler states
SHADER_PASS_NOMIPMAP = 1<<3, //infects image flags
SHADER_PASS_NOCOLORARRAY = 1<< 4,
//FIXME: remove these
SHADER_PASS_VIDEOMAP = 1 << 4,
SHADER_PASS_DETAIL = 1 << 5,
SHADER_PASS_LIGHTMAP = 1 << 6,
SHADER_PASS_DELUXMAP = 1 << 7,
SHADER_PASS_ANIMMAP = 1 << 8
SHADER_PASS_VIDEOMAP = 1 << 5,
SHADER_PASS_DETAIL = 1 << 6,
SHADER_PASS_LIGHTMAP = 1 << 7,
SHADER_PASS_DELUXMAP = 1 << 8,
SHADER_PASS_ANIMMAP = 1 << 9
} flags;
#ifdef D3D11QUAKE
void *becache; //cache for blendstate objects.
#endif
} shaderpass_t;
typedef struct
@ -414,9 +419,13 @@ union programhandle_u
{
void *vert;
void *frag;
void *ctabf;
void *ctabv;
void *layout;
#ifdef D3D9QUAKE
void *ctabf;
void *ctabv;
#endif
#ifdef D3D11QUAKE
void *layout;
#endif
} hlsl;
#endif
};
@ -513,6 +522,7 @@ struct shader_s
SHADER_HASNORMALMAP = 1 << 22, //says that we need to load a normalmap texture
SHADER_HASRIPPLEMAP = 1 << 23, //water surface disturbances for water splashes
SHADER_HASGLOSS = 1 << 24, //
SHADER_NOSHADOWS = 1 << 25, //don't cast shadows
} flags;
program_t *prog;
@ -552,6 +562,7 @@ void Shader_DefaultSkinShell(char *shortname, shader_t *s, const void *args);
void Shader_DefaultBSPLM(char *shortname, shader_t *s, const void *args);
void Shader_DefaultBSPQ1(char *shortname, shader_t *s, const void *args);
void Shader_DefaultBSPQ2(char *shortname, shader_t *s, const void *args);
void Shader_DefaultWaterShader(char *shortname, shader_t *s, const void *args);
void Shader_DefaultSkybox(char *shortname, shader_t *s, const void *args);
void Shader_DefaultCinematic(char *shortname, shader_t *s, const void *args);
void Shader_DefaultScript(char *shortname, shader_t *s, const void *args);
@ -641,8 +652,9 @@ void D3D11BE_SelectEntity(entity_t *ent);
qboolean D3D11BE_SelectDLight(dlight_t *dl, vec3_t colour, unsigned int lmode);
qboolean D3D11Shader_CreateProgram (program_t *prog, const char *name, int permu, char **precompilerconstants, char *vert, char *frag);
void D3D11Shader_DeleteProgram(program_t *prog);
int D3D11Shader_FindUniform(union programhandle_u *h, int type, char *name);
void D3D11Shader_Init(void);
qboolean D3D11Shader_Init(unsigned int featurelevel);
void D3D11BE_Reset(qboolean before);
void D3D11BE_SetupViewCBuffer(void);
void D3D11_UploadLightmap(lightmapinfo_t *lm);
@ -668,10 +680,12 @@ int GLBE_SetupForShadowMap(texid_t shadowmaptex, int texwidth, int texheight, fl
//Called from shadowmapping code into backend
void GLBE_BaseEntTextures(void);
void D3D9BE_BaseEntTextures(void);
void D3D11BE_BaseEntTextures(void);
//prebuilds shadow volumes
void Sh_PreGenerateLights(void);
//Draws lights, called from the backend
void Sh_DrawLights(qbyte *vis);
void Sh_CheckSettings(void);
void SH_FreeShadowMesh(struct shadowmesh_s *sm);
//frees all memory
void Sh_Shutdown(void);

View File

@ -517,10 +517,10 @@ static qboolean HTTP_DL_Work(struct dl_download *dl)
if (con->gzip)
{
#ifdef NPFTE
Con_Printf("HTTP: no support for gzipped files \"%s\"\n", dl->localname);
#else
#if !defined(NPFTE) && defined(AVAIL_ZLIB)
con->file = FS_OpenTemp();
#else
Con_Printf("HTTP: no support for gzipped files \"%s\"\n", dl->localname);
#endif
}
else
@ -618,7 +618,7 @@ static qboolean HTTP_DL_Work(struct dl_download *dl)
dl->status = DL_FAILED;
else
{
#ifndef NPFTE
#if !defined(NPFTE) && defined(AVAIL_ZLIB)
if (con->gzip)
{
VFS_SEEK(con->file, 0);
@ -714,7 +714,7 @@ void HTTPDL_Establish(struct dl_download *dl)
"Content-Length: %i\r\n"
"Content-Type: %s\r\n"
"Connection: close\r\n"
#ifndef NPFTE
#if !defined(NPFTE) && defined(AVAIL_ZLIB)
"Accept-Encoding: gzip\r\n"
#endif
"User-Agent: "FULLENGINENAME"\r\n"
@ -730,7 +730,7 @@ void HTTPDL_Establish(struct dl_download *dl)
"GET %s HTTP/1.1\r\n"
"Host: %s\r\n"
"Connection: close\r\n"
#ifndef NPFTE
#if !defined(NPFTE) && defined(AVAIL_ZLIB)
"Accept-Encoding: gzip\r\n"
#endif
"User-Agent: "FULLENGINENAME"\r\n"

View File

@ -513,7 +513,7 @@ reeval:
d16 = ED_GlobalAtOfs16(progfuncs, st->a);
f = ED_FieldAtOfs(progfuncs, OPB->_int + progfuncs->funcs.fieldadjust);
pr_xstatement = st-pr_statements;
if (PR_RunWarning(&progfuncs->funcs, "assignment to read-only entity in %s (%s.%s)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), d16?PR_StringToNative(&progfuncs->funcs, d16->s_name):NULL, f?f->name:NULL))
if (PR_RunWarning(&progfuncs->funcs, "assignment to read-only entity %i in %s (%s.%s)", OPA->edict, PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), d16?PR_StringToNative(&progfuncs->funcs, d16->s_name):NULL, f?f->name:NULL))
{
st--;
goto cont;
@ -542,7 +542,7 @@ reeval:
{
pr_xstatement = st-pr_statements;
if (PR_RunWarning (&progfuncs->funcs, "OP_LOAD references invalid entity in %s", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name)))
if (PR_RunWarning (&progfuncs->funcs, "OP_LOAD references invalid entity %i in %s", OPA->edict, PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name)))
{
st--;
goto cont;
@ -561,7 +561,7 @@ reeval:
if ((unsigned)OPA->edict >= (unsigned)sv_num_edicts)
{
pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "OP_LOAD_V references invalid entity in %s", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name));
PR_RunError (&progfuncs->funcs, "OP_LOAD_V references invalid entity %i in %s", OPA->edict, PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name));
}
ed = PROG_TO_EDICT(progfuncs, OPA->edict);
#ifdef PARANOID
@ -601,7 +601,7 @@ reeval:
case OP_IF_F:
RUNAWAYCHECK();
if (OPA->_int)
if (OPA->_float)
st += (sofs)st->b - 1; // offset the s++
break;

View File

@ -562,7 +562,7 @@ int PDECL PR_GetFuncArgCount(pubprogfuncs_t *ppf, func_t func)
}
}
func_t PDECL PR_FindFunc(pubprogfuncs_t *ppf, char *funcname, progsnum_t pnum)
func_t PDECL PR_FindFunc(pubprogfuncs_t *ppf, const char *funcname, progsnum_t pnum)
{
progfuncs_t *progfuncs = (progfuncs_t*)ppf;
dfunction_t *f=NULL;
@ -616,45 +616,54 @@ func_t PDECL PR_FindFunc(pubprogfuncs_t *ppf, char *funcname, progsnum_t pnum)
return 0;
}
void PDECL QC_FindPrefixedGlobals(pubprogfuncs_t *ppf, char *prefix, void (PDECL *found) (pubprogfuncs_t *progfuncs, char *name, union eval_s *val, etype_t type) )
void PDECL QC_FindPrefixedGlobals(pubprogfuncs_t *ppf, int pnum, char *prefix, void (PDECL *found) (pubprogfuncs_t *progfuncs, char *name, union eval_s *val, etype_t type, void *ctx), void *ctx)
{
progfuncs_t *progfuncs = (progfuncs_t*)ppf;
unsigned int i;
ddef16_t *def16;
ddef32_t *def32;
int len = strlen(prefix);
unsigned int pnum;
for (pnum = 0; pnum < maxprogs; pnum++)
if (pnum == PR_CURRENT)
pnum = pr_typecurrent;
if (pnum == PR_ANY)
{
if (!pr_progstate[pnum].progs)
continue;
switch(pr_progstate[pnum].structtype)
for (pnum = 0; (unsigned)pnum < maxprogs; pnum++)
{
case PST_DEFAULT:
case PST_KKQWSV:
for (i=1 ; i<pr_progstate[pnum].progs->numglobaldefs ; i++)
{
def16 = &pr_progstate[pnum].globaldefs16[i];
if (!strncmp(def16->s_name+progfuncs->funcs.stringtable,prefix, len))
found(&progfuncs->funcs, def16->s_name+progfuncs->funcs.stringtable, (eval_t *)&pr_progstate[pnum].globals[def16->ofs], def16->type);
}
break;
case PST_QTEST:
case PST_FTE32:
for (i=1 ; i<pr_progstate[pnum].progs->numglobaldefs ; i++)
{
def32 = &pr_progstate[pnum].globaldefs32[i];
if (!strncmp(def32->s_name+progfuncs->funcs.stringtable,prefix, len))
found(&progfuncs->funcs, def32->s_name+progfuncs->funcs.stringtable, (eval_t *)&pr_progstate[pnum].globals[def32->ofs], def32->type);
}
break;
if (!pr_progstate[pnum].progs)
continue;
QC_FindPrefixedGlobals(ppf, pnum, prefix, found, ctx);
}
return;
}
if (!pr_progstate[pnum].progs)
return;
switch(pr_progstate[pnum].structtype)
{
case PST_DEFAULT:
case PST_KKQWSV:
for (i=1 ; i<pr_progstate[pnum].progs->numglobaldefs ; i++)
{
def16 = &pr_progstate[pnum].globaldefs16[i];
if (!strncmp(def16->s_name+progfuncs->funcs.stringtable,prefix, len))
found(&progfuncs->funcs, def16->s_name+progfuncs->funcs.stringtable, (eval_t *)&pr_progstate[pnum].globals[def16->ofs], def16->type, ctx);
}
break;
case PST_QTEST:
case PST_FTE32:
for (i=1 ; i<pr_progstate[pnum].progs->numglobaldefs ; i++)
{
def32 = &pr_progstate[pnum].globaldefs32[i];
if (!strncmp(def32->s_name+progfuncs->funcs.stringtable,prefix, len))
found(&progfuncs->funcs, def32->s_name+progfuncs->funcs.stringtable, (eval_t *)&pr_progstate[pnum].globals[def32->ofs], def32->type, ctx);
}
break;
}
}
eval_t *PDECL PR_FindGlobal(pubprogfuncs_t *ppf, char *globname, progsnum_t pnum, etype_t *type)
eval_t *PDECL PR_FindGlobal(pubprogfuncs_t *ppf, const char *globname, progsnum_t pnum, etype_t *type)
{
progfuncs_t *progfuncs = (progfuncs_t*)ppf;
unsigned int i;

View File

@ -251,7 +251,7 @@ fdef_t *PDECL ED_FieldInfo (pubprogfuncs_t *ppf, unsigned int *count)
ED_FindField
============
*/
fdef_t *ED_FindField (progfuncs_t *progfuncs, char *name)
fdef_t *ED_FindField (progfuncs_t *progfuncs, const char *name)
{
unsigned int i;
@ -315,7 +315,7 @@ unsigned int ED_FindGlobalOfs (progfuncs_t *progfuncs, char *name)
return 0;
}
ddef16_t *ED_FindGlobalFromProgs16 (progfuncs_t *progfuncs, char *name, progsnum_t prnum)
ddef16_t *ED_FindGlobalFromProgs16 (progfuncs_t *progfuncs, const char *name, progsnum_t prnum)
{
ddef16_t *def;
unsigned int i;
@ -328,7 +328,7 @@ ddef16_t *ED_FindGlobalFromProgs16 (progfuncs_t *progfuncs, char *name, progsnum
}
return NULL;
}
ddef32_t *ED_FindGlobalFromProgs32 (progfuncs_t *progfuncs, char *name, progsnum_t prnum)
ddef32_t *ED_FindGlobalFromProgs32 (progfuncs_t *progfuncs, const char *name, progsnum_t prnum)
{
ddef32_t *def;
unsigned int i;
@ -342,7 +342,7 @@ ddef32_t *ED_FindGlobalFromProgs32 (progfuncs_t *progfuncs, char *name, progsnum
return NULL;
}
ddef16_t *ED_FindTypeGlobalFromProgs16 (progfuncs_t *progfuncs, char *name, progsnum_t prnum, int type)
ddef16_t *ED_FindTypeGlobalFromProgs16 (progfuncs_t *progfuncs, const char *name, progsnum_t prnum, int type)
{
ddef16_t *def;
unsigned int i;
@ -366,7 +366,7 @@ ddef16_t *ED_FindTypeGlobalFromProgs16 (progfuncs_t *progfuncs, char *name, prog
}
ddef32_t *ED_FindTypeGlobalFromProgs32 (progfuncs_t *progfuncs, char *name, progsnum_t prnum, int type)
ddef32_t *ED_FindTypeGlobalFromProgs32 (progfuncs_t *progfuncs, const char *name, progsnum_t prnum, int type)
{
ddef32_t *def;
unsigned int i;
@ -419,7 +419,7 @@ unsigned int *ED_FindGlobalOfsFromProgs (progfuncs_t *progfuncs, char *name, pro
ED_FindFunction
============
*/
dfunction_t *ED_FindFunction (progfuncs_t *progfuncs, char *name, progsnum_t *prnum, progsnum_t fromprogs)
dfunction_t *ED_FindFunction (progfuncs_t *progfuncs, const char *name, progsnum_t *prnum, progsnum_t fromprogs)
{
dfunction_t *func;
unsigned int i;
@ -1042,7 +1042,7 @@ void ED_Count (progfuncs_t *progfuncs)
ED_NewString
=============
*/
char *PDECL ED_NewString (pubprogfuncs_t *ppf, char *string, int minlength)
char *PDECL ED_NewString (pubprogfuncs_t *ppf, const char *string, int minlength, pbool demarkup)
{
progfuncs_t *progfuncs = (progfuncs_t*)ppf;
char *newc, *new_p;
@ -1060,7 +1060,7 @@ char *PDECL ED_NewString (pubprogfuncs_t *ppf, char *string, int minlength)
for (i=0 ; i< l ; i++)
{
if (string[i] == '\\' && i < l-1 && string[i+1] != 0)
if (demarkup && string[i] == '\\' && i < l-1 && string[i+1] != 0)
{
i++;
if (string[i] == 'n')
@ -1097,7 +1097,7 @@ pbool PDECL ED_ParseEval (pubprogfuncs_t *ppf, eval_t *eval, int type, char *s)
switch (type & ~DEF_SAVEGLOBAL)
{
case ev_string:
st = PR_StringToProgs(&progfuncs->funcs, ED_NewString (&progfuncs->funcs, s, 0));
st = PR_StringToProgs(&progfuncs->funcs, ED_NewString (&progfuncs->funcs, s, 0, true));
eval->string = st;
break;
@ -1181,7 +1181,7 @@ pbool ED_ParseEpair (progfuncs_t *progfuncs, int qcptr, unsigned int fldofs, int
switch (type)
{
case ev_string:
st = PR_StringToProgs(&progfuncs->funcs, ED_NewString (&progfuncs->funcs, s, 0));
st = PR_StringToProgs(&progfuncs->funcs, ED_NewString (&progfuncs->funcs, s, 0, true));
*(string_t *)(progfuncs->funcs.stringtable + qcptr) = st;
break;

View File

@ -783,7 +783,7 @@ char *PDECL PR_EvaluateDebugString(pubprogfuncs_t *ppf, char *key)
switch (type&~DEF_SAVEGLOBAL)
{
case ev_string:
*(string_t *)val = PR_StringToProgs(&progfuncs->funcs, ED_NewString (&progfuncs->funcs, assignment, 0));
*(string_t *)val = PR_StringToProgs(&progfuncs->funcs, ED_NewString (&progfuncs->funcs, assignment, 0, true));
break;
case ev_float:

View File

@ -365,7 +365,7 @@ void PR_Profile_f (void);
struct edict_s *PDECL ED_Alloc (pubprogfuncs_t *progfuncs);
void PDECL ED_Free (pubprogfuncs_t *progfuncs, struct edict_s *ed);
char *PDECL ED_NewString (pubprogfuncs_t *progfuncs, char *string, int minlength);
char *PDECL ED_NewString (pubprogfuncs_t *ppf, const char *string, int minlength, pbool demarkup);
// returns a copy of the string allocated from the server's string heap
void PDECL ED_Print (pubprogfuncs_t *progfuncs, struct edict_s *ed);
@ -462,15 +462,15 @@ struct qcthread_s *PDECL PR_ForkStack (pubprogfuncs_t *progfuncs);
void PDECL PR_ResumeThread (pubprogfuncs_t *progfuncs, struct qcthread_s *thread);
void PDECL PR_AbortStack (pubprogfuncs_t *progfuncs);
eval_t *PDECL PR_FindGlobal(pubprogfuncs_t *prfuncs, char *globname, progsnum_t pnum, etype_t *type);
ddef16_t *ED_FindTypeGlobalFromProgs16 (progfuncs_t *progfuncs, char *name, progsnum_t prnum, int type);
ddef32_t *ED_FindTypeGlobalFromProgs32 (progfuncs_t *progfuncs, char *name, progsnum_t prnum, int type);
ddef16_t *ED_FindGlobalFromProgs16 (progfuncs_t *progfuncs, char *name, progsnum_t prnum);
ddef32_t *ED_FindGlobalFromProgs32 (progfuncs_t *progfuncs, char *name, progsnum_t prnum);
fdef_t *ED_FindField (progfuncs_t *progfuncs, char *name);
eval_t *PDECL PR_FindGlobal(pubprogfuncs_t *prfuncs, const char *globname, progsnum_t pnum, etype_t *type);
ddef16_t *ED_FindTypeGlobalFromProgs16 (progfuncs_t *progfuncs, const char *name, progsnum_t prnum, int type);
ddef32_t *ED_FindTypeGlobalFromProgs32 (progfuncs_t *progfuncs, const char *name, progsnum_t prnum, int type);
ddef16_t *ED_FindGlobalFromProgs16 (progfuncs_t *progfuncs, const char *name, progsnum_t prnum);
ddef32_t *ED_FindGlobalFromProgs32 (progfuncs_t *progfuncs, const char *name, progsnum_t prnum);
fdef_t *ED_FindField (progfuncs_t *progfuncs, const char *name);
fdef_t *ED_FieldAtOfs (progfuncs_t *progfuncs, unsigned int ofs);
dfunction_t *ED_FindFunction (progfuncs_t *progfuncs, char *name, progsnum_t *pnum, progsnum_t fromprogs);
func_t PDECL PR_FindFunc(pubprogfuncs_t *progfncs, char *funcname, progsnum_t pnum);
dfunction_t *ED_FindFunction (progfuncs_t *progfuncs, const char *name, progsnum_t *pnum, progsnum_t fromprogs);
func_t PDECL PR_FindFunc(pubprogfuncs_t *progfncs, const char *funcname, progsnum_t pnum);
void PDECL PR_Configure (pubprogfuncs_t *progfncs, size_t addressable_size, int max_progs);
int PDECL PR_InitEnts(pubprogfuncs_t *progfncs, int maxents);
char *PR_ValueString (progfuncs_t *progfuncs, etype_t type, eval_t *val, pbool verbose);

View File

@ -105,8 +105,8 @@ struct pubprogfuncs_s
char *(PDECL *saveent) (pubprogfuncs_t *prinst, char *buf, int *size, int maxsize, struct edict_s *ed); //will save just one entities vars
struct edict_s *(PDECL *restoreent) (pubprogfuncs_t *prinst, char *buf, int *size, struct edict_s *ed); //will restore the entity that had it's values saved (can use NULL for ed)
union eval_s *(PDECL *FindGlobal) (pubprogfuncs_t *prinst, char *name, progsnum_t num, etype_t *type); //find a pointer to the globals value
char *(PDECL *AddString) (pubprogfuncs_t *prinst, char *val, int minlength); //dump a string into the progs memory (for setting globals and whatnot)
union eval_s *(PDECL *FindGlobal) (pubprogfuncs_t *prinst, const char *name, progsnum_t num, etype_t *type); //find a pointer to the globals value
char *(PDECL *AddString) (pubprogfuncs_t *prinst, const char *val, int minlength, pbool demarkup); //dump a string into the progs memory (for setting globals and whatnot)
void *(PDECL *Tempmem) (pubprogfuncs_t *prinst, int ammount, char *whatfor); //grab some mem for as long as the progs stays loaded
union eval_s *(PDECL *GetEdictFieldValue)(pubprogfuncs_t *prinst, struct edict_s *ent, char *name, evalc_t *s); //get an entityvar (cache it) and return the possible values
@ -154,7 +154,7 @@ struct pubprogfuncs_s
int (PDECL *QueryField) (pubprogfuncs_t *prinst, unsigned int fieldoffset, etype_t *type, char **name, evalc_t *fieldcache); //find info on a field definition at an offset
void (PDECL *EntClear) (pubprogfuncs_t *progfuncs, struct edict_s *e);
void (PDECL *FindPrefixGlobals) (pubprogfuncs_t *progfuncs, char *prefix, void (PDECL *found) (pubprogfuncs_t *progfuncs, char *name, union eval_s *val, etype_t type) );
void (PDECL *FindPrefixGlobals) (pubprogfuncs_t *progfuncs, int prnum, char *prefix, void (PDECL *found) (pubprogfuncs_t *progfuncs, char *name, union eval_s *val, etype_t type, void *ctx), void *ctx);
void *(PDECL *AddressableAlloc) (pubprogfuncs_t *progfuncs, unsigned int ammount); /*returns memory within the qc block, use stringtoprogs to get a usable qc pointer/string*/
@ -272,7 +272,7 @@ typedef union eval_s
#define PR_FindFunction(pf, name, num) (*pf->FindFunction) (pf, name, num)
#define PR_FindGlobal(pf, name, progs, type) (*pf->FindGlobal) (pf, name, progs, type)
#define PR_AddString(pf, ed, len) (*pf->AddString) (pf, ed, len)
#define PR_AddString(pf, ed, len, demarkup) (*pf->AddString) (pf, ed, len, demarkup)
#define PR_Alloc(pf,size,whatfor) (*pf->Tempmem) (pf, size, whatfor)
#define PR_AddressableAlloc(pf,size) (*pf->AddressableAlloc) (pf, size)
#define PR_AddressableFree(pf,mem) (*pf->AddressableFree) (pf, mem)
@ -306,7 +306,7 @@ typedef union eval_s
#define PR_SetStringOfs(p,o,s) (G_INT(o) = s - p->stringtable)
*/
//#define PR_SetString(p, s) ((s&&*s)?(s - p->stringtable):0)
#define PR_NewString(p, s, l) PR_SetString(p, PR_AddString(p, s, l))
#define PR_NewString(p, s, l) PR_SetString(p, PR_AddString(p, s, l, false))
/**/
#define ev_prog ev_integer

View File

@ -11037,8 +11037,17 @@ void QCC_PR_ParseDefs (char *classname)
}
else
{
QCC_PR_CheckToken("#");
QCC_PR_Lex();
if (type->type == ev_string && QCC_PR_CheckName("_"))
{
QCC_PR_Expect("(");
QCC_PR_Lex();
QCC_PR_Expect(")");
}
else
{
QCC_PR_CheckToken("#");
QCC_PR_Lex();
}
}
continue;
}

View File

@ -1487,16 +1487,7 @@ void QCC_PR_LexString (void)
if (len >= sizeof(pr_immediate_string)-1)
QCC_Error(ERR_INVALIDSTRINGIMMEDIATE, "String length exceeds %i", sizeof(pr_immediate_string)-1);
while(*pr_file_p && qcc_iswhite(*pr_file_p))
{
if (*pr_file_p == '\n')
{
pr_file_p++;
QCC_PR_NewLine(false);
}
else
pr_file_p++;
}
QCC_PR_LexWhitespace();
if (*pr_file_p == '\"') //have annother go
{
pr_file_p++;

View File

@ -1378,7 +1378,7 @@ void NPP_NQWriteEntity(int dest, short data) //replacement write func (nq to qw)
if (!bufferlen)
Con_Printf("NQWriteEntity: Messages should start with WriteByte\n");
if (majortype == svc_temp_entity && data >= 0 && data <= sv.allocated_client_slots)
if (majortype == svc_temp_entity && data > 0 && data <= sv.allocated_client_slots)
if (svs.clients[data-1].viewent)
data = svs.clients[data-1].viewent;

View File

@ -1007,7 +1007,7 @@ progsnum_t AddProgs(char *name)
Con_Printf("Loaded %s\n", name);
PR_AutoCvarSetup(svprogfuncs);
PR_ProgsAdded(svprogfuncs, num, name);
if (!svs.numprogs)
{
@ -2261,6 +2261,11 @@ static void QCBUILTIN PF_setorigin (pubprogfuncs_t *prinst, struct globalvars_s
float *org;
e = G_EDICT(prinst, OFS_PARM0);
if (e->readonly)
{
Con_Printf("setorigin on entity %i\n", e->entnum);
return;
}
org = G_VECTOR(OFS_PARM1);
VectorCopy (org, e->v->origin);
World_LinkEdict (&sv.world, (wedict_t*)e, false);
@ -2291,6 +2296,11 @@ static void QCBUILTIN PF_setsize (pubprogfuncs_t *prinst, struct globalvars_s *p
}
return;
}
if (e->readonly)
{
Con_Printf("setsize on entity %i\n", e->entnum);
return;
}
min = G_VECTOR(OFS_PARM1);
max = G_VECTOR(OFS_PARM2);
VectorCopy (min, e->v->mins);
@ -2313,6 +2323,12 @@ void PF_setmodel_Internal (pubprogfuncs_t *prinst, edict_t *e, char *m)
int i;
model_t *mod;
if (e->readonly)
{
Con_Printf("setmodel on entity %i\n", e->entnum);
return;
}
// check to see if model was properly precached
if (!m || !*m)
i = 0;
@ -2338,7 +2354,7 @@ void PF_setmodel_Internal (pubprogfuncs_t *prinst, edict_t *e, char *m)
sv.strings.model_precache[i] = m; //in a qvm, we expect the caller to have used a static location.
else
#endif
m = sv.strings.model_precache[i] = PR_AddString(prinst, m, 0);
m = sv.strings.model_precache[i] = PR_AddString(prinst, m, 0, false);
if (!strcmp(m + strlen(m) - 4, ".bsp")) //always precache bsps
sv.models[i] = Mod_FindName(m);
Con_Printf("WARNING: SV_ModelIndex: model %s not precached\n", m);
@ -3829,7 +3845,7 @@ int PF_precache_model_Internal (pubprogfuncs_t *prinst, char *s, qboolean queryo
sv.strings.model_precache[i] = s;
else
#endif
sv.strings.model_precache[i] = PR_AddString(prinst, s, 0);
sv.strings.model_precache[i] = PR_AddString(prinst, s, 0, false);
s = sv.strings.model_precache[i];
if (!strcmp(s + strlen(s) - 4, ".bsp") || sv_gameplayfix_setmodelrealbox.ival)
sv.models[i] = Mod_ForName(s, false);
@ -3918,7 +3934,7 @@ void QCBUILTIN PF_precache_vwep_model (pubprogfuncs_t *prinst, struct globalvars
sv.strings.vw_model_precache[i] = s;
else
#endif
sv.strings.vw_model_precache[i] = PR_AddString(prinst, s, 0);
sv.strings.vw_model_precache[i] = PR_AddString(prinst, s, 0, false);
return;
}
if (!strcmp(sv.strings.vw_model_precache[i], s))

View File

@ -463,7 +463,7 @@ static eval_t *QDECL Q1QVMPF_GetEdictFieldValue(pubprogfuncs_t *pf, edict_t *e,
return NULL;
}
static eval_t *QDECL Q1QVMPF_FindGlobal (pubprogfuncs_t *prinst, char *name, progsnum_t num, etype_t *type)
static eval_t *QDECL Q1QVMPF_FindGlobal (pubprogfuncs_t *prinst, const char *name, progsnum_t num, etype_t *type)
{
return NULL;
}

View File

@ -454,14 +454,14 @@ void LoadModelsAndSounds(vfsfile_t *f)
char str[32768];
int i;
sv.strings.model_precache[0] = PR_AddString(svprogfuncs, "", 0);
sv.strings.model_precache[0] = PR_AddString(svprogfuncs, "", 0, false);
for (i=1; i < MAX_MODELS; i++)
{
VFS_GETS(f, str, sizeof(str));
if (!*str)
break;
sv.strings.model_precache[i] = PR_AddString(svprogfuncs, str, 0);
sv.strings.model_precache[i] = PR_AddString(svprogfuncs, str, 0, false);
}
if (i == MAX_MODELS)
{
@ -709,8 +709,8 @@ qboolean SV_LoadLevelCache(char *savename, char *level, char *startspot, qboolea
ent = NULL;
svs.clients[i].edict = ent;
svs.clients[i].name = PR_AddString(svprogfuncs, svs.clients[i].namebuf, sizeof(svs.clients[i].namebuf));
svs.clients[i].team = PR_AddString(svprogfuncs, svs.clients[i].teambuf, sizeof(svs.clients[i].teambuf));
svs.clients[i].name = PR_AddString(svprogfuncs, svs.clients[i].namebuf, sizeof(svs.clients[i].namebuf), false);
svs.clients[i].team = PR_AddString(svprogfuncs, svs.clients[i].teambuf, sizeof(svs.clients[i].teambuf), false);
if (ent)
svs.clients[i].playerclass = ent->xv->playerclass;

View File

@ -1761,7 +1761,7 @@ void SV_Serverinfo_f (void)
return;
}
Con_TPrintf (TL_STARKEYPROTECTED);
Con_Printf ("Can't set * keys\n");
return;
}
Q_strncpyz(value, Cmd_Argv(2), sizeof(value));
@ -1820,7 +1820,7 @@ void SV_Localinfo_f (void)
Info_RemoveNonStarKeys(localinfo);
return;
}
Con_TPrintf (TL_STARKEYPROTECTED);
Con_Printf ("Can't set * keys\n");
return;
}
old = Info_ValueForKey(localinfo, Cmd_Argv(1));

View File

@ -69,7 +69,7 @@ int SV_ModelIndex (char *name)
sv.strings.model_precache[i] = name;
else
#endif
sv.strings.model_precache[i] = PR_AddString(svprogfuncs, name, 0);
sv.strings.model_precache[i] = PR_AddString(svprogfuncs, name, 0, false);
if (!strcmp(name + strlen(name) - 4, ".bsp"))
sv.models[i] = Mod_FindName(sv.strings.model_precache[i]);
@ -1027,10 +1027,10 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
strcpy(sv.strings.sound_precache[0], "");
sv.strings.model_precache[0] = "";
sv.strings.model_precache[1] = PR_AddString(svprogfuncs, sv.modelname, 0);
sv.strings.model_precache[1] = PR_AddString(svprogfuncs, sv.modelname, 0, false);
for (i=1 ; i<sv.world.worldmodel->numsubmodels ; i++)
{
sv.strings.model_precache[1+i] = PR_AddString(svprogfuncs, localmodels[i], 0);
sv.strings.model_precache[1+i] = PR_AddString(svprogfuncs, localmodels[i], 0, false);
sv.models[i+1] = Mod_ForName (localmodels[i], false);
}
@ -1134,8 +1134,8 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
else
#endif
{
svs.clients[i].name = PR_AddString(svprogfuncs, svs.clients[i].namebuf, sizeof(svs.clients[i].namebuf));
svs.clients[i].team = PR_AddString(svprogfuncs, svs.clients[i].teambuf, sizeof(svs.clients[i].teambuf));
svs.clients[i].name = PR_AddString(svprogfuncs, svs.clients[i].namebuf, sizeof(svs.clients[i].namebuf), false);
svs.clients[i].team = PR_AddString(svprogfuncs, svs.clients[i].teambuf, sizeof(svs.clients[i].teambuf), false);
}
#ifdef PEXT_CSQC

View File

@ -1946,7 +1946,7 @@ client_t *SVC_DirectConnect(void)
s = Info_ValueForKey(userinfo[0], "challenge");
if (!strncmp(s, DISTRIBUTION, strlen(DISTRIBUTION)))
challenge = atoi(s+3);
challenge = atoi(s+strlen(DISTRIBUTION));
else
challenge = atoi(s);

View File

@ -2300,7 +2300,7 @@ void SV_SendClientMessages (void)
#ifdef Q3SERVER
if (svs.gametype == GT_QUAKE3)
{
for (i=0, c = svs.clients ; i<MAX_CLIENTS ; i++, c++)
for (i=0, c = svs.clients ; i<svs.allocated_client_slots ; i++, c++)
{
if (c->state <= cs_zombie)
continue;

View File

@ -711,7 +711,7 @@ int main(int argc, char *argv[])
}
#endif
parms.basedir = ".";
parms.basedir = "./";
SV_Init (&parms);

View File

@ -929,7 +929,7 @@ void StartQuakeServer(void)
*COM_SkipPath(bindir) = 0;
parms.binarydir = bindir;
parms.basedir = ".";
parms.basedir = "./";
SV_Init (&parms);

View File

@ -395,6 +395,8 @@ model_t *Mod_FindName (char *name)
{
if (mod_numknown == MAX_MOD_KNOWN)
SV_Error ("mod_numknown == MAX_MOD_KNOWN");
if (strlen(name) >= sizeof(mod->name))
Sys_Error ("model name is too long: %s", name);
strcpy (mod->name, name);
mod->needload = true;
mod_numknown++;

View File

@ -487,7 +487,7 @@ static void SWBE_SubmitMeshesSortList(batch_t *sortlist)
continue;
if (batch->flags & BEF_NODLIGHT)
if (shaderstate.mode == BEM_LIGHT || shaderstate.mode == BEM_SMAPLIGHT)
if (shaderstate.mode == BEM_LIGHT)
continue;
if (batch->flags & BEF_NOSHADOWS)
if (shaderstate.mode == BEM_STENCIL)
@ -501,7 +501,7 @@ static void SWBE_SubmitMeshesSortList(batch_t *sortlist)
if (batch->shader->flags & SHADER_NODRAW)
continue;
if (batch->shader->flags & SHADER_NODLIGHT)
if (shaderstate.mode == BEM_LIGHT || shaderstate.mode == BEM_SMAPLIGHT)
if (shaderstate.mode == BEM_LIGHT)
continue;
if (batch->shader->flags & SHADER_SKY)
{
@ -606,7 +606,7 @@ void SWBE_DrawWorld(qboolean drawworld, qbyte *vis)
shaderstate.wbatch = 0;
}
BE_GenModelBatches(batches);
BE_GenModelBatches(batches, NULL, shaderstate.mode);
// R_GenDlightBatches(batches);
shaderstate.curentity = NULL;

View File

@ -23,7 +23,7 @@ static void VID_Resized(int width, int height)
extern cvar_t vid_conautoscale, vid_conwidth;
vid.pixelwidth = width;
vid.pixelheight = height;
Con_Printf("Resized: %i %i\n", vid.pixelwidth, vid.pixelheight);
//Con_Printf("Resized: %i %i\n", vid.pixelwidth, vid.pixelheight);
Cvar_ForceCallback(&vid_conautoscale);
Cvar_ForceCallback(&vid_conwidth);

View File

@ -19,6 +19,18 @@ PLUG_CFLAGS=
$(OUT_DIR)/fteplug_avplug$(PLUG_NATIVE_EXT): avplug/libavformat/avformat.h
endif
#cygwin uses dll naming.
ifeq ($(FTE_TARGET),cygwin)
ifeq ($(BITS),64)
PLUG_DEFFILE=plugin.def
PLUG_NATIVE_EXT=amd.dll
endif
ifneq ($(BITS),64)
PLUG_DEFFILE=plugin.def
PLUG_NATIVE_EXT=x86.dll
endif
endif
#if they're not on windows, we'll try asking the compiler directly
#the check to see if its already set is to avoid asking msvc, which would probably break things.
ifeq ($(PLUG_NATIVE_EXT),)
@ -103,8 +115,8 @@ $(OUT_DIR)/fteplug_mpq$(PLUG_NATIVE_EXT): mpq/fs_mpq.c mpq/blast.c plugin.c qvm_
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $(OUT_DIR)/fteplug_mpq$(PLUG_NATIVE_EXT) -shared $(PLUG_CFLAGS) -Impq $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS)
native: $(OUT_DIR)/fteplug_mpq$(PLUG_NATIVE_EXT)
$(OUT_DIR)/fteplug_xmpp$(PLUG_NATIVE_EXT): jabber/jabberclient.c jabber/jingle.c jabber/xml.c plugin.c qvm_api.c ../engine/common/sha1.c emailnot/md5.c
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $(OUT_DIR)/fteplug_xmpp$(PLUG_NATIVE_EXT) -shared $(PLUG_CFLAGS) -Ijabber $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS)
$(OUT_DIR)/fteplug_xmpp$(PLUG_NATIVE_EXT): jabber/jabberclient.c jabber/jingle.c jabber/sift.c jabber/xml.c plugin.c qvm_api.c ../engine/common/sha1.c emailnot/md5.c
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $(OUT_DIR)/fteplug_xmpp$(PLUG_NATIVE_EXT) -shared $(PLUG_CFLAGS) -Ijabber $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS) -lresolv
native: $(OUT_DIR)/fteplug_xmpp$(PLUG_NATIVE_EXT)

View File

@ -189,6 +189,28 @@ static void *AVDec_Create(char *medianame)
ctx->pFormatCtx->pb = ioctx;
}
/*
small how-to note for if I ever try to add support for voice-and-video rtp decoding.
this stuff is presumably needed to handle ICE+stun+ports etc.
I prolly need to hack around with adding rtcp too. :s
rtsp: Add support for depacketizing RTP data via custom IO
To use this, set sdpflags=custom_io to the sdp demuxer. During
the avformat_open_input call, the SDP is read from the AVFormatContext
AVIOContext (ctx->pb) - after the avformat_open_input call,
during the av_read_frame() calls, the same ctx->pb is used for reading
packets (and sending back RTCP RR packets).
Normally, one would use this with a read-only AVIOContext for the
SDP during the avformat_open_input call, then close that one and
replace it with a read-write one for the packets after the
avformat_open_input call has returned.
This allows using the RTP depacketizers as "pure" demuxers, without
having them tied to the libavformat network IO.
*/
// Open video file
if(avformat_open_input(&ctx->pFormatCtx, medianame, NULL, NULL)==0)

View File

@ -393,8 +393,6 @@ char *MD5_ToHex(char *input, int inputlen, char *ret, int retlen)
}
char *MD5_ToBinary(char *input, int inputlen, char *ret, int retlen)
{
int v, i;
unsigned char digest[16];
MD5_CTX ctx;
if (retlen < 16)

View File

@ -41,6 +41,7 @@
PreprocessorDefinitions="FTEPLUGIN"
EnableFunctionLevelLinking="true"
BrowseInformation="1"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
@ -186,6 +187,10 @@
RelativePath="..\..\engine\common\sha1.c"
>
</File>
<File
RelativePath=".\sift.c"
>
</File>
<File
RelativePath=".\xml.c"
>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

607
plugins/jabber/sift.c Normal file
View File

@ -0,0 +1,607 @@
#include "xmpp.h"
#ifdef FILETRANSFERS
void XMPP_FT_Frame(jclient_t *jcl)
{
static char *hex = "0123456789abcdef";
char digest[20];
char domain[sizeof(digest)*2+1];
int j;
char *req;
struct ft_s *ft;
for (ft = jcl->ft; ft; ft = ft->next)
{
if (ft->streamstatus == STRM_IDLE)
continue;
if (ft->stream < 0)
{
if (ft->nexthost > 0)
{
ft->nexthost--;
ft->stream = pNet_TCPConnect(ft->streamhosts[ft->nexthost].host, ft->streamhosts[ft->nexthost].port);
if (ft->stream == -1)
continue;
ft->streamstatus = STRM_AUTH;
//'authenticate' with socks5 proxy. tell it that we only support 'authless'.
pNet_Send(ft->stream, "\x05\x01\x00", 3);
}
else
{
JCL_AddClientMessagef(jcl,
"<iq id='%s' to='%s' type='error'>"
"<error type='cancel'>"
"<item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>"
"</error>"
"</iq>", ft->iqid, ft->with);
ft->streamstatus = STRM_IDLE;
}
continue;
}
else
{
char data[8192];
int len;
if (ft->streamstatus == STRM_ACTIVE)
{
len = pNet_Recv(ft->stream, data, sizeof(data)-1);
if (len > 0)
pFS_Write(ft->file, data, len);
}
else
{
len = pNet_Recv(ft->stream, data, sizeof(data)-1);
if (len > 0)
{
if (ft->streamstatus == STRM_AUTH)
{
if (len == 2 && data[0] == 0x05 && data[1] == 0x00)
{
//server has accepted us, woo.
//sid+requester(them)+target(us)
req = va("%s%s%s", ft->sid, ft->with, jcl->jid);
SHA1(digest, sizeof(digest), req, strlen(req));
//in hex
for (req = domain, j=0; j < 20; j++)
{
*req++ = hex[(digest[j]>>4) & 0xf];
*req++ = hex[(digest[j]>>0) & 0xf];
}
*req = 0;
//connect with hostname(3).
req = va("\x05\x01%c\x03""%c%s%c%c", 0, strlen(domain), domain, 0, 0);
pNet_Send(ft->stream, req, strlen(domain)+7);
ft->streamstatus = STRM_AUTHED;
}
else
len = -1;
}
else if (ft->streamstatus == STRM_AUTHED)
{
if (data[0] == 0x05 && data[1] == 0x00)
{
if (pFS_Open(ft->fname, &ft->file, 2) < 0)
{
len = -1;
JCL_AddClientMessagef(jcl, "<iq id='%s' to='%s' type='error'/>", ft->iqid, ft->with);
}
else
{
ft->streamstatus = STRM_ACTIVE;
JCL_AddClientMessagef(jcl,
"<iq id='%s' to='%s' type='result'>"
"<query xmlns='http://jabber.org/protocol/bytestreams' sid='%s'>"
"<streamhost-used jid='%s'/>"
"</query>"
"</iq>", ft->iqid, ft->with, ft->sid, ft->streamhosts[ft->nexthost].jid);
}
}
else
len = -1; //err, this is someone else...
}
}
}
if (len == -1)
{
pNet_Close(ft->stream);
ft->stream = -1;
if (ft->streamstatus == STRM_ACTIVE)
{
int size;
if (ft->file != -1)
pFS_Close(ft->file);
ft->file = -1;
size = pFS_Open(ft->fname, &ft->file, 1);
if (ft->file != -1)
pFS_Close(ft->file);
if (size == ft->size)
{
Con_Printf("File Transfer Completed\n");
continue;
}
else
{
Con_Printf("File Transfer Aborted by peer\n");
continue;
}
}
Con_Printf("File Transfer connection to %s:%i failed\n", ft->streamhosts[ft->nexthost].host, ft->streamhosts[ft->nexthost].port);
}
}
}
}
void XMPP_FT_AcceptFile(jclient_t *jcl, int fileid, qboolean accept)
{
struct ft_s *ft, **link;
char *s;
xmltree_t *repiq, *repsi, *c;
for (link = &jcl->ft; ft=*link; link = &(*link)->next)
{
if (ft->privateid == fileid)
break;
}
if (!ft)
{
Con_Printf("File not known\n");
return;
}
if (!accept)
{
Con_Printf("Declining file \"%s\" from \"%s\" (%i bytes)\n", ft->fname, ft->with, ft->size);
if (!ft->allowed)
{
JCL_AddClientMessagef(jcl,
"<iq type='error' to='%s' id='%s'>"
"<error type='cancel'>"
"<forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>"
"<text>Offer Declined</text>"
"</error>"
"</iq>", ft->with, ft->iqid);
}
else
{
//FIXME: send a proper cancel
}
if (ft->file != -1)
pFS_Close(ft->file);
*link = ft->next;
free(ft);
}
else
{
Con_Printf("Receiving file \"%s\" from \"%s\" (%i bytes)\n", ft->fname, ft->with, ft->size);
ft->allowed = true;
//generate a response.
//FIXME: we ought to delay response until after we prompt.
repiq = XML_CreateNode(NULL, "iq", "", "");
XML_AddParameter(repiq, "type", "result");
XML_AddParameter(repiq, "to", ft->with);
XML_AddParameter(repiq, "id", ft->iqid);
repsi = XML_CreateNode(repiq, "si", "http://jabber.org/protocol/si", "");
XML_CreateNode(repsi, "file", "http://jabber.org/protocol/si/profile/file-transfer", ""); //I don't really get the point of this.
c = XML_CreateNode(repsi, "feature", "http://jabber.org/protocol/feature-neg", "");
c = XML_CreateNode(c, "x", "jabber:x:data", "");
XML_AddParameter(c, "type", "submit");
c = XML_CreateNode(c, "field", "", "");
XML_AddParameter(c, "var", "stream-method");
if (ft->method == FT_IBB)
c = XML_CreateNode(c, "value", "", "http://jabber.org/protocol/ibb");
else if (ft->method == FT_BYTESTREAM)
c = XML_CreateNode(c, "value", "", "http://jabber.org/protocol/bytestreams");
s = XML_GenerateString(repiq, false);
JCL_AddClientMessageString(jcl, s);
free(s);
XML_Destroy(repiq);
}
}
static qboolean XMPP_FT_IBBChunked(jclient_t *jcl, xmltree_t *x, struct iq_s *iq)
{
char *from = XML_GetParameter(x, "from", jcl->domain);
struct ft_s *ft = iq->usrptr, **link, *v;
for (link = &jcl->ft; (v=*link); link = &(*link)->next)
{
if (v == ft && !strcmp(ft->with, from))
{
//its still valid
if (x)
{
char *base64;
char rawbuf[4096];
int sz;
sz = pFS_Read(ft->file, rawbuf, ft->blocksize);
Base64_Add(rawbuf, sz);
base64 = Base64_Finish();
if (sz > 0)
{
ft->sizedone += sz;
if (ft->sizedone == ft->size)
ft->eof = true;
}
if (sz && strlen(base64))
{
x = XML_CreateNode(NULL, "data", "http://jabber.org/protocol/ibb", base64);
XML_AddParameteri(x, "seq", ft->seq++);
XML_AddParameter(x, "sid", ft->sid);
JCL_SendIQNode(jcl, XMPP_FT_IBBChunked, "set", from, x, true)->usrptr = ft;
return true;
}
//else eof
}
//errored or ended
if (x)
Con_Printf("Transfer of %s to %s completed\n", ft->fname, ft->with);
else
Con_Printf("%s aborted %s\n", ft->with, ft->fname);
x = XML_CreateNode(NULL, "close", "http://jabber.org/protocol/ibb", "");
XML_AddParameter(x, "sid", ft->sid);
JCL_SendIQNode(jcl, NULL, "set", from, x, true)->usrptr = ft;
//errored
if (ft->file != -1)
pFS_Close(ft->file);
*link = ft->next;
free(ft);
return true;
}
}
return true; //the ack can come after the bytestream has already finished sending. don't warn about that.
}
static qboolean XMPP_FT_IBBBegun(jclient_t *jcl, xmltree_t *x, struct iq_s *iq)
{
struct ft_s *ft = iq->usrptr, **link, *v;
char *from = XML_GetParameter(x, "from", jcl->domain);
for (link = &jcl->ft; (v=*link); link = &(*link)->next)
{
if (v == ft && !strcmp(ft->with, from))
{
//its still valid
if (!x)
{
Con_Printf("%s aborted %s\n", ft->with, ft->fname);
//errored
if (ft->file != -1)
pFS_Close(ft->file);
*link = ft->next;
free(ft);
}
else
{
ft->begun = true;
ft->method = FT_IBB;
XMPP_FT_IBBChunked(jcl, x, iq);
}
return true;
}
}
return false;
}
qboolean XMPP_FT_OfferAcked(jclient_t *jcl, xmltree_t *x, struct iq_s *iq)
{
struct ft_s *ft = iq->usrptr, **link, *v;
char *from = XML_GetParameter(x, "from", jcl->domain);
for (link = &jcl->ft; (v=*link); link = &(*link)->next)
{
if (v == ft && !strcmp(ft->with, from))
{
//its still valid
if (!x)
{
Con_Printf("%s doesn't want %s\n", ft->with, ft->fname);
//errored
if (ft->file != -1)
pFS_Close(ft->file);
*link = ft->next;
free(ft);
}
else
{
xmltree_t *xo;
Con_Printf("%s accepted %s\n", ft->with, ft->fname);
xo = XML_CreateNode(NULL, "open", "http://jabber.org/protocol/ibb", "");
XML_AddParameter(xo, "sid", ft->sid);
XML_AddParameteri(xo, "block-size", ft->blocksize);
//XML_AddParameter(xo, "stanza", "iq");
JCL_SendIQNode(jcl, XMPP_FT_IBBBegun, "set", XML_GetParameter(x, "from", jcl->domain), xo, true)->usrptr = ft;
}
return true;
}
}
return false;
}
void XMPP_FT_SendFile(jclient_t *jcl, char *console, char *to, char *fname)
{
xmltree_t *xsi, *xfile, *c;
struct ft_s *ft;
Con_SubPrintf(console, "Offering %s to %s.\n", fname, to);
ft = malloc(sizeof(*ft));
memset(ft, 0, sizeof(*ft));
ft->stream = -1;
ft->next = jcl->ft;
jcl->ft = ft;
ft->allowed = true;
ft->transmitting = true;
ft->blocksize = 4096;
Q_strlcpy(ft->fname, fname, sizeof(ft->fname));
Q_snprintf(ft->sid, sizeof(ft->sid), "%x%s", rand(), ft->fname);
Q_strlcpy(ft->md5hash, "", sizeof(ft->md5hash));
ft->size = pFS_Open(ft->fname, &ft->file, 1);
ft->with = strdup(to);
ft->method = FT_IBB;
ft->begun = false;
//generate an offer.
xsi = XML_CreateNode(NULL, "si", "http://jabber.org/protocol/si", "");
XML_AddParameter(xsi, "profile", "http://jabber.org/protocol/si/profile/file-transfer");
XML_AddParameter(xsi, "id", ft->sid);
//XML_AddParameter(xsi, "mime-type", "text/plain");
xfile = XML_CreateNode(xsi, "file", "http://jabber.org/protocol/si/profile/file-transfer", ""); //I don't really get the point of this.
XML_AddParameter(xfile, "name", ft->fname);
XML_AddParameteri(xfile, "size", ft->size);
c = XML_CreateNode(xsi, "feature", "http://jabber.org/protocol/feature-neg", "");
c = XML_CreateNode(c, "x", "jabber:x:data", "");
XML_AddParameter(c, "type", "form");
c = XML_CreateNode(c, "field", "", "");
XML_AddParameter(c, "var", "stream-method");
XML_AddParameter(c, "type", "listsingle");
XML_CreateNode(XML_CreateNode(c, "option", "", ""), "value", "", "http://jabber.org/protocol/ibb");
// XML_CreateNode(XML_CreateNode(c, "option", "", ""), "value", "", "http://jabber.org/protocol/bytestreams");
JCL_SendIQNode(jcl, XMPP_FT_OfferAcked, "set", to, xsi, true)->usrptr = ft;
}
qboolean XMPP_FT_ParseIQSet(jclient_t *jcl, char *iqfrom, char *iqid, xmltree_t *tree)
{
xmltree_t *ot;
//if file transfers are not enabled in this build, reject all iqs
if (!(jcl->enabledcapabilities & CAP_SIFT))
return false;
ot = XML_ChildOfTreeNS(tree, "http://jabber.org/protocol/bytestreams", "query", 0);
if (ot)
{
xmltree_t *c;
struct ft_s *ft;
char *sid = XML_GetParameter(ot, "sid", "");
for (ft = jcl->ft; ft; ft = ft->next)
{
if (!strcmp(ft->sid, sid) && !strcmp(ft->with, iqfrom))
{
if (ft->allowed && !ft->begun && ft->transmitting == false)
{
char *jid;
char *host;
int port;
char *mode = XML_GetParameter(ot, "mode", "tcp");
int i;
if (strcmp(mode, "tcp"))
break;
for (i = 0; ; i++)
{
c = XML_ChildOfTree(ot, "streamhost", i);
if (!c)
break;
jid = XML_GetParameter(c, "jid", "");
host = XML_GetParameter(c, "host", "");
port = atoi(XML_GetParameter(c, "port", "0"));
if (port <= 0 || port > 65535)
continue;
if (ft->nexthost < sizeof(ft->streamhosts) / sizeof(ft->streamhosts[ft->nexthost]))
{
Q_strlcpy(ft->streamhosts[ft->nexthost].jid, jid, sizeof(ft->streamhosts[ft->nexthost].jid));
Q_strlcpy(ft->streamhosts[ft->nexthost].host, host, sizeof(ft->streamhosts[ft->nexthost].host));
ft->streamhosts[ft->nexthost].port = port;
ft->nexthost++;
}
}
ft->streamstatus = STRM_AUTH;
//iq gets acked when we finished connecting to the proxy. *then* the data can flow
Q_strlcpy(ft->iqid, iqid, sizeof(ft->iqid));
return true;
}
}
}
JCL_AddClientMessagef(jcl, "<iq id='%s' to='%s' type='error'/>", iqid, iqfrom);
return true;
}
ot = XML_ChildOfTreeNS(tree, "http://jabber.org/protocol/ibb", "open", 0);
if (ot)
{
struct ft_s *ft;
char *sid = XML_GetParameter(ot, "sid", "");
int blocksize = atoi(XML_GetParameter(ot, "block-size", "4096")); //technically this is required.
char *stanza = XML_GetParameter(ot, "stanza", "iq");
for (ft = jcl->ft; ft; ft = ft->next)
{
if (!strcmp(ft->sid, sid) && !strcmp(ft->with, iqfrom))
{
if (ft->allowed && !ft->begun && ft->transmitting == false)
{
if (blocksize > 65536 || strcmp(stanza, "iq"))
{ //blocksize: MUST NOT be greater than 65535
JCL_AddClientMessagef(jcl,
"<iq id='%s' to='%s' type='error'>"
"<error type='modify'>"
"<not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>"
"</error>"
"</iq>"
, iqid, iqfrom);
}
else if (blocksize > 4096)
{ //ask for smaller chunks
JCL_AddClientMessagef(jcl,
"<iq id='%s' to='%s' type='error'>"
"<error type='modify'>"
"<resource-constraint xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>"
"</error>"
"</iq>"
, iqid, iqfrom);
}
else
{ //it looks okay
pFS_Open(ft->fname, &ft->file, 2);
ft->method = FT_IBB;
ft->blocksize = blocksize;
ft->begun = true;
//if its okay...
JCL_AddClientMessagef(jcl, "<iq id='%s' to='%s' type='result'/>", iqid, iqfrom);
}
break;
}
}
}
return false;
}
ot = XML_ChildOfTreeNS(tree, "http://jabber.org/protocol/ibb", "close", 0);
if (ot)
{
struct ft_s **link, *ft;
char *sid = XML_GetParameter(ot, "sid", "");
for (link = &jcl->ft; *link; link = &(*link)->next)
{
ft = *link;
if (!strcmp(ft->sid, sid) && !strcmp(ft->with, iqfrom))
{
if (ft->begun && ft->method == FT_IBB)
{
int size;
if (ft->file != -1)
pFS_Close(ft->file);
if (ft->transmitting)
{
if (ft->eof)
Con_Printf("Sent \"%s\" to \"%s\"\n", ft->fname, ft->with);
else
Con_Printf("%s aborted transfer of \"%s\"\n", iqfrom, ft->fname);
}
else
{
size = pFS_Open(ft->fname, &ft->file, 1);
if (ft->file != -1)
pFS_Close(ft->file);
if (size == ft->size)
Con_Printf("Received file \"%s\" successfully\n", ft->fname);
else
Con_Printf("%s aborted transfer of \"%s\"\n", iqfrom, ft->fname);
}
*link = ft->next;
free(ft);
//if its okay...
JCL_AddClientMessagef(jcl, "<iq id='%s' to='%s' type='result'/>", iqid, iqfrom);
return true;
}
}
}
return false; //some kind of error
}
ot = XML_ChildOfTreeNS(tree, "http://jabber.org/protocol/ibb", "data", 0);
if (ot)
{
char block[65536];
char *sid = XML_GetParameter(ot, "sid", "");
unsigned short seq = atoi(XML_GetParameter(ot, "seq", "0"));
int blocksize;
struct ft_s *ft;
for (ft = jcl->ft; ft; ft = ft->next)
{
if (!strcmp(ft->sid, sid) && !ft->transmitting)
{
blocksize = Base64_Decode(block, sizeof(block), ot->body, strlen(ot->body));
if (blocksize && blocksize <= ft->blocksize)
{
pFS_Write(ft->file, block, blocksize);
JCL_AddClientMessagef(jcl, "<iq id='%s' to='%s' type='result'/>", iqid, iqfrom);
return true;
}
else
Con_Printf("XMPP: Invalid blocksize in file transfer from %s\n", iqfrom);
break;
}
}
return true;
}
ot = XML_ChildOfTreeNS(tree, "http://jabber.org/protocol/si", "si", 0);
if (ot)
{
char *profile = XML_GetParameter(ot, "profile", "");
if (!strcmp(profile, "http://jabber.org/protocol/si/profile/file-transfer"))
{
char *mimetype = XML_GetParameter(ot, "mime-type", "text/plain");
char *sid = XML_GetParameter(ot, "id", "");
xmltree_t *file = XML_ChildOfTreeNS(ot, "http://jabber.org/protocol/si/profile/file-transfer", "file", 0);
char *fname = XML_GetParameter(file, "name", "file.txt");
char *date = XML_GetParameter(file, "date", "");
char *md5hash = XML_GetParameter(file, "hash", "");
int fsize = strtoul(XML_GetParameter(file, "size", "0"), NULL, 0);
char *desc = XML_GetChildBody(file, "desc", "");
char authlink[512];
char denylink[512];
//file transfer offer
struct ft_s *ft = malloc(sizeof(*ft) + strlen(iqfrom)+1);
memset(ft, 0, sizeof(*ft));
ft->stream = -1;
ft->next = jcl->ft;
jcl->ft = ft;
ft->privateid = ++jcl->privateidseq;
ft->transmitting = false;
Q_strlcpy(ft->iqid, iqid, sizeof(ft->iqid));
Q_strlcpy(ft->sid, sid, sizeof(ft->sid));
Q_strlcpy(ft->fname, fname, sizeof(ft->sid));
Base64_Decode(ft->md5hash, sizeof(ft->md5hash), md5hash, strlen(md5hash));
ft->size = fsize;
ft->file = -1;
ft->with = (char*)(ft+1);
strcpy(ft->with, iqfrom);
ft->method = (fsize > 1024*128)?FT_BYTESTREAM:FT_IBB; //favour bytestreams for large files. for small files, just use ibb as it saves sorting out proxies.
ft->begun = false;
JCL_GenLink(jcl, authlink, sizeof(authlink), "fauth", iqfrom, NULL, va("%i", ft->privateid), "%s", "Accept");
JCL_GenLink(jcl, denylink, sizeof(denylink), "fdeny", iqfrom, NULL, va("%i", ft->privateid), "%s", "Deny");
Con_Printf("%s has offered to send you \"%s\" (%i bytes). %s %s\n", iqfrom, fname, fsize, authlink, denylink);
}
else
{
//profile not understood
JCL_AddClientMessagef(jcl,
"<iq type='error' to='%s' id='%s'>"
"<error code='400' type='cancel'>"
"<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>"
"<bad-profile xmlns='http://jabber.org/protocol/si'/>"
"</error>"
"</iq>", iqfrom, iqid);
}
return true;
}
return false;
}
#endif

View File

@ -2,6 +2,9 @@
#include "xml.h"
//fixme
void (*Con_TrySubPrint)(const char *conname, const char *message);
void XML_Destroy(xmltree_t *t);
char *XML_GetParameter(xmltree_t *t, char *paramname, char *def)
@ -563,7 +566,7 @@ char *XML_GetChildBody(xmltree_t *t, char *paramname, char *def)
return def;
}
void XML_ConPrintTree(xmltree_t *t, int indent)
void XML_ConPrintTree(xmltree_t *t, char *subconsole, int indent)
{
int start, c, chunk;
struct buf_ctx buf = {NULL, 0, 0};
@ -577,7 +580,7 @@ void XML_ConPrintTree(xmltree_t *t, int indent)
chunk = 128;
c = buf.buf[start+chunk];
buf.buf[start+chunk] = 0;
Con_Printf("%s", buf.buf+start);
Con_TrySubPrint(subconsole, buf.buf+start);
buf.buf[start+chunk] = c;
start += chunk;
@ -649,8 +652,6 @@ static qboolean XML_ParseString(char *msg, int *pos, int max, char *out, int out
xmltree_t *XML_FromJSON(xmltree_t *t, char *name, char *json, int *jsonpos, int jsonlen)
{
char child[4096];
char *start;
char *end;
XML_SkipWhite(json, jsonpos, jsonlen);
if (*jsonpos < jsonlen && json[*jsonpos] == '{')

Some files were not shown because too many files have changed in this diff Show More