From f5757777289039a08e441ff9bfe890a0c014d32e Mon Sep 17 00:00:00 2001 From: Spoike Date: Wed, 10 Nov 2010 03:32:47 +0000 Subject: [PATCH] d3d renderer works a little better in q3. git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3639 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_parse.c | 2 - engine/client/clq2_cin.c | 1 - engine/client/m_mp3.c | 2 +- engine/client/merged.h | 2 - engine/client/r_surf.c | 9 +- engine/client/render.h | 1 + engine/client/renderer.c | 9 +- engine/client/sbar.c | 49 +-- engine/client/skin.c | 26 +- engine/common/bothdefs.h | 5 - engine/common/fs.c | 13 +- engine/d3d/d3d_backend.c | 645 +++++++++++++++++++++++++++++++++----- engine/d3d/vid_d3d.c | 291 +++++++++-------- engine/gl/gl_alias.c | 4 +- engine/gl/gl_backend.c | 4 + engine/gl/gl_font.c | 2 + engine/gl/gl_model.c | 2 - engine/gl/gl_rlight.c | 2 +- engine/gl/gl_rmain.c | 4 +- engine/gl/gl_shader.c | 96 ++++-- engine/gl/shader.h | 3 + engine/qclib/qcd_main.c | 4 + engine/server/svq3_game.c | 2 +- 23 files changed, 864 insertions(+), 314 deletions(-) diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 91cc7c368..41e857a48 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -1650,8 +1650,6 @@ void CL_ParseDownload (void) } CL_DownloadFailed(cls.downloadremotename); - - CL_RequestNextDownload (); return; } diff --git a/engine/client/clq2_cin.c b/engine/client/clq2_cin.c index 2bcad4adc..e85c03be2 100644 --- a/engine/client/clq2_cin.c +++ b/engine/client/clq2_cin.c @@ -489,7 +489,6 @@ cinematics_t *CIN_PlayCinematic (char *arg) } else { - cin->cinematictime = 0; // done Con_Printf(CON_WARNING "Cinematic %s not found.\n", name); } return cin; diff --git a/engine/client/m_mp3.c b/engine/client/m_mp3.c index 992a1eb38..b39de0e4d 100644 --- a/engine/client/m_mp3.c +++ b/engine/client/m_mp3.c @@ -1064,7 +1064,7 @@ qboolean Media_Roq_DecodeFrame (cin_t *cin, qboolean nosound) { float curtime = Sys_DoubleTime(); - if ((int)(cin->filmlasttime*30) == (int)((float)realtime*30)) + if ((int)(cin->filmlasttime*30) == (int)((float)realtime*30) && cin->outtype != TF_INVALID) { cin->outunchanged = !!cin->outtype; return true; diff --git a/engine/client/merged.h b/engine/client/merged.h index d82bcb3f1..2f8b1fd6c 100644 --- a/engine/client/merged.h +++ b/engine/client/merged.h @@ -82,7 +82,6 @@ extern void (*R_NewMap) (void); extern void (*R_PreNewMap) (void); extern int (*R_LightPoint) (vec3_t point); -extern void (*R_PushDlights) (void); extern void (*R_AddStain) (vec3_t org, float red, float green, float blue, float radius); extern void (*R_LessenStains) (void); @@ -200,7 +199,6 @@ typedef struct rendererinfo_s { void (*R_PreNewMap) (void); int (*R_LightPoint) (vec3_t point); - void (*R_PushDlights) (void); void (*R_AddStain) (vec3_t org, float red, float green, float blue, float radius); void (*R_LessenStains) (void); diff --git a/engine/client/r_surf.c b/engine/client/r_surf.c index f0559ddee..77e42d12d 100644 --- a/engine/client/r_surf.c +++ b/engine/client/r_surf.c @@ -1952,7 +1952,7 @@ void Surf_GenBrushBatches(batch_t **batches, entity_t *ent) currententity = ent; currentmodel = ent->model; - if (model->nummodelsurfaces != 0 && r_dynamic.value) + if (model->nummodelsurfaces != 0 && r_dynamic.ival) { for (k=rtlights_first; kR_NewMap; R_PreNewMap = ri->R_PreNewMap; R_LightPoint = ri->R_LightPoint; - R_PushDlights = ri->R_PushDlights; R_AddStain = ri->R_AddStain; R_LessenStains = ri->R_LessenStains; diff --git a/engine/client/sbar.c b/engine/client/sbar.c index 8e4b52fc1..629daa45c 100644 --- a/engine/client/sbar.c +++ b/engine/client/sbar.c @@ -1774,6 +1774,14 @@ void Sbar_DrawScoreboard (void) if (cls.protocol == CP_QUAKE2) return; +#ifndef CLIENTONLY + /*no scoreboard in single player (if you want bots, set deathmatch)*/ + if (sv.state && cls.gamemode == GAME_COOP && sv.allocated_client_slots == 1) + { + return; + } +#endif + for (pnum = 0; pnum < cl.splitclients; pnum++) { if (cl.stats[pnum][STAT_HEALTH] <= 0) @@ -1782,19 +1790,6 @@ void Sbar_DrawScoreboard (void) if (deadcount == cl.splitclients && !cl.spectator) { -#ifndef CLIENTONLY - if (sv.state && cls.gamemode == GAME_COOP) - { - for (pnum = 0; pnum < sv.allocated_client_slots; pnum++) - { - if (svs.clients[pnum].state) - if (svs.clients[pnum].netchan.remote_address.type != NA_LOOPBACK) - break; - } - if (pnum == sv.allocated_client_slots) - return; - } -#endif if (cl.teamplay > 0 && !sb_showscores) Sbar_TeamOverlay(); else @@ -1845,7 +1840,6 @@ void Sbar_Hexen2DrawInventory(int pnum) if (sb_hexen2_item_time[pnum]+3 < realtime) return; -#if 1 for (i = sb_hexen2_cur_item[pnum]; i < 15; i++) if (sb_hexen2_cur_item[pnum] == i || cl.stats[pnum][STAT_H2_CNT_TORCH+i] > 0) activeright++; @@ -1877,23 +1871,6 @@ void Sbar_Hexen2DrawInventory(int pnum) Sbar_Hexen2DrawItem(pnum, x, y, i); x+=33; } -#elif 1 - for (i = 0, x=320/2-114; i < 7; i++, x+=33) - { - if ((sb_hexen2_cur_item[pnum]-3+i+30)%15 == sb_hexen2_cur_item[pnum]) - Sbar_DrawPic(x+9, y-12, 11, 11, Draw_SafeCachePic("gfx/artisel.lmp")); - Sbar_Hexen2DrawItem(pnum, x, y, (sb_hexen2_cur_item[pnum]-3+i+30)%15); - } -#else - for (i = 0, x=320/2; i < 3; i++, x+=33) - { - Sbar_Hexen2DrawItem(pnum, x, y, (sb_hexen2_cur_item[pnum]+1+i)%15); - } - for (i = 0, x=320/2-33; i < 3; i++, x-=33) - { - Sbar_Hexen2DrawItem(pnum, x, y, (sb_hexen2_cur_item[pnum]-1-i+45)%15); - } -#endif } void Sbar_Hexen2DrawExtra (int pnum) @@ -2314,12 +2291,6 @@ void Sbar_Draw (void) Sbar_DrawString (0, -8, va("Health: %i", cl.stats[pnum][STAT_HEALTH])); Sbar_DrawString (0, -16, va(" Armor: %i", cl.stats[pnum][STAT_ARMOR])); - - if (cl.stats[pnum][STAT_H2_BLUEMANA]) - Sbar_DrawString (0, -24, va(" Blue: %i", cl.stats[pnum][STAT_H2_BLUEMANA])); - if (cl.stats[pnum][STAT_H2_GREENMANA]) - Sbar_DrawString (0, -32, va(" Green: %i", cl.stats[pnum][STAT_H2_GREENMANA])); - continue; } @@ -2347,7 +2318,7 @@ void Sbar_Draw (void) } else { - if (sb_showscores || cl.stats[pnum][STAT_HEALTH] <= 0) + if (sb_showscores || sb_showteamscores || cl.stats[pnum][STAT_HEALTH] <= 0) Sbar_SoloScoreboard (); else if (cls.gamemode != GAME_DEATHMATCH) Sbar_CoopScoreboard (); @@ -2362,7 +2333,7 @@ void Sbar_Draw (void) } } } - else if (sb_showscores || (cl.stats[pnum][STAT_HEALTH] <= 0 && cl.splitclients == 1)) + else if (sb_showscores || sb_showteamscores || (cl.stats[pnum][STAT_HEALTH] <= 0 && cl.splitclients == 1)) { if (!pnum) { diff --git a/engine/client/skin.c b/engine/client/skin.c index d5dd0701e..4604ea3af 100644 --- a/engine/client/skin.c +++ b/engine/client/skin.c @@ -538,7 +538,31 @@ void Skin_NextDownload (void) if (!*sc->skin->name) continue; - CL_CheckOrEnqueDownloadFile(va("skins/%s.pcx", sc->skin->name), NULL, 0); + if (cls.protocol == CP_QUAKE2) + { + int j; + char *slash; + slash = strchr(sc->skin->name, '/'); + if (slash) + { + *slash = 0; + CL_CheckOrEnqueDownloadFile(va("players/%s/tris.md2", sc->skin->name), NULL, 0); + for (j = 0; j < MAX_MODELS; j++) + { + if (cl.model_name[j][0] == '#') + CL_CheckOrEnqueDownloadFile(va("players/%s/%s", sc->skin->name, cl.model_name[j]+1), NULL, 0); + } + for (j = 0; j < MAX_SOUNDS; j++) + { + if (cl.sound_name[j][0] == '*') + CL_CheckOrEnqueDownloadFile(va("players/%s/%s", sc->skin->name, cl.sound_name[j]+1), NULL, 0); + } + *slash = '/'; + CL_CheckOrEnqueDownloadFile(va("players/%s.pcx", sc->skin->name), NULL, 0); + } + } + else + CL_CheckOrEnqueDownloadFile(va("skins/%s.pcx", sc->skin->name), NULL, 0); } // now load them in for real diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index 7b1434dab..8eaf89578 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -77,11 +77,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define AVAIL_FREETYPE #endif -#ifdef _WIN64 - #undef AVAIL_PNGLIB - #undef AVAIL_ZLIB -#endif - #define ODE_DYNAMIC #ifdef NO_PNG diff --git a/engine/common/fs.c b/engine/common/fs.c index fb631ded7..117a5c6e7 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -14,7 +14,11 @@ #endif #ifdef _MSC_VER -#pragma comment(lib, MSVCLIBSPATH "zlib.lib") +# ifdef _WIN64 +# pragma comment (lib, "../libs/zlib64.lib") +# else +# pragma comment (lib, "../libs/zlib.lib") +# endif #endif hashtable_t filesystemhash; @@ -613,6 +617,7 @@ char *FS_GetPackHashes(char *buffer, int buffersize, qboolean referencedonly) } char *FS_GetPackNames(char *buffer, int buffersize, qboolean referencedonly) { + char temp[MAX_OSPATH]; searchpath_t *search; buffersize--; *buffer = 0; @@ -621,7 +626,8 @@ char *FS_GetPackNames(char *buffer, int buffersize, qboolean referencedonly) { for (search = com_purepaths ; search ; search = search->nextpure) { - Q_strncatz(buffer, va("%s ", search->purepath), buffersize); + COM_StripExtension(search->purepath, temp, sizeof(temp)); + Q_strncatz(buffer, va("%s ", temp), buffersize); } return buffer; } @@ -633,7 +639,8 @@ char *FS_GetPackNames(char *buffer, int buffersize, qboolean referencedonly) search->crc_check = search->funcs->GeneratePureCRC(search->handle, 0, 0); if (search->crc_check) { - Q_strncatz(buffer, va("%s ", search->purepath), buffersize); + COM_StripExtension(search->purepath, temp, sizeof(temp)); + Q_strncatz(buffer, va("%s ", temp), buffersize); } } return buffer; diff --git a/engine/d3d/d3d_backend.c b/engine/d3d/d3d_backend.c index b26bf3b7a..1a65a0b10 100644 --- a/engine/d3d/d3d_backend.c +++ b/engine/d3d/d3d_backend.c @@ -75,6 +75,37 @@ static void FTable_Init(void) r_inversesawtoothtable[i] = 1.0 - t; } } + +typedef vec3_t mat3_t[3]; +static mat3_t axisDefault={{1, 0, 0}, + {0, 1, 0}, + {0, 0, 1}}; + +static void Matrix3_Transpose (mat3_t in, mat3_t out) +{ + out[0][0] = in[0][0]; + out[1][1] = in[1][1]; + out[2][2] = in[2][2]; + + out[0][1] = in[1][0]; + out[0][2] = in[2][0]; + out[1][0] = in[0][1]; + out[1][2] = in[2][1]; + out[2][0] = in[0][2]; + out[2][1] = in[1][2]; +} +static void Matrix3_Multiply_Vec3 (mat3_t a, vec3_t b, vec3_t product) +{ + product[0] = a[0][0]*b[0] + a[0][1]*b[1] + a[0][2]*b[2]; + product[1] = a[1][0]*b[0] + a[1][1]*b[1] + a[1][2]*b[2]; + product[2] = a[2][0]*b[0] + a[2][1]*b[1] + a[2][2]*b[2]; +} + +static int Matrix3_Compare(mat3_t in, mat3_t out) +{ + return !memcmp(in, out, sizeof(mat3_t)); +} + /*================================================*/ typedef struct @@ -90,8 +121,11 @@ typedef struct texid_t curdeluxmap; int curvertdecl; unsigned int shaderbits; + unsigned int curcull; unsigned int lastpasscount; + texid_t curtex[MAX_TMUS]; + mesh_t **meshlist; unsigned int nummeshes; @@ -130,12 +164,12 @@ extern int be_maxpasses; enum { D3D_VDEC_COL4B = 1<<0, - D3D_VDEC_NORMS = 1<<1, - D3D_VDEC_ST0 = 1<<2, - D3D_VDEC_ST1 = 1<<3, + //D3D_VDEC_NORMS = 1<<1, + D3D_VDEC_ST0 = 1<<1, + D3D_VDEC_ST1 = 1<<2, D3D_VDEC_ST2 = 1<<3, - D3D_VDEC_ST3 = 1<<3, - D3D_VDEC_MAX = 16 + D3D_VDEC_ST3 = 1<<4, + D3D_VDEC_MAX = 1<<5 }; IDirect3DVertexDeclaration9 *vertexdecls[D3D_VDEC_MAX]; @@ -201,7 +235,7 @@ void BE_D3D_Reset(qboolean before) elements++; } - if (i & D3D_VDEC_NORMS) +/* if (i & D3D_VDEC_NORMS) { decl[elements].Stream = 2; decl[elements].Offset = 0; @@ -227,7 +261,7 @@ void BE_D3D_Reset(qboolean before) decl[elements].UsageIndex = 1; elements++; } - +*/ for (tmu = 0; tmu < MAX_TMUS; tmu++) { if (i & (D3D_VDEC_ST0<texgen) { default: case T_GEN_DIFFUSE: - IDirect3DDevice9_SetTexture (pD3DDev9, tu, shaderstate.curtexnums->base.ptr); + BindTexture(tu, shaderstate.curtexnums->base.ptr); break; case T_GEN_NORMALMAP: - IDirect3DDevice9_SetTexture (pD3DDev9, tu, shaderstate.curtexnums->bump.ptr); + BindTexture( tu, shaderstate.curtexnums->bump.ptr); break; case T_GEN_SPECULAR: - IDirect3DDevice9_SetTexture (pD3DDev9, tu, shaderstate.curtexnums->specular.ptr); + BindTexture(tu, shaderstate.curtexnums->specular.ptr); break; case T_GEN_UPPEROVERLAY: - IDirect3DDevice9_SetTexture (pD3DDev9, tu, shaderstate.curtexnums->upperoverlay.ptr); + BindTexture(tu, shaderstate.curtexnums->upperoverlay.ptr); break; case T_GEN_LOWEROVERLAY: - IDirect3DDevice9_SetTexture (pD3DDev9, tu, shaderstate.curtexnums->loweroverlay.ptr); + BindTexture(tu, shaderstate.curtexnums->loweroverlay.ptr); break; case T_GEN_FULLBRIGHT: - IDirect3DDevice9_SetTexture (pD3DDev9, tu, shaderstate.curtexnums->fullbright.ptr); + BindTexture(tu, shaderstate.curtexnums->fullbright.ptr); break; case T_GEN_ANIMMAP: - IDirect3DDevice9_SetTexture (pD3DDev9, tu, pass->anim_frames[(int)(pass->anim_fps * shaderstate.curtime) % pass->anim_numframes].ptr); + BindTexture(tu, pass->anim_frames[(int)(pass->anim_fps * shaderstate.curtime) % pass->anim_numframes].ptr); break; /*fixme*/ case T_GEN_SINGLEMAP: - IDirect3DDevice9_SetTexture (pD3DDev9, tu, pass->anim_frames[0].ptr); + BindTexture(tu, pass->anim_frames[0].ptr); break; case T_GEN_DELUXMAP: - IDirect3DDevice9_SetTexture (pD3DDev9, tu, shaderstate.curdeluxmap.ptr); + BindTexture(tu, shaderstate.curdeluxmap.ptr); break; case T_GEN_LIGHTMAP: - IDirect3DDevice9_SetTexture (pD3DDev9, tu, shaderstate.curlightmap.ptr); + BindTexture(tu, shaderstate.curlightmap.ptr); break; /*case T_GEN_CURRENTRENDER: FIXME: no code to grab the current screen and convert to a texture break;*/ case T_GEN_VIDEOMAP: - IDirect3DDevice9_SetTexture (pD3DDev9, tu, Media_UpdateForShader(pass->cin).ptr); + BindTexture(tu, Media_UpdateForShader(pass->cin).ptr); break; } @@ -486,43 +530,66 @@ static void SelectPassTexture(unsigned int tu, shaderpass_t *pass) IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG1, D3DTA_TEXTURE); IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG2, D3DTA_CURRENT); IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3); + + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); break; case GL_REPLACE: IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG1, D3DTA_TEXTURE); IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); +// IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); break; case GL_ADD: + if (!tu) + goto forcemod; IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG1, D3DTA_TEXTURE); IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG2, D3DTA_CURRENT); - if (tu) - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLOROP, D3DTOP_ADD); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLOROP, D3DTOP_ADD); + + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAOP, D3DTOP_ADD); break; case GL_DECAL: + if (!tu) + goto forcemod; IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG1, D3DTA_TEXTURE); IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG2, D3DTA_CURRENT); - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLOROP, D3DTOP_MODULATE); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLOROP, D3DTOP_BLENDTEXTUREALPHA); + + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG2, D3DTA_CURRENT); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); break; default: case GL_MODULATE: + forcemod: IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG1, D3DTA_TEXTURE); IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG2, D3DTA_CURRENT); IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLOROP, D3DTOP_MODULATE); + + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG2, D3DTA_CURRENT); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAOP, D3DTOP_MODULATE); break; } - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAOP, D3DTOP_MODULATE); if (tu == 0) { if (shaderstate.passsinglecolour) { IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG2, D3DTA_CONSTANT); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG2, D3DTA_CONSTANT); IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_CONSTANT, shaderstate.passcolour); } else { IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); } } } @@ -548,15 +615,27 @@ static void colourgenbyte(const shaderpass_t *pass, int cnt, const byte_vec4_t * break; case RGB_GEN_VERTEX: case RGB_GEN_EXACT_VERTEX: - while((cnt)--) + if (!src) { - qbyte r, g, b; - r=src[cnt][0]; - g=src[cnt][1]; - b=src[cnt][2]; - dst[cnt][0] = b; - dst[cnt][1] = g; - dst[cnt][2] = r; + while((cnt)--) + { + dst[cnt][0] = 255;//shaderstate.identitylighting; + dst[cnt][1] = 255;//shaderstate.identitylighting; + dst[cnt][2] = 255;//shaderstate.identitylighting; + } + } + else + { + while((cnt)--) + { + qbyte r, g, b; + r=src[cnt][0]; + g=src[cnt][1]; + b=src[cnt][2]; + dst[cnt][0] = b; + dst[cnt][1] = g; + dst[cnt][2] = r; + } } break; case RGB_GEN_ONE_MINUS_VERTEX: @@ -707,16 +786,14 @@ static void alphagenbyte(const shaderpass_t *pass, int cnt, const byte_vec4_t *s } break; - /*FIXME: specular not supported (most noticable on q3dm0)*/ - /*case ALPHA_GEN_SPECULAR: + case ALPHA_GEN_SPECULAR: { - mat3_t axis; - AngleVectors(shaderstate.curentity->angles, axis[0], axis[1], axis[2]); + int i; VectorSubtract(r_origin, shaderstate.curentity->origin, v1); - if (!Matrix3_Compare(axis, axisDefault)) + if (!Matrix3_Compare(shaderstate.curentity->axis, axisDefault)) { - Matrix3_Multiply_Vec3(axis, v2, v2); + Matrix3_Multiply_Vec3(shaderstate.curentity->axis, v2, v2); } else { @@ -728,10 +805,10 @@ static void alphagenbyte(const shaderpass_t *pass, int cnt, const byte_vec4_t *s VectorSubtract(v2, mesh->xyz_array[i], v1); f = DotProduct(v1, mesh->normals_array[i] ) * Q_rsqrt(DotProduct(v1,v1)); f = f * f * f * f * f; - dst[i][3] = bound (0.0f, f, 1.0f); + dst[i][3] = bound (0.0f, (int)(f*255), 255); } } - break;*/ + break; } } @@ -825,14 +902,12 @@ static unsigned int BE_GenerateColourMods(unsigned int vertcount, const shaderpa static void tcgen_environment(float *st, unsigned int numverts, float *xyz, float *normal) { - /* int i; vec3_t viewer, reflected; float d; vec3_t rorg; - RotateLightVector(shaderstate.curentity->axis, shaderstate.curentity->origin, r_origin, rorg); for (i = 0 ; i < numverts ; i++, xyz += 3, normal += 3, st += 2 ) @@ -849,7 +924,6 @@ static void tcgen_environment(float *st, unsigned int numverts, float *xyz, floa st[0] = 0.5 + reflected[1] * 0.5; st[1] = 0.5 - reflected[2] * 0.5; } - */ } static float *tcgen(const shaderpass_t *pass, int cnt, float *dst, const mesh_t *mesh) @@ -873,8 +947,8 @@ static float *tcgen(const shaderpass_t *pass, int cnt, float *dst, const mesh_t tcgen_environment(dst, cnt, (float*)mesh->xyz_array, (float*)mesh->normals_array); return dst; -// case TC_GEN_DOTPRODUCT: -// return mesh->st_array[0]; + case TC_GEN_DOTPRODUCT: + return dst;//mesh->st_array[0]; case TC_GEN_VECTOR: src = mesh->xyz_array; for (i = 0; i < cnt; i++, dst += 2) @@ -1004,6 +1078,246 @@ static void GenerateTCMods(const shaderpass_t *pass, float *dest) //end texture coords /*******************************************************************************************************************/ +static void deformgen(const deformv_t *deformv, int cnt, const vecV_t *src, vecV_t *dst, const mesh_t *mesh) +{ + float *table; + int j, k; + float args[4]; + float deflect; + switch (deformv->type) + { + default: + case DEFORMV_NONE: + if (src != (const avec4_t*)dst) + memcpy(dst, src, sizeof(*src)*cnt); + break; + + case DEFORMV_WAVE: + if (!mesh->normals_array) + { + if (src != (const avec4_t*)dst) + memcpy(dst, src, sizeof(*src)*cnt); + return; + } + args[0] = deformv->func.args[0]; + args[1] = deformv->func.args[1]; + args[3] = deformv->func.args[2] + deformv->func.args[3] * shaderstate.curtime; + table = FTableForFunc(deformv->func.type); + + for ( j = 0; j < cnt; j++ ) + { + deflect = deformv->args[0] * (src[j][0]+src[j][1]+src[j][2]) + args[3]; + deflect = FTABLE_EVALUATE(table, deflect) * args[1] + args[0]; + + // Deflect vertex along its normal by wave amount + VectorMA(src[j], deflect, mesh->normals_array[j], dst[j]); + } + break; + + case DEFORMV_NORMAL: + //normal does not actually move the verts, but it does change the normals array + //we don't currently support that. + if (src != (const avec4_t*)dst) + memcpy(dst, src, sizeof(*src)*cnt); +/* + args[0] = deformv->args[1] * shaderstate.curtime; + + for ( j = 0; j < cnt; j++ ) + { + args[1] = normalsArray[j][2] * args[0]; + + deflect = deformv->args[0] * R_FastSin(args[1]); + normalsArray[j][0] *= deflect; + deflect = deformv->args[0] * R_FastSin(args[1] + 0.25); + normalsArray[j][1] *= deflect; + VectorNormalizeFast(normalsArray[j]); + } +*/ break; + + case DEFORMV_MOVE: + table = FTableForFunc(deformv->func.type); + deflect = deformv->func.args[2] + shaderstate.curtime * deformv->func.args[3]; + deflect = FTABLE_EVALUATE(table, deflect) * deformv->func.args[1] + deformv->func.args[0]; + + for ( j = 0; j < cnt; j++ ) + VectorMA(src[j], deflect, deformv->args, dst[j]); + break; + + case DEFORMV_BULGE: + args[0] = deformv->args[0]/(2*M_PI); + args[1] = deformv->args[1]; + args[2] = shaderstate.curtime * deformv->args[2]/(2*M_PI); + + for (j = 0; j < cnt; j++) + { + deflect = R_FastSin(mesh->st_array[j][0]*args[0] + args[2])*args[1]; + dst[j][0] = src[j][0]+deflect*mesh->normals_array[j][0]; + dst[j][1] = src[j][1]+deflect*mesh->normals_array[j][1]; + dst[j][2] = src[j][2]+deflect*mesh->normals_array[j][2]; + } + break; + + case DEFORMV_AUTOSPRITE: + if (mesh->numindexes < 6) + break; + + for (j = 0; j < cnt-3; j+=4, src+=4, dst+=4) + { + vec3_t mid, d; + float radius; + mid[0] = 0.25*(src[0][0] + src[1][0] + src[2][0] + src[3][0]); + mid[1] = 0.25*(src[0][1] + src[1][1] + src[2][1] + src[3][1]); + mid[2] = 0.25*(src[0][2] + src[1][2] + src[2][2] + src[3][2]); + VectorSubtract(src[0], mid, d); + radius = 2*VectorLength(d); + + for (k = 0; k < 4; k++) + { + dst[k][0] = mid[0] + radius*((mesh->st_array[k][0]-0.5)*r_refdef.m_view[0+0]-(mesh->st_array[k][1]-0.5)*r_refdef.m_view[0+1]); + dst[k][1] = mid[1] + radius*((mesh->st_array[k][0]-0.5)*r_refdef.m_view[4+0]-(mesh->st_array[k][1]-0.5)*r_refdef.m_view[4+1]); + dst[k][2] = mid[2] + radius*((mesh->st_array[k][0]-0.5)*r_refdef.m_view[8+0]-(mesh->st_array[k][1]-0.5)*r_refdef.m_view[8+1]); + } + } + break; + + case DEFORMV_AUTOSPRITE2: + if (mesh->numindexes < 6) + break; + + for (k = 0; k < mesh->numindexes; k += 6) + { + int long_axis, short_axis; + vec3_t axis; + float len[3]; + mat3_t m0, m1, m2, result; + float *quad[4]; + vec3_t rot_centre, tv; + + quad[0] = (float *)(dst + mesh->indexes[k+0]); + quad[1] = (float *)(dst + mesh->indexes[k+1]); + quad[2] = (float *)(dst + mesh->indexes[k+2]); + + for (j = 2; j >= 0; j--) + { + quad[3] = (float *)(dst + mesh->indexes[k+3+j]); + if (!VectorEquals (quad[3], quad[0]) && + !VectorEquals (quad[3], quad[1]) && + !VectorEquals (quad[3], quad[2])) + { + break; + } + } + + // build a matrix were the longest axis of the billboard is the Y-Axis + VectorSubtract(quad[1], quad[0], m0[0]); + VectorSubtract(quad[2], quad[0], m0[1]); + VectorSubtract(quad[2], quad[1], m0[2]); + len[0] = DotProduct(m0[0], m0[0]); + len[1] = DotProduct(m0[1], m0[1]); + len[2] = DotProduct(m0[2], m0[2]); + + if ((len[2] > len[1]) && (len[2] > len[0])) + { + if (len[1] > len[0]) + { + long_axis = 1; + short_axis = 0; + } + else + { + long_axis = 0; + short_axis = 1; + } + } + else if ((len[1] > len[2]) && (len[1] > len[0])) + { + if (len[2] > len[0]) + { + long_axis = 2; + short_axis = 0; + } + else + { + long_axis = 0; + short_axis = 2; + } + } + else //if ( (len[0] > len[1]) && (len[0] > len[2]) ) + { + if (len[2] > len[1]) + { + long_axis = 2; + short_axis = 1; + } + else + { + long_axis = 1; + short_axis = 2; + } + } + + if (DotProduct(m0[long_axis], m0[short_axis])) + { + VectorNormalize2(m0[long_axis], axis); + VectorCopy(axis, m0[1]); + + if (axis[0] || axis[1]) + { + VectorVectors(m0[1], m0[2], m0[0]); + } + else + { + VectorVectors(m0[1], m0[0], m0[2]); + } + } + else + { + VectorNormalize2(m0[long_axis], axis); + VectorNormalize2(m0[short_axis], m0[0]); + VectorCopy(axis, m0[1]); + CrossProduct(m0[0], m0[1], m0[2]); + } + + for (j = 0; j < 3; j++) + rot_centre[j] = (quad[0][j] + quad[1][j] + quad[2][j] + quad[3][j]) * 0.25; + + if (shaderstate.curentity) + { + VectorAdd(shaderstate.curentity->origin, rot_centre, tv); + } + else + { + VectorCopy(rot_centre, tv); + } + VectorSubtract(r_origin, tv, tv); + + // filter any longest-axis-parts off the camera-direction + deflect = -DotProduct(tv, axis); + + VectorMA(tv, deflect, axis, m1[2]); + VectorNormalizeFast(m1[2]); + VectorCopy(axis, m1[1]); + CrossProduct(m1[1], m1[2], m1[0]); + + Matrix3_Transpose(m1, m2); + Matrix3_Multiply(m2, m0, result); + + for (j = 0; j < 4; j++) + { + VectorSubtract(quad[j], rot_centre, tv); + Matrix3_Multiply_Vec3(result, tv, quad[j]); + VectorAdd(rot_centre, quad[j], quad[j]); + } + } + break; + +// case DEFORMV_PROJECTION_SHADOW: +// break; + } +} + + + /*does not do the draw call, does not consider indicies (except for billboard generation) */ static qboolean BE_DrawMeshChain_SetupPass(shaderpass_t *pass, unsigned int vertcount) { @@ -1025,7 +1339,7 @@ static qboolean BE_DrawMeshChain_SetupPass(shaderpass_t *pass, unsigned int vert break; } if (i == lastpass) - return lastpass; + return false; /*all meshes in a chain must have the same features*/ @@ -1054,13 +1368,13 @@ static qboolean BE_DrawMeshChain_SetupPass(shaderpass_t *pass, unsigned int vert d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, 5+tmu, shaderstate.dynst_buff[tmu], shaderstate.dynst_offs[tmu] - vertcount*sizeof(vec2_t), sizeof(vec2_t))); tmu++; } - if (!tmu) - return false; /*deactivate any extras*/ - for (; tmu < shaderstate.lastpasscount; tmu++) + for (; tmu < shaderstate.lastpasscount; ) { d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, 5+tmu, NULL, 0, 0)); + BindTexture(tmu, NULL); d3dcheck(IDirect3DDevice9_SetTextureStageState(pD3DDev9, tmu, D3DTSS_COLOROP, D3DTOP_DISABLE)); + tmu++; } shaderstate.lastpasscount = tmu; @@ -1089,6 +1403,17 @@ static void BE_DrawMeshChain_Internal(void) unsigned int passno = 0; shaderpass_t *pass = shaderstate.curshader->passes; + if (shaderstate.curcull != (shaderstate.curshader->flags & (SHADER_CULL_FRONT | SHADER_CULL_BACK))) + { + shaderstate.curcull = shaderstate.curshader->flags & (SHADER_CULL_FRONT | SHADER_CULL_BACK); + if (shaderstate.curcull & SHADER_CULL_FRONT) + IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_CULLMODE, D3DCULL_CCW); + else if (shaderstate.curcull & SHADER_CULL_BACK) + IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_CULLMODE, D3DCULL_CW); + else + IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_CULLMODE, D3DCULL_NONE); + } + for (mno = 0, vertcount = 0, idxcount = 0; mno < shaderstate.nummeshes; mno++) { m = shaderstate.meshlist[mno]; @@ -1100,9 +1425,13 @@ static void BE_DrawMeshChain_Internal(void) allocvertexbuffer(shaderstate.dynxyz_buff, shaderstate.dynxyz_size, &shaderstate.dynxyz_offs, &map, vertcount*sizeof(vecV_t)); for (mno = 0, vertcount = 0; mno < shaderstate.nummeshes; mno++) { + vecV_t *dest = (vecV_t*)((char*)map+vertcount*sizeof(vecV_t)); m = shaderstate.meshlist[mno]; - /*fixme: no tcgen*/ - memcpy((char*)map+vertcount*sizeof(vecV_t), m->xyz_array, m->numvertexes*sizeof(vecV_t)); + deformgen(&shaderstate.curshader->deforms[0], m->numvertexes, m->xyz_array, dest, m); + for (i = 1; i < shaderstate.curshader->numdeforms; i++) + { + deformgen(&shaderstate.curshader->deforms[i], m->numvertexes, dest, dest, m); + } vertcount += m->numvertexes; } d3dcheck(IDirect3DVertexBuffer9_Unlock(shaderstate.dynxyz_buff)); @@ -1476,6 +1805,9 @@ static void BE_SubmitBatch(batch_t *batch) shaderstate.nummeshes = batch->meshes - batch->firstmesh; if (!shaderstate.nummeshes) return; + //FIXME: Why does this seem to work in GL? + if (batch->shader->flags & SHADER_FLARE) + return; if (shaderstate.curentity != batch->ent) { shaderstate.curentity = batch->ent; @@ -1523,6 +1855,127 @@ qboolean BE_ShouldDraw(entity_t *e) return true; } + + +#ifdef Q3CLIENT + +//q3 lightning gun +static void R_DrawLightning(entity_t *e) +{ + vec3_t v; + vec3_t dir, cr; + float scale = e->scale; + float length; + + vecV_t points[4]; + vec2_t texcoords[4] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}}; + static index_t indexarray[6] = {0, 1, 2, 0, 2, 3}; + + mesh_t mesh; + + if (!e->forcedshader) + return; + + if (!scale) + scale = 10; + + + VectorSubtract(e->origin, e->oldorigin, dir); + length = Length(dir); + + //this seems to be about right. + texcoords[2][0] = length/128; + texcoords[3][0] = length/128; + + VectorSubtract(r_refdef.vieworg, e->origin, v); + CrossProduct(v, dir, cr); + VectorNormalize(cr); + + VectorMA(e->origin, -scale/2, cr, points[0]); + VectorMA(e->origin, scale/2, cr, points[1]); + + VectorSubtract(r_refdef.vieworg, e->oldorigin, v); + CrossProduct(v, dir, cr); + VectorNormalize(cr); + + VectorMA(e->oldorigin, scale/2, cr, points[2]); + VectorMA(e->oldorigin, -scale/2, cr, points[3]); + + memset(&mesh, 0, sizeof(mesh)); + mesh.vbofirstelement = 0; + mesh.vbofirstvert = 0; + mesh.xyz_array = points; + mesh.indexes = indexarray; + mesh.numindexes = sizeof(indexarray)/sizeof(indexarray[0]); + mesh.colors4f_array = NULL; + mesh.lmst_array = NULL; + mesh.normals_array = NULL; + mesh.numvertexes = 4; + mesh.st_array = texcoords; + BE_DrawMesh_Single(e->forcedshader, &mesh, NULL, NULL); +} +//q3 railgun beam +static void R_DrawRailCore(entity_t *e) +{ + vec3_t v; + vec3_t dir, cr; + float scale = e->scale; + float length; + + mesh_t mesh; + vecV_t points[4]; + vec2_t texcoords[4] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}}; + static index_t indexarray[6] = {0, 1, 2, 0, 2, 3}; + vec4_t colors[4]; + + if (!e->forcedshader) + return; + + if (!scale) + scale = 10; + + + VectorSubtract(e->origin, e->oldorigin, dir); + length = Length(dir); + + //this seems to be about right. + texcoords[2][0] = length/128; + texcoords[3][0] = length/128; + + VectorSubtract(r_refdef.vieworg, e->origin, v); + CrossProduct(v, dir, cr); + VectorNormalize(cr); + + VectorMA(e->origin, -scale/2, cr, points[0]); + VectorMA(e->origin, scale/2, cr, points[1]); + + VectorSubtract(r_refdef.vieworg, e->oldorigin, v); + CrossProduct(v, dir, cr); + VectorNormalize(cr); + + VectorMA(e->oldorigin, scale/2, cr, points[2]); + VectorMA(e->oldorigin, -scale/2, cr, points[3]); + + Vector4Copy(e->shaderRGBAf, colors[0]); + Vector4Copy(e->shaderRGBAf, colors[1]); + Vector4Copy(e->shaderRGBAf, colors[2]); + Vector4Copy(e->shaderRGBAf, colors[3]); + + memset(&mesh, 0, sizeof(mesh)); + mesh.vbofirstelement = 0; + mesh.vbofirstvert = 0; + mesh.xyz_array = points; + mesh.indexes = indexarray; + mesh.numindexes = sizeof(indexarray)/sizeof(indexarray[0]); + mesh.colors4f_array = (vec4_t*)colors; + mesh.lmst_array = NULL; + mesh.normals_array = NULL; + mesh.numvertexes = 4; + mesh.st_array = texcoords; + + BE_DrawMesh_Single(e->forcedshader, &mesh, NULL, NULL); +} +#endif static void BE_GenModelBatches(batch_t **batches) { int i; @@ -1539,23 +1992,52 @@ static void BE_GenModelBatches(batch_t **batches) for (i=0 ; imodel) - continue; - if (ent->model->needload) - continue; + if (!BE_ShouldDraw(ent)) continue; - switch(ent->model->type) + + switch(ent->rtype) { - case mod_brush: - if (r_drawentities.ival == 2) + case RT_MODEL: + default: + if (!ent->model) continue; - Surf_GenBrushBatches(batches, ent); + if (ent->model->needload) + continue; + switch(ent->model->type) + { + case mod_brush: + if (r_drawentities.ival == 2) + continue; + Surf_GenBrushBatches(batches, ent); + break; + case mod_alias: + if (r_drawentities.ival == 3) + continue; + R_GAlias_GenerateBatches(ent, batches); + break; + } break; - case mod_alias: - if (r_drawentities.ival == 3) - continue; - R_GAlias_GenerateBatches(ent, batches); + case RT_SPRITE: + //RQ_AddDistReorder(GLR_DrawSprite, currententity, NULL, currententity->origin); + break; + +#ifdef Q3CLIENT + case RT_BEAM: + case RT_RAIL_RINGS: + case RT_LIGHTNING: + R_DrawLightning(ent); + continue; + case RT_RAIL_CORE: + R_DrawRailCore(ent); + continue; +#endif + + case RT_POLY: + /*not implemented*/ + break; + case RT_PORTALSURFACE: + /*nothing*/ break; } } @@ -1631,22 +2113,31 @@ void BE_DrawWorld (qbyte *vis) shaderstate.curtime = realtime; - BE_UploadLightmaps(false); + if (vis) + { + BE_UploadLightmaps(false); - //make sure the world draws correctly - r_worldentity.shaderRGBAf[0] = 1; - r_worldentity.shaderRGBAf[1] = 1; - r_worldentity.shaderRGBAf[2] = 1; - r_worldentity.shaderRGBAf[3] = 1; - r_worldentity.axis[0][0] = 1; - r_worldentity.axis[1][1] = 1; - r_worldentity.axis[2][2] = 1; + //make sure the world draws correctly + r_worldentity.shaderRGBAf[0] = 1; + r_worldentity.shaderRGBAf[1] = 1; + r_worldentity.shaderRGBAf[2] = 1; + r_worldentity.shaderRGBAf[3] = 1; + r_worldentity.axis[0][0] = 1; + r_worldentity.axis[1][1] = 1; + r_worldentity.axis[2][2] = 1; - BE_SelectMode(BEM_STANDARD, 0); + BE_SelectMode(BEM_STANDARD, 0); - RSpeedRemark(); - BE_SubmitMeshes(true, batches); - RSpeedEnd(RSPEED_WORLD); + RSpeedRemark(); + BE_SubmitMeshes(true, batches); + RSpeedEnd(RSPEED_WORLD); + } + else + { + RSpeedRemark(); + BE_SubmitMeshes(false, batches); + RSpeedEnd(RSPEED_DRAWENTITIES); + } BE_RotateForEntity(&r_worldentity, NULL); } diff --git a/engine/d3d/vid_d3d.c b/engine/d3d/vid_d3d.c index 979400026..12ac65640 100644 --- a/engine/d3d/vid_d3d.c +++ b/engine/d3d/vid_d3d.c @@ -439,16 +439,140 @@ typedef struct tagMONITORINFO } MONITORINFO, *LPMONITORINFO; #endif -static void initD3D9(HWND hWnd, rendererstate_t *info) +static qboolean initD3D9Device(HWND hWnd, rendererstate_t *info, unsigned int devno, unsigned int devtype) { - int i; - int numadaptors; int err; RECT rect; D3DADAPTER_IDENTIFIER9 inf; D3DCAPS9 caps; unsigned int cflags; + memset(&inf, 0, sizeof(inf)); + if (FAILED(IDirect3D9_GetAdapterIdentifier(pD3D, devno, 0, &inf))) + return false; + + if (FAILED(IDirect3D9_GetDeviceCaps(pD3D, devno, devtype, &caps))) + return false; + + memset(&d3dpp, 0, sizeof(d3dpp)); // clear out the struct for use + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; // discard old frames + d3dpp.hDeviceWindow = hWnd; // set the window to be used by Direct3D + d3dpp.BackBufferWidth = info->width; + d3dpp.BackBufferHeight = info->height; + d3dpp.MultiSampleType = info->multisample; + d3dpp.BackBufferCount = 1; + d3dpp.FullScreen_RefreshRateInHz = info->fullscreen?info->rate:0; //don't pass a rate if not fullscreen, d3d doesn't like it. + d3dpp.Windowed = !info->fullscreen; + + d3dpp.EnableAutoDepthStencil = true; + d3dpp.AutoDepthStencilFormat = D3DFMT_D16; + d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; + if (info->fullscreen) + { + if (info->bpp == 16) + d3dpp.BackBufferFormat = D3DFMT_R5G6B5; + else + d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; + } + + switch(info->wait) + { + default: + d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + break; + case 0: + d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; + break; + case 1: + d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; + break; + case 2: + d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_TWO; + break; + case 3: + d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_THREE; + break; + case 4: + d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_FOUR; + break; + } + + cflags = D3DCREATE_FPU_PRESERVE; + if ((caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) && (caps.DevCaps & D3DDEVCAPS_PUREDEVICE)) + cflags |= D3DCREATE_HARDWARE_VERTEXPROCESSING; + else + cflags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING; + //cflags |= D3DCREATE_DISABLE_DRIVER_MANAGEMENT; + + pD3DDev9 = NULL; + // create a device class using this information and information from the d3dpp stuct + err = IDirect3D9_CreateDevice(pD3D, + devno, + devtype, + hWnd, + cflags, + &d3dpp, + &pD3DDev9); + + if (pD3DDev9) + { + HMONITOR hm; + MONITORINFO mi; + char *s; + for (s = inf.Description + strlen(inf.Description)-1; s >= inf.Description && *s <= ' '; s--) + *s = 0; + Con_Printf("D3D9: Using device %s\n", inf.Description); + + vid.numpages = d3dpp.BackBufferCount; + + if (d3dpp.Windowed) //fullscreen we get positioned automagically. + { //windowed, we get positioned at 0,0... which is often going to be on the wrong screen + //the user can figure it out from here + static HANDLE huser32; + BOOL (WINAPI *pGetMonitorInfoA)(HMONITOR hMonitor, LPMONITORINFO lpmi); + if (!huser32) + huser32 = LoadLibrary("user32.dll"); + if (!huser32) + return false; + pGetMonitorInfoA = (void*)GetProcAddress(huser32, "GetMonitorInfoA"); + if (!pGetMonitorInfoA) + return false; + + hm = IDirect3D9_GetAdapterMonitor(pD3D, devno); + memset(&mi, 0, sizeof(mi)); + mi.cbSize = sizeof(mi); + pGetMonitorInfoA(hm, &mi); + rect.left = rect.top = 0; + rect.right = d3dpp.BackBufferWidth; + rect.bottom = d3dpp.BackBufferHeight; + AdjustWindowRectEx(&rect, WS_OVERLAPPEDWINDOW, FALSE, 0); + MoveWindow(d3dpp.hDeviceWindow, mi.rcWork.left, mi.rcWork.top, rect.right-rect.left, rect.bottom-rect.top, false); + } + return true; //successful + } + else + { + char *s; + switch(err) + { + default: s = "Unkown error"; break; + case D3DERR_DEVICELOST: s = "Device lost"; break; + case D3DERR_INVALIDCALL: s = "Invalid call"; break; + case D3DERR_NOTAVAILABLE: s = "Not available"; break; + case D3DERR_OUTOFVIDEOMEMORY: s = "Out of video memory"; break; + } + Con_Printf("IDirect3D9_CreateDevice failed: %s.\n", s); + } + return false; +} + +static void initD3D9(HWND hWnd, rendererstate_t *info) +{ + int i; + int numadaptors; + int err; + D3DADAPTER_IDENTIFIER9 inf; + static HMODULE d3d9dll; LPDIRECT3D9 (WINAPI *pDirect3DCreate9) (int version); @@ -473,124 +597,17 @@ static void initD3D9(HWND hWnd, rendererstate_t *info) numadaptors = IDirect3D9_GetAdapterCount(pD3D); for (i = 0; i < numadaptors; i++) { //try each adaptor in turn until we get one that actually works - - if (FAILED(IDirect3D9_GetDeviceCaps(pD3D, i, D3DDEVTYPE_HAL, &caps))) - continue; - - memset(&d3dpp, 0, sizeof(d3dpp)); // clear out the struct for use - d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; // discard old frames - d3dpp.hDeviceWindow = hWnd; // set the window to be used by Direct3D - d3dpp.BackBufferWidth = info->width; - d3dpp.BackBufferHeight = info->height; - d3dpp.MultiSampleType = info->multisample; - d3dpp.BackBufferCount = 1; - d3dpp.FullScreen_RefreshRateInHz = info->fullscreen?info->rate:0; //don't pass a rate if not fullscreen, d3d doesn't like it. - d3dpp.Windowed = !info->fullscreen; - - d3dpp.EnableAutoDepthStencil = true; - d3dpp.AutoDepthStencilFormat = D3DFMT_D16; - d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; - if (info->fullscreen) - { - if (info->bpp == 16) - d3dpp.BackBufferFormat = D3DFMT_R5G6B5; - else - d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; - } - - switch(info->wait) - { - default: - d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; - break; - case 0: - d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; - break; - case 1: - d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; - break; - case 2: - d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_TWO; - break; - case 3: - d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_THREE; - break; - case 4: - d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_FOUR; - break; - } - - cflags = D3DCREATE_FPU_PRESERVE; - if ((caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) && (caps.DevCaps & D3DDEVCAPS_PUREDEVICE)) - cflags |= D3DCREATE_HARDWARE_VERTEXPROCESSING; - else - cflags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING; - //cflags |= D3DCREATE_DISABLE_DRIVER_MANAGEMENT; - memset(&inf, 0, sizeof(inf)); err = IDirect3D9_GetAdapterIdentifier(pD3D, i, 0, &inf); - - pD3DDev9 = NULL; - // create a device class using this information and information from the d3dpp stuct - err = IDirect3D9_CreateDevice(pD3D, - i, - D3DDEVTYPE_HAL, - hWnd, - cflags, - &d3dpp, - &pD3DDev9); - - if (pD3DDev9) - { - HMONITOR hm; - MONITORINFO mi; - char *s; - for (s = inf.Description + strlen(inf.Description)-1; s >= inf.Description && *s <= ' '; s--) - *s = 0; - Con_Printf("D3D9: Using device %s\n", inf.Description); - - vid.numpages = d3dpp.BackBufferCount; - - if (d3dpp.Windowed) //fullscreen we get positioned automagically. - { //windowed, we get positioned at 0,0... which is often going to be on the wrong screen - //the user can figure it out from here - static HANDLE huser32; - BOOL (WINAPI *pGetMonitorInfoA)(HMONITOR hMonitor, LPMONITORINFO lpmi); - if (!huser32) - huser32 = LoadLibrary("user32.dll"); - if (!huser32) - return; - pGetMonitorInfoA = (void*)GetProcAddress(huser32, "GetMonitorInfoA"); - if (!pGetMonitorInfoA) - return; - - hm = IDirect3D9_GetAdapterMonitor(pD3D, i); - memset(&mi, 0, sizeof(mi)); - mi.cbSize = sizeof(mi); - pGetMonitorInfoA(hm, &mi); - rect.left = rect.top = 0; - rect.right = d3dpp.BackBufferWidth; - rect.bottom = d3dpp.BackBufferHeight; - AdjustWindowRectEx(&rect, WS_OVERLAPPEDWINDOW, FALSE, 0); - MoveWindow(d3dpp.hDeviceWindow, mi.rcWork.left, mi.rcWork.top, rect.right-rect.left, rect.bottom-rect.top, false); - } - return; //successful - } - else - { - char *s; - switch(err) - { - default: s = "Unkown error"; break; - case D3DERR_DEVICELOST: s = "Device lost"; break; - case D3DERR_INVALIDCALL: s = "Invalid call"; break; - case D3DERR_NOTAVAILABLE: s = "Not available"; break; - case D3DERR_OUTOFVIDEOMEMORY: s = "Out of video memory"; break; - } - Con_Printf("IDirect3D9_CreateDevice failed: %s.\n", s); - } + if (strstr(inf.Description, "PerfHUD")) + if (initD3D9Device(hWnd, info, i, D3DDEVTYPE_REF)) + return; + } + for (i = 0; i < numadaptors; i++) + { //try each adaptor in turn until we get one that actually works + if (initD3D9Device(hWnd, info, i, D3DDEVTYPE_HAL)) + return; } - return; } static qboolean D3D9_VID_Init(rendererstate_t *info, unsigned char *palette) @@ -728,16 +745,6 @@ static int (D3D9_R_LightPoint) (vec3_t point) return 0; } -static void (D3D9_R_PushDlights) (void) -{ -} -static void (D3D9_R_AddStain) (vec3_t org, float red, float green, float blue, float radius) -{ -} -static void (D3D9_R_LessenStains) (void) -{ -} - static void (D3D9_VID_DeInit) (void) { /*final shutdown, kill the video stuff*/ @@ -794,18 +801,6 @@ void D3D9_Set2D (void) Matrix4_Identity(m); IDirect3DDevice9_SetTransform(pD3DDev9, D3DTS_VIEW, (D3DMATRIX*)m); - - IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_CULLMODE, D3DCULL_CCW); - - IDirect3DDevice9_SetSamplerState(pD3DDev9, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); - IDirect3DDevice9_SetSamplerState(pD3DDev9, 1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); - - IDirect3DDevice9_SetSamplerState(pD3DDev9, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE); - IDirect3DDevice9_SetSamplerState(pD3DDev9, 1, D3DSAMP_MIPFILTER, D3DTEXF_NONE); - - IDirect3DDevice9_SetSamplerState(pD3DDev9, 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); - IDirect3DDevice9_SetSamplerState(pD3DDev9, 1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); - vport.X = 0; vport.Y = 0; vport.Width = vid.pixelwidth; @@ -944,9 +939,6 @@ static void (D3D9_SCR_UpdateScreen) (void) // R2D_BrightenScreen(); IDirect3DDevice9_EndScene(pD3DDev9); IDirect3DDevice9_Present(pD3DDev9, NULL, NULL, NULL, NULL); - -// pD3DDev->lpVtbl->BeginScene(pD3DDev); - RSpeedEnd(RSPEED_TOTALREFRESH); return; } @@ -1142,9 +1134,13 @@ static void (D3D9_R_RenderView) (void) D3D9_SetupViewPort(); d3d9error(IDirect3DDevice9_Clear(pD3DDev9, 0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1, 0)); R_SetFrustum (r_refdef.m_projection, r_refdef.m_view); + RQ_BeginFrame(); + Surf_DrawWorld(); if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL)) - Surf_DrawWorld(); - P_DrawParticles (); + { + if (cl.worldmodel) + P_DrawParticles (); + } RQ_RenderBatchClear(); } @@ -1217,9 +1213,8 @@ rendererinfo_t d3drendererinfo = D3D9_R_PreNewMap, D3D9_R_LightPoint, - D3D9_R_PushDlights, - D3D9_R_AddStain, - D3D9_R_LessenStains, + Surf_AddStain, + Surf_LessenStains, RMod_Init, RMod_ClearAll, diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index 40a242929..344f2dba1 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -813,8 +813,8 @@ static qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel) if (fb >= 1 && r_fb_models.value) { - ambientlight[0] = ambientlight[1] = ambientlight[2] = 4096; - shadelight[0] = shadelight[1] = shadelight[2] = 4096; + ambientlight[0] = ambientlight[1] = ambientlight[2] = 1; + shadelight[0] = shadelight[1] = shadelight[2] = 1; return true; } else diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index d73362e9b..a011852f7 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -2213,9 +2213,13 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas } break; + case SP_CONSTI: case SP_TEXTURE: qglUniform1iARB(s->progparm[i].handle[perm], s->progparm[i].ival); break; + case SP_CONSTF: + qglUniform1fARB(s->progparm[i].handle[perm], s->progparm[i].fval); + break; case SP_CVARI: qglUniform1iARB(s->progparm[i].handle[perm], ((cvar_t*)s->progparm[i].pval)->ival); break; diff --git a/engine/gl/gl_font.c b/engine/gl/gl_font.c index 0aa6ca5c9..cc6293cf2 100644 --- a/engine/gl/gl_font.c +++ b/engine/gl/gl_font.c @@ -248,6 +248,7 @@ void Font_Init(void) fontplanes.shader = R_RegisterShader("ftefont", "{\n" + "nomipmaps\n" "{\n" "map $diffuse\n" "rgbgen const\n" @@ -259,6 +260,7 @@ void Font_Init(void) fontplanes.backshader = R_RegisterShader("ftefontback", "{\n" + "nomipmaps\n" "{\n" "map $whiteimage\n" "rgbgen const\n" diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index 837e6e9a7..666c9f4f5 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -2659,7 +2659,6 @@ float RadiusFromBounds (vec3_t mins, vec3_t maxs); //combination of R_AddDynamicLights and R_MarkLights static void Q1BSP_StainNode (mnode_t *node, float *parms) { -#ifdef GLQUAKE mplane_t *splitplane; float dist; msurface_t *surf; @@ -2693,7 +2692,6 @@ static void Q1BSP_StainNode (mnode_t *node, float *parms) Q1BSP_StainNode (node->children[0], parms); Q1BSP_StainNode (node->children[1], parms); -#endif } void RMod_FixupNodeMinsMaxs (mnode_t *node, mnode_t *parent) diff --git a/engine/gl/gl_rlight.c b/engine/gl/gl_rlight.c index 8540312a4..a666ce8f4 100644 --- a/engine/gl/gl_rlight.c +++ b/engine/gl/gl_rlight.c @@ -418,7 +418,7 @@ void GLR_MarkQ3Lights (dlight_t *light, int bit, mnode_t *node) R_PushDlights ============= */ -void GLR_PushDlights (void) +void R_PushDlights (void) { int i; dlight_t *l; diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index d810e81c4..56d3a9e15 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -1118,6 +1118,8 @@ void R_RenderScene (void) TRACE(("dbg: calling R_SetFrustrum\n")); R_SetFrustum (r_refdef.m_projection, r_refdef.m_view); + RQ_BeginFrame(); + if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL)) { TRACE(("dbg: calling R_DrawWorld\n")); @@ -1128,8 +1130,6 @@ void R_RenderScene (void) S_ExtraUpdate (); // don't let sound get messed up if going slow - RQ_BeginFrame(); - TRACE(("dbg: calling GLR_DrawEntitiesOnList\n")); GLR_DrawEntitiesOnList (); diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index adb30a234..29b2d89b1 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -31,6 +31,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include +#include +#include "glsupp.h" extern texid_t missing_texture; @@ -248,8 +250,34 @@ static qboolean Shader_EvaluateCondition(char **ptr) else { cv = Cvar_Get(token, "", 0, "Shader Conditions"); - if (cv) - conditiontrue = conditiontrue == !!cv->value; + token = COM_ParseExt ( ptr, false ); + if (*token) + { + float rhs; + char cmp[4]; + memcpy(cmp, token, 4); + token = COM_ParseExt ( ptr, false ); + rhs = atof(token); + if (!strcmp(cmp, "!=")) + conditiontrue = cv->value != rhs; + else if (!strcmp(cmp, "==")) + conditiontrue = cv->value == rhs; + else if (!strcmp(cmp, "<")) + conditiontrue = cv->value < rhs; + else if (!strcmp(cmp, "<=")) + conditiontrue = cv->value <= rhs; + else if (!strcmp(cmp, ">")) + conditiontrue = cv->value > rhs; + else if (!strcmp(cmp, ">=")) + conditiontrue = cv->value >= rhs; + else + conditiontrue = false; + } + else + { + if (cv) + conditiontrue = conditiontrue == !!cv->value; + } } return conditiontrue; @@ -814,6 +842,18 @@ static void Shader_ProgramParam ( shader_t *shader, shaderpass_t *pass, char **p specialint = atoi(token); parmtype = SP_TEXTURE; } + else if (!Q_stricmp(token, "consti")) + { + token = Shader_ParseSensString(ptr); + specialint = atoi(token); + parmtype = SP_CONSTI; + } + else if (!Q_stricmp(token, "constf")) + { + token = Shader_ParseSensString(ptr); + specialfloat = atof(token); + parmtype = SP_CONSTF; + } else if (!Q_stricmp(token, "cvari")) { token = Shader_ParseSensString(ptr); @@ -895,8 +935,12 @@ static void Shader_ProgramParam ( shader_t *shader, shaderpass_t *pass, char **p foundone = false; break; case SP_TEXTURE: + case SP_CONSTI: shader->progparm[shader->numprogparams].ival = specialint; break; + case SP_CONSTF: + shader->progparm[shader->numprogparams].fval = specialfloat; + break; case SP_CVARF: case SP_CVARI: shader->progparm[shader->numprogparams].pval = cv; @@ -1785,7 +1829,6 @@ void Shader_Shutdown (void) void Shader_SetBlendmode (shaderpass_t *pass) { -#ifdef GLQUAKE /*FIXME: move to backnd*/ if (pass->texgen == T_GEN_DELUXMAP) { pass->blendmode = GL_DOT3_RGB_ARB; @@ -1824,7 +1867,6 @@ void Shader_SetBlendmode (shaderpass_t *pass) pass->blendmode = GL_DECAL; else pass->blendmode = GL_MODULATE; -#endif } void Shader_Readpass (shader_t *shader, char **ptr) @@ -1971,7 +2013,11 @@ static qboolean Shader_Parsetok (shader_t *shader, shaderpass_t *pass, shaderkey void Shader_SetPassFlush (shaderpass_t *pass, shaderpass_t *pass2) { -#ifdef GLQUAKE + qboolean config_tex_env_combine = 1;//0; + qboolean config_nv_tex_env_combine4 = 1;//0; + qboolean config_multitexure = be_maxpasses > 1;//0; + qboolean config_env_add = 1;//0; + if (((pass->flags & SHADER_PASS_DETAIL) && !r_detailtextures.value) || ((pass2->flags & SHADER_PASS_DETAIL) && !r_detailtextures.value) || (pass->flags & SHADER_PASS_VIDEOMAP) || (pass2->flags & SHADER_PASS_VIDEOMAP)) @@ -1993,19 +2039,19 @@ void Shader_SetPassFlush (shaderpass_t *pass, shaderpass_t *pass2) { pass->numMergedPasses++; } - else if (gl_config.tex_env_combine || gl_config.nv_tex_env_combine4) + else if (config_tex_env_combine || config_nv_tex_env_combine4) { if ( pass->blendmode == GL_REPLACE ) { - if ((pass2->blendmode == GL_DECAL && gl_config.tex_env_combine) || - (pass2->blendmode == GL_ADD && gl_config.env_add) || - (pass2->blendmode && pass2->blendmode != GL_ADD) || gl_config.nv_tex_env_combine4) + if ((pass2->blendmode == GL_DECAL && config_tex_env_combine) || + (pass2->blendmode == GL_ADD && config_env_add) || + (pass2->blendmode && pass2->blendmode != GL_ADD) || config_nv_tex_env_combine4) { pass->numMergedPasses++; } } else if (pass->blendmode == GL_ADD && - pass2->blendmode == GL_ADD && gl_config.env_add) + pass2->blendmode == GL_ADD && config_env_add) { pass->numMergedPasses++; } @@ -2014,7 +2060,7 @@ void Shader_SetPassFlush (shaderpass_t *pass, shaderpass_t *pass2) pass->numMergedPasses++; } } - else if ( qglMTexCoord2fSGIS ) + else if (config_multitexure) { //don't merge more than 2 tmus. if (pass->numMergedPasses != 1) @@ -2023,7 +2069,7 @@ void Shader_SetPassFlush (shaderpass_t *pass, shaderpass_t *pass2) // check if we can use R_RenderMeshMultitextured if ( pass->blendmode == GL_REPLACE ) { - if ( pass2->blendmode == GL_ADD && gl_config.env_add ) + if ( pass2->blendmode == GL_ADD && config_env_add ) { pass->numMergedPasses = 2; } @@ -2036,12 +2082,11 @@ void Shader_SetPassFlush (shaderpass_t *pass, shaderpass_t *pass2) { pass->numMergedPasses = 2; } - else if (pass->blendmode == GL_ADD && pass2->blendmode == GL_ADD && gl_config.env_add) + else if (pass->blendmode == GL_ADD && pass2->blendmode == GL_ADD && config_env_add) { pass->numMergedPasses = 2; } } -#endif } void Shader_SetFeatures ( shader_t *s ) @@ -2752,13 +2797,24 @@ void Shader_DefaultBSPQ1(char *shortname, shader_t *s, const void *args) "}\n" "param time time\n" "param texture 0 watertexture\n" - "param cvarf r_wateralpha wateralpha\n" + "if r_wateralpha != 1\n" + "[\n" + "param cvarf r_wateralpha wateralpha\n" + "sort blend\n" + "{\n" + "map $diffuse\n" + "blendfunc gl_src_alpha gl_one_minus_src_alpha\n" + "}\n" + "]\n" + "if r_wateralpha == 1\n" + "[\n" + "param constf 1 wateralpha\n" + "sort opaque\n" + "{\n" + "map $diffuse\n" + "}\n" + "]\n" "surfaceparm nodlight\n" - "{\n" - "map $diffuse\n" - "blendfunc gl_src_alpha gl_one_minus_src_alpha\n" - "}\n" - "sort blend\n" "}\n" ); } diff --git a/engine/gl/shader.h b/engine/gl/shader.h index f058039bb..96c666cdb 100644 --- a/engine/gl/shader.h +++ b/engine/gl/shader.h @@ -262,6 +262,8 @@ typedef struct { //things that are set immediatly SP_FIRSTIMMEDIATE, //never set + SP_CONSTI, + SP_CONSTF, SP_CVARI, SP_CVARF, SP_CVAR3F, @@ -271,6 +273,7 @@ typedef struct { union { int ival; + float fval; void *pval; }; } shaderprogparm_t; diff --git a/engine/qclib/qcd_main.c b/engine/qclib/qcd_main.c index f98e5336a..20c6f7ca0 100644 --- a/engine/qclib/qcd_main.c +++ b/engine/qclib/qcd_main.c @@ -8,7 +8,11 @@ #define ZEXPORT VARGS #include "../libs/zlib.h" +#ifdef _WIN64 +# pragma comment (lib, "../libs/zlib64.lib") +#else # pragma comment (lib, "../libs/zlib.lib") +#endif #else #include #endif diff --git a/engine/server/svq3_game.c b/engine/server/svq3_game.c index 7bebd9d6b..3cff77728 100644 --- a/engine/server/svq3_game.c +++ b/engine/server/svq3_game.c @@ -1410,7 +1410,7 @@ static int Q3G_SystemCallsVM(void *offset, unsigned int mask, int fn, const int args[11]=arg[11]; args[12]=arg[12]; - return Q3G_SystemCalls(NULL, ~0, fn, args); + return Q3G_SystemCalls(offset, mask, fn, args); } static qintptr_t EXPORT_FN Q3G_SystemCallsNative(qintptr_t arg, ...)