forked from fte/fteqw
1
0
Fork 0

Implemented device enumeration for SDL+ALSA+OSS4 audio drivers. Back to using the 'default' alsa device by default, warts and all.

Fixed openal linux .so name, now usable in linux.
sdl audio code now uses sdl2 audio, and thus can support multiple devices simultaneously.
linux non-sdl builds now dynamically link to SDL2 for audio. This is now the default audio system in ALL non-android linux builds. This is the only real option to cope with the mess that is alsa.
Fix netgraph when running q2. No longer makes palette assumptions.
Fixed q2 ping values.
Tweaked a load of windows code to use wide chars, because microsoft do not support utf-8.
fixed an issue with winsspi where data from large packets could get lost.
now tries to read .lit2 files (although still refuses to read them for now).
Fixed motionblur. To make Shpuld happy... :P

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4871 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2015-05-14 03:06:58 +00:00
parent 6cd5a6a076
commit 31506617f0
41 changed files with 1099 additions and 601 deletions

View File

@ -1100,15 +1100,15 @@ ifneq (,$(findstring linux,$(FTE_TARGET)))
NPFTE_CFLAGS=$(NPFTECFLAGS) $(W32_CFLAGS) -DMULTITHREAD -fPIC -DDYNAMIC_LIBPNG -DDYNAMIC_LIBJPEG
NPFTEB_DIR=npfte_linux$(BITS)
GLCL_OBJS=$(GL_OBJS) $(D3DGL_OBJS) $(GLQUAKE_OBJS) $(BOTLIB_OBJS) $(SPEEX_OBJS) gl_vidlinuxglx.o gl_videgl.o snd_alsa.o snd_linux.o cd_linux.o sys_linux.o sys_linux_threads.o
GLCL_OBJS=$(GL_OBJS) $(D3DGL_OBJS) $(GLQUAKE_OBJS) $(BOTLIB_OBJS) $(SPEEX_OBJS) gl_vidlinuxglx.o gl_videgl.o snd_alsa.o snd_linux.o snd_sdl.o cd_linux.o sys_linux.o sys_linux_threads.o
GL_EXE_NAME=../fteqw.gl$(BITS)
GLCL_EXE_NAME=../fteqwcl.gl$(BITS)
GL_LDFLAGS=$(GLLDFLAGS) $(XLDFLAGS) $(OGGVORBISLDFLAGS)
GL_CFLAGS=$(GLCFLAGS) -I/usr/X11R6/include $(SPEEXCFLAGS) -DMULTITHREAD -DLIBVORBISFILE_STATIC -DDYNAMIC_LIBPNG -DDYNAMIC_LIBJPEG
GL_CFLAGS=$(GLCFLAGS) -I/usr/X11R6/include $(SPEEXCFLAGS) -DMULTITHREAD -DLIBVORBISFILE_STATIC -DDYNAMIC_LIBPNG -DDYNAMIC_LIBJPEG -DDYNAMIC_SDL
GLB_DIR=gl_linux$(BITS)
GLCL_DIR=glcl_linux$(BITS)
MCL_OBJS=$(D3DGL_OBJS) $(GLQUAKE_OBJS) $(SOFTWARE_OBJS) $(BOTLIB_OBJS) $(SPEEX_OBJS) gl_vidlinuxglx.o gl_videgl.o snd_linux.o snd_alsa.o cd_linux.o sys_linux.o sys_linux_threads.o
MCL_OBJS=$(D3DGL_OBJS) $(GLQUAKE_OBJS) $(SOFTWARE_OBJS) $(BOTLIB_OBJS) $(SPEEX_OBJS) gl_vidlinuxglx.o gl_videgl.o snd_linux.o snd_sdl.o snd_alsa.o cd_linux.o sys_linux.o sys_linux_threads.o
M_EXE_NAME=../fteqw$(BITS)
MCL_EXE_NAME=../fteqwcl$(BITS)
M_LDFLAGS=$(GL_LDFLAGS)

View File

@ -1361,11 +1361,12 @@ qboolean CLQ2_SendCmd (sizebuf_t *buf)
int checksumIndex, i;
int lightlev;
seq_hash = cls.netchan.outgoing_sequence;
cl.movesequence = cls.netchan.outgoing_sequence; //make sure its correct even over map changes.
seq_hash = cl.movesequence;
// send this and the previous cmds in the message, so
// if the last packet was dropped, it can be recovered
i = cls.netchan.outgoing_sequence & UPDATE_MASK;
i = cl.movesequence & UPDATE_MASK;
cmd = &cl.outframes[i].cmd[0];
if (cls.resendinfo)

View File

