big commit. :(

fix crash from qwplayers with invalid modelindexes
rework allow_skybox a little. now applies immediately.
try to fix the appears-outside-of-map bug, again.
dir *.wav now shows a little extra info on mouse-over.
try loading music file extensions that we expect to be able to play via ffmpeg, not just the ones that are directly supported.
rework the hidden fps_presets, show them with tab completion.
fix a possible crash with r_temporalscenecache
fix lightmap updates on submodels not happening properly with the scenecache.
fix the serious memory leak with scenecache.
add r_glsl_pbr cvar to force use of pbr pathways in our glsl.
fix bug in alsa output not supporting float output properly.
preliminary work to have the mixer use floating point mixing. disabled for now.
try to update sys_register_file_associations on linux, still needs work though.
try to work around nquake's config quirks, so config files don't get overwritten.
repackage quake's conchars in order to add padding. this should avoid extra junk on the outside of glyphs.
give fteqcc(commandline version) some extra package extration/creation support. our paks should be more end-user-friendly, and our spanned pk3s are awesome.
write rune state to legacy saved games, so we don't ever have the missing-runes bug ever again...



git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5780 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2020-10-26 06:30:35 +00:00
parent 0ceff5a31d
commit 4d25c073ec
60 changed files with 1733 additions and 839 deletions

View file

@ -2018,11 +2018,11 @@ m-profile:
_qcc-tmp: $(REQDIR)
@$(MAKE) $(TYPE) EXE_NAME="$(EXE_NAME)$(EXEPOSTFIX)" PRECOMPHEADERS="" OUT_DIR="$(OUT_DIR)" WCFLAGS="$(CLIENT_ONLY_CFLAGS) $(WCFLAGS)" LDFLAGS="$(LDFLAGS) $(QCC_LDFLAGS)" OBJS="QCC_OBJS SOBJS"
qcc-rel:
@$(MAKE) _qcc-tmp TYPE=_out-rel REQDIR=reldir EXE_NAME="../fteqcc$(BITS)" OUT_DIR="$(RELEASE_DIR)/$(NCDIRPREFIX)$(QCC_DIR)" SOBJS="qcctui.o $(if $(findstring win,$(FTE_TARGET)),fteqcc.o)"
@$(MAKE) _qcc-tmp TYPE=_out-rel REQDIR=reldir EXE_NAME="../fteqcc$(BITS)" OUT_DIR="$(RELEASE_DIR)/$(NCDIRPREFIX)$(QCC_DIR)" SOBJS="qcctui.o packager.o $(if $(findstring win,$(FTE_TARGET)),fteqcc.o)"
qccgui-rel:
@$(MAKE) _qcc-tmp TYPE=_out-rel REQDIR=reldir EXE_NAME="../fteqccgui$(BITS)" LTO= OUT_DIR="$(RELEASE_DIR)/$(NCDIRPREFIX)$(QCC_DIR)gui" SOBJS="qccgui.o qccguistuff.o packager.o decomp.o fteqcc.o" LDFLAGS="$(LDFLAGS) -lole32 -lcomdlg32 -lcomctl32 -lshlwapi -mwindows"
qcc-dbg:
@$(MAKE) _qcc-tmp TYPE=_out-dbg REQDIR=debugdir EXE_NAME="../fteqcc$(BITS)" OUT_DIR="$(DEBUG_DIR)/$(NCDIRPREFIX)$(QCC_DIR)" SOBJS="qcctui.o $(if $(findstring win,$(FTE_TARGET)),fteqcc.o)"
@$(MAKE) _qcc-tmp TYPE=_out-dbg REQDIR=debugdir EXE_NAME="../fteqcc$(BITS)" OUT_DIR="$(DEBUG_DIR)/$(NCDIRPREFIX)$(QCC_DIR)" SOBJS="qcctui.o packager.o $(if $(findstring win,$(FTE_TARGET)),fteqcc.o)"
qccgui-dbg:
@$(MAKE) _qcc-tmp TYPE=_out-dbg REQDIR=debugdir EXE_NAME="../fteqccgui$(BITS)" LTO= OUT_DIR="$(DEBUG_DIR)/$(NCDIRPREFIX)$(QCC_DIR)gui" SOBJS="qccgui.o qccguistuff.o packager.o decomp.o fteqcc.o" LDFLAGS="$(LDFLAGS) -lole32 -lcomdlg32 -lcomctl32 -lshlwapi -mwindows"

View file

@ -5199,7 +5199,7 @@ void CL_LinkPlayers (void)
continue;
#endif
if (info->spectator)
if (info->spectator || state->modelindex >= countof(cl.model_precache))
continue;
//the extra modelindex check is to stop lame mods from using vweps with rings

View file

@ -2280,7 +2280,8 @@ void CL_CheckServerInfo(void)
qboolean spectating = true;
int i;
qboolean oldwatervis = cls.allow_watervis;
int oldskyboxes = cls.allow_unmaskedskyboxes;
//spectator 2 = spectator-with-scores, considered to be players. this means we don't want to allow spec cheats while they're inactive, because that would be weird.
for (i = 0; i < cl.splitclients; i++)
if (cl.playerview[i].spectator != 1)
@ -2291,7 +2292,7 @@ void CL_CheckServerInfo(void)
cls.allow_cheats = false;
cls.allow_semicheats=true;
cls.allow_skyboxes=false;
cls.allow_unmaskedskyboxes=false;
cls.allow_fbskins = 1;
// cls.allow_fbskins = 0;
// cls.allow_overbrightlight;
@ -2306,8 +2307,12 @@ void CL_CheckServerInfo(void)
else
cls.allow_watervis=false;
if (spectating || cls.demoplayback || atoi(InfoBuf_ValueForKey(&cl.serverinfo, "allow_skybox")) || atoi(InfoBuf_ValueForKey(&cl.serverinfo, "allow_skyboxes")))
cls.allow_skyboxes=true; //mostly obsolete.
s = InfoBuf_ValueForKey(&cl.serverinfo, "allow_skybox");
if (!*s)
s = InfoBuf_ValueForKey(&cl.serverinfo, "allow_skyboxes");
if (!*s)
cls.allow_unmaskedskyboxes = (cl.worldmodel && cl.worldmodel->fromgame != fg_quake);
else cls.allow_unmaskedskyboxes = !!atoi(s);
s = InfoBuf_ValueForKey(&cl.serverinfo, "fbskins");
if (*s)
@ -2409,7 +2414,7 @@ void CL_CheckServerInfo(void)
// if (allowed & 2)
// cls.allow_rearview = true;
if (allowed & 4)
cls.allow_skyboxes = true;
cls.allow_unmaskedskyboxes = true;
// if (allowed & 8)
// cls.allow_mirrors = true;
//16
@ -2480,7 +2485,7 @@ void CL_CheckServerInfo(void)
if (oldteamplay != cl.teamplay)
Skin_FlushPlayers();
if (oldwatervis != cls.allow_watervis)
if (oldwatervis != cls.allow_watervis || oldskyboxes != cls.allow_unmaskedskyboxes)
Shader_NeedReload(false);
CSQC_ServerInfoChanged();
@ -5885,45 +5890,66 @@ qboolean Host_RunFile(const char *fname, int nlen, vfsfile_t *file)
}
else
#endif
{
if (nlen >= 5 && !strncmp(fname, "qw://", 5))
{ //this is also implemented by ezquake, so be careful here...
//"qw://[stream@]host[:port]/COMMAND" join, spectate, qtvplay
char *t, *cmd;
const char *url;
char buffer[8192];
t = Z_Malloc(nlen+1);
memcpy(t, fname, nlen);
t[nlen] = 0;
url = t+5;
{ //this is also implemented by ezquake, so be careful here...
//"qw://[stream@]host[:port]/COMMAND" join, spectate, qtvplay
char *t, *cmd;
const char *url;
char buffer[8192];
t = Z_Malloc(nlen+1);
memcpy(t, fname, nlen);
t[nlen] = 0;
url = t+5;
for (cmd = t+5; *cmd; cmd++)
{
if (*cmd == '/')
for (cmd = t+5; *cmd; cmd++)
{
*cmd++ = 0;
break;
if (*cmd == '/')
{
*cmd++ = 0;
break;
}
}
//quote the url safely.
url = COM_QuotedString(url, buffer, sizeof(buffer), false);
//now figure out what the command actually was
if (!Q_strcasecmp(cmd, "join"))
Cbuf_AddText(va("join %s\n", url), RESTRICT_LOCAL);
else if (!Q_strcasecmp(cmd, "spectate") || !strcmp(cmd, "observe"))
Cbuf_AddText(va("observe %s\n", url), RESTRICT_LOCAL);
else if (!Q_strcasecmp(cmd, "qtvplay"))
Cbuf_AddText(va("qtvplay %s\n", url), RESTRICT_LOCAL);
else if (!*cmd || !Q_strcasecmp(cmd, "connect"))
Cbuf_AddText(va("connect %s\n", url), RESTRICT_LOCAL);
else
Con_Printf("Unknown url command: %s\n", cmd);
if(file)
VFS_CLOSE(file);
Z_Free(t);
return true;
}
//quote the url safely.
url = COM_QuotedString(url, buffer, sizeof(buffer), false);
//now figure out what the command actually was
if (!Q_strcasecmp(cmd, "join"))
Cbuf_AddText(va("join %s\n", url), RESTRICT_LOCAL);
else if (!Q_strcasecmp(cmd, "spectate") || !strcmp(cmd, "observe"))
Cbuf_AddText(va("observe %s\n", url), RESTRICT_LOCAL);
else if (!Q_strcasecmp(cmd, "qtvplay"))
Cbuf_AddText(va("qtvplay %s\n", url), RESTRICT_LOCAL);
else if (!*cmd || !Q_strcasecmp(cmd, "connect"))
Cbuf_AddText(va("connect %s\n", url), RESTRICT_LOCAL);
else
Con_Printf("Unknown url command: %s\n", cmd);
if(file)
VFS_CLOSE(file);
Z_Free(t);
return true;
{
const char *netschemes[] = {"udp://", "udp4//", "udp6//", "ipx://", "tcp://", "tcp4//", "tcp6//", "spx://", "ws://", "wss://", "tls://", "dtls://", "ice://", "rtc://", "ices://", "rtcs://", "irc://", "udg://", "unix://"};
int i;
size_t slen;
for (i = 0; i < countof(netschemes); i++)
{
slen = strlen(netschemes[i]);
if (nlen >= slen && !strncmp(fname, netschemes[i], slen))
{
char quoted[8192];
char *t = Z_Malloc(nlen+1);
memcpy(t, fname, nlen);
t[nlen] = 0;
Cbuf_AddText(va("connect %s\n", COM_QuotedString(t, quoted, sizeof(quoted), false)), RESTRICT_LOCAL);
Z_Free(t);
}
}
}
}
f = Z_Malloc(sizeof(*f) + nlen);

View file

@ -891,6 +891,7 @@ void CL_PredictEntityMovement(entity_state_t *estate, float age)
VectorClear(startstate.velocity);
startstate.onground = false;
startstate.jump_held = false;
startstate.flags = 0;
CL_EntStateToPlayerState(&startstate, estate);
CL_EntStateToPlayerCommand(&cmd, estate, age);
@ -1174,6 +1175,8 @@ void CL_PredictMovePNum (int seat)
{
packet_entities_t *pe;
pe = &cl.inframes[from.frame & UPDATE_MASK].packet_entities;
if (!pe->num_entities && !from.frame)
pe = &cl.inframes[to.frame & UPDATE_MASK].packet_entities;
for (i = 0; i < pe->num_entities; i++)
{
if (pe->entities[i].number == trackent)

View file

@ -222,7 +222,7 @@ qboolean scr_drawloading;
float scr_disabled_time;
cvar_t con_stayhidden = CVARFD("con_stayhidden", "1", CVAR_NOTFROMSERVER, "0: allow console to pounce on the user\n1: console stays hidden unless explicitly invoked\n2:toggleconsole command no longer works\n3: shift+escape key no longer works");
cvar_t show_fps = CVARFD("show_fps", "0", CVAR_ARCHIVE, "Displays the current framerate on-screen.\n0: Off.\n1: framerate average over a second.\n2: Show a frametimes graph (with additional timing info).\n-1: Normalized graph that focuses on the variation ignoring base times.");
cvar_t show_fps = CVARAFD("show_fps"/*qw*/, "0", "scr_showfps"/*qs*/, CVAR_ARCHIVE, "Displays the current framerate on-screen.\n0: Off.\n1: framerate average over a second.\n2: Show a frametimes graph (with additional timing info).\n-1: Normalized graph that focuses on the variation ignoring base times.");
cvar_t show_fps_x = CVAR("show_fps_x", "-1");
cvar_t show_fps_y = CVAR("show_fps_y", "-1");
cvar_t show_clock = CVAR("cl_clock", "0");

View file

@ -527,8 +527,8 @@ typedef struct
float latency; // rolling average
char allow_unmaskedskyboxes; //skyboxes/domes do not need to be depth-masked when set. FIXME: we treat this as an optimisation hint, but some hl/q2/q3 maps require strict do-not-mask rules to look right.
qboolean allow_anyparticles;
qboolean allow_skyboxes; //skyboxes/domes do not need to be depth-masked when set. FIXME: we treat this as an optimisation hint, but some hl/q2/q3 maps require strict do-not-mask rules to look right.
qboolean allow_watervis; //fixme: not checked any more
float allow_fbskins; //fraction of allowance
qboolean allow_cheats;

View file

@ -2770,6 +2770,8 @@ static void Con_DrawMouseOver(console_t *mouseconsole)
char *tiptext = NULL;
shader_t *shader = NULL;
model_t *model = NULL;
sfx_t *audio = NULL;
char *mouseover;
if (!mouseconsole->mouseover || !mouseconsole->mouseover(mouseconsole, &tiptext, &shader))
{
@ -2856,17 +2858,25 @@ static void Con_DrawMouseOver(console_t *mouseconsole)
if (model->loadstate != MLS_LOADED)
model = NULL;
}
key = Info_ValueForKey(info, "playaudio");
if (*key)
{
audio = S_PrecacheSound(key);
if (audio && audio->loadstate != SLS_LOADED)
audio = NULL;
}
}
tiptext = Info_ValueForKey(info, "tip");
}
Z_Free(mouseover);
}
}
if ((tiptext && *tiptext) || shader || model)
if ((tiptext && *tiptext) || shader || model || audio)
{
//FIXME: draw a proper background.
//FIXME: support line breaks.
conchar_t buffer[2048], *starts[64], *ends[countof(starts)];
conchar_t buffer[2048], *starts[64], *ends[countof(starts)], *eot;
int lines, i, px, py;
float tw, th;
float ih = 0, iw = 0;
@ -2874,7 +2884,30 @@ static void Con_DrawMouseOver(console_t *mouseconsole)
float y = mousecursor_y+8;
Font_BeginString(font_console, x, y, &px, &py);
lines = Font_LineBreaks(buffer, COM_ParseFunString(CON_WHITEMASK, tiptext, buffer, sizeof(buffer), false), (256.0 * vid.pixelwidth) / vid.width, countof(starts), starts, ends);
eot = COM_ParseFunString(CON_WHITEMASK, tiptext, buffer, sizeof(buffer), false);
if (audio)
{
struct sfxcache_s cache;
char name[MAX_OSPATH];
float len;
*name = 0;
len = audio->decoder.querydata?audio->decoder.querydata(audio, &cache, name, sizeof(name)):-1;
if (len >= 0)
{
eot = COM_ParseFunString(CON_WHITEMASK, va("\n\n%s\n%gkhz, %s, %ibit, %g seconds%s",
name, cache.speed/1000.0, cache.numchannels==1?"mono":"stereo", QAF_BYTES(cache.format)*8, len, audio->loopstart>=0?" looped":""
), eot, sizeof(buffer)-((char*)eot-(char*)buffer), false);
}
else
{
cache = *(struct sfxcache_s *)audio->decoder.buf;
len = (double)cache.length / cache.speed;
eot = COM_ParseFunString(CON_WHITEMASK, va("\n\n\n%gkhz, %s, %ibit, %g seconds%s",
cache.speed/1000.0, cache.numchannels==1?"mono":"stereo", QAF_BYTES(cache.format)*8, len, audio->loopstart>=0?" looped":""
), eot, sizeof(buffer)-((char*)eot-(char*)buffer), false);
}
}
lines = Font_LineBreaks(buffer, eot, (256.0 * vid.pixelwidth) / vid.width, countof(starts), starts, ends);
th = (Font_CharHeight()*lines * vid.height) / vid.pixelheight;
if (model)

View file

@ -4812,7 +4812,7 @@ qboolean Image_WriteKTXFile(const char *filename, enum fs_relative fsroot, struc
Image_BlockSizeForEncoding(mips->encoding, &bb, &bw, &bh, &bd);
switch(mips->encoding)
safeswitch(mips->encoding)
{
case PTI_ETC1_RGB8: header.glinternalformat = 0x8D64/*GL_ETC1_RGB8_OES*/; break;
case PTI_ETC2_RGB8: header.glinternalformat = 0x9274/*GL_COMPRESSED_RGB8_ETC2*/; break;
@ -4933,6 +4933,7 @@ qboolean Image_WriteKTXFile(const char *filename, enum fs_relative fsroot, struc
case PTI_R16F: header.glinternalformat = 0x822D/*GL_R16F*/; header.glbaseinternalformat = 0x1903/*GL_RED*/; header.glformat = 0x1903/*GL_RED*/; header.gltype = 0x140B/*GL_HALF_FLOAT*/; header.gltypesize = 2; break;
case PTI_R32F: header.glinternalformat = 0x822E/*GL_R32F*/; header.glbaseinternalformat = 0x1903/*GL_RED*/; header.glformat = 0x1903/*GL_RED*/; header.gltype = 0x1406/*GL_FLOAT*/; header.gltypesize = 4; break;
case PTI_RGBA16F: header.glinternalformat = 0x881A/*GL_RGBA16F*/; header.glbaseinternalformat = 0x1908/*GL_RGBA*/; header.glformat = 0x1908/*GL_RGBA*/; header.gltype = 0x140B/*GL_HALF_FLOAT*/; header.gltypesize = 2; break;
case PTI_RGB32F: header.glinternalformat = 0x8815/*GL_RGB32F*/; header.glbaseinternalformat = 0x1907/*GL_RGB*/; header.glformat = 0x1907/*GL_RGB*/; header.gltype = 0x1406/*GL_FLOAT*/; header.gltypesize = 4; break;
case PTI_RGBA32F: header.glinternalformat = 0x8814/*GL_RGBA32F*/; header.glbaseinternalformat = 0x1908/*GL_RGBA*/; header.glformat = 0x1908/*GL_RGBA*/; header.gltype = 0x1406/*GL_FLOAT*/; header.gltypesize = 4; break;
case PTI_A2BGR10: header.glinternalformat = 0x8059/*GL_RGB10_A2*/; header.glbaseinternalformat = 0x1908/*GL_RGBA*/; header.glformat = 0x1908/*GL_RGBA*/; header.gltype = 0x8368/*GL_UNSIGNED_INT_2_10_10_10_REV*/; header.gltypesize = 4; break;
case PTI_E5BGR9: header.glinternalformat = 0x8C3D/*GL_RGB9_E5*/; header.glbaseinternalformat = 0x8C3D/*GL_RGB9_E5*/; header.glformat = 0x1907/*GL_RGB*/; header.gltype = 0x8C3E/*GL_UNSIGNED_INT_5_9_9_9_REV*/; header.gltypesize = 4; break;
@ -4956,7 +4957,6 @@ qboolean Image_WriteKTXFile(const char *filename, enum fs_relative fsroot, struc
case PTI_DEPTH32: header.glinternalformat = 0x81A7/*GL_DEPTH_COMPONENT32*/; header.glbaseinternalformat = 0x1902/*GL_DEPTH_COMPONENT*/; header.glformat = 0x1902/*GL_DEPTH_COMPONENT*/; header.gltype = 0x1406/*GL_FLOAT*/; header.gltypesize = 4; break;
case PTI_DEPTH24_8: header.glinternalformat = 0x88F0/*GL_DEPTH24_STENCIL8*/; header.glbaseinternalformat = 0x84F9/*GL_DEPTH_STENCIL*/; header.glformat = 0x84F9/*GL_DEPTH_STENCIL*/; header.gltype = 0x84FA/*GL_UNSIGNED_INT_24_8*/; header.gltypesize = 4; break;
case PTI_RGB32F:
#ifdef FTE_TARGET_WEB
case PTI_WHOLEFILE:
#endif
@ -4964,8 +4964,8 @@ qboolean Image_WriteKTXFile(const char *filename, enum fs_relative fsroot, struc
case PTI_MAX:
return false;
// default:
// return;
safedefault:
return false;
}
if (strchr(filename, '*') || strchr(filename, ':'))
@ -5142,6 +5142,7 @@ static struct pendingtextureinfo *Image_ReadKTXFile(unsigned int flags, const ch
case 0x8040/*GL_LUMINANCE8*/: encoding = PTI_L8; break;
case 0x8045/*GL_LUMINANCE8_ALPHA8*/: encoding = PTI_L8A8; break;
case 0x881A/*GL_RGBA16F_ARB*/: encoding = PTI_RGBA16F; break;
case 0x8815/*GL_RGB32F_ARB*/: encoding = PTI_RGB32F; break;
case 0x8814/*GL_RGBA32F_ARB*/: encoding = PTI_RGBA32F; break;
case 0x8059/*GL_RGB10_A2*/: encoding = PTI_A2BGR10; break;
case 0x8229/*GL_R8*/: encoding = PTI_R8; break;
@ -5200,6 +5201,10 @@ static struct pendingtextureinfo *Image_ReadKTXFile(unsigned int flags, const ch
else if (header.glformat == 0x80E1/*GL_BGRA*/ && header.gltype == 0x8365/*GL_UNSIGNED_SHORT_4_4_4_4_REV*/)
encoding = PTI_ARGB4444;
break;
default:
encoding = TF_INVALID;
break;
}
if (encoding == TF_INVALID)
{
@ -6065,7 +6070,7 @@ qboolean Image_WriteDDSFile(const char *filename, enum fs_relative fsroot, struc
#define DX9RGBA (0x40|0x1)
#define DX9LUM 0x20000
#define DX9LUMALPHA (0x20000|0x1)
switch(mips->encoding)
safeswitch(mips->encoding)
{
// case PTI_INVALID: h10.dxgiformat = 0x0/*DXGI_FORMAT_UNKNOWN*/; break;
// case PTI_INVALID: h10.dxgiformat = 0x1/*DXGI_FORMAT_R32G32B32A32_TYPELESS*/; break;
@ -6298,10 +6303,8 @@ qboolean Image_WriteDDSFile(const char *filename, enum fs_relative fsroot, struc
case PTI_MAX:
return false;
#ifndef _DEBUG
// default: //don't enable in debug builds, so we get warnings for any cases being missed.
// return false;
#endif
safedefault: //don't enable in debug builds, so we get warnings for any cases being missed.
return false;
}
//truncate the mip chain if they're dodgy sizes.

View file

@ -352,6 +352,20 @@ qboolean Media_CleanupTrackName(const char *track, int *out_track, char *result,
".mp3",
#endif
".wav",
#if defined(PLUGINS) //ffmpeg plugin? woo.
#if !(defined(AVAIL_OGGOPUS) || defined(FTE_TARGET_WEB))
".opus", //opus might be the future, but ogg is the present
#endif
#if !(defined(AVAIL_OGGVORBIS) || defined(FTE_TARGET_WEB))
".ogg",
#endif
#if !(defined(AVAIL_MP3_ACM) || defined(FTE_TARGET_WEB))
".mp3",
#endif
".flac", //supported by QS at least.
//".s3m", //some variant of mod that noone cares about. listed because of qs.
//".umx", //wtf? qs is weird.
#endif
NULL
};
unsigned int tracknum;

View file

@ -703,7 +703,7 @@ void M_Menu_Audio_f (void)
MB_SLIDER("Volume", volume, 0, 1, 0.1, NULL),
MB_COMBOCVAR("Speaker Setup", snd_speakers, speakeroptions, speakervalues, NULL),
MB_COMBOCVAR("Frequency", snd_khz, soundqualityoptions, soundqualityvalues, NULL),
MB_CHECKBOXCVAR("Low Quality (8-bit)", loadas8bit, 0),
MB_CHECKBOXCVAR("Low Quality (8-bit)", snd_loadas8bit, 0),
MB_CHECKBOXCVAR("Flip Speakers", snd_leftisright, 0),
MB_SLIDER("Mixahead", _snd_mixahead, 0, 1, 0.05, NULL),
MB_CHECKBOXCVAR("Disable All Sounds", nosound, 0),
@ -795,7 +795,7 @@ void M_Menu_Particles_f (void)
"highfps",
"spikeset",
"spikeset tsshaft",
"spikeset high tsshaft",
"high tsshaft",
"minimal",
NULL
};
@ -1052,6 +1052,116 @@ const char *presetexec[] =
//end 'realtime'
};
struct
{
const char *name;
const char *desc;
const char *settings;
} builtinpresets[] =
{
{ "hdr",
"Don't let colour depth stop you!",
"set vid_srgb 2\n"
"set r_hdr_irisadaptation 1\n"
},
{ "shib",
"Performance optimisations for large/detailed maps.",
"if r_dynamic >= 1\n"
"{\n" //fake it anyway.
"set r_shadow_realtime_dlight 1\n"
"set r_shadow_realtime_dlight_shadows 0\n"
"set r_dynamic 0\n"
"}\n"
"set r_temporalscenecache 1\n" //the main speedup.
"set r_lightstylespeed 0\n" //FIXME: we shouldn't need this, but its too stuttery without.
"set sv_autooffload 1\n" //Needs polish still.
"set gl_pbolightmaps 1\n" //FIXME: this needs to be the default eventually.
},
{ "qw",
"Enable QuakeWorld-isms, for better gameplay.",
"set sv_nqplayerphysics 0\n"
"set sv_gameplayfix_multiplethinks 1\n"
},
{ "nq"
"Disable QuakeWorld-isms, for nq mod compat.",
"set sv_nqplayerphysics 1\n"
"set sv_gameplayfix_multiplethinks 0\n"
},
{ "dp",
"Reconfigures FTE to mimic DP for compat reasons.",
"if $server then echo Be sure to restart your server\n"
"fps_preset nq\n"
//these are for smc+derived mods
"sv_listen_dp 1\n" //awkward, but forces the server to load the effectinfo.txt in advance.
"sv_bigcoords 1\n" //for viewmodel lep precision (would be better to use csqc)
"r_particledesc \"effectinfo high\"\n" //blurgh.
"dpcompat_noretouchground 1\n" //don't call touch functions on entities that already appear onground. this also changes the order that the onground flag is set relative to touch functions.
"cl_nopred 1\n" //DP doesn't predict by default, and DP mods have a nasty habit of clearing .solid values during prethinks, which screws up prediction. so play safe.
"r_dynamic 0\nr_shadow_realtime_dlight 1\n" //fte has separate cvars for everything. which kinda surprises people and makes stuff twice as bright as it should be.
"r_coronas_intensity 0.25\n"
"con_logcenterprint 0\n" //kinda annoying....
"scr_fov_mode 4\n" //for fairer framerate comparisons
//general compat stuff
"dpcompat_console 1\n" //
"dpcompat_findradiusarealinks 1\n" //faster findradiuses (but that require things are setorigined properly)
"dpcompat_makeshitup 2\n" //flatten shaders to a single pass, then add new specular etc passes.
//"dpcompat_nopremulpics 1\n" //don't use premultiplied alpha (solving issues with compressed image formats)
"dpcompat_psa_ungroup 1\n" //don't use framegroups with psk models at all.
"dpcompat_set 1\n" //handle 3-arg sets differently
"dpcompat_stats 1\n" //truncate float stats
"dpcompat_strcat_limit 16383\n" //xonotic compat. maximum length of strcat strings.
// "sv_listen_dp 1\nsv_listen_nq 0\nsv_listen_qw 0\ncl_loopbackprotocol dpp7\ndpcompat_nopreparse 1\n"
},
{ "tenebrae",
"Reconfigures FTE to mimic Tenebrae for compat/style reasons.",
//for the luls. combine with the tenebrae mod for maximum effect.
"fps_preset nq\n"
"set r_shadow_realtime_world 1\n"
"set r_shadow_realtime_dlight 1\n"
"set r_shadow_bumpscale_basetexture 4\n"
"set r_shadow_shadowmapping 0\n"
"set gl_specular 1\n"
"set gl_specular_power 16\n"
"set gl_specular_fallback 1\n"
"set mod_litsprites_force 1\n"
"set r_nolerp 1\n" //well, that matches tenebrae. for the luls, right?
},
{ "timedemo",
"Reconfigure some stuff to get through timedemos really fast. Some people might consider this cheating.",
//some extra things to pwn timedemos.
"fps_preset fast\n"
"set r_renderscale 1\n"
"set contrast 1\n"
"set gamma 1\n"
"set brightness 0\n"
"set scr_autoid 0\n"
"set scr_autoid_team 0\n"
"set r_dynamic 0\n"
"set sbar_teamstatus 2\n"
"set gl_polyblend 0\n"
#if 1
//these are cheaty settings.
"set gl_flashblend 0\n"
"set cl_predict_players 0\n" //very cheaty. you won't realise its off, but noone would disable it for actual play.
#else
//to make things fair
"set gl_flashblend 1\n"
"set r_part_density 1\n"
#endif
},
};
typedef struct fpsmenuinfo_s
{
menucombo_t *preset;
@ -1159,125 +1269,6 @@ void FPS_Preset_f (void)
}
}
if (!stricmp("hdr", arg))
{
Cbuf_InsertText(
"set vid_srgb 2\n"
"set r_hdr_irisadaptation 1\n"
, RESTRICT_LOCAL, false);
return;
}
if (!stricmp("shib", arg))
{
Cbuf_InsertText(
"if r_dynamic >= 1\n"
"{\n" //fake it anyway.
"set r_shadow_realtime_dlight 1\n"
"set r_shadow_realtime_dlight_shadows 0\n"
"set r_dynamic 0\n"
"}\n"
"set r_temporalscenecache 1\n" //the main speedup.
"set r_lightstylespeed 0\n" //FIXME: we shouldn't need this, but its too stuttery without.
"set sv_autooffload 1\n" //Needs polish still.
"set gl_pbolightmaps 1\n" //FIXME: this needs to be the default eventually.
, RESTRICT_LOCAL, false);
return;
}
if (!stricmp("qw", arg))
{ //enable qwisms
Cbuf_InsertText(
"set sv_nqplayerphysics 0\n"
"set sv_gameplayfix_multiplethinks 1\n"
, RESTRICT_LOCAL, false);
return;
}
if (!stricmp("nq", arg))
{ //disable qwisms, for better mod compat
Cbuf_InsertText(
"set sv_nqplayerphysics 1\n"
"set sv_gameplayfix_multiplethinks 0\n"
, RESTRICT_LOCAL, false);
return;
}
if (!stricmp("dp", arg))
{
#ifdef HAVE_SERVER
if (sv.state)
Cbuf_InsertText("echo Be sure to restart your server\n", RESTRICT_LOCAL, false);
#endif
Cbuf_InsertText(
"fps_preset nq\n"
//these are for smc+derived mods
"sv_listen_dp 1\n" //awkward, but forces the server to load the effectinfo.txt in advance.
"sv_bigcoords 1\n" //for viewmodel lep precision (would be better to use csqc)
"r_particledesc \"effectinfo high\"\n" //blurgh.
"dpcompat_noretouchground 1\n" //don't call touch functions on entities that already appear onground. this also changes the order that the onground flag is set relative to touch functions.
"cl_nopred 1\n" //DP doesn't predict by default, and DP mods have a nasty habit of clearing .solid values during prethinks, which screws up prediction. so play safe.
"r_dynamic 0\nr_shadow_realtime_dlight 1\n" //fte has separate cvars for everything. which kinda surprises people and makes stuff twice as bright as it should be.
"r_coronas_intensity 0.25\n"
"con_logcenterprint 0\n" //kinda annoying....
"scr_fov_mode 4\n" //for fairer framerate comparisons
//general compat stuff
"dpcompat_console 1\n" //
"dpcompat_findradiusarealinks 1\n" //faster findradiuses (but that require things are setorigined properly)
"dpcompat_makeshitup 2\n" //flatten shaders to a single pass, then add new specular etc passes.
//"dpcompat_nopremulpics 1\n" //don't use premultiplied alpha (solving issues with compressed image formats)
"dpcompat_psa_ungroup 1\n" //don't use framegroups with psk models at all.
"dpcompat_set 1\n" //handle 3-arg sets differently
"dpcompat_stats 1\n" //truncate float stats
"dpcompat_strcat_limit 16383\n" //xonotic compat. maximum length of strcat strings.
// "sv_listen_dp 1\nsv_listen_nq 0\nsv_listen_qw 0\ncl_loopbackprotocol dpp7\ndpcompat_nopreparse 1\n"
, RESTRICT_LOCAL, false);
return;
}
if (!stricmp("tenebrae", arg))
{ //for the luls. combine with the tenebrae mod for maximum effect.
Cbuf_InsertText(
"fps_preset nq\n"
"set r_shadow_realtime_world 1\n"
"set r_shadow_realtime_dlight 1\n"
"set r_shadow_bumpscale_basetexture 4\n"
"set r_shadow_shadowmapping 0\n"
"set gl_specular 1\n"
"set gl_specular_power 16\n"
"set gl_specular_fallback 1\n"
"set mod_litsprites_force 1\n"
"set r_nolerp 1\n" //well, that matches tenebrae. for the luls, right?
, RESTRICT_LOCAL, false);
return;
}
if (!stricmp("timedemo", arg))
{
//some extra things to pwn timedemos.
Cbuf_InsertText(
"fps_preset fast\n"
"set r_renderscale 1\n"
"set contrast 1\n"
"set gamma 1\n"
"set brightness 0\n"
"set scr_autoid 0\n"
"set scr_autoid_team 0\n"
"set r_dynamic 0\n"
"set sbar_teamstatus 2\n"
"set gl_polyblend 0\n"
#if 1
//these are cheaty settings.
"set gl_flashblend 0\n"
"set cl_predict_players 0\n" //very cheaty. you won't realise its off, but noone would disable it for actual play.
#else
//to make things fair
"set gl_flashblend 1\n"
"set r_part_density 1\n"
#endif
, RESTRICT_LOCAL, false);
return;
}
for (i = 0; i < PRESET_NUM; i++)
{
if (!stricmp(presetname[i], arg))
@ -1287,10 +1278,53 @@ void FPS_Preset_f (void)
}
}
for (i = 0; i < countof(builtinpresets); i++)
{
if (!stricmp(builtinpresets[i].name, arg))
{
if (doreload)
Cbuf_InsertText("\nfs_restart\nvid_reload\n", RESTRICT_LOCAL, false);
Cbuf_InsertText(builtinpresets[i].settings, RESTRICT_LOCAL, false);
return;
}
}
Con_Printf("Preset %s not recognised\n", arg);
Con_Printf("Valid presests:\n");
for (i = 0; i < PRESET_NUM; i++)
Con_Printf("%s\n", presetname[i]);
for (i = 0; i < countof(builtinpresets); i++)
Con_DPrintf("%s\n", builtinpresets[i].name);
}
static int QDECL CompletePresetList (const char *name, qofs_t flags, time_t mtime, void *parm, searchpathfuncs_t *spath)
{
struct xcommandargcompletioncb_s *ctx = parm;
if (!Q_strncasecmp(name, "configs/preset_", 15))
{
char preset[MAX_QPATH];
COM_StripExtension(name+15, preset, sizeof(preset));
ctx->cb(preset, NULL, NULL, ctx);
}
return true;
}
void FPS_Preset_c(int argn, const char *partial, struct xcommandargcompletioncb_s *ctx)
{
if (argn == 1)
{
int i;
size_t partiallen = strlen(partial);
COM_EnumerateFiles(va("configs/preset_%s*.cfg", partial), CompletePresetList, ctx);
for (i = 0; i < PRESET_NUM; i++)
if (!Q_strncasecmp(partial, presetname[i], partiallen))
ctx->cb(presetname[i], NULL, NULL, ctx);
for (i = 0; i < countof(builtinpresets); i++)
if (!Q_strncasecmp(partial, builtinpresets[i].name, partiallen))
ctx->cb(builtinpresets[i].name, builtinpresets[i].desc, NULL, ctx);
}
}
qboolean M_PresetApply (union menuoption_s *op, struct emenu_s *menu, int key)

View file

@ -1158,24 +1158,29 @@ void M_Menu_MediaFiles_f (void)
// info->ext[info->numext] = ".m3u";
// info->command[info->numext] = "mediaplaylist";
// info->numext++;
#if defined(AVAIL_MP3_ACM) || defined(FTE_TARGET_WEB)
info->ext[info->numext] = ".mp3";
info->command[info->numext] = "media_add";
info->numext++;
#endif
info->ext[info->numext] = ".wav";
info->command[info->numext] = "media_add";
info->numext++;
#if defined(AVAIL_OGGOPUS) || defined(FTE_TARGET_WEB)
#if defined(AVAIL_OGGOPUS) || defined(FTE_TARGET_WEB) || defined(PLUGINS)
info->ext[info->numext] = ".opus";
info->command[info->numext] = "media_add";
info->numext++;
#endif
#if defined(AVAIL_OGGVORBIS) || defined(FTE_TARGET_WEB)
#if defined(AVAIL_OGGVORBIS) || defined(FTE_TARGET_WEB) || defined(PLUGINS)
info->ext[info->numext] = ".ogg";
info->command[info->numext] = "media_add";
info->numext++;
#endif
#if defined(AVAIL_MP3_ACM) || defined(FTE_TARGET_WEB) || defined(PLUGINS)
info->ext[info->numext] = ".mp3";
info->command[info->numext] = "media_add";
info->numext++;
#endif
#if defined(PLUGINS)
info->ext[info->numext] = ".flac";
info->command[info->numext] = "media_add";
info->numext++;
#endif
#endif
#ifdef HAVE_MEDIA_DECODER

View file

@ -1430,6 +1430,7 @@ void M_Reinit(void)
}
void FPS_Preset_f(void);
void FPS_Preset_c(int argn, const char *partial, struct xcommandargcompletioncb_s *ctx);
void M_MenuPop_f(void);
//menu.dat is loaded later... after the video and everything is up.
@ -1438,7 +1439,7 @@ void M_Init (void)
Cmd_AddCommand("menu_restart", M_Restart_f);
Cmd_AddCommand("togglemenu", M_ToggleMenu_f);
Cmd_AddCommand("closemenu", M_CloseMenu_f);
Cmd_AddCommand("fps_preset", FPS_Preset_f);
Cmd_AddCommandAD("fps_preset", FPS_Preset_f, FPS_Preset_c, "Apply a preset");
Cmd_AddCommand("menupop", M_MenuPop_f);
//server browser is kinda complex, and has clipboard integration which we need to sandbox a little

View file

@ -232,9 +232,9 @@ extern "C" {
#endif
#ifdef _WIN64
#define PRIxSIZE "Ix"
#define PRIuSIZE "Iu"
#define PRIiSIZE "Ii"
#define PRIxSIZE PRIx64
#define PRIuSIZE PRIu64
#define PRIiSIZE PRIi64
#else
//don't use I, for the sake of older libcs
#define PRIxSIZE "x"

View file

@ -238,8 +238,17 @@ void R2D_Init(void)
}
glossval = min(gl_specular_fallback.value*255, 255);
glossval *= 0x10101;
if (strchr(gl_specular_fallback.string, ' '))
{
glossval = bound(0, (int)(gl_specular_fallback.vec4[0]*255), 255)<<0;
glossval |= bound(0, (int)(gl_specular_fallback.vec4[1]*255), 255)<<8;
glossval |= bound(0, (int)(gl_specular_fallback.vec4[2]*255), 255)<<16;
}
else
{
glossval = min(gl_specular_fallback.value*255, 255);
glossval *= 0x10101;
}
glossval |= 0x01000000 * bound(0, (int)(gl_specular_fallbackexp.value*255), 255);
glossval = LittleLong(glossval);
normval = 0xffff8080;

View file

@ -29,6 +29,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#if (defined(GLQUAKE) || defined(VKQUAKE)) && defined(MULTITHREAD)
#define THREADEDWORLD
int webo_blocklightmapupdates; //0 no webo, &1=using threadedworld, &2=already uploaded. so update when !=3
#endif
#ifdef BEF_PUSHDEPTH
qboolean r_pushdepth;
@ -1776,7 +1777,7 @@ static void Surf_BuildLightMap_Worker (model_t *wmodel, msurface_t *surf, int sh
}
}
}
else switch(cl.worldmodel->lightmaps.fmt)
else switch(wmodel->lightmaps.fmt)
{
case LM_E5BGR9:
for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
@ -1876,7 +1877,7 @@ static void Surf_BuildLightMap_Worker (model_t *wmodel, msurface_t *surf, int sh
// add all the lightmaps
if (src)
{
switch(cl.worldmodel->lightmaps.fmt)
switch(wmodel->lightmaps.fmt)
{
case LM_E5BGR9:
for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
@ -2882,7 +2883,7 @@ void Surf_GenBrushBatches(batch_t **batches, entity_t *ent)
// calculate dynamic lighting for bmodel if it's not an
// instanced model
if (model->fromgame != fg_quake3 && model->fromgame != fg_doom3 && lightmap && !r_temporalscenecache.ival)
if (model->fromgame != fg_quake3 && model->fromgame != fg_doom3 && lightmap && webo_blocklightmapupdates!=3)
{
int k;
@ -2981,12 +2982,12 @@ void Surf_GenBrushBatches(batch_t **batches, entity_t *ent)
if (!b->shader)
b->shader = R_TextureAnimation(ent->framestate.g[FS_REG].frame[0], b->texture)->shader;
if (bef & BEF_FORCEADDITIVE)
if (bef & BEF_FORCEADDITIVE && b->shader->sort==SHADER_SORT_OPAQUE)
{
b->next = batches[SHADER_SORT_ADDITIVE];
batches[SHADER_SORT_ADDITIVE] = b;
}
else if (bef & BEF_FORCETRANSPARENT)
else if (bef & BEF_FORCETRANSPARENT && b->shader->sort==SHADER_SORT_OPAQUE)
{
b->next = batches[SHADER_SORT_BLEND];
batches[SHADER_SORT_BLEND] = b;
@ -3025,6 +3026,7 @@ struct webostate_s
{
size_t numidx;
size_t maxidx;
size_t firstidx; //offset into the final ebo
index_t *idxbuffer;
batch_t b;
mesh_t m;
@ -3035,12 +3037,15 @@ struct webostate_s
static struct webostate_s *webostates;
static struct webostate_s *webogenerating;
static int webogeneratingstate; //1 if generating, 0 if not, for waiting for sync.
int webo_blocklightmapupdates; //0 no webo, &1=using threadedworld, &2=already uploaded.
static void R_DestroyWorldEBO(struct webostate_s *es)
{
int i;
if (!es)
return;
for (i = 0; i < es->numbatches; i++)
BZ_Free(es->batches[i].idxbuffer);
#ifdef GLQUAKE
if (qrenderer == QR_OPENGL)
qglDeleteBuffersARB(1, &es->ebo.gl.vbo);
@ -3077,14 +3082,16 @@ void R_GeneratedWorldEBO(void *ctx, void *data, size_t a_, size_t b_)
GL_DeselectVAO();
webostate->ebo.gl.addr = NULL;
qglGenBuffersARB(1, &webostate->ebo.gl.vbo);
if (!webostate->ebo.gl.vbo)
qglGenBuffersARB(1, &webostate->ebo.gl.vbo);
GL_SelectEBO(webostate->ebo.gl.vbo);
qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, idxcount*sizeof(index_t), NULL, GL_STATIC_DRAW_ARB);
for (i = 0, idxcount = 0; i < webostate->numbatches; i++)
{
qglBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, idxcount*sizeof(index_t), webostate->batches[i].numidx*sizeof(index_t), webostate->batches[i].idxbuffer);
BZ_Free(webostate->batches[i].idxbuffer);
webostate->batches[i].idxbuffer = (index_t*)NULL + idxcount;
// BZ_Free(webostate->batches[i].idxbuffer);
// webostate->batches[i].idxbuffer = NULL;
webostate->batches[i].firstidx = idxcount;
idxcount += webostate->batches[i].numidx;
}
}
@ -3094,12 +3101,16 @@ void R_GeneratedWorldEBO(void *ctx, void *data, size_t a_, size_t b_)
{ //this malloc is stupid.
//with vulkan we really should be doing this on the worker instead, at least the staging part.
index_t *indexes = malloc(sizeof(*indexes) * idxcount);
BE_VBO_Destroy(&webostate->ebo, webostate->ebomem);
memset(&webostate->ebo, 0, sizeof(webostate->ebo));
webostate->ebomem = NULL;
webostate->ebo.vk.offs = 0;
for (i = 0, idxcount = 0; i < webostate->numbatches; i++)
{
memcpy(indexes + idxcount, webostate->batches[i].idxbuffer, webostate->batches[i].numidx*sizeof(index_t));
BZ_Free(webostate->batches[i].idxbuffer);
webostate->batches[i].idxbuffer = (index_t*)NULL + idxcount;
// BZ_Free(webostate->batches[i].idxbuffer);
// webostate->batches[i].idxbuffer = NULL;
webostate->batches[i].firstidx = idxcount;
idxcount += webostate->batches[i].numidx;
}
if (idxcount)
@ -3144,7 +3155,7 @@ void R_GeneratedWorldEBO(void *ctx, void *data, size_t a_, size_t b_)
b->mesh = &webostate->batches[i].pm;
b->meshes = 1;
m->numindexes = webostate->batches[i].numidx;
m->vbofirstelement = webostate->batches[i].idxbuffer - (index_t*)NULL;
m->vbofirstelement = webostate->batches[i].firstidx;
m->vbofirstvert = 0;
m->indexes = NULL;
b->vbo = &webostate->batches[i].vbo;
@ -3277,13 +3288,25 @@ void R_GenWorldEBO(void *ctx, void *data, size_t a, size_t b)
struct webostate_s *es = ctx;
qbyte *pvs;
es->numbatches = es->wmodel->numbatches;
for (i = 0; i < es->numbatches; i++)
if (!es->numbatches)
{
es->batches[i].numidx = 0;
es->batches[i].maxidx = 0;
es->batches[i].idxbuffer = NULL;
es->numbatches = es->wmodel->numbatches;
for (i = 0; i < es->numbatches; i++)
{
es->batches[i].firstidx = 0;
es->batches[i].numidx = 0;
es->batches[i].maxidx = 0;
es->batches[i].idxbuffer = NULL;
}
}
else
{
for (i = 0; i < es->numbatches; i++)
{
es->batches[i].firstidx = 0;
es->batches[i].numidx = 0;
}
}
//maybe we should just use fatpvs instead, and wait for completion when outside?
@ -3351,19 +3374,19 @@ void Surf_DrawWorld (void)
#ifdef THREADEDWORLD
if ((r_temporalscenecache.ival || currentmodel->numbatches) && !r_refdef.recurse && currentmodel->type == mod_brush)
{
struct webostate_s *webostate, *best = NULL, *kill;
struct webostate_s *webostate, *best = NULL, *kill, **link;
vec_t bestdist = FLT_MAX;
for (webostate = webostates; webostate; webostate = webostate->next)
{
if (webostate->wmodel != currentmodel)
continue;
kill = webostate->next;
if (kill && kill->lastvalid < cls.framecount-5)
{
webostate->next = kill->next;
R_DestroyWorldEBO(kill);
}
// kill = webostate->next;
// if (kill && kill->lastvalid < cls.framecount-5)
// {
// webostate->next = kill->next;
// R_DestroyWorldEBO(kill);
// }
if (webostate->cluster[0] == r_viewcluster && webostate->cluster[1] == r_viewcluster2)
{
@ -3438,8 +3461,31 @@ void Surf_DrawWorld (void)
}
/*TODO submodels too*/
}
webogeneratingstate = true;
webogenerating = BZ_Malloc(sizeof(*webogenerating) + sizeof(webogenerating->batches[0]) * (currentmodel->numbatches-1) + currentmodel->pvsbytes);
webogenerating = NULL;
if (webostate)
webostate->lastvalid = cls.framecount;
for (link = &webostates; (kill=*link); )
{
if (kill->lastvalid < cls.framecount-5 && kill->wmodel == currentmodel)
{ //this one looks old... kill it.
if (webogenerating)
R_DestroyWorldEBO(webogenerating); //can't use more than one!
webogenerating = kill;
*link = kill->next;
}
else
link = &(*link)->next;
}
if (!webogenerating)
{
webogenerating = BZ_Malloc(sizeof(*webogenerating) + sizeof(webogenerating->batches[0]) * (currentmodel->numbatches-1) + currentmodel->pvsbytes);
memset(&webogenerating->ebo, 0, sizeof(webogenerating->ebo));
webogenerating->ebomem = NULL;
webogenerating->numbatches = 0;
}
webogenerating->wmodel = currentmodel;
webogenerating->cluster[0] = r_viewcluster;
webogenerating->cluster[1] = r_viewcluster2;
@ -3912,7 +3958,7 @@ int Surf_NewLightmaps(int count, int width, int height, uploadfmt_t fmt, qboolea
extern cvar_t gl_pbolightmaps;
//we might as well use a pbo for our staging memory.
if (qrenderer == QR_OPENGL && qglBufferStorage && qglMapBufferRange && gl_pbolightmaps.ival && Sys_IsMainThread())
{ //glBufferStorage and GL_MAP_PERSISTENT_BIT generally means gl4.4+
{ //glBufferStorage and GL_MAP_PERSISTENT_BIT generally means gl4.4+ (we need persistent for scenecache)
//pbos are 2.1
if (deluxe && ((i - numlightmaps)&1))
{

View file

@ -173,7 +173,7 @@ cvar_t r_drawviewmodel = CVARF ("r_drawviewmodel", "1", CVAR_ARCHIVE);
cvar_t r_drawviewmodelinvis = CVAR ("r_drawviewmodelinvis", "0");
cvar_t r_dynamic = CVARFD ("r_dynamic", IFMINIMAL("0","1"),
CVAR_ARCHIVE, "0: no standard dlights at all.\n1: coloured dlights will be used, they may show through walls. These are not realtime things.\n2: The dlights will be forced to monochrome (this does not affect coronas/flashblends/rtlights attached to the same light).");
cvar_t r_temporalscenecache = CVARFD ("r_temporalscenecache", "0", CVAR_ARCHIVE, "Controls whether to generate+reuse a scene cache over multiple frames. This is generated on a separate thread to avoid any associated costs. This can significantly boost framerates on complex maps, but can also stress the gpu more (performance tradeoff that varies per map). An outdated cache may be used if the cache takes too long to build (eg: lightmap animations), which could cause the odd glitch when moving fast (but retain more consistent framerates - another tradeoff).\n0: Tranditional quake rendering.\n1: Generate+Use the scene cache.");
cvar_t r_temporalscenecache = CVARFD ("r_temporalscenecache", "", CVAR_ARCHIVE, "Controls whether to generate+reuse a scene cache over multiple frames. This is generated on a separate thread to avoid any associated costs. This can significantly boost framerates on complex maps, but can also stress the gpu more (performance tradeoff that varies per map). An outdated cache may be used if the cache takes too long to build (eg: lightmap animations), which could cause the odd glitch when moving fast (but retain more consistent framerates - another tradeoff).\n0: Tranditional quake rendering.\n1: Generate+Use the scene cache.");
cvar_t r_fastturb = CVARF ("r_fastturb", "0",
CVAR_SHADERSYSTEM);
cvar_t r_skycloudalpha = CVARFD ("r_skycloudalpha", "1", CVAR_RENDERERLATCH, "Controls how opaque the front layer of legacy scrolling skies should be.");
@ -455,7 +455,7 @@ cvar_t gl_smoothcrosshair = CVAR ("gl_smoothcrosshair", "1");
cvar_t gl_maxdist = CVARAD ("gl_maxdist", "0", "gl_farclip", "The distance of the far clip plane. If set to 0, some fancy maths will be used to place it at an infinite distance.");
#ifdef SPECULAR
cvar_t gl_specular = CVARF ("gl_specular", "0.3", CVAR_ARCHIVE|CVAR_SHADERSYSTEM);
cvar_t gl_specular = CVARFD ("gl_specular", "0.3", CVAR_ARCHIVE|CVAR_SHADERSYSTEM, "Multiplier for specular effects.");
cvar_t gl_specular_power = CVARF ("gl_specular_power", "32", CVAR_ARCHIVE|CVAR_SHADERSYSTEM);
cvar_t gl_specular_fallback = CVARF ("gl_specular_fallback", "0.05", CVAR_ARCHIVE|CVAR_RENDERERLATCH);
cvar_t gl_specular_fallbackexp = CVARF ("gl_specular_fallbackexp", "1", CVAR_ARCHIVE|CVAR_RENDERERLATCH);
@ -505,6 +505,7 @@ cvar_t r_shadow_bumpscale_bumpmap = CVARD ("r_shadow_bumpscale_bumpmap", "4",
cvar_t r_shadow_heightscale_basetexture = CVARD ("r_shadow_heightscale_basetexture", "0", "scaler for generation of height maps from legacy paletted content.");
cvar_t r_shadow_heightscale_bumpmap = CVARD ("r_shadow_heightscale_bumpmap", "1", "height scaler for 8bit _bump textures");
cvar_t r_glsl_pbr = CVARFD ("r_glsl_pbr", "0", CVAR_ARCHIVE|CVAR_SHADERSYSTEM, "Force PBR shading.");
cvar_t r_glsl_offsetmapping = CVARFD ("r_glsl_offsetmapping", "0", CVAR_ARCHIVE|CVAR_SHADERSYSTEM, "Enables the use of paralax mapping, adding fake depth to textures.");
cvar_t r_glsl_offsetmapping_scale = CVAR ("r_glsl_offsetmapping_scale", "0.04");
cvar_t r_glsl_offsetmapping_reliefmapping = CVARFD("r_glsl_offsetmapping_reliefmapping", "0", CVAR_ARCHIVE|CVAR_SHADERSYSTEM, "Changes the paralax sampling mode to be a bit nicer, but noticably more expensive at high resolutions. r_glsl_offsetmapping must be set.");
@ -904,6 +905,7 @@ void Renderer_Init(void)
Cvar_Register (&r_coronas_fadedist, GRAPHICALNICETIES);
Cvar_Register (&r_flashblend, GRAPHICALNICETIES);
Cvar_Register (&r_flashblendscale, GRAPHICALNICETIES);
Cvar_Register (&r_glsl_pbr, GRAPHICALNICETIES);
Cvar_Register (&gl_specular, GRAPHICALNICETIES);
Cvar_Register (&gl_specular_power, GRAPHICALNICETIES);
Cvar_Register (&gl_specular_fallback, GRAPHICALNICETIES);

View file

@ -306,13 +306,20 @@ static qboolean QDECL ALSA_InitCard (soundcardinfo_t *sc, const char *pcmname)
#if 1
if (!sc->sn.sampleformat)
sc->sn.sampleformat = (sc->sn.samplebytes==1)?QSF_U8:QSF_S16;
{
if (sc->sn.samplebytes >= 4)
sc->sn.sampleformat = QSF_F32;
else if (sc->sn.samplebytes != 1)
sc->sn.sampleformat = QSF_S16;
else
sc->sn.sampleformat = QSF_U8;
}
switch(sc->sn.sampleformat)
{
case QSF_U8: err = SND_PCM_FORMAT_U8; break;
case QSF_S8: err = SND_PCM_FORMAT_S8; break;
case QSF_S16: err = SND_PCM_FORMAT_S16; break;
case QSF_F32: err = SND_PCM_FORMAT_FLOAT; break;
case QSF_U8: err = SND_PCM_FORMAT_U8; sc->sn.samplebytes=1; break;
case QSF_S8: err = SND_PCM_FORMAT_S8; sc->sn.samplebytes=1; break;
case QSF_S16: err = SND_PCM_FORMAT_S16; sc->sn.samplebytes=2; break;
case QSF_F32: err = SND_PCM_FORMAT_FLOAT; sc->sn.samplebytes=4; break;
default:
Con_Printf (CON_ERROR "ALSA: unsupported sample format %i\n", sc->sn.sampleformat);
goto error;

View file

@ -89,7 +89,7 @@ cvar_t nosound = CVARFD( "nosound", "0", CVAR_ARCHIVE,
"Disable all sound from the engine. Cannot be overriden by configs or anything if set via the -nosound commandline argument.");
cvar_t snd_precache = CVARAF( "s_precache", "1",
"precache", 0);
cvar_t loadas8bit = CVARAFD( "s_loadas8bit", "0",
cvar_t snd_loadas8bit = CVARAFD( "s_loadas8bit", "0",
"loadas8bit", CVAR_ARCHIVE,
"Downsample sounds on load as lower quality 8-bit sound, to save memory.");
#ifdef FTE_TARGET_WEB
@ -2315,7 +2315,7 @@ void S_Init (void)
Cvar_Register(&mastervolume, "Sound controls");
Cvar_Register(&volume, "Sound controls");
Cvar_Register(&snd_precache, "Sound controls");
Cvar_Register(&loadas8bit, "Sound controls");
Cvar_Register(&snd_loadas8bit, "Sound controls");
Cvar_Register(&snd_loadasstereo, "Sound controls");
Cvar_Register(&bgmvolume, "Sound controls");
Cvar_Register(&snd_nominaldistance, "Sound controls");
@ -2857,8 +2857,9 @@ static void SND_Spatialize(soundcardinfo_t *sc, channel_t *ch)
scale = 1;
scale = (1.0 - dist) * scale;
v = ch->master_vol * scale * volscale;
v = bound(0, v, 255);
for (i = 0; i < sc->sn.numchannels; i++)
ch->vol[i] = bound(0, v, 255);
ch->vol[i] = v;
return;
}
@ -2890,7 +2891,8 @@ static void SND_Spatialize(soundcardinfo_t *sc, channel_t *ch)
scale = 1 + DotProduct(listener_vec, sc->speakerdir[i]);
scale = (1.0 - dist) * scale * sc->dist[i];
v = ch->master_vol * scale * volscale;
ch->vol[i] = bound(0, v, 255);
v = bound(0, v, 255);
ch->vol[i] = v;
}
}

View file

@ -569,9 +569,9 @@ static qboolean ResampleSfx (sfx_t *sfx, int inrate, int inchannels, qaudiofmt_t
scale = snd_speed / (double)inrate;
outsamps = insamps * scale;
if (loadas8bit.ival < 0)
if (snd_loadas8bit.ival < 0)
outformat = QAF_S16;
else if (loadas8bit.ival)
else if (snd_loadas8bit.ival)
outformat = QAF_S8;
else
outformat = informat;
@ -789,7 +789,7 @@ static qboolean QDECL S_LoadWavSound (sfx_t *s, qbyte *data, size_t datalen, int
format = QAF_F32;
}
#else
else if (info.format == 3 && info.bitwidth == 4) //signed floats
else if (info.format == 3 && info.bitwidth == 32) //signed floats
{
short *out = (short *)(data + info.dataofs);
float *in = (float *)(data + info.dataofs);

View file

@ -23,25 +23,42 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifdef HAVE_MIXER
//#define MIXER_PAINT_F32
#ifdef MIXER_PAINT_F32
#define MIX_16_8(val) ((val)/(float)(1<<(15+8)))
#define MIX_8_8(val) ((val)/(float)(1<<(7+8)))
typedef struct {
float s[MAXSOUNDCHANNELS];
} portable_samplegroup_t;
#else
#define MIX_16_8(val) ((val)>>8) //value is a 16bit*8bit value (audio*vol) value. discard the lower 8 bits to treat the volume as a fraction
#define MIX_8_8(val) (val) //value is a 8bit*8bit value (audio*vol) value. result is 16bit.
typedef struct {
int s[MAXSOUNDCHANNELS]; //signed, 1=0x7fff ish. will be clamped to allow oversaturation
} portable_samplegroup_t;
#endif
#define PAINTBUFFER_SIZE 2048
portable_samplegroup_t paintbuffer[PAINTBUFFER_SIZE]; //FIXME: we really ought to be using SSE and floats or something.
int *snd_p, snd_vol;
short *snd_out;
static portable_samplegroup_t paintbuffer[PAINTBUFFER_SIZE]; //FIXME: we really ought to be using SSE and floats or something.
void S_TransferPaintBuffer(soundcardinfo_t *sc, int endtime)
{
unsigned int out_idx;
unsigned int count;
unsigned int outlimit;
int *p;
#ifdef MIXER_PAINT_F32
float *p = (float *fte_restrict)paintbuffer;
#else
int *p = (int *fte_restrict) paintbuffer;
#endif
int val;
// int snd_vol;
short *pbuf;
void *pbuf;
int i, numc;
p = (int *) paintbuffer;
count = (endtime - sc->paintedtime) * sc->sn.numchannels;
outlimit = sc->sn.samples;
out_idx = (sc->paintedtime * sc->sn.numchannels) % outlimit;
@ -64,12 +81,21 @@ void S_TransferPaintBuffer(soundcardinfo_t *sc, int endtime)
{
for (i = 0; i < numc; i++)
{
val = *p++;// * snd_vol) >> 8;
#ifdef MIXER_PAINT_F32
val = (*p++ + 1)*128;
if (val > 255)
val = 255;
else if (val < 0)
val = 0;
out[out_idx] = val;
#else
val = *p++;
if (val > 0x7fff)
val = 0x7fff;
else if (val < (short)0x8000)
val = (short)0x8000;
out[out_idx] = (val>>8) + 128;
#endif
out_idx = (out_idx + 1) % outlimit;
}
p += MAXSOUNDCHANNELS - numc;
@ -84,12 +110,21 @@ void S_TransferPaintBuffer(soundcardinfo_t *sc, int endtime)
{
for (i = 0; i < numc; i++)
{
val = *p++;// * snd_vol) >> 8;
#ifdef MIXER_PAINT_F32
val = *p++*128;
if (val > 127)
val = 127;
else if (val < -128)
val = -128;
out[out_idx] = val;
#else
val = *p++;
if (val > 0x7fff)
val = 0x7fff;
else if (val < (short)0x8000)
val = (short)0x8000;
out[out_idx] = (val>>8);
#endif
out_idx = (out_idx + 1) % outlimit;
}
p += MAXSOUNDCHANNELS - numc;
@ -104,7 +139,11 @@ void S_TransferPaintBuffer(soundcardinfo_t *sc, int endtime)
{
for (i = 0; i < numc; i++)
{
val = *p++;// * snd_vol) >> 8;
#ifdef MIXER_PAINT_F32
val = *p++*0x7fff;
#else
val = *p++;
#endif
if (val > 0x7fff)
val = 0x7fff;
else if (val < (short)0x8000)
@ -124,7 +163,11 @@ void S_TransferPaintBuffer(soundcardinfo_t *sc, int endtime)
{
for (i = 0; i < numc; i++)
{
#ifdef MIXER_PAINT_F32 //FIXME: replace with a memcpy.
out[out_idx] = *p++;
#else
out[out_idx] = *p++ * (1.0 / 32768);
#endif
out_idx = (out_idx + 1) % outlimit;
}
p += MAXSOUNDCHANNELS - numc;
@ -375,23 +418,23 @@ static void SND_PaintChannel8_O2I1 (channel_t *ch, sfxcache_t *sc, int starttime
if (rate != (1<<PITCHSHIFT))
{
sfx = (signed char *)sc->data;
sfx = (signed char *fte_restrict)sc->data;
for (i=0 ; i<count ; i++)
{
data = sfx[pos>>PITCHSHIFT];
pos += rate;
paintbuffer[starttime+i].s[0] += ch->vol[0] * data;
paintbuffer[starttime+i].s[1] += ch->vol[1] * data;
paintbuffer[starttime+i].s[0] += MIX_8_8(ch->vol[0] * data);
paintbuffer[starttime+i].s[1] += MIX_8_8(ch->vol[1] * data);
}
}
else
{
sfx = (signed char *)sc->data + (pos>>PITCHSHIFT);
sfx = (signed char *fte_restrict)sc->data + (pos>>PITCHSHIFT);
for (i=0 ; i<count ; i++)
{
data = sfx[i];
paintbuffer[starttime+i].s[0] += ch->vol[0] * data;
paintbuffer[starttime+i].s[1] += ch->vol[1] * data;
paintbuffer[starttime+i].s[0] += MIX_8_8(ch->vol[0] * data);
paintbuffer[starttime+i].s[1] += MIX_8_8(ch->vol[1] * data);
}
}
}
@ -405,21 +448,21 @@ static void SND_PaintChannel8_O2I2 (channel_t *ch, sfxcache_t *sc, int starttime
if (rate != (1<<PITCHSHIFT))
{
sfx = (signed char *)sc->data;
sfx = (signed char *fte_restrict)sc->data;
for (i=0 ; i<count ; i++)
{
paintbuffer[starttime+i].s[0] += ch->vol[0] * sfx[(pos>>(PITCHSHIFT-1))&~1];
paintbuffer[starttime+i].s[1] += ch->vol[1] * sfx[(pos>>(PITCHSHIFT-1))|1];
paintbuffer[starttime+i].s[0] += MIX_8_8(ch->vol[0] * sfx[(pos>>(PITCHSHIFT-1))&~1]);
paintbuffer[starttime+i].s[1] += MIX_8_8(ch->vol[1] * sfx[(pos>>(PITCHSHIFT-1))|1]);
pos += rate;
}
}
else
{
sfx = (signed char *)sc->data + (pos>>PITCHSHIFT)*2;
sfx = (signed char *fte_restrict)sc->data + (pos>>PITCHSHIFT)*2;
for (i=0 ; i<count ; i++)
{
paintbuffer[starttime+i].s[0] += ch->vol[0] * sfx[(i<<1)];
paintbuffer[starttime+i].s[1] += ch->vol[1] * sfx[(i<<1)+1];
paintbuffer[starttime+i].s[0] += MIX_8_8(ch->vol[0] * sfx[(i<<1)]);
paintbuffer[starttime+i].s[1] += MIX_8_8(ch->vol[1] * sfx[(i<<1)+1]);
}
}
}
@ -433,26 +476,26 @@ static void SND_PaintChannel8_O4I1 (channel_t *ch, sfxcache_t *sc, int count, in
if (rate != (1<<PITCHSHIFT))
{
signed char data;
sfx = (signed char *)sc->data;
sfx = (signed char *fte_restrict)sc->data;
for (i=0 ; i<count ; i++)
{
data = sfx[pos>>PITCHSHIFT];
pos += rate;
paintbuffer[i].s[0] += ch->vol[0] * data;
paintbuffer[i].s[1] += ch->vol[1] * data;
paintbuffer[i].s[2] += ch->vol[2] * data;
paintbuffer[i].s[3] += ch->vol[3] * data;
paintbuffer[i].s[0] += MIX_8_8(ch->vol[0] * data);
paintbuffer[i].s[1] += MIX_8_8(ch->vol[1] * data);
paintbuffer[i].s[2] += MIX_8_8(ch->vol[2] * data);
paintbuffer[i].s[3] += MIX_8_8(ch->vol[3] * data);
}
}
else
{
sfx = (signed char *)sc->data + (pos>>PITCHSHIFT);
sfx = (signed char *fte_restrict)sc->data + (pos>>PITCHSHIFT);
for (i=0 ; i<count ; i++)
{
paintbuffer[i].s[0] += ch->vol[0] * sfx[i];
paintbuffer[i].s[1] += ch->vol[1] * sfx[i];
paintbuffer[i].s[2] += ch->vol[2] * sfx[i];
paintbuffer[i].s[3] += ch->vol[3] * sfx[i];
paintbuffer[i].s[0] += MIX_8_8(ch->vol[0] * sfx[i]);
paintbuffer[i].s[1] += MIX_8_8(ch->vol[1] * sfx[i]);
paintbuffer[i].s[2] += MIX_8_8(ch->vol[2] * sfx[i]);
paintbuffer[i].s[3] += MIX_8_8(ch->vol[3] * sfx[i]);
}
}
}
@ -466,30 +509,30 @@ static void SND_PaintChannel8_O6I1 (channel_t *ch, sfxcache_t *sc, int count, in
if (rate != (1<<PITCHSHIFT))
{
signed char data;
sfx = (signed char *)sc->data;
sfx = (signed char *fte_restrict)sc->data;
for (i=0 ; i<count ; i++)
{
data = sfx[pos>>PITCHSHIFT];
pos += rate;
paintbuffer[i].s[0] += ch->vol[0] * data;
paintbuffer[i].s[1] += ch->vol[1] * data;
paintbuffer[i].s[2] += ch->vol[2] * data;
paintbuffer[i].s[3] += ch->vol[3] * data;
paintbuffer[i].s[4] += ch->vol[4] * data;
paintbuffer[i].s[5] += ch->vol[5] * data;
paintbuffer[i].s[0] += MIX_8_8(ch->vol[0] * data);
paintbuffer[i].s[1] += MIX_8_8(ch->vol[1] * data);
paintbuffer[i].s[2] += MIX_8_8(ch->vol[2] * data);
paintbuffer[i].s[3] += MIX_8_8(ch->vol[3] * data);
paintbuffer[i].s[4] += MIX_8_8(ch->vol[4] * data);
paintbuffer[i].s[5] += MIX_8_8(ch->vol[5] * data);
}
}
else
{
sfx = (signed char *)sc->data + (pos>>PITCHSHIFT);
sfx = (signed char *fte_restrict)sc->data + (pos>>PITCHSHIFT);
for (i=0 ; i<count ; i++)
{
paintbuffer[i].s[0] += ch->vol[0] * sfx[i];
paintbuffer[i].s[1] += ch->vol[1] * sfx[i];
paintbuffer[i].s[2] += ch->vol[2] * sfx[i];
paintbuffer[i].s[3] += ch->vol[3] * sfx[i];
paintbuffer[i].s[4] += ch->vol[4] * sfx[i];
paintbuffer[i].s[5] += ch->vol[5] * sfx[i];
paintbuffer[i].s[0] += MIX_8_8(ch->vol[0] * sfx[i]);
paintbuffer[i].s[1] += MIX_8_8(ch->vol[1] * sfx[i]);
paintbuffer[i].s[2] += MIX_8_8(ch->vol[2] * sfx[i]);
paintbuffer[i].s[3] += MIX_8_8(ch->vol[3] * sfx[i]);
paintbuffer[i].s[4] += MIX_8_8(ch->vol[4] * sfx[i]);
paintbuffer[i].s[5] += MIX_8_8(ch->vol[5] * sfx[i]);
}
}
}
@ -503,34 +546,34 @@ static void SND_PaintChannel8_O8I1 (channel_t *ch, sfxcache_t *sc, int count, in
if (rate != (1<<PITCHSHIFT))
{
signed char data;
sfx = (signed char *)sc->data;
sfx = (signed char *fte_restrict)sc->data;
for (i=0 ; i<count ; i++)
{
data = sfx[pos>>PITCHSHIFT];
pos += rate;
paintbuffer[i].s[0] += ch->vol[0] * data;
paintbuffer[i].s[1] += ch->vol[1] * data;
paintbuffer[i].s[2] += ch->vol[2] * data;
paintbuffer[i].s[3] += ch->vol[3] * data;
paintbuffer[i].s[4] += ch->vol[4] * data;
paintbuffer[i].s[5] += ch->vol[5] * data;
paintbuffer[i].s[6] += ch->vol[6] * data;
paintbuffer[i].s[7] += ch->vol[7] * data;
paintbuffer[i].s[0] += MIX_8_8(ch->vol[0] * data);
paintbuffer[i].s[1] += MIX_8_8(ch->vol[1] * data);
paintbuffer[i].s[2] += MIX_8_8(ch->vol[2] * data);
paintbuffer[i].s[3] += MIX_8_8(ch->vol[3] * data);
paintbuffer[i].s[4] += MIX_8_8(ch->vol[4] * data);
paintbuffer[i].s[5] += MIX_8_8(ch->vol[5] * data);
paintbuffer[i].s[6] += MIX_8_8(ch->vol[6] * data);
paintbuffer[i].s[7] += MIX_8_8(ch->vol[7] * data);
}
}
else
{
sfx = (signed char *)sc->data + (pos>>PITCHSHIFT);
sfx = (signed char *fte_restrict)sc->data + (pos>>PITCHSHIFT);
for (i=0 ; i<count ; i++)
{
paintbuffer[i].s[0] += ch->vol[0] * sfx[i];
paintbuffer[i].s[1] += ch->vol[1] * sfx[i];
paintbuffer[i].s[2] += ch->vol[2] * sfx[i];
paintbuffer[i].s[3] += ch->vol[3] * sfx[i];
paintbuffer[i].s[4] += ch->vol[4] * sfx[i];
paintbuffer[i].s[5] += ch->vol[5] * sfx[i];
paintbuffer[i].s[6] += ch->vol[6] * sfx[i];
paintbuffer[i].s[7] += ch->vol[7] * sfx[i];
paintbuffer[i].s[0] += MIX_8_8(ch->vol[0] * sfx[i]);
paintbuffer[i].s[1] += MIX_8_8(ch->vol[1] * sfx[i]);
paintbuffer[i].s[2] += MIX_8_8(ch->vol[2] * sfx[i]);
paintbuffer[i].s[3] += MIX_8_8(ch->vol[3] * sfx[i]);
paintbuffer[i].s[4] += MIX_8_8(ch->vol[4] * sfx[i]);
paintbuffer[i].s[5] += MIX_8_8(ch->vol[5] * sfx[i]);
paintbuffer[i].s[6] += MIX_8_8(ch->vol[6] * sfx[i]);
paintbuffer[i].s[7] += MIX_8_8(ch->vol[7] * sfx[i]);
}
}
}
@ -539,7 +582,6 @@ static void SND_PaintChannel8_O8I1 (channel_t *ch, sfxcache_t *sc, int count, in
static void SND_PaintChannel16_O2I1 (channel_t *ch, sfxcache_t *sc, int starttime, int count, int rate)
{
int data;
int left, right;
int leftvol, rightvol;
signed short *sfx;
int i;
@ -551,26 +593,24 @@ static void SND_PaintChannel16_O2I1 (channel_t *ch, sfxcache_t *sc, int starttim
if (rate != (1<<PITCHSHIFT))
{
signed int data;
sfx = (signed short *)sc->data;
sfx = (signed short *fte_restrict)sc->data;
for (i=0 ; i<count ; i++)
{
int frac = pos&((1<<PITCHSHIFT)-1);
data = sfx[pos>>PITCHSHIFT] * ((1<<PITCHSHIFT)-frac) + sfx[(pos>>PITCHSHIFT)+1] * frac;
pos += rate;
paintbuffer[starttime+i].s[0] += (leftvol * data)>>(PITCHSHIFT+8);
paintbuffer[starttime+i].s[1] += (rightvol * data)>>(PITCHSHIFT+8);
paintbuffer[starttime+i].s[0] += MIX_16_8((leftvol * data)>>PITCHSHIFT);
paintbuffer[starttime+i].s[1] += MIX_16_8((rightvol * data)>>PITCHSHIFT);
}
}
else
{
sfx = (signed short *)sc->data + (pos>>PITCHSHIFT);
sfx = (signed short *fte_restrict)sc->data + (pos>>PITCHSHIFT);
for (i=0 ; i<count ; i++)
{
data = sfx[i];
left = (data * leftvol) >> 8;
right = (data * rightvol) >> 8;
paintbuffer[starttime+i].s[0] += left;
paintbuffer[starttime+i].s[1] += right;
paintbuffer[starttime+i].s[0] += MIX_16_8(data * leftvol);
paintbuffer[starttime+i].s[1] += MIX_16_8(data * rightvol);
}
}
}
@ -588,23 +628,23 @@ static void SND_PaintChannel16_O2I2 (channel_t *ch, sfxcache_t *sc, int starttim
if (rate != (1<<PITCHSHIFT))
{
signed short l, r;
sfx = (signed short *)sc->data;
sfx = (signed short *fte_restrict)sc->data;
for (i=0 ; i<count ; i++)
{
l = sfx[(pos>>(PITCHSHIFT-1))&~1];
r = sfx[(pos>>(PITCHSHIFT-1))|1];
pos += rate;
paintbuffer[starttime+i].s[0] += (ch->vol[0] * l)>>8;
paintbuffer[starttime+i].s[1] += (ch->vol[1] * r)>>8;
paintbuffer[starttime+i].s[0] += MIX_16_8(ch->vol[0] * l);
paintbuffer[starttime+i].s[1] += MIX_16_8(ch->vol[1] * r);
}
}
else
{
sfx = (signed short *)sc->data + (pos>>PITCHSHIFT)*2;
sfx = (signed short *fte_restrict)sc->data + (pos>>PITCHSHIFT)*2;
for (i=0 ; i<count ; i++)
{
paintbuffer[starttime+i].s[0] += (*sfx++ * leftvol) >> 8;
paintbuffer[starttime+i].s[1] += (*sfx++ * rightvol) >> 8;
paintbuffer[starttime+i].s[0] += MIX_16_8(*sfx++ * leftvol);
paintbuffer[starttime+i].s[1] += MIX_16_8(*sfx++ * rightvol);
}
}
}
@ -624,26 +664,26 @@ static void SND_PaintChannel16_O4I1 (channel_t *ch, sfxcache_t *sc, int count, i
if (rate != (1<<PITCHSHIFT))
{
signed short data;
sfx = (signed short *)sc->data;
sfx = (signed short *fte_restrict)sc->data;
for (i=0 ; i<count ; i++)
{
data = sfx[pos>>PITCHSHIFT];
pos += rate;
paintbuffer[i].s[0] += (vol[0] * data)>>8;
paintbuffer[i].s[1] += (vol[1] * data)>>8;
paintbuffer[i].s[2] += (vol[2] * data)>>8;
paintbuffer[i].s[3] += (vol[3] * data)>>8;
paintbuffer[i].s[0] += MIX_16_8(vol[0] * data);
paintbuffer[i].s[1] += MIX_16_8(vol[1] * data);
paintbuffer[i].s[2] += MIX_16_8(vol[2] * data);
paintbuffer[i].s[3] += MIX_16_8(vol[3] * data);
}
}
else
{
sfx = (signed short *)sc->data + (pos>>PITCHSHIFT);
sfx = (signed short *fte_restrict)sc->data + (pos>>PITCHSHIFT);
for (i=0 ; i<count ; i++)
{
paintbuffer[i].s[0] += (sfx[i] * vol[0]) >> 8;
paintbuffer[i].s[1] += (sfx[i] * vol[1]) >> 8;
paintbuffer[i].s[2] += (sfx[i] * vol[2]) >> 8;
paintbuffer[i].s[3] += (sfx[i] * vol[3]) >> 8;
paintbuffer[i].s[0] += MIX_16_8(sfx[i] * vol[0]);
paintbuffer[i].s[1] += MIX_16_8(sfx[i] * vol[1]);
paintbuffer[i].s[2] += MIX_16_8(sfx[i] * vol[2]);
paintbuffer[i].s[3] += MIX_16_8(sfx[i] * vol[3]);
}
}
}
@ -665,30 +705,30 @@ static void SND_PaintChannel16_O6I1 (channel_t *ch, sfxcache_t *sc, int count, i
if (rate != (1<<PITCHSHIFT))
{
signed short data;
sfx = (signed short *)sc->data;
sfx = (signed short *fte_restrict)sc->data;
for (i=0 ; i<count ; i++)
{
data = sfx[pos>>PITCHSHIFT];
pos += rate;
paintbuffer[i].s[0] += (vol[0] * data)>>8;
paintbuffer[i].s[1] += (vol[1] * data)>>8;
paintbuffer[i].s[2] += (vol[2] * data)>>8;
paintbuffer[i].s[3] += (vol[3] * data)>>8;
paintbuffer[i].s[4] += (vol[4] * data)>>8;
paintbuffer[i].s[5] += (vol[5] * data)>>8;
paintbuffer[i].s[0] += MIX_16_8(vol[0] * data);
paintbuffer[i].s[1] += MIX_16_8(vol[1] * data);
paintbuffer[i].s[2] += MIX_16_8(vol[2] * data);
paintbuffer[i].s[3] += MIX_16_8(vol[3] * data);
paintbuffer[i].s[4] += MIX_16_8(vol[4] * data);
paintbuffer[i].s[5] += MIX_16_8(vol[5] * data);
}
}
else
{
sfx = (signed short *)sc->data + (pos>>PITCHSHIFT);
sfx = (signed short *fte_restrict)sc->data + (pos>>PITCHSHIFT);
for (i=0 ; i<count ; i++)
{
paintbuffer[i].s[0] += (sfx[i] * vol[0]) >> 8;
paintbuffer[i].s[1] += (sfx[i] * vol[1]) >> 8;
paintbuffer[i].s[2] += (sfx[i] * vol[2]) >> 8;
paintbuffer[i].s[3] += (sfx[i] * vol[3]) >> 8;
paintbuffer[i].s[4] += (sfx[i] * vol[4]) >> 8;
paintbuffer[i].s[5] += (sfx[i] * vol[5]) >> 8;
paintbuffer[i].s[0] += MIX_16_8(sfx[i] * vol[0]);
paintbuffer[i].s[1] += MIX_16_8(sfx[i] * vol[1]);
paintbuffer[i].s[2] += MIX_16_8(sfx[i] * vol[2]);
paintbuffer[i].s[3] += MIX_16_8(sfx[i] * vol[3]);
paintbuffer[i].s[4] += MIX_16_8(sfx[i] * vol[4]);
paintbuffer[i].s[5] += MIX_16_8(sfx[i] * vol[5]);
}
}
}
@ -712,34 +752,34 @@ static void SND_PaintChannel16_O8I1 (channel_t *ch, sfxcache_t *sc, int count, i
if (rate != (1<<PITCHSHIFT))
{
signed short data;
sfx = (signed short *)sc->data;
sfx = (signed short *fte_restrict)sc->data;
for (i=0 ; i<count ; i++)
{
data = sfx[pos>>PITCHSHIFT];
pos += rate;
paintbuffer[i].s[0] += (vol[0] * data)>>8;
paintbuffer[i].s[1] += (vol[1] * data)>>8;
paintbuffer[i].s[2] += (vol[2] * data)>>8;
paintbuffer[i].s[3] += (vol[3] * data)>>8;
paintbuffer[i].s[4] += (vol[4] * data)>>8;
paintbuffer[i].s[5] += (vol[5] * data)>>8;
paintbuffer[i].s[6] += (vol[6] * data)>>8;
paintbuffer[i].s[7] += (vol[7] * data)>>8;
paintbuffer[i].s[0] += MIX_16_8(vol[0] * data);
paintbuffer[i].s[1] += MIX_16_8(vol[1] * data);
paintbuffer[i].s[2] += MIX_16_8(vol[2] * data);
paintbuffer[i].s[3] += MIX_16_8(vol[3] * data);
paintbuffer[i].s[4] += MIX_16_8(vol[4] * data);
paintbuffer[i].s[5] += MIX_16_8(vol[5] * data);
paintbuffer[i].s[6] += MIX_16_8(vol[6] * data);
paintbuffer[i].s[7] += MIX_16_8(vol[7] * data);
}
}
else
{
sfx = (signed short *)sc->data + (pos>>PITCHSHIFT);
sfx = (signed short *fte_restrict)sc->data + (pos>>PITCHSHIFT);
for (i=0 ; i<count ; i++)
{
paintbuffer[i].s[0] += (sfx[i] * vol[0]) >> 8;
paintbuffer[i].s[1] += (sfx[i] * vol[1]) >> 8;
paintbuffer[i].s[2] += (sfx[i] * vol[2]) >> 8;
paintbuffer[i].s[3] += (sfx[i] * vol[3]) >> 8;
paintbuffer[i].s[4] += (sfx[i] * vol[4]) >> 8;
paintbuffer[i].s[5] += (sfx[i] * vol[5]) >> 8;
paintbuffer[i].s[6] += (sfx[i] * vol[6]) >> 8;
paintbuffer[i].s[7] += (sfx[i] * vol[7]) >> 8;
paintbuffer[i].s[0] += MIX_16_8(sfx[i] * vol[0]);
paintbuffer[i].s[1] += MIX_16_8(sfx[i] * vol[1]);
paintbuffer[i].s[2] += MIX_16_8(sfx[i] * vol[2]);
paintbuffer[i].s[3] += MIX_16_8(sfx[i] * vol[3]);
paintbuffer[i].s[4] += MIX_16_8(sfx[i] * vol[4]);
paintbuffer[i].s[5] += MIX_16_8(sfx[i] * vol[5]);
paintbuffer[i].s[6] += MIX_16_8(sfx[i] * vol[6]);
paintbuffer[i].s[7] += MIX_16_8(sfx[i] * vol[7]);
}
}
}
@ -759,7 +799,7 @@ static void SND_PaintChannel32F_O2I1 (channel_t *ch, sfxcache_t *sc, int startti
if (rate != (1<<PITCHSHIFT))
{
sfx = (float *)sc->data;
sfx = (float *fte_restrict)sc->data;
for (i=0 ; i<count ; i++)
{
float frac = pos&((1<<PITCHSHIFT)-1);
@ -771,7 +811,7 @@ static void SND_PaintChannel32F_O2I1 (channel_t *ch, sfxcache_t *sc, int startti
}
else
{
sfx = (float *)sc->data + (pos>>PITCHSHIFT);
sfx = (float *fte_restrict)sc->data + (pos>>PITCHSHIFT);
for (i=0 ; i<count ; i++)
{
data = sfx[i];
@ -796,7 +836,7 @@ static void SND_PaintChannel32F_O2I2 (channel_t *ch, sfxcache_t *sc, int startti
if (rate != (1<<PITCHSHIFT))
{
float l, r;
sfx = (float *)sc->data;
sfx = (float *fte_restrict)sc->data;
for (i=0 ; i<count ; i++)
{
l = sfx[(pos>>(PITCHSHIFT-1))&~1];
@ -808,7 +848,7 @@ static void SND_PaintChannel32F_O2I2 (channel_t *ch, sfxcache_t *sc, int startti
}
else
{
sfx = (float *)sc->data + (pos>>PITCHSHIFT)*2;
sfx = (float *fte_restrict)sc->data + (pos>>PITCHSHIFT)*2;
for (i=0 ; i<count ; i++)
{
paintbuffer[starttime+i].s[0] += (*sfx++ * leftvol);
@ -832,7 +872,7 @@ static void SND_PaintChannel32F_O4I1 (channel_t *ch, sfxcache_t *sc, int count,
if (rate != (1<<PITCHSHIFT))
{
float data;
sfx = (float *)sc->data;
sfx = (float *fte_restrict)sc->data;
for (i=0 ; i<count ; i++)
{
data = sfx[pos>>PITCHSHIFT];
@ -845,7 +885,7 @@ static void SND_PaintChannel32F_O4I1 (channel_t *ch, sfxcache_t *sc, int count,
}
else
{
sfx = (float *)sc->data + (pos>>PITCHSHIFT);
sfx = (float *fte_restrict)sc->data + (pos>>PITCHSHIFT);
for (i=0 ; i<count ; i++)
{
paintbuffer[i].s[0] += (sfx[i] * vol[0]);
@ -873,7 +913,7 @@ static void SND_PaintChannel32F_O6I1 (channel_t *ch, sfxcache_t *sc, int count,
if (rate != (1<<PITCHSHIFT))
{
float data;
sfx = (float *)sc->data;
sfx = (float *fte_restrict)sc->data;
for (i=0 ; i<count ; i++)
{
data = sfx[pos>>PITCHSHIFT];
@ -888,7 +928,7 @@ static void SND_PaintChannel32F_O6I1 (channel_t *ch, sfxcache_t *sc, int count,
}
else
{
sfx = (float *)sc->data + (pos>>PITCHSHIFT);
sfx = (float *fte_restrict)sc->data + (pos>>PITCHSHIFT);
for (i=0 ; i<count ; i++)
{
paintbuffer[i].s[0] += (sfx[i] * vol[0]);
@ -921,7 +961,7 @@ static void SND_PaintChannel32F_O8I1 (channel_t *ch, sfxcache_t *sc, int count,
if (rate != (1<<PITCHSHIFT))
{
float data;
sfx = (float *)sc->data;
sfx = (float *fte_restrict)sc->data;
for (i=0 ; i<count ; i++)
{
data = sfx[pos>>PITCHSHIFT];
@ -938,7 +978,7 @@ static void SND_PaintChannel32F_O8I1 (channel_t *ch, sfxcache_t *sc, int count,
}
else
{
sfx = (float *)sc->data + (pos>>PITCHSHIFT);
sfx = (float *fte_restrict)sc->data + (pos>>PITCHSHIFT);
for (i=0 ; i<count ; i++)
{
paintbuffer[i].s[0] += (sfx[i] * vol[0]);

View file

@ -32,10 +32,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define PITCHSHIFT 6 /*max audio file length = ((1<<32)>>PITCHSHIFT)/KHZ*/
struct sfx_s;
typedef struct
{
int s[MAXSOUNDCHANNELS];
} portable_samplegroup_t;
typedef struct {
struct sfxcache_s *(QDECL *decodedata) (struct sfx_s *sfx, struct sfxcache_s *buf, ssamplepos_t start, int length); //return true when done.
@ -135,7 +131,7 @@ typedef struct
typedef struct
{
sfx_t *sfx; // sfx number
int vol[MAXSOUNDCHANNELS]; // volume, .8 fixed point.
int vol[MAXSOUNDCHANNELS]; // volume, 0.8 fixed point.
ssamplepos_t pos; // sample position in sfx, <0 means delay sound start (shifted up by PITCHSHIFT)
int rate; // fixed point rate scaling
int flags; // cf_ flags
@ -308,7 +304,7 @@ extern int snd_speed;
extern cvar_t snd_nominaldistance;
extern cvar_t loadas8bit;
extern cvar_t snd_loadas8bit;
extern cvar_t bgmvolume;
extern cvar_t volume, mastervolume;
extern cvar_t snd_capture;

View file

@ -292,17 +292,32 @@ void Sys_Quit (void)
static void Sys_Register_File_Associations_f(void)
{
char xdgbase[MAX_OSPATH];
char confbase[MAX_OSPATH];
if (1)
{
const char *e = getenv("XDG_DATA_HOME");
if (e && *e)
Q_strncpyz(xdgbase, e, sizeof(xdgbase));
{ //user
const char *data = getenv("XDG_DATA_HOME");
const char *config = getenv("XDG_CONFIG_HOME");
const char *home = getenv("HOME");
if (data && *data)
Q_strncpyz(xdgbase, data, sizeof(xdgbase));
else
{
e = getenv("HOME");
if (e && *e)
Q_snprintfz(xdgbase, sizeof(xdgbase), "%s/.local/share", e);
if (home && *home)
Q_snprintfz(xdgbase, sizeof(xdgbase), "%s/.local/share", home);
else
{
Con_Printf("homedir not known\n");
return;
}
}
if (config && *config)
Q_strncpyz(confbase, config, sizeof(confbase));
else
{
if (home && *home)
Q_snprintfz(confbase, sizeof(confbase), "%s/.config", home);
else
{
Con_Printf("homedir not known\n");
@ -311,20 +326,33 @@ static void Sys_Register_File_Associations_f(void)
}
}
else
{
const char *e = getenv("XDG_DATA_DIRS");
while (e && *e == ':')
e++;
if (e && *e)
{ //system... gotta be root...
const char *data = getenv("XDG_DATA_DIRS");
const char *config = getenv("XDG_CONFIG_DIRS");
while (data && *data == ':')
data++;
if (data && *data)
{
char *c;
Q_strncpyz(xdgbase, e, sizeof(xdgbase));
Q_strncpyz(xdgbase, data, sizeof(xdgbase));
c = strchr(xdgbase, ':');
if (*c)
*c = 0;
}
else
Q_strncpyz(xdgbase, "/usr/local/share/", sizeof(xdgbase));
while (config && *config == ':')
config++;
if (config && *config)
{
char *c;
Q_strncpyz(confbase, config, sizeof(confbase));
c = strchr(confbase, ':');
if (*c)
*c = 0;
}
else
Q_strncpyz(confbase, "/etc/xdg/", sizeof(confbase));
}
//we need to create some .desktop file first, so stuff knows how to start us up.
@ -349,7 +377,7 @@ static void Sys_Register_File_Associations_f(void)
if (!strcmp(iconname, "afterquake") || !strcmp(iconname, "nq")) //hacks so that we don't need to create icons.
iconname = "quake";
if (FS_NativePath("icon.png", FS_GAME, iconsyspath, sizeof(iconsyspath)))
if (FS_NativePath("icon.png", FS_PUBBASEGAMEONLY, iconsyspath, sizeof(iconsyspath)))
iconname = iconsyspath;
desktopfile = va(desktopfile,
@ -366,11 +394,11 @@ static void Sys_Register_File_Associations_f(void)
//write out a new file and rename the new over the top of the old
{
char *foundassoc = NULL;
vfsfile_t *out = FS_OpenVFS(va("%s/applications/.mimeapps.list.new", xdgbase), "wb", FS_SYSTEM);
vfsfile_t *out = FS_OpenVFS(va("%s/.mimeapps.list.new", confbase), "wb", FS_SYSTEM);
if (out)
{
qofs_t insize;
char *in = FS_MallocFile(va("%s/applications/mimeapps.list", xdgbase), FS_SYSTEM, &insize);
char *in = FS_MallocFile(va("%s/mimeapps.list", confbase), FS_SYSTEM, &insize);
if (in)
{
qboolean inadded = false;
@ -404,7 +432,7 @@ static void Sys_Register_File_Associations_f(void)
if (foundassoc)
{ //if we found it, or somewhere to insert it, then insert it.
VFS_WRITE(out, in, foundassoc-in);
VFS_PRINTF(out, "x-scheme-handler/qw=fte-%s.desktop\n", fs_manifest->installation);
VFS_PRINTF(out, "x-scheme-handler/qw=fte-%s.desktop;\n", fs_manifest->installation);
VFS_WRITE(out, foundassoc, insize - (foundassoc-in));
}
else
@ -414,11 +442,11 @@ static void Sys_Register_File_Associations_f(void)
if (!foundassoc)
{ //if file not found, or no appropriate section, just concat it on the end.
VFS_PRINTF(out, "[Added Associations]\n");
VFS_PRINTF(out, "x-scheme-handler/qw=fte-%s.desktop\n", fs_manifest->installation);
VFS_PRINTF(out, "x-scheme-handler/qw=fte-%s.desktop;\n", fs_manifest->installation);
}
VFS_FLUSH(out);
VFS_CLOSE(out);
FS_Rename2(va("%s/applications/.mimeapps.list.new", xdgbase), va("%s/applications/mimeapps.list", xdgbase), FS_SYSTEM, FS_SYSTEM);
FS_Rename2(va("%s/.mimeapps.list.new", confbase), va("%s/mimeapps.list", confbase), FS_SYSTEM, FS_SYSTEM);
}
}
}

View file

@ -637,6 +637,8 @@ static rulesetrule_t rulesetrules_strict[] = {
{"ruleset_allow_sensitive_texture_replacements", "0"},
{"ruleset_allow_localvolume", "0"},
{"ruleset_allow_fbmodels", "0"},
{"r_particlesystem", "classic"}, /*block custom particles*/
{"r_part_density", "1"}, /*don't let people thin them out*/
{"scr_autoid_team", "0"}, /*sort of a wallhack*/
{"tp_disputablemacros", "0"},
{"cl_instantrotate", "0"},
@ -645,6 +647,34 @@ static rulesetrule_t rulesetrules_strict[] = {
{"ruleset_allow_in", "0"},
{"r_projection", "0"},
{"gl_shadeq1_name", "*"},
{"cl_rollalpha", "20"},
{"cl_iDrive", "0"},
{NULL}
};
static rulesetrule_t rulesetrules_thunderdome[] = {
{"ruleset_allow_shaders", "0"}, /*users can potentially create all sorts of wallhacks or spiked models with this*/
{"ruleset_allow_watervis", "0"}, /*oh noes! users might be able to see underwater if they're already in said water. oh wait. what? why do we care, dude*/
{"r_vertexlight", "0"},
{"ruleset_allow_playercount", "0"},
{"ruleset_allow_frj", "0"},
{"ruleset_allow_packet", "0"},
{"ruleset_allow_particle_lightning", "0"},
{"ruleset_allow_overlong_sounds", "0"},
{"ruleset_allow_larger_models", "0"},
{"ruleset_allow_modified_eyes", "0"},
{"ruleset_allow_sensitive_texture_replacements", "0"},
{"ruleset_allow_localvolume", "0"},
{"ruleset_allow_fbmodels", "0"},
{"scr_autoid_team", "0"}, /*sort of a wallhack*/
{"tp_disputablemacros", "0"},
{"cl_instantrotate", "0"},
{"v_projectionmode", "0"}, /*no extended fovs*/
{"r_shadow_realtime_world", "0"}, /*static lighting can be used to cast shadows around corners*/
{"ruleset_allow_in", "0"},
{"r_projection", "0"},
{"gl_shadeq1_name", "*"},
// {"cl_rollalpha", "20"},
{"cl_iDrive", "0"},
{NULL}
};
@ -673,9 +703,12 @@ static rulesetrule_t rulesetrules_nqr[] = {
static ruleset_t rulesets[] =
{
{"strict", rulesetrules_strict},
{"nqr", rulesetrules_nqr},
//{"eql", rulesetrules_nqr},
{"strict", rulesetrules_strict},
{"qcon", rulesetrules_strict}, //not authorised but oh well. imported configs tend to piss people off.
{"smackdown", rulesetrules_strict}, //officially, smackdown cannot authorise this, thus we do not use that name. however, imported configs tend to piss people off.
{"thunderdome", rulesetrules_thunderdome}, //more permissive (doesn't block particles.
{"nqr", rulesetrules_nqr},
//{"eql", rulesetrules_nqr},
{NULL}
};

View file

@ -2013,14 +2013,26 @@ void R_DrawNameTags(void)
#if defined(CSQC_DAT) || !defined(CLIENTONLY)
if (r_showshaders.ival && cl.worldmodel && cl.worldmodel->loadstate == MLS_LOADED)
{
#ifdef CSQC_DAT
extern world_t csqc_world;
#endif
trace_t trace;
char *str;
vec3_t targ;
vec2_t scale = {12,12};
msurface_t *surf;
VectorMA(r_refdef.vieworg, 8192, vpn, targ);
//FIXME: should probably do a general trace, to hit (networked) submodels too
cl.worldmodel->funcs.NativeTrace(cl.worldmodel, 0, PE_FRAMESTATE, NULL, r_refdef.vieworg, targ, vec3_origin, vec3_origin, false, ~0, &trace);
#ifdef CSQC_DAT
if (csqc_world.progs)
{
int oldhit = csqc_world.edicts->xv->hitcontentsmaski;
csqc_world.edicts->xv->hitcontentsmaski = ~0;
trace = World_Move(&csqc_world, r_refdef.vieworg, vec3_origin, vec3_origin, targ, MOVE_EVERYTHING, csqc_world.edicts);
csqc_world.edicts->xv->hitcontentsmaski = oldhit;
}
else
#endif
cl.worldmodel->funcs.NativeTrace(cl.worldmodel, 0, PE_FRAMESTATE, NULL, r_refdef.vieworg, targ, vec3_origin, vec3_origin, false, ~0, &trace);
surf = Mod_GetSurfaceNearPoint(cl.worldmodel, trace.endpos);
if (surf)

View file

@ -707,8 +707,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#endif
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
#define FTE_DEPRECATED __attribute__((__deprecated__)) //no idea about the actual gcc version
#ifdef _WIN32
#define LIKEPRINTF(x) __attribute__((format(ms_printf,x,x+1)))
#if defined(_WIN32)
#include <stdio.h>
#ifdef __MINGW_PRINTF_FORMAT
#define LIKEPRINTF(x) __attribute__((format(__MINGW_PRINTF_FORMAT,x,x+1)))
#else
#define LIKEPRINTF(x) __attribute__((format(ms_printf,x,x+1)))
#endif
#else
#define LIKEPRINTF(x) __attribute__((format(printf,x,x+1)))
#endif

View file

@ -805,37 +805,56 @@ static void Cmd_Exec_f (void)
#ifndef QUAKETC
//hack to try to work around nquake's b0rkedness
if (!strncmp(s, "// This is nQuake's Frogbot config", 33))
s = "echo Refusing to exec nQuake's Frogbot config"; //otherwise many people with nquake installed will be fucked over whenever they try playing singleplayer
else if (!strncmp(s, "// ", 3))
{
char *eol = strstr(s, "\n");
if (eol)
{
*eol = 0;
s = eol+1;
if (strstr(f, "nQuake"))
{ //this is evil, but if we're running quake then com_parseutf8 will be 0 and we can just convert to quake chars.
char *in = s;
char *out = s;
int foundone = 0;
while (*in)
{
if (*in == '^')
{
*out++ = 0x80|*++in;
foundone++;
}
else
*out++ = *in;
in++;
}
if (foundone)
Cbuf_InsertText(va("echo fixups for nquake config %s: %i replacements\n", buf, foundone), level, false);
}
}
s = "echo Refusing to exec nQuake's Frogbot config"; //otherwise many people with nquake installed will be fucked over whenever they try playing singleplayer
Cbuf_InsertText (s, level, true);
}
#endif
else
{
int foundone = 0;
while (!strncmp(s, "//", 2))
{
char *eol = strstr(s, "\n");
if (eol)
{
*eol++ = 0;
if (strstr(s, "nQuake") || strstr(s, "N Q U A K E"))
{ //this is evil, but if we're running quake then com_parseutf8 will be 0 and we can just convert to quake chars (less text).
char *out = s = eol;
const char *in = s;
while (*in)
{
if (*in == '\n' && !strncmp(in,"\nexec configs/config.cfg", 24))
{ //ezquake writes its configs elsewhere, and nquake stomps on everything in its autoexec.cfg, so we need to try to work around its breakages
memmove(out, in, 6);out+=6;in+=6;
in += 8;
foundone++;
continue;
}
if (*in == '^')
{
*out++ = 0x80|*++in;
foundone++;
}
else
*out++ = *in;
in++;
}
*out = 0;
break;
}
s = eol;
continue;
}
break;
}
Cbuf_InsertText (s, level, true);
if (foundone)
Cbuf_InsertText(va("\necho \""CON_ERROR"fixups for nquake config %s: %i replacements\"\n", buf, foundone), level, false);
}
#else
Cbuf_InsertText (s, level, true);
#endif
if (cvar_watched)
Cbuf_InsertText (va("echo BEGIN %s", buf), level, true);
BZ_Free(f);

View file

@ -23,6 +23,7 @@ cvar_t r_lerpmuzzlehack = CVARF ("r_lerpmuzzlehack", "1", CVAR_ARCHIVE);
#ifdef MD1MODELS
cvar_t mod_h2holey_bugged = CVARD ("mod_h2holey_bugged", "0", "Hexen2's holey-model flag uses index 0 as transparent (and additionally 255 in gl, due to a bug). GLQuake engines tend to have bugs that use ONLY index 255, resulting in a significant compatibility issue that can be resolved only with this shitty cvar hack.");
cvar_t mod_halftexel = CVARD ("mod_halftexel", "1", "Offset texture coords by a half-texel, for compatibility with glquake and the majority of engine forks.");
cvar_t mod_nomipmap = CVARD ("mod_nomipmap", "0", "Disables the use of mipmaps on quake1 mdls, consistent with its original software renderer.");
#endif
static void QDECL r_meshpitch_callback(cvar_t *var, char *oldvalue)
{
@ -3150,6 +3151,8 @@ void Mod_LoadAliasShaders(model_t *mod)
if (!ruleset_allow_sensitive_texture_replacements.ival)
imageflags |= IF_NOREPLACE;
}
if (mod->fromgame == fg_quake && mod_nomipmap.ival)
imageflags |= IF_NOMIPMAP;
slash = COM_SkipPath(mod->name);
if (slash != mod->name && slash-mod->name < sizeof(alttexpath))

View file

@ -24,8 +24,94 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
cvar_group_t *cvar_groups;
hashtable_t cvar_hash;
bucket_t *cvar_buckets[1024];
//static bucket_t *cvar_buckets[1024];
//static hashtable_t cvar_hash;
typedef struct {
size_t maxentries;
size_t numentries;
struct
{
const char *string;
void *data;
} entry[1];
} abucket_t;
typedef struct {
abucket_t **bucket;
unsigned int numbuckets;
} ahashtable_t; //not thread-safe
static abucket_t *cvar_buckets[1024];
static ahashtable_t cvar_hash = {cvar_buckets, countof(cvar_buckets)};
unsigned int Hash_KeyInsensitive(const char *name, unsigned int modulus);
void *AHash_GetInsensitive(ahashtable_t *table, const char *name)
{
abucket_t *b = table->bucket[Hash_KeyInsensitive(name, table->numbuckets)];
size_t i;
if (b)
for (i = 0; i < b->numentries; i++)
{
if (!strcasecmp(b->entry[i].string, name))
return b->entry[i].data;
}
return NULL;
}
void AHash_RemoveDataInsensitive(ahashtable_t *table, const char *name, void *data)
{
abucket_t *b = table->bucket[Hash_KeyInsensitive(name, table->numbuckets)];
size_t i;
for (i = 0; i < b->numentries; i++)
{
if (b->entry[i].data == data && !strcasecmp(b->entry[i].string, name))
{
//strip it.
b->numentries--;
//shift everything down.
if (b->numentries > i)
memmove(&b->entry[i], &b->entry[i+1], b->numentries-1);
break;
}
}
}
void AHash_AddInsensitive(ahashtable_t *table, const char *name, void *data)
{
unsigned int idx = Hash_KeyInsensitive(name, table->numbuckets);
abucket_t *b = table->bucket[idx];
if (!b)
{ //nothing there!...
b = table->bucket[idx] = BZ_Malloc(sizeof(*b));
b->numentries = 0;
b->maxentries = countof(b->entry);
}
else if (b->numentries == b->maxentries)
{ //can't add anything new
size_t n = b->maxentries*2;
table->bucket[idx] = BZ_Malloc(sizeof(*b)-sizeof(b->entry) + sizeof(b->entry)*n);
memcpy(table->bucket[idx]->entry, b->entry, sizeof(b->entry[0])*b->numentries);
table->bucket[idx]->numentries = b->numentries;
table->bucket[idx]->maxentries = n;
BZ_Free(b);
b = table->bucket[idx];
}
b->entry[b->numentries].data = data;
b->entry[b->numentries].string = name;
b->numentries++;
}
void AHash_Cleanup(ahashtable_t *table)
{
size_t i;
for (i = 0; i < table->numbuckets; i++)
{
if (table->bucket[i] && !table->bucket[i]->numentries)
{
BZ_Free(table->bucket[i]);
table->bucket[i] = NULL;
}
}
}
int cvar_watched;
//cvar_t *cvar_vars;
@ -69,7 +155,7 @@ Cvar_FindVar
*/
cvar_t *Cvar_FindVar (const char *var_name)
{
return Hash_GetInsensitive(&cvar_hash, var_name);
return AHash_GetInsensitive(&cvar_hash, var_name);
/*
cvar_group_t *grp;
cvar_t *var;
@ -1126,9 +1212,9 @@ unlinked:
Cvar_DefaultFree(tbf->defaultstr);
if (tbf->latched_string)
Z_Free(tbf->latched_string);
Hash_RemoveData(&cvar_hash, tbf->name, tbf);
AHash_RemoveDataInsensitive(&cvar_hash, tbf->name, tbf);
if (tbf->name2)
Hash_RemoveData(&cvar_hash, tbf->name2, tbf);
AHash_RemoveDataInsensitive(&cvar_hash, tbf->name2, tbf);
Z_Free(tbf);
}
@ -1190,9 +1276,9 @@ qboolean Cvar_Register (cvar_t *variable, const char *groupname)
Cvar_Free(old);
Hash_AddInsensitive(&cvar_hash, variable->name, variable, &variable->hbn1);
AHash_AddInsensitive(&cvar_hash, variable->name, variable);
if (variable->name2)
Hash_AddInsensitive(&cvar_hash, variable->name2, variable, &variable->hbn2);
AHash_AddInsensitive(&cvar_hash, variable->name2, variable);
return true;
}
@ -1220,9 +1306,9 @@ qboolean Cvar_Register (cvar_t *variable, const char *groupname)
variable->restriction = 0; //exe registered vars
group->cvars = variable;
Hash_AddInsensitive(&cvar_hash, variable->name, variable, &variable->hbn1);
AHash_AddInsensitive(&cvar_hash, variable->name, variable);
if (variable->name2)
Hash_AddInsensitive(&cvar_hash, variable->name2, variable, &variable->hbn2);
AHash_AddInsensitive(&cvar_hash, variable->name2, variable);
variable->string = NULL;
@ -1588,7 +1674,7 @@ void QDECL Cvar_Limiter_ZeroToOne_Callback(struct cvar_s *var, char *oldvalue)
void Cvar_Init(void)
{
memset(cvar_buckets, 0, sizeof(cvar_buckets));
Hash_InitTable(&cvar_hash, sizeof(cvar_buckets)/Hash_BytesForBuckets(1), cvar_buckets);
//Hash_InitTable(&cvar_hash, sizeof(cvar_buckets)/Hash_BytesForBuckets(1), cvar_buckets);
}
void Cvar_Shutdown(void)
@ -1622,4 +1708,5 @@ void Cvar_Shutdown(void)
cvar_groups = grp->next;
Z_Free(grp);
}
AHash_Cleanup(&cvar_hash);
}

View file

@ -82,7 +82,6 @@ typedef struct cvar_s
#ifdef HLSERVER
struct hlcvar_s *hlcvar;
#endif
bucket_t hbn1, hbn2;
} cvar_t;
#ifdef MINIMAL

View file

@ -1584,7 +1584,7 @@ static qboolean FSZIP_ReadCentralEntry(zipfile_t *zip, qbyte *data, struct zipce
entry->gflags = LittleU2FromPtr(data+8);
entry->cmethod = LittleU2FromPtr(data+10);
entry->lastmodfiletime = LittleU2FromPtr(data+12);
entry->lastmodfiledate = LittleU2FromPtr(data+12);
entry->lastmodfiledate = LittleU2FromPtr(data+14);
entry->crc32 = LittleU4FromPtr(data+16);
entry->csize = LittleU4FromPtr(data+20);
entry->usize = LittleU4FromPtr(data+24);

View file

@ -94,7 +94,7 @@ size_t Fragment_ClipPlaneToBrush(vecV_t *points, size_t maxpoints, void *planes,
vec3_t right, forward;
double t;
float *plane;
// if (face[2] != 1)
// return 0;
@ -142,7 +142,7 @@ size_t Fragment_ClipPlaneToBrush(vecV_t *points, size_t maxpoints, void *planes,
numverts = Fragment_ClipPolyToPlane((float*)verts, (float*)verts2, numverts, norm, -plane[3]);
else
numverts = Fragment_ClipPolyToPlane((float*)verts2, (float*)verts, numverts, norm, -plane[3]);
if (numverts < 3) //totally clipped.
return 0;
}
@ -621,7 +621,8 @@ void Mod_ClipDecal(struct model_s *mod, vec3_t center, vec3_t normal, vec3_t tan
if (!mod || mod->loadstate != MLS_LOADED)
return;
else if (mod->type != mod_brush)
;
#ifdef Q1BSPS
else if (mod->fromgame == fg_quake || mod->fromgame == fg_halflife)
Q1BSP_ClipDecalToNodes(mod, &dec, mod->rootnode);
@ -1498,7 +1499,7 @@ void Q1BSP_LoadBrushes(model_t *model, bspx_header_t *bspx, void *mod_base)
brush->planes[brush->numplanes].dist = -perbrush->mins[pl];
brush->numplanes++;
}
/*link it in to the bsp tree*/
Q1BSP_InsertBrush(rootnode, brush, perbrush->mins, perbrush->maxs);
@ -1807,7 +1808,7 @@ static qbyte *Q1BSP_ClusterPVS (model_t *model, int cluster, pvsbuffer_t *buffer
static void SV_Q1BSP_AddToFatPVS (model_t *mod, const vec3_t org, mnode_t *node, pvsbuffer_t *pvsbuffer)
{
mplane_t *plane;
float d;
float d;
while (1)
{
@ -2760,7 +2761,7 @@ void Mod_FindCubemaps_f(void)
size_t nenvmap = 0;
unsigned int *envmapidx = NULL; //*numsurfaces
size_t nenvmapidx = 0, i;
//find targetnames, and store their origins so that we can deal with spotlights.
for (lmp = entlump; ;)
{
@ -2808,7 +2809,7 @@ void Mod_FindCubemaps_f(void)
else if (!strcmp("size", key))
sscanf(value, "%f", &size);
}
if (isenvmap)
{
int e = nenvmap;

View file

@ -218,6 +218,16 @@ static const char *imgs[] =
//they're provided as fallbacks.
#define MAX_FACES 32
enum fontfmt_e
{
FMT_AUTO, //freetype, or quake
FMT_QUAKE, //first is default
FMT_ISO88591, //latin-1 (first 256 chars of unicode too, c1 glyphs are usually invisible)
FMT_WINDOWS1252,//variation of latin-1 with extra glyphs
FMT_KOI8U, //image is 16*16 koi8-u codepage.
FMT_HORIZONTAL, //unicode, charcount=width/(height-2). single strip of chars, like halflife.
};
typedef struct fontface_s
{
struct fontface_s *fnext;
@ -228,8 +238,11 @@ typedef struct fontface_s
struct
{
qbyte *data;
size_t width;
size_t height;
size_t rows; //urgh.
size_t stride;
size_t charheight;
enum fontfmt_e codepage;
qboolean paletted;
} horiz;
#ifdef HALFLIFEMODELS
@ -997,6 +1010,164 @@ static struct charcache_s *Font_LoadPlaceholderGlyph(font_t *f, CHARIDXTYPE char
return c;
}
static struct charcache_s *Font_TryLoadGlyphRaster(font_t *f, fontface_t *qface, CHARIDXTYPE charidx)
{
size_t maxchar = 256;
const unsigned short *c1tab;
size_t c1tabsize;
size_t glyph = charidx;
safeswitch(qface->horiz.codepage)
{
safedefault:
case FMT_AUTO: //shouldn't happen.
case FMT_ISO88591: //all identity.
case FMT_HORIZONTAL: //erk...
c1tab = NULL;
c1tabsize = 0;
break;
case FMT_WINDOWS1252:
{
static const unsigned short win1252[] = {
0x20ac, 0x81,0x201a,0x0192, 0x201e,0x2026,0x2020,0x2021, 0x02c6,0x2030,0x0160,0x2039, 0x0152, 0x8d,0x017d, 0x8f,
0x90,0x2018,0x2019,0x101c, 0x201d,0x2022,0x2013,0x2014, 0x02dc,0x2122,0x0161,0x203a, 0x0153, 0x9d,0x017e,0x0178};
c1tab = win1252;
c1tabsize = sizeof(win1252);
}
break;
case FMT_KOI8U:
{
static const unsigned short koi8u[] = {
0x2500,0x2502,0x250C,0x2510, 0x2514,0x2518,0x251C,0x2524, 0x252C,0x2534,0x253C,0x2580, 0x2584,0x2588,0x258C,0x2590,
0x2591,0x2592,0x2593,0x2320, 0x25A0,0x2219,0x221A,0x2248, 0x2264,0x2265,0x00A0,0x2321, 0x00B0,0x00B2,0x00B7,0x00F7,
0x2550,0x2551,0x2552,0x0451, 0x0454,0x2554,0x0456,0x0457, 0x2557,0x2558,0x2559,0x255A, 0x255B,0x0491,0x255D,0x255E,
0x255F,0x2560,0x2561,0x0401, 0x0404,0x2563,0x0406,0x0407, 0x2566,0x2567,0x2568,0x2569, 0x256A,0x0490,0x256C,0x00A9,
0x044E,0x0430,0x0431,0x0446, 0x0434,0x0435,0x0444,0x0433, 0x0445,0x0438,0x0439,0x043A, 0x043B,0x043C,0x043D,0x043E,
0x043F,0x044F,0x0440,0x0441, 0x0442,0x0443,0x0436,0x0432, 0x044C,0x044B,0x0437,0x0448, 0x044D,0x0449,0x0447,0x044A,
0x042E,0x0410,0x0411,0x0426, 0x0414,0x0415,0x0424,0x0413, 0x0425,0x0418,0x0419,0x041A, 0x041B,0x041C,0x041D,0x041E,
0x041F,0x042F,0x0420,0x0421, 0x0422,0x0423,0x0416,0x0412, 0x042C,0x042B,0x0417,0x0428, 0x042D,0x0429,0x0427,0x042A};
c1tab = koi8u;
c1tabsize = sizeof(koi8u);
}
break;
case FMT_QUAKE:
{
c1tab = NULL;
c1tabsize = 0;
if (glyph >= 0xe000 && glyph < 0xe100)
glyph -= 0xe000;
else if (glyph < 32 || glyph >= 0x80)
return NULL;
}
break;
}
if (glyph >= maxchar)
return NULL;
if (glyph >= 0x80 && glyph < 0x80+c1tabsize)
{
int i;
for (i = 0; ; i++)
{
if (i == c1tabsize)
return NULL;
if (glyph == c1tab[i])
{
glyph = 0x80+i;
break;
}
}
}
{
int gw = (qface->horiz.stride)/(maxchar/qface->horiz.rows);
int gr = glyph / (maxchar/qface->horiz.rows);
int gc = glyph - (gr*(maxchar/qface->horiz.rows));
int gs = qface->horiz.stride;
int gh = qface->horiz.charheight;
struct charcache_s *c;
if (qface->horiz.paletted)
{
qbyte *in = (qbyte*)qface->horiz.data + gc*gw + gr*gs*gh;
/*while (gw >= 1)
{
int y;
gw--; //see if we can strip this column
for (y = 0; y < gh; y++)
if (in[gw+y*gs])
break;
if (y < gh)
{
gw++;
break;
}
}*/
{
int ngw = (gw * f->charheight) / gh;
int ngh = f->charheight;
int x, y;
unsigned int *out2 = alloca(ngw*ngh*4);
if (ngw&&ngh)
{
unsigned int *out1 = alloca(gw*gh*4);
for (y = 0; y < gh; y++)
for (x = 0; x < gw; x++)
out1[x+y*gw] = in[x+y*gs]?d_8to24rgbtable[in[x+y*gs]]:0;
Image_ResampleTexture(PTI_RGBA8, out1, gw, gh, out2, ngw, ngh);
}
c = Font_LoadGlyphData(f, charidx, FT_PIXEL_MODE_RGBA, out2, ngw, ngh, ngw*4);
gw = ngw;
}
}
else
{
unsigned int *in = (unsigned int*)qface->horiz.data + gc*gw + gr*gs*gh;
while (gw >= 1)
{
int y;
gw--; //see if we can strip this column
for (y = 0; y < gh; y++)
if (in[gw+y*gs] & 0x00ffffff)
break;
if (y < gh)
{
gw++;
break;
}
}
if (f->charheight != gh)
{
int ngw = (gw * f->charheight) / gh;
int ngh = f->charheight;
int x, y;
unsigned int *out2 = alloca(ngw*ngh*4);
if (ngw&&ngh)
{ //we need to repack the input, because Image_ResampleTexture can't handle strides
unsigned int *out1 = alloca(gw*gh*4);
for (y = 0; y < gh; y++)
for (x = 0; x < gw; x++)
out1[x+y*gw] = in[x+y*gs];
Image_ResampleTexture(PTI_RGBA8, out1, gw, gh, out2, ngw, ngh);
}
c = Font_LoadGlyphData(f, charidx, FT_PIXEL_MODE_RGBA, out2, ngw, ngh, ngw*4);
gw = ngw;
}
else
c = Font_LoadGlyphData(f, charidx, FT_PIXEL_MODE_RGBA, in, gw, gh, gs*4);
}
if (!gw) //for invisble glyphs (eg: space), we attempt to ensure that there's some substance there. missing spaces is weird.
gw = gh/3;
if (c)
{
c->advance = gw;
c->left = 0;
c->top = 0;
c->flags &= ~CHARF_FORCEWHITE;
return c;
}
}
return NULL;
}
//loads the given charidx for the given font, importing from elsewhere if needed.
static struct charcache_s *Font_TryLoadGlyph(font_t *f, CHARIDXTYPE charidx)
{
@ -1265,62 +1436,9 @@ static struct charcache_s *Font_TryLoadGlyph(font_t *f, CHARIDXTYPE charidx)
#endif
if (qface->horiz.data)
{
#if 1
size_t maxchar = 256;
int gw = qface->horiz.width/maxchar;
#else
int gw = qface->horiz.height-(qface->horiz.height/12);
size_t maxchar = qface->horiz.width / gw;
#endif
size_t glyph = charidx /* - qface->horiz.firstcodepoint*/;
if (glyph < maxchar)
{
unsigned int *glyphdata = (unsigned int*)qface->horiz.data + glyph*gw;
int gh = qface->horiz.height;
int gs = qface->horiz.width;
unsigned int *out = glyphdata;
while (gw >= 1)
{
int y;
gw--; //see if we can strip this column
for (y = 0; y < gh; y++)
if (glyphdata[gw+y*gs] & 0x00ffffff)
break;
if (y < gh)
{
gw++;
break;
}
}
if (f->charheight != gh)
{
int ngw = (gw * f->charheight) / gh;
int ngh = f->charheight;
int x, y;
unsigned int *out2 = alloca(ngw*ngh*4);
if (ngw&&ngh)
{ //we need to repack the input, because Image_ResampleTexture can't handle strides
unsigned int *out1 = alloca(gw*gh*4);
for (y = 0; y < gh; y++)
for (x = 0; x < gw; x++)
out1[x+y*gw] = out[x+y*gs];
Image_ResampleTexture(PTI_RGBA8, out1, gw, gh, out2, ngw, ngh);
}
c = Font_LoadGlyphData(f, charidx, FT_PIXEL_MODE_RGBA, out2, ngw, ngh, ngw*4);
gw = ngw;
}
else
c = Font_LoadGlyphData(f, charidx, FT_PIXEL_MODE_RGBA, out, gw, gh, gs*4);
if (!gw) //for invisble glyphs (eg: space), we attempt to ensure that there's some substance there. missing spaces is weird.
gw = gh/3;
if (c)
{
c->advance = gw;
c->left = 0;
c->top = 0;
return c;
}
}
c = Font_TryLoadGlyphRaster(f, qface, charidx);
if (c)
return c;
}
}
}
@ -1447,8 +1565,11 @@ qboolean Font_LoadHorizontalFont(struct font_s *f, int fheight, const char *font
if (qface->fnext)
qface->fnext->flink = &qface->fnext;
qface->horiz.data = rgbadata;
qface->horiz.width = width;
qface->horiz.height = height;
qface->horiz.stride = width;
qface->horiz.charheight = height;
qface->horiz.rows = 1;
qface->horiz.paletted = false;
qface->horiz.codepage = FMT_ISO88591;
qface->refs++;
Q_strncpyz(qface->name, fontfilename, sizeof(qface->name));
@ -1707,28 +1828,6 @@ static texid_t Font_LoadReplacementConchars(void)
return tex;
return r_nulltex;
}
static texid_t Font_LoadQuakeConchars(void)
{
/*unsigned int i;
qbyte *lump;
lump = W_SafeGetLumpName ("conchars");
if (lump)
{
// add ocrana leds
if (con_ocranaleds.ival)
{
if (con_ocranaleds.ival != 2 || QCRC_Block(lump, 128*128) == 798)
AddOcranaLEDsIndexed (lump, 128, 128);
}
for (i=0 ; i<128*128 ; i++)
if (lump[i] == 0)
lump[i] = 255; // proper transparent color
return R_LoadTexture8("charset", 128, 128, (void*)lump, IF_LOADNOW|IF_UIPIC|IF_NOMIPMAP|IF_NOGAMMA, 1);
}*/
return r_nulltex;
}
#ifdef HEXEN2
static texid_t Font_LoadHexen2Conchars(qboolean iso88591)
@ -1875,16 +1974,6 @@ static texid_t Font_LoadFallbackConchars(void)
return tex;
}
enum fontfmt_e
{
FMT_AUTO, //freetype, or quake
FMT_QUAKE, //first is default
FMT_ISO88591, //latin-1 (first 256 chars of unicode too, c1 glyphs are usually invisible)
FMT_WINDOWS1252,//variation of latin-1 with extra glyphs
FMT_KOI8U, //image is 16*16 koi8-u codepage.
FMT_HORIZONTAL, //unicode, charcount=width/(height-2). single strip of chars, like halflife.
};
/*loads a fallback image. not allowed to fail (use syserror if needed)*/
static texid_t Font_LoadDefaultConchars(enum fontfmt_e *fmt)
{
@ -1892,11 +1981,6 @@ static texid_t Font_LoadDefaultConchars(enum fontfmt_e *fmt)
tex = Font_LoadReplacementConchars();
if (TEXLOADED(tex))
return tex;
tex = Font_LoadQuakeConchars();
if (tex && tex->status == TEX_LOADING)
COM_WorkerPartialSync(tex, &tex->status, TEX_LOADING);
if (TEXLOADED(tex))
return tex;
#ifdef HEXEN2
tex = Font_LoadHexen2Conchars(true);
if (tex && tex->status == TEX_LOADING)
@ -1959,6 +2043,54 @@ void Doom_ExpandPatch(doompatch_t *p, unsigned char *b, int stride)
}
}
static qboolean Font_LoadFontLump(font_t *f, const char *facename)
{
size_t lumpsize = 0;
qbyte lumptype = 0;
void *lumpdata;
if (f->faces == MAX_FACES)
return false; //can't store it...
lumpdata = W_GetLumpName(facename, &lumpsize, &lumptype);
if (!lumpdata)
return false;
if ((lumptype == TYP_MIPTEX && lumpsize==(8*8)*(16*16)) || //proper format
(lumptype == TYP_QPIC && lumpsize==(8*8)*(16*16)+8)) //fucked up buggy format used by some people
{
fontface_t *fa = Z_Malloc(sizeof(*fa));
fa->horiz.data = lumpdata;
fa->horiz.stride = 8*16;
fa->horiz.charheight = 8;
fa->horiz.codepage = FMT_QUAKE;
fa->horiz.paletted = true;
fa->horiz.rows = 16;
if (con_ocranaleds.ival)
{
if (con_ocranaleds.ival != 2 || QCRC_Block(lumpdata, 128*128) == 798)
AddOcranaLEDsIndexed (lumpdata, 128, 128);
}
fa->flink = &fa->fnext;
fa->refs = 1;
f->face[f->faces++] = fa;
return true;
}
#ifdef HALFLIFEMODELS
else if (lumptype == TYP_HLFONT)
{
fontface_t *fa = Z_Malloc(sizeof(*fa));
fa->halflife = lumpdata;
fa->flink = &fa->fnext;
fa->refs = 1;
f->face[f->faces++] = fa;
// f->charheight = fa->halflife->fontheight1; //force the font to a specific size.
return true;
}
#endif
return false; //doesn't match a valid known format
}
//creates a new font object from the given file, with each text row with the given height.
//width is implicit and scales with height and choice of font.
struct font_s *Font_LoadFont(const char *fontfilename, float vheight, float scale, int outline)
@ -2226,9 +2358,18 @@ struct font_s *Font_LoadFont(const char *fontfilename, float vheight, float scal
if (fmt == FMT_HORIZONTAL)
Font_LoadHorizontalFont(f, height, start);
#ifdef AVAIL_FREETYPE
else if (fmt == FMT_AUTO)
Font_LoadFreeTypeFont(f, height, start);
else if (fmt == FMT_AUTO && Font_LoadFreeTypeFont(f, height, start))
;
#endif
else if (!TEXLOADED(f->singletexture) && *start)
{
f->singletexture = R_LoadHiResTexture(start, "fonts:charsets", IF_PREMULTIPLYALPHA|(r_font_linear.ival?IF_LINEAR:IF_NEAREST)|IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|IF_NOPURGE|IF_LOADNOW);
if (f->singletexture->status == TEX_LOADING)
COM_WorkerPartialSync(f->singletexture, &f->singletexture->status, TEX_LOADING);
if (!TEXLOADED(f->singletexture) && f->faces < MAX_FACES)
Font_LoadFontLump(f, start);
}
if (end)
{
@ -2240,42 +2381,8 @@ struct font_s *Font_LoadFont(const char *fontfilename, float vheight, float scal
}
}
#ifdef HALFLIFEMODELS
if (!f->faces)
{
if (f->faces < MAX_FACES)
{
size_t lumpsize;
qbyte lumptype = 0;
void *lumpdata = NULL;
if ((!lumpdata || lumptype != TYP_HLFONT) && *fontfilename)
lumpdata = W_GetLumpName(fontfilename, &lumpsize, &lumptype);
if (!lumpdata || lumptype != TYP_HLFONT)
lumpdata = W_GetLumpName("conchars", &lumpsize, &lumptype);
if (lumpdata && lumptype == TYP_HLFONT)
{
fontface_t *fa = Z_Malloc(sizeof(*fa));
fa->halflife = lumpdata;
fa->flink = &fa->fnext;
fa->refs = 1;
f->face[f->faces++] = fa;
// f->charheight = fa->halflife->fontheight1; //force the font to a specific size.
return f;
}
}
}
#endif
if (!f->faces)
{
//default to only map the ascii-compatible chars from the quake font.
if (*fontfilename)
{
f->singletexture = R_LoadHiResTexture(fontfilename, "fonts:charsets", IF_PREMULTIPLYALPHA|(r_font_linear.ival?IF_LINEAR:IF_NEAREST)|IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|IF_NOPURGE);
if (f->singletexture->status == TEX_LOADING)
COM_WorkerPartialSync(f->singletexture, &f->singletexture->status, TEX_LOADING);
}
}
if (!f->faces && !TEXLOADED(f->singletexture) && r_font_linear.ival)
Font_LoadFontLump(f, "conchars");
defaultplane = INVALIDPLANE;/*assume the bitmap plane - don't use the fallback as people don't think to use com_parseutf8*/
if (TEXLOADED(f->singletexture))

View file

@ -327,6 +327,8 @@ static qboolean Shader_EvaluateCondition(shader_t *shader, const char **ptr)
lhs = r_deluxemapping;
else if (!Q_stricmp(token, "softwarebanding"))
lhs = r_softwarebanding;
else if (!Q_stricmp(token, "unmaskedsky"))
lhs = cls.allow_unmaskedskyboxes; //can/should skip writing depth values for sky surfaces.
//normalmaps are generated if they're not already known.
else if (!Q_stricmp(token, "normalmap"))
@ -1372,7 +1374,7 @@ struct programpermu_s *Shader_LoadPermutation(program_t *prog, unsigned int p)
size_t offset;
qboolean fail = false;
extern cvar_t gl_specular, gl_specular_power;
extern cvar_t r_glsl_pbr, gl_specular, gl_specular_power;
if (~prog->supportedpermutations & p)
return NULL; //o.O
@ -1384,6 +1386,8 @@ struct programpermu_s *Shader_LoadPermutation(program_t *prog, unsigned int p)
Q_strlcatfz(defines, &offset, sizeof(defines), "#define MAX_GPU_BONES %i\n", sh_config.max_gpu_bones);
if (gl_specular.value)
Q_strlcatfz(defines, &offset, sizeof(defines), "#define SPECULAR\n#define SPECULAR_BASE_MUL %f\n#define SPECULAR_BASE_POW %f\n", 1.0*gl_specular.value, max(1,gl_specular_power.value));
if (r_glsl_pbr.ival)
Q_strlcatfz(defines, &offset, sizeof(defines), "#define PBR\n");
#ifdef RTLIGHTS
if (r_fakeshadows)
Q_strlcatfz(defines, &offset, sizeof(defines), "#define FAKESHADOWS\n%s",
@ -1932,7 +1936,7 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
break;
while (*script && *script != '\n')
script++;
};
}
prog->shadertext = Z_StrDup(script);
if (qrenderer == qrtype && ver < 150)
@ -6584,6 +6588,9 @@ char *Shader_DefaultBSPWater(parsestate_t *ps, const char *shortname, char *buff
"{\n"
"surfaceparm nodlight\n"
"surfaceparm nomarks\n"
"if %g < 1\n"
"sort underwater\n"
"endif\n"
"{\n"
"program defaultwarp%s\n"
"map $diffuse\n"
@ -6595,7 +6602,7 @@ char *Shader_DefaultBSPWater(parsestate_t *ps, const char *shortname, char *buff
"}\n"
"surfaceparm hasdiffuse\n"
"}\n"
, (explicitalpha||alpha==1)?"":va("#ALPHA=%g",alpha), alpha, alpha);
, alpha, (explicitalpha||alpha==1)?"":va("#ALPHA=%g",alpha), alpha, alpha);
return buffer;
case 2: //refraction of the underwater surface, with a fresnel
return (

View file

@ -94,12 +94,20 @@ void R_SetSky(const char *sky)
COM_WorkerPartialSync(tex.reflectcube, &tex.reflectcube->status, TEX_LOADING);
if (tex.reflectcube->width && TEXLOADED(tex.reflectcube))
{
/* FIXME: Q2/HL require the skybox to not draw over geometry, shouldn't we force it? --eukara */
if (cls.allow_skyboxes) {
forcedsky = R_RegisterShader(va("skybox_%s", sky), 0, "{\nsort sky\nprogram defaultskybox\n{\nmap \"$cube:$reflectcube\"\ntcgen skybox\n}\nsurfaceparm nodlight\nsurfaceparm sky\n}");
} else {
forcedsky = R_RegisterShader(va("skybox_%s", sky), 0, "{\nsort sky\nprogram defaultskybox\n{\ndepthwrite\nmap \"$cube:$reflectcube\"\ntcgen skybox\n}\nsurfaceparm nodlight\nsurfaceparm sky\n}");
}
forcedsky = R_RegisterShader(va("skybox_%s", sky), 0,
"{\n"
"sort sky\n"
"program defaultskybox\n"
"{\n"
"if !$unmaskedsky\n" /* Q2/HL require the skybox to not draw over geometry, shouldn't we force it? --eukara */
"depthwrite\n"
"endif\n"
"map \"$cube:$reflectcube\"\n"
"tcgen skybox\n"
"}\n"
"surfaceparm nodlight\n"
"surfaceparm sky\n"
"}");
R_BuildDefaultTexnums(&tex, forcedsky, IF_WORLDTEX);
return;
}
@ -222,7 +230,7 @@ qboolean R_DrawSkyroom(shader_t *skyshader)
//q3 mustn't mask sky (breaks q3map2's invisible skyportals), whereas q1 must (or its a cheat). halflife doesn't normally expect masking.
//we also MUST mask any sky inside skyrooms, or you'll see all the entities outside of the skyroom through the room's own sky (q3map2 skyportals are hopefully irrelevant in this case).
#define SKYMUSTBEMASKED (r_worldentity.model->fromgame != fg_quake3 || ((r_refdef.flags & RDF_DISABLEPARTICLES) && r_ignoreentpvs.ival))
#define SKYMUSTBEMASKED (r_worldentity.model->fromgame != fg_quake3 || ((r_refdef.flags & RDF_DISABLEPARTICLES) && r_ignoreentpvs.ival) || !cls.allow_unmaskedskyboxes)
/*
=================
@ -691,7 +699,7 @@ static void gl_skyspherecalc(int skytype)
static void GL_SkyForceDepth(batch_t *batch)
{
if (!cls.allow_skyboxes && batch->texture) //allow a little extra fps.
if (!cls.allow_unmaskedskyboxes && batch->texture) //allow a little extra fps.
{
BE_SelectMode(BEM_DEPTHONLY);
BE_DrawMesh_List(batch->shader, batch->meshes-batch->firstmesh, batch->mesh+batch->firstmesh, batch->vbo, NULL, batch->flags);

View file

@ -3004,7 +3004,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"affine varying vec2 tc;\n"
"varying vec4 light;\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) || defined(PBR)\n"
"varying vec3 eyevector;\n"
"#endif\n"
"#if defined(PBR)||defined(REFLECTCUBEMASK)\n"
@ -3039,9 +3039,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#endif\n"
"#endif\n"
"#if defined(PBR)\n"
"eyevector = e_eyepos - w.xyz;\n"
"#elif defined(SPECULAR)||defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
"#if defined(SPECULAR)||defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) || defined(PBR)\n"
"vec3 eyeminusvertex = e_eyepos - w.xyz;\n"
"eyevector.x = dot(eyeminusvertex, s.xyz);\n"
"eyevector.y = dot(eyeminusvertex, t.xyz);\n"
@ -3086,7 +3084,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"affine out vec2 t_tc[];\n"
"in vec4 light[];\n"
"out vec4 t_light[];\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) || defined(PBR)\n"
"in vec3 eyevector[];\n"
"out vec3 t_eyevector[];\n"
"#endif\n"
@ -3102,7 +3100,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"t_normal[id] = normal[id];\n"
"t_tc[id] = tc[id];\n"
"t_light[id] = light[id];\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) || defined(PBR)\n"
"t_eyevector[id] = eyevector[id];\n"
"#endif\n"
"#ifdef REFLECTCUBEMASK\n"
@ -3135,7 +3133,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"affine out vec2 tc;\n"
"in vec4 t_light[];\n"
"out vec4 light;\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) || defined(PBR)\n"
"in vec3 t_eyevector[];\n"
"out vec3 eyevector;\n"
"#endif\n"
@ -3158,7 +3156,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
//FIXME: we should be recalcing these here, instead of just lerping them
"light = LERP(t_light);\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) || defined(PBR)\n"
"eyevector = LERP(t_eyevector);\n"
"#endif\n"
"#ifdef REFLECTCUBEMASK\n"
@ -3198,7 +3196,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"affine varying vec2 tc;\n"
"varying vec4 light;\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) || defined(PBR)\n"
"varying vec3 eyevector;\n"
"#endif\n"
"#if defined(PBR) || defined(REFLECTCUBEMASK)\n"
@ -3292,7 +3290,8 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#endif\n"
"#else\n"
"#define roughness 0.3\n"
"#define specrgb 1.0 //vec3(dielectricSpecular)\n"
"#define specrgb vec3(1.0) //vec3(dielectricSpecular)\n"
"#define ambientrgb col.rgb\n"
"#endif\n"
"#ifdef BUMP\n"
@ -5668,7 +5667,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#include \"sys/fog.h\"\n"
"#if !defined(TESS_CONTROL_SHADER)\n"
"#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK)\n"
"#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK) || defined(PBR)\n"
"varying vec3 eyevector;\n"
"#endif\n"
@ -5700,7 +5699,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#endif\n"
"void main ()\n"
"{\n"
"#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK)\n"
"#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK) || defined(PBR)\n"
"vec3 eyeminusvertex = e_eyepos - v_position.xyz;\n"
"eyevector.x = dot(eyeminusvertex, v_svector.xyz);\n"
"eyevector.y = dot(eyeminusvertex, v_tvector.xyz);\n"
@ -5751,7 +5750,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"out vec3 t_vertex[];\n"
"in vec3 normal[];\n"
"out vec3 t_normal[];\n"
"#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK)\n"
"#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK) || defined(PBR)\n"
"in vec3 eyevector[];\n"
"out vec3 t_eyevector[];\n"
"#endif\n"
@ -5793,7 +5792,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#endif\n"
"#endif\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) || defined(PBR)\n"
"t_eyevector[id] = eyevector[id];\n"
"#endif\n"
@ -5817,7 +5816,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"in vec3 t_vertex[];\n"
"in vec3 t_normal[];\n"
"#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK)\n"
"#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK) || defined(PBR)\n"
"in vec3 t_eyevector[];\n"
"#endif\n"
"#ifdef REFLECTCUBEMASK\n"
@ -5867,7 +5866,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#ifdef REFLECTCUBEMASK\n"
"invsurface = LERP(t_invsurface);\n"
"#endif\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) || defined(PBR)\n"
"eyevector = LERP(t_eyevector);\n"
"#endif\n"
@ -5973,27 +5972,47 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#define gloss (1.0-roughness)\n"
"#define ambientrgb (specrgb+col.rgb)\n"
"vec3 specrgb = mix(vec3(dielectricSpecular), col.rgb, metalness);\n"
"col.rgb = col.rgb * (1.0 - dielectricSpecular) * (1.0-metalness);\n"
"vec3 albedorgb = col.rgb * (1.0 - dielectricSpecular) * (1.0-metalness);\n"
"#elif defined(SG) //pbr-style specular+glossiness\n"
//occlusion needs to be baked in. :(
"#define roughness (1.0-specs.a)\n"
"#define gloss specs.a\n"
"#define specrgb specs.rgb\n"
"#define ambientrgb (specs.rgb+col.rgb)\n"
"#else //blinn-phong\n"
"#define roughness (1.0-specs.a)\n"
"#define albedorgb col.rgb\n"
"#elif defined(PBR) //PBR using legacy texturemaps\n"
"#define gloss specs.a\n"
"#define specrgb specs.rgb\n"
"#define roughness (1.0-gloss)\n"
//metalness not relevant
//our pbr stuff doesn't much like our inputs.
"vec3 specrgb, albedorgb;\n"
//if (1==0)
//{ //metal
// specrgb = col.rgb;//+specs.rgb;
// albedorgb = vec3(0.0);
//}
//else
//{ //non-metal
"specrgb = vec3(dielectricSpecular);\n"
"albedorgb = col.rgb;//+specs.rgb;\n"
//}
"#define ambientrgb col.rgb\n"
"#else //blinn-phong\n"
"#define gloss specs.a\n"
//occlusion not defined
"#define specrgb specs.rgb\n"
"#endif\n"
"#else\n"
//no specular map specified. doesn't mean we shouldn't have any though, at least with pbr enabled.
"#define roughness 0.3\n"
"#define specrgb 1.0 //vec3(dielectricSpecular)\n"
"#define albedorgb col.rgb\n"
"#endif\n"
//add in specular, if applicable.
"#ifdef PBR\n"
"col.rgb = DoPBR(norm, normalize(eyevector), deluxe, roughness, col.rgb, specrgb, vec3(0.0,1.0,1.0));//*e_light_mul + e_light_ambient*.25*ambientrgb;\n"
"col.rgb = DoPBR(norm, normalize(eyevector), deluxe, roughness, albedorgb, specrgb, vec3(0.0,1.0,1.0));//*e_light_mul + e_light_ambient*.25*ambientrgb;\n"
"#elif defined(gloss)\n"
"vec3 halfdir = normalize(normalize(eyevector) + deluxe); //this norm should be the deluxemap info instead\n"
"float spec = pow(max(dot(halfdir, norm), 0.0), FTE_SPECULAR_EXPONENT * gloss);\n"
@ -11124,7 +11143,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#if defined(VERTEXCOLOURS)\n"
"varying vec4 vc;\n"
"#endif\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) || defined(PBR)\n"
"varying vec3 eyevector;\n"
"#endif\n"
"#ifdef REFLECTCUBEMASK\n"
@ -11169,7 +11188,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#if defined(VERTEXCOLOURS)\n"
"vc = v_colour;\n"
"#endif\n"
"#if defined(SPECULAR)||defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
"#if defined(SPECULAR)||defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) || defined(PBR)\n"
"vec3 eyeminusvertex = e_eyepos - w.xyz;\n"
"eyevector.x = dot(eyeminusvertex, s.xyz);\n"
"eyevector.y = dot(eyeminusvertex, t.xyz);\n"
@ -11210,7 +11229,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"in vec4 vc[];\n"
"out vec4 t_vc[];\n"
"#endif\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) || defined(PBR)\n"
"in vec3 eyevector[];\n"
"out vec3 t_eyevector[];\n"
"#endif\n"
@ -11225,7 +11244,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#if defined(VERTEXCOLOURS)\n"
"t_vc[id] = vc[id];\n"
"#endif\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) || defined(PBR)\n"
"t_eyevector[id] = eyevector[id];\n"
"#endif\n"
@ -11254,7 +11273,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#if defined(VERTEXCOLOURS)\n"
"in vec4 t_vc[];\n"
"#endif\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) || defined(PBR)\n"
"in vec3 t_eyevector[];\n"
"#endif\n"
@ -11280,7 +11299,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#if defined(VERTEXCOLOURS)\n"
"vc = LERP(t_vc);\n"
"#endif\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) || defined(PBR)\n"
"eyevector = LERP(t_eyevector);\n"
"#endif\n"
@ -11347,7 +11366,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"vec4 lc = texture2D(s_lower, tcbase);\n"
"bases.rgb += lc.rgb*e_lowercolour*lc.a;\n"
"#endif\n"
"#if defined(BUMP) || defined(SPECULAR) || defined(REFLECTCUBEMASK)\n"
"#if defined(BUMP) || defined(SPECULAR) || defined(REFLECTCUBEMASK) || defined(PBR)\n"
"vec3 bumps = normalize(vec3(texture2D(s_normalmap, tcbase)) - 0.5);\n"
"#elif defined(REFLECTCUBEMASK)\n"
"vec3 bumps = vec3(0.0,0.0,1.0);\n"
@ -11380,7 +11399,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#endif\n"
"#else\n"
"#define roughness 0.3\n"
"#define specrgb 1.0 //vec3(dielectricSpecular)\n"
"#define specrgb bases.rgb //vec3(dielectricSpecular)\n"
"#endif\n"
"#ifdef PBR\n"

View file

@ -49,37 +49,15 @@ pbool QC_strlcpy(char *dest, const char *src, size_t destsize) WARN_UNUSED_RESUL
pbool QC_strnlcpy(char *dest, const char *src, size_t srclen, size_t destsize) WARN_UNUSED_RESULT;
char *QC_strcasestr(const char *haystack, const char *needle);
#ifdef _MSC_VER
#define QC_vsnprintf _vsnprintf
static void VARGS QC_snprintfz (char *dest, size_t size, const char *fmt, ...)
{
va_list args;
va_start (args, fmt);
_vsnprintf (dest, size-1, fmt, args);
va_end (args);
//make sure its terminated.
dest[size-1] = 0;
}
#else
#define QC_vsnprintf vsnprintf
#define QC_snprintfz snprintf
#endif
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
#ifndef LIKEPRINTF
#define LIKEPRINTF(x) __attribute__((format(printf,x,x+1)))
#endif
#endif
#ifndef LIKEPRINTF
#define LIKEPRINTF(x)
#endif
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
#define FTE_DEPRECATED __attribute__((__deprecated__)) //no idea about the actual gcc version
#ifdef _WIN32
#define LIKEPRINTF(x) __attribute__((format(ms_printf,x,x+1)))
#if defined(_WIN32)
#include <stdio.h>
#ifdef __MINGW_PRINTF_FORMAT
#define LIKEPRINTF(x) __attribute__((format(__MINGW_PRINTF_FORMAT,x,x+1)))
#else
#define LIKEPRINTF(x) __attribute__((format(ms_printf,x,x+1)))
#endif
#else
#define LIKEPRINTF(x) __attribute__((format(printf,x,x+1)))
#endif
@ -90,6 +68,25 @@ static void VARGS QC_snprintfz (char *dest, size_t size, const char *fmt, ...)
#ifndef NORETURN
#define NORETURN
#endif
#ifndef LIKEPRINTF
#define LIKEPRINTF(x)
#endif
#ifdef _MSC_VER
#define QC_vsnprintf _vsnprintf
static void VARGS QC_snprintfz (char *dest, size_t size, const char *fmt, ...) LIKEPRINTF(3)
{
va_list args;
va_start (args, fmt);
_vsnprintf (dest, size-1, fmt, args);
va_end (args);
//make sure its terminated.
dest[size-1] = 0;
}
#else
#define QC_vsnprintf vsnprintf
#define QC_snprintfz snprintf
#endif
double I_FloatTime (void);

View file

@ -54,7 +54,7 @@ unsigned int Hash_Key(const char *name, unsigned int modulus)
return (key%modulus);
}
static unsigned int Hash_KeyInsensitive(const char *name, unsigned int modulus)
unsigned int Hash_KeyInsensitive(const char *name, unsigned int modulus)
{ //fixme: optimize.
unsigned int key;
for (key=0;*name; name++)

View file

@ -1,8 +1,13 @@
#include "qcc.h"
#if !defined(MINIMAL) && !defined(OMIT_QCC)
#include <time.h>
#ifndef _WIN32
#ifdef _WIN32
#include <sys/types.h>
#include <sys/stat.h>
#else
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#endif
void QCC_Canonicalize(char *fullname, size_t fullnamesize, const char *newfile, const char *base);
@ -79,6 +84,7 @@ struct pkgctx_s
struct oldpack_s *next;
char filename[128];
size_t numfiles;
unsigned int part;
struct
{
char name[128];
@ -194,7 +200,7 @@ static struct class_s *PKG_FindClass(struct pkgctx_s *ctx, char *code)
}
return NULL;
}
static struct dataset_s *PKG_FindDataset(struct pkgctx_s *ctx, char *code)
static struct dataset_s *PKG_FindDataset(struct pkgctx_s *ctx, const char *code)
{
struct dataset_s *o;
for (o = ctx->datasets; o; o = o->next)
@ -204,7 +210,7 @@ static struct dataset_s *PKG_FindDataset(struct pkgctx_s *ctx, char *code)
}
return NULL;
}
static struct dataset_s *PKG_GetDataset(struct pkgctx_s *ctx, char *code)
static struct dataset_s *PKG_GetDataset(struct pkgctx_s *ctx, const char *code)
{
struct dataset_s *s = PKG_FindDataset(ctx, code);
if (!s)
@ -373,6 +379,37 @@ static void PKG_CreateOutput(struct pkgctx_s *ctx, struct dataset_s *s, const ch
QCC_Canonicalize(o->filename, sizeof(o->filename), path, ctx->gamepath);
o->next = s->outputs;
s->outputs = o;
if (diff)
{
char *end = path + strlen(path)-2;
unsigned int i;
for (i = 0; i <= 99; i++)
{
#ifdef _WIN32
struct _stat statbuf;
#else
struct stat statbuf;
#endif
sprintf(end, "%02u", i+1);
#ifdef _WIN32
//FIXME: use the utf16 version because microsoft suck and don't allow utf-8
if (_stat(path, &statbuf) == 0)
#else
if (stat(path, &statbuf) == 0)
#endif
{
struct oldpack_s *span = malloc(sizeof(*span));
strcpy(span->filename, path);
span->numfiles = 0;
span->file = NULL;
span->next = o->oldparts;
span->part = i;
o->oldparts = span;
}
}
}
}
static void PKG_ParseOutput(struct pkgctx_s *ctx, pbool diff)
@ -440,6 +477,7 @@ static void PKG_AddOldPack(struct pkgctx_s *ctx, const char *fname)
ctx->oldpacks = pack;
}
#endif
static void PKG_ParseOldPack(struct pkgctx_s *ctx)
{
char token[MAX_OSPATH];
@ -596,7 +634,6 @@ static void PKG_ParseRule(struct pkgctx_s *ctx)
r->next = ctx->rules;
ctx->rules = r;
}
#ifdef _WIN32
static void PKG_AddClassFile(struct pkgctx_s *ctx, struct class_s *c, const char *fname, time_t mtime)
{
struct file_s *f;
@ -618,7 +655,6 @@ static void PKG_AddClassFile(struct pkgctx_s *ctx, struct class_s *c, const char
f->next = c->files;
c->files = f;
}
#endif
static void PKG_AddClassFiles(struct pkgctx_s *ctx, struct class_s *c, const char *fname)
{
#ifdef _WIN32
@ -638,7 +674,45 @@ static void PKG_AddClassFiles(struct pkgctx_s *ctx, struct class_s *c, const cha
} while(FindNextFile(h, &fd));
}
#else
ctx->messagecallback(ctx->userctx, "no wildcard support, sorry\n");
DIR *dir;
struct dirent *ent;
char basepath[MAX_OSPATH], tmppath[MAX_OSPATH];
struct stat statbuf;
QCC_Canonicalize(basepath, sizeof(basepath), fname, ctx->sourcepath);
QC_strlcat(basepath, "/", sizeof(basepath));
dir = opendir(basepath);
if (!dir)
{
ctx->messagecallback(ctx->userctx, "unable to open dir %s\n", basepath);
return;
}
while ((ent = readdir(dir)))
{
if (*ent->d_name == '.')
continue;
QCC_Canonicalize(basepath, sizeof(basepath), ent->d_name, fname);
QCC_Canonicalize(tmppath, sizeof(tmppath), basepath, ctx->sourcepath);
if (stat(tmppath, &statbuf)!=0)
continue;
switch (statbuf.st_mode & S_IFMT)
{
default: //some weird file type. shouldn't be a symlink sadly.
// ctx->messagecallback(ctx->userctx, "found weird %s\n", basepath);
break;
case S_IFDIR:
QC_strlcat(basepath, "/", sizeof(basepath));
// ctx->messagecallback(ctx->userctx, "found dir %s\n", basepath);
PKG_AddClassFiles(ctx, c, basepath);
break;
case S_IFREG:
// ctx->messagecallback(ctx->userctx, "found file %s\n", basepath);
PKG_AddClassFile(ctx, c, basepath, statbuf.st_mtime);
break;
}
}
closedir(dir);
#endif
}
static void PKG_ParseClass(struct pkgctx_s *ctx, char *output)
@ -887,6 +961,7 @@ static void *PKG_OpenSourceFile(struct pkgctx_s *ctx, struct file_s *file, size_
QCC_Canonicalize(fullname, sizeof(fullname), file->name, ctx->sourcepath);
strcpy(file->write.name, file->name);
//WIN32 FIXME: use the utf16 version because microsoft suck and don't allow utf-8
f = fopen(fullname, "rb");
if (!f)
return NULL;
@ -1010,7 +1085,7 @@ static void *PKG_OpenSourceFile(struct pkgctx_s *ctx, struct file_s *file, size_
return data;
}
static void PKG_WritePackageData(struct pkgctx_s *ctx, struct output_s *out, unsigned int index, pbool directoryonly)
static pbool PKG_WritePackageData(struct pkgctx_s *ctx, struct output_s *out, unsigned int index, pbool directoryonly)
{
//helpers to deal with misaligned data. writes little-endian.
#define misbyte(ptr,ofs,data) ((unsigned char*)(ptr))[ofs] = (data)&0xff
@ -1044,12 +1119,27 @@ static void PKG_WritePackageData(struct pkgctx_s *ctx, struct output_s *out, uns
#else
#define compmethod 0/*Z_RAW*/
#endif
if (!compmethod && !directoryonly)
if (!compmethod && !directoryonly && !index)
pak = true; //might as well boost compat...
ext = strrchr(out->filename, '.');
if (ext && !QC_strcasecmp(ext, ".pak") && !index)
pak = true;
if (!directoryonly)
{
for (f = out->files; f ; f=f->write.nextwrite)
{
if (index != f->write.zdisk)
continue; //not in this disk...
break;
}
if (!f)
{
ctx->messagecallback(ctx->userctx, "\t\tNo files to write to %s\n", out->filename);
return false;
}
}
if (out->usediffs && !directoryonly)
{
char newname[MAX_OSPATH];
@ -1068,8 +1158,8 @@ static void PKG_WritePackageData(struct pkgctx_s *ctx, struct output_s *out, uns
outf = fopen(out->filename, "wb");
if (!outf)
{
ctx->messagecallback(ctx->userctx, "Unable to open %s\n", out->filename);
return;
ctx->messagecallback(ctx->userctx, "\t\tUnable to open %s\n", out->filename);
return false;
}
if (pak) //reserve space for the pak header
@ -1080,7 +1170,7 @@ static void PKG_WritePackageData(struct pkgctx_s *ctx, struct output_s *out, uns
for (f = out->files; f ; f=f->write.nextwrite)
{
char header[32+sizeof(f->write.name)];
size_t fnamelen = strlen(f->write.name);
size_t fnamelen;
size_t hofs;
unsigned short gpflags = GPF_UTF8;
@ -1090,8 +1180,9 @@ static void PKG_WritePackageData(struct pkgctx_s *ctx, struct output_s *out, uns
filedata = PKG_OpenSourceFile(ctx, f, &f->write.rawsize);
if (!filedata)
{
ctx->messagecallback(ctx->userctx, "Unable to open %s\n", f->name);
ctx->messagecallback(ctx->userctx, "\t\tUnable to open %s\n", f->name);
}
fnamelen = strlen(f->write.name);
f->write.zcrc = QC_encodecrc(f->write.rawsize, filedata);
misint (header, 0, 0x04034b50);
@ -1104,10 +1195,10 @@ static void PKG_WritePackageData(struct pkgctx_s *ctx, struct output_s *out, uns
misint (header, 18, f->write.rawsize);//compressed size
misint (header, 22, f->write.rawsize);//uncompressed size
misshort(header, 26, fnamelen);//filename length
misshort(header, 28, 0);//extradata length
strcpy(header+30, f->write.name);
misshort(header, 28, 0);//extradata length (filled in later)
memcpy(header+30, f->write.name, fnamelen);
hofs = 30+fnamelen;
//Write extra data here...
misshort(header, 28, hofs-(30+fnamelen));//extradata length
f->write.zhdrofs = ftell(outf);
fwrite(header, 1, hofs, outf);
@ -1170,8 +1261,8 @@ static void PKG_WritePackageData(struct pkgctx_s *ctx, struct output_s *out, uns
struct
{
char name[56];
unsigned int size;
unsigned int offset;
unsigned int size;
} pakentry;
pakheader.tabofs = ftell(outf);
@ -1216,7 +1307,7 @@ static void PKG_WritePackageData(struct pkgctx_s *ctx, struct output_s *out, uns
misint (centralheader, 20, f->write.zipsize);//compressed size
misint (centralheader, 24, f->write.rawsize);//uncompressed size
misshort(centralheader, 28, fnamelen);//filename length
misshort(centralheader, 30, 0);//extradata length
misshort(centralheader, 30, 0);//extradata length (filled in later)
misshort(centralheader, 32, 0);//comment length
misshort(centralheader, 34, f->write.zdisk);//first disk number
misshort(centralheader, 36, 0);//internal file attribs
@ -1292,6 +1383,8 @@ static void PKG_WritePackageData(struct pkgctx_s *ctx, struct output_s *out, uns
fwrite(centralheader, 1, 22, outf);
fclose(outf);
return true;
}
/*
@ -1337,7 +1430,7 @@ static void PKG_ReadPackContents(struct pkgctx_s *ctx, struct oldpack_s *old)
if (header[0] == 'P' && header[1] == 'K' && header[2] == 5 && header[3] == 6)
{
//thisdisk = shortfromptr(header+4);
old->part = shortfromptr(header+4);
//centraldirstart = shortfromptr(header+6);
old->numfiles = shortfromptr(header+8);
//numfiles_all = shortfromptr(header+10);
@ -1360,7 +1453,7 @@ static void PKG_ReadPackContents(struct pkgctx_s *ctx, struct oldpack_s *old)
//gflags = shortfromptr(header+8);
old->file[u].zmethod = shortfromptr(header+10);
old->file[u].dostime = shortfromptr(header+12);
old->file[u].dosdate = shortfromptr(header+12);
old->file[u].dosdate = shortfromptr(header+14);
old->file[u].zcrc = longfromptr(header+16);
old->file[u].zipsize = longfromptr(header+20);
old->file[u].rawsize = longfromptr(header+24);
@ -1462,8 +1555,13 @@ static void PKG_WriteDataset(struct pkgctx_s *ctx, struct dataset_s *set)
for (out = set->outputs; out; out = out->next)
{
if(out->usediffs)
{ //FIXME: look for old parts
{
for (old = out->oldparts; old; old = old->next)
{
PKG_ReadPackContents(ctx, old);
if (out->numparts <= old->part)
out->numparts = old->part + 1;
}
}
}
}
@ -1514,7 +1612,10 @@ static void PKG_WriteDataset(struct pkgctx_s *ctx, struct dataset_s *set)
for (old = out->oldparts; old; old = old->next)
{
if (!PKG_FileIsModified(ctx, old, file))
{
file->write.zdisk = old->part;
break;
}
}
file->write.nextwrite = out->files;
@ -1545,11 +1646,12 @@ static void PKG_WriteDataset(struct pkgctx_s *ctx, struct dataset_s *set)
else
{
ctx->messagecallback(ctx->userctx, "\tGenerating %s[%s] \"%s\"\n", out->code, set->name, out->filename);
PKG_WritePackageData(ctx, out, out->numparts, false);
if (PKG_WritePackageData(ctx, out, out->numparts, false))
{
if(out->usediffs)
PKG_WritePackageData(ctx, out, out->numparts+1, true);
}
}
if(out->usediffs)
PKG_WritePackageData(ctx, out, out->numparts+1, true);
}
}
void Packager_WriteDataset(struct pkgctx_s *ctx, char *setname)
@ -1647,5 +1749,46 @@ void Packager_ParseFile(struct pkgctx_s *ctx, char *scriptname)
void Packager_Destroy(struct pkgctx_s *ctx)
{
free(ctx);
}
pbool Packager_CompressDir(const char *dirname, enum pkgtype_e type, void (*messagecallback)(void *userctx, const char *message, ...), void *userctx)
{
char *ext;
char filename[MAX_QPATH];
struct pkgctx_s *ctx = Packager_Create(messagecallback, userctx);
struct dataset_s *s;
struct class_s *c;
QC_strlcpy(ctx->sourcepath, dirname, sizeof(ctx->sourcepath));
ext = strrchr(ctx->sourcepath, '/');
if (*ctx->sourcepath && (!ext || ext[1]))
QC_strlcat(ctx->sourcepath, "/", sizeof(ctx->sourcepath));
QC_strlcpy(filename, dirname, sizeof(filename));
for (;(ext = strrchr(filename, '/')) && !ext[1]; *ext = 0)
;
ext = strrchr(filename, '.');
if (ext)
*ext = 0;
if (type == PACKAGER_PAK)
QC_strlcat(filename, ".pak", sizeof(filename));
else
QC_strlcat(filename, ".pk3", sizeof(filename));
s = PKG_GetDataset(ctx, "default");
PKG_CreateOutput(ctx, s, "default", filename, type == PACKAGER_PK3_SPANNED);
c = malloc(sizeof(*c));
memset(c, 0, sizeof(*c));
strcpy(c->name, "file");
strcpy(c->outname, "default");
c->next = ctx->classes;
ctx->classes = c;
PKG_AddClassFiles(ctx, c, "");
Packager_WriteDataset(ctx, NULL);
Packager_Destroy(ctx);
return true;
}
#endif

View file

@ -498,7 +498,7 @@ PR_EnterFunction
Returns the new program statement counter
====================
*/
int ASMCALL PR_EnterFunction (progfuncs_t *progfuncs, mfunction_t *f, int progsnum)
static int ASMCALL PR_EnterFunction (progfuncs_t *progfuncs, mfunction_t *f, int progsnum)
{
int i, j, c, o;
prstack_t *st;
@ -562,7 +562,7 @@ int ASMCALL PR_EnterFunction (progfuncs_t *progfuncs, mfunction_t *f, int progsn
PR_LeaveFunction
====================
*/
int ASMCALL PR_LeaveFunction (progfuncs_t *progfuncs)
static int ASMCALL PR_LeaveFunction (progfuncs_t *progfuncs)
{
int i, c;
prstack_t *st;

View file

@ -8,8 +8,13 @@
#define VARGS __cdecl
#endif
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
#ifdef _WIN32
#define LIKEPRINTF(x) __attribute__((format(ms_printf,x,x+1)))
#if defined(_WIN32)
#include <stdio.h>
#ifdef __MINGW_PRINTF_FORMAT
#define LIKEPRINTF(x) __attribute__((format(__MINGW_PRINTF_FORMAT,x,x+1)))
#else
#define LIKEPRINTF(x) __attribute__((format(ms_printf,x,x+1)))
#endif
#else
#define LIKEPRINTF(x) __attribute__((format(printf,x,x+1)))
#endif

View file

@ -1189,10 +1189,16 @@ int WriteSourceFiles(qcc_cachedsourcefile_t *filelist, int h, pbool sourceaswell
struct pkgctx_s;
enum pkgtype_e
{
PACKAGER_PAK,
PACKAGER_PK3,
PACKAGER_PK3_SPANNED,
};
pbool Packager_CompressDir(const char *dirname, enum pkgtype_e type, void (*messagecallback)(void *userctx, const char *message, ...), void *userctx);
struct pkgctx_s *Packager_Create(void (*messagecallback)(void *userctx, const char *message, ...), void *userctx);
void Packager_ParseFile(struct pkgctx_s *ctx, char *scriptfilename);
void Packager_ParseText(struct pkgctx_s *ctx, char *scripttext);
void Packager_WriteDataset(struct pkgctx_s *ctx, char *setname);
void Packager_Destroy(struct pkgctx_s *ctx);

View file

@ -6914,7 +6914,7 @@ QCC_sref_t QCC_PR_GenerateFunctionCallRef (QCC_sref_t newself, QCC_sref_t func,
if (QCC_OPCodeValid(&pr_opcodes[OP_LOADA_V]))
{
copyop[2] = OP_LOADA_V;
// copyop[1] = OP_LOADA_L;
// copyop[1] = OP_LOADA_I64;
copyop[0] = OP_LOADA_F;
copyop_idx = -1;
copyop_index = arglist[i]->index;
@ -8551,6 +8551,7 @@ void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, QCC_type_t *basetype)
static QCC_sref_t QCC_PR_ExpandField(QCC_sref_t ent, QCC_sref_t field, QCC_type_t *fieldtype, unsigned int preserveflags)
{
QCC_type_t *basicfieldtype;
QCC_sref_t r;
if (!fieldtype)
{
@ -8563,20 +8564,26 @@ static QCC_sref_t QCC_PR_ExpandField(QCC_sref_t ent, QCC_sref_t field, QCC_type_
fieldtype = type_variant;
}
}
basicfieldtype = fieldtype;
while(basicfieldtype->type == ev_accessor || basicfieldtype->type == ev_boolean || basicfieldtype->type == ev_enum)
basicfieldtype = (basicfieldtype->type == ev_enum)?basicfieldtype->aux_type:basicfieldtype->parentclass;
//FIXME: class.staticmember should directly read staticmember instead of trying to dereference
switch(fieldtype->type)
switch(basicfieldtype->type)
{
case ev_struct:
case ev_union:
case ev_enum:
{
int i;
int i = 0;
QCC_type_t *type = fieldtype;
QCC_sref_t dest = QCC_GetTemp(type);
QCC_sref_t source = field;
//don't bother trying to optimise any temps here, its not likely to happen anyway.
for (i = 0; i+2 < type->size; i+=3, dest.ofs += 3, source.ofs += 3)
for (; i+2 < type->size; i+=3, dest.ofs += 3, source.ofs += 3)
QCC_PR_SimpleStatement(&pr_opcodes[OP_LOAD_V], ent, source, dest, false);
if (QCC_OPCodeValid(&pr_opcodes[OP_LOAD_I64]))
for (; i+1 < type->size; i+=2, dest.ofs += 2, source.ofs += 2)
QCC_PR_SimpleStatement(&pr_opcodes[OP_LOAD_I64], ent, source, dest, false);
for (; i < type->size; i++, dest.ofs++, source.ofs++)
QCC_PR_SimpleStatement(&pr_opcodes[OP_LOAD_F], ent, source, dest, false);
source.ofs -= type->size;
@ -8586,15 +8593,20 @@ static QCC_sref_t QCC_PR_ExpandField(QCC_sref_t ent, QCC_sref_t field, QCC_type_
if (!(preserveflags & STFL_PRESERVEB))
QCC_FreeTemp(field);
QCC_PR_ParseWarning(WARN_UNDESIRABLECONVENTION, "QCC_PR_ExpandField: inefficient");
if (type->size > 3)
QCC_PR_ParseWarning(WARN_UNDESIRABLECONVENTION, "inefficient - copying %u words to a temp", type->size);
return dest;
}
break;
case ev_void:
case ev_accessor:
case ev_boolean:
case ev_enum:
default:
QCC_PR_ParseErrorPrintSRef(ERR_INTERNAL, field, "QCC_PR_ExpandField: invalid field type");
{
char temp[256];
QCC_PR_ParseErrorPrintSRef(ERR_INTERNAL, field, "QCC_PR_ExpandField: invalid field type %s%s%s", col_type,TypeName(fieldtype, temp, sizeof(temp)),col_none);
}
r = field;
break;
case ev_integer:

View file

@ -4926,6 +4926,7 @@ QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype)
t = QCC_PR_FieldType(t);
t = QCC_PR_FieldType(t);
paramlist[numparms].type = t;
foundinout = false;
}
}
else

View file

@ -51,6 +51,9 @@ extern int sourcefilesnumdefs;
};
static char *cmdlineargs;
static progfuncs_t guiprogfuncs;
static progexterns_t guiprogexterns;
#undef NULL
#define NULL nullptr
@ -541,6 +544,7 @@ private:
time_t filemodifiedtime;
bool modified;
int cursorline;
int cursorindex;
enum endings_e endings; //line endings for this file.
int savefmt; //encoding to save as
QsciDocument doc;
@ -564,6 +568,10 @@ private:
return;
dl.curdoc = oldval;
dl.s->setDocument(dl.curdoc->doc);
//annoying, but it completely loses your position otherwise.
dl.s->setCursorPosition(dl.curdoc->cursorline-1, dl.curdoc->cursorindex);
dl.s->ensureCursorVisible();
}
};
@ -615,6 +623,7 @@ public:
if (curdoc)
{
curdoc->cursorline = line+1;
curdoc->cursorindex = index;
UpdateTitle();
}
});
@ -1381,6 +1390,7 @@ public:
//UpdateEditorTitle(d);
}
UpdateTitle();
return true;
}
@ -2079,27 +2089,25 @@ void RunCompiler(const char *args, pbool quick)
static FILE *logfile;
const char *argv[128];
int argc;
progexterns_t ext;
progfuncs_t funcs;
mainwnd->docs.saveAll();
memset(&funcs, 0, sizeof(funcs));
funcs.funcs.parms = &ext;
memset(&ext, 0, sizeof(ext));
ext.ReadFile = GUIReadFile;
ext.FileSize = GUIFileSize;
ext.WriteFile = QCC_WriteFile;
ext.Sys_Error = Sys_Error;
memset(&guiprogfuncs, 0, sizeof(guiprogfuncs));
guiprogfuncs.funcs.parms = &guiprogexterns;
memset(&guiprogexterns, 0, sizeof(guiprogexterns));
guiprogexterns.ReadFile = GUIReadFile;
guiprogexterns.FileSize = GUIFileSize;
guiprogexterns.WriteFile = QCC_WriteFile;
guiprogexterns.Sys_Error = Sys_Error;
if (quick)
ext.Printf = Dummyprintf;
guiprogexterns.Printf = Dummyprintf;
else
{
ext.Printf = GUIprintf;
guiprogexterns.Printf = GUIprintf;
GUIprintf("");
}
ext.DPrintf = ext.Printf;
guiprogexterns.DPrintf = guiprogexterns.Printf;
if (logfile)
fclose(logfile);
@ -2110,7 +2118,7 @@ void RunCompiler(const char *args, pbool quick)
argc = GUI_BuildParms(args, argv, quick);
if (CompileParams(&funcs, NULL, argc, argv))
if (CompileParams(&guiprogfuncs, NULL, argc, argv))
{
if (!quick)
{
@ -2151,18 +2159,16 @@ void GUI_DoDecompile(void *buf, size_t size)
{
int h = SafeOpenWrite(fname.toUtf8().data(), -1);
progfuncs_t funcs;
progexterns_t ext;
memset(&funcs, 0, sizeof(funcs));
funcs.funcs.parms = &ext;
memset(&ext, 0, sizeof(ext));
ext.ReadFile = GUIReadFile;
ext.FileSize = GUIFileSize;
ext.WriteFile = QCC_WriteFile;
ext.Sys_Error = Sys_Error;
ext.Printf = GUIprintf;
memset(&guiprogfuncs, 0, sizeof(guiprogfuncs));
guiprogfuncs.funcs.parms = &guiprogexterns;
memset(&guiprogexterns, 0, sizeof(guiprogexterns));
guiprogexterns.ReadFile = GUIReadFile;
guiprogexterns.FileSize = GUIFileSize;
guiprogexterns.WriteFile = QCC_WriteFile;
guiprogexterns.Sys_Error = Sys_Error;
guiprogexterns.Printf = GUIprintf;
qccprogfuncs = &funcs;
qccprogfuncs = &guiprogfuncs;
WriteSourceFiles(qcc_vfiles, h, true, false);
qccprogfuncs = NULL;

View file

@ -380,7 +380,7 @@ static char *GUI_ParseInPlace(char **state)
{
if (*end == '\"')
{
end++;
*end++ = 0;
break;
}
else if (*end == '\'' && end[1] == '\\')

View file

@ -406,7 +406,7 @@ compiler_flag_t compiler_flag[] = {
{&pr_subscopedlocals, FLAG_MIDCOMPILE,"subscope", "Subscoped Locals", "Restrict the scope of locals to the block they are actually defined within, as in C."},
{&verbose, FLAG_MIDCOMPILE,"verbose", "Verbose", "Lots of extra compiler messages."},
{&flag_typeexplicit, FLAG_MIDCOMPILE,"typeexplicit", "Explicit types", "All type conversions must be explicit or directly supported by instruction set."},
{&flag_boundchecks, defaultflag, "boundchecks", "Disable Bound Checks", "Disable array index checks, speeding up array access but can result in your code misbehaving."},
{&flag_boundchecks, defaultflag, "boundchecks", "Enforce Bound Checks", "Enforce array index checks to avoid accessing arrays out of bounds. This can be disabled for a speedup (the qcvm will still verify that the access is within the qcvm's memory, but it can't verify that its within the intended array)."},
{&flag_attributes, hideflag, "attributes", "[[attributes]]", "WARNING: This syntax conflicts with vector constructors."},
{&flag_assumevar, hideflag, "assumevar", "explicit consts", "Initialised globals will be considered non-const by default."},
{&flag_dblstarexp, hideflag, "ssp", "** exponent", "Treat ** as an operator for exponents, instead of multiplying by a dereferenced pointer."},
@ -4114,7 +4114,7 @@ static void QCC_CopyFiles (void)
return;
}
for ( p = 0; p < 5; p++)
for ( p = 0; p < countof(QCC_Packname); p++)
{
s = QCC_Packname[p];
if (!*s)

View file

@ -115,6 +115,89 @@ static int logprintf(const char *format, ...)
return 0;
}
static size_t totalsize, filecount;
static void QCC_FileList(const char *name, const void *compdata, size_t compsize, int method, size_t plainsize)
{
totalsize += plainsize;
filecount += 1;
if (!method && compsize==plainsize)
externs->Printf("%8u %s\n", (unsigned)plainsize, name);
else
externs->Printf("%8u %3u%% %s\n", (unsigned)plainsize, plainsize?(unsigned)((100*compsize)/plainsize):100u, name);
}
#include <limits.h>
#ifdef __unix__
#include <sys/stat.h>
void QCC_Mkdir(const char *path)
{
char buf[MAX_OSPATH], *sl;
if (!strchr(path, '/'))
return; //no need to create anything
memcpy(buf, path, MAX_OSPATH);
while((sl=strrchr(buf, '/')))
{
*sl = 0;
mkdir(buf, 0777);
}
}
#else
void QCC_Mkdir(const char *path)
{
//unsupported.
}
#endif
static const char *extractonly;
static pbool extractonlyfound;
static void QCC_FileExtract(const char *name, const void *compdata, size_t compsize, int method, size_t plainsize)
{
if (extractonly)
{
const char *sl = strrchr(extractonly, '/');
if (sl && !sl[1])
{ //trailing / - extract the entire dir.
if (!strcmp(name, extractonly))
return; //ignore the dir itself...
if (strncmp(name, extractonly, strlen(extractonly)))
return;
}
else
if (strcmp(name, extractonly))
return; //ignore it if its not the one we're going for.
}
extractonlyfound = true;
externs->Printf("Extracting %s...", name);
if (plainsize <= INT_MAX)
{
void *buffer = malloc(plainsize);
if (buffer && QC_decode(progfuncs, compsize, plainsize, method, compdata, buffer))
{
QCC_Mkdir(name);
if (!QCC_WriteFile(name, buffer, plainsize))
externs->Printf(" write failure\n");
else
externs->Printf(" done\n");
}
else
externs->Printf(" read failure\n");
free(buffer);
}
else
externs->Printf(" too large\n");
}
static void QCC_PR_PackagerMessage(void *userctx, const char *message, ...)
{
va_list argptr;
char string[1024];
va_start (argptr,message);
QC_vsnprintf (string,sizeof(string)-1,message,argptr);
va_end (argptr);
externs->Printf ("%s", string);
}
int main (int argc, const char **argv)
{
unsigned int i;
@ -137,6 +220,52 @@ int main (int argc, const char **argv)
funcs.funcs.parms->Printf = logprintf;
funcs.funcs.parms->Sys_Error = Sys_Error;
if ((argc == 3 && !strcmp(argv[1], "-l")) || (argc >= 3 && !strcmp(argv[1], "-x")))
{
size_t blobsize;
void *blob = QCC_ReadFile(argv[2], NULL, NULL, &blobsize, false);
if (!blob)
{
logprintf("Unable to read %s\n", argv[2]);
return EXIT_FAILURE;
}
if (argc > 3)
{
for (i = 3; i < argc; i++)
{
extractonly = argv[i];
extractonlyfound = false;
QC_EnumerateFilesFromBlob(blob, blobsize, QCC_FileExtract);
if (!extractonlyfound)
externs->Printf("Unable to find file %s\n", extractonly);
}
extractonly = NULL;
}
else if (argv[1][1] == 'x')
QC_EnumerateFilesFromBlob(blob, blobsize, QCC_FileExtract);
else
{
QC_EnumerateFilesFromBlob(blob, blobsize, QCC_FileList);
externs->Printf("Total size %u bytes, %u files\n", (unsigned)totalsize, (unsigned)filecount);
}
free(blob);
return EXIT_SUCCESS;
}
if (argc == 3 && (!strncmp(argv[1], "-z", 2) || !strcmp(argv[1], "-0") || !strcmp(argv[1], "-9")))
{ //exe -0 foo.pk3dir
enum pkgtype_e t;
if (argv[1][1] == '9')
t = PACKAGER_PK3;
else if (argv[1][1] == '0')
t = PACKAGER_PAK; //not really any difference but oh well
else
t = PACKAGER_PK3_SPANNED;
if (Packager_CompressDir(argv[2], t, QCC_PR_PackagerMessage, NULL))
return EXIT_SUCCESS;
else
return EXIT_FAILURE;
}
for (i = 0; i < argc; i++)
{
if (!argv[i])

View file

@ -257,13 +257,14 @@ int QC_EnumerateFilesFromBlob(const void *blob, size_t blobsize, void (*cb)(cons
continue;
if (nl != QC_ReadRawShort(le+26))
continue; //name is weird...
if (el != QC_ReadRawShort(le+28))
continue; //name is weird...
// if (el != QC_ReadRawShort(le+28))
// continue; //extradata is weird...
csize = QC_ReadRawInt(le+18);
usize = QC_ReadRawInt(le+22);
if (!QC_strlcpy(name, cd+46, (nl+1<sizeof(name))?nl+1:sizeof(name)))
continue; //name was too long.
if (nl >= sizeof(name))
continue; //name is too long
QC_strlcpy(name, cd+46, (nl+1<sizeof(name))?nl+1:sizeof(name));
cb(name, le+30+QC_ReadRawShort(le+26)+QC_ReadRawShort(le+28), csize, method, usize);
ret++;

View file

@ -11409,7 +11409,7 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"bufstr_add", PF_Fixme, 0, 0, 0, 448, "float(strbuf bufhandle, string str, float ordered)"},//DP_QC_STRINGBUFFERS
{"bufstr_free", PF_Fixme, 0, 0, 0, 449, "void(strbuf bufhandle, float string_index)"},//DP_QC_STRINGBUFFERS
{"iscachedpic", PF_Fixme, 0, 0, 0, 451, "float(string name)"},// (EXT_CSQC)
{"precache_pic", PF_Fixme, 0, 0, 0, 452, "string(string name, optional float trywad)"},// (EXT_CSQC)
{"precache_pic", PF_Fixme, 0, 0, 0, 452, "string(string name, optional float flags)"},// (EXT_CSQC)
{"freepic", PF_Fixme, 0, 0, 0, 453, "void(string name)"},// (EXT_CSQC)
{"drawcharacter", PF_Fixme, 0, 0, 0, 454, "float(vector position, float character, vector scale, vector rgb, float alpha, optional float flag)"},// (EXT_CSQC, [EXT_CSQC_???])
{"drawrawstring", PF_Fixme, 0, 0, 0, 455, "float(vector position, string text, vector scale, vector rgb, float alpha, optional float flag)"},// (EXT_CSQC, [EXT_CSQC_???])
@ -13144,6 +13144,8 @@ void PR_DumpPlatform_f(void)
#endif
{"PRECACHE_PIC_FROMWAD","const float", CS|MENU, D("Attempt to load it from the legacy gfx.wad file (usually its better to just use a gfx/ prefix instead)."), 1},
{"PRECACHE_PIC_NOCLAMP","const float", CS|MENU, D("Texture coords for the pic will not be clamped nor padded nor atlased."), 4},
// {"PRECACHE_PIC_MIPMAP", "const float", CS|MENU, D("Force the image to be mipmapped. This might result in it being blurry, but will not be noisy."), 8},
{"PRECACHE_PIC_DOWNLOAD","const float", CS|MENU, D("If no image could be loaded then attempt to download one from the server. This flag can cause the function to block until completion. (Slow!)"), 256},
{"PRECACHE_PIC_TEST", "const float", CS|MENU, D("The precache will block until the image is fully loaded, returning a null string on failure. (Slow!)"), 512},

View file

@ -16,6 +16,26 @@ extern cvar_t pr_ssqc_memsize;
void SV_Savegame_f (void);
typedef struct
{
char name[32];
union
{
int i;
float f;
} parm[NUM_SPAWN_PARMS];
char *parmstr;
client_t *source;
} loadplayer_t;
struct loadinfo_s
{
size_t numplayers;
loadplayer_t *players;
};
//Writes a SAVEGAME_COMMENT_LENGTH character comment describing the current
void SV_SavegameComment (char *text, size_t textsize)
{
@ -80,7 +100,8 @@ void SV_SavegameComment (char *text, size_t textsize)
pbool PDECL SV_ExtendedSaveData(pubprogfuncs_t *progfuncs, void *loadctx, const char **ptr)
{
char token[8192];
struct loadinfo_s *loadinfo = loadctx;
char token[65536];
com_tokentype_t tt;
const char *l = *ptr;
size_t idx;
@ -155,28 +176,35 @@ pbool PDECL SV_ExtendedSaveData(pubprogfuncs_t *progfuncs, void *loadctx, const
l = COM_ParseTokenOut(l, NULL, token, sizeof(token), &tt);if (tt != TTP_STRING)return false;
sv.strings.particle_precache[idx] = PR_AddString(svprogfuncs, token, 0, false);
}
else if (!strcmp(token, "serverflags"))
{ //serverflags N (for map_restart to work properly)
l = COM_ParseTokenOut(l, NULL, token, sizeof(token), &tt);if (tt != TTP_RAWTOKEN)return false;
idx = atoi(token);
svs.serverflags = idx;
}
else if (!strcmp(token, "startspot"))
{ //startspot "foo" (for map_restart to work properly)
l = COM_ParseTokenOut(l, NULL, token, sizeof(token), &tt);if (tt != TTP_RAWTOKEN)return false;
InfoBuf_SetStarKey(&svs.info, "*startspot", token);
}
else if (loadinfo && !strcmp(token, "spawnparm"))
{ //spawnparm idx val (for map_restart to work properly)
l = COM_ParseTokenOut(l, NULL, token, sizeof(token), &tt);if (tt != TTP_RAWTOKEN)return false;
idx = atoi(token);
if (idx == 0)
{ //the parmstr...
l = COM_ParseTokenOut(l, NULL, token, sizeof(token), &tt);if (tt != TTP_STRING)return false;
loadinfo->players[0].parmstr = Z_StrDup(token);
}
else if (idx >= 1 && idx <= countof(loadinfo->players->parm))
{ //regular parm
l = COM_ParseTokenOut(l, NULL, token, sizeof(token), &tt);if (tt != TTP_RAWTOKEN)return false;
loadinfo->players[0].parm[idx-1].f = atof(token);
}
}
//strbuffer+hashtable+etc junk
else if (PR_Common_LoadGame(svprogfuncs, token, &l))
;
/*
else if (!strcmp(token, "buffer"))
{
l = COM_ParseTokenOut(l, NULL, token, sizeof(token), &tt);if (tt != TTP_RAWTOKEN)return false;
//buffer = atoi(token);
l = COM_ParseTokenOut(l, NULL, token, sizeof(token), &tt);if (tt != TTP_RAWTOKEN)return false;
//flags = atoi(token);
l = COM_ParseTokenOut(l, NULL, token, sizeof(token), &tt);if (tt != TTP_STRING)return false;
//"string" == token
return false;
}
else if (!strcmp(token, "bufstr"))
{
l = COM_ParseTokenOut(l, NULL, token, sizeof(token), &tt);if (tt != TTP_RAWTOKEN)return false;
//buffer = atoi(token);
l = COM_ParseTokenOut(l, NULL, token, sizeof(token), &tt);if (tt != TTP_RAWTOKEN)return false;
//idx = atoi(token);
l = COM_ParseTokenOut(l, NULL, token, sizeof(token), &tt);if (tt != TTP_STRING)return false;
return false;
}*/
else
return false;
*ptr = l;
@ -312,8 +340,25 @@ static qboolean SV_LegacySavegame (const char *savename, qboolean verbose)
for (i=1 ; i < countof(sv.strings.sound_precache); i++)
{
if (sv.strings.sound_precache[i])
VFS_PRINTF(f, "sv.lightstyles %i %s\n", i, sv.strings.sound_precache[i]);
VFS_PRINTF(f, "sv.sound_precache %i %s\n", i, sv.strings.sound_precache[i]);
}
for (i=1 ; i < countof(sv.strings.particle_precache); i++)
{
if (sv.strings.particle_precache[i])
VFS_PRINTF(f, "sv.particle_precache %i %s\n", i, sv.strings.particle_precache[i]);
}
VFS_PRINTF(f, "sv.serverflags %i\n", svs.serverflags); //zomg! a fix for losing runes on load;restart!
// VFS_PRINTF(f, "sv.startspot %s\n", InfoBuf_ValueForKey(&svs.info, "*startspot")); //startspot, for restarts.
if (svs.clients->spawn_parmstring)
{
size_t maxlen = strlen(svs.clients->spawn_parmstring)*2+4 + 1;
char *buffer = BZ_Malloc(maxlen);
VFS_PRINTF(f, "spawnparm 0 %s\n", COM_QuotedString(svs.clients->spawn_parmstring, buffer, sizeof(maxlen), false));
BZ_Free(buffer);
}
if (version == SAVEGAME_VERSION_NQ || version == SAVEGAME_VERSION_QW)
for (i=16 ; i < countof(svs.clients->spawn_parms); i++)
VFS_PRINTF(f, "spawnparm %i %g\n", i+1, svs.clients->spawn_parms[i]);
// sv.buffer %i %i "string"
// sv.bufstr %i %i "%s"
VFS_PUTS(f, "*/\n");
@ -1396,18 +1441,6 @@ void SV_AutoSave(void)
#endif
}
typedef struct
{
char name[32];
union
{
int i;
float f;
} parm[NUM_SPAWN_PARMS];
char *parmstr;
client_t *source;
} loadplayer_t;
static void SV_SwapPlayers(client_t *a, client_t *b)
{
size_t i;
@ -1671,6 +1704,10 @@ static qboolean SV_Loadgame_Legacy(const char *savename, const char *filename, v
char *modelnames[MAX_PRECACHE_MODELS];
char *soundnames[MAX_PRECACHE_SOUNDS];
loadplayer_t lp[255];
struct loadinfo_s loadinfo;
loadinfo.numplayers = countof(lp);
loadinfo.players = lp;
if (version != SAVEGAME_VERSION_FTE_LEG && version != SAVEGAME_VERSION_NQ && version != SAVEGAME_VERSION_QW)
{
@ -1867,7 +1904,7 @@ static qboolean SV_Loadgame_Legacy(const char *savename, const char *filename, v
strcpy(file, "loadgame");
clnum=VFS_READ(f, file+8, filelen);
file[filelen+8]='\0';
sv.world.edict_size=svprogfuncs->load_ents(svprogfuncs, file, NULL, NULL, SV_ExtendedSaveData);
sv.world.edict_size=svprogfuncs->load_ents(svprogfuncs, file, &loadinfo, NULL, SV_ExtendedSaveData);
BZ_Free(file);
PR_LoadGlabalStruct(false);

View file

@ -505,7 +505,7 @@ typedef struct client_s
usercmd_t lastcmd; // for filling in big drops and partial predictions
double localtime; // of last message
qboolean jump_held;
qboolean lockangles; //mod is spamming angle changes, don't do relative changes
unsigned int lockanglesseq; //mod is spamming angle changes, don't do relative changes. outgoing sequence. v_angles isn't really known until netchan.incoming_acknowledged>=lockangles
float maxspeed; // localized maxspeed
float entgravity; // localized ent gravity

View file

@ -87,6 +87,12 @@ client_t *SV_GetClientForString(const char *name, int *id)
int first=0;
if (id && *id != -1)
first = *id;
if (first < 0)
{
if (id)
*id=sv.allocated_client_slots;
return NULL;
}
if (!strcmp(name, "*")) //match with all
{
@ -95,10 +101,12 @@ client_t *SV_GetClientForString(const char *name, int *id)
if (cl->state<=cs_loadzombie)
continue;
*id=i+1;
if (id)
*id=i+1;
return cl;
}
*id=sv.allocated_client_slots;
if (id)
*id=sv.allocated_client_slots;
return NULL;
}
@ -114,7 +122,7 @@ client_t *SV_GetClientForString(const char *name, int *id)
if (!*s)
{
int uid = Q_atoi(name);
for (i = first, cl = svs.clients; i < sv.allocated_client_slots; i++, cl++)
for (i = first, cl = svs.clients+first; i < sv.allocated_client_slots; i++, cl++)
{
if (cl->state<=cs_loadzombie)
continue;
@ -585,7 +593,7 @@ void SV_Map_f (void)
Con_DPrintf ("map_restart delay not implemented yet\n");
}
Q_strncpyz (level, ".", sizeof(level));
startspot = NULL;
startspot = NULL; //FIXME: startspot forgotten on restart
//FIXME: if precaches+statics don't change, don't do the whole networking thing.
}

View file

@ -3827,9 +3827,10 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, pvscamera_t
if (cameras && tracecullent && !((unsigned int)ent->v->effects & (EF_DIMLIGHT|EF_BLUE|EF_RED|EF_BRIGHTLIGHT|EF_BRIGHTFIELD|EF_NODEPTHTEST)))
{ //more expensive culling
if ((e <= sv.allocated_client_slots && sv_cullplayers_trace.value) || sv_cullentities_trace.value)
if (Cull_Traceline(e < client->lastseen_count?&client->lastseen_time[e]:NULL, cameras, tracecullent))
continue;
if (!(pvsflags & PVSF_MODE_MASK))
if ((e <= sv.allocated_client_slots && sv_cullplayers_trace.value) || sv_cullentities_trace.value)
if (Cull_Traceline(e < client->lastseen_count?&client->lastseen_time[e]:NULL, cameras, tracecullent))
continue;
}
//EXT_CSQC

View file

@ -187,7 +187,7 @@ cvar_t skill = CVARF("skill", "" , CVAR_SERVERINFO); // 0, 1, 2 or 3
cvar_t spawn = CVARF("spawn", "" , CVAR_SERVERINFO);
cvar_t watervis = CVARF("watervis", "" , CVAR_SERVERINFO);
#pragma warningmsg("Remove this some time")
cvar_t allow_skybox = CVARF("allow_skybox", "", CVAR_SERVERINFO);
cvar_t allow_skybox = CVARFD("allow_skybox", "", CVAR_SERVERINFO, "This setting says whether clients should skip writing skybox depth when rendering skyboxes/skydomes. Skipping depth writes is required for halflife, quake2, and quake3 compat, but q1 content generally requires depth masking. Empty uses format-specific defaults.");
cvar_t sv_allow_splitscreen = CVARFD("allow_splitscreen","",CVAR_SERVERINFO, "Specifies whether clients can use splitscreen extensions to dynamically add additional clients. This only affects remote clients and not the built-in client.\nClients may need to reconnect in order to add seats when this is changed.");
cvar_t fbskins = CVARF("fbskins", "", CVAR_SERVERINFO); //to get rid of lame fuhquake fbskins

View file

@ -349,32 +349,10 @@ static void WPhys_PortalTransform(world_t *w, wedict_t *ent, wedict_t *portal, v
if (ent->entnum > 0 && ent->entnum <= svs.allocated_client_slots)
{
client_t *cl = &svs.clients[ent->entnum-1];
int i;
vec3_t delta;
ent->v->angles[0] *= r_meshpitch.value;
if (!cl->lockangles && (cl->fteprotocolextensions2 & PEXT2_SETANGLEDELTA))
{
cl = ClientReliableWrite_BeginSplit(cl, svcfte_setangledelta, 7);
VectorSubtract(ent->v->angles, ent->v->v_angle, delta);
delta[2] = anglemod(delta[2]);
if (delta[2] > 90 && delta[2] < 270)
{
delta[2] -= 180;
delta[1] -= 180;
delta[0] -= -180;
}
for (i=0 ; i < 3 ; i++)
ClientReliableWrite_Angle16 (cl, delta[i]);
}
else
{
cl = ClientReliableWrite_BeginSplit (cl, svc_setangle, 7);
for (i=0 ; i < 3 ; i++)
ClientReliableWrite_Angle (cl, ent->v->angles[i]);
}
VectorCopy(ent->v->angles, ent->v->v_angle);
ent->v->angles[0] *= r_meshpitch.value;
SV_SendFixAngle(cl, NULL, FIXANGLE_AUTO, true);
}
#endif

View file

@ -1637,7 +1637,7 @@ void SV_SendFixAngle(client_t *client, sizebuf_t *msg, int fixtype, qboolean rol
if (fixtype == FIXANGLE_AUTO)
{
if (!client->lockangles && controller->delta_sequence != -1 && !client->viewent)
if (client->lockanglesseq<controller->netchan.incoming_acknowledged && controller->delta_sequence != -1 && !client->viewent)
fixtype = FIXANGLE_DELTA;
else
fixtype = FIXANGLE_FIXED;
@ -1645,7 +1645,7 @@ void SV_SendFixAngle(client_t *client, sizebuf_t *msg, int fixtype, qboolean rol
if (fixtype == FIXANGLE_DELTA && !(controller->fteprotocolextensions2 & PEXT2_SETANGLEDELTA))
fixtype = FIXANGLE_FIXED; //sorry, can't do it.
if (!client->lockangles && controller->netchan.message.cursize < controller->netchan.message.maxsize/2)
if (client->lockanglesseq>=controller->netchan.incoming_acknowledged && controller->netchan.message.cursize < controller->netchan.message.maxsize/2)
msg = NULL; //try to keep them vaugely reliable, where feasable.
if (!msg)
msg = ClientReliable_StartWrite(client, 10);
@ -1673,7 +1673,7 @@ void SV_SendFixAngle(client_t *client, sizebuf_t *msg, int fixtype, qboolean rol
for (i=0 ; i < 3 ; i++)
MSG_WriteAngle (msg, (i==2&&!roll)?0:ang[i]);
}
client->lockangles = true; //so that spammed fixangles use absolute values, locking the camera in place.
client->lockanglesseq = controller->netchan.outgoing_sequence+1; //so that spammed fixangles use absolute values, locking the camera in place.
}
void SV_WriteEntityDataToMessage (client_t *client, sizebuf_t *msg, int pnum)
@ -1723,8 +1723,6 @@ void SV_WriteEntityDataToMessage (client_t *client, sizebuf_t *msg, int pnum)
SV_SendFixAngle(client, msg, ent->v->fixangle, true);
ent->v->fixangle = FIXANGLE_NO;
}
else
client->lockangles = false;
}
/*sends the a centerprint string directly to the client*/

View file

@ -2432,6 +2432,8 @@ static void World_ClipToNetwork (world_t *w, moveclip_t *clip)
if (touch->modelindex <= 0 || touch->modelindex >= MAX_PRECACHE_MODELS)
continue; //erk
model = cl.model_precache[touch->modelindex];
if (!model)
continue;
VectorCopy(model->mins, bmins);
VectorCopy(model->maxs, bmaxs);
}

View file

@ -57,7 +57,7 @@
affine varying vec2 tc;
varying vec4 light;
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) || defined(PBR)
varying vec3 eyevector;
#endif
#if defined(PBR)||defined(REFLECTCUBEMASK)
@ -92,9 +92,7 @@ void main ()
#endif
#endif
#if defined(PBR)
eyevector = e_eyepos - w.xyz;
#elif defined(SPECULAR)||defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)
#if defined(SPECULAR)||defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) || defined(PBR)
vec3 eyeminusvertex = e_eyepos - w.xyz;
eyevector.x = dot(eyeminusvertex, s.xyz);
eyevector.y = dot(eyeminusvertex, t.xyz);
@ -139,7 +137,7 @@ affine in vec2 tc[];
affine out vec2 t_tc[];
in vec4 light[];
out vec4 t_light[];
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) || defined(PBR)
in vec3 eyevector[];
out vec3 t_eyevector[];
#endif
@ -155,7 +153,7 @@ void main()
t_normal[id] = normal[id];
t_tc[id] = tc[id];
t_light[id] = light[id];
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) || defined(PBR)
t_eyevector[id] = eyevector[id];
#endif
#ifdef REFLECTCUBEMASK
@ -188,7 +186,7 @@ affine in vec2 t_tc[];
affine out vec2 tc;
in vec4 t_light[];
out vec4 light;
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) || defined(PBR)
in vec3 t_eyevector[];
out vec3 eyevector;
#endif
@ -211,7 +209,7 @@ void main()
//FIXME: we should be recalcing these here, instead of just lerping them
light = LERP(t_light);
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) || defined(PBR)
eyevector = LERP(t_eyevector);
#endif
#ifdef REFLECTCUBEMASK
@ -251,7 +249,7 @@ uniform float cvar_gl_specular;
affine varying vec2 tc;
varying vec4 light;
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) || defined(PBR)
varying vec3 eyevector;
#endif
#if defined(PBR) || defined(REFLECTCUBEMASK)
@ -345,7 +343,8 @@ void main ()
#endif
#else
#define roughness 0.3
#define specrgb 1.0 //vec3(dielectricSpecular)
#define specrgb vec3(1.0) //vec3(dielectricSpecular)
#define ambientrgb col.rgb
#endif
#ifdef BUMP

View file

@ -36,7 +36,7 @@
#include "sys/fog.h"
#if !defined(TESS_CONTROL_SHADER)
#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK)
#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK) || defined(PBR)
varying vec3 eyevector;
#endif
@ -68,7 +68,7 @@ varying vec3 vertex, normal;
#endif
void main ()
{
#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK)
#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK) || defined(PBR)
vec3 eyeminusvertex = e_eyepos - v_position.xyz;
eyevector.x = dot(eyeminusvertex, v_svector.xyz);
eyevector.y = dot(eyeminusvertex, v_tvector.xyz);
@ -119,7 +119,7 @@ in vec3 vertex[];
out vec3 t_vertex[];
in vec3 normal[];
out vec3 t_normal[];
#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK)
#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK) || defined(PBR)
in vec3 eyevector[];
out vec3 t_eyevector[];
#endif
@ -161,7 +161,7 @@ void main()
#endif
#endif
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) || defined(PBR)
t_eyevector[id] = eyevector[id];
#endif
@ -185,7 +185,7 @@ layout(triangles) in;
in vec3 t_vertex[];
in vec3 t_normal[];
#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK)
#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK) || defined(PBR)
in vec3 t_eyevector[];
#endif
#ifdef REFLECTCUBEMASK
@ -235,7 +235,7 @@ void main()
#ifdef REFLECTCUBEMASK
invsurface = LERP(t_invsurface);
#endif
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) || defined(PBR)
eyevector = LERP(t_eyevector);
#endif
@ -331,37 +331,57 @@ void main ()
#endif
// col *= factor_base;
#define dielectricSpecular 0.04
#ifdef SPECULAR
vec4 specs = texture2D(s_specular, tc);//*factor_spec;
#ifdef ORM
#define occlusion specs.r
#define roughness specs.g
#define metalness specs.b
#define gloss (1.0-roughness)
#define ambientrgb (specrgb+col.rgb)
vec3 specrgb = mix(vec3(dielectricSpecular), col.rgb, metalness);
col.rgb = col.rgb * (1.0 - dielectricSpecular) * (1.0-metalness);
#elif defined(SG) //pbr-style specular+glossiness
//occlusion needs to be baked in. :(
#define roughness (1.0-specs.a)
#define gloss specs.a
#define specrgb specs.rgb
#define ambientrgb (specs.rgb+col.rgb)
#else //blinn-phong
#define roughness (1.0-specs.a)
#define gloss specs.a
#define specrgb specs.rgb
#define ambientrgb col.rgb
#endif
#else
#define roughness 0.3
#define specrgb 1.0 //vec3(dielectricSpecular)
#endif
#define dielectricSpecular 0.04
#ifdef SPECULAR
vec4 specs = texture2D(s_specular, tc);//*factor_spec;
#ifdef ORM
#define occlusion specs.r
#define roughness specs.g
#define metalness specs.b
#define gloss (1.0-roughness)
#define ambientrgb (specrgb+col.rgb)
vec3 specrgb = mix(vec3(dielectricSpecular), col.rgb, metalness);
vec3 albedorgb = col.rgb * (1.0 - dielectricSpecular) * (1.0-metalness);
#elif defined(SG) //pbr-style specular+glossiness
//occlusion needs to be baked in. :(
#define roughness (1.0-specs.a)
#define gloss specs.a
#define specrgb specs.rgb
#define ambientrgb (specs.rgb+col.rgb)
#define albedorgb col.rgb
#elif defined(PBR) //PBR using legacy texturemaps
#define gloss specs.a
#define roughness (1.0-gloss)
//metalness not relevant
//our pbr stuff doesn't much like our inputs.
vec3 specrgb, albedorgb;
//if (1==0)
//{ //metal
// specrgb = col.rgb;//+specs.rgb;
// albedorgb = vec3(0.0);
//}
//else
//{ //non-metal
specrgb = vec3(dielectricSpecular);
albedorgb = col.rgb;//+specs.rgb;
//}
#define ambientrgb col.rgb
#else //blinn-phong
#define gloss specs.a
//occlusion not defined
#define specrgb specs.rgb
#endif
#else
//no specular map specified. doesn't mean we shouldn't have any though, at least with pbr enabled.
#define roughness 0.3
#define specrgb 1.0 //vec3(dielectricSpecular)
#define albedorgb col.rgb
#endif
//add in specular, if applicable.
#ifdef PBR
col.rgb = DoPBR(norm, normalize(eyevector), deluxe, roughness, col.rgb, specrgb, vec3(0.0,1.0,1.0));//*e_light_mul + e_light_ambient*.25*ambientrgb;
col.rgb = DoPBR(norm, normalize(eyevector), deluxe, roughness, albedorgb, specrgb, vec3(0.0,1.0,1.0));//*e_light_mul + e_light_ambient*.25*ambientrgb;
#elif defined(gloss)
vec3 halfdir = normalize(normalize(eyevector) + deluxe); //this norm should be the deluxemap info instead
float spec = pow(max(dot(halfdir, norm), 0.0), FTE_SPECULAR_EXPONENT * gloss);

View file

@ -52,7 +52,7 @@
#if defined(VERTEXCOLOURS)
varying vec4 vc;
#endif
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) || defined(PBR)
varying vec3 eyevector;
#endif
#ifdef REFLECTCUBEMASK
@ -97,7 +97,7 @@ t = normalize(t);
#if defined(VERTEXCOLOURS)
vc = v_colour;
#endif
#if defined(SPECULAR)||defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)
#if defined(SPECULAR)||defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) || defined(PBR)
vec3 eyeminusvertex = e_eyepos - w.xyz;
eyevector.x = dot(eyeminusvertex, s.xyz);
eyevector.y = dot(eyeminusvertex, t.xyz);
@ -138,7 +138,7 @@ out vec3 t_lightvector[];
in vec4 vc[];
out vec4 t_vc[];
#endif
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) || defined(PBR)
in vec3 eyevector[];
out vec3 t_eyevector[];
#endif
@ -153,7 +153,7 @@ void main()
#if defined(VERTEXCOLOURS)
t_vc[id] = vc[id];
#endif
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) || defined(PBR)
t_eyevector[id] = eyevector[id];
#endif
@ -182,7 +182,7 @@ in vec3 t_lightvector[];
#if defined(VERTEXCOLOURS)
in vec4 t_vc[];
#endif
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) || defined(PBR)
in vec3 t_eyevector[];
#endif
@ -208,7 +208,7 @@ void main()
#if defined(VERTEXCOLOURS)
vc = LERP(t_vc);
#endif
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) || defined(PBR)
eyevector = LERP(t_eyevector);
#endif
@ -275,7 +275,7 @@ void main ()
vec4 lc = texture2D(s_lower, tcbase);
bases.rgb += lc.rgb*e_lowercolour*lc.a;
#endif
#if defined(BUMP) || defined(SPECULAR) || defined(REFLECTCUBEMASK)
#if defined(BUMP) || defined(SPECULAR) || defined(REFLECTCUBEMASK) || defined(PBR)
vec3 bumps = normalize(vec3(texture2D(s_normalmap, tcbase)) - 0.5);
#elif defined(REFLECTCUBEMASK)
vec3 bumps = vec3(0.0,0.0,1.0);
@ -308,7 +308,7 @@ void main ()
#endif
#else
#define roughness 0.3
#define specrgb 1.0 //vec3(dielectricSpecular)
#define specrgb bases.rgb //vec3(dielectricSpecular)
#endif
#ifdef PBR