From c499a8387e1daf9519d443251444beafbdeacea2 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 3 Aug 2023 16:39:17 -0700 Subject: [PATCH 001/485] Fix glibc 2.38 compile glibc 2.38 added strlcpy and strlcat. --- src/doomtype.h | 7 ++++++- src/string.c | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/doomtype.h b/src/doomtype.h index 4660e876d..f4f32edc8 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -164,6 +164,11 @@ char *strcasestr(const char *in, const char *what); #define HAVE_DOSSTR_FUNCS #endif +// glibc 2.38: added strlcpy and strlcat to _DEFAULT_SOURCE +#if defined (__APPLE__) || __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 38) +#define HAVE_STRLCPY +#endif + #ifndef HAVE_DOSSTR_FUNCS int strupr(char *n); // from dosstr.c int strlwr(char *n); // from dosstr.c @@ -171,7 +176,7 @@ int strlwr(char *n); // from dosstr.c #include // for size_t -#ifndef __APPLE__ +#ifndef HAVE_STRLCPY size_t strlcat(char *dst, const char *src, size_t siz); size_t strlcpy(char *dst, const char *src, size_t siz); #endif diff --git a/src/string.c b/src/string.c index c415e5245..34c5e71aa 100644 --- a/src/string.c +++ b/src/string.c @@ -16,7 +16,7 @@ #include #include "doomdef.h" -#if !defined (__APPLE__) +#ifndef HAVE_STRLCPY // Like the OpenBSD version, but it doesn't check for src not being a valid // C string. -- 2.54.0 From f9880e84137505001b0447fa3f7f66cfe8a8bc8a Mon Sep 17 00:00:00 2001 From: Indev Date: Sat, 5 Aug 2023 14:50:12 +0300 Subject: [PATCH 002/485] Fix ban.txt crashing game --- src/d_clisrv.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 727eba4ab..2656d9978 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2905,6 +2905,12 @@ void D_LoadBan(boolean warning) address = strtok(buffer, " /\t\r\n"); mask = strtok(NULL, " \t\r\n"); + if (!address) + { + malformed = true; + continue; + } + if (i == 0 && !strncmp(address, "BANFORMAT", 9)) { if (mask) -- 2.54.0 From 0b55e8df7bca2510275be4c7ad1123625e867fff Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 6 Aug 2023 19:34:50 -0700 Subject: [PATCH 003/485] Rename HAVE_STRLCPY to SRB2_HAVE_STRLCPY, fix non-glibc compile - Fix compile with msvcrt - Fix compile with SDL 2.28.2 --- src/doomtype.h | 12 ++++++++---- src/string.c | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/doomtype.h b/src/doomtype.h index f4f32edc8..27278f0cf 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -164,9 +164,13 @@ char *strcasestr(const char *in, const char *what); #define HAVE_DOSSTR_FUNCS #endif -// glibc 2.38: added strlcpy and strlcat to _DEFAULT_SOURCE -#if defined (__APPLE__) || __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 38) -#define HAVE_STRLCPY +#if defined (__APPLE__) + #define SRB2_HAVE_STRLCPY +#elif defined (__GLIBC_PREREQ) + // glibc 2.38: added strlcpy and strlcat to _DEFAULT_SOURCE + #if __GLIBC_PREREQ(2, 38) + #define SRB2_HAVE_STRLCPY + #endif #endif #ifndef HAVE_DOSSTR_FUNCS @@ -176,7 +180,7 @@ int strlwr(char *n); // from dosstr.c #include // for size_t -#ifndef HAVE_STRLCPY +#ifndef SRB2_HAVE_STRLCPY size_t strlcat(char *dst, const char *src, size_t siz); size_t strlcpy(char *dst, const char *src, size_t siz); #endif diff --git a/src/string.c b/src/string.c index 34c5e71aa..c919ec804 100644 --- a/src/string.c +++ b/src/string.c @@ -16,7 +16,7 @@ #include #include "doomdef.h" -#ifndef HAVE_STRLCPY +#ifndef SRB2_HAVE_STRLCPY // Like the OpenBSD version, but it doesn't check for src not being a valid // C string. -- 2.54.0 From c31e7ff2b37abbd561a4e20b05fdaf726f50203a Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Fri, 8 Sep 2023 12:44:13 +0200 Subject: [PATCH 004/485] Optimize sprite rendering by ignoring completely occluded sprites backport of the srb2 thing judging by perfstats it often cuts the spritecount in half take with a grain of salt since i barely tested it software mode only btw https://git.do.srb2.org/STJr/SRB2/-/merge_requests/2131?commit_id=b8313ceda283ac0c8dd9ab6141e83a31f0bb9639 --- src/r_main.c | 29 +++-------------- src/r_main.h | 2 +- src/r_things.c | 86 ++++++++++++++++++++++++++++++++++++++++++++------ src/r_things.h | 9 +++--- 4 files changed, 87 insertions(+), 39 deletions(-) diff --git a/src/r_main.c b/src/r_main.c index dc914e79a..484cda6d7 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -37,16 +37,6 @@ #include "hardware/hw_main.h" #endif -//profile stuff --------------------------------------------------------- -//#define TIMING -#ifdef TIMING -#include "p5prof.h" -INT64 mycount; -INT64 mytotal = 0; -//unsigned long nombre = 100000; -#endif -//profile stuff --------------------------------------------------------- - // Fineangles in the SCREENWIDTH wide window. #define FIELDOFVIEW 2048 @@ -197,7 +187,8 @@ consvar_t cv_flipcam4 = {"flipcam4", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, consvar_t cv_shadow = {"shadow", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_shadowoffs = {"offsetshadows", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_skybox = {"skybox", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_ffloorclip = {"ffloorclip", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_ffloorclip = {"r_ffloorclip", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_spriteclip = {"r_spriteclip", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_soniccd = {"soniccd", "Off", CV_NETVAR|CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_allowmlook = {"allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_showhud = {"showhud", "Yes", CV_CALL, CV_YesNo, R_SetViewSize, 0, NULL, NULL, 0, 0, NULL}; @@ -1765,26 +1756,15 @@ void R_RenderPlayerView(player_t *player) // The head node is the last node output. -//profile stuff --------------------------------------------------------- -#ifdef TIMING - mytotal = 0; - ProfZeroTimer(); -#endif ps_numbspcalls.value.i = ps_numpolyobjects.value.i = ps_numdrawnodes.value.i = 0; PS_START_TIMING(ps_bsptime); R_RenderBSPNode((INT32)numnodes - 1); PS_STOP_TIMING(ps_bsptime); - ps_numsprites.value.i = visspritecount; PS_START_TIMING(ps_sw_spritecliptime); R_ClipSprites(); PS_STOP_TIMING(ps_sw_spritecliptime); -#ifdef TIMING - RDMSR(0x10, &mycount); - mytotal += mycount; // 64bit add - - CONS_Debug(DBG_RENDER, "RenderBSPNode: 0x%d %d\n", *((INT32 *)&mytotal + 1), (INT32)mytotal); -#endif -//profile stuff --------------------------------------------------------- + + ps_numsprites.value.i = numvisiblesprites; // PORTAL RENDERING PS_START_TIMING(ps_sw_portaltime); @@ -1880,6 +1860,7 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_shadowoffs); CV_RegisterVar(&cv_skybox); CV_RegisterVar(&cv_ffloorclip); + CV_RegisterVar(&cv_spriteclip); CV_RegisterVar(&cv_cam_dist); CV_RegisterVar(&cv_cam_still); diff --git a/src/r_main.h b/src/r_main.h index 70adf1bb5..bd794abeb 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -110,7 +110,7 @@ extern consvar_t cv_homremoval; extern consvar_t cv_chasecam, cv_chasecam2, cv_chasecam3, cv_chasecam4; extern consvar_t cv_flipcam, cv_flipcam2, cv_flipcam3, cv_flipcam4; extern consvar_t cv_shadow, cv_shadowoffs; -extern consvar_t cv_ffloorclip; +extern consvar_t cv_ffloorclip, cv_spriteclip; extern consvar_t cv_translucency; extern consvar_t /*cv_precipdensity,*/ cv_drawdist, /*cv_drawdist_nights,*/ cv_drawdist_precip; extern consvar_t cv_fov; diff --git a/src/r_things.c b/src/r_things.c index 26dad2f0b..80a7db511 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -589,7 +589,8 @@ void R_DelSpriteDefs(UINT16 wadnum) // // GAME FUNCTIONS // -UINT32 visspritecount; +UINT32 visspritecount, numvisiblesprites; + static UINT32 clippedvissprites; static vissprite_t *visspritechunks[MAXVISSPRITES >> VISSPRITECHUNKBITS] = {NULL}; @@ -661,7 +662,7 @@ void R_InitSprites(void) // void R_ClearSprites(void) { - visspritecount = clippedvissprites = 0; + visspritecount = numvisiblesprites = clippedvissprites = 0; } // @@ -935,10 +936,10 @@ static void R_DrawVisSprite(vissprite_t *vis) { vis->scale = FixedMul(vis->scale, this_scale); vis->scalestep = FixedMul(vis->scalestep, this_scale); - vis->xiscale = FixedDiv(vis->xiscale,this_scale); + vis->xiscale = FixedDiv(vis->xiscale, this_scale); vis->isScaled = true; } - dc_texturemid = FixedDiv(dc_texturemid,this_scale); + dc_texturemid = FixedDiv(dc_texturemid, this_scale); } spryscale = vis->scale; @@ -1195,6 +1196,8 @@ static void R_ProjectSprite(mobj_t *thing) INT32 lindex; vissprite_t *vis; + + spritecut_e cut = SC_NONE; angle_t ang = 0; // gcc 4.6 and lower fix fixed_t iscale; @@ -1348,9 +1351,6 @@ static void R_ProjectSprite(mobj_t *thing) I_Assert(lump < max_spritelumps); - if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES) - this_scale = FixedMul(this_scale, ((skin_t *)thing->skin)->highresscale); - spr_width = spritecachedinfo[lump].width; spr_height = spritecachedinfo[lump].height; spr_offset = spritecachedinfo[lump].offset; @@ -1392,6 +1392,14 @@ static void R_ProjectSprite(mobj_t *thing) // calculate edges of the shape spritexscale = interp.spritexscale; spriteyscale = interp.spriteyscale; + + if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES) + { + fixed_t highresscale = ((skin_t *)thing->skin)->highresscale; + spritexscale = FixedMul(spritexscale, highresscale); + spriteyscale = FixedMul(spriteyscale, highresscale); + } + if (spritexscale < 1 || spriteyscale < 1) return; @@ -2085,12 +2093,15 @@ void R_SortVisSprites(void) best = ds; } } + if (best) + { best->next->prev = best->prev; best->prev->next = best->next; best->next = &vsprsortedhead; best->prev = vsprsortedhead.prev; vsprsortedhead.prev->next = best; vsprsortedhead.prev = best; + } } } @@ -2452,7 +2463,45 @@ static void R_DrawPrecipitationSprite(vissprite_t *spr) R_DrawPrecipitationVisSprite(spr); } -// R_ClipSprites +static boolean R_CheckSpriteVisible(vissprite_t *spr, INT32 x1, INT32 x2) +{ + INT16 sz = spr->sz; + INT16 szt = spr->szt; + + fixed_t texturemid, yscale, scalestep = spr->scalestep; + INT32 height; + + if (scalestep) + { + height = spr->patch->height; + yscale = spr->scale; + scalestep = FixedMul(scalestep, spr->spriteyscale); + + if (spr->thingscale != FRACUNIT) + texturemid = FixedDiv(spr->texturemid, max(spr->thingscale, 1)); + else + texturemid = spr->texturemid; + } + + for (INT32 x = x1; x <= x2; x++) + { + if (scalestep) + { + fixed_t top = centeryfrac - FixedMul(texturemid, yscale); + fixed_t bottom = top + (height * yscale); + szt = (INT16)(top >> FRACBITS); + sz = (INT16)(bottom >> FRACBITS); + yscale += scalestep; + } + + if (spr->cliptop[x] < spr->clipbot[x] && sz > spr->cliptop[x] && szt < spr->clipbot[x]) + return true; + } + + return false; +} + +// R_ClipVisSprite // Clips vissprites without drawing, so that portals can work. -Red void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2) { @@ -2635,8 +2684,15 @@ void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2) spr->clipbot[x] = (INT16)viewheight; if (spr->cliptop[x] == -2) - //Fab : 26-04-98: was -1, now clips against console bottom - spr->cliptop[x] = (INT16)con_clipviewtop; + spr->cliptop[x] = -1; + } + + // Check if it'll be visible + // Not done for floorsprites. + if (cv_spriteclip.value) + { + if (!R_CheckSpriteVisible(spr, x1, x2)) + spr->cut |= SC_NOTVISIBLE; } } @@ -2705,6 +2761,13 @@ void R_ClipSprites(void) for (; clippedvissprites < visspritecount; clippedvissprites++) { vissprite_t *spr = R_GetVisSprite(clippedvissprites); + + if (cv_spriteclip.value + && (spr->szt > vid.height || spr->sz < 0)) + { + spr->cut |= SC_NOTVISIBLE; + continue; + } if (spr->x2 < cx) { @@ -2723,6 +2786,9 @@ void R_ClipSprites(void) } R_ClipVisSprite(spr, spr->x1, spr->x2); + + if ((spr->cut & SC_NOTVISIBLE) == 0) + numvisiblesprites++; } } diff --git a/src/r_things.h b/src/r_things.h index ab4688f91..cb96ffbae 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -109,7 +109,10 @@ typedef enum SC_NONE = 0, SC_TOP = 1, SC_BOTTOM = 2, - SC_VFLIP = 3 + SC_VFLIP = 3, + SC_NOTVISIBLE = 4, + SC_CUTMASK = SC_TOP|SC_BOTTOM|SC_NOTVISIBLE, + SC_FLAGMASK = ~SC_CUTMASK } spritecut_e; // A vissprite_t is a thing that will be drawn during a refresh, @@ -152,8 +155,6 @@ typedef struct vissprite_s extracolormap_t *extra_colormap; // global colormaps - //fixed_t xscale; - // Precalculated top and bottom screen coords for the sprite. fixed_t thingheight; // The actual height of the thing (for 3D floors) sector_t *sector; // The sector containing the thing. @@ -175,7 +176,7 @@ typedef struct vissprite_s INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing } vissprite_t; -extern UINT32 visspritecount; +extern UINT32 visspritecount, numvisiblesprites; void R_ClipSprites(void); void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2); -- 2.54.0 From 81c555efd92c483697249566fb440722ffcbcf78 Mon Sep 17 00:00:00 2001 From: Indev Date: Wed, 18 Oct 2023 01:35:32 +0300 Subject: [PATCH 005/485] Fix battle playing wrong ending music sometimes --- src/p_user.c | 50 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 2fc3bb6bc..ae2015bb5 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1135,6 +1135,46 @@ void P_PlayVictorySound(mobj_t *source) S_StartSound(source, sfx_kwin); } +// Can't rely on k_position and K_IsPlayerLosing in battle smh +static UINT8 getPlayerPos(player_t *player) +{ + if (G_BattleGametype()) + { + UINT8 pos = 1; + + for (int i = 0; i < MAXPLAYERS; ++i) { + if (!playeringame[i] || players[i].spectator) continue; + if (players[i].marescore > player->marescore) ++pos; + } + + return pos; + } + + return player->kartstuff[k_position]; +} + +static boolean isPlayerLosing(player_t *player) +{ + if (G_BattleGametype()) { + UINT8 pos = 1; + UINT8 maxpos = 1; + + for (int i = 0; i < MAXPLAYERS; ++i) { + if (!playeringame[i] || players[i].spectator) continue; + if (players[i].marescore > player->marescore) ++pos; + maxpos = max(getPlayerPos(&players[i]), maxpos); + } + + if (maxpos == 1) return false; + + if (maxpos % 2) ++maxpos; + + return pos > (maxpos / 2); + } + + return K_IsPlayerLosing(player); +} + // // P_EndingMusic // @@ -1164,12 +1204,12 @@ boolean P_EndingMusic(player_t *player) return false; bestlocalplayer = &players[displayplayers[0]]; - bestlocalpos = ((players[displayplayers[0]].pflags & PF_TIMEOVER) ? MAXPLAYERS+1 : players[displayplayers[0]].kartstuff[k_position]); + bestlocalpos = ((players[displayplayers[0]].pflags & PF_TIMEOVER) ? MAXPLAYERS+1 : getPlayerPos(&players[displayplayers[0]])); #define setbests(p) \ - if (((players[p].pflags & PF_TIMEOVER) ? MAXPLAYERS+1 : players[p].kartstuff[k_position]) < bestlocalpos) \ + if (((players[p].pflags & PF_TIMEOVER) ? MAXPLAYERS+1 : getPlayerPos(&players[p])) < bestlocalpos) \ { \ bestlocalplayer = &players[p]; \ - bestlocalpos = ((players[p].pflags & PF_TIMEOVER) ? MAXPLAYERS+1 : players[p].kartstuff[k_position]); \ + bestlocalpos = ((players[p].pflags & PF_TIMEOVER) ? MAXPLAYERS+1 : getPlayerPos(&players[p])); \ } setbests(displayplayers[1]); if (splitscreen > 1) @@ -1184,7 +1224,7 @@ boolean P_EndingMusic(player_t *player) return false; bestlocalplayer = player; - bestlocalpos = ((player->pflags & PF_TIMEOVER) ? MAXPLAYERS+1 : player->kartstuff[k_position]); + bestlocalpos = ((player->pflags & PF_TIMEOVER) ? MAXPLAYERS+1 : getPlayerPos(player)); } if (G_RaceGametype() && bestlocalpos == MAXPLAYERS+1) @@ -1193,7 +1233,7 @@ boolean P_EndingMusic(player_t *player) { if (bestlocalpos == 1) sprintf(buffer, "k*win"); - else if (K_IsPlayerLosing(bestlocalplayer)) + else if (isPlayerLosing(bestlocalplayer)) sprintf(buffer, "k*lose"); else sprintf(buffer, "k*ok"); -- 2.54.0 From cec92474d29f998e597df5189efab0897a306ef9 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 18 Oct 2023 01:27:37 +0200 Subject: [PATCH 006/485] Add check for "extra.kart" files contents...... make lapcounter bigger when a map has 10 or more laps (needs updated extra.kart), fixed menu not greying out user defined hud colour --- src/d_main.c | 26 ++++++++++++++++-- src/d_main.h | 5 ++++ src/k_kart.c | 75 +++++++++++++++++++++++++++++++++++++--------------- src/k_kart.h | 1 + src/m_menu.c | 7 +++-- 5 files changed, 88 insertions(+), 26 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 0c0619a6d..33ae8e0f1 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -917,6 +917,11 @@ static boolean AddIWAD(void) boolean found_extra_kart; boolean found_extra2_kart; +boolean snw_speedo; // snowy speedometer check +boolean clr_hud; // colour hud check +boolean big_lap; // bigger lap counter +boolean big_lap_color; // bigger lap counter but colour + static void IdentifyVersion(void) { const char *srb2waddir = NULL; @@ -1266,11 +1271,28 @@ void D_SRB2Main(void) #endif //ifndef DEVELOP - if (found_extra_kart) // found the funny, add it in! + if (found_extra_kart){ // found the funny, add it in! mainwads++; + + // now check for speedometer stuff + if ((W_LumpExists("SP_SMSTC")) && (W_LumpExists("K_TRNULL")) && (W_LumpExists("SP_MKMH")) && (W_LumpExists("SP_MMPH")) && (W_LumpExists("SP_MFRAC")) && (W_LumpExists("SP_MPERC"))) + snw_speedo = true; - if (found_extra2_kart) // found the funny, add it in! + if ((W_LumpExists("K_STLAPB")) && (W_LumpExists("K_STLA2B"))) // check for bigger lap count + big_lap = true; + } + + if (found_extra2_kart){ // found the funny, add it in! mainwads++; + + // now check for colour hud stuff + if ((W_LumpExists("K_SCTIME")) && (W_LumpExists("K_SCTIMW")) && (W_LumpExists("K_SCLAPS")) && (W_LumpExists("K_SCLAPW")) && (W_LumpExists("K_SCBALN")) + && (W_LumpExists("K_SCBALW")) && (W_LumpExists("K_SCKARM")) && (W_LumpExists("K_SCTOUT")) && (W_LumpExists("K_ISMULC")) && (W_LumpExists("K_ITMULC"))) + clr_hud = true; + + if ((W_LumpExists("K_SCLAPB")) && (W_LumpExists("K_SCLA2B"))) // check for bigger lap count but colour + big_lap_color = true; + } // // search for maps diff --git a/src/d_main.h b/src/d_main.h index 679ad1c20..8c91be487 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -28,6 +28,11 @@ extern char srb2path[256]; //Alam: SRB2's Home extern boolean found_extra_kart; // for use in k_kart.c extern boolean found_extra2_kart; // for use in k_kart.c +extern boolean snw_speedo; // snowy speedometer check +extern boolean clr_hud; // colour hud check +extern boolean big_lap; // bigger lap counter +extern boolean big_lap_color; //bigger lap counter but colour + // the infinite loop of D_SRB2Loop() called from win_main for windows version void D_SRB2Loop(void) FUNCNORETURN; diff --git a/src/k_kart.c b/src/k_kart.c index bf5824c15..3670fd583 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -67,6 +67,8 @@ consvar_t cv_colorizedhud = {"colorizedhud", "Off", CV_SAVE, CV_OnOff, NULL, 0, static CV_PossibleValue_t HudColor_cons_t[MAXSKINCOLORS+1]; consvar_t cv_colorizedhudcolor = {"colorizedhudcolor", "Skin Color", CV_SAVE, HudColor_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_biglaps = {"biglaphud", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; // here for ppl who dont want to make 2 more patches for their custom hud + // SOME IMPORTANT VARIABLES DEFINED IN DOOMDEF.H: // gamespeed is cc (0 for easy, 1 for normal, 2 for hard) @@ -685,6 +687,8 @@ void K_RegisterKartStuff(void) CV_RegisterVar(&cv_colorizedhud); CV_RegisterVar(&cv_colorizedhudcolor); + CV_RegisterVar(&cv_biglaps); + CV_RegisterVar(&cv_slamsound); CV_RegisterVar(&cv_minihead); @@ -6906,6 +6910,8 @@ static patch_t *kp_nodraw; static patch_t *kp_timesticker; static patch_t *kp_timestickerwide; static patch_t *kp_lapsticker; +static patch_t *kp_lapstickerbig; +static patch_t *kp_lapstickerbig2; static patch_t *kp_lapstickerwide; static patch_t *kp_lapstickernarrow; static patch_t *kp_splitlapflag; @@ -6919,6 +6925,8 @@ static patch_t *kp_timeoutsticker; static patch_t *kp_timestickerclr; static patch_t *kp_timestickerwideclr; static patch_t *kp_lapstickerclr; +static patch_t *kp_lapstickerbigclr; +static patch_t *kp_lapstickerbig2clr; static patch_t *kp_lapstickerwideclr; static patch_t *kp_lapstickernarrowclr; static patch_t *kp_bumperstickerclr; @@ -7014,22 +7022,31 @@ void K_LoadKartHUDGraphics(void) kp_splitkarmabomb = W_CachePatchName("K_SPTKRM", PU_HUDGFX); kp_timeoutsticker = W_CachePatchName("K_STTOUT", PU_HUDGFX); + if (big_lap){ + kp_lapstickerbig = W_CachePatchName("K_STLAPB", PU_HUDGFX); + kp_lapstickerbig2 = W_CachePatchName("K_STLA2B", PU_HUDGFX); + } + //Colourized hud - if (found_extra2_kart) + if (clr_hud) { kp_timestickerclr = W_CachePatchName("K_SCTIME", PU_HUDGFX); kp_timestickerwideclr = W_CachePatchName("K_SCTIMW", PU_HUDGFX); - kp_lapstickerclr = W_CachePatchName("K_SCLAPS", PU_HUDGFX); - kp_lapstickerwideclr = W_CachePatchName("K_SCLAPW", PU_HUDGFX); + kp_lapstickerclr = W_CachePatchName("K_SCLAPS", PU_HUDGFX); + kp_lapstickerwideclr = W_CachePatchName("K_SCLAPW", PU_HUDGFX); kp_bumperstickerclr = W_CachePatchName("K_SCBALN", PU_HUDGFX); kp_bumperstickerwideclr = W_CachePatchName("K_SCBALW", PU_HUDGFX); kp_karmastickerclr = W_CachePatchName("K_SCKARM", PU_HUDGFX); - kp_timeoutstickerclr = W_CachePatchName("K_SCTOUT", PU_HUDGFX); + kp_timeoutstickerclr = W_CachePatchName("K_SCTOUT", PU_HUDGFX); kp_itemmulstickerclr[1] = W_CachePatchName("K_ISMULC", PU_HUDGFX); kp_itemmulstickerclr[0] = W_CachePatchName("K_ITMULC", PU_HUDGFX); - if (found_extra_kart) - { - skp_smallstickerclr = W_CachePatchName("SC_SMSTC", PU_HUDGFX); + if (big_lap_color){ + kp_lapstickerbigclr = W_CachePatchName("K_SCLAPB", PU_HUDGFX); + kp_lapstickerbig2clr = W_CachePatchName("K_SCLA2B", PU_HUDGFX); + } + + if (snw_speedo){ + skp_smallstickerclr = W_CachePatchName("SC_SMSTC", PU_HUDGFX); } } @@ -7259,7 +7276,7 @@ void K_LoadKartHUDGraphics(void) kp_yougotem = (patch_t *) W_CachePatchName("YOUGOTEM", PU_HUDGFX); - if (found_extra_kart) // snowy speedometer + if (snw_speedo) // snowy speedometer { skp_smallsticker = W_CachePatchName("SP_SMSTC", PU_HUDGFX); skp_speedpatches[0] = W_CachePatchName("K_TRNULL", PU_HUDGFX); // lolxd @@ -7777,7 +7794,7 @@ static void K_drawKartItem(void) if (stplyr->kartstuff[k_itemamount] >= numberdisplaymin && !stplyr->kartstuff[k_itemroulette]) { //Colourized hud - if (cv_colorizedhud.value && found_extra2_kart) + if (cv_colorizedhud.value && clr_hud) { V_DrawMappedPatch(fx + (flipamount ? 48 : 0), fy, V_HUDTRANS|fflags|(flipamount ? V_FLIP : 0), kp_itemmulstickerclr[offset],colormap); // flip this graphic for p2 and p4 in split and shift it. } @@ -7849,7 +7866,7 @@ void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, UI } - if (!cv_colorizedhud.value || !found_extra2_kart) + if (!cv_colorizedhud.value || !clr_hud) V_DrawScaledPatch(TX, TY, splitflags, ((mode == 2) ? kp_lapstickerwide : kp_timestickerwide)); else { @@ -8434,14 +8451,28 @@ static void K_drawKartLaps(void) else { - if (!cv_colorizedhud.value || !found_extra2_kart) - V_DrawScaledPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_lapsticker); + if (!cv_colorizedhud.value || !clr_hud){ + if ((cv_numlaps.value > 9) && (big_lap) && (cv_biglaps.value)){ + if (stplyr->laps+1 > 9) + V_DrawScaledPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_lapstickerbig2); + else + V_DrawScaledPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_lapstickerbig); + } + else + V_DrawScaledPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_lapsticker); + } else { //Colourized hud UINT8 *colormap = R_GetTranslationColormap(TC_DEFAULT, K_GetHudColor(), GTC_CACHE); - - V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_lapstickerclr, colormap); + if ((cv_numlaps.value > 9) && (big_lap_color) && (cv_biglaps.value)){ + if (stplyr->laps+1 > 9) + V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_lapstickerbig2clr, colormap); + else + V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_lapstickerbigclr, colormap); + } + else + V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_lapstickerclr, colormap); } if (stplyr->exiting) @@ -8486,7 +8517,7 @@ static void K_drawKartSpeedometer(void) } // man. - if ((!cv_newspeedometer.value) || (cv_newspeedometer.value && !found_extra_kart)) + if ((!cv_newspeedometer.value) || (cv_newspeedometer.value && !snw_speedo)) { switch (speedtype) { case 1: @@ -8499,14 +8530,14 @@ static void K_drawKartSpeedometer(void) V_DrawKartString(SPDM_X, SPDM_Y, V_HUDTRANS|splitflags, va("%3d fu/t", convSpeed)); break; case 4: // if extra.kart is found, use its included % symbol - if (!found_extra_kart) + if (!snw_speedo) V_DrawKartString(SPDM_X, SPDM_Y, V_HUDTRANS|splitflags, va("%4d P", convSpeed)); else V_DrawKartString(SPDM_X, SPDM_Y, V_HUDTRANS|splitflags, va("%4d %%", convSpeed)); } } - else if (cv_newspeedometer.value && found_extra_kart) { // why bother if we dont? - if (!cv_colorizedhud.value || !found_extra2_kart) + else if (cv_newspeedometer.value && snw_speedo) { // why bother if we dont? + if (!cv_colorizedhud.value || !clr_hud) V_DrawScaledPatch(SPDM_X + 1, SPDM_Y + 4, (V_HUDTRANS|splitflags), (skp_smallsticker)); else { @@ -8576,7 +8607,7 @@ static void K_drawKartBumpersOrKarma(void) if (stplyr->kartstuff[k_bumper] <= 0) { //Colourized hud - if (cv_colorizedhud.value && found_extra2_kart) + if (cv_colorizedhud.value && clr_hud) { V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_karmastickerclr, colormap); } @@ -8590,7 +8621,7 @@ static void K_drawKartBumpersOrKarma(void) { if (stplyr->kartstuff[k_bumper] > 9 && cv_kartbumpers.value > 9) //Colourized hud - if (cv_colorizedhud.value && found_extra2_kart) + if (cv_colorizedhud.value && clr_hud) { V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_bumperstickerwideclr, colormap); } @@ -8600,7 +8631,7 @@ static void K_drawKartBumpersOrKarma(void) } else //Colourized hud - if (cv_colorizedhud.value && found_extra2_kart) + if (cv_colorizedhud.value && clr_hud) { V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_bumperstickerclr, colormap); } @@ -9148,7 +9179,7 @@ static void K_drawBattleFullscreen(void) V_DrawString(x-txoff, ty, 0, va("%d", stplyr->kartstuff[k_comebacktimer]/TICRATE)); else { - if (!cv_colorizedhud.value || !found_extra2_kart) + if (!cv_colorizedhud.value || !clr_hud) V_DrawFixedPatch(x< Date: Tue, 17 Oct 2023 19:54:07 -0400 Subject: [PATCH 007/485] Clear unused-but-set-variable warnings --- src/blua/liolib.c | 2 -- src/d_netfil.c | 3 --- src/hardware/hw_model.c | 3 +++ 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/blua/liolib.c b/src/blua/liolib.c index d1d6f4695..2d69f45cd 100644 --- a/src/blua/liolib.c +++ b/src/blua/liolib.c @@ -445,7 +445,6 @@ static int io_readline (lua_State *L) { static int g_write (lua_State *L, FILE *f, int arg) { int nargs = lua_gettop(L) - 1; int status = 1; - size_t count; for (; nargs--; arg++) { if (lua_type(L, arg) == LUA_TNUMBER) { /* optimization: could be done exactly as for strings */ @@ -455,7 +454,6 @@ static int g_write (lua_State *L, FILE *f, int arg) { else { size_t l; const char *s = luaL_checklstring(L, arg, &l); - count += l; if (ftell(f) + l > FILELIMIT) { luaL_error(L,"write limit bypassed in file. Changes have been discarded."); diff --git a/src/d_netfil.c b/src/d_netfil.c index 881b7b5b2..292fd0262 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -489,7 +489,6 @@ INT32 CL_CheckFiles(void) { INT32 i, j; char wadfilename[MAX_WADPATH]; - size_t packetsize = 0; size_t filestoload = 0; boolean downloadrequired = false; @@ -561,8 +560,6 @@ INT32 CL_CheckFiles(void) } } - packetsize += nameonlylength(fileneeded[i].filename) + 22; - fileneeded[i].status = findfile(fileneeded[i].filename, fileneeded[i].md5sum, true); CONS_Debug(DBG_NETPLAY, "found %d\n", fileneeded[i].status); return 4; diff --git a/src/hardware/hw_model.c b/src/hardware/hw_model.c index 2c36f9744..e77cf43ef 100644 --- a/src/hardware/hw_model.c +++ b/src/hardware/hw_model.c @@ -519,6 +519,9 @@ void GeneratePolygonNormals(model_t *model, int ztag) for (k = 0; k < mesh->numTriangles; k++) { + /// TODO: normalize vectors + (void)vertices; + (void)polyNormals; // Vector::Normal(vertices, polyNormals); vertices += 3 * 3; polyNormals++; -- 2.54.0 From 1b82918384ad60025a79a4c2e84b5dbbb980c29a Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Tue, 17 Oct 2023 19:56:27 -0400 Subject: [PATCH 008/485] Clear misleading-indentation warnings --- src/m_menu.c | 2 ++ src/p_user.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/m_menu.c b/src/m_menu.c index 9d44ff03b..2fd5e929c 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -8312,7 +8312,9 @@ static void M_EraseGuest(INT32 choice) /*if (currentMenu == &SP_NightsGuestReplayDef) M_SetupNextMenu(&SP_NightsAttackDef); else*/ + { M_SetupNextMenu(&SP_TimeAttackDef); + } CV_AddValue(&cv_nextmap, -1); CV_AddValue(&cv_nextmap, 1); M_StartMessage(M_GetText("Guest replay data erased.\n"),NULL,MM_NOTHING); diff --git a/src/p_user.c b/src/p_user.c index 941697540..c2165abf8 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2305,7 +2305,9 @@ static void P_CheckInvincibilityTimer(player_t *player) return; //if (mariomode && !player->powers[pw_super]) // SRB2kart + { player->mo->color = (UINT8)(1 + (leveltime % (MAXSKINCOLORS-1))); + } /*if (leveltime % (TICRATE/7) == 0) { mobj_t *sparkle = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_IVSP); -- 2.54.0 From 79e2596ce6fcb68a0ff1fc64471744b13c35610d Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Tue, 17 Oct 2023 19:57:56 -0400 Subject: [PATCH 009/485] Clear missing-noreturn warnings --- src/sdl/i_system.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 50204f3f7..9131dc9c8 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -3031,7 +3031,7 @@ void I_Sleep(UINT32 ms) } #ifdef NEWSIGNALHANDLER -static void newsignalhandler_Warn(const char *pr) +FUNCNORETURN static ATTRNORETURN void newsignalhandler_Warn(const char *pr) { char text[128]; -- 2.54.0 From a5b99199fcd776856424261bbb5acb9b91ea0bb2 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Tue, 17 Oct 2023 20:05:48 -0400 Subject: [PATCH 010/485] Clear implicit-const-int-float-conversion warnings --- src/m_random.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/m_random.c b/src/m_random.c index 3d46f76b7..197f37239 100644 --- a/src/m_random.c +++ b/src/m_random.c @@ -60,7 +60,7 @@ UINT8 M_RandomByte(void) */ INT32 M_RandomKey(INT32 a) { - return (INT32)((rand()/((unsigned)RAND_MAX+1.0f))*a); + return (INT32)((rand()/((float)(RAND_MAX)+1.0f))*a); } /** Provides a random integer in a given range. @@ -73,7 +73,7 @@ INT32 M_RandomKey(INT32 a) */ INT32 M_RandomRange(INT32 a, INT32 b) { - return (INT32)((rand()/((unsigned)RAND_MAX+1.0f))*(b-a+1))+a; + return (INT32)((rand()/((float)(RAND_MAX)+1.0f))*(b-a+1))+a; } -- 2.54.0 From 7fea4894a2fcb9d9d3d29ac693ad7829b8143a23 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Tue, 17 Oct 2023 20:55:26 -0400 Subject: [PATCH 011/485] Add support for GCC 13.2 --- src/Makefile.cfg | 131 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 123 insertions(+), 8 deletions(-) diff --git a/src/Makefile.cfg b/src/Makefile.cfg index e45265cab..c5794b8da 100644 --- a/src/Makefile.cfg +++ b/src/Makefile.cfg @@ -12,15 +12,18 @@ # to avoid a false positive with the version detection... SUPPORTED_GCC_VERSIONS:=\ - 101 102\ - 91 92 93\ - 81 82 83 84\ - 71 72 73 74 75\ - 61 62 63 64\ - 51 52 53 54 55\ - 40 41 42 43 44 45 46 47 48 49 + 132 131 130\ + 123 122 121 120\ + 114 113 112 111 110\ + 105 104 103 102 101 100 10\ + 95 94 93 92 91 90\ + 85 84 83 82 81 80\ + 75 74 73 72 71 70\ + 64 63 62 61 60\ + 55 54 53 52 51 50\ + 49 48 47 46 45 44 43 42 41 40 -LATEST_GCC_VERSION=10.2 +LATEST_GCC_VERSION=13.2 # gcc or g++ ifdef PREFIX @@ -71,11 +74,99 @@ ifeq (,$(filter GCC%,$(.VARIABLES))) endif endif +ifdef GCC132 +GCC131=1 +endif + +ifdef GCC131 +GCC130=1 +endif + +ifdef GCC13 +GCC130=1 +endif + +ifdef GCC130 +GCC123=1 +endif + +ifdef GCC123 +GCC122=1 +endif + +ifdef GCC122 +GCC121=1 +endif + +ifdef GCC121 +GCC120=1 +endif + +ifdef GCC12 +GCC120=1 +endif + +ifdef GCC120 +GCC114=1 +endif + +ifdef GCC114 +GCC113=1 +endif + +ifdef GCC113 +GCC112=1 +endif + +ifdef GCC112 +GCC111=1 +endif + +ifdef GCC111 +GCC110=1 +endif + +ifdef GCC11 +GCC110=1 +endif + +ifdef GCC110 +GCC105=1 +endif + +ifdef GCC105 +GCC104=1 +endif + +ifdef GCC104 +GCC103=1 +endif + +ifdef GCC103 +GCC102=1 +endif + ifdef GCC102 GCC101=1 endif ifdef GCC101 +GCC100=1 +endif + +ifdef GCC10 +GCC100=1 +endif + +ifdef GCC100 +GCC93=1 +endif + +ifdef GCC95 +GCC94=1 +endif + +ifdef GCC94 GCC93=1 endif @@ -88,6 +179,14 @@ GCC91=1 endif ifdef GCC91 +GCC90=1 +endif + +ifdef GCC90 +GCC85=1 +endif + +ifdef GCC85 GCC84=1 endif @@ -104,6 +203,10 @@ GCC81=1 endif ifdef GCC81 +GCC80=1 +endif + +ifdef GCC80 GCC75=1 endif @@ -124,6 +227,10 @@ GCC71=1 endif ifdef GCC71 +GCC70=1 +endif + +ifdef GCC70 GCC64=1 endif @@ -140,6 +247,10 @@ GCC61=1 endif ifdef GCC61 +GCC60=1 +endif + +ifdef GCC60 GCC55=1 endif @@ -160,6 +271,10 @@ GCC51=1 endif ifdef GCC51 +GCC50=1 +endif + +ifdef GCC50 GCC49=1 endif -- 2.54.0 From 94e7430dd93b026d017be2829adba71891a92057 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Tue, 17 Oct 2023 20:57:14 -0400 Subject: [PATCH 012/485] copy gitlib-ci config from SRB2's next --- .gitlab-ci.yml | 436 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 436 insertions(+) create mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 000000000..f13dac2f8 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,436 @@ +default: + image: debian:stable-slim + +stages: # List of stages for jobs, and their order of execution + - build + +variables: + GIT_STRATEGY: clone + GIT_CLONE_PATH: $CI_BUILDS_DIR/$CI_CONCURRENT_ID/$CI_PROJECT_PATH + +.job_template: &job_build # This job runs in the build stage, which runs first. + + stage: build + + cache: + - key: ccache-$CI_PROJECT_PATH_SLUG-$CI_JOB_NAME_SLUG + fallback_keys: + - cache-$CI_PROJECT_PATH_SLUG-$CI_DEFAULT_BRANCH + - cache-$CI_PROJECT_PATH_SLUG-default + paths: + - ccache + - ccache_statslog + + - key: apt-$CI_JOB_IMAGE + paths: + - apt-cache + unprotect: true + + before_script: + - - | + # debconf + echo -e "\e[0Ksection_start:`date +%s`:debconf[collapsed=true]\r\e[0KSetup debconf's environment" + - export DEBIAN_FRONTEND="noninteractive" + - export DEBIAN_PRIORITY="low" + - export DEBCONF_NONINTERACTIVE_SEEN="true" + - | + # debconf + echo -e "\e[0Ksection_end:`date +%s`:debconf\r\e[0K" + - - | + # dpkg_aa + echo -e "\e[0Ksection_start:`date +%s`:dpkg_aa[collapsed=true]\r\e[0KAdding architectures to dpkg" + - dpkg --add-architecture i386 + - dpkg --add-architecture amd64 + - dpkg --add-architecture arm64 + - | + # dpkg_aa + echo -e "\e[0Ksection_end:`date +%s`:dpkg_aa\r\e[0K" + - - | + # apt_conf + echo -e "\e[0Ksection_start:`date +%s`:apt_conf[collapsed=true]\r\e[0KSetting up APT conf" + - export APT_CACHE_DIR=`pwd`/apt-cache + - mkdir --parents --verbose $APT_CACHE_DIR/partial/ + - touch /etc/apt/apt.conf.d/99build + - | + # apt.conf + echo Adding options to apt.conf':' + - | + # APT::Install-Recommends + echo APT::Install-Recommends "false"\; | tee --append /etc/apt/apt.conf.d/99build + - | + # quit + echo quiet "1"\; | tee --append /etc/apt/apt.conf.d/99build + - | + # APT::Get::Assume-Yes + echo APT::Get::Assume-Yes "true"\; | tee --append /etc/apt/apt.conf.d/99build + - | + # Dir::Cache::Archives + echo Dir::Cache::Archives "$APT_CACHE_DIR"\; | tee --append /etc/apt/apt.conf.d/99build + - | + # apt_conf + echo -e "\e[0Ksection_end:`date +%s`:apt_conf\r\e[0K" + - - | + # apt_update + echo -e "\e[0Ksection_start:`date +%s`:apt_update[collapsed=true]\r\e[0KUpdating APT listing" + - apt-get update + - | + # apt_update + echo -e "\e[0Ksection_end:`date +%s`:apt_update\r\e[0K" + + - - | + # apt_pre + echo -e "\e[0Ksection_start:`date +%s`:apt_pre[collapsed=true]\r\e[0KInstalling pre packages" + - apt-get install apt-utils + - | + # apt_pre + echo -e "\e[0Ksection_end:`date +%s`:apt_pre\r\e[0K" + + - - | + # apt_upgrade + echo -e "\e[0Ksection_start:`date +%s`:apt_upgrade[collapsed=true]\r\e[0KUpdating existing packages" + - apt-get upgrade + - | + # apt_update + echo -e "\e[0Ksection_end:`date +%s`:apt_upgrade\r\e[0K" + + - - | + # apt_common + echo -e "\e[0Ksection_start:`date +%s`:apt_common[collapsed=true]\r\e[0KInstalling common packages" + - apt-get install make git ccache + - | + # apt_common + echo -e "\e[0Ksection_end:`date +%s`:apt_common\r\e[0K" + + - - | + # ccache_config + echo -e "\e[0Ksection_start:`date +%s`:ccache_config[collapsed=true]\r\e[0KSetting up ccache config" + - mkdir --parents --verbose ~/.ccache/ + - touch ~/.ccache/ccache.conf + - | + # cache.conf + echo Adding ccache configution option + - | + # base_dir + echo base_dir = $PWD | tee --append ~/.ccache/ccache.conf + - | + # cache_dir + echo cache_dir = $PWD/ccache | tee --append ~/.ccache/ccache.conf + - | + # compiler_check + echo compiler_check = content | tee --append ~/.ccache/ccache.conf + - | + # stats_log + echo stats_log = $PWD/ccache_statslog | tee --append ~/.ccache/ccache.conf + - | + # max_size + echo max_size = 50M | tee --append ~/.ccache/ccache.conf + - | + # ccache_config + echo -e "\e[0Ksection_end:`date +%s`:ccache_config\r\e[0K" + + - - | + # cache_reset + echo -e "\e[0Ksection_start:`date +%s`:ccache_reset[collapsed=true]\r\e[0KResetting ccache statistics" + - ccache --zero-stats + - ccache --show-stats + - | + # ccache_reset + echo -e "\e[0Ksection_end:`date +%s`:ccache_reset\r\e[0K" + + after_script: + - - | + # apt_clean + echo -e "\e[0Ksection_start:`date +%s`:apt_clean[collapsed=true]\r\e[0KCleaning of unneeded APT packages" + - apt-get autoclean + - | + # apt_clean + echo -e "\e[0Ksection_end:`date +%s`:apt_clean\r\e[0K" + + - - | + # ccache_stats + echo -e "\e[0Ksection_start:`date +%s`:ccache_stats[collapsed=true]\r\e[0Kccache statistics:" + - ccache --show-stats --verbose + - ccache --show-log-stats --verbose + - | + # ccahe_stats + echo -e "\e[0Ksection_end:`date +%s`:ccache_stats\r\e[0K" + +Debian testing GCC: + <<: *job_build + image: debian:testing-slim + + allow_failure: true + + artifacts: + paths: + - "bin/" + - "src/comptime.h" + expose_as: "Debian GCC testing" + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-testing-gcc" + + variables: + CC: gcc + + script: + - - | + # apt_toolchain + echo -e "\e[0Ksection_start:`date +%s`:apt_toolchain[collapsed=true]\r\e[0KInstalling toolchain packages" + - apt-get install gcc + - | + # apt_toolchain + echo -e "\e[0Ksection_end:`date +%s`:apt_toolchain\r\e[0K" + + - - | + # apt_development + echo -e "\e[0Ksection_start:`date +%s`:apt_development[collapsed=true]\r\e[0KInstalling development packages" + - apt-get install libsdl2-mixer-dev libpng-dev libcurl4-openssl-dev libgme-dev libopenmpt-dev + - | + # apt_development + echo -e "\e[0Ksection_end:`date +%s`:apt_development\r\e[0K" + + - - | + # make + echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2" + - make --directory=src --keep-going CCACHE=1 ERRORMODE=1 NONX86=1 || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 NONX86=1 + - | + # make + echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" + +Windows x86: + <<: *job_build + + artifacts: + paths: + - "bin/" + - "src/comptime.h" + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-Win32" + + variables: + PREFIX: i686-w64-mingw32 + + script: + - - | + # apt_toolchain + echo -e "\e[0Ksection_start:`date +%s`:apt_toolchain[collapsed=true]\r\e[0KInstalling toolchain packages" + - apt-get install gcc-mingw-w64-i686-win32 + - | + # apt_toolchain + echo -e "\e[0Ksection_end:`date +%s`:apt_toolchain\r\e[0K" + + - - | + # make + echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2" + - make --directory=src --keep-going CCACHE=1 ERRORMODE=1 MINGW=1 || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 MINGW=1 + - | + # make + echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" + +Debian stable:amd64: + <<: *job_build + + artifacts: + paths: + - "bin/" + - "src/comptime.h" + expose_as: "Debian amd64" + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-x86-64" + + variables: + CC: x86_64-linux-gnu-gcc + OBJCOPY: x86_64-linux-gnu-objcopy + OBJDUMP: x86_64-linux-gnu-objdump + PKG_CONFIG_PATH: /usr/lib/x86_64-linux-gnu/pkgconfig + + script: + - - | + # apt_toolchain + echo -e "\e[0Ksection_start:`date +%s`:apt_toolchain[collapsed=true]\r\e[0KInstalling toolchain packages" + - apt-get install gcc-x86-64-linux-gnu || apt-get install gcc + - | + # apt_toolchain + echo -e "\e[0Ksection_end:`date +%s`:apt_toolchain\r\e[0K" + + - - | + # apt_development + echo -e "\e[0Ksection_start:`date +%s`:apt_development[collapsed=true]\r\e[0KInstalling development packages" + - apt-get install libsdl2-mixer-dev:amd64 libpng-dev:amd64 libcurl4-openssl-dev:amd64 libgme-dev:amd64 libopenmpt-dev:amd64 + - | + # apt_development + echo -e "\e[0Ksection_end:`date +%s`:apt_development\r\e[0K" + + - - | + # make + echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2" + - make --directory=src --keep-going CCACHE=1 ERRORMODE=1 LINUX64=1 || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 LINUX64=1 + - | + # make + echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" + +Debian stable:i386: + <<: *job_build + + artifacts: + paths: + - "bin/" + - "src/comptime.h" + expose_as: "Debian i386" + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-i686" + + variables: + CC: i686-linux-gnu-gcc + OBJCOPY: i686-linux-gnu-objcopy + OBJDUMP: i686-linux-gnu-objdump + PKG_CONFIG_PATH: /usr/lib/i386-linux-gnu/pkgconfig + + script: + - - | + # apt_toolchain + echo -e "\e[0Ksection_start:`date +%s`:apt_toolchain[collapsed=true]\r\e[0KInstalling toolchain packages" + - apt-get install gcc-i686-linux-gnu || apt-get install gcc + - | + # apt_toolchain + echo -e "\e[0Ksection_end:`date +%s`:apt_toolchain\r\e[0K" + + - - | + # apt_development + echo -e "\e[0Ksection_start:`date +%s`:apt_development[collapsed=true]\r\e[0KInstalling development packages" + - apt-get install libsdl2-mixer-dev:i386 libpng-dev:i386 libcurl4-openssl-dev:i386 libgme-dev:i386 libopenmpt-dev:i386 + - | + # apt_development + echo -e "\e[0Ksection_end:`date +%s`:apt_development\r\e[0K" + + - - | + # make + echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2" + - make --directory=src --keep-going CCACHE=1 ERRORMODE=1 LINUX=1 || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 LINUX=1 + - | + # make + echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" + +Debian stable:arm64: + <<: *job_build + + artifacts: + paths: + - "bin/" + - "src/comptime.h" + expose_as: "Debian arm64" + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-aarch64" + + variables: + CC: aarch64-linux-gnu-gcc + OBJCOPY: aarch64-linux-gnu-objcopy + OBJDUMP: aarch64-linux-gnu-objdump + PKG_CONFIG_PATH: /usr/lib/aarch64-linux-gnu/pkgconfig + + script: + - - | + # apt_toolchain + echo -e "\e[0Ksection_start:`date +%s`:apt_toolchain[collapsed=true]\r\e[0KInstalling toolchain packages" + - apt-get install gcc-aarch64-linux-gnu || apt-get install gcc + - | + # apt_toolchain + echo -e "\e[0Ksection_end:`date +%s`:apt_toolchain\r\e[0K" + + - - | + # apt_development + echo -e "\e[0Ksection_start:`date +%s`:apt_development[collapsed=true]\r\e[0KInstalling development packages" + - apt-get install libsdl2-mixer-dev:arm64 libpng-dev:arm64 libcurl4-openssl-dev:arm64 libgme-dev:arm64 libopenmpt-dev:arm64 + - | + # apt_development + echo -e "\e[0Ksection_end:`date +%s`:apt_development\r\e[0K" + + - - | + # make + echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2" + - make --directory=src --keep-going CCACHE=1 ERRORMODE=1 LINUX64=1 ERRORMODE=1 NONX86=1 || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 LINUX64=1 NONX86=1 + - | + # make + echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" + +Windows x64: + <<: *job_build + + artifacts: + paths: + - "bin/" + - "src/comptime.h" + expose_as: "Win64" + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-Win64" + + variables: + PREFIX: x86_64-w64-mingw32 + + script: + - - | + # apt_toolchain + echo -e "\e[0Ksection_start:`date +%s`:apt_toolchain[collapsed=true]\r\e[0KInstalling toolchain packages" + - apt-get install gcc-mingw-w64-x86-64-win32 + - | + # apt_toolchain + echo -e "\e[0Ksection_end:`date +%s`:apt_toolchain\r\e[0K" + + - - | + # make + echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2" + - make --directory=src --keep-going CCACHE=1 ERRORMODE=1 MINGW64=1 || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 MINGW64=1 + - | + # make + echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" + +Debian stable Clang: + <<: *job_build + + allow_failure: true + + artifacts: + paths: + - "bin/" + - "src/comptime.h" + expose_as: "Debian Clang" + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-clang" + + variables: + CC: clang + CFLAGS: -Wno-cast-align + + script: + - - | + # apt_toolchain + echo -e "\e[0Ksection_start:`date +%s`:apt_toolchain[collapsed=true]\r\e[0KInstalling toolchain packages" + - apt-get install clang + - | + # apt_toolchain + echo -e "\e[0Ksection_end:`date +%s`:apt_toolchain\r\e[0K" + + - - | + # apt_development + echo -e "\e[0Ksection_start:`date +%s`:apt_development[collapsed=true]\r\e[0KInstalling development packages" + - apt-get install libsdl2-mixer-dev libpng-dev libcurl4-openssl-dev libgme-dev libopenmpt-dev + - | + # apt_development + echo -e "\e[0Ksection_end:`date +%s`:apt_development\r\e[0K" + + - - | + # make + echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2" + - make --directory=src --keep-going CCACHE=1 ERRORMODE=1 NONX86=1 || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 NONX86=1 + - | + # make + echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" + +Debian testing Clang: + extends: Debian stable Clang + + image: debian:testing-slim + + artifacts: + paths: + - "bin/" + - "src/comptime.h" + expose_as: "Debina Clang testing" + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-testing-clang" + + variables: + CC: clang + CFLAGS: -Wno-cast-align -Wno-deprecated-non-prototype -- 2.54.0 From 579c5ab05235c1b46d7d5b21f3cfd2ed121bbb86 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Tue, 17 Oct 2023 21:09:51 -0400 Subject: [PATCH 013/485] Makefile: Support GCC version 11, 12 and 13 --- src/Makefile.cfg | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Makefile.cfg b/src/Makefile.cfg index c5794b8da..2532a6b24 100644 --- a/src/Makefile.cfg +++ b/src/Makefile.cfg @@ -12,9 +12,9 @@ # to avoid a false positive with the version detection... SUPPORTED_GCC_VERSIONS:=\ - 132 131 130\ - 123 122 121 120\ - 114 113 112 111 110\ + 132 131 130 13\ + 123 122 121 120 12\ + 114 113 112 111 110 11\ 105 104 103 102 101 100 10\ 95 94 93 92 91 90\ 85 84 83 82 81 80\ -- 2.54.0 From 46f0385566cc50a1bbf7c6f698f66ceb6098a860 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Tue, 17 Oct 2023 21:36:27 -0400 Subject: [PATCH 014/485] d_netfile.c: Update libcurl support to 7.88 --- src/d_netfil.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/d_netfil.c b/src/d_netfil.c index 292fd0262..7d4e2406e 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -72,8 +72,13 @@ static boolean SV_SendFile(INT32 node, const char *filename, UINT8 fileid); #ifdef HAVE_CURL size_t curlwrite_data(void *ptr, size_t size, size_t nmemb, FILE *stream); +#if defined(CURL_AT_LEAST_VERSION) && CURL_AT_LEAST_VERSION(7, 35, 0) +int curlprogress_callbackx(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow); +#define XFERINFOFUNCTION +#else int curlprogress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow); #endif +#endif // Sender structure typedef struct filetx_s @@ -1217,6 +1222,18 @@ size_t curlwrite_data(void *ptr, size_t size, size_t nmemb, FILE *stream) return written; } +#ifdef XFERINFOFUNCTION +int curlprogress_callbackx(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) +{ + (void)clientp; + (void)ultotal; + (void)ulnow; // Function prototype requires these but we won't use, so just discard + curl_dlnow = dlnow; + curl_dltotal = dltotal; + getbytes = curl_dlnow / (time(NULL) - curl_starttime); // To-do: Make this more accurate??? + return 0; +} +#else int curlprogress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow) { (void)clientp; @@ -1227,6 +1244,7 @@ int curlprogress_callback(void *clientp, double dltotal, double dlnow, double ul getbytes = curl_dlnow / (time(NULL) - curl_starttime); // To-do: Make this more accurate??? return 0; } +#endif void CURLPrepareFile(const char* url, int dfilenum) { @@ -1256,7 +1274,11 @@ void CURLPrepareFile(const char* url, int dfilenum) curl_easy_setopt(http_handle, CURLOPT_URL, va("%s/%s", url, curl_realname)); // Only allow HTTP and HTTPS +#if defined(CURL_AT_LEAST_VERSION) && CURL_AT_LEAST_VERSION(7, 85, 0) + curl_easy_setopt(http_handle, CURLOPT_PROTOCOLS_STR, "http,https"); +#else curl_easy_setopt(http_handle, CURLOPT_PROTOCOLS, CURLPROTO_HTTP|CURLPROTO_HTTPS); +#endif curl_easy_setopt(http_handle, CURLOPT_USERAGENT, va("SRB2Kart/v%d.%d", VERSION, SUBVERSION)); // Set user agent as some servers won't accept invalid user agents. @@ -1280,7 +1302,11 @@ void CURLPrepareFile(const char* url, int dfilenum) curl_easy_setopt(http_handle, CURLOPT_WRITEDATA, curl_curfile->file); curl_easy_setopt(http_handle, CURLOPT_WRITEFUNCTION, curlwrite_data); curl_easy_setopt(http_handle, CURLOPT_NOPROGRESS, 0L); +#ifdef XFERINFOFUNCTION + curl_easy_setopt(http_handle, CURLOPT_XFERINFOFUNCTION, curlprogress_callbackx); +#else curl_easy_setopt(http_handle, CURLOPT_PROGRESSFUNCTION, curlprogress_callback); +#endif curl_curfile->status = FS_DOWNLOADING; lastfilenum = dfilenum; -- 2.54.0 From 16c70e7b29d1dd1fab11f0b2c7206c95fab9bcd5 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Tue, 17 Oct 2023 21:38:51 -0400 Subject: [PATCH 015/485] GitLab CI: Compile the SDL version of Win32 builds --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f13dac2f8..9114cc179 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -220,7 +220,7 @@ Windows x86: - - | # make echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2" - - make --directory=src --keep-going CCACHE=1 ERRORMODE=1 MINGW=1 || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 MINGW=1 + - make --directory=src --keep-going CCACHE=1 ERRORMODE=1 MINGW=1 SDL=1 || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 MINGW=1 SDL=1 - | # make echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" @@ -373,7 +373,7 @@ Windows x64: - - | # make echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2" - - make --directory=src --keep-going CCACHE=1 ERRORMODE=1 MINGW64=1 || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 MINGW64=1 + - make --directory=src --keep-going CCACHE=1 ERRORMODE=1 MINGW64=1 SDL=1 || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 MINGW64=1 SDL=1 - | # make echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" -- 2.54.0 From 2365ee9cb0be4ee37e08b32fd8dfa3b14a0cf33e Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Tue, 17 Oct 2023 21:42:07 -0400 Subject: [PATCH 016/485] GitLab CI: SRB2 2.1 wants nasm --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9114cc179..874c76aa3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -96,7 +96,7 @@ variables: - - | # apt_common echo -e "\e[0Ksection_start:`date +%s`:apt_common[collapsed=true]\r\e[0KInstalling common packages" - - apt-get install make git ccache + - apt-get install make git ccache nasm - | # apt_common echo -e "\e[0Ksection_end:`date +%s`:apt_common\r\e[0K" -- 2.54.0 From bf6be522ea7b8fcd83d3c301bb68dc25024cf767 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Tue, 17 Oct 2023 21:44:39 -0400 Subject: [PATCH 017/485] GitLib CI: SRB2 2.1 codebase use WFLAGS to control warning flags --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 874c76aa3..3185a6692 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -392,7 +392,7 @@ Debian stable Clang: variables: CC: clang - CFLAGS: -Wno-cast-align + WFLAGS: -Wno-cast-align script: - - | @@ -433,4 +433,4 @@ Debian testing Clang: variables: CC: clang - CFLAGS: -Wno-cast-align -Wno-deprecated-non-prototype + WFLAGS: -Wno-cast-align -Wno-deprecated-non-prototype -- 2.54.0 From 98f8b49e4531062b1cc96fdbd6f40930b7606929 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Tue, 17 Oct 2023 22:36:17 -0400 Subject: [PATCH 018/485] Makefile: support toolchain envs --- src/Makefile.cfg | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Makefile.cfg b/src/Makefile.cfg index 2532a6b24..9d5b879c0 100644 --- a/src/Makefile.cfg +++ b/src/Makefile.cfg @@ -27,17 +27,17 @@ LATEST_GCC_VERSION=13.2 # gcc or g++ ifdef PREFIX - CC=$(PREFIX)-gcc - CXX=$(PREFIX)-g++ - OBJCOPY=$(PREFIX)-objcopy - OBJDUMP=$(PREFIX)-objdump - STRIP=$(PREFIX)-strip - WINDRES=$(PREFIX)-windres + CC?=$(PREFIX)-gcc + CXX?=$(PREFIX)-g++ + OBJCOPY?=$(PREFIX)-objcopy + OBJDUMP?=$(PREFIX)-objdump + STRIP?=$(PREFIX)-strip + WINDRES?=$(PREFIX)-windres else - OBJCOPY=objcopy - OBJDUMP=objdump - STRIP=strip - WINDRES=windres + OBJCOPY?=objcopy + OBJDUMP?=objdump + STRIP?=strip + WINDRES?=windres endif # because Apple screws with us on this -- 2.54.0 From cb4ffe6f60c10f11f5fc5a298ab829e9d44e0ac4 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Tue, 17 Oct 2023 23:12:14 -0400 Subject: [PATCH 019/485] no Dr. Mingw support for Win x64 build --- src/sdl/i_main.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/sdl/i_main.c b/src/sdl/i_main.c index e6644ec51..4ac45aa1d 100644 --- a/src/sdl/i_main.c +++ b/src/sdl/i_main.c @@ -58,8 +58,11 @@ char logfilename[1024]; #endif #endif -#if defined (_WIN32) +#ifdef _WIN32 +#ifndef _AMD64_ #include "exchndl.h" +#define DRMINGW +#endif #endif #if defined (_WIN32) @@ -174,7 +177,9 @@ int main(int argc, char **argv) ) #endif { +#ifdef DRMINGW ExcHndlInit(); +#endif } } #ifndef __MINGW32__ -- 2.54.0 From 37c65ca7e4f8b1b258e54d189fcfe456bfdfa27b Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Tue, 17 Oct 2023 23:14:09 -0400 Subject: [PATCH 020/485] Makefile: PREFIX overwrite make's default CC and CXX --- src/Makefile.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Makefile.cfg b/src/Makefile.cfg index 9d5b879c0..5248dbdfe 100644 --- a/src/Makefile.cfg +++ b/src/Makefile.cfg @@ -27,8 +27,8 @@ LATEST_GCC_VERSION=13.2 # gcc or g++ ifdef PREFIX - CC?=$(PREFIX)-gcc - CXX?=$(PREFIX)-g++ + CC:=$(PREFIX)-gcc + CXX:=$(PREFIX)-g++ OBJCOPY?=$(PREFIX)-objcopy OBJDUMP?=$(PREFIX)-objdump STRIP?=$(PREFIX)-strip -- 2.54.0 From 01911e4d3703371da1a9f086a52e5b7ef4f9bd26 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Tue, 17 Oct 2023 23:19:38 -0400 Subject: [PATCH 021/485] Clear unused-but-set-variable warnings --- src/p_saveg.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index f553ddf6f..c938c3dce 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -494,7 +494,6 @@ static void P_NetUnArchivePlayers(void) static void P_NetArchiveWorld(void) { size_t i; - INT32 statsec = 0, statline = 0; const line_t *li = lines; const side_t *si; UINT8 *put; @@ -587,8 +586,6 @@ static void P_NetArchiveWorld(void) if (diff) { - statsec++; - WRITEUINT16(put, i); WRITEUINT8(put, diff); if (diff & SD_DIFF2) @@ -705,7 +702,6 @@ static void P_NetArchiveWorld(void) if (diff) { - statline++; WRITEINT16(put, i); WRITEUINT8(put, diff); if (diff & LD_DIFF2) -- 2.54.0 From 3c3c59928da42faa360d56ec0652343f24b0f0b8 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Tue, 17 Oct 2023 23:44:30 -0400 Subject: [PATCH 022/485] Makefile: support for Mingw64 toolchain --- src/Makefile.cfg | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Makefile.cfg b/src/Makefile.cfg index 5248dbdfe..b839b5eae 100644 --- a/src/Makefile.cfg +++ b/src/Makefile.cfg @@ -54,7 +54,10 @@ ifeq (,$(filter GCC%,$(.VARIABLES))) version:=$(shell $(CC) --version) # check if this is in fact GCC ifneq (,$(or $(findstring gcc,$(version)),$(findstring GCC,$(version)))) - version:=$(shell $(CC) -dumpversion) + shellversion:=$(shell $(CC) -dumpversion) + + # Try to remove "-win32" + version:=$(subst -win32,.0,$(shellversion)) # Turn version into words of major, minor v:=$(subst ., ,$(version)) -- 2.54.0 From 6eb96a499276d0a01416f6eec8f7f054a2dfce19 Mon Sep 17 00:00:00 2001 From: hayaunderscore Date: Wed, 18 Oct 2023 15:30:46 +0800 Subject: [PATCH 023/485] clean up `extra.kart` and `extra2.kart` lump checking --- src/d_main.c | 33 ++++++++++++++++++--------------- src/w_wad.c | 20 ++++++++++++++++++++ src/w_wad.h | 3 +++ 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 33ae8e0f1..69243f2de 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1271,27 +1271,30 @@ void D_SRB2Main(void) #endif //ifndef DEVELOP - if (found_extra_kart){ // found the funny, add it in! - mainwads++; + if (found_extra_kart || found_extra2_kart) // found the funny, add it in! + { + // HAYA: These are seperated for a reason lmao + if (found_extra_kart) + mainwads++; + if (found_extra2_kart) + mainwads++; // now check for speedometer stuff - if ((W_LumpExists("SP_SMSTC")) && (W_LumpExists("K_TRNULL")) && (W_LumpExists("SP_MKMH")) && (W_LumpExists("SP_MMPH")) && (W_LumpExists("SP_MFRAC")) && (W_LumpExists("SP_MPERC"))) - snw_speedo = true; + if (W_CheckMultipleLumps("SP_SMSTC", "K_TRNULL", "SP_MKMH", "SP_MMPH", "SP_MFRAC", "SP_MPERC", NULL)) + snw_speedo = true; - if ((W_LumpExists("K_STLAPB")) && (W_LumpExists("K_STLA2B"))) // check for bigger lap count - big_lap = true; - } - - if (found_extra2_kart){ // found the funny, add it in! - mainwads++; + // check for bigger lap count + if (W_CheckMultipleLumps("K_STLAPB", "K_STLA2B", NULL)) + big_lap = true; // now check for colour hud stuff - if ((W_LumpExists("K_SCTIME")) && (W_LumpExists("K_SCTIMW")) && (W_LumpExists("K_SCLAPS")) && (W_LumpExists("K_SCLAPW")) && (W_LumpExists("K_SCBALN")) - && (W_LumpExists("K_SCBALW")) && (W_LumpExists("K_SCKARM")) && (W_LumpExists("K_SCTOUT")) && (W_LumpExists("K_ISMULC")) && (W_LumpExists("K_ITMULC"))) - clr_hud = true; + if (W_CheckMultipleLumps("K_SCTIME", "K_SCTIMW", "K_SCLAPS", "K_SCLAPW", \ + "K_SCBALN", "K_SCBALW", "K_SCKARM", "K_SCTOUT", "K_ISMULC", "K_ITMULC", NULL)) + clr_hud = true; - if ((W_LumpExists("K_SCLAPB")) && (W_LumpExists("K_SCLA2B"))) // check for bigger lap count but colour - big_lap_color = true; + // check for bigger lap count but color** its color bitch + if (W_CheckMultipleLumps("K_SCLAPB", "K_SCLA2B", NULL)) + big_lap_color = true; } // diff --git a/src/w_wad.c b/src/w_wad.c index 2aba94321..f9e449268 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -1319,6 +1319,26 @@ UINT8 W_LumpExists(const char *name) return false; } +UINT8 W_CheckMultipleLumps(const char* lump, ...) +{ + va_list lumps; + va_start(lumps, lump); + const char* lumpname = lump; + + while (lumpname != NULL) + { + if (!W_LumpExists(lumpname)) + { + va_end(lumps); + return FALSE; + } + lumpname = va_arg(lumps, const char*); + } + + va_end(lumps); + return TRUE; +} + size_t W_LumpLengthPwad(UINT16 wad, UINT16 lump) { if (!TestValidLump(wad, lump)) diff --git a/src/w_wad.h b/src/w_wad.h index b2b518793..52e726d80 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -22,6 +22,8 @@ #pragma interface #endif +#include // hopefully this shouldn't cause any problems... + // a raw entry of the wad directory // NOTE: This sits here and not in w_wad.c because p_setup.c makes use of it to load map WADs inside PK3s. #if defined(_MSC_VER) @@ -165,6 +167,7 @@ lumpnum_t W_GetNumForName(const char *name); // like W_CheckNumForName but I_Err lumpnum_t W_GetNumForLongName(const char *name); lumpnum_t W_CheckNumForNameInBlock(const char *name, const char *blockstart, const char *blockend); UINT8 W_LumpExists(const char *name); // Lua uses this. +UINT8 W_CheckMultipleLumps(const char* lump, ...); // variadic version of above lmao size_t W_LumpLengthPwad(UINT16 wad, UINT16 lump); size_t W_LumpLength(lumpnum_t lumpnum); -- 2.54.0 From cd682e3961757f1c1fd3cd496834896189dedf4e Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Thu, 19 Oct 2023 09:39:35 +0200 Subject: [PATCH 024/485] Avoid branch prediction slowdowns in bla bla but better i hope --- src/r_main.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/r_main.c b/src/r_main.c index a4a353276..1d3a6968c 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -333,7 +333,7 @@ static void FlipCam4_OnChange(void) // // killough 5/2/98: reformatted // -INT32 R_PointOnSide(fixed_t x, fixed_t y, node_t *node) +INT32 R_PointOnSide(fixed_t x, fixed_t y, node_t *restrict node) { if (!node->dx) return x <= node->x ? node->dy > 0 : node->dy < 0; @@ -344,14 +344,15 @@ INT32 R_PointOnSide(fixed_t x, fixed_t y, node_t *node) x -= node->x; y -= node->y; - // Try to quickly decide by looking at sign bits. - if ((node->dy ^ node->dx ^ x ^ y) < 0) - return (node->dy ^ x) < 0; // (left is negative) - return FixedMul(y, node->dx>>FRACBITS) >= FixedMul(node->dy>>FRACBITS, x); + // Try to quickly decide by looking at sign bits. + // also use a mask to avoid branch prediction + INT32 mask = (node->dy ^ node->dx ^ x ^ y) >> 31; + return (mask & ((node->dy ^ x) < 0)) | // (left is negative) + (~mask & (FixedMul(y, node->dx>>FRACBITS) >= FixedMul(node->dy>>FRACBITS, x))); } // killough 5/2/98: reformatted -INT32 R_PointOnSegSide(fixed_t x, fixed_t y, seg_t *line) +INT32 R_PointOnSegSide(fixed_t x, fixed_t y, seg_t *restrict line) { fixed_t lx = line->v1->x; fixed_t ly = line->v1->y; @@ -368,9 +369,10 @@ INT32 R_PointOnSegSide(fixed_t x, fixed_t y, seg_t *line) y -= ly; // Try to quickly decide by looking at sign bits. - if ((ldy ^ ldx ^ x ^ y) < 0) - return (ldy ^ x) < 0; // (left is negative) - return FixedMul(y, ldx>>FRACBITS) >= FixedMul(ldy>>FRACBITS, x); + // also use a mask to avoid branch prediction + INT32 mask = (ldy ^ ldx ^ x ^ y) >> 31; + return (mask & ((ldy ^ x) < 0)) | // (left is negative) + (~mask & (FixedMul(y, ldx>>FRACBITS) >= FixedMul(ldy>>FRACBITS, x))); } // -- 2.54.0 From 654784690ebb93d6626e756b12e93bd581482e6a Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Thu, 19 Oct 2023 10:12:32 +0200 Subject: [PATCH 025/485] we dont have asm stuff --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3185a6692..636831aee 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -96,7 +96,7 @@ variables: - - | # apt_common echo -e "\e[0Ksection_start:`date +%s`:apt_common[collapsed=true]\r\e[0KInstalling common packages" - - apt-get install make git ccache nasm + - apt-get install make git ccache - | # apt_common echo -e "\e[0Ksection_end:`date +%s`:apt_common\r\e[0K" -- 2.54.0 From ff41393edda764e06d68b1a21270f124901f3000 Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Thu, 19 Oct 2023 10:46:30 +0200 Subject: [PATCH 026/485] Fix segfaults on some systems due to polyvertex being NULL https://git.do.srb2.org/STJr/SRB2/-/merge_requests/2065 --- src/hardware/hw_main.c | 102 +++++++++++++++++++++++++++++++++-------- 1 file changed, 84 insertions(+), 18 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index cee87551f..9ef00afae 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -834,11 +834,27 @@ void HWR_RenderPlane(extrasubsector_t *xsub, boolean isceiling, fixed_t fixedhei { P_ClosestPointOnLine(viewx, viewy, line->linedef, &v); dist = FIXED_TO_FLOAT(R_PointToDist(v.x, v.y)); - - x1 = ((polyvertex_t *)line->pv1)->x; - y1 = ((polyvertex_t *)line->pv1)->y; - xd = ((polyvertex_t *)line->pv2)->x - x1; - yd = ((polyvertex_t *)line->pv2)->y - y1; + + if (line->pv1) + { + x1 = ((polyvertex_t *)line->pv1)->x; + y1 = ((polyvertex_t *)line->pv1)->y; + } + else + { + x1 = FIXED_TO_FLOAT(line->v1->x); + y1 = FIXED_TO_FLOAT(line->v1->x); + } + if (line->pv2) + { + xd = ((polyvertex_t *)line->pv2)->x - x1; + yd = ((polyvertex_t *)line->pv2)->y - y1; + } + else + { + xd = FIXED_TO_FLOAT(line->v2->x) - x1; + yd = FIXED_TO_FLOAT(line->v2->y) - y1; + } // Based on the seg length and the distance from the line, split horizon into multiple poly sets to reduce distortion dist = sqrtf((xd*xd) + (yd*yd)) / dist / 16.0f; @@ -1425,11 +1441,27 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom gr_sidedef = gr_curline->sidedef; gr_linedef = gr_curline->linedef; - - vs.x = ((polyvertex_t *)gr_curline->pv1)->x; - vs.y = ((polyvertex_t *)gr_curline->pv1)->y; - ve.x = ((polyvertex_t *)gr_curline->pv2)->x; - ve.y = ((polyvertex_t *)gr_curline->pv2)->y; + + if (gr_curline->pv1) + { + vs.x = ((polyvertex_t *)gr_curline->pv1)->x; + vs.y = ((polyvertex_t *)gr_curline->pv1)->y; + } + else + { + vs.x = FIXED_TO_FLOAT(gr_curline->v1->x); + vs.y = FIXED_TO_FLOAT(gr_curline->v1->y); + } + if (gr_curline->pv2) + { + ve.x = ((polyvertex_t *)gr_curline->pv2)->x; + ve.y = ((polyvertex_t *)gr_curline->pv2)->y; + } + else + { + ve.x = FIXED_TO_FLOAT(gr_curline->v2->x); + ve.y = FIXED_TO_FLOAT(gr_curline->v2->y); + } #ifdef ESLOPE v1x = FLOAT_TO_FIXED(vs.x); @@ -2478,10 +2510,28 @@ static boolean CheckClip(sector_t * afrontsector, sector_t * abacksector) if (afrontsector->f_slope || afrontsector->c_slope || abacksector->f_slope || abacksector->c_slope) { fixed_t v1x, v1y, v2x, v2y; // the seg's vertexes as fixed_t - v1x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->x); - v1y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->y); - v2x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->x); - v2y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->y); + + if (gr_curline->pv1) + { + v1x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->x); + v1y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->y); + } + else + { + v1x = gr_curline->v1->x; + v1y = gr_curline->v1->y; + } + if (gr_curline->pv2) + { + v2x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->x); + v2y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->y); + } + else + { + v2x = gr_curline->v2->x; + v2y = gr_curline->v2->y; + } + #define SLOPEPARAMS(slope, end1, end2, normalheight) \ if (slope) { \ end1 = P_GetZAt(slope, v1x, v1y); \ @@ -2617,10 +2667,26 @@ void HWR_AddLine(seg_t *line) gr_curline = line; - v1x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->x); - v1y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->y); - v2x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->x); - v2y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->y); + if (gr_curline->pv1) + { + v1x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->x); + v1y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->y); + } + else + { + v1x = gr_curline->v1->x; + v1y = gr_curline->v1->y; + } + if (gr_curline->pv2) + { + v2x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->x); + v2y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->y); + } + else + { + v2x = gr_curline->v2->x; + v2y = gr_curline->v2->y; + } // OPTIMIZE: quickly reject orthogonal back sides. angle1 = R_PointToAngle64(v1x, v1y); -- 2.54.0 From d380391d80df2416403bea87f3d18e0c92a372b3 Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Thu, 19 Oct 2023 11:15:03 +0200 Subject: [PATCH 027/485] Clean up the backtrace code and make it use write() more safely. --- src/sdl/i_system.c | 77 +++++++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 32 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index c27dae519..4b943c932 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -259,71 +259,84 @@ SDL_bool framebuffer = SDL_FALSE; UINT8 keyboard_started = false; #ifdef UNIXBACKTRACE -#define STDERR_WRITE(string) if (fd != -1) I_OutputMsg("%s", string) -#define CRASHLOG_WRITE(string) if (fd != -1) write(fd, string, strlen(string)) -#define CRASHLOG_STDERR_WRITE(string) \ - if (fd != -1)\ - write(fd, string, strlen(string));\ - I_OutputMsg("%s", string) + +static void bt_write_file(int fd, const char *string) { + ssize_t written = 0; + ssize_t sourcelen = strlen(string); + + while (fd != -1 && (written != -1 && errno != EINTR) && written < sourcelen) + written = write(fd, string, sourcelen); +} + +static void bt_write_stderr(const char *string) { + bt_write_file(STDERR_FILENO, string); +} + +static void bt_write_all(int fd, const char *string) { + bt_write_file(fd, string); + bt_write_file(STDERR_FILENO, string); +} static void write_backtrace(INT32 signal) { int fd = -1; - size_t size; time_t rawtime; struct tm timeinfo; + size_t bt_size; enum { BT_SIZE = 1024, STR_SIZE = 32 }; - void *array[BT_SIZE]; + void *funcptrs[BT_SIZE]; char timestr[STR_SIZE]; - const char *error = "An error occurred within SRB2! Send this stack trace to someone who can help!\n"; - const char *error2 = "(Or find crash-log.txt in your SRB2 directory.)\n"; // Shown only to stderr. + const char *filename = va("%s" PATHSEP "%s", srb2home, "crash-log.txt"); - fd = open(va("%s" PATHSEP "%s", srb2home, "crash-log.txt"), O_CREAT|O_APPEND|O_RDWR, S_IRUSR|S_IWUSR); + fd = open(filename, O_CREAT|O_APPEND|O_RDWR, S_IRUSR|S_IWUSR); - if (fd == -1) - I_OutputMsg("\nWARNING: Couldn't open crash log for writing! Make sure your permissions are correct. Please save the below report!\n"); + if (fd == -1) // File handle error + bt_write_stderr("\nWARNING: Couldn't open crash log for writing! Make sure your permissions are correct. Please save the below report!\n"); // Get the current time as a string. time(&rawtime); localtime_r(&rawtime, &timeinfo); strftime(timestr, STR_SIZE, "%a, %d %b %Y %T %z", &timeinfo); - CRASHLOG_WRITE("------------------------\n"); // Nice looking seperator + bt_write_file(fd, "------------------------\n"); // Nice looking seperator - CRASHLOG_STDERR_WRITE("\n"); // Newline to look nice for both outputs. - CRASHLOG_STDERR_WRITE(error); // "Oops, SRB2 crashed" message - STDERR_WRITE(error2); // Tell the user where the crash log is. + bt_write_all(fd, "\n"); // Newline to look nice for both outputs. + bt_write_all(fd, "An error occurred within SRB2! Send this stack trace to someone who can help!\n"); + + if (fd != -1) // If the crash log exists, + bt_write_stderr("(Or find crash-log.txt in your SRB2 directory.)\n"); // tell the user where the crash log is. // Tell the log when we crashed. - CRASHLOG_WRITE("Time of crash: "); - CRASHLOG_WRITE(timestr); - CRASHLOG_WRITE("\n"); + bt_write_file(fd, "Time of crash: "); + bt_write_file(fd, timestr); + bt_write_file(fd, "\n"); // Give the crash log the cause and a nice 'Backtrace:' thing // The signal is given to the user when the parent process sees we crashed. - CRASHLOG_WRITE("Cause: "); - CRASHLOG_WRITE(strsignal(signal)); - CRASHLOG_WRITE("\n"); // Newline for the signal name + bt_write_file(fd, "Cause: "); + bt_write_file(fd, strsignal(signal)); + bt_write_file(fd, "\n"); // Newline for the signal name - CRASHLOG_STDERR_WRITE("\nBacktrace:\n"); + bt_write_all(fd, "\nBacktrace:\n"); // Flood the output and log with the backtrace - size = backtrace(array, BT_SIZE); - backtrace_symbols_fd(array, size, fd); - backtrace_symbols_fd(array, size, STDERR_FILENO); + bt_size = backtrace(funcptrs, BT_SIZE); + backtrace_symbols_fd(funcptrs, bt_size, fd); + backtrace_symbols_fd(funcptrs, bt_size, STDERR_FILENO); - CRASHLOG_WRITE("\n"); // Write another newline to the log so it looks nice :) + bt_write_file(fd, "\n"); // Write another newline to the log so it looks nice :) - close(fd); + if (fd != -1) { + fsync(fd); // reaaaaally make sure we got that data written. + close(fd); + } } -#undef STDERR_WRITE -#undef CRASHLOG_WRITE -#undef CRASHLOG_STDERR_WRITE #endif // UNIXBACKTRACE + static void I_ReportSignal(int num, int coredumped) { //static char msg[] = "oh no! back to reality!\r\n"; -- 2.54.0 From 581b503edf7a48239ad8aa6995dd5b179bcaabc9 Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Fri, 20 Oct 2023 07:45:00 +0200 Subject: [PATCH 028/485] Uncap palette lump palettes & allow flashpal palettes to display during pause --- src/st_stuff.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/st_stuff.c b/src/st_stuff.c index 98272c01c..9bc182d17 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -239,15 +239,11 @@ void ST_doPaletteStuff(void) { INT32 palette; - if (paused || P_AutoPause()) - palette = 0; - else if (stplyr && stplyr->flashcount) + if (stplyr && stplyr->flashcount) palette = stplyr->flashpal; else palette = 0; - palette = min(max(palette, 0), 13); - #ifdef HWRENDER if ((rendermode == render_opengl && !cv_grpaletteshader.value) || (rendermode == render_opengl && cv_grpaletteshader.value && !cv_grflashpal.value)) palette = 0; // No flashpals here in OpenGL -- 2.54.0 From 21c9ae8f7eac67b1540880af77f55ec8db5511c4 Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Fri, 20 Oct 2023 08:09:07 +0200 Subject: [PATCH 029/485] revert this again MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit despite what kk says, opengl sdl render hint is so much worse performancewise in software mode. some of the feedback we´ve gotten on saturn also more or less confirms this --- src/sdl/i_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 9676fca23..e5eea84fa 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1849,7 +1849,7 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen) // "direct3d" driver (D3D9) causes Drmingw exchndl // to not write RPT files. Every other driver // seems fine. - SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl"); + SDL_SetHint(SDL_HINT_RENDER_DRIVER, "direct3d11"); renderer = SDL_CreateRenderer(window, -1, flags); if (renderer == NULL) -- 2.54.0 From bfd0f0c7c2ee10629ea2f3679aa30ba8297f20da Mon Sep 17 00:00:00 2001 From: Indev Date: Fri, 20 Oct 2023 15:38:53 +0300 Subject: [PATCH 030/485] Fix wrong boolean constants used in W_CheckMultipleWads. That was causing compilation error on linux, and maybe on other non windows platforms --- src/w_wad.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/w_wad.c b/src/w_wad.c index f9e449268..0914ec963 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -1330,13 +1330,13 @@ UINT8 W_CheckMultipleLumps(const char* lump, ...) if (!W_LumpExists(lumpname)) { va_end(lumps); - return FALSE; + return false; } lumpname = va_arg(lumps, const char*); } va_end(lumps); - return TRUE; + return true; } size_t W_LumpLengthPwad(UINT16 wad, UINT16 lump) -- 2.54.0 From fec433372d9e6bcd1b2098044a6155365931c84d Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Sat, 21 Oct 2023 02:49:14 +0200 Subject: [PATCH 031/485] clean up shader stuff a bit Makes the game not "hard crash" when it fails to compile shaders Fixes issues with shader leveltime also fixes an issue where certain textures were blurred with shaders enables --- src/hardware/hw_defs.h | 9 + src/hardware/hw_drv.h | 74 ++-- src/hardware/hw_main.c | 47 +- src/hardware/r_opengl/r_opengl.c | 713 ++++++++++++++++++------------- src/sdl/hwsym_sdl.c | 2 + src/sdl/i_video.c | 2 + 6 files changed, 492 insertions(+), 355 deletions(-) diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index 6002fcf18..674ae876a 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -250,6 +250,15 @@ enum hwdsetspecialstate }; typedef enum hwdsetspecialstate hwdspecialstate_t; +// Lactozilla: Shader info +// Generally set at the start of the frame. +enum hwdshaderinfo +{ + HWD_SHADERINFO_LEVELTIME = 1, +}; + +typedef enum hwdshaderinfo hwdshaderinfo_t; + enum hwdportalstate { HWD_PORTAL_NORMAL, diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index d00055d59..bcf627236 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -39,6 +39,7 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUI EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags); EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FBOOLEAN StencilMask, FRGBAFloat *ClearColor); EXPORT void HWRAPI(SetTexture) (FTextureInfo *TexInfo); +EXPORT void HWRAPI(UpdateTexture) (FTextureInfo *TexInfo); EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 *dst_data); EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip, float farclip); EXPORT void HWRAPI(ClearMipMapCache) (void); @@ -74,8 +75,9 @@ EXPORT void HWRAPI(KillShaders) (void); EXPORT void HWRAPI(SetShader) (int shader); EXPORT void HWRAPI(UnSetShader) (void); +EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value); EXPORT void HWRAPI(LoadCustomShader) (int number, char *shader, size_t size, boolean fragment); -EXPORT void HWRAPI(InitCustomShaders) (void); +EXPORT boolean HWRAPI(InitCustomShaders) (void); EXPORT void HWRAPI(StartBatching) (void); EXPORT void HWRAPI(RenderBatches) (precise_t *sSortTime, precise_t *sDrawTime, int *sNumPolys, int *sNumVerts, int *sNumCalls, int *sNumShaders, int *sNumTextures, int *sNumPolyFlags, int *sNumColors); @@ -91,47 +93,49 @@ EXPORT void HWRAPI(ClearLightTableCache) (void); struct hwdriver_s { - Init pfnInit; - SetPalette pfnSetPalette; - FinishUpdate pfnFinishUpdate; - Draw2DLine pfnDraw2DLine; - DrawPolygon pfnDrawPolygon; - SetBlend pfnSetBlend; - ClearBuffer pfnClearBuffer; - SetTexture pfnSetTexture; - ReadRect pfnReadRect; - GClipRect pfnGClipRect; - ClearMipMapCache pfnClearMipMapCache; - SetSpecialState pfnSetSpecialState; - DrawModel pfnDrawModel; - CreateModelVBOs pfnCreateModelVBOs; - SetTransform pfnSetTransform; - GetTextureUsed pfnGetTextureUsed; - PostImgRedraw pfnPostImgRedraw; - FlushScreenTextures pfnFlushScreenTextures; - StartScreenWipe pfnStartScreenWipe; - EndScreenWipe pfnEndScreenWipe; - DoScreenWipe pfnDoScreenWipe; - DrawIntermissionBG pfnDrawIntermissionBG; - MakeScreenTexture pfnMakeScreenTexture; + Init pfnInit; + SetPalette pfnSetPalette; + FinishUpdate pfnFinishUpdate; + Draw2DLine pfnDraw2DLine; + DrawPolygon pfnDrawPolygon; + SetBlend pfnSetBlend; + ClearBuffer pfnClearBuffer; + SetTexture pfnSetTexture; + UpdateTexture pfnUpdateTexture; + ReadRect pfnReadRect; + GClipRect pfnGClipRect; + ClearMipMapCache pfnClearMipMapCache; + SetSpecialState pfnSetSpecialState; + DrawModel pfnDrawModel; + CreateModelVBOs pfnCreateModelVBOs; + SetTransform pfnSetTransform; + GetTextureUsed pfnGetTextureUsed; + PostImgRedraw pfnPostImgRedraw; + FlushScreenTextures pfnFlushScreenTextures; + StartScreenWipe pfnStartScreenWipe; + EndScreenWipe pfnEndScreenWipe; + DoScreenWipe pfnDoScreenWipe; + DrawIntermissionBG pfnDrawIntermissionBG; + MakeScreenTexture pfnMakeScreenTexture; MakeScreenFinalTexture pfnMakeScreenFinalTexture; DrawScreenFinalTexture pfnDrawScreenFinalTexture; - RenderSkyDome pfnRenderSkyDome; + RenderSkyDome pfnRenderSkyDome; - LoadShaders pfnLoadShaders; - KillShaders pfnKillShaders; - SetShader pfnSetShader; - UnSetShader pfnUnSetShader; + LoadShaders pfnLoadShaders; + KillShaders pfnKillShaders; + SetShader pfnSetShader; + UnSetShader pfnUnSetShader; - LoadCustomShader pfnLoadCustomShader; - InitCustomShaders pfnInitCustomShaders; + SetShaderInfo pfnSetShaderInfo; + LoadCustomShader pfnLoadCustomShader; + InitCustomShaders pfnInitCustomShaders; - StartBatching pfnStartBatching; - RenderBatches pfnRenderBatches; + StartBatching pfnStartBatching; + RenderBatches pfnRenderBatches; - AddLightTable pfnAddLightTable; - ClearLightTableCache pfnClearLightTableCache; + AddLightTable pfnAddLightTable; + ClearLightTableCache pfnClearLightTableCache; }; extern struct hwdriver_s hwdriver; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 9ef00afae..643c669c4 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -171,17 +171,23 @@ static void CV_screentextures_ONChange(void) static void CV_useCustomShaders_ONChange(void) { - if (rendermode == render_opengl) - HWD.pfnInitCustomShaders(); + if (rendermode == render_opengl) + { + if (cv_grshaders.value) + HWD.pfnInitCustomShaders(); + } } static void CV_grpaletteshader_OnChange(void) { - if (rendermode == render_opengl) + if (rendermode == render_opengl) { - HWD.pfnSetSpecialState(HWD_SET_PALETTE_SHADER_ENABLED, cv_grpaletteshader.value); - gr_use_palette_shader = cv_grpaletteshader.value; - V_SetPalette(0); + if (cv_grshaders.value) + { + HWD.pfnSetSpecialState(HWD_SET_PALETTE_SHADER_ENABLED, cv_grpaletteshader.value); + gr_use_palette_shader = cv_grpaletteshader.value; + V_SetPalette(0); + } } } @@ -1513,8 +1519,10 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom if (gr_backsector) { - INT32 gr_toptexture, gr_bottomtexture; + INT32 gr_toptexture = 0, gr_bottomtexture = 0; // two sided line + boolean bothceilingssky = false; // turned on if both back and front ceilings are sky + boolean bothfloorssky = false; // likewise, but for floors #ifdef ESLOPE SLOPEPARAMS(gr_backsector->c_slope, worldhigh, worldhighslope, gr_backsector->ceilingheight) @@ -1629,17 +1637,23 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom // hack to allow height changes in outdoor areas // This is what gets rid of the upper textures if there should be sky - if (gr_frontsector->ceilingpic == skyflatnum && - gr_backsector->ceilingpic == skyflatnum) + if (gr_frontsector->ceilingpic == skyflatnum + && gr_backsector->ceilingpic == skyflatnum) { - worldtop = worldhigh; -#ifdef ESLOPE - worldtopslope = worldhighslope; -#endif + bothceilingssky = true; } - gr_toptexture = R_GetTextureNum(gr_sidedef->toptexture); - gr_bottomtexture = R_GetTextureNum(gr_sidedef->bottomtexture); + // likewise, but for floors and upper textures + if (gr_frontsector->floorpic == skyflatnum + && gr_backsector->floorpic == skyflatnum) + { + bothfloorssky = true; + } + + if (!bothceilingssky) + gr_toptexture = R_GetTextureNum(gr_sidedef->toptexture); + if (!bothfloorssky) + gr_bottomtexture = R_GetTextureNum(gr_sidedef->bottomtexture); // check TOP TEXTURE if (( @@ -6170,6 +6184,9 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) HWD.pfnClearBuffer(true, false, false, &ClearColor); } + if (cv_grshaders.value) + HWD.pfnSetShaderInfo(HWD_SHADERINFO_LEVELTIME, (INT32)leveltime); // The water surface shader needs the leveltime. + if (viewnumber > 3) return; diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index e8ab8dcbd..32694737f 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -29,7 +29,7 @@ #include "../../v_video.h" // pLocalPalette #include "../../r_data.h" // NearestColor -#include "../../p_tick.h" // for leveltime (NOTE: THIS IS BAD, FIGURE OUT HOW TO PROPERLY IMPLEMENT gl_leveltime) +//#include "../../p_tick.h" // for leveltime (NOTE: THIS IS BAD, FIGURE OUT HOW TO PROPERLY IMPLEMENT gl_leveltime) #include "../../i_system.h" // for I_GetPreciseTime (batching time measurements) #include "../hw_main.h" @@ -109,7 +109,7 @@ const GLubyte *gl_extensions = NULL; //Hurdler: 04/10/2000: added for the kick ass coronas as Boris wanted;-) static GLfloat modelMatrix[16]; static GLfloat projMatrix[16]; -static GLint viewport[4]; +static GLint viewport[4]; #ifdef USE_PALETTED_TEXTURE PFNGLCOLORTABLEEXTPROC glColorTableEXT = NULL; @@ -125,6 +125,10 @@ static GLuint startScreenWipe = 0; static GLuint endScreenWipe = 0; static GLuint finalScreenTexture = 0; +// Lactozilla: Set shader programs and uniforms +static void *Shader_Load(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade); +static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade); + // shortcut for ((float)1/i) static const GLfloat byte2float[256] = { 0.000000f, 0.003922f, 0.007843f, 0.011765f, 0.015686f, 0.019608f, 0.023529f, 0.027451f, @@ -161,6 +165,7 @@ static const GLfloat byte2float[256] = { 0.972549f, 0.976471f, 0.980392f, 0.984314f, 0.988235f, 0.992157f, 0.996078f, 1.000000f }; + // -----------------+ // GL_DBG_Printf : Output debug messages to debug log if DEBUG_TO_FILE is defined, // : else do nothing @@ -168,7 +173,7 @@ static const GLfloat byte2float[256] = { // -----------------+ #ifdef DEBUG_TO_FILE -FILE *gllogstream = NULL; +FILE *gllogstream; #endif FUNCPRINTF void GL_DBG_Printf(const char *format, ...) @@ -177,19 +182,72 @@ FUNCPRINTF void GL_DBG_Printf(const char *format, ...) char str[4096] = ""; va_list arglist; - if (gllogstream) - { - va_start(arglist, format); - vsnprintf(str, 4096, format, arglist); - va_end(arglist); + if (!gllogstream) + gllogstream = fopen("ogllog.txt", "w"); + + va_start(arglist, format); + vsnprintf(str, 4096, format, arglist); + va_end(arglist); - fwrite(str, strlen(str), 1, gllogstream); - } + fwrite(str, strlen(str), 1, gllogstream); #else (void)format; #endif } + +// -----------------+ +// GL_MSG_Warning : Raises a warning. +// : +// Returns : +// -----------------+ + + +static void GL_MSG_Warning(const char *format, ...) +{ + char str[4096] = ""; + va_list arglist; + + va_start(arglist, format); + vsnprintf(str, 4096, format, arglist); + va_end(arglist); + +#ifdef HAVE_SDL + CONS_Alert(CONS_WARNING, "%s", str); +#endif +#ifdef DEBUG_TO_FILE + if (!gllogstream) + gllogstream = fopen("ogllog.txt", "w"); + fwrite(str, strlen(str), 1, gllogstream); +#endif +} + +// -----------------+ +// GL_MSG_Error : Raises an error. +// : +// Returns : +// -----------------+ + +static void GL_MSG_Error(const char *format, ...) +{ + char str[4096] = ""; + va_list arglist; + + va_start(arglist, format); + vsnprintf(str, 4096, format, arglist); + va_end(arglist); + +#ifdef HAVE_SDL + CONS_Alert(CONS_ERROR, "%s", str); +#endif +#ifdef DEBUG_TO_FILE + if (!gllogstream) + gllogstream = fopen("ogllog.txt", "w"); + fwrite(str, strlen(str), 1, gllogstream); +#endif +} + + #ifdef STATIC_OPENGL /* 1.0 functions */ /* Miscellaneous */ @@ -253,10 +311,7 @@ FUNCPRINTF void GL_DBG_Printf(const char *format, ...) #define pglTexParameteri glTexParameteri #define pglTexImage2D glTexImage2D #define pglTexImage3D glTexImage3D - -/* Fog */ -#define pglFogf glFogf -#define pglFogfv glFogfv +#define pglTexSubImage2D glTexSubImage2D /* 1.1 functions */ /* texture objects */ //GL_EXT_texture_object @@ -376,11 +431,8 @@ static PFNglTexImage2D pglTexImage2D; typedef void (APIENTRY * PFNglTexImage3D) (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); static PFNglTexImage3D pglTexImage3D; -/* Fog */ -typedef void (APIENTRY * PFNglFogf) (GLenum pname, GLfloat param); -static PFNglFogf pglFogf; -typedef void (APIENTRY * PFNglFogfv) (GLenum pname, const GLfloat *params); -static PFNglFogfv pglFogfv; +typedef void (APIENTRY * PFNglTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +static PFNglTexSubImage2D pglTexSubImage2D; /* 1.1 functions */ /* texture objects */ //GL_EXT_texture_object @@ -441,7 +493,7 @@ boolean SetupGLfunc(void) func = GetGLFunc(#proc); \ if (!func) \ { \ - GL_DBG_Printf("failed to get OpenGL function: %s\n", #proc); \ + GL_MSG_Warning("failed to get OpenGL function: %s", #proc); \ } \ GETOPENGLFUNC(pglClearColor, glClearColor) @@ -496,9 +548,7 @@ boolean SetupGLfunc(void) GETOPENGLFUNC(pglTexEnvi, glTexEnvi) GETOPENGLFUNC(pglTexParameteri, glTexParameteri) GETOPENGLFUNC(pglTexImage2D, glTexImage2D) - - GETOPENGLFUNC(pglFogf, glFogf) - GETOPENGLFUNC(pglFogfv, glFogfv) + GETOPENGLFUNC(pglTexSubImage2D , glTexSubImage2D) GETOPENGLFUNC(pglGenTextures, glGenTextures) GETOPENGLFUNC(pglDeleteTextures, glDeleteTextures) @@ -617,6 +667,9 @@ typedef struct gl_shaderprogram_s } gl_shaderprogram_t; static gl_shaderprogram_t gl_shaderprograms[MAXSHADERPROGRAMS]; +// Shader info +static INT32 shader_leveltime = 0; + // ======================== // Fragment shader macros // ======================== @@ -1013,7 +1066,10 @@ EXPORT boolean HWRAPI(LoadShaders) (void) // gl_vertShader = pglCreateShader(GL_VERTEX_SHADER); if (!gl_vertShader) - I_Error("Hardware driver: Error creating vertex shader %d", i); + { + GL_MSG_Error("LoadShaders: Error creating vertex shader %d\n", i); + continue; + } pglShaderSource(gl_vertShader, 1, &vert_shader, NULL); pglCompileShader(gl_vertShader); @@ -1030,7 +1086,8 @@ EXPORT boolean HWRAPI(LoadShaders) (void) infoLog = malloc(logLength); pglGetShaderInfoLog(gl_vertShader, logLength, NULL, infoLog); - I_Error("Hardware driver: Error compiling vertex shader %d\n%s", i, infoLog); + GL_MSG_Error("LoadShaders: Error compiling vertex shader %d\n%s", i, infoLog); + continue; } // @@ -1038,7 +1095,10 @@ EXPORT boolean HWRAPI(LoadShaders) (void) // gl_fragShader = pglCreateShader(GL_FRAGMENT_SHADER); if (!gl_fragShader) - I_Error("Hardware driver: Error creating fragment shader %d", i); + { + GL_MSG_Error("LoadShaders: Error creating fragment shader %d\n", i); + continue; + } pglShaderSource(gl_fragShader, 1, &frag_shader, NULL); pglCompileShader(gl_fragShader); @@ -1055,7 +1115,8 @@ EXPORT boolean HWRAPI(LoadShaders) (void) infoLog = malloc(logLength); pglGetShaderInfoLog(gl_fragShader, logLength, NULL, infoLog); - I_Error("Hardware driver: Error compiling fragment shader %d\n%s", i, infoLog); + GL_MSG_Error("LoadShaders: Error compiling fragment shader %d\n%s", i, infoLog); + continue; } shader = &gl_shaderprograms[i]; @@ -1067,12 +1128,19 @@ EXPORT boolean HWRAPI(LoadShaders) (void) // check link status pglGetProgramiv(shader->program, GL_LINK_STATUS, &result); - if (result != GL_TRUE) - I_Error("Hardware driver: Error linking shader program %d", i); // delete the shader objects pglDeleteShader(gl_vertShader); pglDeleteShader(gl_fragShader); + + // couldn't link? + if (result != GL_TRUE) + { + shader->program = 0; + shader->custom = false; + GL_MSG_Error("LoadShaders: Error linking shader program %d\n", i); + continue; + } // 13062019 #define GETUNI(uniform) pglGetUniformLocation(shader->program, uniform); @@ -1121,6 +1189,29 @@ EXPORT boolean HWRAPI(LoadShaders) (void) return true; } + +// +// Shader info +// Those are given to the uniforms. +// + +EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value) +{ +#ifdef GL_SHADERS + switch (info) + { + case HWD_SHADERINFO_LEVELTIME: + shader_leveltime = value; + break; + default: + break; + } +#else + (void)info; + (void)value; +#endif +} + // // Custom shader loading // @@ -1145,13 +1236,17 @@ EXPORT void HWRAPI(LoadCustomShader) (int number, char *shader, size_t size, boo strncpy(gl_customvertexshaders[number], shader, size); gl_customvertexshaders[number][size] = 0; } +#else + (void)number; + (void)shader; + (void)size; + (void)fragment; #endif } -EXPORT void HWRAPI(InitCustomShaders) (void) +EXPORT boolean HWRAPI(InitCustomShaders) (void) { #ifdef GL_SHADERS - KillShaders(); return LoadShaders(); @@ -1162,21 +1257,24 @@ EXPORT void HWRAPI(InitCustomShaders) (void) #endif } + EXPORT void HWRAPI(SetShader) (int shader) { #ifdef GL_SHADERS if (gl_allowshaders) { - gl_shadersenabled = true; if ((GLuint)shader != gl_currentshaderprogram) { gl_currentshaderprogram = shader; gl_shaderprogramchanged = true; } + gl_shadersenabled = true; + return; } - else +#else + (void)shader; #endif - gl_shadersenabled = false; + gl_shadersenabled = false; } EXPORT void HWRAPI(UnSetShader) (void) @@ -1351,9 +1449,6 @@ void SetModelView(GLint w, GLint h) screen_height = h; pglViewport(0, 0, w, h); -#ifdef GL_ACCUM_BUFFER_BIT - pglClear(GL_ACCUM_BUFFER_BIT); -#endif pglMatrixMode(GL_PROJECTION); pglLoadIdentity(); @@ -1816,6 +1911,211 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) } +// -----------------+ +// UpdateTexture : Updates the texture data. +// -----------------+ +EXPORT void HWRAPI(UpdateTexture) (FTextureInfo *pTexInfo) +{ + // Download a mipmap + boolean updatemipmap = true; + static RGBA_t tex[2048*2048]; + const GLvoid *ptex = tex; + INT32 w, h; + GLuint texnum = 0; + + if (!pTexInfo->downloaded) + { + pglGenTextures(1, &texnum); + pTexInfo->downloaded = texnum; + updatemipmap = false; + } + else + texnum = pTexInfo->downloaded; + + //GL_DBG_Printf ("DownloadMipmap %d %x\n",(INT32)texnum,pTexInfo->grInfo.data); + + w = pTexInfo->width; + h = pTexInfo->height; + + + if ((pTexInfo->grInfo.format == GR_TEXFMT_P_8) || + (pTexInfo->grInfo.format == GR_TEXFMT_AP_88)) + { + const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; + INT32 i, j; + + for (j = 0; j < h; j++) + { + for (i = 0; i < w; i++) + { + if ((*pImgData == HWR_PATCHES_CHROMAKEY_COLORINDEX) && + (pTexInfo->flags & TF_CHROMAKEYED)) + { + tex[w*j+i].s.red = 0; + 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 + { + tex[w*j+i].s.red = myPaletteData[*pImgData].s.red; + tex[w*j+i].s.green = myPaletteData[*pImgData].s.green; + tex[w*j+i].s.blue = myPaletteData[*pImgData].s.blue; + tex[w*j+i].s.alpha = myPaletteData[*pImgData].s.alpha; + } + + pImgData++; + + if (pTexInfo->grInfo.format == GR_TEXFMT_AP_88) + { + if (!(pTexInfo->flags & TF_CHROMAKEYED)) + tex[w*j+i].s.alpha = *pImgData; + pImgData++; + } + + } + } + } + else if (pTexInfo->grInfo.format == GR_RGBA) + { + // corona test : passed as ARGB 8888, which is not in glide formats + // Hurdler: not used for coronas anymore, just for dynamic lighting + ptex = pTexInfo->grInfo.data; + } + else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_INTENSITY_88) + { + const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; + INT32 i, j; + + for (j = 0; j < h; j++) + { + for (i = 0; i < w; i++) + { + tex[w*j+i].s.red = *pImgData; + tex[w*j+i].s.green = *pImgData; + tex[w*j+i].s.blue = *pImgData; + pImgData++; + tex[w*j+i].s.alpha = *pImgData; + pImgData++; + } + } + } + else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_8) // Used for fade masks + { + const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; + INT32 i, j; + + for (j = 0; j < h; j++) + { + for (i = 0; i < w; i++) + { + tex[w*j+i].s.red = 255; // 255 because the fade mask is modulated with the screen texture, so alpha affects it while the colours don't + tex[w*j+i].s.green = 255; + tex[w*j+i].s.blue = 255; + tex[w*j+i].s.alpha = *pImgData; + pImgData++; + } + } + } + else + GL_MSG_Warning ("SetTexture(bad format) %ld\n", pTexInfo->grInfo.format); + + + // the texture number was already generated by pglGenTextures + pglBindTexture(GL_TEXTURE_2D, texnum); + tex_downloaded = texnum; + + // disable texture filtering on any texture that has holes so there's no dumb borders or blending issues + if (pTexInfo->flags & TF_TRANSPARENT) + { + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + else + { + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter); + } + + if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_INTENSITY_88) + { + //pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + if (MipMap) + { + pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); + if (pTexInfo->flags & TF_TRANSPARENT) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff + else + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4); + //pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR_MIPMAP_LINEAR); + } + else + { + if (updatemipmap) + pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + else + pglTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + } + } + else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_8) + { + //pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + if (MipMap) + { + pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_ALPHA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); + if (pTexInfo->flags & TF_TRANSPARENT) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff + else + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4); + //pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR_MIPMAP_LINEAR); + } + else + { + if (updatemipmap) + pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + else + pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + } + } + else + { + if (MipMap) + { + pgluBuild2DMipmaps(GL_TEXTURE_2D, textureformatGL, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + // Control the mipmap level of detail + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); // the lower the number, the higer the detail + if (pTexInfo->flags & TF_TRANSPARENT) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff + else + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 5); + } + else + { + if (updatemipmap) + pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + else + pglTexImage2D(GL_TEXTURE_2D, 0, textureformatGL, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + } + } + + if (pTexInfo->flags & TF_WRAPX) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + else + Clamp2D(GL_TEXTURE_WRAP_S); + + if (pTexInfo->flags & TF_WRAPY) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + else + Clamp2D(GL_TEXTURE_WRAP_T); + + if (maximumAnisotropy) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropic_filter); +} + + // -----------------+ // SetTexture : The mipmap becomes the current texture source // -----------------+ @@ -1830,220 +2130,13 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) { if (pTexInfo->downloaded != tex_downloaded) { - if (!gl_batching) - pglBindTexture(GL_TEXTURE_2D, pTexInfo->downloaded); + pglBindTexture(GL_TEXTURE_2D, pTexInfo->downloaded); tex_downloaded = pTexInfo->downloaded; } } else { - // Download a mipmap - static RGBA_t tex[2048*2048]; - const GLvoid *ptex = tex; - INT32 w, h; - GLuint texnum = 0; - - pglGenTextures(1, &texnum); - //GL_DBG_Printf("DownloadMipmap %d\n", (INT32)texnum, pTexInfo->grInfo.data); - - w = pTexInfo->width; - h = pTexInfo->height; - -#ifdef USE_PALETTED_TEXTURE - if (glColorTableEXT && - (pTexInfo->grInfo.format == GR_TEXFMT_P_8) && - !(pTexInfo->flags & TF_CHROMAKEYED)) - { - // do nothing here. - // Not a problem with MiniGL since we don't use paletted texture - } - else -#endif - - if ((pTexInfo->grInfo.format == GR_TEXFMT_P_8) || - (pTexInfo->grInfo.format == GR_TEXFMT_AP_88)) - { - const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; - INT32 i, j; - - for (j = 0; j < h; j++) - { - for (i = 0; i < w; i++) - { - if ((*pImgData == HWR_PATCHES_CHROMAKEY_COLORINDEX) && - (pTexInfo->flags & TF_CHROMAKEYED)) - { - tex[w*j+i].s.red = 0; - 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 - { - tex[w*j+i].s.red = myPaletteData[*pImgData].s.red; - tex[w*j+i].s.green = myPaletteData[*pImgData].s.green; - tex[w*j+i].s.blue = myPaletteData[*pImgData].s.blue; - tex[w*j+i].s.alpha = myPaletteData[*pImgData].s.alpha; - } - - pImgData++; - - if (pTexInfo->grInfo.format == GR_TEXFMT_AP_88) - { - if (!(pTexInfo->flags & TF_CHROMAKEYED)) - tex[w*j+i].s.alpha = *pImgData; - pImgData++; - } - - } - } - } - else if (pTexInfo->grInfo.format == GR_RGBA) - { - // corona test : passed as ARGB 8888, which is not in glide formats - // Hurdler: not used for coronas anymore, just for dynamic lighting - ptex = pTexInfo->grInfo.data; - } - else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_INTENSITY_88) - { - const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; - INT32 i, j; - - for (j = 0; j < h; j++) - { - for (i = 0; i < w; i++) - { - tex[w*j+i].s.red = *pImgData; - tex[w*j+i].s.green = *pImgData; - tex[w*j+i].s.blue = *pImgData; - pImgData++; - tex[w*j+i].s.alpha = *pImgData; - pImgData++; - } - } - } - else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_8) // Used for fade masks - { - const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; - INT32 i, j; - - for (j = 0; j < h; j++) - { - for (i = 0; i < w; i++) - { - tex[w*j+i].s.red = 255; // 255 because the fade mask is modulated with the screen texture, so alpha affects it while the colours don't - tex[w*j+i].s.green = 255; - tex[w*j+i].s.blue = 255; - tex[w*j+i].s.alpha = *pImgData; - pImgData++; - } - } - } - else - GL_DBG_Printf("SetTexture(bad format) %ld\n", pTexInfo->grInfo.format); - - // the texture number was already generated by pglGenTextures - pglBindTexture(GL_TEXTURE_2D, texnum); - pTexInfo->downloaded = texnum; - tex_downloaded = texnum; - - // disable texture filtering on any texture that has holes so there's no dumb borders or blending issues - if (pTexInfo->flags & TF_TRANSPARENT) - { - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - } - else - { - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter); - } - -#ifdef USE_PALETTED_TEXTURE - //Hurdler: not really supported and not tested recently - if (glColorTableEXT && - (pTexInfo->grInfo.format == GR_TEXFMT_P_8) && - !(pTexInfo->flags & TF_CHROMAKEYED)) - { - glColorTableEXT(GL_TEXTURE_2D, GL_RGB8, 256, GL_RGB, GL_UNSIGNED_BYTE, palette_tex); - pglTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, w, h, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, pTexInfo->grInfo.data); - } - else -#endif - if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_INTENSITY_88) - { - //pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - if (MipMap) - { - pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); -#ifdef GL_TEXTURE_MIN_LOD - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); -#endif -#ifdef GL_TEXTURE_MAX_LOD - if (pTexInfo->flags & TF_TRANSPARENT) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff - else - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4); -#endif - //pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR_MIPMAP_LINEAR); - } - else - pglTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - } - else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_8) - { - //pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - if (MipMap) - { - pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_ALPHA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); -#ifdef GL_TEXTURE_MIN_LOD - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); -#endif -#ifdef GL_TEXTURE_MAX_LOD - if (pTexInfo->flags & TF_TRANSPARENT) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff - else - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4); -#endif - //pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR_MIPMAP_LINEAR); - } - else - pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - } - else - { - if (MipMap) - { - pgluBuild2DMipmaps(GL_TEXTURE_2D, textureformatGL, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - // Control the mipmap level of detail -#ifdef GL_TEXTURE_MIN_LOD - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); // the lower the number, the higer the detail -#endif -#ifdef GL_TEXTURE_MAX_LOD - if (pTexInfo->flags & TF_TRANSPARENT) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff - else - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 5); -#endif - } - else - pglTexImage2D(GL_TEXTURE_2D, 0, textureformatGL, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - } - - if (pTexInfo->flags & TF_WRAPX) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - else - Clamp2D(GL_TEXTURE_WRAP_S); - - if (pTexInfo->flags & TF_WRAPY) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - else - Clamp2D(GL_TEXTURE_WRAP_T); - - if (maximumAnisotropy) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropic_filter); - + UpdateTexture(pTexInfo); pTexInfo->nextmipmap = NULL; if (gr_cachetail) { // insertion at the tail @@ -2055,7 +2148,8 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) } } -static void load_shaders(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade) + +static void *Shader_Load(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade) { #ifdef GL_SHADERS if (gl_shadersenabled && pglUseProgram) @@ -2063,68 +2157,77 @@ static void load_shaders(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat * gl_shaderprogram_t *shader = &gl_shaderprograms[gl_currentshaderprogram]; if (shader->program) { - boolean custom = (gl_shaderprograms[gl_currentshaderprogram].custom); - // 13062019 - // Check for fog - //if (changed) + if (gl_shaderprogramchanged) { - if (!custom) - { - if (gl_shaderprogramchanged) - { - pglUseProgram(gl_shaderprograms[gl_currentshaderprogram].program); - gl_shaderprogramchanged = false; - } - } - else // always load custom shaders - { - if (gl_shaderprogramchanged) - { - pglUseProgram(gl_shaderprograms[gl_currentshaderprogram].program); - gl_shaderprogramchanged = false; - } - } - } - - // set uniforms - { - #define UNIFORM_1(uniform, a, function) \ - if (uniform != -1) \ - function (uniform, a); - - #define UNIFORM_2(uniform, a, b, function) \ - if (uniform != -1) \ - function (uniform, a, b); - - #define UNIFORM_3(uniform, a, b, c, function) \ - if (uniform != -1) \ - function (uniform, a, b, c); - - #define UNIFORM_4(uniform, a, b, c, d, function) \ - if (uniform != -1) \ - function (uniform, a, b, c, d); - - // polygon - UNIFORM_4(shader->uniforms[gluniform_poly_color], poly->red, poly->green, poly->blue, poly->alpha, pglUniform4f); - UNIFORM_4(shader->uniforms[gluniform_tint_color], tint->red, tint->green, tint->blue, tint->alpha, pglUniform4f); - UNIFORM_4(shader->uniforms[gluniform_fade_color], fade->red, fade->green, fade->blue, fade->alpha, pglUniform4f); - UNIFORM_1(shader->uniforms[gluniform_lighting], Surface->LightInfo.light_level, pglUniform1f); - UNIFORM_1(shader->uniforms[gluniform_fade_start], Surface->LightInfo.fade_start, pglUniform1f); - UNIFORM_1(shader->uniforms[gluniform_fade_end], Surface->LightInfo.fade_end, pglUniform1f); - UNIFORM_1(shader->uniforms[gluniform_leveltime], ((float)leveltime) / TICRATE, pglUniform1f); - - #undef UNIFORM_1 - #undef UNIFORM_2 - #undef UNIFORM_3 - #undef UNIFORM_4 + pglUseProgram(gl_shaderprograms[gl_currentshaderprogram].program); + gl_shaderprogramchanged = false; } + Shader_SetUniforms(Surface, poly, tint, fade); + return shader; } else pglUseProgram(0); } +#else + (void)Surface; + (void)poly; + (void)tint; + (void)fade; +#endif + return NULL; +} + +static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade) +{ +#ifdef GL_SHADERS + if (gl_shadersenabled) + { + gl_shaderprogram_t *shader = &gl_shaderprograms[gl_currentshaderprogram]; + if (!shader->program) + return; + + #define UNIFORM_1(uniform, a, function) \ + if (uniform != -1) \ + function (uniform, a); + + #define UNIFORM_2(uniform, a, b, function) \ + if (uniform != -1) \ + function (uniform, a, b); + + #define UNIFORM_3(uniform, a, b, c, function) \ + if (uniform != -1) \ + function (uniform, a, b, c); + + #define UNIFORM_4(uniform, a, b, c, d, function) \ + if (uniform != -1) \ + function (uniform, a, b, c, d); + + // polygon + UNIFORM_4(shader->uniforms[gluniform_poly_color], poly->red, poly->green, poly->blue, poly->alpha, pglUniform4f); + UNIFORM_4(shader->uniforms[gluniform_tint_color], tint->red, tint->green, tint->blue, tint->alpha, pglUniform4f); + UNIFORM_4(shader->uniforms[gluniform_fade_color], fade->red, fade->green, fade->blue, fade->alpha, pglUniform4f); + if (Surface != NULL) + { + UNIFORM_1(shader->uniforms[gluniform_lighting], Surface->LightInfo.light_level, pglUniform1f); + UNIFORM_1(shader->uniforms[gluniform_fade_start], Surface->LightInfo.fade_start, pglUniform1f); + UNIFORM_1(shader->uniforms[gluniform_fade_end], Surface->LightInfo.fade_end, pglUniform1f); + } + UNIFORM_1(shader->uniforms[gluniform_leveltime], ((float)shader_leveltime) / TICRATE, pglUniform1f); + + #undef UNIFORM_1 + #undef UNIFORM_2 + #undef UNIFORM_3 + #undef UNIFORM_4 + } +#else + (void)Surface; + (void)poly; + (void)tint; + (void)fade; #endif } + // unfinished draw call batching // Note: could use realloc in the array reallocation code @@ -2342,7 +2445,7 @@ EXPORT void HWRAPI(RenderBatches) (precise_t *sSortTime, precise_t *sDrawTime, i if (gl_allowshaders) { - load_shaders(¤tSurfaceInfo, &firstPoly, &firstTint, &firstFade); + Shader_Load(¤tSurfaceInfo, &firstPoly, &firstTint, &firstFade); if (gl_use_palette_shader) { pglActiveTexture(GL_TEXTURE2);// this stuff could be done better but gonna do it quick like this for now @@ -2551,7 +2654,7 @@ EXPORT void HWRAPI(RenderBatches) (precise_t *sSortTime, precise_t *sDrawTime, i fade.blue = byte2float[nextSurfaceInfo.FadeColor.s.blue]; fade.alpha = byte2float[nextSurfaceInfo.FadeColor.s.alpha]; - load_shaders(&nextSurfaceInfo, &poly, &tint, &fade); + Shader_Load(&nextSurfaceInfo, &poly, &tint, &fade); currentShader = nextShader; changeShader = false; @@ -2603,7 +2706,7 @@ EXPORT void HWRAPI(RenderBatches) (precise_t *sSortTime, precise_t *sDrawTime, i fade.blue = byte2float[nextSurfaceInfo.FadeColor.s.blue]; fade.alpha = byte2float[nextSurfaceInfo.FadeColor.s.alpha]; - load_shaders(&nextSurfaceInfo, &poly, &tint, &fade); + Shader_Load(&nextSurfaceInfo, &poly, &tint, &fade); if (gl_use_palette_shader) { @@ -2721,7 +2824,7 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUI } } - load_shaders(pSurf, &poly, &tint, &fade); + Shader_Load(pSurf, &poly, &tint, &fade); } else UnSetShader(); @@ -3468,7 +3571,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float fade.blue = byte2float[Surface->FadeColor.s.blue]; fade.alpha = byte2float[Surface->FadeColor.s.alpha]; - load_shaders(Surface, &poly, &tint, &fade); + Shader_Load(Surface, &poly, &tint, &fade); pglEnable(GL_CULL_FACE); pglEnable(GL_NORMALIZE); diff --git a/src/sdl/hwsym_sdl.c b/src/sdl/hwsym_sdl.c index dcaaa7f51..4af37ee42 100644 --- a/src/sdl/hwsym_sdl.c +++ b/src/sdl/hwsym_sdl.c @@ -83,6 +83,7 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(SetBlend); GETFUNC(ClearBuffer); GETFUNC(SetTexture); + GETFUNC(UpdateTexture); GETFUNC(ReadRect); GETFUNC(GClipRect); GETFUNC(ClearMipMapCache); @@ -108,6 +109,7 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(SetShader); GETFUNC(UnSetShader); + GETFUNC(SetShaderInfo); GETFUNC(LoadCustomShader); GETFUNC(InitCustomShaders); diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index e5eea84fa..8a5e37afb 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -2117,6 +2117,7 @@ void I_StartupGraphics(void) HWD.pfnSetBlend = hwSym("SetBlend",NULL); HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL); HWD.pfnSetTexture = hwSym("SetTexture",NULL); + HWD.pfnUpdateTexture = hwSym("UpdateTexture",NULL); HWD.pfnReadRect = hwSym("ReadRect",NULL); HWD.pfnGClipRect = hwSym("GClipRect",NULL); HWD.pfnClearMipMapCache = hwSym("ClearMipMapCache",NULL); @@ -2143,6 +2144,7 @@ void I_StartupGraphics(void) HWD.pfnSetShader = hwSym("SetShader",NULL); HWD.pfnUnSetShader = hwSym("UnSetShader",NULL); + HWD.pfnSetShaderInfo = hwSym("SetShaderInfo",NULL); HWD.pfnLoadCustomShader = hwSym("LoadCustomShader",NULL); HWD.pfnInitCustomShaders = hwSym("InitCustomShaders",NULL); -- 2.54.0 From 7b136a62c47aec4d336ae5830c72140bfbc48ce4 Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Sat, 21 Oct 2023 03:05:30 +0200 Subject: [PATCH 032/485] revert this part well with how some kart mapss are set up, this doesent work out --- src/hardware/hw_main.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 643c669c4..2a4844ff9 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1519,10 +1519,8 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom if (gr_backsector) { - INT32 gr_toptexture = 0, gr_bottomtexture = 0; + INT32 gr_toptexture, gr_bottomtexture; // two sided line - boolean bothceilingssky = false; // turned on if both back and front ceilings are sky - boolean bothfloorssky = false; // likewise, but for floors #ifdef ESLOPE SLOPEPARAMS(gr_backsector->c_slope, worldhigh, worldhighslope, gr_backsector->ceilingheight) @@ -1640,20 +1638,14 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom if (gr_frontsector->ceilingpic == skyflatnum && gr_backsector->ceilingpic == skyflatnum) { - bothceilingssky = true; + worldtop = worldhigh; +#ifdef ESLOPE + worldtopslope = worldhighslope; +#endif } - // likewise, but for floors and upper textures - if (gr_frontsector->floorpic == skyflatnum - && gr_backsector->floorpic == skyflatnum) - { - bothfloorssky = true; - } - - if (!bothceilingssky) - gr_toptexture = R_GetTextureNum(gr_sidedef->toptexture); - if (!bothfloorssky) - gr_bottomtexture = R_GetTextureNum(gr_sidedef->bottomtexture); + gr_toptexture = R_GetTextureNum(gr_sidedef->toptexture); + gr_bottomtexture = R_GetTextureNum(gr_sidedef->bottomtexture); // check TOP TEXTURE if (( -- 2.54.0 From 7c6b03145d2b7cbabf125283e2f2e67881795ce3 Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Sat, 21 Oct 2023 03:20:23 +0200 Subject: [PATCH 033/485] uncap water effects also caps software heatwave effect since it was sped up with interp note : waterofs was left out, due to it producing stutters on water surfaces in softwaremode --- src/hardware/hw_main.c | 4 +--- src/hardware/r_opengl/r_opengl.c | 7 ++++--- src/r_plane.c | 2 +- src/v_video.c | 10 +++++++--- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 2a4844ff9..ca9ed609b 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -6378,7 +6378,7 @@ void HWR_DoPostProcessor(player_t *player) { // 10 by 10 grid. 2 coordinates (xy) float v[SCREENVERTS][SCREENVERTS][2]; - static double disStart = 0; + float disStart = (leveltime-1) + FIXED_TO_FLOAT(rendertimefrac); UINT8 x, y; INT32 WAVELENGTH; @@ -6409,8 +6409,6 @@ void HWR_DoPostProcessor(player_t *player) } } HWD.pfnPostImgRedraw(v); - if (!(paused || P_AutoPause())) - disStart += FIXED_TO_FLOAT(renderdeltatics); // Capture the screen again for screen waving on the intermission if(gamestate != GS_INTERMISSION) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 32694737f..bb051fa23 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -23,6 +23,7 @@ #include #include +#include "../../r_local.h" // For rendertimefrac, used for the leveltime shader uniform #include "r_opengl.h" #include "r_vbo.h" @@ -668,7 +669,7 @@ typedef struct gl_shaderprogram_s static gl_shaderprogram_t gl_shaderprograms[MAXSHADERPROGRAMS]; // Shader info -static INT32 shader_leveltime = 0; +static float shader_leveltime = 0; // ======================== // Fragment shader macros @@ -1201,7 +1202,7 @@ EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value) switch (info) { case HWD_SHADERINFO_LEVELTIME: - shader_leveltime = value; + shader_leveltime = (((float)(value-1)) + FIXED_TO_FLOAT(rendertimefrac)) / TICRATE; break; default: break; @@ -2212,7 +2213,7 @@ static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAF UNIFORM_1(shader->uniforms[gluniform_fade_start], Surface->LightInfo.fade_start, pglUniform1f); UNIFORM_1(shader->uniforms[gluniform_fade_end], Surface->LightInfo.fade_end, pglUniform1f); } - UNIFORM_1(shader->uniforms[gluniform_leveltime], ((float)shader_leveltime) / TICRATE, pglUniform1f); + UNIFORM_1(shader->uniforms[gluniform_leveltime], shader_leveltime, pglUniform1f); #undef UNIFORM_1 #undef UNIFORM_2 diff --git a/src/r_plane.c b/src/r_plane.c index 096b5f0a9..3578bd7b4 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -698,7 +698,7 @@ void R_DrawPlanes(void) } #ifndef NOWATER waterofs = (leveltime & 1)*16384; - wtofs = leveltime * 140; + wtofs = ((leveltime-1)*140) + ((rendertimefrac*140) / FRACUNIT); #endif } diff --git a/src/v_video.c b/src/v_video.c index 21d286ba7..8950fdf9d 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -2645,7 +2645,8 @@ void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param) UINT8 *tmpscr = screens[4]; UINT8 *srcscr = screens[0]; INT32 y; - angle_t disStart = (leveltime * 128) & FINEMASK; // in 0 to FINEANGLE + // Set disStart to a range from 0 to FINEANGLE, incrementing by 128 per tic + angle_t disStart = (((leveltime-1)*128) + (rendertimefrac / (FRACUNIT/128))) & FINEMASK; INT32 newpix; INT32 sine; //UINT8 *transme = transtables + ((tr_trans50-1)< Date: Sat, 21 Oct 2023 11:42:19 +0200 Subject: [PATCH 034/485] Join last server button in multiplayer menu (thx nep c:) from: https://github.com/NepDisk/srb2k-planeptune/commit/3f42ca357e16702a47a1197a738d92741b38950f also now finally works with server browser --- src/d_netcmd.c | 6 ++++++ src/d_netcmd.h | 3 +++ src/m_menu.c | 36 ++++++++++++++++++++++++++++++------ 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 6756c4517..27e3613ed 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -375,6 +375,9 @@ consvar_t cv_tripleorbinaut = {"tripleorbinaut", "On", CV_NETVAR|CV_CHEAT, C consvar_t cv_quadorbinaut = {"quadorbinaut", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_dualjawz = {"dualjawz", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +//Save server ip +consvar_t cv_lastserver = {"lastserver", "", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; + static CV_PossibleValue_t kartminimap_cons_t[] = {{0, "MIN"}, {10, "MAX"}, {0, NULL}}; consvar_t cv_kartminimap = {"kartminimap", "4", CV_SAVE, kartminimap_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_kartcheck = {"kartcheck", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -1104,6 +1107,9 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_resume); CV_RegisterVar(&cv_fading); + //Value used to store last server player has joined + CV_RegisterVar(&cv_lastserver); + CV_RegisterVar(&cv_showallmaps); // ingame object placing diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 1474788a2..83f3cb5a1 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -111,6 +111,9 @@ extern consvar_t cv_thundershield, cv_hyudoro, cv_pogospring, cv_kitchensink; extern consvar_t cv_triplesneaker, cv_triplebanana, cv_decabanana; extern consvar_t cv_tripleorbinaut, cv_quadorbinaut, cv_dualjawz; +//Lastserver +extern consvar_t cv_lastserver; + extern consvar_t cv_kartminimap; extern consvar_t cv_kartcheck; extern consvar_t cv_kartinvinsfx; diff --git a/src/m_menu.c b/src/m_menu.c index fce86a854..44ffa8870 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -21,6 +21,8 @@ #include "doomdef.h" #include "d_main.h" #include "d_netcmd.h" +#include "d_clisrv.h" +#include "i_net.h" #include "console.h" #include "r_fps.h" #include "r_local.h" @@ -425,6 +427,7 @@ static void M_HandleImageDef(INT32 choice); static void M_HandleLevelStats(INT32 choice); #ifndef NONET static void M_HandleConnectIP(INT32 choice); +static void M_ConnectLastServer(INT32 choice); #endif static void M_HandleSetupMultiPlayer(INT32 choice); static void M_HandleVideoMode(INT32 choice); @@ -1045,10 +1048,12 @@ static menuitem_t MP_MainMenu[] = {IT_HEADER, NULL, "Join a game", NULL, 132-24}, #ifndef NONET {IT_STRING|IT_CALL, NULL, "Internet server browser...",M_PreConnectMenu, 142-24}, - {IT_STRING|IT_KEYHANDLER, NULL, "Specify IPv4 address:", M_HandleConnectIP, 150-24}, + {IT_STRING|IT_CALL, NULL, "Join last server", M_ConnectLastServer, 150-24}, + {IT_STRING|IT_KEYHANDLER, NULL, "Specify IPv4 address:", M_HandleConnectIP, 158-24}, #else {IT_GRAYEDOUT, NULL, "Internet server browser...",NULL, 142-24}, - {IT_GRAYEDOUT, NULL, "Specify IPv4 address:", NULL, 150-24}, + {IT_GRAYEDOUT, NULL, "Join last server", NULL, 150-24}, + {IT_GRAYEDOUT, NULL, "Specify IPv4 address:", NULL, 158-24}, #endif //{IT_HEADER, NULL, "Player setup", NULL, 80}, //{IT_STRING|IT_CALL, NULL, "Name, character, color...", M_SetupMultiPlayer, 90}, @@ -9069,8 +9074,10 @@ static void M_Connect(INT32 choice) { // do not call menuexitfunc M_ClearMenus(false); - - COM_BufAddText(va("connect node %d\n", serverlist[choice-FIRSTSERVERLINE + serverlistpage * SERVERS_PER_PAGE].node)); + + CV_Set(&cv_lastserver, I_GetNodeAddress(serverlist[choice-FIRSTSERVERLINE + serverlistpage * SERVERS_PER_PAGE].node)); + + COM_BufAddText(va("connect node %d\n", serverlist[choice-FIRSTSERVERLINE + serverlistpage * SERVERS_PER_PAGE].node)); } static void M_Refresh(INT32 choice) @@ -9780,7 +9787,7 @@ Update the maxplayers label... ); #ifndef NONET - y += MP_MainMenu[8].alphaKey; + y += MP_MainMenu[9].alphaKey; V_DrawFill(x+5, y+4+5, /*16*8 + 6,*/ BASEVIDWIDTH - 2*(x+5), 8+6, 239); @@ -9788,7 +9795,7 @@ Update the maxplayers label... V_DrawString(x+8,y+12, V_ALLOWLOWERCASE, setupm_ip); // draw text cursor for name - if (itemOn == 8 + if (itemOn == 9 && skullAnimCounter < 4) //blink cursor V_DrawCharacter(x+8+V_StringWidth(setupm_ip, V_ALLOWLOWERCASE),y+12,'_',false); #endif @@ -9947,6 +9954,7 @@ static void M_ConnectIP(INT32 choice) M_ClearMenus(true); + CV_Set(&cv_lastserver,setupm_ip); COM_BufAddText(va("connect \"%s\"\n", setupm_ip)); // A little "please wait" message. @@ -9958,6 +9966,22 @@ static void M_ConnectIP(INT32 choice) I_FinishUpdate(); // page flip or blit buffer } + +//Join Last server +static void M_ConnectLastServer(INT32 choice) +{ + (void)choice; + + if (!*cv_lastserver.string) + { + M_StartMessage("You haven't previosuly joined a server.\n", NULL, MM_NOTHING); + return; + } + + M_ClearMenus(true); + COM_BufAddText(va("connect \"%s\"\n", cv_lastserver.string)); +} + // Tails 11-19-2002 static void M_HandleConnectIP(INT32 choice) { -- 2.54.0 From 7ebccc19dba946f74504b79fa62c7748a93f268c Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Sat, 21 Oct 2023 12:06:43 +0200 Subject: [PATCH 035/485] fixuer de typo --- src/m_menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index 44ffa8870..0c7e696e1 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -9974,7 +9974,7 @@ static void M_ConnectLastServer(INT32 choice) if (!*cv_lastserver.string) { - M_StartMessage("You haven't previosuly joined a server.\n", NULL, MM_NOTHING); + M_StartMessage("You haven't previously joined a server.\n", NULL, MM_NOTHING); return; } -- 2.54.0 From 2cec4c8b5202c99951f324d1128cf69aeda40f4f Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Sat, 21 Oct 2023 12:12:35 +0200 Subject: [PATCH 036/485] add M_DrawGenericScrollMenu will most likely need this since saturn menu esp is starting to fill up --- src/m_menu.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/src/m_menu.c b/src/m_menu.c index 0c7e696e1..c93981078 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -384,6 +384,7 @@ static UINT8 playback_enterheld = 0; // horrid hack to prevent holding the butto // Drawing functions static void M_DrawGenericMenu(void); static void M_DrawGenericBackgroundMenu(void); +static void M_DrawGenericScrollMenu(void); static void M_DrawCenteredMenu(void); static void M_DrawAddons(void); static void M_DrawSkyRoom(void); @@ -4406,6 +4407,139 @@ static void M_DrawGenericBackgroundMenu(void) M_DrawGenericMenu(); } +#define scrollareaheight 72 + +// note that alphakey is multiplied by 2 for scrolling menus to allow greater usage in UINT8 range. +static void M_DrawGenericScrollMenu(void) +{ + INT32 x, y, i, max, bottom, tempcentery, cursory = 0; + + // DRAW MENU + x = currentMenu->x; + y = currentMenu->y; + + if (currentMenu->menuitems[currentMenu->numitems-1].alphaKey < scrollareaheight) + tempcentery = currentMenu->y; // Not tall enough to scroll, but this thinker is used in case it becomes so + else if ((currentMenu->menuitems[itemOn].alphaKey*2 - currentMenu->menuitems[0].alphaKey*2) <= scrollareaheight) + tempcentery = currentMenu->y - currentMenu->menuitems[0].alphaKey*2; + else if ((currentMenu->menuitems[currentMenu->numitems-1].alphaKey*2 - currentMenu->menuitems[itemOn].alphaKey*2) <= scrollareaheight) + tempcentery = currentMenu->y - currentMenu->menuitems[currentMenu->numitems-1].alphaKey*2 + 2*scrollareaheight; + else + tempcentery = currentMenu->y - currentMenu->menuitems[itemOn].alphaKey*2 + scrollareaheight; + + for (i = 0; i < currentMenu->numitems; i++) + { + if (currentMenu->menuitems[i].status != IT_DISABLED && currentMenu->menuitems[i].alphaKey*2 + tempcentery >= currentMenu->y) + break; + } + + for (bottom = currentMenu->numitems; bottom > 0; bottom--) + { + if (currentMenu->menuitems[bottom-1].status != IT_DISABLED) + break; + } + + for (max = bottom; max > 0; max--) + { + if (currentMenu->menuitems[max-1].status != IT_DISABLED && currentMenu->menuitems[max-1].alphaKey*2 + tempcentery <= (currentMenu->y + 2*scrollareaheight)) + break; + } + + if (i) + V_DrawString(currentMenu->x - 20, currentMenu->y - (skullAnimCounter/5), highlightflags, "\x1A"); // up arrow + if (max != bottom) + V_DrawString(currentMenu->x - 20, currentMenu->y + 2*scrollareaheight + (skullAnimCounter/5), highlightflags, "\x1B"); // down arrow + + // draw title (or big pic) + M_DrawMenuTitle(); + + for (; i < max; i++) + { + y = currentMenu->menuitems[i].alphaKey*2 + tempcentery; + if (i == itemOn) + cursory = y; + switch (currentMenu->menuitems[i].status & IT_DISPLAY) + { + case IT_PATCH: + // unsupported + break; + case IT_NOTHING: + case IT_DYBIGSPACE: + break; + case IT_STRING: + case IT_WHITESTRING: + if (i != itemOn && (currentMenu->menuitems[i].status & IT_DISPLAY)==IT_STRING) + V_DrawString(x, y, V_ALLOWLOWERCASE, currentMenu->menuitems[i].text); + else + V_DrawString(x, y, V_ALLOWLOWERCASE|highlightflags, currentMenu->menuitems[i].text); + + // Cvar specific handling + switch (currentMenu->menuitems[i].status & IT_TYPE) + case IT_CVAR: + { + consvar_t *cv = (consvar_t *)currentMenu->menuitems[i].itemaction; + switch (currentMenu->menuitems[i].status & IT_CVARTYPE) + { + case IT_CV_SLIDER: + M_DrawSlider(x, y, cv, (i == itemOn)); + case IT_CV_NOPRINT: // color use this + case IT_CV_INVISSLIDER: // monitor toggles use this + break; + case IT_CV_STRING: +#if 1 + if (y + 12 > (currentMenu->y + 2*scrollareaheight)) + break; + M_DrawTextBox(x, y + 4, MAXSTRINGLENGTH, 1); + V_DrawString(x + 8, y + 12, V_ALLOWLOWERCASE, cv->string); + if (skullAnimCounter < 4 && i == itemOn) + V_DrawCharacter(x + 8 + V_StringWidth(cv->string, 0), y + 12, + '_' | 0x80, false); +#else // cool new string type stuff, not ready for limelight + if (i == itemOn) + { + V_DrawFill(x-2, y-1, MAXSTRINGLENGTH*8 + 4, 8+3, 159); + V_DrawString(x, y, V_ALLOWLOWERCASE, cv->string); + if (skullAnimCounter < 4) + V_DrawCharacter(x + V_StringWidth(cv->string, 0), y, '_' | 0x80, false); + } + else + V_DrawRightAlignedString(BASEVIDWIDTH - x, y, + highlightflags|V_ALLOWLOWERCASE, cv->string); +#endif + break; + default: + V_DrawRightAlignedString(BASEVIDWIDTH - x, y, + ((cv->flags & CV_CHEAT) && !CV_IsSetToDefault(cv) ? V_REDMAP : highlightflags)|V_ALLOWLOWERCASE, cv->string); + if (i == itemOn) + { + V_DrawCharacter(BASEVIDWIDTH - x - 10 - V_StringWidth(cv->string, 0) - (skullAnimCounter/5), y, + '\x1C' | highlightflags, false); + V_DrawCharacter(BASEVIDWIDTH - x + 2 + (skullAnimCounter/5), y, + '\x1D' | highlightflags, false); + } + break; + } + break; + } + break; + case IT_TRANSTEXT: + V_DrawString(x, y, V_TRANSLUCENT|V_ALLOWLOWERCASE, currentMenu->menuitems[i].text); + break; + case IT_QUESTIONMARKS: + V_DrawString(x, y, V_ALLOWLOWERCASE|V_TRANSLUCENT|V_OLDSPACING, M_CreateSecretMenuOption(currentMenu->menuitems[i].text)); + break; + case IT_HEADERTEXT: + V_DrawString(x-16, y, highlightflags|V_ALLOWLOWERCASE, currentMenu->menuitems[i].text); + break; + } + } + + // DRAW THE SKULL CURSOR + V_DrawScaledPatch(currentMenu->x - 24, cursory, 0, + W_CachePatchName("M_CURSOR", PU_CACHE)); +} + + static void M_DrawPauseMenu(void) { #if 0 -- 2.54.0 From eaf2506b4f7357033cbe46921e956db0d0a18d1e Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Sat, 21 Oct 2023 12:23:55 +0200 Subject: [PATCH 037/485] almost forgor respect the menu caps choice --- src/m_menu.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index c93981078..3f5134b39 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4452,6 +4452,8 @@ static void M_DrawGenericScrollMenu(void) // draw title (or big pic) M_DrawMenuTitle(); + + INT32 lowercase = !cv_menucaps.value ? V_ALLOWLOWERCASE : 0; for (; i < max; i++) { @@ -4469,9 +4471,9 @@ static void M_DrawGenericScrollMenu(void) case IT_STRING: case IT_WHITESTRING: if (i != itemOn && (currentMenu->menuitems[i].status & IT_DISPLAY)==IT_STRING) - V_DrawString(x, y, V_ALLOWLOWERCASE, currentMenu->menuitems[i].text); + V_DrawString(x, y, lowercase, currentMenu->menuitems[i].text); else - V_DrawString(x, y, V_ALLOWLOWERCASE|highlightflags, currentMenu->menuitems[i].text); + V_DrawString(x, y, lowercase|highlightflags, currentMenu->menuitems[i].text); // Cvar specific handling switch (currentMenu->menuitems[i].status & IT_TYPE) @@ -4490,7 +4492,7 @@ static void M_DrawGenericScrollMenu(void) if (y + 12 > (currentMenu->y + 2*scrollareaheight)) break; M_DrawTextBox(x, y + 4, MAXSTRINGLENGTH, 1); - V_DrawString(x + 8, y + 12, V_ALLOWLOWERCASE, cv->string); + V_DrawString(x + 8, y + 12, lowercase, cv->string); if (skullAnimCounter < 4 && i == itemOn) V_DrawCharacter(x + 8 + V_StringWidth(cv->string, 0), y + 12, '_' | 0x80, false); @@ -4498,18 +4500,18 @@ static void M_DrawGenericScrollMenu(void) if (i == itemOn) { V_DrawFill(x-2, y-1, MAXSTRINGLENGTH*8 + 4, 8+3, 159); - V_DrawString(x, y, V_ALLOWLOWERCASE, cv->string); + V_DrawString(x, y, lowercase, cv->string); if (skullAnimCounter < 4) V_DrawCharacter(x + V_StringWidth(cv->string, 0), y, '_' | 0x80, false); } else V_DrawRightAlignedString(BASEVIDWIDTH - x, y, - highlightflags|V_ALLOWLOWERCASE, cv->string); + highlightflags|lowercase, cv->string); #endif break; default: V_DrawRightAlignedString(BASEVIDWIDTH - x, y, - ((cv->flags & CV_CHEAT) && !CV_IsSetToDefault(cv) ? V_REDMAP : highlightflags)|V_ALLOWLOWERCASE, cv->string); + ((cv->flags & CV_CHEAT) && !CV_IsSetToDefault(cv) ? V_REDMAP : highlightflags)|lowercase, cv->string); if (i == itemOn) { V_DrawCharacter(BASEVIDWIDTH - x - 10 - V_StringWidth(cv->string, 0) - (skullAnimCounter/5), y, @@ -4523,13 +4525,13 @@ static void M_DrawGenericScrollMenu(void) } break; case IT_TRANSTEXT: - V_DrawString(x, y, V_TRANSLUCENT|V_ALLOWLOWERCASE, currentMenu->menuitems[i].text); + V_DrawString(x, y, V_TRANSLUCENT|lowercase, currentMenu->menuitems[i].text); break; case IT_QUESTIONMARKS: - V_DrawString(x, y, V_ALLOWLOWERCASE|V_TRANSLUCENT|V_OLDSPACING, M_CreateSecretMenuOption(currentMenu->menuitems[i].text)); + V_DrawString(x, y, lowercase|V_TRANSLUCENT|V_OLDSPACING, M_CreateSecretMenuOption(currentMenu->menuitems[i].text)); break; case IT_HEADERTEXT: - V_DrawString(x-16, y, highlightflags|V_ALLOWLOWERCASE, currentMenu->menuitems[i].text); + V_DrawString(x-16, y, highlightflags|lowercase, currentMenu->menuitems[i].text); break; } } -- 2.54.0 From 6f3770a54a73a74eb2a6f878083a45051f3cba20 Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Sat, 21 Oct 2023 12:57:55 +0200 Subject: [PATCH 038/485] update the credits and menu add ppl to credits, and just have less seperation between the ppl that contributed to saturn move flashpal setting to opengl options --- src/m_menu.c | 69 +++++++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 3f5134b39..caf8762f6 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1363,23 +1363,24 @@ static menuitem_t OP_OpenGLOptionsMenu[] = { {IT_STRING | IT_CVAR, NULL, "3D Models", &cv_grmdls, 5}, {IT_STRING | IT_CVAR, NULL, "Fallback Player 3D Model", &cv_grfallbackplayermodel, 15}, - {IT_STRING|IT_CVAR, NULL, "Shaders", &cv_grshaders, 25}, + {IT_STRING | IT_CVAR, NULL, "Shaders", &cv_grshaders, 25}, //{IT_STRING|IT_CVAR, NULL, "Use custom Shaders", &cv_grusecustomshaders, 35}, - {IT_STRING|IT_CVAR, NULL, "Palette Rendering", &cv_grpaletteshader, 35}, - {IT_STRING | IT_CVAR, NULL, "Min Shader Brightness", &cv_secbright, 45}, + {IT_STRING | IT_CVAR, NULL, "Palette Rendering", &cv_grpaletteshader, 35}, + {IT_STRING | IT_CVAR, NULL, "Flashpals in Palette Renderer", &cv_grflashpal, 45}, + {IT_STRING | IT_CVAR, NULL, "Min Shader Brightness", &cv_secbright, 55}, - {IT_STRING|IT_CVAR, NULL, "Texture Quality", &cv_scr_depth, 65}, - {IT_STRING|IT_CVAR, NULL, "Texture Filter", &cv_grfiltermode, 75}, - {IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_granisotropicmode, 85}, + {IT_STRING|IT_CVAR, NULL, "Texture Quality", &cv_scr_depth, 75}, + {IT_STRING|IT_CVAR, NULL, "Texture Filter", &cv_grfiltermode, 85}, + {IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_granisotropicmode, 95}, - {IT_STRING|IT_CVAR, NULL, "Visual Portals", &cv_grportals, 95}, + {IT_STRING|IT_CVAR, NULL, "Visual Portals", &cv_grportals, 105}, - {IT_STRING|IT_CVAR, NULL, "Wall Contrast Style", &cv_grfakecontrast, 115}, - {IT_STRING|IT_CVAR, NULL, "Sprite Billboarding", &cv_grspritebillboarding, 125}, - {IT_STRING|IT_CVAR, NULL, "Software Perspective", &cv_grshearing, 135}, - {IT_STRING|IT_CVAR, NULL, "Rendering Distance", &cv_grrenderdistance, 145}, + {IT_STRING|IT_CVAR, NULL, "Wall Contrast Style", &cv_grfakecontrast, 125}, + {IT_STRING|IT_CVAR, NULL, "Sprite Billboarding", &cv_grspritebillboarding, 135}, + {IT_STRING|IT_CVAR, NULL, "Software Perspective", &cv_grshearing, 145}, + {IT_STRING|IT_CVAR, NULL, "Rendering Distance", &cv_grrenderdistance, 155}, - {IT_SUBMENU|IT_STRING, NULL, "Gamma...", &OP_OpenGLColorDef, 160}, + {IT_SUBMENU|IT_STRING, NULL, "Gamma...", &OP_OpenGLColorDef, 170}, }; static menuitem_t OP_OpenGLColorMenu[] = @@ -1724,10 +1725,8 @@ static menuitem_t OP_SaturnMenu[] = {IT_STRING | IT_CVAR, NULL, "Show Lap Emblem", &cv_showlapemblem, 85}, {IT_STRING | IT_CVAR, NULL, "Show Minimap Names", &cv_showminimapnames, 95}, {IT_STRING | IT_CVAR, NULL, "Small Minimap Players", &cv_minihead, 105}, - {IT_STRING | IT_CVAR, NULL, "Less Midnight Channel Flicker", &cv_lessflicker, 115}, -#ifdef HWRENDER - {IT_STRING | IT_CVAR, NULL, "Flashpals in Palette Renderer", &cv_grflashpal, 125}, -#endif + {IT_STRING | IT_CVAR, NULL, "Less Midnight Channel Flicker", &cv_lessflicker, 120}, + {IT_SUBMENU|IT_STRING, NULL, "Player distortion...", &OP_PlayerDistortDef, 140}, {IT_SUBMENU|IT_STRING, NULL, "Hud Offsets...", &OP_HudOffsetDef, 155}, @@ -1747,7 +1746,6 @@ enum sm_mapnames, sm_smallmap, sm_pisschannel, - sm_flashpal, sm_distortionmenu, sm_hudoffsets, sm_credits, @@ -1801,29 +1799,34 @@ static menuitem_t OP_SaturnCreditsMenu[] = { {IT_HEADER, NULL, "Saturn Credits", NULL, 0}, - {IT_HEADER, NULL, "Main Devs <3", NULL, 20}, + {IT_HEADER, NULL, "Thanks to all contributers <3", NULL, 25}, {IT_STRING2+IT_SPACE, NULL, "alufolie91 aka Alug", NULL, 30}, {IT_STRING2+IT_SPACE, NULL, "Indev", NULL, 40}, + {IT_STRING2+IT_SPACE, NULL, "Haya", NULL, 50}, + {IT_STRING2+IT_SPACE, NULL, "Nepdisk", NULL, 60}, + {IT_STRING2+IT_SPACE, NULL, "xyzzy", NULL, 70}, - {IT_HEADER, NULL, "Testers <3", NULL, 60}, - {IT_STRING2+IT_SPACE, NULL, "Sunflower aka AnimeSonic", NULL, 70}, - {IT_STRING2+IT_SPACE, NULL, "Yuz aka Yuzler", NULL, 80}, - {IT_STRING2+IT_SPACE, NULL, "Democrab", NULL, 90}, - {IT_STRING2+IT_SPACE, NULL, "EXpand aka Maver", NULL, 100}, + {IT_STRING+IT_SPACE, NULL, "", NULL, 73}, // dummy text - {IT_HEADER, NULL, "Special Thanks <3", NULL, 120}, + {IT_STRING2+IT_SPACE, NULL, "Sunflower aka AnimeSonic", NULL, 80}, + {IT_STRING2+IT_SPACE, NULL, "Yuz aka Yuzler", NULL, 90}, + {IT_STRING2+IT_SPACE, NULL, "Democrab", NULL, 100}, + {IT_STRING2+IT_SPACE, NULL, "EXpand aka Maver", NULL, 110}, + {IT_STRING2+IT_SPACE, NULL, "Nexit", NULL, 120}, + + {IT_HEADER, NULL, "Special Thanks <3", NULL, 130}, + + + {IT_STRING2+IT_SPACE, NULL, "All of Sunflower's Garden", NULL, 150}, + {IT_STRING2+IT_SPACE, NULL, "Galactice", NULL, 160}, + {IT_STRING2+IT_SPACE, NULL, "Himie and", NULL, 170}, + {IT_STRING2+IT_SPACE, NULL, "The Moe Mansion / Birdhouse Team", NULL, 180}, - {IT_STRING2+IT_SPACE, NULL, "xyzzy", NULL, 130}, - {IT_STRING2+IT_SPACE, NULL, "Haya", NULL, 140}, - {IT_STRING2+IT_SPACE, NULL, "Galactice", NULL, 150}, - {IT_STRING2+IT_SPACE, NULL, "Himie and", NULL, 160}, - {IT_STRING2+IT_SPACE, NULL, "The Moe Mansion / Birdhouse Team", NULL, 170}, - {IT_STRING2+IT_SPACE, NULL, "All of Sunflower's Garden", NULL, 180}, - {IT_STRING+IT_SPACE, NULL, "", NULL, 190}, // dummy text - {IT_STRING, NULL, "", NULL, 200}, // dummy text II + {IT_STRING+IT_SPACE, NULL, "", NULL, 190}, // dummy text II + {IT_STRING, NULL, "", NULL, 200}, // dummy text III }; static menuitem_t OP_BirdMenu[] = @@ -2387,7 +2390,7 @@ menu_t OP_MonitorToggleDef = }; #ifdef HWRENDER -menu_t OP_OpenGLOptionsDef = DEFAULTMENUSTYLE("M_VIDEO", OP_OpenGLOptionsMenu, &OP_VideoOptionsDef, 30, 30); +menu_t OP_OpenGLOptionsDef = DEFAULTMENUSTYLE("M_VIDEO", OP_OpenGLOptionsMenu, &OP_VideoOptionsDef, 30, 20); menu_t OP_OpenGLColorDef = { -- 2.54.0 From 68b88e40b544d3d47351cc96d7702d2d0eb392d7 Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Sat, 21 Oct 2023 15:44:38 +0200 Subject: [PATCH 039/485] smol change --- src/hardware/r_opengl/r_opengl.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index bb051fa23..9f029ce01 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1153,15 +1153,15 @@ EXPORT boolean HWRAPI(LoadShaders) (void) shader->uniforms[gluniform_lighting] = GETUNI("lighting"); shader->uniforms[gluniform_fade_start] = GETUNI("fade_start"); shader->uniforms[gluniform_fade_end] = GETUNI("fade_end"); + + // misc. (custom shaders) + shader->uniforms[gluniform_leveltime] = GETUNI("leveltime"); // palette rendering shader->uniforms[gluniform_palette] = GETUNI("palette"); shader->uniforms[gluniform_color_lookup] = GETUNI("lookup_tex"); shader->uniforms[gluniform_lighttable_tex] = GETUNI("lighttable_tex"); - // misc. (custom shaders) - shader->uniforms[gluniform_leveltime] = GETUNI("leveltime"); - #undef GETUNI // set permanent uniform values @@ -4238,6 +4238,9 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int width, int height) ClearBuffer(true, false, false, &clearColour); pglBindTexture(GL_TEXTURE_2D, finalScreenTexture); + // prepare shader, if it is enabled + Shader_SetUniforms(NULL, NULL, NULL, NULL); + if (gl_use_palette_shader && cv_grshaders.value) { pglUseProgram(gl_shaderprograms[8].program); // palette shader -- 2.54.0 From 5c2d8f6901f4751176bc2fb59a6bd8496d820308 Mon Sep 17 00:00:00 2001 From: Indev Date: Sun, 22 Oct 2023 12:59:25 +0300 Subject: [PATCH 040/485] Fix characters with SF_HIRES flag being displayed too big in grid skin select menu --- src/m_menu.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index caf8762f6..0c0ad0509 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -10699,6 +10699,7 @@ static void M_DrawSetupMultiPlayerMenu(void) sprdef = &skins[0].spritedef; break; default: + skintodisplay = setupm_fakeskin; if (R_SkinAvailable(skins[setupm_fakeskin].name) != -1) sprdef = &skins[R_SkinAvailable(skins[setupm_fakeskin].name)].spritedef; else @@ -10732,13 +10733,13 @@ static void M_DrawSetupMultiPlayerMenu(void) // draw player sprite if (setupm_fakecolor) // inverse should never happen { - UINT8 *colormap = R_GetTranslationColormap(setupm_fakeskin, setupm_fakecolor, GTC_MENUCACHE); + UINT8 *colormap = R_GetTranslationColormap(skintodisplay, setupm_fakecolor, GTC_MENUCACHE); - if (skins[setupm_fakeskin].flags & SF_HIRES) + if (skins[skintodisplay].flags & SF_HIRES) { V_DrawFixedPatch((mx+43)< Date: Sat, 21 Oct 2023 23:28:45 -0400 Subject: [PATCH 041/485] Port Prevent dropped ticcmds due to interp timing jutter from srb2-next --- src/d_clisrv.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 1c74dcfa1..6e56d3ac4 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -4981,26 +4981,36 @@ static void HandlePacketFromPlayer(SINT8 node) /// \todo Use a separate cvar for that kind of timeout? freezetimeout[node] = I_GetTime() + connectiontimeout; + //Ported this from 2.2 Prevent dropped ticcmds due to interp timing jutter + // If we've alredy received a ticcmd for this tic, just submit it for the next one. + tic_t faketic = maketic; + if ((!!(netcmds[maketic % TICQUEUE][netconsole].angleturn & TICCMD_RECEIVED)) + && (maketic - firstticstosend < TICQUEUE - 1)) + faketic++; + + + // Don't do anything for packets of type NODEKEEPALIVE? // Sryder 2018/07/01: Update the freezetimeout still! if (netbuffer->packettype == PT_NODEKEEPALIVE || netbuffer->packettype == PT_NODEKEEPALIVEMIS) break; - // Copy ticcmd - G_MoveTiccmd(&netcmds[maketic%TICQUEUE][netconsole], &netbuffer->u.clientpak.cmd, 1); + // Copy ticcmd Prevent dropped ticcmds due to interp timing jutter + G_MoveTiccmd(&netcmds[faketic%TICQUEUE][netconsole], &netbuffer->u.clientpak.cmd, 1); + // Check ticcmd for "speed hacks" if (CheckForSpeedHacks((UINT8)netconsole)) break; - // Splitscreen cmd + // Splitscreen cmd Prevent dropped ticcmds due to interp timing jutter if (((netbuffer->packettype == PT_CLIENT2CMD || netbuffer->packettype == PT_CLIENT2MIS) || (netbuffer->packettype == PT_CLIENT3CMD || netbuffer->packettype == PT_CLIENT3MIS) || (netbuffer->packettype == PT_CLIENT4CMD || netbuffer->packettype == PT_CLIENT4MIS)) && (nodetoplayer2[node] >= 0)) { - G_MoveTiccmd(&netcmds[maketic%TICQUEUE][(UINT8)nodetoplayer2[node]], + G_MoveTiccmd(&netcmds[faketic%TICQUEUE][(UINT8)nodetoplayer2[node]], &netbuffer->u.client2pak.cmd2, 1); if (CheckForSpeedHacks((UINT8)nodetoplayer2[node])) @@ -5011,7 +5021,7 @@ static void HandlePacketFromPlayer(SINT8 node) || (netbuffer->packettype == PT_CLIENT4CMD || netbuffer->packettype == PT_CLIENT4MIS)) && (nodetoplayer3[node] >= 0)) { - G_MoveTiccmd(&netcmds[maketic%TICQUEUE][(UINT8)nodetoplayer3[node]], + G_MoveTiccmd(&netcmds[faketic%TICQUEUE][(UINT8)nodetoplayer3[node]], &netbuffer->u.client3pak.cmd3, 1); if (CheckForSpeedHacks((UINT8)nodetoplayer3[node])) @@ -5021,7 +5031,7 @@ static void HandlePacketFromPlayer(SINT8 node) if ((netbuffer->packettype == PT_CLIENT4CMD || netbuffer->packettype == PT_CLIENT4MIS) && (nodetoplayer4[node] >= 0)) { - G_MoveTiccmd(&netcmds[maketic%TICQUEUE][(UINT8)nodetoplayer4[node]], + G_MoveTiccmd(&netcmds[faketic%TICQUEUE][(UINT8)nodetoplayer4[node]], &netbuffer->u.client4pak.cmd4, 1); if (CheckForSpeedHacks((UINT8)nodetoplayer4[node])) -- 2.54.0 From 773e243c880bc0e4e88378278d3636ed3152a6c1 Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Mon, 23 Oct 2023 15:34:38 +0200 Subject: [PATCH 042/485] ugh make that save lol --- src/hardware/hw_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index ca9ed609b..e49cfaa8f 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -142,7 +142,7 @@ consvar_t cv_grusecustomshaders = {"gr_usecustomshaders", "Yes", CV_CALL|CV_SAVE consvar_t cv_grpaletteshader = {"gr_paletteshader", "Off", CV_CALL|CV_SAVE, CV_OnOff, CV_grpaletteshader_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grflashpal = {"gr_flashpal", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_grflashpal = {"gr_flashpal", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grmdls = {"gr_mdls", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grfallbackplayermodel = {"gr_fallbackplayermodel", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -- 2.54.0 From 601928f49fe628abd2acd8ff77e7d5ceb5ca1c47 Mon Sep 17 00:00:00 2001 From: Indev Date: Tue, 24 Oct 2023 20:57:42 +0300 Subject: [PATCH 043/485] Only add command to history if it differs from previous one --- src/console.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/console.c b/src/console.c index 83654aaed..21c9eb695 100644 --- a/src/console.c +++ b/src/console.c @@ -1142,7 +1142,10 @@ boolean CON_Responder(event_t *ev) CONS_Printf("\x86""%c""\x80""%s\n", CON_PROMPTCHAR, inputlines[inputline]); - inputline = (inputline+1) & 31; + // Only add command to history if it differs from previous one + if (strcmp(inputlines[inputline], inputlines[(inputline-1) & 31])) + inputline = (inputline+1) & 31; + inputhist = inputline; CON_InputClear(); -- 2.54.0 From 8950e31f4c1fae54cac178ebf61c955c7e094a86 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Wed, 25 Oct 2023 19:26:34 -0400 Subject: [PATCH 044/485] Colorized Itembox --- src/d_main.c | 2 +- src/k_kart.c | 44 ++++++++++++++++++++++++++++++++++++++------ 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 69243f2de..3d946dd85 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1289,7 +1289,7 @@ void D_SRB2Main(void) // now check for colour hud stuff if (W_CheckMultipleLumps("K_SCTIME", "K_SCTIMW", "K_SCLAPS", "K_SCLAPW", \ - "K_SCBALN", "K_SCBALW", "K_SCKARM", "K_SCTOUT", "K_ISMULC", "K_ITMULC", NULL)) + "K_SCBALN", "K_SCBALW", "K_SCKARM", "K_SCTOUT", "K_ISMULC", "K_ITMULC", "K_ITBC","K_ITBCD", "K_ISBC", "K_ISBCD", NULL)) clr_hud = true; // check for bigger lap count but color** its color bitch diff --git a/src/k_kart.c b/src/k_kart.c index 3670fd583..fa0ebad5b 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -6935,6 +6935,7 @@ static patch_t *kp_karmastickerclr; static patch_t *kp_timeoutstickerclr; static patch_t *skp_smallstickerclr; static patch_t *kp_itemmulstickerclr[2]; +static patch_t *kp_itembgclr[4]; static patch_t *kp_startcountdown[16]; static patch_t *kp_racefinish[6]; @@ -7037,7 +7038,11 @@ void K_LoadKartHUDGraphics(void) kp_bumperstickerclr = W_CachePatchName("K_SCBALN", PU_HUDGFX); kp_bumperstickerwideclr = W_CachePatchName("K_SCBALW", PU_HUDGFX); kp_karmastickerclr = W_CachePatchName("K_SCKARM", PU_HUDGFX); - kp_timeoutstickerclr = W_CachePatchName("K_SCTOUT", PU_HUDGFX); + kp_timeoutstickerclr = W_CachePatchName("K_SCTOUT", PU_HUDGFX); + kp_itembgclr[0] = W_CachePatchName("K_ITBC", PU_HUDGFX); + kp_itembgclr[1] = W_CachePatchName("K_ITBCD", PU_HUDGFX); + kp_itembgclr[2] = W_CachePatchName("K_ISBC", PU_HUDGFX); + kp_itembgclr[3] = W_CachePatchName("K_ISBCD", PU_HUDGFX); kp_itemmulstickerclr[1] = W_CachePatchName("K_ISMULC", PU_HUDGFX); kp_itemmulstickerclr[0] = W_CachePatchName("K_ITMULC", PU_HUDGFX); if (big_lap_color){ @@ -7528,7 +7533,13 @@ static void K_drawKartItem(void) // Set to 'no item' just in case. const UINT8 offset = ((splitscreen > 1) ? 1 : 0); patch_t *localpatch = kp_nodraw; - patch_t *localbg = ((offset) ? kp_itembg[2] : kp_itembg[0]); + patch_t *localbg; + + if (cv_colorizedhud.value && clr_hud) + localbg = ((offset) ? kp_itembgclr[2] : kp_itembgclr[0]); + else + localbg = ((offset) ? kp_itembg[2] : kp_itembg[0]); + patch_t *localinv = ((offset) ? kp_invincibility[((leveltime % (6*3)) / 3) + 7] : kp_invincibility[(leveltime % (7*3)) / 3]); INT32 fx = 0, fy = 0, fflags = 0; // final coords for hud and flags... //INT32 splitflags = K_calcSplitFlags(V_SNAPTOTOP|V_SNAPTOLEFT); @@ -7688,7 +7699,10 @@ static void K_drawKartItem(void) break; case KITEM_INVINCIBILITY: localpatch = localinv; - localbg = kp_itembg[offset+1]; + if (cv_colorizedhud.value && clr_hud) + localbg = kp_itembgclr[offset+1]; + else + localbg = kp_itembg[offset+1]; break; case KITEM_BANANA: localpatch = kp_banana[offset]; @@ -7710,7 +7724,10 @@ static void K_drawKartItem(void) break; case KITEM_SPB: localpatch = kp_selfpropelledbomb[offset]; - localbg = kp_itembg[offset+1]; + if (cv_colorizedhud.value && clr_hud) + localbg = kp_itembgclr[offset+1]; + else + localbg = kp_itembg[offset+1]; break; case KITEM_GROW: localpatch = kp_grow[offset]; @@ -7720,7 +7737,10 @@ static void K_drawKartItem(void) break; case KITEM_THUNDERSHIELD: localpatch = kp_thundershield[offset]; - localbg = kp_itembg[offset+1]; + if (cv_colorizedhud.value && clr_hud) + localbg = kp_itembgclr[offset+1]; + else + localbg = kp_itembg[offset+1]; break; case KITEM_HYUDORO: localpatch = kp_hyudoro[offset]; @@ -7788,8 +7808,20 @@ static void K_drawKartItem(void) if (localcolor != SKINCOLOR_NONE) colmap = R_GetTranslationColormap(colormode, localcolor, GTC_CACHE); - V_DrawScaledPatch(fx, fy, V_HUDTRANS|fflags, localbg); + + if (cv_colorizedhud.value && clr_hud) + { + V_DrawMappedPatch(fx, fy, V_HUDTRANS|fflags, localbg,colormap); + } + else + { + V_DrawScaledPatch(fx, fy, V_HUDTRANS|fflags, localbg); + } + + + + // Then, the numbers: if (stplyr->kartstuff[k_itemamount] >= numberdisplaymin && !stplyr->kartstuff[k_itemroulette]) { -- 2.54.0 From 895bd2da15ea3d5a07900b66df9f83c8f33ff8d7 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Wed, 25 Oct 2023 19:57:46 -0400 Subject: [PATCH 045/485] Made this a menu option anyway lololololol --- src/k_kart.c | 13 ++++++++----- src/k_kart.h | 1 + src/m_menu.c | 11 ++++++----- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index fa0ebad5b..43cdce5a6 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -63,6 +63,8 @@ consvar_t cv_saltysquish = {"hardcodehopsquish", "On", CV_SAVE, CV_OnOff, NULL, //Colourized HUD consvar_t cv_colorizedhud = {"colorizedhud", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_colorizeditembox = {"colorizeditembox", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; + static CV_PossibleValue_t HudColor_cons_t[MAXSKINCOLORS+1]; consvar_t cv_colorizedhudcolor = {"colorizedhudcolor", "Skin Color", CV_SAVE, HudColor_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -686,6 +688,7 @@ void K_RegisterKartStuff(void) //Colourized HUD CV_RegisterVar(&cv_colorizedhud); CV_RegisterVar(&cv_colorizedhudcolor); + CV_RegisterVar(&cv_colorizeditembox); CV_RegisterVar(&cv_biglaps); @@ -7535,7 +7538,7 @@ static void K_drawKartItem(void) patch_t *localpatch = kp_nodraw; patch_t *localbg; - if (cv_colorizedhud.value && clr_hud) + if (cv_colorizeditembox.value && cv_colorizedhud.value && clr_hud) localbg = ((offset) ? kp_itembgclr[2] : kp_itembgclr[0]); else localbg = ((offset) ? kp_itembg[2] : kp_itembg[0]); @@ -7699,7 +7702,7 @@ static void K_drawKartItem(void) break; case KITEM_INVINCIBILITY: localpatch = localinv; - if (cv_colorizedhud.value && clr_hud) + if (cv_colorizeditembox.value && cv_colorizedhud.value && clr_hud) localbg = kp_itembgclr[offset+1]; else localbg = kp_itembg[offset+1]; @@ -7724,7 +7727,7 @@ static void K_drawKartItem(void) break; case KITEM_SPB: localpatch = kp_selfpropelledbomb[offset]; - if (cv_colorizedhud.value && clr_hud) + if (cv_colorizeditembox.value && cv_colorizedhud.value && clr_hud) localbg = kp_itembgclr[offset+1]; else localbg = kp_itembg[offset+1]; @@ -7737,7 +7740,7 @@ static void K_drawKartItem(void) break; case KITEM_THUNDERSHIELD: localpatch = kp_thundershield[offset]; - if (cv_colorizedhud.value && clr_hud) + if (cv_colorizeditembox.value && cv_colorizedhud.value && clr_hud) localbg = kp_itembgclr[offset+1]; else localbg = kp_itembg[offset+1]; @@ -7809,7 +7812,7 @@ static void K_drawKartItem(void) colmap = R_GetTranslationColormap(colormode, localcolor, GTC_CACHE); - if (cv_colorizedhud.value && clr_hud) + if (cv_colorizeditembox.value && cv_colorizedhud.value && clr_hud) { V_DrawMappedPatch(fx, fy, V_HUDTRANS|fflags, localbg,colormap); } diff --git a/src/k_kart.h b/src/k_kart.h index c930be1a8..18be989cd 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -22,6 +22,7 @@ UINT8 K_GetHudColor(); void K_RegisterKartStuff(void); extern consvar_t cv_colorizedhud; +extern consvar_t cv_colorizeditembox; extern consvar_t cv_colorizedhudcolor; extern consvar_t cv_biglaps; diff --git a/src/m_menu.c b/src/m_menu.c index 0c0ad0509..42c36c06b 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1721,11 +1721,12 @@ static menuitem_t OP_SaturnMenu[] = {IT_STRING | IT_CVAR, NULL, "Input Display outside of RA", &cv_showinput, 45}, {IT_STRING | IT_CVAR, NULL, "Small Speedometer", &cv_newspeedometer, 55}, {IT_STRING | IT_CVAR, NULL, "Colourized HUD", &cv_colorizedhud, 65}, - {IT_STRING | IT_CVAR, NULL, "Colourized HUD Color", &cv_colorizedhudcolor, 75}, - {IT_STRING | IT_CVAR, NULL, "Show Lap Emblem", &cv_showlapemblem, 85}, - {IT_STRING | IT_CVAR, NULL, "Show Minimap Names", &cv_showminimapnames, 95}, - {IT_STRING | IT_CVAR, NULL, "Small Minimap Players", &cv_minihead, 105}, - {IT_STRING | IT_CVAR, NULL, "Less Midnight Channel Flicker", &cv_lessflicker, 120}, + {IT_STRING | IT_CVAR, NULL, "Colourized Itembox", &cv_colorizeditembox, 75}, + {IT_STRING | IT_CVAR, NULL, "Colourized HUD Color", &cv_colorizedhudcolor, 85}, + {IT_STRING | IT_CVAR, NULL, "Show Lap Emblem", &cv_showlapemblem, 95}, + {IT_STRING | IT_CVAR, NULL, "Show Minimap Names", &cv_showminimapnames, 105}, + {IT_STRING | IT_CVAR, NULL, "Small Minimap Players", &cv_minihead, 115}, + {IT_STRING | IT_CVAR, NULL, "Less Midnight Channel Flicker", &cv_lessflicker, 125}, {IT_SUBMENU|IT_STRING, NULL, "Player distortion...", &OP_PlayerDistortDef, 140}, {IT_SUBMENU|IT_STRING, NULL, "Hud Offsets...", &OP_HudOffsetDef, 155}, -- 2.54.0 From 25398af8f591e465ef8ef71423e921a933fdb240 Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Fri, 27 Oct 2023 18:54:53 +0200 Subject: [PATCH 046/485] add toggle for dark itembox bg some may dislike how it looks with the colour hud --- src/k_kart.c | 34 ++++++++++++++++++++++------------ src/k_kart.h | 1 + 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 43cdce5a6..563f4aca9 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -69,6 +69,8 @@ consvar_t cv_colorizeditembox = {"colorizeditembox", "Off", CV_SAVE, CV_OnOff, N static CV_PossibleValue_t HudColor_cons_t[MAXSKINCOLORS+1]; consvar_t cv_colorizedhudcolor = {"colorizedhudcolor", "Skin Color", CV_SAVE, HudColor_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_darkitembox = {"darkitembox", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; + consvar_t cv_biglaps = {"biglaphud", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; // here for ppl who dont want to make 2 more patches for their custom hud @@ -690,6 +692,8 @@ void K_RegisterKartStuff(void) CV_RegisterVar(&cv_colorizedhudcolor); CV_RegisterVar(&cv_colorizeditembox); + CV_RegisterVar(&cv_darkitembox); + CV_RegisterVar(&cv_biglaps); CV_RegisterVar(&cv_slamsound); @@ -7702,10 +7706,12 @@ static void K_drawKartItem(void) break; case KITEM_INVINCIBILITY: localpatch = localinv; - if (cv_colorizeditembox.value && cv_colorizedhud.value && clr_hud) - localbg = kp_itembgclr[offset+1]; - else - localbg = kp_itembg[offset+1]; + if (cv_darkitembox.value){ + if (cv_colorizeditembox.value && cv_colorizedhud.value && clr_hud) + localbg = kp_itembgclr[offset+1]; + else + localbg = kp_itembg[offset+1]; + } break; case KITEM_BANANA: localpatch = kp_banana[offset]; @@ -7727,10 +7733,12 @@ static void K_drawKartItem(void) break; case KITEM_SPB: localpatch = kp_selfpropelledbomb[offset]; - if (cv_colorizeditembox.value && cv_colorizedhud.value && clr_hud) - localbg = kp_itembgclr[offset+1]; - else - localbg = kp_itembg[offset+1]; + if (cv_darkitembox.value){ + if (cv_colorizeditembox.value && cv_colorizedhud.value && clr_hud) + localbg = kp_itembgclr[offset+1]; + else + localbg = kp_itembg[offset+1]; + } break; case KITEM_GROW: localpatch = kp_grow[offset]; @@ -7740,10 +7748,12 @@ static void K_drawKartItem(void) break; case KITEM_THUNDERSHIELD: localpatch = kp_thundershield[offset]; - if (cv_colorizeditembox.value && cv_colorizedhud.value && clr_hud) - localbg = kp_itembgclr[offset+1]; - else - localbg = kp_itembg[offset+1]; + if (cv_darkitembox.value){ + if (cv_colorizeditembox.value && cv_colorizedhud.value && clr_hud) + localbg = kp_itembgclr[offset+1]; + else + localbg = kp_itembg[offset+1]; + } break; case KITEM_HYUDORO: localpatch = kp_hyudoro[offset]; diff --git a/src/k_kart.h b/src/k_kart.h index 18be989cd..1b8e9c7ab 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -24,6 +24,7 @@ void K_RegisterKartStuff(void); extern consvar_t cv_colorizedhud; extern consvar_t cv_colorizeditembox; extern consvar_t cv_colorizedhudcolor; +extern consvar_t cv_darkitembox; extern consvar_t cv_biglaps; boolean K_IsPlayerLosing(player_t *player); -- 2.54.0 From 7d7c053fc1f41c7a76743a5f165a3c1cfbbd0ea2 Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Mon, 30 Oct 2023 08:19:55 +0100 Subject: [PATCH 047/485] Revert "more sprite rotation anlges = smoother sprite rotation" This reverts commit 0921eb57c4792fc5cb2b120de04d8905513ae75c. --- src/doomdef.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doomdef.h b/src/doomdef.h index c0008dfd4..b7b3d44bc 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -631,7 +631,7 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// Sprite rotation #define ROTSPRITE -#define ROTANGLES 180 // Needs to be a divisor of 360 (45, 60, 90, 120...) +#define ROTANGLES 72 // Needs to be a divisor of 360 (45, 60, 90, 120...) #define ROTANGDIFF (360 / ROTANGLES) /// Hardware renderer: OpenGL -- 2.54.0 From f2b0b8359ed2e785553636a777fdc34e02476422 Mon Sep 17 00:00:00 2001 From: Indev Date: Mon, 30 Oct 2023 12:35:57 +0300 Subject: [PATCH 048/485] Add description for custom lua features --- LUASTUFF.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 LUASTUFF.md diff --git a/LUASTUFF.md b/LUASTUFF.md new file mode 100644 index 000000000..2ccd71dcb --- /dev/null +++ b/LUASTUFF.md @@ -0,0 +1,39 @@ +# SRB2Kart Saturn: Custom lua features + +## mobj.localskin and player.localskin fields + +Allow reading and assigning localskins to players. Local skins for other objects aren't supported currently. + +## mobj.rollsum field + +**Not netsafe**. Returns total sprite rotation value, taking sliptideroll and sloperoll cvars value into account. +Mainly for use in visual-only addons like secondcolor. + +## player.sliproll field + +**Not netsafe**. Returns player's current sliptide roll angle, taking sliptideroll cvar value into account. + +## hud.setVoteBackground(name) + +Changes vote background texture prefix (game looks for PREFIX + "W" or "C" (depends on resolution) + FRAME\_NUMBER). + +## hud.add(fn, "vote") and hud.add(fn, "intermission") + +Hud hooks for vote screen and intermission screen. They only get drawer (`v`) as argument. +To check if those hooks are available, check if globals FEATURE\_VOTEHUD and FEATURE\_INERMISSIONHUD +exist. + +## mobj.spritexscale, mobj.spriteyscale, mobj.spritexoffset, mobj.spriteyoffset, mobj.rollangle, mobj.sloperoll, mobj.rollmodel fields + +Same fields as in SRB2 2.2 + +## S\_StopSoundByNum + +Allows stopping specific sound globally. Because this function starts with S\_, like state, checking +if it exists is a bit more complicated: + +```lua +if rawget(_G, "S_StopSoundByNum") ~= nil then + ... -- Can use it +end +``` -- 2.54.0 From 3f8a2277697a4e1b060a709ffb74294e53f5a2c1 Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Mon, 30 Oct 2023 20:59:38 +0100 Subject: [PATCH 049/485] comment that out for now we dont use it yet, so lets not make compiler cry about smth unused --- src/m_menu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 42c36c06b..d47c78796 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -384,7 +384,7 @@ static UINT8 playback_enterheld = 0; // horrid hack to prevent holding the butto // Drawing functions static void M_DrawGenericMenu(void); static void M_DrawGenericBackgroundMenu(void); -static void M_DrawGenericScrollMenu(void); +//static void M_DrawGenericScrollMenu(void); static void M_DrawCenteredMenu(void); static void M_DrawAddons(void); static void M_DrawSkyRoom(void); @@ -4414,7 +4414,7 @@ static void M_DrawGenericBackgroundMenu(void) #define scrollareaheight 72 // note that alphakey is multiplied by 2 for scrolling menus to allow greater usage in UINT8 range. -static void M_DrawGenericScrollMenu(void) +/*static void M_DrawGenericScrollMenu(void) { INT32 x, y, i, max, bottom, tempcentery, cursory = 0; @@ -4543,7 +4543,7 @@ static void M_DrawGenericScrollMenu(void) // DRAW THE SKULL CURSOR V_DrawScaledPatch(currentMenu->x - 24, cursory, 0, W_CachePatchName("M_CURSOR", PU_CACHE)); -} +}*/ static void M_DrawPauseMenu(void) -- 2.54.0 From ee2bc85fe7eecbf912fbdb56e46ad1181749026c Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 31 Oct 2023 11:02:12 +0100 Subject: [PATCH 050/485] v4 --- src/doomdef.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doomdef.h b/src/doomdef.h index b7b3d44bc..f41a02782 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -127,8 +127,8 @@ extern char logfilename[1024]; #else #define VERSION 1 // Game version #define SUBVERSION 6 // more precise version number -#define VERSIONSTRING "Saturn v3 " -#define VERSIONSTRINGW L"Saturn v3" +#define VERSIONSTRING "Saturn v4 " +#define VERSIONSTRINGW L"Saturn v4" // Hey! If you change this, add 1 to the MODVERSION below! Otherwise we can't force updates! // And change CMakeLists.txt (not src/, but in root), for CMake users! // AND appveyor.yml, for the build bots! -- 2.54.0 From 3ccf44a0be4de5b35cf5518286e4cd0716803d33 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 2 Nov 2023 15:02:26 +0100 Subject: [PATCH 051/485] fixuer localskin stuff Fixes the Apply to all players and displaying player not working (thx haya c: ) Fixes the Vibrating? player animation speeding up when uncapped in localskinmenu Make so that the char spin speed respects the setting from saturn options (and add pain support ) --- src/m_menu.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index d47c78796..b95bb4806 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -12182,10 +12182,10 @@ static void M_LocalSkinChange(INT32 choice) switch (itemOn) { case 3: - COM_BufAddText(va("localskin -a %s", cv_fakelocalskin.string)); + COM_BufAddText(va("localskin %s -a", cv_fakelocalskin.string)); break; case 4: - COM_BufAddText(va("localskin -d 0 %s", cv_fakelocalskin.string)); + COM_BufAddText(va("localskin %s -d 0", cv_fakelocalskin.string)); break; case 5: COM_BufAddText(va("localskin %s", cv_fakelocalskin.string)); @@ -12216,16 +12216,19 @@ static void M_DrawLocalSkinMenu(void) #define charw 72 // anim the player in the box - if (--multi_tics <= 0) + multi_tics -= renderdeltatics; + while (multi_tics <= 0) { - st = multi_state->nextstate; + st = cv_skinselectspin.value == SKINSELECTSPIN_PAIN ? S_KART_PAIN : multi_state->nextstate; if (st != S_NULL) multi_state = &states[st]; - multi_tics = multi_state->tics; - if (multi_tics == -1) - multi_tics = 15; - } + if (multi_state->tics <= -1) + multi_tics += 15*FRACUNIT; + else + multi_tics += multi_state->tics * FRACUNIT; + } + // skin 0 is default player sprite if (R_AnySkinAvailable(cv_fakelocalskin.string) != -1) { @@ -12256,7 +12259,7 @@ static void M_DrawLocalSkinMenu(void) //minenice's speen css, it's a piece of shit but hey //patch = W_CachePatchNum(sprframe->lumppat[1], PU_CACHE); - speenframe = (I_GetTime()*4/TICRATE + 1)%8; + speenframe = (I_GetTime()*cv_skinselectspin.value/TICRATE + 1)%8; //this is a very shitty solution for checking if a sprite needs flipping //but it works -- 2.54.0 From 9ed348c8a89c7c60750192cad490ecb58a611245 Mon Sep 17 00:00:00 2001 From: Indev Date: Fri, 3 Nov 2023 14:11:56 +0300 Subject: [PATCH 052/485] Use libbacktrace for crash logs (wip) --- src/sdl/Makefile.cfg | 5 +++++ src/sdl/i_main.c | 19 +++++++++++++++++++ src/sdl/i_system.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+) diff --git a/src/sdl/Makefile.cfg b/src/sdl/Makefile.cfg index f733725af..4335b58ab 100644 --- a/src/sdl/Makefile.cfg +++ b/src/sdl/Makefile.cfg @@ -106,6 +106,11 @@ endif endif endif +ifndef NOLIBBACKTRACE + OPTS+=-DHAVE_LIBBACKTRACE + LIBS:=-lbacktrace $(LIBS) +endif + CFLAGS+=$(SDL_CFLAGS) LIBS:=$(SDL_LDFLAGS) $(LIBS) ifdef STATIC diff --git a/src/sdl/i_main.c b/src/sdl/i_main.c index 49af2cf97..1d2e2395f 100644 --- a/src/sdl/i_main.c +++ b/src/sdl/i_main.c @@ -37,6 +37,12 @@ //#define SDLMAIN #endif +#ifdef HAVE_LIBBACKTRACE +#include + +struct backtrace_state *bt_state = NULL; +#endif + #ifdef SDLMAIN #include "SDL_main.h" #elif defined(FORCESDLMAIN) @@ -105,6 +111,19 @@ int main(int argc, char **argv) myargc = argc; myargv = argv; /// \todo pull out path to exe from this string +#ifdef HAVE_LIBBACKTRACE + bt_state = backtrace_create_state( + argv[0], +#ifdef HAVE_THREADS + 1, +#else + 0, +#endif + NULL, + NULL + ); +#endif + #ifdef HAVE_TTF #ifdef _WIN32 I_StartupTTF(FONTPOINTSIZE, SDL_INIT_VIDEO|SDL_INIT_AUDIO, SDL_SWSURFACE); diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 4b943c932..8a778a523 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -67,6 +67,12 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); #define _MATH_DEFINES_DEFINED #include "SDL.h" +#ifdef HAVE_LIBBACKTRACE +#include +// TODO - move this to some header file instead +extern struct backtrace_state *bt_state; +#endif + #ifdef HAVE_TTF #include "i_ttf.h" #endif @@ -395,6 +401,17 @@ static void I_ReportSignal(int num, int coredumped) FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num) { D_QuitNetGame(); // Fix server freezes + +#ifdef HAVE_LIBBACKTRACE + FILE *out = fopen(va("%s" PATHSEP "%s", srb2home, "crash-log-libbacktrace.txt"), "w"); + + if (out) + { + backtrace_print(bt_state, 2, out); + fclose(out); + } +#endif + #ifdef UNIXBACKTRACE write_backtrace(num); #endif @@ -791,6 +808,17 @@ static void I_RegisterSignals (void) #ifdef NEWSIGNALHANDLER static void signal_handler_child(INT32 num) { + +#ifdef HAVE_LIBBACKTRACE + FILE *out = fopen(va("%s" PATHSEP "%s", srb2home, "crash-log-libbacktrace.txt"), "w"); + + if (out) + { + backtrace_print(bt_state, 2, out); + fclose(out); + } +#endif + #ifdef UNIXBACKTRACE write_backtrace(num); #endif -- 2.54.0 From dc16f8b4a662e3c0ca4f31685644f81edbb3a310 Mon Sep 17 00:00:00 2001 From: Indev Date: Fri, 3 Nov 2023 15:04:38 +0300 Subject: [PATCH 053/485] Make libbacktrace crash reports append to file instead of overwriting. Add more info into libbacktrace crash reports --- src/sdl/i_system.c | 69 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 21 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 8a778a523..99a8d22e4 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -67,12 +67,6 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); #define _MATH_DEFINES_DEFINED #include "SDL.h" -#ifdef HAVE_LIBBACKTRACE -#include -// TODO - move this to some header file instead -extern struct backtrace_state *bt_state; -#endif - #ifdef HAVE_TTF #include "i_ttf.h" #endif @@ -145,10 +139,13 @@ extern struct backtrace_state *bt_state; #if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) #include -#include #define UNIXBACKTRACE #endif +#if defined(UNIXBACKTRACE) || defined(HAVE_LIBBACKTRACE) +#include +#endif + // Locations for searching the srb2.srb #if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) #define DEFAULTWADLOCATION1 "/usr/local/share/games/SRB2Kart" @@ -203,6 +200,48 @@ static char returnWadPath[256]; #include "../byteptr.h" #endif +#ifdef HAVE_LIBBACKTRACE +#include +// TODO - move this to some header file instead +extern struct backtrace_state *bt_state; + +static void write_backtrace_libbacktrace(INT32 num) +{ + FILE *out = fopen(va("%s" PATHSEP "%s", srb2home, "crash-log-libbacktrace.txt"), "a"); + + time_t rawtime; + struct tm timeinfo; + char timestr[64]; + + if (!out) + { + fprintf(stderr, "\nWARNING: Couldn't open crash log for writing! Make sure your permissions are correct. Please save the below report!\n"); + out = stderr; + } + + // Get the current time as a string. + time(&rawtime); + localtime_r(&rawtime, &timeinfo); + strftime(timestr, 64, "%a, %d %b %Y %T %z", &timeinfo); + + fprintf(out, "------------------------\n\n"); + fprintf(out, "Time of crash: %s\n", timestr); + + fprintf(out, "Caused by: %s\n", strsignal(num)); + + fprintf(out, "\nBacktrace:\n"); + + backtrace_print(bt_state, 2, out); + + if (out != stderr) + { + fclose(out); + fprintf(stderr, "Crash report created, find crash-log-libbacktrace.txt in your SRB2Kart directory\n"); + } +} + +#endif + /** \brief The JoyReset function \param JoySet Joystick info to reset @@ -403,13 +442,7 @@ FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num) D_QuitNetGame(); // Fix server freezes #ifdef HAVE_LIBBACKTRACE - FILE *out = fopen(va("%s" PATHSEP "%s", srb2home, "crash-log-libbacktrace.txt"), "w"); - - if (out) - { - backtrace_print(bt_state, 2, out); - fclose(out); - } + write_backtrace_libbacktrace(num); #endif #ifdef UNIXBACKTRACE @@ -810,13 +843,7 @@ static void signal_handler_child(INT32 num) { #ifdef HAVE_LIBBACKTRACE - FILE *out = fopen(va("%s" PATHSEP "%s", srb2home, "crash-log-libbacktrace.txt"), "w"); - - if (out) - { - backtrace_print(bt_state, 2, out); - fclose(out); - } + write_backtrace_libbacktrace(num); #endif #ifdef UNIXBACKTRACE -- 2.54.0 From 067ebba4d49b8db2c34991f5e83e63b1a5397884 Mon Sep 17 00:00:00 2001 From: Indev Date: Fri, 3 Nov 2023 15:12:44 +0300 Subject: [PATCH 054/485] Don't use libbacktrace on win32 --- src/win32/Makefile.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/src/win32/Makefile.cfg b/src/win32/Makefile.cfg index c31b07dcf..d04c6712f 100644 --- a/src/win32/Makefile.cfg +++ b/src/win32/Makefile.cfg @@ -36,6 +36,7 @@ endif ifndef NONET ifndef MINGW64 #miniupnc is broken with MINGW64 HAVE_MINIUPNPC=1 + NOLIBBACKTRACE=1 endif endif -- 2.54.0 From 6c1426f1f3c80dd4d7d1489e16896f0aaa168d41 Mon Sep 17 00:00:00 2001 From: Indev Date: Fri, 3 Nov 2023 15:18:55 +0300 Subject: [PATCH 055/485] Always include time.h --- src/sdl/i_system.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 99a8d22e4..77da982c6 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -43,6 +43,7 @@ typedef HANDLE (WINAPI *p_OpenFileMappingA) (DWORD, BOOL, LPCSTR); typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); #endif #include +#include #include #include #ifdef __GNUC__ @@ -142,10 +143,6 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); #define UNIXBACKTRACE #endif -#if defined(UNIXBACKTRACE) || defined(HAVE_LIBBACKTRACE) -#include -#endif - // Locations for searching the srb2.srb #if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) #define DEFAULTWADLOCATION1 "/usr/local/share/games/SRB2Kart" -- 2.54.0 From ae5cf2116f3745670805596730664e4c76604454 Mon Sep 17 00:00:00 2001 From: Indev Date: Fri, 3 Nov 2023 15:37:31 +0300 Subject: [PATCH 056/485] Don't use unix-specific functions for libbacktrace crash report --- src/sdl/i_system.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 77da982c6..79b07b161 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -202,12 +202,33 @@ static char returnWadPath[256]; // TODO - move this to some header file instead extern struct backtrace_state *bt_state; +static void printsignal(FILE *fp, INT32 num) +{ + switch (num) + { + case SIGILL: + fprintf(fp, "SIGILL - illegal instruction - invalid function image"); + break; + case SIGFPE: + fprintf(fp, "SIGFPE - mathematical exception"); + break; + case SIGSEGV: + fprintf(fp, "SIGSEGV - segment violation"); + break; + case SIGABRT: + fprintf(fp, "SIGABRT - abnormal termination triggered by abort call"); + break; + default: + fprintf(fp, "Signal number %d", num); + } +} + static void write_backtrace_libbacktrace(INT32 num) { FILE *out = fopen(va("%s" PATHSEP "%s", srb2home, "crash-log-libbacktrace.txt"), "a"); time_t rawtime; - struct tm timeinfo; + struct tm *timeinfo; char timestr[64]; if (!out) @@ -218,13 +239,14 @@ static void write_backtrace_libbacktrace(INT32 num) // Get the current time as a string. time(&rawtime); - localtime_r(&rawtime, &timeinfo); - strftime(timestr, 64, "%a, %d %b %Y %T %z", &timeinfo); + timeinfo = localtime(&rawtime); + strftime(timestr, 64, "%a, %d %b %Y %T %z", timeinfo); fprintf(out, "------------------------\n\n"); fprintf(out, "Time of crash: %s\n", timestr); - fprintf(out, "Caused by: %s\n", strsignal(num)); + fprintf(out, "Caused by: "); + printsignal(out, num); fprintf(out, "\nBacktrace:\n"); -- 2.54.0 From 3e0cc1bb4882b7efa1d83ee9e583194e9ad95788 Mon Sep 17 00:00:00 2001 From: Indev Date: Fri, 3 Nov 2023 15:54:17 +0300 Subject: [PATCH 057/485] Use asctime instead of manually formatting time --- src/sdl/i_system.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 79b07b161..c385b22d7 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -229,7 +229,6 @@ static void write_backtrace_libbacktrace(INT32 num) time_t rawtime; struct tm *timeinfo; - char timestr[64]; if (!out) { @@ -240,10 +239,9 @@ static void write_backtrace_libbacktrace(INT32 num) // Get the current time as a string. time(&rawtime); timeinfo = localtime(&rawtime); - strftime(timestr, 64, "%a, %d %b %Y %T %z", timeinfo); fprintf(out, "------------------------\n\n"); - fprintf(out, "Time of crash: %s\n", timestr); + fprintf(out, "Time of crash: %s\n", asctime(timeinfo)); fprintf(out, "Caused by: "); printsignal(out, num); -- 2.54.0 From 37459d3d0970bdbbb441b07416bc929018f1baaf Mon Sep 17 00:00:00 2001 From: Indev Date: Fri, 3 Nov 2023 17:46:36 +0300 Subject: [PATCH 058/485] Simple backtrace in non-debug builds --- src/sdl/i_system.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index c385b22d7..d367d6e81 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -223,6 +223,59 @@ static void printsignal(FILE *fp, INT32 num) } } +typedef struct bt_out_buf_s { + char *pos; + size_t size; + unsigned n; +} bt_out_buf_t; + +static void bt_syminfo_cb(void *data, uintptr_t pc, const char *symname, uintptr_t symval, uintptr_t symsize) +{ + bt_out_buf_t *buf = (bt_out_buf_t*)data; + + if (!symname) + symname = "???"; + + int n = snprintf(buf->pos, buf->size, "%p %s\n", (void*)pc, symname); + + if (n <= 0) + { + buf->size = 0; + return; + } + + buf->pos += n; + buf->size -= n; +} + +static int bt_simple_cb(void *data, uintptr_t pc) +{ + bt_out_buf_t *buf = (bt_out_buf_t*)data; + + backtrace_syminfo(bt_state, pc, bt_syminfo_cb, NULL, data); + + if (!buf->size) return 1; + + buf->n++; + + return 0; +} + +static void backtrace_print_simple(FILE *fp) +{ + const size_t BUFSIZE = 8192; + char backtrace[BUFSIZE]; + + bt_out_buf_t buf; + buf.pos = backtrace; + buf.size = BUFSIZE; + buf.n = 1; + + backtrace_simple(bt_state, 2, bt_simple_cb, NULL, (void*)&buf); + + fputs(backtrace, fp); +} + static void write_backtrace_libbacktrace(INT32 num) { FILE *out = fopen(va("%s" PATHSEP "%s", srb2home, "crash-log-libbacktrace.txt"), "a"); @@ -248,7 +301,13 @@ static void write_backtrace_libbacktrace(INT32 num) fprintf(out, "\nBacktrace:\n"); +#ifdef _DEBUG + // Full backtrace, prints files and line numbers backtrace_print(bt_state, 2, out); +#else + // Simple backtrace, only prints function names + backtrace_print_simple(out); +#endif if (out != stderr) { -- 2.54.0 From df60b9ceeed444441603687045264d2a9a0d6630 Mon Sep 17 00:00:00 2001 From: Indev Date: Sat, 4 Nov 2023 22:00:17 +0300 Subject: [PATCH 059/485] Try to get full traceback in all builds, or fall back to simple traceback if that failed --- src/sdl/i_system.c | 66 +++++++++++++++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index d367d6e81..c62df9378 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -224,13 +224,16 @@ static void printsignal(FILE *fp, INT32 num) } typedef struct bt_out_buf_s { + boolean error; char *pos; size_t size; - unsigned n; } bt_out_buf_t; static void bt_syminfo_cb(void *data, uintptr_t pc, const char *symname, uintptr_t symval, uintptr_t symsize) { + (void)symval; + (void)symsize; + bt_out_buf_t *buf = (bt_out_buf_t*)data; if (!symname) @@ -256,24 +259,37 @@ static int bt_simple_cb(void *data, uintptr_t pc) if (!buf->size) return 1; - buf->n++; + return 0; +} + +static int bt_full_cb(void *data, uintptr_t pc, const char *filename, int lineno, const char *function) +{ + bt_out_buf_t *buf = (bt_out_buf_t*)data; + + if (!filename) filename = "???"; + if (!function) function = "???"; + + int n = snprintf(buf->pos, buf->size, "%p %s\n\t%s:%d\n", (void*)pc, function, filename, lineno); + + if (n <= 0) return 1; + + buf->pos += n; + buf->size -= n; + + if (!buf->size) return 1; return 0; } -static void backtrace_print_simple(FILE *fp) +static void bt_error_cb(void *data, const char *msg, int errnum) { - const size_t BUFSIZE = 8192; - char backtrace[BUFSIZE]; + (void)msg; // We don't need this - bt_out_buf_t buf; - buf.pos = backtrace; - buf.size = BUFSIZE; - buf.n = 1; + bt_out_buf_t *buf = (bt_out_buf_t*)data; - backtrace_simple(bt_state, 2, bt_simple_cb, NULL, (void*)&buf); - - fputs(backtrace, fp); + // No debug info + if (errnum == -1) + buf->error = true; } static void write_backtrace_libbacktrace(INT32 num) @@ -283,6 +299,15 @@ static void write_backtrace_libbacktrace(INT32 num) time_t rawtime; struct tm *timeinfo; + const size_t BUFSIZE = 8192; + char backtrace[BUFSIZE]; + + bt_out_buf_t buf; + buf.error = false; + buf.pos = backtrace; + buf.size = BUFSIZE; + + if (!out) { fprintf(stderr, "\nWARNING: Couldn't open crash log for writing! Make sure your permissions are correct. Please save the below report!\n"); @@ -301,13 +326,16 @@ static void write_backtrace_libbacktrace(INT32 num) fprintf(out, "\nBacktrace:\n"); -#ifdef _DEBUG - // Full backtrace, prints files and line numbers - backtrace_print(bt_state, 2, out); -#else - // Simple backtrace, only prints function names - backtrace_print_simple(out); -#endif + // Try to get full backtrace, it will print files and line numbers + backtrace_full(bt_state, 2, bt_full_cb, bt_error_cb, (void*)&buf); + + if (buf.error) + { + // Fall back to simple backtrace, only prints function names + backtrace_simple(bt_state, 2, bt_simple_cb, NULL, (void*)&buf); + } + + fputs(backtrace, out); if (out != stderr) { -- 2.54.0 From 84d966546737a48f6542092231f45c0cd6293c29 Mon Sep 17 00:00:00 2001 From: Indev Date: Sat, 4 Nov 2023 22:30:38 +0300 Subject: [PATCH 060/485] Bye bye unix-specific backtrace --- src/sdl/i_system.c | 99 ++-------------------------------------------- 1 file changed, 4 insertions(+), 95 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index c62df9378..d29f56821 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -138,11 +138,6 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); #include #endif -#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) -#include -#define UNIXBACKTRACE -#endif - // Locations for searching the srb2.srb #if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) #define DEFAULTWADLOCATION1 "/usr/local/share/games/SRB2Kart" @@ -292,9 +287,9 @@ static void bt_error_cb(void *data, const char *msg, int errnum) buf->error = true; } -static void write_backtrace_libbacktrace(INT32 num) +static void write_backtrace(INT32 num) { - FILE *out = fopen(va("%s" PATHSEP "%s", srb2home, "crash-log-libbacktrace.txt"), "a"); + FILE *out = fopen(va("%s" PATHSEP "%s", srb2home, "crash-log.txt"), "a"); time_t rawtime; struct tm *timeinfo; @@ -340,7 +335,7 @@ static void write_backtrace_libbacktrace(INT32 num) if (out != stderr) { fclose(out); - fprintf(stderr, "Crash report created, find crash-log-libbacktrace.txt in your SRB2Kart directory\n"); + fprintf(stderr, "Crash report created, find crash-log.txt in your SRB2Kart directory\n"); } } @@ -407,85 +402,6 @@ SDL_bool framebuffer = SDL_FALSE; UINT8 keyboard_started = false; -#ifdef UNIXBACKTRACE - -static void bt_write_file(int fd, const char *string) { - ssize_t written = 0; - ssize_t sourcelen = strlen(string); - - while (fd != -1 && (written != -1 && errno != EINTR) && written < sourcelen) - written = write(fd, string, sourcelen); -} - -static void bt_write_stderr(const char *string) { - bt_write_file(STDERR_FILENO, string); -} - -static void bt_write_all(int fd, const char *string) { - bt_write_file(fd, string); - bt_write_file(STDERR_FILENO, string); -} - -static void write_backtrace(INT32 signal) -{ - int fd = -1; - time_t rawtime; - struct tm timeinfo; - size_t bt_size; - - enum { BT_SIZE = 1024, STR_SIZE = 32 }; - void *funcptrs[BT_SIZE]; - char timestr[STR_SIZE]; - - const char *filename = va("%s" PATHSEP "%s", srb2home, "crash-log.txt"); - - fd = open(filename, O_CREAT|O_APPEND|O_RDWR, S_IRUSR|S_IWUSR); - - if (fd == -1) // File handle error - bt_write_stderr("\nWARNING: Couldn't open crash log for writing! Make sure your permissions are correct. Please save the below report!\n"); - - // Get the current time as a string. - time(&rawtime); - localtime_r(&rawtime, &timeinfo); - strftime(timestr, STR_SIZE, "%a, %d %b %Y %T %z", &timeinfo); - - bt_write_file(fd, "------------------------\n"); // Nice looking seperator - - bt_write_all(fd, "\n"); // Newline to look nice for both outputs. - bt_write_all(fd, "An error occurred within SRB2! Send this stack trace to someone who can help!\n"); - - if (fd != -1) // If the crash log exists, - bt_write_stderr("(Or find crash-log.txt in your SRB2 directory.)\n"); // tell the user where the crash log is. - - // Tell the log when we crashed. - bt_write_file(fd, "Time of crash: "); - bt_write_file(fd, timestr); - bt_write_file(fd, "\n"); - - // Give the crash log the cause and a nice 'Backtrace:' thing - // The signal is given to the user when the parent process sees we crashed. - bt_write_file(fd, "Cause: "); - bt_write_file(fd, strsignal(signal)); - bt_write_file(fd, "\n"); // Newline for the signal name - - bt_write_all(fd, "\nBacktrace:\n"); - - // Flood the output and log with the backtrace - bt_size = backtrace(funcptrs, BT_SIZE); - backtrace_symbols_fd(funcptrs, bt_size, fd); - backtrace_symbols_fd(funcptrs, bt_size, STDERR_FILENO); - - bt_write_file(fd, "\n"); // Write another newline to the log so it looks nice :) - - if (fd != -1) { - fsync(fd); // reaaaaally make sure we got that data written. - close(fd); - } -} - -#endif // UNIXBACKTRACE - - static void I_ReportSignal(int num, int coredumped) { //static char msg[] = "oh no! back to reality!\r\n"; @@ -546,12 +462,9 @@ FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num) D_QuitNetGame(); // Fix server freezes #ifdef HAVE_LIBBACKTRACE - write_backtrace_libbacktrace(num); -#endif - -#ifdef UNIXBACKTRACE write_backtrace(num); #endif + I_ReportSignal(num, 0); I_ShutdownSystem(); signal(num, SIG_DFL); //default signal action @@ -947,10 +860,6 @@ static void signal_handler_child(INT32 num) { #ifdef HAVE_LIBBACKTRACE - write_backtrace_libbacktrace(num); -#endif - -#ifdef UNIXBACKTRACE write_backtrace(num); #endif -- 2.54.0 From bf2eecf9a4536c2dc4e956d26c90c4c1dd45c388 Mon Sep 17 00:00:00 2001 From: Alug <136046486+alufolie91@users.noreply.github.com> Date: Sat, 4 Nov 2023 20:39:19 +0100 Subject: [PATCH 061/485] Update README.md i most likely forgor smth but the most important thing was libbacktrace dependency for building the gam,e --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.md b/README.md index 9bf915be8..c21b843de 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,11 @@ - Sprites player rotation on slopes; going on hills, levitate, going down, and so on alters your sprites (configurable) - You can alter all the base kart HUD element offsets on the fly in the Saturn Options settings menu - `addfilelocal` Command, for those who want to use things like their custom hud in netgames (Same as addfile but completely client sided) +- Palette rendering, make the OpenGL renderer (almost) look like software mode! - OpenMPT for Tracker module playback instead of GME - Fixes looping and sounds better - Allows filter configuration +- Colourize your Kart HUD, to either your player color or whichever colour you like! (optional / requieres extra2.kart file) - The minimal brightness with Shaders can be configured, now you can seeeee in dark areas (0-255 , uses Sector brightness values) - Lua HUD hooks for Intermission (ex: You can make hostmod votes still visible during intermission!) - Lua HUD hooks for Vote Screen (ex: You can make hostmod votes still visible during map vote screen!) @@ -17,9 +19,12 @@ - Smaller Speedometer (optional / requieres extra.kart file) - Record Attack input display can now be used everywhere - Smaller minimap icons and also show player names on the minimap (toggable) +- Support for animated votescreens! - `showmusiccredit` command, shows you the current music track again - `listskins` show a list of all skins currently loaded - Visual Portals from Haya's HEP Client +- Horizonline effect in OpenGL (watch the endless bricks on SNES Bowsers Castle!) +- Localskins! use whatever skin you like! - Toggable lowercase menu's also from Haya's HEP client - Everything that Galaxy has @@ -39,6 +44,9 @@ - Toggable Lap animation - Main menu shows the current renderer being used - MSAA and A2C Antialiasing support (Configurable in renderer.txt file) +- A simple button to rejoin your last visited server +- Ability to show ALL maps in the mapselect screen, this includes hidden or hellmaps "showallmaps yes/no" +- Ability to toggle the Stagetitlecard "maptitles on/off" ## Performance / Debugging @@ -57,6 +65,11 @@ - The annoying depraction messages for `P_TeleportMove` and `P_AproxDistance` have been silenced - Silenced the annoying "cant find next map..." messages as theyre super useless and annoying anyways - Added a small cooldown on `map` command due to spamming causing a SIGSEGV +- Many bugfixes to the Software renderer, so its much less prone to crashing +- Many bugfixes to the OpenGL renderer (too many too list all of them here; check the changelogs for more information) +- Bugfixes to the soundsystem, mainly regarding Sound muting +- Refactored Zone Memory Allocations (helps a bit with large maps) +- Many many more crash fixes and other bugfixes to the basegame (too many too list all of them here; check the changelogs for more information) ## MISC - Bird's Camara Tilting feature is no longer turned on by default @@ -67,12 +80,16 @@ - A2C antialiasing makes transparent surfaces even more transparent - You tell us! c: +## Note +Check the LUASTUFF file for more information on all the lua things Saturn has. + ## Dependencies - SDL2 (Linux/OS X only) - SDL2-Mixer (Linux/OS X only) - libupnp (Linux/OS X only) - libgme (Linux/OS X only) - libopenmpt (Linux/OS X only) +- libbacktrace (Linux/OS X only) ## Compiling -- 2.54.0 From 966b273ecdfa477111e32ad3860a8bcdc00a2ba9 Mon Sep 17 00:00:00 2001 From: Indev Date: Sat, 4 Nov 2023 23:00:05 +0300 Subject: [PATCH 062/485] More information in debug log --- src/sdl/i_system.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index d29f56821..c3b04bed7 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -289,7 +289,7 @@ static void bt_error_cb(void *data, const char *msg, int errnum) static void write_backtrace(INT32 num) { - FILE *out = fopen(va("%s" PATHSEP "%s", srb2home, "crash-log.txt"), "a"); + FILE *out = fopen(va("%s" PATHSEP "%s", srb2home, "srb2kart-crash-log.txt"), "a"); time_t rawtime; struct tm *timeinfo; @@ -314,6 +314,12 @@ static void write_backtrace(INT32 num) timeinfo = localtime(&rawtime); fprintf(out, "------------------------\n\n"); + + fprintf(out, "Program name: %s %s\n", SRB2APPLICATION, VERSIONSTRING); + + if (compdate && comptime && comprevision && compbranch) + fprintf(out, "Compiled: %s %s, commit %s, branch %s\n", compdate, comptime, comprevision, compbranch); + fprintf(out, "Time of crash: %s\n", asctime(timeinfo)); fprintf(out, "Caused by: "); @@ -335,7 +341,7 @@ static void write_backtrace(INT32 num) if (out != stderr) { fclose(out); - fprintf(stderr, "Crash report created, find crash-log.txt in your SRB2Kart directory\n"); + fprintf(stderr, "Crash report created, find srb2kart-crash-log.txt in your SRB2Kart directory\n"); } } -- 2.54.0 From 8028c285ffcee02dc182b4c51a440899ba53bf52 Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Sat, 4 Nov 2023 21:02:35 +0100 Subject: [PATCH 063/485] Add libs and DLLs for libbacktrace --- libs/DLL-README.txt | 5 +- libs/libbacktrace/LICENSE.txt | 29 +++ libs/libbacktrace/README.md | 36 ++++ .../bin/x86_64/libbacktrace-0.dll | Bin 0 -> 79738 bytes .../bin/x86_64/libgcc_s_seh-1.dll | Bin 0 -> 117427 bytes .../bin/x86_64/libwinpthread-1.dll | Bin 0 -> 60356 bytes libs/libbacktrace/include/backtrace.h | 188 ++++++++++++++++++ libs/libbacktrace/lib/x86_64/libbacktrace.a | Bin 0 -> 57136 bytes 8 files changed, 256 insertions(+), 2 deletions(-) create mode 100644 libs/libbacktrace/LICENSE.txt create mode 100644 libs/libbacktrace/README.md create mode 100644 libs/libbacktrace/bin/x86_64/libbacktrace-0.dll create mode 100644 libs/libbacktrace/bin/x86_64/libgcc_s_seh-1.dll create mode 100644 libs/libbacktrace/bin/x86_64/libwinpthread-1.dll create mode 100644 libs/libbacktrace/include/backtrace.h create mode 100644 libs/libbacktrace/lib/x86_64/libbacktrace.a diff --git a/libs/DLL-README.txt b/libs/DLL-README.txt index c44558666..8d388d412 100644 --- a/libs/DLL-README.txt +++ b/libs/DLL-README.txt @@ -23,10 +23,11 @@ and don't forget to build r_opengl.dll for srb2dd. ## srb2kart, 64-bit -* libs\dll-binaries\x86_64\exchndl.dll * libs\dll-binaries\x86_64\libgme.dll * libs\dll-binaries\x86_64\discord-rpc.dll -* libs\dll-binaries\x86_64\mgwhelp.dll (depend for exchndl.dll) * libs\SDL2\x86_64-w64-mingw32\bin\SDL2.dll * libs\SDL2_mixer\x86_64-w64-mingw32\bin\*.dll (get everything) * libs\libopenmpt\x86_64\bin\mingw\libopenmpt.dll +* libs\libbacktrace\bin\x86_64\libbacktrace-0.dll +* libs\libbacktrace\bin\x86_64\libgcc_s_seh-1.dll +* libs\libbacktrace\bin\x86_64\libwinpthread-1.dll \ No newline at end of file diff --git a/libs/libbacktrace/LICENSE.txt b/libs/libbacktrace/LICENSE.txt new file mode 100644 index 000000000..495411538 --- /dev/null +++ b/libs/libbacktrace/LICENSE.txt @@ -0,0 +1,29 @@ +# Copyright (C) 2012-2016 Free Software Foundation, Inc. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: + +# (1) Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. + +# (2) Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. + +# (3) The name of the author may not be used to +# endorse or promote products derived from this software without +# specific prior written permission. + +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/libs/libbacktrace/README.md b/libs/libbacktrace/README.md new file mode 100644 index 000000000..c82834d17 --- /dev/null +++ b/libs/libbacktrace/README.md @@ -0,0 +1,36 @@ +# libbacktrace +A C library that may be linked into a C/C++ program to produce symbolic backtraces + +Initially written by Ian Lance Taylor . + +This is version 1.0. +It is likely that this will always be version 1.0. + +The libbacktrace library may be linked into a program or library and +used to produce symbolic backtraces. +Sample uses would be to print a detailed backtrace when an error +occurs or to gather detailed profiling information. +In general the functions provided by this library are async-signal-safe, +meaning that they may be safely called from a signal handler. + +The libbacktrace library is provided under a BSD license. +See the source files for the exact license text. + +The public functions are declared and documented in the header file +backtrace.h, which should be #include'd by a user of the library. + +Building libbacktrace will generate a file backtrace-supported.h, +which a user of the library may use to determine whether backtraces +will work. +See the source file backtrace-supported.h.in for the macros that it +defines. + +As of October 2020, libbacktrace supports ELF, PE/COFF, Mach-O, and +XCOFF executables with DWARF debugging information. +In other words, it supports GNU/Linux, *BSD, macOS, Windows, and AIX. +The library is written to make it straightforward to add support for +other object file and debugging formats. + +The library relies on the C++ unwind API defined at +https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html +This API is provided by GCC and clang. diff --git a/libs/libbacktrace/bin/x86_64/libbacktrace-0.dll b/libs/libbacktrace/bin/x86_64/libbacktrace-0.dll new file mode 100644 index 0000000000000000000000000000000000000000..14bc20738d9ddf7854e1a0a09449bca8e98bcce7 GIT binary patch literal 79738 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 literal 0 HcmV?d00001 diff --git a/libs/libbacktrace/bin/x86_64/libgcc_s_seh-1.dll b/libs/libbacktrace/bin/x86_64/libgcc_s_seh-1.dll new file mode 100644 index 0000000000000000000000000000000000000000..fb2e767ec57d6cf3bef0e7e22b40198f630643c7 GIT binary patch literal 117427 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%0Dwwp%J-c!|GYfU_>|2C;# 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 E-=%g+p#T5? literal 0 HcmV?d00001 diff --git a/libs/libbacktrace/include/backtrace.h b/libs/libbacktrace/include/backtrace.h new file mode 100644 index 000000000..777e1460b --- /dev/null +++ b/libs/libbacktrace/include/backtrace.h @@ -0,0 +1,188 @@ +/* backtrace.h -- Public header file for stack backtrace library. + Copyright (C) 2012-2020 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Google. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + (1) Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + (2) Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + (3) The name of the author may not be used to + endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. */ + +#ifndef BACKTRACE_H +#define BACKTRACE_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* The backtrace state. This struct is intentionally not defined in + the public interface. */ + +struct backtrace_state; + +/* The type of the error callback argument to backtrace functions. + This function, if not NULL, will be called for certain error cases. + The DATA argument is passed to the function that calls this one. + The MSG argument is an error message. The ERRNUM argument, if + greater than 0, holds an errno value. The MSG buffer may become + invalid after this function returns. + + As a special case, the ERRNUM argument will be passed as -1 if no + debug info can be found for the executable, but the function + requires debug info (e.g., backtrace_full, backtrace_pcinfo). The + MSG in this case will be something along the lines of "no debug + info". Similarly, ERRNUM will be passed as -1 if there is no + symbol table, but the function requires a symbol table (e.g., + backtrace_syminfo). This may be used as a signal that some other + approach should be tried. */ + +typedef void (*backtrace_error_callback) (void *data, const char *msg, + int errnum); + +/* Create state information for the backtrace routines. This must be + called before any of the other routines, and its return value must + be passed to all of the other routines. FILENAME is the path name + of the executable file; if it is NULL the library will try + system-specific path names. If not NULL, FILENAME must point to a + permanent buffer. If THREADED is non-zero the state may be + accessed by multiple threads simultaneously, and the library will + use appropriate atomic operations. If THREADED is zero the state + may only be accessed by one thread at a time. This returns a state + pointer on success, NULL on error. If an error occurs, this will + call the ERROR_CALLBACK routine. + + Calling this function allocates resources that cannot be freed. + There is no backtrace_free_state function. The state is used to + cache information that is expensive to recompute. Programs are + expected to call this function at most once and to save the return + value for all later calls to backtrace functions. */ + +extern struct backtrace_state *backtrace_create_state ( + const char *filename, int threaded, + backtrace_error_callback error_callback, void *data); + +/* The type of the callback argument to the backtrace_full function. + DATA is the argument passed to backtrace_full. PC is the program + counter. FILENAME is the name of the file containing PC, or NULL + if not available. LINENO is the line number in FILENAME containing + PC, or 0 if not available. FUNCTION is the name of the function + containing PC, or NULL if not available. This should return 0 to + continuing tracing. The FILENAME and FUNCTION buffers may become + invalid after this function returns. */ + +typedef int (*backtrace_full_callback) (void *data, uintptr_t pc, + const char *filename, int lineno, + const char *function); + +/* Get a full stack backtrace. SKIP is the number of frames to skip; + passing 0 will start the trace with the function calling + backtrace_full. DATA is passed to the callback routine. If any + call to CALLBACK returns a non-zero value, the stack backtrace + stops, and backtrace returns that value; this may be used to limit + the number of stack frames desired. If all calls to CALLBACK + return 0, backtrace returns 0. The backtrace_full function will + make at least one call to either CALLBACK or ERROR_CALLBACK. This + function requires debug info for the executable. */ + +extern int backtrace_full (struct backtrace_state *state, int skip, + backtrace_full_callback callback, + backtrace_error_callback error_callback, + void *data); + +/* The type of the callback argument to the backtrace_simple function. + DATA is the argument passed to simple_backtrace. PC is the program + counter. This should return 0 to continue tracing. */ + +typedef int (*backtrace_simple_callback) (void *data, uintptr_t pc); + +/* Get a simple backtrace. SKIP is the number of frames to skip, as + in backtrace. DATA is passed to the callback routine. If any call + to CALLBACK returns a non-zero value, the stack backtrace stops, + and backtrace_simple returns that value. Otherwise + backtrace_simple returns 0. The backtrace_simple function will + make at least one call to either CALLBACK or ERROR_CALLBACK. This + function does not require any debug info for the executable. */ + +extern int backtrace_simple (struct backtrace_state *state, int skip, + backtrace_simple_callback callback, + backtrace_error_callback error_callback, + void *data); + +/* Print the current backtrace in a user readable format to a FILE. + SKIP is the number of frames to skip, as in backtrace_full. Any + error messages are printed to stderr. This function requires debug + info for the executable. */ + +extern void backtrace_print (struct backtrace_state *state, int skip, FILE *); + +/* Given PC, a program counter in the current program, call the + callback function with filename, line number, and function name + information. This will normally call the callback function exactly + once. However, if the PC happens to describe an inlined call, and + the debugging information contains the necessary information, then + this may call the callback function multiple times. This will make + at least one call to either CALLBACK or ERROR_CALLBACK. This + returns the first non-zero value returned by CALLBACK, or 0. */ + +extern int backtrace_pcinfo (struct backtrace_state *state, uintptr_t pc, + backtrace_full_callback callback, + backtrace_error_callback error_callback, + void *data); + +/* The type of the callback argument to backtrace_syminfo. DATA and + PC are the arguments passed to backtrace_syminfo. SYMNAME is the + name of the symbol for the corresponding code. SYMVAL is the + value and SYMSIZE is the size of the symbol. SYMNAME will be NULL + if no error occurred but the symbol could not be found. */ + +typedef void (*backtrace_syminfo_callback) (void *data, uintptr_t pc, + const char *symname, + uintptr_t symval, + uintptr_t symsize); + +/* Given ADDR, an address or program counter in the current program, + call the callback information with the symbol name and value + describing the function or variable in which ADDR may be found. + This will call either CALLBACK or ERROR_CALLBACK exactly once. + This returns 1 on success, 0 on failure. This function requires + the symbol table but does not require the debug info. Note that if + the symbol table is present but ADDR could not be found in the + table, CALLBACK will be called with a NULL SYMNAME argument. + Returns 1 on success, 0 on error. */ + +extern int backtrace_syminfo (struct backtrace_state *state, uintptr_t addr, + backtrace_syminfo_callback callback, + backtrace_error_callback error_callback, + void *data); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif + +#endif diff --git a/libs/libbacktrace/lib/x86_64/libbacktrace.a b/libs/libbacktrace/lib/x86_64/libbacktrace.a new file mode 100644 index 0000000000000000000000000000000000000000..891dd11d698405090a096cffcee59a3dde6b7906 GIT binary patch literal 57136 zcmdSC3w&HvwLgBQN$Io{PYMNtfDAZjYD-C=U?N3k+DUr`CJ@>JQL9OsM^jCkkWAX} z5CSu4dz_9&ZpG^D)#~Nv?NzQ;?`UZG#FPsH`M*-nqk_Hv1A#de)-hhhw)Un~o^%bZZJkY?=k|^jtKy#L8#>!Myw43CP4)4n+Rixsd!mso&tvC` zmF=zG@D;08#8=d}uDHpIT;3F~UA>}djVED8Q)^RwXVYjj%G=i9iPqfFGXl8Zdr(zuqIVi+&u@(VQ4 zm>qBGjthMJe*vSqZgyjRy#Dx6BqU^1_s?F|+4(o389j)1!JPb9rFgtIA7y}EXyN?% z9}ko)YFd5CtiZgk6|M2WvKs?ci$A&e!a#dR+vgz48G*90*%!_x0sOq>@!`3E|3>}1 zWto7mapQQ(QE;3%Bx~{?ew1v1Z>GTBe;>fZ><$Vqc+*Wcc|mDixrz+@&6>Qp;-ZVC zPV1&LuAL;AtWO%oJb?=HN>0?a<%Tf}rQhMy$B%&fN7Ur(?tIlKfk>Zk5vKINkWm_% z-JTzBA9ySLJggHe5`Qp6sBy#-X$eaH^`BrEkG2}d2X0fil*FqJji*5yM(G|kX!{6$ zQG1`2ni5SFSryk5ubEudk9)wptABTMpM+bf$yUV_6>vqdc_#wQvmspk{yX6$?54L; z6RZl~gXF^eTEBT;zd3K$?&jv%Zg_afb&IXU;nJABH1H}wTOXNr}kRhv9Z-2bnN)dOdRorEoXGfU0zu2m< zisNtKzkf~0N-ZuPIxCmIl|pb$rsMrqBEyLOHD_5BySg$ie~?vTPwA&W8(z9w(M#17 zS*b{{yUKncY9F!eNU(&@?Uwy49|D<=g2&$eE=at*5Qa&p^Zv>KwRrGf*kEO2hTlN8K=itO> zIx=C*f|iI1K(z~?FEk7-!4D$umQSO& zs6xn(*$i#<$O~mGuY^?6r!pA|H}V8aR6aBy@vpsJ>a*NRZ4UM!f|Z(IY}rqCYq}DTNOv+*PvuRtKvx9vh1b7KrFQ(xE_fgWG%;1$zTuen!~x4 zU254aD1CR)b{aSL|wJ`hn{QhlloK<|9{DE zc!?unw3vZdYC_b0)Uuy~Y|&ie6=ly^_MxbKj5?Rt?W1y71q=MKR0x_?jf!Xu2BJF$ z3q_W()CtjwLu(!bVxojtsq6eIv6A%wY!8)YfnV;@4r)I`)yV0C*az?ttMGM{iMZE% zG?u!;AFGJ^I|35A=5#9+MgEI;mBaLuo8Q`H-gnTf+O=ERA1D18D*g1-yy+F;>B?q& zOKe7L7g}GBa3S`jqkPSWt<*f|PT1dZ=9-Tx;$dWPvX$~@8PSO^BzKSE*Yk|VRUS)E zWJmSjKKzTp0M*3MbZQ8dC_zBA-28L;eQ$6R;#;W&5bLkmKJ8yozo#kvKEa}X$105Y zwU!-MD$VwwReC)h6m=vDLiEK}!Dot~)Be_{6c3mpaK4&JY#8$hf6$HA96WJKy`(e_8r7C-)Y$TRG zzXJSN_9IrhHCSq%4Xe^n4BJ#x)%$YShf<5ndk>mP)@RHfv~J(Sq%B_7sc#`;)r=)Ao0%SYtBXj`_;tYZPpWm*5rZ2-bt0om%G0mwcj4Pm-SHz zBmWA!f|-l`Rd&|0voO&mUX4?|M*OcMBQ&e2D`DGS8ChHsmKqxRfvfj3=lf&iJ(fOc z2KW?ZRhvS*`f^0Zy@H?F+?1bMMnfV^VqMv<4; zaduEB&&xI48D;Ahu9)r289* zKZfFy5pJ%%8-%0w;i2z1<)<8<5jkE-IjZ8Lf$FlWPBt^^Z7s)`{bEjz|KiF~RfSiS zqbo$qaqz9<$Z-nf=+YbL$HR#Is?`5OU^#mjov-$PDBs1_?S~CifRzfvRy+d#Vs#*r zsxPnXeK~$P1Q`*XV+{1WqHrO@@?BG8%{UO=!HTo&aPinkJqRJqB5P(iPdAiW__S!0 zw3Kd49bG2Sb<_iT@8vIkO7N)6)kMl&A&OQFo2^laN_g>4_a_qlbzH4C9pbw~@#G4aPzH6j{VA^QU$Fc>xW~HqH zEAdK!F5hC7ZwAeqd0(~9ye~8%yz}LvoiF;slb;Mv-ZPpABGye%F^zYP=(d+py6UlG zp2}9bS~vXn$-!gN#Qu+8-vxhfeHWs>3$;9)`c9o2HXj{bc=RKY)Hu~mxxNQ|?*7Z) zS5DVnk6*q?-twt#EZ3a9`s_#f;5_H)b1Zdk)O>VwD(NTB9gBUB<=gbesPcj0_%=ti zSC~t7z;JC7Zx+TYZ=0ET6E4j6pu*7VuBuE4Y`l4Yztc~P$<*abyy@?n=?Td`0&9$N zWL`q2Xy>I-{W``jMbVj&pte3YA|G1NXsR%Xu3&6ez5jKLs4>iR`q%IXOci==)ldgPpB>GJp6ihHF*6LshYq z)cz%kRtyLulqwshV?%IQ;@?T<7iMNrs%lo^n9n*LgY3b#F;w?k<`0v>A|@%QthOo+ zn0KTw|D*)*5E7w6!XryWWp7l@JaA;qDsY&Z!f6^tk>*Y^*Ikc0RivSCo#h)I8DzZFwQ!A|$-E8~$DPSr zG9^$r3!)4`E-~n93v0Zz$~PFpc&_BC^i*(m3u+Wq$LXh-{VJ3t00^D*y0ZT4ucQg6 z{@kJeRnS+U%Ayy~LRv`b%t*E>J+%;dNuERh?4-X|_)7-;$R!&PcSzAE^WCp`nEyN< zFb{$$3@{r-6NEIGEH9IolL0a_V(G#O*$aeb2%>x@QvwpP)KU(~T7#HbxUStwT~$KH zOLWaFM#`>gnsv5B;-^Tq(y;B(Ut^Dvp+)s_l%(INm?`$W(^-g|m4xx8rd|X0L!Am3Kmy-|}c5A*{gh-1)ZBw<55>pqd zd@p3*gpG6iS(M|*Q54q|Sqv&FV$TzsScR)f#ujCX;-EJIl2D-yD4E#H7@NzCT~_)s zHZI+$(71YpBh`SSzJ6UZt|d}U%xODrQ}VQ--u-6p4?rW=K%dFXMvI}w+@)HjG6{(- zjFq}d_;6dUZ>I(G!p53yqi!O5F@Q4_L$UPTN@VGiP6XeS0i*OFzIKye5MP9970CSl z&!n+In!606UPP0km4+;OAR67@c)6v&lD%3K*D+Zc(sxW&))hgMiI1e+vJ_ zVR%4*31)8%favY07X4ZYc7{!;n&z*L z8qtG5K3JS-hJB9(L#gZLIFr1k=vm8U&h-{37^gBbkI;#|eGe;gRBuH}sMHf8savPA zDz@UWvUkMn4UwnRf}+%|0phm-PxM!Sj-;+TlXhOkJs2;rdY zei`ZuVP>)#n4z!h_Vxgn7>QQ=%1nNY0X--tX}Im_PB%Tx-BtuZOVQF7wUaT_4D21N z6G{dP5CKntSZcmS&txMaM=)s;b1X_`5xmw2JT(Tykj*CC**=yb3rM3xa)P{71))W> zGq3UUfg%WPf@Bp+g=6g7ny0ROp5v$m@`g~Rq?SiUOS_;@Q-o%Y!R-Ep4^*=pv zD=^U+k4GRPs6BcY%>6(tRCzp=gKY19E6wV}V~9l{F?f+JUz76xGGA%q&1h zXjRN_SzT=v%!f|E|3wnZE)XMw=HYSyeZs8nyM$-XK&NK+5B-BDn$YlEBB-{kpShk!9 zY;ZU3w7ESDW!sZGmOF5__rcM%P;Ue9?GQXL-_Ltuc-ETpSm{42lm~O&y#VZ8R>SnW zEZ@sGaw8g!xfHUuZRk}qOh2-mqXjQD+f=tY{ z|BMOyfdXLQ!7i-H&H+Q``#^$I!0YBARx|dk2(6`Ll`42NJ{YGuKU5 z;XR|n2MSJ7^fPw~W$5n};~n?a9-Qv%Aqv%t)F=l2-_FV7)j2&@$$d zy;uT!03!T-#Qc|FB3gfv_aIs3et0+0ie5%E*M34}RX!%GKf?8Mb`;G%YT3s!2*%L1A8UAf&BS!%QJI3PUfKI6GugtFkKFAm{n?!^{=_`GOWbtdcEg!2m+ulc-`m}ARD&nH zG2`T0?}n4FY_*h9)hD~JxtS9|C<0?P*GdeZV!V`oaWhS72J0$3MT7pvOmPkkGAKT&r3$xt;iQEgOjWodsWe*a21Q9@JfoaFG*D- zK>=;^QWgJo#OHiKW~O?sk~nxiLouFI9gL!tor^3f|LDwHIFS{Hm!p=6FeHXM<}44r z$~K4&P&&oTgqN5G-MI9EN2OZA=*7#$lw6Jc#@6)<2+OPMtSL5Ov`!eKbs|e+GM3(z zW8(c{+<1X8@xCSv0rQ3V^HHiVz9)DDjB-GD0QZ=^UzW&sSJ{tcX0f@L_Z^|1R$bNm zMto5fW(%rPl_giCr@zh`pu5CmV$-7N&Dn1sLhCI`!{r(2%=PG@@`0s9#9=JkFU1uol+e5@*F@Z z0`PTH^Wi3`;zrX;CSjFBjS!VRXThHqI+zQovWGPlaNHw#ADy?iu>686(y?-1l-3`m zt#hcyIb4EI$hjX(Tg=%d-2)=DSQU_o+4~?Uu_X+bK) zxwV|R*0_ErHzlD8RZ7M%lcl7Eu`Vm2vh0nRJrqmt2yS6&kg3C6{6+>3VFOeT5nMAr zC81(r-Tg73l$}lN^~EZnqh@j%N;W?gd##YOG@-JCRdCiYWVbloMV87_m4&#KpfYje zKx0RmJ4-5NooNzS5}6IHhU>rX3k!+BDXT~rIjU}wHBujQ-!Du$Rk?}!Wdg% z{c=9`B>X1k4EV{1#SKCy^`q4>Y5;ocorljX_$^tg(x&U$lI*7xm*|@+VFA_D0Z1GH z2@*sB6se(~pa|K!Xx{AKWP?b>XU-Ig+{d*i^NM1yC9F3Kn>?`HrlQ|mw+JmG2E9sM z<>!<~#lvReayAy(IHwByg6ahr)1lF}03@<~%_=Fnxp} zF6P7G7A6;zb`eQ~24$lt`D4%)+%r>uMvx1u+gJyDtF}7Azd5NMPc`< zDsC+@*Ou`KlSnc9EzBRyqMGh}snGHr!qy{y%EFRbD~F2<{V}`I)!YS~ur0y75^Fhg z8^(4tI?G9^;IqZ4g2eDbGr1lGUA;CjyedBFvPl8M=t@zWt5erOo3Wt@U2+Vwfe}ZV zy2XMdCX1Em$iEmBRf)(mb0?f_X7(nilU|F6=X~nqxMo-N&xxB017>m(V>zTTLu82) z%xPJdd?0fQWlH+b(J&$VIxVSnPXXoH5#(Gql-B+N8x`wX4c1GbHyEswDn_V{k}KQs z_$B`v1^zZ%Y_{hskh{(gWKRNF{mfGJP$Dy7AvtTx=?S!>7H|UkXqYgup&I}bbU+I20<&Fg4B12(qpbt_D}sXG3+;!UqpI)XX1so631W= z5928@JUMR4!k2}vQ06M2Xjrnd(y?H9_yIrSV2c~-w;KGxB@;oUCmO$2k`H7MLAHlJ zXkia*@4@(w>G)t<9PQ4lv6=IVIWs2hFR@4Ek^L`mz>rVKZ>6p&QMpKlRmfTyUMw+f zesWYEW^$2K6Z0{X3jlkvfvS$p$wp2&`8$kMAz#MU{4^+jM%gD$E5=fHJM+Mpgs0ZQ zR)uh{viHK{q0O=I6iwV(Y?#R>P>-;tnI~CWj@|eLai}>pv5}OCj%fPo_RMV}KxH>< z+6{D6eV}E;PZF`HCwr2WR?}Ek;?^SR6R9-(iQY4`$9ZVyg9zF)^Uq$i9})N?yib7w zAMn73Jn*0g?(x9175p*hZW3c={N;Dmv{f(^*jUY?Usa5alTKIdnvbEyqOXZ#MP_m# z%5JWG25GRp&RpAq$HcKSx;~V+)jzH4tp76Gl-83VrDIN0D-p8p$8DGupM`n+4w>|2#+CDLlr_-q(;D*)w}@VwiF;reOX^l+)>x!CTZ`h;>%* zx2_H$&3zFr)m1`udmlt8Ik0S%d8Z8^45x#0Ju=Up7@iI15XeYs!BouPn#q4gzfbG2 z9!T+2uuThvWx>!Yl@hX6EJmWLu@|Zao3H~)VHqkGyPctUC`C;A%@jjs0_f9xU4*;L zTvGQ(xyB*XONZIJ4(3J`{tJY3;oI=U+_xen3LeUSR@)^So8GH+x=KK(S7)IYoddW) zy(&e{egvVe|0Xg%jR|!&emr@yv9f;w%X#tt00j8h0;1eGIXN+ms(BnpPqOlCKM?eM z>n!`t%!i)BIQ$2|C_5TWFRTlvuAjw8bc#s43rBn+T#Ap>Tv?(H*di#(s?^n?%s*kE z%WC@(m~|?)*HbPg)isIHySRuER1`BKl^VuyEd~vYw-&3tIa@H3UpqYhOZ~bohb9@JH5s2ou+jLZF_BYuFK(#IGWb>!)EnW>s_oc?Ilb z1iKO1D|?^ALJZPHQj1{%p_oNZ!?#d=X)smxAlnY=Shm67P6c7Lh!v#6&W8}2OS$tP z7LcmI5NX0C&O=G&R%juW^51Y*c0ep4wJ^^T=Eh&QAEU=?_Rgi zlP$xNCG)RL^|I=z4vfg3=E7yEqzY0GWfnUP_GYI;8Dv~G$AcmS^dc5TW=~*6pd@i6 zy{QPz{tW+IxuX8(rKXl*x4PMD0S`$~LAYd*{1wWD0kWC=C3sU6Y9>1niB=J|>`i8o znfy44CROu8h$UNx@Lc)Di9DNhj!iJvUV<>`!p{<*4C}uDBACvOS7O$rmv%gyxT!D@ z7r|2`QF|B@4=}H+MOOxa%p44`QQWv+_O_syuD(mDg`0E8%|ZO5-Js`$Vxg1yF)*y} zO%xb=Tc)t*;oU51*I}5O?7v8&9z^h@qnXp`DCl#j7GO%$BV9dWU5Ym=65pjF!&nNI zHIP~a^@{8ob{OSL6U->VjOKu*(j!D6C*@F;X+SzELW7NAtJY4ajH@E9a=IdM)M73s zy~tc6xn=f}*=fvd0RQ@Q31AS|CbH*2Ych9&IBZED_PE#+0Fy zsHAHAM)|oDYXc#_1P+9XoO`iz56C_3HJhLyrg95|@M9a;sz8CadEobEHouLOG?!39 zBm0{-l|HbrJwQZLUu79)Jz_gZ7XqZIZ%DReiz6q z0m)np={Zb3V8Fh@-Z@?ZCK{mC3gzBDH<+l!@m z&w?Nz|Kl!xmS`3C42C@-w>(-fT`oh~w7)6YhD@|058ei*Pa0*gpU+1~I{7NRSylwfGWd#3}wEx6ABVF?lI&39|ik;AC#nNDL=PVDunKd5-Ye!ZWqm9QOaiWpl(9cyl z*!FvGBW12GG_%!%vU)#E=5Xz!N-~_PP4%p2%=EW?w^USPSJ%tBtoFm6;_70aPKI@U6c{W_h`Ng(VUD&0hGbiasCE&6 zYdkQ=Y7!Cn77r|45dxUD+k@|M;Z${b6v`~Mh&Wq>ii*G018?)d+g%u20`HJj6{iZ+ zOlIpunaMmr8Kj+l7wp$?+(RTy46B*rSlAcoE|?Wr)LHt}=q1Cfn2=>+)9u{`ZK5_i z6!5|y9#}Gxl{}$MES)v5m&Q|cQm-9VmK}t~K#{6RIGnoH&-sr_geG3#uCl+zs*T#e zpteTsudSDxYG-T&y>G#;QEl2B7i|y)iNa%a{6@zrpt#a$kV!It5xFY6Y9aI3X`cm3 zGVc^i)wOUbFgb~_$5C>0avmlBJrY~;YWf09X=Yq$(u3+lv9XyD@2BH|YDD?VU3kC) zV<;Y0^(zPBE+JPyFMu&AO^M{TNu&&Ta$nBqGY-(gg)r7jU-m`RHuF9t@>D~04v+WY z+44P(kU>Ja{L0y23f8S#lbkB;=QHp}cn7cQc_-PegK7)|&0nVQ(UFk{S+&?MjMoN| z5pn>2>RdK5N8w0dWj|g04#=@oi8l+(bw5XsBU|hGBmo)}CXx{$LYXiChiY>yAHF6eY1dFX#!|9PCFUhc%;>2A3|x|T6UW#o1?V;je5>XITqP-85>J% zX#NyA1)~HCHBdsQI<#l12V@qGbz6XK8<00G<#t@y7Cev%*y{~Y@~ux!%1q#Hri^&!aUB)up_vuY?c6-IYIjQFGy@q7l9kSR&gPqwF^hmg;TxysFHk0>aH!W=Rh#6-q7P2 zEHyNr=WqnYV4OIPl92zPkf}4plmPhLD zcoA!s^en8V62m1`cDig($xUcbnkzK9Zr8=(n-Pf5eb3mXvLo0dkE(T9saDE-vp9cv z{~t!H55d?zAbtrml)6v+*#}coBfL9#%JB#rCD^>rsMyzeE(`Mt4DZ~j=DNGEtuK~7 zD}r0JVR|CwdluWC`)2GbI|z|ibB=*#`7iedX-$1Q@oWJI+mDwWj1+7T!)yLOGgu z5QrW|NvZO)p^M2uZBPoJ;B?Ww^Em;CO4$yyVJ2lh5DEl`Ryne2aL;K&*U7`=nQHiy zN+FZ0!9DCW_;u59d{2@(oilqSNtyCtd7;j6q0xVl0krj>JeV8Ti+fa~GDG%^5l&V4 zS@3F3+DycrPYVM^*>*)cELIM&2-9xzN0>&=g=xtY9C2p+(-XO`B@7<+A;3zj*9>T` zp+L%G`5Z`ibw`IR>*}r7yCXlmIlL&4RaG@V2Z<~P7A$C3p+RA6(w>xS)i%gpJ*eg15$iv4}wvk2>w!viAXG1J8ciA@M=dg&=!B zDc+oFy|MJgw20YDoJcc%n#?Az$*wvV77Io4+E zBdd-zDm$nd1b<`fPj&~=yW@W3)crt?0jWe#hHouS4%=b`;vB|Z){IU?siQEa(TWjs zZ3JUZ3WuS8%NEIu%+L6`0uqQxb~=7*CK?C{cutBzr;m!%j)3l#*&QFdk2J9Dh%C`< zbR7URG%^APjqDO+R7C?1R{4sQWQeZg5CSn2G3H{g&JbX8-D~hk=KA6vnTt2?J_MVJ z!pdL@f;n4!F30BDd$Y+mb5#<9N_GE~d0{)==MlhS_2ZGg9E&r`3yw&6aMYFO@Fr2# z%nX(XYeTsrIS!3m>)vwRF0Q~vam;a43AP5$oxqpyk{NWmSeKyYY`veWLVxyk9d#*W zA4X^lulYF5jNbDm@R;Awh*2*^40MJ$mZmgywK}yG!x?VJ>1|}=#dCO(AUgwGM$^+L zSThE|kZPz-mb8xE%E-Ja#fOO-$oyG>nLpxAMI=MgYEfe$-&~9xS!HvVn#q@NPvRZW za8LJykDJLS@kp2aI@E_dLNLE94HO0)PEt)>3|_Vv47duq=ya;;yu(cD6mzCvXuQ0` zOm|1(CDI$Iy<*~4sj+65V@=Kl)nQHi6TT`8IYqp>4i?B1v&SBD9%m$bIvQha#z@S! zBTp{b_e*r8d{y>S*-3bgq7p=S>$_WuSl1wTPr=wvCv@&=1&9p%8`&&Zy@ zSCvo&@QAZg0Cr+u1#_{~Y1uD9RNVZiMsyB;4r^?@#ULTZdK*Z&rGYk)I@%QqV)p(O zZ!<8iaHvb72QVB?I1N2-1F&l7p&ySb0u5IQsAs$v&sS8hRpvv=^_9e8|2lB#;-7r2W%)J=de+MJXweU%UWhaQ<#{L)m@i?3THAv^S2zP9bBhX+8_y#R2TsBKQM~VMYUQ^>r znqtka6ieXP{wnT#xqzAl-JzPqY#adk4Y!R`(_o}POIkTI+71(`&6Xbcqm|&~A25$`+?;Ip9}xnx$9m!~yIK_9 z(Fd@j?5k#n?-WS!T%MHn<(E67( z-fvDE#zdUEz5kI^6blDf3&o3XzrvzF&X?^B$eTppghZ@#YcMu+2GXN5h;fqiUSO+I zmq-kr5h>fW+_iVS?25BqsC3+9lxca91FHBQY-X;`EnKSii(~1|fTCWe$8Dv@p%V}~ zUEAS;#4sM4qw?>1R4w^A!+yB<0q}$4bw_2V)-mDV=5vuJp3vz1eSTCmU$yF%J0=HM z_2`)C*RU6;!82BoIaF1>oD7NiSPEr|rqD95Ka+`QP$iM-Uilo7C?Pq1poMXugCxu! zVY-X_5vGc{Fk7t)(^R=|zynidT|9e1fsyA{0LjHUz!&Zb><>; z?x@RdCJ5UPVN45eqXPEtbJ$6VMV7l&RxlbY3J~{*Jk4o$OFNbrESx#*9x+i8qYenZ zF}GdJ)=Ao1>J7dteH2wTWg zg}<$`kIANIxVqKtnX9(a=1d3nRra)O4dLxu5Sgd*W^l)1!0);SIDJ79xx^?IMa@oW zkav&hRWkTdelQ8cy#@?Ht8x4oILtLKyei0z743)=n~{n6lz61qRU*s00E37DFicb( z4mjkt(sj!~i|_UnnqO+?bRE`?-ue%$8th8E_*T!G*oZe1SheP{fo!3|$v0grwhSy5 zJqQY@V0OYlQh17A*&<;kKT4`jY&QZ^Z9yt0BF4$kCm$kO38gbWVac)!Acgga$e;P; zZHR$BrrSy{gwOGUHL$Rq0aUK-ybmlC-9cBCd=wTovrC)+jP$@0>rC!$A}2C7dZ6RF z3VZQzuFXft0w?3K+X+%slN8cU(-;4MVF>7FKpG2vxFh2Od_>(*7&L$Bdz>wUcpnWx zWp6+WVJQG&(&7WcEhf+K2)rW3HgQNHpc4RCo8UrW-B?K4I}ZrX zSg2G7yUxf~1LOLinH18=o99!Q5WdAtBm|M0!bYo#RR<5K#FNlQKv||8Lc2Gh&Z$b&lyvQm)nb{#DQ@r0N zudyMFZNDF)pp?a=V;yN9o;~|RFgn=&Z!Ce*L-FD4Y}p%`?+8}rmD@AF|DLlL%(~Q- z2S8OCnux9>w1r##Rz-R9e1FgaJyqT|L#Z+lyj$H_iYx zldsA+&$WP~`aqCmE7KM$)9|ktIlY9Dt?FmV=@xL9&BFO{#y8jsgH8iwd{T; z9JNPPb|$T0L%}`I?i&UY^9&`P^&{(UmT7~ixC~ui!MLv&#Lz~lTS#HZITEzfEI5e9 zzs2eC03Tq~`{nNF0NhjRfR(zw-AY}poO8zrHh>x!qpic4pb6|rUfV?!rmEP?`)kl1j?b}sZl zw})Z&^_Z}q#Bom#)7cA);P=#71MB$6pS`dIan}O^k~jYBg|b9d3NC>qLH+>xQ#Ybj|~>k+AC1Fttde6 z!LG}>Kw_~vm>zdCc>@@O9XOBFLsCptzH9-eV^Dt-HGkPHm|YmB3(oc+Ugk73KP+XR z4|Q{G1;EnDHydIMcrK?`Tnc2|$Z) zrgA6Q)w9l><^wKeuD28tb|!w1+|z_6ep@x6Iz#}c@SV|w=mVk(SW);hvZu=YmgA2l zkTv}=hCn#k8{Z%Wtk~dLTLH2)3Anqpk)r7jIGJ*@B3=Je%;4tp=at=n;FiizSHun!8xXyi~g&Q4~ZC?WeM= zYQZK~RIJm{Cv|1uuHKNuAQHm;O1nz*Yp9=(LOY415Xhk`4Rlk1-c`f(+Ez z=+M&{3b*A5nL;P-M=aF#E#K73eh`e%h0!Bj`5=kfp!y&a<&$*Z{oJM2ArUSNss`Ut zY}q`9D=Fg}%l=dV&qaKe#&3VF1f}!i!naWDn@X*LI}VTle&)0*%7M26=Cn^)j8F

