From 906b705bf06b8ccecc6a15226127b33feaf0703a Mon Sep 17 00:00:00 2001 From: Spoike Date: Tue, 21 Apr 2015 04:12:00 +0000 Subject: [PATCH] after much breaking, the webgl port now utilises the browser's ogg/mp3 decoder, and the browser's png decompresser. pngs/jpegs do not provide size information. fixed non-browser ogg decoding and openal logic. should finally be fixed, I guess. wasted some time on an ezhud plugin, along with ensuring certain info is available to the plugin. this is still a work in progress however. non-web builds are now able to download images from urls. download progress does not display for uri_get/uri_post builtins, nor other non-saved things. q1qvm logic now uses pr_maxedicts cvar. the gamecode api still provides no way to tell how many are permissable, so set at own risk. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4852 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_demo.c | 4 +- engine/client/cl_input.c | 6 +- engine/client/cl_main.c | 8 +- engine/client/cl_parse.c | 73 +- engine/client/cl_plugin.inc | 172 +- engine/client/cl_screen.c | 6 +- engine/client/client.h | 2 + engine/client/console.c | 5 +- engine/client/image.c | 77 +- engine/client/in_win.c | 9 +- engine/client/keys.c | 4 +- engine/client/m_mp3.c | 2 + engine/client/merged.h | 8 +- engine/client/net_master.c | 10 +- engine/client/p_script.c | 4 +- engine/client/pr_csqc.c | 2 +- engine/client/r_2d.c | 57 +- engine/client/r_part.c | 6 +- engine/client/r_partset.h | 23 +- engine/client/r_surf.c | 2 +- engine/client/render.h | 2 +- engine/client/renderer.c | 6 +- engine/client/sbar.c | 6 +- engine/client/snd_al.c | 160 +- engine/client/snd_dma.c | 7 +- engine/client/snd_mem.c | 23 + engine/client/snd_mix.c | 2 +- engine/client/snd_ov.c | 3 +- engine/client/sys_win.c | 2 +- engine/client/view.c | 4 +- engine/client/zqtp.c | 4 +- engine/common/bothdefs.h | 4 +- engine/common/common.h | 2 - engine/common/cvar.c | 20 +- engine/common/cvar.h | 7 +- engine/common/fs.c | 12 +- engine/common/log.c | 8 +- engine/common/net_wins.c | 14 +- engine/common/plugin.c | 9 +- engine/common/pr_bgcmd.c | 1 + engine/common/q3common.c | 47 +- engine/common/translate.c | 2 +- engine/common/vm.h | 3 + engine/dotnet2005/ftequake.sln | 39 + engine/gl/gl_draw.c | 6 + engine/gl/gl_draw.h | 3 +- engine/gl/gl_shader.c | 2 +- engine/gl/gl_vidnt.c | 8 +- engine/http/httpclient.c | 11 +- engine/http/iweb.h | 1 + engine/qclib/qccmain.c | 82 +- engine/server/pr_q1qvm.c | 63 +- engine/server/sv_mvd.c | 4 +- engine/web/ftejslib.h | 5 + engine/web/ftejslib.js | 74 + fteqtv/forward.c | 6 +- fteqtv/httpsv.c | 59 +- fteqtv/menu.c | 2 +- fteqtv/netchan.c | 39 +- fteqtv/parse.c | 2 +- fteqtv/qtv.h | 6 +- fteqtv/qw.c | 24 +- fteqtv/rcon.c | 5 +- fteqtv/source.c | 16 +- plugins/ezhud/ezhud.vcproj | 244 + plugins/ezhud/ezquakeisms.c | 585 +++ plugins/ezhud/ezquakeisms.h | 153 + plugins/ezhud/hud.c | 1535 ++++++ plugins/ezhud/hud.h | 177 + plugins/ezhud/hud_common.c | 8250 ++++++++++++++++++++++++++++++++ plugins/ezhud/hud_common.h | 56 + plugins/ezhud/hud_editor.c | 2800 +++++++++++ plugins/ezhud/hud_editor.h | 59 + plugins/plugin.c | 61 +- plugins/plugin.h | 65 +- 75 files changed, 14968 insertions(+), 302 deletions(-) create mode 100644 plugins/ezhud/ezhud.vcproj create mode 100644 plugins/ezhud/ezquakeisms.c create mode 100644 plugins/ezhud/ezquakeisms.h create mode 100644 plugins/ezhud/hud.c create mode 100644 plugins/ezhud/hud.h create mode 100644 plugins/ezhud/hud_common.c create mode 100644 plugins/ezhud/hud_common.h create mode 100644 plugins/ezhud/hud_editor.c create mode 100644 plugins/ezhud/hud_editor.h diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c index 0c5e27d79..2b3a57e7b 100644 --- a/engine/client/cl_demo.c +++ b/engine/client/cl_demo.c @@ -789,7 +789,7 @@ readit: } break; - case dem_set : + case dem_set: if (readdemobytes (&demopos, &j, 4) != 4) { olddemotime = demtime; @@ -800,6 +800,7 @@ readit: olddemotime = demtime; return 0; } + cls.demostarttime = demtime; cls.netchan.outgoing_sequence = LittleLong(j); cls.netchan.incoming_sequence = LittleLong(i); cl.movesequence = cls.netchan.outgoing_sequence; @@ -1658,6 +1659,7 @@ void CL_PlayDemoStream(vfsfile_t *file, struct dl_download *dl, char *filename, Netchan_Setup (NS_CLIENT, &cls.netchan, &net_from, 0); demtime = -bufferdelay; + cls.demostarttime = 0; cl.gametime = -bufferdelay; cl.gametimemark = realtime;//demtime; if (demtime < -0.5) diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index c99448da7..42fe2ea20 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -27,7 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. float in_sensitivityscale = 1; -void CL_SpareMsec_Callback (struct cvar_s *var, char *oldvalue); +static void QDECL CL_SpareMsec_Callback (struct cvar_s *var, char *oldvalue); cvar_t cl_nodelta = CVAR("cl_nodelta","0"); @@ -1011,7 +1011,7 @@ void CLNQ_SendMove (usercmd_t *cmd, int pnum, sizebuf_t *buf) } } -void Name_Callback(struct cvar_s *var, char *oldvalue) +void QDECL Name_Callback(struct cvar_s *var, char *oldvalue) { if (cls.state <= ca_connected) return; @@ -1301,7 +1301,7 @@ void CL_UseIndepPhysics(qboolean allow) } #endif -void CL_SpareMsec_Callback (struct cvar_s *var, char *oldvalue) +static void QDECL CL_SpareMsec_Callback (struct cvar_s *var, char *oldvalue) { if (var->value > 50) { diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index f0156f6ee..af9bebca6 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -28,8 +28,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "shader.h" #include // callbacks -void CL_Sbar_Callback(struct cvar_s *var, char *oldvalue); -void Name_Callback(struct cvar_s *var, char *oldvalue); +void QDECL CL_Sbar_Callback(struct cvar_s *var, char *oldvalue); +void QDECL Name_Callback(struct cvar_s *var, char *oldvalue); // we need to declare some mouse variables here, because the menu system // references them even when on a unix system. @@ -57,7 +57,7 @@ cvar_t cl_nopext = CVARF("cl_nopext", "0", CVAR_ARCHIVE); cvar_t cl_pext_mask = CVAR("cl_pext_mask", "0xffffffff"); cvar_t cl_nolerp = CVARD("cl_nolerp", "0", "Disables interpolation. If set, missiles/monsters will be smoother, but they may be more laggy. Does not affect players. A value of 2 means 'interpolate only in single-player/coop'."); cvar_t cl_nolerp_netquake = CVARD("cl_nolerp_netquake", "0", "Disables interpolation when connected to an NQ server. Does affect players, even the local player. You probably don't want to set this."); -cvar_t hud_tracking_show = CVAR("hud_tracking_show", "1"); +cvar_t *hud_tracking_show; extern cvar_t net_compress; cvar_t cl_defaultport = CVARAFD("cl_defaultport", STRINGIFY(PORT_QWSERVER), "port", 0, "The default port to connect to servers.\nQW: "STRINGIFY(PORT_QWSERVER)", NQ: "STRINGIFY(PORT_NQSERVER)", Q2: "STRINGIFY(PORT_Q2SERVER)"."); @@ -3656,7 +3656,7 @@ void CL_Init (void) #endif Cvar_Register (&cl_countpendingpl, cl_controlgroup); Cvar_Register (&cl_threadedphysics, cl_controlgroup); - Cvar_Register (&hud_tracking_show, "statusbar"); + hud_tracking_show = Cvar_Get("hud_tracking_show", "1", 0, "statusbar"); Cvar_Register (&cl_download_mapsrc, cl_controlgroup); Cvar_Register (&cl_dlemptyterminate, cl_controlgroup); diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 9c1a524ef..bf75ef0d6 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -357,6 +357,59 @@ int CL_CalcNet (float scale) return percent; } +float CL_CalcNet2 (float *ping, float *ping_min, float *ping_max, float *ping_stddev) +{ + int i; + outframe_t *frame; + int lost = 0; + int pending = 0; + int sent; + int valid = 0; +// char st[80]; + + *ping = 0; + *ping_max = 0; + *ping_min = 1000000000000; + + sent = NET_TIMINGS; + + for (i=cl.movesequence-UPDATE_BACKUP+1 + ; i <= cl.movesequence + ; i++) + { + frame = &cl.outframes[i&UPDATE_MASK]; + if (i > cl.lastackedmovesequence) + { // no response yet + if (cl_countpendingpl.ival) + lost++; + } + else if (frame->latency == -1) + lost++; // lost + else if (frame->latency == -2) + ; // choked + else if (frame->latency == -3) + sent--; // c2spps +// else if (frame->invalid) +// packet_latency[i&NET_TIMINGSMASK] = 9998; // invalid delta + else + { + *ping += frame->latency; + if (*ping_max < frame->latency) + *ping_max = frame->latency; + if (*ping_min > frame->latency) + *ping_min = frame->latency; + valid++; + } + } + + *ping /= valid; + + if (pending == sent || sent < 1) + return 1; //shouldn't ever happen. + else + return lost / sent; +} + void CL_AckedInputFrame(int inseq, int outseq, qboolean worldstateokay) { unsigned int i; @@ -427,7 +480,7 @@ qboolean CL_EnqueDownload(const char *filename, const char *localname, unsigned downloadlist_t *dl; qboolean webdl = false; char ext[8]; - if (!strncmp(filename, "http://", 7)) + if (!strncmp(filename, "http://", 7) || !strncmp(filename, "https://", 8)) { if (!localname) return false; @@ -5741,37 +5794,41 @@ void CL_ParsePrecache(void) } } -void CL_DumpPacket(void) +void Con_HexDump(qbyte *packet, size_t len) { int i; - char *packet = net_message.data; int pos; pos = 0; - while(pos < net_message.cursize) + while(pos < len) { Con_Printf("%5i ", pos); for (i = 0; i < 16; i++) { - if (pos >= net_message.cursize) + if (pos >= len) Con_Printf(" - "); else - Con_Printf("%2x ", (unsigned char)packet[pos]); + Con_Printf("%2x ", packet[pos]); pos++; } pos-=16; for (i = 0; i < 16; i++) { - if (pos >= net_message.cursize) + if (pos >= len) Con_Printf("X"); else if (packet[pos] == 0 || packet[pos] == '\t' || packet[pos] == '\r' || packet[pos] == '\n') Con_Printf("."); else - Con_Printf("%c", (unsigned char)packet[pos]); + Con_Printf("%c", packet[pos]); pos++; } Con_Printf("\n"); } + +} +void CL_DumpPacket(void) +{ + Con_HexDump(net_message.data, net_message.cursize); } void CL_ParsePortalState(void) diff --git a/engine/client/cl_plugin.inc b/engine/client/cl_plugin.inc index 42c8f50fe..8d51ddde8 100644 --- a/engine/client/cl_plugin.inc +++ b/engine/client/cl_plugin.inc @@ -208,6 +208,45 @@ static void Plug_FreePlugImages(plugin_t *plug) } } +//int R2D_ImageSize (qhandle_t image, float *w, float *h) +static qintptr_t VARGS Plug_Draw_ImageSize(void *offset, quintptr_t mask, const qintptr_t *arg) +{ + float *w = VM_POINTER(arg[1]), *h = VM_POINTER(arg[2]); + int iw, ih, ret; + mpic_t *pic; + int i; + + if (VM_OOB(arg[1], sizeof(*w)) || VM_OOB(arg[2], sizeof(*w))) + return -1; + *w = 0; + *h = 0; + if (qrenderer == QR_NONE) + return 0; + + i = VM_LONG(arg[0]); + if (i <= 0 || i > pluginimagearraylen) + return -1; // you fool + i = i - 1; + if (pluginimagearray[i].plugin != currentplug) + return -1; + + if (pluginimagearray[i].pic) + pic = pluginimagearray[i].pic; + else if (pluginimagearray[i].type == 1) + return 0; //wasn't loaded. + else + { + pic = R2D_SafeCachePic(pluginimagearray[i].name); + if (!pic) + return -1; + } + + ret = R_GetShaderSizes(pic, &iw, &ih, true); + *w = iw; + *h = ih; + return ret; +} + //int R2D_Image (float x, float y, float w, float h, float s1, float t1, float s2, float t2, qhandle_t image) static qintptr_t VARGS Plug_Draw_Image(void *offset, quintptr_t mask, const qintptr_t *arg) { @@ -240,21 +279,7 @@ static qintptr_t VARGS Plug_Draw_Image(void *offset, quintptr_t mask, const qint //x1,y1,x2,y2 static qintptr_t VARGS Plug_Draw_Line(void *offset, quintptr_t mask, const qintptr_t *arg) { - switch(qrenderer) //FIXME: I don't want qrenderer seen outside the refresh - { -#ifdef GLQUAKE - case QR_OPENGL: - qglDisable(GL_TEXTURE_2D); - qglBegin(GL_LINES); - qglVertex2f(VM_FLOAT(arg[0]), VM_FLOAT(arg[1])); - qglVertex2f(VM_FLOAT(arg[2]), VM_FLOAT(arg[3])); - qglEnd(); - qglEnable(GL_TEXTURE_2D); - break; -#endif - default: - return 0; - } + R2D_Line(VM_FLOAT(arg[0]), VM_FLOAT(arg[1]), VM_FLOAT(arg[2]), VM_FLOAT(arg[3]), NULL); return 1; } static qintptr_t VARGS Plug_Draw_Character(void *offset, quintptr_t mask, const qintptr_t *arg) @@ -431,16 +456,61 @@ static qintptr_t VARGS Plug_LocalPlayerNumber(void *offset, quintptr_t mask, con { return cl.playerview[0].playernum; } +static qintptr_t VARGS Plug_GetLocalPlayerNumbers(void *offset, quintptr_t mask, const qintptr_t *arg) +{ + int i; + int first = VM_LONG(arg[0]); + int count = VM_LONG(arg[1]); + int *playernums = VM_POINTER(arg[2]); + int *spectracks = VM_POINTER(arg[3]); + if (count < 0 || count > 1000) count = 0; + if (VM_OOB(arg[2], sizeof(*playernums)*count) || VM_OOB(arg[3], sizeof(*playernums)*count)) + return false; + if (first < 0) first = 0; + if (first > cl.splitclients) first = cl.splitclients; + if (first+count > cl.splitclients) count = cl.splitclients-first; + for (i = 0; i < count; i++) + { + playernums[i] = cl.playerview[i].playernum; + spectracks[i] = Cam_TrackNum(&cl.playerview[i]); + } + return count; +} static qintptr_t VARGS Plug_GetServerInfo(void *offset, quintptr_t mask, const qintptr_t *arg) { char *outptr = VM_POINTER(arg[0]); unsigned int outlen = VM_LONG(arg[1]); + extern float demtime; if (VM_OOB(arg[0], outlen)) return false; Q_strncpyz(outptr, cl.serverinfo, outlen); + Q_strncatz(outptr, va("\\intermission\\%i", cl.intermission), outlen); + switch(cls.demoplayback) + { + case DPB_NONE: + break; + case DPB_MVD: + case DPB_EZTV: + Q_strncatz(outptr, "\\demotype\\mvd", outlen); + break; + case DPB_QUAKEWORLD: + Q_strncatz(outptr, "\\demotype\\qw", outlen); + break; +#ifdef NQPROT + case DPB_NETQUAKE: + Q_strncatz(outptr, "\\demotype\\nq", outlen); + break; +#endif +#ifdef Q2CLIENT + case DPB_QUAKE2: + Q_strncatz(outptr, "\\demotype\\q2", outlen); + break; +#endif + } + Q_strncatz(outptr, va("\\demotime\\%f", demtime-cls.demostarttime), outlen); return true; } @@ -455,6 +525,75 @@ static qintptr_t VARGS Plug_SetUserInfo(void *offset, quintptr_t mask, const qin return true; } +typedef struct { + int seats; + struct + { + float avg; + float mn; + float mx; + float stddev; + float loss; + } ping; + float mlatency; + float mrate; + float vlatency; + float vrate; + vec3_t speed; //player speed + + struct + { + float in_pps; + float in_bps; + float out_pps; + float out_bps; + } clrate; + struct + { + float in_pps; + float in_bps; + float out_pps; + float out_bps; + } svrate; +} vmnetinfo_t; +#define has(x) (((quintptr_t)&((vmnetinfo_t*)NULL)->x + sizeof(((vmnetinfo_t*)NULL)->x)) <= outlen) +//aka: misc other hud timing crap +static qintptr_t VARGS Plug_GetNetworkInfo(void *offset, quintptr_t mask, const qintptr_t *arg) +{ + vmnetinfo_t *outptr = VM_POINTER(arg[0]); + unsigned int outlen = VM_LONG(arg[1]); + if (VM_OOB(arg[0], outlen)) + return false; + + if (has(seats)) + outptr->seats = cl.splitclients; + if (has(ping)) + outptr->ping.loss = CL_CalcNet2 (&outptr->ping.avg, &outptr->ping.mn, &outptr->ping.mx, &outptr->ping.stddev); + + if (has(mlatency)) + outptr->mlatency = 0; + if (has(mrate)) + outptr->mrate = 0; + if (has(vlatency)) + outptr->vlatency = 0; + + if (has(speed)) + VectorCopy(outptr->speed, r_refdef.playerview->simvel); + + if (has(clrate)) + NET_GetRates(cls.sockets, &outptr->clrate.in_pps, &outptr->clrate.out_pps, &outptr->clrate.in_bps, &outptr->clrate.out_bps); + if (has(svrate)) + { + memset(&outptr->svrate, 0, sizeof(outptr->svrate)); +#ifndef CLIENTONLY + NET_GetRates(svs.sockets, &outptr->svrate.in_pps, &outptr->svrate.out_pps, &outptr->svrate.in_bps, &outptr->svrate.out_bps); +#endif + } + + return sizeof(vmnetinfo_t); +} +#undef has + static qintptr_t VARGS Plug_GetLocationName(void *offset, quintptr_t mask, const qintptr_t *arg) { float *locpoint = VM_POINTER(arg[0]); @@ -807,6 +946,7 @@ void Plug_Client_Init(void) Plug_RegisterBuiltin("Draw_LoadImageShader", Plug_Draw_LoadImageShader, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("Draw_LoadImage", Plug_Draw_LoadImagePic, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("Draw_Image", Plug_Draw_Image, PLUG_BIF_NEEDSRENDERER); + Plug_RegisterBuiltin("Draw_ImageSize", Plug_Draw_ImageSize, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("Draw_Character", Plug_Draw_Character, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("Draw_String", Plug_Draw_String, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("Draw_Fill", Plug_Draw_Fill, PLUG_BIF_NEEDSRENDERER); @@ -832,8 +972,10 @@ void Plug_Client_Init(void) Plug_RegisterBuiltin("GetLocationName", Plug_GetLocationName, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("GetPlayerInfo", Plug_GetPlayerInfo, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("LocalPlayerNumber", Plug_LocalPlayerNumber, PLUG_BIF_NEEDSRENDERER); + Plug_RegisterBuiltin("GetLocalPlayerNumbers", Plug_GetLocalPlayerNumbers, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("GetServerInfo", Plug_GetServerInfo, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("SetUserInfo", Plug_SetUserInfo, PLUG_BIF_NEEDSRENDERER); +// Plug_RegisterBuiltin("GetNetworkInfo", Plug_GetNetworkInfo, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("S_RawAudio", Plug_S_RawAudio, PLUG_BIF_NEEDSRENDERER); diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index 8ea905105..ddbfbf8f8 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -1080,7 +1080,7 @@ void SCR_ShowPic_Script_f(void) //============================================================================= -void SCR_Fov_Callback (struct cvar_s *var, char *oldvalue) +void QDECL SCR_Fov_Callback (struct cvar_s *var, char *oldvalue) { if (var->value < 10) { @@ -1094,7 +1094,7 @@ void SCR_Fov_Callback (struct cvar_s *var, char *oldvalue) } } -void SCR_Viewsize_Callback (struct cvar_s *var, char *oldvalue) +void QDECL SCR_Viewsize_Callback (struct cvar_s *var, char *oldvalue) { if (var->value < 30) { @@ -1108,7 +1108,7 @@ void SCR_Viewsize_Callback (struct cvar_s *var, char *oldvalue) } } -void CL_Sbar_Callback(struct cvar_s *var, char *oldvalue) +void QDECL CL_Sbar_Callback(struct cvar_s *var, char *oldvalue) { } diff --git a/engine/client/client.h b/engine/client/client.h index 99c8c10f4..8953f1277 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -477,6 +477,7 @@ typedef struct float td_lastframe; // to meter out one message a frame int td_startframe; // host_framecount at start float td_starttime; // realtime at second frame of timedemo + float demostarttime; // the time of the first frame, so we don't get weird results with qw demos int challenge; @@ -1087,6 +1088,7 @@ void CL_ParseQTVFile(vfsfile_t *f, const char *fname, qtvfile_t *result); #define NET_TIMINGSMASK 255 extern int packet_latency[NET_TIMINGS]; int CL_CalcNet (float scale); +float CL_CalcNet2 (float *ping, float *ping_min, float *ping_max, float *ping_stddev); void CL_ClearParseState(void); void CL_Parse_Disconnected(void); void CL_DumpPacket(void); diff --git a/engine/client/console.c b/engine/client/console.c index 164dbbaf9..9e89b955c 100644 --- a/engine/client/console.c +++ b/engine/client/console.c @@ -1136,8 +1136,9 @@ int Con_DrawInput (console_t *con, qboolean focused, int left, int right, int y, maskedtext[p+cmdstart] = (unsigned int)fname[p] | (COLOR_GREEN<string; tex_extensions_count = 0; @@ -3831,7 +3828,7 @@ qboolean Image_LoadTextureFromMemory(texid_t tex, int flags, const char *iname, COM_FileExtension(fname, ext, sizeof(ext)); Q_strncatz(aname, "_alpha.", sizeof(aname)); Q_strncatz(aname, ext, sizeof(aname)); - if ((alph = COM_LoadFile (aname, 5, &alphsize))) + if (!strchr(aname, ':') && (alph = COM_LoadFile (aname, 5, &alphsize))) { if ((alphadata = Read32BitImageFile(alph, alphsize, &alpha_width, &alpha_height, &hasalpha, aname))) { @@ -3859,6 +3856,28 @@ qboolean Image_LoadTextureFromMemory(texid_t tex, int flags, const char *iname, } BZ_Free(rgbadata); } +#ifdef FTE_TARGET_WEB + else if (1) + { + struct pendingtextureinfo *mips; + mips = Z_Malloc(sizeof(*mips)); + mips->type = (flags & IF_3DMAP)?PTI_3D:PTI_2D; + mips->mipcount = 1; + mips->encoding = PTI_WHOLEFILE; + mips->extrafree = NULL; + mips->mip[0].width = 1; + mips->mip[0].height = 1; + mips->mip[0].data = filedata; + mips->mip[0].datasize = filesize; + mips->mip[0].needfree = true; + //width+height are not yet known. bah. + if (flags & IF_NOWORKER) + Image_LoadTextureMips(tex, mips, 0, 0); + else + COM_AddWork(0, Image_LoadTextureMips, tex, mips, 0, 0); + return true; + } +#endif else Sys_Printf("Unable to read file %s (format unsupported)\n", fname); @@ -4250,6 +4269,32 @@ image_t *Image_CreateTexture (const char *identifier, const char *subdir, unsign return image; } +//called on main thread. oh well. +void Image_Downloaded(struct dl_download *dl) +{ + qboolean success = false; + image_t *tex = dl->user_ctx; + image_t *p; + + //make sure the renderer wasn't restarted mid-download + for (p = imagelist; p; p = p->next) + if (p == tex) + break; + if (p) + { + if (dl->status == DL_FINISHED) + { + size_t fsize = VFS_GETLEN(dl->file); + char *buf = BZ_Malloc(fsize); + if (VFS_READ(dl->file, buf, fsize) == fsize) + if (Image_LoadTextureFromMemory(tex, tex->flags, tex->ident, dl->url, buf, fsize)) + success = true; + } + if (!success) + Image_LoadTexture_Failed(tex, NULL, 0, 0); + } +} + //find a texture. will try to load it from disk, using the fallback if it would fail. image_t *Image_GetTexture(const char *identifier, const char *subpath, unsigned int flags, void *fallbackdata, void *fallbackpalette, int fallbackwidth, int fallbackheight, uploadfmt_t fallbackfmt) { @@ -4348,7 +4393,19 @@ image_t *Image_GetTexture(const char *identifier, const char *subpath, unsigned Image_LoadHiResTextureWorker(tex, NULL, 0, 0); else { - if (lowpri) + if (!strncmp(tex->ident, "http://", 7) || !strncmp(tex->ident, "https://", 8)) + { + struct dl_download *dl = HTTP_CL_Get(tex->ident, NULL, Image_Downloaded); + dl->user_ctx = tex; + dl->file = VFSPIPE_Open(); + dl->isquery = true; +#ifdef MULTITHREAD + DL_CreateThread(dl, NULL, NULL); +#else + tex->status = TEX_FAILED; //HACK: so nothing waits for it. +#endif + } + else if (lowpri) COM_AddWork(5, Image_LoadHiResTextureWorker, tex, NULL, 0, 0); else COM_AddWork(2+(seq++%3), Image_LoadHiResTextureWorker, tex, NULL, 0, 0); @@ -4417,7 +4474,7 @@ static void Image_ParseTextureMode(char *cvarname, char *modename, int modes[3]) } Con_Printf("%s: mode %s was not recognised\n", cvarname, modename); } -void Image_TextureMode_Callback (struct cvar_s *var, char *oldvalue) +void QDECL Image_TextureMode_Callback (struct cvar_s *var, char *oldvalue) { int mip[3]={1,0,1}, pic[3]={1,-1,1}, mipcap[2] = {0, 1000}; float anis = 1; diff --git a/engine/client/in_win.c b/engine/client/in_win.c index 922d711c1..c5c1315bd 100644 --- a/engine/client/in_win.c +++ b/engine/client/in_win.c @@ -1362,12 +1362,15 @@ void INS_Accumulate (void) #endif { GetCursorPos (¤t_mouse_pos); + SetCursorPos (window_center_x, window_center_y); IN_MouseMove(sysmouse.qdeviceid, false, current_mouse_pos.x - window_center_x, current_mouse_pos.y - window_center_y, 0, 0); } - - // force the mouse to the center, so there's room to move (rawinput ignore this apparently) - SetCursorPos (window_center_x, window_center_y); + else + { + // force the mouse to the center, so there's room to move (rawinput ignore this apparently) + SetCursorPos (window_center_x, window_center_y); + } } if (!mouseactive) diff --git a/engine/client/keys.c b/engine/client/keys.c index 72f2e6c60..b13c557f2 100644 --- a/engine/client/keys.c +++ b/engine/client/keys.c @@ -60,7 +60,7 @@ qboolean keydown[K_MAX]; char *releasecommand[K_MAX][MAX_INDEVS]; //this is the console command to be invoked when the key is released. should free it. qbyte releasecommandlevel[K_MAX][MAX_INDEVS]; //and this is the cbuf level it is to be run at. -void Con_Selectioncolour_Callback(struct cvar_s *var, char *oldvalue); +static void QDECL Con_Selectioncolour_Callback(struct cvar_s *var, char *oldvalue); extern cvar_t con_displaypossibilities; cvar_t con_selectioncolour = CVARFC("con_selectioncolour", "0", CVAR_RENDERERCALLBACK, Con_Selectioncolour_Callback); @@ -488,7 +488,7 @@ int Con_ExecuteLine(console_t *con, char *line) vec3_t sccolor; -void Con_Selectioncolour_Callback(struct cvar_s *var, char *oldvalue) +static void QDECL Con_Selectioncolour_Callback(struct cvar_s *var, char *oldvalue) { if (qrenderer != QR_NONE) SCR_StringToRGB(var->string, sccolor, 1); diff --git a/engine/client/m_mp3.c b/engine/client/m_mp3.c index 665541aac..11ab8c6c7 100644 --- a/engine/client/m_mp3.c +++ b/engine/client/m_mp3.c @@ -3978,6 +3978,8 @@ static void S_MP3_Purge(sfx_t *sfx) if (dec->dstdata) BZ_Free(dec->dstdata); BZ_Free(dec); + + sfx->loadstate = SLS_NOTLOADED; } /*must be thread safe*/ diff --git a/engine/client/merged.h b/engine/client/merged.h index 7d3ac60e2..28c31ed05 100644 --- a/engine/client/merged.h +++ b/engine/client/merged.h @@ -85,6 +85,7 @@ void R2D_Image2dQuad(vec2_t points[], vec2_t texcoords[], mpic_t *pic); void R2D_ImageColours(float r, float g, float b, float a); void R2D_ImagePaletteColour(unsigned int i, float a); void R2D_FillBlock(float x, float y, float w, float h); +void R2D_Line(float x1, float y1, float x2, float y2, mpic_t *pic); extern void (*Draw_Init) (void); @@ -203,7 +204,10 @@ typedef enum uploadfmt TF_DEPTH24, TF_DEPTH32, TF_RGBA16F, - TF_RGBA32F + TF_RGBA32F, + + /*for weird systems where the gl driver needs to do the decode (read: webgl)*/ + TF_SYSTEMDECODE } uploadfmt_t; enum @@ -286,6 +290,8 @@ struct pendingtextureinfo PTI_S3RGBA1, PTI_S3RGBA3, PTI_S3RGBA5, + //weird specialcase mess to take advantage of webgl so we don't need redundant bloat where we're already strugging with potential heap limits + PTI_WHOLEFILE, //depth formats PTI_DEPTH16, PTI_DEPTH24, diff --git a/engine/client/net_master.c b/engine/client/net_master.c index 002ed2e1c..82b204a5d 100644 --- a/engine/client/net_master.c +++ b/engine/client/net_master.c @@ -45,7 +45,7 @@ void Master_DetermineMasterTypes(void) #define MAX_MASTER_ADDRESSES 4 //each master might have multiple dns addresses, typically both ipv4+ipv6. we want to report to both address families so we work with remote single-stack hosts. #ifndef CLIENTONLY -void Net_Masterlist_Callback(struct cvar_s *var, char *oldvalue); +static void QDECL Net_Masterlist_Callback(struct cvar_s *var, char *oldvalue); static void SV_SetMaster_f (void); #else #define Net_Masterlist_Callback NULL @@ -149,7 +149,7 @@ void Net_Master_Init(void) #ifndef CLIENTONLY -void Net_Masterlist_Callback(struct cvar_s *var, char *oldvalue) +static void QDECL Net_Masterlist_Callback(struct cvar_s *var, char *oldvalue) { int i; @@ -2000,7 +2000,10 @@ void MasterInfo_Request(master_t *mast) { mast->dl = HTTP_CL_Get(mast->address, NULL, MasterInfo_ProcessHTTPJSON); if (mast->dl) + { mast->dl->user_ctx = mast; + mast->dl->isquery = true; + } } break; case MT_MASTERHTTP: @@ -2008,7 +2011,10 @@ void MasterInfo_Request(master_t *mast) { mast->dl = HTTP_CL_Get(mast->address, NULL, MasterInfo_ProcessHTTP); if (mast->dl) + { mast->dl->user_ctx = mast; + mast->dl->isquery = true; + } } break; #endif diff --git a/engine/client/p_script.c b/engine/client/p_script.c index 6b50f6dd1..e604536ed 100644 --- a/engine/client/p_script.c +++ b/engine/client/p_script.c @@ -367,7 +367,7 @@ extern cvar_t r_bloodstains; extern cvar_t gl_part_flame; // callbacks -static void R_ParticleDesc_Callback(struct cvar_s *var, char *oldvalue); +static void QDECL R_ParticleDesc_Callback(struct cvar_s *var, char *oldvalue); extern cvar_t r_particledesc; extern cvar_t r_part_rain_quantity; @@ -3027,7 +3027,7 @@ static void R_Particles_KillAllEffects(void) } } -static void R_ParticleDesc_Callback(struct cvar_s *var, char *oldvalue) +static void QDECL R_ParticleDesc_Callback(struct cvar_s *var, char *oldvalue) { char token[256]; qboolean first; diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index fd584203c..148af4250 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -4146,7 +4146,7 @@ typedef struct unsigned int maxents; //buffer size struct { - unsigned short n; //don't rely on the ent->v->entnum + unsigned int n; //don't rely on the ent->v->entnum csqcedict_t *e; //the csqc ent } *e; } csqcdelta_pack_t; diff --git a/engine/client/r_2d.c b/engine/client/r_2d.c index bcc2e72b0..0fef1a150 100644 --- a/engine/client/r_2d.c +++ b/engine/client/r_2d.c @@ -43,20 +43,20 @@ extern cvar_t vid_conautoscale; extern cvar_t vid_conheight; extern cvar_t vid_conwidth; extern cvar_t con_textsize; -void R2D_Font_Callback(struct cvar_s *var, char *oldvalue); -void R2D_Conautoscale_Callback(struct cvar_s *var, char *oldvalue); -void R2D_ScreenAngle_Callback(struct cvar_s *var, char *oldvalue); -void R2D_Conheight_Callback(struct cvar_s *var, char *oldvalue); -void R2D_Conwidth_Callback(struct cvar_s *var, char *oldvalue); +static void QDECL R2D_Font_Callback(struct cvar_s *var, char *oldvalue); +static void QDECL R2D_Conautoscale_Callback(struct cvar_s *var, char *oldvalue); +static void QDECL R2D_ScreenAngle_Callback(struct cvar_s *var, char *oldvalue); +static void QDECL R2D_Conheight_Callback(struct cvar_s *var, char *oldvalue); +static void QDECL R2D_Conwidth_Callback(struct cvar_s *var, char *oldvalue); extern cvar_t crosshair; extern cvar_t crosshaircolor; extern cvar_t crosshairsize; extern cvar_t crosshairimage; extern cvar_t crosshairalpha; -void R2D_Crosshair_Callback(struct cvar_s *var, char *oldvalue); -void R2D_CrosshairImage_Callback(struct cvar_s *var, char *oldvalue); -void R2D_CrosshairColor_Callback(struct cvar_s *var, char *oldvalue); +static void QDECL R2D_Crosshair_Callback(struct cvar_s *var, char *oldvalue); +static void QDECL R2D_CrosshairImage_Callback(struct cvar_s *var, char *oldvalue); +static void QDECL R2D_CrosshairColor_Callback(struct cvar_s *var, char *oldvalue); //We need this for minor things though, so we'll just use the slow accurate method. @@ -487,6 +487,29 @@ void R2D_FillBlock(float x, float y, float w, float h) BE_DrawMesh_Single(shader_draw_fill, &draw_mesh, NULL, &shader_draw_fill->defaulttextures, r2d_be_flags); } +void R2D_Line(float x1, float y1, float x2, float y2, shader_t *shader) +{ + VectorSet(draw_mesh_xyz[0], x1, y1, 0); + Vector2Set(draw_mesh_st[0], 0, 0); + + VectorSet(draw_mesh_xyz[1], x2, y2, 0); + Vector2Set(draw_mesh_st[1], 1, 0); + + if (!shader) + { + if (draw_mesh_colors[0][3] != 1) + shader = shader_draw_fill_trans; + else + shader = shader_draw_fill; + } + + draw_mesh.numvertexes = 2; + draw_mesh.numindexes = 2; + BE_DrawMesh_Single(shader, &draw_mesh, NULL, &shader->defaulttextures, BEF_LINES); + draw_mesh.numvertexes = 4; + draw_mesh.numindexes = 6; +} + void R2D_ScalePic (float x, float y, float width, float height, mpic_t *pic) { R2D_Image(x, y, width, height, 0, 0, 1, 1, pic); @@ -642,7 +665,7 @@ void R2D_TileClear (float x, float y, float w, float h) BE_DrawMesh_Single(draw_backtile, &draw_mesh, NULL, &draw_backtile->defaulttextures, r2d_be_flags); } -void R2D_Conback_Callback(struct cvar_s *var, char *oldvalue) +void QDECL R2D_Conback_Callback(struct cvar_s *var, char *oldvalue) { if (qrenderer == QR_NONE || !strcmp(var->string, "none")) { @@ -823,7 +846,7 @@ void R2D_Font_Changed(void) font_console = font_default; } -void R2D_Font_Callback(struct cvar_s *var, char *oldvalue) +static void QDECL R2D_Font_Callback(struct cvar_s *var, char *oldvalue) { con_textsize.modified = true; } @@ -909,7 +932,7 @@ void R2D_Console_Resize(void) #endif } -void R2D_Conheight_Callback(struct cvar_s *var, char *oldvalue) +static void QDECL R2D_Conheight_Callback(struct cvar_s *var, char *oldvalue) { if (var->value > 1536) //anything higher is unreadable. { @@ -925,7 +948,7 @@ void R2D_Conheight_Callback(struct cvar_s *var, char *oldvalue) R2D_Console_Resize(); } -void R2D_Conwidth_Callback(struct cvar_s *var, char *oldvalue) +static void QDECL R2D_Conwidth_Callback(struct cvar_s *var, char *oldvalue) { //let let the user be too crazy if (var->value > 2048) //anything higher is unreadable. @@ -942,12 +965,12 @@ void R2D_Conwidth_Callback(struct cvar_s *var, char *oldvalue) R2D_Console_Resize(); } -void R2D_Conautoscale_Callback(struct cvar_s *var, char *oldvalue) +static void QDECL R2D_Conautoscale_Callback(struct cvar_s *var, char *oldvalue) { R2D_Console_Resize(); } -void R2D_ScreenAngle_Callback(struct cvar_s *var, char *oldvalue) +static void QDECL R2D_ScreenAngle_Callback(struct cvar_s *var, char *oldvalue) { R2D_Console_Resize(); } @@ -1258,17 +1281,17 @@ void R2D_Crosshair_Update(void) } -void R2D_CrosshairImage_Callback(struct cvar_s *var, char *oldvalue) +static void QDECL R2D_CrosshairImage_Callback(struct cvar_s *var, char *oldvalue) { R2D_Crosshair_Update(); } -void R2D_Crosshair_Callback(struct cvar_s *var, char *oldvalue) +static void QDECL R2D_Crosshair_Callback(struct cvar_s *var, char *oldvalue) { R2D_Crosshair_Update(); } -void R2D_CrosshairColor_Callback(struct cvar_s *var, char *oldvalue) +static void QDECL R2D_CrosshairColor_Callback(struct cvar_s *var, char *oldvalue) { SCR_StringToRGB(var->string, ch_color, 255); diff --git a/engine/client/r_part.c b/engine/client/r_part.c index 147a33ec8..195a3ff13 100644 --- a/engine/client/r_part.c +++ b/engine/client/r_part.c @@ -483,7 +483,7 @@ void R_Clutter_Purge(void) -void R_Rockettrail_Callback(struct cvar_s *var, char *oldvalue) +static void QDECL R_Rockettrail_Callback(struct cvar_s *var, char *oldvalue) { int i; model_t *mod; @@ -501,7 +501,7 @@ void R_Rockettrail_Callback(struct cvar_s *var, char *oldvalue) } } -void R_Grenadetrail_Callback(struct cvar_s *var, char *oldvalue) +static void QDECL R_Grenadetrail_Callback(struct cvar_s *var, char *oldvalue) { int i; model_t *mod; @@ -543,7 +543,7 @@ particleengine_t *particlesystem[] = NULL, }; -void R_ParticleSystem_Callback(struct cvar_s *var, char *oldvalue) +static void QDECL R_ParticleSystem_Callback(struct cvar_s *var, char *oldvalue) { int i; if (pe) diff --git a/engine/client/r_partset.h b/engine/client/r_partset.h index 098ef26d4..0435cea1d 100644 --- a/engine/client/r_partset.h +++ b/engine/client/r_partset.h @@ -1,9 +1,30 @@ +/* +WARNING: THIS FILE IS GENERATED BY 'generatebuiltin.c'. +YOU SHOULD NOT EDIT THIS FILE BY HAND +*/ + extern char *particle_set_spikeset; +#define R_PARTSET_BUILTINS_spikeset {"spikeset", &particle_set_spikeset}, extern char *particle_set_faithful; +#define R_PARTSET_BUILTINS_faithful {"faithful", &particle_set_faithful}, extern char *particle_set_highfps; +#define R_PARTSET_BUILTINS_highfps {"highfps", &particle_set_highfps}, extern char *particle_set_high; +#define R_PARTSET_BUILTINS_high {"high", &particle_set_high}, extern char *particle_set_minimal; +#define R_PARTSET_BUILTINS_minimal {"minimal", &particle_set_minimal}, +#ifdef HEXEN2 extern char *particle_set_h2part; +#define R_PARTSET_BUILTINS_h2part {"h2part", &particle_set_h2part}, +#else +#define R_PARTSET_BUILTINS_h2part +#endif +#ifdef Q2CLIENT extern char *particle_set_q2part; +#define R_PARTSET_BUILTINS_q2part {"q2part", &particle_set_q2part}, +#else +#define R_PARTSET_BUILTINS_q2part +#endif extern char *particle_set_tsshaft; -#define R_PARTSET_BUILTINS {"spikeset", &particle_set_spikeset},{"faithful", &particle_set_faithful},{"highfps", &particle_set_highfps},{"high", &particle_set_high},{"minimal", &particle_set_minimal},{"h2part", &particle_set_h2part},{"q2part", &particle_set_q2part},{"tsshaft", &particle_set_tsshaft}, +#define R_PARTSET_BUILTINS_tsshaft {"tsshaft", &particle_set_tsshaft}, +#define R_PARTSET_BUILTINS R_PARTSET_BUILTINS_spikeset R_PARTSET_BUILTINS_faithful R_PARTSET_BUILTINS_highfps R_PARTSET_BUILTINS_high R_PARTSET_BUILTINS_minimal R_PARTSET_BUILTINS_h2part R_PARTSET_BUILTINS_q2part R_PARTSET_BUILTINS_tsshaft diff --git a/engine/client/r_surf.c b/engine/client/r_surf.c index 885c51bcf..31c82f9b6 100644 --- a/engine/client/r_surf.c +++ b/engine/client/r_surf.c @@ -64,7 +64,7 @@ int Surf_LightmapShift (model_t *model) return lightmap_shift; } -void Surf_RebuildLightmap_Callback (struct cvar_s *var, char *oldvalue) +void QDECL Surf_RebuildLightmap_Callback (struct cvar_s *var, char *oldvalue) { Mod_RebuildLightmaps(); } diff --git a/engine/client/render.h b/engine/client/render.h index 3d068cacb..66feb286c 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -327,7 +327,7 @@ extern int numlightmaps; extern int lightmap_bytes; // 1, 3, or 4 extern qboolean lightmap_bgra; /*true=bgra, false=rgba*/ -void Surf_RebuildLightmap_Callback (struct cvar_s *var, char *oldvalue); +void QDECL Surf_RebuildLightmap_Callback (struct cvar_s *var, char *oldvalue); void R_SetSky(char *skyname); /*override all sky shaders*/ diff --git a/engine/client/renderer.c b/engine/client/renderer.c index e697bdca2..90f04521a 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -35,9 +35,9 @@ unsigned int d_8to24bgrtable[256]; extern int gl_anisotropy_factor; // callbacks used for cvars -void SCR_Viewsize_Callback (struct cvar_s *var, char *oldvalue); -void SCR_Fov_Callback (struct cvar_s *var, char *oldvalue); -void Image_TextureMode_Callback (struct cvar_s *var, char *oldvalue); +void QDECL SCR_Viewsize_Callback (struct cvar_s *var, char *oldvalue); +void QDECL SCR_Fov_Callback (struct cvar_s *var, char *oldvalue); +void QDECL Image_TextureMode_Callback (struct cvar_s *var, char *oldvalue); cvar_t vid_vsync = CVARAF ("vid_wait", "0", "vid_vsync", CVAR_ARCHIVE); diff --git a/engine/client/sbar.c b/engine/client/sbar.c index c6bc9707b..b4fd28195 100644 --- a/engine/client/sbar.c +++ b/engine/client/sbar.c @@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" #include "shader.h" -extern cvar_t hud_tracking_show; +extern cvar_t *hud_tracking_show; #define CON_ALTMASK (CON_2NDCHARSETTEXT|CON_WHITEMASK) @@ -2734,7 +2734,7 @@ void Sbar_Draw (playerview_t *pv) { if (pv->cam_auto != CAM_TRACK) { - if (hud_tracking_show.ival || cl_sbar.ival) + if (hud_tracking_show->ival || cl_sbar.ival) { //this is annoying. Sbar_DrawPic (0, 0, 320, 24, sb_scorebar); Sbar_DrawString (160-7*8,4, "SPECTATOR MODE"); @@ -2750,7 +2750,7 @@ void Sbar_Draw (playerview_t *pv) else Sbar_DrawNormal (pv); - if (hud_tracking_show.ival) + if (hud_tracking_show->ival) { Q_snprintfz(st, sizeof(st), "Tracking %-.64s", cl.players[pv->cam_spec_track].name); diff --git a/engine/client/snd_al.c b/engine/client/snd_al.c index 124e37b0f..136279176 100644 --- a/engine/client/snd_al.c +++ b/engine/client/snd_al.c @@ -133,6 +133,7 @@ static AL_API void (AL_APIENTRY *palSourceUnqueueBuffers)(ALuint source, ALsizei #define AL_ORIENTATION 0x100F #define AL_SOURCE_STATE 0x1010 #define AL_PLAYING 0x1012 +#define AL_BUFFERS_QUEUED 0x1015 #define AL_BUFFERS_PROCESSED 0x1016 #define AL_REFERENCE_DISTANCE 0x1020 #define AL_ROLLOFF_FACTOR 0x1021 @@ -285,10 +286,10 @@ extern int loaded_sfx; extern int num_sfx; -static void OnChangeALMaxDistance (cvar_t *var, char *value); -static void OnChangeALSpeedOfSound (cvar_t *var, char *value); -static void OnChangeALDopplerFactor (cvar_t *var, char *value); -static void OnChangeALDistanceModel (cvar_t *var, char *value); +static void QDECL OnChangeALMaxDistance (cvar_t *var, char *value); +static void QDECL OnChangeALSpeedOfSound (cvar_t *var, char *value); +static void QDECL OnChangeALDopplerFactor (cvar_t *var, char *value); +static void QDECL OnChangeALDistanceModel (cvar_t *var, char *value); /* static void S_Init_f(void); static void S_Info(void); @@ -358,12 +359,19 @@ static void PrintALError(char *string) Con_Printf("OpenAL - %s: %x: %s\n",string,err,text); } -void OpenAL_LoadCache(unsigned int *bufptr, sfxcache_t *sc, float volume) +qboolean OpenAL_LoadCache(unsigned int *bufptr, sfxcache_t *sc, float volume) { unsigned int fmt; unsigned int size; switch(sc->width) { +#ifdef FTE_TARGET_WEB + case 0: + palGenBuffers(1, bufptr); + emscriptenfte_al_loadaudiofile(*bufptr, sc->data, sc->length); + //not allowed to play it yet, because it (probably) doesn't exist yet. + return false; +#endif case 1: if (sc->numchannels == 2) { @@ -389,7 +397,7 @@ void OpenAL_LoadCache(unsigned int *bufptr, sfxcache_t *sc, float volume) } break; default: - return; + return false; } PrintALError("pre Buffer Data"); palGenBuffers(1, bufptr); @@ -436,12 +444,22 @@ void OpenAL_LoadCache(unsigned int *bufptr, sfxcache_t *sc, float volume) free(tmp); } else + { +#if 0 + short *tmp = malloc(size); + memcpy(tmp, sc->data, size); + palBufferData(*bufptr, fmt, tmp, size, sc->speed); + free(tmp); +#else palBufferData(*bufptr, fmt, sc->data, size, sc->speed); +#endif + } } //FIXME: we need to handle oal-oom error codes PrintALError("Buffer Data"); + return true; } void OpenAL_CvarInit(void) @@ -519,16 +537,35 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, unsigned palSourceStop(src); //reclaim any queued buffers - palGetSourcei(src, AL_SOURCE_TYPE, &buf); - if (buf == AL_STREAMING) + if (src) { - for(;;) + palGetSourcei(src, AL_SOURCE_TYPE, &buf); + if (buf == AL_STREAMING) { - palGetSourcei(src, AL_BUFFERS_PROCESSED, &buf); - if (!buf) - break; - palSourceUnqueueBuffers(src, 1, &buf); - palDeleteBuffers(1, &buf); + for(;;) + { + palGetSourcei(src, AL_BUFFERS_PROCESSED, &buf); + if (!buf) + break; + palSourceUnqueueBuffers(src, 1, &buf); + palDeleteBuffers(1, &buf); + } + } + } + if (!schanged && sfx +#ifndef FTE_TARGET_WEB + && (chan->looping || (!sfx->decoder.decodedata && sfx->decoder.buf && ((sfxcache_t*)sfx->decoder.buf)->loopstart)) +#endif + ) + { + palGetSourcei(src, AL_SOURCE_STATE, &buf); + if (buf != AL_PLAYING) + { + schanged = true; + if (chan->looping) + chan->pos = 0; + else + sfx = chan->sfx = NULL; } } @@ -560,47 +597,82 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, unsigned if (!S_LoadSound(sfx)) return; //can't load it if (sfx->loadstate != SLS_LOADED) + { + if (sfx->loadstate == SLS_LOADING) + { + palDeleteSources(1, &src); + oali->source[chnum] = 0; + } return; //not available yet + } if (sfx->decoder.decodedata) { int offset; - sfxcache_t sbuf, *sc = sfx->decoder.decodedata(sfx, &sbuf, chan->pos>>PITCHSHIFT, 65536); - memcpy(&sbuf, sc, sizeof(sbuf)); + sfxcache_t sbuf, *sc; + palGetSourcei(src, AL_BUFFERS_QUEUED, &buf); + if (buf <= 2) + { //decode periodically instead of all at the start. + sc = sfx->decoder.decodedata(sfx, &sbuf, chan->pos>>PITCHSHIFT, 65536); + memcpy(&sbuf, sc, sizeof(sbuf)); - //hack up the sound to offset it correctly - offset = (chan->pos>>PITCHSHIFT) - sbuf.soundoffset; - sbuf.data += offset * sc->width*sc->numchannels; - sbuf.length -= offset; + //hack up the sound to offset it correctly + offset = (chan->pos>>PITCHSHIFT) - sbuf.soundoffset; + sbuf.data += offset * sc->width*sc->numchannels; + sbuf.length -= offset; - if (!sbuf.length && (chan->pos>>PITCHSHIFT) == sbuf.soundoffset) - { - chan->sfx = NULL; - if (sfx->decoder.ended) + if (!sbuf.length)// && (chan->pos>>PITCHSHIFT) == sbuf.soundoffset) { - if (!S_IsPlayingSomewhere(sfx)) - sfx->decoder.ended(sfx); + palGetSourcei(src, AL_SOURCE_STATE, &buf); + if (buf != AL_PLAYING) + { + if (chan->looping) + chan->pos = 0; + else if(sbuf.loopstart != -1) + chan->pos = sbuf.loopstart<sfx = NULL; + if (sfx->decoder.ended) + { + if (!S_IsPlayingSomewhere(sfx)) + sfx->decoder.ended(sfx); + } + } + return; + } + } + else + { + sbuf.soundoffset = 0; + + //build a buffer with it and queue it up. + //buffer will be purged later on when its unqueued + OpenAL_LoadCache(&buf, &sbuf, max(1,cvolume)); + palSourceQueueBuffers(src, 1, &buf); + + //yay + chan->pos += sbuf.length<pos += sbuf.length<openal_buffer, sfx->decoder.buf, 1); + if (!sfx->decoder.buf) + return; + if (!OpenAL_LoadCache(&sfx->openal_buffer, sfx->decoder.buf, 1)) + return; palSourcei(src, AL_BUFFER, sfx->openal_buffer); } } +#ifdef FTE_TARGET_WEB + //loading an ogg is async, so we must wait until its valid. + else if (!palIsBuffer(sfx->openal_buffer)) + return; +#endif else palSourcei(src, AL_BUFFER, sfx->openal_buffer); } @@ -788,20 +860,20 @@ static qboolean OpenAL_Init(soundcardinfo_t *sc, const char *devname) return true; } -static void OnChangeALMaxDistance (cvar_t *var, char *oldvalue) +static void QDECL OnChangeALMaxDistance (cvar_t *var, char *oldvalue) { } -static void OnChangeALSpeedOfSound (cvar_t *var, char *value) +static void QDECL OnChangeALSpeedOfSound (cvar_t *var, char *value) { if (palSpeedOfSound) palSpeedOfSound(var->value); } -static void OnChangeALDopplerFactor (cvar_t *var, char *oldvalue) +static void QDECL OnChangeALDopplerFactor (cvar_t *var, char *oldvalue) { if (palDopplerFactor) palDopplerFactor(var->value); } -static void OnChangeALDistanceModel (cvar_t *var, char *value) +static void QDECL OnChangeALDistanceModel (cvar_t *var, char *oldvalue) { if (!palDistanceModel) return; diff --git a/engine/client/snd_dma.c b/engine/client/snd_dma.c index 2aac2691c..aa22756f3 100644 --- a/engine/client/snd_dma.c +++ b/engine/client/snd_dma.c @@ -117,7 +117,7 @@ cvar_t snd_device = CVARAF( "s_device", "", cvar_t snd_device_opts = CVARFD( "_s_device_opts", "", CVAR_NOSET, "The possible audio output devices, in \"value\" \"description\" pairs, for gamecode to read."); #ifdef VOICECHAT -static void S_Voip_Play_Callback(cvar_t *var, char *oldval); +static void QDECL S_Voip_Play_Callback(cvar_t *var, char *oldval); cvar_t snd_voip_capturedevice = CVARF("cl_voip_capturedevice", "", CVAR_ARCHIVE); cvar_t snd_voip_capturedevice_opts = CVARFD("_cl_voip_capturedevice_opts", "", CVAR_NOSET, "The possible audio capture devices, in \"value\" \"description\" pairs, for gamecode to read."); int voipbutton; //+voip, no longer part of cl_voip_send to avoid it getting saved @@ -1332,7 +1332,7 @@ static void S_Voip_f(void) qspeex_preprocess_ctl(s_voip.speexdsp.preproc, SPEEX_PREPROCESS_SET_AGC_MAX_GAIN, &i); } } -static void S_Voip_Play_Callback(cvar_t *var, char *oldval) +static void QDECL S_Voip_Play_Callback(cvar_t *var, char *oldval) { if (cls.fteprotocolextensions2 & PEXT2_VOICECHAT) { @@ -2571,6 +2571,9 @@ void S_Music_Clear(sfx_t *onlyifsample) sc->channel[i].pos = 0; sc->channel[i].sfx = NULL; + if (sc->ChannelUpdate) + sc->ChannelUpdate(sc, &sc->channel[i], true); + if (s && s->decoder.ended && !S_IsPlayingSomewhere(s)) //if we aint playing it elsewhere, free it compleatly. s->decoder.ended(s); } diff --git a/engine/client/snd_mem.c b/engine/client/snd_mem.c index 1729c090c..b15173d8f 100644 --- a/engine/client/snd_mem.c +++ b/engine/client/snd_mem.c @@ -730,8 +730,31 @@ qboolean S_LoadWavSound (sfx_t *s, qbyte *data, int datalen, int sndspeed) qboolean S_LoadOVSound (sfx_t *s, qbyte *data, int datalen, int sndspeed); +#ifdef FTE_TARGET_WEB +//web browsers contain their own decoding libraries that our openal stuff can use. +qboolean S_LoadBrowserFile (sfx_t *s, qbyte *data, int datalen, int sndspeed) +{ + sfxcache_t *sc; + s->decoder.buf = sc = BZ_Malloc(sizeof(sfxcache_t) + datalen); + sc->data = (qbyte*)(sc+1); + sc->length = datalen; + sc->width = 0; //ie: not pcm + sc->loopstart = -1; + sc->speed = sndspeed; + sc->numchannels = 2; + sc->soundoffset = 0; + memcpy(sc->data, data, datalen); + + return true; +} +#endif + +//highest priority is last. S_LoadSound_t AudioInputPlugins[10] = { +#ifdef FTE_TARGET_WEB + S_LoadBrowserFile, +#endif #ifdef AVAIL_OGGVORBIS S_LoadOVSound, #endif diff --git a/engine/client/snd_mix.c b/engine/client/snd_mix.c index 6373e4e56..e67d7294a 100644 --- a/engine/client/snd_mix.c +++ b/engine/client/snd_mix.c @@ -226,7 +226,7 @@ void S_PaintChannels(soundcardinfo_t *sc, int endtime) else SND_PaintChannel8_O8I1(ch, scache, count); } - else + else if (scache->width == 2) { if (scache->numchannels==2) SND_PaintChannel16_O2I2(ch, scache, ltime-sc->paintedtime, count); diff --git a/engine/client/snd_ov.c b/engine/client/snd_ov.c index 786fa117f..81a786627 100644 --- a/engine/client/snd_ov.c +++ b/engine/client/snd_ov.c @@ -235,7 +235,7 @@ sfxcache_t *OV_DecodeSome(struct sfx_s *sfx, struct sfxcache_s *buf, int start, { buf->data = dec->decodedbuffer; buf->soundoffset = dec->decodedbytestart / (2 * dec->srcchannels); - buf->length = dec->decodedbytecount; + buf->length = dec->decodedbytecount / (2 * dec->srcchannels); buf->loopstart = -1; buf->numchannels = dec->srcchannels; buf->speed = snd_speed; @@ -264,6 +264,7 @@ void OV_CancelDecoder(sfx_t *s) dec->decodedbuffer = NULL; BZ_Free(dec); + s->loadstate = SLS_NOTLOADED; } static size_t VARGS read_func (void *ptr, size_t size, size_t nmemb, void *datasource) diff --git a/engine/client/sys_win.c b/engine/client/sys_win.c index fadc4f47d..518d43832 100644 --- a/engine/client/sys_win.c +++ b/engine/client/sys_win.c @@ -3870,7 +3870,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin *COM_SkipPath(bindir) = 0; parms.argv = (const char **)sys_argv; - host_parms.binarydir = bindir; + parms.binarydir = bindir; COM_InitArgv (parms.argc, parms.argv); c = COM_CheckParm("-qcdebug"); diff --git a/engine/client/view.c b/engine/client/view.c index d942ca6cc..7b134cc03 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -299,7 +299,7 @@ void V_DriftPitch (playerview_t *pv) ============================================================================== */ -void V_Gamma_Callback(struct cvar_s *var, char *oldvalue); +static void QDECL V_Gamma_Callback(struct cvar_s *var, char *oldvalue); cshift_t cshift_empty = { {130,80,50}, 0 }; cshift_t cshift_water = { {130,80,50}, 128 }; @@ -372,7 +372,7 @@ void BuildGammaTable (float g, float c, float b) V_CheckGamma ================= */ -void V_Gamma_Callback(struct cvar_s *var, char *oldvalue) +static void QDECL V_Gamma_Callback(struct cvar_s *var, char *oldvalue) { BuildGammaTable (v_gamma.value, v_contrast.value, v_brightness.value); V_UpdatePalette (true); diff --git a/engine/client/zqtp.c b/engine/client/zqtp.c index 141a41cc5..50eb67fea 100644 --- a/engine/client/zqtp.c +++ b/engine/client/zqtp.c @@ -67,7 +67,7 @@ qboolean suppress; #define Q_rint(f) ((int)((f)+0.5)) // callbacks used for TP cvars -void TP_SkinCvar_Callback(struct cvar_s *var, char *oldvalue); +static void QDECL TP_SkinCvar_Callback(struct cvar_s *var, char *oldvalue); //a list of all the cvars //this is down to the fact that I keep defining them but forgetting to register. :/ @@ -3441,7 +3441,7 @@ static void TP_MsgFilter_f (void) } } -void TP_SkinCvar_Callback(struct cvar_s *var, char *oldvalue) +static void QDECL TP_SkinCvar_Callback(struct cvar_s *var, char *oldvalue) { Skin_FlushPlayers(); } diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index a8e1106da..6ea773a95 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -96,6 +96,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define AVAIL_DSOUND #define AVAIL_D3D #endif +//#define AVAIL_XZDEC #if !defined(MINIMAL) && !defined(NPFTE) && !defined(NPQTV) #if defined(_WIN32) && !defined(FTE_SDL) && !defined(WINRT) @@ -140,6 +141,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #endif #ifdef NO_ZLIB #undef AVAIL_ZLIB + #undef AVAIL_XZDEC #endif #ifdef NO_OGG #undef AVAIL_OGGVORBIS @@ -276,7 +278,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define FULLENGINENAME "FTE QuakeWorld" //the posh name for the engine #endif #ifndef ENGINEWEBSITE - #define ENGINEWEBSITE "http://www.fteqw.com" //url for program + #define ENGINEWEBSITE "http://fte.triptohell.info" //url for program #endif #ifdef QUAKETC diff --git a/engine/common/common.h b/engine/common/common.h index 78b40077f..38a962890 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -596,8 +596,6 @@ typedef enum { LOG_RCON, LOG_TYPES } logtype_t; -void Log_Dir_Callback (struct cvar_s *var, char *oldvalue); -void Log_Name_Callback (struct cvar_s *var, char *oldvalue); void Log_String (logtype_t lognum, char *s); void Con_Log (char *s); void Log_Logfile_f (void); diff --git a/engine/common/cvar.c b/engine/common/cvar.c index d2c544f96..c1d329756 100644 --- a/engine/common/cvar.c +++ b/engine/common/cvar.c @@ -801,6 +801,22 @@ cvar_t *Cvar_SetCore (cvar_t *var, const char *value, qboolean force) var->value = Q_atof (var->string); var->ival = Q_atoi (var->string); + { + char *str = COM_Parse(var->string); + var->vec4[0] = atof(com_token); + str = COM_Parse(str); + var->vec4[1] = atof(com_token); + str = COM_Parse(str); + var->vec4[2] = atof(com_token); + if (!str || !*str) + var->vec4[3] = 1; + else + { + str = COM_Parse(str); + var->vec4[3] = atof(com_token); + } + } + if (latch) { if (strcmp(latch, value)) @@ -1364,7 +1380,7 @@ void Cvar_WriteVariables (vfsfile_t *f, qboolean all) } } -void Cvar_Hook(cvar_t *cvar, void (*callback) (struct cvar_s *var, char *oldvalue)) +void Cvar_Hook(cvar_t *cvar, void (QDECL *callback) (struct cvar_s *var, char *oldvalue)) { cvar->callback = callback; } @@ -1398,7 +1414,7 @@ void Cvar_ApplyCallbacks(int callbackflag) } // standard callbacks -void Cvar_Limiter_ZeroToOne_Callback(struct cvar_s *var, char *oldvalue) +void QDECL Cvar_Limiter_ZeroToOne_Callback(struct cvar_s *var, char *oldvalue) { if (var->value > 1) { diff --git a/engine/common/cvar.h b/engine/common/cvar.h index 520a45f88..9d5e98e42 100644 --- a/engine/common/cvar.h +++ b/engine/common/cvar.h @@ -69,13 +69,14 @@ typedef struct cvar_s //free style :) char *name2; - void (*callback) (struct cvar_s *var, char *oldvalue); + void (QDECL *callback) (struct cvar_s *var, char *oldvalue); char *description; char *enginevalue; //when changing manifest dir, the cvar will be reset to this value. never freed. char *defaultstr; //this is the current mod's default value. set on first update. int ival; + vec4_t vec4; //0,0,0,1 if something didn't parse. qbyte restriction; #ifdef HLSERVER @@ -174,7 +175,7 @@ void Cvar_ConfigChanged(void); int Cvar_ApplyLatches(int latchflag); //sets vars to their latched values -void Cvar_Hook(cvar_t *cvar, void (*callback) (struct cvar_s *var, char *oldvalue)); +void Cvar_Hook(cvar_t *cvar, void (QDECL *callback) (struct cvar_s *var, char *oldvalue)); //hook a cvar with a given callback function at runtime void Cvar_Unhook(cvar_t *cvar); @@ -186,7 +187,7 @@ void Cvar_ForceCallback(cvar_t *cvar); void Cvar_ApplyCallbacks(int callbackflag); //forces callbacks to be ran for given flags -void Cvar_Limiter_ZeroToOne_Callback(struct cvar_s *var, char *oldvalue); +void QDECL Cvar_Limiter_ZeroToOne_Callback(struct cvar_s *var, char *oldvalue); //cvar callback to limit cvar value to 0 or 1 float Cvar_VariableValue (const char *var_name); diff --git a/engine/common/fs.c b/engine/common/fs.c index 6fa97cafc..493bc84d0 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -12,7 +12,7 @@ #include "winquake.h" #endif -static void fs_game_callback(cvar_t *var, char *oldvalue); +static void QDECL fs_game_callback(cvar_t *var, char *oldvalue); hashtable_t filesystemhash; qboolean com_fschanged = true; qboolean com_installer = false; @@ -31,7 +31,7 @@ static int fs_referencetype; int fs_finds; void COM_CheckRegistered (void); -static void fs_game_callback(cvar_t *var, char *oldvalue) +static void QDECL fs_game_callback(cvar_t *var, char *oldvalue) { static qboolean runaway = false; char buf[MAX_OSPATH]; @@ -4209,9 +4209,15 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean confpath[i] = loc.search?loc.search->handle:NULL; } +#if defined(NACL) || defined(FTE_TARGET_WEB) || defined(ANDROID) || defined(WINRT) + //these targets are considered to be sandboxed already, and have their own app-based base directory which they will always use. + Q_strncpyz (newbasedir, host_parms.basedir, sizeof(newbasedir)); + fixedbasedir = true; +#else i = COM_CheckParm ("-basedir"); fixedbasedir = i && i < com_argc-1; Q_strncpyz (newbasedir, fixedbasedir?com_argv[i+1]:host_parms.basedir, sizeof(newbasedir)); +#endif //make sure it has a trailing slash, or is empty. woo. FS_CleanDir(newbasedir, sizeof(newbasedir)); @@ -4409,7 +4415,7 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean #endif { - void (*callback)(struct cvar_s *var, char *oldvalue) = fs_game.callback; + void (QDECL *callback)(struct cvar_s *var, char *oldvalue) = fs_game.callback; fs_game.callback = NULL; Cvar_ForceSet(&fs_game, FS_GetGamedir(false)); fs_game.callback = callback; diff --git a/engine/common/log.c b/engine/common/log.c index ef3df4990..69878a338 100644 --- a/engine/common/log.c +++ b/engine/common/log.c @@ -3,8 +3,8 @@ #include "quakedef.h" // cvar callbacks -void Log_Dir_Callback (struct cvar_s *var, char *oldvalue); -void Log_Name_Callback (struct cvar_s *var, char *oldvalue); +static void QDECL Log_Dir_Callback (struct cvar_s *var, char *oldvalue); +static void QDECL Log_Name_Callback (struct cvar_s *var, char *oldvalue); // cvars #define CONLOGGROUP "Console logging" @@ -32,7 +32,7 @@ qboolean log_newline[LOG_TYPES]; extern char gamedirfile[]; // Log_Dir_Callback: called when a log_dir is changed -void Log_Dir_Callback (struct cvar_s *var, char *oldvalue) +static void QDECL Log_Dir_Callback (struct cvar_s *var, char *oldvalue) { char *t = var->string; char *e = t + (*t?strlen(t):0); @@ -47,7 +47,7 @@ void Log_Dir_Callback (struct cvar_s *var, char *oldvalue) } // Log_Name_Callback: called when a log_name is changed -void Log_Name_Callback (struct cvar_s *var, char *oldvalue) +static void QDECL Log_Name_Callback (struct cvar_s *var, char *oldvalue) { char *t = var->string; diff --git a/engine/common/net_wins.c b/engine/common/net_wins.c index f6c99ad0b..1ae5e9e82 100644 --- a/engine/common/net_wins.c +++ b/engine/common/net_wins.c @@ -5540,7 +5540,7 @@ qboolean NET_WasSpecialPacket(netsrc_t netsrc) return false; } -void NET_UPNPIGP_Callback(cvar_t *var, char *oldval) +static void QDECL NET_UPNPIGP_Callback(cvar_t *var, char *oldval) { } cvar_t net_upnpigp = CVARCD("net_upnpigp", "0", NET_UPNPIGP_Callback, "If set, enables the use of the upnp-igd protocol to punch holes in your local NAT box."); @@ -5642,42 +5642,42 @@ void NET_InitClient(void) #ifndef CLIENTONLY #ifdef HAVE_IPV4 -void SV_Tcpport_Callback(struct cvar_s *var, char *oldvalue) +void QDECL SV_Tcpport_Callback(struct cvar_s *var, char *oldvalue) { FTENET_AddToCollection(svs.sockets, var->name, var->string, NA_TCP, true); } cvar_t sv_port_tcp = CVARC("sv_port_tcp", "", SV_Tcpport_Callback); #endif #ifdef IPPROTO_IPV6 -void SV_Tcpport6_Callback(struct cvar_s *var, char *oldvalue) +void QDECL SV_Tcpport6_Callback(struct cvar_s *var, char *oldvalue) { FTENET_AddToCollection(svs.sockets, var->name, var->string, NA_TCPV6, true); } cvar_t sv_port_tcp6 = CVARC("sv_port_tcp6", "", SV_Tcpport6_Callback); #endif #ifdef HAVE_IPV4 -void SV_Port_Callback(struct cvar_s *var, char *oldvalue) +void QDECL SV_Port_Callback(struct cvar_s *var, char *oldvalue) { FTENET_AddToCollection(svs.sockets, var->name, var->string, NA_IP, true); } cvar_t sv_port_ipv4 = CVARC("sv_port", STRINGIFY(PORT_QWSERVER), SV_Port_Callback); #endif #ifdef IPPROTO_IPV6 -void SV_PortIPv6_Callback(struct cvar_s *var, char *oldvalue) +void QDECL SV_PortIPv6_Callback(struct cvar_s *var, char *oldvalue) { FTENET_AddToCollection(svs.sockets, var->name, var->string, NA_IPV6, true); } cvar_t sv_port_ipv6 = CVARC("sv_port_ipv6", "", SV_PortIPv6_Callback); #endif #ifdef USEIPX -void SV_PortIPX_Callback(struct cvar_s *var, char *oldvalue) +void QDECL SV_PortIPX_Callback(struct cvar_s *var, char *oldvalue) { FTENET_AddToCollection(svs.sockets, var->name, var->string, NA_IPX, true); } cvar_t sv_port_ipx = CVARC("sv_port_ipx", "", SV_PortIPX_Callback); #endif #ifdef HAVE_NATPMP -void SV_Port_NatPMP_Callback(struct cvar_s *var, char *oldvalue) +void QDECL SV_Port_NatPMP_Callback(struct cvar_s *var, char *oldvalue) { FTENET_AddToCollection(svs.sockets, var->name, va("natpmp://%s", var->string), NA_NATPMP, true); } diff --git a/engine/common/plugin.c b/engine/common/plugin.c index 6d1b1c763..6da84dfda 100644 --- a/engine/common/plugin.c +++ b/engine/common/plugin.c @@ -514,6 +514,8 @@ static qintptr_t VARGS Plug_Cvar_GetNVFDG(void *offset, quintptr_t mask, const q char *description = VM_POINTER(arg[3]); char *groupname = VM_POINTER(arg[4]); + if (!defaultvalue) + return (qintptr_t)Cvar_FindVar(name); return (qintptr_t)Cvar_Get2(name, defaultvalue, flags&1, description, groupname); } @@ -1463,7 +1465,8 @@ void Plug_Tick(void) { if (currentplug->tick) { - VM_Call(currentplug->vm, currentplug->tick, (int)(realtime*1000)); + float rt = realtime, st = cl.time; + VM_Call(currentplug->vm, currentplug->tick, (int)(realtime*1000), *(int*)&(rt), *(int*)&(st)); } } currentplug = oldplug; @@ -1629,7 +1632,7 @@ void Plug_SBar(playerview_t *pv) return; ret = 0; - if (!plug_sbar.ival || cl.splitclients > 1) + if (!plug_sbar.ival) currentplug = NULL; else { @@ -1639,7 +1642,7 @@ void Plug_SBar(playerview_t *pv) { //if you don't use splitscreen, use a full videosize rect. R2D_ImageColours(1, 1, 1, 1); // ensure menu colors are reset - ret |= VM_Call(currentplug->vm, currentplug->sbarlevel[0], pv-cl.playerview, r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height, sb_showscores+sb_showteamscores*2); + ret |= VM_Call(currentplug->vm, currentplug->sbarlevel[0], pv-cl.playerview, (int)r_refdef.vrect.x, (int)r_refdef.vrect.y, (int)r_refdef.vrect.width, (int)r_refdef.vrect.height, sb_showscores+sb_showteamscores*2); break; } } diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c index b78f752d1..817b0730a 100644 --- a/engine/common/pr_bgcmd.c +++ b/engine/common/pr_bgcmd.c @@ -4006,6 +4006,7 @@ void QCBUILTIN PF_uri_get (pubprogfuncs_t *prinst, struct globalvars_s *pr_glob dl->user_ctx = w; dl->user_float = id; dl->user_num = *w->g.self; + dl->isquery = true; G_FLOAT(OFS_RETURN) = 1; } else diff --git a/engine/common/q3common.c b/engine/common/q3common.c index f5e8cbd97..9b3433275 100644 --- a/engine/common/q3common.c +++ b/engine/common/q3common.c @@ -128,9 +128,9 @@ int VM_FRead (char *dest, int quantity, int fnum, int owner) return quantity; } -/* -void VM_fputs (progfuncs_t *prinst, struct globalvars_s *pr_globals) +int VM_FWrite (char *dest, int quantity, int fnum, int owner) { +/* int fnum = G_FLOAT(OFS_PARM0); char *msg = PF_VarString(prinst, 1, pr_globals); int len = strlen(msg); @@ -157,8 +157,49 @@ void VM_fputs (progfuncs_t *prinst, struct globalvars_s *pr_globals) if (pf_fopen_files[fnum].len < pf_fopen_files[fnum].ofs + len) pf_fopen_files[fnum].len = pf_fopen_files[fnum].ofs + len; pf_fopen_files[fnum].ofs+=len; -} */ + return 0; +} +void VM_FSeek (int fnum, int offset, int seektype, int owner) +{ + fnum--; + if (fnum < 0 || fnum >= MAX_VM_FILES) + return; //out of range + if (vm_fopen_files[fnum].owner != owner) + return; //cgs? + if (!vm_fopen_files[fnum].data) + return; //not open + + switch(seektype) + { + case 0: + offset = vm_fopen_files[fnum].ofs + offset; + case 1: + offset = vm_fopen_files[fnum].len + offset; + break; + default: + case 2: + offset = offset; + break; + } + if (offset < 0) + offset = 0; + if (offset > vm_fopen_files[fnum].len) + offset = vm_fopen_files[fnum].len; + vm_fopen_files[fnum].ofs = offset; +} +int VM_FTell (int fnum, int owner) +{ + fnum--; + if (fnum < 0 || fnum >= MAX_VM_FILES) + return 0; //out of range + if (vm_fopen_files[fnum].owner != owner) + return 0; //cgs? + if (!vm_fopen_files[fnum].data) + return 0; //not open + + return vm_fopen_files[fnum].ofs; +} void VM_fcloseall (int owner) { int i; diff --git a/engine/common/translate.c b/engine/common/translate.c index 16386ca83..e29675c95 100644 --- a/engine/common/translate.c +++ b/engine/common/translate.c @@ -12,7 +12,7 @@ char sys_language[64] = ""; struct language_s languages[MAX_LANGUAGES]; -void TL_LanguageChanged(struct cvar_s *var, char *oldvalue) +static void QDECL TL_LanguageChanged(struct cvar_s *var, char *oldvalue) { #ifndef CLIENTONLY svs.language = TL_FindLanguage(var->string); diff --git a/engine/common/vm.h b/engine/common/vm.h index a7139c4f6..cac2787e9 100644 --- a/engine/common/vm.h +++ b/engine/common/vm.h @@ -130,6 +130,9 @@ void Script_Get_File_And_Line(int handle, char *filename, int *line); #define VM_FS_APPEND2 3 //I don't know, don't ask me. look at q3 source int VM_fopen (char *name, int *handle, int fmode, int owner); int VM_FRead (char *dest, int quantity, int fnum, int owner); +int VM_FWrite (char *dest, int quantity, int fnum, int owner); +void VM_FSeek (int fnum, int offset, int seektype, int owner); +int VM_FTell (int fnum, int owner); void VM_fclose (int fnum, int owner); void VM_fcloseall (int owner); int VM_GetFileList(char *path, char *ext, char *output, int buffersize); diff --git a/engine/dotnet2005/ftequake.sln b/engine/dotnet2005/ftequake.sln index 8c26b4b56..3abda8a27 100644 --- a/engine/dotnet2005/ftequake.sln +++ b/engine/dotnet2005/ftequake.sln @@ -56,6 +56,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bulletplug", "..\..\plugins EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "odeplug", "..\..\plugins\odeplug\odeplug.vcproj", "{ED16B405-BDCD-4EB8-BF70-761964301368}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ezhud", "..\..\plugins\ezhud\ezhud.vcproj", "{E475BFF0-6766-48BA-BE44-931C068AC5B0}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution D3DDebug|Win32 = D3DDebug|Win32 @@ -736,6 +738,42 @@ Global {ED16B405-BDCD-4EB8-BF70-761964301368}.Release|Win32.ActiveCfg = Release|Win32 {ED16B405-BDCD-4EB8-BF70-761964301368}.Release|Win32.Build.0 = Release|Win32 {ED16B405-BDCD-4EB8-BF70-761964301368}.Release|x64.ActiveCfg = Release|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.D3DDebug|Win32.ActiveCfg = Debug|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.D3DDebug|Win32.Build.0 = Debug|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.D3DDebug|x64.ActiveCfg = Debug|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.D3DRelease|Win32.ActiveCfg = Release|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.D3DRelease|Win32.Build.0 = Release|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.D3DRelease|x64.ActiveCfg = Release|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.Debug Dedicated Server|Win32.ActiveCfg = Debug|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.Debug Dedicated Server|Win32.Build.0 = Debug|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.Debug Dedicated Server|x64.ActiveCfg = Debug|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.Debug|Win32.ActiveCfg = Debug|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.Debug|Win32.Build.0 = Debug|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.Debug|x64.ActiveCfg = Debug|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.GLDebug|Win32.ActiveCfg = Debug|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.GLDebug|Win32.Build.0 = Debug|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.GLDebug|x64.ActiveCfg = Debug|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.GLRelease|Win32.ActiveCfg = Release|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.GLRelease|Win32.Build.0 = Release|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.GLRelease|x64.ActiveCfg = Release|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.MDebug|Win32.ActiveCfg = Debug|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.MDebug|Win32.Build.0 = Debug|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.MDebug|x64.ActiveCfg = Debug|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.MinGLDebug|Win32.ActiveCfg = Debug|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.MinGLDebug|Win32.Build.0 = Debug|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.MinGLDebug|x64.ActiveCfg = Debug|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.MinGLRelease|Win32.ActiveCfg = Release|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.MinGLRelease|Win32.Build.0 = Release|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.MinGLRelease|x64.ActiveCfg = Release|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.MRelease|Win32.ActiveCfg = Release|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.MRelease|Win32.Build.0 = Release|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.MRelease|x64.ActiveCfg = Release|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.Release Dedicated Server|Win32.ActiveCfg = Release|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.Release Dedicated Server|Win32.Build.0 = Release|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.Release Dedicated Server|x64.ActiveCfg = Release|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.Release|Win32.ActiveCfg = Release|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.Release|Win32.Build.0 = Release|Win32 + {E475BFF0-6766-48BA-BE44-931C068AC5B0}.Release|x64.ActiveCfg = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -755,6 +793,7 @@ Global {74542CA7-48C1-4664-9007-66F751131EA3} = {8CED01C6-2C61-4EC5-90B6-574D9756D773} {82285268-9C3B-44AD-BBE7-40670F9D2628} = {8CED01C6-2C61-4EC5-90B6-574D9756D773} {ED16B405-BDCD-4EB8-BF70-761964301368} = {8CED01C6-2C61-4EC5-90B6-574D9756D773} + {E475BFF0-6766-48BA-BE44-931C068AC5B0} = {8CED01C6-2C61-4EC5-90B6-574D9756D773} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution AMDCaProjectFile = C:\Games\Quake\wip\engine\dotnet2005\CodeAnalyst\ftequake.caw diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c index 7130fd340..a9bc0b9f5 100644 --- a/engine/gl/gl_draw.c +++ b/engine/gl/gl_draw.c @@ -390,6 +390,12 @@ qboolean GL_LoadTextureMips(texid_t tex, struct pendingtextureinfo *mips) } switch(mips->encoding) { +#ifdef FTE_TARGET_WEB + case PTI_WHOLEFILE: + if (!i) + emscriptenfte_gl_loadtexturefile(tex->num, &tex->width, &tex->height, mips->mip[i].data, mips->mip[i].datasize); + break; +#endif case PTI_DEPTH16: qglTexImage2D(targface, j, gl_config.gles?GL_DEPTH_COMPONENT:GL_DEPTH_COMPONENT16_ARB, mips->mip[i].width, mips->mip[i].height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, mips->mip[i].data); break; diff --git a/engine/gl/gl_draw.h b/engine/gl/gl_draw.h index 1b7a9bf63..b9a866966 100644 --- a/engine/gl/gl_draw.h +++ b/engine/gl/gl_draw.h @@ -30,6 +30,7 @@ mpic_t *R2D_SafeCachePic (const char *path); mpic_t *R2D_SafePicFromWad (const char *name); void R2D_ImageColours(float r, float g, float b, float a); void R2D_Image(float x, float y, float w, float h, float s1, float t1, float s2, float t2, mpic_t *pic); +void R2D_Line(float x1, float y1, float x2, float y2, mpic_t *pic); void R2D_ScalePic (float x, float y, float width, float height, mpic_t *pic); void R2D_SubPic(float x, float y, float width, float height, mpic_t *pic, float srcx, float srcy, float srcwidth, float srcheight); void R2D_ConsoleBackground (int firstline, int lastline, qboolean forceopaque); @@ -42,4 +43,4 @@ void R2D_Shutdown(void); void R2D_PolyBlend (void); void R2D_BrightenScreen (void); -void R2D_Conback_Callback(struct cvar_s *var, char *oldvalue); +void QDECL R2D_Conback_Callback(struct cvar_s *var, char *oldvalue); diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index 874892626..2c541d081 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -4345,7 +4345,7 @@ void QDECL R_BuildLegacyTexnums(shader_t *shader, const char *fallbackname, cons extern cvar_t r_shadow_bumpscale_basetexture; if (!TEXVALID(tex->bump) && *shader->mapname) tex->bump = R_LoadHiResTexture(va("%s_norm", shader->mapname), NULL, imageflags|IF_TRYBUMP); - if (!TEXVALID(tex->bump)) + if (!TEXVALID(tex->bump) && (r_shadow_bumpscale_basetexture.ival||*imagename=='*'||gl_load24bit.ival)) tex->bump = Image_GetTexture(va("%s_norm", imagename), subpath, imageflags|IF_TRYBUMP, (r_shadow_bumpscale_basetexture.ival||*imagename=='*')?mipdata[0]:NULL, palette, width, height, TF_HEIGHT8PAL); } diff --git a/engine/gl/gl_vidnt.c b/engine/gl/gl_vidnt.c index 25b1e9185..baf3d0dcb 100644 --- a/engine/gl/gl_vidnt.c +++ b/engine/gl/gl_vidnt.c @@ -1480,7 +1480,7 @@ qboolean VID_AttachGL (rendererstate_t *info) return true; } -void VID_Wait_Override_Callback(struct cvar_s *var, char *oldvalue) +static void QDECL VID_Wait_Override_Callback(struct cvar_s *var, char *oldvalue) { if (qwglSwapIntervalEXT && *vid_vsync.string) qwglSwapIntervalEXT(vid_vsync.value); @@ -1524,7 +1524,7 @@ void GLVID_Recenter_f(void) } } -void VID_WndAlpha_Override_Callback(struct cvar_s *var, char *oldvalue) +static void QDECL VID_WndAlpha_Override_Callback(struct cvar_s *var, char *oldvalue) { //this code tells windows to use the alpha channel of the screen, but does really nasty things with the mouse such that its unplayable. //its not useful. @@ -2109,6 +2109,7 @@ LONG WINAPI GLMainWndProc ( { COPYDATASTRUCT *cds = (COPYDATASTRUCT*)lParam; Host_RunFile(cds->lpData, cds->cbData, NULL); + lRet = 1; } break; case WM_KILLFOCUS: @@ -2234,7 +2235,10 @@ LONG WINAPI GLMainWndProc ( case WM_INPUT: // raw input handling if (!vid_initializing) + { INS_RawInput_Read((HANDLE)lParam); + lRet = 0; + } break; case WM_USER: diff --git a/engine/http/httpclient.c b/engine/http/httpclient.c index 242f1f869..3c229fc18 100644 --- a/engine/http/httpclient.c +++ b/engine/http/httpclient.c @@ -1097,6 +1097,10 @@ qboolean DL_Decide(struct dl_download *dl) #endif /*!defined(NACL)*/ #ifdef MULTITHREAD +static void HTTP_Wake_Think(void *ctx, void *data, size_t a, size_t b) +{ + HTTP_CL_Think(); +} static int DL_Thread_Work(void *arg) { struct dl_download *dl = arg; @@ -1118,6 +1122,9 @@ static int DL_Thread_Work(void *arg) break; } } + + COM_AddWork(0, HTTP_Wake_Think, NULL, NULL, 0, 0); + return 0; } @@ -1207,7 +1214,7 @@ struct dl_download *HTTP_CL_Get(const char *url, const char *localfile, void (*N activedownloads = newdl; - if (!cls.download && localfile) + if (!cls.download && localfile && !newdl->isquery) { cls.download = &newdl->qdownload; newdl->qdownload.method = DL_HTTP; @@ -1269,7 +1276,7 @@ void HTTP_CL_Think(void) } link = &dl->next; - if (!cls.download) + if (!cls.download && !dl->isquery) { cls.download = &dl->qdownload; dl->qdownload.method = DL_HTTP; diff --git a/engine/http/iweb.h b/engine/http/iweb.h index 1ee88d70e..183b153b6 100644 --- a/engine/http/iweb.h +++ b/engine/http/iweb.h @@ -103,6 +103,7 @@ struct dl_download unsigned int user_num; float user_float; void *user_ctx; + qboolean isquery; //will not be displayed in the download/progress bar stuff. qdownload_t qdownload; diff --git a/engine/qclib/qccmain.c b/engine/qclib/qccmain.c index ed83d48c6..d0a58430c 100644 --- a/engine/qclib/qccmain.c +++ b/engine/qclib/qccmain.c @@ -2243,7 +2243,7 @@ int QCC_PR_FinishCompilation (void) { //not all of these will have a class defined, as some will be regular spawn functions, so don't error on that t = QCC_TypeForName(d->name+10); - if (t) + if (t && t->type == ev_entity) { QCC_PR_EmitClassFromFunction(d, t); pr_scope = NULL; @@ -2354,7 +2354,7 @@ char *Sva(char *msg, ...) #define PROGDEFS_MAX_SIZE 16384 //write (to file buf) and add to the crc -static void Add(char *p, unsigned short *crc, char *file) +static void Add_WithCRC(char *p, unsigned short *crc, char *file) { char *s; int i = strlen(file); @@ -2367,20 +2367,20 @@ static void Add(char *p, unsigned short *crc, char *file) } file[i]='\0'; } -#define ADD(p) Add(p, &crc, file) +#define ADD_CRC(p) Add_WithCRC(p, &crc, file) //#define ADD(p) {char *s;int i = strlen(p);for(s=p;*s;s++,i++){QCC_CRC_ProcessByte(&crc, *s);file[i] = *s;}file[i]='\0';} -static void Add3(char *p, unsigned short *crc, char *file) +static void Add_CrcOnly(char *p, unsigned short *crc, char *file) { char *s; for(s=p;*s;s++) QCC_CRC_ProcessByte(crc, *s); } -#define ADD3(p) Add3(p, &crc, file) +#define EAT_CRC(p) Add_CrcOnly(p, &crc, file) unsigned short QCC_PR_WriteProgdefs (char *filename) { -#define ADD2(p) QC_strlcat(file, p, sizeof(file)) //no crc (later changes) +#define ADD_ONLY(p) QC_strlcat(file, p, sizeof(file)) //no crc (later changes) char file[PROGDEFS_MAX_SIZE]; QCC_def_t *d; int f; @@ -2393,20 +2393,16 @@ unsigned short QCC_PR_WriteProgdefs (char *filename) // print global vars until the first field is defined - //ADD: crc and dump - //ADD2: dump but don't crc - //ADD3: crc but don't dump - - ADD("\n/* "); + ADD_CRC("\n/* "); if (qcc_targetformat == QCF_HEXEN2 || qcc_targetformat == QCF_FTEH2) - ADD3("generated by hcc, do not modify"); + EAT_CRC("generated by hcc, do not modify"); else - ADD3("file generated by qcc, do not modify"); - ADD2("File generated by FTEQCC, relevent for engine modding only, the generated crc must be the same as your engine expects."); - ADD(" */\n\ntypedef struct"); - ADD2(" globalvars_s"); - ADD(qcva("\n{")); - ADD2("\tint pad;\n" + EAT_CRC("file generated by qcc, do not modify"); + ADD_ONLY("File generated by FTEQCC, relevent for engine modding only, the generated crc must be the same as your engine expects."); + ADD_CRC(" */\n\ntypedef struct"); + ADD_ONLY(" globalvars_s"); + ADD_CRC(qcva("\n{")); + ADD_ONLY("\tint pad;\n" "\tint ofs_return[3];\n" //makes it easier with the get globals func "\tint ofs_parm0[3];\n" "\tint ofs_parm1[3];\n" @@ -2416,7 +2412,7 @@ unsigned short QCC_PR_WriteProgdefs (char *filename) "\tint ofs_parm5[3];\n" "\tint ofs_parm6[3];\n" "\tint ofs_parm7[3];\n"); - ADD3(qcva("\tint\tpad[%i];\n", RESERVED_OFS)); + EAT_CRC(qcva("\tint\tpad[%i];\n", RESERVED_OFS)); for (d=pr.def_head.next ; d ; d=d->next) { if (!strcmp (d->name, "end_sys_globals")) @@ -2427,36 +2423,36 @@ unsigned short QCC_PR_WriteProgdefs (char *filename) switch (d->type->type) { case ev_float: - ADD(qcva("\tfloat\t%s;\n",d->name)); + ADD_CRC(qcva("\tfloat\t%s;\n",d->name)); break; case ev_vector: - ADD(qcva("\tvec3_t\t%s;\n",d->name)); + ADD_CRC(qcva("\tvec3_t\t%s;\n",d->name)); if (d->deftail) d=d->deftail; // skip the elements break; case ev_string: - ADD(qcva("\tstring_t\t%s;\n",d->name)); + ADD_CRC(qcva("\tstring_t\t%s;\n",d->name)); break; case ev_function: - ADD(qcva("\tfunc_t\t%s;\n",d->name)); + ADD_CRC(qcva("\tfunc_t\t%s;\n",d->name)); break; case ev_entity: - ADD(qcva("\tint\t%s;\n",d->name)); + ADD_CRC(qcva("\tint\t%s;\n",d->name)); break; case ev_integer: - ADD(qcva("\tint\t%s;\n",d->name)); + ADD_CRC(qcva("\tint\t%s;\n",d->name)); break; default: - ADD(qcva("\tint\t%s;\n",d->name)); + ADD_CRC(qcva("\tint\t%s;\n",d->name)); break; } } - ADD("} globalvars_t;\n\n"); + ADD_CRC("} globalvars_t;\n\n"); // print all fields - ADD("typedef struct"); - ADD2(" entvars_s"); - ADD("\n{\n"); + ADD_CRC("typedef struct"); + ADD_ONLY(" entvars_s"); + ADD_CRC("\n{\n"); for (d=pr.def_head.next ; d ; d=d->next) { if (!strcmp (d->name, "end_sys_fields")) @@ -2468,35 +2464,35 @@ unsigned short QCC_PR_WriteProgdefs (char *filename) switch (d->type->aux_type->type) { case ev_float: - ADD(qcva("\tfloat\t%s;\n",d->name)); + ADD_CRC(qcva("\tfloat\t%s;\n",d->name)); break; case ev_vector: - ADD(qcva("\tvec3_t\t%s;\n",d->name)); + ADD_CRC(qcva("\tvec3_t\t%s;\n",d->name)); if (d->deftail) d=d->deftail; // skip the elements break; case ev_string: - ADD(qcva("\tstring_t\t%s;\n",d->name)); + ADD_CRC(qcva("\tstring_t\t%s;\n",d->name)); break; case ev_function: - ADD(qcva("\tfunc_t\t%s;\n",d->name)); + ADD_CRC(qcva("\tfunc_t\t%s;\n",d->name)); break; case ev_entity: - ADD(qcva("\tint\t%s;\n",d->name)); + ADD_CRC(qcva("\tint\t%s;\n",d->name)); break; case ev_integer: - ADD(qcva("\tint\t%s;\n",d->name)); + ADD_CRC(qcva("\tint\t%s;\n",d->name)); break; default: - ADD(qcva("\tint\t%s;\n",d->name)); + ADD_CRC(qcva("\tint\t%s;\n",d->name)); break; } } - ADD("} entvars_t;\n\n"); + ADD_CRC("} entvars_t;\n\n"); /* ///temp - ADD2("//with this the crc isn't needed for fields.\n#ifdef FIELDSSTRUCT\nstruct fieldvars_s {\n\tint ofs;\n\tint type;\n\tchar *name;\n} fieldvars[] = {\n"); + ADD_ONLY("//with this the crc isn't needed for fields.\n#ifdef FIELDSSTRUCT\nstruct fieldvars_s {\n\tint ofs;\n\tint type;\n\tchar *name;\n} fieldvars[] = {\n"); f=0; for (d=pr.def_head.next ; d ; d=d->next) { @@ -2506,15 +2502,15 @@ unsigned short QCC_PR_WriteProgdefs (char *filename) if (d->type->type != ev_field) continue; if (f) - ADD2(",\n"); - ADD2(qcva("\t{%i,\t%i,\t\"%s\"}",G_INT(d->ofs), d->type->aux_type->type, d->name)); + ADD_ONLY(",\n"); + ADD_ONLY(qcva("\t{%i,\t%i,\t\"%s\"}",G_INT(d->ofs), d->type->aux_type->type, d->name)); f = 1; } - ADD2("\n};\n#endif\n\n"); + ADD_ONLY("\n};\n#endif\n\n"); //end temp */ - ADD2(qcva("#define PROGHEADER_CRC %i\n", crc)); + ADD_ONLY(qcva("#define PROGHEADER_CRC %i\n", crc)); if (QCC_CheckParm("-progdefs")) { diff --git a/engine/server/pr_q1qvm.c b/engine/server/pr_q1qvm.c index 28ec65bf5..7266ba8fe 100755 --- a/engine/server/pr_q1qvm.c +++ b/engine/server/pr_q1qvm.c @@ -132,7 +132,7 @@ typedef enum g_acos, //55 G_CMD_ARGC, G_CMD_ARGV, - G_TraceCapsule, + G_TraceBox, //was G_TraceCapsule G_FS_OpenFile, G_FS_CloseFile, //60 G_FS_ReadFile, @@ -340,7 +340,7 @@ typedef enum { static const char *q1qvmentstring; static vm_t *q1qvm; static pubprogfuncs_t q1qvmprogfuncs; -static edict_t *q1qvmedicts[MAX_Q1QVM_EDICTS]; +static edict_t **q1qvmedicttable; static void *evars; //pointer to the gamecodes idea of an edict_t @@ -366,10 +366,10 @@ static edict_t *QDECL Q1QVMPF_EdictNum(pubprogfuncs_t *pf, unsigned int num) if (/*num < 0 ||*/ num >= sv.world.max_edicts) return NULL; - e = q1qvmedicts[num]; + e = q1qvmedicttable[num]; if (!e) { - e = q1qvmedicts[num] = Z_TagMalloc(sizeof(edict_t)+sizeof(extentvars_t), VMFSID_Q1QVM); + e = q1qvmedicttable[num] = Z_TagMalloc(sizeof(edict_t)+sizeof(extentvars_t), VMFSID_Q1QVM); e->v = (stdentvars_t*)((char*)evars + (num * sv.world.edict_size) + WASTED_EDICT_T_SIZE); e->xv = (extentvars_t*)(e+1); e->entnum = num; @@ -518,7 +518,7 @@ static int WrapQCBuiltin(builtin_t func, void *offset, quintptr_t mask, const qi gv.param[argnum++].f = VM_FLOAT(*arg++); break; case 'i': - gv.param[argnum++].f = VM_LONG(*arg++); + gv.param[argnum++].f = VM_LONG(*arg++); //vanilla qc does not support ints, but qvms do. this means ints need to be converted to floats for the builtin to understand them properly. break; case 'n': //ent num gv.param[argnum++].i = EDICT_TO_PROG(svprogfuncs, Q1QVMPF_EdictNum(svprogfuncs, VM_LONG(*arg++))); @@ -583,7 +583,7 @@ static qintptr_t syscallhandle (void *offset, quintptr_t mask, qintptr_t fn, con case G_REMOVE_ENT: if (arg[0] >= sv.world.max_edicts) return false; - Q1QVMPF_EntRemove(svprogfuncs, q1qvmedicts[arg[0]]); + Q1QVMPF_EntRemove(svprogfuncs, q1qvmedicttable[arg[0]]); return true; case G_PRECACHE_SOUND: @@ -949,7 +949,7 @@ static qintptr_t syscallhandle (void *offset, quintptr_t mask, qintptr_t fn, con } break; - case G_TraceCapsule: + case G_TraceBox: WrapQCBuiltin(PF_svtraceline, offset, mask, arg, "vvinvv"); break; @@ -991,22 +991,17 @@ static qintptr_t syscallhandle (void *offset, quintptr_t mask, qintptr_t fn, con if (VM_OOB(arg[0], arg[1])) return 0; return VM_FRead(VM_POINTER(arg[0]), VM_LONG(arg[1]), VM_LONG(arg[2]), VMFSID_Q1QVM); -/* + //not supported, open will fail anyway case G_FS_WriteFile: + if (VM_OOB(arg[0], arg[1])) + return 0; return VM_FWrite(VM_POINTER(arg[0]), VM_LONG(arg[1]), VM_LONG(arg[2]), VMFSID_Q1QVM); - break; -*/ -/* case G_FS_SeekFile: -// int trap_FS_SeekFile( fileHandle_t handle, int offset, int type ) - return VM_FSeek(VM_LONG(arg[0]), VM_LONG(arg[1]), VM_LONG(arg[2])); - break; -*/ -/* + VM_FSeek(VM_LONG(arg[0]), VM_LONG(arg[1]), VM_LONG(arg[2]), VMFSID_Q1QVM); + return 0; case G_FS_TellFile: - break; -*/ + return VM_FTell(VM_LONG(arg[0]), VMFSID_Q1QVM); case G_FS_GetFileList: if (VM_OOB(arg[2], arg[3])) @@ -1089,7 +1084,7 @@ static qintptr_t syscallhandle (void *offset, quintptr_t mask, qintptr_t fn, con match = ""; for (i = first+1; i < sv.world.num_edicts; i++) { - e = q1qvmedicts[i]; + e = q1qvmedicttable[i]; field = VM_POINTER(*((string_t*)e->v + ofs/4)); if (field == NULL) { @@ -1321,6 +1316,11 @@ void Q1QVM_Shutdown(void) if (svprogfuncs == &q1qvmprogfuncs) sv.world.progs = svprogfuncs = NULL; Z_FreeTags(VMFSID_Q1QVM); + if (q1qvmedicttable) + { + Z_Free(q1qvmedicttable); + q1qvmedicttable = NULL; + } } } @@ -1368,9 +1368,16 @@ qboolean PR_LoadQ1QVM(void) gameDataN_t *gd, gdm; gameData32_t *gd32; qintptr_t ret; + qintptr_t limit; + extern cvar_t pr_maxedicts; if (q1qvm) VM_Destroy(q1qvm); + if (q1qvmedicttable) + { + Z_Free(q1qvmedicttable); + q1qvmedicttable = NULL; + } q1qvm = VM_Create("qwprogs", com_nogamedirnativecode.ival?NULL:syscallnative, syscallqvm); if (!q1qvm) @@ -1412,7 +1419,7 @@ qboolean PR_LoadQ1QVM(void) sv.world.max_edicts = 0; //so clear these out, just in case sv.world.edict_size = 0; //if we get a division by zero, then at least its a safe crash - memset(q1qvmedicts, 0, sizeof(q1qvmedicts)); + q1qvmedicttable = NULL; q1qvmprogfuncs.stringtable = VM_MemoryBase(q1qvm); @@ -1441,14 +1448,26 @@ qboolean PR_LoadQ1QVM(void) gd = (gameDataN_t*)((char*)VM_MemoryBase(q1qvm) + ret); //qvm is 32bit } + sv.world.num_edicts = 1; + sv.world.max_edicts = bound(64, pr_maxedicts.ival, MAX_EDICTS); + q1qvmedicttable = Z_Malloc(sizeof(*q1qvmedicttable) * sv.world.max_edicts); + + limit = VM_MemoryMask(q1qvm); + if ((qintptr_t)gd->ents < 0 || (qintptr_t)gd->ents > limit) + gd->ents = NULL; + if (gd->sizeofent < 0 || gd->sizeofent > (0xffffffff-(qintptr_t)gd->ents) / sv.world.max_edicts) + gd->sizeofent = 0xffffffff / MAX_EDICTS; + if ((qintptr_t)gd->global < 0 || (qintptr_t)gd->global > limit) + gd->global = NULL; + if ((qintptr_t)gd->fields < 0 || (qintptr_t)gd->fields > limit) + gd->fields = NULL; + sv.world.edict_size = gd->sizeofent; vevars = (qintptr_t)gd->ents; evars = ((char*)VM_MemoryBase(q1qvm) + vevars); //FIXME: range check this pointer //FIXME: range check the globals pointer - sv.world.num_edicts = 1; - sv.world.max_edicts = sizeof(q1qvmedicts)/sizeof(q1qvmedicts[0]); //WARNING: global is not remapped yet... //This code is written evilly, but works well enough diff --git a/engine/server/sv_mvd.c b/engine/server/sv_mvd.c index 76a02db44..bb0418492 100644 --- a/engine/server/sv_mvd.c +++ b/engine/server/sv_mvd.c @@ -30,7 +30,7 @@ void SV_MVDStop_f (void); #define demo_size_padding 0x1000 -static void SV_DemoDir_Callback(struct cvar_s *var, char *oldvalue); +static void QDECL SV_DemoDir_Callback(struct cvar_s *var, char *oldvalue); cvar_t sv_demoUseCache = CVARD("sv_demoUseCache", "0", "If set, demo data will be flushed only periodically"); cvar_t sv_demoCacheSize = CVAR("sv_demoCacheSize", "0x80000"); //half a meg @@ -731,7 +731,7 @@ void Sys_freedir(dir_t *dir) // only one .. is allowed (so we can get to the same dir as the quake exe) -static void SV_DemoDir_Callback(struct cvar_s *var, char *oldvalue) +static void QDECL SV_DemoDir_Callback(struct cvar_s *var, char *oldvalue) { char *value; diff --git a/engine/web/ftejslib.h b/engine/web/ftejslib.h index f36bbcc2c..5accdf519 100644 --- a/engine/web/ftejslib.h +++ b/engine/web/ftejslib.h @@ -26,6 +26,11 @@ void emscriptenfte_alert(const char *msg); void emscriptenfte_print(const char *msg); void emscriptenfte_abortmainloop(const char *caller); +//we're trying to avoid including libpng+libjpeg+libogg in javascript due to it being redundant bloat. +//to use such textures/sounds, we can just 'directly' load them via webgl +void emscriptenfte_gl_loadtexturefile(int gltexid, int *width, int *height, void *data, int datasize); +void emscriptenfte_al_loadaudiofile(int al_buf, void *data, int datasize); + //avoid all of emscripten's sdl emulation. //this resolves input etc issues. unsigned long emscriptenfte_ticks_ms(void); diff --git a/engine/web/ftejslib.js b/engine/web/ftejslib.js index f5cfc0dd6..233b12b38 100644 --- a/engine/web/ftejslib.js +++ b/engine/web/ftejslib.js @@ -649,5 +649,79 @@ console.log("onerror: " + _url + " status " + http.status); }; http.send(null); + }, + + emscriptenfte_al_loadaudiofile : function(buf, dataptr, datasize) + { + //match emscripten's openal support. + if (!buf) + return; + buf = buf - 1; + + var ctx = AL.currentContext; + try + { + //its async, so it needs its own copy of an arraybuffer + var abuf = new ArrayBuffer(datasize); + new Uint8Array(abuf).set(HEAPU8.subarray(dataptr, dataptr+datasize)); + AL.currentContext.ctx.decodeAudioData(abuf, function(buffer) + { + ctx.buf[buf] = buffer; + }, function() + { + console.log("Audio Callback failed!"); + }); + } + catch (e) + { + console.log("unable to decode audio data"); + console.log(e); + } + }, + + emscriptenfte_gl_loadtexturefile : function(texid, widthptr, heightptr, dataptr, datasize) + { + function encode64(data) { + var BASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + var PAD = '='; + var ret = ''; + var leftchar = 0; + var leftbits = 0; + for (var i = 0; i < data.length; i++) { + leftchar = (leftchar << 8) | data[i]; + leftbits += 8; + while (leftbits >= 6) { + var curr = (leftchar >> (leftbits-6)) & 0x3f; + leftbits -= 6; + ret += BASE[curr]; + } + } + if (leftbits == 2) { + ret += BASE[(leftchar&3) << 4]; + ret += PAD + PAD; + } else if (leftbits == 4) { + ret += BASE[(leftchar&0xf) << 2]; + ret += PAD; + } + return ret; + } + + //make sure the texture is defined before its loaded, so we get no errors + GLctx.texImage2D(GLctx.TEXTURE_2D, 0, GLctx.RGBA, 1,1,0,GLctx.RGBA, GLctx.UNSIGNED_BYTE, null); + + var img = new Image(); + var gltex = GL.textures[texid]; + img.onload = function() + { + console.log("Image Callback called!"); + var oldtex = GLctx.getParameter(GLctx.TEXTURE_BINDING_2D); //blurgh, try to avoid breaking anything in this unexpected event. + GLctx.bindTexture(GLctx.TEXTURE_2D, gltex); + GLctx.texImage2D(GLctx.TEXTURE_2D, 0, GLctx.RGBA, GLctx.RGBA, GLctx.UNSIGNED_BYTE, img); + GLctx.generateMipmap(GLctx.TEXTURE_2D); + GLctx.bindTexture(GLctx.TEXTURE_2D, oldtex); + }; + img.crossorigin = true; + img.src = "data:image/png;base64," + encode64(HEAPU8.subarray(dataptr, dataptr+datasize)); + img.onload(); } }); diff --git a/fteqtv/forward.c b/fteqtv/forward.c index 0ecef61cd..a40ef0026 100644 --- a/fteqtv/forward.c +++ b/fteqtv/forward.c @@ -180,8 +180,8 @@ void Net_TryFlushProxyBuffer(cluster_t *cluster, oproxy_t *prox) int length; int bufpos; - if (prox->drop) - return; +// if (prox->drop) +// return; while (prox->bufferpos >= MAX_PROXY_BUFFER) { //so we never get any issues with wrapping.. @@ -212,12 +212,14 @@ void Net_TryFlushProxyBuffer(cluster_t *cluster, oproxy_t *prox) { case 0: //eof / they disconnected prox->drop = true; + prox->flushing = false; break; case -1: if (qerrno != EWOULDBLOCK && qerrno != EAGAIN) //not a problem, so long as we can flush it later. { Sys_Printf(cluster, "network error from client proxy\n"); prox->drop = true; //drop them if we get any errors + prox->flushing = false; } break; default: diff --git a/fteqtv/httpsv.c b/fteqtv/httpsv.c index a145269fc..8f9f70029 100644 --- a/fteqtv/httpsv.c +++ b/fteqtv/httpsv.c @@ -202,6 +202,7 @@ static void HTTPSV_SendHTMLHeader(cluster_t *cluster, oproxy_t *dest, char *titl Net_ProxySend(cluster, dest, buffer, strlen(buffer)); +#if 0 if (plugin) { s = @@ -225,6 +226,7 @@ static void HTTPSV_SendHTMLHeader(cluster_t *cluster, oproxy_t *dest, char *titl ""; Net_ProxySend(cluster, dest, s, strlen(s)); } +#endif } static void HTTPSV_SendHTMLFooter(cluster_t *cluster, oproxy_t *dest) @@ -233,12 +235,14 @@ static void HTTPSV_SendHTMLFooter(cluster_t *cluster, oproxy_t *dest) char buffer[2048]; /*Proxy version*/ - snprintf(buffer, sizeof(buffer), "
Server Version: %i www.fteqw.com", cluster->buildnumber); + snprintf(buffer, sizeof(buffer), "
Server Version: %i "PROXYWEBSITE"", cluster->buildnumber); Net_ProxySend(cluster, dest, buffer, strlen(buffer)); +#if 0 /*Plugin version*/ s = ""; Net_ProxySend(cluster, dest, s, strlen(s)); +#endif /*terminate html page*/ s = "\n" @@ -790,11 +794,25 @@ static void HTTPSV_GeneratePlugin(cluster_t *cluster, oproxy_t *dest) "" "" "
" + +#if 1 +#define EMBEDDEDWEBGLORIGIN "http://86.191.129.12:80"//127.0.0.1:80" +#define EMBEDDEDWEBGLURL EMBEDDEDWEBGLORIGIN"/ftewebgl.html" +#else +#define EMBEDDEDWEBGLORIGIN "http://triptohell.info" +#define EMBEDDEDWEBGLURL EMBEDDEDWEBGLORIGIN"/moodles/web/ftewebgl.html" +#endif + +#if 1 + "" +#else /*once for IE*/ "" @@ -833,9 +851,11 @@ static void HTTPSV_GeneratePlugin(cluster_t *cluster, oproxy_t *dest) "Plugin failed to load" "" "" +#endif "
" "