@ -3970,12 +3970,13 @@ void Host_RunFileNotify(struct dl_download *dl)
#define HRF_QTVINFO (1<<12)
#define HRF_MANIFEST (1<<13)
#define HRF_BSP (1<<14)
#define HRF_PACKAGE (1<<15)
#define HRF_MODEL (1<<16)
#define HRF_PACKAGE (1<<15) //pak or pk3 that should be installed.
#define HRF_ARCHIVE (1<<16) //zip - treated as a multiple-file 'installer'
#define HRF_MODEL (1<<17)
#define HRF_ACTION (HRF_OVERWRITE|HRF_NOOVERWRITE|HRF_ABORT)
#define HRF_DEMO (HRF_DEMO_MVD|HRF_DEMO_QWD|HRF_DEMO_DM2|HRF_DEMO_DEM)
#define HRF_FILETYPES (HRF_DEMO|HRF_QTVINFO|HRF_MANIFEST|HRF_BSP|HRF_PACKAGE|HRF_MODEL)
#define HRF_FILETYPES (HRF_DEMO|HRF_QTVINFO|HRF_MANIFEST|HRF_BSP|HRF_PACKAGE|HRF_MODEL|HRF_ARCHIVE)
typedef struct {
unsigned int flags;
vfsfile_t *srcfile;
@ -3987,18 +3988,27 @@ int waitingformanifest;
void Host_DoRunFile(hrf_t *f);
void CL_PlayDemoStream(vfsfile_t *file, struct dl_download *, char *filename, qboolean issyspath, int demotype, float bufferdelay);
void CL_ParseQTVDescriptor(vfsfile_t *f, const char *name);
qboolean FS_PathURLCache(char *url, char *path, size_t pathsize);
void Host_RunFileDownloaded(struct dl_download *dl)
{
//fixme: sort out flags from mime type....
hrf_t *f = dl->user_ctx;
f->srcfile = dl->file;
dl->file = NULL;
if (dl->status == DL_FAILED)
{
f->flags |= HRF_ABORT;
f->srcfile = NULL;
}
else
{
f->srcfile = dl->file;
dl->file = NULL;
}
Host_DoRunFile(f);
}
void Host_BeginFileDownload(struct dl_download *dl, char *mimetype)
qboolean Host_BeginFileDownload(struct dl_download *dl, char *mimetype)
{
qboolean result = false;
//at this point the file is still downloading, so don't copy it out just yet.
hrf_t *f = dl->user_ctx;
@ -4020,6 +4030,8 @@ void Host_BeginFileDownload(struct dl_download *dl, char *mimetype)
f->flags |= HRF_MANIFEST;
else if (!strcmp(mimetype, "application/x-multiviewdemo"))
f->flags |= HRF_DEMO_MVD;
else if (!strcmp(mimetype, "application/zip"))
f->flags |= HRF_ARCHIVE;
// else if (!strcmp(mimetype, "application/x-ftebsp"))
// f->flags |= HRF_BSP;
// else if (!strcmp(mimetype, "application/x-ftepackage"))
@ -4051,11 +4063,14 @@ void Host_BeginFileDownload(struct dl_download *dl, char *mimetype)
f->flags |= HRF_PACKAGE;
else
{
Con_Printf("file extension of %s not recognised\n", f->fname);
if (mimetype)
Con_Printf("mime type \"%s\" and file extension of \"%s\" not recognised\n", mimetype, f->fname);
else
Con_Printf("file extension of \"%s\" not recognised\n", f->fname);
//file type not guessable from extension either.
f->flags |= HRF_ABORT;
Host_DoRunFile(f);
return;
return false;
}
if (f->flags & HRF_MANIFEST)
@ -4079,16 +4094,37 @@ void Host_BeginFileDownload(struct dl_download *dl, char *mimetype)
{
//just use a pipe instead of a temp file, working around an issue with temp files on android
dl->file = VFSPIPE_Open();
return;
return true;
}
else if (f->flags & HRF_ARCHIVE)
{
char cachename[MAX_QPATH];
if (!FS_PathURLCache(f->fname, cachename, sizeof(cachename)))
return false;
f->srcfile = FS_OpenVFS(cachename, "rb", FS_ROOT);
if (f->srcfile)
{
f->flags |= HRF_OPENED;
Host_DoRunFile(f);
return false;
}
FS_CreatePath(cachename, FS_ROOT);
dl->file = FS_OpenVFS(cachename, "wb", FS_ROOT);
if (dl->file)
return true; //okay, continue downloading.
}
else if (f->flags & HRF_DEMO)
Con_Printf("%s: format not supported\n", f->fname); //demos that are not supported in this build for one reason or another
else
return;
return true;
//demos stream, so we want to continue the http download, but we don't want to do anything with the result.
if (f->flags & HRF_DEMO)
result = true;
f->flags |= HRF_ABORT;
Host_DoRunFile(f);
return;
return result;
}
void Host_RunFilePrompted(void *ctx, int button)
{
@ -4292,6 +4328,21 @@ void Host_DoRunFile(hrf_t *f)
Host_DoRunFile(f);
return;
}
else if (f->flags & HRF_ARCHIVE)
{
struct gamepacks packagespaths[2];
if (f->srcfile)
VFS_CLOSE(f->srcfile);
f->srcfile = NULL;
memset(packagespaths, 0, sizeof(packagespaths));
packagespaths[0].url = f->fname;
COM_Gamedir("", packagespaths);
f->flags |= HRF_ABORT;
Host_DoRunFile(f);
return;
}
else if (!(f->flags & HRF_QTVINFO))
{
Con_Printf("Host_DoRunFile: filetype not handled\n");

View File

@ -320,7 +320,7 @@ int CL_CalcNet (float scale)
; i++)
{
frame = &cl.outframes[i&UPDATE_MASK];
if (i > cl.lastackedmovesequence)
if (i > cl.ackedmovesequence)
{
// no response yet
if (cl_countpendingpl.ival)
@ -2861,7 +2861,7 @@ void CLQW_ParseServerData (void)
#endif
{
COM_FlushTempoaryPacks();
COM_Gamedir(str);
COM_Gamedir(str, NULL);
#ifndef CLIENTONLY
Info_SetValueForStarKey (svs.info, "*gamedir", str, MAX_SERVERINFO_STRING);
#endif
@ -3092,9 +3092,9 @@ void CLQ2_ParseServerData (void)
// set gamedir
if (!*str)
COM_Gamedir("baseq2");
COM_Gamedir("baseq2", NULL);
else
COM_Gamedir(str);
COM_Gamedir(str, NULL);
// if ((*str && (!fs_gamedirvar->string || !*fs_gamedirvar->string || strcmp(fs_gamedirvar->string, str))) || (!*str && (fs_gamedirvar->string || *fs_gamedirvar->string)))
// Cvar_Set("game", str);

View File

@ -722,6 +722,9 @@ static void CLQ2_ParsePacketEntities (q2frame_t *oldframe, q2frame_t *newframe)
unsigned int oldindex, oldnum;
cl.validsequence = cls.netchan.incoming_sequence;
cl.ackedmovesequence = cl.validsequence;
cl.outframes[cl.ackedmovesequence&UPDATE_MASK].latency = realtime - cl.outframes[cl.ackedmovesequence&UPDATE_MASK].senttime;
newframe->parse_entities = cl.parse_entities;
newframe->num_entities = 0;

View File

@ -511,7 +511,7 @@ qboolean CLQ3_SystemInfoChanged(char *str)
COM_FlushTempoaryPacks();
if (!*value)
value = "baseq3";
COM_Gamedir(value);
COM_Gamedir(value, NULL);
#ifndef CLIENTONLY
Info_SetValueForStarKey (svs.info, "*gamedir", value, MAX_SERVERINFO_STRING);
#endif

View File

@ -610,7 +610,7 @@ int INS_InitDInput (void)
if (!hInstDI)
{
hInstDI = LoadLibrary("dinput.dll");
hInstDI = Sys_LoadLibrary("dinput.dll", NULL);
if (hInstDI == NULL)
{

View File

@ -251,9 +251,9 @@ int loadedtracknames;
#ifdef WINAMP
qboolean WinAmp_GetHandle (void)
{
if ((hwnd_winamp = FindWindow("Winamp", NULL)))
if ((hwnd_winamp = FindWindowW(L"Winamp", NULL)))
return true;
if ((hwnd_winamp = FindWindow("Winamp v1.x", NULL)))
if ((hwnd_winamp = FindWindowW(L"Winamp v1.x", NULL)))
return true;
*currenttrack.nicename = '\0';

View File

@ -38,8 +38,16 @@ void M_DrawTextBox (int x, int y, int width, int lines)
cx = x;
cy = y;
p = R2D_SafeCachePic ("gfx/box_tl.lmp");
if (!p)
return; //assume we can't find any
switch(R_GetShaderSizes(p, NULL, NULL, false))
{
case -1:
return; //still pending
case 0:
R2D_ImageColours(0.0, 0.0, 0.0, 1.0);
R2D_FillBlock(x + ((vid.width - 320)>>1), y, width*8+16, lines*8+16);
R2D_ImageColours(1.0, 1.0, 1.0, 1.0);
return;
}
M_DrawScalePic (cx, cy, 8, 8, p);
p = R2D_SafeCachePic ("gfx/box_ml.lmp");
if (p)

View File

@ -5333,6 +5333,7 @@ static struct {
//DP_QC_URI_GET
{"uri_get", PF_uri_get, 513}, // #513 float(string uril, float id) uri_get
{"uri_post", PF_uri_get, 513}, // #513 float(string uril, float id) uri_post
{"tokenize_console", PF_tokenize_console, 514},
{"argv_start_index", PF_argv_start_index, 515},

View File

@ -2055,6 +2055,7 @@ static struct {
{"uri_unescape", PF_uri_unescape, 511},
{"num_for_edict", PF_etof, 512},
{"uri_get", PF_uri_get, 513},
{"uri_post", PF_uri_get, 513},
{"tokenize_console", PF_tokenize_console, 514},
{"argv_start_index", PF_argv_start_index, 515},
{"argv_end_index", PF_argv_end_index, 516},

View File

@ -714,7 +714,6 @@ qboolean R2D_Font_WasAdded(char *buffer, char *fontfilename)
return true;
}
extern qboolean WinNT;
qboolean MyRegGetStringValue(HKEY base, char *keyname, char *valuename, void *data, int datalen);
qboolean MyRegGetStringValueMultiSz(HKEY base, char *keyname, char *valuename, void *data, int datalen);
void R2D_Font_AddFontLink(char *buffer, int buffersize, char *fontname)
{
@ -786,15 +785,14 @@ void R2D_Font_Changed(void)
#if defined(_WIN32) && !defined(FTE_SDL) && !defined(WINRT)
if (!strcmp(gl_font.string, "?"))
{
BOOL (APIENTRY *pChooseFontA)(LPCHOOSEFONTA) = NULL;
BOOL (APIENTRY *pChooseFontW)(LPCHOOSEFONTW) = NULL;
dllfunction_t funcs[] =
{
{(void*)&pChooseFontA, "ChooseFontA"},
{(void*)&pChooseFontW, "ChooseFontW"},
{NULL}
};
qboolean MyRegGetStringValue(HKEY base, char *keyname, char *valuename, void *data, int datalen);
LOGFONT lf = {0};
CHOOSEFONTA cf = {sizeof(cf)};
LOGFONTW lf = {0};
CHOOSEFONTW cf = {sizeof(cf)};
extern HWND mainwindow;
font_default = Font_LoadFont(8, "");
if (tsize != 8)
@ -807,28 +805,30 @@ void R2D_Font_Changed(void)
cf.Flags = CF_FORCEFONTEXIST | CF_TTONLY;
cf.lpLogFont = &lf;
Sys_LoadLibrary("Comdlg32.dll", funcs);
Sys_LoadLibrary("comdlg32.dll", funcs);
if (pChooseFontA && pChooseFontA(&cf))
if (pChooseFontW && pChooseFontW(&cf))
{
char fname[MAX_OSPATH*8];
char lfFaceName[MAX_OSPATH];
char *keyname;
narrowen(lfFaceName, sizeof(lfFaceName), lf.lfFaceName);
*fname = 0;
//FIXME: should enumerate and split & and ignore sizes and () crap.
if (!*fname)
{
keyname = va("%s%s%s (TrueType)", lf.lfFaceName, lf.lfWeight>=FW_BOLD?" Bold":"", lf.lfItalic?" Italic":"");
keyname = va("%s%s%s (TrueType)", lfFaceName, lf.lfWeight>=FW_BOLD?" Bold":"", lf.lfItalic?" Italic":"");
if (!MyRegGetStringValue(HKEY_LOCAL_MACHINE, WinNT?"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts":"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts", keyname, fname, sizeof(fname)))
*fname = 0;
}
if (!*fname)
{
keyname = va("%s (OpenType)", lf.lfFaceName);
keyname = va("%s (OpenType)", lfFaceName);
if (!MyRegGetStringValue(HKEY_LOCAL_MACHINE, WinNT?"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts":"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts", keyname, fname, sizeof(fname)))
*fname = 0;
}
R2D_Font_AddFontLink(fname, sizeof(fname), lf.lfFaceName);
R2D_Font_AddFontLink(fname, sizeof(fname), lfFaceName);
Cvar_Set(&gl_font, fname);
}
return;

View File

@ -809,7 +809,13 @@ static qboolean OpenAL_InitLibrary(void)
if (!openallib_tried)
{
openallib_tried = true;
#ifdef _WIN32
openallib = Sys_LoadLibrary("OpenAL32", openalfuncs);
#else
openallib = Sys_LoadLibrary("libopenal.so.1", openalfuncs);
if (!openallib)
openallib = Sys_LoadLibrary("libopenal", openalfuncs);
#endif
}
return !!openallib;
#endif

View File

@ -68,6 +68,10 @@ snd_pcm_sframes_t (*psnd_pcm_mmap_commit) (snd_pcm_t *pcm, snd_pcm_uframes_t off
snd_pcm_sframes_t (*psnd_pcm_writei) (snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size);
int (*psnd_pcm_prepare) (snd_pcm_t *pcm);
int (*psnd_device_name_hint) (int card, const char *iface, void ***hints);
char * (*psnd_device_name_get_hint) (const void *hint, const char *id);
int (*psnd_device_name_free_hint) (void **hints);
static unsigned int ALSA_MMap_GetDMAPos (soundcardinfo_t *sc)
{
@ -178,6 +182,8 @@ static void ALSA_Shutdown (soundcardinfo_t *sc)
if (sc->Submit == ALSA_RW_Submit)
free(sc->sn.buffer);
Con_DPrintf("Alsa closed\n");
}
static void *ALSA_LockBuffer(soundcardinfo_t *sc, unsigned int *sampidx)
@ -213,35 +219,39 @@ static qboolean Alsa_InitAlsa(void)
}
psnd_pcm_open = dlsym(alsasharedobject, "snd_pcm_open");
psnd_pcm_close = dlsym(alsasharedobject, "snd_pcm_close");
psnd_strerror = dlsym(alsasharedobject, "snd_strerror");
psnd_pcm_hw_params_any = dlsym(alsasharedobject, "snd_pcm_hw_params_any");
psnd_pcm_hw_params_set_access = dlsym(alsasharedobject, "snd_pcm_hw_params_set_access");
psnd_pcm_hw_params_set_format = dlsym(alsasharedobject, "snd_pcm_hw_params_set_format");
psnd_pcm_hw_params_set_channels = dlsym(alsasharedobject, "snd_pcm_hw_params_set_channels");
psnd_pcm_hw_params_set_rate_near = dlsym(alsasharedobject, "snd_pcm_hw_params_set_rate_near");
psnd_pcm_open = dlsym(alsasharedobject, "snd_pcm_open");
psnd_pcm_close = dlsym(alsasharedobject, "snd_pcm_close");
psnd_strerror = dlsym(alsasharedobject, "snd_strerror");
psnd_pcm_hw_params_any = dlsym(alsasharedobject, "snd_pcm_hw_params_any");
psnd_pcm_hw_params_set_access = dlsym(alsasharedobject, "snd_pcm_hw_params_set_access");
psnd_pcm_hw_params_set_format = dlsym(alsasharedobject, "snd_pcm_hw_params_set_format");
psnd_pcm_hw_params_set_channels = dlsym(alsasharedobject, "snd_pcm_hw_params_set_channels");
psnd_pcm_hw_params_set_rate_near = dlsym(alsasharedobject, "snd_pcm_hw_params_set_rate_near");
psnd_pcm_hw_params_set_period_size_near = dlsym(alsasharedobject, "snd_pcm_hw_params_set_period_size_near");
psnd_pcm_hw_params = dlsym(alsasharedobject, "snd_pcm_hw_params");
psnd_pcm_sw_params_current = dlsym(alsasharedobject, "snd_pcm_sw_params_current");
psnd_pcm_hw_params = dlsym(alsasharedobject, "snd_pcm_hw_params");
psnd_pcm_sw_params_current = dlsym(alsasharedobject, "snd_pcm_sw_params_current");
psnd_pcm_sw_params_set_start_threshold = dlsym(alsasharedobject, "snd_pcm_sw_params_set_start_threshold");
psnd_pcm_sw_params_set_stop_threshold = dlsym(alsasharedobject, "snd_pcm_sw_params_set_stop_threshold");
psnd_pcm_sw_params = dlsym(alsasharedobject, "snd_pcm_sw_params");
psnd_pcm_hw_params_get_buffer_size = dlsym(alsasharedobject, "snd_pcm_hw_params_get_buffer_size");
psnd_pcm_avail_update = dlsym(alsasharedobject, "snd_pcm_avail_update");
psnd_pcm_state = dlsym(alsasharedobject, "snd_pcm_state");
psnd_pcm_start = dlsym(alsasharedobject, "snd_pcm_start");
psnd_pcm_recover = dlsym(alsasharedobject, "snd_pcm_recover");
psnd_pcm_set_params = dlsym(alsasharedobject, "snd_pcm_set_params");
psnd_pcm_hw_params_sizeof = dlsym(alsasharedobject, "snd_pcm_hw_params_sizeof");
psnd_pcm_sw_params_sizeof = dlsym(alsasharedobject, "snd_pcm_sw_params_sizeof");
psnd_pcm_sw_params = dlsym(alsasharedobject, "snd_pcm_sw_params");
psnd_pcm_hw_params_get_buffer_size = dlsym(alsasharedobject, "snd_pcm_hw_params_get_buffer_size");
psnd_pcm_avail_update = dlsym(alsasharedobject, "snd_pcm_avail_update");
psnd_pcm_state = dlsym(alsasharedobject, "snd_pcm_state");
psnd_pcm_start = dlsym(alsasharedobject, "snd_pcm_start");
psnd_pcm_recover = dlsym(alsasharedobject, "snd_pcm_recover");
psnd_pcm_set_params = dlsym(alsasharedobject, "snd_pcm_set_params");
psnd_pcm_hw_params_sizeof = dlsym(alsasharedobject, "snd_pcm_hw_params_sizeof");
psnd_pcm_sw_params_sizeof = dlsym(alsasharedobject, "snd_pcm_sw_params_sizeof");
psnd_pcm_hw_params_set_buffer_size_near = dlsym(alsasharedobject, "snd_pcm_hw_params_set_buffer_size_near");
psnd_pcm_mmap_begin = dlsym(alsasharedobject, "snd_pcm_mmap_begin");
psnd_pcm_mmap_commit = dlsym(alsasharedobject, "snd_pcm_mmap_commit");
psnd_pcm_mmap_begin = dlsym(alsasharedobject, "snd_pcm_mmap_begin");
psnd_pcm_mmap_commit = dlsym(alsasharedobject, "snd_pcm_mmap_commit");
psnd_pcm_writei = dlsym(alsasharedobject, "snd_pcm_writei");
psnd_pcm_prepare = dlsym(alsasharedobject, "snd_pcm_prepare");
psnd_pcm_writei = dlsym(alsasharedobject, "snd_pcm_writei");
psnd_pcm_prepare = dlsym(alsasharedobject, "snd_pcm_prepare");
psnd_device_name_hint = dlsym(alsasharedobject, "snd_device_name_hint");
psnd_device_name_get_hint = dlsym(alsasharedobject, "snd_device_name_get_hint");
psnd_device_name_free_hint = dlsym(alsasharedobject, "snd_device_name_free_hint");
alsaworks = psnd_pcm_open
&& psnd_pcm_close
@ -267,20 +277,17 @@ static qboolean Alsa_InitAlsa(void)
&& psnd_pcm_mmap_begin
&& psnd_pcm_mmap_commit
&& psnd_pcm_writei && psnd_pcm_prepare
&& psnd_device_name_hint && psnd_device_name_get_hint && psnd_device_name_free_hint
;
return alsaworks;
}
static int ALSA_InitCard (soundcardinfo_t *sc, int cardnum)
static qboolean QDECL ALSA_InitCard (soundcardinfo_t *sc, const char *pcmname)
{
snd_pcm_t *pcm;
snd_pcm_uframes_t buffer_size;
soundcardinfo_t *ec; //existing card
char *pcmname;
cvar_t *devname;
int err;
snd_pcm_hw_params_t *hw;
snd_pcm_sw_params_t *sw;
@ -294,7 +301,7 @@ static int ALSA_InitCard (soundcardinfo_t *sc, int cardnum)
if (!Alsa_InitAlsa())
{
Con_Printf(CON_ERROR "Alsa does not appear to be installed or compatible\n");
return 2;
return false;
}
hw = alloca(psnd_pcm_hw_params_sizeof());
@ -303,17 +310,8 @@ static int ALSA_InitCard (soundcardinfo_t *sc, int cardnum)
memset(hw, 0, psnd_pcm_hw_params_sizeof());
//WARNING: 'default' as the default sucks arse. it adds about a second's worth of lag.
devname = Cvar_Get(va("snd_alsadevice%i", cardnum+1), (cardnum==0?"hw":(cardnum==1?"default":"")), 0, "Sound controls");
pcmname = devname->string;
if (!*pcmname)
return 2;
for (ec = sndcardinfo; ec; ec = ec->next)
if (!strcmp(ec->name, pcmname))
break;
if (ec)
return 2; //no more
if (!pcmname)
pcmname = "default";
sc->inactive_sound = true; //linux sound devices always play sound, even when we're not the active app...
@ -323,7 +321,7 @@ static int ALSA_InitCard (soundcardinfo_t *sc, int cardnum)
SND_PCM_NONBLOCK);
if (0 > err)
{
Con_Printf (CON_ERROR "Error: open error: %s\n", psnd_strerror (err));
Con_Printf (CON_ERROR "ALSA Error: open error (%s): %s\n", pcmname, psnd_strerror (err));
return 0;
}
Con_Printf ("ALSA: Using PCM %s.\n", pcmname);
@ -332,8 +330,7 @@ static int ALSA_InitCard (soundcardinfo_t *sc, int cardnum)
err = psnd_pcm_set_params(pcm, ((sc->sn.samplebits==8)?SND_PCM_FORMAT_U8:SND_PCM_FORMAT_S16), (mmap?SND_PCM_ACCESS_MMAP_INTERLEAVED:SND_PCM_ACCESS_RW_INTERLEAVED), sc->sn.numchannels, sc->sn.speed, true, 0.04*1000000);
if (0 > err)
{
Con_Printf (CON_ERROR "ALSA: error setting params. %s\n",
psnd_strerror (err));
Con_Printf (CON_ERROR "ALSA: error setting params. %s\n", psnd_strerror (err));
goto error;
}
@ -346,16 +343,14 @@ static int ALSA_InitCard (soundcardinfo_t *sc, int cardnum)
err = psnd_pcm_hw_params_any (pcm, hw);
if (0 > err)
{
Con_Printf (CON_ERROR "ALSA: error setting hw_params_any. %s\n",
psnd_strerror (err));
Con_Printf (CON_ERROR "ALSA: error setting hw_params_any. %s\n", psnd_strerror (err));
goto error;
}
err = psnd_pcm_hw_params_set_access (pcm, hw, mmap?SND_PCM_ACCESS_MMAP_INTERLEAVED:SND_PCM_ACCESS_RW_INTERLEAVED);
if (0 > err)
{
Con_Printf (CON_ERROR "ALSA: Failure to set interleaved PCM access. %s\n",
psnd_strerror (err));
Con_Printf (CON_ERROR "ALSA: Failure to set interleaved PCM access. %s\n", psnd_strerror (err));
goto error;
}
@ -433,8 +428,7 @@ static int ALSA_InitCard (soundcardinfo_t *sc, int cardnum)
err = psnd_pcm_hw_params_set_period_size_near (pcm, hw, &frag_size, 0);
if (0 > err)
{
Con_Printf (CON_ERROR "ALSA: unable to set period size near %i. %s\n",
(int) frag_size, psnd_strerror (err));
Con_Printf (CON_ERROR "ALSA: unable to set period size near %i. %s\n", (int) frag_size, psnd_strerror (err));
goto error;
}
err = psnd_pcm_hw_params (pcm, hw);
@ -445,26 +439,22 @@ static int ALSA_InitCard (soundcardinfo_t *sc, int cardnum)
}
err = psnd_pcm_sw_params_current (pcm, sw);
if (0 > err) {
Con_Printf (CON_ERROR "ALSA: unable to determine current sw params. %s\n",
psnd_strerror (err));
Con_Printf (CON_ERROR "ALSA: unable to determine current sw params. %s\n", psnd_strerror (err));
goto error;
}
err = psnd_pcm_sw_params_set_start_threshold (pcm, sw, ~0U);
if (0 > err) {
Con_Printf (CON_ERROR "ALSA: unable to set playback threshold. %s\n",
psnd_strerror (err));
Con_Printf (CON_ERROR "ALSA: unable to set playback threshold. %s\n", psnd_strerror (err));
goto error;
}
err = psnd_pcm_sw_params_set_stop_threshold (pcm, sw, ~0U);
if (0 > err) {
Con_Printf (CON_ERROR "ALSA: unable to set playback stop threshold. %s\n",
psnd_strerror (err));
Con_Printf (CON_ERROR "ALSA: unable to set playback stop threshold. %s\n", psnd_strerror (err));
goto error;
}
err = psnd_pcm_sw_params (pcm, sw);
if (0 > err) {
Con_Printf (CON_ERROR "ALSA: unable to install sw params. %s\n",
psnd_strerror (err));
Con_Printf (CON_ERROR "ALSA: unable to install sw params. %s\n", psnd_strerror (err));
goto error;
}
@ -485,8 +475,7 @@ static int ALSA_InitCard (soundcardinfo_t *sc, int cardnum)
err = psnd_pcm_hw_params_get_buffer_size (hw, &buffer_size);
if (0 > err) {
Con_Printf (CON_ERROR "ALSA: unable to get buffer size. %s\n",
psnd_strerror (err));
Con_Printf (CON_ERROR "ALSA: unable to get buffer size. %s\n", psnd_strerror (err));
goto error;
}
sc->sn.speed = rate;
@ -530,8 +519,7 @@ static int ALSA_InitCard (soundcardinfo_t *sc, int cardnum)
err = psnd_pcm_prepare(pcm);
if (0 > err)
{
Con_Printf (CON_ERROR "ALSA: unable to prepare for use. %s\n",
psnd_strerror (err));
Con_Printf (CON_ERROR "ALSA: unable to prepare for use. %s\n", psnd_strerror (err));
goto error;
}
}
@ -542,7 +530,45 @@ error:
psnd_pcm_close (pcm);
return false;
}
#define SDRVNAME "ALSA"
static qboolean QDECL ALSA_Enumerate(void (QDECL *cb) (const char *drivername, const char *devicecode, const char *readablename))
{
size_t i;
void **hints;
int (*pALSA_InitCard) (soundcardinfo_t *sc, int cardnum) = &ALSA_InitCard;
if (Alsa_InitAlsa())
{
if (!psnd_device_name_hint(-1, "pcm", &hints))
{
for (i = 0; hints[i]; i++)
{
char *n = psnd_device_name_get_hint(hints[i], "NAME");
if (n)
{
char *t = psnd_device_name_get_hint(hints[i], "IOID");
if (!t || strcasecmp(t, "Input"))
{
char *d = psnd_device_name_get_hint(hints[i], "DESC");
if (d)
cb(SDRVNAME, n, va("ALSA (%s)", d));
else
cb(SDRVNAME, n, n);
free(d);
}
free(t);
free(n); //dangerous to free things across boundaries.
}
}
psnd_device_name_free_hint(hints);
}
else
return false;
}
return true;
}
sounddriver_t ALSA_Output =
{
SDRVNAME,
ALSA_InitCard,
ALSA_Enumerate
};

View File

@ -112,8 +112,8 @@ cvar_t snd_linearresample_stream = CVARAF( "s_linearresample_stream", "0",
cvar_t snd_mixerthread = CVARAD( "s_mixerthread", "1",
"snd_mixerthread", "When enabled sound mixing will be run on a separate thread. Currently supported only by directsound. Other drivers may unconditionally thread audio. Set to 0 only if you have issues.");
cvar_t snd_device = CVARAF( "s_device", "",
"snd_device", CVAR_ARCHIVE);
cvar_t snd_device = CVARAFD( "s_device", "",
"snd_device", CVAR_ARCHIVE, "This is the sound device(s) to use, in the form of driver:device. If desired, multiple devices can be listed in space-seperated (quoted) tokens. _s_device_opts contains any enumerated options. In all seriousness, use the menu to set this if you wish to keep your hair.");
cvar_t snd_device_opts = CVARFD( "_s_device_opts", "", CVAR_NOSET, "The possible audio output devices, in \"value\" \"description\" pairs, for gamecode to read.");
#ifdef VOICECHAT
@ -1484,11 +1484,13 @@ void S_DefaultSpeakerConfiguration(soundcardinfo_t *sc)
sounddriver_t DSOUND_Output;
sounddriver_t SDL_Output;
sounddriver_t ALSA_Output;
sounddriver_t OSS_Output;
#ifdef AVAIL_OPENAL
extern sounddriver_t OPENAL_Output;
#endif
sounddriver pALSA_InitCard;
sounddriver pSNDIO_InitCard;
sounddriver pOSS_InitCard;
sounddriver pMacOS_InitCard;
@ -1506,7 +1508,15 @@ sounddriver_t *outputdrivers[] =
#ifdef AVAIL_OPENAL
&OPENAL_Output,
#endif
#ifdef _WIN32
&DSOUND_Output,
#endif
&SDL_Output, //prefered on linux
#ifdef __linux__
&ALSA_Output, //pure shite
#endif
&OSS_Output, //good, but not likely to work any more
NULL
};
typedef struct {
@ -1523,10 +1533,6 @@ sdriver_t olddrivers[] = {
#endif
{"SNDIO", &pSNDIO_InitCard}, //prefered on OpenBSD
{"SDL", &pSDL_InitCard}, //prefered on linux
{"ALSA", &pALSA_InitCard}, //pure shite
{"OSS", &pOSS_InitCard}, //good, but not likely to work any more
{"WaveOut", &pWAV_InitCard}, //doesn't work properly in vista, etc.
{NULL, NULL}
};
@ -1586,7 +1592,7 @@ static soundcardinfo_t *SNDDMA_Init(char *driver, char *device)
for (i = 0; outputdrivers[i]; i++)
{
sd = outputdrivers[i];
if (sd && (!driver || !Q_strcasecmp(sd->name, driver)))
if (sd && sd->name && (!driver || !Q_strcasecmp(sd->name, driver)))
{
//skip drivers which are not present.
if (!sd->InitCard)

View File

@ -82,7 +82,7 @@ static void OSS_Alsa_Submit(soundcardinfo_t *sc, int start, int end)
{
if (result >= 0)
sc->snd_sent += result;
printf("full?\n");
// printf("full?\n");
return;
}
sc->snd_sent += chunk;
@ -119,7 +119,7 @@ static void OSS_Unlock(soundcardinfo_t *sc, void *buffer)
{
}
static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
static qboolean OSS_InitCard(soundcardinfo_t *sc, const char *snddev)
{ //FIXME: implement snd_multipledevices somehow.
int rc;
int fmt;
@ -127,8 +127,6 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
int i;
struct audio_buf_info info;
int caps;
char *snddev = NULL;
cvar_t *devname;
qboolean alsadetected = false;
#ifdef __linux__
@ -137,11 +135,13 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
alsadetected = true;
#endif
devname = Cvar_Get(va("snd_devicename%i", cardnum+1), cardnum?"":"/dev/dsp", 0, "Sound controls");
snddev = devname->string;
if (!*snddev)
return 2;
if (!snddev || !*snddev)
snddev = "/dev/dsp";
else if (strncmp(snddev, "/dev/dsp", 8))
{
Con_Printf("Refusing to use non-dsp device\n");
return false;
}
sc->inactive_sound = true; //linux sound devices always play sound, even when we're not the active app...
@ -165,7 +165,7 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
perror(snddev);
Con_Printf(CON_ERROR "OSS: Could not open %s\n", snddev);
OSS_Shutdown(sc);
return 0;
return false;
}
Q_strncpyz(sc->name, snddev, sizeof(sc->name));
@ -176,7 +176,7 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
perror(snddev);
Con_Printf(CON_ERROR "OSS: Could not reset %s\n", snddev);
OSS_Shutdown(sc);
return 0;
return false;
}
//check its general capabilities, we need trigger+mmap
@ -185,7 +185,7 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
perror(snddev);
Con_Printf(CON_ERROR "OSS: Sound driver too old\n");
OSS_Shutdown(sc);
return 0;
return false;
}
//choose channels
@ -197,7 +197,7 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
perror(snddev);
Con_Printf(CON_ERROR "OSS: Could not set %s to channels=%d\n", snddev, sc->sn.numchannels);
OSS_Shutdown(sc);
return 0;
return false;
}
sc->sn.numchannels = tmp;
#else
@ -210,7 +210,7 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
perror(snddev);
Con_Printf(CON_ERROR "OSS: Could not set %s to stereo=%d\n", snddev, sc->sn.numchannels);
OSS_Shutdown(sc);
return 0;
return false;
}
if (tmp)
sc->sn.numchannels = 2;
@ -227,7 +227,7 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
{ //their card doesn't support 8bit which we're trying to use.
Con_Printf(CON_ERROR "OSS: No needed sample formats supported\n");
OSS_Shutdown(sc);
return 0;
return false;
}
if (sc->sn.samplebits == 16)
{
@ -238,7 +238,7 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
perror(snddev);
Con_Printf(CON_ERROR "OSS: Could not support 16-bit data. Try 8-bit.\n");
OSS_Shutdown(sc);
return 0;
return false;
}
}
else if (sc->sn.samplebits == 8)
@ -250,7 +250,7 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
perror(snddev);
Con_Printf(CON_ERROR "OSS: Could not support 8-bit data.\n");
OSS_Shutdown(sc);
return 0;
return false;
}
}
else
@ -258,7 +258,7 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
perror(snddev);
Con_Printf(CON_ERROR "OSS: %d-bit sound not supported.\n", sc->sn.samplebits);
OSS_Shutdown(sc);
return 0;
return false;
}
//choose speed
@ -276,7 +276,7 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
perror(snddev);
Con_Printf(CON_ERROR "OSS: Failed to obtain a suitable rate\n");
OSS_Shutdown(sc);
return 0;
return false;
}
}
sc->sn.speed = tmp;
@ -287,7 +287,7 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
perror("GETOSPACE");
Con_Printf(CON_ERROR "OSS: Um, can't do GETOSPACE?\n");
OSS_Shutdown(sc);
return 0;
return false;
}
sc->sn.samples = info.fragstotal * info.fragsize;
sc->sn.samples /= (sc->sn.samplebits/8);
@ -297,7 +297,7 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
sc->sn.buffer = MAP_FAILED;
if (alsadetected)
{
Con_Printf("Alsa detected. Refusing to mmap.\n");
Con_Printf("Refusing to mmap oss device in case alsa's oss emulation crashes.\n");
}
else if ((caps & DSP_CAP_TRIGGER) && (caps & DSP_CAP_MMAP))
{
@ -335,7 +335,7 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
perror(snddev);
Con_Printf(CON_ERROR "OSS: Could not toggle.\n");
OSS_Shutdown(sc);
return 0;
return false;
}
tmp = PCM_ENABLE_OUTPUT;
rc = ioctl(sc->audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
@ -344,7 +344,7 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
perror(snddev);
Con_Printf(CON_ERROR "OSS: Could not toggle.\n");
OSS_Shutdown(sc);
return 0;
return false;
}
sc->Submit = OSS_MMap_Submit;
sc->GetDMAPos = OSS_MMap_GetDMAPos;
@ -357,10 +357,103 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
sc->SetWaterDistortion = OSS_SetUnderWater;
sc->Shutdown = OSS_Shutdown;
return 1;
return true;
}
int (*pOSS_InitCard) (soundcardinfo_t *sc, int cardnum) = &OSS_InitCard;
#define SDRVNAME "OSS"
typedef struct oss_sysinfo {
char product[32]; /* E.g. SunOS Audio */
char version[32]; /* E.g. 4.0a */
int versionnum; /* See OSS_GETVERSION */
char options[128]; /* NOT SUPPORTED */
int numaudios; /* # of audio/dsp devices */
int openedaudio[8]; /* Reserved, always 0 */
int numsynths; /* NOT SUPPORTED, always 0 */
int nummidis; /* NOT SUPPORTED, always 0 */
int numtimers; /* NOT SUPPORTED, always 0 */
int nummixers; /* # of mixer devices */
int openedmidi[8]; /* Mask of midi devices are busy */
int numcards; /* Number of sound cards in the system */
int numaudioengines; /* Number of audio engines in the system */
char license[16]; /* E.g. "GPL" or "CDDL" */
char revision_info[256]; /* Reserved */
int filler[172]; /* Reserved */
} oss_sysinfo;
#define SNDCTL_SYSINFO _IOR ('X', 1, oss_sysinfo)
typedef struct oss_audioinfo {
int dev; /* Device to query */
char name[64]; /* Human readable name */
int busy; /* reserved */
int pid; /* reserved */
int caps; /* PCM_CAP_INPUT, PCM_CAP_OUTPUT */
int iformats; /* Supported input formats */
int oformats; /* Supported output formats */
int magic; /* reserved */
char cmd[64]; /* reserved */
int card_number;
int port_number; /* reserved */
int mixer_dev;
int legacy_device; /* Obsolete field. Replaced by devnode */
int enabled; /* reserved */
int flags; /* reserved */
int min_rate; /* Minimum sample rate */
int max_rate; /* Maximum sample rate */
int min_channels; /* Minimum number of channels */
int max_channels; /* Maximum number of channels */
int binding; /* reserved */
int rate_source; /* reserved */
char handle[32]; /* reserved */
unsigned int nrates; /* reserved */
unsigned int rates[20]; /* reserved */
char song_name[64]; /* reserved */
char label[16]; /* reserved */
int latency; /* reserved */
char devnode[32]; /* Device special file name (absolute path) */
int next_play_engine; /* reserved */
int next_rec_engine; /* reserved */
int filler[184]; /* reserved */
} oss_audioinfo;
#define SNDCTL_AUDIOINFO _IOWR('X', 7, oss_audioinfo)
static qboolean QDECL OSS_Enumerate(void (QDECL *cb) (const char *drivername, const char *devicecode, const char *readablename))
{
int i;
int fd = open("/dev/mixer", O_RDWR, 0);
oss_sysinfo si;
if (fd == -1)
return true; //oss not supported. don't list any devices.
if (ioctl(fd, SNDCTL_SYSINFO, &si) != -1)
{
if ((si.versionnum>>16) >= 4)
{ //only trust all the fields if its recent enough
for(i = 0; i < si.numaudios; i++)
{
oss_audioinfo ai;
ai.dev = i;
if (ioctl(fd, SNDCTL_AUDIOINFO, &ai) != -1)
cb(SDRVNAME, ai.devnode, ai.name);
}
close(fd);
return true;
}
else
printf("Not enumerating OSS %u.%u.%u devices.\n", (si.versionnum>>16)&0xffff, (si.versionnum>>8)&0xff, si.versionnum&0xff);
}
else
printf("OSS driver is too old to support device enumeration.\n");
close(fd);
return false; //enumeration failed.
}
sounddriver_t OSS_Output =
{
SDRVNAME,
OSS_InitCard,
OSS_Enumerate
};

