diff --git a/src/console.c b/src/console.c index 70f8ab6f8..3c06561ce 100644 --- a/src/console.c +++ b/src/console.c @@ -842,8 +842,9 @@ boolean CON_Responder(event_t *ev) return true; } - // don't eat the key - return false; + // ...why shouldn't it eat the key? if it doesn't, it just means you + // can control Sonic from the console, which is silly + return true; //return false; } // command completion forward (tab) and backward (shift-tab) @@ -1042,7 +1043,7 @@ boolean CON_Responder(event_t *ev) // enter a char into the command prompt if (key < 32 || key > 127) - return false; + return true; // even if key can't be printed, eat it anyway // add key to cmd line here if (key >= 'A' && key <= 'Z' && !shiftdown) //this is only really necessary for dedicated servers diff --git a/src/d_clisrv.c b/src/d_clisrv.c index d48f223c7..36d13fc14 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1157,22 +1157,37 @@ static inline void CL_DrawConnectionStatus(void) if (lastfilenum != -1) { INT32 dldlength; - static char tempname[32]; + static char tempname[28]; + fileneeded_t *file = &fileneeded[lastfilenum]; + char *filename = file->filename; Net_GetNetStat(); - dldlength = (INT32)((fileneeded[lastfilenum].currentsize/(double)fileneeded[lastfilenum].totalsize) * 256); + dldlength = (INT32)((file->currentsize/(double)file->totalsize) * 256); if (dldlength > 256) dldlength = 256; V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, 256, 8, 175); V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, dldlength, 8, 160); memset(tempname, 0, sizeof(tempname)); - nameonly(strncpy(tempname, fileneeded[lastfilenum].filename, 31)); + // offset filename to just the name only part + filename += strlen(filename) - nameonlylength(filename); + + if (strlen(filename) > sizeof(tempname)-1) // too long to display fully + { + size_t endhalfpos = strlen(filename)-10; + // display as first 14 chars + ... + last 10 chars + // which should add up to 27 if our math(s) is correct + snprintf(tempname, sizeof(tempname), "%.14s...%.10s", filename, filename+endhalfpos); + } + else // we can copy the whole thing in safely + { + strncpy(tempname, filename, sizeof(tempname)-1); + } V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-32, V_YELLOWMAP, va(M_GetText("Downloading \"%s\""), tempname)); V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE, - va(" %4uK/%4uK",fileneeded[lastfilenum].currentsize>>10,fileneeded[lastfilenum].totalsize>>10)); + va(" %4uK/%4uK",fileneeded[lastfilenum].currentsize>>10,file->totalsize>>10)); V_DrawRightAlignedString(BASEVIDWIDTH/2+128, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE, va("%3.1fK/s ", ((double)getbps)/1024)); } @@ -2229,7 +2244,7 @@ static void Command_connect(void) // Assume we connect directly. boolean viams = false; - if (COM_Argc() < 2) + if (COM_Argc() < 2 || *COM_Argv(1) == 0) { CONS_Printf(M_GetText( "Connect (port): connect to a server\n" @@ -3984,7 +3999,8 @@ FILESTAMP INT32 k = *txtpak++; // playernum const size_t txtsize = txtpak[0]+1; - M_Memcpy(D_GetTextcmd(i, k), txtpak, txtsize); + if (i >= gametic) // Don't copy old net commands + M_Memcpy(D_GetTextcmd(i, k), txtpak, txtsize); txtpak += txtsize; } } diff --git a/src/d_main.c b/src/d_main.c index 063d28453..fbec5f7d8 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -730,11 +730,6 @@ void D_StartTitle(void) CON_ToggleOff(); // Reset the palette -#ifdef HWRENDER - if (rendermode == render_opengl) - HWR_SetPaletteColor(0); - else -#endif if (rendermode != render_none) V_SetPaletteLump("PLAYPAL"); } @@ -1068,7 +1063,7 @@ void D_SRB2Main(void) // add any files specified on the command line with -file wadfile // to the wad list - if (!(M_CheckParm("-connect"))) + if (!(M_CheckParm("-connect") && !M_CheckParm("-server"))) { if (M_CheckParm("-file")) { @@ -1224,7 +1219,15 @@ void D_SRB2Main(void) R_Init(); // setting up sound - CONS_Printf("S_Init(): Setting up sound.\n"); + if (dedicated) + { + nosound = true; + nomidimusic = nodigimusic = true; + } + else + { + CONS_Printf("S_Init(): Setting up sound.\n"); + } if (M_CheckParm("-nosound")) nosound = true; if (M_CheckParm("-nomusic")) // combines -nomidimusic and -nodigmusic @@ -1323,7 +1326,7 @@ void D_SRB2Main(void) ultimatemode = true; } - if (autostart || netgame || M_CheckParm("+connect") || M_CheckParm("-connect")) + if (autostart || netgame) { gameaction = ga_nothing; @@ -1361,8 +1364,7 @@ void D_SRB2Main(void) } } - if (server && !M_CheckParm("+map") && !M_CheckParm("+connect") - && !M_CheckParm("-connect")) + if (server && !M_CheckParm("+map")) { // Prevent warping to nonexistent levels if (W_CheckNumForName(G_BuildMapName(pstartmap)) == LUMPERROR) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 3696dd974..673d64fd8 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -582,7 +582,6 @@ void D_RegisterServerCommands(void) */ void D_RegisterClientCommands(void) { - const char *username; INT32 i; for (i = 0; i < MAXSKINCOLORS; i++) @@ -639,8 +638,6 @@ void D_RegisterClientCommands(void) #endif // register these so it is saved to config - if ((username = I_GetUserName())) - cv_playername.defaultvalue = username; CV_RegisterVar(&cv_playername); CV_RegisterVar(&cv_playercolor); CV_RegisterVar(&cv_skin); // r_things.c (skin NAME) diff --git a/src/d_netfil.c b/src/d_netfil.c index 172624ad2..6742cfe28 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -990,19 +990,41 @@ filestatus_t checkfilemd5(char *filename, const UINT8 *wantedmd5sum) return FS_FOUND; // will never happen, but makes the compiler shut up } +// Rewritten by Monster Iestyn to be less stupid +// Note: if completepath is true, "filename" is modified, but only if FS_FOUND is going to be returned +// (Don't worry about WinCE's version of filesearch, nobody cares about that OS anymore) filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean completepath) { - filestatus_t homecheck = filesearch(filename, srb2home, wantedmd5sum, false, 10); - if (homecheck == FS_FOUND) - return filesearch(filename, srb2home, wantedmd5sum, completepath, 10); + filestatus_t homecheck; // store result of last file search + boolean badmd5 = false; // store whether md5 was bad from either of the first two searches (if nothing was found in the third) - homecheck = filesearch(filename, srb2path, wantedmd5sum, false, 10); - if (homecheck == FS_FOUND) - return filesearch(filename, srb2path, wantedmd5sum, completepath, 10); + // first, check SRB2's "home" directory + homecheck = filesearch(filename, srb2home, wantedmd5sum, completepath, 10); + if (homecheck == FS_FOUND) // we found the file, so return that we have :) + return FS_FOUND; + else if (homecheck == FS_MD5SUMBAD) // file has a bad md5; move on and look for a file with the right md5 + badmd5 = true; + // if not found at all, just move on without doing anything + + // next, check SRB2's "path" directory + homecheck = filesearch(filename, srb2path, wantedmd5sum, completepath, 10); + + if (homecheck == FS_FOUND) // we found the file, so return that we have :) + return FS_FOUND; + else if (homecheck == FS_MD5SUMBAD) // file has a bad md5; move on and look for a file with the right md5 + badmd5 = true; + // if not found at all, just move on without doing anything + + // finally check "." directory #ifdef _arch_dreamcast - return filesearch(filename, "/cd", wantedmd5sum, completepath, 10); + homecheck = filesearch(filename, "/cd", wantedmd5sum, completepath, 10); #else - return filesearch(filename, ".", wantedmd5sum, completepath, 10); + homecheck = filesearch(filename, ".", wantedmd5sum, completepath, 10); #endif + + if (homecheck != FS_NOTFOUND) // if not found this time, fall back on the below return statement + return homecheck; // otherwise return the result we got + + return (badmd5 ? FS_MD5SUMBAD : FS_NOTFOUND); // md5 sum bad or file not found } diff --git a/src/f_finale.c b/src/f_finale.c index 692abb35f..958bef0f6 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -233,11 +233,19 @@ static void F_SkyScroll(INT32 scrollspeed) #ifdef HWRENDER else if (rendermode != render_none) { // if only software rendering could be this simple and retarded - scrolled = animtimer; - if (scrolled > 0) - V_DrawScaledPatch(scrolled - SHORT(pat->width), 0, 0, pat); - for (x = 0; x < fakedwidth; x += SHORT(pat->width)) - V_DrawScaledPatch(x + scrolled, 0, 0, pat); + INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); + INT32 y, pw = SHORT(pat->width) * dupz, ph = SHORT(pat->height) * dupz; + scrolled = animtimer * dupz; + for (x = 0; x < vid.width; x += pw) + { + for (y = 0; y < vid.height; y += ph) + { + if (scrolled > 0) + V_DrawScaledPatch(scrolled - pw, y, V_NOSCALESTART, pat); + + V_DrawScaledPatch(x + scrolled, y, V_NOSCALESTART, pat); + } + } } #endif @@ -969,7 +977,7 @@ static const char *credits[] = { "\1Programming", "Alam \"GBC\" Arias", "Logan \"GBA\" Arias", - "Tim \"RedEnchilada\" Bordelon", + "Colette \"fickle\" Bordelon", "Callum Dickinson", "Scott \"Graue\" Feeney", "Nathan \"Jazz\" Giroux", @@ -978,12 +986,12 @@ static const char *credits[] = { "Ronald \"Furyhunter\" Kinard", // The SDL2 port "John \"JTE\" Muniz", "Ehab \"Wolfy\" Saeed", + "\"Kaito Sinclaire\"", "\"SSNTails\"", - "Matthew \"Inuyasha\" Walsh", "", "\1Programming", "\1Assistance", - "\"chi.miru\"", // Red's secret weapon, the REAL reason slopes exist (also helped port drawing code from ZDoom) + "\"chi.miru\"", // helped port slope drawing code from ZDoom "Andrew \"orospakr\" Clunis", "Gregor \"Oogaland\" Dick", "Louis-Antoine \"LJSonic\" de Moulins", // for fixing 2.1's netcode (de Rochefort doesn't quite fit on the screen sorry lol) @@ -999,7 +1007,7 @@ static const char *credits[] = { "", "\1Sprite Artists", "Odi \"Iceman404\" Atunzu", - "Victor \"VAdaPEGA\" Ara\x1Fjo", // Araújo -- sorry for our limited font! D: + "Victor \"VAdaPEGA\" Ara\x1Fjo", // Araújo -- sorry for our limited font! D: "Jim \"MotorRoach\" DeMello", "Desmond \"Blade\" DesJardins", "Sherman \"CoatRack\" DesJardins", @@ -1017,7 +1025,7 @@ static const char *credits[] = { "\1Music and Sound", "\1Production", "Malcolm \"RedXVI\" Brown", - "David \"Bulmybag\" Bulmer", + "Dave \"DemonTomatoDave\" Bulmer", "Paul \"Boinciel\" Clempson", "Cyan Helkaraxe", "Kepa \"Nev3r\" Iceta", @@ -1041,13 +1049,13 @@ static const char *credits[] = { "Kepa \"Nev3r\" Iceta", "Thomas \"Shadow Hog\" Igoe", "Erik \"Torgo\" Nielsen", + "\"Kaito Sinclaire\"", "Wessel \"Spherallic\" Smit", "\"Spazzo\"", "\"SSNTails\"", "Rob Tisdell", "Jarrett \"JEV3\" Voight", "Johnny \"Sonikku\" Wallbank", - "Matthew \"Inuyasha\" Walsh", "Marco \"Digiku\" Zafra", "", "\1Boss Design", diff --git a/src/g_game.c b/src/g_game.c index d3c55e0cc..bcae69fda 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3588,7 +3588,8 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean unlocktriggers = 0; // clear itemfinder, just in case - CV_StealthSetValue(&cv_itemfinder, 0); + if (!dedicated) // except in dedicated servers, where it is not registered and can actually I_Error debug builds + CV_StealthSetValue(&cv_itemfinder, 0); } // internal game map diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index 70d776d9e..c05ff3e79 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -20,8 +20,8 @@ #define _HWR_DEFS_ #include "../doomtype.h" -#define ZCLIP_PLANE 4.0f -#define NZCLIP_PLANE 0.9f +#define ZCLIP_PLANE 4.0f // Used for the actual game drawing +#define NZCLIP_PLANE 0.9f // Seems to be only used for the HUD and screen textures // ========================================================================== // SIMPLE TYPES @@ -133,12 +133,13 @@ enum EPolyFlags PF_Masked = 0x00000001, // Poly is alpha scaled and 0 alpha pels are discarded (holes in texture) PF_Translucent = 0x00000002, // Poly is transparent, alpha = level of transparency - PF_Additive = 0x00000024, // Poly is added to the frame buffer + PF_Additive = 0x00000004, // Poly is added to the frame buffer PF_Environment = 0x00000008, // Poly should be drawn environment mapped. // Hurdler: used for text drawing PF_Substractive = 0x00000010, // for splat PF_NoAlphaTest = 0x00000020, // hiden param - PF_Blending = (PF_Environment|PF_Additive|PF_Translucent|PF_Masked|PF_Substractive)&~PF_NoAlphaTest, + PF_Fog = 0x00000040, // Fog blocks + PF_Blending = (PF_Environment|PF_Additive|PF_Translucent|PF_Masked|PF_Substractive|PF_Fog)&~PF_NoAlphaTest, // other flag bits diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index f23753ee5..84081dd25 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -147,10 +147,7 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, // | /| // |/ | // 0--1 - float sdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f; - float sdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f; - float pdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f*FIXED_TO_FLOAT(pscale); - float pdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f*FIXED_TO_FLOAT(pscale); + float dupx, dupy, fscale, fwidth, fheight; if (alphalevel >= 10 && alphalevel < 13) return; @@ -161,40 +158,108 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, else HWR_GetMappedPatch(gpatch, colormap); + dupx = (float)vid.dupx; + dupy = (float)vid.dupy; + switch (option & V_SCALEPATCHMASK) { case V_NOSCALEPATCH: - pdupx = pdupy = 2.0f; + dupx = dupy = 1.0f; break; case V_SMALLSCALEPATCH: - pdupx = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupx); - pdupy = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupy); + dupx = (float)vid.smalldupx; + dupy = (float)vid.smalldupy; break; case V_MEDSCALEPATCH: - pdupx = 2.0f * FIXED_TO_FLOAT(vid.fmeddupx); - pdupy = 2.0f * FIXED_TO_FLOAT(vid.fmeddupy); + dupx = (float)vid.meddupx; + dupy = (float)vid.meddupy; break; } - if (option & V_NOSCALESTART) - sdupx = sdupy = 2.0f; + dupx = dupy = (dupx < dupy ? dupx : dupy); + fscale = FIXED_TO_FLOAT(pscale); - if (option & V_SPLITSCREEN) - sdupy /= 2.0f; - - if (option & V_FLIP) // Need to flip both this and sow + if (option & V_OFFSET) { - v[0].x = v[3].x = (cx*sdupx-(gpatch->width-gpatch->leftoffset)*pdupx)/vid.width - 1; - v[2].x = v[1].x = (cx*sdupx+gpatch->leftoffset*pdupx)/vid.width - 1; + cx -= (float)gpatch->leftoffset * dupx * fscale; + cy -= (float)gpatch->topoffset * dupy * fscale; } else { - v[0].x = v[3].x = (cx*sdupx-gpatch->leftoffset*pdupx)/vid.width - 1; - v[2].x = v[1].x = (cx*sdupx+(gpatch->width-gpatch->leftoffset)*pdupx)/vid.width - 1; + cy -= (float)gpatch->topoffset * fscale; + if (option & V_FLIP) + cx -= ((float)gpatch->width - (float)gpatch->leftoffset) * fscale; + else + cx -= (float)gpatch->leftoffset * fscale; } - v[0].y = v[1].y = 1-(cy*sdupy-gpatch->topoffset*pdupy)/vid.height; - v[2].y = v[3].y = 1-(cy*sdupy+(gpatch->height-gpatch->topoffset)*pdupy)/vid.height; + if (option & V_SPLITSCREEN) + cy /= 2; + + if (!(option & V_NOSCALESTART)) + { + cx = cx * dupx; + cy = cy * dupy; + + if (!(option & V_SCALEPATCHMASK)) + { + // if it's meant to cover the whole screen, black out the rest + // cx and cy are possibly *slightly* off from float maths + // This is done before here compared to software because we directly alter cx and cy to centre + if (cx >= -0.1f && cx <= 0.1f && SHORT(gpatch->width) == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && SHORT(gpatch->height) == BASEVIDHEIGHT) + { + // Need to temporarily cache the real patch to get the colour of the top left pixel + patch_t *realpatch = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC); + const column_t *column = (const column_t *)((const UINT8 *)(realpatch) + LONG((realpatch)->columnofs[0])); + const UINT8 *source = (const UINT8 *)(column) + 3; + HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); + Z_Free(realpatch); + } + // centre screen + if (vid.width != BASEVIDWIDTH * vid.dupx) + { + if (option & V_SNAPTORIGHT) + cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)); + else if (!(option & V_SNAPTOLEFT)) + cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/2; + } + if (vid.height != BASEVIDHEIGHT * vid.dupy) + { + if ((option & (V_SPLITSCREEN|V_SNAPTOBOTTOM)) == (V_SPLITSCREEN|V_SNAPTOBOTTOM)) + cy += ((float)vid.height/2 - ((float)BASEVIDHEIGHT/2 * dupy)); + else if (option & V_SNAPTOBOTTOM) + cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)); + else if (!(option & V_SNAPTOTOP)) + cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/2; + } + } + } + + if (pscale != FRACUNIT) + { + fwidth = (float)gpatch->width * fscale * dupx; + fheight = (float)gpatch->height * fscale * dupy; + } + else + { + fwidth = (float)gpatch->width * dupx; + fheight = (float)gpatch->height * dupy; + } + + // positions of the cx, cy, are between 0 and vid.width/vid.height now, we need them to be between -1 and 1 + cx = -1 + (cx / (vid.width/2)); + cy = 1 - (cy / (vid.height/2)); + + // fwidth and fheight are similar + fwidth /= vid.width / 2; + fheight /= vid.height / 2; + + // set the polygon vertices to the right positions + v[0].x = v[3].x = cx; + v[2].x = v[1].x = cx + fwidth; + + v[0].y = v[1].y = cy; + v[2].y = v[3].y = cy - fheight; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; @@ -247,10 +312,7 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal // | /| // |/ | // 0--1 - float sdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f; - float sdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f; - float pdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f*FIXED_TO_FLOAT(pscale); - float pdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f*FIXED_TO_FLOAT(pscale); + float dupx, dupy, fscale, fwidth, fheight; if (alphalevel >= 10 && alphalevel < 13) return; @@ -258,28 +320,109 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal // make patch ready in hardware cache HWR_GetPatch(gpatch); + dupx = (float)vid.dupx; + dupy = (float)vid.dupy; + switch (option & V_SCALEPATCHMASK) { case V_NOSCALEPATCH: - pdupx = pdupy = 2.0f; + dupx = dupy = 1.0f; break; case V_SMALLSCALEPATCH: - pdupx = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupx); - pdupy = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupy); + dupx = (float)vid.smalldupx; + dupy = (float)vid.smalldupy; break; case V_MEDSCALEPATCH: - pdupx = 2.0f * FIXED_TO_FLOAT(vid.fmeddupx); - pdupy = 2.0f * FIXED_TO_FLOAT(vid.fmeddupy); + dupx = (float)vid.meddupx; + dupy = (float)vid.meddupy; break; } - if (option & V_NOSCALESTART) - sdupx = sdupy = 2.0f; + dupx = dupy = (dupx < dupy ? dupx : dupy); + fscale = FIXED_TO_FLOAT(pscale); - v[0].x = v[3].x = (cx*sdupx - gpatch->leftoffset * pdupx) / vid.width - 1; - v[2].x = v[1].x = (cx*sdupx + ((w-sx) - gpatch->leftoffset) * pdupx) / vid.width - 1; - v[0].y = v[1].y = 1 - (cy*sdupy - gpatch->topoffset * pdupy) / vid.height; - v[2].y = v[3].y = 1 - (cy*sdupy + ((h-sy) - gpatch->topoffset) * pdupy) / vid.height; + cy -= (float)gpatch->topoffset * fscale; + cx -= (float)gpatch->leftoffset * fscale; + + if (!(option & V_NOSCALESTART)) + { + cx = cx * dupx; + cy = cy * dupy; + + if (!(option & V_SCALEPATCHMASK)) + { + // if it's meant to cover the whole screen, black out the rest + // cx and cy are possibly *slightly* off from float maths + // This is done before here compared to software because we directly alter cx and cy to centre + if (cx >= -0.1f && cx <= 0.1f && SHORT(gpatch->width) == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && SHORT(gpatch->height) == BASEVIDHEIGHT) + { + // Need to temporarily cache the real patch to get the colour of the top left pixel + patch_t *realpatch = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC); + const column_t *column = (const column_t *)((const UINT8 *)(realpatch) + LONG((realpatch)->columnofs[0])); + const UINT8 *source = (const UINT8 *)(column) + 3; + HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); + Z_Free(realpatch); + } + // centre screen + if (vid.width != BASEVIDWIDTH * vid.dupx) + { + if (option & V_SNAPTORIGHT) + cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)); + else if (!(option & V_SNAPTOLEFT)) + cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/2; + } + if (vid.height != BASEVIDHEIGHT * vid.dupy) + { + if ((option & (V_SPLITSCREEN|V_SNAPTOBOTTOM)) == (V_SPLITSCREEN|V_SNAPTOBOTTOM)) + cy += ((float)vid.height/2 - ((float)BASEVIDHEIGHT/2 * dupy)); + else if (option & V_SNAPTOBOTTOM) + cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)); + else if (!(option & V_SNAPTOTOP)) + cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/2; + } + } + } + + fwidth = w; + fheight = h; + + if (fwidth > w - sx) + fwidth = w - sx; + + if (fheight > h - sy) + fheight = h - sy; + + if (fwidth > gpatch->width) + fwidth = gpatch->width; + + if (fheight > gpatch->height) + fheight = gpatch->height; + + if (pscale != FRACUNIT) + { + fwidth *= fscale * dupx; + fheight *= fscale * dupy; + } + else + { + fwidth *= dupx; + fheight *= dupy; + } + + // positions of the cx, cy, are between 0 and vid.width/vid.height now, we need them to be between -1 and 1 + cx = -1 + (cx / (vid.width/2)); + cy = 1 - (cy / (vid.height/2)); + + // fwidth and fheight are similar + fwidth /= vid.width / 2; + fheight /= vid.height / 2; + + // set the polygon vertices to the right positions + v[0].x = v[3].x = cx; + v[2].x = v[1].x = cx + fwidth; + + v[0].y = v[1].y = cy; + v[2].y = v[3].y = cy - fheight; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; @@ -656,7 +799,7 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color) { FOutVector v[4]; FSurfaceInfo Surf; - float sdupx, sdupy; + float fx, fy, fw, fh; if (w < 0 || h < 0) return; // consistency w/ software @@ -665,16 +808,79 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color) // | /| // |/ | // 0--1 - sdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f; - sdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f; - if (color & V_NOSCALESTART) - sdupx = sdupy = 2.0f; + fx = (float)x; + fy = (float)y; + fw = (float)w; + fh = (float)h; - v[0].x = v[3].x = (x*sdupx)/vid.width - 1; - v[2].x = v[1].x = (x*sdupx + w*sdupx)/vid.width - 1; - v[0].y = v[1].y = 1-(y*sdupy)/vid.height; - v[2].y = v[3].y = 1-(y*sdupy + h*sdupy)/vid.height; + if (!(color & V_NOSCALESTART)) + { + float dupx = (float)vid.dupx, dupy = (float)vid.dupy; + + if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT) + { + RGBA_t rgbaColour = V_GetColor(color); + FRGBAFloat clearColour; + clearColour.red = (float)rgbaColour.s.red / 255; + clearColour.green = (float)rgbaColour.s.green / 255; + clearColour.blue = (float)rgbaColour.s.blue / 255; + clearColour.alpha = 1; + HWD.pfnClearBuffer(true, false, &clearColour); + return; + } + + fx *= dupx; + fy *= dupy; + fw *= dupx; + fh *= dupy; + + if (vid.width != BASEVIDWIDTH * vid.dupx) + { + if (color & V_SNAPTORIGHT) + fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)); + else if (!(color & V_SNAPTOLEFT)) + fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 2; + } + if (vid.height != BASEVIDHEIGHT * dupy) + { + // same thing here + if (color & V_SNAPTOBOTTOM) + fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)); + else if (!(color & V_SNAPTOTOP)) + fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 2; + } + } + + if (fx >= vid.width || fy >= vid.height) + return; + if (fx < 0) + { + fw += fx; + fx = 0; + } + if (fy < 0) + { + fh += fy; + fy = 0; + } + + if (fw <= 0 || fh <= 0) + return; + if (fx + fw > vid.width) + fw = (float)vid.width - fx; + if (fy + fh > vid.height) + fh = (float)vid.height - fy; + + fx = -1 + fx / (vid.width / 2); + fy = 1 - fy / (vid.height / 2); + fw = fw / (vid.width / 2); + fh = fh / (vid.height / 2); + + v[0].x = v[3].x = fx; + v[2].x = v[1].x = fx + fw; + v[0].y = v[1].y = fy; + v[2].y = v[3].y = fy - fh; //Hurdler: do we still use this argb color? if not, we should remove it v[0].argb = v[1].argb = v[2].argb = v[3].argb = 0xff00ff00; //; diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index 7672f47c2..a5ac82001 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -79,6 +79,7 @@ EXPORT char *HWRAPI(GetRenderer) (void); #define SCREENVERTS 10 EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]); #endif +EXPORT void HWRAPI(FlushScreenTextures) (void); EXPORT void HWRAPI(StartScreenWipe) (void); EXPORT void HWRAPI(EndScreenWipe) (void); EXPORT void HWRAPI(DoScreenWipe) (float alpha); @@ -124,6 +125,7 @@ struct hwdriver_s #ifdef SHUFFLE PostImgRedraw pfnPostImgRedraw; #endif + FlushScreenTextures pfnFlushScreenTextures; StartScreenWipe pfnStartScreenWipe; EndScreenWipe pfnEndScreenWipe; DoScreenWipe pfnDoScreenWipe; diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index 94eef1d3e..fea06caff 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -68,6 +68,7 @@ typedef struct gr_vissprite_s struct gr_vissprite_s *prev; struct gr_vissprite_s *next; float x1, x2; + float z1, z2; float tz, ty; lumpnum_t patchlumpnum; boolean flip; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 05391f4d0..a5fe6b673 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -117,7 +117,7 @@ consvar_t cv_grfiltermode = {"gr_filtermode", "Nearest", CV_CALL, grfiltermode_c consvar_t cv_granisotropicmode = {"gr_anisotropicmode", "1", CV_CALL, granisotropicmode_cons_t, CV_anisotropic_ONChange, 0, NULL, NULL, 0, 0, NULL}; //static consvar_t cv_grzbuffer = {"gr_zbuffer", "On", 0, CV_OnOff}; -consvar_t cv_grcorrecttricks = {"gr_correcttricks", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_grcorrecttricks = {"gr_correcttricks", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grsolvetjoin = {"gr_solvetjoin", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; static void CV_FogDensity_ONChange(void) @@ -489,10 +489,10 @@ UINT32 HWR_Lighting(INT32 light, UINT32 color, UINT32 fadecolor, boolean fogbloc } -static UINT8 HWR_FogBlockAlpha(INT32 light, UINT32 color, UINT32 fadecolor) // Let's see if this can work +static UINT8 HWR_FogBlockAlpha(INT32 light, UINT32 color) // Let's see if this can work { - RGBA_t realcolor, fogcolor, surfcolor; - INT32 alpha, fogalpha; + RGBA_t realcolor, surfcolor; + INT32 alpha; // Don't go out of bounds if (light < 0) @@ -501,13 +501,11 @@ static UINT8 HWR_FogBlockAlpha(INT32 light, UINT32 color, UINT32 fadecolor) // L light = 255; realcolor.rgba = color; - fogcolor.rgba = fadecolor; alpha = (realcolor.s.alpha*255)/25; - fogalpha = (fogcolor.s.alpha*255)/25; - // Fog blocks seem to get slightly more opaque with more opaque colourmap opacity, and much more opaque with darker brightness - surfcolor.s.alpha = (UINT8)(CALCLIGHT(light, ((0xFF-light)+alpha)/2)+CALCLIGHT(0xFF-light, ((light)+fogalpha)/2)); + // at 255 brightness, alpha is between 0 and 127, at 0 brightness alpha will always be 255 + surfcolor.s.alpha = (alpha*light)/(2*256)+255-light; return surfcolor.s.alpha; } @@ -773,10 +771,10 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, true); } - if (PolyFlags & PF_Translucent) + if (PolyFlags & (PF_Translucent|PF_Fog)) { Surf.FlatColor.s.alpha = (UINT8)alpha; - PolyFlags |= PF_Modulated|PF_Occlude|PF_Clip; + PolyFlags |= PF_Modulated|PF_Clip; } else PolyFlags |= PF_Masked|PF_Modulated|PF_Clip; @@ -1067,12 +1065,11 @@ static float HWR_ClipViewSegment(INT32 x, polyvertex_t *v1, polyvertex_t *v2) // // HWR_SplitWall // -static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, FSurfaceInfo* Surf, UINT32 cutflag) +static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, FSurfaceInfo* Surf, UINT32 cutflag, ffloor_t *pfloor) { /* SoM: split up and light walls according to the lightlist. This may also include leaving out parts of the wall that can't be seen */ - GLTexture_t * glTex; float realtop, realbot, top, bot; float pegt, pegb, pegmul; @@ -1095,8 +1092,8 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, INT32 solid, i; lightlist_t * list = sector->lightlist; const UINT8 alpha = Surf->FlatColor.s.alpha; - FUINT lightnum; - extracolormap_t *colormap; + FUINT lightnum = sector->lightlevel; + extracolormap_t *colormap = NULL; realtop = top = wallVerts[3].y; realbot = bot = wallVerts[0].y; @@ -1112,7 +1109,7 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, endpegmul = (endpegb - endpegt) / (endtop - endbot); #endif - for (i = 1; i < sector->numlights; i++) + for (i = 0; i < sector->numlights; i++) { #ifdef ESLOPE if (endtop < endrealbot) @@ -1120,35 +1117,38 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, if (top < realbot) return; - //Hurdler: fix a crashing bug, but is it correct? -// if (!list[i].caster) -// continue; + // There's a compiler warning here if this comment isn't here because of indentation + if (!(list[i].flags & FF_NOSHADE)) + { + if (pfloor && (pfloor->flags & FF_FOG)) + { + lightnum = pfloor->master->frontsector->lightlevel; + colormap = pfloor->master->frontsector->extra_colormap; + } + else + { + lightnum = *list[i].lightlevel; + colormap = list[i].extra_colormap; + } + } solid = false; - if (list[i].caster) + if ((sector->lightlist[i].flags & FF_CUTSOLIDS) && !(cutflag & FF_EXTRA)) + solid = true; + else if ((sector->lightlist[i].flags & FF_CUTEXTRA) && (cutflag & FF_EXTRA)) { - if (sector->lightlist[i].caster->flags & FF_CUTSOLIDS && !(cutflag & FF_EXTRA)) - solid = true; - else if (sector->lightlist[i].caster->flags & FF_CUTEXTRA && cutflag & FF_EXTRA) + if (sector->lightlist[i].flags & FF_EXTRA) { - if (sector->lightlist[i].caster->flags & FF_EXTRA) - { - if (sector->lightlist[i].caster->flags == cutflag) // Only merge with your own types - solid = true; - } - else + if ((sector->lightlist[i].flags & (FF_FOG|FF_SWIMMABLE)) == (cutflag & (FF_FOG|FF_SWIMMABLE))) // Only merge with your own types solid = true; } else - solid = false; + solid = true; } else solid = false; - if (cutflag == FF_CUTSOLIDS) // These are regular walls sent in from StoreWallRange, they shouldn't be cut from this - solid = false; - #ifdef ESLOPE if (list[i].slope) { @@ -1188,34 +1188,55 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, if (solid && endtop > endbheight) endtop = endbheight; #endif - continue; } +#ifdef ESLOPE + if (i + 1 < sector->numlights) + { + if (list[i+1].slope) + { + temp = P_GetZAt(list[i+1].slope, v1x, v1y); + bheight = FIXED_TO_FLOAT(temp); + temp = P_GetZAt(list[i+1].slope, v2x, v2y); + endbheight = FIXED_TO_FLOAT(temp); + } + else + bheight = endbheight = FIXED_TO_FLOAT(list[i+1].height); + } + else + { + bheight = realbot; + endbheight = endrealbot; + } +#else + if (i + 1 < sector->numlights) + { + bheight = FIXED_TO_FLOAT(list[i+1].height); + } + else + { + bheight = realbot; + } +#endif + +#ifdef ESLOPE + if (endbheight >= endtop) +#endif + if (bheight >= top) + continue; + //Found a break; - bot = height; + bot = bheight; if (bot < realbot) bot = realbot; #ifdef ESLOPE - endbot = endheight; + endbot = endbheight; if (endbot < endrealbot) endbot = endrealbot; #endif - - // colormap test - if (list[i-1].caster) - { - lightnum = *list[i-1].lightlevel; - colormap = list[i-1].extra_colormap; - } - else - { - lightnum = sector->lightlevel; - colormap = sector->extra_colormap; - } - Surf->FlatColor.s.alpha = alpha; #ifdef ESLOPE @@ -1238,23 +1259,16 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, wallVerts[0].y = wallVerts[1].y = bot; #endif - glTex = HWR_GetTexture(texnum); - if (cutflag & FF_TRANSLUCENT) + if (cutflag & FF_FOG) + HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Fog|PF_NoTexture, true, lightnum, colormap); + else if (cutflag & FF_TRANSLUCENT) HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Translucent, false, lightnum, colormap); - else if (glTex->mipmap.flags & TF_TRANSPARENT) - HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Environment, false, lightnum, colormap); else HWR_ProjectWall(wallVerts, Surf, PF_Masked, lightnum, colormap); - if (solid) - top = bheight; - else - top = height; + top = bot; #ifdef ESLOPE - if (solid) - endtop = endbheight; - else - endtop = endheight; + endtop = endbot; #endif } @@ -1266,17 +1280,7 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, if (top <= realbot) return; - if (list[i-1].caster) - { - lightnum = *list[i-1].lightlevel; - colormap = list[i-1].extra_colormap; - } - else - { - lightnum = sector->lightlevel; - colormap = sector->extra_colormap; - } - Surf->FlatColor.s.alpha = alpha; + Surf->FlatColor.s.alpha = alpha; #ifdef ESLOPE wallVerts[3].t = pegt + ((realtop - top) * pegmul); @@ -1298,119 +1302,14 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, wallVerts[0].y = wallVerts[1].y = bot; #endif - glTex = HWR_GetTexture(texnum); - if (cutflag & FF_TRANSLUCENT) + if (cutflag & FF_FOG) + HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Fog|PF_NoTexture, true, lightnum, colormap); + else if (cutflag & FF_TRANSLUCENT) HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Translucent, false, lightnum, colormap); - else if (glTex->mipmap.flags & TF_TRANSPARENT) - HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Environment, false, lightnum, colormap); else HWR_ProjectWall(wallVerts, Surf, PF_Masked, lightnum, colormap); } -// -// HWR_SplitFog -// Exclusively for fog -// -static void HWR_SplitFog(sector_t *sector, wallVert3D *wallVerts, FSurfaceInfo* Surf, UINT32 cutflag, FUINT lightnum, extracolormap_t *colormap) -{ - /* SoM: split up and light walls according to the - lightlist. This may also include leaving out parts - of the wall that can't be seen */ - float realtop, realbot, top, bot; - float pegt, pegb, pegmul; - float height = 0.0f, bheight = 0.0f; - INT32 solid, i; - lightlist_t * list = sector->lightlist; - const UINT8 alpha = Surf->FlatColor.s.alpha; - - realtop = top = wallVerts[2].y; - realbot = bot = wallVerts[0].y; - pegt = wallVerts[2].t; - pegb = wallVerts[0].t; - pegmul = (pegb - pegt) / (top - bot); - - for (i = 1; i < sector->numlights; i++) - { - if (top < realbot) - return; - - //Hurdler: fix a crashing bug, but is it correct? -// if (!list[i].caster) -// continue; - - solid = false; - - if (list[i].caster) - { - if (sector->lightlist[i].caster->flags & FF_FOG && cutflag & FF_FOG) // Only fog cuts fog - { - if (sector->lightlist[i].caster->flags & FF_EXTRA) - { - if (sector->lightlist[i].caster->flags == cutflag) // only cut by the same - solid = true; - } - else - solid = true; - } - } - - height = FIXED_TO_FLOAT(list[i].height); - - if (solid) - bheight = FIXED_TO_FLOAT(*list[i].caster->bottomheight); - - if (height >= top) - { - if (solid && top > bheight) - top = bheight; - continue; - } - - //Found a break; - bot = height; - - if (bot < realbot) - bot = realbot; - - { - - - - Surf->FlatColor.s.alpha = alpha; - } - - wallVerts[3].t = wallVerts[2].t = pegt + ((realtop - top) * pegmul); - wallVerts[0].t = wallVerts[1].t = pegt + ((realtop - bot) * pegmul); - - // set top/bottom coords - wallVerts[2].y = wallVerts[3].y = top; - wallVerts[0].y = wallVerts[1].y = bot; - - if (!solid) // Don't draw it if there's more fog behind it - HWR_AddTransparentWall(wallVerts, Surf, 0, PF_Translucent|PF_NoTexture, true, lightnum, colormap); - - top = height; - } - - bot = realbot; - if (top <= realbot) - return; - - { - - Surf->FlatColor.s.alpha = alpha; - } - - wallVerts[3].t = wallVerts[2].t = pegt + ((realtop - top) * pegmul); - wallVerts[0].t = wallVerts[1].t = pegt + ((realtop - bot) * pegmul); - - // set top/bottom coords - wallVerts[2].y = wallVerts[3].y = top; - wallVerts[0].y = wallVerts[1].y = bot; - - HWR_AddTransparentWall(wallVerts, Surf, 0, PF_Translucent|PF_NoTexture, true, lightnum, colormap); -} - // HWR_DrawSkyWalls // Draw walls into the depth buffer so that anything behind is culled properly static void HWR_DrawSkyWall(wallVert3D *wallVerts, FSurfaceInfo *Surf, fixed_t bottom, fixed_t top) @@ -1687,7 +1586,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) #endif if (gr_frontsector->numlights) - HWR_SplitWall(gr_frontsector, wallVerts, gr_toptexture, &Surf, FF_CUTSOLIDS); + HWR_SplitWall(gr_frontsector, wallVerts, gr_toptexture, &Surf, FF_CUTLEVEL, NULL); else if (grTex->mipmap.flags & TF_TRANSPARENT) HWR_AddTransparentWall(wallVerts, &Surf, gr_toptexture, PF_Environment, false, lightnum, colormap); else @@ -1770,7 +1669,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) #endif if (gr_frontsector->numlights) - HWR_SplitWall(gr_frontsector, wallVerts, gr_bottomtexture, &Surf, FF_CUTSOLIDS); + HWR_SplitWall(gr_frontsector, wallVerts, gr_bottomtexture, &Surf, FF_CUTLEVEL, NULL); else if (grTex->mipmap.flags & TF_TRANSPARENT) HWR_AddTransparentWall(wallVerts, &Surf, gr_bottomtexture, PF_Environment, false, lightnum, colormap); else @@ -2033,15 +1932,14 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) } #endif - if (grTex->mipmap.flags & TF_TRANSPARENT) - blendmode = PF_Translucent; - if (gr_frontsector->numlights) { if (!(blendmode & PF_Masked)) - HWR_SplitWall(gr_frontsector, wallVerts, gr_midtexture, &Surf, FF_TRANSLUCENT); + HWR_SplitWall(gr_frontsector, wallVerts, gr_midtexture, &Surf, FF_TRANSLUCENT, NULL); else - HWR_SplitWall(gr_frontsector, wallVerts, gr_midtexture, &Surf, FF_CUTSOLIDS); + { + HWR_SplitWall(gr_frontsector, wallVerts, gr_midtexture, &Surf, FF_CUTLEVEL, NULL); + } } else if (!(blendmode & PF_Masked)) HWR_AddTransparentWall(wallVerts, &Surf, gr_midtexture, blendmode, false, lightnum, colormap); @@ -2192,7 +2090,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) #endif // I don't think that solid walls can use translucent linedef types... if (gr_frontsector->numlights) - HWR_SplitWall(gr_frontsector, wallVerts, gr_midtexture, &Surf, FF_CUTSOLIDS); + HWR_SplitWall(gr_frontsector, wallVerts, gr_midtexture, &Surf, FF_CUTLEVEL, NULL); else { if (grTex->mipmap.flags & TF_TRANSPARENT) @@ -2314,7 +2212,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) { FBITFIELD blendmode; - blendmode = PF_Translucent|PF_NoTexture; + blendmode = PF_Fog|PF_NoTexture; lightnum = rover->master->frontsector->lightlevel; colormap = rover->master->frontsector->extra_colormap; @@ -2322,15 +2220,15 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) if (rover->master->frontsector->extra_colormap) { - Surf.FlatColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel,rover->master->frontsector->extra_colormap->rgba,rover->master->frontsector->extra_colormap->fadergba); + Surf.FlatColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel,rover->master->frontsector->extra_colormap->rgba); } else { - Surf.FlatColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel,NORMALFOG,FADEFOG); + Surf.FlatColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel,NORMALFOG); } if (gr_frontsector->numlights) - HWR_SplitFog(gr_frontsector, wallVerts, &Surf, rover->flags, lightnum, colormap); + HWR_SplitWall(gr_frontsector, wallVerts, 0, &Surf, rover->flags, rover); else HWR_AddTransparentWall(wallVerts, &Surf, 0, blendmode, true, lightnum, colormap); } @@ -2338,18 +2236,14 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) { FBITFIELD blendmode = PF_Masked; - if (rover->flags & FF_TRANSLUCENT) + if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) { blendmode = PF_Translucent; Surf.FlatColor.s.alpha = (UINT8)rover->alpha-1 > 255 ? 255 : rover->alpha-1; } - else if (grTex->mipmap.flags & TF_TRANSPARENT) - { - blendmode = PF_Environment; - } if (gr_frontsector->numlights) - HWR_SplitWall(gr_frontsector, wallVerts, texnum, &Surf, rover->flags); + HWR_SplitWall(gr_frontsector, wallVerts, texnum, &Surf, rover->flags, rover); else { if (blendmode != PF_Masked) @@ -2438,22 +2332,22 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) { FBITFIELD blendmode; - blendmode = PF_Translucent|PF_NoTexture; + blendmode = PF_Fog|PF_NoTexture; lightnum = rover->master->frontsector->lightlevel; colormap = rover->master->frontsector->extra_colormap; if (rover->master->frontsector->extra_colormap) { - Surf.FlatColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel,rover->master->frontsector->extra_colormap->rgba,rover->master->frontsector->extra_colormap->fadergba); + Surf.FlatColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel,rover->master->frontsector->extra_colormap->rgba); } else { - Surf.FlatColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel,NORMALFOG,FADEFOG); + Surf.FlatColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel,NORMALFOG); } if (gr_backsector->numlights) - HWR_SplitFog(gr_backsector, wallVerts, &Surf, rover->flags, lightnum, colormap); + HWR_SplitWall(gr_backsector, wallVerts, 0, &Surf, rover->flags, rover); else HWR_AddTransparentWall(wallVerts, &Surf, 0, blendmode, true, lightnum, colormap); } @@ -2461,18 +2355,14 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) { FBITFIELD blendmode = PF_Masked; - if (rover->flags & FF_TRANSLUCENT) + if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) { blendmode = PF_Translucent; Surf.FlatColor.s.alpha = (UINT8)rover->alpha-1 > 255 ? 255 : rover->alpha-1; } - else if (grTex->mipmap.flags & TF_TRANSPARENT) - { - blendmode = PF_Environment; - } if (gr_backsector->numlights) - HWR_SplitWall(gr_backsector, wallVerts, texnum, &Surf, rover->flags); + HWR_SplitWall(gr_backsector, wallVerts, texnum, &Surf, rover->flags, rover); else { if (blendmode != PF_Masked) @@ -2786,7 +2676,7 @@ static void HWR_AddLine(seg_t * line) angle_t span, tspan; // SoM: Backsector needs to be run through R_FakeFlat - sector_t tempsec; + static sector_t tempsec; if (line->polyseg && !(line->polyseg->flags & POF_RENDERSIDES)) return; @@ -3011,8 +2901,8 @@ static boolean HWR_CheckBBox(fixed_t *bspcoord) py2 = bspcoord[checkcoord[boxpos][3]]; // check clip list for an open space - angle1 = R_PointToAngle(px1, py1) - dup_viewangle; - angle2 = R_PointToAngle(px2, py2) - dup_viewangle; + angle1 = R_PointToAngle2(dup_viewx>>1, dup_viewy>>1, px1>>1, py1>>1) - dup_viewangle; + angle2 = R_PointToAngle2(dup_viewx>>1, dup_viewy>>1, px2>>1, py2>>1) - dup_viewangle; span = angle1 - angle2; @@ -3345,7 +3235,7 @@ static void HWR_Subsector(size_t num) INT16 count; seg_t *line; subsector_t *sub; - sector_t tempsec; //SoM: 4/7/2000 + static sector_t tempsec; //SoM: 4/7/2000 INT32 floorlightlevel; INT32 ceilinglightlevel; INT32 locFloorHeight, locCeilingHeight; @@ -3528,8 +3418,6 @@ static void HWR_Subsector(size_t num) { /// \todo fix light, xoffs, yoffs, extracolormap ? ffloor_t * rover; - - R_Prep3DFloors(gr_frontsector); for (rover = gr_frontsector->ffloors; rover; rover = rover->next) { @@ -3563,19 +3451,19 @@ static void HWR_Subsector(size_t num) light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); if (rover->master->frontsector->extra_colormap) - alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap->rgba, rover->master->frontsector->extra_colormap->fadergba); + alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap->rgba); else - alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG, FADEFOG); + alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG); HWR_AddTransparentFloor(0, &extrasubsectors[num], false, *rover->bottomheight, *gr_frontsector->lightlist[light].lightlevel, - alpha, rover->master->frontsector, PF_Translucent|PF_NoTexture, + alpha, rover->master->frontsector, PF_Fog|PF_NoTexture, true, rover->master->frontsector->extra_colormap); } - else if (rover->flags & FF_TRANSLUCENT) // SoM: Flags are more efficient + else if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) // SoM: Flags are more efficient { light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); #ifndef SORTING @@ -3626,19 +3514,19 @@ static void HWR_Subsector(size_t num) light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); if (rover->master->frontsector->extra_colormap) - alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap->rgba, rover->master->frontsector->extra_colormap->fadergba); + alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap->rgba); else - alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG, FADEFOG); + alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG); HWR_AddTransparentFloor(0, &extrasubsectors[num], true, *rover->topheight, *gr_frontsector->lightlist[light].lightlevel, - alpha, rover->master->frontsector, PF_Translucent|PF_NoTexture, + alpha, rover->master->frontsector, PF_Fog|PF_NoTexture, true, rover->master->frontsector->extra_colormap); } - else if (rover->flags & FF_TRANSLUCENT) + else if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) { light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); #ifndef SORTING @@ -4040,12 +3928,10 @@ static boolean HWR_DoCulling(line_t *cullheight, line_t *viewcullheight, float v static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float this_scale) { - UINT8 i; - float tr_x, tr_y; - FOutVector *wv; FOutVector swallVerts[4]; FSurfaceInfo sSurf; fixed_t floorheight, mobjfloor; + float offset = 0; mobjfloor = HWR_OpaqueFloorAtPos( spr->mobj->x, spr->mobj->y, @@ -4084,6 +3970,8 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t } floorheight = FixedInt(spr->mobj->z - floorheight); + + offset = floorheight; } else floorheight = FixedInt(spr->mobj->z - mobjfloor); @@ -4096,47 +3984,42 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t // 0--1 // x1/x2 were already scaled in HWR_ProjectSprite + // First match the normal sprite swallVerts[0].x = swallVerts[3].x = spr->x1; swallVerts[2].x = swallVerts[1].x = spr->x2; + swallVerts[0].z = swallVerts[3].z = spr->z1; + swallVerts[2].z = swallVerts[1].z = spr->z2; if (spr->mobj && this_scale != 1.0f) { // Always a pixel above the floor, perfectly flat. swallVerts[0].y = swallVerts[1].y = swallVerts[2].y = swallVerts[3].y = spr->ty - gpatch->topoffset * this_scale - (floorheight+3); - swallVerts[0].z = swallVerts[1].z = spr->tz - (gpatch->height-gpatch->topoffset) * this_scale; - swallVerts[2].z = swallVerts[3].z = spr->tz + gpatch->topoffset * this_scale; + // Now transform the TOP vertices along the floor in the direction of the camera + swallVerts[3].x = spr->x1 + ((gpatch->height * this_scale) + offset) * gr_viewcos; + swallVerts[2].x = spr->x2 + ((gpatch->height * this_scale) + offset) * gr_viewcos; + swallVerts[3].z = spr->z1 + ((gpatch->height * this_scale) + offset) * gr_viewsin; + swallVerts[2].z = spr->z2 + ((gpatch->height * this_scale) + offset) * gr_viewsin; } else { // Always a pixel above the floor, perfectly flat. swallVerts[0].y = swallVerts[1].y = swallVerts[2].y = swallVerts[3].y = spr->ty - gpatch->topoffset - (floorheight+3); - // Spread out top away from the camera. (Fixme: Make it always move out in the same direction!... somehow.) - swallVerts[0].z = swallVerts[1].z = spr->tz - (gpatch->height-gpatch->topoffset); - swallVerts[2].z = swallVerts[3].z = spr->tz + gpatch->topoffset; + // Now transform the TOP vertices along the floor in the direction of the camera + swallVerts[3].x = spr->x1 + (gpatch->height + offset) * gr_viewcos; + swallVerts[2].x = spr->x2 + (gpatch->height + offset) * gr_viewcos; + swallVerts[3].z = spr->z1 + (gpatch->height + offset) * gr_viewsin; + swallVerts[2].z = spr->z2 + (gpatch->height + offset) * gr_viewsin; } - // transform - wv = swallVerts; - - for (i = 0; i < 4; i++,wv++) + // We also need to move the bottom ones away when shadowoffs is on + if (cv_shadowoffs.value) { - // Offset away from the camera based on height from floor. - if (cv_shadowoffs.value) - wv->z += floorheight; - wv->z += 3; - - //look up/down ----TOTAL SUCKS!!!--- do the 2 in one!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - tr_x = wv->z; - tr_y = wv->y; - wv->y = (tr_x * gr_viewludcos) + (tr_y * gr_viewludsin); - wv->z = (tr_x * gr_viewludsin) - (tr_y * gr_viewludcos); - // ---------------------- mega lame test ---------------------------------- - - //scale y before frustum so that frustum can be scaled to screen height - wv->y *= ORIGINAL_ASPECT * gr_fovlud; - wv->x *= gr_fovlud; + swallVerts[0].x = spr->x1 + offset * gr_viewcos; + swallVerts[1].x = spr->x2 + offset * gr_viewcos; + swallVerts[0].z = spr->z1 + offset * gr_viewsin; + swallVerts[1].z = spr->z2 + offset * gr_viewsin; } if (spr->flip) @@ -4216,6 +4099,291 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t } } +static void HWR_SplitSprite(gr_vissprite_t *spr) +{ + float this_scale = 1.0f; + FOutVector wallVerts[4]; + GLPatch_t *gpatch; + FSurfaceInfo Surf; + const boolean hires = (spr->mobj && spr->mobj->skin && ((skin_t *)spr->mobj->skin)->flags & SF_HIRES); + extracolormap_t *colormap; + FUINT lightlevel; + FBITFIELD blend = 0; + UINT8 alpha; + + INT32 i; + float realtop, realbot, top, bot; + float towtop, towbot, towmult; + float bheight; + const sector_t *sector = spr->mobj->subsector->sector; + const lightlist_t *list = sector->lightlist; +#ifdef ESLOPE + float endrealtop, endrealbot, endtop, endbot; + float endbheight; + fixed_t temp; + fixed_t v1x, v1y, v2x, v2y; +#endif + + this_scale = FIXED_TO_FLOAT(spr->mobj->scale); + + if (hires) + this_scale = this_scale * FIXED_TO_FLOAT(((skin_t *)spr->mobj->skin)->highresscale); + + gpatch = W_CachePatchNum(spr->patchlumpnum, PU_CACHE); + + // cache the patch in the graphics card memory + //12/12/99: Hurdler: same comment as above (for md2) + //Hurdler: 25/04/2000: now support colormap in hardware mode + HWR_GetMappedPatch(gpatch, spr->colormap); + + // Draw shadow BEFORE sprite + if (cv_shadow.value // Shadows enabled + && (spr->mobj->flags & (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY)) != (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY) // Ceiling scenery have no shadow. + && !(spr->mobj->flags2 & MF2_DEBRIS) // Debris have no corona or shadow. +#ifdef ALAM_LIGHTING + && !(t_lspr[spr->mobj->sprite]->type // Things with dynamic lights have no shadow. + && (!spr->mobj->player || spr->mobj->player->powers[pw_super])) // Except for non-super players. +#endif + && (spr->mobj->z >= spr->mobj->floorz)) // Without this, your shadow shows on the floor, even after you die and fall through the ground. + { + //////////////////// + // SHADOW SPRITE! // + //////////////////// + HWR_DrawSpriteShadow(spr, gpatch, this_scale); + } + + wallVerts[0].x = wallVerts[3].x = spr->x1; + wallVerts[2].x = wallVerts[1].x = spr->x2; + wallVerts[0].z = wallVerts[3].z = spr->z1; + wallVerts[1].z = wallVerts[2].z = spr->z2; + + wallVerts[2].y = wallVerts[3].y = spr->ty; + if (spr->mobj && this_scale != 1.0f) + wallVerts[0].y = wallVerts[1].y = spr->ty - gpatch->height * this_scale; + else + wallVerts[0].y = wallVerts[1].y = spr->ty - gpatch->height; + + v1x = FLOAT_TO_FIXED(spr->x1); + v1y = FLOAT_TO_FIXED(spr->z1); + v2x = FLOAT_TO_FIXED(spr->x2); + v2y = FLOAT_TO_FIXED(spr->z2); + + if (spr->flip) + { + wallVerts[0].sow = wallVerts[3].sow = gpatch->max_s; + wallVerts[2].sow = wallVerts[1].sow = 0; + }else{ + wallVerts[0].sow = wallVerts[3].sow = 0; + wallVerts[2].sow = wallVerts[1].sow = gpatch->max_s; + } + + // flip the texture coords (look familiar?) + if (spr->vflip) + { + wallVerts[3].tow = wallVerts[2].tow = gpatch->max_t; + wallVerts[0].tow = wallVerts[1].tow = 0; + }else{ + wallVerts[3].tow = wallVerts[2].tow = 0; + wallVerts[0].tow = wallVerts[1].tow = gpatch->max_t; + } + + realtop = top = wallVerts[3].y; + realbot = bot = wallVerts[0].y; + towtop = wallVerts[3].tow; + towbot = wallVerts[0].tow; + towmult = (towbot - towtop) / (top - bot); + +#ifdef ESLOPE + endrealtop = endtop = wallVerts[2].y; + endrealbot = endbot = wallVerts[1].y; +#endif + + if (!cv_translucency.value) // translucency disabled + { + Surf.FlatColor.s.alpha = 0xFF; + blend = PF_Translucent|PF_Occlude; + } + else if (spr->mobj->flags2 & MF2_SHADOW) + { + Surf.FlatColor.s.alpha = 0x40; + blend = PF_Translucent; + } + else if (spr->mobj->frame & FF_TRANSMASK) + blend = HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf); + else + { + // BP: i agree that is little better in environement but it don't + // work properly under glide nor with fogcolor to ffffff :( + // Hurdler: PF_Environement would be cool, but we need to fix + // the issue with the fog before + Surf.FlatColor.s.alpha = 0xFF; + blend = PF_Translucent|PF_Occlude; + } + + alpha = Surf.FlatColor.s.alpha; + + // Start with the lightlevel and colormap from the top of the sprite + lightlevel = *list[sector->numlights - 1].lightlevel; + colormap = list[sector->numlights - 1].extra_colormap; + i = 0; + temp = FLOAT_TO_FIXED(realtop); + + if (spr->mobj->frame & FF_FULLBRIGHT) + lightlevel = 255; + +#ifdef ESLOPE + for (i = 1; i < sector->numlights; i++) + { + fixed_t h = sector->lightlist[i].slope ? P_GetZAt(sector->lightlist[i].slope, spr->mobj->x, spr->mobj->y) + : sector->lightlist[i].height; + if (h <= temp) + { + if (!(spr->mobj->frame & FF_FULLBRIGHT)) + lightlevel = *list[i-1].lightlevel; + colormap = list[i-1].extra_colormap; + break; + } + } +#else + i = R_GetPlaneLight(sector, temp, false); + if (!(spr->mobj->frame & FF_FULLBRIGHT)) + lightlevel = *list[i].lightlevel; + colormap = list[i].extra_colormap; +#endif + + for (i = 0; i < sector->numlights; i++) + { +#ifdef ESLOPE + if (endtop < endrealbot) +#endif + if (top < realbot) + return; + + // even if we aren't changing colormap or lightlevel, we still need to continue drawing down the sprite + if (!(list[i].flags & FF_NOSHADE) && (list[i].flags & FF_CUTSPRITES)) + { + if (!(spr->mobj->frame & FF_FULLBRIGHT)) + lightlevel = *list[i].lightlevel; + colormap = list[i].extra_colormap; + } + +#ifdef ESLOPE + if (i + 1 < sector->numlights) + { + if (list[i+1].slope) + { + temp = P_GetZAt(list[i+1].slope, v1x, v1y); + bheight = FIXED_TO_FLOAT(temp); + temp = P_GetZAt(list[i+1].slope, v2x, v2y); + endbheight = FIXED_TO_FLOAT(temp); + } + else + bheight = endbheight = FIXED_TO_FLOAT(list[i+1].height); + } + else + { + bheight = realbot; + endbheight = endrealbot; + } +#else + if (i + 1 < sector->numlights) + { + bheight = FIXED_TO_FLOAT(list[i+1].height); + } + else + { + bheight = realbot; + } +#endif + +#ifdef ESLOPE + if (endbheight >= endtop) +#endif + if (bheight >= top) + continue; + + bot = bheight; + + if (bot < realbot) + bot = realbot; + +#ifdef ESLOPE + endbot = endbheight; + + if (endbot < endrealbot) + endbot = endrealbot; +#endif + +#ifdef ESLOPE + wallVerts[3].tow = towtop + ((realtop - top) * towmult); + wallVerts[2].tow = towtop + ((endrealtop - endtop) * towmult); + wallVerts[0].tow = towtop + ((realtop - bot) * towmult); + wallVerts[1].tow = towtop + ((endrealtop - endbot) * towmult); + + wallVerts[3].y = top; + wallVerts[2].y = endtop; + wallVerts[0].y = bot; + wallVerts[1].y = endbot; +#else + wallVerts[3].tow = wallVerts[2].tow = towtop + ((realtop - top) * towmult); + wallVerts[0].tow = wallVerts[1].tow = towtop + ((realtop - bot) * towmult); + + wallVerts[2].y = wallVerts[3].y = top; + wallVerts[0].y = wallVerts[1].y = bot; +#endif + + if (colormap) + Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false); + else + Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false); + + Surf.FlatColor.s.alpha = alpha; + + HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip); + + top = bot; +#ifdef ESLOPE + endtop = endbot; +#endif + } + + bot = realbot; +#ifdef ESLOPE + endbot = endrealbot; + if (endtop <= endrealbot) +#endif + if (top <= realbot) + return; + + // If we're ever down here, somehow the above loop hasn't draw all the light levels of sprite +#ifdef ESLOPE + wallVerts[3].tow = towtop + ((realtop - top) * towmult); + wallVerts[2].tow = towtop + ((endrealtop - endtop) * towmult); + wallVerts[0].tow = towtop + ((realtop - bot) * towmult); + wallVerts[1].tow = towtop + ((endrealtop - endbot) * towmult); + + wallVerts[3].y = top; + wallVerts[2].y = endtop; + wallVerts[0].y = bot; + wallVerts[1].y = endbot; +#else + wallVerts[3].tow = wallVerts[2].tow = towtop + ((realtop - top) * towmult); + wallVerts[0].tow = wallVerts[1].tow = towtop + ((realtop - bot) * towmult); + + wallVerts[2].y = wallVerts[3].y = top; + wallVerts[0].y = wallVerts[1].y = bot; +#endif + + if (colormap) + Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false); + else + Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false); + + Surf.FlatColor.s.alpha = alpha; + + HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip); +} + // -----------------+ // HWR_DrawSprite : Draw flat sprites // : (monsters, bonuses, weapons, lights, ...) @@ -4223,10 +4391,8 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t // -----------------+ static void HWR_DrawSprite(gr_vissprite_t *spr) { - UINT8 i; - float tr_x, tr_y, this_scale = 1.0f; + float this_scale = 1.0f; FOutVector wallVerts[4]; - FOutVector *wv; GLPatch_t *gpatch; // sprite patch converted to hardware FSurfaceInfo Surf; const boolean hires = (spr->mobj && spr->mobj->skin && ((skin_t *)spr->mobj->skin)->flags & SF_HIRES); @@ -4241,6 +4407,12 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) if (!spr->mobj->subsector) return; + if (spr->mobj->subsector->sector->numlights) + { + HWR_SplitSprite(spr); + return; + } + // cache sprite graphics //12/12/99: Hurdler: // OK, I don't change anything for MD2 support because I want to be @@ -4273,24 +4445,8 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) // make a wall polygon (with 2 triangles), using the floor/ceiling heights, // and the 2d map coords of start/end vertices - wallVerts[0].z = wallVerts[1].z = wallVerts[2].z = wallVerts[3].z = spr->tz; - - // transform - wv = wallVerts; - - for (i = 0; i < 4; i++,wv++) - { - //look up/down ----TOTAL SUCKS!!!--- do the 2 in one!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - tr_x = wv->z; - tr_y = wv->y; - wv->y = (tr_x * gr_viewludcos) + (tr_y * gr_viewludsin); - wv->z = (tr_x * gr_viewludsin) - (tr_y * gr_viewludcos); - // ---------------------- mega lame test ---------------------------------- - - //scale y before frustum so that frustum can be scaled to screen height - wv->y *= ORIGINAL_ASPECT * gr_fovlud; - wv->x *= gr_fovlud; - } + wallVerts[0].z = wallVerts[3].z = spr->z1; + wallVerts[1].z = wallVerts[2].z = spr->z2; if (spr->flip) { @@ -4342,26 +4498,8 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) UINT8 lightlevel = 255; extracolormap_t *colormap = sector->extra_colormap; - if (sector->numlights) - { - INT32 light; - - light = R_GetPlaneLight(sector, spr->mobj->z + spr->mobj->height, false); // Always use the light at the top instead of whatever I was doing before - - if (!(spr->mobj->frame & FF_FULLBRIGHT)) - lightlevel = *sector->lightlist[light].lightlevel; - - if (sector->lightlist[light].extra_colormap) - colormap = sector->lightlist[light].extra_colormap; - } - else - { - if (!(spr->mobj->frame & FF_FULLBRIGHT)) - lightlevel = sector->lightlevel; - - if (sector->extra_colormap) - colormap = sector->extra_colormap; - } + if (!(spr->mobj->frame & FF_FULLBRIGHT)) + lightlevel = sector->lightlevel; if (colormap) Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false); @@ -4401,11 +4539,8 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) // Sprite drawer for precipitation static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) { - UINT8 i; FBITFIELD blend = 0; - float tr_x, tr_y; FOutVector wallVerts[4]; - FOutVector *wv; GLPatch_t *gpatch; // sprite patch converted to hardware FSurfaceInfo Surf; @@ -4431,24 +4566,8 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) // make a wall polygon (with 2 triangles), using the floor/ceiling heights, // and the 2d map coords of start/end vertices - wallVerts[0].z = wallVerts[1].z = wallVerts[2].z = wallVerts[3].z = spr->tz; - - // transform - wv = wallVerts; - - for (i = 0; i < 4; i++, wv++) - { - //look up/down ----TOTAL SUCKS!!!--- do the 2 in one!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - tr_x = wv->z; - tr_y = wv->y; - wv->y = (tr_x * gr_viewludcos) + (tr_y * gr_viewludsin); - wv->z = (tr_x * gr_viewludsin) - (tr_y * gr_viewludcos); - // ---------------------- mega lame test ---------------------------------- - - //scale y before frustum so that frustum can be scaled to screen height - wv->y *= ORIGINAL_ASPECT * gr_fovlud; - wv->x *= gr_fovlud; - } + wallVerts[0].z = wallVerts[3].z = spr->z1; + wallVerts[1].z = wallVerts[2].z = spr->z2; wallVerts[0].sow = wallVerts[3].sow = 0; wallVerts[2].sow = wallVerts[1].sow = gpatch->max_s; @@ -4581,6 +4700,33 @@ static void HWR_SortVisSprites(void) gr_vsprsortedhead.prev->next = best; gr_vsprsortedhead.prev = best; } + + // Sryder: Oh boy, while it's nice having ALL the sprites sorted properly, it fails when we bring MD2's into the + // mix and they want to be translucent. So let's place all the translucent sprites and MD2's AFTER + // everything else, but still ordered of course, the depth buffer can handle the opaque ones plenty fine. + // We just need to move all translucent ones to the end in order + // TODO: Fully sort all sprites and MD2s with walls and floors, this part will be unnecessary after that + best = gr_vsprsortedhead.next; + for (i = 0; i < gr_visspritecount; i++) + { + if ((best->mobj->flags2 & MF2_SHADOW) || (best->mobj->frame & FF_TRANSMASK)) + { + if (best == gr_vsprsortedhead.next) + { + gr_vsprsortedhead.next = best->next; + } + best->prev->next = best->next; + best->next->prev = best->prev; + best->prev = gr_vsprsortedhead.prev; + gr_vsprsortedhead.prev->next = best; + gr_vsprsortedhead.prev = best; + ds = best; + best = best->next; + ds->next = &gr_vsprsortedhead; + } + else + best = best->next; + } } // A drawnode is something that points to a 3D floor, 3D side, or masked @@ -4914,6 +5060,7 @@ static void HWR_CreateDrawNodes(void) // Draw all vissprites // -------------------------------------------------------------------------- #ifdef SORTING +// added the stransform so they can be switched as drawing happenes so MD2s and sprites are sorted correctly with each other static void HWR_DrawSprites(void) { if (gr_visspritecount > 0) @@ -4934,44 +5081,20 @@ static void HWR_DrawSprites(void) { if (!cv_grmd2.value || md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f) HWR_DrawSprite(spr); - } - else if (!cv_grmd2.value || md2_models[spr->mobj->sprite].notfound || md2_models[spr->mobj->sprite].scale < 0.0f) - HWR_DrawSprite(spr); - } - } -} -#endif -// -------------------------------------------------------------------------- -// Draw all MD2 -// -------------------------------------------------------------------------- -static void HWR_DrawMD2S(void) -{ - if (gr_visspritecount > 0) - { - gr_vissprite_t *spr; - - // draw all MD2 back to front - for (spr = gr_vsprsortedhead.next; - spr != &gr_vsprsortedhead; - spr = spr->next) - { -#ifdef HWPRECIP - if (!spr->precip) - { -#endif - if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) - { - if (md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound == false && md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale > 0.0f) + else + HWR_DrawMD2(spr); + } + else + { + if (!cv_grmd2.value || md2_models[spr->mobj->sprite].notfound || md2_models[spr->mobj->sprite].scale < 0.0f) + HWR_DrawSprite(spr); + else HWR_DrawMD2(spr); } - else if (md2_models[spr->mobj->sprite].notfound == false && md2_models[spr->mobj->sprite].scale > 0.0f) - HWR_DrawMD2(spr); -#ifdef HWPRECIP - } -#endif } } } +#endif // -------------------------------------------------------------------------- // HWR_AddSprites @@ -5056,8 +5179,10 @@ static void HWR_ProjectSprite(mobj_t *thing) { gr_vissprite_t *vis; float tr_x, tr_y; - float tx, tz; + float tz; float x1, x2; + float z1, z2; + float rightsin, rightcos; float this_scale; float gz, gzt; spritedef_t *sprdef; @@ -5084,7 +5209,9 @@ static void HWR_ProjectSprite(mobj_t *thing) if (tz < ZCLIP_PLANE && (!cv_grmd2.value || md2_models[thing->sprite].notfound == true)) //Yellow: Only MD2's dont disappear return; - tx = (tr_x * gr_viewsin) - (tr_y * gr_viewcos); + // The above can stay as it works for cutting sprites that are too close + tr_x = FIXED_TO_FLOAT(thing->x); + tr_y = FIXED_TO_FLOAT(thing->y); // decide which patch to use for sprite relative to player #ifdef RANGECHECK @@ -5139,23 +5266,23 @@ static void HWR_ProjectSprite(mobj_t *thing) if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES) this_scale = this_scale * FIXED_TO_FLOAT(((skin_t *)thing->skin)->highresscale); - // calculate edges of the shape + rightsin = FIXED_TO_FLOAT(FINESINE((viewangle + ANGLE_90)>>ANGLETOFINESHIFT)); + rightcos = FIXED_TO_FLOAT(FINECOSINE((viewangle + ANGLE_90)>>ANGLETOFINESHIFT)); if (flip) - tx -= FIXED_TO_FLOAT(spritecachedinfo[lumpoff].width - spritecachedinfo[lumpoff].offset) * this_scale; + { + x1 = (FIXED_TO_FLOAT(spritecachedinfo[lumpoff].width - spritecachedinfo[lumpoff].offset) * this_scale); + x2 = (FIXED_TO_FLOAT(spritecachedinfo[lumpoff].offset) * this_scale); + } else - tx -= FIXED_TO_FLOAT(spritecachedinfo[lumpoff].offset) * this_scale; + { + x1 = (FIXED_TO_FLOAT(spritecachedinfo[lumpoff].offset) * this_scale); + x2 = (FIXED_TO_FLOAT(spritecachedinfo[lumpoff].width - spritecachedinfo[lumpoff].offset) * this_scale); + } - // project x - x1 = gr_windowcenterx + (tx * gr_centerx / tz); - - //faB : tr_x doesnt matter - // hurdler: it's used in cliptosolidsegs - tr_x = x1; - - x1 = tx; - - tx += FIXED_TO_FLOAT(spritecachedinfo[lumpoff].width) * this_scale; - x2 = gr_windowcenterx + (tx * gr_centerx / tz); + z1 = tr_y + x1 * rightsin; + z2 = tr_y - x2 * rightsin; + x1 = tr_x + x1 * rightcos; + x2 = tr_x - x2 * rightcos; if (thing->eflags & MFE_VERTICALFLIP) { @@ -5192,13 +5319,10 @@ static void HWR_ProjectSprite(mobj_t *thing) // store information in a vissprite vis = HWR_NewVisSprite(); vis->x1 = x1; -#if 0 vis->x2 = x2; -#else - (void)x2; -#endif - vis->x2 = tx; - vis->tz = tz; + vis->z1 = z1; + vis->z2 = z2; + vis->tz = tz; // Keep tz for the simple sprite sorting that happens vis->dispoffset = thing->info->dispoffset; // Monster Iestyn: 23/11/15: HARDWARE SUPPORT AT LAST vis->patchlumpnum = sprframe->lumppat[rot]; vis->flip = flip; @@ -5229,7 +5353,7 @@ static void HWR_ProjectSprite(mobj_t *thing) vis->colormap = colormaps; // set top/bottom coords - vis->ty = gzt - gr_viewz; + vis->ty = gzt; //CONS_Debug(DBG_RENDER, "------------------\nH: sprite : %d\nH: frame : %x\nH: type : %d\nH: sname : %s\n\n", // thing->sprite, thing->frame, thing->type, sprnames[thing->sprite]); @@ -5248,8 +5372,10 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) { gr_vissprite_t *vis; float tr_x, tr_y; - float tx, tz; + float tz; float x1, x2; + float z1, z2; + float rightsin, rightcos; spritedef_t *sprdef; spriteframe_t *sprframe; size_t lumpoff; @@ -5267,7 +5393,8 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) if (tz < ZCLIP_PLANE) return; - tx = (tr_x * gr_viewsin) - (tr_y * gr_viewcos); + tr_x = FIXED_TO_FLOAT(thing->x); + tr_y = FIXED_TO_FLOAT(thing->y); // decide which patch to use for sprite relative to player if ((unsigned)thing->sprite >= numsprites) @@ -5294,32 +5421,32 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) lumpoff = sprframe->lumpid[0]; flip = sprframe->flip; // Will only be 0x00 or 0xFF - // calculate edges of the shape - tx -= FIXED_TO_FLOAT(spritecachedinfo[lumpoff].offset); + rightsin = FIXED_TO_FLOAT(FINESINE((viewangle + ANGLE_90)>>ANGLETOFINESHIFT)); + rightcos = FIXED_TO_FLOAT(FINECOSINE((viewangle + ANGLE_90)>>ANGLETOFINESHIFT)); + if (flip) + { + x1 = FIXED_TO_FLOAT(spritecachedinfo[lumpoff].width - spritecachedinfo[lumpoff].offset); + x2 = FIXED_TO_FLOAT(spritecachedinfo[lumpoff].offset); + } + else + { + x1 = FIXED_TO_FLOAT(spritecachedinfo[lumpoff].offset); + x2 = FIXED_TO_FLOAT(spritecachedinfo[lumpoff].width - spritecachedinfo[lumpoff].offset); + } - // project x - x1 = gr_windowcenterx + (tx * gr_centerx / tz); - - //faB : tr_x doesnt matter - // hurdler: it's used in cliptosolidsegs - tr_x = x1; - - x1 = tx; - - tx += FIXED_TO_FLOAT(spritecachedinfo[lumpoff].width); - x2 = gr_windowcenterx + (tx * gr_centerx / tz); + z1 = tr_y + x1 * rightsin; + z2 = tr_y - x2 * rightsin; + x1 = tr_x + x1 * rightcos; + x2 = tr_x - x2 * rightcos; // // store information in a vissprite // vis = HWR_NewVisSprite(); vis->x1 = x1; -#if 0 vis->x2 = x2; -#else - (void)x2; -#endif - vis->x2 = tx; + vis->z1 = z1; + vis->z2 = z2; vis->tz = tz; vis->dispoffset = 0; // Monster Iestyn: 23/11/15: HARDWARE SUPPORT AT LAST vis->patchlumpnum = sprframe->lumppat[rot]; @@ -5329,7 +5456,7 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) vis->colormap = colormaps; // set top/bottom coords - vis->ty = FIXED_TO_FLOAT(thing->z + spritecachedinfo[lumpoff].topoffset) - gr_viewz; + vis->ty = FIXED_TO_FLOAT(thing->z + spritecachedinfo[lumpoff].topoffset); vis->precip = true; } @@ -5357,12 +5484,13 @@ static void HWR_DrawSkyBackground(player_t *player) //Hurdler: the sky is the only texture who need 4.0f instead of 1.0 // because it's called just after clearing the screen // and thus, the near clipping plane is set to 3.99 - v[0].x = v[3].x = -4.0f; - v[1].x = v[2].x = 4.0f; - v[0].y = v[1].y = -4.0f; - v[2].y = v[3].y = 4.0f; + // Sryder: Just use the near clipping plane value then + v[0].x = v[3].x = -ZCLIP_PLANE-1; + v[1].x = v[2].x = ZCLIP_PLANE+1; + v[0].y = v[1].y = -ZCLIP_PLANE-1; + v[2].y = v[3].y = ZCLIP_PLANE+1; - v[0].z = v[1].z = v[2].z = v[3].z = 4.0f; + v[0].z = v[1].z = v[2].z = v[3].z = ZCLIP_PLANE+1; // X @@ -5430,7 +5558,7 @@ static inline void HWR_ClearView(void) (INT32)gr_viewwindowy, (INT32)(gr_viewwindowx + gr_viewwidth), (INT32)(gr_viewwindowy + gr_viewheight), - 3.99f); + ZCLIP_PLANE); HWD.pfnClearBuffer(false, true, 0); //disable clip window - set to full size @@ -5469,6 +5597,8 @@ void HWR_SetViewSize(void) gr_pspritexscale = gr_viewwidth / BASEVIDWIDTH; gr_pspriteyscale = ((vid.height*gr_pspritexscale*BASEVIDWIDTH)/BASEVIDHEIGHT)/vid.width; + + HWD.pfnFlushScreenTextures(); } // ========================================================================== @@ -5477,7 +5607,6 @@ void HWR_SetViewSize(void) void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player) { const float fpov = FIXED_TO_FLOAT(cv_grfov.value+player->fovadd); - FTransform stransform; postimg_t *type; if (splitscreen && player == &players[secondarydisplayplayer]) @@ -5541,31 +5670,12 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player) atransform.y = gr_viewy; // FIXED_TO_FLOAT(viewy) atransform.z = gr_viewz; // FIXED_TO_FLOAT(viewz) atransform.scalex = 1; - atransform.scaley = ORIGINAL_ASPECT; + atransform.scaley = (float)vid.width/vid.height; atransform.scalez = 1; atransform.fovxangle = fpov; // Tails atransform.fovyangle = fpov; // Tails atransform.splitscreen = splitscreen; - // Transform for sprites - stransform.anglex = 0.0f; - stransform.angley = -270.0f; - - if (*type == postimg_flip) - stransform.flip = true; - else - stransform.flip = false; - - stransform.x = 0.0f; - stransform.y = 0.0f; - stransform.z = 0.0f; - stransform.scalex = 1; - stransform.scaley = 1; - stransform.scalez = 1; - stransform.fovxangle = 90.0f; - stransform.fovyangle = 90.0f; - stransform.splitscreen = splitscreen; - gr_fovlud = (float)(1.0l/tan((double)(fpov*M_PIl/360l))); //------------------------------------------------------------------------ @@ -5644,10 +5754,7 @@ if (0) #ifdef SORTING HWR_SortVisSprites(); #endif - HWR_DrawMD2S(); - // Draw the sprites with trivial transform - HWD.pfnSetTransform(&stransform); #ifdef SORTING HWR_DrawSprites(); #endif @@ -5692,7 +5799,6 @@ if (0) void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) { const float fpov = FIXED_TO_FLOAT(cv_grfov.value+player->fovadd); - FTransform stransform; postimg_t *type; const boolean skybox = (skyboxmo[0] && cv_skybox.value); // True if there's a skybox object and skyboxes are on @@ -5771,31 +5877,12 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) atransform.y = gr_viewy; // FIXED_TO_FLOAT(viewy) atransform.z = gr_viewz; // FIXED_TO_FLOAT(viewz) atransform.scalex = 1; - atransform.scaley = ORIGINAL_ASPECT; + atransform.scaley = (float)vid.width/vid.height; atransform.scalez = 1; atransform.fovxangle = fpov; // Tails atransform.fovyangle = fpov; // Tails atransform.splitscreen = splitscreen; - // Transform for sprites - stransform.anglex = 0.0f; - stransform.angley = -270.0f; - - if (*type == postimg_flip) - stransform.flip = true; - else - stransform.flip = false; - - stransform.x = 0.0f; - stransform.y = 0.0f; - stransform.z = 0.0f; - stransform.scalex = 1; - stransform.scaley = 1; - stransform.scalez = 1; - stransform.fovxangle = 90.0f; - stransform.fovyangle = 90.0f; - stransform.splitscreen = splitscreen; - gr_fovlud = (float)(1.0l/tan((double)(fpov*M_PIl/360l))); //------------------------------------------------------------------------ @@ -5874,10 +5961,7 @@ if (0) #ifdef SORTING HWR_SortVisSprites(); #endif - HWR_DrawMD2S(); - // Draw the sprites with trivial transform - HWD.pfnSetTransform(&stransform); #ifdef SORTING HWR_DrawSprites(); #endif @@ -6068,6 +6152,7 @@ void HWR_Shutdown(void) HWR_FreeExtraSubsectors(); HWR_FreePolyPool(); HWR_FreeTextureCache(); + HWD.pfnFlushScreenTextures(); } void transform(float *cx, float *cy, float *cz) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 205b399b8..8e3ae3e21 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -59,7 +59,7 @@ typedef struct GLRGBAFloat GLRGBAFloat; #define N_PI_DEMI (M_PIl/2.0f) //(1.5707963268f) #define ASPECT_RATIO (1.0f) //(320.0f/200.0f) -#define FAR_CLIPPING_PLANE 150000.0f // Draw further! Tails 01-21-2001 +#define FAR_CLIPPING_PLANE 32768.0f // Draw further! Tails 01-21-2001 static float NEAR_CLIPPING_PLANE = NZCLIP_PLANE; // ************************************************************************** @@ -107,10 +107,19 @@ static GLint viewport[4]; #endif // Yay for arbitrary numbers! NextTexAvail is buggy for some reason. -static GLuint screentexture = 60000; -static GLuint startScreenWipe = 60001; -static GLuint endScreenWipe = 60002; -static GLuint finalScreenTexture = 60003; +// Sryder: NextTexAvail is broken for these because palette changes or changes to the texture filter or antialiasing +// flush all of the stored textures, leaving them unavailable at times such as between levels +// These need to start at 0 and be set to their number, and be reset to 0 when deleted so that intel GPUs +// can know when the textures aren't there, as textures are always considered resident in their virtual memory +// TODO: Store them in a more normal way +#define SCRTEX_SCREENTEXTURE 65535 +#define SCRTEX_STARTSCREENWIPE 65534 +#define SCRTEX_ENDSCREENWIPE 65533 +#define SCRTEX_FINALSCREENTEXTURE 65532 +static GLuint screentexture = 0; +static GLuint startScreenWipe = 0; +static GLuint endScreenWipe = 0; +static GLuint finalScreenTexture = 0; #if 0 GLuint screentexture = FIRST_TEX_AVAIL; #endif @@ -263,6 +272,7 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) /* texture mapping */ //GL_EXT_copy_texture #ifndef KOS_GL_COMPATIBILITY #define pglCopyTexImage2D glCopyTexImage2D +#define pglCopyTexSubImage2D glCopyTexSubImage2D #endif #else //!STATIC_OPENGL @@ -387,6 +397,8 @@ static PFNglBindTexture pglBindTexture; /* texture mapping */ //GL_EXT_copy_texture typedef void (APIENTRY * PFNglCopyTexImage2D) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); static PFNglCopyTexImage2D pglCopyTexImage2D; +typedef void (APIENTRY * PFNglCopyTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +static PFNglCopyTexSubImage2D pglCopyTexSubImage2D; #endif /* GLU functions */ typedef GLint (APIENTRY * PFNgluBuild2DMipmaps) (GLenum target, GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *data); @@ -503,6 +515,7 @@ boolean SetupGLfunc(void) GETOPENGLFUNC(pglBindTexture , glBindTexture) GETOPENGLFUNC(pglCopyTexImage2D , glCopyTexImage2D) + GETOPENGLFUNC(pglCopyTexSubImage2D , glCopyTexSubImage2D) #undef GETOPENGLFUNC @@ -654,6 +667,10 @@ void SetModelView(GLint w, GLint h) { // DBG_Printf("SetModelView(): %dx%d\n", (int)w, (int)h); + // The screen textures need to be flushed if the width or height change so that they be remade for the correct size + if (screen_width != w || screen_height != h) + FlushScreenTextures(); + screen_width = w; screen_height = h; @@ -801,6 +818,7 @@ void Flush(void) screentexture = FIRST_TEX_AVAIL; } #endif + tex_downloaded = 0; } @@ -1056,30 +1074,56 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) switch (PolyFlags & PF_Blending) { case PF_Translucent & PF_Blending: pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency +#ifndef KOS_GL_COMPATIBILITY + pglAlphaFunc(GL_NOTEQUAL, 0.0f); +#endif break; case PF_Masked & PF_Blending: // Hurdler: does that mean lighting is only made by alpha src? // it sounds ok, but not for polygonsmooth pglBlendFunc(GL_SRC_ALPHA, GL_ZERO); // 0 alpha = holes in texture +#ifndef KOS_GL_COMPATIBILITY + pglAlphaFunc(GL_GREATER, 0.5f); +#endif break; case PF_Additive & PF_Blending: #ifdef ATI_RAGE_PRO_COMPATIBILITY pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency #else pglBlendFunc(GL_SRC_ALPHA, GL_ONE); // src * alpha + dest +#endif +#ifndef KOS_GL_COMPATIBILITY + pglAlphaFunc(GL_NOTEQUAL, 0.0f); #endif break; case PF_Environment & PF_Blending: pglBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); +#ifndef KOS_GL_COMPATIBILITY + pglAlphaFunc(GL_NOTEQUAL, 0.0f); +#endif break; case PF_Substractive & PF_Blending: // good for shadow // not realy but what else ? pglBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); +#ifndef KOS_GL_COMPATIBILITY + pglAlphaFunc(GL_NOTEQUAL, 0.0f); +#endif + break; + case PF_Fog & PF_Fog: + // Sryder: Fog + // multiplies input colour by input alpha, and destination colour by input colour, then adds them + pglBlendFunc(GL_SRC_ALPHA, GL_SRC_COLOR); +#ifndef KOS_GL_COMPATIBILITY + pglAlphaFunc(GL_NOTEQUAL, 0.0f); +#endif break; default : // must be 0, otherwise it's an error // No blending pglBlendFunc(GL_ONE, GL_ZERO); // the same as no blending +#ifndef KOS_GL_COMPATIBILITY + pglAlphaFunc(GL_GREATER, 0.5f); +#endif break; } } @@ -1339,6 +1383,7 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) tex[w*j+i].s.green = 0; tex[w*j+i].s.blue = 0; tex[w*j+i].s.alpha = 0; + pTexInfo->flags |= TF_TRANSPARENT; // there is a hole in it } else { @@ -1409,8 +1454,22 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) tex_downloaded = pTexInfo->downloaded; pglBindTexture(GL_TEXTURE_2D, pTexInfo->downloaded); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter); + // disable texture filtering on any texture that has holes so there's no dumb borders or blending issues + if (pTexInfo->flags & TF_TRANSPARENT) + { +#ifdef KOS_GL_COMPATIBILITY + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NONE); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NONE); +#else + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); +#endif + } + else + { + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter); + } #ifdef KOS_GL_COMPATIBILITY pglTexImage2D(GL_TEXTURE_2D, 0, GL_ARGB4444, w, h, 0, GL_ARGB4444, GL_UNSIGNED_BYTE, ptex); @@ -1864,12 +1923,6 @@ static void DrawMD2Ex(INT32 *gl_cmd_buffer, md2_frame_t *frame, INT32 duration, ambient[1] = 0.75f; if (ambient[2] > 0.75f) ambient[2] = 0.75f; - - if (color[3] < 255) - { - pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - pglDepthMask(GL_FALSE); - } } pglEnable(GL_CULL_FACE); @@ -1896,10 +1949,12 @@ static void DrawMD2Ex(INT32 *gl_cmd_buffer, md2_frame_t *frame, INT32 duration, pglMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient); pglMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse); #endif + if (color[3] < 255) + SetBlend(PF_Translucent|PF_Modulated|PF_Clip); + else + SetBlend(PF_Masked|PF_Modulated|PF_Occlude|PF_Clip); } - DrawPolygon(NULL, NULL, 0, PF_Masked|PF_Modulated|PF_Occlude|PF_Clip); - pglPushMatrix(); // should be the same as glLoadIdentity //Hurdler: now it seems to work pglTranslatef(pos->x, pos->z, pos->y); @@ -1907,14 +1962,6 @@ static void DrawMD2Ex(INT32 *gl_cmd_buffer, md2_frame_t *frame, INT32 duration, scaley = -scaley; pglRotatef(pos->angley, 0.0f, -1.0f, 0.0f); pglRotatef(pos->anglex, -1.0f, 0.0f, 0.0f); - //pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency - - // Remove depth mask when the model is transparent so it doesn't cut thorugh sprites // SRB2CBTODO: For all stuff too?! - if (color && color[3] < 255) - { - pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency - pglDepthMask(GL_FALSE); - } val = *gl_cmd_buffer++; @@ -1982,7 +2029,6 @@ static void DrawMD2Ex(INT32 *gl_cmd_buffer, md2_frame_t *frame, INT32 duration, if (color) pglDisable(GL_LIGHTING); pglShadeModel(GL_FLAT); - pglDepthMask(GL_TRUE); pglDisable(GL_CULL_FACE); } @@ -2135,10 +2181,25 @@ EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]) } #endif //SHUFFLE +// Sryder: This needs to be called whenever the screen changes resolution in order to reset the screen textures to use +// a new size +EXPORT void HWRAPI(FlushScreenTextures) (void) +{ + pglDeleteTextures(1, &screentexture); + pglDeleteTextures(1, &startScreenWipe); + pglDeleteTextures(1, &endScreenWipe); + pglDeleteTextures(1, &finalScreenTexture); + screentexture = 0; + startScreenWipe = 0; + endScreenWipe = 0; + finalScreenTexture = 0; +} + // Create Screen to fade from EXPORT void HWRAPI(StartScreenWipe) (void) { INT32 texsize = 2048; + boolean firstTime = (startScreenWipe == 0); // Use a power of two texture, dammit if(screen_width <= 512) @@ -2147,27 +2208,38 @@ EXPORT void HWRAPI(StartScreenWipe) (void) texsize = 1024; // Create screen texture + if (firstTime) + startScreenWipe = SCRTEX_STARTSCREENWIPE; pglBindTexture(GL_TEXTURE_2D, startScreenWipe); + + if (firstTime) + { #ifdef KOS_GL_COMPATIBILITY - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_FILTER_NONE); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_FILTER_NONE); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_FILTER_NONE); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_FILTER_NONE); #else - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); #endif - Clamp2D(GL_TEXTURE_WRAP_S); - Clamp2D(GL_TEXTURE_WRAP_T); + Clamp2D(GL_TEXTURE_WRAP_S); + Clamp2D(GL_TEXTURE_WRAP_T); #ifndef KOS_GL_COMPATIBILITY - pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0); + pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0); +#endif + } + else +#ifndef KOS_GL_COMPATIBILITY + pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize); #endif - tex_downloaded = 0; // 0 so it knows it doesn't have any of the cached patches downloaded right now + tex_downloaded = startScreenWipe; } // Create Screen to fade to EXPORT void HWRAPI(EndScreenWipe)(void) { INT32 texsize = 2048; + boolean firstTime = (endScreenWipe == 0); // Use a power of two texture, dammit if(screen_width <= 512) @@ -2176,21 +2248,32 @@ EXPORT void HWRAPI(EndScreenWipe)(void) texsize = 1024; // Create screen texture + if (firstTime) + endScreenWipe = SCRTEX_ENDSCREENWIPE; pglBindTexture(GL_TEXTURE_2D, endScreenWipe); + + if (firstTime) + { #ifdef KOS_GL_COMPATIBILITY - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_FILTER_NONE); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_FILTER_NONE); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_FILTER_NONE); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_FILTER_NONE); #else - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); #endif - Clamp2D(GL_TEXTURE_WRAP_S); - Clamp2D(GL_TEXTURE_WRAP_T); + Clamp2D(GL_TEXTURE_WRAP_S); + Clamp2D(GL_TEXTURE_WRAP_T); #ifndef KOS_GL_COMPATIBILITY - pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0); + pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0); +#endif + } + else +#ifndef KOS_GL_COMPATIBILITY + pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize); #endif - tex_downloaded = 0; // 0 so it knows it doesn't have any of the cached patches downloaded right now + + tex_downloaded = endScreenWipe; } @@ -2232,7 +2315,7 @@ EXPORT void HWRAPI(DrawIntermissionBG)(void) pglEnd(); - tex_downloaded = 0; // 0 so it knows it doesn't have any of the cached patches downloaded right now + tex_downloaded = screentexture; } // Do screen fades! @@ -2323,6 +2406,7 @@ EXPORT void HWRAPI(DoScreenWipe)(float alpha) pglDisable(GL_TEXTURE_2D); // disable the texture in the 2nd texture unit pglActiveTexture(GL_TEXTURE0); + tex_downloaded = endScreenWipe; } else { @@ -2348,11 +2432,10 @@ EXPORT void HWRAPI(DoScreenWipe)(float alpha) pglTexCoord2f(xfix, 0.0f); pglVertex3f(1.0f, -1.0f, 1.0f); pglEnd(); + tex_downloaded = endScreenWipe; #ifndef MINI_GL_COMPATIBILITY } #endif - - tex_downloaded = 0; // 0 so it knows it doesn't have any of the cached patches downloaded right now } @@ -2360,6 +2443,7 @@ EXPORT void HWRAPI(DoScreenWipe)(float alpha) EXPORT void HWRAPI(MakeScreenTexture) (void) { INT32 texsize = 2048; + boolean firstTime = (screentexture == 0); // Use a power of two texture, dammit if(screen_width <= 512) @@ -2368,26 +2452,37 @@ EXPORT void HWRAPI(MakeScreenTexture) (void) texsize = 1024; // Create screen texture + if (firstTime) + screentexture = SCRTEX_SCREENTEXTURE; pglBindTexture(GL_TEXTURE_2D, screentexture); + + if (firstTime) + { #ifdef KOS_GL_COMPATIBILITY - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_FILTER_NONE); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_FILTER_NONE); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_FILTER_NONE); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_FILTER_NONE); #else - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); #endif - Clamp2D(GL_TEXTURE_WRAP_S); - Clamp2D(GL_TEXTURE_WRAP_T); + Clamp2D(GL_TEXTURE_WRAP_S); + Clamp2D(GL_TEXTURE_WRAP_T); #ifndef KOS_GL_COMPATIBILITY - pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0); + pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0); +#endif + } + else +#ifndef KOS_GL_COMPATIBILITY + pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize); #endif - tex_downloaded = 0; // 0 so it knows it doesn't have any of the cached patches downloaded right now + tex_downloaded = screentexture; } EXPORT void HWRAPI(MakeScreenFinalTexture) (void) { INT32 texsize = 2048; + boolean firstTime = (finalScreenTexture == 0); // Use a power of two texture, dammit if(screen_width <= 512) @@ -2396,27 +2491,40 @@ EXPORT void HWRAPI(MakeScreenFinalTexture) (void) texsize = 1024; // Create screen texture + if (firstTime) + finalScreenTexture = SCRTEX_FINALSCREENTEXTURE; pglBindTexture(GL_TEXTURE_2D, finalScreenTexture); + + if (firstTime) + { #ifdef KOS_GL_COMPATIBILITY - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_FILTER_NONE); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_FILTER_NONE); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_FILTER_NONE); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_FILTER_NONE); #else - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); #endif - Clamp2D(GL_TEXTURE_WRAP_S); - Clamp2D(GL_TEXTURE_WRAP_T); + Clamp2D(GL_TEXTURE_WRAP_S); + Clamp2D(GL_TEXTURE_WRAP_T); #ifndef KOS_GL_COMPATIBILITY - pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0); + pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0); +#endif + } + else +#ifndef KOS_GL_COMPATIBILITY + pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize); #endif - tex_downloaded = 0; // 0 so it knows it doesn't have any of the cached patches downloaded right now + tex_downloaded = finalScreenTexture; } EXPORT void HWRAPI(DrawScreenFinalTexture)(int width, int height) { float xfix, yfix; + float origaspect, newaspect; + float xoff = 1, yoff = 1; // xoffset and yoffset for the polygon to have black bars around the screen + FRGBAFloat clearColour; INT32 texsize = 2048; if(screen_width <= 1024) @@ -2427,35 +2535,47 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int width, int height) xfix = 1/((float)(texsize)/((float)((screen_width)))); yfix = 1/((float)(texsize)/((float)((screen_height)))); - //pglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + origaspect = (float)screen_width / screen_height; + newaspect = (float)width / height; + if (origaspect < newaspect) + { + xoff = origaspect / newaspect; + yoff = 1; + } + else if (origaspect > newaspect) + { + xoff = 1; + yoff = newaspect / origaspect; + } + pglViewport(0, 0, width, height); + clearColour.red = clearColour.green = clearColour.blue = 0; + clearColour.alpha = 1; + ClearBuffer(true, false, &clearColour); pglBindTexture(GL_TEXTURE_2D, finalScreenTexture); pglBegin(GL_QUADS); pglColor4f(1.0f, 1.0f, 1.0f, 1.0f); // Bottom left pglTexCoord2f(0.0f, 0.0f); - pglVertex3f(-1, -1, 1.0f); + pglVertex3f(-xoff, -yoff, 1.0f); // Top left pglTexCoord2f(0.0f, yfix); - pglVertex3f(-1, 1, 1.0f); + pglVertex3f(-xoff, yoff, 1.0f); // Top right pglTexCoord2f(xfix, yfix); - pglVertex3f(1, 1, 1.0f); + pglVertex3f(xoff, yoff, 1.0f); // Bottom right pglTexCoord2f(xfix, 0.0f); - pglVertex3f(1, -1, 1.0f); + pglVertex3f(xoff, -yoff, 1.0f); pglEnd(); - SetModelView(screen_width, screen_height); - SetStates(); - - tex_downloaded = 0; // 0 so it knows it doesn't have any of the cached patches downloaded right now + tex_downloaded = finalScreenTexture; } #endif //HWRENDER diff --git a/src/lua_script.c b/src/lua_script.c index 167e4a0b4..ce96878bf 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -478,10 +478,10 @@ static const struct { {NULL, ARCH_NULL} }; -static UINT8 GetUserdataArchType(void) +static UINT8 GetUserdataArchType(int index) { UINT8 i; - lua_getmetatable(gL, -1); + lua_getmetatable(gL, index); for (i = 0; meta2arch[i].meta; i++) { @@ -560,7 +560,7 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) break; } case LUA_TUSERDATA: - switch (GetUserdataArchType()) + switch (GetUserdataArchType(myindex)) { case ARCH_MOBJINFO: { @@ -777,6 +777,7 @@ static void ArchiveTables(void) CONS_Alert(CONS_ERROR, "Type of value for table %d entry '%s' (%s) could not be archived!\n", i, lua_tostring(gL, -1), luaL_typename(gL, -1)); lua_pop(gL, 1); } + lua_pop(gL, 1); } lua_pop(gL, 1); diff --git a/src/m_fixed.c b/src/m_fixed.c index ce7471a28..014457386 100644 --- a/src/m_fixed.c +++ b/src/m_fixed.c @@ -33,7 +33,9 @@ */ fixed_t FixedMul(fixed_t a, fixed_t b) { - return (fixed_t)((((INT64)a * b) ) / FRACUNIT); + // Need to cast to unsigned before shifting to avoid undefined behaviour + // for negative integers + return (fixed_t)(((UINT64)((INT64)a * b)) >> FRACBITS); } #endif //__USE_C_FIXEDMUL__ diff --git a/src/m_menu.c b/src/m_menu.c index ea93d1e2d..79ac6800b 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6295,6 +6295,13 @@ static void M_DrawConnectIPMenu(void) static void M_ConnectIP(INT32 choice) { (void)choice; + + if (*setupm_ip == 0) + { + M_StartMessage("You must specify an IP address.\n", NULL, MM_NOTHING); + return; + } + COM_BufAddText(va("connect \"%s\"\n", setupm_ip)); // A little "please wait" message. @@ -6536,7 +6543,7 @@ static void M_HandleSetupMultiPlayer(INT32 choice) if (choice < 32 || choice > 127 || itemOn != 0) break; l = strlen(setupm_name); - if (l < MAXPLAYERNAME-1) + if (l < MAXPLAYERNAME) { S_StartSound(NULL,sfx_menu1); // Tails setupm_name[l] =(char)choice; diff --git a/src/m_misc.c b/src/m_misc.c index 8193571e8..041899a3b 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -644,13 +644,12 @@ static void M_PNGhdr(png_structp png_ptr, png_infop png_info_ptr, PNG_CONST png_ static void M_PNGText(png_structp png_ptr, png_infop png_info_ptr, PNG_CONST png_byte movie) { #ifdef PNG_TEXT_SUPPORTED -#define SRB2PNGTXT 11 //PNG_KEYWORD_MAX_LENGTH(79) is the max +#define SRB2PNGTXT 10 //PNG_KEYWORD_MAX_LENGTH(79) is the max png_text png_infotext[SRB2PNGTXT]; char keytxt[SRB2PNGTXT][12] = { - "Title", "Author", "Description", "Playername", "Mapnum", "Mapname", + "Title", "Description", "Playername", "Mapnum", "Mapname", "Location", "Interface", "Revision", "Build Date", "Build Time"}; char titletxt[] = "Sonic Robo Blast 2 " VERSIONSTRING; - png_charp authortxt = I_GetUserName(); png_charp playertxt = cv_playername.zstring; char desctxt[] = "SRB2 Screenshot"; char Movietxt[] = "SRB2 Movie"; @@ -700,19 +699,18 @@ static void M_PNGText(png_structp png_ptr, png_infop png_info_ptr, PNG_CONST png png_infotext[i].key = keytxt[i]; png_infotext[0].text = titletxt; - png_infotext[1].text = authortxt; if (movie) - png_infotext[2].text = Movietxt; + png_infotext[1].text = Movietxt; else - png_infotext[2].text = desctxt; - png_infotext[3].text = playertxt; - png_infotext[4].text = maptext; - png_infotext[5].text = lvlttltext; - png_infotext[6].text = locationtxt; - png_infotext[7].text = interfacetxt; - png_infotext[8].text = strncpy(ctrevision, comprevision, sizeof(ctrevision)-1); - png_infotext[9].text = strncpy(ctdate, compdate, sizeof(ctdate)-1); - png_infotext[10].text = strncpy(cttime, comptime, sizeof(cttime)-1); + png_infotext[1].text = desctxt; + png_infotext[2].text = playertxt; + png_infotext[3].text = maptext; + png_infotext[4].text = lvlttltext; + png_infotext[5].text = locationtxt; + png_infotext[6].text = interfacetxt; + png_infotext[7].text = strncpy(ctrevision, comprevision, sizeof(ctrevision)-1); + png_infotext[8].text = strncpy(ctdate, compdate, sizeof(ctdate)-1); + png_infotext[9].text = strncpy(cttime, comptime, sizeof(cttime)-1); png_set_text(png_ptr, png_info_ptr, png_infotext, SRB2PNGTXT); #undef SRB2PNGTXT diff --git a/src/p_setup.c b/src/p_setup.c index 8e746457b..d8c913e0f 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2503,11 +2503,6 @@ boolean P_SetupLevel(boolean skipprecip) // Reset the palette -#ifdef HWRENDER - if (rendermode == render_opengl) - HWR_SetPaletteColor(0); - else -#endif if (rendermode != render_none) V_SetPaletteLump("PLAYPAL"); @@ -2565,6 +2560,7 @@ boolean P_SetupLevel(boolean skipprecip) { tic_t starttime = I_GetTime(); tic_t endtime = starttime + (3*TICRATE)/2; + tic_t nowtime; S_StartSound(NULL, sfx_s3kaf); @@ -2574,9 +2570,17 @@ boolean P_SetupLevel(boolean skipprecip) F_WipeEndScreen(); F_RunWipe(wipedefs[wipe_speclevel_towhite], false); + nowtime = lastwipetic; // Hold on white for extra effect. - while (I_GetTime() < endtime) - I_Sleep(); + while (nowtime < endtime) + { + // wait loop + while (!((nowtime = I_GetTime()) - lastwipetic)) + I_Sleep(); + lastwipetic = nowtime; + if (moviemode) // make sure we save frames for the white hold too + M_SaveFrame(); + } ranspecialwipe = 1; } @@ -2994,7 +2998,7 @@ boolean P_AddWadFile(const char *wadfilename, char **firstmapname) if ((numlumps = W_LoadWadFile(wadfilename)) == INT16_MAX) { - CONS_Printf(M_GetText("Errors occured while loading %s; not added.\n"), wadfilename); + CONS_Printf(M_GetText("Errors occurred while loading %s; not added.\n"), wadfilename); return false; } else wadnum = (UINT16)(numwadfiles-1); diff --git a/src/sdl/hwsym_sdl.c b/src/sdl/hwsym_sdl.c index f4686d2bf..05ac6450e 100644 --- a/src/sdl/hwsym_sdl.c +++ b/src/sdl/hwsym_sdl.c @@ -94,6 +94,7 @@ void *hwSym(const char *funcName,void *handle) #ifdef SHUFFLE GETFUNC(PostImgRedraw); #endif //SHUFFLE + GETFUNC(FlushScreenTextures); GETFUNC(StartScreenWipe); GETFUNC(EndScreenWipe); GETFUNC(DoScreenWipe); diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 3ad57559d..e86a39cab 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -2709,7 +2709,7 @@ const char *I_LocateWad(void) return waddir; } -#if defined(LINUX) || defined(LINUX64) +#ifdef __linux__ #define MEMINFO_FILE "/proc/meminfo" #define MEMTOTAL "MemTotal:" #define MEMFREE "MemFree:" @@ -2729,20 +2729,23 @@ UINT32 I_GetFreeMem(UINT32 *total) }; if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "kvm_open")) == NULL) { - *total = 0L; + if (total) + *total = 0L; return 0; } if (kvm_nlist(kd, namelist) != 0) { kvm_close (kd); - *total = 0L; + if (total) + *total = 0L; return 0; } if (kvm_read(kd, namelist[X_SUM].n_value, &sum, sizeof (sum)) != sizeof (sum)) { kvm_close(kd); - *total = 0L; + if (total) + *total = 0L; return 0; } kvm_close(kd); @@ -2773,7 +2776,7 @@ UINT32 I_GetFreeMem(UINT32 *total) (PVOID) &pr_arena, sizeof (UINT32)); return pr_arena; -#elif defined (LINUX) || defined (LINUX64) +#elif defined (__linux__) /* Linux */ char buf[1024]; char *memTag; @@ -2789,25 +2792,28 @@ UINT32 I_GetFreeMem(UINT32 *total) if (n < 0) { // Error - *total = 0L; + if (total) + *total = 0L; return 0; } buf[n] = '\0'; - if (NULL == (memTag = strstr(buf, MEMTOTAL))) + if ((memTag = strstr(buf, MEMTOTAL)) == NULL) { // Error - *total = 0L; + if (total) + *total = 0L; return 0; } memTag += sizeof (MEMTOTAL); totalKBytes = atoi(memTag); - if (NULL == (memTag = strstr(buf, MEMFREE))) + if ((memTag = strstr(buf, MEMFREE)) == NULL) { // Error - *total = 0L; + if (total) + *total = 0L; return 0; } @@ -2822,7 +2828,7 @@ UINT32 I_GetFreeMem(UINT32 *total) if (total) *total = 48<<20; return 48<<20; -#endif /* LINUX */ +#endif } const CPUInfoFlags *I_CPUInfo(void) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 1bda0e180..4eab0ae3c 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -658,6 +658,14 @@ static void Impl_HandleMouseButtonEvent(SDL_MouseButtonEvent evt, Uint32 type) SDL_memset(&event, 0, sizeof(event_t)); + // Ignore the event if the mouse is not actually focused on the window. + // This can happen if you used the mouse to restore keyboard focus; + // this apparently makes a mouse button down event but not a mouse button up event, + // resulting in whatever key was pressed down getting "stuck" if we don't ignore it. + // -- Monster Iestyn (28/05/18) + if (SDL_GetMouseFocus() != window) + return; + /// \todo inputEvent.button.which if (USE_MOUSEINPUT) { @@ -1442,6 +1450,7 @@ void I_StartupGraphics(void) #ifdef SHUFFLE HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL); #endif + HWD.pfnFlushScreenTextures=hwSym("FlushScreenTextures",NULL); HWD.pfnStartScreenWipe = hwSym("StartScreenWipe",NULL); HWD.pfnEndScreenWipe = hwSym("EndScreenWipe",NULL); HWD.pfnDoScreenWipe = hwSym("DoScreenWipe",NULL); diff --git a/src/sdl/ogl_sdl.c b/src/sdl/ogl_sdl.c index cd7ced7ca..4347b35b2 100644 --- a/src/sdl/ogl_sdl.c +++ b/src/sdl/ogl_sdl.c @@ -214,8 +214,11 @@ void OglSdlFinishUpdate(boolean waitvbl) HWR_DrawScreenFinalTexture(sdlw, sdlh); SDL_GL_SwapWindow(window); - SetModelView(realwidth, realheight); - SetStates(); + GClipRect(0, 0, realwidth, realheight, NZCLIP_PLANE); + + // Sryder: We need to draw the final screen texture again into the other buffer in the original position so that + // effects that want to take the old screen can do so after this + HWR_DrawScreenFinalTexture(realwidth, realheight); } EXPORT void HWRAPI( OglSdlSetPalette) (RGBA_t *palette, RGBA_t *pgamma) diff --git a/src/sdl/sdl_sound.c b/src/sdl/sdl_sound.c index 1a2cabd23..6c70c163b 100644 --- a/src/sdl/sdl_sound.c +++ b/src/sdl/sdl_sound.c @@ -1180,12 +1180,6 @@ void I_StartupSound(void) audio.callback = I_UpdateStream; audio.userdata = &localdata; - if (dedicated) - { - nosound = nomidimusic = nodigimusic = true; - return; - } - // Configure sound device CONS_Printf("I_StartupSound:\n"); @@ -1481,9 +1475,6 @@ void I_InitMusic(void) I_AddExitFunc(I_ShutdownGMEMusic); #endif - if ((nomidimusic && nodigimusic) || dedicated) - return; - #ifdef HAVE_MIXER MIX_VERSION(&MIXcompiled) MIXlinked = Mix_Linked_Version(); diff --git a/src/sdl12/hwsym_sdl.c b/src/sdl12/hwsym_sdl.c index 54f5da3a0..49340138f 100644 --- a/src/sdl12/hwsym_sdl.c +++ b/src/sdl12/hwsym_sdl.c @@ -100,6 +100,7 @@ void *hwSym(const char *funcName,void *handle) #ifdef SHUFFLE GETFUNC(PostImgRedraw); #endif //SHUFFLE + GETFUNC(FlushScreenTextures); GETFUNC(StartScreenWipe); GETFUNC(EndScreenWipe); GETFUNC(DoScreenWipe); diff --git a/src/sdl12/i_video.c b/src/sdl12/i_video.c index 197924eda..349e06cba 100644 --- a/src/sdl12/i_video.c +++ b/src/sdl12/i_video.c @@ -1972,6 +1972,7 @@ void I_StartupGraphics(void) #ifdef SHUFFLE HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL); #endif + HWD.pfnFlushScreenTextures=hwSym("FlushScreenTextures",NULL); HWD.pfnStartScreenWipe = hwSym("StartScreenWipe",NULL); HWD.pfnEndScreenWipe = hwSym("EndScreenWipe",NULL); HWD.pfnDoScreenWipe = hwSym("DoScreenWipe",NULL); diff --git a/src/st_stuff.c b/src/st_stuff.c index 3562a9b71..72e0b6b94 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -210,17 +210,17 @@ void ST_doPaletteStuff(void) else palette = 0; +#ifdef HWRENDER + if (rendermode == render_opengl) + palette = 0; // No flashpals here in OpenGL +#endif + palette = min(max(palette, 0), 13); if (palette != st_palette) { st_palette = palette; -#ifdef HWRENDER - if (rendermode == render_opengl) - HWR_SetPaletteColor(0); - else -#endif if (rendermode != render_none) { V_SetPaletteLump(GetPalette()); // Reset the palette diff --git a/src/v_video.c b/src/v_video.c index cc81cedbc..161c03d0b 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -937,14 +937,6 @@ void V_DrawPatchFill(patch_t *pat) INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); INT32 x, y, pw = SHORT(pat->width) * dupz, ph = SHORT(pat->height) * dupz; -#ifdef HWRENDER - if (rendermode == render_opengl) - { - pw = FixedMul(SHORT(pat->width)*FRACUNIT, vid.fdupx)>>FRACBITS; - ph = FixedMul(SHORT(pat->height)*FRACUNIT, vid.fdupy)>>FRACBITS; - } -#endif - for (x = 0; x < vid.width; x += pw) { for (y = 0; y < vid.height; y += ph) diff --git a/src/win32/win_dll.c b/src/win32/win_dll.c index 8fa4d17f7..c9b3fba4e 100644 --- a/src/win32/win_dll.c +++ b/src/win32/win_dll.c @@ -117,6 +117,7 @@ static loadfunc_t hwdFuncTable[] = { #ifdef SHUFFLE {"PostImgRedraw@4", &hwdriver.pfnPostImgRedraw}, #endif + {"FlushScreenTextures@0",&hwdriver.pfnFlushScreenTextures}, {"StartScreenWipe@0", &hwdriver.pfnStartScreenWipe}, {"EndScreenWipe@0", &hwdriver.pfnEndScreenWipe}, {"DoScreenWipe@4", &hwdriver.pfnDoScreenWipe}, @@ -147,6 +148,7 @@ static loadfunc_t hwdFuncTable[] = { #ifdef SHUFFLE {"PostImgRedraw", &hwdriver.pfnPostImgRedraw}, #endif + {"FlushScreenTextures"},&hwdriver.pfnFlushScreenTextures}, {"StartScreenWipe", &hwdriver.pfnStartScreenWipe}, {"EndScreenWipe", &hwdriver.pfnEndScreenWipe}, {"DoScreenWipe", &hwdriver.pfnDoScreenWipe},