From dfd8e1aaed713fc4e2b397bf9956ccef0a225ad1 Mon Sep 17 00:00:00 2001 From: Spoike Date: Tue, 14 Jun 2005 04:52:10 +0000 Subject: [PATCH] Redesigned sound code for greater modularity. Added support for dp6/dp7 protocols (ents are still broken). md3 tags should work properly (still suffer from origin-of-parent interpolation bugs) git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@1089 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_cam.c | 4 + engine/client/cl_ents.c | 88 ++- engine/client/cl_input.c | 16 +- engine/client/cl_main.c | 18 +- engine/client/cl_master.h | 2 + engine/client/cl_parse.c | 13 +- engine/client/cl_screen.c | 4 +- engine/client/cl_tent.c | 1 + engine/client/cl_ui.c | 49 +- engine/client/client.h | 5 +- engine/client/console.c | 2 + engine/client/in_sdl.c | 5 + engine/client/keys.c | 5 +- engine/client/menu.c | 67 +- engine/client/merged.h | 2 +- engine/client/pr_csqc.c | 7 +- engine/client/r_part.c | 4 +- engine/client/render.h | 2 +- engine/client/renderer.c | 17 +- engine/client/snd_alsa.c | 201 ++--- engine/client/snd_dma.c | 263 ++++--- engine/client/snd_linux.c | 171 ++-- engine/client/snd_mem.c | 4 - engine/client/snd_mix.c | 208 +---- engine/client/snd_sdl.c | 115 ++- engine/client/snd_win.c | 1412 +++++----------------------------- engine/client/sound.h | 84 +- engine/client/sys_win.c | 2 +- engine/client/view.c | 46 ++ engine/client/winquake.h | 22 +- engine/client/zqtp.c | 8 +- engine/common/common.c | 13 +- engine/common/common.h | 1 + engine/common/gl_q2bsp.c | 4 +- engine/common/net.h | 3 + engine/common/net_chan.c | 45 +- engine/common/net_wins.c | 2 +- engine/common/protocol.h | 5 +- engine/common/q1bsp.c | 5 +- engine/common/zone.c | 8 +- engine/ftequake/ftequake.dsp | 662 ++++++++++++++++ engine/gl/gl_alias.c | 193 ++++- engine/gl/gl_ppl.c | 2 +- engine/gl/gl_rmain.c | 4 + engine/gl/gl_rsurf.c | 1 - engine/qclib/execloop.h | 2 +- engine/qclib/execloop16.h | 914 ---------------------- engine/qclib/execloop16d.h | 2 +- engine/qclib/execloop32.h | 2 +- engine/qclib/execloop32d.h | 2 +- engine/qclib/initlib.c | 11 +- engine/qclib/pr_edict.c | 7 +- engine/qclib/pr_exec.c | 8 +- engine/qclib/qcc_pr_comp.c | 81 +- engine/qclib/qcc_pr_lex.c | 4 +- engine/server/net_preparse.c | 25 +- engine/server/pr_cmds.c | 154 +++- engine/server/server.h | 6 +- engine/server/sv_ents.c | 340 +++++++- engine/server/sv_init.c | 8 +- engine/server/sv_main.c | 51 +- engine/server/sv_phys.c | 5 +- engine/server/sv_send.c | 92 ++- engine/server/sv_user.c | 49 +- engine/sw/sw_screen.c | 1 + 65 files changed, 2511 insertions(+), 3048 deletions(-) delete mode 100644 engine/qclib/execloop16.h diff --git a/engine/client/cl_cam.c b/engine/client/cl_cam.c index 7fb0bd046..6d91354cd 100644 --- a/engine/client/cl_cam.c +++ b/engine/client/cl_cam.c @@ -132,6 +132,7 @@ void Cam_Unlock(int pnum) void Cam_Lock(int pnum, int playernum) { + int i; cam_lastviewtime[pnum] = -1000; @@ -148,6 +149,9 @@ void Cam_Lock(int pnum, int playernum) } Sbar_Changed(); + + for (i = 0; i < MAX_CLIENTS; i++) + CL_NewTranslation(i); } trace_t Cam_DoTrace(vec3_t vec1, vec3_t vec2) diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 56fa0f63d..fa1267328 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -1233,19 +1233,32 @@ float CL_LerpEntityFrac(float lerprate, float lerptime) return f; } +float CL_EntLerpFactor(int entnum) +{ + float f; + if (cl.lerpents[entnum].lerprate<=0) + return 0; + else + f = 1-(cl.time-cl.lerpents[entnum].lerptime)/cl.lerpents[entnum].lerprate; + if (f<0) + f=0; + if (f>1) + f=1; + return f; +} + void CL_RotateAroundTag(entity_t *ent, int num, int tagent, int tagnum) { entity_state_t *ps; float *org=NULL, *ang=NULL; vec3_t axis[3]; - vec3_t temp[3]; vec3_t destorg; + float transform[12], parent[12], result[12], old[12], temp[12]; int model = 0; //these two are only initialised because msvc sucks at detecting usage. int frame = 0; - - float *tagorg=NULL; - float *tagaxis; + int frame2 = cl.lerpents[tagent].frame; + float frame2ness; // ent->keynum = tagent; @@ -1288,12 +1301,51 @@ void CL_RotateAroundTag(entity_t *ent, int num, int tagent, int tagnum) AngleVectors(ang, axis[0], axis[1], axis[2]); VectorInverse(axis[1]); - if (Mod_GetTag) - Mod_GetTag(cl.model_precache[model], tagnum, frame, &tagorg, &tagaxis); - else - tagaxis = NULL; - if (tagaxis) + frame2ness = CL_EntLerpFactor(tagent); + if (Mod_GetTag && Mod_GetTag(cl.model_precache[model], tagnum, frame, frame2, frame2ness, cl.time - cl.lerpents[tagent].framechange, cl.time - cl.lerpents[tagent].framechange, transform)) { + old[0] = ent->axis[0][0]; + old[1] = ent->axis[1][0]; + old[2] = ent->axis[2][0]; + old[3] = ent->origin[0]; + old[4] = ent->axis[0][1]; + old[5] = ent->axis[1][1]; + old[6] = ent->axis[2][1]; + old[7] = ent->origin[1]; + old[8] = ent->axis[0][2]; + old[9] = ent->axis[1][2]; + old[10] = ent->axis[2][2]; + old[11] = ent->origin[2]; + + parent[0] = axis[0][0]; + parent[1] = axis[1][0]; + parent[2] = axis[2][0]; + parent[3] = org[0]; + parent[4] = axis[0][1]; + parent[5] = axis[1][1]; + parent[6] = axis[2][1]; + parent[7] = org[1]; + parent[8] = axis[0][2]; + parent[9] = axis[1][2]; + parent[10] = axis[2][2]; + parent[11] = org[2]; + + R_ConcatTransforms((void*)old, (void*)parent, (void*)temp); + R_ConcatTransforms((void*)temp, (void*)transform, (void*)result); + + ent->axis[0][0] = result[0]; + ent->axis[1][0] = result[1]; + ent->axis[2][0] = result[2]; + ent->origin[0] = result[3]; + ent->axis[0][1] = result[4]; + ent->axis[1][1] = result[5]; + ent->axis[2][1] = result[6]; + ent->origin[1] = result[7]; + ent->axis[0][2] = result[8]; + ent->axis[1][2] = result[9]; + ent->axis[2][2] = result[10]; + ent->origin[2] = result[11]; +/* VectorAdd(org, ent->origin, destorg); VectorMA(destorg, tagorg[0], ent->axis[0], destorg); VectorMA(destorg, tagorg[1], ent->axis[1], destorg); @@ -1303,14 +1355,13 @@ void CL_RotateAroundTag(entity_t *ent, int num, int tagent, int tagnum) // Con_Printf("Found tag %i\n", cl.lerpents[tagent].tagindex); Matrix3_Multiply(axis, ent->axis, temp); //the ent->axis here is the result of the parent's transforms Matrix3_Multiply((void*)tagaxis, temp, ent->axis); +*/ } else //hrm. { memcpy(ent->axis, axis, sizeof(temp)); VectorCopy(org, ent->origin); } - - } // if (org) // VectorAdd(ent->origin, org, ent->origin); @@ -1615,6 +1666,7 @@ void CL_LinkPacketEntities (void) { //hmm. hexen spider gibs... dl = CL_AllocDlight (s1->number); VectorCopy (ent->origin, dl->origin); + dl->origin[2] += 1; dl->radius = 200; dl->die = (float)cl.time; dl->color[0] = 0.20; @@ -2223,15 +2275,15 @@ void CL_LinkPlayers (void) if ((!r_flashblend.value || j != cl.playernum[0]) && r_powerupglow.value) { if ((state->effects & (EF_BLUE | EF_RED)) == (EF_BLUE | EF_RED)) - CL_NewDlight (j+1, state->origin[0], state->origin[1], state->origin[2], 200 + (rand()&31), 0.1, 3)->noppl = (j != cl.playernum[0]); + CL_NewDlight (j+1, state->origin[0], state->origin[1], state->origin[2], 200 + (r_lightflicker.value?(rand()&31):0), 0.1, 3)->noppl = (j != cl.playernum[0]); else if (state->effects & EF_BLUE) - CL_NewDlight (j+1, state->origin[0], state->origin[1], state->origin[2], 200 + (rand()&31), 0.1, 1)->noppl = (j != cl.playernum[0]); + CL_NewDlight (j+1, state->origin[0], state->origin[1], state->origin[2], 200 + (r_lightflicker.value?(rand()&31):0), 0.1, 1)->noppl = (j != cl.playernum[0]); else if (state->effects & EF_RED) - CL_NewDlight (j+1, state->origin[0], state->origin[1], state->origin[2], 200 + (rand()&31), 0.1, 2)->noppl = (j != cl.playernum[0]); + CL_NewDlight (j+1, state->origin[0], state->origin[1], state->origin[2], 200 + (r_lightflicker.value?(rand()&31):0), 0.1, 2)->noppl = (j != cl.playernum[0]); else if (state->effects & EF_BRIGHTLIGHT) - CL_NewDlight (j+1, state->origin[0], state->origin[1], state->origin[2] + 16, 400 + (rand()&31), 0.1, 0)->noppl = (j != cl.playernum[0]); + CL_NewDlight (j+1, state->origin[0], state->origin[1], state->origin[2] + 16, 400 + (r_lightflicker.value?(rand()&31):0), 0.1, 0)->noppl = (j != cl.playernum[0]); else if (state->effects & EF_DIMLIGHT) - CL_NewDlight (j+1, state->origin[0], state->origin[1], state->origin[2], 200 + (rand()&31), 0.1, 0)->noppl = (j != cl.playernum[0]); + CL_NewDlight (j+1, state->origin[0], state->origin[1], state->origin[2], 200 + (r_lightflicker.value?(rand()&31):0), 0.1, 0)->noppl = (j != cl.playernum[0]); } if (state->modelindex < 1) @@ -2297,12 +2349,12 @@ void CL_LinkPlayers (void) { if (j == cl.playernum[pnum]) { - if (cl.spectator) +/* if (cl.spectator) { cl_numvisedicts--; continue; } - angles[0] = -1*cl.viewangles[pnum][0] / 3; +*/ angles[0] = -1*cl.viewangles[pnum][0] / 3; angles[1] = cl.viewangles[pnum][1]; angles[2] = cl.viewangles[pnum][2]; ent->origin[0] = cl.simorg[pnum][0]; diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index f410bd830..7a9155a44 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -543,7 +543,7 @@ CL_FinishMove */ void CL_FinishMove (usercmd_t *cmd, int msecs, int pnum) { - int ms, i; + int i; int bits; // @@ -793,15 +793,10 @@ float CL_FilterTime (double time, float wantfps) //now returns the extra time no { fpscap = cls.maxfps ? max (30.0, cls.maxfps) : 0x7fff; - if (wantfps>0) - fps = bound (10.0, wantfps, fpscap); + if (wantfps < 1) + fps = fpscap; else - { -// if (com_serveractive) -// fps = fpscap; -// else - fps = bound (30.0, rate.value/80.0, fpscap); - } + fps = bound (10.0, wantfps, fpscap); } if (time < 1000 / fps) @@ -882,6 +877,7 @@ int CL_RemoveClientCommands(char *command) if (!clientcmdlist) return removed; } + first = clientcmdlist; while(first->next) { if (!strcmp(first->next->command, command)) @@ -1011,8 +1007,6 @@ void CL_SendCmd (float frametime) int lost; int seq_hash; int firstsize; - int extramsec; - vec3_t v; float wantfps; qbyte lightlev; diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 3f8c2b4fc..e9f089e98 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -1005,7 +1005,7 @@ void CL_User_f (void) int i; #ifndef CLIENTONLY - if (isDedicated) + if (sv.state) { SV_User_f(); return; @@ -1964,7 +1964,7 @@ void CLNQ_ConnectionlessPacket(void) Con_TPrintf (TLC_DUPCONNECTION); return; } - net_from.port = htons(MSG_ReadLong()); + net_from.port = htons((short)MSG_ReadLong()); Netchan_Setup (NS_CLIENT, &cls.netchan, net_from, cls.qport); cls.netchan.isnqprotocol = true; cls.netchan.compress = 0; @@ -2941,7 +2941,7 @@ void Host_Init (quakeparms_t *parms) Hunk_AllocName (0, "-HOST_HUNKLEVEL-"); host_hunklevel = Hunk_LowMark (); - R_SetRenderer(0);//set the renderer stuff to 'none'... + R_SetRenderer(-1);//set the renderer stuff to unset... host_initialized = true; @@ -2977,15 +2977,17 @@ void Host_Init (quakeparms_t *parms) if ((i = COM_CheckParm ("-bpp"))) Cvar_Set(Cvar_FindVar("vid_bpp"), com_argv[i+1]); - if (!qrenderer && *vid_renderer.string) + if (qrenderer<=0 && *vid_renderer.string) + { + Cmd_ExecuteString("vid_restart\n", RESTRICT_LOCAL); + } + if (qrenderer<=0) { Cmd_ExecuteString("vid_restart\n", RESTRICT_LOCAL); } - if (!qrenderer) - { - Cmd_ExecuteString("vid_restart\n", RESTRICT_LOCAL); - } + if (qrenderer == QR_NONE) + Con_Printf("Use the setrenderer command to use a gui\n"); UI_Init(); diff --git a/engine/client/cl_master.h b/engine/client/cl_master.h index 3a43a6954..78c1d7e2b 100644 --- a/engine/client/cl_master.h +++ b/engine/client/cl_master.h @@ -147,3 +147,5 @@ qboolean Master_GetSortDescending(void); int Master_NumSorted(void); void Master_ClearMasks(void); serverinfo_t *Master_SortedServer(int idx); +void Master_SetMaskString(qboolean or, hostcachekey_t field, char *param, slist_test_t testop); +void Master_SetMaskInteger(qboolean or, hostcachekey_t field, int param, slist_test_t testop); diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 512d4f0e8..98c7e554b 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -1222,7 +1222,7 @@ void CL_ParseServerData (void) if (cls.fteprotocolextensions & PEXT_FLOATCOORDS) { sizeofcoord = 4; - sizeofangle = 1; + sizeofangle = 2; } else { @@ -2386,6 +2386,7 @@ void CL_NewTranslation (int slot) char *s; player_info_t *player; + int local; if (slot >= MAX_CLIENTS) Sys_Error ("CL_NewTranslation: slot > MAX_CLIENTS"); @@ -2411,7 +2412,15 @@ void CL_NewTranslation (int slot) bottom = player->bottomcolor; if (!cl.splitclients && !(cl.fpd & FPD_NO_FORCE_COLOR)) //no colour/skin forcing in splitscreen. { - if (cl.teamplay && !strcmp(player->team, cl.players[cl.playernum[0]].team)) + if (cl.teamplay && cl.spectator) + { + local = Cam_TrackNum(0); + if (local < 0) + local = cl.playernum[0]; + } + else + local = cl.playernum[0]; + if (cl.teamplay && !strcmp(player->team, cl.players[local].team)) { if (cl_teamtopcolor>=0) top = cl_teamtopcolor; diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index be452f698..07fbb9efd 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -106,7 +106,7 @@ extern cvar_t scr_printspeed; extern cvar_t scr_allowsnap; extern cvar_t scr_sshot_type; extern cvar_t crosshair; -extern cvar_t con_height; +extern cvar_t scr_consize; qboolean scr_initialized; // ready to draw @@ -1259,7 +1259,7 @@ void SCR_SetUpToDrawConsole (void) } else if (key_dest == key_console || scr_chatmode) { - scr_conlines = vid.height*con_height.value/100; // half screen + scr_conlines = vid.height*scr_consize.value; // half screen if (scr_conlines < 32) scr_conlines = 32; //prevent total loss of console. else if (scr_conlines>vid.height) diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index 7ad67452f..eae8d6859 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -344,6 +344,7 @@ void CL_ParseBeam (int tent) { m = Mod_ForName("progs/beam.mdl", false); //remember to precache! btype = P_FindParticleType("te_beam"); + etype = P_FindParticleType("te_beam_end"); } else { diff --git a/engine/client/cl_ui.c b/engine/client/cl_ui.c index 984db0b2b..2a7a169b8 100644 --- a/engine/client/cl_ui.c +++ b/engine/client/cl_ui.c @@ -368,50 +368,37 @@ int VM_LerpTag(void *out, model_t *model, int f1, int f2, float l2, char *tagnam float *ang; float *org; - float *org1; - float *ang1; - float *org2; - float *ang2; - - float l1; + float tr[12]; + qboolean found; org = (float*)out; ang = ((float*)out+3); - l1 = 1-l2; - - if (Mod_GetTag) { if (Mod_TagNumForName) tagnum = Mod_TagNumForName(model, tagname); else tagnum = 0; - Mod_GetTag(model, tagnum, f1, &org1, &ang1); - Mod_GetTag(model, tagnum, f2, &org2, &ang2); + found = Mod_GetTag(model, tagnum, f1, f2, l2, 0, 0, tr); } else + found = false; + + if (found) { - ang1=ang2=NULL; - org1=org2=NULL; //msvc was warning about this not being present. - } - if (ang1 && ang2) - { - org[0] = org1[0]*l1 + org2[0]*l2; - org[1] = org1[1]*l1 + org2[1]*l2; - org[2] = org1[2]*l1 + org2[2]*l2; - - ang[0] = ang1[0]*l1 + ang2[0]*l2; - ang[1] = ang1[1]*l1 + ang2[1]*l2; - ang[2] = ang1[2]*l1 + ang2[2]*l2; - - ang[3] = ang1[3]*l1 + ang2[3]*l2; - ang[4] = ang1[4]*l1 + ang2[4]*l2; - ang[5] = ang1[5]*l1 + ang2[5]*l2; - - ang[6] = ang1[6]*l1 + ang2[6]*l2; - ang[7] = ang1[7]*l1 + ang2[7]*l2; - ang[8] = ang1[8]*l1 + ang2[8]*l2; + ang[0] = tr[0]; + ang[1] = tr[1]; + ang[2] = tr[2]; + org[0] = tr[3]; + ang[3] = tr[4]; + ang[4] = tr[5]; + ang[5] = tr[6]; + org[1] = tr[7]; + ang[6] = tr[8]; + ang[7] = tr[9]; + ang[8] = tr[10]; + org[2] = tr[11]; return true; } diff --git a/engine/client/client.h b/engine/client/client.h index 841ff3361..f60f68423 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -384,9 +384,8 @@ typedef struct downloadlist_s { typedef struct { float lerptime; -#ifdef HALFLIFEMODELS float framechange; //marks time of last frame change - for halflife model sequencing. -#endif + float oldframechange; float lerprate; //inverse rate... vec3_t origin; vec3_t angles; @@ -787,6 +786,8 @@ qboolean CSQC_DrawView(void); void CSQC_Shutdown(void); qboolean CSQC_StuffCmd(char *cmd); qboolean CSQC_CenterPrint(char *cmd); +qboolean CSQC_ConsoleCommand(char *cmd); +qboolean CSQC_KeyPress(int key, qboolean down); #endif // diff --git a/engine/client/console.c b/engine/client/console.c index d1c298957..0e9e2606a 100644 --- a/engine/client/console.c +++ b/engine/client/console.c @@ -68,6 +68,7 @@ cvar_t con_numnotifylines = {"con_notifylines","4"}; //max lines to show cvar_t con_notifytime = {"con_notifytime","3"}; //seconds cvar_t con_centernotify = {"con_centernotify", "0"}; cvar_t con_displaypossabilities = {"con_displaypossabilities", "1"}; +cvar_t cl_chatmode = {"cl_chatmode", "2"}; #define NUM_CON_TIMES 24 float con_times[NUM_CON_TIMES]; // realtime time the line was generated @@ -511,6 +512,7 @@ void Con_Init (void) Cvar_Register (&con_centernotify, "Console controls"); Cvar_Register (&con_numnotifylines, "Console controls"); Cvar_Register (&con_displaypossabilities, "Console controls"); + Cvar_Register (&cl_chatmode, "Console controls"); Cmd_AddCommand ("toggleconsole", Con_ToggleConsole_f); Cmd_AddCommand ("togglechat", Con_ToggleChat_f); diff --git a/engine/client/in_sdl.c b/engine/client/in_sdl.c index b34889cf7..ec86b2628 100644 --- a/engine/client/in_sdl.c +++ b/engine/client/in_sdl.c @@ -212,6 +212,11 @@ int mouse_x, mouse_y; void ResetFrameBuffers(void); #endif +#ifdef RGLQUAKE +extern int glwidth; +extern int glheight; +#endif + void Sys_SendKeyEvents(void) { SDL_Event event; diff --git a/engine/client/keys.c b/engine/client/keys.c index de7adc8b9..407b25858 100644 --- a/engine/client/keys.c +++ b/engine/client/keys.c @@ -53,6 +53,7 @@ qboolean keydown[256]; qboolean deltaused[256][KEY_MODIFIERSTATES]; extern cvar_t con_displaypossabilities; +extern cvar_t cl_chatmode; static int KeyModifier (qboolean shift, qboolean alt, qboolean ctrl) { @@ -354,7 +355,7 @@ void Con_ExecuteLine(console_t *con, char *line) con_commandmatch=1; if (line[0] == '\\' || line[0] == '/') Cbuf_AddText (line+1, RESTRICT_LOCAL); // skip the > - else if (Cmd_IsCommand(line)) + else if (cl_chatmode.value && Cmd_IsCommand(line)) Cbuf_AddText (line, RESTRICT_LOCAL); // valid command #ifdef Q2CLIENT else if (cls.protocol == CP_QUAKE2) @@ -362,7 +363,7 @@ void Con_ExecuteLine(console_t *con, char *line) #endif else { // convert to a chat message - if (cls.state >= ca_connected && (strncmp(line, "say ", 4))) + if (cl_chatmode.value == 1 || ((cls.state >= ca_connected && cl_chatmode.value == 2) && (strncmp(line, "say ", 4)))) { if (keydown[K_CTRL]) Cbuf_AddText ("say_team ", RESTRICT_LOCAL); diff --git a/engine/client/menu.c b/engine/client/menu.c index 00824d4c0..71b94ea00 100644 --- a/engine/client/menu.c +++ b/engine/client/menu.c @@ -148,50 +148,59 @@ void M_DrawTextBox (int x, int y, int width, int lines) // draw left side cx = x; cy = y; - p = Draw_CachePic ("gfx/box_tl.lmp"); - M_DrawTransPic (cx, cy, p); - p = Draw_CachePic ("gfx/box_ml.lmp"); - for (n = 0; n < lines; n++) - { - cy += 8; + p = Draw_SafeCachePic ("gfx/box_tl.lmp"); + if (p) M_DrawTransPic (cx, cy, p); - } - p = Draw_CachePic ("gfx/box_bl.lmp"); - M_DrawTransPic (cx, cy+8, p); + p = Draw_SafeCachePic ("gfx/box_ml.lmp"); + if (p) + for (n = 0; n < lines; n++) + { + cy += 8; + M_DrawTransPic (cx, cy, p); + } + p = Draw_SafeCachePic ("gfx/box_bl.lmp"); + if (p) + M_DrawTransPic (cx, cy+8, p); // draw middle cx += 8; while (width > 0) { cy = y; - p = Draw_CachePic ("gfx/box_tm.lmp"); - M_DrawTransPic (cx, cy, p); - p = Draw_CachePic ("gfx/box_mm.lmp"); - for (n = 0; n < lines; n++) - { - cy += 8; - if (n == 1) - p = Draw_CachePic ("gfx/box_mm2.lmp"); + p = Draw_SafeCachePic ("gfx/box_tm.lmp"); + if (p) M_DrawTransPic (cx, cy, p); - } - p = Draw_CachePic ("gfx/box_bm.lmp"); - M_DrawTransPic (cx, cy+8, p); + p = Draw_SafeCachePic ("gfx/box_mm.lmp"); + if (p) + for (n = 0; n < lines; n++) + { + cy += 8; + if (n == 1) + p = Draw_CachePic ("gfx/box_mm2.lmp"); + M_DrawTransPic (cx, cy, p); + } + p = Draw_SafeCachePic ("gfx/box_bm.lmp"); + if (p) + M_DrawTransPic (cx, cy+8, p); width -= 2; cx += 16; } // draw right side cy = y; - p = Draw_CachePic ("gfx/box_tr.lmp"); - M_DrawTransPic (cx, cy, p); - p = Draw_CachePic ("gfx/box_mr.lmp"); - for (n = 0; n < lines; n++) - { - cy += 8; + p = Draw_SafeCachePic ("gfx/box_tr.lmp"); + if (p) M_DrawTransPic (cx, cy, p); - } - p = Draw_CachePic ("gfx/box_br.lmp"); - M_DrawTransPic (cx, cy+8, p); + p = Draw_SafeCachePic ("gfx/box_mr.lmp"); + if (p) + for (n = 0; n < lines; n++) + { + cy += 8; + M_DrawTransPic (cx, cy, p); + } + p = Draw_SafeCachePic ("gfx/box_br.lmp"); + if (p) + M_DrawTransPic (cx, cy+8, p); } //============================================================================= diff --git a/engine/client/merged.h b/engine/client/merged.h index 209260fdb..1fc71b199 100644 --- a/engine/client/merged.h +++ b/engine/client/merged.h @@ -103,7 +103,7 @@ extern qbyte *FNC(Mod_Q1LeafPVS) (struct mleaf_s *leaf, struct model_s *mode extern void FNC(Mod_NowLoadExternal) (void); extern void FNC(Mod_Think) (void); -extern void (*Mod_GetTag) (struct model_s *model, int tagnum, int frame, float **org, float **axis); +extern qboolean (*Mod_GetTag) (struct model_s *model, int tagnum, int frame, int frame2, float f2ness, float f1time, float f2time, float *transforms); extern int (*Mod_TagNumForName) (struct model_s *model, char *name); #undef FNC diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index 2eca7811f..66252b24d 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -1266,7 +1266,7 @@ void PF_cs_sound(progfuncs_t *prinst, struct globalvars_s *pr_globals) sfx_t *sfx; - entity = G_EDICT(prinst, OFS_PARM0); + entity = (csqcedict_t*)G_EDICT(prinst, OFS_PARM0); channel = G_FLOAT(OFS_PARM1); sample = PR_GetStringOfs(prinst, OFS_PARM2); volume = G_FLOAT(OFS_PARM3) * 255; @@ -1912,6 +1912,11 @@ void CSQC_ParseEntities(void) packetsize = MSG_ReadShort(); packetstart = msg_readcount; } + else + { + packetsize = 0; + packetstart = 0; + } ent = csqcent[entnum]; if (!ent) diff --git a/engine/client/r_part.c b/engine/client/r_part.c index cfed11d44..0612f92b3 100644 --- a/engine/client/r_part.c +++ b/engine/client/r_part.c @@ -1283,7 +1283,8 @@ void P_NewServer(void) Con_Printf("Couldn't find particle description, using spikeset\n"); Cbuf_AddText(particle_set_spikeset, RESTRICT_SERVER); } -#if defined(_DEBUG) && defined(WIN32) //expand the particles cfg into a C style quoted string, and copy to clipboard so I can paste it in. +/* +#if defined(_DEBUG) && defined(_WIN32) //expand the particles cfg into a C style quoted string, and copy to clipboard so I can paste it in. { char *TL_ExpandToCString(char *in); extern HWND mainwindow; @@ -1321,6 +1322,7 @@ void P_NewServer(void) CloseClipboard(); } #endif +*/ } } diff --git a/engine/client/render.h b/engine/client/render.h index d55fda617..e0e369632 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -223,7 +223,7 @@ void R_SetVrect (vrect_t *pvrect, vrect_t *pvrectin, int lineadj); #if defined(RGLQUAKE) void GLMod_Init (void); -void GLMod_GetTag(struct model_s *model, int tagnum, int frame, float **org, float **axis); +qboolean GLMod_GetTag(struct model_s *model, int tagnum, int frame, int frame2, float f2ness, float f1time, float f2time, float *result); int GLMod_TagNumForName(struct model_s *model, char *name); void GLMod_ClearAll (void); struct model_s *GLMod_ForName (char *name, qboolean crash); diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 756895886..c959e06db 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -162,7 +162,7 @@ cvar_t gl_lateswap = {"gl_lateswap", "0"}; cvar_t scr_sshot_type = {"scr_sshot_type", "jpg"}; -cvar_t con_height = {"con_height", "50"}; +cvar_t scr_consize = {"scr_consize", "0.5"}; cvar_t scr_viewsize = {"viewsize","100", NULL, CVAR_ARCHIVE}; cvar_t scr_fov = {"fov","90", NULL, CVAR_ARCHIVE}; // 10 - 170 cvar_t scr_conspeed = {"scr_conspeed","300"}; @@ -491,7 +491,7 @@ void Renderer_Init(void) Cvar_Register (&scr_centertime, SCREENOPTIONS); Cvar_Register (&scr_printspeed, SCREENOPTIONS); Cvar_Register (&scr_allowsnap, SCREENOPTIONS); - Cvar_Register (&con_height, SCREENOPTIONS); + Cvar_Register (&scr_consize, SCREENOPTIONS); Cvar_Register(&r_bloodstains, GRAPHICALNICETIES); @@ -605,7 +605,7 @@ struct mleaf_s *(*Mod_PointInLeaf) (float *p, struct model_s *model); qbyte *(*Mod_Q1LeafPVS) (struct mleaf_s *leaf, struct model_s *model, qbyte *buffer); void (*Mod_NowLoadExternal) (void); void (*Mod_Think) (void); -void (*Mod_GetTag) (struct model_s *model, int tagnum, int frame, float **org, float **axis); +qboolean (*Mod_GetTag) (struct model_s *model, int tagnum, int frame, int frame2, float f2ness, float f1time, float f2time, float *transforms); int (*Mod_TagNumForName) (struct model_s *model, char *name); @@ -626,7 +626,7 @@ void (*VID_SetWindowCaption) (char *msg); void (*SCR_UpdateScreen) (void); -r_qrenderer_t qrenderer=QR_NONE; +r_qrenderer_t qrenderer=-1; char *q_renderername = "Non-Selected renderer"; @@ -695,7 +695,7 @@ struct { qbyte *(*Mod_Q1LeafPVS) (struct mleaf_s *leaf, struct model_s *model, qbyte *buffer); void (*Mod_NowLoadExternal) (void); void (*Mod_Think) (void); - void (*Mod_GetTag) (struct model_s *model, int tagnum, int frame, float **org, float **axis); + qboolean(*Mod_GetTag) (model_t *model, int tagnum, int frame1, int frame2, float f2ness, float f1time, float f2time, float *result); int (*Mod_TagNumForName) (struct model_s *model, char *name); @@ -1254,6 +1254,9 @@ void M_Menu_Video_f (void) void R_SetRenderer(int wanted) { + qrenderer = wanted; + if (wanted<0) + wanted=QR_NONE; q_renderername = rendererinfo[wanted].name[0]; Draw_PicFromWad = rendererinfo[wanted].Draw_PicFromWad; @@ -1333,8 +1336,6 @@ void R_SetRenderer(int wanted) SCR_UpdateScreen = rendererinfo[wanted].SCR_UpdateScreen; - - qrenderer = wanted; } static qbyte default_quakepal[768] = @@ -1845,7 +1846,7 @@ void R_SetRenderer_f (void) } else if (!stricmp(Cmd_Argv(1), "dedicated")) { - Cvar_Set(&vid_renderer, "sv"); + Cvar_Set(&vid_renderer, "dedicated"); R_RestartRenderer_f(); } else if (!stricmp(Cmd_Argv(1), "SW") || !stricmp(Cmd_Argv(1), "Software")) diff --git a/engine/client/snd_alsa.c b/engine/client/snd_alsa.c index 6b77b790d..eb07b9bca 100755 --- a/engine/client/snd_alsa.c +++ b/engine/client/snd_alsa.c @@ -32,18 +32,82 @@ #include "quakedef.h" -static int snd_inited; -static snd_pcm_uframes_t buffer_size; -static const char *pcmname = NULL; -static snd_pcm_t *pcm; - -soundcardinfo_t *sndcardinfo; - -qboolean snd_firsttime; - -int SNDDMA_Init (soundcardinfo_t *sc) +static unsigned int ALSA_GetDMAPos (soundcardinfo_t *sc) { + const snd_pcm_channel_area_t *areas; + snd_pcm_uframes_t offset; + snd_pcm_uframes_t nframes = sc->sn.samples / sc->sn.numchannels; + + snd_pcm_avail_update (sc->handle); + snd_pcm_mmap_begin (sc->handle, &areas, &offset, &nframes); + offset *= sc->sn.numchannels; + nframes *= sc->sn.numchannels; + sc->sn.samplepos = offset; + sc->sn.buffer = areas->addr; + return sc->sn.samplepos; +} + +static void ALSA_Shutdown (soundcardinfo_t *sc) +{ + snd_pcm_close (sc->handle); +} + +static void ALSA_Submit (soundcardinfo_t *sc) +{ + extern int soundtime; + int state; + int count = sc->paintedtime - soundtime; + const snd_pcm_channel_area_t *areas; + snd_pcm_uframes_t nframes; + snd_pcm_uframes_t offset; + + nframes = count / sc->sn.numchannels; + + snd_pcm_avail_update (sc->handle); + snd_pcm_mmap_begin (sc->handle, &areas, &offset, &nframes); + + state = snd_pcm_state (sc->handle); + + switch (state) { + case SND_PCM_STATE_PREPARED: + snd_pcm_mmap_commit (sc->handle, offset, nframes); + snd_pcm_start (sc->handle); + break; + case SND_PCM_STATE_RUNNING: + snd_pcm_mmap_commit (sc->handle, offset, nframes); + break; + default: + break; + } +} + +static void *ALSA_LockBuffer(soundcardinfo_t *sc) +{ + return sc->sn.buffer; +} + +static void ALSA_UnlockBuffer(soundcardinfo_t *sc, void *buffer) +{ +} + +static void ALSA_SetUnderWater(soundcardinfo_t *sc, qboolean underwater) +{ +} + +void S_UpdateCapture(void) +{ +} + +static int ALSA_InitCard (soundcardinfo_t *sc, int cardnum) +{ + snd_pcm_t *pcm; + snd_pcm_uframes_t buffer_size; + + soundcardinfo_t *ec; //existing card + char *pcmname; + cvar_t *devname; + int err, i; int bps = -1, stereo = -1; unsigned int rate = 0; @@ -54,11 +118,19 @@ int SNDDMA_Init (soundcardinfo_t *sc) snd_pcm_hw_params_alloca (&hw); snd_pcm_sw_params_alloca (&sw); -// COMMANDLINEOPTION: Linux ALSA Sound: -sndpcm selects which pcm device to us, default is "default" - if ((i=COM_CheckParm("-sndpcm"))!=0) - pcmname=com_argv[i+1]; - if (!pcmname) - pcmname = "default"; + devname = Cvar_Get(va("snd_alsadevice%i", cardnum+1), cardnum==0?"default":"", 0, "Sound controls"); + pcmname = devname->string; + + if (!*pcmname) + return 2; + + for (ec = sndcardinfo; ec; ec = ec->next) + if (!strcmp(ec->name, pcmname)) + break; + if (ec) + return 2; //no more + + sc->inactive_sound = true; //linux sound devices always play sound, even when we're not the active app... // COMMANDLINEOPTION: Linux ALSA Sound: -sndbits sets sound precision to 8 or 16 bit (email me if you want others added) if ((i=COM_CheckParm("-sndbits")) != 0) @@ -104,8 +176,7 @@ int SNDDMA_Init (soundcardinfo_t *sc) goto error; } - err = snd_pcm_hw_params_set_access (pcm, hw, - SND_PCM_ACCESS_MMAP_INTERLEAVED); + err = snd_pcm_hw_params_set_access (pcm, hw, SND_PCM_ACCESS_MMAP_INTERLEAVED); if (0 > err) { Con_Printf ("ALSA: Failure to set noninterleaved PCM access. %s\n" "Note: Interleaved is not supported\n", @@ -115,12 +186,10 @@ int SNDDMA_Init (soundcardinfo_t *sc) switch (bps) { case -1: - err = snd_pcm_hw_params_set_format (pcm, hw, - SND_PCM_FORMAT_S16); + err = snd_pcm_hw_params_set_format (pcm, hw, SND_PCM_FORMAT_S16); if (0 <= err) { bps = 16; - } else if (0 <= (err = snd_pcm_hw_params_set_format (pcm, hw, - SND_PCM_FORMAT_U8))) { + } else if (0 <= (err = snd_pcm_hw_params_set_format (pcm, hw, SND_PCM_FORMAT_U8))) { bps = 8; } else { Con_Printf ("ALSA: no useable formats. %s\n", @@ -149,8 +218,7 @@ int SNDDMA_Init (soundcardinfo_t *sc) err = snd_pcm_hw_params_set_channels (pcm, hw, 2); if (0 <= err) { stereo = 1; - } else if (0 <= (err = snd_pcm_hw_params_set_channels (pcm, hw, - 1))) { + } else if (0 <= (err = snd_pcm_hw_params_set_channels (pcm, hw, 1))) { stereo = 0; } else { Con_Printf ("ALSA: no usable channels. %s\n", @@ -261,11 +329,18 @@ int SNDDMA_Init (soundcardinfo_t *sc) goto error; } + sc->Lock = ALSA_LockBuffer; + sc->Unlock = ALSA_UnlockBuffer; + sc->SetWaterDistortion = ALSA_SetUnderWater; + sc->Submit = ALSA_Submit; + sc->Shutdown = ALSA_Shutdown; + sc->GetDMAPos = ALSA_GetDMAPos; + sc->sn.samples = buffer_size * sc->sn.numchannels; // mono samples in buffer sc->sn.speed = rate; - SNDDMA_GetDMAPos (sc); // sets shm->buffer + sc->handle = pcm; + ALSA_GetDMAPos (sc); // sets shm->buffer - snd_inited = 1; return true; error: @@ -273,80 +348,6 @@ error: return false; } -int SNDDMA_GetDMAPos (soundcardinfo_t *sc) -{ - const snd_pcm_channel_area_t *areas; - snd_pcm_uframes_t offset; - snd_pcm_uframes_t nframes = sc->sn.samples / sc->sn.numchannels; +int (*pALSA_InitCard) (soundcardinfo_t *sc, int cardnum) = &ALSA_InitCard; - if (!snd_inited) - return 0; - - snd_pcm_avail_update (pcm); - snd_pcm_mmap_begin (pcm, &areas, &offset, &nframes); - offset *= sc->sn.numchannels; - nframes *= sc->sn.numchannels; - sc->sn.samplepos = offset; - sc->sn.buffer = areas->addr; - return sc->sn.samplepos; -} - -void SNDDMA_Shutdown (soundcardinfo_t *sc) -{ - if (snd_inited) { - snd_pcm_close (pcm); - snd_inited = 0; - } -} - -/* - SNDDMA_Submit - - Send sound to device if buffer isn't really the dma buffer -*/ -void SNDDMA_Submit (soundcardinfo_t *sc) -{ - extern int soundtime; - int state; - int count = sc->paintedtime - soundtime; - const snd_pcm_channel_area_t *areas; - snd_pcm_uframes_t nframes; - snd_pcm_uframes_t offset; - - nframes = count / sc->sn.numchannels; - - snd_pcm_avail_update (pcm); - snd_pcm_mmap_begin (pcm, &areas, &offset, &nframes); - - state = snd_pcm_state (pcm); - - switch (state) { - case SND_PCM_STATE_PREPARED: - snd_pcm_mmap_commit (pcm, offset, nframes); - snd_pcm_start (pcm); - break; - case SND_PCM_STATE_RUNNING: - snd_pcm_mmap_commit (pcm, offset, nframes); - break; - default: - break; - } -} - -void *S_LockBuffer(soundcardinfo_t *sc) -{ - return sc->sn.buffer; -} - -void S_UnlockBuffer(soundcardinfo_t *sc) -{ -} - -void SNDDMA_SetUnderWater(qboolean underwater) -{ -} - -void S_UpdateCapture(void) -{ -} diff --git a/engine/client/snd_dma.c b/engine/client/snd_dma.c index 40563045a..f97e72c33 100644 --- a/engine/client/snd_dma.c +++ b/engine/client/snd_dma.c @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -21,12 +21,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" -#ifndef __CYGWIN__ - -#ifdef _WIN32 -#include "winquake.h" -#endif - void S_Play(void); void S_PlayVol(void); void S_SoundList(void); @@ -40,14 +34,13 @@ void S_UpdateCard(soundcardinfo_t *sc); // Internal sound data & structures // ======================================================================= +soundcardinfo_t *sndcardinfo; //the master card. int snd_blocked = 0; static qboolean snd_ambient = 1; qboolean snd_initialized = false; int snd_speed; -qboolean snd_multipledevices = false; - vec3_t listener_origin; vec3_t listener_forward; vec3_t listener_right; @@ -89,6 +82,8 @@ cvar_t snd_playersoundvolume = {"snd_localvolume", "1"}; //sugested by crunch cvar_t snd_capture = {"snd_capture", "0"}; +cvar_t snd_usemultipledevices = {"snd_multipledevices", "0"}; + // ==================================================================== // User-setable variables @@ -145,6 +140,61 @@ void S_SoundInfo_f(void) } +sounddriver pDSOUND_InitCard; +sounddriver pALSA_InitCard; +sounddriver pOSS_InitCard; +sounddriver pSDL_InitCard; +sounddriver pWAV_InitCard; + +sounddriver *drivers[] = { + &pDSOUND_InitCard, + &pALSA_InitCard, + &pOSS_InitCard, + &pSDL_InitCard, + &pWAV_InitCard, + NULL +}; + +static int SNDDMA_Init(soundcardinfo_t *sc, int *cardnum, int *drivernum) +{ + sounddriver *sd; + int st = 0; + + memset(sc, 0, sizeof(*sc)); + if (snd_khz.value >= 45) + sc->sn.speed = 48000; + else if (snd_khz.value >= 30) //set by a slider + sc->sn.speed = 44100; + else if (snd_khz.value >= 20) + sc->sn.speed = 22050; + else + sc->sn.speed = 11025; + + sd = drivers[*drivernum]; + if (!sd) + return 2; //no more cards. + if (!*sd) //driver not loaded + st = 2; + else + st = (**sd)(sc, *cardnum); + if (st == 1) //worked + { + *cardnum += 1; //use the next card next time + return st; + } + else if (st == 0) //failed, try the next card with this driver. + { + *cardnum += 1; + return SNDDMA_Init(sc, cardnum, drivernum); + } + else //card number wasn't valid, try the first card of the next driver + { + *cardnum = 0; + *drivernum += 1; + return SNDDMA_Init(sc, cardnum, drivernum); + } +} + /* ================ S_Startup @@ -153,6 +203,7 @@ S_Startup void S_Startup (void) { + int cardnum, drivernum; int warningmessage=0; int rc; soundcardinfo_t *sc; @@ -167,28 +218,14 @@ void S_Startup (void) if (!fakedma) { -#if defined(_WIN32) && !defined(NODIRECTX) - extern int aimedforguid; //restart directsound guid aims. - aimedforguid=0; -#endif - for(;;) + for(cardnum = 0, drivernum = 0;;) { sc = Z_Malloc(sizeof(soundcardinfo_t)); - if (snd_khz.value >= 45) - sc->sn.speed = 48000; - else if (snd_khz.value >= 30) //set by a slider - sc->sn.speed = 44100; - else if (snd_khz.value >= 20) - sc->sn.speed = 22050; - else - sc->sn.speed = 11025; - rc = SNDDMA_Init(sc); + rc = SNDDMA_Init(sc, &cardnum, &drivernum); if (!rc) //error stop { -#ifndef _WIN32 Con_Printf("S_Startup: SNDDMA_Init failed.\n"); -#endif Z_Free(sc); break; } @@ -255,7 +292,7 @@ void S_Startup (void) warningmessage = true; } - Z_Free(sc); + Z_Free(sc); continue; } } @@ -264,35 +301,44 @@ void S_Startup (void) sc->next = sndcardinfo; sndcardinfo = sc; + + if (!snd_usemultipledevices.value) + break; } } sound_started = 1; } +void SNDDMA_SetUnderWater(qboolean underwater) +{ + soundcardinfo_t *sc; + + for (sc = sndcardinfo; sc; sc=sc->next) + sc->SetWaterDistortion(sc, underwater); +} + void S_Restart_f (void) -{ - extern qboolean snd_firsttime; +{ Cache_Flush();//forget the old sounds. if (COM_CheckParm("-nosound")) return; - S_StopAllSounds (true); + S_StopAllSounds (true); S_Shutdown(); sound_started = 0; - snd_firsttime = true; S_Startup(); ambient_sfx[AMBIENT_WATER] = S_PrecacheSound ("ambience/water1.wav"); - ambient_sfx[AMBIENT_SKY] = S_PrecacheSound ("ambience/wind2.wav"); + ambient_sfx[AMBIENT_SKY] = S_PrecacheSound ("ambience/wind2.wav"); S_StopAllSounds (true); } void S_Control_f (void) -{ +{ int i; char *command; if (Cmd_Argc() < 2) @@ -304,7 +350,7 @@ void S_Control_f (void) { Cache_Flush();//forget the old sounds. - S_StopAllSounds (true); + S_StopAllSounds (true); S_Shutdown(); sound_started = 0; @@ -313,29 +359,29 @@ void S_Control_f (void) { if (!Q_strcasecmp(Cmd_Argv (2), "off")) { - if (snd_multipledevices) + if (snd_usemultipledevices.value) { - snd_multipledevices = false; - S_Restart_f(); - } + Cvar_SetValue(&snd_usemultipledevices, 0); + S_Restart_f(); + } } - else if (!snd_multipledevices) + else if (!snd_usemultipledevices.value) { - snd_multipledevices = true; + Cvar_SetValue(&snd_usemultipledevices, 1); S_Restart_f(); } return; } if (!Q_strcasecmp(command, "single")) { - snd_multipledevices = false; + Cvar_SetValue(&snd_usemultipledevices, 0); S_Restart_f(); return; } if (!Q_strcasecmp(command, "rate") || !Q_strcasecmp(command, "speed")) { - Cvar_SetValue(&snd_khz, atof(Cmd_Argv (2))/1000); + Cvar_SetValue(&snd_khz, atof(Cmd_Argv (2))/1000); S_Restart_f(); return; } @@ -449,12 +495,6 @@ void S_Init (void) // if (COM_CheckParm("-simsound")) // fakedma = true; - if (COM_CheckParm ("-nomultipledevices") || COM_CheckParm ("-singlesound")) - snd_multipledevices = false; - - if (COM_CheckParm ("-multisound")) - snd_multipledevices = true; - p = COM_CheckParm ("-soundspeed"); if (p) { @@ -462,7 +502,7 @@ void S_Init (void) Cvar_SetValue(&snd_khz, atof(com_argv[p+1])/1000); else Sys_Error ("S_Init: you must specify a speed in KB after -soundspeed"); - } + } Cmd_AddCommand("play", S_Play); @@ -496,6 +536,15 @@ void S_Init (void) Cvar_Register(&snd_inactive, "Sound controls"); Cvar_Register(&snd_playersoundvolume, "Sound controls"); + Cvar_Register(&snd_usemultipledevices, "Sound controls"); + + + if (COM_CheckParm ("-nomultipledevices") || COM_CheckParm ("-singlesound")) + Cvar_SetValue(&snd_usemultipledevices, 0); + + if (COM_CheckParm ("-multisound")) + Cvar_SetValue(&snd_usemultipledevices, 1); + if (host_parms.memsize < 0x800000) { @@ -559,12 +608,12 @@ void S_ShutdownCard(soundcardinfo_t *sc) aimedforguid = 0; #endif if (!fakedma) - { - SNDDMA_Shutdown(sc); - } + { + sc->Shutdown(sc); + } } void S_Shutdown(void) -{ +{ soundcardinfo_t *sc, *next; for (sc = sndcardinfo; sc; sc=next) { @@ -608,12 +657,12 @@ sfx_t *S_FindName (char *name) if (num_sfx == MAX_SFX) Sys_Error ("S_FindName: out of sfx_t"); - + sfx = &known_sfx[i]; strcpy (sfx->name, name); num_sfx++; - + return sfx; } @@ -627,7 +676,7 @@ S_TouchSound void S_TouchSound (char *name) { sfx_t *sfx; - + if (!sound_started) return; @@ -649,11 +698,11 @@ sfx_t *S_PrecacheSound (char *name) return NULL; sfx = S_FindName (name); - + // cache it in if (precache.value &&sndcardinfo) S_LoadSound (sfx); - + return sfx; } @@ -701,8 +750,8 @@ channel_t *SND_PickChannel(soundcardinfo_t *sc, int entnum, int entchannel) if (sc->channel[first_to_die].sfx) sc->channel[first_to_die].sfx = NULL; - return &sc->channel[first_to_die]; -} + return &sc->channel[first_to_die]; +} /* ================= @@ -732,9 +781,9 @@ void SND_Spatialize(soundcardinfo_t *sc, channel_t *ch) // calculate stereo seperation and distance attenuation snd = ch->sfx; VectorSubtract(ch->origin, listener_origin, source_vec); - + dist = VectorNormalize(source_vec) * ch->dist_mult; - + dotright = DotProduct(listener_right, source_vec); dotforward = DotProduct(listener_forward, source_vec); dotup = DotProduct(listener_up, source_vec); @@ -778,7 +827,7 @@ void S_StartSoundCard(soundcardinfo_t *sc, int entnum, int entchannel, sfx_t *sf target_chan = SND_PickChannel(sc, entnum, entchannel); if (!target_chan) return; - + // spatialize memset (target_chan, 0, sizeof(*target_chan)); if (!origin) @@ -809,7 +858,7 @@ void S_StartSoundCard(soundcardinfo_t *sc, int entnum, int entchannel, sfx_t *sf target_chan->pos = startpos; target_chan->end = sc->paintedtime + scache->length; target_chan->looping = false; - + // if an identical sound has also been started this frame, offset the pos // a bit to keep it from just making the first one louder check = &sc->channel[NUM_AMBIENTS]; @@ -917,12 +966,14 @@ void S_StopAllSoundsC (void) void S_ClearBuffer (soundcardinfo_t *sc) { + void *buffer; + int clear; -#if defined(_WIN32) && !defined(NODIRECTX) - if (!sound_started || (!sc->sn.buffer && !sc->pDSBuf)) -#else +//#if defined(_WIN32) && !defined(NODIRECTX) +// if (!sound_started || (!sc->sn.buffer && !sc->pDSBuf)) +//#else if (!sound_started || !sc->sn.buffer) -#endif +//#endif return; if (sc->sn.samplebits == 8) @@ -930,6 +981,13 @@ void S_ClearBuffer (soundcardinfo_t *sc) else clear = 0; + buffer = sc->Lock(sc); + if (buffer) + { + Q_memset(sc->sn.buffer, clear, sc->sn.samples * sc->sn.samplebits/8); + sc->Unlock(sc, buffer); + } +/* #if defined(_WIN32) && !defined(NODIRECTX) if (sc->pDSBuf) { @@ -960,13 +1018,14 @@ void S_ClearBuffer (soundcardinfo_t *sc) Q_memset(pData, clear, sc->sn.samples * sc->sn.samplebits/8); sc->pDSBuf->lpVtbl->Unlock(sc->pDSBuf, pData, dwSize, NULL, 0); - + } else #endif { Q_memset(sc->sn.buffer, clear, sc->sn.samples * sc->sn.samplebits/8); } +*/ } /* @@ -1010,7 +1069,7 @@ void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation) ss->dist_mult = (attenuation/64) / sound_nominal_clip_dist; ss->end = scard->paintedtime + scache->length; ss->looping = true; - + SND_Spatialize (scard, ss); } } @@ -1051,7 +1110,7 @@ void S_UpdateAmbientSounds (soundcardinfo_t *sc) scache = S_LoadSound (newmusic); if (scache) - { + { chan->sfx = newmusic; chan->pos = 0; chan->end = sc->paintedtime + scache->length+1000; @@ -1078,11 +1137,11 @@ void S_UpdateAmbientSounds (soundcardinfo_t *sc) for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++) { - chan = &sc->channel[ambient_channel]; + chan = &sc->channel[ambient_channel]; chan->sfx = ambient_sfx[ambient_channel]; VectorCopy(listener_origin, chan->origin); - + vol = ambient_level.value * l->ambient_sound_level[ambient_channel]; if (vol < 8) vol = 0; @@ -1100,7 +1159,7 @@ void S_UpdateAmbientSounds (soundcardinfo_t *sc) if (chan->master_vol < vol) chan->master_vol = vol; } - + chan->vol[0] = chan->vol[1] = chan->vol[2] = chan->vol[3] = chan->vol[4] = chan->vol[5] = chan->master_vol; } } @@ -1141,13 +1200,13 @@ void S_UpdateCard(soundcardinfo_t *sc) if (!sc->inactive_sound) return; } - + // update general area ambient sound sources S_UpdateAmbientSounds (sc); combine = NULL; -// update spatialization for static and dynamic sounds +// update spatialization for static and dynamic sounds ch = sc->channel+NUM_AMBIENTS+NUM_MUSICS; for (i=NUM_AMBIENTS+ NUM_MUSICS ; itotal_chans; i++, ch++) { @@ -1160,7 +1219,7 @@ void S_UpdateCard(soundcardinfo_t *sc) // try to combine static sounds with a previous channel of the same // sound effect so we don't mix five torches every frame - + if (i > MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS + NUM_MUSICS) { // see if it can just use the last one @@ -1180,7 +1239,7 @@ void S_UpdateCard(soundcardinfo_t *sc) for (j=MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS+ NUM_MUSICS ; jsfx == ch->sfx) break; - + if (j == sc->total_chans) { combine = NULL; @@ -1200,8 +1259,8 @@ void S_UpdateCard(soundcardinfo_t *sc) continue; } } - - + + } // @@ -1217,29 +1276,29 @@ void S_UpdateCard(soundcardinfo_t *sc) // Con_Printf ("%i, %i %i %i %i %i %i %s\n", i, ch->vol[0], ch->vol[1], ch->vol[2], ch->vol[3], ch->vol[4], ch->vol[5], ch->sfx->name); total++; } - + Con_Printf ("----(%i)----\n", total); } -// mix some sound +// mix some sound S_Update_(sc); } void GetSoundtime(soundcardinfo_t *sc) { - int samplepos; + int samplepos; int fullsamples; - + fullsamples = sc->sn.samples / sc->sn.numchannels; // it is possible to miscount buffers if it has wrapped twice between // calls to S_Update. Oh well. - samplepos = SNDDMA_GetDMAPos(sc); + samplepos = sc->GetDMAPos(sc); if (samplepos < sc->oldsamplepos) { sc->buffers++; // buffer wrapped - + if (sc->paintedtime > 0x40000000) { // time to chop things off to avoid 32 bit limits sc->buffers = 0; @@ -1310,28 +1369,12 @@ void S_Update_(soundcardinfo_t *sc) if (endtime - soundtime > samps) endtime = soundtime + samps; -#if defined(_WIN32) && !defined(NODIRECTX) -// if the buffer was lost or stopped, restore it and/or restart it - { - DWORD dwStatus; - - if (sc->pDSBuf) - { - if (sc->pDSBuf->lpVtbl->GetStatus (sc->pDSBuf, &dwStatus) != DD_OK) - Con_Printf ("Couldn't get sound buffer status\n"); - - if (dwStatus & DSBSTATUS_BUFFERLOST) - sc->pDSBuf->lpVtbl->Restore (sc->pDSBuf); - - if (!(dwStatus & DSBSTATUS_PLAYING)) - sc->pDSBuf->lpVtbl->Play(sc->pDSBuf, 0, 0, DSBPLAY_LOOPING); - } - } -#endif + if (sc->Restore) + sc->Restore(sc); S_PaintChannels (sc, endtime); - SNDDMA_Submit (sc); + sc->Submit(sc); } /* @@ -1348,7 +1391,7 @@ void S_Play(void) int i; char name[256]; sfx_t *sfx; - + i = 1; while (isfx, r_origin, 1, 32767, 0); } } - -#endif //cygwin diff --git a/engine/client/snd_linux.c b/engine/client/snd_linux.c index bf8e17926..36836a5f4 100644 --- a/engine/client/snd_linux.c +++ b/engine/client/snd_linux.c @@ -1,44 +1,3 @@ -#ifdef __CYGWIN__ -#include "quakedef.h" -int SNDDMA_Init(soundcardinfo_t *sc) -{ - Con_Printf("Cygwin targets do not have sound. Sorry.\n"); - return 0; -} -void S_Init(void) -{ - Con_Printf("Cygwin targets do not have sound. Sorry.\n"); -} -void S_Startup (void){} -void S_Restart_f (void){} -void SNDDMA_SetUnderWater(qboolean underwater) {} -void S_RawAudio(int sourceid, qbyte *data, int speed, int samples, int channels, int width){} -void S_Shutdown (void){} -void S_ShutdownCur (void){} -void S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation){} -void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation){} -void S_StopSound (int entnum, int entchannel){} -void S_StopAllSounds(qboolean clear){} -void S_ClearBuffer (soundcardinfo_t *sc){} -void S_Update (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up){} -void S_ExtraUpdate (void){} -sfx_t *S_PrecacheSound (char *sample) -{ - return NULL; -} -void S_TouchSound (char *sample){} -void S_LocalSound (char *s){} -void S_ClearPrecache (void){} -void S_BeginPrecaching (void){} -void S_EndPrecaching (void){} - -cvar_t bgmvolume; -cvar_t volume; -cvar_t precache; - -int snd_speed; -#else - #include #include #include @@ -51,20 +10,54 @@ int snd_speed; #include #include "quakedef.h" -qboolean snd_firsttime = true; static int tryrates[] = { 11025, 22051, 44100, 8000 }; -soundcardinfo_t *sndcardinfo; - -void SNDDMA_SetUnderWater(qboolean underwater) //simply a stub. Any ideas how to actually implement this properly? +static void OSS_SetUnderWater(qboolean underwater) //simply a stub. Any ideas how to actually implement this properly? { } -void S_UpdateCapture(void) //any ideas how to get microphone input? +static int OSS_GetDMAPos(soundcardinfo_t *sc) +{ + struct count_info count; + + if (ioctl(sc->audio_fd, SNDCTL_DSP_GETOPTR, &count)==-1) + { + perror("/dev/dsp"); + Con_Printf("Uh, sound dead.\n"); + close(sc->audio_fd); + return 0; + } +// shm->samplepos = (count.bytes / (shm->samplebits / 8)) & (shm->samples-1); +// fprintf(stderr, "%d \r", count.ptr); + sc->sn.samplepos = count.ptr / (sc->sn.samplebits / 8); + + return sc->sn.samplepos; + +} + +static void OSS_Shutdown(soundcardinfo_t *sc) +{ + if (sc->sn.buffer) //close it properly, so we can go and restart it later. + munmap(sc->sn.buffer, sc->sn.samples * (sc->sn.samplebits/8)); + if (sc->audio_fd) + close(sc->audio_fd); + *sc->name = '\0'; +} + +static void OSS_Submit(soundcardinfo_t *sc) { } -int SNDDMA_Init(soundcardinfo_t *sc) +static void *OSS_Lock(soundcardinfo_t *sc) +{ + return sc->sn.buffer; +} + +static void OSS_Unlock(soundcardinfo_t *sc, void *buffer) +{ +} + +static int OSS_InitCard(soundcardinfo_t *sc, int cardnum) { //FIXME: implement snd_multipledevices somehow. int rc; int fmt; @@ -96,22 +89,22 @@ int SNDDMA_Init(soundcardinfo_t *sc) { perror(snddev); Con_Printf("Could not open %s\n", snddev); - + devname = Cvar_Get("snd_devicename2", "", 0, "Sound controls"); snddev = devname->string; if (*snddev) //try a secondary if they named one { printf("Initing sound device %s\n", snddev); sc->audio_fd = open(snddev, O_RDWR | O_NONBLOCK); - + if (sc->audio_fd < 0) Con_Printf("Could not open %s\n", snddev); } - + if (sc->audio_fd < 0) { Con_Printf("Running without sound\n"); - SNDDMA_Shutdown(sc); + OSS_Shutdown(sc); return 0; } } @@ -122,7 +115,7 @@ int SNDDMA_Init(soundcardinfo_t *sc) { perror(snddev); Con_Printf("Could not reset %s\n", snddev); - SNDDMA_Shutdown(sc); + OSS_Shutdown(sc); return 0; } @@ -130,25 +123,25 @@ int SNDDMA_Init(soundcardinfo_t *sc) { perror(snddev); Con_Printf("Sound driver too old\n"); - SNDDMA_Shutdown(sc); + OSS_Shutdown(sc); return 0; } if (!(caps & DSP_CAP_TRIGGER) || !(caps & DSP_CAP_MMAP)) { Con_Printf("Sorry but your soundcard can't do this\n"); - SNDDMA_Shutdown(sc); + OSS_Shutdown(sc); return 0; } if (ioctl(sc->audio_fd, SNDCTL_DSP_GETOSPACE, &info)==-1) - { + { perror("GETOSPACE"); Con_Printf("Um, can't do GETOSPACE?\n"); - SNDDMA_Shutdown(sc); + OSS_Shutdown(sc); return 0; } - + sc->sn.splitbuffer = 0; // set sample bits & speed @@ -195,12 +188,12 @@ int SNDDMA_Init(soundcardinfo_t *sc) // memory map the dma buffer sc->sn.buffer = (unsigned char *) mmap(NULL, info.fragstotal - * info.fragsize, PROT_WRITE, MAP_FILE|MAP_SHARED, sc->audio_fd, 0); + * info.fragsize, PROT_WRITE, MAP_FILE|MAP_SHARED, sc->audio_fd, 0); if (!sc->sn.buffer) { perror(snddev); Con_Printf("Could not mmap %s\n", snddev); - SNDDMA_Shutdown(sc); + OSS_Shutdown(sc); return 0; } @@ -212,7 +205,7 @@ int SNDDMA_Init(soundcardinfo_t *sc) { perror(snddev); Con_Printf("Could not set %s to stereo=%d", snddev, sc->sn.numchannels); - SNDDMA_Shutdown(sc); + OSS_Shutdown(sc); return 0; } if (tmp) @@ -225,19 +218,19 @@ int SNDDMA_Init(soundcardinfo_t *sc) { perror(snddev); Con_Printf("Could not set %s speed to %d", snddev, sc->sn.speed); - SNDDMA_Shutdown(sc); + OSS_Shutdown(sc); return 0; } if (sc->sn.samplebits == 16) - { + { rc = AFMT_S16_LE; rc = ioctl(sc->audio_fd, SNDCTL_DSP_SETFMT, &rc); if (rc < 0) { perror(snddev); Con_Printf("Could not support 16-bit data. Try 8-bit.\n"); - SNDDMA_Shutdown(sc); + OSS_Shutdown(sc); return 0; } } @@ -249,7 +242,7 @@ int SNDDMA_Init(soundcardinfo_t *sc) { perror(snddev); Con_Printf("Could not support 8-bit data.\n"); - SNDDMA_Shutdown(sc); + OSS_Shutdown(sc); return 0; } } @@ -257,7 +250,7 @@ int SNDDMA_Init(soundcardinfo_t *sc) { perror(snddev); Con_Printf("%d-bit sound not supported.", sc->sn.samplebits); - SNDDMA_Shutdown(sc); + OSS_Shutdown(sc); return 0; } @@ -269,7 +262,7 @@ int SNDDMA_Init(soundcardinfo_t *sc) { perror(snddev); Con_Printf("Could not toggle.\n"); - SNDDMA_Shutdown(sc); + OSS_Shutdown(sc); return 0; } tmp = PCM_ENABLE_OUTPUT; @@ -278,52 +271,26 @@ int SNDDMA_Init(soundcardinfo_t *sc) { perror(snddev); Con_Printf("Could not toggle.\n"); - SNDDMA_Shutdown(sc); + OSS_Shutdown(sc); return 0; } sc->sn.samplepos = 0; + sc->Lock = OSS_Lock; + sc->Unlock = OSS_Unlock; + sc->SetWaterDistortion = OSS_SetUnderWater; + sc->Submit = OSS_Submit; + sc->Shutdown = OSS_Shutdown; + sc->GetDMAPos = OSS_GetDMAPos; + return 1; } -int SNDDMA_GetDMAPos(soundcardinfo_t *sc) -{ - struct count_info count; +int (*pOSS_InitCard) (soundcardinfo_t *sc, int cardnum) = &OSS_InitCard; - if (ioctl(sc->audio_fd, SNDCTL_DSP_GETOPTR, &count)==-1) - { - perror("/dev/dsp"); - Con_Printf("Uh, sound dead.\n"); - close(sc->audio_fd); - return 0; - } -// shm->samplepos = (count.bytes / (shm->samplebits / 8)) & (shm->samples-1); -// fprintf(stderr, "%d \r", count.ptr); - sc->sn.samplepos = count.ptr / (sc->sn.samplebits / 8); - return sc->sn.samplepos; -} - -void SNDDMA_Shutdown(soundcardinfo_t *sc) -{ - if (sc->sn.buffer) //close it properly, so we can go and restart it later. - munmap(sc->sn.buffer, sc->sn.samples * (sc->sn.samplebits/8)); - if (sc->audio_fd) - close(sc->audio_fd); - *sc->name = '\0'; -} - -/* -============== -SNDDMA_Submit - -Send sound to device if buffer isn't really the dma buffer -=============== -*/ -void SNDDMA_Submit(soundcardinfo_t *sc) +void S_UpdateCapture(void) { } - -#endif diff --git a/engine/client/snd_mem.c b/engine/client/snd_mem.c index a2e46a1dd..094d02e94 100644 --- a/engine/client/snd_mem.c +++ b/engine/client/snd_mem.c @@ -21,8 +21,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" -#ifndef __CYGWIN__ - #include "winquake.h" int cache_full_cycle; @@ -428,5 +426,3 @@ wavinfo_t GetWavinfo (char *name, qbyte *wav, int wavlength) return info; } - -#endif diff --git a/engine/client/snd_mix.c b/engine/client/snd_mix.c index 41c66d232..e0b162306 100644 --- a/engine/client/snd_mix.c +++ b/engine/client/snd_mix.c @@ -21,18 +21,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" -#ifndef __CYGWIN__ - #ifndef NOSOUNDASM #define NOSOUNDASM //since channels per sound card went to 6 (portable_samplegroup_t was changed) #endif -#ifdef _WIN32 -#include "winquake.h" -#else -#define DWORD unsigned long -#endif - #define PAINTBUFFER_SIZE 2048 portable_samplegroup_t paintbuffer[PAINTBUFFER_SIZE]; int snd_scaletable[32][256]; @@ -72,49 +64,16 @@ void S_TransferStereo16 (soundcardinfo_t *sc, int endtime) { int lpos; int lpaintedtime; - DWORD *pbuf; -#if defined(_WIN32) && !defined(NODIRECTX) - int reps; - DWORD dwSize=0,dwSize2=0; - DWORD *pbuf2; - HRESULT hresult; -#endif + short *pbuf; snd_vol = volume.value*256; snd_p = (int *) paintbuffer; lpaintedtime = sc->paintedtime; -#if defined(_WIN32) && !defined(NODIRECTX) - if (sc->pDSBuf) - { - reps = 0; - - while ((hresult = sc->pDSBuf->lpVtbl->Lock(sc->pDSBuf, 0, sc->gSndBufSize, (void**)&pbuf, &dwSize, - (void**)&pbuf2, &dwSize2, 0)) != DS_OK) - { - if (hresult != DSERR_BUFFERLOST) - { - Con_Printf ("S_TransferStereo16: DS::Lock Sound Buffer Failed\n"); - S_ShutdownCard (sc); - SNDDMA_Init (sc); - return; - } - - if (++reps > 10000) - { - Con_Printf ("S_TransferStereo16: DS: couldn't restore buffer\n"); - S_ShutdownCard (sc); - SNDDMA_Init (sc); - return; - } - } - } - else -#endif - { - pbuf = (DWORD *)sc->sn.buffer; - } + pbuf = sc->Lock(sc); + if (!pbuf) + return; while (lpaintedtime < endtime) { @@ -139,10 +98,7 @@ void S_TransferStereo16 (soundcardinfo_t *sc, int endtime) lpaintedtime += (sc->snd_linear_count>>1); } -#if defined(_WIN32) && !defined(NODIRECTX) - if (sc->pDSBuf) - sc->pDSBuf->lpVtbl->Unlock(sc->pDSBuf, pbuf, dwSize, NULL, 0); -#endif + sc->Unlock(sc, pbuf); } void Snd_WriteLinearBlastStereo16_4Speaker (soundcardinfo_t *sc) @@ -195,49 +151,16 @@ void S_Transfer4Speaker16 (soundcardinfo_t *sc, int endtime) { int lpos; int lpaintedtime; - DWORD *pbuf; -#if defined(_WIN32) && !defined(NODIRECTX) - int reps; - DWORD dwSize=0,dwSize2=0; - DWORD *pbuf2; - HRESULT hresult; -#endif + short *pbuf; snd_vol = volume.value*256; snd_p = (int *) paintbuffer; lpaintedtime = sc->paintedtime; -#if defined(_WIN32) && !defined(NODIRECTX) - if (sc->pDSBuf) - { - reps = 0; - - while ((hresult = sc->pDSBuf->lpVtbl->Lock(sc->pDSBuf, 0, sc->gSndBufSize, (void**)&pbuf, &dwSize, - (void**)&pbuf2, &dwSize2, 0)) != DS_OK) - { - if (hresult != DSERR_BUFFERLOST) - { - Con_Printf ("S_TransferStereo16: DS::Lock Sound Buffer Failed\n"); - S_ShutdownCard (sc); - SNDDMA_Init (sc); - return; - } - - if (++reps > 10000) - { - Con_Printf ("S_TransferStereo16: DS: couldn't restore buffer\n"); - S_ShutdownCard (sc); - SNDDMA_Init (sc); - return; - } - } - } - else -#endif - { - pbuf = (DWORD *)sc->sn.buffer; - } + pbuf = sc->Lock(sc); + if (!pbuf) + return; while (lpaintedtime < endtime) { @@ -262,10 +185,7 @@ void S_Transfer4Speaker16 (soundcardinfo_t *sc, int endtime) lpaintedtime += (sc->snd_linear_count>>2); } -#if defined(_WIN32) && !defined(NODIRECTX) - if (sc->pDSBuf) - sc->pDSBuf->lpVtbl->Unlock(sc->pDSBuf, pbuf, dwSize, NULL, 0); -#endif + sc->Unlock(sc, pbuf); } void Snd_WriteLinearBlast6Speaker16 (soundcardinfo_t *sc) @@ -339,49 +259,16 @@ void S_Transfer6Speaker16 (soundcardinfo_t *sc, int endtime) { int lpos; int lpaintedtime; - DWORD *pbuf; -#if defined(_WIN32) && !defined(NODIRECTX) - int reps; - DWORD dwSize=0,dwSize2=0; - DWORD *pbuf2; - HRESULT hresult; -#endif + short *pbuf; snd_vol = volume.value*256; snd_p = (int *) paintbuffer; lpaintedtime = sc->paintedtime; -#if defined(_WIN32) && !defined(NODIRECTX) - if (sc->pDSBuf) - { - reps = 0; - - while ((hresult = sc->pDSBuf->lpVtbl->Lock(sc->pDSBuf, 0, sc->gSndBufSize, (void**)&pbuf, &dwSize, - (void**)&pbuf2, &dwSize2, 0)) != DS_OK) - { - if (hresult != DSERR_BUFFERLOST) - { - Con_Printf ("S_TransferStereo16: DS::Lock Sound Buffer Failed\n"); - S_ShutdownCard (sc); - SNDDMA_Init (sc); - return; - } - - if (++reps > 10000) - { - Con_Printf ("S_TransferStereo16: DS: couldn't restore buffer\n"); - S_ShutdownCard (sc); - SNDDMA_Init (sc); - return; - } - } - } - else -#endif - { - pbuf = (DWORD *)sc->sn.buffer; - } + pbuf = sc->Lock(sc); + if (!pbuf) + return; while (lpaintedtime < endtime) { @@ -406,10 +293,7 @@ void S_Transfer6Speaker16 (soundcardinfo_t *sc, int endtime) lpaintedtime += (sc->snd_linear_count/6); } -#if defined(_WIN32) && !defined(NODIRECTX) - if (sc->pDSBuf) - sc->pDSBuf->lpVtbl->Unlock(sc->pDSBuf, pbuf, dwSize, NULL, 0); -#endif + sc->Unlock(sc, pbuf); } void S_TransferPaintBuffer(soundcardinfo_t *sc, int endtime) @@ -421,13 +305,7 @@ void S_TransferPaintBuffer(soundcardinfo_t *sc, int endtime) int step; int val; int snd_vol; - DWORD *pbuf; -#if defined(_WIN32) && !defined(NODIRECTX) - int reps; - DWORD dwSize=0,dwSize2=0; - DWORD *pbuf2; - HRESULT hresult; -#endif + short *pbuf; if (sc->sn.samplebits == 16 && sc->sn.numchannels == 2) { @@ -456,38 +334,9 @@ void S_TransferPaintBuffer(soundcardinfo_t *sc, int endtime) step = 3 - sc->sn.numchannels; snd_vol = volume.value*256; - - -#if defined(_WIN32) && !defined(NODIRECTX) - if (sc->pDSBuf) - { - reps = 0; - - while ((hresult = sc->pDSBuf->lpVtbl->Lock(sc->pDSBuf, 0, sc->gSndBufSize, (void**)&pbuf, &dwSize, - (void**)&pbuf2,&dwSize2, 0)) != DS_OK) - { - if (hresult != DSERR_BUFFERLOST) - { - Con_Printf ("S_TransferPaintBuffer: DS::Lock Sound Buffer Failed\n"); - S_ShutdownCard (sc); - SNDDMA_Init (sc); - return; - } - - if (++reps > 10000) - { - Con_Printf ("S_TransferPaintBuffer: DS: couldn't restore buffer\n"); - S_ShutdownCard (sc); - SNDDMA_Init (sc); - return; - } - } - } - else -#endif - { - pbuf = (DWORD *)sc->sn.buffer; - } + pbuf = sc->Lock(sc); + if (!pbuf) + return; if (sc->sn.samplebits == 16) { @@ -520,22 +369,7 @@ void S_TransferPaintBuffer(soundcardinfo_t *sc, int endtime) } } -#if defined(_WIN32) && !defined(NODIRECTX) - if (sc->pDSBuf) { - DWORD dwNewpos, dwWrite; - int il = sc->paintedtime; - int ir = endtime - sc->paintedtime; - - ir += il; - - sc->pDSBuf->lpVtbl->Unlock(sc->pDSBuf, pbuf, dwSize, NULL, 0); - - sc->pDSBuf->lpVtbl->GetCurrentPosition(sc->pDSBuf, &dwNewpos, &dwWrite); - -// if ((dwNewpos >= il) && (dwNewpos <= ir)) -// Con_Printf("%d-%d p %d c\n", il, ir, dwNewpos); - } -#endif + sc->Unlock(sc, pbuf); } @@ -995,5 +829,3 @@ void SND_PaintChannelFrom16_4Speaker (channel_t *ch, sfxcache_t *sc, int count) ch->pos += count; } - -#endif diff --git a/engine/client/snd_sdl.c b/engine/client/snd_sdl.c index 8023c0428..0ebab23c1 100644 --- a/engine/client/snd_sdl.c +++ b/engine/client/snd_sdl.c @@ -3,53 +3,61 @@ #include -extern cvar_t snd_khz; - #define SOUND_BUFFER_SIZE 0x0400 -int snd_inited; - -soundcardinfo_t *sndcardinfo; - -int snd_firsttime = 0; - -int aimedforguid; - -//lamocodec. -static char buffer[SOUND_BUFFER_SIZE]; -int sndpos; - -void SNDDMA_Submit(soundcardinfo_t *sc) -{ //We already wrote it into the 'dma' buffer (heh, the closest we can get to it at least) - //so we now wait for sdl to request it. - //yes, this can result in slow sound. -} -void SNDDMA_Shutdown(soundcardinfo_t *sc) +static void SSDL_Shutdown(soundcardinfo_t *sc) { - if (snd_inited) - { - snd_inited = false; - SDL_CloseAudio(); - } +Con_Printf("Shutdown SDL sound\n"); + SDL_CloseAudio(); +Con_Printf("buffer\n"); + if (sc->sn.buffer) + free(sc->sn.buffer); + sc->sn.buffer = NULL; +Con_Printf("down\n"); } -int SNDDMA_GetDMAPos(soundcardinfo_t *sc) +static unsigned int SSDL_GetDMAPos(soundcardinfo_t *sc) { - sc->sn.samplepos = (sndpos / (sc->sn.samplebits/8)) % sc->sn.samples; + sc->sn.samplepos = (sc->snd_sent / (sc->sn.samplebits/8)) % sc->sn.samples; return sc->sn.samplepos; } -void SNDDMA_Paint(void *userdata, qbyte *stream, int len) +//this function is called from inside SDL. +//transfer the 'dma' buffer into the buffer it requests. +static void SSDL_Paint(void *userdata, qbyte *stream, int len) { + soundcardinfo_t *sc = userdata; + if (len > SOUND_BUFFER_SIZE) len = SOUND_BUFFER_SIZE; //whoa nellie! - if (len > SOUND_BUFFER_SIZE - sndpos) + if (len > SOUND_BUFFER_SIZE - sc->snd_sent) { //buffer will wrap, fill in the rest - memcpy(stream, buffer + sndpos, SOUND_BUFFER_SIZE - sndpos); - len -= SOUND_BUFFER_SIZE - sndpos; - sndpos = 0; + memcpy(stream, sc->sn.buffer + sc->snd_sent, SOUND_BUFFER_SIZE - sc->snd_sent); + len -= SOUND_BUFFER_SIZE - sc->snd_sent; + sc->snd_sent = 0; } //and finish from the start - memcpy(stream, buffer + sndpos, len); - sndpos += len; + memcpy(stream, sc->sn.buffer + sc->snd_sent, len); + sc->snd_sent += len; +} + +static void *SSDL_LockBuffer(soundcardinfo_t *sc) +{ + SDL_LockAudio(); + return sc->sn.buffer; +} + +static void SSDL_UnlockBuffer(soundcardinfo_t *sc, void *buffer) +{ + SDL_UnlockAudio(); +} + +static void SSDL_SetUnderWater(soundcardinfo_t *sc, qboolean uw) +{ +} + + +static void SSDL_Submit(soundcardinfo_t *sc) +{ + //SDL will call SSDL_Paint to paint when it's time, and the sound buffer is always there... } @@ -57,16 +65,15 @@ void S_UpdateCapture(void) //any ideas how to get microphone input? { } -int SNDDMA_Init(soundcardinfo_t *sc) +static int SDL_InitCard(soundcardinfo_t *sc, int cardnum) { SDL_AudioSpec desired, obtained; - if (snd_inited) + if (cardnum) { //our init code actually calls this function multiple times, in the case that the user has multiple sound cards -// Con_Printf("Sound was already inited\n"); return 2; //erm. SDL won't allow multiple sound cards anyway. } - + Con_Printf("SDL AUDIO INITING\n"); if(SDL_InitSubSystem(SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE)) { @@ -76,24 +83,12 @@ Con_Printf("SDL AUDIO INITING\n"); memset(&desired, 0, sizeof(desired)); - if (!sc->sn.speed) - { - if (snd_khz.value >= 45) - sc->sn.speed = 48000; - else if (snd_khz.value >= 30) //set by a slider - sc->sn.speed = 44100; - else if (snd_khz.value >= 20) - sc->sn.speed = 22050; - else - sc->sn.speed = 11025; - } - desired.freq = sc->sn.speed; desired.channels = 2; desired.samples = SOUND_BUFFER_SIZE; desired.format = AUDIO_S16; - desired.callback = SNDDMA_Paint; - desired.userdata = sc; + desired.callback = SSDL_Paint; + desired.userdata = sc; if ( SDL_OpenAudio(&desired, &obtained) < 0 ) @@ -105,14 +100,18 @@ Con_Printf("SDL AUDIO INITING\n"); sc->sn.speed = desired.freq; sc->sn.samplebits = 16; sc->sn.samples = SOUND_BUFFER_SIZE; - sc->sn.buffer = buffer; + sc->sn.buffer = malloc(SOUND_BUFFER_SIZE*sc->sn.samplebits/8); Con_Printf("Got sound %i-%i\n", obtained.freq, obtained.format); - snd_inited = true; SDL_PauseAudio(0); + + sc->Lock = SSDL_LockBuffer; + sc->Unlock = SSDL_UnlockBuffer; + sc->SetWaterDistortion = SSDL_SetUnderWater; + sc->Submit = SSDL_Submit; + sc->Shutdown = SSDL_Shutdown; + sc->GetDMAPos = SSDL_GetDMAPos; + return true; } -void SNDDMA_SetUnderWater(qboolean underwater) -{ -} - +sounddriver pSDL_InitCard = &SDL_InitCard; diff --git a/engine/client/snd_win.c b/engine/client/snd_win.c index ea64944bc..4c847352f 100644 --- a/engine/client/snd_win.c +++ b/engine/client/snd_win.c @@ -20,66 +20,23 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" #include "winquake.h" -#ifndef NODIRECTX -#define iDirectSoundCreate(a,b,c) pDirectSoundCreate(a,b,c) -#define iDirectSoundEnumerate(a,b,c) pDirectSoundEnumerate(a,b) - -HRESULT (WINAPI *pDirectSoundCreate)(GUID FAR *lpGUID, LPDIRECTSOUND FAR *lplpDS, IUnknown FAR *pUnkOuter); -HRESULT (WINAPI *pDirectSoundCaptureCreate)(GUID FAR *lpGUID, LPDIRECTSOUNDCAPTURE FAR *lplpDS, IUnknown FAR *pUnkOuter); -HRESULT (WINAPI *pDirectSoundEnumerate)(LPDSENUMCALLBACKA lpCallback, LPVOID lpContext ); -#endif - // 64K is > 1 second at 16-bit, 22050 Hz #define WAV_BUFFERS 64 #define WAV_MASK 0x3F #define WAV_BUFFER_SIZE 0x0400 #define SECONDARY_BUFFER_SIZE 0x10000 -typedef enum {SIS_SUCCESS, SIS_FAILURE, SIS_NOTAVAIL, SIS_NOMORE} sndinitstat; +static void WAV_Submit(soundcardinfo_t *sc); -static qboolean wavonly; -//static qboolean dsound_init; -//static qboolean wav_init; -qboolean snd_firsttime = true; -static qboolean primary_format_set; - -static int sample16; -//static int snd_sent, snd_completed; - - -/* - * Global variables. Must be visible to window-procedure function - * so it can unlock and free the data block after it has been played. - */ - -/* -HANDLE hData; -HPSTR lpData, lpData2; - -HGLOBAL hWaveHdr; -LPWAVEHDR lpWaveHdr; - -HWAVEOUT hWaveOut; - -WAVEOUTCAPS wavecaps; - -DWORD gSndBufSize; - -MMTIME mmstarttime; - -LPDIRECTSOUND pDS; -LPDIRECTSOUNDBUFFER pDSBuf, pDSPBuf; -*/ -HINSTANCE hInstDS; - -sndinitstat SNDDMA_InitDirect (soundcardinfo_t *sc); -qboolean SNDDMA_InitWav (soundcardinfo_t *sc); - - - - - -soundcardinfo_t *sndcardinfo; +typedef struct { + HWAVEOUT hWaveOut; + HANDLE hData; + HGLOBAL hWaveHdr; + HPSTR lpData; + LPWAVEHDR lpWaveHdr; +// DWORD mmstarttime; + DWORD gSndBufSize; +} wavhandle_t; /* ================== @@ -90,15 +47,17 @@ S_BlockSound void S_BlockSound (void) { soundcardinfo_t *sc; + wavhandle_t *wh; snd_blocked++; for (sc = sndcardinfo; sc; sc=sc->next) { - if (sc->snd_iswave && !sc->inactive_sound) + if (sc->Submit == WAV_Submit && !sc->inactive_sound) { + wh = sc->handle; if (snd_blocked == 1) - waveOutReset (sc->hWaveOut); + waveOutReset (wh->hWaveOut); } } } @@ -116,965 +75,65 @@ void S_UnblockSound (void) } +static void *WAV_Lock (soundcardinfo_t *sc) +{ + return sc->sn.buffer; +} +static void WAV_Unlock (soundcardinfo_t *sc, void *buffer) +{ +} + /* ================== FreeSound ================== */ //per device -void FreeSound (soundcardinfo_t *sc) +static void WAV_Shutdown (soundcardinfo_t *sc) { int i; + wavhandle_t *wh = sc->handle; -#ifndef NODIRECTX - if (sc->EaxKsPropertiesSet) + if (!wh) + return; + sc->handle = NULL; + + waveOutReset (wh->hWaveOut); + + if (wh->lpWaveHdr) { - IKsPropertySet_Release(sc->EaxKsPropertiesSet); + for (i=0 ; i< WAV_BUFFERS ; i++) + waveOutUnprepareHeader (wh->hWaveOut, wh->lpWaveHdr+i, sizeof(WAVEHDR)); } - if (sc->pDSBuf) + waveOutClose (wh->hWaveOut); + + if (wh->hWaveHdr) { - sc->pDSBuf->lpVtbl->Stop(sc->pDSBuf); - sc->pDSBuf->lpVtbl->Release(sc->pDSBuf); + GlobalUnlock(wh->hWaveHdr); + GlobalFree(wh->hWaveHdr); } -// only release primary buffer if it's not also the mixing buffer we just released - if (sc->pDSPBuf && (sc->pDSBuf != sc->pDSPBuf)) + if (wh->hData) { - sc->pDSPBuf->lpVtbl->Release(sc->pDSPBuf); + GlobalUnlock(wh->hData); + GlobalFree(wh->hData); } - if (sc->pDS) - { - sc->pDS->lpVtbl->SetCooperativeLevel (sc->pDS, mainwindow, DSSCL_NORMAL); - sc->pDS->lpVtbl->Release(sc->pDS); - } -#endif - if (sc->hWaveOut) - { - waveOutReset (sc->hWaveOut); + wh->hWaveOut = 0; + wh->hData = 0; + wh->hWaveHdr = 0; + wh->lpData = NULL; + wh->lpWaveHdr = NULL; - if (sc->lpWaveHdr) - { - for (i=0 ; i< WAV_BUFFERS ; i++) - waveOutUnprepareHeader (sc->hWaveOut, sc->lpWaveHdr+i, sizeof(WAVEHDR)); - } - - waveOutClose (sc->hWaveOut); - - if (sc->hWaveHdr) - { - GlobalUnlock(sc->hWaveHdr); - GlobalFree(sc->hWaveHdr); - } - - if (sc->hData) - { - GlobalUnlock(sc->hData); - GlobalFree(sc->hData); - } - - } - -#ifndef NODIRECTX - sc->pDS = NULL; - sc->pDSBuf = NULL; - sc->pDSPBuf = NULL; - sc->EaxKsPropertiesSet = NULL; - sc->dsound_init = false; -#endif - sc->hWaveOut = 0; - sc->hData = 0; - sc->hWaveHdr = 0; - sc->lpData = NULL; - sc->lpWaveHdr = NULL; - sc->wav_init = false; + Z_Free(wh); } -#ifndef NODIRECTX -const char *dsndcard; -GUID FAR *dsndguid; -int dsnd_guids; -int aimedforguid; -BOOL (CALLBACK DSEnumCallback)(GUID FAR *guid, LPCSTR str1, LPCSTR str2, LPVOID parm) + +static void WAV_SetUnderWater(soundcardinfo_t *sc, qboolean underwater) { - if (guid == NULL) - return TRUE; - if (aimedforguid == dsnd_guids) - { - dsndcard = str1; - dsndguid = guid; - } - dsnd_guids++; - return TRUE; -} - - -/* - Direct Sound. - These following defs should be moved to winquake.h somewhere. - - We tell DS to use a different wave format. We do this to gain extra channels. >2 - We still use the old stuff too, when we can for compatability. - - EAX 2 is also supported. - This is a global state. Once applied, it's applied for other programs too. - We have to do a few special things to try to ensure support in all it's different versions. -*/ - -/* new formatTag:*/ -# define WAVE_FORMAT_EXTENSIBLE (0xfffe) - -/* Speaker Positions:*/ -# define SPEAKER_FRONT_LEFT 0x1 -# define SPEAKER_FRONT_RIGHT 0x2 -# define SPEAKER_FRONT_CENTER 0x4 -# define SPEAKER_LOW_FREQUENCY 0x8 -# define SPEAKER_BACK_LEFT 0x10 -# define SPEAKER_BACK_RIGHT 0x20 -# define SPEAKER_FRONT_LEFT_OF_CENTER 0x40 -# define SPEAKER_FRONT_RIGHT_OF_CENTER 0x80 -# define SPEAKER_BACK_CENTER 0x100 -# define SPEAKER_SIDE_LEFT 0x200 -# define SPEAKER_SIDE_RIGHT 0x400 -# define SPEAKER_TOP_CENTER 0x800 -# define SPEAKER_TOP_FRONT_LEFT 0x1000 -# define SPEAKER_TOP_FRONT_CENTER 0x2000 -# define SPEAKER_TOP_FRONT_RIGHT 0x4000 -# define SPEAKER_TOP_BACK_LEFT 0x8000 -# define SPEAKER_TOP_BACK_CENTER 0x10000 -# define SPEAKER_TOP_BACK_RIGHT 0x20000 - -/* Bit mask locations reserved for future use*/ -# define SPEAKER_RESERVED 0x7FFC0000 - -/* Used to specify that any possible permutation of speaker configurations*/ -# define SPEAKER_ALL 0x80000000 - -/* DirectSound Speaker Config*/ -# define KSAUDIO_SPEAKER_MONO (SPEAKER_FRONT_CENTER) -# define KSAUDIO_SPEAKER_STEREO (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT) -# define KSAUDIO_SPEAKER_QUAD (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | \ - SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT) -# define KSAUDIO_SPEAKER_SURROUND (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | \ - SPEAKER_FRONT_CENTER | SPEAKER_BACK_CENTER) -# define KSAUDIO_SPEAKER_5POINT1 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | \ - SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | \ - SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT) -# define KSAUDIO_SPEAKER_7POINT1 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | \ - SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | \ - SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | \ - SPEAKER_FRONT_LEFT_OF_CENTER | SPEAKER_FRONT_RIGHT_OF_CENTER) - -typedef struct { - WAVEFORMATEX Format; - union { - WORD wValidBitsPerSample; /* bits of precision */ - WORD wSamplesPerBlock; /* valid if wBitsPerSample==0 */ - WORD wReserved; /* If neither applies, set to */ - /* zero. */ - } Samples; - DWORD dwChannelMask; /* which channels are */ - /* present in stream */ - GUID SubFormat; -} QWAVEFORMATEX; - -const static GUID KSDATAFORMAT_SUBTYPE_PCM = {0x00000001,0x0000,0x0010, - {0x80, - 0x00, - 0x00, - 0xaa, - 0x00, - 0x38, - 0x9b, - 0x71}}; - -#ifdef _IKsPropertySet_ -const static GUID CLSID_EAXDIRECTSOUND = {0x4ff53b81, 0x1ce0, 0x11d3, -{0xaa, 0xb8, 0x0, 0xa0, 0xc9, 0x59, 0x49, 0xd5}}; -const static GUID DSPROPSETID_EAX20_LISTENERPROPERTIES = {0x306a6a8, 0xb224, 0x11d2, -{0x99, 0xe5, 0x0, 0x0, 0xe8, 0xd8, 0xc7, 0x22}}; - -typedef struct _EAXLISTENERPROPERTIES -{ - long lRoom; // room effect level at low frequencies - long lRoomHF; // room effect high-frequency level re. low frequency level - float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect - float flDecayTime; // reverberation decay time at low frequencies - float flDecayHFRatio; // high-frequency to low-frequency decay time ratio - long lReflections; // early reflections level relative to room effect - float flReflectionsDelay; // initial reflection delay time - long lReverb; // late reverberation level relative to room effect - float flReverbDelay; // late reverberation delay time relative to initial reflection - unsigned long dwEnvironment; // sets all listener properties - float flEnvironmentSize; // environment size in meters - float flEnvironmentDiffusion; // environment diffusion - float flAirAbsorptionHF; // change in level per meter at 5 kHz - unsigned long dwFlags; // modifies the behavior of properties -} EAXLISTENERPROPERTIES, *LPEAXLISTENERPROPERTIES; -enum -{ - EAX_ENVIRONMENT_GENERIC, - EAX_ENVIRONMENT_PADDEDCELL, - EAX_ENVIRONMENT_ROOM, - EAX_ENVIRONMENT_BATHROOM, - EAX_ENVIRONMENT_LIVINGROOM, - EAX_ENVIRONMENT_STONEROOM, - EAX_ENVIRONMENT_AUDITORIUM, - EAX_ENVIRONMENT_CONCERTHALL, - EAX_ENVIRONMENT_CAVE, - EAX_ENVIRONMENT_ARENA, - EAX_ENVIRONMENT_HANGAR, - EAX_ENVIRONMENT_CARPETEDHALLWAY, - EAX_ENVIRONMENT_HALLWAY, - EAX_ENVIRONMENT_STONECORRIDOR, - EAX_ENVIRONMENT_ALLEY, - EAX_ENVIRONMENT_FOREST, - EAX_ENVIRONMENT_CITY, - EAX_ENVIRONMENT_MOUNTAINS, - EAX_ENVIRONMENT_QUARRY, - EAX_ENVIRONMENT_PLAIN, - EAX_ENVIRONMENT_PARKINGLOT, - EAX_ENVIRONMENT_SEWERPIPE, - EAX_ENVIRONMENT_UNDERWATER, - EAX_ENVIRONMENT_DRUGGED, - EAX_ENVIRONMENT_DIZZY, - EAX_ENVIRONMENT_PSYCHOTIC, - - EAX_ENVIRONMENT_COUNT -}; -typedef enum -{ - DSPROPERTY_EAXLISTENER_NONE, - DSPROPERTY_EAXLISTENER_ALLPARAMETERS, - DSPROPERTY_EAXLISTENER_ROOM, - DSPROPERTY_EAXLISTENER_ROOMHF, - DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR, - DSPROPERTY_EAXLISTENER_DECAYTIME, - DSPROPERTY_EAXLISTENER_DECAYHFRATIO, - DSPROPERTY_EAXLISTENER_REFLECTIONS, - DSPROPERTY_EAXLISTENER_REFLECTIONSDELAY, - DSPROPERTY_EAXLISTENER_REVERB, - DSPROPERTY_EAXLISTENER_REVERBDELAY, - DSPROPERTY_EAXLISTENER_ENVIRONMENT, - DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE, - DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION, - DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF, - DSPROPERTY_EAXLISTENER_FLAGS -} DSPROPERTY_EAX_LISTENERPROPERTY; - -const static GUID DSPROPSETID_EAX20_BUFFERPROPERTIES ={ - 0x306a6a7, - 0xb224, - 0x11d2, - {0x99, 0xe5, 0x0, 0x0, 0xe8, 0xd8, 0xc7, 0x22}}; - -const static GUID CLSID_EAXDirectSound ={ - 0x4ff53b81, - 0x1ce0, - 0x11d3, - {0xaa, 0xb8, 0x0, 0xa0, 0xc9, 0x59, 0x49, 0xd5}}; - -typedef struct _EAXBUFFERPROPERTIES -{ - long lDirect; // direct path level - long lDirectHF; // direct path level at high frequencies - long lRoom; // room effect level - long lRoomHF; // room effect level at high frequencies - float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect - long lObstruction; // main obstruction control (attenuation at high frequencies) - float flObstructionLFRatio; // obstruction low-frequency level re. main control - long lOcclusion; // main occlusion control (attenuation at high frequencies) - float flOcclusionLFRatio; // occlusion low-frequency level re. main control - float flOcclusionRoomRatio; // occlusion room effect level re. main control - long lOutsideVolumeHF; // outside sound cone level at high frequencies - float flAirAbsorptionFactor; // multiplies DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF - unsigned long dwFlags; // modifies the behavior of properties -} EAXBUFFERPROPERTIES, *LPEAXBUFFERPROPERTIES; - -typedef enum -{ - DSPROPERTY_EAXBUFFER_NONE, - DSPROPERTY_EAXBUFFER_ALLPARAMETERS, - DSPROPERTY_EAXBUFFER_DIRECT, - DSPROPERTY_EAXBUFFER_DIRECTHF, - DSPROPERTY_EAXBUFFER_ROOM, - DSPROPERTY_EAXBUFFER_ROOMHF, - DSPROPERTY_EAXBUFFER_ROOMROLLOFFFACTOR, - DSPROPERTY_EAXBUFFER_OBSTRUCTION, - DSPROPERTY_EAXBUFFER_OBSTRUCTIONLFRATIO, - DSPROPERTY_EAXBUFFER_OCCLUSION, - DSPROPERTY_EAXBUFFER_OCCLUSIONLFRATIO, - DSPROPERTY_EAXBUFFER_OCCLUSIONROOMRATIO, - DSPROPERTY_EAXBUFFER_OUTSIDEVOLUMEHF, - DSPROPERTY_EAXBUFFER_AIRABSORPTIONFACTOR, - DSPROPERTY_EAXBUFFER_FLAGS -} DSPROPERTY_EAX_BUFFERPROPERTY; -#endif - -/* -================== -SNDDMA_InitDirect - -Direct-Sound support -================== -*/ -sndinitstat SNDDMA_InitDirect (soundcardinfo_t *sc) -{ - extern cvar_t snd_khz, snd_eax, snd_speakers, snd_inactive; - DSBUFFERDESC dsbuf; - DSBCAPS dsbcaps; - DWORD dwSize, dwWrite; - DSCAPS dscaps; - QWAVEFORMATEX format, pformat; - HRESULT hresult; - int reps; - - memset ((void *)&sc->sn, 0, sizeof (sc->sn)); - - sc->sn.numchannels = 2; - sc->sn.samplebits = 16; - if (!sc->sn.speed) - { - if (snd_khz.value >= 45) - sc->sn.speed = 48000; - else if (snd_khz.value >= 30) //set by a slider - sc->sn.speed = 44100; - else if (snd_khz.value >= 20) - sc->sn.speed = 22050; - else - sc->sn.speed = 11025; - } - - memset (&format, 0, sizeof(format)); - - if (snd_speakers.value >= 5) //5.1 surround - { - format.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; - format.Format.cbSize = 22; - memcpy(&format.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM, sizeof(GUID)); - - format.dwChannelMask = KSAUDIO_SPEAKER_5POINT1; - sc->sn.numchannels = 6; - } - else if (snd_speakers.value >= 3) //4 speaker quad - { - format.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; - format.Format.cbSize = 22; - memcpy(&format.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM, sizeof(GUID)); - - format.dwChannelMask = KSAUDIO_SPEAKER_QUAD; - sc->sn.numchannels = 4; - } - else if (snd_speakers.value >= 1.5) //stereo - { - format.Format.wFormatTag = WAVE_FORMAT_PCM; - format.Format.cbSize = 0; - sc->sn.numchannels = 2; - } - else //mono time - { - format.Format.wFormatTag = WAVE_FORMAT_PCM; - format.Format.cbSize = 0; - sc->sn.numchannels = 1; - } - - format.Format.nChannels = sc->sn.numchannels; - format.Format.wBitsPerSample = sc->sn.samplebits; - format.Format.nSamplesPerSec = sc->sn.speed; - format.Format.nBlockAlign = format.Format.nChannels - *format.Format.wBitsPerSample / 8; - format.Format.nAvgBytesPerSec = format.Format.nSamplesPerSec - *format.Format.nBlockAlign; - - if (!hInstDS) - { - hInstDS = LoadLibrary("dsound.dll"); - - if (hInstDS == NULL) - { - Con_SafePrintf ("Couldn't load dsound.dll\n"); - return SIS_FAILURE; - } - - pDirectSoundCreate = (void *)GetProcAddress(hInstDS,"DirectSoundCreate"); - - if (!pDirectSoundCreate) - { - Con_SafePrintf ("Couldn't get DS proc addr\n"); - return SIS_FAILURE; - } - - pDirectSoundEnumerate = (void *)GetProcAddress(hInstDS,"DirectSoundEnumerateA"); - } - - dsnd_guids=0; - dsndguid=NULL; - dsndcard="DirectSound"; - if (pDirectSoundEnumerate) - pDirectSoundEnumerate(&DSEnumCallback, NULL); - if (!snd_multipledevices) - dsndguid=NULL; - - aimedforguid++; - - if (!dsndguid) //no more... - if (aimedforguid != 1) //not the first device. - return SIS_NOMORE; - //EAX attempt -#ifndef MINIMAL - sc->pDS = NULL; - if (snd_eax.value) - { - CoInitialize(NULL); - if (FAILED(CoCreateInstance( &CLSID_EAXDirectSound, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectSound, (void **)&sc->pDS ))) - sc->pDS=NULL; - else - IDirectSound_Initialize(sc->pDS, dsndguid); - } - - if (!sc->pDS) -#endif - { - while ((hresult = iDirectSoundCreate(dsndguid, &sc->pDS, NULL)) != DS_OK) - { - if (hresult != DSERR_ALLOCATED) - { - Con_SafePrintf (": create failed\n"); - return SIS_FAILURE; - } - -// if (MessageBox (NULL, -// "The sound hardware is in use by another app.\n\n" -// "Select Retry to try to start sound again or Cancel to run Quake with no sound.", -// "Sound not available", -// MB_RETRYCANCEL | MB_SETFOREGROUND | MB_ICONEXCLAMATION) != IDRETRY) -// { - Con_SafePrintf (": failure\n" - " hardware already in use\n" - " Close the other app then use snd_restart\n"); - return SIS_NOTAVAIL; -// } - } - } - Q_strncpyz(sc->name, dsndcard, sizeof(sc->name)); - - dscaps.dwSize = sizeof(dscaps); - - if (DS_OK != sc->pDS->lpVtbl->GetCaps (sc->pDS, &dscaps)) - { - Con_SafePrintf ("Couldn't get DS caps\n"); - } - - if (dscaps.dwFlags & DSCAPS_EMULDRIVER) - { - Con_SafePrintf ("No DirectSound driver installed\n"); - FreeSound (sc); - return SIS_FAILURE; - } - - if (DS_OK != sc->pDS->lpVtbl->SetCooperativeLevel (sc->pDS, mainwindow, DSSCL_EXCLUSIVE)) - { - Con_SafePrintf ("Set coop level failed\n"); - FreeSound (sc); - return SIS_FAILURE; - } - - -// get access to the primary buffer, if possible, so we can set the -// sound hardware format - memset (&dsbuf, 0, sizeof(dsbuf)); - dsbuf.dwSize = sizeof(DSBUFFERDESC); - dsbuf.dwFlags = DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME; - dsbuf.dwBufferBytes = 0; - dsbuf.lpwfxFormat = NULL; - - memset(&dsbcaps, 0, sizeof(dsbcaps)); - dsbcaps.dwSize = sizeof(dsbcaps); - primary_format_set = false; - - if (!COM_CheckParm ("-snoforceformat")) - { - if (DS_OK == sc->pDS->lpVtbl->CreateSoundBuffer(sc->pDS, &dsbuf, &sc->pDSPBuf, NULL)) - { - pformat = format; - - if (DS_OK != sc->pDSPBuf->lpVtbl->SetFormat (sc->pDSPBuf, (WAVEFORMATEX *)&pformat)) - { -// if (snd_firsttime) -// Con_SafePrintf ("Set primary sound buffer format: no\n"); - } - else -// { -// if (snd_firsttime) -// Con_SafePrintf ("Set primary sound buffer format: yes\n"); - - primary_format_set = true; -// } - } - } - - if (!primary_format_set || !COM_CheckParm ("-primarysound")) - { - // create the secondary buffer we'll actually work with - memset (&dsbuf, 0, sizeof(dsbuf)); - dsbuf.dwSize = sizeof(DSBUFFERDESC); - dsbuf.dwFlags = DSBCAPS_CTRLFREQUENCY; //dmw 29 may, 2003 removed locsoftware - if (snd_inactive.value) - { - dsbuf.dwFlags |= DSBCAPS_GLOBALFOCUS; - sc->inactive_sound = true; - } - dsbuf.dwBufferBytes = SECONDARY_BUFFER_SIZE; - dsbuf.lpwfxFormat = (WAVEFORMATEX *)&format; - - memset(&dsbcaps, 0, sizeof(dsbcaps)); - dsbcaps.dwSize = sizeof(dsbcaps); - - if (DS_OK != sc->pDS->lpVtbl->CreateSoundBuffer(sc->pDS, &dsbuf, &sc->pDSBuf, NULL)) - { - Con_SafePrintf ("DS:CreateSoundBuffer Failed"); - FreeSound (sc); - return SIS_FAILURE; - } - - sc->sn.numchannels = format.Format.nChannels; - sc->sn.samplebits = format.Format.wBitsPerSample; - sc->sn.speed = format.Format.nSamplesPerSec; - - if (DS_OK != sc->pDSBuf->lpVtbl->GetCaps (sc->pDSBuf, &dsbcaps)) - { - Con_SafePrintf ("DS:GetCaps failed\n"); - FreeSound (sc); - return SIS_FAILURE; - } - -// if (snd_firsttime) -// Con_SafePrintf ("Using secondary sound buffer\n"); - } - else - { - if (DS_OK != sc->pDS->lpVtbl->SetCooperativeLevel (sc->pDS, mainwindow, DSSCL_WRITEPRIMARY)) - { - Con_SafePrintf ("Set coop level failed\n"); - FreeSound (sc); - return SIS_FAILURE; - } - - if (DS_OK != sc->pDSPBuf->lpVtbl->GetCaps (sc->pDSPBuf, &dsbcaps)) - { - Con_Printf ("DS:GetCaps failed\n"); - return SIS_FAILURE; - } - - sc->pDSBuf = sc->pDSPBuf; -// Con_SafePrintf ("Using primary sound buffer\n"); - } - - sc->gSndBufSize = dsbcaps.dwBufferBytes; - -#if 1 - // Make sure mixer is active - sc->pDSBuf->lpVtbl->Play(sc->pDSBuf, 0, 0, DSBPLAY_LOOPING); - -/* if (snd_firsttime) - Con_SafePrintf(" %d channel(s)\n" - " %d bits/sample\n" - " %d bytes/sec\n", - shm->channels, shm->samplebits, shm->speed);*/ - - -// initialize the buffer - reps = 0; - - while ((hresult = sc->pDSBuf->lpVtbl->Lock(sc->pDSBuf, 0, sc->gSndBufSize, (void**)&sc->lpData, &dwSize, NULL, NULL, 0)) != DS_OK) - { - if (hresult != DSERR_BUFFERLOST) - { - Con_SafePrintf ("SNDDMA_InitDirect: DS::Lock Sound Buffer Failed\n"); - FreeSound (sc); - return SIS_FAILURE; - } - - if (++reps > 10000) - { - Con_SafePrintf ("SNDDMA_InitDirect: DS: couldn't restore buffer\n"); - FreeSound (sc); - return SIS_FAILURE; - } - } - - memset(sc->lpData, 0, dwSize); -// lpData[4] = lpData[5] = 0x7f; // force a pop for debugging - -// Sleep(500); - - sc->pDSBuf->lpVtbl->Unlock(sc->pDSBuf, sc->lpData, dwSize, NULL, 0); - - /* we don't want anyone to access the buffer directly w/o locking it first. */ - sc->lpData = NULL; - sc->pDSBuf->lpVtbl->Stop(sc->pDSBuf); -#endif - sc->pDSBuf->lpVtbl->GetCurrentPosition(sc->pDSBuf, &sc->mmstarttime, &dwWrite); - sc->pDSBuf->lpVtbl->Play(sc->pDSBuf, 0, 0, DSBPLAY_LOOPING); - - sc->sn.soundalive = true; - sc->sn.splitbuffer = false; - sc->sn.samples = sc->gSndBufSize/(sc->sn.samplebits/8); - sc->sn.samplepos = 0; - sc->sn.submission_chunk = 1; - sc->sn.buffer = (unsigned char *) sc->lpData; - sample16 = (sc->sn.samplebits/8) - 1; - - sc->dsound_init = true; - -#ifdef _IKsPropertySet_ - //attempt at eax support - if (snd_eax.value) - { - int r; - DWORD support; - - if (SUCCEEDED(IDirectSoundBuffer_QueryInterface(sc->pDSBuf, &IID_IKsPropertySet, (void*)&sc->EaxKsPropertiesSet))) - { - r = IKsPropertySet_QuerySupport(sc->EaxKsPropertiesSet, &DSPROPSETID_EAX20_LISTENERPROPERTIES, DSPROPERTY_EAXLISTENER_ALLPARAMETERS, &support); - if(!SUCCEEDED(r) || (support&(KSPROPERTY_SUPPORT_GET|KSPROPERTY_SUPPORT_SET)) - != (KSPROPERTY_SUPPORT_GET|KSPROPERTY_SUPPORT_SET)) - { - IKsPropertySet_Release(sc->EaxKsPropertiesSet); - sc->EaxKsPropertiesSet = NULL; - Con_SafePrintf ("EAX 2 not supported\n"); - return SIS_SUCCESS;//otherwise successful. It can be used for normal sound anyway. - } - - //worked. EAX is supported. - } - else - { - Con_SafePrintf ("Couldn't get extended properties\n"); - sc->EaxKsPropertiesSet = NULL; - } - } -#endif - return SIS_SUCCESS; -} -#endif -void SNDDMA_SetUnderWater(qboolean underwater) -{ -#ifndef NODIRECTX - soundcardinfo_t *sc; -#ifdef _IKsPropertySet_ - //attempt at eax support. - //EAX is a global thing. Get it going in a game and your media player will be doing it too. - - for (sc = sndcardinfo; sc; sc = sc->next) - if (sc->EaxKsPropertiesSet) //only on ds cards. - { - EAXLISTENERPROPERTIES ListenerProperties = {0}; - -/* DWORD p; - IKsPropertySet_Get(sc->EaxKsPropertiesSet, &DSPROPSETID_EAX20_LISTENERPROPERTIES, - DSPROPERTY_EAXLISTENER_ALLPARAMETERS, 0, 0, &ListenerProperties, - sizeof(ListenerProperties), &p); -*/ - if (underwater) - { -#if 1 //phycotic. - ListenerProperties.flEnvironmentSize = 2.8; - ListenerProperties.flEnvironmentDiffusion = 0.240; - ListenerProperties.lRoom = -374; - ListenerProperties.lRoomHF = -150; - ListenerProperties.flRoomRolloffFactor = 0; - ListenerProperties.flAirAbsorptionHF = -5; - ListenerProperties.lReflections = -10000; - ListenerProperties.flReflectionsDelay = 0.053; - ListenerProperties.lReverb = 625; - ListenerProperties.flReverbDelay = 0.08; - ListenerProperties.flDecayTime = 5.096; - ListenerProperties.flDecayHFRatio = 0.910; - ListenerProperties.dwFlags = 0x3f; - ListenerProperties.dwEnvironment = EAX_ENVIRONMENT_PSYCHOTIC; -#else - ListenerProperties.flEnvironmentSize = 5.8; - ListenerProperties.flEnvironmentDiffusion = 0; - ListenerProperties.lRoom = -374; - ListenerProperties.lRoomHF = -2860; - ListenerProperties.flRoomRolloffFactor = 0; - ListenerProperties.flAirAbsorptionHF = -5; - ListenerProperties.lReflections = -889; - ListenerProperties.flReflectionsDelay = 0.024; - ListenerProperties.lReverb = 797; - ListenerProperties.flReverbDelay = 0.035; - ListenerProperties.flDecayTime = 5.568; - ListenerProperties.flDecayHFRatio = 0.100; - ListenerProperties.dwFlags = 0x3f; - ListenerProperties.dwEnvironment = EAX_ENVIRONMENT_UNDERWATER; -#endif - } - else - { - ListenerProperties.flEnvironmentSize = 1; - ListenerProperties.flEnvironmentDiffusion = 0; - ListenerProperties.lRoom = 0; - ListenerProperties.lRoomHF = 0; - ListenerProperties.flRoomRolloffFactor = 0; - ListenerProperties.flAirAbsorptionHF = 0; - ListenerProperties.lReflections = 1000; - ListenerProperties.flReflectionsDelay = 0; - ListenerProperties.lReverb = 813; - ListenerProperties.flReverbDelay = 0.00; - ListenerProperties.flDecayTime = 0.1; - ListenerProperties.flDecayHFRatio = 0.1; - ListenerProperties.dwFlags = 0x3f; - ListenerProperties.dwEnvironment = EAX_ENVIRONMENT_GENERIC; - } - -// env = EAX_ENVIRONMENT_UNDERWATER; - - if (FAILED(IKsPropertySet_Set(sc->EaxKsPropertiesSet, &DSPROPSETID_EAX20_LISTENERPROPERTIES, - DSPROPERTY_EAXLISTENER_ALLPARAMETERS, 0, 0, &ListenerProperties, - sizeof(ListenerProperties)))) - Con_SafePrintf ("EAX set failed\n"); - } -#endif -#endif -} -/* -================== -SNDDM_InitWav - -Crappy windows multimedia base -================== -*/ -qboolean SNDDMA_InitWav (soundcardinfo_t *sc) -{ - extern cvar_t snd_khz; - WAVEFORMATEX format; - int i; - HRESULT hr; - - sc->snd_sent = 0; - sc->snd_completed = 0; - - sc->sn.numchannels = 2; - sc->sn.samplebits = 16; - - if (!sc->sn.speed) - { - if (snd_khz.value == 48) - sc->sn.speed = 48000; - else if (snd_khz.value == 44 || snd_khz.value == 44.1) - sc->sn.speed = 44100; - else if (snd_khz.value == 22 || snd_khz.value == 22.05) - sc->sn.speed = 22050; - else - sc->sn.speed = 11025; - } - - memset (&format, 0, sizeof(format)); - format.wFormatTag = WAVE_FORMAT_PCM; - format.nChannels = sc->sn.numchannels; - format.wBitsPerSample = sc->sn.samplebits; - format.nSamplesPerSec = sc->sn.speed; - format.nBlockAlign = format.nChannels - *format.wBitsPerSample / 8; - format.cbSize = 0; - format.nAvgBytesPerSec = format.nSamplesPerSec - *format.nBlockAlign; - - /* Open a waveform device for output using window callback. */ - while ((hr = waveOutOpen((LPHWAVEOUT)&sc->hWaveOut, WAVE_MAPPER, - &format, - 0, 0L, CALLBACK_NULL)) != MMSYSERR_NOERROR) - { - if (hr != MMSYSERR_ALLOCATED) - { - Con_SafePrintf ("waveOutOpen failed\n"); - return false; - } - -// if (MessageBox (NULL, -// "The sound hardware is in use by another app.\n\n" -// "Select Retry to try to start sound again or Cancel to run Quake with no sound.", -// "Sound not available", -// MB_RETRYCANCEL | MB_SETFOREGROUND | MB_ICONEXCLAMATION) != IDRETRY) -// { - Con_SafePrintf ("waveOutOpen failure;\n" - " hardware already in use\nclose the app, then try using snd_restart\n"); - return false; -// } - } - - /* - * Allocate and lock memory for the waveform data. The memory - * for waveform data must be globally allocated with - * GMEM_MOVEABLE and GMEM_SHARE flags. - - */ - sc->gSndBufSize = WAV_BUFFERS*WAV_BUFFER_SIZE; - sc->hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, sc->gSndBufSize); - if (!sc->hData) - { - Con_SafePrintf ("Sound: Out of memory.\n"); - FreeSound (sc); - return false; - } - sc->lpData = GlobalLock(sc->hData); - if (!sc->lpData) - { - Con_SafePrintf ("Sound: Failed to lock.\n"); - FreeSound (sc); - return false; - } - memset (sc->lpData, 0, sc->gSndBufSize); - - /* - * Allocate and lock memory for the header. This memory must - * also be globally allocated with GMEM_MOVEABLE and - * GMEM_SHARE flags. - */ - sc->hWaveHdr = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, - (DWORD) sizeof(WAVEHDR) * WAV_BUFFERS); - - if (sc->hWaveHdr == NULL) - { - Con_SafePrintf ("Sound: Failed to Alloc header.\n"); - FreeSound (sc); - return false; - } - - sc->lpWaveHdr = (LPWAVEHDR) GlobalLock(sc->hWaveHdr); - - if (sc->lpWaveHdr == NULL) - { - Con_SafePrintf ("Sound: Failed to lock header.\n"); - FreeSound (sc); - return false; - } - - memset (sc->lpWaveHdr, 0, sizeof(WAVEHDR) * WAV_BUFFERS); - - /* After allocation, set up and prepare headers. */ - for (i=0 ; ilpWaveHdr[i].dwBufferLength = WAV_BUFFER_SIZE; - sc->lpWaveHdr[i].lpData = sc->lpData + i*WAV_BUFFER_SIZE; - - if (waveOutPrepareHeader(sc->hWaveOut, sc->lpWaveHdr+i, sizeof(WAVEHDR)) != - MMSYSERR_NOERROR) - { - Con_SafePrintf ("Sound: failed to prepare wave headers\n"); - FreeSound (sc); - return false; - } - } - - sc->sn.soundalive = true; - sc->sn.splitbuffer = false; - sc->sn.samples = sc->gSndBufSize/(sc->sn.samplebits/8); - sc->sn.samplepos = 0; - sc->sn.submission_chunk = 1; - sc->sn.buffer = (unsigned char *) sc->lpData; - sample16 = (sc->sn.samplebits/8) - 1; - - sc->wav_init = true; - - return true; -} - -/* -================== -SNDDMA_Init - -Try to find a sound device to mix for. -Returns false if nothing is found. -================== -*/ - -int SNDDMA_Init(soundcardinfo_t *sc) -{ - sndinitstat stat; - - if (COM_CheckParm ("-wavonly")) - wavonly = true; - - sc->inactive_sound = false; //don't generate sound when the window is inactive. - -#ifndef NODIRECTX - sc->dsound_init = -#endif - sc->wav_init = 0; - - stat = SIS_FAILURE; // assume DirectSound won't initialize - -#ifndef NODIRECTX - /* Init DirectSound */ - if (!wavonly) - { - if (snd_firsttime || sc->snd_isdirect) - { - stat = SNDDMA_InitDirect (sc); - - if (stat == SIS_SUCCESS) - { - sc->snd_isdirect = true; - - if (snd_firsttime) - Con_DPrintf ("%s initialized\n", sc->name); - - return 1; - } - else if (stat == SIS_NOMORE) - return 2; - else - { - sc->snd_isdirect = false; - Con_DPrintf ("DirectSound failed to init\n"); - } - } - } -#endif - -// if DirectSound didn't succeed in initializing, try to initialize -// waveOut sound, unless DirectSound failed because the hardware is -// already allocated (in which case the user has already chosen not -// to have sound) -#ifndef NODIRECTX - if (!sc->dsound_init && (stat != SIS_NOTAVAIL)) -#endif - { - if (snd_firsttime || sc->snd_iswave) - { - - sc->snd_iswave = SNDDMA_InitWav (sc); - - if (sc->snd_iswave) - { - if (snd_firsttime) - Con_SafePrintf ("Wave sound initialized\n"); - } - else - { - Con_SafePrintf ("Wave sound failed to init\n"); - } - } - } - - snd_firsttime = false; - -#ifndef NODIRECTX - if (!sc->dsound_init && !sc->wav_init) -#endif - { - if (snd_firsttime) - Con_SafePrintf ("No sound device initialized\n"); - - return 2; - } - - return 1; } /* @@ -1086,29 +145,14 @@ inside the recirculating dma buffer, so the mixing code will know how many sample are required to fill it up. =============== */ -int SNDDMA_GetDMAPos(soundcardinfo_t *sc) +static int WAV_GetDMAPos(soundcardinfo_t *sc) { - DWORD mmtime; int s; - DWORD dwWrite; -#ifndef NODIRECTX - if (sc->dsound_init) - { - sc->pDSBuf->lpVtbl->GetCurrentPosition(sc->pDSBuf, &mmtime, &dwWrite); - s = mmtime - sc->mmstarttime; - } - else -#endif - if (sc->wav_init) - { - s = sc->snd_sent * WAV_BUFFER_SIZE; - } - else - s = 0; + s = sc->snd_sent * WAV_BUFFER_SIZE; - s >>= sample16; + s >>= (sc->sn.samplebits/8) - 1; // s = (s/shm->numchannels % (shm->samples-1))*shm->numchannels; @@ -1117,18 +161,16 @@ int SNDDMA_GetDMAPos(soundcardinfo_t *sc) /* ============== -SNDDMA_Submit +WAV_Submit Send sound to device if buffer isn't really the dma buffer =============== */ -void SNDDMA_Submit(soundcardinfo_t *sc) +static void WAV_Submit(soundcardinfo_t *sc) { LPWAVEHDR h; int wResult; - - if (!sc->wav_init) - return; + wavhandle_t *wh = sc->handle; // // find which sound blocks have completed @@ -1141,7 +183,7 @@ void SNDDMA_Submit(soundcardinfo_t *sc) break; } - if ( ! (sc->lpWaveHdr[ sc->snd_completed & WAV_MASK].dwFlags & WHDR_DONE) ) + if ( ! (wh->lpWaveHdr[ sc->snd_completed & WAV_MASK].dwFlags & WHDR_DONE) ) { break; } @@ -1152,9 +194,9 @@ void SNDDMA_Submit(soundcardinfo_t *sc) // // submit two new sound blocks // - while (((sc->snd_sent - sc->snd_completed) >> sample16) < 4) + while (((sc->snd_sent - sc->snd_completed) >> ((sc->sn.samplebits/8) - 1)) < 4) { - h = sc->lpWaveHdr + ( sc->snd_sent&WAV_MASK ); + h = wh->lpWaveHdr + ( sc->snd_sent&WAV_MASK ); sc->snd_sent++; /* @@ -1162,212 +204,160 @@ void SNDDMA_Submit(soundcardinfo_t *sc) * waveOutWrite function returns immediately and waveform * data is sent to the output device in the background. */ - wResult = waveOutWrite(sc->hWaveOut, h, sizeof(WAVEHDR)); + wResult = waveOutWrite(wh->hWaveOut, h, sizeof(WAVEHDR)); if (wResult != MMSYSERR_NOERROR) { Con_SafePrintf ("Failed to write block to device\n"); - FreeSound (sc); + WAV_Shutdown (sc); return; } } } + + /* -============== -SNDDMA_Shutdown +================== +SNDDM_InitWav -Reset the sound device for exiting -=============== +Crappy windows multimedia base +================== */ -void SNDDMA_Shutdown(soundcardinfo_t *sc) +int WAV_InitCard (soundcardinfo_t *sc, int cardnum) { - FreeSound (sc); + extern cvar_t snd_khz; + WAVEFORMATEX format; + int i; + HRESULT hr; + wavhandle_t *wh; + + if (cardnum != 0) + return 2; //we only support one card, at the moment. + + wh = sc->handle = Z_Malloc(sizeof(wavhandle_t)); + + sc->snd_sent = 0; + sc->snd_completed = 0; + + sc->sn.numchannels = 2; + sc->sn.samplebits = 16; + + memset (&format, 0, sizeof(format)); + format.wFormatTag = WAVE_FORMAT_PCM; + format.nChannels = sc->sn.numchannels; + format.wBitsPerSample = sc->sn.samplebits; + format.nSamplesPerSec = sc->sn.speed; + format.nBlockAlign = format.nChannels + *format.wBitsPerSample / 8; + format.cbSize = 0; + format.nAvgBytesPerSec = format.nSamplesPerSec + *format.nBlockAlign; + + /* Open a waveform device for output using window callback. */ + while ((hr = waveOutOpen((LPHWAVEOUT)&wh->hWaveOut, WAVE_MAPPER, + &format, + 0, 0L, CALLBACK_NULL)) != MMSYSERR_NOERROR) + { + if (hr != MMSYSERR_ALLOCATED) + { + Con_SafePrintf ("waveOutOpen failed\n"); + WAV_Shutdown (sc); + return false; + } + +// if (MessageBox (NULL, +// "The sound hardware is in use by another app.\n\n" +// "Select Retry to try to start sound again or Cancel to run Quake with no sound.", +// "Sound not available", +// MB_RETRYCANCEL | MB_SETFOREGROUND | MB_ICONEXCLAMATION) != IDRETRY) +// { + Con_SafePrintf ("waveOutOpen failure;\n" + " hardware already in use\nclose the app, then try using snd_restart\n"); + WAV_Shutdown (sc); + return false; +// } + } + + /* + * Allocate and lock memory for the waveform data. The memory + * for waveform data must be globally allocated with + * GMEM_MOVEABLE and GMEM_SHARE flags. + + */ + wh->gSndBufSize = WAV_BUFFERS*WAV_BUFFER_SIZE; + wh->hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, wh->gSndBufSize); + if (!wh->hData) + { + Con_SafePrintf ("Sound: Out of memory.\n"); + WAV_Shutdown (sc); + return false; + } + wh->lpData = GlobalLock(wh->hData); + if (!wh->lpData) + { + Con_SafePrintf ("Sound: Failed to lock.\n"); + WAV_Shutdown (sc); + return false; + } + memset (wh->lpData, 0, wh->gSndBufSize); + + /* + * Allocate and lock memory for the header. This memory must + * also be globally allocated with GMEM_MOVEABLE and + * GMEM_SHARE flags. + */ + wh->hWaveHdr = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, + (DWORD) sizeof(WAVEHDR) * WAV_BUFFERS); + + if (wh->hWaveHdr == NULL) + { + Con_SafePrintf ("Sound: Failed to Alloc header.\n"); + WAV_Shutdown (sc); + return false; + } + + wh->lpWaveHdr = (LPWAVEHDR) GlobalLock(wh->hWaveHdr); + + if (wh->lpWaveHdr == NULL) + { + Con_SafePrintf ("Sound: Failed to lock header.\n"); + WAV_Shutdown (sc); + return false; + } + + memset (wh->lpWaveHdr, 0, sizeof(WAVEHDR) * WAV_BUFFERS); + + /* After allocation, set up and prepare headers. */ + for (i=0 ; ilpWaveHdr[i].dwBufferLength = WAV_BUFFER_SIZE; + wh->lpWaveHdr[i].lpData = wh->lpData + i*WAV_BUFFER_SIZE; + + if (waveOutPrepareHeader(wh->hWaveOut, wh->lpWaveHdr+i, sizeof(WAVEHDR)) != + MMSYSERR_NOERROR) + { + Con_SafePrintf ("Sound: failed to prepare wave headers\n"); + WAV_Shutdown (sc); + return false; + } + } + + sc->sn.soundalive = true; + sc->sn.splitbuffer = false; + sc->sn.samples = wh->gSndBufSize/(sc->sn.samplebits/8); + sc->sn.samplepos = 0; + sc->sn.submission_chunk = 1; + sc->sn.buffer = (unsigned char *) wh->lpData; + + + sc->Lock = WAV_Lock; + sc->Unlock = WAV_Unlock; + sc->SetWaterDistortion = WAV_SetUnderWater; + sc->Submit = WAV_Submit; + sc->Shutdown = WAV_Shutdown; + sc->GetDMAPos = WAV_GetDMAPos; + + return true; } - - - - - - - - - - - - - - -#if !defined(NODIRECTX) && defined(VOICECHAT) - - - -LPDIRECTSOUNDCAPTURE DSCapture; -LPDIRECTSOUNDCAPTUREBUFFER DSCaptureBuffer; -long lastreadpos; -long bufferbytes = 1024*1024; - -long inputwidth = 2; - -static WAVEFORMATEX wfxFormat; - -int SNDDMA_InitCapture (void) -{ - DSCBUFFERDESC bufdesc; - - wfxFormat.wFormatTag = WAVE_FORMAT_PCM; - wfxFormat.nChannels = 1; - wfxFormat.nSamplesPerSec = 11025; - wfxFormat.wBitsPerSample = 8*inputwidth; - wfxFormat.nBlockAlign = wfxFormat.nChannels * (wfxFormat.wBitsPerSample / 8); - wfxFormat.nAvgBytesPerSec = wfxFormat.nSamplesPerSec * wfxFormat.nBlockAlign; - wfxFormat.cbSize = 0; - - bufdesc.dwSize = sizeof(bufdesc); - bufdesc.dwBufferBytes = bufferbytes; - bufdesc.dwFlags = 0; - bufdesc.dwReserved = 0; - bufdesc.lpwfxFormat = &wfxFormat; - - if (DSCaptureBuffer) - { - IDirectSoundCaptureBuffer_Stop(DSCaptureBuffer); - IDirectSoundCaptureBuffer_Release(DSCaptureBuffer); - DSCaptureBuffer=NULL; - } - if (DSCapture) - { - IDirectSoundCapture_Release(DSCapture); - DSCapture=NULL; - } - - - if (!hInstDS) - { - hInstDS = LoadLibrary("dsound.dll"); - - if (hInstDS == NULL) - { - Con_SafePrintf ("Couldn't load dsound.dll\n"); - return SIS_FAILURE; - } - - } - if (!pDirectSoundCaptureCreate) - { - pDirectSoundCaptureCreate = (void *)GetProcAddress(hInstDS,"DirectSoundCaptureCreate"); - - if (!pDirectSoundCreate) - { - Con_SafePrintf ("Couldn't get DS proc addr\n"); - return SIS_FAILURE; - } - -// pDirectSoundCaptureEnumerate = (void *)GetProcAddress(hInstDS,"DirectSoundCaptureEnumerateA"); - } - pDirectSoundCaptureCreate(NULL, &DSCapture, NULL); - - if (FAILED(IDirectSoundCapture_CreateCaptureBuffer(DSCapture, &bufdesc, &DSCaptureBuffer, NULL))) - { - Con_SafePrintf ("Couldn't create a capture buffer\n"); - IDirectSoundCapture_Release(DSCapture); - DSCapture=NULL; - return SIS_FAILURE; - } - - IDirectSoundCaptureBuffer_Start(DSCaptureBuffer, DSBPLAY_LOOPING); - - lastreadpos = 0; - - return SIS_SUCCESS; -} - -void SNDVC_Submit(qbyte *buffer, int samples, int freq, int width); -void S_UpdateCapture(void) -{ - HRESULT hr; - LPBYTE lpbuf1 = NULL; - LPBYTE lpbuf2 = NULL; - DWORD dwsize1 = 0; - DWORD dwsize2 = 0; - - DWORD capturePos; - DWORD readPos; - long filled; - static int update; - - char *pBuffer; - - -// return; - - if (!snd_capture.value) - { - if (DSCaptureBuffer) - { - IDirectSoundCaptureBuffer_Stop(DSCaptureBuffer); - IDirectSoundCaptureBuffer_Release(DSCaptureBuffer); - DSCaptureBuffer=NULL; - } - if (DSCapture) - { - IDirectSoundCapture_Release(DSCapture); - DSCapture=NULL; - } - return; - } - else if (!DSCaptureBuffer) - { - SNDDMA_InitCapture(); - return; - } - -// Query to see how much data is in buffer. - hr = IDirectSoundCaptureBuffer_GetCurrentPosition( DSCaptureBuffer, &capturePos, &readPos ); - if( hr != DS_OK ) - { - return; - } - filled = readPos - lastreadpos; - if( filled < 0 ) filled += bufferbytes; // unwrap offset - - if (filled > 1400) //figure out how much we need to empty it by, and if that's enough to be worthwhile. - filled = 1400; - else if (filled < 1400) - return; - - if ((filled/inputwidth) & 1) //force even numbers of samples - filled -= inputwidth; - - pBuffer = BZ_Malloc(filled*inputwidth); - - - // Lock free space in the DS - hr = IDirectSoundCaptureBuffer_Lock ( DSCaptureBuffer, lastreadpos, filled, (void **) &lpbuf1, &dwsize1, - (void **) &lpbuf2, &dwsize2, 0); - if (hr == DS_OK) - { - // Copy from DS to the buffer - memcpy( pBuffer, lpbuf1, dwsize1); - if(lpbuf2 != NULL) - { - memcpy( pBuffer+dwsize1, lpbuf2, dwsize2); - } - // Update our buffer offset and unlock sound buffer - lastreadpos = (lastreadpos + dwsize1 + dwsize2) % bufferbytes; - IDirectSoundCaptureBuffer_Unlock ( DSCaptureBuffer, lpbuf1, dwsize1, lpbuf2, dwsize2); - } - else - { - BZ_Free(pBuffer); - return; - } - - SNDVC_MicInput(pBuffer, filled, wfxFormat.nSamplesPerSec, inputwidth); - BZ_Free(pBuffer); -} -#else -void S_UpdateCapture(void) -{ -} -#endif +int (*pWAV_InitCard) (soundcardinfo_t *sc, int cardnum) = &WAV_InitCard; diff --git a/engine/client/sound.h b/engine/client/sound.h index d896a3e4e..d3939f7b4 100644 --- a/engine/client/sound.h +++ b/engine/client/sound.h @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -59,7 +59,7 @@ typedef struct sfxcache_s int loopstart; int speed; int width; - int stereo; + int stereo; qbyte data[1]; // variable sized } sfxcache_t; @@ -81,7 +81,7 @@ typedef struct typedef struct { sfx_t *sfx; // sfx number - int vol[MAXSOUNDCHANNELS]; // 0-255 volume + int vol[MAXSOUNDCHANNELS]; // 0-255 volume int delay[MAXSOUNDCHANNELS]; int end; // end time in global paintsamples int pos; // sample position in sfx @@ -139,15 +139,6 @@ channel_t *SND_PickChannel(soundcardinfo_t *sc, int entnum, int entchannel); // spatializes a channel void SND_Spatialize(soundcardinfo_t *sc, channel_t *ch); -// initializes cycling through a DMA buffer and returns information on it -int SNDDMA_Init(soundcardinfo_t *sc); - -// gets the current DMA position -int SNDDMA_GetDMAPos(soundcardinfo_t *sc); - -// shutdown the DMA xfer. -void SNDDMA_Shutdown(soundcardinfo_t *sc); - // restart entire sound subsystem void S_Restart_f (void); @@ -190,7 +181,7 @@ extern cvar_t volume; extern cvar_t snd_capture; extern qboolean snd_initialized; -extern qboolean snd_multipledevices; +extern cvar_t snd_usemultipledevices; extern int snd_blocked; @@ -200,59 +191,60 @@ sfxcache_t *S_LoadSound (sfx_t *s); wavinfo_t GetWavinfo (char *name, qbyte *wav, int wavlength); void SND_InitScaletable (void); -void SNDDMA_Submit(soundcardinfo_t *sc); void S_AmbientOff (void); void S_AmbientOn (void); - - - -#ifndef _WIN32 - +//inititalisation functions. +typedef int (*sounddriver) (soundcardinfo_t *sc, int cardnum); +extern sounddriver pDSOUND_InitCard; +extern sounddriver pALSA_InitCard; +extern sounddriver pOSS_InitCard; +extern sounddriver pSDL_InitCard; +extern sounddriver pWAV_InitCard; struct soundcardinfo_s { //windows has one defined AFTER directsound + char name[256]; //a description of the card. + struct soundcardinfo_s *next; + +//speaker orientations for spacialisation. float dist[MAX_CHANNELS]; float pitch[MAX_CHANNELS]; float yaw[MAX_CHANNELS]; - char name[256]; +//info on which sound effects are playing + channel_t channel[MAX_CHANNELS]; + int total_chans; +//mixer + volatile dma_t sn; //why is this volatile? + qboolean inactive_sound; //continue mixing for this card even when the window isn't active. + qboolean selfpainting; //allow the sound code to call the right functions when it feels the need (not properly supported). - qboolean selfpainting; //allow the sound code to call the right functions when it feels the need. - //sdl uses this and runs multithreaded. + int paintedtime; //used in the mixer + int oldsamplepos; //fixme: is this still needed? + int snd_linear_count; //used by the mixer. + int buffers; //used to keep track of buffer wraps for consistant sound - qboolean inactive_sound; + int rawend; //streaming audio (avi/cin/roq) + int rawstart; - qboolean snd_isdirect; - qboolean snd_iswave; - - int paintedtime; - int oldsamplepos; - int buffers; - - qboolean dsound_init; - qboolean wav_init; - - volatile dma_t sn; - - int snd_linear_count; +//callbacks + void *(*Lock) (soundcardinfo_t *sc); + void (*Unlock) (soundcardinfo_t *sc, void *buffer); + void (*Submit) (soundcardinfo_t *sc); + void (*Shutdown) (soundcardinfo_t *sc); + unsigned int (*GetDMAPos) (soundcardinfo_t *sc); + void (*SetWaterDistortion) (soundcardinfo_t *sc, qboolean underwater); + void (*Restore) (soundcardinfo_t *sc); +//driver -specific + void *handle; int snd_sent; int snd_completed; - int audio_fd; - -channel_t channel[MAX_CHANNELS]; -int total_chans; - -int rawend; -int rawstart; - - struct soundcardinfo_s *next; }; -#endif extern soundcardinfo_t *sndcardinfo; diff --git a/engine/client/sys_win.c b/engine/client/sys_win.c index 949acce1c..058157298 100644 --- a/engine/client/sys_win.c +++ b/engine/client/sys_win.c @@ -1135,7 +1135,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin #ifndef CLIENTONLY if (isDedicated) { - NET_Sleep(100, false); + NET_Sleep(50, false); // find time passed since last cycle newtime = Sys_DoubleTime (); diff --git a/engine/client/view.c b/engine/client/view.c index 8ba54ae96..4b08fb513 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -454,6 +454,13 @@ void V_cshift_f (void) { if (Cmd_Argc() != 5 && Cmd_Argc() != 1) //this is actually to warn of a malice bug (and prevent a totally black screen) more than it is to help the user. :/ { //The 1 is so teamfortress can use it to clear. + if (Cmd_FromGamecode()) //nehahra does nasty things and becomes unplayable. + { + cl.cshifts[CSHIFT_SERVER].destcolor[0] = 0; + cl.cshifts[CSHIFT_SERVER].destcolor[1] = 0; + cl.cshifts[CSHIFT_SERVER].destcolor[2] = 0; + cl.cshifts[CSHIFT_SERVER].percent = 0; + } Con_Printf("v_cshift: v_cshift \n"); return; } @@ -1274,6 +1281,42 @@ void SCR_VRectForPlayer(vrect_t *vrect, int pnum) r_refdef.fov_y = CalcFov(r_refdef.fov_x, vrect->width, vrect->height); } +void ML_Project(vec3_t in, vec3_t out, vec3_t viewangles, vec3_t vieworg, float wdivh, float fovy); +void R_DrawNameTags(void) +{ + int i; + vec3_t center; + vec3_t tagcenter; + vec3_t waste, waste2; + frame_t *frame; + player_state_t *state; + + if (!cl.spectator && !cls.demoplayback) + return; + +#ifdef RGLQUAKE + if (qrenderer == QR_OPENGL) + GL_Set2D(); +#endif + + frame = &cl.frames[cl.parsecount&UPDATE_MASK]; + state = frame->playerstate; + for (i = 0; i < MAX_CLIENTS; i++, state++) + { + if (state->messagenum != cl.parsecount) + continue; // not present this frame + if (!TraceLineN(r_refdef.vieworg, state->origin, waste, waste2)) + { + VectorCopy(state->origin, tagcenter); + tagcenter[2] += 32; + ML_Project(tagcenter, center, r_refdef.viewangles, r_refdef.vieworg, (float)r_refdef.vrect.width/r_refdef.vrect.height, r_refdef.fov_y); + if (center[2] > 1) + return; + Draw_FunString(center[0]*r_refdef.vrect.width+r_refdef.vrect.x, (1-center[1])*r_refdef.vrect.height+r_refdef.vrect.y, cl.players[i].name); + } + } +} + void V_RenderPlayerViews(int plnum) { int viewnum; @@ -1306,7 +1349,10 @@ void V_RenderPlayerViews(int plnum) R_RenderView_fisheye(); else #endif + { R_RenderView (); + R_DrawNameTags(); + } if (scr_chatmode == 2) { diff --git a/engine/client/winquake.h b/engine/client/winquake.h index bb759af9a..8bec90ccb 100644 --- a/engine/client/winquake.h +++ b/engine/client/winquake.h @@ -78,7 +78,7 @@ extern LPDIRECTDRAWSURFACE lpFrontBuffer; extern LPDIRECTDRAWSURFACE lpBackBuffer; extern LPDIRECTDRAWPALETTE lpDDPal; #endif - +/* struct soundcardinfo_s { int snd_linear_count; //change in asm_i386.h. MUST be first @@ -86,6 +86,14 @@ struct soundcardinfo_s { float yaw[MAXSOUNDCHANNELS]; float dist[MAXSOUNDCHANNELS]; + void *handle; + void *(*Lock) (soundcardinfo_t *sc); + void (*Unlock) (soundcardinfo_t *sc, void *buffer); + void (*Submit) (soundcardinfo_t *sc); + void (*Shutdown) (soundcardinfo_t *sc); + unsigned int (*GetDMAPos) (soundcardinfo_t *sc); + void (*SetWaterDistortion) (soundcardinfo_t *sc, qboolean underwater); + #ifndef NODIRECTX LPDIRECTSOUND pDS; LPDIRECTSOUNDBUFFER pDSBuf; @@ -102,21 +110,13 @@ struct soundcardinfo_s { qboolean selfpainting; qboolean inactive_sound; -#ifndef NODIRECTX - qboolean snd_isdirect; -#endif - qboolean snd_iswave; + int paintedtime; int oldpaintedtime; int oldsamplepos; int buffers; -#ifndef NODIRECTX - qboolean dsound_init; -#endif - qboolean wav_init; - dma_t sn; @@ -139,7 +139,7 @@ int total_chans; struct soundcardinfo_s *next; }; - +*/ //void VID_LockBuffer (void); diff --git a/engine/client/zqtp.c b/engine/client/zqtp.c index 97a1fbe6c..c6a6bfbfd 100644 --- a/engine/client/zqtp.c +++ b/engine/client/zqtp.c @@ -1801,7 +1801,7 @@ static void TP_TeamColor_f (void) { cl_teamtopcolor = -1; cl_teambottomcolor = -1; - if (qrenderer) //make sure we have the renderer initialised... + if (qrenderer>QR_NONE) //make sure we have the renderer initialised... for (i = 0; i < MAX_CLIENTS; i++) CL_NewTranslation(i); return; @@ -1826,7 +1826,7 @@ static void TP_TeamColor_f (void) cl_teamtopcolor = top; cl_teambottomcolor = bottom; - if (qrenderer) //make sure we have the renderer initialised... + if (qrenderer>QR_NONE) //make sure we have the renderer initialised... for (i = 0; i < MAX_CLIENTS; i++) CL_NewTranslation(i); } @@ -1852,7 +1852,7 @@ static void TP_EnemyColor_f (void) { cl_enemytopcolor = -1; cl_enemybottomcolor = -1; - if (qrenderer) //make sure we have the renderer initialised... + if (qrenderer>QR_NONE) //make sure we have the renderer initialised... for (i = 0; i < MAX_CLIENTS; i++) CL_NewTranslation(i); return; @@ -1877,7 +1877,7 @@ static void TP_EnemyColor_f (void) cl_enemytopcolor = top; cl_enemybottomcolor = bottom; - if (qrenderer) //make sure we have the renderer initialised... + if (qrenderer>QR_NONE) //make sure we have the renderer initialised... for (i = 0; i < MAX_CLIENTS; i++) CL_NewTranslation(i); } diff --git a/engine/common/common.c b/engine/common/common.c index d5d44ff0a..5ab43ac05 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -731,13 +731,17 @@ void MSG_WriteAngle16 (sizebuf_t *sb, float f) { MSG_WriteShort (sb, (int)(f*65536/360) & 65535); } +void MSG_WriteAngle8 (sizebuf_t *sb, float f) +{ + MSG_WriteByte (sb, (int)(f*256/360) & 255); +} void MSG_WriteAngle (sizebuf_t *sb, float f) { if (sizeofangle==2) MSG_WriteAngle16(sb, f); else - MSG_WriteByte (sb, (int)(f*256/360) & 255); + MSG_WriteAngle8 (sb, f); } void MSG_WriteDeltaUsercmd (sizebuf_t *buf, usercmd_t *from, usercmd_t *cmd) @@ -4223,8 +4227,8 @@ gamemode_info_t gamemode_info[] = { //note that there is no basic 'fte' gamemode, this is because we aim for network compatability. Darkplaces-Quake is the closest we get. //this is to avoid having too many gamemodes anyway. {"Darkplaces-Quake", "darkplaces", "-quake", "id1/pak0.pak", "id1", "qw", "fte"}, - {"Darkplaces-Hipnotic", "hipnotic", "-hipnotic", "hipnotic/pak0.pak","id1", "qw", "hipnotic", "fte"}, - {"Darkplaces-Rogue", "rogue", "-rogue", "rogue/pak0.pak", "id1", "qw", "rogue", "fte"}, + {"Darkplaces-Hipnotic", "hipnotic", "-hipnotic", NULL/*"hipnotic/pak0.pak"*/,"id1", "qw", "hipnotic", "fte"}, + {"Darkplaces-Rogue", "rogue", "-rogue", NULL/*"rogue/pak0.pak", "id1"*/, "qw", "rogue", "fte"}, {"Nexuiz", "nexuiz", "-nexuiz", "data/data.pk3", "id1", "qw", "data", "fte"}, //supported commercial mods (some are currently only partially supported) @@ -4252,7 +4256,6 @@ void COM_InitFilesystem (void) int gamenum=-1; - char *check; // // -basedir @@ -4270,6 +4273,8 @@ void COM_InitFilesystem (void) //identify the game from a telling file for (i = 0; gamemode_info[i].gamename; i++) { + if (!gamemode_info[i].auniquefile) + return; f = fopen(va("%s/%s", com_quakedir, gamemode_info[i].auniquefile), "rb"); if (f) { diff --git a/engine/common/common.h b/engine/common/common.h index fb5b0232a..efd9b60a3 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -135,6 +135,7 @@ void MSG_WriteString (sizebuf_t *sb, const char *s); void MSG_WriteCoord (sizebuf_t *sb, float f); void MSG_WriteBigCoord (sizebuf_t *sb, float f); void MSG_WriteAngle (sizebuf_t *sb, float f); +void MSG_WriteAngle8 (sizebuf_t *sb, float f); void MSG_WriteAngle16 (sizebuf_t *sb, float f); void MSG_WriteDeltaUsercmd (sizebuf_t *sb, struct usercmd_s *from, struct usercmd_s *cmd); void MSG_WriteDir (sizebuf_t *sb, float *dir); diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c index 77ebba1ca..721a9829f 100644 --- a/engine/common/gl_q2bsp.c +++ b/engine/common/gl_q2bsp.c @@ -2394,11 +2394,11 @@ mesh_t *GL_CreateMeshForPatch (model_t *mod, int patchwidth, int patchheight, in void CModQ3_SortShaders(void) { - texture_t *textemp; +/* texture_t *textemp; int i, j; //sort loadmodel->textures //correct pointers in loadmodel->texinfo -/* + for (i = 0; i < numtexinfo; i++) { for (j = i+1; j < numtexinfo; j++) diff --git a/engine/common/net.h b/engine/common/net.h index 64c66ee24..ff37f369c 100644 --- a/engine/common/net.h +++ b/engine/common/net.h @@ -156,6 +156,9 @@ void Netchan_Setup (netsrc_t sock, netchan_t *chan, netadr_t adr, int qport); qboolean Netchan_CanPacket (netchan_t *chan, int rate); qboolean Netchan_CanReliable (netchan_t *chan, int rate); +#ifdef NQPROT +qboolean NQNetChan_Process(netchan_t *chan); +#endif #ifdef HUFFNETWORK int Huff_PreferedCompressionCRC (void); diff --git a/engine/common/net_chan.c b/engine/common/net_chan.c index 4e7b881f0..18c88e443 100644 --- a/engine/common/net_chan.c +++ b/engine/common/net_chan.c @@ -352,26 +352,6 @@ void Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate) send.maxsize = MAX_NQMSGLEN + PACKET_HEADER; send.cursize = 0; - //send out the unreliable - if (length) - { - MSG_WriteLong(&send, 0); - MSG_WriteLong(&send, BigLong(chan->outgoing_unreliable)); - chan->outgoing_unreliable++; - - SZ_Write (&send, data, length); - - *(int*)send_buf = BigLong(NETFLAG_UNRELIABLE | send.cursize); - NET_SendPacket (chan->sock, send.cursize, send.data, chan->remote_address); - - if (chan->cleartime < realtime) - chan->cleartime = realtime + send.cursize/(float)rate; - else - chan->cleartime += send.cursize/(float)rate; - - send.cursize = 0; - } - if (!chan->reliable_length && chan->message.cursize) { memcpy (chan->reliable_buf, chan->message_buf, chan->message.cursize); @@ -389,6 +369,11 @@ void Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate) i = MAX_NQDATAGRAM; SZ_Write (&send, chan->reliable_buf+chan->reliable_start, i); + if (send.cursize + length < send.maxsize) + { //throw the unreliable packet into the same one as the reliable (but not sent reliably) + SZ_Write (&send, data, length); + length = 0; + } if (chan->reliable_start+i == chan->reliable_length) @@ -402,6 +387,26 @@ void Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate) else chan->cleartime += send.cursize/(float)rate; } + + //send out the unreliable (if still unsent) + if (length) + { + MSG_WriteLong(&send, 0); + MSG_WriteLong(&send, BigLong(chan->outgoing_unreliable)); + chan->outgoing_unreliable++; + + SZ_Write (&send, data, length); + + *(int*)send_buf = BigLong(NETFLAG_UNRELIABLE | send.cursize); + NET_SendPacket (chan->sock, send.cursize, send.data, chan->remote_address); + + if (chan->cleartime < realtime) + chan->cleartime = realtime + send.cursize/(float)rate; + else + chan->cleartime += send.cursize/(float)rate; + + send.cursize = 0; + } return; } #endif diff --git a/engine/common/net_wins.c b/engine/common/net_wins.c index 3035f6b92..1c1666449 100644 --- a/engine/common/net_wins.c +++ b/engine/common/net_wins.c @@ -430,7 +430,7 @@ qboolean NET_StringToSockaddr (char *s, struct sockaddr_qstorage *sadr) int len; memset(&udp6hint, 0, sizeof(udp6hint)); - udp6hint.ai_family = 0;//Any... AF_INET6; + udp6hint.ai_family = 0;//Any... we check for AF_INET6 or 4 udp6hint.ai_socktype = SOCK_DGRAM; udp6hint.ai_protocol = IPPROTO_UDP; diff --git a/engine/common/protocol.h b/engine/common/protocol.h index 90b4c1d57..564a1118b 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -198,7 +198,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define svcdp_precache 54 // [short] precacheindex [string] filename, precacheindex is + 0 for modelindex and +32768 for soundindex #define svc_nails2 54 //qwe - [qbyte] num [52 bits] nxyzpy 8 12 12 12 4 8 - +#define svcdp_spawnbaseline2 55 #ifdef PEXT_VIEW2 #define svc_view2 56 #endif @@ -206,6 +206,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define svc_lightstylecol 57 #endif +#define svcdp_entities 57 + #ifdef PEXT_BULLETENS #define svc_bulletentext 58 #endif @@ -660,6 +662,7 @@ enum { typedef struct entity_state_s { int number; // edict index + int bitmask; // for dp ents, so lost state can be repeated in replacement packets. int flags; // nolerp, etc vec3_t origin; diff --git a/engine/common/q1bsp.c b/engine/common/q1bsp.c index 6062f18d8..d5bfc1f19 100644 --- a/engine/common/q1bsp.c +++ b/engine/common/q1bsp.c @@ -459,8 +459,8 @@ int Fragment_ClipPolyToPlane(float *inverts, float *outverts, int incount, float int clippedcount = 0; vec3_t impact; - float *lastvalid; //the reason these arn't just an index is because it'd need to be a special case for the first vert. - float lastvaliddot; + float *lastvalid = NULL; //the reason these arn't just an index is because it'd need to be a special case for the first vert. + float lastvaliddot = 0; for (i = 0; i < incount; i++) { @@ -539,7 +539,6 @@ int Fragment_ClipPolyToPlane(float *inverts, float *outverts, int incount, float void Fragment_ClipTriangle(fragmentdecal_t *dec, float *a, float *b, float *c) { //emit the triangle, and clip it's fragments. - int start, i; int p; float verts[MAXFRAGMENTVERTS*3]; float verts2[MAXFRAGMENTVERTS*3]; diff --git a/engine/common/zone.c b/engine/common/zone.c index 679e54f43..b739edee5 100644 --- a/engine/common/zone.c +++ b/engine/common/zone.c @@ -947,6 +947,9 @@ Hunk_AllocName */ void *Hunk_AllocName (int size, char *name) { +#ifdef NOHIGH + int roundup; +#endif hunk_t *h; #ifdef PARANOID @@ -971,7 +974,10 @@ void *Hunk_AllocName (int size, char *name) h = (hunk_t *)(hunk_base + hunk_low_used); #ifdef NOHIGH - if (!VirtualAlloc (hunk_base, hunk_low_used+size+sizeof(hunk_t), MEM_COMMIT, PAGE_READWRITE)) + roundup = hunk_low_used+size+sizeof(hunk_t); + roundup += 1024*64; + roundup &= ~(1024*64 - 1); + if (!VirtualAlloc (hunk_base, roundup, MEM_COMMIT, PAGE_READWRITE)) { char *buf; Hunk_Print(true); diff --git a/engine/ftequake/ftequake.dsp b/engine/ftequake/ftequake.dsp index 5e35a41f7..f7a5877d2 100644 --- a/engine/ftequake/ftequake.dsp +++ b/engine/ftequake/ftequake.dsp @@ -2098,6 +2098,10 @@ SOURCE=..\client\skin.c # End Source File # Begin Source File +SOURCE=..\client\snd_directx.c +# End Source File +# Begin Source File + SOURCE=..\client\snd_dma.c !IF "$(CFG)" == "ftequake - Win32 Release" @@ -5002,70 +5006,728 @@ SOURCE=..\common\zone.c # Begin Source File SOURCE=..\QCLIB\Comprout.c + +!IF "$(CFG)" == "ftequake - Win32 Release" + # SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + # End Source File # Begin Source File SOURCE=..\qclib\execloop.h + +!IF "$(CFG)" == "ftequake - Win32 Release" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" + +!ENDIF + # End Source File # Begin Source File SOURCE=..\QCLIB\hash.c + +!IF "$(CFG)" == "ftequake - Win32 Release" + # SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + # End Source File # Begin Source File SOURCE=..\QCLIB\initlib.c + +!IF "$(CFG)" == "ftequake - Win32 Release" + # SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + # End Source File # Begin Source File SOURCE=..\QCLIB\pr_edict.c + +!IF "$(CFG)" == "ftequake - Win32 Release" + # SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + # End Source File # Begin Source File SOURCE=..\QCLIB\Pr_exec.c + +!IF "$(CFG)" == "ftequake - Win32 Release" + # SUBTRACT CPP /WX /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" + +# SUBTRACT CPP /WX /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" + +# SUBTRACT CPP /WX /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" + +# SUBTRACT CPP /WX /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" + +# SUBTRACT CPP /WX /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" + +# SUBTRACT CPP /WX /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" + +# SUBTRACT CPP /WX /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" + +# SUBTRACT CPP /WX /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" + +# SUBTRACT CPP /WX /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" + +# SUBTRACT CPP /WX /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" + +# SUBTRACT CPP /WX /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" + +# SUBTRACT CPP /WX /YX /Yc /Yu + +!ENDIF + # End Source File # Begin Source File SOURCE=..\QCLIB\pr_multi.c + +!IF "$(CFG)" == "ftequake - Win32 Release" + # SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + # End Source File # Begin Source File SOURCE=..\QCLIB\progtype.h + +!IF "$(CFG)" == "ftequake - Win32 Release" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" + +!ENDIF + # End Source File # Begin Source File SOURCE=..\QCLIB\qcc_cmdlib.c + +!IF "$(CFG)" == "ftequake - Win32 Release" + # SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + # End Source File # Begin Source File SOURCE=..\QCLIB\qcc_pr_comp.c + +!IF "$(CFG)" == "ftequake - Win32 Release" + # SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" + +# PROP Exclude_From_Build 1 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + # End Source File # Begin Source File SOURCE=..\QCLIB\qcc_pr_lex.c + +!IF "$(CFG)" == "ftequake - Win32 Release" + # SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" + +# PROP Exclude_From_Build 1 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + # End Source File # Begin Source File SOURCE=..\QCLIB\QccMain.c + +!IF "$(CFG)" == "ftequake - Win32 Release" + # SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" + +# PROP Exclude_From_Build 1 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + # End Source File # Begin Source File SOURCE=..\QCLIB\qcd_main.c + +!IF "$(CFG)" == "ftequake - Win32 Release" + # SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + # End Source File # Begin Source File SOURCE=..\QCLIB\qcdecomp.c + +!IF "$(CFG)" == "ftequake - Win32 Release" + # SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" + +# PROP Exclude_From_Build 1 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + # End Source File # End Group # Begin Group "asm" diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index abe1f828b..fe9e2f1c6 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -8,6 +8,8 @@ #define SKELETALMODELS #endif +#define MAX_BONES 256 + //FIXME typedef struct { @@ -119,6 +121,7 @@ typedef struct { #ifdef SKELETALMODELS typedef struct { + char name[32]; int parent; } galiasbone_t; @@ -289,7 +292,7 @@ static void R_LerpFrames(mesh_t *mesh, galiaspose_t *p1, galiaspose_t *p2, float #ifdef SKELETALMODELS static void R_BuildSkeletalMesh(mesh_t *mesh, float *plerp, float **pose, int poses, galiasbone_t *bones, int bonecount, galisskeletaltransforms_t *weights, int numweights) { - float bonepose[256][12]; + float bonepose[MAX_BONES][12]; float *outhead; galisskeletaltransforms_t *v; @@ -594,6 +597,7 @@ static galiastexnum_t *GL_ChooseSkin(galiasinfo_t *inf, char *modelname, entity_ int frame; int tc, bc; + int local; if (!gl_nocolors.value) { @@ -607,7 +611,15 @@ static galiastexnum_t *GL_ChooseSkin(galiasinfo_t *inf, char *modelname, entity_ //colour forcing if (cl.splitclients<2 && !(cl.fpd & FPD_NO_FORCE_COLOR)) //no colour/skin forcing in splitscreen. { - if (cl.teamplay && !strcmp(e->scoreboard->team, cl.players[cl.playernum[0]].team)) + if (cl.teamplay && cl.spectator) + { + local = Cam_TrackNum(0); + if (local < 0) + local = cl.playernum[0]; + } + else + local = cl.playernum[0]; + if (cl.teamplay && !strcmp(e->scoreboard->team, cl.players[local].team)) { if (cl_teamtopcolor>=0) tc = cl_teamtopcolor; @@ -2814,28 +2826,157 @@ typedef struct { -void GLMod_GetTag(model_t *model, int tagnum, int frame, float **org, float **axis) +qboolean GLMod_GetTag(model_t *model, int tagnum, int frame1, int frame2, float f2ness, float f1time, float f2time, float *result) { galiasinfo_t *inf; - md3tag_t *t; - *org = NULL; - *axis = NULL; + if (!model || model->type != mod_alias) - return; + return false; inf = Mod_Extradata(model); - t = (md3tag_t*)((char*)inf + inf->ofstags); - if (tagnum <= 0 || tagnum > inf->numtags) - return; - if (frame < 0 || frame >= inf->numtagframes) - return; - tagnum--; //tagnum 0 is 'use my angles/org' +#ifdef SKELETALMODELS + if (inf->numbones) + { + galiasbone_t *bone; + galiasgroup_t *g1, *g2; - t += tagnum; - t += inf->numtags*frame; - *org = t->org; - *axis = (float*)t->ang; + float tempmatrix[12]; //flipped between this and bonematrix + float *matrix; //the matrix for a single bone in a single pose. + float m[12]; //combined interpolated version of 'matrix'. + int b, k; //counters + + float *pose[4]; //the per-bone matricies (one for each pose) + float plerp[4]; //the ammount of that pose to use (must combine to 1) + int numposes = 0; + + if (tagnum <= 0 || tagnum > inf->numbones) + return false; + tagnum--; //tagnum 0 is 'use my angles/org' + + if (frame1 < 0 || frame1 >= inf->groups) + return false; + if (frame2 < 0 || frame2 >= inf->groups) + { + f2ness = 0; + frame2 = frame1; + } + + bone = (galiasbone_t*)((char*)inf + inf->ofsbones); +//the higher level merges old/new anims, but we still need to blend between automated frame-groups. + g1 = (galiasgroup_t*)((char *)inf + inf->groupofs + sizeof(galiasgroup_t)*frame1); + g2 = (galiasgroup_t*)((char *)inf + inf->groupofs + sizeof(galiasgroup_t)*frame2); + + frame1 = (int)f1time%g1->numposes; + frame2 = ((int)f1time+1)%g1->numposes; + f1time = f1time - (int)f1time; + pose[numposes] = (float *)((char *)g1 + g1->poseofs + sizeof(float)*inf->numbones*12*frame1); + plerp[numposes] = (1-f1time) * (1-f2ness); + numposes++; + if (frame1 != frame2) + { + pose[numposes] = (float *)((char *)g1 + g1->poseofs + sizeof(float)*inf->numbones*12*frame2); + plerp[numposes] = f1time * (1-f2ness); + numposes++; + } + if (f2ness) + { + frame1 = (int)f2time%g2->numposes; + frame2 = ((int)f2time+1)%g2->numposes; + f2time = f2time - (int)f2time; + pose[numposes] = (float *)((char *)g2 + g2->poseofs + sizeof(float)*inf->numbones*12*frame1); + plerp[numposes] = (1-f2time) * f2ness; + numposes++; + if (frame1 != frame2) + { + pose[numposes] = (float *)((char *)g2 + g2->poseofs + sizeof(float)*inf->numbones*12*frame2); + plerp[numposes] = f2time * f2ness; + numposes++; + } + } + + //set up the identity matrix + for (k = 0;k < 12;k++) + result[k] = 0; + result[0] = 1; + result[5] = 1; + result[10] = 1; + while(tagnum >= 0) + { + //set up the per-bone transform matrix + for (k = 0;k < 12;k++) + m[k] = 0; + for (b = 0;b < numposes;b++) + { + matrix = pose[b] + tagnum*12; + + for (k = 0;k < 12;k++) + m[k] += matrix[k] * plerp[b]; + } + + memcpy(tempmatrix, result, sizeof(tempmatrix)); + R_ConcatTransforms((void*)m, (void*)tempmatrix, (void*)result); + + tagnum = bone[tagnum].parent; + } + + return true; + } +#endif + if (inf->numtags) + { + md3tag_t *t1, *t2; + + if (tagnum <= 0 || tagnum > inf->numtags) + return false; + if (frame1 < 0 || frame1 >= inf->numtagframes) + return false; + if (frame2 < 0 || frame2 >= inf->numtagframes) + frame2 = frame1; + tagnum--; //tagnum 0 is 'use my angles/org' + + t1 = (md3tag_t*)((char*)inf + inf->ofstags); + t1 += tagnum; + t1 += inf->numtags*frame1; + + t2 = (md3tag_t*)((char*)inf + inf->ofstags); + t2 += tagnum; + t2 += inf->numtags*frame2; + + if (t1 == t2) + { + result[0] = t1->ang[0][0]; + result[1] = t1->ang[1][0]; + result[2] = t1->ang[2][0]; + result[3] = t1->org[0]; + result[4] = t1->ang[0][1]; + result[5] = t1->ang[1][1]; + result[6] = t1->ang[2][1]; + result[7] = t1->org[1]; + result[8] = t1->ang[0][2]; + result[9] = t1->ang[1][2]; + result[10] = t1->ang[2][2]; + result[11] = t1->org[2]; + } + else + { + float f1ness = 1-f2ness; + result[0] = t1->ang[0][0]*f1ness + t2->ang[0][0]*f2ness; + result[1] = t1->ang[1][0]*f1ness + t2->ang[1][0]*f2ness; + result[2] = t1->ang[2][0]*f1ness + t2->ang[2][0]*f2ness; + result[3] = t1->org[0]*f1ness + t2->org[0]*f2ness; + result[4] = t1->ang[0][1]*f1ness + t2->ang[0][1]*f2ness; + result[5] = t1->ang[1][1]*f1ness + t2->ang[1][1]*f2ness; + result[6] = t1->ang[2][1]*f1ness + t2->ang[2][1]*f2ness; + result[7] = t1->org[1]*f1ness + t2->org[1]*f2ness; + result[8] = t1->ang[0][2]*f1ness + t2->ang[0][2]*f2ness; + result[9] = t1->ang[1][2]*f1ness + t2->ang[1][2]*f2ness; + result[10] = t1->ang[2][2]*f1ness + t2->ang[2][2]*f2ness; + result[11] = t1->org[2]*f1ness + t2->org[2]*f2ness; + } + return true; + } + return false; } int GLMod_TagNumForName(model_t *model, char *name) @@ -2846,14 +2987,27 @@ int GLMod_TagNumForName(model_t *model, char *name) if (!model || model->type != mod_alias) return 0; - inf = Mod_Extradata(model); + +#ifdef SKELETALMODELS + if (inf->numbones) + { + galiasbone_t *b; + b = (galiasbone_t*)((char*)inf + inf->ofsbones); + for (i = 0; i < inf->numbones; i++) + { + if (!strcmp(b[i].name, name)) + return i+1; + } + } +#endif t = (md3tag_t*)((char*)inf + inf->ofstags); for (i = 0; i < inf->numtags; i++) { if (!strcmp(t[i].name, name)) return i+1; } + return 0; } @@ -3361,7 +3515,10 @@ void GLMod_LoadZymoticModel(model_t *mod, void *buffer) bone = Hunk_Alloc(root->numtransforms*sizeof(*transforms)); inbone = (zymbone_t*)((char*)header + header->lump_bones.start); for (i = 0; i < root->numbones; i++) + { + Q_strncpyz(bone[i].name, inbone[i].name, sizeof(bone[i].name)); bone[i].parent = BigLong(inbone[i].parent); + } root->ofsbones = (char *)bone - (char *)root; renderlist = (int*)((char*)header + header->lump_render.start); diff --git a/engine/gl/gl_ppl.c b/engine/gl/gl_ppl.c index 5bab0c22f..a670044f9 100644 --- a/engine/gl/gl_ppl.c +++ b/engine/gl/gl_ppl.c @@ -676,6 +676,7 @@ static void PPL_BaseChain_Bump_4TMU(msurface_t *s, texture_t *tex) qglDisable(GL_TEXTURE_2D); GL_SelectTexture(GL_TEXTURE1_ARB); + GL_TexEnv(GL_MODULATE); qglDisableClientState(GL_TEXTURE_COORD_ARRAY); qglDisable(GL_TEXTURE_2D); @@ -2250,7 +2251,6 @@ void PPL_LightBModelTexturesFP(entity_t *e, dlight_t *light, vec3_t colour) VectorSubtract(r_refdef.vieworg, e->origin, relativeeyeorigin); qglEnable(GL_BLEND); - GL_TexEnv(GL_MODULATE); qglBlendFunc(GL_ONE, GL_ONE); if (qglGetError()) diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index c73197fa0..41f265641 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -1501,6 +1501,10 @@ r_refdef must be set before the first call void R_RenderScene (void) { qboolean GLR_DoomWorld(void); + + if (!cl.worldmodel) + r_refdef.flags |= Q2RDF_NOWORLDMODEL; + if (!mirror) GLR_SetupFrame (); diff --git a/engine/gl/gl_rsurf.c b/engine/gl/gl_rsurf.c index 1a781328c..9dd35febf 100644 --- a/engine/gl/gl_rsurf.c +++ b/engine/gl/gl_rsurf.c @@ -3767,7 +3767,6 @@ void GL_BuildLightmaps (void) { int i, j; model_t *m; - msurface_t *fa; r_framecount = 1; // no dlightcache diff --git a/engine/qclib/execloop.h b/engine/qclib/execloop.h index b1268556b..fae820ebf 100644 --- a/engine/qclib/execloop.h +++ b/engine/qclib/execloop.h @@ -395,7 +395,7 @@ reeval: if (ed->readonly) { pr_xstatement = st-pr_statements; - PR_RunError (progfuncs, "assignment to read-only entity in %s", pr_xfunction->s_name); + PR_RunError (progfuncs, "assignment to read-only entity in %s", progfuncs->stringtable + pr_xfunction->s_name); } OPC->_int = ENGINEPOINTER((((int *)edvars(ed)) + OPB->_int + progfuncs->fieldadjust)); break; diff --git a/engine/qclib/execloop16.h b/engine/qclib/execloop16.h deleted file mode 100644 index 157726f1d..000000000 --- a/engine/qclib/execloop16.h +++ /dev/null @@ -1,914 +0,0 @@ -//qc execution code. -//we have two conditions. -//one allows us to debug and trace through our code, the other doesn't. - -//hopefully, the compiler will do a great job at optimising this code for us, where required. -//if it dosn't, then bum. - -//the general overhead should be reduced significantly, and I would be supprised if it did run slower. - -//run away loops are checked for ONLY on gotos and function calls. This might give a poorer check, but it will run faster overall. - -//Appears to work fine. - -#if INTSIZE == 16 -#define cont cont16 -#define reeval reeval16 -#define st st16 -#define pr_statements pr_statements16 -#define fakeop fakeop16 -#define dstatement_t dstatement16_t -#define sofs signed short -#define uofs unsigned short -#elif INTSIZE == 32 -#define cont cont32 -#define reeval reeval32 -#define st st32 -#define pr_statements pr_statements32 -#define fakeop fakeop32 -#define dstatement_t dstatement32_t -#define sofs signed int -#define uofs unsigned int -#elif INTSIZE == 24 -#error INTSIZE should be set to 32. -#else -#error Bad cont size -#endif - - -//rely upon just st -{ -#ifdef DEBUGABLE -cont: //last statement may have been a breakpoint - s = st-pr_statements; - s+=1; - s=ShowStep(progfuncs, s); - st = pr_statements + s; - -reeval: -#else - st++; -#endif - - switch (st->op) - { - case OP_ADD_F: - OPC->_float = OPA->_float + OPB->_float; - break; - case OP_ADD_V: - OPC->vector[0] = OPA->vector[0] + OPB->vector[0]; - OPC->vector[1] = OPA->vector[1] + OPB->vector[1]; - OPC->vector[2] = OPA->vector[2] + OPB->vector[2]; - break; - - case OP_SUB_F: - OPC->_float = OPA->_float - OPB->_float; - break; - case OP_SUB_V: - OPC->vector[0] = OPA->vector[0] - OPB->vector[0]; - OPC->vector[1] = OPA->vector[1] - OPB->vector[1]; - OPC->vector[2] = OPA->vector[2] - OPB->vector[2]; - break; - - case OP_MUL_F: - OPC->_float = OPA->_float * OPB->_float; - break; - case OP_MUL_V: - OPC->_float = OPA->vector[0]*OPB->vector[0] - + OPA->vector[1]*OPB->vector[1] - + OPA->vector[2]*OPB->vector[2]; - break; - case OP_MUL_FV: - OPC->vector[0] = OPA->_float * OPB->vector[0]; - OPC->vector[1] = OPA->_float * OPB->vector[1]; - OPC->vector[2] = OPA->_float * OPB->vector[2]; - break; - case OP_MUL_VF: - OPC->vector[0] = OPB->_float * OPA->vector[0]; - OPC->vector[1] = OPB->_float * OPA->vector[1]; - OPC->vector[2] = OPB->_float * OPA->vector[2]; - break; - - case OP_DIV_F: - OPC->_float = OPA->_float / OPB->_float; - break; - case OP_DIV_VF: - OPC->vector[0] = OPB->_float / OPA->vector[0]; - OPC->vector[1] = OPB->_float / OPA->vector[1]; - OPC->vector[2] = OPB->_float / OPA->vector[2]; - break; - - case OP_BITAND: - OPC->_float = (float)((int)OPA->_float & (int)OPB->_float); - break; - - case OP_BITOR: - OPC->_float = (float)((int)OPA->_float | (int)OPB->_float); - break; - - - case OP_GE: - OPC->_float = (float)(OPA->_float >= OPB->_float); - break; - case OP_GE_I: - OPC->_int = (int)(OPA->_int >= OPB->_int); - break; - case OP_GE_IF: - OPC->_float = (float)(OPA->_int >= OPB->_float); - break; - case OP_GE_FI: - OPC->_float = (float)(OPA->_float >= OPB->_int); - break; - - case OP_LE: - OPC->_float = (float)(OPA->_float <= OPB->_float); - break; - case OP_LE_I: - OPC->_int = (int)(OPA->_int <= OPB->_int); - break; - case OP_LE_IF: - OPC->_float = (float)(OPA->_int <= OPB->_float); - break; - case OP_LE_FI: - OPC->_float = (float)(OPA->_float <= OPB->_int); - break; - - case OP_GT: - OPC->_float = (float)(OPA->_float > OPB->_float); - break; - case OP_GT_I: - OPC->_int = (int)(OPA->_int > OPB->_int); - break; - case OP_GT_IF: - OPC->_float = (float)(OPA->_int > OPB->_float); - break; - case OP_GT_FI: - OPC->_float = (float)(OPA->_float > OPB->_int); - break; - - case OP_LT: - OPC->_float = (float)(OPA->_float < OPB->_float); - break; - case OP_LT_I: - OPC->_int = (int)(OPA->_int < OPB->_int); - break; - case OP_LT_IF: - OPC->_float = (float)(OPA->_int < OPB->_float); - break; - case OP_LT_FI: - OPC->_float = (float)(OPA->_float < OPB->_int); - break; - - case OP_AND: - OPC->_float = (float)(OPA->_float && OPB->_float); - break; - case OP_OR: - OPC->_float = (float)(OPA->_float || OPB->_float); - break; - - case OP_NOT_F: - OPC->_float = (float)(!OPA->_float); - break; - case OP_NOT_V: - OPC->_float = (float)(!OPA->vector[0] && !OPA->vector[1] && !OPA->vector[2]); - break; - case OP_NOT_S: - OPC->_float = (float)(!(OPA->string) || !*(OPA->string+progfuncs->stringtable)); - break; - case OP_NOT_FNC: - OPC->_float = (float)(!(OPA->function & ~0xff000000)); - break; - case OP_NOT_ENT: - OPC->_float = (float)(PROG_TO_EDICT(OPA->edict) == (edictrun_t *)sv_edicts); - break; - - case OP_EQ_F: - OPC->_float = (float)(OPA->_float == OPB->_float); - break; - case OP_EQ_IF: - OPC->_float = (float)(OPA->_int == OPB->_float); - break; - case OP_EQ_FI: - OPC->_float = (float)(OPA->_float == OPB->_int); - break; - - - case OP_EQ_V: - OPC->_float = (float)((OPA->vector[0] == OPB->vector[0]) && - (OPA->vector[1] == OPB->vector[1]) && - (OPA->vector[2] == OPB->vector[2])); - break; - case OP_EQ_S: - if (OPA->string==OPB->string) - OPC->_float = true; - else if (!OPA->string) - { - if (!OPB->string || !*(OPB->string+progfuncs->stringtable)) - OPC->_float = true; - else - OPC->_float = false; - } - else if (!OPB->string) - { - if (!OPA->string || !*(OPA->string+progfuncs->stringtable)) - OPC->_float = true; - else - OPC->_float = false; - } - else - OPC->_float = (float)(!strcmp(OPA->string+progfuncs->stringtable,OPB->string+progfuncs->stringtable)); - break; - case OP_EQ_E: - OPC->_float = (float)(OPA->_int == OPB->_int); - break; - case OP_EQ_FNC: - OPC->_float = (float)(OPA->function == OPB->function); - break; - - - case OP_NE_F: - OPC->_float = (float)(OPA->_float != OPB->_float); - break; - case OP_NE_V: - OPC->_float = (float)((OPA->vector[0] != OPB->vector[0]) || - (OPA->vector[1] != OPB->vector[1]) || - (OPA->vector[2] != OPB->vector[2])); - break; - case OP_NE_S: - if (OPA->string==OPB->string) - OPC->_float = false; - else if (!OPA->string) - { - if (!OPB->string || !*(OPB->string+progfuncs->stringtable)) - OPC->_float = false; - else - OPC->_float = true; - } - else if (!OPB->string) - { - if (!OPA->string || !*(OPA->string+progfuncs->stringtable)) - OPC->_float = false; - else - OPC->_float = true; - } - else - OPC->_float = (float)(strcmp(OPA->string+progfuncs->stringtable,OPB->string+progfuncs->stringtable)); - break; - case OP_NE_E: - OPC->_float = (float)(OPA->_int != OPB->_int); - break; - case OP_NE_FNC: - OPC->_float = (float)(OPA->function != OPB->function); - break; - -//================== - case OP_STORE_IF: - OPB->_float = (float)OPA->_int; - break; - case OP_STORE_FI: - OPB->_int = (int)OPA->_float; - break; - case OP_STORE_I: - OPB->_int = OPA->_int; - break; - case OP_STORE_F: - case OP_STORE_ENT: - case OP_STORE_FLD: // integers - case OP_STORE_S: - case OP_STORE_FNC: // pointers - OPB->_int = OPA->_int; - break; - case OP_STORE_V: - OPB->vector[0] = OPA->vector[0]; - OPB->vector[1] = OPA->vector[1]; - OPB->vector[2] = OPA->vector[2]; - break; - - //store a value to a pointer - case OP_STOREP_IF: - ptr = (eval_t *)(OPB->_int); - ptr->_float = (float)OPA->_int; - break; - case OP_STOREP_FI: - ptr = (eval_t *)(OPB->_int); - ptr->_int = (int)OPA->_float; - break; - case OP_STOREP_I: - ptr = (eval_t *)(OPB->_int); - ptr->_int = OPA->_int; - break; - case OP_STOREP_F: - case OP_STOREP_ENT: - case OP_STOREP_FLD: // integers - case OP_STOREP_S: - case OP_STOREP_FNC: // pointers - ptr = (eval_t *)(OPB->_int); - ptr->_int = OPA->_int; - break; - case OP_STOREP_V: - ptr = (eval_t *)(OPB->_int); - ptr->vector[0] = OPA->vector[0]; - ptr->vector[1] = OPA->vector[1]; - ptr->vector[2] = OPA->vector[2]; - break; - - case OP_STOREP_C: //store character in a string - ptr = (eval_t *)(OPB->_int); - *(unsigned char *)ptr = (char)OPA->_float; - break; - - case OP_MULSTORE_F: // f *= f - OPB->_float *= OPA->_float; - break; - case OP_MULSTORE_V: // v *= f - OPB->vector[0] *= OPA->_float; - OPB->vector[1] *= OPA->_float; - OPB->vector[2] *= OPA->_float; - break; - case OP_MULSTOREP_F: // e.f *= f - ptr = (eval_t *)(OPB->_int); - OPC->_float = (ptr->_float *= OPA->_float); - break; - case OP_MULSTOREP_V: // e.v *= f - ptr = (eval_t *)(OPB->_int); - OPC->vector[0] = (ptr->vector[0] *= OPA->_float); - OPC->vector[0] = (ptr->vector[1] *= OPA->_float); - OPC->vector[0] = (ptr->vector[2] *= OPA->_float); - break; - - case OP_DIVSTORE_F: // f /= f - OPB->_float /= OPA->_float; - break; - case OP_DIVSTOREP_F: // e.f /= f - ptr = (eval_t *)(OPB->_int); - OPC->_float = (ptr->_float /= OPA->_float); - break; - - case OP_ADDSTORE_F: // f += f - OPB->_float += OPA->_float; - break; - case OP_ADDSTORE_V: // v += v - OPB->vector[0] += OPA->vector[0]; - OPB->vector[1] += OPA->vector[1]; - OPB->vector[2] += OPA->vector[2]; - break; - case OP_ADDSTOREP_F: // e.f += f - ptr = (eval_t *)(OPB->_int); - OPC->_float = (ptr->_float += OPA->_float); - break; - case OP_ADDSTOREP_V: // e.v += v - ptr = (eval_t *)(OPB->_int); - OPC->vector[0] = (ptr->vector[0] += OPA->vector[0]); - OPC->vector[1] = (ptr->vector[1] += OPA->vector[1]); - OPC->vector[2] = (ptr->vector[2] += OPA->vector[2]); - break; - - case OP_SUBSTORE_F: // f -= f - OPB->_float -= OPA->_float; - break; - case OP_SUBSTORE_V: // v -= v - OPB->vector[0] -= OPA->vector[0]; - OPB->vector[1] -= OPA->vector[1]; - OPB->vector[2] -= OPA->vector[2]; - break; - case OP_SUBSTOREP_F: // e.f -= f - ptr = (eval_t *)(OPB->_int); - OPC->_float = (ptr->_float -= OPA->_float); - break; - case OP_SUBSTOREP_V: // e.v -= v - ptr = (eval_t *)(OPB->_int); - OPC->vector[0] = (ptr->vector[0] -= OPA->vector[0]); - OPC->vector[1] = (ptr->vector[1] -= OPA->vector[1]); - OPC->vector[2] = (ptr->vector[2] -= OPA->vector[2]); - break; - - - //get a pointer to a field var - case OP_ADDRESS: - ed = PROG_TO_EDICT(OPA->edict); -#ifdef PARANOID - NUM_FOR_EDICT(ed); // make sure it's in range -#endif - if (ed->readonly) - PR_RunError (progfuncs, "assignment to read-only entity"); - OPC->_int = (int)(((int *)edvars(ed)) + OPB->_int); - break; - - //load a field to a value - case OP_LOAD_I: - case OP_LOAD_F: - case OP_LOAD_FLD: - case OP_LOAD_ENT: - case OP_LOAD_S: - case OP_LOAD_FNC: - ed = PROG_TO_EDICT(OPA->edict); -#ifdef PARANOID - NUM_FOR_EDICT(ed); // make sure it's in range -#endif - ptr = (eval_t *)(((int *)edvars(ed)) + OPB->_int); - OPC->_int = ptr->_int; - break; - - case OP_LOAD_V: - ed = PROG_TO_EDICT(OPA->edict); -#ifdef PARANOID - NUM_FOR_EDICT(ed); // make sure it's in range -#endif - ptr = (eval_t *)(((int *)edvars(ed)) + OPB->_int); - OPC->vector[0] = ptr->vector[0]; - OPC->vector[1] = ptr->vector[1]; - OPC->vector[2] = ptr->vector[2]; - break; - -//================== - - case OP_IFNOTS: - RUNAWAYCHECK(); - if (!OPA->string || !*OPA->string) - st += (sofs)st->b - 1; // offset the s++ - break; - - case OP_IFNOT: - RUNAWAYCHECK(); - if (!OPA->_int) - st += (sofs)st->b - 1; // offset the s++ - break; - - case OP_IFS: - RUNAWAYCHECK(); - if (OPA->string && *OPA->string) - st += (sofs)st->b - 1; // offset the s++ - break; - - case OP_IF: - RUNAWAYCHECK(); - if (OPA->_int) - st += (sofs)st->b - 1; // offset the s++ - break; - - case OP_GOTO: - RUNAWAYCHECK(); - st += (sofs)st->a - 1; // offset the s++ - break; - - case OP_CALL8H: - case OP_CALL7H: - case OP_CALL6H: - case OP_CALL5H: - case OP_CALL4H: - case OP_CALL3H: - case OP_CALL2H: - G_VECTOR(OFS_PARM1)[0] = OPC->vector[0]; - G_VECTOR(OFS_PARM1)[1] = OPC->vector[1]; - G_VECTOR(OFS_PARM1)[2] = OPC->vector[2]; - case OP_CALL1H: - G_VECTOR(OFS_PARM0)[0] = OPB->vector[0]; - G_VECTOR(OFS_PARM0)[1] = OPB->vector[1]; - G_VECTOR(OFS_PARM0)[2] = OPB->vector[2]; - - case OP_CALL8: - case OP_CALL7: - case OP_CALL6: - case OP_CALL5: - case OP_CALL4: - case OP_CALL3: - case OP_CALL2: - case OP_CALL1: - case OP_CALL0: - RUNAWAYCHECK(); - pr_xstatement = st-pr_statements; - - - if (st->op > OP_CALL8) - pr_argc = st->op - (OP_CALL1H-1); - else - pr_argc = st->op - OP_CALL0; - fnum = OPA->function; - if ((fnum & ~0xff000000)<=0) - { - pr_trace++; - printf("NULL function from qc.\n"); -#ifndef DEBUGABLE - goto cont; -#endif - break; - } - - p=pr_typecurrent; -//about to switch. needs caching. - - //if it's an external call, switch now (before any function pointers are used) - PR_MoveParms(progfuncs, (fnum & 0xff000000)>>24, p); - PR_SwitchProgs(progfuncs, (fnum & 0xff000000)>>24); - - newf = &pr_functions[fnum & ~0xff000000]; - - if (newf->first_statement < 0) - { // negative statements are built in functions - i = -newf->first_statement; -// p = pr_typecurrent; - if (i < externs->numglobalbuiltins) - { - (*externs->globalbuiltins[i]) (progfuncs, (struct globalvars_s *)current_progstate->globals); - if (prinst->continuestatement!=-1) - { - st=&pr_statements[prinst->continuestatement]; - prinst->continuestatement=-1; - break; - } - } - else - { - i -= externs->numglobalbuiltins; - if (i > current_progstate->numbuiltins) - { - if (newf->first_statement == -0x7fffffff) - ((builtin_t)newf->profile) (progfuncs, (struct globalvars_s *)current_progstate->globals); - else - PR_RunError (progfuncs, "Bad builtin call number"); - } - else - current_progstate->builtins [i] (progfuncs, (struct globalvars_s *)current_progstate->globals); - } - PR_MoveParms(progfuncs, p, pr_typecurrent); -// memcpy(&pr_progstate[p].globals[OFS_RETURN], ¤t_progstate->globals[OFS_RETURN], sizeof(vec3_t)); - PR_SwitchProgs(progfuncs, (progsnum_t)p); - -//#ifndef DEBUGABLE //decide weather non debugger wants to start debugging. - s = st-pr_statements; - goto restart; -//#endif -// break; - } -// PR_MoveParms((OPA->function & 0xff000000)>>24, pr_typecurrent); -// PR_SwitchProgs((OPA->function & 0xff000000)>>24); - s = PR_EnterFunction (progfuncs, newf, p); - st = &pr_statements[s]; - - goto restart; -// break; - - case OP_DONE: - case OP_RETURN: - - RUNAWAYCHECK(); - - pr_globals[OFS_RETURN] = pr_globals[st->a]; - pr_globals[OFS_RETURN+1] = pr_globals[st->a+1]; - pr_globals[OFS_RETURN+2] = pr_globals[st->a+2]; - - s = PR_LeaveFunction (progfuncs); - st = &pr_statements[s]; - if (pr_depth == exitdepth) - { - PR_MoveParms(progfuncs, initial_progs, pr_typecurrent); - PR_SwitchProgs(progfuncs, initial_progs); - return; // all done - } - goto restart; -// break; - - case OP_STATE: - externs->stateop(progfuncs, OPA->_float, OPB->function); - break; - - case OP_ADD_I: - OPC->_int = OPA->_int + OPB->_int; - break; - case OP_ADD_FI: - OPC->_float = OPA->_float + (float)OPB->_int; - break; - case OP_ADD_IF: - OPC->_float = (float)OPA->_int + OPB->_float; - break; - - case OP_SUB_I: - OPC->_int = OPA->_int - OPB->_int; - break; - case OP_SUB_FI: - OPC->_float = OPA->_float - (float)OPB->_int; - break; - case OP_SUB_IF: - OPC->_float = (float)OPA->_int - OPB->_float; - break; - - case OP_C_ITOF: - OPC->_float = (float)OPA->_int; - break; - case OP_C_FTOI: - OPC->_int = (int)OPA->_float; - break; - - case OP_CP_ITOF: - ptr = (eval_t *)(((qbyte *)sv_edicts) + OPA->_int); - OPC->_float = (float)ptr->_int; - break; - - case OP_CP_FTOI: - ptr = (eval_t *)(((qbyte *)sv_edicts) + OPA->_int); - OPC->_int = (int)ptr->_float; - break; - - case OP_BITAND_I: - OPC->_int = (OPA->_int & OPB->_int); - break; - - case OP_BITOR_I: - OPC->_int = (OPA->_int | OPB->_int); - break; - - case OP_MUL_I: - OPC->_int = OPA->_int * OPB->_int; - break; - case OP_DIV_I: - if (OPB->_int == 0) //no division by zero allowed... - OPC->_int = 0; - else - OPC->_int = OPA->_int / OPB->_int; - break; - case OP_EQ_I: - OPC->_int = (OPA->_int == OPB->_int); - break; - case OP_NE_I: - OPC->_int = (OPA->_int != OPB->_int); - break; - - - //array/structure reading/riting. - case OP_GLOBALADDRESS: - OPC->_int = (int)(&((int)(OPA->_int)) + OPB->_int); - break; - case OP_POINTER_ADD: //pointer to 32 bit (remember to *3 for vectors) - OPC->_int = OPA->_int + OPB->_int*4; - break; - - case OP_LOADA_I: - case OP_LOADA_F: - case OP_LOADA_FLD: - case OP_LOADA_ENT: - case OP_LOADA_S: - case OP_LOADA_FNC: - ptr = (eval_t *)(&((int)(OPA->_int)) + OPB->_int); - OPC->_int = ptr->_int; - break; - - case OP_LOADA_V: - ptr = (eval_t *)(&((int)(OPA->_int)) + OPB->_int); - OPC->vector[0] = ptr->vector[0]; - OPC->vector[1] = ptr->vector[1]; - OPC->vector[2] = ptr->vector[2]; - break; - - case OP_ADD_SF: //(char*)c = (char*)a + (float)b - OPC->_int = OPA->_int + (int)OPB->_float; - break; - case OP_SUB_S: //(float)c = (char*)a - (char*)b - OPC->_int = OPA->_int - OPB->_int; - break; - case OP_LOADP_C: //load character from a string - ptr = (eval_t *)(((int)(OPA->_int)) + (int)OPB->_float); - OPC->_float = *(unsigned char *)ptr; - break; - case OP_LOADP_I: - case OP_LOADP_F: - case OP_LOADP_FLD: - case OP_LOADP_ENT: - case OP_LOADP_S: - case OP_LOADP_FNC: -#ifdef PRBOUNDSCHECK - if (OPB->_int < 0 || OPB->_int >= pr_edict_size/4) - { - Host_Error("Progs attempted to read an invalid field in an edict (%i)\n", OPB->_int); - return; - } -#endif - ptr = (eval_t *)(((int)(OPA->_int)) + OPB->_int); - OPC->_int = ptr->_int; - break; - - case OP_LOADP_V: -#ifdef PRBOUNDSCHECK - if (OPB->_int < 0 || OPB->_int + 2 >= pr_edict_size/4) - { - Host_Error("Progs attempted to read an invalid field in an edict (%i)\n", OPB->_int); - return; - } -#endif - - ptr = (eval_t *)(((int)(OPA->_int)) + OPB->_int); - OPC->vector[0] = ptr->vector[0]; - OPC->vector[1] = ptr->vector[1]; - OPC->vector[2] = ptr->vector[2]; - break; - - case OP_POWER_I: - OPC->_int = OPA->_int ^ OPB->_int; - break; - case OP_RSHIFT_I: - OPC->_int = OPA->_int >> OPB->_int; - break; - case OP_LSHIFT_I: - OPC->_int = OPA->_int << OPB->_int; - break; - - - case OP_FETCH_GBL_F: - case OP_FETCH_GBL_S: - case OP_FETCH_GBL_E: - case OP_FETCH_GBL_FNC: - i = (int)OPB->_float; - if(i < 0 || i > G_INT((uofs)st->a - 1)) - { - PR_RunError(progfuncs, "array index out of bounds: %s[%d]", PR_GlobalStringNoContents(progfuncs, st->a), i); - } - t = (eval_t *)&pr_globals[(uofs)st->a + i]; - OPC->_int = t->_int; - break; - case OP_FETCH_GBL_V: - i = (int)OPB->_float; - if(i < 0 || i > G_INT((uofs)st->a - 1)) - { - PR_RunError(progfuncs, "array index out of bounds: %s[%d]", PR_GlobalStringNoContents(progfuncs, st->a), i); - } - t = (eval_t *)&pr_globals[(uofs)st->a - +((int)OPB->_float)*3]; - OPC->vector[0] = t->vector[0]; - OPC->vector[1] = t->vector[1]; - OPC->vector[2] = t->vector[2]; - break; - - case OP_CSTATE: - externs->cstateop(progfuncs, OPA->_float, OPB->_float, fnum); - break; - - case OP_CWSTATE: - externs->cwstateop(progfuncs, OPA->_float, OPB->_float, fnum); - break; - - case OP_THINKTIME: - externs->thinktimeop(progfuncs, (struct edict_s *)PROG_TO_EDICT(OPA->edict), OPB->_float); - break; - - - case OP_BITSET: // b (+) a - OPB->_float = (float)((int)OPB->_float | (int)OPA->_float); - break; - case OP_BITSETP: // .b (+) a - ptr = (eval_t *)(OPB->_int); - ptr->_float = (float)((int)ptr->_float | (int)OPA->_float); - break; - case OP_BITCLR: // b (-) a - OPB->_float = (float)((int)OPB->_float & ~((int)OPA->_float)); - break; - case OP_BITCLRP: // .b (-) a - ptr = (eval_t *)(OPB->_int); - ptr->_float = (float)((int)ptr->_float & ~((int)OPA->_float)); - break; - - case OP_RAND0: - G_FLOAT(OFS_RETURN) = (rand()&0x7fff)/((float)0x7fff); - break; - case OP_RAND1: - G_FLOAT(OFS_RETURN) = (rand()&0x7fff)/((float)0x7fff)*OPA->_float; - break; - case OP_RAND2: - if(OPA->_float < OPB->_float) - { - G_FLOAT(OFS_RETURN) = OPA->_float+((rand()&0x7fff)/((float)0x7fff) - *(OPB->_float-OPA->_float)); - } - else - { - G_FLOAT(OFS_RETURN) = OPB->_float+((rand()&0x7fff)/((float)0x7fff) - *(OPA->_float-OPB->_float)); - } - break; - case OP_RANDV0: - G_FLOAT(OFS_RETURN+0) = (rand()&0x7fff)/((float)0x7fff); - G_FLOAT(OFS_RETURN+1) = (rand()&0x7fff)/((float)0x7fff); - G_FLOAT(OFS_RETURN+2) = (rand()&0x7fff)/((float)0x7fff); - break; - case OP_RANDV1: - G_FLOAT(OFS_RETURN+0) = (rand()&0x7fff)/((float)0x7fff)*OPA->vector[0]; - G_FLOAT(OFS_RETURN+1) = (rand()&0x7fff)/((float)0x7fff)*OPA->vector[1]; - G_FLOAT(OFS_RETURN+2) = (rand()&0x7fff)/((float)0x7fff)*OPA->vector[2]; - break; - case OP_RANDV2: - for(i = 0; i < 3; i++) - { - if(OPA->vector[i] < OPB->vector[i]) - { - G_FLOAT(OFS_RETURN+i) = OPA->vector[i]+((rand()&0x7fff)/((float)0x7fff) - *(OPB->vector[i]-OPA->vector[i])); - } - else - { - G_FLOAT(OFS_RETURN+i) = OPB->vector[i]+(rand()*(1.0f/RAND_MAX) - *(OPA->vector[i]-OPB->vector[i])); - } - } - break; - - - case OP_SWITCH_F: - case OP_SWITCH_V: - case OP_SWITCH_S: - case OP_SWITCH_E: - case OP_SWITCH_FNC: - swtch = OPA; - swtchtype = st->op; - RUNAWAYCHECK(); - st += (sofs)st->b - 1; // offset the st++ - break; - case OP_CASE: - switch(swtchtype) - { - case OP_SWITCH_F: - if (swtch->_float == OPA->_float) - { - RUNAWAYCHECK(); - st += (sofs)st->b-1; // -1 to offset the s++ - } - break; - case OP_SWITCH_E: - case OP_SWITCH_FNC: - if (swtch->_int == OPA->_int) - { - RUNAWAYCHECK(); - st += (sofs)st->b-1; // -1 to offset the s++ - } - break; - case OP_SWITCH_S: - if (swtch->_int == OPA->_int) - { - RUNAWAYCHECK(); - st += (sofs)st->b-1; // -1 to offset the s++ - } - if ((!swtch->_int && progfuncs->stringtable[OPA->string]) || (!OPA->_int && progfuncs->stringtable[swtch->string])) //one is null (cannot be not both). - break; - if (!strcmp(progfuncs->stringtable+swtch->string, progfuncs->stringtable+OPA->string)) - { - RUNAWAYCHECK(); - st += (sofs)st->b-1; // -1 to offset the s++ - } - break; - case OP_SWITCH_V: - if (swtch->vector[0] == OPA->vector[0] && swtch->vector[1] == OPA->vector[1] && swtch->vector[2] == OPA->vector[2]) - { - RUNAWAYCHECK(); - st += (sofs)st->b-1; // -1 to offset the s++ - } - break; - default: - PR_RunError (progfuncs, "OP_CASE with bad/missing OP_SWITCH %i", swtchtype); - break; - } - break; - case OP_CASERANGE: - switch(swtchtype) - { - case OP_SWITCH_F: - if (swtch->_float >= OPA->_float && swtch->_float <= OPB->_float) - { - RUNAWAYCHECK(); - st += (sofs)st->c-1; // -1 to offset the s++ - } - break; - default: - PR_RunError (progfuncs, "OP_CASERANGE with bad/missing OP_SWITCH %i", swtchtype); - } - break; - - default: - if (st->op & 0x8000) //break point! - { - pr_xstatement = s = st-pr_statements; - - printf("Break point hit.\n"); - if (pr_trace<1) - pr_trace=1; //this is what it's for - - s = ShowStep(progfuncs, s); - st = &pr_statements[s]; //let the user move execution - pr_xstatement = s = st-pr_statements; - - memcpy(&fakeop, st, sizeof(dstatement_t)); //don't hit the new statement as a break point, cos it's probably the same one. - fakeop.op &= ~0x8000; - st = &fakeop; //a little remapping... - - goto reeval; //reexecute - } - pr_xstatement = st-pr_statements; - PR_RunError (progfuncs, "Bad opcode %i", st->op); - } -} - - -#undef cont -#undef reeval -#undef st -#undef pr_statements -#undef fakeop -#undef dstatement_t -#undef sofs -#undef uofs diff --git a/engine/qclib/execloop16d.h b/engine/qclib/execloop16d.h index b1268556b..fae820ebf 100644 --- a/engine/qclib/execloop16d.h +++ b/engine/qclib/execloop16d.h @@ -395,7 +395,7 @@ reeval: if (ed->readonly) { pr_xstatement = st-pr_statements; - PR_RunError (progfuncs, "assignment to read-only entity in %s", pr_xfunction->s_name); + PR_RunError (progfuncs, "assignment to read-only entity in %s", progfuncs->stringtable + pr_xfunction->s_name); } OPC->_int = ENGINEPOINTER((((int *)edvars(ed)) + OPB->_int + progfuncs->fieldadjust)); break; diff --git a/engine/qclib/execloop32.h b/engine/qclib/execloop32.h index b1268556b..fae820ebf 100644 --- a/engine/qclib/execloop32.h +++ b/engine/qclib/execloop32.h @@ -395,7 +395,7 @@ reeval: if (ed->readonly) { pr_xstatement = st-pr_statements; - PR_RunError (progfuncs, "assignment to read-only entity in %s", pr_xfunction->s_name); + PR_RunError (progfuncs, "assignment to read-only entity in %s", progfuncs->stringtable + pr_xfunction->s_name); } OPC->_int = ENGINEPOINTER((((int *)edvars(ed)) + OPB->_int + progfuncs->fieldadjust)); break; diff --git a/engine/qclib/execloop32d.h b/engine/qclib/execloop32d.h index b1268556b..fae820ebf 100644 --- a/engine/qclib/execloop32d.h +++ b/engine/qclib/execloop32d.h @@ -395,7 +395,7 @@ reeval: if (ed->readonly) { pr_xstatement = st-pr_statements; - PR_RunError (progfuncs, "assignment to read-only entity in %s", pr_xfunction->s_name); + PR_RunError (progfuncs, "assignment to read-only entity in %s", progfuncs->stringtable + pr_xfunction->s_name); } OPC->_int = ENGINEPOINTER((((int *)edvars(ed)) + OPB->_int + progfuncs->fieldadjust)); break; diff --git a/engine/qclib/initlib.c b/engine/qclib/initlib.c index 1bb3dab21..7e2320189 100644 --- a/engine/qclib/initlib.c +++ b/engine/qclib/initlib.c @@ -98,7 +98,9 @@ int PR_InitEnts(progfuncs_t *progfuncs, int max_ents) return max_fields_size; } -char tempedicts[2048]; //used as a safty buffer +edictrun_t tempedict; //used as a safty buffer +float tempedictfields[2048]; + void PR_Configure (progfuncs_t *progfuncs, int addressable_size, int max_progs) //can be used to wipe all memory { int i; @@ -139,9 +141,12 @@ void PR_Configure (progfuncs_t *progfuncs, int addressable_size, int max_progs) prinst->reorganisefields = false; maxedicts = 1; + prinst->edicttable = &sv_edicts; sv_num_edicts = 1; //set up a safty buffer so things won't go horribly wrong too often - sv_edicts=(struct edict_s *)tempedicts; - ((edictrun_t*)sv_edicts)->readonly = true; + sv_edicts=(struct edict_s *)&tempedict; + tempedict.readonly = true; + tempedict.fields = tempedictfields; + tempedict.isfree = false; } diff --git a/engine/qclib/pr_edict.c b/engine/qclib/pr_edict.c index 46d914056..1243e1349 100644 --- a/engine/qclib/pr_edict.c +++ b/engine/qclib/pr_edict.c @@ -1620,7 +1620,7 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags) ddef32_t *d32; func_t CheckSpawn=0; - extern char tempedicts[]; + extern edictrun_t tempedict; int crc = 1; int entsize = 0; @@ -1885,8 +1885,9 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags) pr_typecurrent=0; sv_num_edicts = 1; //set up a safty buffer so things won't go horribly wrong too often - sv_edicts=(struct edict_s *)tempedicts; - ((edictrun_t*)sv_edicts)->readonly = true; + sv_edicts=(struct edict_s *)&tempedict; + prinst->edicttable = &sv_edicts; + sv_num_edicts = numents; //should be fine diff --git a/engine/qclib/pr_exec.c b/engine/qclib/pr_exec.c index fc48cc946..6c23b5ecb 100644 --- a/engine/qclib/pr_exec.c +++ b/engine/qclib/pr_exec.c @@ -209,8 +209,8 @@ void VARGS PR_RunError (progfuncs_t *progfuncs, char *error, ...) //editbadfile(pr_strings + pr_xfunction->s_file, -1); - pr_depth = 0; // dump the stack so host_error can shutdown functions - prinst->exitdepth = 0; +// pr_depth = 0; // dump the stack so host_error can shutdown functions +// prinst->exitdepth = 0; Abort (string); } @@ -259,7 +259,11 @@ int PR_EnterFunction (progfuncs_t *progfuncs, dfunction_t *f, int progsnum) // save off any locals that the new function steps on (to a side place, fromwhere they are restored on exit) c = f->locals; if (localstack_used + c > LOCALSTACK_SIZE) + { + localstack_used -= pr_spushed; + pr_depth--; PR_RunError (progfuncs, "PR_ExecuteProgram: locals stack overflow\n"); + } for (i=0 ; i < c ; i++) localstack[localstack_used+i] = ((int *)pr_globals)[f->parm_start + i]; diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index 193e4aa78..3914975e7 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -314,10 +314,10 @@ QCC_opcode_t pr_opcodes[] = {7, "", "THINKTIME", -1, ASSOC_LEFT, &type_entity, &type_float, &type_void}, - {7, "(+)", "BITSET", 6, ASSOC_RIGHT, &type_float, &type_float, &type_float}, - {7, "(+)", "BITSETP", 6, ASSOC_RIGHT, &type_pointer, &type_float, &type_float}, - {7, "(-)", "BITCLR", 6, ASSOC_RIGHT, &type_float, &type_float, &type_float}, - {7, "(-)", "BITCLRP", 6, ASSOC_RIGHT, &type_pointer, &type_float, &type_float}, + {7, "|=", "BITSET_F", 6, ASSOC_RIGHT, &type_float, &type_float, &type_float}, + {7, "|=", "BITSETP_F", 6, ASSOC_RIGHT, &type_pointer, &type_float, &type_float}, + {7, "(-)", "BITCLR_F", 6, ASSOC_RIGHT, &type_float, &type_float, &type_float}, + {7, "(-)", "BITCLRP_F", 6, ASSOC_RIGHT, &type_pointer, &type_float, &type_float}, {7, "", "RAND0", -1, ASSOC_LEFT, &type_void, &type_void, &type_float}, {7, "", "RAND1", -1, ASSOC_LEFT, &type_float, &type_void, &type_float}, @@ -477,18 +477,29 @@ QCC_opcode_t pr_opcodes[] = {7, "<>", "GADDRESS", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, -{7, "<>", "GLOAD_I", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, -{7, "<>", "GLOAD_F", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, -{7, "<>", "GLOAD_FLD", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, -{7, "<>", "GLOAD_ENT", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, -{7, "<>", "GLOAD_S", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, -{7, "<>", "GLOAD_FNC", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "GLOAD_I", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "GLOAD_F", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "GLOAD_FLD", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "GLOAD_ENT", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "GLOAD_S", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "GLOAD_FNC", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, -{7, "<>", "BOUNDCHECK", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "BOUNDCHECK", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, -{7, "=", "STOREP_P", 6, ASSOC_RIGHT, &type_pointer, &type_pointer, &type_void}, -{7, "", "PUSH", -1, ASSOC_RIGHT, &type_float, &type_void, &type_pointer}, -{7, "", "POP", -1, ASSOC_RIGHT, &type_float, &type_void, &type_void}, +{7, "=", "STOREP_P", 6, ASSOC_RIGHT, &type_pointer, &type_pointer, &type_void}, +{7, "", "PUSH", -1, ASSOC_RIGHT, &type_float, &type_void, &type_pointer}, +{7, "", "POP", -1, ASSOC_RIGHT, &type_float, &type_void, &type_void}, + + {7, "|=", "BITSET_I", 6, ASSOC_RIGHT, &type_integer, &type_integer, &type_integer}, + {7, "|=", "BITSETP_I", 6, ASSOC_RIGHT, &type_pointer, &type_integer, &type_integer}, + {7, "*=", "MULSTORE_I", 6, ASSOC_RIGHT_RESULT, &type_integer, &type_integer, &type_integer}, + {7, "*=", "MULSTOREP_I", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_vector}, + {7, "/=", "DIVSTORE_I", 6, ASSOC_RIGHT_RESULT, &type_integer, &type_integer, &type_integer}, + {7, "/=", "DIVSTOREP_I", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_vector}, + {7, "+=", "ADDSTORE_I", 6, ASSOC_RIGHT_RESULT, &type_integer, &type_integer, &type_integer}, + {7, "+=", "ADDSTOREP_I", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_integer}, + {7, "-=", "SUBSTORE_I", 6, ASSOC_RIGHT_RESULT, &type_integer, &type_integer, &type_integer}, + {7, "-=", "SUBSTOREP_I", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_vector, &type_vector}, {0, NULL} }; @@ -842,13 +853,14 @@ void QCC_FreeOffset(gofs_t ofs, unsigned int size) { freeoffset_t *fofs; if (ofs+size == numpr_globals) - { + { //fixme: is this a bug? numpr_globals -= size; return; } for (fofs = freeofs; fofs; fofs=fofs->next) { + //fixme: if this means the last block becomes free, free them all. if (fofs->ofs == ofs + size) { fofs->ofs -= size; @@ -1328,10 +1340,13 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var QCC_PR_ParseWarning(0, "Result of comparison is constant"); break; case OP_EQ_F: - case OP_EQ_V: case OP_EQ_S: case OP_EQ_E: case OP_EQ_FNC: +// if (opt_shortenifnots) +// if (var_b->constant && ((int*)qcc_pr_globals)[var_b->ofs]==0) // (a == 0) becomes (!a) +// op = &pr_opcodes[(op - pr_opcodes) - OP_EQ_F + OP_NOT_F]; + case OP_EQ_V: case OP_NE_F: case OP_NE_V: @@ -7297,25 +7312,27 @@ void QCC_PR_ParseDefs (char *classname) v = pr_immediate._float; QCC_PR_Lex(); } - - bits = 0; - i = (int)v; - if (i != v) - QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTINTEGER, "enumflags - %f not an integer", v); - else - { - while(i) - { - if (((i>>1)<<1) != i) - bits++; - i>>=1; - } - if (bits != 1) - QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTBINARY, "enumflags - value %i not a single bit", (int)v); - } } + + bits = 0; + i = (int)v; + if (i != v) + QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTINTEGER, "enumflags - %f not an integer", v); + else + { + while(i) + { + if (((i>>1)<<1) != i) + bits++; + i>>=1; + } + if (bits != 1) + QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTBINARY, "enumflags - value %i not a single bit", (int)v); + } + def = QCC_MakeFloatDef(v); pHash_Add(&globalstable, name, def, qccHunkAlloc(sizeof(bucket_t))); + v*=2; if (QCC_PR_CheckToken("}")) diff --git a/engine/qclib/qcc_pr_lex.c b/engine/qclib/qcc_pr_lex.c index 370d6c9f3..6ce1c668e 100644 --- a/engine/qclib/qcc_pr_lex.c +++ b/engine/qclib/qcc_pr_lex.c @@ -43,12 +43,12 @@ int numCompilerConstants; char *pr_punctuation[] = // longer symbols must be before a shorter partial match -{"&&", "||", "<=", ">=","==", "!=", "/=", "*=", "+=", "-=", "|=", "(+)", "(-)", "++", "--", "->", "::", ";", ",", "!", "*", "/", "(", ")", "-", "+", "=", "[", "]", "{", "}", "...", "..", ".", "<<", "<", ">>", ">" , "#" , "@", "&" , "|", "^", ":", NULL}; +{"&&", "||", "<=", ">=","==", "!=", "/=", "*=", "+=", "-=", "(+)", "|=", "(-)", "++", "--", "->", "::", ";", ",", "!", "*", "/", "(", ")", "-", "+", "=", "[", "]", "{", "}", "...", "..", ".", "<<", "<", ">>", ">" , "#" , "@", "&" , "|", "^", ":", NULL}; char *pr_punctuationremap[] = //a nice bit of evilness. //|= -> (+) //-> -> . -{"&&", "||", "<=", ">=","==", "!=", "/=", "*=", "+=", "-=", "(+)","(+)", "(-)", "++", "--", ".", "::", ";", ",", "!", "*", "/", "(", ")", "-", "+", "=", "[", "]", "{", "}", "...", "..", ".", "<<", "<", ">>", ">" , "#" , "@", "&" , "|", "^", ":", NULL}; +{"&&", "||", "<=", ">=","==", "!=", "/=", "*=", "+=", "-=", "|=", "|=", "(-)", "++", "--", ".", "::", ";", ",", "!", "*", "/", "(", ")", "-", "+", "=", "[", "]", "{", "}", "...", "..", ".", "<<", "<", ">>", ">" , "#" , "@", "&" , "|", "^", ":", NULL}; // simple types. function types are dynamically allocated QCC_type_t *type_void;// = {ev_void/*, &def_void*/}; diff --git a/engine/server/net_preparse.c b/engine/server/net_preparse.c index 2dfbf5125..5baedd4ee 100644 --- a/engine/server/net_preparse.c +++ b/engine/server/net_preparse.c @@ -135,10 +135,21 @@ void NPP_Flush(void) } bufferlen = 0; break; - case svcdp_showlmp: case svcdp_hidelmp: - ignoreprotocol = true; - Con_Printf ("Ignoring svc_showlmp\n"); + requireextension = PEXT_SHOWPIC; + buffer[0] = svc_hidepic; + break; + case svcdp_showlmp: + requireextension = PEXT_SHOWPIC; + memmove(buffer+2, buffer+1, bufferlen-1); + bufferlen++; + buffer[0] = svc_showpic; + buffer[1] = 0; //top left + //pad the bytes to shorts. + buffer[bufferlen] = buffer[bufferlen-1]; + buffer[bufferlen-1] = 0; + buffer[bufferlen+1] = 0; + bufferlen+=2; break; case svc_temp_entity: @@ -455,13 +466,15 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw) if (!data) protocollen = bufferlen; break; - case svcdp_showlmp: // [string] slotname [string] lmpfilename [short] x [short] y + case svcdp_showlmp: // [string] slotname [string] lmpfilename [byte] x [byte] y + //note: nehara uses bytes! + //and the rest of dp uses shorts. how nasty is that? if (!data) - { //second string, plus 4 bytes. + { //second string, plus 2 bytes. int i; for (i = 0; i < bufferlen; i++) if (!buffer[i]) - protocollen = bufferlen+4; + protocollen = bufferlen+2; } break; } diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index a1ecca8fd..46555be73 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -3022,6 +3022,53 @@ void PF_dropclient (progfuncs_t *prinst, struct globalvars_s *pr_globals) cl->drop = true; return; } + + + +//DP_QC_BOTCLIENT +//entity() spawnclient = #454; +void PF_spawnclient (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int i; + for (i = 0; i < sv.allocated_client_slots; i++) + { + if (!*svs.clients[i].name) + { + svs.clients[i].protocol = SCP_BAD; + svs.clients[i].state = cs_spawned; + svs.clients[i].netchan.message.allowoverflow = true; + svs.clients[i].netchan.message.maxsize = 0; + svs.clients[i].datagram.allowoverflow = true; + svs.clients[i].datagram.maxsize = 0; + RETURN_EDICT(prinst, svs.clients[i].edict); + return; + } + } + RETURN_EDICT(prinst, sv.edicts); +} + +//DP_QC_BOTCLIENT +//float(entity client) clienttype = #455; +void PF_clienttype (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int entnum = G_EDICTNUM(prinst, OFS_PARM0); + if (entnum < 1 || entnum > sv.allocated_client_slots) + { + G_FLOAT(OFS_RETURN) = 3; //not a client slot + return; + } + entnum--; + if (svs.clients[entnum].state < cs_connected) + { + G_FLOAT(OFS_RETURN) = 0; //disconnected + return; + } + if (svs.clients[entnum].protocol == SCP_BAD) + G_FLOAT(OFS_RETURN) = 2; //an active, not-bot client. + else + G_FLOAT(OFS_RETURN) = 1; //an active, not-bot client. +} + /* ================= PF_localcmd @@ -5992,6 +6039,8 @@ lh_extension_t QSG_Extensions[] = { {"DP_EF_FULLBRIGHT"}, //Rerouted to hexen2 support. {"DP_EF_NODRAW"}, //implemented by sending it with no modelindex {"DP_EF_RED"}, + {"DP_ENT_EXTERIORMODELTOCLIENT"}, + {"DP_GFX_SKINFILES"}, {"DP_HALFLIFE_MAP_CVAR"}, {"DP_MONSTERWALK"}, {"DP_MOVETYPEBOUNCEMISSILE"}, //I added the code for hexen2 support. @@ -8288,22 +8337,87 @@ typedef struct { float ang[3][3]; } md3tag_t; -md3tag_t *SV_GetTags(int modelindex, int *tagcount) +typedef struct zymlump_s { - md3Header_t *file; - file = (md3Header_t*)COM_LoadTempFile(sv.model_precache[modelindex]); + int start; + int length; +} zymlump_t; +typedef struct zymtype1header_s +{ + char id[12]; // "ZYMOTICMODEL", length 12, no termination + int type; // 0 (vertex morph) 1 (skeletal pose) or 2 (skeletal scripted) + int filesize; // size of entire model file + float mins[3], maxs[3], radius; // for clipping uses + int numverts; + int numtris; + int numsurfaces; + int numbones; // this may be zero in the vertex morph format (undecided) + int numscenes; // 0 in skeletal scripted models + +// skeletal pose header + // lump offsets are relative to the file + zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct) + zymlump_t lump_poses; // float pose[numposes][numbones][6]; // animation data + zymlump_t lump_bones; // zymbone_t bone[numbones]; + zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better) + zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct + zymlump_t lump_texcoords; // float texcoords[numvertices][2]; + zymlump_t lump_render; // int renderlist[rendersize]; // sorted by shader with run lengths (int count), shaders are sequentially used, each run can be used with glDrawElements (each triangle is 3 int indices) + zymlump_t lump_surfnames; // char shadername[numsurfaces][32]; // shaders used on this model + zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation +} zymtype1header_t; +typedef struct zymbone_s +{ + char name[32]; + int flags; + int parent; // parent bone number +} zymbone_t; + +int SV_TagForName(int modelindex, char *tagname) +{ + int i; + unsigned int *file; + + file = (void*)COM_LoadTempFile(sv.model_precache[modelindex]); if (!file) { Con_Printf("setattachment: \"%s\" is missing\n", sv.model_precache[modelindex]); - return NULL; + return 0; } - if (file->ident != MD3_IDENT) + + if (*file == MD3_IDENT) { - Con_DPrintf("setattachment: not an md3 (%s)\n", sv.model_precache[modelindex]); - return NULL; + md3Header_t *md3 = (md3Header_t*)file; + md3tag_t *tag; + + tag = (md3tag_t*)((char*)md3 + md3->ofsTags); + + for (i = 0;i < md3->numTags;i++) + { + if (!strcmp(tagname, tag[i].name)) + { + return i + 1; + } + } } - *tagcount = file->numTags; - return (md3tag_t*)((char*)file + file->ofsTags); + else if (!strncmp((char*)file, "ZYMOTICMODEL", 12) && BigLong(file[3]) == 1) + { + zymtype1header_t *zym = (zymtype1header_t*)file; + zymbone_t *tag; + + tag = (zymbone_t*)((char*)zym + BigLong(zym->lump_bones.start)); + + for (i = BigLong(zym->numbones)-1;i >=0;i--) + { + if (!strcmp(tagname, tag[i].name)) + { + return i + 1; + } + } + } + else + Con_DPrintf("setattachment: %s not supported\n", sv.model_precache[modelindex]); + return 0; } void PF_setattachment(progfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -8315,9 +8429,7 @@ void PF_setattachment(progfuncs_t *prinst, struct globalvars_s *pr_globals) eval_t *te; eval_t *ti; - int i, modelindex; - md3tag_t *model; - int tagcount; + int modelindex; te = prinst->GetEdictFieldValue(prinst, e, "tag_entity", NULL); ti = prinst->GetEdictFieldValue(prinst, e, "tag_index", NULL); @@ -8328,18 +8440,11 @@ void PF_setattachment(progfuncs_t *prinst, struct globalvars_s *pr_globals) if (tagentity != sv.edicts && tagname && tagname[0]) { modelindex = (int)tagentity->v->modelindex; - if (modelindex > 0 && modelindex < MAX_MODELS && (model = SV_GetTags(modelindex, &tagcount))) + if (modelindex > 0 && modelindex < MAX_MODELS && sv.model_precache[modelindex]) { - for (i = 0;i < tagcount;i++) - { - if (!strcmp(tagname, model[i].name)) - { - e->tagindex = i + 1; - break; - } - } + e->tagindex = SV_TagForName(modelindex, tagname); if (e->tagindex == 0) - Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i (model \"%s\") but could not find it\n", NUM_FOR_EDICT(prinst, e), NUM_FOR_EDICT(prinst, tagentity), tagname, tagname, NUM_FOR_EDICT(prinst, tagentity), model->name); + Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i (model \"%s\") but could not find it\n", NUM_FOR_EDICT(prinst, e), NUM_FOR_EDICT(prinst, tagentity), tagname, tagname, NUM_FOR_EDICT(prinst, tagentity), sv.models[modelindex]->name); } else Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i but it has no model\n", NUM_FOR_EDICT(prinst, e), NUM_FOR_EDICT(prinst, tagentity), tagname, tagname, NUM_FOR_EDICT(prinst, tagentity)); @@ -8351,7 +8456,7 @@ void PF_setattachment(progfuncs_t *prinst, struct globalvars_s *pr_globals) MSG_WriteShort(&sv.multicast, e->entnum); MSG_WriteShort(&sv.multicast, e->tagent); MSG_WriteShort(&sv.multicast, e->tagindex); - + SV_MulticastProtExt(vec3_origin, MULTICAST_ALL_R, 0xffffffff, PEXT_SETATTACHMENT, 0); if (te) @@ -8749,6 +8854,9 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"dropclient", PF_dropclient, 0, 0, 0, 453},// #453 void(entity player) dropclient + {"spawnclient", PF_spawnclient, 0, 0, 0, 454}, //entity() spawnclient = #454; + {"clienttype", PF_clienttype, 0, 0, 0, 455}, //float(entity client) clienttype = #455; + //end other peoples extras {"writestring2", PF_WriteString2, 0, 0, 0, 700}, //writestring but without the null terminator. makes things a little nicer. diff --git a/engine/server/server.h b/engine/server/server.h index f0b494e5e..7541cd16c 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -489,7 +489,7 @@ typedef struct client_s unsigned long zquake_extensions; enum { - SCP_BAD, + SCP_BAD, //don't send (a bot) SCP_QUAKEWORLD, SCP_QUAKE2, SCP_NETQUAKE, @@ -967,6 +967,10 @@ void SV_FindModelNumbers (void); // // sv_user.c // +#ifdef NQPROT +void SVNQ_New_f (void); +void SVNQ_ExecuteClientMessage (client_t *cl); +#endif void SV_ExecuteClientMessage (client_t *cl); void SVQ2_ExecuteClientMessage (client_t *cl); int SV_PMTypeForClient (client_t *cl); diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index 90108edac..d635f389d 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -695,6 +695,323 @@ void SV_EmitPacketEntities (client_t *client, packet_entities_t *to, sizebuf_t * MSG_WriteShort (msg, 0); // end of packetentities } +#ifdef NQPROT + +// reset all entity fields (typically used if status changed) +#define E5_FULLUPDATE (1<<0) +// E5_ORIGIN32=0: short[3] = s->origin[0] * 8, s->origin[1] * 8, s->origin[2] * 8 +// E5_ORIGIN32=1: float[3] = s->origin[0], s->origin[1], s->origin[2] +#define E5_ORIGIN (1<<1) +// E5_ANGLES16=0: byte[3] = s->angle[0] * 256 / 360, s->angle[1] * 256 / 360, s->angle[2] * 256 / 360 +// E5_ANGLES16=1: short[3] = s->angle[0] * 65536 / 360, s->angle[1] * 65536 / 360, s->angle[2] * 65536 / 360 +#define E5_ANGLES (1<<2) +// E5_MODEL16=0: byte = s->modelindex +// E5_MODEL16=1: short = s->modelindex +#define E5_MODEL (1<<3) +// E5_FRAME16=0: byte = s->frame +// E5_FRAME16=1: short = s->frame +#define E5_FRAME (1<<4) +// byte = s->skin +#define E5_SKIN (1<<5) +// E5_EFFECTS16=0 && E5_EFFECTS32=0: byte = s->effects +// E5_EFFECTS16=1 && E5_EFFECTS32=0: short = s->effects +// E5_EFFECTS16=0 && E5_EFFECTS32=1: int = s->effects +// E5_EFFECTS16=1 && E5_EFFECTS32=1: int = s->effects +#define E5_EFFECTS (1<<6) +// bits >= (1<<8) +#define E5_EXTEND1 (1<<7) + +// byte = s->renderflags +#define E5_FLAGS (1<<8) +// byte = bound(0, s->alpha * 255, 255) +#define E5_ALPHA (1<<9) +// byte = bound(0, s->scale * 16, 255) +#define E5_SCALE (1<<10) +// flag +#define E5_ORIGIN32 (1<<11) +// flag +#define E5_ANGLES16 (1<<12) +// flag +#define E5_MODEL16 (1<<13) +// byte = s->colormap +#define E5_COLORMAP (1<<14) +// bits >= (1<<16) +#define E5_EXTEND2 (1<<15) + +// short = s->tagentity +// byte = s->tagindex +#define E5_ATTACHMENT (1<<16) +// short[4] = s->light[0], s->light[1], s->light[2], s->light[3] +// byte = s->lightstyle +// byte = s->lightpflags +#define E5_LIGHT (1<<17) +// byte = s->glowsize +// byte = s->glowcolor +#define E5_GLOW (1<<18) +// short = s->effects +#define E5_EFFECTS16 (1<<19) +// int = s->effects +#define E5_EFFECTS32 (1<<20) +// flag +#define E5_FRAME16 (1<<21) +// unused +#define E5_UNUSED22 (1<<22) +// bits >= (1<<24) +#define E5_EXTEND3 (1<<23) + +// unused +#define E5_UNUSED24 (1<<24) +// unused +#define E5_UNUSED25 (1<<25) +// unused +#define E5_UNUSED26 (1<<26) +// unused +#define E5_UNUSED27 (1<<27) +// unused +#define E5_UNUSED28 (1<<28) +// unused +#define E5_UNUSED29 (1<<29) +// unused +#define E5_UNUSED30 (1<<30) +// bits2 > 0 +#define E5_EXTEND4 (1<<31) + + + +void SVDP_EmitEntity(entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qboolean isnew) +{ + int bits; + if (!memcmp(from, to, sizeof(entity_state_t))) + return; //didn't change + + bits = 0; + if (isnew) + bits |= E5_FULLUPDATE; + + if (!VectorCompare(from->origin, to->origin)) + bits |= E5_ORIGIN; + if (!VectorCompare(from->angles, to->angles)) + bits |= E5_ANGLES; + if (from->modelindex != to->modelindex) + bits |= E5_MODEL; + if (from->frame != to->frame) + bits |= E5_FRAME; + if (from->skinnum != to->skinnum) + bits |= E5_SKIN; + if (from->effects != to->effects) + bits |= E5_EFFECTS; + if (from->flags != to->flags) + bits |= E5_FLAGS; + if (from->trans != to->trans) + bits |= E5_ALPHA; +// if (from->scale != to->scale) +// bits |= E5_SCALE; + if (from->colormap != to->colormap) + bits |= E5_COLORMAP; +// if (from->tagentity != to->tagentity || o->tagindex != to->tagindex) +// bits |= E5_ATTACHMENT; +// if (from->light[0] != to->light[0] || o->light[1] != to->light[1] || o->light[2] != to->light[2] || o->light[3] != to->light[3] || o->lightstyle != to->lightstyle || o->lightpflags != to->lightpflags) +// bits |= E5_LIGHT; +// if (from->glowsize != to->glowsize || o->glowcolor != to->glowcolor) +// bits |= E5_GLOW; +// if (from->colormod[0] != to->colormod[0] || o->colormod[1] != to->colormod[1] || o->colormod[2] != to->colormod[2]) +// bits |= E5_COLORMOD; + + if ((bits & E5_ORIGIN) && (/*!(to->flags & RENDER_LOWPRECISION) ||*/ to->origin[0] < -4096 || to->origin[0] >= 4096 || to->origin[1] < -4096 || to->origin[1] >= 4096 || to->origin[2] < -4096 || to->origin[2] >= 4096)) + bits |= E5_ORIGIN32; + if ((bits & E5_ANGLES)/* && !(to->flags & RENDER_LOWPRECISION)*/) + bits |= E5_ANGLES16; + if ((bits & E5_MODEL) && to->modelindex >= 256) + bits |= E5_MODEL16; + if ((bits & E5_FRAME) && to->frame >= 256) + bits |= E5_FRAME16; + if (bits & E5_EFFECTS) + { + if (to->effects >= 65536) + bits |= E5_EFFECTS32; + else if (to->effects >= 256) + bits |= E5_EFFECTS16; + } + if (bits >= 256) + bits |= E5_EXTEND1; + if (bits >= 65536) + bits |= E5_EXTEND2; + if (bits >= 16777216) + bits |= E5_EXTEND3; + + to->bitmask |= bits; + + if (!bits) + return; + + MSG_WriteShort(msg, to->number); + MSG_WriteByte(msg, bits & 0xFF); + if (bits & E5_EXTEND1) + MSG_WriteByte(msg, (bits >> 8) & 0xFF); + if (bits & E5_EXTEND2) + MSG_WriteByte(msg, (bits >> 16) & 0xFF); + if (bits & E5_EXTEND3) + MSG_WriteByte(msg, (bits >> 24) & 0xFF); + if (bits & E5_FLAGS) + MSG_WriteByte(msg, to->flags); + if (bits & E5_ORIGIN) + { + if (bits & E5_ORIGIN32) + { + MSG_WriteFloat(msg, to->origin[0]); + MSG_WriteFloat(msg, to->origin[1]); + MSG_WriteFloat(msg, to->origin[2]); + } + else + { + MSG_WriteShort(msg, to->origin[0]*8); + MSG_WriteShort(msg, to->origin[1]*8); + MSG_WriteShort(msg, to->origin[2]*8); + } + } + if (bits & E5_ANGLES) + { + if (bits & E5_ANGLES16) + { + MSG_WriteAngle16(msg, to->angles[0]); + MSG_WriteAngle16(msg, to->angles[1]); + MSG_WriteAngle16(msg, to->angles[2]); + } + else + { + MSG_WriteAngle8(msg, to->angles[0]); + MSG_WriteAngle8(msg, to->angles[1]); + MSG_WriteAngle8(msg, to->angles[2]); + } + } + if (bits & E5_MODEL) + { + if (bits & E5_MODEL16) + MSG_WriteShort(msg, to->modelindex); + else + MSG_WriteByte(msg, to->modelindex); + } + if (bits & E5_FRAME) + { + if (bits & E5_FRAME16) + MSG_WriteShort(msg, to->frame); + else + MSG_WriteByte(msg, to->frame); + } + if (bits & E5_SKIN) + MSG_WriteByte(msg, to->skinnum); + if (bits & E5_EFFECTS) + { + if (bits & E5_EFFECTS32) + MSG_WriteLong(msg, to->effects); + else if (bits & E5_EFFECTS16) + MSG_WriteShort(msg, to->effects); + else + MSG_WriteByte(msg, to->effects); + } + if (bits & E5_ALPHA) + MSG_WriteByte(msg, to->trans*255); + if (bits & E5_SCALE) + MSG_WriteByte(msg, to->scale); + if (bits & E5_COLORMAP) + MSG_WriteByte(msg, to->colormap); +// if (bits & E5_ATTACHMENT) +// { +// MSG_WriteShort(msg, to->tagentity); +// MSG_WriteByte(msg, to->tagindex); +// } +// if (bits & E5_LIGHT) +// { +// MSG_WriteShort(msg, to->light[0]); +// MSG_WriteShort(msg, to->light[1]); +// MSG_WriteShort(msg, to->light[2]); +// MSG_WriteShort(msg, to->light[3]); +// MSG_WriteByte(msg, to->lightstyle); +// MSG_WriteByte(msg, to->lightpflags); +// } +// if (bits & E5_GLOW) +// { +// MSG_WriteByte(msg, to->glowsize); +// MSG_WriteByte(msg, to->glowcolor); +// } +// if (bits & E5_COLORMOD) +// { +// MSG_WriteByte(msg, to->colormod[0]); +// MSG_WriteByte(msg, to->colormod[1]); +// MSG_WriteByte(msg, to->colormod[2]); +// } +} + +void SVDP_EmitEntitiesUpdate (client_t *client, packet_entities_t *to, sizebuf_t *msg) +{ + edict_t *ent; + client_frame_t *fromframe; + packet_entities_t *from; + int oldindex, newindex; + int oldnum, newnum; + int oldmax; + + // this is the frame that we are going to delta update from + if (client->delta_sequence != -1) + { + fromframe = &client->frames[client->delta_sequence & UPDATE_MASK]; + from = &fromframe->entities; + oldmax = from->num_entities; + } + else + { + oldmax = 0; // no delta update + from = NULL; + } + client->delta_sequence++; + + MSG_WriteByte(msg, svcdp_entities); + MSG_WriteLong(msg, 0); + if (client->protocol == SCP_DARKPLACES7) + MSG_WriteLong(msg, 0); + + for (newindex = 0; newindex < to->num_entities; newindex++) + to->entities[newindex].bitmask = 0; + + newindex = 0; + oldindex = 0; +//Con_Printf ("---%i to %i ----\n", client->delta_sequence & UPDATE_MASK +// , client->netchan.outgoing_sequence & UPDATE_MASK); + while (newindex < to->num_entities || oldindex < oldmax) + { + newnum = newindex >= to->num_entities ? 0x7fff : to->entities[newindex].number; + oldnum = oldindex >= oldmax ? 0x7fff : from->entities[oldindex].number; + + if (newnum == oldnum) + { // delta update from old position +//Con_Printf ("delta %i\n", newnum); + SVDP_EmitEntity (&from->entities[oldindex], &to->entities[newindex], msg, false); + oldindex++; + newindex++; + continue; + } + + if (newnum < oldnum) + { // this is a new entity, send it from the baseline + ent = EDICT_NUM(svprogfuncs, newnum); +//Con_Printf ("baseline %i\n", newnum); + SVDP_EmitEntity (&ent->baseline, &to->entities[newindex], msg, true); + newindex++; + continue; + } + + if (newnum > oldnum) + { // the old entity isn't present in the new message +//Con_Printf ("remove %i\n", oldnum); + MSG_WriteShort(msg, oldnum | 0x8000); + oldindex++; + continue; + } + } + + MSG_WriteShort(msg, 0x8000); +} +#endif int SV_HullNumForPlayer(int h2hull, float *mins, float *maxs) @@ -1940,9 +2257,6 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore edict_t *clent; client_frame_t *frame; entity_state_t *state; -#ifdef NQPROT - int nqprot = !ISQWCLIENT(client); -#endif client_t *split; @@ -2077,7 +2391,7 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore if (client->viewent #ifdef NQPROT - && !nqprot + && ISQWCLIENT(client) #endif ) //this entity is watching from outside themselves. The client is tricked into thinking that they themselves are in the view ent, and a new dummy ent (the old them) must be spawned. { @@ -2132,7 +2446,7 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore } #ifdef NQPROT - for (e=(nqprot?1:sv.allocated_client_slots+1) ; eprotocol == SCP_NETQUAKE) { if (msg->cursize + 32 > msg->maxsize) break; @@ -2226,8 +2540,9 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore continue; } #endif - if (SV_AddNailUpdate (ent)) - continue; // added to the special update list + if (ISQWCLIENT(client)) + if (SV_AddNailUpdate (ent)) + continue; // added to the special update list #ifdef PEXT_LIGHTUPDATES if (client->fteprotocolextensions & PEXT_LIGHTUPDATES) if (SV_AddLightUpdate (ent)) @@ -2397,8 +2712,15 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore #endif } #ifdef NQPROT - if (nqprot) + if (client->protocol == SCP_NETQUAKE) return; + + if (client->protocol == SCP_DARKPLACES6 || client->protocol == SCP_DARKPLACES7) + { + SVDP_EmitEntitiesUpdate(client, pack, msg); + SV_EmitCSQCUpdate(client, msg); + return; + } #endif if (!sv.demostatevalid) diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index 1f7376387..392a42bb4 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -544,11 +544,15 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us } if (sv_bigcoords.value) + { sizeofcoord = 4; + sizeofangle = 2; + } else + { sizeofcoord = 2; - - sizeofangle = 1; + sizeofangle = 1; + } VoteFlushAll(); #ifndef SERVERONLY diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index f698ba138..f3d4069ac 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -242,6 +242,16 @@ void VARGS SV_Error (char *error, ...) _vsnprintf (string,sizeof(string)-1, error,argptr); va_end (argptr); + if (svprogfuncs) + { + int size = 1024*1024*8; + char *buffer = BZ_Malloc(size); + svprogfuncs->save_ents(svprogfuncs, buffer, &size, 3); + COM_WriteFile("ssqccore.txt", buffer, size); + BZ_Free(buffer); + } + + SV_EndRedirect(); Con_Printf ("SV_Error: %s\n",string); @@ -299,8 +309,9 @@ void SV_FinalMessage (char *message) for (i=0, cl = svs.clients ; istate >= cs_spawned) - Netchan_Transmit (&cl->netchan, sv.datagram.cursize - , sv.datagram.data, 10000); + if (ISNQCLIENT(cl) || ISQWCLIENT(cl)) + Netchan_Transmit (&cl->netchan, sv.datagram.cursize + , sv.datagram.data, 10000); } @@ -997,9 +1008,12 @@ void SVC_GetChallenge (void) } Netchan_OutOfBand(NS_SERVER, net_from, over-buf, buf); - -// buf = va("challenge FTE%i", svs.challenges[i].challenge); -// Netchan_OutOfBand(NS_SERVER, net_from, strlen(buf)+1, buf); + if (sv_listen.value >= 2) + { + //dp can respond to this (and fte won't get confused because the challenge will be wrong) + buf = va("challenge FTE%i", svs.challenges[i].challenge); + Netchan_OutOfBand(NS_SERVER, net_from, strlen(buf)+1, buf); + } } // Netchan_OutOfBandPrint (net_from, "%c%i", S2C_CHALLENGE, @@ -1209,6 +1223,8 @@ client_t *SVC_DirectConnect(void) if (*(Cmd_Argv(0)+7) == '\\') { + if (sv_listen.value < 2) + return NULL; Q_strncpyz (userinfo[0], net_message.data + 11, sizeof(userinfo[0])-1); if (strcmp(Info_ValueForKey(userinfo[0], "protocol"), "darkplaces 3")) @@ -1225,7 +1241,15 @@ client_t *SVC_DirectConnect(void) else protocol = SCP_DARKPLACES6; - challenge = atoi(Info_ValueForKey(userinfo[0], "challenge")); + s = Info_ValueForKey(userinfo[0], "challenge"); + if (!strncmp(s, "FTE", 3)) + challenge = atoi(s+3); + else + challenge = atoi(s); + + s = Info_ValueForKey(userinfo[0], "name"); + if (!*s) + Info_SetValueForKey(userinfo[0], "name", "CONNECTING", sizeof(userinfo[0])); qport = 0; } @@ -1434,7 +1458,9 @@ client_t *SVC_DirectConnect(void) SV_FixupName(name, name); if (!*name) + { name = "Hidden"; + } else if (!stricmp(name, "console")) name = "Not Console"; //have fun dudes. @@ -2022,12 +2048,12 @@ qboolean SV_ConnectionlessPacket (void) return false; } +#ifdef NQPROT void SVNQ_ConnectionlessPacket(void) { sizebuf_t sb; int header; int length; - client_t *client; char *str; char buffer[256]; if (net_from.type == NA_LOOPBACK) @@ -2077,6 +2103,7 @@ void SVNQ_ConnectionlessPacket(void) break; } } +#endif /* ============================================================================== @@ -2458,7 +2485,7 @@ void SV_CheckTimeouts (void) if (cl->state == cs_connected || cl->state == cs_spawned) { if (!cl->spectator) nclients++; - if (cl->netchan.last_received < droptime && cl->netchan.remote_address.type != NA_LOOPBACK) { + if (cl->netchan.last_received < droptime && cl->netchan.remote_address.type != NA_LOOPBACK && cl->protocol != SCP_BAD) { SV_BroadcastTPrintf (PRINT_HIGH, STL_CLIENTTIMEDOUT, cl->name); SV_DropClient (cl); cl->state = cs_free; // don't bother with zombie state @@ -3056,7 +3083,7 @@ void Master_Heartbeat (void) { char string[2048]; int active; - int i; + int i, j; qboolean madeqwstring = false; char data[2]; @@ -3112,9 +3139,9 @@ void Master_Heartbeat (void) { // count active users active = 0; - for (i=0 ; iv->origin[1]; end[2] = ent->v->origin[2] - 1; trace = SV_Move(ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent); - if (trace.fraction < 1 && trace.plane.normal[2] >= 0.7) + if (trace.fraction <= DIST_EPSILON && trace.plane.normal[2] >= 0.7) { ent->v->flags = (int)ent->v->flags | FL_ONGROUND; ent->v->groundentity = EDICT_TO_PROG(svprogfuncs, trace.ent); diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index 4b44170bb..e7fc8b709 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -223,17 +223,33 @@ EVENT MESSAGES static void SV_PrintToClient(client_t *cl, int level, char *string) { - ClientReliableWrite_Begin (cl, cl->protocol==SCP_QUAKE2?svcq2_print:svc_print, strlen(string)+3); -#ifdef NQPROT - if (!ISQWCLIENT(cl)) + switch (cl->protocol) { + case SCP_BAD: //bot + break; +#ifdef Q2SERVER + case SCP_QUAKE2: + ClientReliableWrite_Begin (cl, svcq2_print, strlen(string)+3); + ClientReliableWrite_Byte (cl, level); + ClientReliableWrite_String (cl, string); + break; +#endif +#ifdef NQPROT + case SCP_NETQUAKE: + case SCP_DARKPLACES6: + case SCP_DARKPLACES7: + ClientReliableWrite_Begin (cl, svc_print, strlen(string)+3); if (level == PRINT_CHAT) ClientReliableWrite_Byte (cl, 1); - } - else + ClientReliableWrite_String (cl, string); + break; #endif + case SCP_QUAKEWORLD: + ClientReliableWrite_Begin (cl, svc_print, strlen(string)+3); ClientReliableWrite_Byte (cl, level); - ClientReliableWrite_String (cl, string); + ClientReliableWrite_String (cl, string); + break; + } } @@ -329,6 +345,8 @@ void VARGS SV_BroadcastPrintf (int level, char *fmt, ...) continue; if (!cl->state) continue; + if (cl->protocol == SCP_BAD) + continue; if (cl->controller) continue; @@ -526,9 +544,14 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int continue; } -#ifdef NQPROT - if (!ISQWCLIENT(client)) + switch (client->protocol) { + case SCP_BAD: + break; +#ifdef NQPROT + case SCP_NETQUAKE: + case SCP_DARKPLACES6: + case SCP_DARKPLACES7: if (reliable) { ClientReliableCheckBlock(client, sv.nqmulticast.cursize); @@ -536,16 +559,18 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int } else SZ_Write (&client->datagram, sv.nqmulticast.data, sv.nqmulticast.cursize); - } - else + break; #endif - if (reliable) - { - ClientReliableCheckBlock(client, sv.multicast.cursize); - ClientReliableWrite_SZ(client, sv.multicast.data, sv.multicast.cursize); + case SCP_QUAKEWORLD: + if (reliable) + { + ClientReliableCheckBlock(client, sv.multicast.cursize); + ClientReliableWrite_SZ(client, sv.multicast.data, sv.multicast.cursize); + } + else + SZ_Write (&client->datagram, sv.multicast.data, sv.multicast.cursize); + break; } - else - SZ_Write (&client->datagram, sv.multicast.data, sv.multicast.cursize); } } else @@ -914,11 +939,11 @@ void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg) for (split = client; split; split=split->controlled, pnum++) SV_WriteEntityDataToMessage(split, msg, pnum); - +/* MSG_WriteByte (msg, svc_time); MSG_WriteFloat(msg, sv.physicstime); client->nextservertimeupdate = sv.physicstime; - +*/ // Z_EXT_TIME protocol extension // every now and then, send an update so that extrapolation // on client side doesn't stray too far off @@ -942,6 +967,7 @@ void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg) MSG_WriteByte (msg, svc_time); MSG_WriteFloat(msg, sv.physicstime); client->nextservertimeupdate = sv.physicstime; + Con_Printf("%f\n", sv.physicstime); bits = 0; @@ -960,6 +986,7 @@ void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg) #define SU_WEAPONFRAME (1<<12) #define SU_ARMOR (1<<13) #define SU_WEAPON (1<<14) +#define SU_EXTEND1 (1<<15) if (ent->v->view_ofs[2] != DEFAULT_VIEWHEIGHT) bits |= SU_VIEWHEIGHT; @@ -1002,6 +1029,9 @@ void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg) // if (ent->v->weapon) bits |= SU_WEAPON; + if (bits >= 65536) + bits |= SU_EXTEND1; + // send the data MSG_WriteByte (msg, svc_clientdata); @@ -1018,11 +1048,19 @@ void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg) // if (bits & (SU_PUNCH1<v->punchangle[i]); if (bits & (SU_VELOCITY1<v->velocity[i]/16); + { + if (client->protocol == SCP_DARKPLACES6 || client->protocol == SCP_DARKPLACES7) + MSG_WriteCoord(msg, ent->v->velocity[i]); + else + MSG_WriteChar (msg, ent->v->velocity[i]/16); + } } -// [always sent] if (bits & SU_ITEMS) - MSG_WriteLong (msg, items); + if (bits & SU_ITEMS) + MSG_WriteLong (msg, items); + + if (client->protocol == SCP_DARKPLACES6 || client->protocol == SCP_DARKPLACES7) + return; if (bits & SU_WEAPONFRAME) MSG_WriteByte (msg, ent->v->weaponframe); @@ -1184,6 +1222,8 @@ void SV_UpdateClientStats (client_t *client, int pnum) stats[STAT_VIEW2] = 0; #endif + stats[STAT_VIEWZOOM] = 255; + SV_UpdateQCStats(ent, stats); //dmw tweek for stats @@ -1526,6 +1566,9 @@ void SV_UpdateToReliableMessages (void) if (client->controller) continue; //splitscreen + if (client->protocol == SCP_BAD) + continue; //botclient + #ifdef Q2SERVER if (ISQ2CLIENT(client)) { @@ -1681,6 +1724,13 @@ void SV_SendClientMessages (void) } } + if (c->protocol == SCP_BAD) + { + SZ_Clear (&c->netchan.message); + SZ_Clear (&c->datagram); + continue; + } + // if the reliable message overflowed, // drop the client if (c->netchan.message.overflowed) diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 841eb6bb0..3d5936e31 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -3238,13 +3238,25 @@ void SVNQ_PreSpawn_f (void) } else { - MSG_WriteByte(&host_client->netchan.message, svc_spawnbaseline); + if (host_client->protocol != SCP_NETQUAKE && (state->modelindex > 255 || state->frame > 255)) + { + MSG_WriteByte(&host_client->netchan.message, svcdp_spawnbaseline2); - MSG_WriteShort (&host_client->netchan.message, e); + MSG_WriteShort (&host_client->netchan.message, e); - MSG_WriteByte (&host_client->netchan.message, state->modelindex&255); + MSG_WriteShort (&host_client->netchan.message, state->modelindex); + MSG_WriteShort (&host_client->netchan.message, state->frame); + } + else + { + MSG_WriteByte(&host_client->netchan.message, svc_spawnbaseline); + + MSG_WriteShort (&host_client->netchan.message, e); + + MSG_WriteByte (&host_client->netchan.message, state->modelindex&255); + MSG_WriteByte (&host_client->netchan.message, state->frame&255); + } - MSG_WriteByte (&host_client->netchan.message, state->frame); MSG_WriteByte (&host_client->netchan.message, (int)state->colormap); MSG_WriteByte (&host_client->netchan.message, (int)state->skinnum); for (i=0 ; i<3 ; i++) @@ -4597,14 +4609,38 @@ void SVNQ_ReadClientMove (usercmd_t *move) move->msec=100; // read buttons - bits = MSG_ReadByte (); + if (host_client->protocol == SCP_DARKPLACES6 || host_client->protocol == SCP_DARKPLACES7) + bits = MSG_ReadLong(); + else + bits = MSG_ReadByte (); move->buttons = bits; i = MSG_ReadByte (); if (i) move->impulse = i; - + if (host_client->protocol == SCP_DARKPLACES6 || host_client->protocol == SCP_DARKPLACES7) + { + /*move->cursor_screen[0] = */MSG_ReadShort() * (1.0f / 32767.0f); + /*move->cursor_screen[1] = */MSG_ReadShort() * (1.0f / 32767.0f); + /*move->cursor_start[0] = */MSG_ReadFloat(); + /*move->cursor_start[1] = */MSG_ReadFloat(); + /*move->cursor_start[2] = */MSG_ReadFloat(); + /*move->cursor_impact[0] = */MSG_ReadFloat(); + /*move->cursor_impact[1] = */MSG_ReadFloat(); + /*move->cursor_impact[2] = */MSG_ReadFloat(); + /*move->cursor_entitynumber = */(unsigned short)MSG_ReadShort(); +/* if (move->cursor_entitynumber >= prog->max_edicts) + { + Con_DPrintf("SV_ReadClientMessage: client send bad cursor_entitynumber\n"); + move->cursor_entitynumber = 0; + } + // as requested by FrikaC, cursor_trace_ent is reset to world if the + // entity is free at time of receipt + if (PRVM_EDICT_NUM(move->cursor_entitynumber)->priv.server->free) + move->cursor_entitynumber = 0; + if (msg_badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__); +*/ } if (i && SV_FiltureImpulse(i, host_client->trustlevel)) @@ -4656,7 +4692,6 @@ void SVNQ_ExecuteClientMessage (client_t *cl) // mark time so clients will know how much to predict // other players cl->localtime = sv.time; - cl->delta_sequence = -1; // no delta unless requested while (1) { if (msg_badread) diff --git a/engine/sw/sw_screen.c b/engine/sw/sw_screen.c index c56c6f253..f320f704d 100644 --- a/engine/sw/sw_screen.c +++ b/engine/sw/sw_screen.c @@ -67,6 +67,7 @@ void SWSCR_UpdateScreen (void) #ifdef _WIN32 { // don't suck up any cpu if minimized + extern qboolean Minimized; if (Minimized) return; }