VA25i#Rc>G0jvKN( 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 Date: Sat, 4 Nov 2023 20:39:19 +0100 Subject: [PATCH 064/485] Update README.md i most likely forgor smth but the most important thing was libbacktrace dependency for building the gam,e --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.md b/README.md index 9bf915be8..c21b843de 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,11 @@ - Sprites player rotation on slopes; going on hills, levitate, going down, and so on alters your sprites (configurable) - You can alter all the base kart HUD element offsets on the fly in the Saturn Options settings menu - `addfilelocal` Command, for those who want to use things like their custom hud in netgames (Same as addfile but completely client sided) +- Palette rendering, make the OpenGL renderer (almost) look like software mode! - OpenMPT for Tracker module playback instead of GME - Fixes looping and sounds better - Allows filter configuration +- Colourize your Kart HUD, to either your player color or whichever colour you like! (optional / requieres extra2.kart file) - The minimal brightness with Shaders can be configured, now you can seeeee in dark areas (0-255 , uses Sector brightness values) - Lua HUD hooks for Intermission (ex: You can make hostmod votes still visible during intermission!) - Lua HUD hooks for Vote Screen (ex: You can make hostmod votes still visible during map vote screen!) @@ -17,9 +19,12 @@ - Smaller Speedometer (optional / requieres extra.kart file) - Record Attack input display can now be used everywhere - Smaller minimap icons and also show player names on the minimap (toggable) +- Support for animated votescreens! - `showmusiccredit` command, shows you the current music track again - `listskins` show a list of all skins currently loaded - Visual Portals from Haya's HEP Client +- Horizonline effect in OpenGL (watch the endless bricks on SNES Bowsers Castle!) +- Localskins! use whatever skin you like! - Toggable lowercase menu's also from Haya's HEP client - Everything that Galaxy has @@ -39,6 +44,9 @@ - Toggable Lap animation - Main menu shows the current renderer being used - MSAA and A2C Antialiasing support (Configurable in renderer.txt file) +- A simple button to rejoin your last visited server +- Ability to show ALL maps in the mapselect screen, this includes hidden or hellmaps "showallmaps yes/no" +- Ability to toggle the Stagetitlecard "maptitles on/off" ## Performance / Debugging @@ -57,6 +65,11 @@ - The annoying depraction messages for `P_TeleportMove` and `P_AproxDistance` have been silenced - Silenced the annoying "cant find next map..." messages as theyre super useless and annoying anyways - Added a small cooldown on `map` command due to spamming causing a SIGSEGV +- Many bugfixes to the Software renderer, so its much less prone to crashing +- Many bugfixes to the OpenGL renderer (too many too list all of them here; check the changelogs for more information) +- Bugfixes to the soundsystem, mainly regarding Sound muting +- Refactored Zone Memory Allocations (helps a bit with large maps) +- Many many more crash fixes and other bugfixes to the basegame (too many too list all of them here; check the changelogs for more information) ## MISC - Bird's Camara Tilting feature is no longer turned on by default @@ -67,12 +80,16 @@ - A2C antialiasing makes transparent surfaces even more transparent - You tell us! c: +## Note +Check the LUASTUFF file for more information on all the lua things Saturn has. + ## Dependencies - SDL2 (Linux/OS X only) - SDL2-Mixer (Linux/OS X only) - libupnp (Linux/OS X only) - libgme (Linux/OS X only) - libopenmpt (Linux/OS X only) +- libbacktrace (Linux/OS X only) ## Compiling -- 2.54.0 From 262a07ea9ae617cc2ba60144265febe62893cf9c Mon Sep 17 00:00:00 2001 From: Alug <136046486+alufolie91@users.noreply.github.com> Date: Sat, 4 Nov 2023 21:10:45 +0100 Subject: [PATCH 065/485] Update README.md before i forgert that later lmao --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index c21b843de..fa2bb6881 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,10 @@ - Refactored Zone Memory Allocations (helps a bit with large maps) - Many many more crash fixes and other bugfixes to the basegame (too many too list all of them here; check the changelogs for more information) +- Crash Backtraces have been replaced by libbacktrace (except for 32bit Windows builds) + - Crashlogs now contain alot more informations. and even more if your build has debug symbols + - Also allows 64bit Windows builds to produce Crashlogs! + ## MISC - Bird's Camara Tilting feature is no longer turned on by default - Bird's warning on the title screen has been removed -- 2.54.0 From a211badb73688e56a41ff39dc6edc39f741e54e3 Mon Sep 17 00:00:00 2001 From: Alug <136046486+alufolie91@users.noreply.github.com> Date: Sat, 4 Nov 2023 21:11:25 +0100 Subject: [PATCH 066/485] Update README.md bruh this formatting --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fa2bb6881..d5a3d2b41 100644 --- a/README.md +++ b/README.md @@ -72,8 +72,8 @@ - Many many more crash fixes and other bugfixes to the basegame (too many too list all of them here; check the changelogs for more information) - Crash Backtraces have been replaced by libbacktrace (except for 32bit Windows builds) - - Crashlogs now contain alot more informations. and even more if your build has debug symbols - - Also allows 64bit Windows builds to produce Crashlogs! +Crashlogs now contain alot more informations. and even more if your build has debug symbols +Also allows 64bit Windows builds to produce Crashlogs! ## MISC - Bird's Camara Tilting feature is no longer turned on by default -- 2.54.0 From 3b4187389317abdbf4f3589d51ee82f9115d31cc Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 4 Nov 2023 23:09:39 +0100 Subject: [PATCH 067/485] make the thing compile, remove drmingw stuff from 64bit builds and properly link libbacktrace rip in piece drmingw but we got goddamn 64bit crashlogs now c: --- libs/DLL-README.txt | 5 +---- libs/dll-binaries/x86_64/exchndl.dll | Bin 29696 -> 0 bytes libs/dll-binaries/x86_64/mgwhelp.dll | Bin 828416 -> 0 bytes libs/drmingw/lib/win64/libexchndl.a | Bin 3206 -> 0 bytes libs/drmingw/lib/win64/libmgwhelp.a | Bin 83034 -> 0 bytes .../libbacktrace/bin/x86_64/libbacktrace-0.dll | Bin 79738 -> 0 bytes .../libbacktrace/bin/x86_64/libgcc_s_seh-1.dll | Bin 117427 -> 0 bytes .../bin/x86_64/libwinpthread-1.dll | Bin 60356 -> 0 bytes src/sdl/Makefile.cfg | 4 ++++ src/win32/Makefile.cfg | 6 +----- 10 files changed, 6 insertions(+), 9 deletions(-) delete mode 100644 libs/dll-binaries/x86_64/exchndl.dll delete mode 100644 libs/dll-binaries/x86_64/mgwhelp.dll delete mode 100644 libs/drmingw/lib/win64/libexchndl.a delete mode 100644 libs/drmingw/lib/win64/libmgwhelp.a delete mode 100644 libs/libbacktrace/bin/x86_64/libbacktrace-0.dll delete mode 100644 libs/libbacktrace/bin/x86_64/libgcc_s_seh-1.dll delete mode 100644 libs/libbacktrace/bin/x86_64/libwinpthread-1.dll diff --git a/libs/DLL-README.txt b/libs/DLL-README.txt index 8d388d412..a88bf9938 100644 --- a/libs/DLL-README.txt +++ b/libs/DLL-README.txt @@ -27,7 +27,4 @@ and don't forget to build r_opengl.dll for srb2dd. * libs\dll-binaries\x86_64\discord-rpc.dll * libs\SDL2\x86_64-w64-mingw32\bin\SDL2.dll * libs\SDL2_mixer\x86_64-w64-mingw32\bin\*.dll (get everything) -* libs\libopenmpt\x86_64\bin\mingw\libopenmpt.dll -* libs\libbacktrace\bin\x86_64\libbacktrace-0.dll -* libs\libbacktrace\bin\x86_64\libgcc_s_seh-1.dll -* libs\libbacktrace\bin\x86_64\libwinpthread-1.dll \ No newline at end of file +* libs\libopenmpt\x86_64\bin\mingw\libopenmpt.dll \ No newline at end of file diff --git a/libs/dll-binaries/x86_64/exchndl.dll b/libs/dll-binaries/x86_64/exchndl.dll deleted file mode 100644 index 747d7a3d560364af4d1ab588e251afd5d7b12871..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29696 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 mzs&xn^h+>DaUTF+?B@Kuh}o~c>m`| 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