View File

@ -1,24 +1,117 @@
#include "quakedef.h"
#include "winquake.h"
#ifdef DYNAMIC_SDL
#define SDL_MAJOR_VERSION 2
//if we're not an sdl build, we probably want to link to sdl libraries dynamically or something.
#include <stdint.h>
#define SDL_AudioDeviceID uint32_t
#define SDL_INIT_AUDIO 0x00000010
#define SDL_INIT_NOPARACHUTE 0x00100000
#define SDL_AUDIO_ALLOW_FREQUENCY_CHANGE 0x00000001
#define SDL_AUDIO_ALLOW_FORMAT_CHANGE 0x00000002
#define SDL_AUDIO_ALLOW_CHANNELS_CHANGE 0x00000004
#define AUDIO_S16LSB 0x8010
#define AUDIO_S16MSB 0x9010
#if __BYTE_ORDER == __BIG_ENDIAN
#define AUDIO_S16SYS AUDIO_S16MSB
#else
#define AUDIO_S16SYS AUDIO_S16LSB
#endif
typedef uint16_t SDL_AudioFormat;
typedef void VARGS (*SDL_AudioCallback)(void *userdata, uint8_t *stream, int len);
typedef struct SDL_AudioSpec
{
int freq;
SDL_AudioFormat format;
uint8_t channels;
uint8_t silence;
uint16_t samples;
uint16_t padding;
uint32_t size;
SDL_AudioCallback callback;
void *userdata;
} SDL_AudioSpec;
static int (*SDL_Init) (uint32_t flags);
static int (*SDL_InitSubSystem) (uint32_t flags);
static SDL_AudioDeviceID (*SDL_OpenAudioDevice) (const char *dev, int iscapture, const SDL_AudioSpec *desired, SDL_AudioSpec *obtained, int allowed_changes);
static void (*SDL_PauseAudioDevice) (SDL_AudioDeviceID fd, int pausestate);
static void (*SDL_LockAudioDevice) (SDL_AudioDeviceID fd);
static void (*SDL_UnlockAudioDevice) (SDL_AudioDeviceID fd);
static int (*SDL_CloseAudioDevice) (SDL_AudioDeviceID fd);
static int (*SDL_GetNumAudioDevices) (int iscapture);
static const char *(*SDL_GetAudioDeviceName) (int index, int iscapture);
static const char *(*SDL_GetError) (void);
#else
#include <SDL.h>
#endif
#define SELFPAINT
//SDL calls a callback each time it needs to repaint the 'hardware' buffers
//This results in extra latency.
//SDL runs does this multithreaded.
//This results in extra latency due it needing to buffer that much data.
//So we tell it a fairly pathetically sized buffer and try and get it to copy often
//hopefully this lowers sound latency, and has no suddenly starting sounds and stuff.
//It still has greater latency than direct access, of course.
//On the plus side, SDL calls the callback from another thread. this means we can set up some tiny buffer size, and if we're mixing inside the callback then you can actually get lower latency than waiting for an entire frame (yay rtlights)
static qboolean SSDL_InitAudio(void)
{
static qboolean inited = false;
#ifdef DYNAMIC_SDL
static dllfunction_t funcs[] =
{
{(void*)&SDL_Init, "SDL_Init"},
{(void*)&SDL_InitSubSystem, "SDL_InitSubSystem"},
{(void*)&SDL_OpenAudioDevice, "SDL_OpenAudioDevice"},
{(void*)&SDL_PauseAudioDevice, "SDL_PauseAudioDevice"},
{(void*)&SDL_LockAudioDevice, "SDL_LockAudioDevice"},
{(void*)&SDL_UnlockAudioDevice, "SDL_UnlockAudioDevice"},
{(void*)&SDL_CloseAudioDevice, "SDL_CloseAudioDevice"},
{(void*)&SDL_GetNumAudioDevices, "SDL_GetNumAudioDevices"},
{(void*)&SDL_GetAudioDeviceName, "SDL_GetAudioDeviceName"},
{(void*)&SDL_GetError, "SDL_GetError"},
{NULL, NULL}
};
static dllhandle_t *libsdl;
if (!libsdl)
{
libsdl = Sys_LoadLibrary("libSDL2.so", funcs);
if (libsdl)
SDL_Init(SDL_INIT_NOPARACHUTE);
else
{
Con_Printf("Unable to load libSDL2 library\n");
return false;
}
}
#endif
if (!inited)
if(SDL_InitSubSystem(SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE))
{
Con_Printf("Couldn't initialize SDL audio subsystem (%s)\n", SDL_GetError());
return false;
}
inited = true;
return true;
}
//FIXME: One thing I saw in quakeforge was that quakeforge basically leaves the audio locked except for a really short period of time.
//An interesting idea, which ensures the driver can only paint in a small time-frame. this would possibly allow lower latency painting.
static void SSDL_Shutdown(soundcardinfo_t *sc)
{
Con_DPrintf("Shutdown SDL sound\n");
#if SDL_MAJOR_VERSION >= 2
SDL_PauseAudioDevice(sc->audio_fd, 1);
SDL_CloseAudioDevice(sc->audio_fd);
#else
SDL_CloseAudio();
#endif
#ifndef SELFPAINT
if (sc->sn.buffer)
free(sc->sn.buffer);
@ -67,14 +160,22 @@ static void VARGS SSDL_Paint(void *userdata, qbyte *stream, int len)
static void *SSDL_LockBuffer(soundcardinfo_t *sc, unsigned int *sampidx)
{
#if SDL_MAJOR_VERSION >= 2
SDL_LockAudioDevice(sc->audio_fd);
#else
SDL_LockAudio();
#endif
return sc->sn.buffer;
}
static void SSDL_UnlockBuffer(soundcardinfo_t *sc, void *buffer)
{
#if SDL_MAJOR_VERSION >= 2
SDL_UnlockAudioDevice(sc->audio_fd);
#else
SDL_UnlockAudio();
#endif
}
static void SSDL_SetUnderWater(soundcardinfo_t *sc, qboolean uw)
@ -87,18 +188,11 @@ static void SSDL_Submit(soundcardinfo_t *sc, int start, int end)
//SDL will call SSDL_Paint to paint when it's time, and the sound buffer is always there...
}
static int SDL_InitCard(soundcardinfo_t *sc, int cardnum)
static qboolean SDL_InitCard(soundcardinfo_t *sc, const char *devicename)
{
SDL_AudioSpec desired, obtained;
if (cardnum)
{ //our init code actually calls this function multiple times, in the case that the user has multiple sound cards
return 2; //erm. SDL won't allow multiple sound cards anyway.
}
Con_Printf("Initing SDL audio.\n");
if(SDL_InitSubSystem(SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE))
if(!SSDL_InitAudio())
{
Con_Printf("Couldn't initialize SDL audio subsystem\n");
return false;
@ -114,19 +208,26 @@ static int SDL_InitCard(soundcardinfo_t *sc, int cardnum)
desired.userdata = sc;
memcpy(&obtained, &desired, sizeof(obtained));
#ifdef FTE_TARGET_WEB
if ( SDL_OpenAudio(&desired, NULL) < 0 )
#if SDL_MAJOR_VERSION >= 2
sc->audio_fd = SDL_OpenAudioDevice(devicename, false, &desired, &obtained, (sndcardinfo?0:SDL_AUDIO_ALLOW_FREQUENCY_CHANGE) | SDL_AUDIO_ALLOW_CHANNELS_CHANGE);
if (!sc->audio_fd)
{
Con_Printf("SDL: SNDDMA_Init: couldn't open sound device (%s).\n", SDL_GetError());
Con_Printf("SDL_OpenAudioDevice(%s) failed: couldn't open sound device (%s).\n", devicename?devicename:"default", SDL_GetError());
return false;
}
obtained = desired;
if (devicename)
Con_Printf("Initing SDL audio device '%s'.\n", devicename);
else
Con_Printf("Initing default SDL audio device.\n");
#else
if (sndcardinfo)
return false; //SDL1 only supports opening one audio device at a time. the existing one might not be sdl, but I don't care.
if ( SDL_OpenAudio(&desired, &obtained) < 0 )
{
Con_Printf("SDL: SNDDMA_Init: couldn't open sound device (%s).\n", SDL_GetError());
Con_Printf("SDL_OpenAudio failed: couldn't open sound device (%s).\n", SDL_GetError());
return false;
}
Con_Printf("Initing default SDL audio device.\n");
#endif
sc->sn.numchannels = obtained.channels;
sc->sn.speed = obtained.freq;
@ -155,10 +256,41 @@ static int SDL_InitCard(soundcardinfo_t *sc, int cardnum)
sc->Shutdown = SSDL_Shutdown;
sc->GetDMAPos = SSDL_GetDMAPos;
#if SDL_MAJOR_VERSION >= 2
SDL_PauseAudioDevice(sc->audio_fd, 0);
#else
SDL_PauseAudio(0);
#endif
return true;
}
sounddriver pSDL_InitCard = &SDL_InitCard;
#define SDRVNAME "SDL"
static qboolean QDECL SDL_Enumerate(void (QDECL *cb) (const char *drivername, const char *devicecode, const char *readablename))
{
#if SDL_MAJOR_VERSION >= 2
int max, i;
if(SSDL_InitAudio())
{
max = SDL_GetNumAudioDevices(false);
for (i = 0; i < max; i++)
{
const char *devname = SDL_GetAudioDeviceName(i, false);
if (devname)
cb(SDRVNAME, devname, va("SDL (%s)", devname));
}
}
return true;
#else
return false;
#endif
}
sounddriver_t SDL_Output =
{
SDRVNAME,
SDL_InitCard,
SDL_Enumerate
};

View File

@ -578,7 +578,7 @@ vfsfile_t *VFSPIPE_Open(void)
#endif
#ifdef _WIN32
qboolean MyRegGetStringValue(HKEY base, char *keyname, char *valuename, void *data, DWORD datalen)
qboolean MyRegGetStringValue(HKEY base, const char *keyname, const char *valuename, void *data, size_t datalen)
{
qboolean result = false;
HKEY subkey;

View File

@ -43,10 +43,6 @@ __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; //13.35+
wchar_t *widen(wchar_t *out, size_t outlen, const char *utf8);
char *narrowen(char *out, size_t outlen, wchar_t *wide);
#ifdef WINRT //you're going to need a different sys_ port.
qboolean isDedicated = false;
qboolean ActiveApp;
@ -368,15 +364,20 @@ dllhandle_t *Sys_LoadLibrary(const char *name, dllfunction_t *funcs)
{
int i;
HMODULE lib;
wchar_t wide[MAX_OSPATH];
lib = LoadLibrary(name);
widen(wide, sizeof(wide), name);
lib = LoadLibraryW(wide);
if (!lib)
{
if (!strstr(COM_SkipPath(name), ".dll"))
{ //.dll implies that it is a system dll, or something that is otherwise windows-specific already.
#ifdef _WIN64
lib = LoadLibrary(va("%s_64", name));
lib = LoadLibrary(va("%s_64", name));
#elif defined(_WIN32)
lib = LoadLibrary(va("%s_32", name));
lib = LoadLibrary(va("%s_32", name));
#endif
}
if (!lib)
return NULL;
}
@ -763,7 +764,7 @@ DWORD CrashExceptionHandler (qboolean iswatchdog, DWORD exceptionCode, LPEXCEPTI
//generate a minidump, but only if we were compiled by something that used usable debugging info. its a bit pointless otherwise.
#ifdef _MSC_VER
hDbgHelp = LoadLibrary ("DBGHELP");
hDbgHelp = LoadLibraryA ("DBGHELP");
if (hDbgHelp)
fnMiniDumpWriteDump = (MINIDUMPWRITEDUMP)GetProcAddress (hDbgHelp, "MiniDumpWriteDump");
else
@ -790,9 +791,9 @@ DWORD CrashExceptionHandler (qboolean iswatchdog, DWORD exceptionCode, LPEXCEPTI
else if (*com_gamepath)
Q_strncpyz(dumpPath, com_gamepath, sizeof(dumpPath));
else
GetTempPath (sizeof(dumpPath)-16, dumpPath);
GetTempPathA (sizeof(dumpPath)-16, dumpPath);
Q_strncatz(dumpPath, DISTRIBUTION"CrashDump.dmp", sizeof(dumpPath));
dumpfile = CreateFile (dumpPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
dumpfile = CreateFileA (dumpPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (dumpfile)
{
MINIDUMP_EXCEPTION_INFORMATION crashinfo;
@ -803,19 +804,19 @@ DWORD CrashExceptionHandler (qboolean iswatchdog, DWORD exceptionCode, LPEXCEPTI
{
CloseHandle(dumpfile);
Q_snprintfz(msg, sizeof(msg), "You can find the crashdump at:\n%s\nPlease send this file to someone.\n\nWarning: sensitive information (like your current user name) might be present in the dump.\nYou will probably want to compress it.", dumpPath);
MessageBox(NULL, msg, DISTRIBUTION " Sucks", 0);
MessageBoxA(NULL, msg, DISTRIBUTION " Sucks", 0);
}
else
MessageBox(NULL, "MiniDumpWriteDump failed", "oh noes", 0);
MessageBoxA(NULL, "MiniDumpWriteDump failed", "oh noes", 0);
}
else
{
Q_snprintfz(msg, sizeof(msg), "unable to open %s\nno dump created.", dumpPath);
MessageBox(NULL, msg, "oh noes", 0);
MessageBoxA(NULL, msg, "oh noes", 0);
}
}
else
MessageBox(NULL, "Kaboom! Sorry. No MiniDumpWriteDump function.", DISTRIBUTION " Sucks", 0);
MessageBoxA(NULL, "Kaboom! Sorry. No MiniDumpWriteDump function.", DISTRIBUTION " Sucks", 0);
#endif
return EXCEPTION_EXECUTE_HANDLER;
}
@ -1071,7 +1072,7 @@ static int Sys_EnumerateFiles2 (const char *match, int matchstart, int neststart
memcpy(tmproot, match, neststart);
strcpy(tmproot+neststart, "*.*");
r = FindFirstFile(tmproot, &fd);
r = FindFirstFileA(tmproot, &fd);
strcpy(tmproot+neststart, "");
if (r==(HANDLE)-1)
return 1;
@ -1093,7 +1094,7 @@ static int Sys_EnumerateFiles2 (const char *match, int matchstart, int neststart
}
}
}
} while(FindNextFile(r, &fd) && go);
} while(FindNextFileA(r, &fd) && go);
FindClose(r);
}
else
@ -1107,7 +1108,7 @@ static int Sys_EnumerateFiles2 (const char *match, int matchstart, int neststart
memcpy(tmproot, match, neststart);
strcpy(tmproot+neststart, "*.*");
r = FindFirstFile(tmproot, &fd);
r = FindFirstFileA(tmproot, &fd);
strcpy(tmproot+neststart, "");
if (r==(HANDLE)-1)
return 1;
@ -1138,7 +1139,7 @@ static int Sys_EnumerateFiles2 (const char *match, int matchstart, int neststart
}
}
}
} while(FindNextFile(r, &fd) && go);
} while(FindNextFileA(r, &fd) && go);
FindClose(r);
}
}
@ -1458,7 +1459,6 @@ void VARGS Sys_Error (const char *error, ...)
{
va_list argptr;
char text[1024];
//, text2[1024];
// DWORD dummy;
va_start (argptr, error);
@ -1474,7 +1474,11 @@ void VARGS Sys_Error (const char *error, ...)
SV_Shutdown();
#endif
MessageBox(NULL, text, "Error", 0);
{
wchar_t wtext[1024];
widen(wtext, sizeof(wtext), text);
MessageBoxW(NULL, wtext, L"Error", 0);
}
#ifndef SERVERONLY
CloseHandle (qwclsemaphore);
@ -1991,11 +1995,11 @@ qboolean Sys_InitTerminal (void)
SetConsoleCtrlHandler (HandlerRoutine, TRUE);
SetConsoleCP(CP_UTF8);
SetConsoleOutputCP(CP_UTF8);
SetConsoleTitle (FULLENGINENAME " dedicated server");
SetConsoleTitleW (_L(FULLENGINENAME) L" dedicated server");
if (isPlugin)
{
hinput = CreateFile("CONIN$",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,0,OPEN_EXISTING,0,0);
houtput = CreateFile("CONOUT$",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,0,OPEN_EXISTING,0,0);
hinput = CreateFileA("CONIN$",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,0,OPEN_EXISTING,0,0);
houtput = CreateFileA("CONOUT$",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,0,OPEN_EXISTING,0,0);
}
else
{
@ -2415,7 +2419,7 @@ void Win7_Init(void)
HRESULT (WINAPI *pSetCurrentProcessExplicitAppUserModelID)(PCWSTR AppID);
h = LoadLibrary("shell32.dll");
h = LoadLibraryW(L"shell32.dll");
if (h)
{
pSHOpenWithDialog = (void*)GetProcAddress(h, "SHOpenWithDialog");
@ -2549,29 +2553,35 @@ int MyRegGetIntValue(HKEY base, char *keyname, char *valuename, int defaultval)
DWORD datalen = sizeof(result);
HKEY subkey;
DWORD type = REG_NONE;
if (RegOpenKeyEx(base, keyname, 0, KEY_READ, &subkey) == ERROR_SUCCESS)
wchar_t wide[MAX_PATH];
if (RegOpenKeyExW(base, widen(wide, sizeof(wide), keyname), 0, KEY_READ, &subkey) == ERROR_SUCCESS)
{
if (ERROR_SUCCESS != RegQueryValueEx(subkey, valuename, NULL, &type, (void*)&result, &datalen) || type != REG_DWORD)
if (ERROR_SUCCESS != RegQueryValueExW(subkey, widen(wide, sizeof(wide), valuename), NULL, &type, (void*)&result, &datalen) || type != REG_DWORD)
result = defaultval;
RegCloseKey (subkey);
}
return result;
}
qboolean MyRegGetStringValue(HKEY base, char *keyname, char *valuename, void *data, int datalen)
//result is utf-8
qboolean MyRegGetStringValue(HKEY base, const char *keyname, const char *valuename, void *data, size_t datalen)
{
qboolean result = false;
HKEY subkey;
DWORD type = REG_NONE;
if (RegOpenKeyEx(base, keyname, 0, KEY_READ, &subkey) == ERROR_SUCCESS)
wchar_t wide[MAX_PATH];
wchar_t wdata[MAX_PATH];
DWORD dwlen = sizeof(wdata) - sizeof(wdata[0]);
if (RegOpenKeyExW(base, widen(wide, sizeof(wide), keyname), 0, KEY_READ, &subkey) == ERROR_SUCCESS)
{
DWORD dwlen = datalen;
result = ERROR_SUCCESS == RegQueryValueEx(subkey, valuename, NULL, &type, data, &dwlen);
datalen = dwlen;
result = ERROR_SUCCESS == RegQueryValueExW(subkey, widen(wide, sizeof(wide), valuename), NULL, &type, (BYTE*)wdata, &dwlen);
RegCloseKey (subkey);
}
if (result && (type == REG_SZ || type == REG_EXPAND_SZ))
((char*)data)[datalen] = 0;
{
wdata[dwlen/sizeof(wchar_t)] = 0;
narrowen(data, datalen, wdata);
}
else
((char*)data)[0] = 0;
return result;
@ -3196,9 +3206,9 @@ static BOOL microsoft_access(LPCSTR pszFolder, DWORD dwAccessDesired)
DWORD dwNeeded;
wchar_t wpath[MAX_OSPATH];
widen(wpath, sizeof(wpath), pszFolder);
GetFileSecurity(pszFolder,si,NULL,0,&dwNeeded);
GetFileSecurityW(wpath,si,NULL,0,&dwNeeded);
psdSD = malloc(dwNeeded);
GetFileSecurity(pszFolder,si,psdSD,dwNeeded,&dwNeeded);
GetFileSecurityW(wpath,si,psdSD,dwNeeded,&dwNeeded);
ImpersonateSelf(SecurityImpersonation);
OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &hToken);
memset(&GenericMapping, 0xff, sizeof(GENERIC_MAPPING));
@ -3275,7 +3285,7 @@ static LRESULT CALLBACK stoopidstoopidstoopid(HWND w, UINT m, WPARAM wp, LPARAM
struct egadsthisisretarded
{
char title[MAX_OSPATH];
wchar_t title[MAX_OSPATH];
char subdir[MAX_OSPATH];
char parentdir[MAX_OSPATH];
char statustext[MAX_OSPATH];
@ -3294,13 +3304,13 @@ static INT CALLBACK StupidBrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LP
switch(uMsg)
{
case BFFM_INITIALIZED:
OutputDebugString("initialised\n");
OutputDebugStringA("initialised\n");
//combat windows putting new windows behind everything else if it takes a while for UAC prompts to go away
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
//combat windows bug where renaming something doesn't update the dialog's path
list = FindWindowEx(hwnd, NULL, "SHBROWSEFORFOLDER SHELLNAMESPACE CONTROL", NULL);
list = FindWindowExW(hwnd, NULL, L"SHBROWSEFORFOLDER SHELLNAMESPACE CONTROL", NULL);
if (list)
omgwtfwhyohwhy = (WNDPROC)SetWindowLongPtr(list, GWLP_WNDPROC, (LONG_PTR)stoopidstoopidstoopid);
@ -3317,7 +3327,7 @@ static INT CALLBACK StupidBrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LP
;
else
#endif
if (GetCurrentDirectory(sizeof(szDir)/sizeof(TCHAR), szDir) && microsoft_access(szDir, ACCESS_READ | ACCESS_WRITE))
if (GetCurrentDirectory(sizeof(szDir)/sizeof(TCHAR), szDir))// && microsoft_access(szDir, ACCESS_READ | ACCESS_WRITE))
;
SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)szDir);
// SendMessage(hwnd, BFFM_SETEXPANDED, TRUE, (LPARAM)szDir);
@ -3336,7 +3346,7 @@ static INT CALLBACK StupidBrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LP
case BFFM_VALIDATEFAILEDW:
return 1;//!microsoft_access("C:\\Games\\", ACCESS_READ | ACCESS_WRITE))
case BFFM_SELCHANGED:
OutputDebugString("selchanged\n");
OutputDebugStringA("selchanged\n");
if (SHGetPathFromIDList((LPITEMIDLIST)lp, pData->parentdir))
{
// OutputDebugString(va("selchanged: %s\n", szDir));
@ -3345,7 +3355,8 @@ static INT CALLBACK StupidBrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LP
//fixme: verify that id1 is a subdir perhaps?
if (edit)
{
SetWindowText(edit, fs_gamename.string);
wchar_t wide[128];
SetWindowTextW(edit, widen(wide, sizeof(wide), fs_gamename.string));
SendMessageA(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)va("%s", pData->parentdir));
}
else
@ -3365,14 +3376,25 @@ LRESULT CALLBACK NoCloseWindowProc(HWND w, UINT m, WPARAM wp, LPARAM lp)
return DefWindowProc(w, m, wp, lp);
}
void FS_Directorize(char *fname, size_t fnamesize)
{
size_t l = strlen(fname);
if (!l) //technically already a directory
return;
if (fname[l-1] == '\\' || fname[l-1] == '//')
return; //already a directory
Q_strncatz(fname, "/", fnamesize);
}
void FS_CreateBasedir(const char *path);
qboolean Sys_DoInstall(void)
{
extern ftemanifest_t *fs_manifest;
char exepath[MAX_OSPATH];
char newexepath[MAX_OSPATH];
char resultpath[MAX_PATH];
BROWSEINFO bi;
wchar_t wide[MAX_PATH];
char resultpath[MAX_OSPATH];
BROWSEINFOW bi;
LPITEMIDLIST il;
struct egadsthisisretarded diediedie;
@ -3385,9 +3407,9 @@ qboolean Sys_DoInstall(void)
memset(&bi, 0, sizeof(bi));
bi.hwndOwner = mainwindow; //note that this is usually still null
bi.pidlRoot = NULL;
GetCurrentDirectory(sizeof(resultpath)-1, resultpath);
bi.pszDisplayName = resultpath;
Q_snprintfz(diediedie.title, sizeof(diediedie.title), "Where would you like to install %s to?", fs_gamename.string);
_snwprintf(diediedie.title, countof(diediedie.title), L"Where would you like to install %s to?", widen(wide, sizeof(wide), fs_gamename.string));
GetCurrentDirectoryW(countof(wide)-1, wide);
bi.pszDisplayName = wide;
bi.lpszTitle = diediedie.title;
bi.ulFlags = BIF_RETURNONLYFSDIRS|BIF_STATUSTEXT | BIF_EDITBOX|BIF_NEWDIALOGSTYLE|BIF_VALIDATE;
bi.lpfn = StupidBrowseCallbackProc;
@ -3396,20 +3418,21 @@ qboolean Sys_DoInstall(void)
Q_strncpyz(diediedie.subdir, fs_gamename.string, sizeof(diediedie.subdir));
il = SHBrowseForFolder(&bi);
il = SHBrowseForFolderW(&bi);
if (il)
{
SHGetPathFromIDList(il, resultpath);
SHGetPathFromIDListW(il, wide);
CoTaskMemFree(il);
}
else
return true;
narrowen(resultpath, sizeof(resultpath), wide);
Q_strncatz(resultpath, "/", sizeof(resultpath));
FS_Directorize(resultpath, sizeof(resultpath));
if (*diediedie.subdir)
{
Q_strncatz(resultpath, diediedie.subdir, sizeof(resultpath));
Q_strncatz(resultpath, "/", sizeof(resultpath));
FS_Directorize(resultpath, sizeof(resultpath));
}
FS_CreateBasedir(resultpath);
@ -3836,7 +3859,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
#endif
#ifdef CATCHCRASH
LoadLibrary ("DBGHELP"); //heap corruption can prevent loadlibrary from working properly, so do this in advance.
LoadLibraryA ("DBGHELP"); //heap corruption can prevent loadlibrary from working properly, so do this in advance.
#ifdef _MSC_VER
__try
#else
@ -3966,11 +3989,11 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
HWND old;
qtvfile = parms.argv[1];
old = FindWindow("FTEGLQuake", NULL);
old = FindWindowW(L"FTEGLQuake", NULL);
if (!old)
old = FindWindow("FTED3D11QUAKE", NULL);
old = FindWindowW(L"FTED3D11QUAKE", NULL);
if (!old)
old = FindWindow("FTED3D9QUAKE", NULL);
old = FindWindowW(L"FTED3D9QUAKE", NULL);
if (old)
{
COPYDATASTRUCT cds;

View File

@ -79,8 +79,8 @@ static qboolean Headless_VID_Init (rendererstate_t *info, unsigned char *pale
//tray icon crap, so the user can still restore the game.
extern HWND mainwindow;
extern HINSTANCE global_hInstance;
WNDCLASSA wc;
NOTIFYICONDATA data;
WNDCLASSW wc;
NOTIFYICONDATAW data;
//Shell_NotifyIcon requires a window to provide events etc.
wc.style = 0;
@ -92,18 +92,18 @@ static qboolean Headless_VID_Init (rendererstate_t *info, unsigned char *pale
wc.hCursor = LoadCursor (NULL,IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = 0;
wc.lpszClassName = "FTEHeadlessClass";
RegisterClassA(&wc);
wc.lpszClassName = L"FTEHeadlessClass";
RegisterClassW(&wc);
mainwindow = CreateWindowExA(0L, wc.lpszClassName, "FTE QuakeWorld", 0, 0, 0, 0, 0, NULL, NULL, global_hInstance, NULL);
mainwindow = CreateWindowExW(0L, wc.lpszClassName, L"FTE QuakeWorld", 0, 0, 0, 0, 0, NULL, NULL, global_hInstance, NULL);
data.cbSize = sizeof(data);
data.hWnd = mainwindow;
data.uID = 0;
data.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
data.uCallbackMessage = WM_USER;
data.hIcon = wc.hIcon;
strcpy(data.szTip, "Right-click to restore");
Shell_NotifyIcon(NIM_ADD, &data);
wcscpy(data.szTip, L"Right-click to restore");
Shell_NotifyIconW(NIM_ADD, &data);
#endif
return true;
}

View File

@ -612,7 +612,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define MAX_QPATH 128 // max length of a quake game pathname
#define MAX_OSPATH 256 // max length of a filesystem pathname
#define MAX_OSPATH 1024 // max length of a filesystem pathname (260 on windows, but needs to be longer for utf8)
#define ON_EPSILON 0.1 // point on plane side epsilon

View File

@ -458,6 +458,16 @@ vfsfile_t *FS_OpenVFS(const char *filename, const char *mode, enum fs_relative r
vfsfile_t *FS_OpenTemp(void);
vfsfile_t *FS_OpenTCP(const char *name, int defaultport);
#ifdef _WIN32
//windows doesn't support utf-8. Which is a shame really, because that's the charset we expect from everything.
#define countof(array) (sizeof(array)/sizeof(array[0]))
char *narrowen(char *out, size_t outlen, wchar_t *wide);
wchar_t *widen(wchar_t *out, size_t outbytes, const char *utf8);
#define __L(x) L ## x
#define _L(x) __L(x)
qboolean MyRegGetStringValue(void *hkey_base, const char *keyname, const char *valuename, void *data, size_t datalen);
#endif
void FS_UnloadPackFiles(void);
void FS_ReloadPackFiles(void);
char *FSQ3_GenerateClientPacksList(char *buffer, int maxlen, int basechecksum);
@ -522,7 +532,12 @@ void COM_InitFilesystem (void); //does not set up any gamedirs.
qboolean FS_DownloadingPackage(void);
qboolean FS_ChangeGame(ftemanifest_t *newgame, qboolean allowreloadconfigs, qboolean allowbasedirchange);
void FS_Shutdown(void);
void COM_Gamedir (const char *dir);
struct gamepacks
{
char *path;
char *url;
};
void COM_Gamedir (const char *dir, const struct gamepacks *packagespaths);
char *FS_GetGamedir(qboolean publicpathonly);
char *FS_GetBasedir(void);
char *FS_GetManifestArgs(void);

View File

@ -179,7 +179,7 @@ int fs_hash_files;
static const char *FS_GetCleanPath(const char *pattern, char *outbuf, int outlen);
const char *FS_GetCleanPath(const char *pattern, char *outbuf, int outlen);
void FS_RegisterDefaultFileSystems(void);
static void COM_CreatePath (char *path);
ftemanifest_t *FS_ReadDefaultManifest(char *newbasedir, size_t newbasedirsize, qboolean fixedbasedir);
@ -1232,7 +1232,7 @@ void FS_ReferenceControl(unsigned int refflag, unsigned int resetflags)
}
//outbuf might not be written into
static const char *FS_GetCleanPath(const char *pattern, char *outbuf, int outlen)
const char *FS_GetCleanPath(const char *pattern, char *outbuf, int outlen)
{
const char *s;
char *o;
@ -1265,6 +1265,11 @@ static const char *FS_GetCleanPath(const char *pattern, char *outbuf, int outlen
Con_Printf("Error: absolute path in filename %s\n", pattern);
return NULL;
}
if (!*s)
{
*o++ = '\0';
break;
}
Con_Printf("Error: empty directory name (%s)\n", pattern);
s++;
continue;
@ -1958,6 +1963,105 @@ searchpathfuncs_t *FS_OpenPackByExtension(vfsfile_t *f, const char *pakname)
return NULL;
}
static void FS_AddManifestPackages(searchpath_t **oldpaths, const char *purepath, const char *logicalpaths, searchpath_t *search, const char *extension, searchpathfuncs_t *(QDECL *OpenNew)(vfsfile_t *file, const char *desc))
{
int i;
searchpathfuncs_t *handle;
unsigned int keptflags;
vfsfile_t *vfs;
flocation_t loc;
int ptlen, palen;
ptlen = strlen(purepath);
for (i = 0; i < sizeof(fs_manifest->package) / sizeof(fs_manifest->package[0]); i++)
{
char ext[8];
if (fs_manifest->package[i].path && !strcmp(COM_FileExtension(fs_manifest->package[i].path, ext, sizeof(ext)), extension))
{
palen = strlen(fs_manifest->package[i].path);
if (palen > ptlen && (fs_manifest->package[i].path[ptlen] == '/' || fs_manifest->package[i].path[ptlen] == '\\' )&& !strncmp(purepath, fs_manifest->package[i].path, ptlen))
{
searchpath_t *oldp;
char pname[MAX_OSPATH];
char lname[MAX_OSPATH];
char lname2[MAX_OSPATH];
if (fs_manifest->package[i].crcknown)
snprintf(lname, sizeof(lname), "%#x", fs_manifest->package[i].crc);
else
snprintf(lname, sizeof(lname), "");
if (!FS_GenCachedPakName(fs_manifest->package[i].path, lname, pname, sizeof(pname)))
continue;
snprintf (lname, sizeof(lname), "%s%s", logicalpaths, pname+ptlen+1);
snprintf (lname2, sizeof(lname), "%s%s", logicalpaths, fs_manifest->package[i].path+ptlen+1);
for (oldp = com_searchpaths; oldp; oldp = oldp->next)
{
if (!Q_strcasecmp(oldp->purepath, fs_manifest->package[i].path))
break;
if (!Q_strcasecmp(oldp->logicalpath, lname))
break;
if (!Q_strcasecmp(oldp->logicalpath, lname2))
break;
}
if (!oldp)
{
handle = FS_GetOldPath(oldpaths, lname2, &keptflags);
if (!handle)
handle = FS_GetOldPath(oldpaths, lname, &keptflags);
if (!handle)
{
vfs = NULL;
if (search)
{
if (search->handle->FindFile(search->handle, &loc, pname+ptlen+1, NULL))
vfs = search->handle->OpenVFS(search->handle, &loc, "r");
}
else
{
vfs = FS_OpenVFS(fs_manifest->package[i].path, "rb", FS_ROOT);
if (vfs)
snprintf (lname, sizeof(lname), "%s", lname2);
else
vfs = FS_OpenVFS(pname, "rb", FS_ROOT);
}
if (vfs)
handle = OpenNew (vfs, lname);
}
if (handle && fs_manifest->package[i].crcknown)
{
int truecrc = handle->GeneratePureCRC(handle, 0, false);
if (truecrc != fs_manifest->package[i].crc)
{
Con_Printf(CON_ERROR "File \"%s\" has hash %#x (required: %#x). Please delete it or move it away\n", lname, truecrc, fs_manifest->package[i].crc);
handle->ClosePath(handle);
handle = NULL;
}
}
if (handle)
FS_AddPathHandle(oldpaths, fs_manifest->package[i].path, lname, handle, SPF_COPYPROTECTED|SPF_UNTRUSTED|keptflags, (unsigned int)-1);
}
}
}
}
}
static void FS_AddDownloadManifestPackages(searchpath_t **oldpaths, unsigned int loadstuff)//, const char *purepath, searchpath_t *search, const char *extension, searchpathfuncs_t *(QDECL *OpenNew)(vfsfile_t *file, const char *desc))
{
int i;
char logicalroot[MAX_OSPATH];
FS_NativePath("downloads/", FS_ROOT, logicalroot, sizeof(logicalroot));
for (i = 0; i < sizeof(searchpathformats)/sizeof(searchpathformats[0]); i++)
{
if (!searchpathformats[i].extension || !searchpathformats[i].OpenNew)// || !searchpathformats[i].loadscan)
continue;
if (loadstuff & (1<<i))
{
FS_AddManifestPackages(oldpaths, "downloads", logicalroot, NULL, searchpathformats[i].extension, searchpathformats[i].OpenNew);
}
}
}
static void FS_AddDataFiles(searchpath_t **oldpaths, const char *purepath, const char *logicalpath, searchpath_t *search, const char *extension, searchpathfuncs_t *(QDECL *OpenNew)(vfsfile_t *file, const char *desc))
{
//search is the parent
@ -2006,66 +2110,7 @@ static void FS_AddDataFiles(searchpath_t **oldpaths, const char *purepath, const
wp.oldpaths = oldpaths;
search->handle->EnumerateFiles(search->handle, pakfile, FS_AddWildDataFiles, &wp);
//and load any named in the manifest (this happens when they're crced or whatever)
{
int ptlen, palen;
ptlen = strlen(purepath);
for (i = 0; i < sizeof(fs_manifest->package) / sizeof(fs_manifest->package[0]); i++)
{
char ext[8];
if (fs_manifest->package[i].path && !strcmp(COM_FileExtension(fs_manifest->package[i].path, ext, sizeof(ext)), extension))
{
palen = strlen(fs_manifest->package[i].path);
if (palen > ptlen && (fs_manifest->package[i].path[ptlen] == '/' || fs_manifest->package[i].path[ptlen] == '\\' )&& !strncmp(purepath, fs_manifest->package[i].path, ptlen))
{
searchpath_t *oldp;
char pname[MAX_OSPATH];
char lname[MAX_OSPATH];
if (fs_manifest->package[i].crcknown)
snprintf(lname, sizeof(lname), "%#x", fs_manifest->package[i].crc);
else
snprintf(lname, sizeof(lname), "");
if (!FS_GenCachedPakName(fs_manifest->package[i].path, lname, pname, sizeof(pname)))
continue;
snprintf (lname, sizeof(lname), "%s%s", logicalpaths, pname+ptlen+1);
for (oldp = com_searchpaths; oldp; oldp = oldp->next)
{
if (!Q_strcasecmp(oldp->purepath, fs_manifest->package[i].path))
break;
if (!Q_strcasecmp(oldp->logicalpath, lname))
break;
}
if (!oldp)
{
handle = FS_GetOldPath(oldpaths, lname, &keptflags);
if (!handle)
{
if (search->handle->FindFile(search->handle, &loc, pname+ptlen+1, NULL))
{
vfs = search->handle->OpenVFS(search->handle, &loc, "r");
if (vfs)
handle = OpenNew (vfs, lname);
}
}
if (handle && fs_manifest->package[i].crcknown)
{
int truecrc = handle->GeneratePureCRC(handle, 0, false);
if (truecrc != fs_manifest->package[i].crc)
{
Con_Printf(CON_ERROR "File \"%s\" has hash %#x (required: %#x). Please delete it or move it away\n", lname, truecrc, fs_manifest->package[i].crc);
handle->ClosePath(handle);
handle = NULL;
}
}
if (handle)
FS_AddPathHandle(oldpaths, fs_manifest->package[i].path, lname, handle, SPF_COPYPROTECTED|SPF_UNTRUSTED|keptflags, (unsigned int)-1);
}
}
}
}
}
FS_AddManifestPackages(oldpaths, purepath, logicalpaths, search, extension, OpenNew);
}
static searchpath_t *FS_AddPathHandle(searchpath_t **oldpaths, const char *purepath, const char *logicalpath, searchpathfuncs_t *handle, unsigned int flags, unsigned int loadstuff)
@ -2308,6 +2353,43 @@ void FS_ExtractDir(char *in, char *out, int outlen)
*out = 0;
}
qboolean FS_PathURLCache(const char *url, char *path, size_t pathsize)
{
const char *FS_GetCleanPath(const char *pattern, char *outbuf, int outlen);
char tmp[MAX_QPATH];
char *o = tmp, *e = o + sizeof(tmp)-1;
const char *i = url;
strcpy(o, "downloads/");
o += strlen(o);
while(*i)
{
if (*i == ':' || *i == '?' || *i == '*' || *i == '&')
{
if (i[0] == ':' && i[1] == '/' && i[2] == '/')
{
i+=2;
continue;
}
*o++ = '_';
i++;
continue;
}
if (*i == '\\')
{
*o++ = '/';
i++;
continue;
}
*o++ = *i++;
}
*o = 0;
if (!FS_GetCleanPath(tmp, path, pathsize))
return false;
return true;
}
/*
================
COM_Gamedir
@ -2315,7 +2397,7 @@ COM_Gamedir
Sets the gamedir and path to a different directory.
================
*/
void COM_Gamedir (const char *dir)
void COM_Gamedir (const char *dir, const struct gamepacks *packagespaths)
{
ftemanifest_t *man;
if (!fs_manifest)
@ -2323,7 +2405,7 @@ void COM_Gamedir (const char *dir)
//don't allow leading dots, hidden files are evil.
//don't allow complex paths. those are evil too.
if (!*dir || *dir == '.' || !strcmp(dir, ".") || strstr(dir, "..") || strstr(dir, "/")
if (*dir == '.' || !strcmp(dir, ".") || strstr(dir, "..") || strstr(dir, "/")
|| strstr(dir, "\\") || strstr(dir, ":") )
{
Con_Printf ("Gamedir should be a single filename, not a path\n");
@ -2333,7 +2415,7 @@ void COM_Gamedir (const char *dir)
man = NULL;
if (!man)
{
vfsfile_t *f = VFSOS_Open(va("%s%s.fmf", com_gamepath, dir), "rb");
vfsfile_t *f = *dir?VFSOS_Open(va("%s%s.fmf", com_gamepath, dir), "rb"):NULL;
if (f)
{
size_t len = VFS_GETLEN(f);
@ -2363,7 +2445,7 @@ void COM_Gamedir (const char *dir)
FS_Manifest_PurgeGamedirs(man);
if (*dir)
{
char token[MAX_QPATH];
char token[MAX_QPATH], quot[MAX_QPATH];
char *dup = Z_StrDup(dir); //FIXME: is this really needed?
dir = dup;
while ((dir = COM_ParseStringSet(dir, token, sizeof(token))))
@ -2373,11 +2455,19 @@ void COM_Gamedir (const char *dir)
if (!*token)
continue;
Cmd_TokenizeString(va("gamedir \"%s\"", token), false, false);
Cmd_TokenizeString(va("gamedir %s", COM_QuotedString(token, quot, sizeof(quot), false)), false, false);
FS_Manifest_ParseTokens(man);
}
Z_Free(dup);
}
while(packagespaths && packagespaths->path)
{
char quot[MAX_QPATH];
char quot2[MAX_OSPATH];
Cmd_TokenizeString(va("package %s - %s", COM_QuotedString(packagespaths->path, quot, sizeof(quot), false), COM_QuotedString(packagespaths->url, quot2, sizeof(quot2), false)), false, false);
FS_Manifest_ParseTokens(man);
packagespaths++;
}
}
FS_ChangeGame(man, cfg_reload_on_gamedir.ival, false);
}
@ -2482,7 +2572,15 @@ qboolean FS_GenCachedPakName(char *pname, char *crc, char *local, int llen)
return false;
}
fn = COM_SkipPath(pname);
for (fn = pname; *fn; fn++)
{
if (*fn == '\\' || *fn == '/')
{
fn++;
break;
}
}
// fn = COM_SkipPath(pname);
if (fn == pname)
{ //only allow it if it has some game path first.
*local = 0;
@ -2504,12 +2602,14 @@ qboolean FS_GenCachedPakName(char *pname, char *crc, char *local, int llen)
qboolean FS_LoadPackageFromFile(vfsfile_t *vfs, char *pname, char *localname, int *crc, unsigned int flags)
{
int i;
char *ext = COM_FileExtension(pname);
char *ext = "zip";//(pname);
searchpathfuncs_t *handle;
searchpath_t *oldlist = NULL;
searchpath_t *sp;
com_fschanged = true;
for (i = 0; i < sizeof(searchpathformats)/sizeof(searchpathformats[0]); i++)
{
if (!searchpathformats[i].extension || !searchpathformats[i].OpenNew)
@ -2536,7 +2636,7 @@ qboolean FS_LoadPackageFromFile(vfsfile_t *vfs, char *pname, char *localname, in
if (sp)
{
FS_FlushFSHashReally();
com_fschanged = true;
return true;
}
}
@ -2828,6 +2928,8 @@ void FS_ReloadPackFilesFlags(unsigned int reloadflags)
}
}
FS_AddDownloadManifestPackages(&oldpaths, reloadflags);
/*sv_pure: Reload pure paths*/
if (fs_purenames && fs_purecrcs)
{
@ -3067,11 +3169,13 @@ static qboolean Sys_SteamHasFile(char *basepath, int basepathlen, char *steamdir
DWORD resultlen;
HKEY key = NULL;
if (RegOpenKeyEx(HKEY_CURRENT_USER, "SOFTWARE\\Valve\\Steam", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
if (RegOpenKeyExW(HKEY_CURRENT_USER, L"SOFTWARE\\Valve\\Steam", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
{
resultlen = basepathlen;
RegQueryValueEx(key, "SteamPath", NULL, NULL, basepath, &resultlen);
wchar_t suckysucksuck[MAX_OSPATH];
resultlen = sizeof(suckysucksuck);
RegQueryValueExW(key, L"SteamPath", NULL, NULL, (void*)suckysucksuck, &resultlen);
RegCloseKey(key);
narrowen(basepath, basepathlen, suckysucksuck);
Q_strncatz(basepath, va("/SteamApps/common/%s", steamdir), basepathlen);
if ((f = fopen(va("%s/%s", basepath, fname), "rb")))
{
@ -3086,12 +3190,12 @@ static qboolean Sys_SteamHasFile(char *basepath, int basepathlen, char *steamdir
static INT CALLBACK StupidBrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LPARAM pData)
{ //'stolen' from microsoft's knowledge base.
//required to work around microsoft being annoying.
TCHAR szDir[MAX_PATH];
char *foo;
wchar_t szDir[MAX_PATH];
wchar_t *foo;
switch(uMsg)
{
case BFFM_INITIALIZED:
if (GetCurrentDirectory(sizeof(szDir)/sizeof(TCHAR), szDir))
if (GetCurrentDirectoryW(sizeof(szDir)/sizeof(TCHAR), szDir))
{
// foo = strrchr(szDir, '\\');
// if (foo)
@ -3099,16 +3203,23 @@ static INT CALLBACK StupidBrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LP
// foo = strrchr(szDir, '\\');
// if (foo)
// *foo = 0;
SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)szDir);
SendMessageW(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)szDir);
}
break;
case BFFM_VALIDATEFAILEDW:
break; //FIXME: validate that the gamedir contains what its meant to
case BFFM_SELCHANGED:
if (SHGetPathFromIDList((LPITEMIDLIST) lp ,szDir))
if (SHGetPathFromIDListW((LPITEMIDLIST) lp, szDir))
{
while(foo = strchr(szDir, '\\'))
wchar_t statustxt[MAX_OSPATH];
while(foo = wcschr(szDir, '\\'))
*foo = '/';
//fixme: verify that id1 is a subdir perhaps?
SendMessage(hwnd,BFFM_SETSTATUSTEXT,0,pData?(LPARAM)va("%s/%s", szDir, pData):(LPARAM)szDir);
if (pData)
_snwprintf(statustxt, countof(statustxt), L"%s/%s", szDir, pData);
else
_snwprintf(statustxt, countof(statustxt), L"%s", szDir);
statustxt[countof(statustxt)-1] = 0; //ms really suck.
SendMessageW(hwnd,BFFM_SETSTATUSTEXT,0,(LPARAM)statustxt);
}
break;
}
@ -3119,15 +3230,20 @@ static INT CALLBACK StupidBrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LP
qboolean Sys_DoDirectoryPrompt(char *basepath, size_t basepathsize, const char *poshname, const char *savedname)
{
#ifndef SERVERONLY
char resultpath[MAX_PATH];
BROWSEINFO bi;
wchar_t resultpath[MAX_OSPATH];
wchar_t title[MAX_OSPATH];
BROWSEINFOW bi;
LPITEMIDLIST il;
memset(&bi, 0, sizeof(bi));
bi.hwndOwner = mainwindow; //note that this is usually still null
bi.pidlRoot = NULL;
GetCurrentDirectory(sizeof(resultpath)-1, resultpath);
GetCurrentDirectoryW(sizeof(resultpath)-1, resultpath);
bi.pszDisplayName = resultpath;
bi.lpszTitle = va("Please locate your existing %s installation", poshname);
widen(resultpath, sizeof(resultpath), poshname);
_snwprintf(title, countof(title), L"Please locate your existing %s installation", resultpath);
bi.lpszTitle = title;
bi.ulFlags = BIF_RETURNONLYFSDIRS|BIF_STATUSTEXT;
bi.lpfn = StupidBrowseCallbackProc;
bi.lParam = 0;//(LPARAM)poshname;
@ -3136,18 +3252,17 @@ qboolean Sys_DoDirectoryPrompt(char *basepath, size_t basepathsize, const char *
//force mouse to deactivate, so that we can actually see it.
INS_UpdateGrabs(false, false);
il = SHBrowseForFolder(&bi);
il = SHBrowseForFolderW(&bi);
if (il)
{
SHGetPathFromIDList(il, resultpath);
SHGetPathFromIDListW(il, resultpath);
CoTaskMemFree(il);
Q_strncpyz(basepath, resultpath, basepathsize);
narrowen(basepath, basepathsize, resultpath);
if (savedname)
{
HKEY key = NULL;
//and save it into the windows registry
if (RegCreateKeyEx(HKEY_CURRENT_USER, "SOFTWARE\\" FULLENGINENAME "\\GamePaths",
if (RegCreateKeyExW(HKEY_CURRENT_USER, L"SOFTWARE\\" _L(FULLENGINENAME) L"\\GamePaths",
0, NULL,
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
@ -3155,7 +3270,9 @@ qboolean Sys_DoDirectoryPrompt(char *basepath, size_t basepathsize, const char *
&key,
NULL) == ERROR_SUCCESS)
{
RegSetValueEx(key, savedname, 0, REG_SZ, basepath, strlen(basepath));
wchar_t wsavedname[MAX_OSPATH];
widen(wsavedname, sizeof(wsavedname), savedname);
RegSetValueExW(key, wsavedname, 0, REG_SZ, (BYTE*)resultpath, sizeof(wchar_t)*wcslen(resultpath));
RegCloseKey(key);
}
@ -3165,29 +3282,24 @@ qboolean Sys_DoDirectoryPrompt(char *basepath, size_t basepathsize, const char *
#endif
return false;
}
DWORD GetFileAttributesU(const char * lpFileName)
{
wchar_t wide[MAX_OSPATH];
widen(wide, sizeof(wide), lpFileName);
return GetFileAttributesW(wide);
}
qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *basepath, int basepathlen, qboolean allowprompts)
{
DWORD resultlen;
HKEY key = NULL;
#ifndef INVALID_FILE_ATTRIBUTES
#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
#endif
//first, try and find it in our game paths location
if (RegOpenKeyEx(HKEY_CURRENT_USER, "SOFTWARE\\" FULLENGINENAME "\\GamePaths", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
if (MyRegGetStringValue(HKEY_CURRENT_USER, "SOFTWARE\\" FULLENGINENAME "\\GamePaths", gamename, basepath, basepathlen))
{
resultlen = basepathlen;
if (!RegQueryValueEx(key, gamename, NULL, NULL, basepath, &resultlen))
{
if (GetFileAttributes(basepath) != INVALID_FILE_ATTRIBUTES)
{
RegCloseKey(key);
return true;
}
}
RegCloseKey(key);
if (GetFileAttributesU(basepath) != INVALID_FILE_ATTRIBUTES)
return true;
}
@ -3197,8 +3309,10 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base
{
"c:/quake/", //quite a lot of people have it in c:\quake, as that's the default install location from the quake cd.
"c:/games/quake/", //personally I use this
"c:/nquake/", //nquake seems to have moved out of programfiles now. woo.
#ifdef _WIN64
//quite a few people have nquake installed. we need to an api function to read the directory for non-english-windows users.
//quite a few people have nquake installed. FIXME: we need to an api function to read the directory for non-english-windows users.
va("%s/nQuake/", getenv("%ProgramFiles(x86)%")), //64bit builds should look in both places
va("%s/nQuake/", getenv("%ProgramFiles%")), //
#else
@ -3207,7 +3321,6 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base
NULL
};
int i;
FILE *f;
//try and find it via steam
//reads HKEY_LOCAL_MACHINE\SOFTWARE\Valve\Steam\InstallPath
@ -3222,9 +3335,14 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base
{
char syspath[MAX_OSPATH];
Q_snprintfz(syspath, sizeof(syspath), "%sid1/pak0.pak", prefix[i]);
if ((f = fopen("c:/quake/quake.exe", "rb")))
if (GetFileAttributesU(syspath) != INVALID_FILE_ATTRIBUTES)
{
Q_strncpyz(basepath, prefix[i], sizeof(basepath));
return true;
}
Q_snprintfz(syspath, sizeof(syspath), "%squake.exe", prefix[i]);
if (GetFileAttributesU(syspath) != INVALID_FILE_ATTRIBUTES)
{
fclose(f);
Q_strncpyz(basepath, prefix[i], sizeof(basepath));
return true;
}
@ -3233,21 +3351,11 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base
if (!strcmp(gamename, "quake2"))
{
FILE *f;
DWORD resultlen;
HKEY key = NULL;
//look for HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\Quake2_exe\Path
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\Quake2_exe", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
if (MyRegGetStringValue(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\Quake2_exe", "Path", basepath, basepathlen))
{
resultlen = basepathlen;
RegQueryValueEx(key, "Path", NULL, NULL, basepath, &resultlen);
RegCloseKey(key);
if ((f = fopen(va("%s/quake2.exe", basepath), "rb")))
{
fclose(f);
if (GetFileAttributesU(va("%s/quake2.exe", basepath)) != INVALID_FILE_ATTRIBUTES)
return true;
}
}
if (Sys_SteamHasFile(basepath, basepathlen, "quake 2", "quake2.exe"))
@ -3256,43 +3364,22 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base
if (!strcmp(gamename, "et"))
{
FILE *f;
DWORD resultlen;
HKEY key = NULL;
//reads HKEY_LOCAL_MACHINE\SOFTWARE\Activision\Wolfenstein - Enemy Territory
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Activision\\Wolfenstein - Enemy Territory", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
if (MyRegGetStringValue(HKEY_LOCAL_MACHINE, "SOFTWARE\\Activision\\Wolfenstein - Enemy Territory", "InstallPath", basepath, basepathlen))
{
resultlen = basepathlen;
RegQueryValueEx(key, "InstallPath", NULL, NULL, basepath, &resultlen);
RegCloseKey(key);
if ((f = fopen(va("%s/ET.exe", basepath), "rb")))
{
fclose(f);
return true;
}
// if (GetFileAttributesU(va("%s/ET.exe", basepath) != INVALID_FILE_ATTRIBUTES)
// return true;
return true;
}
}
if (!strcmp(gamename, "quake3"))
{
FILE *f;
DWORD resultlen;
HKEY key = NULL;
//reads HKEY_LOCAL_MACHINE\SOFTWARE\id\Quake III Arena\InstallPath
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\id\\Quake III Arena", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
if (MyRegGetStringValue(HKEY_LOCAL_MACHINE, "SOFTWARE\\id\\Quake III Arena", "InstallPath", basepath, basepathlen))
{
resultlen = basepathlen;
RegQueryValueEx(key, "InstallPath", NULL, NULL, basepath, &resultlen);
RegCloseKey(key);
if ((f = fopen(va("%s/quake3.exe", basepath), "rb")))
{
fclose(f);
if (GetFileAttributesU(va("%s/quake3.exe", basepath)) != INVALID_FILE_ATTRIBUTES)
return true;
}
}
if (Sys_SteamHasFile(basepath, basepathlen, "quake 3 arena", "quake3.exe"))
@ -3301,31 +3388,16 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base
if (!strcmp(gamename, "wop"))
{
DWORD resultlen;
HKEY key = NULL;
//reads HKEY_LOCAL_MACHINE\SOFTWARE\World Of Padman\Path
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\World Of Padman", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
{
resultlen = basepathlen;
RegQueryValueEx(key, "Path", NULL, NULL, basepath, &resultlen);
RegCloseKey(key);
if (MyRegGetStringValue(HKEY_LOCAL_MACHINE, "SOFTWARE\\World Of Padman", "Path", basepath, basepathlen))
return true;
}
}
/*
if (!strcmp(gamename, "d3"))
{
DWORD resultlen;
HKEY key = NULL;
//reads HKEY_LOCAL_MACHINE\SOFTWARE\id\Doom 3\InstallPath
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\id\\Doom 3", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
{
resultlen = basepathlen;
RegQueryValueEx(key, "InstallPath", NULL, NULL, basepath, &resultlen);
RegCloseKey(key);
if (MyRegGetStringValue(HKEY_LOCAL_MACHINE, L"SOFTWARE\\id\\Doom 3", "InstallPath", basepath, basepathlen))
return true;
}
}
*/
@ -4668,7 +4740,7 @@ qboolean FS_FixupGamedirForExternalFile(char *input, char *filename, size_t fnam
{
Con_Printf("switching gamedir for %s\n", filename);
*sep = 0;
COM_Gamedir(filename);
COM_Gamedir(filename, NULL);
memmove(filename, sep+1, strlen(sep+1)+1);
return true;
}
@ -4767,22 +4839,28 @@ void COM_InitFilesystem (void)
#if defined(_WIN32) && !defined(WINRT)
{ //win32 sucks.
HMODULE shfolder = LoadLibrary("shfolder.dll");
DWORD winver = (DWORD)LOBYTE(LOWORD(GetVersion()));
if (shfolder)
HRESULT (WINAPI *dSHGetFolderPathW) (HWND hwndOwner, int nFolder, HANDLE hToken, DWORD dwFlags, wchar_t *pszPath) = NULL;
dllfunction_t funcs[] =
{
HRESULT (WINAPI *dSHGetFolderPath) (HWND hwndOwner, int nFolder, HANDLE hToken, DWORD dwFlags, LPTSTR pszPath);
dSHGetFolderPath = (void *)GetProcAddress(shfolder, "SHGetFolderPathA");
if (dSHGetFolderPath)
{(void**)&dSHGetFolderPathW, "SHGetFolderPathW"},
{NULL,NULL}
};
DWORD winver = (DWORD)LOBYTE(LOWORD(GetVersion()));
/*HMODULE shfolder =*/ Sys_LoadLibrary("shfolder.dll", funcs);
if (dSHGetFolderPathW)
{
wchar_t wfolder[MAX_PATH];
char folder[MAX_PATH];
// 0x5 == CSIDL_PERSONAL
if (dSHGetFolderPathW(NULL, 0x5, NULL, 0, wfolder) == S_OK)
{
char folder[MAX_PATH];
// 0x5 == CSIDL_PERSONAL
if (dSHGetFolderPath(NULL, 0x5, NULL, 0, folder) == S_OK)
Q_snprintfz(com_homepath, sizeof(com_homepath), "%s/My Games/%s/", folder, FULLENGINENAME);
narrowen(folder, sizeof(folder), wfolder);
Q_snprintfz(com_homepath, sizeof(com_homepath), "%s/My Games/%s/", folder, FULLENGINENAME);
}
// FreeLibrary(shfolder);
}
// if (shfolder)
// FreeLibrary(shfolder);
if (!*com_homepath)
{
@ -4803,13 +4881,15 @@ void COM_InitFilesystem (void)
else if (winver >= 0x5) // Windows 2000/XP/2003
{
HMODULE advapi32;
advapi32 = LoadLibrary("advapi32.dll");
BOOL (WINAPI *dCheckTokenMembership) (HANDLE TokenHandle, PSID SidToCheck, PBOOL IsMember) = NULL;
dllfunction_t funcs[] =
{
{(void**)&dCheckTokenMembership, "CheckTokenMembership"},
{NULL,NULL}
};
advapi32 = Sys_LoadLibrary("advapi32.dll", funcs);
if (advapi32)
{
BOOL (WINAPI *dCheckTokenMembership) (HANDLE TokenHandle, PSID SidToCheck, PBOOL IsMember);
dCheckTokenMembership = (void *)GetProcAddress(advapi32, "CheckTokenMembership");
if (dCheckTokenMembership)
{
// on XP systems, only use a home directory by default if we're a limited user or if we're on a network
@ -4843,7 +4923,7 @@ void COM_InitFilesystem (void)
FreeSid(adminSID);
}
FreeLibrary(advapi32);
Sys_CloseLibrary(advapi32);
}
}
#endif

View File

@ -28,7 +28,7 @@ static struct
BOOL (WINAPI *pCertGetCertificateChain) (HCERTCHAINENGINE,PCCERT_CONTEXT,LPFILETIME,HCERTSTORE,PCERT_CHAIN_PARA,DWORD,LPVOID,PCCERT_CHAIN_CONTEXT*);
BOOL (WINAPI *pCertVerifyCertificateChainPolicy) (LPCSTR,PCCERT_CHAIN_CONTEXT,PCERT_CHAIN_POLICY_PARA,PCERT_CHAIN_POLICY_STATUS);
void (WINAPI *pCertFreeCertificateChain) (PCCERT_CHAIN_CONTEXT);
DWORD (WINAPI *pCertNameToStrA) (DWORD dwCertEncodingType, PCERT_NAME_BLOB pName, DWORD dwStrType, LPTSTR psz, DWORD csz);
DWORD (WINAPI *pCertNameToStrA) (DWORD dwCertEncodingType, PCERT_NAME_BLOB pName, DWORD dwStrType, LPCSTR psz, DWORD csz);
PCCERT_CONTEXT (WINAPI *pCertCreateSelfSignCertificate) (HCRYPTPROV,PCERT_NAME_BLOB,DWORD,PCRYPT_KEY_PROV_INFO,PCRYPT_ALGORITHM_IDENTIFIER,PSYSTEMTIME,PSYSTEMTIME,PCERT_EXTENSIONS);
BOOL (WINAPI *pCertStrToNameA) (DWORD,LPCSTR,DWORD,void *,BYTE *,DWORD *,LPCSTR *);
@ -112,15 +112,6 @@ typedef struct {
char headerdata[1024], footerdata[1024];
} sslfile_t;
static int SSPI_CopyIntoBuffer(struct sslbuf *buf, const void *data, unsigned int bytes)
{
if (bytes > buf->datasize - buf->avail)
bytes = buf->datasize - buf->avail;
memcpy(buf->data + buf->avail, data, bytes);
buf->avail += bytes;
return bytes;
}
static int SSPI_ExpandBuffer(struct sslbuf *buf, size_t bytes)
{
if (bytes < buf->datasize)
@ -129,6 +120,19 @@ static int SSPI_ExpandBuffer(struct sslbuf *buf, size_t bytes)
return bytes;
}
static int SSPI_CopyIntoBuffer(struct sslbuf *buf, const void *data, unsigned int bytes, qboolean expand)
{
if (bytes > buf->datasize - buf->avail)
{
if (!expand || SSPI_ExpandBuffer(buf, buf->avail + bytes + 1024) < buf->avail + bytes)
bytes = buf->datasize - buf->avail;
}
memcpy(buf->data + buf->avail, data, bytes);
buf->avail += bytes;
return bytes;
}
static void SSPI_Error(sslfile_t *f, char *error)
{
f->handshaking = HS_ERROR;
@ -177,7 +181,6 @@ static void SSPI_Decode(sslfile_t *f)
SecBufferDesc BuffDesc;
SecBuffer SecBuff[4];
ULONG ulQop = 0;
SecBuffer *data = NULL;
SecBuffer *extra = NULL;
int i;
@ -216,16 +219,28 @@ static void SSPI_Decode(sslfile_t *f)
for (i = 0; i < BuffDesc.cBuffers; i++)
{
if (SecBuff[i].BufferType == SECBUFFER_DATA && !data)
data = &SecBuff[i];
if (SecBuff[i].BufferType == SECBUFFER_EXTRA && !extra)
switch(SecBuff[i].BufferType)
{
case SECBUFFER_DATA:
if (SSPI_CopyIntoBuffer(&f->inraw, SecBuff[i].pvBuffer, SecBuff[i].cbBuffer, true) != SecBuff[i].cbBuffer)
SSPI_Error(f, "outraw buffer overflowed\n");
break;
case SECBUFFER_EXTRA:
if (extra)
SSPI_Error(f, "multiple extra buffers\n");
extra = &SecBuff[i];
break;
case SECBUFFER_EMPTY:
case SECBUFFER_MISSING:
case SECBUFFER_STREAM_TRAILER:
case SECBUFFER_STREAM_HEADER:
break;
default:
SSPI_Error(f, "got unexpected buffer type\n");
break;
}
}
//copy the data out to the result, yay.
if (data)
SSPI_CopyIntoBuffer(&f->inraw, data->pvBuffer, data->cbBuffer);
//retain the extra. if there's no extra then mark it so.
if (extra)
{
@ -288,17 +303,17 @@ static void SSPI_Encode(sslfile_t *f)
f->outraw.avail = 0;
//fixme: these should be made non-fatal.
if (SSPI_CopyIntoBuffer(&f->outcrypt, SecBuff[0].pvBuffer, SecBuff[0].cbBuffer) < SecBuff[0].cbBuffer)
if (SSPI_CopyIntoBuffer(&f->outcrypt, SecBuff[0].pvBuffer, SecBuff[0].cbBuffer, true) < SecBuff[0].cbBuffer)
{
SSPI_Error(f, "crypt buffer overflowed\n");
return;
}
if (SSPI_CopyIntoBuffer(&f->outcrypt, SecBuff[1].pvBuffer, SecBuff[1].cbBuffer) < SecBuff[1].cbBuffer)
if (SSPI_CopyIntoBuffer(&f->outcrypt, SecBuff[1].pvBuffer, SecBuff[1].cbBuffer, true) < SecBuff[1].cbBuffer)
{
SSPI_Error(f, "crypt buffer overflowed\n");
return;
}
if (SSPI_CopyIntoBuffer(&f->outcrypt, SecBuff[2].pvBuffer, SecBuff[2].cbBuffer) < SecBuff[2].cbBuffer)
if (SSPI_CopyIntoBuffer(&f->outcrypt, SecBuff[2].pvBuffer, SecBuff[2].cbBuffer, true) < SecBuff[2].cbBuffer)
{
SSPI_Error(f, "crypt buffer overflowed\n");
return;
@ -686,7 +701,7 @@ static void SSPI_Handshake (sslfile_t *f)
}
}
if (SSPI_CopyIntoBuffer(&f->outcrypt, OutSecBuff.pvBuffer, OutSecBuff.cbBuffer) < OutSecBuff.cbBuffer)
if (SSPI_CopyIntoBuffer(&f->outcrypt, OutSecBuff.pvBuffer, OutSecBuff.cbBuffer, true) < OutSecBuff.cbBuffer)
{
SSPI_Error(f, "crypt overflow\n");
return;
@ -765,7 +780,12 @@ static int QDECL SSPI_WriteBytes (struct vfsfile_s *file, const void *buffer, in
{
sslfile_t *f = (sslfile_t *)file;
bytestowrite = SSPI_CopyIntoBuffer(&f->outraw, buffer, bytestowrite);
//don't endlessly accept data faster than we can push it out.
//we'll buffer a little, but don't go overboard
if (f->outcrypt.avail > 8192)
return false;
bytestowrite = SSPI_CopyIntoBuffer(&f->outraw, buffer, bytestowrite, false);
if (f->handshaking)
{

View File

@ -5556,21 +5556,13 @@ void NET_Init (void)
#if defined(_WIN32) && defined(HAVE_PACKET)
int r;
#ifdef IPPROTO_IPV6
HMODULE ws2_32dll;
ws2_32dll = LoadLibrary("ws2_32.dll");
if (ws2_32dll)
dllfunction_t fncs[] =
{
pfreeaddrinfo = (void *)GetProcAddress(ws2_32dll, "freeaddrinfo");
pgetaddrinfo = (void *)GetProcAddress(ws2_32dll, "getaddrinfo");
if (!pgetaddrinfo || !pfreeaddrinfo)
{
pgetaddrinfo = NULL;
pfreeaddrinfo = NULL;
FreeLibrary(ws2_32dll);
}
}
else
pgetaddrinfo = NULL;
{(void**)&pfreeaddrinfo, "getaddrinfo"},
{(void**)&pgetaddrinfo, "freeaddrinfo"},
{NULL, NULL}
};
Sys_LoadLibrary("ws2_32.dll", fncs);
#endif
r = WSAStartup (MAKEWORD(2, 2), &winsockdata);

View File

@ -236,7 +236,7 @@ qboolean QCExternalDebuggerCommand(char *text)
if (sv.state)
Cbuf_AddText("restart\n", RESTRICT_LOCAL);
#endif
Host_EndGame("Reloading QC");
// Host_EndGame("Reloading QC");
}
else if (!strncmp(text, "qcbreakpoint ", 13))
{

View File

@ -1,12 +1,5 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "FTEQuake", "..\setup\setup.vdproj", "{E0EE8B50-3A75-42A9-B80A-787675979B0C}"
ProjectSection(ProjectDependencies) = postProject
{72269FEE-293D-40BC-A7AE-E429F4496869} = {72269FEE-293D-40BC-A7AE-E429F4496869}
{9767E236-8454-44E9-8999-CD5BDAFBE9BA} = {9767E236-8454-44E9-8999-CD5BDAFBE9BA}
{82285268-9C3B-44AD-BBE7-40670F9D2628} = {82285268-9C3B-44AD-BBE7-40670F9D2628}
EndProjectSection
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}"
@ -86,33 +79,6 @@ Global
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.D3DDebug|Win32.ActiveCfg = Release
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.D3DDebug|x64.ActiveCfg = Release
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.D3DRelease|Win32.ActiveCfg = Release
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.D3DRelease|x64.ActiveCfg = Release
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.D3DRelease|x64.Build.0 = Release
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.Debug Dedicated Server|Win32.ActiveCfg = Debug
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.Debug Dedicated Server|x64.ActiveCfg = Debug
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.Debug|Win32.ActiveCfg = Debug
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.Debug|x64.ActiveCfg = Release
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.Debug|x64.Build.0 = Release
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.GLDebug|Win32.ActiveCfg = Debug
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.GLDebug|x64.ActiveCfg = Debug
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.GLRelease|Win32.ActiveCfg = Release
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.GLRelease|x64.ActiveCfg = Release
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.MDebug|Win32.ActiveCfg = Debug
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.MDebug|x64.ActiveCfg = Release
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.MDebug|x64.Build.0 = Release
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.MinGLDebug|Win32.ActiveCfg = Debug
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.MinGLDebug|x64.ActiveCfg = Debug
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.MinGLRelease|Win32.ActiveCfg = Release
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.MinGLRelease|x64.ActiveCfg = Debug
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.MRelease|Win32.ActiveCfg = Release
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.MRelease|x64.ActiveCfg = Debug
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.Release Dedicated Server|Win32.ActiveCfg = Release
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.Release Dedicated Server|x64.ActiveCfg = Release
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.Release|Win32.ActiveCfg = Release
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.Release|x64.ActiveCfg = Release
{0018E098-B12A-4E4D-9B22-6772DA287080}.D3DDebug|Win32.ActiveCfg = Release|Win32
{0018E098-B12A-4E4D-9B22-6772DA287080}.D3DDebug|Win32.Build.0 = Release|Win32
{0018E098-B12A-4E4D-9B22-6772DA287080}.D3DDebug|x64.ActiveCfg = Release|Win32

View File

@ -1647,34 +1647,44 @@ void Mod_LoadLighting (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean
#ifndef SERVERONLY
if (!litdata && r_loadlits.value)
{
char *litname;
char litnamemaps[MAX_QPATH];
char litnamelits[MAX_QPATH];
int depthmaps;
int depthlits;
char *litnames[] = {
"maps/%s.lit2",
"maps/%s.lit",
"lits/%s.lit2",
"lits/%s.lit"
};
char litbase[MAX_QPATH];
int depth;
int bestdepth = 0x7fffffff;
int best = -1;
int i;
char litname[MAX_QPATH];
size_t litsize;
qboolean inhibitvalidation = false;
{
Q_strncpyz(litnamemaps, loadmodel->name, sizeof(litnamelits));
COM_StripExtension(loadmodel->name, litnamemaps, sizeof(litnamemaps));
COM_DefaultExtension(litnamemaps, ".lit", sizeof(litnamemaps));
depthmaps = COM_FDepthFile(litnamemaps, false);
}
COM_StripExtension(loadmodel->name, litbase, sizeof(litbase));
for (i = 0; i < sizeof(litnames)/sizeof(litnames[0]); i++)
{
Q_strncpyz(litnamelits, "lits/", sizeof(litnamelits));
COM_StripExtension(COM_SkipPath(loadmodel->name), litnamelits+5, sizeof(litnamelits) - 5);
Q_strncatz(litnamelits, ".lit", sizeof(litnamelits));
depthlits = COM_FDepthFile(litnamelits, false);
Q_snprintfz(litname, sizeof(litname), litnames[i], litbase);
depth = COM_FDepthFile(litname, false);
if (depth < bestdepth)
{
bestdepth = depth;
best = i;
}
}
if (best >= 0)
{
Q_snprintfz(litname, sizeof(litname), litnames[best], litbase);
litdata = FS_LoadMallocGroupFile(&loadmodel->memgroup, litname, &litsize);
}
else
{
litdata = NULL;
litsize = 0;
}
if (depthmaps <= depthlits)
litname = litnamemaps; //maps has priority over lits
else
litname = litnamelits;
litdata = FS_LoadMallocGroupFile(&loadmodel->memgroup, litname, &litsize);
if (litdata)
if (litdata && litsize >= 8)
{ //validate it, if we loaded one.
if (litdata[0] != 'Q' || litdata[1] != 'L' || litdata[2] != 'I' || litdata[3] != 'T')
{
@ -2531,7 +2541,7 @@ void ModQ1_Batches_BuildQ1Q2Poly(model_t *mod, msurface_t *surf, builddata_t *co
float *vec;
float s, t, d;
int sty;
int w,h;
// int w,h;
//output the mesh's indicies
for (i=0 ; i<mesh->numvertexes-2 ; i++)

View File

@ -38,30 +38,43 @@ static void R_LineGraph (int x, int h)
{
int i;
int s;
int color;
int color, color2 = 0xff;
s = NET_GRAPHHEIGHT;
if (h == 10000)
color = 0x6f; // yellow
if (h == 10000 || h<0)
{
color = 0; // yellow
color2 = 1;
h=abs(h);
}
else if (h == 9999)
color = 0x4f; // red
{
color = 2; // red
color2 = 3;
}
else if (h == 9998)
color = 0xd0; // blue
{
color = 4; // blue
color2 = 5;
}
else
color = 0xfe; // white
{
color = 6; // white
color2 = 7;
}
if (h>s)
h = s;
for (i=0 ; i<h ; i++)
if (i & 1)
ngraph_texels[NET_GRAPHHEIGHT - i - 1][x] = 0xff;
ngraph_texels[NET_GRAPHHEIGHT - i - 1][x] = (qbyte)color2;
else
ngraph_texels[NET_GRAPHHEIGHT - i - 1][x] = (qbyte)color;
for ( ; i<s ; i++)
ngraph_texels[NET_GRAPHHEIGHT - i - 1][x] = (qbyte)0xff;
ngraph_texels[NET_GRAPHHEIGHT - i - 1][x] = (qbyte)8;
}
/*
@ -94,6 +107,19 @@ static void Draw_CharToNetGraph (int x, int y, int num)
R_NetGraph
==============
*/
//instead of assuming the quake palette, we should use a predictable lookup table. it makes the docs much easier.
static unsigned ngraph_palette[] =
{
0xff00ffff, //yellow
0xff00efef, //yellow2
0xff0000ff, //red
0xff0000ef, //red2
0xffff0000, //blue
0xffef0000, //blue2
0xffffffff, //white
0xffefefef, //white2
0x00000000 //invisible.
};
void R_NetGraph (void)
{
int a, x, i, y;
@ -116,18 +142,23 @@ void R_NetGraph (void)
}
else
{
int last = 10000;
lost = CL_CalcNet(r_netgraph.value);
for (a=0 ; a<NET_TIMINGS ; a++)
{
i = (cl.movesequence-a) & NET_TIMINGSMASK;
R_LineGraph (NET_TIMINGS-1-a, packet_latency[i]);
if (packet_latency[i] != 10000)
last = packet_latency[i];
else if (last >= 0)
last = -last;
R_LineGraph (NET_TIMINGS-1-a, last);
}
}
// now load the netgraph texture into gl and draw it
for (y = 0; y < NET_GRAPHHEIGHT; y++)
for (x = 0; x < NET_TIMINGS; x++)
ngraph_pixels[y][x] = d_8to24rgbtable[ngraph_texels[y][x]];
ngraph_pixels[y][x] = ngraph_palette[ngraph_texels[y][x]];
x = ((vid.width - 320)>>1);
x=-x;

View File

@ -1354,12 +1354,10 @@ static void R_RenderMotionBlur(void)
"}\n"
"}\n"
);
// GLBE_RenderToTexture(sceneblur_texture, r_nulltex, r_nulltex, r_nulltex, false);
Con_Printf("FIXME: tex_sourcecolour = sceneblur_texture\n");
GLBE_FBO_Sources(sceneblur_texture, r_nulltex);
R2D_ImageColours(1, 1, 1, gl_motionblur.value);
R2D_Image(0, 0, vid.width, vid.height, cs-vs, ct+vt, cs+vs, ct-vt, shader);
Con_Printf("FIXME: tex_sourcecolour = reset\n");
// GLBE_RenderToTexture(r_nulltex, r_nulltex, r_nulltex, r_nulltex, false);
GLBE_RenderToTextureUpdate2d(false);
//grab the current image so we can feed that back into the next frame.
GL_MTBind(0, GL_TEXTURE_2D, sceneblur_texture);
@ -1786,8 +1784,8 @@ void GLR_RenderView (void)
GLBE_FBO_Sources(r_nulltex, r_nulltex);
// if (gl_motionblur.value>0 && gl_motionblur.value < 1 && qglCopyTexImage2D)
// R_RenderMotionBlur();
if (gl_motionblur.value>0 && gl_motionblur.value < 1 && qglCopyTexImage2D)
R_RenderMotionBlur();
checkglerror();
}

View File

@ -1387,7 +1387,7 @@ static const char *glsl_hdrs[] =
#endif
"}\n"
"#else\n"
"#define skeletaltransform() ftetransform()\n"
"#define skeletaltransform ftetransform\n"
"vec4 skeletaltransform_wnst(out vec3 w, out vec3 n, out vec3 t, out vec3 b)"
"{"
"n = v_normal;"
@ -1820,8 +1820,12 @@ static GLhandleARB GLSlang_CreateShader (const char *name, int ver, const char *
"#define v_position v_position1\n"
"#endif\n"
"uniform mat4 m_modelviewprojection;\n"
// "#define ftetransform() (m_modelviewprojection * vec4(v_position, 1.0))\n"
#if 1//def FTE_TARGET_WEB
//IE is buggy
"vec4 ftetransform() { return m_modelviewprojection * vec4(v_position, 1.0); }\n"
#else
"#define ftetransform() (m_modelviewprojection * vec4(v_position, 1.0))\n"
#endif
;
length[strings] = strlen(prstrings[strings]);
strings++;

View File

@ -79,7 +79,7 @@ typedef BOOL (WINAPI *lpfnSetLayeredWindowAttributes)(HWND hwnd, COLORREF crKey,
extern cvar_t vid_conwidth, vid_conautoscale;
#define WINDOW_CLASS_NAME "FTEGLQuake"
#define WINDOW_CLASS_NAME L"FTEGLQuake"
#define MAX_MODE_LIST 128
#define VID_ROW_SIZE 3
@ -187,8 +187,8 @@ extern cvar_t vid_gl_context_selfreset;
int window_center_x, window_center_y, window_x, window_y, window_width, window_height;
RECT window_rect;
HMODULE hInstGL = NULL;
HMODULE hInstwgl = NULL;
dllhandle_t *hInstGL = NULL;
dllhandle_t *hInstwgl = NULL;
static qboolean usingminidriver;
static char reqminidriver[MAX_OSPATH];
static char opengldllname[MAX_OSPATH];
@ -387,7 +387,7 @@ void *getwglfunc(char *name)
if (!hInstwgl)
{
TRACE(("dbg: getwglfunc: explicitly loading opengl32.dll\n", name));
hInstwgl = LoadLibrary("opengl32.dll");
hInstwgl = LoadLibraryA("opengl32.dll");
}
TRACE(("dbg: getwglfunc: %s: wglgetting\n", name));
proc = GetProcAddress(hInstwgl, name);
@ -459,10 +459,10 @@ qboolean GLInitialise (char *renderer)
{
usingminidriver = false;
if (hInstGL)
FreeLibrary(hInstGL);
Sys_CloseLibrary(hInstGL);
hInstGL=NULL;
if (hInstwgl)
FreeLibrary(hInstwgl);
Sys_CloseLibrary(hInstwgl);
hInstwgl=NULL;
Q_strncpyz(reqminidriver, renderer, sizeof(reqminidriver));
@ -471,8 +471,7 @@ qboolean GLInitialise (char *renderer)
if (*renderer && stricmp(renderer, "opengl32.dll") && stricmp(renderer, "opengl32"))
{
Con_DPrintf ("Loading renderer dll \"%s\"", renderer);
hInstGL = LoadLibrary(opengldllname);
hInstGL = Sys_LoadLibrary(opengldllname, NULL);
if (hInstGL)
{
usingminidriver = true;
@ -490,7 +489,7 @@ qboolean GLInitialise (char *renderer)
strcpy(opengldllname, "opengl32");
Con_DPrintf ("Loading renderer dll \"%s\"", opengldllname);
emode = SetErrorMode(SEM_FAILCRITICALERRORS); /*no annoying errors if they use glide*/
hInstGL = LoadLibrary(opengldllname);
hInstGL = Sys_LoadLibrary(opengldllname, NULL);
SetErrorMode(emode);
if (hInstGL)
@ -766,10 +765,10 @@ qboolean VID_SetWindowedMode (rendererstate_t *info)
WindowRect = centerrect(pleft, ptop, pwidth, pheight, wwidth, wheight);
// Create the DIB window
dibwindow = CreateWindowEx (
dibwindow = CreateWindowExW (
ExWindowStyle,
WINDOW_CLASS_NAME,
FULLENGINENAME,
_L(FULLENGINENAME),
WindowStyle,
WindowRect.left, WindowRect.top,
WindowRect.right - WindowRect.left,
@ -797,7 +796,7 @@ qboolean VID_SetWindowedMode (rendererstate_t *info)
av = 70;
if (av < 255)
{
HMODULE hm = GetModuleHandle("user32.dll");
HMODULE hm = GetModuleHandleA("user32.dll");
lpfnSetLayeredWindowAttributes pSetLayeredWindowAttributes;
pSetLayeredWindowAttributes = (void*)GetProcAddress(hm, "SetLayeredWindowAttributes");
@ -864,7 +863,9 @@ qboolean VID_SetWindowedMode (rendererstate_t *info)
void GLVID_SetCaption(char *text)
{
SetWindowText(mainwindow, text);
wchar_t wide[2048];
widen(wide, sizeof(wide), text);
SetWindowTextW(mainwindow, wide);
}
@ -926,10 +927,10 @@ qboolean VID_SetFullDIBMode (rendererstate_t *info)
wheight = rect.bottom - rect.top;
// Create the DIB window
dibwindow = CreateWindowEx (
dibwindow = CreateWindowExW (
ExWindowStyle,
WINDOW_CLASS_NAME,
FULLENGINENAME,
_L(FULLENGINENAME),
WindowStyle,
rect.left, rect.top,
wwidth,
@ -1001,6 +1002,21 @@ static void Win_Touch_Init(HWND wnd);
static qboolean CreateMainWindow(rendererstate_t *info)
{
qboolean stat;
WNDCLASSW wc;
/* Register the frame class */
wc.style = CS_OWNDC;
wc.lpfnWndProc = (WNDPROC)GLMainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = global_hInstance;
wc.hIcon = hIcon;
wc.hCursor = hArrowCursor;
wc.hbrBackground = NULL;
wc.lpszMenuName = 0;
wc.lpszClassName = WINDOW_CLASS_NAME;
if (!RegisterClassW (&wc)) //this isn't really fatal, we'll let the CreateWindow fail instead.
Con_Printf("RegisterClass failed\n");
if (!info->fullscreen)
{
TRACE(("dbg: GLVID_SetMode: VID_SetWindowedMode\n"));
@ -1032,10 +1048,10 @@ int GLVID_WindowThread(void *cond)
wnd = mainwindow;
Sys_ConditionSignal(cond);
while (GetMessage(&msg, NULL, 0, 0))
while (GetMessageW(&msg, NULL, 0, 0))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
TranslateMessageW (&msg);
DispatchMessageW (&msg);
//ShowCursor is thread-local.
if (cursor != mouseshowtoggle)
@ -1347,13 +1363,15 @@ qboolean VID_AttachGL (rendererstate_t *info)
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.
{
wchar_t systemglw[MAX_OSPATH+1];
char systemgl[MAX_OSPATH+1];
GetSystemDirectory(systemgl, sizeof(systemgl)-1);
strncat(systemgl, "\\", sizeof(systemgl)-1);
GetSystemDirectoryW(systemglw, countof(systemglw)-1);
narrowen(systemgl, sizeof(systemgl), systemglw);
Q_strncatz(systemgl, "\\", sizeof(systemgl));
if (*info->subrenderer)
strncat(systemgl, info->subrenderer, sizeof(systemgl)-1);
Q_strncatz(systemgl, info->subrenderer, sizeof(systemgl));
else
strncat(systemgl, "opengl32.dll", sizeof(systemgl)-1);
Q_strncatz(systemgl, "opengl32.dll", sizeof(systemgl));
TRACE(("dbg: VID_AttachGL: GLInitialise (system dir specific)\n"));
if (GLInitialise(systemgl))
{
@ -1616,7 +1634,7 @@ static void QDECL VID_WndAlpha_Override_Callback(struct cvar_s *var, char *oldva
if (modestate==MS_WINDOWED)
{
int av;
HMODULE hm = GetModuleHandle("user32.dll");
HMODULE hm = GetModuleHandleA("user32.dll");
lpfnSetLayeredWindowAttributes pSetLayeredWindowAttributes;
pSetLayeredWindowAttributes = (void*)GetProcAddress(hm, "SetLayeredWindowAttributes");
@ -2106,7 +2124,7 @@ static BOOL (WINAPI *pCloseTouchInputHandle)(HTOUCHINPUT hTouchInput);
static void Win_Touch_Init(HWND wnd)
{
HMODULE lib;
lib = LoadLibrary("user32.dll");
lib = LoadLibraryA("user32.dll");
pRegisterTouchWindow = (void*)GetProcAddress(lib, "RegisterTouchWindow");
pGetTouchInputInfo = (void*)GetProcAddress(lib, "GetTouchInputInfo");
pCloseTouchInputHandle = (void*)GetProcAddress(lib, "CloseTouchInputHandle");
@ -2387,7 +2405,7 @@ LONG WINAPI GLMainWndProc (
case WM_CLOSE:
if (!vid_initializing)
if (MessageBox (hWnd, "Are you sure you want to quit?", "Confirm Exit",
if (MessageBoxW (hWnd, L"Are you sure you want to quit?", L"Confirm Exit",
MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES)
{
Cbuf_AddText("\nquit\n", RESTRICT_LOCAL);
@ -2433,7 +2451,7 @@ LONG WINAPI GLMainWndProc (
lRet = TRUE;
break;
default:
lRet = DefWindowProc (hWnd, uMsg, wParam, lParam);
lRet = DefWindowProcW (hWnd, uMsg, wParam, lParam);
break;
}
break;
@ -2446,7 +2464,7 @@ LONG WINAPI GLMainWndProc (
default:
/* pass all unhandled messages to DefWindowProc */
lRet = DefWindowProc (hWnd, uMsg, wParam, lParam);
lRet = DefWindowProcW (hWnd, uMsg, wParam, lParam);
break;
}
@ -2503,7 +2521,7 @@ void GLVID_DeInit (void)
Cvar_Unhook(&vid_wndalpha);
Cmd_RemoveCommand("vid_recenter");
UnregisterClass(WINDOW_CLASS_NAME, global_hInstance);
UnregisterClassW(WINDOW_CLASS_NAME, global_hInstance);
}
/*
@ -2516,7 +2534,6 @@ qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette)
extern int isPlugin;
// qbyte *ptmp;
DEVMODE devmode;
WNDCLASS wc;
memset(&devmode, 0, sizeof(devmode));
@ -2527,21 +2544,6 @@ qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette)
rf->VID_DestroyCursor = WIN_DestroyCursor;
rf->VID_SetCursor = WIN_SetCursor;
/* Register the frame class */
wc.style = CS_OWNDC;
wc.lpfnWndProc = (WNDPROC)GLMainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = global_hInstance;
wc.hIcon = hIcon;
wc.hCursor = hArrowCursor;
wc.hbrBackground = NULL;
wc.lpszMenuName = 0;
wc.lpszClassName = WINDOW_CLASS_NAME;
if (!RegisterClass (&wc)) //this isn't really fatal, we'll let the CreateWindow fail instead.
MessageBox(NULL, "RegisterClass failed", "GAH", 0);
vid_initialized = false;
vid_initializing = true;

View File

@ -542,7 +542,15 @@ static qboolean HTTP_DL_Work(struct dl_download *dl)
}
if (dl->notifystarted)
dl->notifystarted(dl, *mimetype?mimetype:NULL);
{
if (!dl->notifystarted(dl, *mimetype?mimetype:NULL))
{
dl->notifycomplete = NULL;
dl->status = DL_FAILED;
return false;
}
}
if (!dl->file)
{
@ -853,7 +861,7 @@ void HTTPDL_Establish(struct dl_download *dl)
Q_snprintfz(con->buffer, con->bufferlen,
"GET %s HTTP/1.1\r\n"
"Host: %s\r\n"
"Connection: close\r\n"
"Connection: close\r\n" //theoretically, this is not needed. but as our code will basically do it anyway, it might as well be here FIXME: implement connection reuse.
#if !defined(NPFTE) && defined(AVAIL_ZLIB)
"Accept-Encoding: gzip\r\n"
#endif

View File

@ -142,7 +142,7 @@ struct dl_download
/*not used internally by the backend, but used by HTTP_CL_Get/thread wrapper*/
struct dl_download *next;
void (*notifystarted) (struct dl_download *dl, char *mimetype); //mime can be null for some protocols, read dl->totalsize for size.
qboolean (*notifystarted) (struct dl_download *dl, char *mimetype); //mime can be null for some protocols, read dl->totalsize for size. false if the mime just isn't acceptable.
void (*notifycomplete) (struct dl_download *dl);
};

View File

@ -3385,7 +3385,7 @@ retry:
d16 = ED_FindGlobal16(progfuncs, s);
if (!d16)
{
printf("Progs requires \"%s\" the external function \"%s\", but the definition was stripped\n", filename, s);
printf("\"%s\" requires the external function \"%s\", but the definition was stripped\n", filename, s);
PRHunkFree(progfuncs, hmark);
pr_progs=NULL;
return false;

View File

@ -9917,7 +9917,8 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"uri_escape", PF_uri_escape, 0, 0, 0, 510, "string(string in)"},//DP_QC_URI_ESCAPE
{"uri_unescape", PF_uri_unescape, 0, 0, 0, 511, "string(string in)"},//DP_QC_URI_ESCAPE
{"num_for_edict", PF_num_for_edict, 0, 0, 0, 512, "float(entity ent)"},//DP_QC_NUM_FOR_EDICT
{"uri_get", PF_uri_get, 0, 0, 0, 513, D("float(string uril, float id, optional string postmimetype, optional string postdata)", "uri_get() gets content from an URL and calls a callback \"uri_get_callback\" with it set as string; an unique ID of the transfer is returned\nreturns 1 on success, and then calls the callback with the ID, 0 or the HTTP status code, and the received data in a string")},//DP_QC_URI_GET
{"uri_get", PF_uri_get, 0, 0, 0, 513, D("#define uri_post uri_get\nfloat(string uril, float id, optional string postmimetype, optional string postdata)", "uri_get() gets content from an URL and calls a callback \"uri_get_callback\" with it set as string; an unique ID of the transfer is returned\nreturns 1 on success, and then calls the callback with the ID, 0 or the HTTP status code, and the received data in a string")},//DP_QC_URI_GET
{"uri_post", PF_uri_get, 0, 0, 0, 513, D("float(string uril, float id, optional string postmimetype, optional string postdata)", "uri_get() gets content from an URL and calls a callback \"uri_get_callback\" with it set as string; an unique ID of the transfer is returned\nreturns 1 on success, and then calls the callback with the ID, 0 or the HTTP status code, and the received data in a string"), true},//DP_QC_URI_POST
{"tokenize_console",PF_tokenize_console,0, 0, 0, 514, D("float(string str)", "Tokenize a string exactly as the console's tokenizer would do so. The regular tokenize builtin became bastardized for convienient string parsing, which resulted in a large disparity that can be exploited to bypass checks implemented in a naive SV_ParseClientCommand function, therefore you can use this builtin to make sure it exactly matches.")},
{"argv_start_index",PF_argv_start_index,0, 0, 0, 515, D("float(float idx)", "Returns the character index that the tokenized arg started at.")},
{"argv_end_index", PF_argv_end_index, 0, 0, 0, 516, D("float(float idx)", "Returns the character index that the tokenized arg stopped at.")},

View File

@ -2315,7 +2315,7 @@ static void SV_Gamedir_f (void)
}
dir = Z_StrDup(dir);
COM_Gamedir (dir);
COM_Gamedir (dir, NULL);
Info_SetValueForStarKey (svs.info, "*gamedir", dir, MAX_SERVERINFO_STRING);
Z_Free(dir);
}

View File

@ -3099,8 +3099,8 @@ void SV_Snapshot_BuildStateQ1(entity_state_t *state, edict_t *ent, client_t *cli
}
}
else if (progstype == PROG_UNKNOWN)
{
if (state->effects & 16)
{ //unknown progs crc. things here are basically hacks.
if (state->effects & 16) //tenebrae's EF_FULLDYNAMIC
{
state->effects &= ~16;
state->lightpflags |= PFLAGS_FULLDYNAMIC;

View File

@ -1184,17 +1184,24 @@ static void WPhys_Physics_Noclip (world_t *w, wedict_t *ent)
VectorMA (ent->v->angles, host_frametime, ent->v->avelocity, ent->v->angles);
VectorMA (ent->v->origin, host_frametime, ent->v->velocity, end);
trace = World_Move (w, ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NOMONSTERS, (wedict_t*)ent);
impact = trace.ent;
if (impact && impact->v->solid == SOLID_PORTAL)
#ifndef CLIENTONLY
//allow spectators to no-clip through portals without bogging down sock's mods.
if (ent->entnum > 0 && ent->entnum <= sv.allocated_client_slots && w == &sv.world)
{
vec3_t move;
vec3_t from;
VectorCopy(trace.endpos, from); //just in case
VectorSubtract(end, trace.endpos, move);
WPhys_PortalTransform(w, ent, impact, from, move);
VectorAdd(from, move, end);
trace = World_Move (w, ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NOMONSTERS, (wedict_t*)ent);
impact = trace.ent;
if (impact && impact->v->solid == SOLID_PORTAL)
{
vec3_t move;
vec3_t from;
VectorCopy(trace.endpos, from); //just in case
VectorSubtract(end, trace.endpos, move);
WPhys_PortalTransform(w, ent, impact, from, move);
VectorAdd(from, move, end);
}
}
#endif
VectorCopy(end, ent->v->origin);
World_LinkEdict (w, (wedict_t*)ent, false);

View File

@ -7000,27 +7000,6 @@ void SVQ2_ExecuteClientMessage (client_t *cl)
SV_DropClient(cl);
}
// calc ping time
frame = &cl->frameunion.q2frames[cl->netchan.incoming_acknowledged & Q2UPDATE_MASK];
if (frame->senttime != -1)
{
int ping_time = realtime*1000 - frame->senttime; //no more phenomanally low pings please
if (ping_time > sv_minping.value+1)
{
cl->delay -= 0.001;
if (cl->delay < 0)
cl->delay = 0;
}
if (ping_time < sv_minping.value)
{
cl->delay += 0.001;
if (cl->delay > 1)
cl->delay = 1;
}
frame->senttime = -1;
frame->ping_time = ping_time;
}
// make sure the reply sequence number matches the incoming
// sequence number
if (cl->netchan.incoming_sequence >= cl->netchan.outgoing_sequence)
@ -7028,9 +7007,39 @@ void SVQ2_ExecuteClientMessage (client_t *cl)
else
cl->send_message = false; // don't reply, sequences have slipped
// calc ping time
if (cl->netchan.outgoing_sequence - cl->netchan.incoming_acknowledged > Q2UPDATE_MASK)
{
cl->delay -= 0.001;
if (cl->delay < 0)
cl->delay = 0;
}
else
{
frame = &cl->frameunion.q2frames[cl->netchan.incoming_acknowledged & Q2UPDATE_MASK];
if (frame->senttime != -1)
{
int ping_time = (int)(realtime*1000) - frame->senttime; //no more phenomanally low pings please
if (ping_time > sv_minping.value+1)
{
cl->delay -= 0.001;
if (cl->delay < 0)
cl->delay = 0;
}
if (ping_time < sv_minping.value)
{
cl->delay += 0.001;
if (cl->delay > 1)
cl->delay = 1;
}
frame->senttime = -1;
frame->ping_time = ping_time;
}
}
// save time for ping calculations
cl->frameunion.q2frames[cl->netchan.outgoing_sequence & Q2UPDATE_MASK].senttime = realtime*1000;
cl->frameunion.q2frames[cl->netchan.outgoing_sequence & Q2UPDATE_MASK].ping_time = -1;
// cl->frameunion.q2frames[cl->netchan.outgoing_sequence & Q2UPDATE_MASK].senttime = realtime*1000;
// cl->frameunion.q2frames[cl->netchan.outgoing_sequence & Q2UPDATE_MASK].ping_time = -1;
host_client = cl;
sv_player = host_client->edict;
@ -7115,6 +7124,7 @@ void SVQ2_ExecuteClientMessage (client_t *cl)
newcmd.upmove = 0;
}
host_client->q2edict->client->ping = SV_CalcPing (host_client, false);
if (!sv.paused)
{
if (net_drop < 20)

View File

@ -631,11 +631,14 @@ void SVQ2_BuildClientFrame (client_t *client)
numprojs = 0; // no projectiles yet
#endif
// this is the frame we are creating
frame = &client->frameunion.q2frames[sv.framenum & Q2UPDATE_MASK];
// this is the frame the client will be acking (EVIL HACKS!)
frame = &client->frameunion.q2frames[client->netchan.outgoing_sequence & Q2UPDATE_MASK];
frame->senttime = realtime*1000; // save it for ping calc later
// this is the frame we are creating
frame = &client->frameunion.q2frames[sv.framenum & Q2UPDATE_MASK];
// find the client's PVS
for (i=0 ; i<3 ; i++)
org[i] = clent->client->ps.pmove.origin[i]*0.125 + clent->client->ps.viewoffset[i];