1
0
Fork 0
forked from fte/fteqw

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 NPFTE_CFLAGS=$(NPFTECFLAGS) $(W32_CFLAGS) -DMULTITHREAD -fPIC -DDYNAMIC_LIBPNG -DDYNAMIC_LIBJPEG
NPFTEB_DIR=npfte_linux$(BITS) 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) GL_EXE_NAME=../fteqw.gl$(BITS)
GLCL_EXE_NAME=../fteqwcl.gl$(BITS) GLCL_EXE_NAME=../fteqwcl.gl$(BITS)
GL_LDFLAGS=$(GLLDFLAGS) $(XLDFLAGS) $(OGGVORBISLDFLAGS) 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) GLB_DIR=gl_linux$(BITS)
GLCL_DIR=glcl_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) M_EXE_NAME=../fteqw$(BITS)
MCL_EXE_NAME=../fteqwcl$(BITS) MCL_EXE_NAME=../fteqwcl$(BITS)
M_LDFLAGS=$(GL_LDFLAGS) M_LDFLAGS=$(GL_LDFLAGS)

View file

@ -1361,11 +1361,12 @@ qboolean CLQ2_SendCmd (sizebuf_t *buf)
int checksumIndex, i; int checksumIndex, i;
int lightlev; 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 // send this and the previous cmds in the message, so
// if the last packet was dropped, it can be recovered // 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]; cmd = &cl.outframes[i].cmd[0];
if (cls.resendinfo) if (cls.resendinfo)

View file

@ -3970,12 +3970,13 @@ void Host_RunFileNotify(struct dl_download *dl)
#define HRF_QTVINFO (1<<12) #define HRF_QTVINFO (1<<12)
#define HRF_MANIFEST (1<<13) #define HRF_MANIFEST (1<<13)
#define HRF_BSP (1<<14) #define HRF_BSP (1<<14)
#define HRF_PACKAGE (1<<15) #define HRF_PACKAGE (1<<15) //pak or pk3 that should be installed.
#define HRF_MODEL (1<<16) #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_ACTION (HRF_OVERWRITE|HRF_NOOVERWRITE|HRF_ABORT)
#define HRF_DEMO (HRF_DEMO_MVD|HRF_DEMO_QWD|HRF_DEMO_DM2|HRF_DEMO_DEM) #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 { typedef struct {
unsigned int flags; unsigned int flags;
vfsfile_t *srcfile; vfsfile_t *srcfile;
@ -3987,18 +3988,27 @@ int waitingformanifest;
void Host_DoRunFile(hrf_t *f); 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_PlayDemoStream(vfsfile_t *file, struct dl_download *, char *filename, qboolean issyspath, int demotype, float bufferdelay);
void CL_ParseQTVDescriptor(vfsfile_t *f, const char *name); 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) void Host_RunFileDownloaded(struct dl_download *dl)
{ {
//fixme: sort out flags from mime type....
hrf_t *f = dl->user_ctx; hrf_t *f = dl->user_ctx;
if (dl->status == DL_FAILED)
{
f->flags |= HRF_ABORT;
f->srcfile = NULL;
}
else
{
f->srcfile = dl->file; f->srcfile = dl->file;
dl->file = NULL; dl->file = NULL;
}
Host_DoRunFile(f); 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. //at this point the file is still downloading, so don't copy it out just yet.
hrf_t *f = dl->user_ctx; hrf_t *f = dl->user_ctx;
@ -4020,6 +4030,8 @@ void Host_BeginFileDownload(struct dl_download *dl, char *mimetype)
f->flags |= HRF_MANIFEST; f->flags |= HRF_MANIFEST;
else if (!strcmp(mimetype, "application/x-multiviewdemo")) else if (!strcmp(mimetype, "application/x-multiviewdemo"))
f->flags |= HRF_DEMO_MVD; f->flags |= HRF_DEMO_MVD;
else if (!strcmp(mimetype, "application/zip"))
f->flags |= HRF_ARCHIVE;
// else if (!strcmp(mimetype, "application/x-ftebsp")) // else if (!strcmp(mimetype, "application/x-ftebsp"))
// f->flags |= HRF_BSP; // f->flags |= HRF_BSP;
// else if (!strcmp(mimetype, "application/x-ftepackage")) // else if (!strcmp(mimetype, "application/x-ftepackage"))
@ -4051,11 +4063,14 @@ void Host_BeginFileDownload(struct dl_download *dl, char *mimetype)
f->flags |= HRF_PACKAGE; f->flags |= HRF_PACKAGE;
else 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. //file type not guessable from extension either.
f->flags |= HRF_ABORT; f->flags |= HRF_ABORT;
Host_DoRunFile(f); Host_DoRunFile(f);
return; return false;
} }
if (f->flags & HRF_MANIFEST) 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 //just use a pipe instead of a temp file, working around an issue with temp files on android
dl->file = VFSPIPE_Open(); 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) 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 Con_Printf("%s: format not supported\n", f->fname); //demos that are not supported in this build for one reason or another
else 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; f->flags |= HRF_ABORT;
Host_DoRunFile(f); Host_DoRunFile(f);
return; return result;
} }
void Host_RunFilePrompted(void *ctx, int button) void Host_RunFilePrompted(void *ctx, int button)
{ {
@ -4292,6 +4328,21 @@ void Host_DoRunFile(hrf_t *f)
Host_DoRunFile(f); Host_DoRunFile(f);
return; 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)) else if (!(f->flags & HRF_QTVINFO))
{ {
Con_Printf("Host_DoRunFile: filetype not handled\n"); Con_Printf("Host_DoRunFile: filetype not handled\n");

View file

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

View file

@ -722,6 +722,9 @@ static void CLQ2_ParsePacketEntities (q2frame_t *oldframe, q2frame_t *newframe)
unsigned int oldindex, oldnum; unsigned int oldindex, oldnum;
cl.validsequence = cls.netchan.incoming_sequence; 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->parse_entities = cl.parse_entities;
newframe->num_entities = 0; newframe->num_entities = 0;

View file

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

View file

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

View file

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

View file

@ -38,8 +38,16 @@ void M_DrawTextBox (int x, int y, int width, int lines)
cx = x; cx = x;
cy = y; cy = y;
p = R2D_SafeCachePic ("gfx/box_tl.lmp"); p = R2D_SafeCachePic ("gfx/box_tl.lmp");
if (!p) switch(R_GetShaderSizes(p, NULL, NULL, false))
return; //assume we can't find any {
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); M_DrawScalePic (cx, cy, 8, 8, p);
p = R2D_SafeCachePic ("gfx/box_ml.lmp"); p = R2D_SafeCachePic ("gfx/box_ml.lmp");
if (p) if (p)

View file

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

View file

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

View file

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

View file

@ -809,7 +809,13 @@ static qboolean OpenAL_InitLibrary(void)
if (!openallib_tried) if (!openallib_tried)
{ {
openallib_tried = true; openallib_tried = true;
#ifdef _WIN32
openallib = Sys_LoadLibrary("OpenAL32", openalfuncs); openallib = Sys_LoadLibrary("OpenAL32", openalfuncs);
#else
openallib = Sys_LoadLibrary("libopenal.so.1", openalfuncs);
if (!openallib)
openallib = Sys_LoadLibrary("libopenal", openalfuncs);
#endif
} }
return !!openallib; return !!openallib;
#endif #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); 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_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) 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) if (sc->Submit == ALSA_RW_Submit)
free(sc->sn.buffer); free(sc->sn.buffer);
Con_DPrintf("Alsa closed\n");
} }
static void *ALSA_LockBuffer(soundcardinfo_t *sc, unsigned int *sampidx) static void *ALSA_LockBuffer(soundcardinfo_t *sc, unsigned int *sampidx)
@ -243,6 +249,10 @@ static qboolean Alsa_InitAlsa(void)
psnd_pcm_writei = dlsym(alsasharedobject, "snd_pcm_writei"); psnd_pcm_writei = dlsym(alsasharedobject, "snd_pcm_writei");
psnd_pcm_prepare = dlsym(alsasharedobject, "snd_pcm_prepare"); 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 alsaworks = psnd_pcm_open
&& psnd_pcm_close && psnd_pcm_close
&& psnd_strerror && psnd_strerror
@ -267,20 +277,17 @@ static qboolean Alsa_InitAlsa(void)
&& psnd_pcm_mmap_begin && psnd_pcm_mmap_begin
&& psnd_pcm_mmap_commit && psnd_pcm_mmap_commit
&& psnd_pcm_writei && psnd_pcm_prepare && psnd_pcm_writei && psnd_pcm_prepare
&& psnd_device_name_hint && psnd_device_name_get_hint && psnd_device_name_free_hint
; ;
return alsaworks; 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_t *pcm;
snd_pcm_uframes_t buffer_size; snd_pcm_uframes_t buffer_size;
soundcardinfo_t *ec; //existing card
char *pcmname;
cvar_t *devname;
int err; int err;
snd_pcm_hw_params_t *hw; snd_pcm_hw_params_t *hw;
snd_pcm_sw_params_t *sw; snd_pcm_sw_params_t *sw;
@ -294,7 +301,7 @@ static int ALSA_InitCard (soundcardinfo_t *sc, int cardnum)
if (!Alsa_InitAlsa()) if (!Alsa_InitAlsa())
{ {
Con_Printf(CON_ERROR "Alsa does not appear to be installed or compatible\n"); 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()); 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()); memset(hw, 0, psnd_pcm_hw_params_sizeof());
//WARNING: 'default' as the default sucks arse. it adds about a second's worth of lag. //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"); if (!pcmname)
pcmname = devname->string; pcmname = "default";
if (!*pcmname)
return 2;
for (ec = sndcardinfo; ec; ec = ec->next)
if (!strcmp(ec->name, pcmname))
break;
if (ec)
return 2; //no more
sc->inactive_sound = true; //linux sound devices always play sound, even when we're not the active app... 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); SND_PCM_NONBLOCK);
if (0 > err) 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; return 0;
} }
Con_Printf ("ALSA: Using PCM %s.\n", pcmname); 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); 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) if (0 > err)
{ {
Con_Printf (CON_ERROR "ALSA: error setting params. %s\n", Con_Printf (CON_ERROR "ALSA: error setting params. %s\n", psnd_strerror (err));
psnd_strerror (err));
goto error; goto error;
} }
@ -346,16 +343,14 @@ static int ALSA_InitCard (soundcardinfo_t *sc, int cardnum)
err = psnd_pcm_hw_params_any (pcm, hw); err = psnd_pcm_hw_params_any (pcm, hw);
if (0 > err) if (0 > err)
{ {
Con_Printf (CON_ERROR "ALSA: error setting hw_params_any. %s\n", Con_Printf (CON_ERROR "ALSA: error setting hw_params_any. %s\n", psnd_strerror (err));
psnd_strerror (err));
goto error; goto error;
} }
err = psnd_pcm_hw_params_set_access (pcm, hw, mmap?SND_PCM_ACCESS_MMAP_INTERLEAVED:SND_PCM_ACCESS_RW_INTERLEAVED); err = psnd_pcm_hw_params_set_access (pcm, hw, mmap?SND_PCM_ACCESS_MMAP_INTERLEAVED:SND_PCM_ACCESS_RW_INTERLEAVED);
if (0 > err) if (0 > err)
{ {
Con_Printf (CON_ERROR "ALSA: Failure to set interleaved PCM access. %s\n", Con_Printf (CON_ERROR "ALSA: Failure to set interleaved PCM access. %s\n", psnd_strerror (err));
psnd_strerror (err));
goto error; 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); err = psnd_pcm_hw_params_set_period_size_near (pcm, hw, &frag_size, 0);
if (0 > err) if (0 > err)
{ {
Con_Printf (CON_ERROR "ALSA: unable to set period size near %i. %s\n", Con_Printf (CON_ERROR "ALSA: unable to set period size near %i. %s\n", (int) frag_size, psnd_strerror (err));
(int) frag_size, psnd_strerror (err));
goto error; goto error;
} }
err = psnd_pcm_hw_params (pcm, hw); 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); err = psnd_pcm_sw_params_current (pcm, sw);
if (0 > err) { if (0 > err) {
Con_Printf (CON_ERROR "ALSA: unable to determine current sw params. %s\n", Con_Printf (CON_ERROR "ALSA: unable to determine current sw params. %s\n", psnd_strerror (err));
psnd_strerror (err));
goto error; goto error;
} }
err = psnd_pcm_sw_params_set_start_threshold (pcm, sw, ~0U); err = psnd_pcm_sw_params_set_start_threshold (pcm, sw, ~0U);
if (0 > err) { if (0 > err) {
Con_Printf (CON_ERROR "ALSA: unable to set playback threshold. %s\n", Con_Printf (CON_ERROR "ALSA: unable to set playback threshold. %s\n", psnd_strerror (err));
psnd_strerror (err));
goto error; goto error;
} }
err = psnd_pcm_sw_params_set_stop_threshold (pcm, sw, ~0U); err = psnd_pcm_sw_params_set_stop_threshold (pcm, sw, ~0U);
if (0 > err) { if (0 > err) {
Con_Printf (CON_ERROR "ALSA: unable to set playback stop threshold. %s\n", Con_Printf (CON_ERROR "ALSA: unable to set playback stop threshold. %s\n", psnd_strerror (err));
psnd_strerror (err));
goto error; goto error;
} }
err = psnd_pcm_sw_params (pcm, sw); err = psnd_pcm_sw_params (pcm, sw);
if (0 > err) { if (0 > err) {
Con_Printf (CON_ERROR "ALSA: unable to install sw params. %s\n", Con_Printf (CON_ERROR "ALSA: unable to install sw params. %s\n", psnd_strerror (err));
psnd_strerror (err));
goto error; 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); err = psnd_pcm_hw_params_get_buffer_size (hw, &buffer_size);
if (0 > err) { if (0 > err) {
Con_Printf (CON_ERROR "ALSA: unable to get buffer size. %s\n", Con_Printf (CON_ERROR "ALSA: unable to get buffer size. %s\n", psnd_strerror (err));
psnd_strerror (err));
goto error; goto error;
} }
sc->sn.speed = rate; sc->sn.speed = rate;
@ -530,8 +519,7 @@ static int ALSA_InitCard (soundcardinfo_t *sc, int cardnum)
err = psnd_pcm_prepare(pcm); err = psnd_pcm_prepare(pcm);
if (0 > err) if (0 > err)
{ {
Con_Printf (CON_ERROR "ALSA: unable to prepare for use. %s\n", Con_Printf (CON_ERROR "ALSA: unable to prepare for use. %s\n", psnd_strerror (err));
psnd_strerror (err));
goto error; goto error;
} }
} }
@ -542,7 +530,45 @@ error:
psnd_pcm_close (pcm); psnd_pcm_close (pcm);
return false; 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", 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."); "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", "", cvar_t snd_device = CVARAFD( "s_device", "",
"snd_device", CVAR_ARCHIVE); "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."); 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 #ifdef VOICECHAT
@ -1484,11 +1484,13 @@ void S_DefaultSpeakerConfiguration(soundcardinfo_t *sc)
sounddriver_t DSOUND_Output; sounddriver_t DSOUND_Output;
sounddriver_t SDL_Output;
sounddriver_t ALSA_Output;
sounddriver_t OSS_Output;
#ifdef AVAIL_OPENAL #ifdef AVAIL_OPENAL
extern sounddriver_t OPENAL_Output; extern sounddriver_t OPENAL_Output;
#endif #endif
sounddriver pALSA_InitCard;
sounddriver pSNDIO_InitCard; sounddriver pSNDIO_InitCard;
sounddriver pOSS_InitCard; sounddriver pOSS_InitCard;
sounddriver pMacOS_InitCard; sounddriver pMacOS_InitCard;
@ -1506,7 +1508,15 @@ sounddriver_t *outputdrivers[] =
#ifdef AVAIL_OPENAL #ifdef AVAIL_OPENAL
&OPENAL_Output, &OPENAL_Output,
#endif #endif
#ifdef _WIN32
&DSOUND_Output, &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 NULL
}; };
typedef struct { typedef struct {
@ -1523,10 +1533,6 @@ sdriver_t olddrivers[] = {
#endif #endif
{"SNDIO", &pSNDIO_InitCard}, //prefered on OpenBSD {"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. {"WaveOut", &pWAV_InitCard}, //doesn't work properly in vista, etc.
{NULL, NULL} {NULL, NULL}
}; };
@ -1586,7 +1592,7 @@ static soundcardinfo_t *SNDDMA_Init(char *driver, char *device)
for (i = 0; outputdrivers[i]; i++) for (i = 0; outputdrivers[i]; i++)
{ {
sd = outputdrivers[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. //skip drivers which are not present.
if (!sd->InitCard) if (!sd->InitCard)

View file

@ -82,7 +82,7 @@ static void OSS_Alsa_Submit(soundcardinfo_t *sc, int start, int end)
{ {
if (result >= 0) if (result >= 0)
sc->snd_sent += result; sc->snd_sent += result;
printf("full?\n"); // printf("full?\n");
return; return;
} }
sc->snd_sent += chunk; 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. { //FIXME: implement snd_multipledevices somehow.
int rc; int rc;
int fmt; int fmt;
@ -127,8 +127,6 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
int i; int i;
struct audio_buf_info info; struct audio_buf_info info;
int caps; int caps;
char *snddev = NULL;
cvar_t *devname;
qboolean alsadetected = false; qboolean alsadetected = false;
#ifdef __linux__ #ifdef __linux__
@ -137,11 +135,13 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
alsadetected = true; alsadetected = true;
#endif #endif
devname = Cvar_Get(va("snd_devicename%i", cardnum+1), cardnum?"":"/dev/dsp", 0, "Sound controls"); if (!snddev || !*snddev)
snddev = devname->string; snddev = "/dev/dsp";
else if (strncmp(snddev, "/dev/dsp", 8))
if (!*snddev) {
return 2; 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... 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); perror(snddev);
Con_Printf(CON_ERROR "OSS: Could not open %s\n", snddev); Con_Printf(CON_ERROR "OSS: Could not open %s\n", snddev);
OSS_Shutdown(sc); OSS_Shutdown(sc);
return 0; return false;
} }
Q_strncpyz(sc->name, snddev, sizeof(sc->name)); Q_strncpyz(sc->name, snddev, sizeof(sc->name));
@ -176,7 +176,7 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
perror(snddev); perror(snddev);
Con_Printf(CON_ERROR "OSS: Could not reset %s\n", snddev); Con_Printf(CON_ERROR "OSS: Could not reset %s\n", snddev);
OSS_Shutdown(sc); OSS_Shutdown(sc);
return 0; return false;
} }
//check its general capabilities, we need trigger+mmap //check its general capabilities, we need trigger+mmap
@ -185,7 +185,7 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
perror(snddev); perror(snddev);
Con_Printf(CON_ERROR "OSS: Sound driver too old\n"); Con_Printf(CON_ERROR "OSS: Sound driver too old\n");
OSS_Shutdown(sc); OSS_Shutdown(sc);
return 0; return false;
} }
//choose channels //choose channels
@ -197,7 +197,7 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
perror(snddev); perror(snddev);
Con_Printf(CON_ERROR "OSS: Could not set %s to channels=%d\n", snddev, sc->sn.numchannels); Con_Printf(CON_ERROR "OSS: Could not set %s to channels=%d\n", snddev, sc->sn.numchannels);
OSS_Shutdown(sc); OSS_Shutdown(sc);
return 0; return false;
} }
sc->sn.numchannels = tmp; sc->sn.numchannels = tmp;
#else #else
@ -210,7 +210,7 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
perror(snddev); perror(snddev);
Con_Printf(CON_ERROR "OSS: Could not set %s to stereo=%d\n", snddev, sc->sn.numchannels); Con_Printf(CON_ERROR "OSS: Could not set %s to stereo=%d\n", snddev, sc->sn.numchannels);
OSS_Shutdown(sc); OSS_Shutdown(sc);
return 0; return false;
} }
if (tmp) if (tmp)
sc->sn.numchannels = 2; 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. { //their card doesn't support 8bit which we're trying to use.
Con_Printf(CON_ERROR "OSS: No needed sample formats supported\n"); Con_Printf(CON_ERROR "OSS: No needed sample formats supported\n");
OSS_Shutdown(sc); OSS_Shutdown(sc);
return 0; return false;
} }
if (sc->sn.samplebits == 16) if (sc->sn.samplebits == 16)
{ {
@ -238,7 +238,7 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
perror(snddev); perror(snddev);
Con_Printf(CON_ERROR "OSS: Could not support 16-bit data. Try 8-bit.\n"); Con_Printf(CON_ERROR "OSS: Could not support 16-bit data. Try 8-bit.\n");
OSS_Shutdown(sc); OSS_Shutdown(sc);
return 0; return false;
} }
} }
else if (sc->sn.samplebits == 8) else if (sc->sn.samplebits == 8)
@ -250,7 +250,7 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
perror(snddev); perror(snddev);
Con_Printf(CON_ERROR "OSS: Could not support 8-bit data.\n"); Con_Printf(CON_ERROR "OSS: Could not support 8-bit data.\n");
OSS_Shutdown(sc); OSS_Shutdown(sc);
return 0; return false;
} }
} }
else else
@ -258,7 +258,7 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
perror(snddev); perror(snddev);
Con_Printf(CON_ERROR "OSS: %d-bit sound not supported.\n", sc->sn.samplebits); Con_Printf(CON_ERROR "OSS: %d-bit sound not supported.\n", sc->sn.samplebits);
OSS_Shutdown(sc); OSS_Shutdown(sc);
return 0; return false;
} }
//choose speed //choose speed
@ -276,7 +276,7 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
perror(snddev); perror(snddev);
Con_Printf(CON_ERROR "OSS: Failed to obtain a suitable rate\n"); Con_Printf(CON_ERROR "OSS: Failed to obtain a suitable rate\n");
OSS_Shutdown(sc); OSS_Shutdown(sc);
return 0; return false;
} }
} }
sc->sn.speed = tmp; sc->sn.speed = tmp;
@ -287,7 +287,7 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
perror("GETOSPACE"); perror("GETOSPACE");
Con_Printf(CON_ERROR "OSS: Um, can't do GETOSPACE?\n"); Con_Printf(CON_ERROR "OSS: Um, can't do GETOSPACE?\n");
OSS_Shutdown(sc); OSS_Shutdown(sc);
return 0; return false;
} }
sc->sn.samples = info.fragstotal * info.fragsize; sc->sn.samples = info.fragstotal * info.fragsize;
sc->sn.samples /= (sc->sn.samplebits/8); 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; sc->sn.buffer = MAP_FAILED;
if (alsadetected) 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)) 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); perror(snddev);
Con_Printf(CON_ERROR "OSS: Could not toggle.\n"); Con_Printf(CON_ERROR "OSS: Could not toggle.\n");
OSS_Shutdown(sc); OSS_Shutdown(sc);
return 0; return false;
} }
tmp = PCM_ENABLE_OUTPUT; tmp = PCM_ENABLE_OUTPUT;
rc = ioctl(sc->audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp); rc = ioctl(sc->audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
@ -344,7 +344,7 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
perror(snddev); perror(snddev);
Con_Printf(CON_ERROR "OSS: Could not toggle.\n"); Con_Printf(CON_ERROR "OSS: Could not toggle.\n");
OSS_Shutdown(sc); OSS_Shutdown(sc);
return 0; return false;
} }
sc->Submit = OSS_MMap_Submit; sc->Submit = OSS_MMap_Submit;
sc->GetDMAPos = OSS_MMap_GetDMAPos; sc->GetDMAPos = OSS_MMap_GetDMAPos;
@ -357,10 +357,103 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
sc->SetWaterDistortion = OSS_SetUnderWater; sc->SetWaterDistortion = OSS_SetUnderWater;
sc->Shutdown = OSS_Shutdown; 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 "quakedef.h"
#include "winquake.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> #include <SDL.h>
#endif
#define SELFPAINT #define SELFPAINT
//SDL calls a callback each time it needs to repaint the 'hardware' buffers //SDL calls a callback each time it needs to repaint the 'hardware' buffers
//This results in extra latency. //This results in extra latency due it needing to buffer that much data.
//SDL runs does this multithreaded.
//So we tell it a fairly pathetically sized buffer and try and get it to copy often //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. //hopefully this lowers sound latency, and has no suddenly starting sounds and stuff.
//It still has greater latency than direct access, of course. //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) static void SSDL_Shutdown(soundcardinfo_t *sc)
{ {
Con_DPrintf("Shutdown SDL sound\n"); 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(); SDL_CloseAudio();
#endif
#ifndef SELFPAINT #ifndef SELFPAINT
if (sc->sn.buffer) if (sc->sn.buffer)
free(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) static void *SSDL_LockBuffer(soundcardinfo_t *sc, unsigned int *sampidx)
{ {
#if SDL_MAJOR_VERSION >= 2
SDL_LockAudioDevice(sc->audio_fd);
#else
SDL_LockAudio(); SDL_LockAudio();
#endif
return sc->sn.buffer; return sc->sn.buffer;
} }
static void SSDL_UnlockBuffer(soundcardinfo_t *sc, void *buffer) static void SSDL_UnlockBuffer(soundcardinfo_t *sc, void *buffer)
{ {
#if SDL_MAJOR_VERSION >= 2
SDL_UnlockAudioDevice(sc->audio_fd);
#else
SDL_UnlockAudio(); SDL_UnlockAudio();
#endif
} }
static void SSDL_SetUnderWater(soundcardinfo_t *sc, qboolean uw) 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... //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; SDL_AudioSpec desired, obtained;
if (cardnum) if(!SSDL_InitAudio())
{ //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))
{ {
Con_Printf("Couldn't initialize SDL audio subsystem\n"); Con_Printf("Couldn't initialize SDL audio subsystem\n");
return false; return false;
@ -114,19 +208,26 @@ static int SDL_InitCard(soundcardinfo_t *sc, int cardnum)
desired.userdata = sc; desired.userdata = sc;
memcpy(&obtained, &desired, sizeof(obtained)); memcpy(&obtained, &desired, sizeof(obtained));
#ifdef FTE_TARGET_WEB #if SDL_MAJOR_VERSION >= 2
if ( SDL_OpenAudio(&desired, NULL) < 0 ) 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; 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 #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 ) 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; return false;
} }
Con_Printf("Initing default SDL audio device.\n");
#endif #endif
sc->sn.numchannels = obtained.channels; sc->sn.numchannels = obtained.channels;
sc->sn.speed = obtained.freq; sc->sn.speed = obtained.freq;
@ -155,10 +256,41 @@ static int SDL_InitCard(soundcardinfo_t *sc, int cardnum)
sc->Shutdown = SSDL_Shutdown; sc->Shutdown = SSDL_Shutdown;
sc->GetDMAPos = SSDL_GetDMAPos; sc->GetDMAPos = SSDL_GetDMAPos;
#if SDL_MAJOR_VERSION >= 2
SDL_PauseAudioDevice(sc->audio_fd, 0);
#else
SDL_PauseAudio(0); SDL_PauseAudio(0);
#endif
return true; 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 #endif
#ifdef _WIN32 #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; qboolean result = false;
HKEY subkey; HKEY subkey;

View file

@ -43,10 +43,6 @@ __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; //13.35+ __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. #ifdef WINRT //you're going to need a different sys_ port.
qboolean isDedicated = false; qboolean isDedicated = false;
qboolean ActiveApp; qboolean ActiveApp;
@ -368,15 +364,20 @@ dllhandle_t *Sys_LoadLibrary(const char *name, dllfunction_t *funcs)
{ {
int i; int i;
HMODULE lib; HMODULE lib;
wchar_t wide[MAX_OSPATH];
lib = LoadLibrary(name); widen(wide, sizeof(wide), name);
lib = LoadLibraryW(wide);
if (!lib) 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 #ifdef _WIN64
lib = LoadLibrary(va("%s_64", name)); lib = LoadLibrary(va("%s_64", name));
#elif defined(_WIN32) #elif defined(_WIN32)
lib = LoadLibrary(va("%s_32", name)); lib = LoadLibrary(va("%s_32", name));
#endif #endif
}
if (!lib) if (!lib)
return NULL; 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. //generate a minidump, but only if we were compiled by something that used usable debugging info. its a bit pointless otherwise.
#ifdef _MSC_VER #ifdef _MSC_VER
hDbgHelp = LoadLibrary ("DBGHELP"); hDbgHelp = LoadLibraryA ("DBGHELP");
if (hDbgHelp) if (hDbgHelp)
fnMiniDumpWriteDump = (MINIDUMPWRITEDUMP)GetProcAddress (hDbgHelp, "MiniDumpWriteDump"); fnMiniDumpWriteDump = (MINIDUMPWRITEDUMP)GetProcAddress (hDbgHelp, "MiniDumpWriteDump");
else else
@ -790,9 +791,9 @@ DWORD CrashExceptionHandler (qboolean iswatchdog, DWORD exceptionCode, LPEXCEPTI
else if (*com_gamepath) else if (*com_gamepath)
Q_strncpyz(dumpPath, com_gamepath, sizeof(dumpPath)); Q_strncpyz(dumpPath, com_gamepath, sizeof(dumpPath));
else else
GetTempPath (sizeof(dumpPath)-16, dumpPath); GetTempPathA (sizeof(dumpPath)-16, dumpPath);
Q_strncatz(dumpPath, DISTRIBUTION"CrashDump.dmp", sizeof(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) if (dumpfile)
{ {
MINIDUMP_EXCEPTION_INFORMATION crashinfo; MINIDUMP_EXCEPTION_INFORMATION crashinfo;
@ -803,19 +804,19 @@ DWORD CrashExceptionHandler (qboolean iswatchdog, DWORD exceptionCode, LPEXCEPTI
{ {
CloseHandle(dumpfile); 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); 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 else
MessageBox(NULL, "MiniDumpWriteDump failed", "oh noes", 0); MessageBoxA(NULL, "MiniDumpWriteDump failed", "oh noes", 0);
} }
else else
{ {
Q_snprintfz(msg, sizeof(msg), "unable to open %s\nno dump created.", dumpPath); 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 else
MessageBox(NULL, "Kaboom! Sorry. No MiniDumpWriteDump function.", DISTRIBUTION " Sucks", 0); MessageBoxA(NULL, "Kaboom! Sorry. No MiniDumpWriteDump function.", DISTRIBUTION " Sucks", 0);
#endif #endif
return EXCEPTION_EXECUTE_HANDLER; return EXCEPTION_EXECUTE_HANDLER;
} }
@ -1071,7 +1072,7 @@ static int Sys_EnumerateFiles2 (const char *match, int matchstart, int neststart
memcpy(tmproot, match, neststart); memcpy(tmproot, match, neststart);
strcpy(tmproot+neststart, "*.*"); strcpy(tmproot+neststart, "*.*");
r = FindFirstFile(tmproot, &fd); r = FindFirstFileA(tmproot, &fd);
strcpy(tmproot+neststart, ""); strcpy(tmproot+neststart, "");
if (r==(HANDLE)-1) if (r==(HANDLE)-1)
return 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); FindClose(r);
} }
else else
@ -1107,7 +1108,7 @@ static int Sys_EnumerateFiles2 (const char *match, int matchstart, int neststart
memcpy(tmproot, match, neststart); memcpy(tmproot, match, neststart);
strcpy(tmproot+neststart, "*.*"); strcpy(tmproot+neststart, "*.*");
r = FindFirstFile(tmproot, &fd); r = FindFirstFileA(tmproot, &fd);
strcpy(tmproot+neststart, ""); strcpy(tmproot+neststart, "");
if (r==(HANDLE)-1) if (r==(HANDLE)-1)
return 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); FindClose(r);
} }
} }
@ -1458,7 +1459,6 @@ void VARGS Sys_Error (const char *error, ...)
{ {
va_list argptr; va_list argptr;
char text[1024]; char text[1024];
//, text2[1024];
// DWORD dummy; // DWORD dummy;
va_start (argptr, error); va_start (argptr, error);
@ -1474,7 +1474,11 @@ void VARGS Sys_Error (const char *error, ...)
SV_Shutdown(); SV_Shutdown();
#endif #endif
MessageBox(NULL, text, "Error", 0); {
wchar_t wtext[1024];
widen(wtext, sizeof(wtext), text);
MessageBoxW(NULL, wtext, L"Error", 0);
}
#ifndef SERVERONLY #ifndef SERVERONLY
CloseHandle (qwclsemaphore); CloseHandle (qwclsemaphore);
@ -1991,11 +1995,11 @@ qboolean Sys_InitTerminal (void)
SetConsoleCtrlHandler (HandlerRoutine, TRUE); SetConsoleCtrlHandler (HandlerRoutine, TRUE);
SetConsoleCP(CP_UTF8); SetConsoleCP(CP_UTF8);
SetConsoleOutputCP(CP_UTF8); SetConsoleOutputCP(CP_UTF8);
SetConsoleTitle (FULLENGINENAME " dedicated server"); SetConsoleTitleW (_L(FULLENGINENAME) L" dedicated server");
if (isPlugin) if (isPlugin)
{ {
hinput = CreateFile("CONIN$",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 = CreateFile("CONOUT$",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 else
{ {
@ -2415,7 +2419,7 @@ void Win7_Init(void)
HRESULT (WINAPI *pSetCurrentProcessExplicitAppUserModelID)(PCWSTR AppID); HRESULT (WINAPI *pSetCurrentProcessExplicitAppUserModelID)(PCWSTR AppID);
h = LoadLibrary("shell32.dll"); h = LoadLibraryW(L"shell32.dll");
if (h) if (h)
{ {
pSHOpenWithDialog = (void*)GetProcAddress(h, "SHOpenWithDialog"); pSHOpenWithDialog = (void*)GetProcAddress(h, "SHOpenWithDialog");
@ -2549,29 +2553,35 @@ int MyRegGetIntValue(HKEY base, char *keyname, char *valuename, int defaultval)
DWORD datalen = sizeof(result); DWORD datalen = sizeof(result);
HKEY subkey; HKEY subkey;
DWORD type = REG_NONE; 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; result = defaultval;
RegCloseKey (subkey); RegCloseKey (subkey);
} }
return result; 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; qboolean result = false;
HKEY subkey; HKEY subkey;
DWORD type = REG_NONE; 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 == RegQueryValueExW(subkey, widen(wide, sizeof(wide), valuename), NULL, &type, (BYTE*)wdata, &dwlen);
result = ERROR_SUCCESS == RegQueryValueEx(subkey, valuename, NULL, &type, data, &dwlen);
datalen = dwlen;
RegCloseKey (subkey); RegCloseKey (subkey);
} }
if (result && (type == REG_SZ || type == REG_EXPAND_SZ)) if (result && (type == REG_SZ || type == REG_EXPAND_SZ))
((char*)data)[datalen] = 0; {
wdata[dwlen/sizeof(wchar_t)] = 0;
narrowen(data, datalen, wdata);
}
else else
((char*)data)[0] = 0; ((char*)data)[0] = 0;
return result; return result;
@ -3196,9 +3206,9 @@ static BOOL microsoft_access(LPCSTR pszFolder, DWORD dwAccessDesired)
DWORD dwNeeded; DWORD dwNeeded;
wchar_t wpath[MAX_OSPATH]; wchar_t wpath[MAX_OSPATH];
widen(wpath, sizeof(wpath), pszFolder); widen(wpath, sizeof(wpath), pszFolder);
GetFileSecurity(pszFolder,si,NULL,0,&dwNeeded); GetFileSecurityW(wpath,si,NULL,0,&dwNeeded);
psdSD = malloc(dwNeeded); psdSD = malloc(dwNeeded);
GetFileSecurity(pszFolder,si,psdSD,dwNeeded,&dwNeeded); GetFileSecurityW(wpath,si,psdSD,dwNeeded,&dwNeeded);
ImpersonateSelf(SecurityImpersonation); ImpersonateSelf(SecurityImpersonation);
OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &hToken); OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &hToken);
memset(&GenericMapping, 0xff, sizeof(GENERIC_MAPPING)); memset(&GenericMapping, 0xff, sizeof(GENERIC_MAPPING));
@ -3275,7 +3285,7 @@ static LRESULT CALLBACK stoopidstoopidstoopid(HWND w, UINT m, WPARAM wp, LPARAM
struct egadsthisisretarded struct egadsthisisretarded
{ {
char title[MAX_OSPATH]; wchar_t title[MAX_OSPATH];
char subdir[MAX_OSPATH]; char subdir[MAX_OSPATH];
char parentdir[MAX_OSPATH]; char parentdir[MAX_OSPATH];
char statustext[MAX_OSPATH]; char statustext[MAX_OSPATH];
@ -3294,13 +3304,13 @@ static INT CALLBACK StupidBrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LP
switch(uMsg) switch(uMsg)
{ {
case BFFM_INITIALIZED: 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 //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); 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 //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) if (list)
omgwtfwhyohwhy = (WNDPROC)SetWindowLongPtr(list, GWLP_WNDPROC, (LONG_PTR)stoopidstoopidstoopid); 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 else
#endif #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_SETSELECTION, TRUE, (LPARAM)szDir);
// SendMessage(hwnd, BFFM_SETEXPANDED, 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: case BFFM_VALIDATEFAILEDW:
return 1;//!microsoft_access("C:\\Games\\", ACCESS_READ | ACCESS_WRITE)) return 1;//!microsoft_access("C:\\Games\\", ACCESS_READ | ACCESS_WRITE))
case BFFM_SELCHANGED: case BFFM_SELCHANGED:
OutputDebugString("selchanged\n"); OutputDebugStringA("selchanged\n");
if (SHGetPathFromIDList((LPITEMIDLIST)lp, pData->parentdir)) if (SHGetPathFromIDList((LPITEMIDLIST)lp, pData->parentdir))
{ {
// OutputDebugString(va("selchanged: %s\n", szDir)); // 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? //fixme: verify that id1 is a subdir perhaps?
if (edit) 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)); SendMessageA(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)va("%s", pData->parentdir));
} }
else else
@ -3365,14 +3376,25 @@ LRESULT CALLBACK NoCloseWindowProc(HWND w, UINT m, WPARAM wp, LPARAM lp)
return DefWindowProc(w, m, wp, 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); void FS_CreateBasedir(const char *path);
qboolean Sys_DoInstall(void) qboolean Sys_DoInstall(void)
{ {
extern ftemanifest_t *fs_manifest; extern ftemanifest_t *fs_manifest;
char exepath[MAX_OSPATH]; char exepath[MAX_OSPATH];
char newexepath[MAX_OSPATH]; char newexepath[MAX_OSPATH];
char resultpath[MAX_PATH]; wchar_t wide[MAX_PATH];
BROWSEINFO bi; char resultpath[MAX_OSPATH];
BROWSEINFOW bi;
LPITEMIDLIST il; LPITEMIDLIST il;
struct egadsthisisretarded diediedie; struct egadsthisisretarded diediedie;
@ -3385,9 +3407,9 @@ qboolean Sys_DoInstall(void)
memset(&bi, 0, sizeof(bi)); memset(&bi, 0, sizeof(bi));
bi.hwndOwner = mainwindow; //note that this is usually still null bi.hwndOwner = mainwindow; //note that this is usually still null
bi.pidlRoot = NULL; bi.pidlRoot = NULL;
GetCurrentDirectory(sizeof(resultpath)-1, resultpath); _snwprintf(diediedie.title, countof(diediedie.title), L"Where would you like to install %s to?", widen(wide, sizeof(wide), fs_gamename.string));
bi.pszDisplayName = resultpath; GetCurrentDirectoryW(countof(wide)-1, wide);
Q_snprintfz(diediedie.title, sizeof(diediedie.title), "Where would you like to install %s to?", fs_gamename.string); bi.pszDisplayName = wide;
bi.lpszTitle = diediedie.title; bi.lpszTitle = diediedie.title;
bi.ulFlags = BIF_RETURNONLYFSDIRS|BIF_STATUSTEXT | BIF_EDITBOX|BIF_NEWDIALOGSTYLE|BIF_VALIDATE; bi.ulFlags = BIF_RETURNONLYFSDIRS|BIF_STATUSTEXT | BIF_EDITBOX|BIF_NEWDIALOGSTYLE|BIF_VALIDATE;
bi.lpfn = StupidBrowseCallbackProc; bi.lpfn = StupidBrowseCallbackProc;
@ -3396,20 +3418,21 @@ qboolean Sys_DoInstall(void)
Q_strncpyz(diediedie.subdir, fs_gamename.string, sizeof(diediedie.subdir)); Q_strncpyz(diediedie.subdir, fs_gamename.string, sizeof(diediedie.subdir));
il = SHBrowseForFolder(&bi); il = SHBrowseForFolderW(&bi);
if (il) if (il)
{ {
SHGetPathFromIDList(il, resultpath); SHGetPathFromIDListW(il, wide);
CoTaskMemFree(il); CoTaskMemFree(il);
} }
else else
return true; return true;
narrowen(resultpath, sizeof(resultpath), wide);
Q_strncatz(resultpath, "/", sizeof(resultpath)); FS_Directorize(resultpath, sizeof(resultpath));
if (*diediedie.subdir) if (*diediedie.subdir)
{ {
Q_strncatz(resultpath, diediedie.subdir, sizeof(resultpath)); Q_strncatz(resultpath, diediedie.subdir, sizeof(resultpath));
Q_strncatz(resultpath, "/", sizeof(resultpath)); FS_Directorize(resultpath, sizeof(resultpath));
} }
FS_CreateBasedir(resultpath); FS_CreateBasedir(resultpath);
@ -3836,7 +3859,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
#endif #endif
#ifdef CATCHCRASH #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 #ifdef _MSC_VER
__try __try
#else #else
@ -3966,11 +3989,11 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
HWND old; HWND old;
qtvfile = parms.argv[1]; qtvfile = parms.argv[1];
old = FindWindow("FTEGLQuake", NULL); old = FindWindowW(L"FTEGLQuake", NULL);
if (!old) if (!old)
old = FindWindow("FTED3D11QUAKE", NULL); old = FindWindowW(L"FTED3D11QUAKE", NULL);
if (!old) if (!old)
old = FindWindow("FTED3D9QUAKE", NULL); old = FindWindowW(L"FTED3D9QUAKE", NULL);
if (old) if (old)
{ {
COPYDATASTRUCT cds; 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. //tray icon crap, so the user can still restore the game.
extern HWND mainwindow; extern HWND mainwindow;
extern HINSTANCE global_hInstance; extern HINSTANCE global_hInstance;
WNDCLASSA wc; WNDCLASSW wc;
NOTIFYICONDATA data; NOTIFYICONDATAW data;
//Shell_NotifyIcon requires a window to provide events etc. //Shell_NotifyIcon requires a window to provide events etc.
wc.style = 0; 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.hCursor = LoadCursor (NULL,IDC_ARROW);
wc.hbrBackground = NULL; wc.hbrBackground = NULL;
wc.lpszMenuName = 0; wc.lpszMenuName = 0;
wc.lpszClassName = "FTEHeadlessClass"; wc.lpszClassName = L"FTEHeadlessClass";
RegisterClassA(&wc); 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.cbSize = sizeof(data);
data.hWnd = mainwindow; data.hWnd = mainwindow;
data.uID = 0; data.uID = 0;
data.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; data.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
data.uCallbackMessage = WM_USER; data.uCallbackMessage = WM_USER;
data.hIcon = wc.hIcon; data.hIcon = wc.hIcon;
strcpy(data.szTip, "Right-click to restore"); wcscpy(data.szTip, L"Right-click to restore");
Shell_NotifyIcon(NIM_ADD, &data); Shell_NotifyIconW(NIM_ADD, &data);
#endif #endif
return true; 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_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 #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_OpenTemp(void);
vfsfile_t *FS_OpenTCP(const char *name, int defaultport); 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_UnloadPackFiles(void);
void FS_ReloadPackFiles(void); void FS_ReloadPackFiles(void);
char *FSQ3_GenerateClientPacksList(char *buffer, int maxlen, int basechecksum); 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_DownloadingPackage(void);
qboolean FS_ChangeGame(ftemanifest_t *newgame, qboolean allowreloadconfigs, qboolean allowbasedirchange); qboolean FS_ChangeGame(ftemanifest_t *newgame, qboolean allowreloadconfigs, qboolean allowbasedirchange);
void FS_Shutdown(void); 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_GetGamedir(qboolean publicpathonly);
char *FS_GetBasedir(void); char *FS_GetBasedir(void);
char *FS_GetManifestArgs(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); void FS_RegisterDefaultFileSystems(void);
static void COM_CreatePath (char *path); static void COM_CreatePath (char *path);
ftemanifest_t *FS_ReadDefaultManifest(char *newbasedir, size_t newbasedirsize, qboolean fixedbasedir); 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 //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; const char *s;
char *o; 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); Con_Printf("Error: absolute path in filename %s\n", pattern);
return NULL; return NULL;
} }
if (!*s)
{
*o++ = '\0';
break;
}
Con_Printf("Error: empty directory name (%s)\n", pattern); Con_Printf("Error: empty directory name (%s)\n", pattern);
s++; s++;
continue; continue;
@ -1958,6 +1963,105 @@ searchpathfuncs_t *FS_OpenPackByExtension(vfsfile_t *f, const char *pakname)
return NULL; 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)) 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 //search is the parent
@ -2006,66 +2110,7 @@ static void FS_AddDataFiles(searchpath_t **oldpaths, const char *purepath, const
wp.oldpaths = oldpaths; wp.oldpaths = oldpaths;
search->handle->EnumerateFiles(search->handle, pakfile, FS_AddWildDataFiles, &wp); search->handle->EnumerateFiles(search->handle, pakfile, FS_AddWildDataFiles, &wp);
FS_AddManifestPackages(oldpaths, purepath, logicalpaths, search, extension, OpenNew);
//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);
}
}
}
}
}
} }
static searchpath_t *FS_AddPathHandle(searchpath_t **oldpaths, const char *purepath, const char *logicalpath, searchpathfuncs_t *handle, unsigned int flags, unsigned int loadstuff) 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; *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 COM_Gamedir
@ -2315,7 +2397,7 @@ COM_Gamedir
Sets the gamedir and path to a different directory. 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; ftemanifest_t *man;
if (!fs_manifest) 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 leading dots, hidden files are evil.
//don't allow complex paths. those are evil too. //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, ":") ) || strstr(dir, "\\") || strstr(dir, ":") )
{ {
Con_Printf ("Gamedir should be a single filename, not a path\n"); Con_Printf ("Gamedir should be a single filename, not a path\n");
@ -2333,7 +2415,7 @@ void COM_Gamedir (const char *dir)
man = NULL; man = NULL;
if (!man) 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) if (f)
{ {
size_t len = VFS_GETLEN(f); size_t len = VFS_GETLEN(f);
@ -2363,7 +2445,7 @@ void COM_Gamedir (const char *dir)
FS_Manifest_PurgeGamedirs(man); FS_Manifest_PurgeGamedirs(man);
if (*dir) if (*dir)
{ {
char token[MAX_QPATH]; char token[MAX_QPATH], quot[MAX_QPATH];
char *dup = Z_StrDup(dir); //FIXME: is this really needed? char *dup = Z_StrDup(dir); //FIXME: is this really needed?
dir = dup; dir = dup;
while ((dir = COM_ParseStringSet(dir, token, sizeof(token)))) while ((dir = COM_ParseStringSet(dir, token, sizeof(token))))
@ -2373,11 +2455,19 @@ void COM_Gamedir (const char *dir)
if (!*token) if (!*token)
continue; 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); FS_Manifest_ParseTokens(man);
} }
Z_Free(dup); 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); 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; return false;
} }
fn = COM_SkipPath(pname); for (fn = pname; *fn; fn++)
{
if (*fn == '\\' || *fn == '/')
{
fn++;
break;
}
}
// fn = COM_SkipPath(pname);
if (fn == pname) if (fn == pname)
{ //only allow it if it has some game path first. { //only allow it if it has some game path first.
*local = 0; *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) qboolean FS_LoadPackageFromFile(vfsfile_t *vfs, char *pname, char *localname, int *crc, unsigned int flags)
{ {
int i; int i;
char *ext = COM_FileExtension(pname); char *ext = "zip";//(pname);
searchpathfuncs_t *handle; searchpathfuncs_t *handle;
searchpath_t *oldlist = NULL; searchpath_t *oldlist = NULL;
searchpath_t *sp; searchpath_t *sp;
com_fschanged = true;
for (i = 0; i < sizeof(searchpathformats)/sizeof(searchpathformats[0]); i++) for (i = 0; i < sizeof(searchpathformats)/sizeof(searchpathformats[0]); i++)
{ {
if (!searchpathformats[i].extension || !searchpathformats[i].OpenNew) if (!searchpathformats[i].extension || !searchpathformats[i].OpenNew)
@ -2536,7 +2636,7 @@ qboolean FS_LoadPackageFromFile(vfsfile_t *vfs, char *pname, char *localname, in
if (sp) if (sp)
{ {
FS_FlushFSHashReally(); com_fschanged = true;
return true; return true;
} }
} }
@ -2828,6 +2928,8 @@ void FS_ReloadPackFilesFlags(unsigned int reloadflags)
} }
} }
FS_AddDownloadManifestPackages(&oldpaths, reloadflags);
/*sv_pure: Reload pure paths*/ /*sv_pure: Reload pure paths*/
if (fs_purenames && fs_purecrcs) if (fs_purenames && fs_purecrcs)
{ {
@ -3067,11 +3169,13 @@ static qboolean Sys_SteamHasFile(char *basepath, int basepathlen, char *steamdir
DWORD resultlen; DWORD resultlen;
HKEY key = NULL; 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; wchar_t suckysucksuck[MAX_OSPATH];
RegQueryValueEx(key, "SteamPath", NULL, NULL, basepath, &resultlen); resultlen = sizeof(suckysucksuck);
RegQueryValueExW(key, L"SteamPath", NULL, NULL, (void*)suckysucksuck, &resultlen);
RegCloseKey(key); RegCloseKey(key);
narrowen(basepath, basepathlen, suckysucksuck);
Q_strncatz(basepath, va("/SteamApps/common/%s", steamdir), basepathlen); Q_strncatz(basepath, va("/SteamApps/common/%s", steamdir), basepathlen);
if ((f = fopen(va("%s/%s", basepath, fname), "rb"))) 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) static INT CALLBACK StupidBrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LPARAM pData)
{ //'stolen' from microsoft's knowledge base. { //'stolen' from microsoft's knowledge base.
//required to work around microsoft being annoying. //required to work around microsoft being annoying.
TCHAR szDir[MAX_PATH]; wchar_t szDir[MAX_PATH];
char *foo; wchar_t *foo;
switch(uMsg) switch(uMsg)
{ {
case BFFM_INITIALIZED: case BFFM_INITIALIZED:
if (GetCurrentDirectory(sizeof(szDir)/sizeof(TCHAR), szDir)) if (GetCurrentDirectoryW(sizeof(szDir)/sizeof(TCHAR), szDir))
{ {
// foo = strrchr(szDir, '\\'); // foo = strrchr(szDir, '\\');
// if (foo) // if (foo)
@ -3099,16 +3203,23 @@ static INT CALLBACK StupidBrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LP
// foo = strrchr(szDir, '\\'); // foo = strrchr(szDir, '\\');
// if (foo) // if (foo)
// *foo = 0; // *foo = 0;
SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)szDir); SendMessageW(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)szDir);
} }
break; break;
case BFFM_VALIDATEFAILEDW:
break; //FIXME: validate that the gamedir contains what its meant to
case BFFM_SELCHANGED: 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 = '/'; *foo = '/';
//fixme: verify that id1 is a subdir perhaps? if (pData)
SendMessage(hwnd,BFFM_SETSTATUSTEXT,0,pData?(LPARAM)va("%s/%s", szDir, pData):(LPARAM)szDir); _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; 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) qboolean Sys_DoDirectoryPrompt(char *basepath, size_t basepathsize, const char *poshname, const char *savedname)
{ {
#ifndef SERVERONLY #ifndef SERVERONLY
char resultpath[MAX_PATH]; wchar_t resultpath[MAX_OSPATH];
BROWSEINFO bi; wchar_t title[MAX_OSPATH];
BROWSEINFOW bi;
LPITEMIDLIST il; LPITEMIDLIST il;
memset(&bi, 0, sizeof(bi)); memset(&bi, 0, sizeof(bi));
bi.hwndOwner = mainwindow; //note that this is usually still null bi.hwndOwner = mainwindow; //note that this is usually still null
bi.pidlRoot = NULL; bi.pidlRoot = NULL;
GetCurrentDirectory(sizeof(resultpath)-1, resultpath); GetCurrentDirectoryW(sizeof(resultpath)-1, resultpath);
bi.pszDisplayName = 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.ulFlags = BIF_RETURNONLYFSDIRS|BIF_STATUSTEXT;
bi.lpfn = StupidBrowseCallbackProc; bi.lpfn = StupidBrowseCallbackProc;
bi.lParam = 0;//(LPARAM)poshname; 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. //force mouse to deactivate, so that we can actually see it.
INS_UpdateGrabs(false, false); INS_UpdateGrabs(false, false);
il = SHBrowseForFolder(&bi); il = SHBrowseForFolderW(&bi);
if (il) if (il)
{ {
SHGetPathFromIDList(il, resultpath); SHGetPathFromIDListW(il, resultpath);
CoTaskMemFree(il); CoTaskMemFree(il);
Q_strncpyz(basepath, resultpath, basepathsize); narrowen(basepath, basepathsize, resultpath);
if (savedname) if (savedname)
{ {
HKEY key = NULL; HKEY key = NULL;
//and save it into the windows registry //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, 0, NULL,
REG_OPTION_NON_VOLATILE, REG_OPTION_NON_VOLATILE,
KEY_WRITE, KEY_WRITE,
@ -3155,7 +3270,9 @@ qboolean Sys_DoDirectoryPrompt(char *basepath, size_t basepathsize, const char *
&key, &key,
NULL) == ERROR_SUCCESS) 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); RegCloseKey(key);
} }
@ -3165,30 +3282,25 @@ qboolean Sys_DoDirectoryPrompt(char *basepath, size_t basepathsize, const char *
#endif #endif
return false; 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) qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *basepath, int basepathlen, qboolean allowprompts)
{ {
DWORD resultlen;
HKEY key = NULL;
#ifndef INVALID_FILE_ATTRIBUTES #ifndef INVALID_FILE_ATTRIBUTES
#define INVALID_FILE_ATTRIBUTES ((DWORD)-1) #define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
#endif #endif
//first, try and find it in our game paths location //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 (GetFileAttributesU(basepath) != INVALID_FILE_ATTRIBUTES)
if (!RegQueryValueEx(key, gamename, NULL, NULL, basepath, &resultlen))
{
if (GetFileAttributes(basepath) != INVALID_FILE_ATTRIBUTES)
{
RegCloseKey(key);
return true; return true;
} }
}
RegCloseKey(key);
}
if (!strcmp(gamename, "quake")) if (!strcmp(gamename, "quake"))
@ -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:/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:/games/quake/", //personally I use this
"c:/nquake/", //nquake seems to have moved out of programfiles now. woo.
#ifdef _WIN64 #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(x86)%")), //64bit builds should look in both places
va("%s/nQuake/", getenv("%ProgramFiles%")), // va("%s/nQuake/", getenv("%ProgramFiles%")), //
#else #else
@ -3207,7 +3321,6 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base
NULL NULL
}; };
int i; int i;
FILE *f;
//try and find it via steam //try and find it via steam
//reads HKEY_LOCAL_MACHINE\SOFTWARE\Valve\Steam\InstallPath //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]; char syspath[MAX_OSPATH];
Q_snprintfz(syspath, sizeof(syspath), "%sid1/pak0.pak", prefix[i]); 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)); Q_strncpyz(basepath, prefix[i], sizeof(basepath));
return true; return true;
} }
@ -3233,22 +3351,12 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base
if (!strcmp(gamename, "quake2")) 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 //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; if (GetFileAttributesU(va("%s/quake2.exe", basepath)) != INVALID_FILE_ATTRIBUTES)
RegQueryValueEx(key, "Path", NULL, NULL, basepath, &resultlen);
RegCloseKey(key);
if ((f = fopen(va("%s/quake2.exe", basepath), "rb")))
{
fclose(f);
return true; return true;
} }
}
if (Sys_SteamHasFile(basepath, basepathlen, "quake 2", "quake2.exe")) if (Sys_SteamHasFile(basepath, basepathlen, "quake 2", "quake2.exe"))
return true; return true;
@ -3256,44 +3364,23 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base
if (!strcmp(gamename, "et")) if (!strcmp(gamename, "et"))
{ {
FILE *f;
DWORD resultlen;
HKEY key = NULL;
//reads HKEY_LOCAL_MACHINE\SOFTWARE\Activision\Wolfenstein - Enemy Territory //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; // if (GetFileAttributesU(va("%s/ET.exe", basepath) != INVALID_FILE_ATTRIBUTES)
RegQueryValueEx(key, "InstallPath", NULL, NULL, basepath, &resultlen); // return true;
RegCloseKey(key);
if ((f = fopen(va("%s/ET.exe", basepath), "rb")))
{
fclose(f);
return true;
}
return true; return true;
} }
} }
if (!strcmp(gamename, "quake3")) if (!strcmp(gamename, "quake3"))
{ {
FILE *f;
DWORD resultlen;
HKEY key = NULL;
//reads HKEY_LOCAL_MACHINE\SOFTWARE\id\Quake III Arena\InstallPath //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; if (GetFileAttributesU(va("%s/quake3.exe", basepath)) != INVALID_FILE_ATTRIBUTES)
RegQueryValueEx(key, "InstallPath", NULL, NULL, basepath, &resultlen);
RegCloseKey(key);
if ((f = fopen(va("%s/quake3.exe", basepath), "rb")))
{
fclose(f);
return true; return true;
} }
}
if (Sys_SteamHasFile(basepath, basepathlen, "quake 3 arena", "quake3.exe")) if (Sys_SteamHasFile(basepath, basepathlen, "quake 3 arena", "quake3.exe"))
return true; return true;
@ -3301,32 +3388,17 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base
if (!strcmp(gamename, "wop")) if (!strcmp(gamename, "wop"))
{ {
DWORD resultlen; if (MyRegGetStringValue(HKEY_LOCAL_MACHINE, "SOFTWARE\\World Of Padman", "Path", basepath, basepathlen))
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);
return true; return true;
} }
}
/* /*
if (!strcmp(gamename, "d3")) if (!strcmp(gamename, "d3"))
{ {
DWORD resultlen;
HKEY key = NULL;
//reads HKEY_LOCAL_MACHINE\SOFTWARE\id\Doom 3\InstallPath //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) if (MyRegGetStringValue(HKEY_LOCAL_MACHINE, L"SOFTWARE\\id\\Doom 3", "InstallPath", basepath, basepathlen))
{
resultlen = basepathlen;
RegQueryValueEx(key, "InstallPath", NULL, NULL, basepath, &resultlen);
RegCloseKey(key);
return true; return true;
} }
}
*/ */
if (!strcmp(gamename, "hexen2") || !strcmp(gamename, "h2mp")) if (!strcmp(gamename, "hexen2") || !strcmp(gamename, "h2mp"))
@ -4668,7 +4740,7 @@ qboolean FS_FixupGamedirForExternalFile(char *input, char *filename, size_t fnam
{ {
Con_Printf("switching gamedir for %s\n", filename); Con_Printf("switching gamedir for %s\n", filename);
*sep = 0; *sep = 0;
COM_Gamedir(filename); COM_Gamedir(filename, NULL);
memmove(filename, sep+1, strlen(sep+1)+1); memmove(filename, sep+1, strlen(sep+1)+1);
return true; return true;
} }
@ -4767,22 +4839,28 @@ void COM_InitFilesystem (void)
#if defined(_WIN32) && !defined(WINRT) #if defined(_WIN32) && !defined(WINRT)
{ //win32 sucks. { //win32 sucks.
HMODULE shfolder = LoadLibrary("shfolder.dll"); HRESULT (WINAPI *dSHGetFolderPathW) (HWND hwndOwner, int nFolder, HANDLE hToken, DWORD dwFlags, wchar_t *pszPath) = NULL;
dllfunction_t funcs[] =
{
{(void**)&dSHGetFolderPathW, "SHGetFolderPathW"},
{NULL,NULL}
};
DWORD winver = (DWORD)LOBYTE(LOWORD(GetVersion())); DWORD winver = (DWORD)LOBYTE(LOWORD(GetVersion()));
/*HMODULE shfolder =*/ Sys_LoadLibrary("shfolder.dll", funcs);
if (shfolder) if (dSHGetFolderPathW)
{
HRESULT (WINAPI *dSHGetFolderPath) (HWND hwndOwner, int nFolder, HANDLE hToken, DWORD dwFlags, LPTSTR pszPath);
dSHGetFolderPath = (void *)GetProcAddress(shfolder, "SHGetFolderPathA");
if (dSHGetFolderPath)
{ {
wchar_t wfolder[MAX_PATH];
char folder[MAX_PATH]; char folder[MAX_PATH];
// 0x5 == CSIDL_PERSONAL // 0x5 == CSIDL_PERSONAL
if (dSHGetFolderPath(NULL, 0x5, NULL, 0, folder) == S_OK) if (dSHGetFolderPathW(NULL, 0x5, NULL, 0, wfolder) == S_OK)
{
narrowen(folder, sizeof(folder), wfolder);
Q_snprintfz(com_homepath, sizeof(com_homepath), "%s/My Games/%s/", folder, FULLENGINENAME); Q_snprintfz(com_homepath, sizeof(com_homepath), "%s/My Games/%s/", folder, FULLENGINENAME);
} }
// FreeLibrary(shfolder);
} }
// if (shfolder)
// FreeLibrary(shfolder);
if (!*com_homepath) if (!*com_homepath)
{ {
@ -4803,13 +4881,15 @@ void COM_InitFilesystem (void)
else if (winver >= 0x5) // Windows 2000/XP/2003 else if (winver >= 0x5) // Windows 2000/XP/2003
{ {
HMODULE advapi32; 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) if (advapi32)
{ {
BOOL (WINAPI *dCheckTokenMembership) (HANDLE TokenHandle, PSID SidToCheck, PBOOL IsMember);
dCheckTokenMembership = (void *)GetProcAddress(advapi32, "CheckTokenMembership");
if (dCheckTokenMembership) 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 // 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); FreeSid(adminSID);
} }
FreeLibrary(advapi32); Sys_CloseLibrary(advapi32);
} }
} }
#endif #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 *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); BOOL (WINAPI *pCertVerifyCertificateChainPolicy) (LPCSTR,PCCERT_CHAIN_CONTEXT,PCERT_CHAIN_POLICY_PARA,PCERT_CHAIN_POLICY_STATUS);
void (WINAPI *pCertFreeCertificateChain) (PCCERT_CHAIN_CONTEXT); 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); 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 *); BOOL (WINAPI *pCertStrToNameA) (DWORD,LPCSTR,DWORD,void *,BYTE *,DWORD *,LPCSTR *);
@ -112,15 +112,6 @@ typedef struct {
char headerdata[1024], footerdata[1024]; char headerdata[1024], footerdata[1024];
} sslfile_t; } 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) static int SSPI_ExpandBuffer(struct sslbuf *buf, size_t bytes)
{ {
if (bytes < buf->datasize) if (bytes < buf->datasize)
@ -129,6 +120,19 @@ static int SSPI_ExpandBuffer(struct sslbuf *buf, size_t bytes)
return 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) static void SSPI_Error(sslfile_t *f, char *error)
{ {
f->handshaking = HS_ERROR; f->handshaking = HS_ERROR;
@ -177,7 +181,6 @@ static void SSPI_Decode(sslfile_t *f)
SecBufferDesc BuffDesc; SecBufferDesc BuffDesc;
SecBuffer SecBuff[4]; SecBuffer SecBuff[4];
ULONG ulQop = 0; ULONG ulQop = 0;
SecBuffer *data = NULL;
SecBuffer *extra = NULL; SecBuffer *extra = NULL;
int i; int i;
@ -216,15 +219,27 @@ static void SSPI_Decode(sslfile_t *f)
for (i = 0; i < BuffDesc.cBuffers; i++) for (i = 0; i < BuffDesc.cBuffers; i++)
{ {
if (SecBuff[i].BufferType == SECBUFFER_DATA && !data) switch(SecBuff[i].BufferType)
data = &SecBuff[i]; {
if (SecBuff[i].BufferType == SECBUFFER_EXTRA && !extra) 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]; 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. //retain the extra. if there's no extra then mark it so.
if (extra) if (extra)
@ -288,17 +303,17 @@ static void SSPI_Encode(sslfile_t *f)
f->outraw.avail = 0; f->outraw.avail = 0;
//fixme: these should be made non-fatal. //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"); SSPI_Error(f, "crypt buffer overflowed\n");
return; 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"); SSPI_Error(f, "crypt buffer overflowed\n");
return; 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"); SSPI_Error(f, "crypt buffer overflowed\n");
return; 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"); SSPI_Error(f, "crypt overflow\n");
return; return;
@ -765,7 +780,12 @@ static int QDECL SSPI_WriteBytes (struct vfsfile_s *file, const void *buffer, in
{ {
sslfile_t *f = (sslfile_t *)file; 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) if (f->handshaking)
{ {

View file

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

View file

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

View file

@ -1,12 +1,5 @@
Microsoft Visual Studio Solution File, Format Version 9.00 Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005 # 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}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "botlib", "botlib.vcproj", "{0018E098-B12A-4E4D-9B22-6772DA287080}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fteqcc", "..\qclib\dotnet2005\qcc.vcproj", "{2866F783-6B44-4655-A38D-D53874037454}" 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 Release|x64 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution 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.ActiveCfg = Release|Win32
{0018E098-B12A-4E4D-9B22-6772DA287080}.D3DDebug|Win32.Build.0 = Release|Win32 {0018E098-B12A-4E4D-9B22-6772DA287080}.D3DDebug|Win32.Build.0 = Release|Win32
{0018E098-B12A-4E4D-9B22-6772DA287080}.D3DDebug|x64.ActiveCfg = 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 #ifndef SERVERONLY
if (!litdata && r_loadlits.value) if (!litdata && r_loadlits.value)
{ {
char *litname; char *litnames[] = {
char litnamemaps[MAX_QPATH]; "maps/%s.lit2",
char litnamelits[MAX_QPATH]; "maps/%s.lit",
int depthmaps; "lits/%s.lit2",
int depthlits; "lits/%s.lit"
};
char litbase[MAX_QPATH];
int depth;
int bestdepth = 0x7fffffff;
int best = -1;
int i;
char litname[MAX_QPATH];
size_t litsize; size_t litsize;
qboolean inhibitvalidation = false; qboolean inhibitvalidation = false;
COM_StripExtension(loadmodel->name, litbase, sizeof(litbase));
for (i = 0; i < sizeof(litnames)/sizeof(litnames[0]); i++)
{ {
Q_strncpyz(litnamemaps, loadmodel->name, sizeof(litnamelits)); Q_snprintfz(litname, sizeof(litname), litnames[i], litbase);
COM_StripExtension(loadmodel->name, litnamemaps, sizeof(litnamemaps)); depth = COM_FDepthFile(litname, false);
COM_DefaultExtension(litnamemaps, ".lit", sizeof(litnamemaps)); if (depth < bestdepth)
depthmaps = COM_FDepthFile(litnamemaps, false);
}
{ {
Q_strncpyz(litnamelits, "lits/", sizeof(litnamelits)); bestdepth = depth;
COM_StripExtension(COM_SkipPath(loadmodel->name), litnamelits+5, sizeof(litnamelits) - 5); best = i;
Q_strncatz(litnamelits, ".lit", sizeof(litnamelits));
depthlits = COM_FDepthFile(litnamelits, false);
} }
}
if (depthmaps <= depthlits) if (best >= 0)
litname = litnamemaps; //maps has priority over lits {
else Q_snprintfz(litname, sizeof(litname), litnames[best], litbase);
litname = litnamelits;
litdata = FS_LoadMallocGroupFile(&loadmodel->memgroup, litname, &litsize); litdata = FS_LoadMallocGroupFile(&loadmodel->memgroup, litname, &litsize);
if (litdata) }
else
{
litdata = NULL;
litsize = 0;
}
if (litdata && litsize >= 8)
{ //validate it, if we loaded one. { //validate it, if we loaded one.
if (litdata[0] != 'Q' || litdata[1] != 'L' || litdata[2] != 'I' || litdata[3] != 'T') 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 *vec;
float s, t, d; float s, t, d;
int sty; int sty;
int w,h; // int w,h;
//output the mesh's indicies //output the mesh's indicies
for (i=0 ; i<mesh->numvertexes-2 ; i++) 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 i;
int s; int s;
int color; int color, color2 = 0xff;
s = NET_GRAPHHEIGHT; s = NET_GRAPHHEIGHT;
if (h == 10000) if (h == 10000 || h<0)
color = 0x6f; // yellow {
color = 0; // yellow
color2 = 1;
h=abs(h);
}
else if (h == 9999) else if (h == 9999)
color = 0x4f; // red {
color = 2; // red
color2 = 3;
}
else if (h == 9998) else if (h == 9998)
color = 0xd0; // blue {
color = 4; // blue
color2 = 5;
}
else else
color = 0xfe; // white {
color = 6; // white
color2 = 7;
}
if (h>s) if (h>s)
h = s; h = s;
for (i=0 ; i<h ; i++) for (i=0 ; i<h ; i++)
if (i & 1) if (i & 1)
ngraph_texels[NET_GRAPHHEIGHT - i - 1][x] = 0xff; ngraph_texels[NET_GRAPHHEIGHT - i - 1][x] = (qbyte)color2;
else else
ngraph_texels[NET_GRAPHHEIGHT - i - 1][x] = (qbyte)color; ngraph_texels[NET_GRAPHHEIGHT - i - 1][x] = (qbyte)color;
for ( ; i<s ; i++) 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 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) void R_NetGraph (void)
{ {
int a, x, i, y; int a, x, i, y;
@ -116,18 +142,23 @@ void R_NetGraph (void)
} }
else else
{ {
int last = 10000;
lost = CL_CalcNet(r_netgraph.value); lost = CL_CalcNet(r_netgraph.value);
for (a=0 ; a<NET_TIMINGS ; a++) for (a=0 ; a<NET_TIMINGS ; a++)
{ {
i = (cl.movesequence-a) & NET_TIMINGSMASK; 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 // now load the netgraph texture into gl and draw it
for (y = 0; y < NET_GRAPHHEIGHT; y++) for (y = 0; y < NET_GRAPHHEIGHT; y++)
for (x = 0; x < NET_TIMINGS; x++) 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 = ((vid.width - 320)>>1);
x=-x; x=-x;

View file

@ -1354,12 +1354,10 @@ static void R_RenderMotionBlur(void)
"}\n" "}\n"
"}\n" "}\n"
); );
// GLBE_RenderToTexture(sceneblur_texture, r_nulltex, r_nulltex, r_nulltex, false); GLBE_FBO_Sources(sceneblur_texture, r_nulltex);
Con_Printf("FIXME: tex_sourcecolour = sceneblur_texture\n");
R2D_ImageColours(1, 1, 1, gl_motionblur.value); 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); 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_RenderToTextureUpdate2d(false);
// GLBE_RenderToTexture(r_nulltex, r_nulltex, r_nulltex, r_nulltex, false);
//grab the current image so we can feed that back into the next frame. //grab the current image so we can feed that back into the next frame.
GL_MTBind(0, GL_TEXTURE_2D, sceneblur_texture); GL_MTBind(0, GL_TEXTURE_2D, sceneblur_texture);
@ -1786,8 +1784,8 @@ void GLR_RenderView (void)
GLBE_FBO_Sources(r_nulltex, r_nulltex); GLBE_FBO_Sources(r_nulltex, r_nulltex);
// if (gl_motionblur.value>0 && gl_motionblur.value < 1 && qglCopyTexImage2D) if (gl_motionblur.value>0 && gl_motionblur.value < 1 && qglCopyTexImage2D)
// R_RenderMotionBlur(); R_RenderMotionBlur();
checkglerror(); checkglerror();
} }

View file

@ -1387,7 +1387,7 @@ static const char *glsl_hdrs[] =
#endif #endif
"}\n" "}\n"
"#else\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)" "vec4 skeletaltransform_wnst(out vec3 w, out vec3 n, out vec3 t, out vec3 b)"
"{" "{"
"n = v_normal;" "n = v_normal;"
@ -1820,8 +1820,12 @@ static GLhandleARB GLSlang_CreateShader (const char *name, int ver, const char *
"#define v_position v_position1\n" "#define v_position v_position1\n"
"#endif\n" "#endif\n"
"uniform mat4 m_modelviewprojection;\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" "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]); length[strings] = strlen(prstrings[strings]);
strings++; strings++;

View file

@ -79,7 +79,7 @@ typedef BOOL (WINAPI *lpfnSetLayeredWindowAttributes)(HWND hwnd, COLORREF crKey,
extern cvar_t vid_conwidth, vid_conautoscale; extern cvar_t vid_conwidth, vid_conautoscale;
#define WINDOW_CLASS_NAME "FTEGLQuake" #define WINDOW_CLASS_NAME L"FTEGLQuake"
#define MAX_MODE_LIST 128 #define MAX_MODE_LIST 128
#define VID_ROW_SIZE 3 #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; int window_center_x, window_center_y, window_x, window_y, window_width, window_height;
RECT window_rect; RECT window_rect;
HMODULE hInstGL = NULL; dllhandle_t *hInstGL = NULL;
HMODULE hInstwgl = NULL; dllhandle_t *hInstwgl = NULL;
static qboolean usingminidriver; static qboolean usingminidriver;
static char reqminidriver[MAX_OSPATH]; static char reqminidriver[MAX_OSPATH];
static char opengldllname[MAX_OSPATH]; static char opengldllname[MAX_OSPATH];
@ -387,7 +387,7 @@ void *getwglfunc(char *name)
if (!hInstwgl) if (!hInstwgl)
{ {
TRACE(("dbg: getwglfunc: explicitly loading opengl32.dll\n", name)); TRACE(("dbg: getwglfunc: explicitly loading opengl32.dll\n", name));
hInstwgl = LoadLibrary("opengl32.dll"); hInstwgl = LoadLibraryA("opengl32.dll");
} }
TRACE(("dbg: getwglfunc: %s: wglgetting\n", name)); TRACE(("dbg: getwglfunc: %s: wglgetting\n", name));
proc = GetProcAddress(hInstwgl, name); proc = GetProcAddress(hInstwgl, name);
@ -459,10 +459,10 @@ qboolean GLInitialise (char *renderer)
{ {
usingminidriver = false; usingminidriver = false;
if (hInstGL) if (hInstGL)
FreeLibrary(hInstGL); Sys_CloseLibrary(hInstGL);
hInstGL=NULL; hInstGL=NULL;
if (hInstwgl) if (hInstwgl)
FreeLibrary(hInstwgl); Sys_CloseLibrary(hInstwgl);
hInstwgl=NULL; hInstwgl=NULL;
Q_strncpyz(reqminidriver, renderer, sizeof(reqminidriver)); Q_strncpyz(reqminidriver, renderer, sizeof(reqminidriver));
@ -471,8 +471,7 @@ qboolean GLInitialise (char *renderer)
if (*renderer && stricmp(renderer, "opengl32.dll") && stricmp(renderer, "opengl32")) if (*renderer && stricmp(renderer, "opengl32.dll") && stricmp(renderer, "opengl32"))
{ {
Con_DPrintf ("Loading renderer dll \"%s\"", renderer); Con_DPrintf ("Loading renderer dll \"%s\"", renderer);
hInstGL = LoadLibrary(opengldllname); hInstGL = Sys_LoadLibrary(opengldllname, NULL);
if (hInstGL) if (hInstGL)
{ {
usingminidriver = true; usingminidriver = true;
@ -490,7 +489,7 @@ qboolean GLInitialise (char *renderer)
strcpy(opengldllname, "opengl32"); strcpy(opengldllname, "opengl32");
Con_DPrintf ("Loading renderer dll \"%s\"", opengldllname); Con_DPrintf ("Loading renderer dll \"%s\"", opengldllname);
emode = SetErrorMode(SEM_FAILCRITICALERRORS); /*no annoying errors if they use glide*/ emode = SetErrorMode(SEM_FAILCRITICALERRORS); /*no annoying errors if they use glide*/
hInstGL = LoadLibrary(opengldllname); hInstGL = Sys_LoadLibrary(opengldllname, NULL);
SetErrorMode(emode); SetErrorMode(emode);
if (hInstGL) if (hInstGL)
@ -766,10 +765,10 @@ qboolean VID_SetWindowedMode (rendererstate_t *info)
WindowRect = centerrect(pleft, ptop, pwidth, pheight, wwidth, wheight); WindowRect = centerrect(pleft, ptop, pwidth, pheight, wwidth, wheight);
// Create the DIB window // Create the DIB window
dibwindow = CreateWindowEx ( dibwindow = CreateWindowExW (
ExWindowStyle, ExWindowStyle,
WINDOW_CLASS_NAME, WINDOW_CLASS_NAME,
FULLENGINENAME, _L(FULLENGINENAME),
WindowStyle, WindowStyle,
WindowRect.left, WindowRect.top, WindowRect.left, WindowRect.top,
WindowRect.right - WindowRect.left, WindowRect.right - WindowRect.left,
@ -797,7 +796,7 @@ qboolean VID_SetWindowedMode (rendererstate_t *info)
av = 70; av = 70;
if (av < 255) if (av < 255)
{ {
HMODULE hm = GetModuleHandle("user32.dll"); HMODULE hm = GetModuleHandleA("user32.dll");
lpfnSetLayeredWindowAttributes pSetLayeredWindowAttributes; lpfnSetLayeredWindowAttributes pSetLayeredWindowAttributes;
pSetLayeredWindowAttributes = (void*)GetProcAddress(hm, "SetLayeredWindowAttributes"); pSetLayeredWindowAttributes = (void*)GetProcAddress(hm, "SetLayeredWindowAttributes");
@ -864,7 +863,9 @@ qboolean VID_SetWindowedMode (rendererstate_t *info)
void GLVID_SetCaption(char *text) 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; wheight = rect.bottom - rect.top;
// Create the DIB window // Create the DIB window
dibwindow = CreateWindowEx ( dibwindow = CreateWindowExW (
ExWindowStyle, ExWindowStyle,
WINDOW_CLASS_NAME, WINDOW_CLASS_NAME,
FULLENGINENAME, _L(FULLENGINENAME),
WindowStyle, WindowStyle,
rect.left, rect.top, rect.left, rect.top,
wwidth, wwidth,
@ -1001,6 +1002,21 @@ static void Win_Touch_Init(HWND wnd);
static qboolean CreateMainWindow(rendererstate_t *info) static qboolean CreateMainWindow(rendererstate_t *info)
{ {
qboolean stat; 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) if (!info->fullscreen)
{ {
TRACE(("dbg: GLVID_SetMode: VID_SetWindowedMode\n")); TRACE(("dbg: GLVID_SetMode: VID_SetWindowedMode\n"));
@ -1032,10 +1048,10 @@ int GLVID_WindowThread(void *cond)
wnd = mainwindow; wnd = mainwindow;
Sys_ConditionSignal(cond); Sys_ConditionSignal(cond);
while (GetMessage(&msg, NULL, 0, 0)) while (GetMessageW(&msg, NULL, 0, 0))
{ {
TranslateMessage (&msg); TranslateMessageW (&msg);
DispatchMessage (&msg); DispatchMessageW (&msg);
//ShowCursor is thread-local. //ShowCursor is thread-local.
if (cursor != mouseshowtoggle) 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. 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]; char systemgl[MAX_OSPATH+1];
GetSystemDirectory(systemgl, sizeof(systemgl)-1); GetSystemDirectoryW(systemglw, countof(systemglw)-1);
strncat(systemgl, "\\", sizeof(systemgl)-1); narrowen(systemgl, sizeof(systemgl), systemglw);
Q_strncatz(systemgl, "\\", sizeof(systemgl));
if (*info->subrenderer) if (*info->subrenderer)
strncat(systemgl, info->subrenderer, sizeof(systemgl)-1); Q_strncatz(systemgl, info->subrenderer, sizeof(systemgl));
else else
strncat(systemgl, "opengl32.dll", sizeof(systemgl)-1); Q_strncatz(systemgl, "opengl32.dll", sizeof(systemgl));
TRACE(("dbg: VID_AttachGL: GLInitialise (system dir specific)\n")); TRACE(("dbg: VID_AttachGL: GLInitialise (system dir specific)\n"));
if (GLInitialise(systemgl)) if (GLInitialise(systemgl))
{ {
@ -1616,7 +1634,7 @@ static void QDECL VID_WndAlpha_Override_Callback(struct cvar_s *var, char *oldva
if (modestate==MS_WINDOWED) if (modestate==MS_WINDOWED)
{ {
int av; int av;
HMODULE hm = GetModuleHandle("user32.dll"); HMODULE hm = GetModuleHandleA("user32.dll");
lpfnSetLayeredWindowAttributes pSetLayeredWindowAttributes; lpfnSetLayeredWindowAttributes pSetLayeredWindowAttributes;
pSetLayeredWindowAttributes = (void*)GetProcAddress(hm, "SetLayeredWindowAttributes"); pSetLayeredWindowAttributes = (void*)GetProcAddress(hm, "SetLayeredWindowAttributes");
@ -2106,7 +2124,7 @@ static BOOL (WINAPI *pCloseTouchInputHandle)(HTOUCHINPUT hTouchInput);
static void Win_Touch_Init(HWND wnd) static void Win_Touch_Init(HWND wnd)
{ {
HMODULE lib; HMODULE lib;
lib = LoadLibrary("user32.dll"); lib = LoadLibraryA("user32.dll");
pRegisterTouchWindow = (void*)GetProcAddress(lib, "RegisterTouchWindow"); pRegisterTouchWindow = (void*)GetProcAddress(lib, "RegisterTouchWindow");
pGetTouchInputInfo = (void*)GetProcAddress(lib, "GetTouchInputInfo"); pGetTouchInputInfo = (void*)GetProcAddress(lib, "GetTouchInputInfo");
pCloseTouchInputHandle = (void*)GetProcAddress(lib, "CloseTouchInputHandle"); pCloseTouchInputHandle = (void*)GetProcAddress(lib, "CloseTouchInputHandle");
@ -2387,7 +2405,7 @@ LONG WINAPI GLMainWndProc (
case WM_CLOSE: case WM_CLOSE:
if (!vid_initializing) 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) MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES)
{ {
Cbuf_AddText("\nquit\n", RESTRICT_LOCAL); Cbuf_AddText("\nquit\n", RESTRICT_LOCAL);
@ -2433,7 +2451,7 @@ LONG WINAPI GLMainWndProc (
lRet = TRUE; lRet = TRUE;
break; break;
default: default:
lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); lRet = DefWindowProcW (hWnd, uMsg, wParam, lParam);
break; break;
} }
break; break;
@ -2446,7 +2464,7 @@ LONG WINAPI GLMainWndProc (
default: default:
/* pass all unhandled messages to DefWindowProc */ /* pass all unhandled messages to DefWindowProc */
lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); lRet = DefWindowProcW (hWnd, uMsg, wParam, lParam);
break; break;
} }
@ -2503,7 +2521,7 @@ void GLVID_DeInit (void)
Cvar_Unhook(&vid_wndalpha); Cvar_Unhook(&vid_wndalpha);
Cmd_RemoveCommand("vid_recenter"); 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; extern int isPlugin;
// qbyte *ptmp; // qbyte *ptmp;
DEVMODE devmode; DEVMODE devmode;
WNDCLASS wc;
memset(&devmode, 0, sizeof(devmode)); 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_DestroyCursor = WIN_DestroyCursor;
rf->VID_SetCursor = WIN_SetCursor; 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_initialized = false;
vid_initializing = true; vid_initializing = true;

View file

@ -542,7 +542,15 @@ static qboolean HTTP_DL_Work(struct dl_download *dl)
} }
if (dl->notifystarted) 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) if (!dl->file)
{ {
@ -853,7 +861,7 @@ void HTTPDL_Establish(struct dl_download *dl)
Q_snprintfz(con->buffer, con->bufferlen, Q_snprintfz(con->buffer, con->bufferlen,
"GET %s HTTP/1.1\r\n" "GET %s HTTP/1.1\r\n"
"Host: %s\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) #if !defined(NPFTE) && defined(AVAIL_ZLIB)
"Accept-Encoding: gzip\r\n" "Accept-Encoding: gzip\r\n"
#endif #endif

View file

@ -142,7 +142,7 @@ struct dl_download
/*not used internally by the backend, but used by HTTP_CL_Get/thread wrapper*/ /*not used internally by the backend, but used by HTTP_CL_Get/thread wrapper*/
struct dl_download *next; 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); void (*notifycomplete) (struct dl_download *dl);
}; };

View file

@ -3385,7 +3385,7 @@ retry:
d16 = ED_FindGlobal16(progfuncs, s); d16 = ED_FindGlobal16(progfuncs, s);
if (!d16) 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); PRHunkFree(progfuncs, hmark);
pr_progs=NULL; pr_progs=NULL;
return false; 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_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 {"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 {"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.")}, {"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_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.")}, {"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); dir = Z_StrDup(dir);
COM_Gamedir (dir); COM_Gamedir (dir, NULL);
Info_SetValueForStarKey (svs.info, "*gamedir", dir, MAX_SERVERINFO_STRING); Info_SetValueForStarKey (svs.info, "*gamedir", dir, MAX_SERVERINFO_STRING);
Z_Free(dir); 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) else if (progstype == PROG_UNKNOWN)
{ { //unknown progs crc. things here are basically hacks.
if (state->effects & 16) if (state->effects & 16) //tenebrae's EF_FULLDYNAMIC
{ {
state->effects &= ~16; state->effects &= ~16;
state->lightpflags |= PFLAGS_FULLDYNAMIC; state->lightpflags |= PFLAGS_FULLDYNAMIC;

View file

@ -1184,6 +1184,10 @@ 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->angles, host_frametime, ent->v->avelocity, ent->v->angles);
VectorMA (ent->v->origin, host_frametime, ent->v->velocity, end); VectorMA (ent->v->origin, host_frametime, ent->v->velocity, end);
#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)
{
trace = World_Move (w, ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NOMONSTERS, (wedict_t*)ent); trace = World_Move (w, ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NOMONSTERS, (wedict_t*)ent);
impact = trace.ent; impact = trace.ent;
if (impact && impact->v->solid == SOLID_PORTAL) if (impact && impact->v->solid == SOLID_PORTAL)
@ -1195,6 +1199,9 @@ static void WPhys_Physics_Noclip (world_t *w, wedict_t *ent)
WPhys_PortalTransform(w, ent, impact, from, move); WPhys_PortalTransform(w, ent, impact, from, move);
VectorAdd(from, move, end); VectorAdd(from, move, end);
} }
}
#endif
VectorCopy(end, ent->v->origin); VectorCopy(end, ent->v->origin);
World_LinkEdict (w, (wedict_t*)ent, false); World_LinkEdict (w, (wedict_t*)ent, false);

View file

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

View file

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