From 524168b20b3a32d26cc9ca38f982940eda1a468e Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 2 Oct 2025 17:15:14 +0200 Subject: [PATCH 001/219] experiment: remove opengl adjusted segs in theory this should improve levelload times and reduce memory usage? gotta see if it really does, visually so far there seems to be no difference at all --- src/hardware/hw_bsp.c | 103 ---------------------------------- src/hardware/hw_main.cpp | 116 ++++++++------------------------------- src/p_setup.c | 11 ++++ src/r_defs.h | 12 ++-- 4 files changed, 43 insertions(+), 199 deletions(-) diff --git a/src/hardware/hw_bsp.c b/src/hardware/hw_bsp.c index 8cad91168..5889dcb44 100644 --- a/src/hardware/hw_bsp.c +++ b/src/hardware/hw_bsp.c @@ -80,14 +80,6 @@ static poly_t *HWR_AllocPoly(INT32 numpts) return p; } -static polyvertex_t *HWR_AllocVertex(void) -{ - polyvertex_t *p; - size_t size = sizeof(polyvertex_t); - p = Z_Malloc(size, PU_HWRPLANE, NULL); - return p; -} - /// \todo polygons should be freed in reverse order for efficiency, /// for now don't free because it doesn't free in reverse order static void HWR_FreePoly(poly_t *poly) @@ -855,100 +847,6 @@ static INT32 SolveTProblem(void) return numsplitpoly; } -#define NEARDIST (0.75f) -#define MYMAX (10000000000000.0f) - -/* Adjust true segs (from the segs lump) to be exactely the same as - * plane polygone segs - * This also convert fixed_t point of segs in float (in moste case - * it share the same vertice - */ -static void AdjustSegs(void) -{ - size_t i, count; - INT32 j; - seg_t *lseg; - poly_t *p; - INT32 v1found = 0, v2found = 0; - float nearv1, nearv2; - - for (i = 0; i < numsubsectors; i++) - { - count = subsectors[i].numlines; - lseg = &segs[subsectors[i].firstline]; - p = extrasubsectors[i].planepoly; - - if (!p) - continue; - - for (; count--; lseg++) - { - float distv1,distv2,tmp; - nearv1 = nearv2 = MYMAX; - - // Don't touch polyobject segs. We'll compensate - // for this when we go about drawing them. - if (lseg->polyseg) - continue; - - for (j = 0; j < p->numpts; j++) - { - distv1 = p->pts[j].x - FIXED_TO_FLOAT(lseg->v1->x); - tmp = p->pts[j].y - FIXED_TO_FLOAT(lseg->v1->y); - distv1 = distv1*distv1+tmp*tmp; - - if (distv1 <= nearv1) - { - v1found = j; - nearv1 = distv1; - } - - // the same with v2 - distv2 = p->pts[j].x - FIXED_TO_FLOAT(lseg->v2->x); - tmp = p->pts[j].y - FIXED_TO_FLOAT(lseg->v2->y); - distv2 = distv2*distv2+tmp*tmp; - - if (distv2 <= nearv2) - { - v2found = j; - nearv2 = distv2; - } - } - - if (nearv1 <= NEARDIST*NEARDIST) - // share vertice with segs - lseg->pv1 = &(p->pts[v1found]); - else - { - // BP: here we can do better, using PointInSeg and compute - // the right point position also split a polygone side to - // solve a T-intersection, but too mush work - - // convert fixed vertex to float vertex - polyvertex_t *pv = HWR_AllocVertex(); - pv->x = FIXED_TO_FLOAT(lseg->v1->x); - pv->y = FIXED_TO_FLOAT(lseg->v1->y); - lseg->pv1 = pv; - } - - if (nearv2 <= NEARDIST*NEARDIST) - lseg->pv2 = &(p->pts[v2found]); - else - { - polyvertex_t *pv = HWR_AllocVertex(); - pv->x = FIXED_TO_FLOAT(lseg->v2->x); - pv->y = FIXED_TO_FLOAT(lseg->v2->y); - lseg->pv2 = pv; - } - - lseg->pv1->x2 = FloatToFixed(lseg->pv1->x); - lseg->pv1->y2 = FloatToFixed(lseg->pv1->y); - lseg->pv2->x2 = FloatToFixed(lseg->pv2->x); - lseg->pv2->y2 = FloatToFixed(lseg->pv2->y); - } - } -} - // call this routine after the BSP of a Doom wad file is loaded, // and it will generate all the convex polys for the hardware renderer @@ -1017,7 +915,6 @@ void HWR_CreatePlanePolygons(INT32 bspnum) #else SolveTProblem(); #endif - AdjustSegs(); #ifdef DEBUG_HWBSP //debug debug.. diff --git a/src/hardware/hw_main.cpp b/src/hardware/hw_main.cpp index c88b075a1..dc8cb55c0 100644 --- a/src/hardware/hw_main.cpp +++ b/src/hardware/hw_main.cpp @@ -741,27 +741,11 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool P_ClosestPointOnLine(viewx, viewy, ld, &v); dist = FixedToFloat(R_PointToDist(v.x, v.y)); - if (line->pv1) - { - x1 = line->pv1->x; - y1 = line->pv1->y; - } - else - { - x1 = FixedToFloat(line->v1->x); - y1 = FixedToFloat(line->v1->y); - } + x1 = (line->fv1.x); + y1 = (line->fv1.y); - if (line->pv2) - { - xd = line->pv2->x - x1; - yd = line->pv2->y - y1; - } - else - { - xd = FixedToFloat(line->v2->x) - x1; - yd = FixedToFloat(line->v2->y) - y1; - } + xd = (line->fv2.x) - x1; + yd = (line->fv2.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; @@ -825,11 +809,11 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf) M_ClearBox(segbbox); M_AddToBox(segbbox, - FloatToFixed(gl_curline->pv1->x), - FloatToFixed(gl_curline->pv1->y)); + FloatToFixed(gl_curline->fv1.x), + FloatToFixed(gl_curline->fv1.y)); M_AddToBox(segbbox, - FloatToFixed(gl_curline->pv2->x), - FloatToFixed(gl_curline->pv2->y)); + FloatToFixed(gl_curline->fv2.x), + FloatToFixed(gl_curline->fv2.y)); splat = (wallsplat_t *)gl_curline->linedef->splats; for (; splat; splat = splat->next) @@ -1324,35 +1308,15 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom const boolean noencore = (gl_linedef->flags & ML_TFERLINE); - if (LIKELY(gl_curline->pv1)) - { - vs.x = gl_curline->pv1->x; - vs.y = gl_curline->pv1->y; - v1x = gl_curline->pv1->x2; - v1y = gl_curline->pv1->y2; - } - else - { - vs.x = FixedToFloat(gl_curline->v1->x); - vs.y = FixedToFloat(gl_curline->v1->y); - v1x = gl_curline->v1->x; - v1y = gl_curline->v1->y; - } + vs.x = (gl_curline->fv1.x); + vs.y = (gl_curline->fv1.y); + v1x = gl_curline->v1->x; + v1y = gl_curline->v1->y; - if (LIKELY(gl_curline->pv2)) - { - ve.x = gl_curline->pv2->x; - ve.y = gl_curline->pv2->y; - v2x = gl_curline->pv2->x2; - v2y = gl_curline->pv2->y2; - } - else - { - ve.x = FixedToFloat(gl_curline->v2->x); - ve.y = FixedToFloat(gl_curline->v2->y); - v2x = gl_curline->v2->x; - v2y = gl_curline->v2->y; - } + ve.x = (gl_curline->fv2.x); + ve.y = (gl_curline->fv2.y); + v2x = gl_curline->v2->x; + v2y = gl_curline->v2->y; #define SLOPEPARAMS(slope, end1, end2, normalheight) \ end1 = P_GetZAt(slope, v1x, v1y, normalheight); \ @@ -2203,27 +2167,11 @@ static boolean CheckClip(sector_t * afrontsector, sector_t * abacksector) { fixed_t v1x, v1y, v2x, v2y; // the seg's vertexes as fixed_t - if (LIKELY(gl_curline->pv1)) - { - v1x = gl_curline->pv1->x2; - v1y = gl_curline->pv1->y2; - } - else - { - v1x = gl_curline->v1->x; - v1y = gl_curline->v1->y; - } + v1x = gl_curline->v1->x; + v1y = gl_curline->v1->y; - if (LIKELY(gl_curline->pv2)) - { - v2x = gl_curline->pv2->x2; - v2y = gl_curline->pv2->y2; - } - else - { - v2x = gl_curline->v2->x; - v2y = gl_curline->v2->y; - } + v2x = gl_curline->v2->x; + v2y = gl_curline->v2->y; #define SLOPEPARAMS(slope, end1, end2, normalheight) \ end1 = P_GetZAt(slope, v1x, v1y, normalheight); \ @@ -2428,27 +2376,11 @@ static void HWR_AddLine(seg_t *line) gl_curline = line; - if (LIKELY(gl_curline->pv1)) - { - v1x = gl_curline->pv1->x2; - v1y = gl_curline->pv1->y2; - } - else - { - v1x = gl_curline->v1->x; - v1y = gl_curline->v1->y; - } + v1x = gl_curline->v1->x; + v1y = gl_curline->v1->y; - if (LIKELY(gl_curline->pv2)) - { - v2x = gl_curline->pv2->x2; - v2y = gl_curline->pv2->y2; - } - else - { - v2x = gl_curline->v2->x; - v2y = gl_curline->v2->y; - } + v2x = gl_curline->v2->x; + v2y = gl_curline->v2->y; // OPTIMIZE: quickly reject orthogonal back sides. angle1 = R_PointToAngle64(v1x, v1y); diff --git a/src/p_setup.c b/src/p_setup.c index 2ccbd1821..afdda1ded 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -544,7 +544,18 @@ static void P_LoadSegs(UINT8 *data) { li->v1 = &vertexes[SHORT(ml->v1)]; li->v2 = &vertexes[SHORT(ml->v2)]; +#ifdef HWRENDER + if (rendermode == render_opengl) + { + li->fv1.x = FixedToFloat(li->v1->x); + li->fv1.y = FixedToFloat(li->v1->y); + //li->fv1.z = FixedToFloat(li->v1->z); // z is unused in gl + li->fv2.x = FixedToFloat(li->v2->x); + li->fv2.y = FixedToFloat(li->v2->y); + //li->fv2.z = FixedToFloat(li->v2->z); + } +#endif li->length = P_SegLength(li); li->angle = (SHORT(ml->angle))<offset = (SHORT(ml->offset))< Date: Thu, 2 Oct 2025 18:37:05 +0200 Subject: [PATCH 002/219] a thousand curses upon you polyobjects! --- src/hardware/hw_main.cpp | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/hardware/hw_main.cpp b/src/hardware/hw_main.cpp index dc8cb55c0..1c7234d2c 100644 --- a/src/hardware/hw_main.cpp +++ b/src/hardware/hw_main.cpp @@ -729,6 +729,9 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool for (i = 0; i < subsector->numlines; i++, line++) { + if (line->polyseg) + continue; + line_t* ld = line->linedef; // this check sucks and is a hotspot lel @@ -1308,16 +1311,26 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom const boolean noencore = (gl_linedef->flags & ML_TFERLINE); - vs.x = (gl_curline->fv1.x); - vs.y = (gl_curline->fv1.y); v1x = gl_curline->v1->x; v1y = gl_curline->v1->y; - - ve.x = (gl_curline->fv2.x); - ve.y = (gl_curline->fv2.y); v2x = gl_curline->v2->x; v2y = gl_curline->v2->y; + if (gl_curline->polyseg) + { + vs.x = FixedToFloat(v1x); + vs.y = FixedToFloat(v1y); + ve.x = FixedToFloat(v2x); + ve.y = FixedToFloat(v2y); + } + else + { + vs.x = gl_curline->fv1.x; + vs.y = gl_curline->fv1.y; + ve.x = gl_curline->fv2.x; + ve.y = gl_curline->fv2.y; + } + #define SLOPEPARAMS(slope, end1, end2, normalheight) \ end1 = P_GetZAt(slope, v1x, v1y, normalheight); \ end2 = P_GetZAt(slope, v2x, v2y, normalheight); -- 2.54.0 From 2eac9fc295e0579cbc1efb4c709ab54ae2e6d154 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 3 Oct 2025 16:39:04 +0200 Subject: [PATCH 003/219] tiny cleanup p_map also save a little division and abs --- src/p_map.c | 139 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 93 insertions(+), 46 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index d3d23cb2e..4a880ad42 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -345,6 +345,7 @@ static boolean PIT_CheckThing(mobj_t *thing) blockdist = thing->radius + tmthing->radius; if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist) return true; // didn't hit it + // see if it went over / under if (tmthing->z > thing->z + thing->height) return true; // overhead @@ -1712,10 +1713,14 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) tmbbox[BOXRIGHT] = x + tmthing->radius; tmbbox[BOXLEFT] = x - tmthing->radius; - if (thing->x != x || thing->y != y || thing->subsector == NULL) + if (thing->x != x || thing->y != y || !thing->subsector) + { newsec = R_PointInSubsector(x, y)->sector; + } else + { newsec = thing->subsector->sector; + } ceilingline = blockingline = NULL; @@ -1808,17 +1813,17 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) midheight = (bottomheight + ((topheight - bottomheight)/2)); - delta1 = thing->z - midheight; - delta2 = thingtop - midheight; + delta1 = abs(thing->z - midheight); + delta2 = abs(thingtop - midheight); - if (topheight > tmfloorz && abs(delta1) < abs(delta2) + if (topheight > tmfloorz && delta1 < delta2 && !(rover->flags & FF_REVERSEPLATFORM)) { tmfloorz = tmdropoffz = topheight; tmfloorslope = *rover->t_slope; } - if (bottomheight < tmceilingz && abs(delta1) >= abs(delta2) + if (bottomheight < tmceilingz && delta1 >= delta2 && !(rover->flags & FF_PLATFORM) && !(thing->type == MT_SKIM && (rover->flags & FF_SWIMMABLE))) { @@ -1869,7 +1874,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) { sector_t *polysec; fixed_t delta1, delta2, thingtop; - fixed_t polytop, polybottom; + fixed_t polytop, polybottom, polymid; po->validcount = validcount; @@ -1895,21 +1900,24 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) } thingtop = thing->z + thing->height; - delta1 = thing->z - (polybottom + ((polytop - polybottom)/2)); - delta2 = thingtop - (polybottom + ((polytop - polybottom)/2)); + polymid = (polybottom + ((polytop - polybottom)/2)); - if (polytop > tmfloorz && abs(delta1) < abs(delta2)) + delta1 = abs(thing->z - polymid); + delta2 = abs(thingtop - polymid); + + if (polytop > tmfloorz && delta1 < delta2) { tmfloorz = tmdropoffz = polytop; tmfloorslope = NULL; } - if (polybottom < tmceilingz && abs(delta1) >= abs(delta2)) + if (polybottom < tmceilingz && delta1 >= delta2) { tmceilingz = tmdrpoffceilz = polybottom; tmceilingslope = NULL; } } + plink = (polymaplink_t *)(plink->link.next); } } @@ -1994,10 +2002,14 @@ static boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam) tmbbox[BOXRIGHT] = x + thiscam->radius; tmbbox[BOXLEFT] = x - thiscam->radius; - if (thiscam->x != x || thiscam->y != y || thiscam->subsector == NULL) - newsec = R_PointInSubsectorFast(x, y)->sector; + if (thiscam->x != x || thiscam->y != y || !thiscam->subsector) + { + newsec = R_PointInSubsector(x, y)->sector; + } else + { newsec = thiscam->subsector->sector; + } ceilingline = blockingline = NULL; @@ -2042,24 +2054,25 @@ static boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam) for (rover = newsec->ffloors; rover; rover = rover->next) { - fixed_t topheight, bottomheight; + fixed_t topheight, bottomheight, midheight; - if (!(rover->flags & FF_BLOCKOTHERS) || !(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERALL) || UNLIKELY(GETSECSPECIAL(rover->master->frontsector->special, 4) == 12)) + if (!(rover->flags & FF_BLOCKOTHERS) || !(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERALL) + || UNLIKELY(GETSECSPECIAL(rover->master->frontsector->special, 4) == 12)) continue; topheight = P_CameraGetFOFTopZ(thiscam, newsec, rover, x, y, NULL); bottomheight = P_CameraGetFOFBottomZ(thiscam, newsec, rover, x, y, NULL); + midheight = (bottomheight + ((topheight - bottomheight)/2)); - delta1 = thiscam->z - (bottomheight - + ((topheight - bottomheight)/2)); - delta2 = thingtop - (bottomheight - + ((topheight - bottomheight)/2)); + delta1 = abs(thiscam->z - midheight); + delta2 = abs(thingtop - midheight); - if (topheight > tmfloorz && abs(delta1) < abs(delta2)) + if (topheight > tmfloorz && delta1 < delta2) { tmfloorz = tmdropoffz = topheight; } - if (bottomheight < tmceilingz && abs(delta1) >= abs(delta2)) + + if (bottomheight < tmceilingz && delta1 >= delta2) { tmceilingz = tmdrpoffceilz = bottomheight; } @@ -2085,6 +2098,7 @@ static boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam) validcount++; for (by = yl; by <= yh; by++) + { for (bx = xl; bx <= xh; bx++) { INT32 offset; @@ -2106,7 +2120,7 @@ static boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam) { sector_t *polysec; fixed_t delta1, delta2, thingtop; - fixed_t polytop, polybottom; + fixed_t polytop, polybottom, polymid; po->validcount = validcount; @@ -2137,18 +2151,21 @@ static boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam) } thingtop = thiscam->z + thiscam->height; - delta1 = thiscam->z - (polybottom + ((polytop - polybottom)/2)); - delta2 = thingtop - (polybottom + ((polytop - polybottom)/2)); + polymid = (polybottom + ((polytop - polybottom)/2)); - if (polytop > tmfloorz && abs(delta1) < abs(delta2)) + delta1 = abs(thiscam->z - polymid); + delta2 = abs(thingtop - polymid); + + if (polytop > tmfloorz && delta1 < delta2) tmfloorz = tmdropoffz = polytop; - if (polybottom < tmceilingz && abs(delta1) >= abs(delta2)) + if (polybottom < tmceilingz && delta1 >= delta2) tmceilingz = tmdrpoffceilz = polybottom; } plink = (polymaplink_t *)(plink->link.next); } } + } } // check lines @@ -3202,32 +3219,46 @@ stairstep: } do { - if (tmxmove > mo->radius) { + if (tmxmove > mo->radius) + { newx = mo->x + mo->radius; tmxmove -= mo->radius; - } else if (tmxmove < -mo->radius) { + } + else if (tmxmove < -mo->radius) + { newx = mo->x - mo->radius; tmxmove += mo->radius; - } else { + } + else + { newx = mo->x + tmxmove; tmxmove = 0; } - if (tmymove > mo->radius) { + + if (tmymove > mo->radius) + { newy = mo->y + mo->radius; tmymove -= mo->radius; - } else if (tmymove < -mo->radius) { + } + else if (tmymove < -mo->radius) + { newy = mo->y - mo->radius; tmymove += mo->radius; - } else { + } + else + { newy = mo->y + tmymove; tmymove = 0; } - if (!P_TryMove(mo, newx, newy, true)) { + + if (!P_TryMove(mo, newx, newy, true)) + { if (success) return; // Good enough!! else goto retry; } + success = true; } while(tmxmove || tmymove); } @@ -3603,7 +3634,7 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush) if (thing->subsector->sector->ffloors && (realcrush || thing->flags & MF_PUSHABLE)) { ffloor_t *rover; - fixed_t topheight, bottomheight; + fixed_t topheight, bottomheight, midheight; fixed_t delta1, delta2; INT32 thingtop = thing->z + thing->height; @@ -3615,10 +3646,12 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush) topheight = *rover->topheight; bottomheight = *rover->bottomheight; + midheight = ((bottomheight + topheight)/2); - delta1 = thing->z - (bottomheight + topheight)/2; - delta2 = thingtop - (bottomheight + topheight)/2; - if (bottomheight <= thing->ceilingz && abs(delta1) >= abs(delta2)) + delta1 = abs(thing->z - midheight); + delta2 = abs(thingtop - midheight); + + if (bottomheight <= thing->ceilingz && delta1 >= delta2) { if (thing->flags & MF_PUSHABLE) { @@ -3667,6 +3700,7 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush) killer = P_SpawnMobj(thing->x, thing->y, thing->z, MT_NULL); killer->threshold = 44; // Special flag for crushing } + if (!thing->player) P_DamageMobj(thing, killer, killer, DMG_INSTAKILL); else @@ -3746,9 +3780,11 @@ boolean P_CheckSector(sector_t *sector, boolean crunch) do { for (n = sector->touching_thinglist; n; n = n->m_thinglist_next) // go through list + { if (!n->visited) // unprocessed thing found { n->visited = true; // mark thing as processed + if (!(n->m_thing->flags & MF_NOBLOCKMAP)) //jff 4/7/98 don't do these { if (!PIT_ChangeSector(n->m_thing, false)) // process it @@ -3757,8 +3793,10 @@ boolean P_CheckSector(sector_t *sector, boolean crunch) return nofit; } } + break; // exit and start over } + } } while (n); // repeat from scratch until all things left are marked valid // Nothing blocked us, so lets crush for real! @@ -3780,15 +3818,18 @@ boolean P_CheckSector(sector_t *sector, boolean crunch) do { for (n = sec->touching_thinglist; n; n = n->m_thinglist_next) - if (!n->visited) { - n->visited = true; - if (!(n->m_thing->flags & MF_NOBLOCKMAP)) + if (!n->visited) { - PIT_ChangeSector(n->m_thing, true); - return nofit; + n->visited = true; + + if (!(n->m_thing->flags & MF_NOBLOCKMAP)) + { + PIT_ChangeSector(n->m_thing, true); + return nofit; + } + break; } - break; } } while (n); } @@ -3803,9 +3844,11 @@ boolean P_CheckSector(sector_t *sector, boolean crunch) do { for (n = sector->touching_thinglist; n; n = n->m_thinglist_next) // go through list + { if (!n->visited) // unprocessed thing found { n->visited = true; // mark thing as processed + if (!(n->m_thing->flags & MF_NOBLOCKMAP)) //jff 4/7/98 don't do these { PIT_ChangeSector(n->m_thing, true); // process it @@ -3813,6 +3856,7 @@ boolean P_CheckSector(sector_t *sector, boolean crunch) } break; // exit and start over } + } } while (n); // repeat from scratch until all things left are marked valid return nofit; @@ -4087,7 +4131,7 @@ fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height) for (rover = sec->ffloors; rover; rover = rover->next) { - fixed_t topheight, bottomheight; + fixed_t topheight, bottomheight, midheight; if (!(rover->flags & FF_EXISTS)) continue; @@ -4105,13 +4149,16 @@ fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height) if (floorz < z) floorz = z; } + continue; } - delta1 = z - (bottomheight + ((topheight - bottomheight)/2)); - delta2 = thingtop - (bottomheight + ((topheight - bottomheight)/2)); + midheight = (bottomheight + ((topheight - bottomheight)/2)); - if (topheight > floorz && abs(delta1) < abs(delta2)) + delta1 = abs(z - midheight); + delta2 = abs(thingtop - midheight); + + if (topheight > floorz && delta1 < delta2) floorz = topheight; } } -- 2.54.0 From 1e1dbfc450e19ca6b1ad3276ca272934d4627a00 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 2 Oct 2025 23:40:01 +0200 Subject: [PATCH 004/219] oops all include guards --- src/b_bot.h | 5 +++++ src/core/memory.h | 2 +- src/core/static_vec.hpp | 2 +- src/core/thread_pool.h | 2 +- src/d_protocol.h | 5 +++++ src/k_director.h | 5 +++++ src/lua_hook.h | 5 +++++ src/lua_libs.h | 5 +++++ src/m_cond.h | 5 +++++ src/r_skins.h | 1 + src/y_inter.h | 5 +++++ 11 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/b_bot.h b/src/b_bot.h index 20b2803b6..11438f1a7 100644 --- a/src/b_bot.h +++ b/src/b_bot.h @@ -10,8 +10,13 @@ /// \file b_bot.h /// \brief Basic bot handling +#ifndef __B_BOT__ +#define __B_BOT__ + void B_BuildTiccmd(player_t *player, ticcmd_t *cmd); void B_KeysToTiccmd(mobj_t *mo, ticcmd_t *cmd, boolean forward, boolean backward, boolean left, boolean right, boolean strafeleft, boolean straferight, boolean jump, boolean spin); boolean B_CheckRespawn(player_t *player); void B_MoveBlocked(player_t *player); void B_RespawnBot(INT32 playernum); + +#endif diff --git a/src/core/memory.h b/src/core/memory.h index d568d34e9..77e7206b5 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -1,4 +1,4 @@ -// BLANKART +// SONIC ROBO BLAST 2 KART //----------------------------------------------------------------------------- // Copyright (C) 2024 by Ronald "Eidolon" Kinard // Copyright (C) 2024 by Kart Krew diff --git a/src/core/static_vec.hpp b/src/core/static_vec.hpp index a5a529564..c1f486a2b 100644 --- a/src/core/static_vec.hpp +++ b/src/core/static_vec.hpp @@ -1,4 +1,4 @@ -// BLANKART +// SONIC ROBO BLAST 2 KART //----------------------------------------------------------------------------- // Copyright (C) 2024 by Ronald "Eidolon" Kinard // Copyright (C) 2024 by Kart Krew diff --git a/src/core/thread_pool.h b/src/core/thread_pool.h index 75961614e..71eebdaf1 100644 --- a/src/core/thread_pool.h +++ b/src/core/thread_pool.h @@ -1,4 +1,4 @@ -// BLANKART +// SONIC ROBO BLAST 2 KART //----------------------------------------------------------------------------- // Copyright (C) 2024 by Ronald "Eidolon" Kinard // Copyright (C) 2024 by Kart Krew diff --git a/src/d_protocol.h b/src/d_protocol.h index 43220fb95..92bc8bfce 100644 --- a/src/d_protocol.h +++ b/src/d_protocol.h @@ -9,6 +9,9 @@ /// \file d_protocol.h /// \brief srb2kart:// protocol stuff +#ifndef __D_PROTOCOL__ +#define __D_PROTOCOL__ + void D_SetupProtocol(void); void D_CreateProtocol(void); @@ -16,3 +19,5 @@ void D_DeleteProtocol(void); #ifdef HAVE_CURL void D_DownloadReplay(const char *url, const char *path); #endif + +#endif //__D_PROTOCOL__ diff --git a/src/k_director.h b/src/k_director.h index 30b44d9cf..4c99ce164 100644 --- a/src/k_director.h +++ b/src/k_director.h @@ -10,9 +10,14 @@ /// \file k_director.h /// \brief SRB2kart automatic spectator camera. +#ifndef __K_DIRECTOR__ +#define __K_DIRECTOR__ + boolean K_DirectorIsAvailable(void); void K_InitDirector(void); void K_UpdateDirector(void); void K_DrawDirectorDebugger(void); void K_DirectorFollowAttack(player_t *player, mobj_t *inflictor, mobj_t *source); void K_ToggleDirector(void); + +#endif diff --git a/src/lua_hook.h b/src/lua_hook.h index 64c91cc24..14437c26f 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -10,6 +10,9 @@ /// \file lua_hook.h /// \brief hooks for Lua scripting +#ifndef __LUA_HOOK__ +#define __LUA_HOOK__ + #include "r_defs.h" #include "d_player.h" #include "s_sound.h" @@ -146,3 +149,5 @@ boolean LUA_HookPlayerSquish(player_t *player, mobj_t *inflictor, mobj_t *source // (note: function format in lua doesn't include maxresults, so its function(result, gametype, secondgametype, prevmap) // to get maxresults use #result) void LUA_HookSetupVote(INT16 result[], INT16 maxresults, UINT8 gt, UINT8 secondgt); + +#endif //__LUA_HOOK__ diff --git a/src/lua_libs.h b/src/lua_libs.h index 729cea68d..b14ddab6a 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -10,6 +10,9 @@ /// \file lua_libs.h /// \brief libraries for Lua scripting +#ifndef __LUA_LIBS__ +#define __LUA_LIBS__ + #include "doomtype.h" #include "blua/lua.h" @@ -73,3 +76,5 @@ int LUA_ThinkerLib(lua_State *L); int LUA_MapLib(lua_State *L); int LUA_BlockmapLib(lua_State *L); int LUA_HudLib(lua_State *L); + +#endif //__LUA_LIBS__ diff --git a/src/m_cond.h b/src/m_cond.h index 07e4480d1..06bf30faf 100644 --- a/src/m_cond.h +++ b/src/m_cond.h @@ -10,6 +10,9 @@ /// \file m_cond.h /// \brief Unlockable condition system for SRB2 version 2.1 +#ifndef __M_COND__ +#define __M_COND__ + #include "doomdef.h" // -------- @@ -182,3 +185,5 @@ UINT8 M_GotLowEnoughTime(INT32 tictime); //UINT8 M_GotHighEnoughRings(INT32 trings); #define M_Achieved(a) ((a) >= MAXCONDITIONSETS || conditionSets[a].achieved) + +#endif //__M_COND__ diff --git a/src/r_skins.h b/src/r_skins.h index cada396f4..6231e8a18 100644 --- a/src/r_skins.h +++ b/src/r_skins.h @@ -15,6 +15,7 @@ #ifndef __R_SKINS__ #define __R_SKINS__ + #ifdef __cplusplus extern "C" { #endif diff --git a/src/y_inter.h b/src/y_inter.h index 401461db7..e749f0c28 100644 --- a/src/y_inter.h +++ b/src/y_inter.h @@ -9,6 +9,9 @@ /// \file y_inter.h /// \brief Tally screens, or "Intermissions" as they were formally called in Doom +#ifndef __Y_INTER__ +#define __Y_INTER__ + extern boolean usebuffer; void Y_IntermissionDrawer(void); @@ -90,3 +93,5 @@ typedef struct patch_t *rubyicon; // encore ruby patch } votescreen_t; extern votescreen_t VoteScreen; + +#endif // __Y_INTER__ -- 2.54.0 From 58a38ac6c40b6b7f5aa636508e9bbb3859bf16c4 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 3 Oct 2025 16:40:31 +0200 Subject: [PATCH 005/219] add "SATURN_TESTING" define currently to hide the commit string from titlescreen on release builds could be used for other crap wish could use comptime to autogenerate this, but it runs after compile & linking --- src/doomdef.h | 3 +++ src/m_menu.c | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/doomdef.h b/src/doomdef.h index 677554b78..eba5ed5b1 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -120,6 +120,9 @@ extern char logfilename[1024]; #define SUBVERSION 6 // more precise version number #define VERSIONSTRING "Saturn v9" #define VERSIONSTRINGW L"Saturn v9" + +#define SATURN_TESTING // comment out for saturn release builds! + // 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! #endif diff --git a/src/m_menu.c b/src/m_menu.c index 0248ffc85..af63de94f 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1432,10 +1432,11 @@ void M_Drawer(void) V_DrawThinString(vid.dup, vid.height - 20*vid.dup, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, compbranch); V_DrawThinString(vid.dup, vid.height - 10*vid.dup, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, comprevision); #else // Regular build - V_DrawThinString(vid.dup, vid.height - 20*vid.dup, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, comprevision); // Removeur this for release! im just lazy to make a new flag or smth +#ifdef SATURN_TESTING // ok not regular build lmao, we dont need to show this stuff in Saturn release builds + V_DrawThinString(vid.dup, vid.height - 20*vid.dup, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, comprevision); +#endif V_DrawThinString(vid.dup, vid.height - 10*vid.dup, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, va("%s", VERSIONSTRING)); #endif - #ifdef HWRENDER if (rendermode == render_opengl) V_DrawThinString(0, 0, V_GREENMAP|V_SNAPTOTOP|V_SNAPTOLEFT|V_TRANSLUCENT|V_ALLOWLOWERCASE, ("Opengl")); -- 2.54.0 From 8f007155cd39c664adf0858459fb9c57d15259d1 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 3 Oct 2025 21:36:27 +0100 Subject: [PATCH 006/219] update libbacktrace (win x64) --- libs/libbacktrace/LICENSE.txt | 8 ++-- libs/libbacktrace/README.md | 12 ++++- libs/libbacktrace/lib/x86_64/libbacktrace.a | Bin 314252 -> 315466 bytes libs/libbacktrace/lib/x86_64/libbacktrace.la | 41 ++++++++++++++++++ libs/libbacktrace/lib/x86_64/libbacktrace.lai | 41 ++++++++++++++++++ 5 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 libs/libbacktrace/lib/x86_64/libbacktrace.la create mode 100644 libs/libbacktrace/lib/x86_64/libbacktrace.lai diff --git a/libs/libbacktrace/LICENSE.txt b/libs/libbacktrace/LICENSE.txt index 495411538..e9e256244 100644 --- a/libs/libbacktrace/LICENSE.txt +++ b/libs/libbacktrace/LICENSE.txt @@ -5,13 +5,13 @@ # met: # (1) Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. +# 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. - +# 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. @@ -26,4 +26,4 @@ # 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 +# POSSIBILITY OF SUCH DAMAGE. diff --git a/libs/libbacktrace/README.md b/libs/libbacktrace/README.md index c82834d17..1a7a04568 100644 --- a/libs/libbacktrace/README.md +++ b/libs/libbacktrace/README.md @@ -10,8 +10,18 @@ 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. +That said, on systems that use `dl_iterate_phdr`, such as GNU/Linux, +the first call to a libbacktrace function will call `dl_iterate_phdr`, +which is not in general async-signal-safe. Therefore, programs +that call libbacktrace from a signal handler should ensure that they +make an initial call from outside of a signal handler. +Similar considerations apply when arranging to call libbacktrace +from within malloc; `dl_iterate_phdr` can also call malloc, +so make an initial call to a libbacktrace function outside of +malloc before trying to call libbacktrace functions within malloc. The libbacktrace library is provided under a BSD license. See the source files for the exact license text. @@ -25,7 +35,7 @@ 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 +As of July 2024, 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 diff --git a/libs/libbacktrace/lib/x86_64/libbacktrace.a b/libs/libbacktrace/lib/x86_64/libbacktrace.a index 4b4447b5854ddb63b3235ffe47774e2a4687f7cf..e0d1c4e9d7129553506f4a603d33843fe920c206 100644 GIT binary patch delta 104571 zcmb@P2YgjU^Y_o(y9t3H(v+$M1&K-tU>6m{f{GG~h)T0O>Z6D>QR=04kn2GYoq!^s zh(PFqQUwGAq)V@Yw9u>Y{$}T#$xYP%>s#_k_I`I}cXoHSoIT~94Dbs4oK|4)3(pq+ z*$Kz~J$K9r^Izj`PPkhiCp>J36aM-(C%mMU6W%h}F@v|t-`5u%ll9N7y{6!_$=$+K z$;;Ox{A79?GneQAFIq2r3sp+589yR)^L-DdB;luNt~Yz-b@=De9AT%OSM8Z_p`2;` z9A`+#aXPxU2I6t@xa^8M}i8@Zf-caLbfLHNZWcY2l<1F@AEm%Zg*0y+jG{a<2b{M zgq&a8O}TCl?|U!gotkJ0xOo!u(;>HHVi{WRK9g7`jy?!EucUvNxFkOJ;J4l?e`ARr zws`l6{CmxfC8|2^%KS;`&lIQ<%EPhD6zT3w`%B(%V~JQ%_xq<(zU5Dp`j}0;6_`qY z;=wj?S&XMIee{bEjd9 zrL3j8OCE1ZkGQ3(|4MDsFH~Phg>$aFe!WKDCrUj~qkoT5L)j7{DTnK%uYK}XqU!F6 zr#_$!ZsVuh(*y3drx(&}cX*9bG%o$e8h28bdb($yd7W~lzw~T6&+BO}YT!<4Ffw%I2lwfhSJQ&@g0D;u(L?FW z8$KRS%iUaW%q_4W{rdHqeJ|ZOYhm9WrIwQ89R9}L{KhDlZ}VmzqVjI{|2#oQ(pUVa zYSyycf^YAoyVK9VT|7iDq!)PiMl$6mUBB*bX;#vGq2-P4vG;PiP2Q_cQ`|4!8%9sK zk2LE>UEPJvCT4AXoA*;Fw>$p*hVWRZd0wJN(+hl1n&=((!4|($id(Yf`GOCQ<8C_j zOyA{)%L^X9BmM4HJHoUwJ)!M;VcO}oX*VEe>TpiB?Qo6sob9iMvyZ|8ou?61NnaKj zL`Yw+>q@%ay|vpuT9;1UpCZcX*62~1_Pfn{JWV6qSv}s%Q{fY9u13#=AND?cn_Ho0 zHOlL@>^UrS-c8Tls~=?>TwnBl?xxoVT)&Q5BFl|E?!fG<(f88f7t+IhZlw|x`omh! zg>7y_4Qq7&i4NZiLHCO#KkUj?uI5(lTQcX#eq7?E!@s-l_MLXqO?|FkKk~(j(>Cco-9Q}OpBbob(KK6oMizI1D+z2`5U zZfI-?8j^n7*yqYpT6*&}<%u@Aqkj1WVY#(CX}FuX&ZP`@%(^O6&)u=ENa(BXZpyKn z;s(rioNjKu^_8ic`{eq{iBENh8}UQVQ*QV5)v3L^eEkD7g7y~rz0$7jNCLmX$OJM-5rd3tpgc|u{7SI(`zp)w}l zM;j_2oB*!jZr@OiI=Q!OtV;de#v5--e84wE&I4}$jgQ~>WIHj?e6r&tI_=#Z8&hes zTW(Wjgs*L?fG`UF!Ckhg8eMgBYf0KY*1A7$ zez-{Au9@18eQihhe~5eQmO_!UzV`4W$p?*NI&+90uFnEL%ZHGE8YABnBcB#if#aDK zFsEYVara9BZ0C~7aooElQ;~Q>S9j@_WZL2$-%_Z^pZ4e=wfM+Sgl3s(?k!sj75O2? zXA@$ypSjO(ElUgC_FIe7H?Fs}Je_oZ+FFXf6~2<5yEmwek+ zQrDe{9m69!Vom5H_x4?tu#DEyYFgJdWK&)9^C%Gc1k@t$8q9)8w7H5?0%N& zyLEP#PdwyTEaV(=`|o}Z4cM~#ZY-4HJ-3Ibt(&~(&O8}CrSxfcJI>z6+`)V92q$*# z=Pi1OlHI9$a?>(*!Jb)(^ZN!Zn(ubr`&=kTKX=vMWUA$!-CGXsyKUdo)ZBe{UwJIQ z!}gU!rsex?$Km?uzSGpj-L-!TR^NdK%1~8z=7ERlqI>GVqx7Dea2-I1M&-oU z-ib~geTG7B5vi=Pf`)L-Ra5*zeU*6-FvzkO?PiU^FnBCeK&fk4Bh6AI8zRD zY~`6-X`g%e%ssjDG?N;Tlc$-ReD>bN@+v6rzH_z`z2%NLn}kj4{IeCvbB~?96^=NLcC^iplu<2Nc*RXQbAMvQiDtAPVv0L=J?xgel1xqAXRlPE$J|a=DkGeBrE=l`KNI0>;N+F+ z82pv5roxFOuiT!uFb}x1n&7NE`)XyLW;QJGX9aMrKPzM3*!|CHsPVEtYlf!Pu^sZg z`|!0&i77fhQ{0cQ)x>UN*|jI>KW^gnyRpLDfBlwXoBSEUi_yx)F*Cx{bw9XXsOWzh zNR#+zc}eu42nJ~QWjF15A@um1>s9F`_tN!hH2SlLX*H#K2}G6gQH7`iKAI8Lq+30l zPd!QZd)JBXrW)SeAu4`frKVz<$EY2jJQ1DpKjL^(3;PcK!Ew(1oWNe=_N7oHM!ilU zDjIU$@P>uxe%kD<523WpUR;cDhZM?*I zBzetyKAwscY5BI8=h?drTPB`2JbR;FB%UhL25(wCm7w$9`gpW@g7;@U6)H0QEy=^J z?hWQVZP2iJUb!4pm|X9v9H@%xwZ})|!WKdO7kYDYP<1-)UClv{(Vt$G1S*+3)G|H)*aV69_?_5fo;!F~LGOc{bQeA44d;)$y=6J!ptrmW zIpLY1-tD>QPCDs5pNo>Il-D*FH7-&yRqV2FpMF>Tgf+=j@s8)BLe$WUOQaNP>)n?~ zx1*C@Nu(sY)9a8(WvP)j5g*0BdPXcf`<~4mjwZ)b=%XY`aqfBA%SfbB^s#qSZX`U3 zBLV-+{%gWAUZdPpnp%6^bJIOVzN#q+L!F$vnyFDIvFhw~xoL5T_RMx~q#ua#dUf() zbY1n*^3g-Mj<7u+J(zgvDalOEDX&C+dYbO_-p)@CQY~+6el+NiH#a|=@PW5KKUE4n z@{~6=A63Y)wIilP#Wvpa1*mi=T+M4!fU3}4-n0T#iC*^(6hLb~@$wam|+o%9H$dk@@2?^0v$i@WH98#+BKro&?#XNuSKZYt#6cQ@UF zky-C&5>^tP?H&m zT!!L2{^AxQa>FRhcyIb^)TCGu;7$0u;Z?}P(RH2T-UgI~(n>yKHxpxyw|C2 z+~dHiUj8?Lslb}E-+hB#pb~F@U&EiR=?8%KIl?vV2I%5#d6T}$KLj{{*I<(Sg$0>!s(EW&X0=&xi`8gYbk z48dO?j&P2R_*=n|#t3q!p@Z-jdJmD3fLl27F(UT?D&gDC!t|TpALB2;q>=SY&@V>4q*Ls%;Qj`QMvr zz@`o!qfj)j8Fidi4uFNcrfW13IuNx8`^R9vfk9~PK9a<{etTI9>ND2VZNXSW8kg8Stt?>5$WGJPKqCV2z6n%;MXshi?yAQ#GSx} zHIF87X($8hkCp(kC9n+kt%H;P-coX4DVnT?lGPB%HB~sXvWEKtz?HR;9g%DLocjgfHd(B%=p-AA||GjVb4)}|2|HhwU-1lb=_NVR9 zzj{-g8G+TT-pusj-{j8bL7O?&gF)tGH1aP+XLF&=9EtT|kUNEQ^G{6Wj~~PU-P3-I z0dzS;@Fzlyk8re4d%tTeVt~M~MHzz@#WG{IidBRO6YbJrjBi6&j0lSrVK(DcZbdKF zUU-OB9HKno7mU<&jGN#-U?9S8zF2806e+%hcHWt?ee%aTB6bJGcoAVJpc%INWR5nhF-j zoWXC9Vqv==1toug@9?KX64+_dww{eoA%4V8%7et~9m^(wZd0%k_n&bf{P8uQi46RIgC}=(>-km6>gT_>$M+ zL%ON(rCy<7y+gU(ywOZ81mnF?A5yVfPWBFc)kiI7dI`ereWgm>`-TqnmD;1zCwh6> zqIDDdhx+1{51JHbd*3GIdA-(q7d>OvV*U5}qD6cFIOToamP(jYJT%s{rSg%Dwhwtp zM-Oi15jxb4&}AnCSDc_jeKA5IMUj1ZumXd@3iPKz${1M+i5!!Dl-3+2wuz6cM~Uhh zgk530bp(s;F)oMd+M(#R|A-PFLIxJqGd)kxcPDtdAncXF8PSVhonx>)69QO&FjyD- z_z~UgFH5nFxY&+I%;f861Q4Gya8{UV5Zcy27PJN!v<8^j8m^wn=pULpfS1E-cCDt= zV7+H095(zY3Rn@bg<(8_+Zl`|TLv&F0~nOCqFt;B%niqA7GKpI#W z>R;znJLWl}2@u@$N~Mr}jL{_8JE1KSzxyp(U~ril6WI88fF zIa)Zmu3s-Y#(>9NBx+<3p8XSTp3$DoqfadQebdPN&=Ye;WOmMkkj3w>Mt*saNNLo_ zj({LA8;)~Nhoe*5n+RsCZ3P&`Sd+lXJPkwfEt~|dQ{W{if|g8`OSk5;leGFI_ctnb ztOxopD8zo6ohPKEv+Yb!5D*0o>4~}nBY+V-x!)1m(jl~y&+4;UOFuy{h_tBCtUjCx z;cCDuW(QAQ22}83KL&)>=V|Sn5Vj6HhR}IoTpu*(D_CH3A~Cx7w9hJ_Kws_0xCX(_ zV~<^E=|uxW))vMJ+v**H4B=0JRD;l3$LPT!7RLe8?WhbI6wS-*aj69yJgj#_s*x=r z>;?&eHX+i%AgqOA%|SJUhca4{MJ2hc3c0XQ#3a;Mu5eK&A|B=?#ZQB|jVf#TupAS! z#v}{3>m>C@=hrg`KLOM+2r(ic!D2EDi%A`WkXMy@)`^^h^^JqYrm>W7X8z+aVpZ2u zgl#WE9CGLl9%_d$)M^`q7;~WyGq>5O6w)uVbwRlKB!xf3V*>a@*0^Zi_}d$B_8rJx z#~?iBP3}mkm9L#7{N@RNh0}BXk)yUq^TkT}P?%y^;Z^8Fh2ub7PkA*vQBhkxZ($c4 z2JC^cZzn3whr{nLc>Ow2u}a@x;CWpj)|i{n#2)A&?|O-Hxp{G{ZfppSCs z{>3GlcZqI@?r9f~Bl^USwgQlxxkTQn&U8~Dz^N-)awB^2ip^cQ|5b9YX3q`Dh^v%0 z#w2eNk`08juZq>10pI+Y#p={Q>4dkgGunsgyTUu!nF>7$+SWC6Q;emKcw)eB1T;JU zQ3=fvYvax%T|=|Gg<@Ne=v*sl5ST)ASvRj_7rMFhvTmV1-8s1`5&filD2H2Ed_X3RACIuTeK+WvQ|u|(bYZiF=;l+nv(A#}MeeaAv*i?BJ>?~Jr^1B> zou)lwjMnAf!%sy*y1%@>+~mKF*vJc~19@85K0f8x=fcY$J7nmVXkzNfpn@J>MEIbg%)`wx>FIe_zL|ZwDAgMSc=Ec z8qh7|mF!M8dxN@Dt_b(qDdOD=K2Rm9&xfUj7Z?y?BJ%3T%f0y)U2>XtLo;pVv55-X zr6E(*m{n*lRx^al&SF*1=xFfCh8y#G%!i#=I}x}97X2i3vnJs!0}LVwlcWJTSdv1S zRv_;W^L1mzetO6`Jr;6Jq|8gbBa3}Z3cJ*kUn*}C17}JI zcr%B3#i%3`Yd8=3GA5bEq-WVzF-iQ6m9ni_bnS|+5nip?7Iz5d%N6t=Mi*yhSFY^F zox$s8cizV!oMSt~>epb=wBniK>QtN0;Mk5CgluRTHjU^y`7yK3(Jl+;}91oGTp06)`_`Ci`CbIH|Wr zxuOA!9ox!o*J$=NzMy~;f1H(Kb1E!5Qpk&h#rw^s%-Z;U-zRhpo9}wT=|<4^)|39uJe7Cm7wlgBLZ1ky54XaZDR${g zuuD%h2(eKYN3olb?QB+?IL!^j+#)#vQ9mF(3W%+P^?-=8rY9$2Huej-{dtt4`NG+n zFG9chuxu;CLq(X&MOK_v?Z%~3YeqO%xJ9sc%uEo@dEF-OWzWMyQ67JG_!vk=^981b zxNrs7gj4d`1|d#St&nX5xsqceDR8~PDXYE6%5&F`*h^R%3q_MNRiS7K7fWVYWMIf0 zgv)wpz^9>U_L{h_@fG$`r&VyFoW)nz>zGy%*s=<_oMvs=3gqUYDR~U8sl{_SzkG@j z2ZjpmhklLCip$luVmZ|?wHwf3v|GF$0^4D}5{vGTIDa>fb~ ziWLX}{a~fOK`51bnJZ_$-A`B1;>Nx&*y2{iQ_aQwY!R^V0Igu))TqGM283xFtZvT+8otrey$3>pBou%TSHJD805p$kk{Z zRHJcF4S-amF;|02Xv`(RFaUN}Z)QMvW-|&%Fj7FKS5U&vPjC;$AdC)1lDv2ViY9_u zIF9Rv3R+)yDEnoDkSozBs6?Zn5&)@0Bd)}9_@a?P2w&jlOVIL0LCYHjmGG}B1^Z&| z22=+{@QnlUH`Y9y54kk{b1OtKC&ySCJC=6*VCm2gw0otcWk1vLJ(k?PbZH-xbpGF! zkgO#nYXKm?fMgRC5J@&c3CSiXA=v~aB>!^>DOy5`mH_fgNYN5fw15;XAVmv!&tD|$ z3MGZXPm>4JTyzC?u!HG1;1z=qzv1?UaVJCi>6M_LUg6@G4dGNMefDq$guO>#SB0A# ze@>y^-&ypkEvEtzGe1hdMR~sOk}>}x=jSmGkbZuV`*|k%`9*^e{fs9XI|Lp5V$jhq z1|9t(9}M^>WcP{yGvZU8PQ294cWE_x7bLDpVTAXGpnF01fdBbOjE{BbXvpw^o?sb1 zE_v@p>CVWKC=JB?eARqnEdx;L*)B^^0=NEEbK)}|NPJWc9Pz3;0@o(th#~9<;Ly4B z>kmL&HOJ>>Jj9V|5Msz#87hD=XYtZX>i#oPB-IRAM^o1M!gYj6X!V$hn1&Yj?I8>s zdr-IDU_TuEl#Za@b(G~sH+r0Q#xSmA_ts9U5pM&;VEnL8JGlII=9gmI)@d@|V z|6DKB0jvFAYEVCG4NxFb{iRrxYV2tAesk%@h>Qqs`uB6`IG##NH3+ZIL(30$F!;0$ z#()TV92oR7@X|VNGcqBxErl%Ta3DHd8g2J&X3<I&?meJ{qj6Xe z^8i0lJ>R0;Em}hkTjIoxgT#%4#EpZ*je{u%uLkxf&%@?0qvIF@SUR8G6Tt@zi4+A- zSjSR?7|0@&N(f8KEN8Dbuh>#?CdtGkS$HAlN(2=_k=S7(Lxc-r400rE4s4V#=zX8z z2dSc-5@RZ3g!OyL4qJ>YUYB{ILoR(S z16ukzM#+6DD(=%PieyzJJKk$Qgm3a{dDz124Yo@-fMB-CPS!t+)HB#X;eakeEIv4@ z2m}5Pwp7^mVERf${B)tS@O9Ueg(^VLA^`G}(*otA7BnkcPQayuR8D_Hxc?I(x z9!mEIjltd0$H}cMLO5)j72#vqZ)^e~8W+1I>BQm7t8*5vFwi*%i?V@DE`hT5x-A4k##x`Wb|o#+7C~1rKBQ3O!_v6Nx4Bx zN)BRDb`X=&gP4>b#H0d#%yGOkBPhRCVz^y(gGxv&sD#9VN=PiIgv5eMNGzy?#DYpl zEU1KyIpp;iNoR|>!)eZN+{)`7C!Hj>@*wIx!fP@S_vx^09_vjTMMdh21&!eQG`RB+ z?IZVTAlNvpG245TZw+)84*B4&e7~E&;^#y(Yg*R|C6|VOA z7c}aNzcyLQg=XUy|J-Egrj7TijiC~`rj4iX$5T-^Z(A?lSlksuWRX=Rg~ww9-YJc+ z%8jQz-qP*_9?LuBd{Nsns>E4-a!snBgJrqJpsSsT^`15btpGzX^GK^lis znW5iVyzlGpX#00rvcwEmXt0W9?K22|m}*C&`C%&k>WvvkMdCJ0r2|vNcF$=vXPTEb z4i1?!jgHQ=b&MRHNvmezdtQa3>)P9nE{=}Is8}B4>bK~hJO<6GMOlm?x^Yo9V-W0Ilvx?@!9}(*aR(RC zz{M8t9=Mo(S)9cbqI(u+GX=rX#oqBR;O?V~>5SwxXBOlB@yRc#P}31hD1B)bD~PUL zYTYvx6H!_R!Qf?CQXx8FS+=qu_-GzwpkG=WAxy;(&L=TQmVrM;_rVt`|i@!#hPgG2?K|o4i}r5$s2n zdetUEy%bwLukl1G7KcsWZeP87H=XvzLLGN{H_h53v)yh4B|DCnV?3HfH$OaPFCE)U z1!MZzO=uC33EyoW_1%|ktrpKfJYb)7Q4PH*@IV z9NrhYbBVv6mTC}U(`k2aI1$BOapGsV&SUS{NF=KYn_8Uz`RU{a3Mz#>*jV9Q3mX_5 z2!m5C5$jeD8q0D6=!|*>h4OZ`9&cwy&-}kWBeSO{-p}7qnTTHzdkLJ&XdIN$IJ1nuIeq&7b@r4C za|mVfO!3-Jrec15{`L6;s%+E3G5u?$!l)`I0&4(b?$ zwxO_xhHk<|y*dVA8lTibW*1RGSr9*+Lf=Q0j3NBy^mn}2&L9@MFOXY z=PKZs8OR{GY?Ip4fj|mT`d6_oLkz#ZMa`Tk4Z$@*W=OH0=CmU1ENy)aHpWVAy_)e zwv=V417f&zfw9`wa2=BkVi$Zvz8yrbSUcQ{9i=4@bpM)d@QjrpI(uWbT0yX!Q{B#$myI#v z-llBHAULzxR`gc69GM@lJAlu+U_`(P$cu5o*C)NzGpKL`*C)?yg|Gga2I4N;vT4}A zNe1F6zr|``R5TFd!dr|rXr%ig9=ILTv9LtvZzufba39SQ$MEWyWq2XY!tHqBh>BZ7 z?Vr^`vBVoYlL|bzWIJu&&i=zh@CVy=>b8R&6J6LbkU`LEM`jJcSH0sivHc#rlf0eQ zV=pe;Nh@|z9D5hv_}WQ(cTxhsq{GG$IlPndNgPSEZIJfag`KobXdSI8$cK3yXJG&h z+eHg@aVbUQj+4P9CLBTS5gbPp96{_6oDbiu%DRo_?PVOEA(exh&4WWOel22ZP2htm zHUKsqHjMc1tY;pE*BT*pTN zX59`tzQcA?W-M3uuV3ZUF zubi43(PAXd(O6g5L@czfAR}8J-)<0vF|rerXBQ5lXib-`)MG2*3wJGfiU9j>r34$R zSlpirHZ2~Z$1Fi==^o{Rg5xgE?gJt`>U;egjaFY$&bf& zy$b!VkEthGky#tuO3azVKV1{g;H(U%Mp6g7yo~3G;{-`C1>~$PjB_>ku?6= zAa#|tVsVft*MV|T4udmh{7M~uuqS(x(qC6|mW0dR)DT}KSp9@R(KUE_>S46d0v!U&qW9qBXY_5I#WkSLCFS z6E?V9fM0P2t`Fn1(?lb@iNM(=P9tMH!>N%1r?O$3+!}jViX9^-uJ}rhtqEOKq*bH<1M$y}^b4EXtZ3hngUy}%+K+icI$g|AKIvtV(Uth|_DLGt+A*YPvPNQNMWEE6VSRWk^2?wu#v zr_&Hqv3SHL#&@D|`VEs<^}@W8Isa49NE-ANC&hX#^$d#oR|Wg!M%Zx!CegmYrbe?l zPSW^}lgdgZ&~B|ehFK1?z+OiZM`3Q`*RO4+Qq~}7C{o|S@cHLVF-q=lv1dm~D7GL6 zLq^JF9on!pvl5xnY)#@ck@0e5jq^?WZ3?1n4V{6F0dA)HCpCU7S9q|!(#l_y%1pxF z&_E13KL3hnW-M2DYHS8c60whe+6^@ydF2O(D0C{WKaQGZH^8&_7AQY7j$5BQS6IUR zG5g#Lz8+y84q~l5>A-}taq|W{WrQpEu^rqG*h_!nflCl>$k>OW?GDNFmf}eZ6!k5N zYHSeNq7t;I1QQgMphYEUQ3*j&jkPHIgpe&NL5s4l`w7~otwTw2ei4y&NkobhmbM8? z>x9uhG)q_-CM->}%r5-961fxo##!Xz?&oKBA(rASN@*6QFpE-_MJ~$QwG0o=!g-td zLiIX)#|wZP+*m0QqIvc*zBJCFw9R5r7EbwsvVbUS6JOkBTLA9FRNu2US5N^Ym9~bX zp`q=)+P{VixKqP2-K;dWv=4i&+7%! z=UD^zg!gbi{$jw~ztn*V=w;!bR*rKQ{5Z&l*7gox@mb;+F(KIZ?0pN-7nR zaNwvmCSd#qsa3vR>(@4^6T6bzt7T<|^=+{kwVuxO``T-&-+4jHsLm*X^Mh8W~^6AP-AWYJ|rW zUic0X!f$_~gpQ710SqrZ009M_Ntm*d;#rd78Jw~X^DNaM-1Kuyenc?! zG8=@)47#jVGeA6SkkCNwz?B%Ceks^6$PYJh#uCbHTNdqs4Mwps1_HF~#-Le&7_y&i zvk~t0URZ@kb1{nGU|!vvxG;A%Vz_n?Pd;0X#`w^fkVU02R`HMd**-ag=AwIl=d}#y z)&~8IUu#Tbxx#tl{Yx=8egphi3C~JR-u^4>8Wtv2@ij@Kkq^crR=rYEL_|a-dql^XyAqv9;>Bz+)88zVN zHqGDXk5%z(ku2;B{$9gB{!$Dk(88-`{pP z2G5pUTg#Wf;Hb0kRYQXiPeEh8NB2c|TM%3;!uRFY(C@#n25FDkB$$Uwk)nwcjx!@x z^Fu4PDBrr3VU)t}2=OEgtjqH-VLT1Ps{k?t=HpD-YMP8R_?pUU`en6$DM}LIvXp-* zN_0G{BsZ>e#Bqk8XmqBH!$52zTr`PE#IwUMB{mT}`n!Ex$2J17h(xnFScKNWaqPdK zXcR0lzWQT-%=%vl&*RW52H`Jj;hc5t;Z}Znh0#xix*Yq3GLR07)h{#=-OR*Sh~zgaDF2!~TY8NO|edBXW2u=cEfWzJ>E!DDuz-E{^YmRL3i zix3XR{HLH4UV}1YT&5#mdE#{v`xA`dRdjq6g*)N`0zS{N%zBuQz2?jq>Nl1zMk5>q zsBJzOOG5$m3_?6B6I`X8okriMv1<`N#R=-$gSYYJby&{g7p-lxC5^V*Y`>(t-F5HiPD8wt>*fiOvfvovGKmr zxkm(dcRI!=Jb)ulkI0Jd+(?ATXP>n)Y={-0W;0?aEH|Yf{&sbj~eT zyfMfwxBs;RFJf-wOEenLw+Giba~U@aI_%BY0jBnLNb4AmZtZC6?G@WV6(Z+4oau;^ zaLA?z`U$qj_Tmmh_+>8&w?RkabCs1LT4HOwZFIm~TS8;QA5FH=H4~+QnbAzboC*IhNRP?b-_o4#$Hd{yb@F+Nu5spoV zV^a-6c*M%2MBgPtyvrM@Y-B;F!<};3mKc6e!5r@NS?9!#4r*+oL-AaJ`KEn-d@(He&p0Z?p%rR`v%P5K7>kQa_~B1 z*BYraW}a9946_yh{?Lf|Dw-t5n+ZDl$t_9-i;{(rM-Yl%I|$21l0;HChU*UU-4S^~ zi=Tw=W#ZqKb)&uAxOU*v-RR5N8#YtEg!tL7qHAZ*{$m&3rXK0lk}m>GXt}c;KJAZ5 zd++LdSR=2#$Fj_K6^pz9DwN`yw=LGsw>hreWw#}Rx-?m-YHk(~s zxhQTHw(a+kS8Ffb^nmwK*N^|Uh+*xfw#zg$r`^1m*t~W-y^(vVINHKfXLrj3EqNh? zxEwQtrY(1}aR<-nqgeFMVtNHpCSa&D1oYxv36F=4E*zcM*=jAY9^k#U zpKhL=e?Qf`HI&cs-l9;+(56yeUkW{y(~N%b>j%Tpycx6CQfN({(2#!kM%T@=XXFiS zGm$GTOs|&xTbijDs(4ZN`>Wo^zcyLd-0W&Tss)4#TbrpLPHk(tpz|DaxK&z~_{jEC zan!|u8^>S&5b2n-j^B1P+dJ;*Y|`w)=^vQPoL;oN7a2JunLWLzZ*MXYIU1R%y=inG z+@`a~Av32B?L$nCKxS}XUd~KLU%K9pOqT(?AelV_=omia;9~|4q%8x(~JKGN-T)F#7zeV+~B%dh@* z5C02$2G2|Iw=1!!v{wD6qvaWAyjp4)EgXjTPYt83_}D&-j^g9YFv26x{Ma+TkY)Ih zTm1UZG&}Z7T8Kh)at!euMLf>TPm1)$g}XsB?PJHdbhjO`nX_oYEQ+ZJPF;hCVE9RL z+=X+@xH0rK?8uWU{sSaz4v&$Fxd`#4z)XADvq)Op?vn4g{#_MtKSRC@>p!6(&yc7T z&oK4aNv4l|4#WO^8@T>WTfF)ywiG-kG%iATc9-vf;+O9%;F~PwXSubB z?}DxQ3hqII|Ccm)SF?RmmcLtO?fLf@apw_|h=B|@01ducws8VV%cA`^O1vY>J`1ZB z{JV#^EeM+iMwd*qcg%3p%p9;c5V5O}JB)l=?_VT}NrST#xxE%x^6$L)H{IlZTX3Jt zzq4i_#hoW7xDVvtZ-%RX9?#>?zYi5F&MwvaM3Tq}ZUR{wNQ|34c=Da^=GavLs|98% zUt{MB{+QiZEDTl)zLAl2Ig8+86o0!M*w~E(+@I_?Kq+vK=mb zqoaP}J5PMsEoR*gR%*FCXZA%_(4iG%POPBw_>e16!6mTlQe0xgrLw>vt~RmbaNWc% z{h3N!apJ2^xDsT#+siO~{l!~DX80N!w+0pSlj6eC#MNj&t^obJv_Vp90e1)d%R-L% z@)tV4HnS>x8G0Z2S5oX15VYEOd-=j*Y!uf;u>RnHhvS{W0T0JJewzrtN&zjy%E7N+ zz-n$^W`Q?%n4j(2JNU&F_*JF<_62#ng8fepI}egMc#!x%6r8jFoWS7UFC08Z{BC8u zzl~pI$Nv|D-_ae3;#2-1hP)U3-x~M~|NLRpfKVDfCJx{?s2lvZ4g8w*1Ni?P82lZ< z2bX~&0^1q(ed=5fy!+dX=^BdQm2&>8_58GWBfEWJw*NM4+=jF-vG(5!&3R@ZtGt?8 zl|fWqUhOAx%pWJ{+zDJOvM+!3U;XTuQ77r!lQ@7wdJg@MS3%-Eq6TkNx%yl z5c1!@iT665r0qz%K7-C@5Wfv|;b}5+?5kG)S&3Jvnic<3noMOR);z@h&!M|f241pj z@LJs&XRrvIAruJd1%6?yS$=`m;sgKXU_U;3U!-$a(arV^r7>;5OG&j2f5|cRB6c12 zMWrT!_TtxUvhN@@2kaY2|5eV+jCi-F!5`jU`mZv|OG~lW=7zxknJwXZL3JF-JWmiD_KPHXy4K64P9mcH%p?4;Ucwh5m2lgzD@x`LY7;!5B-I?>**R1GBBR*P$APEA43OG!HGrvHHO18cg?b3wxSHG_oZQUf17pws{)PHzPgAN5!I86@`J zsuNi0r8F31D;RN(s_?wh4RwS1HwTHU+bIoJ?Ln0tQz}|7$m@Y5?`Wk(s(t-M9;|4; zarOaQ*|vX%^pa(y(iD(5GtW!G_^twybT28r29k6~RFu7mZWP7`p9Z$fh1ktCV|t-zZv9sNa-<;q z-VS>9eWigQ@yA+F8(YX}r3LQ$l`EO9jB9JsB{k@>LjVNC%zk*4CwSw2b z9zZcORB0SY>RK1g741V9Ppxfbo>XcC5`!Hf%aCsx76mWTmpIO;OoB zN)M>Eipr`66mgzVb&Wu1t0dJ*Rc$@hVkPk_jb*`aQ&W|_sq~I&o2iWbBbIrt)ZzAr z?QjxdM^$&RYS#8pSs$eVsvWGdAxcA4J5pt7N?)pWBF}#*c(SUes(OaX<|xfq?Lw6; zRa&9i)hb)3v{AKNRTkNyxJT6oRCZYDm})arc2?=4YOkt{@8L+}3`mAvg359W@zYg# zRb5ckg_Vk{Hc4frl#*3jR%Izl_o(&(l~qxy3W`X*o={;8rJ5kormC!-QUldCR9RD{ zH&y$N%9<&)P;DDrk@TJPu~J7>cTrgnr9P@1pt8YALsUCdWh0f+RQshbi-etts-CRs zsVbYHG)J`$_%h=J&NL1?lY84ZfiH~{_!3)u)ds#aj`gLie;q?X<}OM&xAzV9Q5v8$ zSZRpTP^FPdX-Z!zO;nnUFB>Thrj(&{R_UVBRV7R)zez?ZK`FOVUQ1}daSE!iuu^fQB&AYH$x3CFQk3pddO)d) zQdOlV!v6Y)p`yZ?N~ucqlo}{CRBEd9rqVk~&6HXwwNZ+Etk_Yhi&77zK1u_W1}hCw z8mcr>DNX51rHMkk|C_ABsY**t(2FaSRx7Pj+NiWuX@}Atr2|Tbm5zZTGG{YXcvk76 z(p4pXW>j(*r39tiN_mwEDiu~Lu9Or}ETxpJR8}cP=^mvAl&UCIReD0HhEh$XRG+Z_ ztEa*SN)45oDpiRO+Fn)Z38flJHI-78>M1o)YRDw(UsDynsq~IgGo?8o-foipFXXR) z679+KTbB6JgAku~a5s_D6XEOlOLR(OY`tlzmQvX`lrO>u(N3ZCq<~H+T~*3eGSEJu zR7a_eQdgxJN;{SQ2q@xQ4AALtdtiE#(tf3I=|Edasj5;>r6EdVmG&x~RJvvf?N4-y z+!2^Aqts04ic-!pLApXp_bWZA^q$feN{f`%D(x(T^-r8$I5{x=meNqApOv;M9a1{0 zl>g4aN|I7}rB{{SQHo4bTv;|4G$uI;-02Dhrnj(j|Z-ZvmARQYx<6 zG9rt>{dcRnrmA06dRJ+zrW>#HHK?hr-~yE`Qd+Ls-&D3sX+J0;nJ)rs!VJEDR6a16 z2PAFJuT)H_gi^9nS*3fG9#nc<=_#dJ5yiSn4V9WIbx_L8(FZcA^rs+c$T&^+mC_8Q zIZBIsiX=MARLEBXrNzH0@ijq_?N&OhbWG`-(j_IniYR&Gm2Oljz{Kkx)+QC+sZ>en zKBdQ$sw>r0N>zGUsgcrKAn{gfka(+01(Yu}?4bzEMFs(-*26*4;?YVIl)h1#1(HG*f+X)c)oxVUskB$=5J>V~6XGvg z=dBb7i-N>p1&~yxvQibLs!Go&J+JhxQgfw`lsYK&07aybJ}QiYq=uuFCW53|b2Qz2 zrDaMhm3{?@l^r0-dswx{l+HyIFDZp82bpt&By(|)R5eNIPNi~6_kpC~svyZ*Q?;o| zFZ+b`uaOGhQhHbEV~`je0g@p#QE9GfcPJfFx(1R;hwcd|QHk$~`0HOWpw#tFkQ8^H zQZ3as1c||>O3js8DRoeaDD?q}_&1Qaf0xqlN=KD0fFy^xFUXOgbOT7LQ2IVy{~m=CIL6F-W}72PCc@p!Av2Fr{%I@xo+~;OvUW2(+j zx}@}{Qv8EK!FiREK~m|mO7|)~sPwqfQxU~_AZbZk5L^S#bXOXv+DS_3N~=Ip@LHv< zN;{MegQSepAZ{?$ztBTL=6IzWl?o^o2TA5TK;o@Rs=ZI?F{SECH9?ZMK1lMu#ahfi z?El`?gsqi6QtASd%>6);`E%6{SNcL}g3?r_8A^*mVsHOLC|_Ki0in=kRp0b*kg$Z( z{UCAm!%9ym)ljMjl0q7Tq|(h*+bW=l(;+}7qSOZ@nLh_Wl6Nsk z^8TvY%}Tp1q5X-@eia@AN#^q)$sDQ@v^ZYrMx_Eu#g&qj%7esSDoFg>Na^h=y8d<7 zgaehvgBm(q!AVNfm1Zd|21y~Sl@6=+n9@0=OG=Rt9zAGi3yD`M2oi($fuz>em7Z7a zf0Q~YO;g&X^ys63y_b|;6XNx+6HuzqRjHrSASF*}gwmHv6P3ONN%eOq9a0KC7L*nb z^7nr?s<41kait`sJC({QRRT$Ijg`77eXF!jsc_XG$88Z{Q|tapAo0R|N{=a3SE{L$ zs`Ro_Bc->L-c@R?^pQ_k|GKEKhtfc$sM2ty(MnU5W+<%%i9fa}om1^4rBF3AIO6d5 zj%T!Vqf!B-;z~(Mr9o0iEu~IM%aqP4-S&8pql(f~kE47sGZI3%ZZk<~meLZXbxJ#x z{!qH0^kDVCawPNS z3GK)Fr^3S^@kfp)g1ROu#&I*Pg)oC+g6XLBf1W zHz^ebiNVq;yHlyWY9CbDBTA2}_IZ`nR*Jl#__k6rkQDck$~q{GQW~o?OKG0cYNd5b zyOs6}@%6t`Dm0PDfN?nwCC=FDKDh+3n^>4HazW|AAE-RI- z5y%=Sby4c4G*@W}NZh{`Br|M-(hj9PHBi2&kErmt(s`xJO4mVB!8@J_=mn()ASw7w zkXU|4sio3~0Y#k70Xp53`YU~+G*oG%(s-pwO4F5QDgCIlL}`;HyZ&uc;Xb89N+*@h zC|y-@@Z6-dGbczqbF)&CQWZ^CRq2^$b^Uu@h4qzQQF=q^ZKY-)DQ<+)c#yb%rly;# zv{>mUrN~;v4N5zd_9z_$NpZRHe5g=mrAI(g@be(?M{T87lo~6&EyU~Jdn#-J64U*Z z#w&dXl0tq2Ng+#=Rx7Pj+NQKq>5$SNAb4l(>IHf#F`IU+(l~77nDywv_ z(t}EmgKV`TPAwJIRcffzRO!DUX-Qj^wO8t{)LUt=(h#LlN@FeA_3vw-xN8PT3R$WN zS17Gl+N88gX`fOCNbKdW6?ANIkjNfXs#^=|p9tSm;Yg*$N*PL*K~lk7sX;g8Q7WWV zOsSMovQkB*$i0e>f}}DvKvD=l<1PcPq0)bp{;R}Kz)RkaN<&pUQfa)>Bq3h^rUNDO ze2^5pLKCi5+N88iX`j*|rOP0(XKDxb@`9ux1(j|A`RiXv6()lub9JRgN*^i>QW^@9 zN>2nyA(NG6D$P||uCywmxDg};?*fUz6RJI}bVcd9QbL^|Z+?*Ey$vLlxkIUfQe~g8 z{#5}=!B2rCa~(}sU#W@G8%oWTS}1h}iM=$CENkB?tx+w1-N8QpLXJ~6C^$DrYMoc9 zh|(=er9gf+DLoI8>NnDKuPME&#NVlqGCr=0`7dU=K`1m@)#H@DQTk44E=Y1LQQEEA z{Yw1R3@I){={(5hjW~ts1!kUBdP}Ll(sZTyAZh1nkeFVlv`uNJ(jkykH3KAhuUf5L z|C|>CGdY!RP`Vi;nUg@0IYqViC_SQ7P3c*Xbp07)Ttf+X{Us(nQ1DWzwX>VhP1Bar0% zuWH{{YAeL+UwajH2TA6EAjv#RwPTgOR^l(`NSkJZB<~`nZK~a=bV%tBP_X|~;RU6* zmjZ)jKoDc2a*q;!??;O3qSOy0mHr$g)f%q!h0+A2^axPQEC5O7HL6~(^qbNyrQbo4 z_Y_F-{;68Ll+&+5E~Pw5g+QDa&tI1WO6H2HzE|l{rN@7 z>d%DvhY>IgCD-}~Jp;Qhe_G*Fr`@an>^7!tk>hVh7fuz>ogTz}uDy>jjt+W*+h3o@K-qWf* zuXOztUH`(b2Bvd^B=gN6$$W=u?^3F)biYznkmP+<>2=k4# zs^xDG;umF%QW~rDHORmJI|C@0m#TV&(t4#$O1nT(@L`bTJ*(P_O8i1RL{Nn|r94Xc zBZ^5NG59!0TwP1)ebs)hlm?Q5CxfJrsY-K|7AUO*Nf{e_!uoeo)n}BhDmje<(>axH zP)Y)c!Mi|GnTJ&SsM6C)&neYolJ&2F3f}^W!9F1I!lx>ms`RtcKBdb_1)2m_>M4D$ zlm?QjPHhqiS~mkiap3}`MM^*aFVfxw&Zhd0|3BxRbMM^QSB!ly7_!XRLbB6fgeXha zLaEePQ`DWzDAO1bbtIy+s3^3E6lM3-rYtR_(jqBRq=oyzhbDrn* zet+Jd{c}F|+&hExK50McbJ7vg52TZ%-%00uiWmVDMKg{iC6dxfRY2s|{K8ZRp^aqytEC8P0Mbla(6KA6-AR2({Yk??n)Viu z)_5|lcasW94}iS=-yEPOUPyYKj_XOAN!v*uf;8=Cq+e-0O*&7qZuC1WE<#KqWr8$d zBaqglHLYz)SCM*<`hzsZNNP8e#*rp@g!jMq0yVptAWgi$GshZ>NY9X-C#@m9PTEM? zOxg|7JobS!kMG2a`G6iO4vfHZL>kfx|cs!O_z)C{C)+k!N0cUrF= ziTpK8e~QkY@ZdNOSwur-<>FkH&dYXq2BxZIC8z z0@B1SNbN|SNO`2*q=BR%q|u-}%s=e<@`0L30nJ6Ehd^4-nsfB77!HU5(H1L-HyDUfCof3r_nqz)jB(uLHW z)?uW(Nb^A6{%3NVg;Y!jPkha2G)ZQU&qxBEx{S5Nfzu+Bym?V(aDUDQ-)=X+yq!uLk^CX(K2dNjSA4m&5fi(RNtbZ!L3sKjw z?KJNJX~2D?&uRUR+K;3_zMlerW!g&{3(`EwQ>#RZG$XboT?x`8xzzGVw~%fpO#o@} zAD~u3nnUYjAdURAT4n#YoQ^9&Is%S>G~i#-=Okp3i1oaAR*0@D6`6r_b-NLoVc3)EgB zy&_gw|6+}|DZWeEE@s!dhuS{U=d}Jvik|GJNCRnM(n(pQ2Bg;V_h;0xEyYeCZPo`! zPk^*A&(m)u=}po`(iV`W_<-8SqyxS+VthmKd(uz7+4zeTy3;Re3@H($nN*@yjZ}-) zM%0>+db@=B#~S@84g~4M8c!+)X?wg)`WU1c9|CC$eogwGe$}SV?N#{s`yZsa?r1GT7AVik+uMWlfq{eE7wJk_%H;mRBNjKAP0<}9y1t3lPAn7Su zp9OjA-^&zVA#EUSBJCu-N7@6@OnxE#1=5a9n(DVg8mS^kTQxI6F^iM~(tuZhG)xa# zdyxi^29rjS#*oI7CX=RuBoC~A3p_N9Wu#T4??77CQzT=Wuf>x(kOq;)lh%>8kq!&# z`u8WrM)&xkTa)^e3P_KUwvv7#W!>vXX-?`%8bm6*7x`=LUWcfS{vOQ-K!edpvBnpq zuW0>=+6mG*lKf>EO&i5LQmB>pDPmkr^Mwy%hWKV<9BC4%lr)#LjPxAoHPSlLPSSfW z;YY0TIeu#0e*o!#t5M*Wzc#52Nd3B!ZlHBE=?>Ba(lk;5Xzvm%p=vP3)4Jp=U zkT&6V(ubr^NC!z@k$wSbyyW}*WvwzuwI-yzV!+vdH;Jo#R;Sm(hH<_NuQB^B~>W&L$@T2AUy%nf&L~PNh3YN z^S^NvUnHeJ;D^p6Ws|NZ4I<@}o&xCzSVwIONJrET(tBdXe8WgTK=BLGS7LUpKT$hD z`khu|rXSiSMT0bLI;k$H1*z{$!w` zw@Ld*=Sb}z^!;upy-Yem8dKu?6_oJ(ZwW+g;D<=_LE1S>s4XKcr}Y(TYe^eu-A?U) zq)$nagT$Xnzmm>?vxt3H) zqX_YG(iNo6pggzXt_Er1p|svWx|MVX=`N6_eVE##q$M6<{aZ$HIY^UyM>IZY14A$`{i0Zz9EeNcWK*B+Vu{q{m55la`ZKlU^geO?r1W z^4GHdkKzZU1EeoVr$E|9gN$p$^m(we_R99hP#e5 ziZq5ag*1&+LVAew97tPX7q$0EAA|J1@l%B23DWO08;)Nro0LkbKzbCU0hf_hk=`Qh zBJJ}C>)#2AH!Sc=eHTar7J;;7W|9_?o*=zMT0`1F+D$qF(#WTTbp5OIn4d{~QhQQo z(jd}M(jBA;r0JylNhKg%pqEm6`Z2D5>nOfOdKaXSiXAC-CG{f>APoU&ot`3XrFAFieUR4p zQ)&lE$4QZs#M2;6VlMVe7$l{U(n*hiG{sY-_dr^}6ZHFybe4Yh6K)=|{)H7m>7**8 z8X(Q20kv#Wb6VR|>r5I?YlJk5^ccu{|GS>zcG4%LuSnIF_=UNQ)RNSNG>mi`=`PX( zq_^b1FxTe#gyNT=!PxcT7t=|9lZ>UlHHnl)stD57%A}S>YDjAvkFfsrpg4$h7ihR4 zMVL;l6r{zPOIirh;y(=7|3O?m$QWta`>V#jeq}C0jnOp|l!G=Wq=DkZ%}+6@}%cI9`S_epz%bp6{8)Zz0r&EJuJ zBmF`82c-3kUFm0>NJX#(j^QUOTQ zK1h0s)@MmC`xG%=@zK~o+C+LEqybNWv?Kl@MZM%(Ympj~x`4Dxx{fM-Eklh7)kl0a(BB6T2LO}d^`3epO% zR82nr{Q#)-{Fw9=>08pzAkFR%kam;3+D{uMC6mgLs)4+sf;4SQkhlJ|p<@?PH_|mA zO+1)1k=7}s`$#iLvq=w=mVz|i<_J)m^+VEUG@l`vYy2b?LE2hXNp(o|Nu5EO$!Kb~ zkfwNq^=}%*86Zva5J(&8aaxypUSvtN< zdWE!sw2AaSNCTb(X#<}lg{xpP@fq{#ck{UA;J6-X1Gr1f{wIa1(tzb3IDOWkSq&*;Q;C-YoN#BqP)?)qB)wmR>w1V^*Y1A9OHA0$2 zdIF?HT?f*P-y&@z?IL|l+Aje$$zjqF(s7W6K0``e=ch;|RUu`Nnu9cLZ)*KWLp;Lz zH-h3Vq}xe%lBSZ1KpJ{B=~-G|AiY9bOWF<6wBL)S>)$b&e{U%}8BI-ATPb z8u=!W7JqVtqC;8((z3oz+DO_=+D-b9^eO2e>1Wcfq^yma2iCs^9>yBYNv%j7NnJ_3 zKspu%QyWei1JZgJ3+X+Orri(HwBOTu zjPx7nkBt$(sm)D(;#g8Gkak2}QZ}g>=}J-uQZJAeW;{rHJ3@NQw?>Q&J{sFV!wngu zdqA4;KGK(@Z%Ds@h8vRNZ)(One%feKJShdF#j5WT>TenyDGmo|z_B1L!Z=bP=>gI# zkOq93^d;#JQu4cgymF-K?{fXS9HNHlO&UYTv7|d`eTcN2^bY;DlD?qzH&XUyKetFO zaVF_0(gxC>BzueBMrj~zqjXXYQf*QrQWH{p5GpM1e{Tfp0LdpksAgE7Cv73U57KTr z1kxgWO*%&Uh4dRp+c$ozPqjea=O1l=T7(`n52rSf+Cw1CZXRh7X({P>(n`|nr1hk4 zB0w$Iagf&O9L<4kes-~>L{d7b3aK`!9;peb1*x4!SpPav%p>(C4FqYiZlE@rbO&hy zX&OkYbU#SbK1%CC(lQ~;Kg{0eD6Rl$;;p1FNk>5%@GM9>;vZ6IyRXHNQb`p^wLzLk z?snv_{eCS(rC~HrCp}8*S=;wZ4EiMhVX3B-|8!L8Mp6-Jf7rL4_6dLgFWMJdlj_79 z#sIfvnvu#S_L9ce6SY8K|d*0Y$RL;AL%AMg~(Y~*W+q^hLLNUca$k*+08CPj*f z50jRXULtKE?IIl@eMdUl*l(GkSNcW0jTGqaTi0L&Vx-9Wx45S-K6|xKi+lUDx{pum zukq<(fcnm58f@@OD!7p}sb5m`@*IDn-<>(G9+sGRCJ7xB4`RG>h~ssmWO1 z@1Jo#)gJHD>H?p#?(->qx=-UG#94*Dn0miYy-9l?@U@hgKGiSwY4C$Sttj#7?^!1waBN*i+y@wsZVc{_L6=hB|Zs1 zS^rFleUw-A(>D4Y2~XJ8YP5SIx($S3j|yYaFmAyS8!<9)Qn8sY8ZD`b#dS0=Aw0j4 z)NZCWjamV<`P3Fr`-Iv7S3~_x<8O+%@G=<;(u{{w+dyp-wFUv-FB_y4nMSRE+I(sY zsI3T~{WX(S6t~dP|8M0@BhK)(8e3+UJYLs%WNL7I3ZHUIy{HjORR zcF?a`l%KXGNYg$|Z8^2SLDy?0^8ab8<82_-@~M46?J%`|xLK>;0Fb8ro0<^=&FS-$ zUBRi6WMwC!DZCdJ5hKHS`EILRA`0xiUdFk-ipaowy@T^`6%oyQy@zvwigCVXd;wbO zib)9+e+Qi~omF>RX-TpQ=*z;uT^dj|#TSk8P+l2w&ePG6~*>6<*Yg)bUSp{}Z;zOoMLtF8EEs45GzzIsAEQB&16zGw`F+WsiZ_bOF$sr~@9V4SMmsh$zv z@y?#7Qo) zx~#peruAC7+0vQY&#G!RS=;^!YqlAY31J&DLzUvCGhMA0NCt#$$bA93QP3Qa`aKEC zaWxris=Wo0!D1U9f||Hwq55h~0b!#EYZkS^5#on1$@I1jxnC*C{YpuuyV7CO5z-H& zpGYT2zmfhR0o-^I3mGa}vLG6=6j-iFva<~72_>L>4llm?LGU65)wkZvO3?Xp)TY5Dqt@FUjkH&g*lSR|sW&BRaD zj!^r7n(WBbFBhbKw^7R%O}CwM#iU0J$H1uAZ zaUPEK_TO>h zZ`bvETEk6q)~HBrq_mB$_^H$fl<8`6?@*FmwseMV?4q_0 zl;mpoVMx98Ca5HJl=jq{plaf+BzGybhUL~Jm$3#Oh8VJ`#ov`6O#(?0)0lyudP|dy zqH3}$(3uwxl8tt(kxVL2YX-GUQZtV*bX!uq5~QK8Bi%^46C`!OAO4}X9;6w+P1+37 zV!cQ0Bhpu-Z-u1(vBr6d7P?vkhCv!8m0AT-6_6J73Q|AP2+}lCF-g+ND2MUr}}RWgwP zIw!?f=cJO%NlB}7GQ+iIVQgt<&&GoYwXOzLlE#ZQUK4a_D`_WbAL%pFFCYz*gkhpo zl{5mR*;T{tOs(xfnuqKKmHNtGkW%bVaSUlJDMBhF$p%qFFCo1OlIAvzt<=6C$yQOV zCYsPq8!;;SXk?SRfYk9?YV!C*vnwJk0cr7i zJ5juf)SJ|gB>PeP!{C}sDkMEhdJd$mCA(0iPf4<>>J3CJ5$FgglSOB59a1()7I(F_ zCbc7VCUqmpGOsCQ?bJME{Zo<^CkqFb{`NEvrZ}A1L~2v0EuywmG~IvAzx$&5!{e~5 z(r0;6U45;=>4ZMZ!_4;oMe;?a*!0t!rcb2P2~H zo^CzptoqWb=1eTK7U5wB9)R?Y0^WqO1STRoba(tJ5-BPsxKtO+$CT@z0LX%QYK$qKHT{FM2s@3>Txj@Cx6 zL#i(uHWiyuY(;8I>O{&V^(6HNX(kdY14r3yS{}9DAoXiBddzL3aAi2dp0cBzCL1oA zkkeq8Q)a_9YlF4ZO3%r;{L(?+7M0A@L0`1VO7aGM*R`K-wmyu;pkMKxb@jgoeUj7d zed{W3AL+CT*$?dc-Y ze9{8aVvvsQ=cv6%T1D%6YHxdlk^c=)v-^!y2@_4Vb|5W6CsIGs0MZ!JSkhEdgtQo> zk>zKSj(i!VD*pHQ^c(a4{qVeok^g&8#``1H9hG`xSoNWmZQ9OPA6n&|Z~I%R`hFqi zBWt2np=q@IV(P~!h!as&g-98lg(XD!@X9oK;|6h-n~|x zK-ygA*}c})fogM|(|fIIG3hM~hbSHC4g;*&gS`7*RhvkLibrN<=M~S&l((53*0qQI2OP$X zO%n%6oWtOPmOT@TW&`p{)UR9dfxP0cbBm9{70Zen1FYS2J-}G!oYqWxfk@ z=ft(Ix+!yuCuR=sT=I10Za2}y%C}kVtA>I8%=NlEx3t{dNO1mR>9xe7HYmr@{$61ulDxc31QXXz%*-#D zpSc5^XP%JGzZsPoFk??*QA?DfQ>lH#ZK>k@Xr$6+Zbf9!pzk7RxjZymd-&y*UTsS& zOv%HK?2E=w(HSgzQh)K=-Z^ukSQpNS~z{LGoS?visPxAaO0k%zQ%pyU>>$dpHU zopJsH=iK5&nYih|e(ItR%8Y_58YdQ2fJc{{RU-!;1x{u!NE^eC*|OXBu-Dc*bRZNL0(>CqP#%0J_DVo@E`&?`Fv4 z&Y4q${pL7Y83Www7Fn{5lKd)u-ygjS-RI4|l1^zoZ`@kaH>uk@hwbjgMYdGAq*J)n zhly9cE7$V5a)-h#DD>v6&R2}g9FRCYjLmT~26C}L^3IQTx8glHdycjCD%81TfZemzUx|f75N-53NA1ytk+Xrs`R^pYzB8}JJGtfu ziLbX$&Moa1F!NgNNh~}jnU>mnx|P}pnHx8H#?B6jOE!(}&}!#|=q^Q@5@(cy2P_E% zEscp!X~eUEN$X&n_-bz9b~9&ZK^t^sOm5*jXr;5^Nhf-iPE0V5IXc5~OCvqZAEXP4 zw@EGc{d4}jv|5H+nd7KWZfU%1KXTD@*$}&#XL4KpJfVsICM2);PdB+F?v0-7R=5pA z<{XC1O}N64In$;1ccd7<4{A8EsE_&t#AnjsqaDvhuyT}i$#&aVKKjZnemA$oz~!Xh zrMU;>76<&!$t~%ZIUGIYcTQ(?<5HBZ%Z$$xXBk~_wC=A6$f{Tt_0ocoxOPB&co~- z?plxL6;Hc#_Wvx||NBNE%~KT%o|q(YUh&~>C0B=Y_T(1l=H||D3J+TqBi~Iz)dpu~ zb;;S;vlxrhQCUXhOF_91*=q$!g!fgl^^j|{=D|8p>ooVt%-RX8wef(m%kmC zIGu;lAn6ikv~ySb4X$&y;?p^M64y?{vV*&5*?WTC3!IZ*Td9%fP>PF}m{LUYmzcc7 zjqT$`qdBn1yfeCUtL?JL>`a^i7k`nN^ioN_o!9DIVxfp!a9)Jp#AkCY+!C=+$US|= z@ky~*eA*7f>XvK1->tYsuhPzug1<^~!&oDda!YVK>uBX|i_5iUxkI>H@zsAE9f4Zr zV*Qco%f`d4hqrp?daHJ~?XtPY>^#}wjU*TT?6$qDtos;1@!y|1e_k8TT|G*BX6Jfa z&*J=WB)519vi5hRG7m~7h2^f*`7arVyN+4z`V;WhA8ZXy77?I^cE7&4KfKjA31LCN~)8jKALiKSp!b8>!{8t4w= z=t2y3UAz;EWG&+Y{*ydTG&&UTz-pdYco=;89XoMGFZf_tOX{5XdbrEX*wgP|i&Y<5 zhi!H&mYYLv-$uHbpC28DCAiE;#QNyZFn?sB_T7p%C(dx(38xiu=aqQM66SUfs;iUh z=)}LzpTBs=cIi^>-T5QN(Yk-4&R9dRgv{uKR=B7nfBGfS3Do#EOrY-gk%v1%@z$Qj z7OH)9NuKdXui`xGkDjGH!aa)*bSwPokDm2*DC7hCZ?`X1V+b4i}83mE%5A^mq5kIuzV zE3-?J-NcOh%d82PHp0>B5sWfF*uShR${1xIqGMa$$jJUvSAlqUm~P8CfAnv(d2Z=I z^XO^!maXe}?nUdCoAT&lR42Fe+U%qE{&Bwhh1~zcvjSSID|Rl%xzSglea{`;iqM@) z!d;4EyQ0zm7V+<+t03YFSx)Qkt(VMn=jiv=XmhpG`v>b(jkkV5-=g6#4$Gm(<#TG| z;_q&aJZf2{S<$)qN2^QV)KAXKKU(F@H=S)iTJ_9i=fsazg@m&|NxyZ?I`(XCX>gWP z?wHkhZNFnyOu)R>8Ft*dtKutoH=2pan{XbBMrs4j$9b`H^0-yC@nFL^a=l@EGRQEt z3^a^>0}Nv#9wv>v&M=zct+4!`&3L&>2+nEFl|Ne*ywB*Ig+E*A=CZY~{A}$>GxOKp zZ`q?w^I_+>Z8tRQIF*BTRdcx0Dri?TXE_6cc71cRQy8>6V>`72w(_QI=kZFwBM#HN zCNKe9qk{8S(9ScbIJqIaojJ#u8M5oOecSVd3mnaC)9e#%NrmKPnggx5Kj3{$`Fzi9 zD;^HO#hQBpYK_*;FCjbIT;ya#+2zd-oXex^4wwBX!v(L+$lE^eT^zv0NIVvhJX#`v znQfF$NO6`$*&WSIYrl)KFEgwE<>lG}dHh;QeOs930Bi1!dknjrlO1hWHyb#;qwRX; z&CcD?b}zKnu4w!6iXCly6p14~1Nlx1H0^`sMxGNr=2VKY@2=JrZQKk;aO{Yi#@smU zj$4iCfv6aaiTw~icGkq$^;^pKsB9d;JMt$En=tCei4%rR7<2b1V@4omC4$}w)2%ql zNlV@zNUDp}31K{#cG6<)rcKuZ=i+cv-#l`>Q5>kzq!E%}g_MtJf^J0P!9d34P}f6Q z;oKc-*Kg4Tp8{0F5u7k_yk=Oc87_c0+c(@XdbBY+5d9c3{U5Zg&Sywlv2rYKhB(T} zK$@$`9>n!Dr)r#CIdTxV9Y=7&U1KK% z{CF$__6bI9 zD^prO217D{!)#2SLdl4aqvuJdRf1h5l8Dk(uZ$nj_3)z&EG@+2>X(}u#uSVnd6|a1i8U{`5~7Yk zz8((!aYXIL#ZBd>oFJjc}2^5kLO&+Av`Bfa4QpY)$w^9c+U9yTGvnj;J5ucN5@7xj2oB2wjq6eHVP?`1x1%?>1u(Hx`RfR*Sq051&2Fk zN&v+;@Nzp)zELSJ+xQ*f_n5Ka+Ng_k;1YN}CZ6^B<0>c%)9zC%+LN5iGKn2y9Pp9J7# zj|-`vl=NXlyinR)Ep5czv7(X7kMPz8X$ZR6*vv|Am~g+S4U8J?v3rwOeLWdJA$)Mu z?IVp_t$5jYwL*cK<1lI*@I0|NxvvUY@O1Zz4_c9gmC*XZ?;7!S2djgPsJsG(PhJ2c z$x0c3#O_$V5&k1^xMQ^dFj)fFGN0wOB?Y$(__8X2d%#%Xq$1(=(wWkyk-(iE#W(yh@S&-HXyslk{cB&J~`kWM!a3{wpgqoR`z385O#z8{lq*2CwZUmooNo z^S~xvhW?9XiqqSfTft84FYi0NiLtLt2_E`)3Eb&1@c&$d>Xutox325m;E^)HXLwer z-tYevJiScS0+=mmLK|;$Q0miV0%u@=Txgj~8?jN0*V$LOZV~^!6m8wDWkXuIE!huw zeo~qTE(+=Pt5!8I(JoUa_Upaq*H~{1Nx!~YHoaS9zh@&}!@lNuOKv}x_0~}&x&24C zVlvzEOBC{wUQNABtNyQE9Tcrj9pN z>Skd5SdZm=4UTFfM&j|nRe_f8!S+3bZ*atSz(sDL)-zZDqpKUnKcd|aty`dmd^Nu_ zv^F@d$$(~d4{KywaGa~u31xR+yv!rgrnNzCXkwl)C-s0a0Ex? z7~M^`%6H)MR#$3*cZjYu3zzphU)I2ryOYj8HSpZ4nbW?e-O0SgDXM8VFdb*LoVGZJ zYT9kCzP&l#j?3`*tB#DG6-c}sM;o^Z|4x<`+>YzbIBLn@`KP9gov(3uNF*6M=Q3pI z{DaH0&ds&#+pbKnfgy^cP5zC>FDVkDDXtpha6_EP7y|#RaoJrY331XLePeJrYHf0+ zJu6s#8aQZpHwAdeE0piNQV-81^PR8slvv-+!BvO)c3YeZ>Z9}Woz?a2M&=&paDBU$ zS?Ji8*;(c{PQ%Oapeg~=RbC^^-tIY62dlBXY$Ma`ZErRAn7(C#=V}{OV5!o>?CUy) z=21_Ao>bo)fTt|sE~&27Nc57+Rmgv~X+yroPOM}*+b^@Ln46ptC3DEUxq%AKoW^!+kDhn~&~vkC z_C*$m-Penqq_O*Yv6H;mNm|mr8nmwl?dz7*?2DkOZqN?H&4Kptk=EQd?zTs6HUo3h z5nL*o?k1P>3(4Q6%6WD9B^BiSM}^#0=CBnz$%vEB0xQ+Bm)M7`zpX&_63|!nMTXf? zk49Z2d=mAG(>5EErH?Z<+pZYdZ=N!d67L_pmlc}ejY-?M=|a-zh>L%gKtWjTQGHgAO^JwXH~n`s41Bh1^%r*f(-tx zN-qCa_oq!S2h|y!gMHnFI@wYAhGewFwr`4IwvyrDaM|kz;@*fWd%ZUP*Tk~dZ>OwC zEqgr!*_FNCU4BOeUOT}icAM&l+&(&Fy=Vt=me?<%xunm2w7-ax>o1()P0%50lI7y% zluydb`9%43>2h9|zAasx&!m4}QLg7y+E7W(8!Ek1N%TXN9;qzXuT_5AJs+xER0Y>u zN<+Btd)PaNo@76_!m>8y39N(m6A|;c>27H3@2!=#(n@=W4cn)&KgHtoeA>1&SH~h) z_Ek1sDBo~<5kY-?!rW&@%hoRBS|oazOUc6ZERVjIjQnJh8~mKoruOBL`$JOK`$OwP z*4(10_NP(n!y^1I@ykRxuSs5$>>8$*N9#d&+-tQtXeBX}DQ-wU!I773v^9s>2hC*x zH+Is2BwQ{@*_9%f^V7agGlzK<4fVN@CMLn3e(q)$g+jthwXH~fiFQ$&g?c+LG_&h8 z92@NiTVj`(kD1Zays3@pob*a^8SBz=Z#n-ovnyXwz|uE2``OLMSSW@)Gw{A!iPcGk z$xwHt{O(p_W7>%{*M1_cw4B+`>D%0H68Rx0_4^^XUPcC6@_3xKD!QDRWYBl8Gvr?JmEtf;rf! z+QP0D`GEE7E2h5dOgMgQo|m=CUKsdFqW)zUg>ZT=^sPHAPKF+jiXCUnHLBD)5olH$ zWsO=A6@NjfWnz7d+Tu%x;Um)g@Tzd^y=9WE3cnJLc#1eJu^)_iB*qKmr}``TS+{LZ zq&}I3B3)S5+{&XJs(4e+Hr#oOugzU+cRqv6o?_i$uL--tr?JOlMJSHn zlIRL^QqHBgus`(^j5efs0^KQaY1{Za9>ZNQBGO>^wNN{I$-FRfxBB6P?Dbj-5X4)2 zXe;f_wu+lk4A)Ic<5{IVYLyasqLj%)DV2v(E=9@ONp5B5IPF{6Y2|lF?>vBCm%!mcgRr9pd^%1kH#)%yZM*wdHynA3Rn{cEU}l{tAqZ=(fxTkB%yJPXIpn;MA{Y1LH3W9c=1K5o2wWixK*6mVqyf9?!S8d2|+wa;5 z_nJ*JtpaZ{*M#yOw8#bRa{S&JtoRqYl|e%>3NxW(r%Jnwd z67XgCF(d|PY4FU-9RoVG+`3(q7@G#k7pE`7XJT=3t29ii6pI4Up4LKBf-|5BxM{v}FV$LAYm zQ%j#+>Zh45ig(Zcw9YcGHxfm;v}X8oA+6X2%Wd`n0DLv|O;Z-I$;#`k7FWWf1Y_GRNQ;i9DSC<7u?CUl5^&0zn zjeR|12hHo9kGkMnyqC89=v%9dGn!_OGiv5!PBUuON}g}x-ji?Cgd$tHTPNb_@t5J! zXq?ug52VxoiJl&lfE!X-zv(e0F>qNBi?yfEzd9$h&bwV;+%!NlHps!=??SFi?2dEg zozlrrQIz}SCtxszZKQ>ko~nT+u{)0P2p1Q7AZ^D{|B(`#I_Lv0_5ikMq*Up&8H+?}eO`9r4A&94D!h zorY8GPIe1(lry-KU2zaPb&1_@JX&b{8uOA?UvHhWU^r*ZvoEo{6D$qEQW{zvy2P?C z>Pz&Iy*&KB^Fb%OdgQ`a4N`->=Y{7b*%H-5iJV-v39uoBheY>0B!~a-kX$?uj4{X

N% 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 L)UOTVrOW>S3_u*{ delta 104190 zcmb@P2YgjU^Y_o(Y(hv7sZxcYAhA&`_=tj{h>98z5S6C#sE-8!6=`w_gkDTI=s|k# zB^VH}0n!B|AXR!5r1uW*Z+6a^+(iAq&s*|I_I`I}cXoHSoIT~9{4%;=f3INbi_aA= zyz0*Z;Yw ze`l1Sf>Bi2Ym;tjXMAer6Fumyf79Gfl{4zb3=7>>snSCU_-PT>vS&Vre~RadavFN; zyG0ero!ZxN28SG{v3q;&kEyJimb-j(wJ#iJsQY8?J7dnJI?kz{?xEawM9=XY=Uw-f zxI1Z}TRHB|xZ`6TXHrXYuH0~&#odu>aITQ^RaBI>@P(+`bA6xRahB!^d5cR$mC0YT zzTv=FK{No+?|dPQR40 zL(mS6R66`-#_p#}5xwl*sQnS`cUwKvk?Ocdo>@dI+^KcS(l;6F>fBA)>gAf}-lXCg z?>yIt=wtV%=kKKE8T+0uO%!%RFWi+UvQh2>FKo=7x6q64(#DL>Uo1#eDI@KrW<+D$ zQ%P&d&G@O_YbYnnrKxV&m*1f0GkU)K0@3Xm8ylGH)yO!|FplWwjFXKF(PQqpSC-Pd z?t;d{L-7mUS6*F1YctBe_DzVM%h=N7$r#$=7Jq9&!L=DTZ`SQ|`POe2^+_qalpN>q z_wJ#$M!TF#mk&3~DA>Ccm9Ehb)_N@ZxB>*-FO~T;nX6pSP3lu7_szas z;^o5^-Hv@`7cSTP=FKC2UO?~k8(cOMgR|~{Th?dP?2Cn@TE^vm`6$mjy}0Z4*6FkS za1*!ifaY|c`{{s%^n?50z|-_gM)@zW{!GkxbPz>RgN(<%44cYpt2<5#`Z$w6pK+Yg z;8cA6r;X#x2e-y&a$CpQ%5r?BWE}r`wJET&7M7wKj?)BxE%4W}hWp*fyY6WD6jC8N z7=J^MM{TeC$iE$D%NvgK{F{!`w}s=JYwkGh@i+W+ zWWwJp=*r=5IyfDFgWWeqzmMf}@$jgp-2!7uQ%XjaG0)#esTp0?Rv=pD&iM5UgpaM; zNqyZCnJ(>dXJuBWr`%(i#X?_ocWWLi9NmAO54rC8 zTJ)Z~WqmbDar13Rqyg?D8!98+`x`3W+x0U^H#FUGu2*&(qWYmv9H(&Kjv}x84L)Ok zAM7|2++`cO=55zSVhz%$)Vo1UO!ZjsG3Lf5*v zjW;LIBDcflI>o;EJS%(IhortA!_q?c_sx$M>yVtKZSQM4JB~?lD{LteKHzH)Pmz4k zIHnbc_~H8e=x6y9@@^6GO%d`j5fwO|RROa%LLU9F6u@?ls2qpB+p`q$*SoqKwBg0_}D;Z!Jqr z-K$&6(^u}D+p5w;_myoG5%$_vHU1~jxClY9Hl;_;+IhTM05 ze;{xdviPLjLn&*y1~Tjpp5gh@xA zrCsjOqj%w;wiscQd-!Pe5{WNJR$dhPJa2t!(o#FdIPrbl8pn#`p!eFbWO~HiajYV_ zZl2@C3f8WdmBWeUMJmIscDyQOxE~y^8o&A#(T1GW?$qP8Lf2n$Pac1min!%ZB+?Q$ z=|p8Bx7&#wI5;*x`7{Rfgp>EuBzOJEl2pMxak5ykM?Mk*E$?%j_g<1t=J{UFO*mBv zuB>;e99;a_sr#vxJK@v|RNp;&s%m`w4<%QWQ{Sz8`a$})`_AcS&@Ho0-%l^PJ5Lv{ zd)80Ei$W7L0fWb+twcjj*H)63HJ^wk#OqJ*2ssZm$eh@x(cau{tus$kZnw{wstA8X z_=bD>%o8-$t$Oyw(85OUn9JpO^c5hy-g|T1jS`vI%`Rbkdit>0npa~ARE3Q@L zS!TnE*DHdXU$2S{uY3Io)OgeNx}h=kZGTL2pTAKhK0$|Pg4_E>T^jCgy74qMbW7a4 z7YocYH*YVo%%2dv7OiR)F(FJXH+-{5@rI41Nqn%pEc#Fw>@VU80Kk=!}gV<@Ht(Jx%4kTSIg&Rr4MVQOSqyXd$L~All){ z^U$fV5Qm!@*mv*`4s-VB1oj$tE`=gK*&7g|;-OP-dQ(F5FfI4?hEUpauW%Gqj9>ni zB#&{HdoM-NgL$s|0&=du<)ubZ9ctxmi=tO4-m7Zp1uE$!8)Pr(&E=0*ydwtfsOsGt zP1Qm#v~&|sl&7#aAe!!{eBSrb)SOy+C1Q}Ip4T*niWPg~9Vw3|?>20ic-rvfP4>Qs zp~|$xTO32B>5#WK2CeqITXIp6Vq@QyJlyJDV9xUi8aCB?EEg4}?p~u@s7iOQFFxYa zTT5bc(!G_rs21(?^2AaNI_}ktr80TWsQOH6uR|-fTl+#h%f7R zV)O6Z(Yp$H;oNi&J>*U0j}qRd+;C7MFIOBq)7z^WM|ab1uW1}5QX#Kr95pLeCQ0nF zZ=ZQj{DdXR+~-}7qasw-D;!Ui=xwidJl%;-dM}<5sF>F;p6;U;y!rSj`PH*x;W;cs z@N!gIVhn{oOQ1^50}p?dhsx5sUb#F-w;RU+{+ajJbVa-m^H4c@%X9P41I50oD+xoN zJNJB`Hl6rN^KjVwIYgQB#@$Lk5jozQ`7yYTdFlBHM^*1=etIN+Z*9p;&R(x#0eXhY zd7l-aN2rE3y8zm=*;`crK4|WpEkIR5_t*Aj=ckIfwsyvhsNB+PT9C?x&err&3Q~0{ z?kz4zRj9sqt{@s4_R18ZyFxo^dg+C!l=n^{`d9H{*i`TjcUm+Cmu-Cl*8a!6?~#}$ zd;1C@Yd!DQ!t|feIIk~8P39nS5{jevi(Z6CXav%DKfgiEOXLN{;qR8$A&*MS z{5<*{Kp99%d)42hKGF9A@AiIqlU|N~82F%f$6LUsfltiq_!hlLr5l4A;m_8zCE!ht za7{l0eCqwtlBN~t159Rl|8$(P0j7K7|4pOr`wh65<@caN%a3%NV)zR^j7VF+n;dxx zkrjY>-bZg!t#ENf^We|scnwgWBb=iT{yygj=U9cmA34$t0gXlnapZjjw;@shf1&n> z+zTj=zo&a3auXhl?g^+3Np<{14?<)J;641szKg1V=v97)iWTTN76S%0>bPZ8GgV4(V-c(~Ywdojz((;)B$7w--SjcBir-nlt(=5XN4%lyO z5L!F=v_?U7Ue)RpdN)o4lwK!U+KXn2CKu)B1)&l|~siHFP?aD~Cc(r!h<% z970yA7o-k5=9|>e3M6W55UvFz8H5`E^@G%nt=*8rW_H6&eRCi!^oIq6Y`8w`nPms* z;6bzyUbc}-2g#(xy0M7jhXbh~fYY*v8;7&|1yyIip!&Xt@PS5{anyJeycIYLMWP`h z{Ts(g@m&w0F6TO0|rYe6k4Y2Hejx02=s`FSg8B`UEe$)pbqWe((?LWruPJ9CNqy)Lb( zNH}or|K7Lj`~Staf8$Rv?)x(r`_uO5U%e^L48v-6Z)W-MZ*u4Gpv@fV!60)Y8u^!^ zbGXoE4oCVh$X$tZ^G`(Ock%$;({YpmoH|JGCqj&msI=Z4{jRZy0RqDoWei#r%ZxcH zRv9KtTGvjad>g`IL|Ci{vl*{eTWVM@{SeJRM0ulLG*Z)1Zme6)K!o4?kMU^J9vML2TU-@@9QX#YzHB9ie>n z+}QeVY+8CJH?|3kB^U_%ddVMCp^}(1_zhAl>JX%0xi|Y`D#0xt;$?nJcjOszoQ5B# z+hNU(^(w=D45Ix`lb6trN*X{9@3BuP!Spy!W4t#$p;FOfF3{?W-s7K8>FCuLX?(Kx zL^~>I#wUm7dka6IBGL1cLrYVvFnVc9XkUs~x*gpfy)Pw{+>@n+OwZ7_J+1JeZ+nI| z_YD2Dq7d%w87h#L*wL3p;e)aY#Q(B?i;d35>^uT(oUZb-k-<$h9m+xs>t&+CO=NA!$Yi1pw58V%wD zz+UgWc2wHz<)N{&9aRV~wSCA-I(l$9kI*4@gw8!7IR6A~?t>8uDT=(@PcRs)kowc0 z(kNL9u`xB{j?#}uiEZNJ*iqa!F$hl|rKpd?SZt4SIrOp}ieBH(DE?o_z@i4`{Bas} zf~O0@3nw`vI`OOX47OuJ0P7D1>w+6xoPN9eBVDzllZw@j3n`n?-0_16j}- zV9*+1R%^I=W>3G+l>WRNp0H~*B?ap}E8(!dXj9tCuq_P33EaV8FxfJIK^efHjFlZC zO<-b(&#eWF1vt6`w@`eZWdYK_!Vv!|r`j>k!;G!TDQhN~D*{ACtVLj2ZysBr%A?da zgzP`=PhepCR0pr-G%6f6BaYLUWye>L^XgG5TBrgj7bfmw2#dpasDy`u?Z!rE4VQH(VS9Bxg`ch%p!XG;5oUN+JDR6j9$G zTz-6WxT9b#}mpWNA20FwQe$)hk8E&|wl zHCt{(4_~#pt6sfI-LK`$4N1RilrO?0?-3FWgp;m`)!P8Wu4l74`a13M_H;q}Fn#BH zH@i@g$3d%-Lxm$Obtd>u8UfAPe^f%V&DywoTXJYpw@_s35uIWsjRRAN&h6$^?n<|n zo7*jPDZ3KUo83aW+@ew}xVyJ5jKlnw-9sa~ha%evgJ>s&`@36fh4yz3o$sEN7kphb z=6d(gQm;~1Y+10<9_{f}m~Jyiu|#>vUFmu5;(oTX?*$Dz&5n{S7q(i6EW-|ivQSw_ONs(;E|e2DE%C+n6b9V zv2%pwAX`;0P|8JH)hE8WLUXQU8)$p4(2*+DCe&Q=vLRfb;9d?}*Q2*DT;oFox@Tu{ z2!PrBEpj$A2-$=jD{Mx`tiQ^O689NCIAc9?J(<@Bl#TEQq;F&pa>jaok!HDFAEU4? zakWs8#c;4^+S4JcHzg@G;e=R}0K7DDj`Yq!Qw^jZfuHb>b0;UrszJ9AWxO%HNodNPB}PGh0SNCaD2emDeF_F0d9^xd>(UTyReJ zaG%iPK2j_@tGkWnaFz)D0VKuy&8Do{_D6sH|BrXt@(koUmEi zH`Ki!k5V*WI7jnE=rqhp9W#XfuXX;AM>NlimTpG_8G*NzY!u8E+2Hnoh>tUkgXd$Ek9=UfY6Qs zV#EN@1PmOp9Gq_QAaVSJ=sZq#1^1Qf8H6_mgreGD%-t9ews~U?dLS;K6NM|qP`nBW_b7~*;-_NHW2u}lEHVCioCtT#NKgwJU z@25QnSc>q^1HKe+(FzeJ<60&sjj$=mmS@0VJ%jKpprJu1mg~Xte(DDs^$fy&fQAO4 zlmIQ@vK79L4=JKv&LV;W8gl_>P(TBNPzu0Rd%#|pXkZYET?he}tPo+cce+0=TKm;} zm93nEl|}}kSb5c2*^dm33_`I2A>fJ?B9zL#%9S%C_R}#~Xy*HZEv`g7$sD#80qF;5 zK63IE2lK-LT6lo)FswT!>h`cn{esSa!5x9{a4J`Pd>V}$#4yaIC4((|O>0LnEEz-J z;r3_)gK*F^d+B8w?VZjNgrjHj-4KJ1lXF=D1jrwl1G<-MxxEs}I z;H3?~#WGamGOAI}AmnN^3#!p9s0Ki)(TuCXB{bs_U>E?qKWt_|xPLPWh&56`mRC^1 zT9nY(AWTk0l6(dqLqM$^$8|%6tS@?@>{ks!u0+$I5>10j0HhL4xf1i>i>3x4e1Ur} zLCc#4EpHlB!oR2#?2EY@P#qM(_YK6~So3f`c6u z{z5zVSn9r)j_hNS&i}g-619XxEdb;fkZ6Je!igp*A<+aSB$}Xv#D6ZKl9o_OO91&L zRMHYEX#thAfJ$1x`~D(fS12hAej1)iQ_vOI!KTtqz-tB}exo`T#f=Q{xF8zSs1&M1aF~a*P=w1*$ z;D0_6<6{vz8ZvyKCs>A$BVNZex;vbaM%Pj4*Ue3-^y^&dNiIuJ0=NEkv+GM9NPJWc z9Pzq30+%M?h?H4q3b6MA`uQgyE}G+WIiBH2G6*r`tPB;vn6r3f6`jSiOyMMxl1U>o zePJeH5?VcGBBr6m4SNW~#vatIH`ouG2GKSwD@g_+DvY%q&N${V3?D-9h+KS^W`k(8CI^YoSml`z6UIP?}RDUTJr5ZaLy+2*LH7p~7t2J!_ z?OZ_cEy9!Eq2-4=8GPCXV?YEw4h;GkcqEhCj7$h^OCbw79Ec8=M%#UxnZ1BEFR(s1 zCHb0!ZB^{v14=j=hXpYY@DnxgE!y3pHRP}*PTVX=+$>1kEJ)nUS{9cE_J@B*2A3E{ z8Ni$$*gaur8$u!qJpG6*q{MJSaJmX=x0S#MskrQ%GIiAl2XLd=y2DuN=h!$gKK z7sMFkNYotIC}Gh1KEn~vPth@7q?|iW6x1YV2{EJJsLdl@sujc}br1_n{ru=(Eqt2I zg2Vy~5(^C2m^I)JWAt>|cZ90}2seDsDdrrAzz=i;-IByU zn1cg&l9&?ZpFdD<4rDwDfg^lKWIt+^5+TiK<9+yvkEdVXwJ|EzJ60yMzM>W}EC}{liED zgAEi8=pw}8gQJQt;QwGtg>4U}ujG_`)so!e9ZlwO&~<$BDaLx#vg4PQ4|2} zWwor=XnDO+9u22LucAlMkvtOQfX#&Fp$C}!br~eBV41XmNm{^^`I{7w5F8NF60)1m zu^F@G?Ou#G0a!8u^NDIcQOzf+`G}pGn-(e(HmLnM9A}dZLiCzFFiVeFMBn@{R-}u^ z((1{AnUiVv6u|>iXneZhlyv%Hjv(6A-9O5sVc-8QQW-sL7qiYz$*?SfmO0?+@T{=Q zvba+i4n6vfF9+~=X=MEIViWu0#j-zMEc@fdvUpnziof$q#P3s1WS!0f8P$jx{nOK2 zDXB;hlfDgNQf?5Fl7pC(9mJ&cASUGpF{ywb!=sN;!>NE)VyInpgGxv&sD#9VN=PiI zgv5eMNGzy?#DYplEU1KyIphrZL{j-Dy zr+qn)m4vXM6~^FlRm>f5sOlDbNuwyCCT7~QvDq4o=$5fr4F;bW`?n2-_`+B(eH7gm zePJy19OsP~NkyONIgSR5`)iY>Txgb#`{yP@H)euYZxoe|8#95XO`zg#zII-jF;p}( zZGu;3G#>w+>kSx9Sl}j5rZ;;up6kh+KyxPAJZ8>Bn(tj?_56wSn^$5C)W1!n?RH*cM2u8uuz+RnE(m6(+d*h%rqj>ftg%!q zdPzEMOc&ed(`oW-FMTZPIC(a0pKI$F-aePU|CaK(Mbk1n+CDCcKE{Cf@mt#PZPv&K zZ?@6bpv6S^mb%a5PDiwnO^@hWD?u$qf_Xkb)IEOI^ z)-KMf3wYCFu1oZ$#dO`$z1J7hPd{ffglOi^ISfIt{b%p`IQV+|&$Rz%He&YwjN8UH z$5W9O{g%+UrP+)ix^Ss=O*-bEG!25T%d(|H)LWLLC1T%5rAYu){ZE`6e@_yd>30RN%t)zk8u?ZMY16Pu}Qr6N9D{(f;>Vy-Z zmDy}y5Xce*`MgzJomTT!@f83J866;4`ZxZPt%8V-TJ1|D|LoPYV0E??R|X)2$5&@7 z5^~7``4?-r$p3t?hIX&XRwSY)*02ZK^OFkFObD)IPlf2sHCbaHEKynP!C$Rqtwcwx z#nX?;lkjB3*tIl8==fSJE~6(=v7(v3@@|kPYF5AEAh*q1KM4;PY~yXMH)axsi9OcY zDH)9e-SFMAf?yLe$E!CPx47qEf9JKDOeLbR(_81O*X^c#-fXC&_wA;Mdt{#5-JfK~ zLGlYP{}j3{;fuYrV=ono=w>&zby%kQnZ0z`ri#A2m#*z)*FA7;FD38G=3nhn$VcwW z*`$5AX2%UF62^&zkproo1M#UNb|#Sa9Z9%2fyS`Lt<1@BO+jpkDT5A0alDc87+OP3#AUe2Hs0_P&fnva7Ih#W|jzPHvK* zQpkhN6V9iwNx{J`IGqx)Zs(w}EN4xk6d zOX7=G@PvI74UNZ2ZXe*v?Wch%X7r!@WhcI*1+5>mMj-sb=7t;Wp@RJ(zJs&vrpI%q zQ+}`c3W^D{!~f4Navw%#G%zTXx2z3#%Q|rG|MgjyJq_`GpGM`wensqMZZ4x)P)4(? zGXCZi>HpUmQXHlX%H)aR^_@;7{QCUY=M1Q_O$*2T-<&?!ez9}Fp90|=bAVm)^52Yn zWR$7n&mMH99X1$^wo0iT*^lTVE0x`{MXVrbvPC%;WaRN7=7I-8{Q)AQT#O3C>ffHg z@M!qElM@ssaxU$wnRI7Zc9~JwH1gK+0wz{{gAg;{%CJwHIG$w)u?Sch3eB9wGK5$K ztPD%RJgf%w4MN*a*h4#);rd{GgD{oP+aR+`rl2f;V`tL$;fzs)-`xJD7TXrYBKN+F zaHy5N@6N2fFP@x-3<6a57C&nxStygoQvb0O>lXFnh!xvbz2vR6 zn1^7;I6gAr5F`>re;@Bl_(8Pu&{VMQgcLG-dN60`1!Jjs%-SG!fh{jEfbQxm!^(|`VENKX?2{J>9eKV&OX%}%D z@1-XOrTa1nj@zVCx-W%j;-tvZ5yP)q^pj;tqqy`eDYoUD)=EDg6}E1KY|o^i^v|V6 z5MbL5*Yb`b(SWB-=4f*p1!EHrPb2Dk8u6`@BW+vL5bc=kU_9!hCia@gbUF>vP%#hG&5ToM2F0z zTTyqXwUc#@7>01<-^d}uoR?uMg~-%r4`odeSq0FYR)$G#D=iCxPBC#p$~V;i8_I)c zw$PIK2=J6H1dRuOL$_uLWg0=Y=^LDlYFdb8?m)cf8?Kgm4bg6Ma(E4b<=%`8Dn={3 zsTp|6ck>(^Exj9asd!jcrtHnYA~kjckDP4HfC$$xb2LNlDM$JR%Nj0dMoJK!v@u7O zAehIg?&O-w9vJann{p(BVE<-Y(Nc1`u>f9X0EczOaDWGp7lVSYKYBanP|+~1KOWo) zNBuPo#HVs<*txiOu$4ys9+?M5MFTM|tVLLZM*1G&>%U|26_x1p?S$W4?&I0w7+amQ zjV+`}-%f?H#2-WLpSnVk;mw{)1s}=SPOG=G|1b;uk+z-AY-h)$E$SS|Ah^Iq`Xz#o zdDrJ+r`>fY_1bAY)-Zi1&EHAU>|K1JYbUMWNwNF}4jV^g>rToqaU{{UL3(K?cF{JW zb+oD=@8k9V7F+i|yJ*HPE~S{&M*$0GkL1rc^5jM?j<*-ZHsvKhdM zKtvvmMLu+;Lfj0(BSO*sbtqe7Co6{9=tc-`;2)Db^}o2w@OO`CMBXBh-I1}6-QW?i zz_8tt;Px@H|MkjnwyJP7klJ898Rb6|B8;i~$3|Zc=(&lv>IiXKgKsZ&^smt~sy#d+ z=^Nwwd{TAUR>}4zYm0>o{k#pcInlBHj~OtP7k=ENLdeguyle*8XGgF_>TLX54A^pQ zp$%JjP;@f*T!MQHNd_TqE`;$dVEzdnxiG0>5Z{`ZN@wj;GB7wBPo=zS5F!Uo5)fi? z$8>huVd*zA&k_3=F$_9%aDRK8;d8qi+jtQG*;5sRIXq-1R~It?ZXw)Jl^=sCcy&A1 z3*oUH{0xnqBmjHc*^J~V!?)28T8DP+WOJH1yJ$WXNd_UCl(R>(W*22zF+!W3FY4pR zY}`dBtpefj-C`gKb4%R+O3t8k+}S zcg~RqTa+M=C^Zi>$OEtJogUU=B+k)DSJ*@>w5}i{`yStJ5QQ?K>p9?lE9+Af^L2BsjMScGx6)*5C4DQ+$+80cUaf?K+DKwHgVfN&48D6Eg`)?K7d!b{2rqXyGU2R6 z7+W9gX~Y${;E|Qo-r1Iv79}C0gBO}oHj^0t|70^;TCSKRWD<)Y2T!18uVG}ZB9z&4 z;hNB8sePE6g*y51$gWqR-}MpoL@TmtgIk5UbNT0L;u)Nh;k-yZgEy1$JaL>L38sLY zvPI#9&4lGV4I>68XUJq7CZ}4gM<3*g{zuypN^YMN%U;Rt zs;=-#~#aC`5 z2P++u8?OYIs7P+=Dxnn~AWG+%E2K@Xyh1U9Q@@JGpb2vrIa-Y8VWaZFns@bw4#@DFR{Nd_jAjr%mnif}$ZmV2B9q~R*Q-?K~b?KxhE3CGgIm7`yp5~qfiRu{xoM{tLOlHu+c7+t>alqS*F9GB{-s=2?*-EBzI{Ln04frml(`XL7RI4oWD4Lo%gD^`6T zUhoM3Lue6(Pt2d#gYz67&KOPgd2Yt|R_r_PN3;y21Kjeu}g|lbECg!?rto4+}a_nIwiFK6Wv4>xq9+i|B zm+x;o9E0abPORh0UvSg`_^OFPh^L$}-;?)+d0P-%E5i5T*3y<=S%b7YY!b}FIY`mm ziHbJ;>;o#cDBrr3VU)t}2zLXT7=$={MB&L7UIkEkU_RQUuA$+G<7+5u=qIGHm!c#Q z*uNAdI-XUM8`n9aIRh;DUco8fUlZY?Nkk%^9eE<1juJxGVe>Q@?q?r3fh@|PR% zt*ERVqk|mg+OO0V$&w609EzjT=4Yjvuc=_;XPXKkQrRx$vU$=u<^Vq}gRIv9E|x-K`C6%tQePxuW_JihSy2Vc8uWFv~x8@b;bn*d>&+(^{`E~e-vFA%@?B) z-T>4yH%C+NF}x#2i05R2tF)6w(=_Ol48q!+ppiXz8(&_ZdXx%fcIe*`Q=xyyjP7>Vy{0>*csJM6?P05_2hIM@XvhA}N4sF- zeYDHDF1WkXIVQFmjy&hO% z3Ugp=d5uxtYS?UU!uSxQ_)0C;3aOiGx>uRL?)YOz9oC31?zk3lv$kV$GCS3;$;$?% zb8flfjY0Nj$Dcd#BGx@T7>x#8wsp>0#?6dQ>+^Slsr8*wJ4dB$?QHAq-TNC=3?J;Y zzcW(8AsE%aPcKP_&q2L8FTyW-iwvKe ztqkE|UxrWiUIR0vABEvKE*>9y`m+q-AN?gSK35N58Nv+%M262JRKnHt`Wddthg+bhIwPJZ?HqrUH1qqsO272Ma~`pkIo*BcS|94s zHzJN2qGma*&A0Wz(;+rjNwakz?HtHYi}>+_1L^!gZ}vtiUL(uBr~tmL)|ov#08V6t zW5>aXNd_T2Vr5dI?~)WRZWG-Xp7HtC&*N-M3_qn{wtn8DOMGVsH8yEO@KAy2(IvA> zbW?5_n}=CH0=wuaKk}>XDL*o#7k7~#8E^Z>k6i3c6X6oJW?qNwiG9NCBVW6-51otD zA_9l`O3*HNPqQL|X2scfT34YCrFV{@llYWbXj(T#4Xjp<}xCCR7rW zgV!0m)<~T(^TZ0EkL?wJKQx-;OpG@VboP^5lnfRn3nPyp6u)pFmX8F9RN@$}JIHrK zX@k4) zuu4nikCG;%_2SkA)4F!~i{eDv6K$hk#XWMoHLdOCwz+}+lHNhEA71Id#P}>UZ0)*>~D+c(_wUnEJKq!OpS<5?XcFHzL!d(Ej)GBwb|H)7ea_T zAdVxk9W&p4DC!9xPyIN%T6#o66C~@}YH@3`Nt>ZtH*}D~urJ1=LjiDX( zy5rWieLu!MCVLx}lL!1q``S}G_z|?&wwcr7vH&N;hpl$QNL^Ig+*%Rnefrp=0fYMt<7kRPRFeH zaP^0_{pQzJ16Y{;u^Ij8=yv85EIVdv+th6F{vAi-K#OBF4!QnO5pNghJfgE%-8r+1 zNwsUGe=IVSd(ym~WaKDhGJDcx#KLj_GNXIZz}~nsXAeDQa&Ovzm>hIW*FL<0nLT~z zWM49;>>6Y;`_qp85ZXn^bR9q|29STG@fQHRv6+`4t{o}@U`$>6wWHu$x$qp zQ7#rsWN#Fky*#Wv5#@ z^^Jh+0KU)aU+VC`gJ80PcBaPg@|DV%r z`JHg1Uhd%IlAakZcgH(Lu#YAo6dLC zkKp5kH4BGk&ogTat=&R=&l@+dop5lY7~QoA_lUR3tz!Rv><;_#6zhGynf%|R$&nLL z+_UxX(>mELI3{^)n38d;2#?I-mv1J_#>aPZHxu9S`f(!Mg9QICY4G-C`(!MCXUy93 zZ!6+vBP3x18SeQRd}VCuB$Sp-``;+>+AI6)t6K1H7~)PKY#JENm~3y7;Xaw!Xzv+f zBOx~x`A*({ktiY!PE6#ET42e)+2-G8lUr=Ttu6m%nt>EIo3Me9+dJ}rvVp6=o517m zZ^SvJdTU7XI>CJ(YXgaKp9c@R^9>xk3ShOsV!@ZyF}V$9Hx>(n)q?L`WM9t0xci%}{Gy=lj(;_luhijMH#%xL-)!P5Z4v8suu{tvIkO?Wk~Xg- zvuh09T9;K7zVf^e_c#5Tp~?6)z3jC_ zdkw^o;!+6K9~|&-yfZl9;dsX{2*Fzu_>~`6IrxnVSk3MGDey85^PPPm2fvE~zp9iM zE%@(6z_pHpwDusGO$Ukp=fFYx?*>fQL;TMM_-)B}B^$q;j{nmIzjZsDhEMyyAN)6+ z|F;Hu;NLk6=pRbO$B_Q~PIQC+pMhVqxIg~~1B1V9_~0^7guF%FF?;MA(zzaZo45HQ zITXfQ;{3Pe`Dtw;ytdkZzjg3hYX42ooM$|;%FCuz8ARoE)P5qz{CA$uT<=9uh`!8lRc(Ww*{(xs?I5ZM*c@1TdNM0UkvqmTb zDL(P~NB_N$xRGyPHR#V_`yX~TVQS0&-UHOt4E~eONkpsTA=-HZ z?+CpXGS5Zl`oue3HuMJm4c(1$p=Z3I!Mdtmcd{o?X-XC{`22lBVpOz1`2+=+B zHs2i@SSl3z+`M<{gx;#C|F+ya`KC#jm%DxFRIbqdxx5pDqAKKhChw_G9WPJRx=`E} z?{tUI9fh8Y|G+=v1~iC z9Hz3dB?5y3O9u4L?EyVrI-p8r0y1|5)Ke)#X*m;LH8IX6pcGg4&LGQ8r4nTWS(4IQ zN^L=scTG9RdBNICyeG)GwIRKA`HDdjsvAO4~s%+Ctjj7mWFD zKqA`+5_^9rT?R?P58WT+XbZAA!p^T19Oor#aJy2dVqoxgkiEF*Jgu}HB!zrkDWGOm z1KO{2Ug_2cf-0;4J!?yQ{Xr(Q-#FtR3yP~$BQSH@6T$3#5me7+=>)28={)FpOXq3_ zIj$;|!6GCrE{qQ;?pb^Y-TPdSWAJk*UrhfFp%`q54@o$^ZjkVHxZovQT%uAPkU0HK z5Ps2+PD7G%l2arxu9>MSn zS+ByaN@qb*g=Bp7M%p?> zQTI#<%zUXd86?^}dIar!6eJFQS?S*(Nw)(eUU;o%kfWEY}PHsg$7F zvMS?zlJ`EPj_P%k7VHo>E~QrMj%P z+9Z`VP-?8&CMs*8)KazYs_X-$)~fx4P`)^+y{bE_x~s}klzOYSzsgdT2CH_6%7!bA zR_*ve7Ir2F=uB62y2|D#%~x$TUuK-ZnZ{vfazl*z(l~)HvBg(y;7j9(FVTMEbPffX zyDH&gfN!w3Qh%jXrNK%=l!hyfRvND~S!sI6U;m7guEIG=^Ob&3TBNj8X{FK{rA(!b zN?Vn7D24YZ9#A^0bWG`#(mAC|O4pPynti_+rC6mrO8JC%|5r$bMU_e_B`B3uN>sW} zsglwIO4XFAE7eqb3S`$m3>6jDRZ3E7pww8YiBb!tmP+p`eW27@=@X^)SbuzXbyn)C zl%mvIslQUH(qN?_O2d^#D~(s0>=X8X(^Z(RwA2LETB)=~DN|{q(pIG%N_&(JC>>Th z#>DHNaZai5oYEzwYfAiFsmyYt6swd+DW6gyrJ_nDl@g-;_0KqERhX!BpHd~I2b8KQ zRadI1^psK^rMgN<0fn6g0XmJ9nkcnUsvZ-xy{6JrN_CX#DkUj3P-?8y#FAbATBxw4 z(z{9@D9s1)c9ZNsB7X=J@8CqidD0Sg={{jcZo7$`9-zmqwj9P*O-nB+!M|Z&_z2o5 z>WqYdPAFYdiYpUnpHix?^odfk(j29oN`ESaFDZ7qGcdhLX}?lbxjR;5Eq=adTE9au?Fs-X0`(z{Ai!iuZz3kJ;|kW}U>O;DN&s%|UzqskU5tx)anD%+*BpS8UH z#XFaP@FFHw2wOfem=`2%FQ8OHskBm}(tSz~Dm|j~q*86Amw5jvg}ki7CQ2=oIw^&f zdV{3WgFsU0v8tV@G)HN^(&B)^&awdQl|ZS?29@zOL6PlNI;?a|>AccqCBBL%d1I7r zRVru+?T>fLsqk*4DoPJ2)ljOXR97iU=~bnsN^gV2TOWhOTU{$+{gWD|Xu<(XX-Y$t zMk=K%%~ASMX|d8TO1~;?Q3~_LRH?!NrNc^BKvHW{DX4WJkmM+;R7R06K#vIr!3GgZ4$ zX{XX&r9&Xed&4I@!;%jb6=89Z7_11A%2ZXVu2fU$S)~`0-cxF&^qEp8r4%Mv|9Y!1 z4J4HrsWcfR)tayAeo$Jbv`T3MNUZDtN#4V%J*IS?@4rYpFRL(AHOQO?B$-QsBwd2i z-AeZ>Jp_`1Yl0+iUDYNjy&6#1X&RvOw$gh_?LlI27zlO5e3`7YK(#xR4k_ILNu@&% z1Qf5t_e82;{lWTI0w{I88zjX&r1X+%n}Eb%3#C>{ZIwDHg_U}P#PT4Jls5JOUH>L( z!dXfgN|(?ODVzG{C^ zTBfv0X#>cf|B|xA>(o;%xlp27fkY*sMbSu@iRSI{?LZ#jy$vg-o znMbO2tkN{4SxWOklJ{qjWmB>rux^bW{h|GI0!0ZJ1Ipmev={Yq6pQd~2oZb~zh_9+#u8RWR5W;hsT zRUi~EJfu`Zsg_b*r6i?Sm6|HOt@NJK$4Z|C6n44>=%gqOP)bu8sx(q5U1^TeI*|Bd zo6>pJURDY{!3{?H#5XFwO^@h zsM09a&Qw~U+8>p63)%Hgg@-}nk6cd$b&Xfb2NG>vrG82)m3D)q`hS9?#V3@`s`dsb zEb7qHLBjk>g_Vkf#9%p<-K|tXwU4OmF{LL}`+~~qDZLd|d`Ia6kQDcs$~q~HP#UB3 ztlq*^6amY`HlwGS#KskVXAs~{}@80c?u zI?O-dhpKL))Q;6wo2;@PO2bq;QDsw=W`U%TWhz^xv;idJXh&^b|Bk8pl+tCT>q;@t z1fGdgDyURMDM6{M()~)60}4C;3eb66=^3Txl^Q5DR(emVl~Pxw6r}-5X-Y#a+4XOv z3de!OHCL4Gs}sl?D|J=stF%CA2}s<(4kR<|H>Dj)d+K2Q6ZH`l9#^`cbVcbVC=sKA zoV%V4=tZT*ASt*dNG!jr)JEx3rEnL;Zc6=>zEB#XG+b$d(iEj{l)hD3sI)|BlMt_e z+f=wu>5$S%rL#)cl=uNBX=iSbc;+^x1f}YluBOtnAbEY=^dpHKvLW= zr3oN$|6EPCKpG>m;omJsQC4QDn3NcEzDCJiw zu2f2?JV+W+86=f{LbXpTy;v9JOCj}D_zFlew^8b@Gyo(9M}Q>n7^SI7GnM9n#NJ|% zQ}@+uWjDxp+bDN*S@ zr3aNBQF;<2)e66)!k3krD78@f4@k1KQ&~r)?n=FsQk4cPjZhjR#OvQwptx%eND5i1 z30EquSK6esOKG3dDUjGJ@KSL8SP~?%N0eR$`RBjyt8lo|&q}A1u7IS1aY;cp)$s( z$@~LI3SOxR*C=gL+NQKm>5$SDkk~Wz0(<#D()L11w=>E5S4M@2Ajw=ysj1SZN&}UK zfTYrsK~l(crMXHAlvXIMuBYqYMhKB>|SYx(puGCuw>Uievn@Z z&I6L-@+lQlx?QO($nPel7eHdAsiu2F={==ZO6_09`X^?(K`1m*)nk>WDa}$^0FoR_ zly<9jztSt)F^0XjMA-m8@2Dkf=Z=9QpnvP$^3|FA5*HW^qkVmAj#Vl zBzga%+7Ff5`GobaqYAr&B=Z1}WFDc~F-lXFW-84CN#4au+f=(#>5$T&OtSu+RpCXY z=vM-RZC9nfAgT0MAQ_lLmBuMeQp$J*ZR1r z651c{d<_(X--E=}E0vC_w$Q6Vx>6vi^gWXW!rIAWwm8O9t?_7}NU8dUbD#Z;-o0WEhB=Zp^dM#*iv{GKB z0!k&6N-NzD5_>O!;Ay`9+e8r5S=AGiW`U&E--E=}3zb$Xtx?(vl0x=@B<~s3UQoIT z^4Gtp*8|geK$7`3kYv6~wf87hReD&dCP?x=r}U<3-&Xoa>Ep0sXQi%613_Xi9V7$u zN2T4WjcpR7E1+}_$RC(W4=X+D6V|`lKq({%RNao{7QQ;(X{q#~QX8d?Aj!+$7OZab zrmA+Z(g>w7N>f4p{ogsj>NfLIRj*W9ue3>N7f1>|461JPo>T25C4On1cp+LTuTp`g znE#?qfKUuR2@+Sor1YU`zfu|vl7gp$#7er-0;M07R)M69-vSCdCsln`>6(($EHKSq zy_7<3QAz-b!FxbbnSZJFaiwRJo>yvM$*zBmRmk7!6ob7%;)Ovf`(LEp37k#!A3y$c z?m73)oqcR$?1RDBhY+$1p}{C5N!F5YT4hV6uAMQBC33XblBg)8ED^FxC1r0>s&A8Q zQK`iL^*--&Uaso<|NWQyaOXbH`?H?U`JB%=_s(JkwTJqK`hzOg*RQ1;HJe%hX;)YD z<@&c8LEXEJ)D~(F^$~T5I!1j<{Xm_gexWW?kw8Dc;dm;UN~6kBRjBGzeMtA|2F6-a zIZVBcu{%_9|93a2gZ?0-)jX-mNF75>p{7y}q-7UET6Q^8S5oV#_o$ta_x|@2Pz!&- z}GL)xwKkmjqy)cVv75wazfL*-IEA+2x}q!V)@V~eQwsKeBG zs_0#QXDUE4-?08w_J|)FfwYlE%-D{p9jIHW+o^t#mc0+sJs!c-$Ek7DBvAx?h&QH# zTKIYD9cEllZKZZn`yefQl=_*ezfxBy>u&#mCEShn^|VW2Fay#G>p;3EO_|z)x{2yY z-41Dq0gT;CJwgrl6)~OywYkZV7M|lL8!u9esaL60)H~EBYAdxD(l!o4+Q#>8D)v9# z_>mdUQ@>Hh0Kae?q=idEI&Sit?y723O{xK;4Yz=_YzL;^Jb>%p?F`;Y4WRC&MnGEO z97xZD#nhWjJxqNAX~U->?ds1|qA<&5!I5qk;H@)siTzqQ2|Y@MfIQtQ*kRQM;(U z)B#AF`wG&sXPA1Px9`LKKNlm6+g>(p) zQ>!2yg^i4Dp>{C!6UGiuN16KF16=9Qq`&1)G}%C}&2Xz-UkQxkW&5u*FB~{kHc;k6yTtqFQR#2;{_aUwDJ4jdjpQ%esEk4B0 z*MfS4S~>*nYc(G+_!Ff2be6J)`mq=)0n)N9sRyXZ)J*CW6&mK1jTp6k8a=65)Hdo5 zYS?hU;e1Gs=WIwj{X8|Fsjo5i2KAPkiv5o_-ed56YNwklsrwl_NF8J9k5udkzca-l z?Mxb#N!6m7j^O&&g25Xh9o9+IJV^KRRpwhxy-RJPwn19rW5zzE4l^}!g2De%KQZ}F zD)gwoPjOT-q>YqjtUOhjsdX5uPjyzw``>O1-T~=}HH6B8bUfapK83X5FCiW3Z>aw= zU-^-K*_)^cl?O$%x#z&fh8*p=)GO3$)LYaVYCEJI{4Z1=wV1{QD&a9dwILZgc?CT0l95Nj5$7yMbrxFdr13wo-#)H zu|%pB)sq@Rt)q5O$6dMW-yaOtdD5@CDRnzFntG1fPW?n>KIPZakm^MBq{cmk^-uTi z9RzjIKV#BakSt6DpWH_^R=VyV(LKZVQMHfiW*JLguM0d zRZy#b3(_uZWyYPI^E2x|!-p4W?d#bOx+rY#XFAY8UmPn~MF9Hx4uSIrX)h zEU7;+c9!~usm5f#YMY9MbX3!*YE&cY*2!G|?q+Z(q$l7=#>PR~|4EemsX}c;{#2o+ zzCbNt>g$ZXNqtF0z9CEH`PG!8YEpHn29S0zhp}AhHYgL5+BEty-@{BDN{v#<`Zt=v zJgR`232BAzQ3t8ZRQ41<-$T@!)LCj!zMpS26wx8f2XzRiQL`XTozK`JYAI9SVr&hy zfvGzg`+zz^eGwr~Q$JI`LE44D(|!j-R6L}qrKuWJQ>qW7BX}?5%`HfF825jpJjNRn zs66T!YBn{WT0||QR#5Axjnocmk4V?QPZ>N!9jCsfPEqHmKd8%8Oo2aI@l-iT_q_&V zb*^5^uV?TEstu$AcQd4g`!Mw`>VE2B>M=;mKEv2-YQC?CvB;;f6w)H!Q&*@GQ~lIT zNZ%O7=lRAQR1uGB~>d%AyabfS7v|DhrU@JwLEie;lfnN`W2ge^L+Uc* z9f(|yL9>QhMe9k({KasF$=XPNv9lMTmDwW(rMNoqEv6)vJyP#dW|)Inbn)$#CH&X9IdKAx7MW6S(no5;{G+!?D2K5Q^9iWavItr2R7%ZfI zr~aY>FZe|gp~i+xpCVK`l|fC1v|CFcZEh7)-%-i>_b!unFnJI4F;kB+_9b^FMm-B@iI=DkA?@H<=DR@s&V2SfZ3F9H*kinrMwO*1LfS|z#oW$wf^>qM zpe|9y0zWl{Do&MxvJE*mG8oIGYD3wEq&D*vF*^D*dQy);%?!ynmazgzyETJ)9@6f= z3~7ngOkGQDp|(?dpiHbkxEOxxQuHfjEcB~RgS6qYR28Z^RiA1^wS%-{3sr z_F2gF?>`9Yo;<=LW0-LQHI;gXav&|clG;jr2x%9NK)NGeP?7J+AF1=yZ&dIlzmaN? z-bB=6tUaWSbcJ+3dqdh>f9gI+yE;rI-~XM?=0!V9~4Qb5_A+33_ zWK_NZY1L~XEwYQLd#MA|5$a1w%U-17UiM?fsalY>mgNcSUlRtKQ|+h@R3Atixfjw7 zj%4a6Y66uMzQC#qWL`q-Bd!wV0YkHF1Ugk2jh#*pBKz^?8S3a zKA{f0!u9WS1htXBsF)>wH6B5DP-hdM-k zOP!-GQ)x^6ZdIY`t7QFa$zU#Z2Q`oyN{yxpsJE%TkS;WbARV`3)N!VsguMH|Gfcj~ zulm)5A+5R?VsdL!Sb*9jZ~uQQ;nz`Dwpa4X@$KQ z>qk9A4WS-|WQt<_o4{Zm^$euFe$mSqZ!BZ#3Thp-k=g-i*?o|n2gjNEEpmU9E z4TFC`TG)QwS6N7pVmeiws!cVbno>EC)^{JIC-0-wnAg$1CeLNYCDbNJ8{SIorS?(B zAg$#)NcZ?0Q-7f@Q-Nh(&3OOg(@3VuL0Vx;NPC@2b!X~W>Sai~x|CW=ZJ<7)_PcV| zzeAu-pKqA_J#~S)Nc{!re#S5N8&0OuAnkr7Nb}WaY9p%Ua;|?jGMEc#;qH(Y9>~=D zsG-!O)M!Y{PN806>MPWnROBsk1GSm@2+|7ALV6(nqGI0gQ!7)oskV?FlJ-|DM#yc{F6tnp75)zCo`hETN`W*rlWIlXOx;NpK)RdD zy%@g#`!T5d`6=}^^&NE@(&jEgdYJ5$e%UZpgepOmhrF&rTDGyI>iXA=8QW6rsjiR~ z?nMn_>PTt~HG!H+Jwq*kw7#t?(Y_ArJ_J=qnfx1NuJVhNf^@XXQB|oLR2xVe8OYdu z)JR_uW0X&00;ENzK{`k;Fm*n)lv+l;4Qbg;ke2t7+Lh0jy*Z~6O~ zOr=p}sVY=;>Uv1)>j~92{0LRz>xq=g4E^*(AS^(ZwO(y~*imo!z@zgL*?P3kRb z1GSm@2+|7AK{~*fsqou=Y89$3q@BJ2((!ExdG~)g4CYb;A#G$bV^34hQ}d`Lkd{~p zX>%Kyx`o<9eH0-NL0b50NDH51>Mzt~D)5fKC-IP$EkV_0YCWnc)xs0*|88QiBXtL) z6^?>*fb*!COkF{(r}jfSzz3&D4Ye22vj25s?)rC<$rq@Ll)2vD;~g#zk*4sU}owsvUI;)Xbd=y%_694T5x+hBDtc zrcR=!yNbv~XBLBVAuYTF(nj85>KbY@wT=1^(z1sjE&E@lo}?~N7dLVJGdKH%N%!HHjq0Y?e%_08$L*VMV+9|Kw9DwW5yQ0Y%G;X z6@|20HB_?xwPvs%q!m60X%`-$#!-`~ry;HIW$G*HB30ylzrGSw1;|_ft_QW6&eR}g ze2{vSsne*X)E4I3PJPbQ3slxtzqOnQIhlHi+Ccq5+1vavDh}xwrBM~BDpVb+K9vp0 z4&(jr-Jnj8!PFEl*)(3IwoxBJdYHb1v(;#hbCiNnMN=c z(h7fv^g#SYg?9R}II0*`lBxn}8#z0%{^@bQ4MA03CXc0NGxc}d&zBtZCI4ZmmX-f> zRCPBso;novQ-7r*C1d?yQ>tpBVKl(Rj5iukC6fGn4<`E>N4-d`r4CWQQmH9^*+wc^ z|7sWWgMX&_`XtTQiBi52%lL{b>#GY@3uCICZc61)-KhtuCm{I`s<5AV3_8?zwfzdu zQ)V4MmQ0nSYEn(8o2c8U5!Cny`3$vydV|_P?V%1+-&2Kk{gLU@-0$iGRG@>Ox++(N z^>1z`KlsYczUFrJwX%z^^<8}x-s-EuZNAP?&Aa=tho}yH{MaLXeSO>y()F*-U4F3W zAYc9O_cfe)ntFw*|Dd1muSa}U8RBc@XkVFQe5H-`^~hMXuP4mY<9rpH=&LhzV3Hpz zI@wo^JYT)0_*$0l>(bM{a;N&LKf_o5XFNrWr=RtM3#c{JC)9_}`S~7r-q)rVeceCT z*Zc*(-lFzUg_ONe@?rl?qoPaE5NaYdm)bxbrhcX5hca|5Lxw-~aFTm#T_vbBp7?!B zDhubI7i`F2Q>rD^hH6h?u6kuL8$I=)dQ*2%4?sA(v71;ljCOd&8mtQ4NLM2R5Lt0ez|3i1* zWAww3xLRzLXJ`3#ZiNzswxi1fo9kY6*}{|TWitc`xiFn&kG zC=wkhh9TU1P2@U6R$%G6TB?QQNso?nLgZ|v=twU_vTH^~@GU2VQn2`5t!M@!Sy%wC zMr1`;fK~ZwL{^4<&7vcR5t)8dbmRv_mf6OLx}l_Yp$V6!~v@1#%_V+gtHAwN zKT&6?3)DplaO;a$Xi#an0U3VFz~pzgEJL=XVaq6vubP_17-p%Ln$FY=#xf}xQ7xOr z7^a~SmXp+S-(qR9G=(<@SSttPYb961sF9H5Fy*&Vjq-TL8~0(sNq04yYLE3r^Yw!? z^?pb?9&bEMMM7v_gX0*SO+8P&PQ6L3hP092s3a^=+FU6}Yc5CCqOyENj5a=v9O_Q0 zFEyT;Ocg-dh27LCrkxi1y|HgI`kLQ2&Lr!g#%h!C@;xHc z{fIMWwpDCRqnoTB>_FozCq36HZdTPRbZ)NowB=uF%XhZ=ndaSVB3-Ot=-NxJv-NiC zo`_r@Z1<*C)dky?-Iy%-D!FT|;>Pwcb`Zktm3zH14BW!w!eQg9N`?UQ1~JS9FP1{d zwM$doD-J%0!X`dYFv_`-gQ6M^Nrk2{0blWv6!OVkoW|s0jt{30ON2_eDng|)HJz~x zs(~lWxW)`NhqUVM)ZNshknFK($eTIMw;s}l-=nrd+N}>6`-J+M`c5QQ+<4;(gBA|3 zRv3n~nqrKVq{>3tg&U}DRDWs|l}ClpW)ZjD6uIJPHI)$1L6?cFlG9Svkdm`fV{%ri z+E8*XYJGA(Rm3wMGun@JV@%FZH=nbpr*)$dcsQ zOk;OL)!o!bnJPz1Qx`#6-%h4}N!ggA+C~kkKHl_tg?mCZk=Zt$hia+twT7#G_^OSZ zpa3HVPd&#}VQkBM)N@Q@a*nCw9Me>}rbrAomvT@vIUUkuIqfwjjjE(enktRxe3bLE zBA)SvoS&-Ukd)B#Qzt_v=2- zO$;G63^QVs@@ZsIZ6VEg8)Ncugj>WIPtAw4`-`Y$)Cy`HwUOH43i}^#>|yXzO1?v( zRUfCmrA|TG8TtN&u1E>Eh0+pox2Gyam7}UsHDa;UXvXUpyq;Rn)?AtEiG&MU~tts(ypCTk_eCsw||b=~Q*9Hr0q~s*;<_ z8yUQb>P&T`ZTb9WA+$R2`vkY8ZNPm32WTHfF0V^m_JIrLrhl=rvUq zdR0qG7J7}fr)0_3n5>=JhOB?yXdzYwPh1AFncR!PevHZ6O3gTuu@@OzAThaxN^@R# z(yDv)qqUR+mR)-VQcWWrE1^7A;dvI%tC20(lAADz1oWbE^HWyMn37Q+TSRfXGkt>f zV0=`>2~V`9q(*(B5k+U|MC)a}_Ox3wbCMMof9|DqBxlQdR@N`$=7;9PTAq-%4pr4zCV+RjP*E(rK^(gH5Ow)QwaQ)rqgaRx3_{$lh3RKoq_j#W(||~6W4Lgm60)wd*3vS_U;695)ND8!11S@)Wg;Y z^FF8Guyspd+cf9P!&cS6>gi7Ch;?(|z3EQ(BUbsi6ug69jl=f&bmyrfRwZ+rv+#&j zxn3`DSuRI z$8GrCj~T|{KR!d=OYU?Vlr8yoqHg8peUy{;VXM5)atoGa>_dj!yxfe;R_mlwxp{3e z(sT13$jHjg8=oN`PPDDJ`3I?F!scN;r5-6Tx^buE@lz!`0+OkH-nrboA9L~wkrfMz zTLB8T$@@l%NRFJmVbX@YEkU*%X~wHIdBR*=mRgOwbY*z8g|2?pNI=KkIz*!`XIzcJbsQ<1Ne( zupZ|xipZLYK}V61X*qctGN!{PZ}&#u-%)qZBi>PUCqhm^iN~c>-nlD!P~@m3k8g&K z6yEOjMyisB*NPB(*DK>*9LKfT$TiQ((eKwLuUAIr3Hy`BH$_JZ>|?nFt245|yhGT> zHU-TviH2olweR`Q!`G?c7CSd@RL0Vz=$y=Rq5wE#KH7Pc3vx)wMhkrNvv9OUmUcUR-e%$+J`*DB7CXfFVr8?#(9BiBS*~#@+`x$9F z;aKu`x#{rwiEKs=_H(cgxr6487p7q{M;(Ivk!AhkTquW2I+;^&v*}LRysa{w>Yzk! z{<4e|>?yk4w%(PTf<(C(<{+3ZpJTK)zc?9(QxDy{+&1r0PLq>EQ*he5bw~}(B+s~= z*pVx-!;boB&Ra4LCxbJP(v0oQvA#t(9_ z!7{TwM;cm+wJawe`;K8Ol05MSj7rY>X(t*_m4CVUy)s6&t+yZFq0IU1o80^j?u@`3 z%+0trC+|?b{W)9C*e4sw2;}#$bDJDX9#<9h4ct;_4;=S>@b@-2!G#ljJ{=$Gs`d7TEjS7uYvBXTG*lBVXdsC9laz8r|3!w#ctx_`0^^HxFCg ze%ubT-tN)O!p5+;oN-$)7{7;ypY2r8EzUgYc&A!^yW*Yh-j?4zrTv!Uc89$2_F(LO ze!Fm!eaSbyFWV!rUHGz`TKR3W+o* zi8feWWJ=4_nINB$=3=BrBOnXEeB#`;-fm3pyq}|H@Bf*}723$?cL?W9aGIX5YD5kU z|Il4Fd!w(NChSfg-wkkAy7tw7zjpb}#d+7+O)Zo&IP2Oo_%yoqFU!3g@e)|KWH+U7 zZr%^=^KTC0K<4G-pc5xfSfwJThaZ+Ev#?8@^02}b%2FWj4W+^~dBwSsjRst#yQn$K zUHGIEjorl)Ln0fQoY7U$tfc706Kxx7&{kYu*%WF>Apr_neD5aE13F{a;67*t^`Xf^z1s$d#8?IOxii2-YZFKmBUm)%$0E zDirSh%kS}8?XlNk8MO3PYvnZ4D|oJV@o~q%uk4>Q3kz&pIWXhgX*E8g7x`;;#qW_@ z69!R+N{UST?dr~7+e^Kij6!;$gD>vLW4v`_a`U=n3}%OLm^!yFXlLf&#KGwh$;sR5 zw$naut9zPMbyqW#sJFQjMtnjy=_f8ZgWYRUr@W)}_UB?bpNu}qs^YEWIr+nIt@ztA zf3gbC?AW&BcPCF+jy^>#4Okhb$@1hc4Y|pivJ(bkbXq0P-!iaGldVIw7_#__#qc-U zVC`w&k^wgnGMMjlQ8T7N+**2c7at-%`+K^q=`T zVO%p(WU=daqm>)knvi2X?M~W>n(0=kX#JYIkgbo3Lm>9mt|i3{(j2& zw={*Ze_%(kkjSj&)lz{QSx+zIRHxUVmEs=ljJ^=+-pU9H9)zt{@*C&^=zF$?5KjFeCt;9e|xZS%Ia8n-#z zG2brRG0!g5<_3g^;5HH0%!mn zzOW7^lV8<865shVay1nVt(TeX4@7%hEM>ZsMGaUTa9dEAD2Jk8kXaZ)cUkK-i?g}I&FaqKQ&!u6b;_x5 z+DbJ)a2lPqs+$#^ey6RHNwKHoaJ9=k`ASYf@I`0BX}lL+aN0^)v--3Z7cg&iHl4K| zEA-r|j-Zbk!HkkQOC%`UN)?2tT6^A2mq4|t=J+Rw|jy_iJ1SToKd zTCs+6OPrl$KJAQ-vs2AYjuU6Ms(DnV3?5t2wtdFiIE;+}c$Y72G)4txmXUh7h-1au zt<4o{+Qr*7%?c;IRvV#>pG#}rMyA=rnz8Fi!wx#r6YL6RS!YFpUES>A98IuqF>5$A z67B0twZI#eT6iX=quo(~>$>0^UWn~{=kY}Q@$zl(Axi^1gAexq&!D^eK77A1HV_ks z#ZG<@cC%A7$*$2@J~=%nc^)1-tnbi!?jAO@@6bVy-(ySSgqU2w117S9qgk`n_d z)lm8eY#(-pCE3?qHzRBq_v7i7zIVV7BQH>~MjaHvqA1^`3A!~JQv&IA5uJs|MCT}) zZIpm-He7Tw3>%^i7HEU=eT#eX3=T!Y!vhBzQv1;^Id6exBp4*mfoej*vt+vCe~=|~@H zRIxH-^nXVDM?5*QRjuN3ILl(Hrs0YIHL{u&FVjOlQpFFvI(>@RWzt7u<8euTu>Y{T z?=>1&Vaf73B8&0tROmcc#4a0&LGLOQ!KF8CzdC7H{2$){-u#J3tHLtgl zVm?Rs3NrkKXUsNi6v2s`jAzU~Y@`F_@l2HoERWH}-Lo(7q->;`UNiycrkv!%Ox!%A z&qLC>Y8cyRfp%8K7g2R{R8kwyv{$n5>6TZ_G~^rZovehfs-nH!NSTZ*PvIGJ02}WC zt7YSBY=qIoWo%S9gN>NK@FfS47I?6S1Fl z@RV#c$Hv#dA=zk;jq=#DqIkyKhK+teS3G0;W8-DudD$3-jnoqOfhas zU}F;Su>3ek?0Rfn!PZGh`V<>OQgJHb8T$h^-UQ~##_!lj!spMIWFxLVzQcu$K6q9y zj*Y4~wl7siN-1o7kLZ_pHm-_|v^DrrAE&-N0*3tP(mXT167t3zkY5ZcnTC&w@r?Nf z`I-O?W#cq9x&WPI;}2{M0`9@HLhN;haZ3q&x#%BGt=f3A5}Hp%!Z>6bgJL z%W`FX4%f--Y6S$8AI2TJ|+lzC|lBBayNinN~@uvDo+k z*eazmqYK4F71vh#naOV9%gB2P&xl*PBo_KaJkjPD?5fSd8h|zzneiQDuwIrCL8eZU zF|8IFmG36WBVb@A8%xYm5y{sPDUTq}!+6Htj*W@HQ&Ol&3oL%}a3?>$c8QHxYc+(e z9=OIB)f=Fh@u)6xD!u2+~e2ZD{dR7QT={1KBfxxMULMi$aTNutbPl&F3b9J z0co+Fv9$#87x0Yjg^i=YVLaX4Jjw3(a@)d}lV;+>Qn!rLkI4Rml$ZJVC-6I-Mh!U! zPO}1Eeg%;;W@v@fAUhRb4yENOmyEJNX*`YE_oF}6agB(50LVh92A-W|0#?R_N**$~ zeZsLb#O* z3`5?5xXjAqdrMh4e0gr`%bajjXX&wwnuIY{%=>tYVnSQI%g)?PkqX$M^z0 zS{s$Ci#=od6R5q1+ZEi-p(}w$)1@z|sZQ@SyHq5qdq&!gIB5#JKAJ{XjME)fOn+QY zV(v!Dli2@9@r-#G8w-Hv@vQy?HU=SQ9b}6gjg9SyZp72*@-(*Qc-5tQyA)f1;3*^* z;#qsn4cK}Dr5is7;9)NfX-3)Md{oKNG;`d$K@MhWFDI*%T|9#8p`7kWy=MQ6irKg& zlSd7GF;1Yi;5`owFz&Y!Cgluoib(rUT~kNYt_C9Zzw`nN0VYYz)qQWxXx6sf^lA9j8bYjJ3X=@y0U-Uv(LPOGPypF&TP$CG3sxl@ROHU zcEzmqKX#=`obHNLSS#Y?(&_51ztMAOSXACSqO<;6PZvjJo)De+UwXR7%NvnitccF6 z7lG(boK4UU%dx$9O;-2N#tb)Pg|CDY$DT0^56Rux%dMk?U;dT%q5_`lEkc~sV=$a;0@`nNv(9+mq*bjAOcxr@Br z^EzzS(cN=9{LkS}ecaDm7kkH(`=1$&&@K#q$VNYke~B_}oG&ZbwYtu&i~C#Y+f9LL z=~yaeV^yDuXZijE@YesPK;sXQwiSU*cqX>OMoyseVk~{%Vf%>0CL-28P*HxyKD`2N zvz%V(c7;}*!1j2`J9eW}pya|7+#O=OKb{pEdl!wiC@PO;=tOYvV53i>!hH?;|_s^v%Af6rq^!$3v(5t;SK`HnNWqFt_`q#eNKCwStz zIBdvc_-X!fEf778$WIb=cd1DrQFiGs1pchx9Ia?qZzS&|lVl8H16eW#NzcM@fed-O zd4pW_u!ow!0x! z+$m+IW!U$3lDFaIN7OTN%t|s8N$F?>&+;ScBUE2PHL+O*&)_}vj1Hzd79Fv9lN+jU zbkxwj*u2ZRsR}-ZD|GIuf)BB3IZLb9H=1`jKUJ}7nbVw7Rq?XHX;;;5cJsi7xVMzC z`m?GG)npVNk7qM?Y%dj&p_-09X9o2}M7R?U7onA!sl^2P;O z@CfyD%GAar>gTlAmq%;c^|1A7ZMy|teyEM(*Uu?c$F5_(@8s06E1N@|2kO|Fkxy~p z|vxi|C;fAzw zUr#~!?bHb+@v=SbR2p7ZmcCrtc{9t->e9=e5SS7)d)dzgQClyswy@UL%d0Ky)fPr= zQ&W)Z^CF)Y!HZjIFRio}D*d{&*=y#EKrv@UJv*^w54+z0YsTis?EzcOz>E|$Bt1%T zdnB)~75TcDyuO{fu%x_RDtRhRURRc0UIwqIsH9XB-?1Yu7ag~nW;axUPImJ;nWmlW z=5;d7>tvelayRW=H|&cb?j>4wsubgw_@UVqZP{-k^TN%#7b?)4}AYSB!u zXr@;*(<_?k70vXDW_m?4uNKYnie`C5v%I2NUePSCXqHzr%PpEM9d7IuZR{0o>=kY7 z6>aPlZR{0oEb~h)8AiZ#+FoZju6e+UA8sVzTNYPJSGMQdUs;!|K-PTd9sAmZ82p;} zb#|Rd&yr6W;q;8S1ygRxs1v?Y8qTVY*ZKBA^Sp_&cvIm%tkA>WZK#dk@n<7x^X=En zE#@_WAMJ}#tszH#!u*8j9EMjD&UYyEu=7*{yL7MnQf5qkVpbpyeGg}rf6AyNRi8Hh z8J%lS2>vrFjr=ouu=wTTh&mS<;P&q79@sI14QXh;ZQmEiW~ITc;ppxBgbfMN+wUg+ zoE*Kqqv)z)(c1-RE_(a@)b~nq+nL$WZdTz7_lSI9y=DjMp+WnYEl21_`<(>Ye#bf8 z&@RWG*my}uI zzV0jYTN$TIBkcJC9=j%3uO3@~10!FfkQFgurZXXvShFBq6%HaA*}Srt+|jIP6$l zOA9xr_EB?5KnjmbnJ3Hmyp&H<-1y9*k#~zq!j)osi%Z1Y|L9th{8PZa-IY2%P5FE5 z&Ek8D|1EaSNQSzyR~2F(@y^@%c7+xRPSeJAQsmKCzmfU&Gv<6Vb|~|lNO`MBRO+-6 z%Sv3`)LrG*&?Gj~(ClkBybs?;c>+t#es|~JNV%MX=zB%KcX#=<;zzN|NIzQK{;jy# z*ZH8aUBC5@K^cx8gYSoAe)&gZXM!G$*HR9rNV*=CwNKdYQ9;J2qvEt|Vy8x(f%loW z;%pmh;bksnzgs=dYi!CnhnF2iXBWeZoWPR!e(JQ6xcbUO)X9h$9q`sBZ+3=`aX;Hh zk#;Lh^EUef^RldC_H%)^tq8VX2_6dK<%Q5&?iBkjG%Y6n5o3l?w({9PgDUgwX)!Zn z60Zg-oAd3NF>C$MapaNE`F`jMq1jiSgKUcc>Se>uhVrh9_(})g|>a`IYylXksSX<1XHZ7(RTdzAJ)N)MFI_-1y)idN_uZ=%Uz8QjcH+Ze#8PqOC8f!P^4 z;GAe?SG)rshI!eHP{p7gQQNp5H#47_8v=OQ5cob|4eK%AK5owln%&$SA^+QEwowa9 zP_5fA$E6l`y|&z=Io#>r9G~D!HP^a>yViW)#QFNZy!5gUna4~_>-qLE^J|20ZrFxt zg{H9mfZ5f4Y>^pfJ)}J{aGILS@h;OljY9V`Yh2ur@GR52{2xJm@q^{wKm#%MYjMSiCr~@5EX&mSQ1F_%#9BpCmq?gqKfK#uhOny`}fwS`hNTg=iZenz-}*H8e$T zniq$c$KqvI;?qfZ*^}}+?vejjDeu5bNsm(6qtxJ0Y7s_ehW}Sp?i`kiTu3!8q!JfW zh2Vdc=iLJCO{ALWZK=)OF7MtY&3AV$I)hY>ZKrXzT|RPkShB4d`$pN>7@fX4I(;!Z z6XUUUDgmR@*Zwi-vt+#NN%mOEd536}!1L;OuvI=il}zhye?tp59tdZ&Wi?PKc?f z#yugVE7+Evn7!psGH5N)^^c&8eBxjuy09F< zzvsgw2>ag-%EUWn`CR1cBN8<#*|O$me_)zD(TltoyvR|;%OSj@b?45m#Dj@0-0{Vw z(X9;cY}}pmc2Fw+N3E+(vyZ*nTy0uUMdkw-xjwS5kr=$X)4Y#P^FBJw`{*G=hum4- zM`wATs9E0U>P~p=yA8+0Yuq;E78ySxbgNzStw8W8vq8pu`+55p+v6|xI=PK`& zlc3pCdm#sak87&$Y&ZEs=IHO%HXAS7aPh4hdeRsnZ`5y+a0?<7FoWI!#dZ+Kjc?;<${0x!GE5EqnTM7w`x~goo}}&khe(h zgm&ZOBa{jlA(k*wLJQ7UM9^;0-_t*Gplpl&|56gSV2Ixll|LdC;oEew;jhNStZ65sN}Gpf^>fx$`G&7|nvtej-Gh!mKT zB72HgygOo5wlz3Gt8(l6TV)CVs4T&5-3vDxy`;hfufhb39LCQ7nG4$}?vGuUekx}{ zJ3E-_|FA_-j2Z4n+-VoO*Lk;{-6(SP8~(*Gti{Uy?MT%gis;bQ=HJ4btqF3PPOx9F z|CX{bI0*;Uo)lUV`diB0m;*6LnHS!UGs>T-&fuFcOQSjw>^w6(GsTt$JW3-)q6Zdt zs>mS?c{!x9f5{;YdO4&~rM$0kPrK07Mk7XO!G_8>4tDLnzP6);XTPsF;+pN>>M*ct zwfo|W6ui2B7;Vh(e>Q1g4MX-@-Ru$b)~jvcehxFv|M3ui#(D2tbgmdteJ>{StM*X& zx>-Jt!t2K1&Y--?{>$r|;djFFDm}w1o03d2C8s)OdwhyuiWA(55!QMWbdP&ntrj2G;w1Bb{G_6HlKI;_$^3wu0pD4doAT%#^N&Q|p}sa- z?^`?s$jvtdpK)cbiIur#tH9%f?H>Y*EG(0YtfdxWd+gOgY`q?{KL%HIbkF~B6pUDc ztN|zMdv&0HI5BaD{r4RF`4ek!*v)X->C(Y27HO8KN5wX>ae{th?v*zMTk) zVZZzzH<3?By4rC`))1_=Nu}T^_DnaYdnpdB;#<@*xUW7IJ1!0{FDEZg#_hFUt*^<_ z+dfuO^7Pg`z46XQuPLEbvpd?Q%1cRW1TOe8SRwh*PkGpeg;m>1bFS}b*YEBBe1j45 zl!3o0SZThj5qyOFWZS5WPn;x!T^ZjJ#EssIDKDq^p_fzE$Tf6L%1`;QWGG6!Zy7;<6_TpUrW-;3l(mgSyKKd4o9g?J z5xjaH4zxcGEVbOz&OQ?QCgh%ZY!gTR>Iso+cj;#TX?_=QPX+sPd)$M;=$uif1Wt&F zaqd(%g3)1_=0-4TdfQgK5&R{^9Y+jglAUzPbg$WNq@Wt>4;cygdvEraW%DRc~Lm)O?zU~U9SSdY%an|5rqB{8C zpzm#VM^yFtZFXj(@Jz2nuvo|%9hn|1Vtr{W3#LpB7R8_TnjQ>mtgRi3jRx@;dA%B&CdSk35yluvF#N6aV=ud1^If4C!BmtEhyD{x3?&ES zCDAI<4EsBzN3$N7zjw;?Jb(;xF!s1J%nlt6F9?}qongK0dZBrN?4qb{S#P_FS;yJm z+pdnnJB+cj``A@uhkYBwLK+)bv8HYxd!c>JpA@+msG8)Qe#WX3x+&>+FtEcp`&gi| zlRdyrH;+602jI6=Ryd;v;FnMOIhzOA_eR{mxFp}gwcS4zr@Dgerf%#%xB{rYhHh|U z3AjWwb9FtWG5G;-T zkpM->SRTQ5bXf2%}Eir=nFLa&Tu!*%7KTL};mtV7Ji=X}hCxiI$2Va{@QH%7t{OM?xr!5{IB1SEr!sU0r~5jQ)V+`?dIs*ZA3iCay+7*{)u}$VB7^ zeQjd{sFGU_DU83!OiicePz$J~)Cx*|u~}=`OrcVDvg;qzk-J0ufojY@_m2bWUm(;V zcHPTZoT+Jym8H^|n!#8mRg0-vjLFbz8!{>-@Wk!494!rIQ*9tgw%ozh)Lf=^W~zLi zuBkn!UQETV8&VTaDm-L-b>CGuA&fGz|N3{jD?;(cL-<2M14oK$B@csnMOazEfF#92P?b%f0!EPCmRvQ#!-`*I+HPndXcG17<-*s z!PIx%81_Hj*u>;*O#Ya$PpK2sf2p4!-So?l)0Z7N_ zJXNfWA8Srcf^_yg18Ld0knYk#Px!N6uP}Kfli#M+Gj%&-yQz0`ufnv~B^WD3m1k;o#%fbNs9u!(qK>vPoLW#8?Q8I51~*Y# zsa=qE=2ONFQSw_hT1zrjnW{!Lp_==`f1?Cy)%W^A;{j?6HGz7LnoI4X_EMifTJz_O z9j7k2a@Rlkj~BH6C8$zVHL50cJ9Q^Dgc?D;M!i98rnZ&m`nMZF?dxYuK1_YV)I!Rt z;Lq{&{F2w6L`oO+kqL~Vo6 zhWtg>FBtrqI#2yZ8R`B$RfDvVnp8ukwuH3%xlHX$-9hz+Q!PZne>K5u&su$Id8bm!vji4T<#!-_*5krQ5I)k&Qxzs}HHR=s&4fQUyjoL+h zLLH#KtcdpY=$vHm4D}bJM=_?7pRXjO2cis>L1j|)sD@Mvs0n^R1<}P}`}eSlPi3oQ{cFSE&5#!EK@DT-NNNlzmQb%#Z$r{mtbgw@_&)Ukq*WI(c8dB1!ksm4-L0yAzB*KQ zsvk9hT1R~=lJ(CtPJ`aCLYQBe6#)cP@l-OE2H_v_Rbi|;bsePL&tWW=x(&iVl)bAO z+SiOvBcfVQ9fhtiEh;W5c-3oE&qG392?+MK$Jnn-P+ zzJhd*Pf)=uKNbsl>t7iLD^OWf18M-IdpDTcLmi|pQzh&9CF)Zxs16abJJqGWU*rrG zcby+=1L-K-1L@ukqDE4qsC;S~HO~{)zn2)?4(Z-~L51;|p~iBly^wa{1Y@Tl?aVpK zZ0N^=R2-!B6_=Q-fAK~dlglx=8e=u7ET*=Avn~3Eb?i5LlraqBCV-`)HLdK zY6EqUl0Vg<4ch@<@^|+%*3Ol?{tadDdFoB-DD@Xr$?~hYo!UjUwEfhVsFrO2W za{ar&VB3(NaXa+~)iuUXEu`dc{p&vAzew>e%mUZ%dGx+eLZ83Ad&bCi5{1Tp#iZ>kbnLLH>eQ{__pYFbibs9BIs zxMhr;pydCU&@RaLQ&bh9h_VHPdDJE@XPKJJ&waZ>QUZT1=Me_~OQrE6 z*(y*4WQ;fJQcaoKmAa1_PtBqhQ*TpyMY8^x#uWzB&?)V8SE?_hT^K|SVd^C6J*p8t z8N~)_?!wPVcTk@~THhC?(Y~^f!84E+{)4etd{(L5stjprW5&8N)}OJ_)JCR$$k=IL z5u*-1M$`(ML)u6ust+}Uia^@wJnC6$Df1npPEwbs1bqINi1QDFRL-TS9@U+CidsnR zpiWaEd^D%suSjM6Uv-^-OjTtZ#?OUA#VBJ|qh?!|0z{;FvDl;>QsDw4`k@r7OqLjB zR=P<)ta+`l5O9iH;tOcP5+n*i?c<~H}RJvRSP~lbDQ9WG8(dGZZ^|kqyIzW&xkik zgm#;0nQ4uw&-AwGN08dlgthB20!o_;Qni+vT0j~9x5i?pX{+gDkcvrL``$ERI%~RM zx&dRR@>Y2CY_PVR^A=REwI)Wnmeyz5Z#oE4fj8njZ^l*-l$jEyY7?)e(k(I7X9&-K zjTW0t%T2AOm8K_59j0}r4W<`Nub8%ibaJ1OlGw$9*FB_iy$_uoI%-gbO+j;%WwEt7 zkhB%nSXF7PjPkCx)@7~R+8;c5B|Kx1tKvy(1*tMzK292E1?V7OSvy88HTo77vd;#r zZ#jnY;@D!?utLNZlpp0vjdq76C9q>%2WVWQ zb-J|Mp|qi^QBjDl*!J`T+pr=vWjlE$hsL_B&im=+F!*ANEXdFkT*u*fkYHxGpOgt7MFZ}*1zGiCtAQwY~p zn7Z!0a7QLI>K!Pd6r0w`Vq*;hc42n+FxZ1V9^Ai<}Rpp&+DmPV{YDql*g5XYz z51Jk_Jql8_I1^Sy?>4<-`oMGuq{^Hy@d;hpoJ+G*&Uld$>mc&p#e!uvGlrzB?WR|q z?oDfh);_U@qw$FrWun1nN})T{4J*r1GDu`Gnqed}{h?@ysoq3)C@bBei0)8CA0t|6 z>Hz6P=(CEk$!F!UO~s;?E^#LlDvI&(p)lc?tyk=TA&#az-F4H8hQrC+qJ>q{J&|XM z1@_`tvnq|Sb_?-R2sjFt_I0^ ztuv|SBT6gJ5T-R%+MKZYR?{L|nGt^=;GR8;JsXk2vx++LohcNa6%T2!_Jp`w z5gjm%gOu(ZHFdo6K-L`5iA}T6Ql!l`6@gSB|AkrBQd705#?)YHGPQtIg~#)7d|oK| zBo+9a6TWC-Tryd^Ox>n_(|~CZq=O8b#%%pMOUd9w7K0y5r%V&3Gp4^x=Ri8hl!@Ms zEecQTAXzI+D@@OT;(V+x2s(i}yO&MdOxsPnK)U?5DWvW|1A zzHkDfZp7a>%IAGdq`p`s|sw|v1 zuVRi^J8Jp~q-ya)RD=)ZC!gXHdX?jXDK|f>F?=s%RN)%a0$XoM8W)@D zOpT^{O`H|1!*QWS(JGJ*vd)A#!(g+dQ+pR+0+VB1=A)r_p(Q@(;z5w6U9ioAA4!-)}FG)r$VLMY3+!$qtrBhZv5_| q@$;^IFtFfg{KO{~WyjWrZCV+_w?yn>jn~sN5x&HzqJB)t- diff --git a/libs/libbacktrace/lib/x86_64/libbacktrace.la b/libs/libbacktrace/lib/x86_64/libbacktrace.la new file mode 100644 index 000000000..65545c71e --- /dev/null +++ b/libs/libbacktrace/lib/x86_64/libbacktrace.la @@ -0,0 +1,41 @@ +# libbacktrace.la - a libtool library file +# Generated by libtool (GNU libtool 1.3134 2009-11-29) 2.2.7a +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='' + +# Names of this library. +library_names='' + +# The name of the static archive. +old_library='libbacktrace.a' + +# Linker flags that can not go in dependency_libs. +inherited_linker_flags='' + +# Libraries that this one depends upon. +dependency_libs='' + +# Names of additional weak libraries provided by this library +weak_library_names='' + +# Version information for libbacktrace. +current=0 +age=0 +revision=0 + +# Is this an already installed library? +installed=no + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='/mingw64/lib' diff --git a/libs/libbacktrace/lib/x86_64/libbacktrace.lai b/libs/libbacktrace/lib/x86_64/libbacktrace.lai new file mode 100644 index 000000000..594559c43 --- /dev/null +++ b/libs/libbacktrace/lib/x86_64/libbacktrace.lai @@ -0,0 +1,41 @@ +# libbacktrace.la - a libtool library file +# Generated by libtool (GNU libtool 1.3134 2009-11-29) 2.2.7a +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='' + +# Names of this library. +library_names='' + +# The name of the static archive. +old_library='libbacktrace.a' + +# Linker flags that can not go in dependency_libs. +inherited_linker_flags='' + +# Libraries that this one depends upon. +dependency_libs='' + +# Names of additional weak libraries provided by this library +weak_library_names='' + +# Version information for libbacktrace. +current=0 +age=0 +revision=0 + +# Is this an already installed library? +installed=yes + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='/mingw64/lib' -- 2.54.0 From 8d3435291b399f7f178957fa0dbfe9e5b1e57fc9 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 3 Oct 2025 21:55:49 +0100 Subject: [PATCH 007/219] fix windows compile --- src/doomdef.h | 2 +- src/qs22j.c | 3 +- src/sdl/i_system.cpp | 234 ++++++++++++++++++++++--------------------- 3 files changed, 120 insertions(+), 119 deletions(-) diff --git a/src/doomdef.h b/src/doomdef.h index eba5ed5b1..30419978b 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -92,7 +92,7 @@ extern char logfilename[1024]; // not sure if this belongs here lul // TODO: figure out whats preventing 32bit windows from working with libbacktrace -#if defined(_WIN32) && !defined(MINGW64) +#if defined(_WIN32) && !defined(__MINGW64__) #define HAVE_DRMINGW #endif diff --git a/src/qs22j.c b/src/qs22j.c index bc94d6648..3b0b6151a 100644 --- a/src/qs22j.c +++ b/src/qs22j.c @@ -18,7 +18,6 @@ #include #include "qs22j.h" -#include "doomdef.h" #define INSORTTHRESH 5 // if n < this use insertion sort // MUST be >= 2 @@ -89,7 +88,7 @@ static inline char *med3(char *a, char *b, char *c, int (*compar)(const void *, void qs22j(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) { // we have nothing to sort - if (UNLIKELY(nmemb <= 1)) + if (__builtin_expect(!!(nmemb <= 1), 0) ) //UNLIKELY - thx windoze { return; } diff --git a/src/sdl/i_system.cpp b/src/sdl/i_system.cpp index 97d9b27b4..7314995e8 100644 --- a/src/sdl/i_system.cpp +++ b/src/sdl/i_system.cpp @@ -1453,122 +1453,7 @@ void I_SleepDuration(precise_t duration) #endif } -#ifdef HAVE_THREADS -#include "../core/thread_pool.h" -static std::thread::id g_main_thread_id; -#endif - -boolean g_in_exiting_signal_handler = false; - -static void I_PrintSignal(INT32 signal_num, boolean core_dumped, char *signal_msg) -{ - const char *sigmsg; - - switch (signal_num) - { -#ifdef SIGINT - case SIGINT: - sigmsg = ("SIGINT - SRB2Kart-Saturn was interrupted prematurely by the user."); - break; -#endif - case SIGILL: // illegal instruction - invalid function image - sigmsg = ("SIGILL - SRB2Kart-Saturn has attempted to execute an illegal instruction and needs to close."); - break; - case SIGFPE: // mathematical exception - sigmsg = ("SIGFPE - SRB2Kart-Saturn has encountered a mathematical exception and needs to close."); - break; - case SIGSEGV: // segment violation - sigmsg = ("SIGSEGV - SRB2Kart-Saturn has attempted to access a memory location that it shouldn't and needs to close."); - break; -#ifdef SIGTERM - case SIGTERM: // Software termination signal from kill - sigmsg = ("SIGTERM - SRB2Kart-Saturn was terminated by a kill signal."); - break; -#endif -#ifdef SIGBREAK - case SIGBREAK: // Ctrl-Break sequence - sigmsg =("SIGBREAK - SRB2Kart-Saturn was terminated by a Ctrl-Break sequence.") - break; -#endif - case SIGABRT: // abnormal termination triggered by abort call - sigmsg = ("SIGABRT - SRB2Kart-Saturn was terminated by an abort signal."); - break; - default: - sprintf(signal_msg, "Signal number %d", signal_num); - sigmsg = (core_dumped ? "Unknown signal" : signal_msg); - break; - } - - if (core_dumped) - { - if (sigmsg) - sprintf(signal_msg, "%s (core dumped)", sigmsg); - else - strcat(signal_msg, " (core dumped)"); - } - else - { - sprintf(signal_msg, "%s", sigmsg); - } -} - -static void I_ReportSignal(int num, int coredumped) -{ - char sigmsg[512]; - - I_PrintSignal(num, coredumped, sigmsg); - - size_t len = strlen(sigmsg); - snprintf(sigmsg + len, sizeof(sigmsg) - len, "\n\nCrash report has been saved into %s", CRASH_LOGFILE_NAME); - I_OutputMsg("\nProcess killed by signal: %s\n\n", sigmsg); - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Process killed by signal", sigmsg, NULL); -} - -#ifndef NEWSIGNALHANDLER -FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num) -{ - g_in_exiting_signal_handler = true; - -#ifdef HAVE_THREADS - if (g_main_thread_id != std::this_thread::get_id()) - { - // Do not attempt any sort of recovery if this signal triggers off the main thread - signal(num, SIG_DFL); - raise(num); - exit(-2); - } -#endif - - D_QuitNetGame(); // Fix server freezes - -#ifdef HAVE_LIBBACKTRACE - write_backtrace(BT_CRASH_REASON_SIGNAL(num)); -#endif - - I_ReportSignal(num, 0); - I_ShutdownSystem(); - signal(num, SIG_DFL); //default signal action - raise(num); - I_Quit(); -} -#endif - -FUNCNORETURN static ATTRNORETURN void quit_handler(int num) -{ -#ifdef HAVE_THREADS - if (g_main_thread_id != std::this_thread::get_id()) - { - // Do not attempt any sort of recovery if this signal triggers off the main thread - signal(num, SIG_DFL); - raise(num); - exit(-2); - } -#endif - - signal(num, SIG_DFL); //default signal action - raise(num); - I_Quit(); -} +static void I_PrintSignal(INT32 signal_num, boolean core_dumped, char *signal_msg); #ifdef HAVE_LIBBACKTRACE #include @@ -1750,6 +1635,123 @@ static void write_backtrace(bt_crash_reason_t reason) } #endif +#ifdef HAVE_THREADS +#include "../core/thread_pool.h" +static std::thread::id g_main_thread_id; +#endif + +boolean g_in_exiting_signal_handler = false; + +static void I_PrintSignal(INT32 signal_num, boolean core_dumped, char *signal_msg) +{ + const char *sigmsg; + + switch (signal_num) + { +#ifdef SIGINT + case SIGINT: + sigmsg = ("SIGINT - SRB2Kart-Saturn was interrupted prematurely by the user."); + break; +#endif + case SIGILL: // illegal instruction - invalid function image + sigmsg = ("SIGILL - SRB2Kart-Saturn has attempted to execute an illegal instruction and needs to close."); + break; + case SIGFPE: // mathematical exception + sigmsg = ("SIGFPE - SRB2Kart-Saturn has encountered a mathematical exception and needs to close."); + break; + case SIGSEGV: // segment violation + sigmsg = ("SIGSEGV - SRB2Kart-Saturn has attempted to access a memory location that it shouldn't and needs to close."); + break; +#ifdef SIGTERM + case SIGTERM: // Software termination signal from kill + sigmsg = ("SIGTERM - SRB2Kart-Saturn was terminated by a kill signal."); + break; +#endif +#ifdef SIGBREAK + case SIGBREAK: // Ctrl-Break sequence + sigmsg =("SIGBREAK - SRB2Kart-Saturn was terminated by a Ctrl-Break sequence."); + break; +#endif + case SIGABRT: // abnormal termination triggered by abort call + sigmsg = ("SIGABRT - SRB2Kart-Saturn was terminated by an abort signal."); + break; + default: + sprintf(signal_msg, "Signal number %d", signal_num); + sigmsg = (core_dumped ? "Unknown signal" : signal_msg); + break; + } + + if (core_dumped) + { + if (sigmsg) + sprintf(signal_msg, "%s (core dumped)", sigmsg); + else + strcat(signal_msg, " (core dumped)"); + } + else + { + sprintf(signal_msg, "%s", sigmsg); + } +} + +static void I_ReportSignal(int num, int coredumped) +{ + char sigmsg[512]; + + I_PrintSignal(num, coredumped, sigmsg); + + size_t len = strlen(sigmsg); + snprintf(sigmsg + len, sizeof(sigmsg) - len, "\n\nCrash report has been saved into %s", CRASH_LOGFILE_NAME); + I_OutputMsg("\nProcess killed by signal: %s\n\n", sigmsg); + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Process killed by signal", sigmsg, NULL); +} + +#ifndef NEWSIGNALHANDLER +FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num) +{ + g_in_exiting_signal_handler = true; + +#ifdef HAVE_THREADS + if (g_main_thread_id != std::this_thread::get_id()) + { + // Do not attempt any sort of recovery if this signal triggers off the main thread + signal(num, SIG_DFL); + raise(num); + exit(-2); + } +#endif + + D_QuitNetGame(); // Fix server freezes + +#ifdef HAVE_LIBBACKTRACE + write_backtrace(BT_CRASH_REASON_SIGNAL(num)); +#endif + + I_ReportSignal(num, 0); + I_ShutdownSystem(); + signal(num, SIG_DFL); //default signal action + raise(num); + I_Quit(); +} +#endif + +FUNCNORETURN static ATTRNORETURN void quit_handler(int num) +{ +#ifdef HAVE_THREADS + if (g_main_thread_id != std::this_thread::get_id()) + { + // Do not attempt any sort of recovery if this signal triggers off the main thread + signal(num, SIG_DFL); + raise(num); + exit(-2); + } +#endif + + signal(num, SIG_DFL); //default signal action + raise(num); + I_Quit(); +} + static void I_RegisterSignals(void) { #ifdef HAVE_THREADS -- 2.54.0 From f85c7ef961cca8d75b53e6f5d58aaad137f904d4 Mon Sep 17 00:00:00 2001 From: Indev Date: Sat, 4 Oct 2025 17:25:03 +0300 Subject: [PATCH 008/219] Copyleft :3 --- src/k_stats.c | 11 +++++++++++ src/k_stats.h | 11 +++++++++++ src/lua_udatalib.c | 11 +++++++++++ src/lua_udatalib.h | 13 ++++++++++++- src/m_curl.c | 11 +++++++++++ src/m_curl.h | 11 +++++++++++ src/m_emotes.cpp | 11 +++++++++++ src/m_emotes.h | 11 +++++++++++ src/m_textinput.c | 11 +++++++++++ src/m_textinput.h | 11 +++++++++++ 10 files changed, 111 insertions(+), 1 deletion(-) diff --git a/src/k_stats.c b/src/k_stats.c index 538b4e3e3..9063aa854 100644 --- a/src/k_stats.c +++ b/src/k_stats.c @@ -1,3 +1,14 @@ +// SONIC ROBO BLAST 2 KART SATURN +//----------------------------------------------------------------------------- +// Copyright (C) 2025 by Indev. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file k_stats.h +/// \brief Game statistics handling + #include "k_stats.h" #include "doomstat.h" #include "g_game.h" diff --git a/src/k_stats.h b/src/k_stats.h index bd145de56..00dfff021 100644 --- a/src/k_stats.h +++ b/src/k_stats.h @@ -1,3 +1,14 @@ +// SONIC ROBO BLAST 2 KART SATURN +//----------------------------------------------------------------------------- +// Copyright (C) 2025 by Indev. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file k_stats.h +/// \brief Game statistics handling + #ifndef __K_STATS__ #define __K_STATS__ diff --git a/src/lua_udatalib.c b/src/lua_udatalib.c index d7cd68278..962fb0638 100644 --- a/src/lua_udatalib.c +++ b/src/lua_udatalib.c @@ -1,3 +1,14 @@ +// SONIC ROBO BLAST 2 KART SATURN +//----------------------------------------------------------------------------- +// Copyright (C) 2025 by Indev. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file lua_udatalib.c +/// \brief Implementation of lua userdata object metatables based on getter/setter functions + #include "doomtype.h" #include "m_fixed.h" #include "lua_udatalib.h" diff --git a/src/lua_udatalib.h b/src/lua_udatalib.h index acff4cf3b..ad23bf898 100644 --- a/src/lua_udatalib.h +++ b/src/lua_udatalib.h @@ -1,3 +1,14 @@ +// SONIC ROBO BLAST 2 KART SATURN +//----------------------------------------------------------------------------- +// Copyright (C) 2025 by Indev. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file lua_udatalib.h +/// \brief Implementation of lua userdata object metatables based on getter/setter functions + #ifndef __LUA_UDATALIB_H__ #define __LUA_UDATALIB_H__ @@ -100,4 +111,4 @@ void udatalib_addfields(lua_State *L, int mt, const udata_field_t fields[]); return 0; \ } -#endif \ No newline at end of file +#endif diff --git a/src/m_curl.c b/src/m_curl.c index c96007996..77588a3fb 100644 --- a/src/m_curl.c +++ b/src/m_curl.c @@ -1,3 +1,14 @@ +// SONIC ROBO BLAST 2 KART SATURN +//----------------------------------------------------------------------------- +// Copyright (C) 2025 by Indev. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file m_curl.c +/// \brief Common curl-related functions shared across http-mserv and file download + #include "m_curl.h" #include "doomtype.h" #include "i_system.h" // I_OutputMsg diff --git a/src/m_curl.h b/src/m_curl.h index 928a164e9..adbabda21 100644 --- a/src/m_curl.h +++ b/src/m_curl.h @@ -1,3 +1,14 @@ +// SONIC ROBO BLAST 2 KART SATURN +//----------------------------------------------------------------------------- +// Copyright (C) 2025 by Indev. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file m_curl.h +/// \brief Common curl-related functions shared across http-mserv and file download + #ifndef __M_CURL__ #define __M_CURL__ diff --git a/src/m_emotes.cpp b/src/m_emotes.cpp index facc7fb54..9ae434547 100644 --- a/src/m_emotes.cpp +++ b/src/m_emotes.cpp @@ -1,3 +1,14 @@ +// SONIC ROBO BLAST 2 KART SATURN +//----------------------------------------------------------------------------- +// Copyright (C) 2025 by Indev. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file m_emotes.cpp +/// \brief Chat emotes handling + #include #include #include diff --git a/src/m_emotes.h b/src/m_emotes.h index 783c6ec17..9921e4444 100644 --- a/src/m_emotes.h +++ b/src/m_emotes.h @@ -1,3 +1,14 @@ +// SONIC ROBO BLAST 2 KART SATURN +//----------------------------------------------------------------------------- +// Copyright (C) 2025 by Indev. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file m_emotes.h +/// \brief Chat emotes handling + #ifndef __M_EMOTES__ #define __M_EMOTES__ diff --git a/src/m_textinput.c b/src/m_textinput.c index 353c8122b..882d35e35 100644 --- a/src/m_textinput.c +++ b/src/m_textinput.c @@ -1,3 +1,14 @@ +// SONIC ROBO BLAST 2 KART SATURN +//----------------------------------------------------------------------------- +// Copyright (C) 2025 by Indev. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file m_textinput.c +/// \brief User text input implementation + #include "m_textinput.h" #include "m_menu.h" // MAXSTRINGLENGTH #include "v_video.h" diff --git a/src/m_textinput.h b/src/m_textinput.h index 1cc1c5005..512a47b7c 100644 --- a/src/m_textinput.h +++ b/src/m_textinput.h @@ -1,3 +1,14 @@ +// SONIC ROBO BLAST 2 KART SATURN +//----------------------------------------------------------------------------- +// Copyright (C) 2025 by Indev. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file m_textinput.h +/// \brief User text input implementation + #ifndef __M_TEXTINPUT__ #define __M_TEXTINPUT__ -- 2.54.0 From c5dce0e785ff379ec88f8589464564431cb3546f Mon Sep 17 00:00:00 2001 From: Indev Date: Sat, 4 Oct 2025 17:25:39 +0300 Subject: [PATCH 009/219] oops --- src/k_stats.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_stats.c b/src/k_stats.c index 9063aa854..f4fac90d3 100644 --- a/src/k_stats.c +++ b/src/k_stats.c @@ -6,7 +6,7 @@ // terms of the GNU General Public License, version 2. // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file k_stats.h +/// \file k_stats.c /// \brief Game statistics handling #include "k_stats.h" -- 2.54.0 From b03d5c53edb85c4e5a4c3f3304da65418557265d Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 4 Oct 2025 22:02:50 +0200 Subject: [PATCH 010/219] simplify titledlighting stuff for span drawers - use a std::vector for the tiltlightbufffer, only for easier checking if it needs to be resized from resolution change - move stuff into its own function - simplify R_CalcTiltedLighting no functional change, no performance improvement, just looks neater --- src/r_draw_span.cpp | 80 ++++++++++++++++----------------------------- 1 file changed, 28 insertions(+), 52 deletions(-) diff --git a/src/r_draw_span.cpp b/src/r_draw_span.cpp index 92d64fd6e..cfa053382 100644 --- a/src/r_draw_span.cpp +++ b/src/r_draw_span.cpp @@ -25,6 +25,9 @@ #define local_for_thread static #endif +#include +#include + // ========================================================================== // SPANS // ========================================================================== @@ -182,31 +185,39 @@ static void R_DrawSpanTemplate(drawspandata_t* ds) // R_CalcTiltedLighting // Exactly what it says on the tin. I wish I wasn't too lazy to explain things properly. -static void R_CalcTiltedLighting(INT32 *lightbuffer, INT32 x1, INT32 x2, fixed_t start, fixed_t end) +static void R_CalcTiltedLighting(std::vector& lightbuffer, INT32 x1, INT32 x2, fixed_t start, fixed_t end) { // ZDoom uses a different lighting setup to us, and I couldn't figure out how to adapt their version // of this function. Here's my own. - INT32 i, left = x1, right = x2; + INT32 i; const fixed_t step = (end-start)/(x2 - x1 + 1); // I wanna do some optimizing by checking for out-of-range segments on either side to fill in all at once, // but I'm too bad at coding to not crash the game trying to do that. I guess this is fast enough for now... - for (i = left; i <= right; i++) + for (i = x1; i <= x2; i++) { - lightbuffer[i] = (start += step) >> FRACBITS; - - if (lightbuffer[i] < 0) - { - lightbuffer[i] = 0; - } - else if (lightbuffer[i] >= MAXLIGHTSCALE) - { - lightbuffer[i] = MAXLIGHTSCALE-1; - } + fixed_t light = start >> FRACBITS; + lightbuffer[i] = CLAMP(light, 0, MAXLIGHTSCALE - 1); + start += step; } } +static void R_GetTiltedLighting(std::vector& tiltlighting, const drawspandata_t* ds, const float iz, const int width, const INT32 stride) +{ + float planelightfloat = PLANELIGHTFLOAT; + const fixed_t lightstart = FloatToFixed(iz * planelightfloat); + const fixed_t lightend = FloatToFixed((iz + ds->szp.x * width) * planelightfloat); + + if (tiltlighting.size() != (size_t)viewwidth) + { + tiltlighting.resize(viewwidth); + } + + R_CalcTiltedLighting(tiltlighting, ds->x1, ds->x2, lightstart, lightend); + //CONS_Printf("tilted lighting %f to %f (foc %f)\n", FixedToFloat(lightstart), FixedToFloat(lightend), focallengthf); +} + template static void R_DrawTiltedSpanTemplate(drawspandata_t* ds) { @@ -223,35 +234,18 @@ static void R_DrawTiltedSpanTemplate(drawspandata_t* ds) float endz, endu, endv; UINT32 stepu, stepv; UINT32 bit; - local_for_thread INT32 *tiltlighting = NULL; - local_for_thread INT32 oldviewwidth = 0; - - // dont realloc every frame pls thx - if (tiltlighting == NULL || oldviewwidth != viewwidth) - { - tiltlighting = static_cast(realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth)); - oldviewwidth = viewwidth; - } INT32 x1 = ds->x1; const INT32 nflatxshift = ds->nflatxshift; const INT32 nflatyshift = ds->nflatyshift; const INT32 nflatmask = ds->nflatmask; const INT32 stride = vid.width; + local_for_thread std::vector tiltlighting; iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); // Lighting is simple. It's just linear interpolation from start to end - { - float planelightfloat = PLANELIGHTFLOAT; - float lightstart, lightend; - - lightend = (iz + ds->szp.x*width) * planelightfloat; - lightstart = iz * planelightfloat; - - R_CalcTiltedLighting(tiltlighting, ds->x1, ds->x2, FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); - //CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf); - } + R_GetTiltedLighting(tiltlighting, ds, iz, width, stride); uz = ds->sup.z + ds->sup.y*(centery-ds->y) + ds->sup.x*(ds->x1-centerx); vz = ds->svp.z + ds->svp.y*(centery-ds->y) + ds->svp.x*(ds->x1-centerx); @@ -423,31 +417,13 @@ void R_DrawFogSpan_Tilted(drawspandata_t* ds) int width = ds->x2 - ds->x1; float iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); UINT8 * restrict dest; - - local_for_thread INT32 *tiltlighting = NULL; - local_for_thread INT32 oldviewwidth = 0; - - // dont realloc every frame pls thx - if (tiltlighting == NULL || oldviewwidth != viewwidth) - { - tiltlighting = static_cast(realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth)); - oldviewwidth = viewwidth; - } + local_for_thread std::vector tiltlighting; dest = R_Address(ds->x1, ds->y); const INT32 stride = vid.width; // Lighting is simple. It's just linear interpolation from start to end - { - float planelightfloat = PLANELIGHTFLOAT; - float lightstart, lightend; - - lightend = (iz + ds->szp.x*width) * planelightfloat; - lightstart = iz * planelightfloat; - - R_CalcTiltedLighting(tiltlighting, ds->x1, ds->x2, FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); - //CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf); - } + R_GetTiltedLighting(tiltlighting, ds, iz, width, stride); do { -- 2.54.0 From 78ad3e9710cc439a8b7c22d87ef22f26757b7233 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 5 Oct 2025 02:26:55 +0200 Subject: [PATCH 011/219] some fixes for texture generation - Fix negative y offsets for both normal and y-flipped patches - simplify column wrapping/nonpow2 handling - Single-patch textures: print an error if patch header is missing, cease memory errors sadly does not fix our invalid columns we get occasionally --- src/r_data.c | 158 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 100 insertions(+), 58 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index 65c6c4435..c6ffd6945 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -94,7 +94,7 @@ static UINT32 **texturecolumnofs; // column offset lookup table for each texture UINT8 **texturecache; // graphics data for each generated full-size texture // texture width is a power of 2, so it can easily repeat along sidedefs using a simple mask -static INT32 *texturewidthmask; +static INT32 *texturewidth; fixed_t *textureheight; // needed for texture pegging @@ -260,6 +260,7 @@ static inline void R_DrawColumnInCache(column_t *patch, UINT8 *cache, INT32 orig if (position < 0) { count += position; + source -= position; // start further down the column position = 0; } @@ -273,6 +274,50 @@ static inline void R_DrawColumnInCache(column_t *patch, UINT8 *cache, INT32 orig } } +static UINT8 *R_AllocateTextureBlock(size_t blocksize, UINT8 **user) +{ + texturememory += blocksize; + + return Z_Malloc(blocksize, PU_LEVEL, user); +} + +static UINT8 *R_AllocateDummyTextureBlock(size_t width, UINT8 **user) +{ + // Allocate dummy data. Keep 4-bytes aligned. + // Column offsets will be initialized to 0, which points to the 0xff byte (empty column flag). + size_t blocksize = 4 + (width * 4); + UINT8 *block = R_AllocateTextureBlock(blocksize, user); + + memset(block, 0, blocksize); + block[0] = 0xff; + + return block; +} + +static boolean R_CheckTextureLumpLength(texture_t *texture, size_t patch) +{ + UINT16 wadnum = texture->patches[patch].wad; + UINT16 lumpnum = texture->patches[patch].lump; + size_t lumplength = W_LumpLengthPwad(wadnum, lumpnum); + + // The header does not exist + if (lumplength < offsetof(softwarepatch_t, columnofs)) + { + CONS_Alert( + CONS_ERROR, + "%.8s: texture lump data is too small. Expected %s bytes, got %s. (%s)\n", + texture->name, + sizeu1(offsetof(softwarepatch_t, columnofs)), + sizeu2(lumplength), + wadfiles[wadnum]->lumpinfo[lumpnum].fullname + ); + + return false; + } + + return true; +} + // // R_GenerateTexture // @@ -297,6 +342,10 @@ UINT8 *R_GenerateTexture(size_t texnum) column_t *patchcol; UINT8 *colofs; + UINT16 wadnum; + lumpnum_t lumpnum; + size_t lumplength; + I_Assert(texnum <= (size_t)numtextures); texture = textures[texnum]; I_Assert(texture != NULL); @@ -311,45 +360,57 @@ UINT8 *R_GenerateTexture(size_t texnum) { boolean holey = false; patch = texture->patches; + + wadnum = patch->wad; + lumpnum = patch->lump; + lumplength = W_LumpLengthPwad(wadnum, lumpnum); + + // The header does not exist + if (R_CheckTextureLumpLength(texture, 0) == false) + { + block = R_AllocateDummyTextureBlock(texture->width, &texturecache[texnum]); + texturecolumnofs[texnum] = (UINT32*)&block[4]; + textures[texnum]->holes = true; + return block; + } + pdata = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_LEVEL); realpatch = (softwarepatch_t *)pdata; // Check the patch for holes. if (texture->width > SHORT(realpatch->width) || texture->height > SHORT(realpatch->height)) holey = true; - else + + colofs = (UINT8 *)realpatch->columnofs; + + for (x = 0; x < texture->width; x++) { - colofs = (UINT8 *)realpatch->columnofs; + column_t *col = (column_t *)((UINT8 *)realpatch + LONG(*(UINT32 *)&colofs[x<<2])); - for (x = 0; x < texture->width; x++) + INT32 topdelta, prevdelta = -1, y = 0; + + while (col->topdelta != 0xff) { - column_t *col = (column_t *)((UINT8 *)realpatch + LONG(*(UINT32 *)&colofs[x<<2])); - - INT32 topdelta, prevdelta = -1, y = 0; - - while (col->topdelta != 0xff) - { - topdelta = col->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - if (topdelta > y) - break; - y = topdelta + col->length + 1; - col = (column_t *)((UINT8 *)col + col->length + 4); - } - - if (y < texture->height) - holey = true; // this texture is HOLEy! D: + topdelta = col->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + if (topdelta > y) + break; + y = topdelta + col->length + 1; + col = (column_t *)((UINT8 *)col + col->length + 4); } + + if (y < texture->height) + holey = true; // this texture is HOLEy! D: } // If the patch uses transparency, we have to save it this way. if (holey) { texture->holes = true; - blocksize = W_LumpLengthPwad(patch->wad, patch->lump); - block = Z_Calloc(blocksize, PU_LEVEL, &texturecache[texnum]); + blocksize = lumplength; + block = Z_Calloc(blocksize, PU_LEVEL, &texturecache[texnum]); // will change tag at end of this function M_Memcpy(block, realpatch, blocksize); texturememory += blocksize; @@ -365,7 +426,6 @@ UINT8 *R_GenerateTexture(size_t texnum) goto done; } - // Otherwise, do multipatch format. } @@ -387,7 +447,10 @@ UINT8 *R_GenerateTexture(size_t texnum) // Composite the columns together. for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++) { - pdata = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_LEVEL); + wadnum = patch->wad; + lumpnum = patch->lump; + pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_LEVEL); + lumplength = W_LumpLengthPwad(wadnum, lumpnum); realpatch = (softwarepatch_t *)pdata; x1 = patch->originx; @@ -439,6 +502,7 @@ INT32 R_GetTextureNum(INT32 texnum) { if (texnum < 0 || texnum >= numtextures) return 0; + return texturetranslation[texnum]; } @@ -456,17 +520,12 @@ void R_CheckTextureCache(INT32 tex) static inline INT32 wrap_column(fixed_t tex, INT32 col) { - if (texturewidthmask[tex]) - col &= texturewidthmask[tex]; // set by load textures - else - { - const INT16 texwidth = textures[tex]->width; + INT32 width = texturewidth[tex]; - // Odd width texture, cannot just mask. - // Sometime gets colnum = -1 or = width, even without tiling. - // Test LostCiv, Map 20, crates. - col = ((col % texwidth) + texwidth) % texwidth; - } + if (width & (width - 1)) + col = (UINT32)col % width; + else + col &= (width - 1); return col; } @@ -516,7 +575,6 @@ static INT32 Rloadtextures (INT32 i, INT32 w) { UINT16 j, numlumps = 0; - INT32 k; UINT16 texstart, texend, texturesLumpPos; softwarepatch_t *patchlump; texpatch_t *patch; @@ -568,8 +626,10 @@ Rloadtextures (INT32 i, INT32 w) // Set texture properties. M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name)); texture->hash = quickncasehash(texture->name, 8); + texture->width = SHORT(patchlump->width); texture->height = SHORT(patchlump->height); + texture->type = TEXTURETYPE_SINGLEPATCH; texture->patchcount = 1; texture->holes = false; @@ -583,25 +643,7 @@ Rloadtextures (INT32 i, INT32 w) Z_Free(patchlump); - // determine width power of 2 -#if 1 - // [WDJ] only need to determine if exact power of 2. - k = 1; - while (k < texture->width) - k<<=1; -#else - // Largest power of 2 that fits within width. - k = 1; - while (k << 1 <= texture->width) - k <<= 1; -#endif - if (k != texture->width) - { - // Odd width - k = 1; // make texturewidthmask = 0 - } - - texturewidthmask[i] = k - 1; + texturewidth[i] = texture->width; textureheight[i] = texture->height << FRACBITS; i++; } @@ -709,7 +751,7 @@ static void R_AllocateTextures(INT32 add) // Allocate texture referencing cache. recallocuser(&texturecache, oldsize, newsize); // Allocate texture width table. - recallocuser(&texturewidthmask, oldsize, newsize); + recallocuser(&texturewidth, oldsize, newsize); // Allocate texture height table. recallocuser(&textureheight, oldsize, newsize); // Create translation table for global animation. @@ -1181,7 +1223,7 @@ void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *texindex) newTexture = R_ParseTexture(true); // Store the new texture textures[*texindex] = newTexture; - texturewidthmask[*texindex] = newTexture->width - 1; + texturewidth[*texindex] = newTexture->width; textureheight[*texindex] = newTexture->height << FRACBITS; // Increment i back in R_LoadTextures() (*texindex)++; -- 2.54.0 From f5b60c3f36af7c9ac1c31cfff1638ca3739ab8e7 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 5 Oct 2025 03:10:28 +0200 Subject: [PATCH 012/219] port "Use separate table for maskedtexturecol" from: https://git.do.srb2.org/STJr/SRB2/-/commit/97311dc5b00ab232a6e898c085c20d2f6bdbfa3b ~~cherry-picking this would be horrendous sry~~ --- src/r_defs.h | 4 +- src/r_main.cpp | 2 + src/r_plane.cpp | 8 +- src/r_plane.h | 2 - src/r_segs.cpp | 418 ++++++++++++++++++++++++++--------------------- src/r_segs.h | 1 + src/r_things.cpp | 4 +- 7 files changed, 244 insertions(+), 195 deletions(-) diff --git a/src/r_defs.h b/src/r_defs.h index 3d49b70a8..5f9a0d41a 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -615,12 +615,12 @@ typedef struct drawseg_s // Pointers to lists for sprite clipping, all three adjusted so [x1] is first value. INT16 *sprtopclip; INT16 *sprbottomclip; - INT16 *maskedtexturecol; + fixed_t *maskedtexturecol; struct visplane_s *ffloorplanes[MAXFFLOORS]; INT32 numffloorplanes; struct ffloor_s *thicksides[MAXFFLOORS]; - INT16 *thicksidecol; + fixed_t *thicksidecol; INT32 numthicksides; fixed_t *frontscale; diff --git a/src/r_main.cpp b/src/r_main.cpp index ee5fcd0f8..08f1e68a1 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1400,6 +1400,7 @@ void R_RenderPlayerView(player_t *player) R_ClearClipSegs(); R_ClearDrawSegs(); + R_ClearSegTables(); R_ClearPlanes(); R_ClearSprites(); @@ -1434,6 +1435,7 @@ void R_RenderPlayerView(player_t *player) R_ClearClipSegs(); } R_ClearDrawSegs(); + R_ClearSegTables(); R_ClearSprites(); // check for new console commands. diff --git a/src/r_plane.cpp b/src/r_plane.cpp index d4b718123..e76b0374a 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -60,10 +60,6 @@ INT32 numffloors; #define visplane_hash(picnum,lightlevel,height) \ ((unsigned)((picnum)*3+(lightlevel)+(height)*7) & VISPLANEHASHMASK) -//SoM: 3/23/2000: Use boom opening limit removal -size_t maxopenings; -INT16 *openings, *lastopening; /// \todo free leak - // // Clip values are the solid pixel bounding the range. // floorclip starts out SCREENHEIGHT @@ -339,13 +335,13 @@ void R_ClearPlanes(void) R_ClearFFloorClips(); for (i = 0; i < MAXVISPLANES; i++) + { for (*freehead = visplanes[i], visplanes[i] = NULL; freehead && *freehead ;) { freehead = &(*freehead)->next; } - - lastopening = openings; + } // left to right mapping angle = (viewangle-ANGLE_90)>>ANGLETOFINESHIFT; diff --git a/src/r_plane.h b/src/r_plane.h index d3b22ea30..c76f9d6c0 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -67,8 +67,6 @@ extern visplane_t *floorplane; extern visplane_t *ceilingplane; // Visplane related. -extern INT16 *lastopening, *openings; -extern size_t maxopenings; extern INT16 *floorclip, *ceilingclip; extern fixed_t *frontscale, *yslopetab; diff --git a/src/r_segs.cpp b/src/r_segs.cpp index 70740eb5b..bedec68ab 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -78,9 +78,21 @@ static fixed_t topfrac, topstep; static fixed_t bottomfrac, bottomstep; static lighttable_t **walllights; -static INT16 *maskedtexturecol; +static fixed_t *maskedtexturecol; static fixed_t *maskedtextureheight = NULL; +static size_t numopenings; +static INT16 *openings, *lastopening; + +static size_t texturecolumntablesize; +static fixed_t *texturecolumntable, *curtexturecolumntable; + +void R_ClearSegTables(void) +{ + lastopening = openings; + curtexturecolumntable = texturecolumntable; +} + // ========================================================================== // R_RenderMaskedSegRange // ========================================================================== @@ -306,141 +318,137 @@ static void R_RenderMaskedSegLoop(drawcolumndata_t* dc, drawseg_t *drawseg, INT3 else dc->texturemid -= (textureheight[texnum])*times; - const INT16 colnum = maskedtexturecol[dc->x]; + // Check for overflows first + if (R_OverflowTest(dc)) + { + // Eh, no, go away, don't waste our time + if (dc->numlights) + { + for (i = 0; i < dc->numlights; i++) + { + rlight = &dc->lightlist[i]; + rlight->height += rlight->heightstep; + } + } + + spryscale += rw_scalestep; + continue; + } // calculate lighting - if (colnum != INT16_MAX) + if (dc->numlights) { - // Check for overflows first - if (R_OverflowTest(dc)) + lighttable_t **xwalllights; + + sprbotscreen = INT32_MAX; + sprtopscreen = windowtop = (centeryfrac - FixedMul(dc->texturemid, spryscale)); + + realbot = windowbottom = FixedMul(textureheight[texnum], spryscale) + sprtopscreen; + dc->iscale = 0xffffffffu / (unsigned)spryscale; + + // draw the texture + col = (column_t *)((UINT8 *)R_GetColumn(texnum, (maskedtexturecol[dc->x] >> FRACBITS)) - 3); + + auto set_light_vars = [&](INT32 k) { - // Eh, no, go away, don't waste our time - if (dc->numlights) + rlight = &dc->lightlist[k]; + + lightnum = rlight->lightnum; + + if (lightnum < 0) + xwalllights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + xwalllights = scalelight[LIGHTLEVELS-1]; + else + xwalllights = scalelight[lightnum]; + + pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; + + if (pindex >= MAXLIGHTSCALE) + pindex = MAXLIGHTSCALE - 1; + + if (rlight->extra_colormap) + rlight->rcolormap = rlight->extra_colormap->colormap + (xwalllights[pindex] - colormaps); + else + rlight->rcolormap = xwalllights[pindex]; + }; + + auto set_colormap_below_light = [&] + { + dc->colormap = rlight->rcolormap; + if (encoremap && !(ldef->flags & ML_TFERLINE)) + dc->colormap += COLORMAP_REMAPOFFSET; + }; + + // Use the base sector's light level above the first FOF. + // You can imagine it as the sky casting its light on top of the highest FOF. + set_light_vars(0); + set_colormap_below_light(); + + for (i = 0; i < dc->numlights; i++) + { + if ((dc->lightlist[i].flags & FF_NOSHADE)) + continue; + + set_light_vars(i); + + height = rlight->height; + rlight->height += rlight->heightstep; + + if (height <= windowtop) { - for (i = 0; i < dc->numlights; i++) + set_colormap_below_light(); + continue; + } + + windowbottom = height; + if (windowbottom >= realbot) + { + windowbottom = realbot; + colfunc_2s(dc, col); + for (i++; i < dc->numlights; i++) { rlight = &dc->lightlist[i]; rlight->height += rlight->heightstep; } + + continue; } - spryscale += rw_scalestep; - continue; - } + colfunc_2s(dc, col); - if (dc->numlights) - { - lighttable_t **xwalllights; - - sprbotscreen = INT32_MAX; - sprtopscreen = windowtop = (centeryfrac - FixedMul(dc->texturemid, spryscale)); - - realbot = windowbottom = FixedMul(textureheight[texnum], spryscale) + sprtopscreen; - dc->iscale = 0xffffffffu / (unsigned)spryscale; - - // draw the texture - col = (column_t *)((UINT8 *)R_GetColumn(texnum, colnum) - 3); - - auto set_light_vars = [&](INT32 k) - { - rlight = &dc->lightlist[k]; - - lightnum = rlight->lightnum; - - if (lightnum < 0) - xwalllights = scalelight[0]; - else if (lightnum >= LIGHTLEVELS) - xwalllights = scalelight[LIGHTLEVELS-1]; - else - xwalllights = scalelight[lightnum]; - - pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; - - if (pindex >= MAXLIGHTSCALE) - pindex = MAXLIGHTSCALE - 1; - - if (rlight->extra_colormap) - rlight->rcolormap = rlight->extra_colormap->colormap + (xwalllights[pindex] - colormaps); - else - rlight->rcolormap = xwalllights[pindex]; - }; - - auto set_colormap_below_light = [&] - { - dc->colormap = rlight->rcolormap; - if (encoremap && !(ldef->flags & ML_TFERLINE)) - dc->colormap += COLORMAP_REMAPOFFSET; - }; - - // Use the base sector's light level above the first FOF. - // You can imagine it as the sky casting its light on top of the highest FOF. - set_light_vars(0); + windowtop = windowbottom + 1; set_colormap_below_light(); - - for (i = 0; i < dc->numlights; i++) - { - if ((dc->lightlist[i].flags & FF_NOSHADE)) - continue; - - set_light_vars(i); - - height = rlight->height; - rlight->height += rlight->heightstep; - - if (height <= windowtop) - { - set_colormap_below_light(); - continue; - } - - windowbottom = height; - if (windowbottom >= realbot) - { - windowbottom = realbot; - colfunc_2s(dc, col); - for (i++; i < dc->numlights; i++) - { - rlight = &dc->lightlist[i]; - rlight->height += rlight->heightstep; - } - - continue; - } - colfunc_2s(dc, col); - - windowtop = windowbottom + 1; - set_colormap_below_light(); - } - windowbottom = realbot; - if (windowtop < windowbottom) - colfunc_2s(dc, col); - - spryscale += rw_scalestep; - continue; } + windowbottom = realbot; + if (windowtop < windowbottom) + colfunc_2s(dc, col); - // calculate lighting - pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; - - if (pindex >= MAXLIGHTSCALE) - pindex = MAXLIGHTSCALE - 1; - - dc->colormap = walllights[pindex]; - if (encoremap && !(ldef->flags & ML_TFERLINE)) - dc->colormap += COLORMAP_REMAPOFFSET; - - if (frontsector->extra_colormap) - dc->colormap = frontsector->extra_colormap->colormap + (dc->colormap - colormaps); - - sprtopscreen = centeryfrac - FixedMul(dc->texturemid, spryscale); - dc->iscale = 0xffffffffu / (unsigned)spryscale; - - // draw the texture - col = (column_t *)((UINT8 *)R_GetColumn(texnum, colnum) - 3); - - colfunc_2s(dc, col); + spryscale += rw_scalestep; + continue; } + // calculate lighting + pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; + + if (pindex >= MAXLIGHTSCALE) + pindex = MAXLIGHTSCALE - 1; + + dc->colormap = walllights[pindex]; + if (encoremap && !(ldef->flags & ML_TFERLINE)) + dc->colormap += COLORMAP_REMAPOFFSET; + + if (frontsector->extra_colormap) + dc->colormap = frontsector->extra_colormap->colormap + (dc->colormap - colormaps); + + sprtopscreen = centeryfrac - FixedMul(dc->texturemid, spryscale); + dc->iscale = 0xffffffffu / (unsigned)spryscale; + + // draw the texture + col = (column_t *)((UINT8 *)R_GetColumn(texnum, (maskedtexturecol[dc->x] >> FRACBITS)) - 3); + + colfunc_2s(dc, col); + spryscale += rw_scalestep; } } @@ -632,6 +640,7 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf void (*colfunc_2s) (drawcolumndata_t* dc, column_t *); + // Calculate light table. // Use different light tables // for horizontal / vertical / diagonal. Diagonal? @@ -899,14 +908,11 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf // draw the columns for (dc->x = x1; dc->x <= x2; dc->x++) { - if (maskedtexturecol[dc->x] == INT16_MAX) - continue; - // skew FOF walls if (ffloortextureslide) { if (oldx != -1) - dc->texturemid += FixedMul(ffloortextureslide, (maskedtexturecol[oldx]-maskedtexturecol[dc->x])<texturemid += FixedMul(ffloortextureslide, (maskedtexturecol[oldx]-maskedtexturecol[dc->x])); oldx = dc->x; } @@ -936,9 +942,6 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf continue; } - // Get data for the column - col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc->x]) - 3); - if (!fog) { dc->iscale = 0xffffffffu / (unsigned)spryscale; @@ -949,6 +952,9 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf R_SetColumnFunc(BASEDRAWFUNC); } + // Get data for the column + col = (column_t *)((UINT8 *)R_GetColumn(texnum, (maskedtexturecol[dc->x] >> FRACBITS)) - 3); + // SoM: New code does not rely on R_DrawColumnShadowed which // will (hopefully) put less strain on the stack. if (dc->numlights) @@ -1159,13 +1165,14 @@ static inline void R_ExpandPlaneY(visplane_t *pl, INT32 x, INT16 top, INT16 bott static void R_DrawWallColumn(drawcolumndata_t* dc, INT32 yl, INT32 yh, fixed_t mid, fixed_t texturecolumn, INT32 texture, boolean remap) { + const INT32 itexturecolumn = texturecolumn >> FRACBITS; dc->yl = yl; dc->yh = yh; dc->texturemid = mid; - dc->source = R_GetColumn(texture, texturecolumn); + dc->source = R_GetColumn(texture, itexturecolumn); dc->texheight = textureheight[texture] >> FRACBITS; dc->sourcelength = dc->texheight; - //R_SetColumnFunc(colfunctype); + R_SetColumnFunc(colfunctype); coldrawfunc_t* colfunccopy = colfunc; drawcolumndata_t dc_copy = *dc; if (remap) @@ -1346,7 +1353,7 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) // calculate texture offset angle = (rw_centerangle + xtoviewangle[rw_x])>>ANGLETOFINESHIFT; // Mask 4095 to guarantee this index is within bounds - texturecolumn = rw_offset-FixedMul(FINETANGENT(angle & 4095),rw_distance); + texturecolumn = rw_offset-FixedMul(FINETANGENT(angle & 4095), rw_distance); if (oldtexturecolumn != -1) { @@ -1357,8 +1364,6 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) } oldtexturecolumn = texturecolumn; - texturecolumn >>= FRACBITS; - // texturecolumn and lighting are independent of wall tiers if (segtextured) { @@ -1515,7 +1520,7 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) if (maskedtexture || numthicksides) { // save texturecol for backdrawing of masked mid texture - maskedtexturecol[rw_x] = (INT16)texturecolumn; + maskedtexturecol[rw_x] = texturecolumn; if (maskedtextureheight != NULL) { @@ -1616,7 +1621,7 @@ static void R_MarkSegBounds(void) if (markfloor) // no bottom wall floorclip[rw_x] = bottomclip; - if (floorclip[rw_x] <= ceilingclip[rw_x] + 1) + if ((markceiling || markfloor) && (floorclip[rw_x] <= ceilingclip[rw_x] + 1)) { solidcol[rw_x] = 1; didsolidcol = true; @@ -1672,6 +1677,78 @@ void R_AllocSegMemory(void) } } + +//SoM: Code to remove limits on openings. +static void R_AllocClippingTables(size_t range) +{ + size_t pos = lastopening - openings; + size_t need = range * 2; // for both sprtopclip and sprbottomclip + + if (pos + need < numopenings) + return; + + INT16 *oldopenings = openings; + INT16 *oldlast = lastopening; + + if (numopenings == 0) + numopenings = 16384; + + numopenings += need; + openings = static_cast(Z_Realloc(openings, numopenings * sizeof (*openings), PU_STATIC, NULL)); + lastopening = openings + pos; + + if (!oldopenings) + return; + + // borrowed fix from *cough* zdoom *cough* + // [RH] We also need to adjust the openings pointers that + // were already stored in drawsegs. + for (drawseg_t *ds = drawsegs; ds < ds_p; ds++) + { + // Check if it's in range of the openings +#define CHECK(which) \ + if (which + ds->x1 >= oldopenings && which + ds->x1 <= oldlast) \ + which = (which - oldopenings) + openings + CHECK(ds->sprtopclip); + CHECK(ds->sprbottomclip); +#undef CHECK + } +} + +static void R_AllocTextureColumnTables(size_t range) +{ + size_t pos = curtexturecolumntable - texturecolumntable; + + // For both tables, we reserve exactly an amount of memory that's equivalent to + // how many columns the seg will take on the entire screen (think about it) + if (pos + range < texturecolumntablesize) + return; + + fixed_t *oldtable = texturecolumntable; + fixed_t *oldlast = curtexturecolumntable; + + if (texturecolumntablesize == 0) + texturecolumntablesize = 16384; + + texturecolumntablesize += range; + texturecolumntable = static_cast(Z_Realloc(texturecolumntable, texturecolumntablesize * sizeof (*texturecolumntable), PU_STATIC, NULL)); + curtexturecolumntable = texturecolumntable + pos; + + if (!oldtable) + return; + + for (drawseg_t *ds = drawsegs; ds < ds_p; ds++) + { + // Check if it's in range of the tables +#define CHECK(which) \ + if (which + ds->x1 >= oldtable && which + ds->x1 <= oldlast) \ + which = (which - oldtable) + texturecolumntable + CHECK(ds->maskedtexturecol); + CHECK(ds->thicksidecol); +#undef CHECK + } +} + // // R_StoreWallRange // A wall segment will be drawn @@ -1745,41 +1822,6 @@ void R_StoreWallRange(INT32 start, INT32 stop) ds_p->curline = curline; rw_stopx = stop+1; - //SoM: Code to remove limits on openings. - { - size_t pos = lastopening - openings; - size_t need = (rw_stopx - start)*4 + pos; - - if (need > maxopenings) - { - drawseg_t *ds; //needed for fix from *cough* zdoom *cough* - INT16 *oldopenings = openings; - INT16 *oldlast = lastopening; - - do - maxopenings = maxopenings ? maxopenings*2 : 16384; - while (need > maxopenings); - openings = static_cast(Z_Realloc(openings, maxopenings * sizeof (*openings), PU_STATIC, NULL)); - lastopening = openings + pos; - - if (oldopenings == NULL) - return; - - // borrowed fix from *cough* zdoom *cough* - // [RH] We also need to adjust the openings pointers that - // were already stored in drawsegs. - for (ds = drawsegs; ds < ds_p; ds++) - { -#define ADJUST(p) if (ds->p + ds->x1 >= oldopenings && ds->p + ds->x1 <= oldlast) ds->p = (ds->p - oldopenings) + openings; - ADJUST(maskedtexturecol); - ADJUST(sprtopclip); - ADJUST(sprbottomclip); - ADJUST(thicksidecol); -#undef ADJUST - } - } - } // end of code to remove limits on openings - // calculate scale at both ends and step ds_p->scale1 = rw_scale = R_ScaleFromGlobalAngle(viewangle + xtoviewangle[start]); @@ -2160,6 +2202,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) rw_toptexturemid += sidedef->rowoffset; rw_bottomtexturemid += sidedef->rowoffset; + R_AllocTextureColumnTables(rw_stopx - start); + // allocate space for masked texture tables if (frontsector && backsector && (frontsector->tag != backsector->tag) && (backsector->ffloors || frontsector->ffloors)) { @@ -2173,8 +2217,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) maskedtexture = true; - ds_p->thicksidecol = maskedtexturecol = lastopening - rw_x; - lastopening += rw_stopx - rw_x; + ds_p->thicksidecol = maskedtexturecol = curtexturecolumntable - rw_x; + curtexturecolumntable += rw_stopx - rw_x; lowcut = std::max(worldbottom, worldlow) + viewz; highcut = std::min(worldtop, worldhigh) + viewz; @@ -2356,10 +2400,11 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) { // masked midtexture + if (!ds_p->thicksidecol) { - ds_p->maskedtexturecol = maskedtexturecol = lastopening - rw_x; - lastopening += rw_stopx - rw_x; + ds_p->maskedtexturecol = maskedtexturecol = curtexturecolumntable - rw_x; + curtexturecolumntable += rw_stopx - rw_x; } else ds_p->maskedtexturecol = ds_p->thicksidecol; @@ -2939,18 +2984,23 @@ void R_StoreWallRange(INT32 start, INT32 stop) } // save sprite clipping info - if (((ds_p->silhouette & SIL_TOP) || maskedtexture) && !ds_p->sprtopclip) + if (maskedtexture || (ds_p->silhouette & (SIL_TOP | SIL_BOTTOM))) { - M_Memcpy(lastopening, ceilingclip+start, 2*(rw_stopx - start)); - ds_p->sprtopclip = lastopening - start; - lastopening += rw_stopx - start; - } + R_AllocClippingTables(rw_stopx - start); - if (((ds_p->silhouette & SIL_BOTTOM) || maskedtexture) && !ds_p->sprbottomclip) - { - M_Memcpy(lastopening, floorclip + start, 2*(rw_stopx-start)); - ds_p->sprbottomclip = lastopening - start; - lastopening += rw_stopx - start; + if (((ds_p->silhouette & SIL_TOP) || maskedtexture) && !ds_p->sprtopclip) + { + M_Memcpy(lastopening, ceilingclip + start, 2*(rw_stopx - start)); + ds_p->sprtopclip = lastopening - start; + lastopening += rw_stopx - start; + } + + if (((ds_p->silhouette & SIL_BOTTOM) || maskedtexture) && !ds_p->sprbottomclip) + { + M_Memcpy(lastopening, floorclip + start, 2*(rw_stopx - start)); + ds_p->sprbottomclip = lastopening - start; + lastopening += rw_stopx - start; + } } if (maskedtexture) @@ -2958,13 +3008,13 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (!(ds_p->silhouette & SIL_TOP)) { ds_p->silhouette |= SIL_TOP; - ds_p->tsilheight = (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) ? INT32_MIN: INT32_MAX; + ds_p->tsilheight = (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) ? INT32_MIN : INT32_MAX; } if (!(ds_p->silhouette & SIL_BOTTOM)) { ds_p->silhouette |= SIL_BOTTOM; - ds_p->bsilheight = (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) ? INT32_MAX: INT32_MIN; + ds_p->bsilheight = (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) ? INT32_MAX : INT32_MIN; } } diff --git a/src/r_segs.h b/src/r_segs.h index 27dbbe54f..c40fcd331 100644 --- a/src/r_segs.h +++ b/src/r_segs.h @@ -25,6 +25,7 @@ extern "C" { void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2); void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pffloor); void R_StoreWallRange(INT32 start, INT32 stop); +void R_ClearSegTables(void); void R_AllocSegMemory(void); diff --git a/src/r_things.cpp b/src/r_things.cpp index 7f1d5af54..8229369a7 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -2249,11 +2249,13 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps } ds->curline->polyseg->visplane = NULL; } + if (ds->maskedtexturecol) { entry = R_CreateDrawNode(head); entry->seg = ds; } + if (ds->numffloorplanes) { for (i = 0; i < ds->numffloorplanes; i++) @@ -3028,7 +3030,7 @@ static void R_DrawMaskedList(drawnode_t* head) else if (r2->seg && r2->seg->maskedtexturecol != NULL) { next = r2->prev; - R_RenderMaskedSegRange( r2->seg, r2->seg->x1, r2->seg->x2); + R_RenderMaskedSegRange(r2->seg, r2->seg->x1, r2->seg->x2); r2->seg->maskedtexturecol = NULL; R_DoneWithNode(r2); r2 = next; -- 2.54.0 From 1d0fedddfd6e280db0a2f4f1de7ecbceffee41be Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 5 Oct 2025 04:05:45 +0200 Subject: [PATCH 013/219] add bounds check to R_GetLinedefTransTable --- src/r_segs.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/r_segs.cpp b/src/r_segs.cpp index bedec68ab..e5a542c72 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -152,7 +152,18 @@ static void R_Render2sidedMultiPatchColumn(drawcolumndata_t* dc, column_t *colum transnum_t R_GetLinedefTransTable(fixed_t alpha) { - return static_cast((20*(FRACUNIT - alpha - 1) + FRACUNIT) >> (FRACBITS+1)); + if (alpha >= FRACUNIT) + { + return static_cast(0); + } + else if (alpha <= 0) + { + return NUMTRANSMAPS; + } + else + { + return static_cast((20*(FRACUNIT - alpha - 1) + FRACUNIT) >> (FRACBITS+1)); + } } static inline boolean R_OverflowTest(drawcolumndata_t* dc) @@ -1916,8 +1927,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) numbackffloors = 0; - for (i = 0; i < MAXFFLOORS; i++) - ds_p->thicksides[i] = NULL; + memset(ds_p->thicksides, 0, MAXFFLOORS * sizeof(*ds_p->thicksides)); if (numffloors) { -- 2.54.0 From 90ff1c4fc02b7242be8a0503e112768bd9bd53d2 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 5 Oct 2025 04:57:18 +0200 Subject: [PATCH 014/219] small fixups for r_segs --- src/r_segs.cpp | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/r_segs.cpp b/src/r_segs.cpp index e5a542c72..e6a603192 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -196,7 +196,7 @@ static void R_RenderMaskedSegLoop(drawcolumndata_t* dc, drawseg_t *drawseg, INT3 ldef = curline->linedef; - range = std::max(drawseg->x2-drawseg->x1, 1); + range = std::max(drawseg->x2-drawseg->x1, 1); // Setup lighting based on the presence/lack-of 3D floors. dc->numlights = 0; @@ -694,7 +694,7 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf fog = true; } - range = std::max(drawseg->x2-drawseg->x1, 1); + range = std::max(drawseg->x2-drawseg->x1, 1); //SoM: Moved these up here so they are available for my lightlist calculations rw_scalestep = drawseg->scalestep; spryscale = drawseg->scale1 + (x1 - drawseg->x1)*rw_scalestep; @@ -1679,10 +1679,10 @@ void R_AllocSegMemory(void) fixed_t *frontscale_p = frontscaletable; fixed_t *maskedheight_p = maskedheighttable; - for (drawseg_t *ds = drawsegs; ds < lastseg; ds++) + for (drawseg_t *drawseg = drawsegs; drawseg < lastseg; drawseg++) { - ds->frontscale = frontscale_p; - ds->maskedtextureheight = maskedheight_p; + drawseg->frontscale = frontscale_p; + drawseg->maskedtextureheight = maskedheight_p; frontscale_p += viewwidth; maskedheight_p += viewwidth; } @@ -1708,20 +1708,20 @@ static void R_AllocClippingTables(size_t range) openings = static_cast(Z_Realloc(openings, numopenings * sizeof (*openings), PU_STATIC, NULL)); lastopening = openings + pos; - if (!oldopenings) + if (oldopenings == NULL) return; // borrowed fix from *cough* zdoom *cough* // [RH] We also need to adjust the openings pointers that // were already stored in drawsegs. - for (drawseg_t *ds = drawsegs; ds < ds_p; ds++) + for (drawseg_t *drawseg = drawsegs; drawseg < ds_p; drawseg++) { // Check if it's in range of the openings #define CHECK(which) \ - if (which + ds->x1 >= oldopenings && which + ds->x1 <= oldlast) \ + if (which + drawseg->x1 >= oldopenings && which + drawseg->x1 <= oldlast) \ which = (which - oldopenings) + openings - CHECK(ds->sprtopclip); - CHECK(ds->sprbottomclip); + CHECK(drawseg->sprtopclip); + CHECK(drawseg->sprbottomclip); #undef CHECK } } @@ -1745,17 +1745,17 @@ static void R_AllocTextureColumnTables(size_t range) texturecolumntable = static_cast(Z_Realloc(texturecolumntable, texturecolumntablesize * sizeof (*texturecolumntable), PU_STATIC, NULL)); curtexturecolumntable = texturecolumntable + pos; - if (!oldtable) + if (oldtable == NULL) return; - for (drawseg_t *ds = drawsegs; ds < ds_p; ds++) + for (drawseg_t *drawseg = drawsegs; drawseg < ds_p; drawseg++) { // Check if it's in range of the tables #define CHECK(which) \ - if (which + ds->x1 >= oldtable && which + ds->x1 <= oldlast) \ + if (which + drawseg->x1 >= oldtable && which + drawseg->x1 <= oldlast) \ which = (which - oldtable) + texturecolumntable - CHECK(ds->maskedtexturecol); - CHECK(ds->thicksidecol); + CHECK(drawseg->maskedtexturecol); + CHECK(drawseg->thicksidecol); #undef CHECK } } @@ -1778,6 +1778,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) INT32 range; vertex_t segleft, segright; fixed_t ceilingfrontslide, floorfrontslide, ceilingbackslide, floorbackslide; + const INT32 twosidedmidtexture = R_GetTextureNum(curline->sidedef->midtexture); drawcolumndata_t dc = {}; maskedtextureheight = NULL; @@ -2407,7 +2408,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) ds_p->numthicksides = numthicksides = i; } - if (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) + if (twosidedmidtexture) { // masked midtexture @@ -3018,13 +3019,13 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (!(ds_p->silhouette & SIL_TOP)) { ds_p->silhouette |= SIL_TOP; - ds_p->tsilheight = (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) ? INT32_MIN : INT32_MAX; + ds_p->tsilheight = (twosidedmidtexture) ? INT32_MIN : INT32_MAX; } if (!(ds_p->silhouette & SIL_BOTTOM)) { ds_p->silhouette |= SIL_BOTTOM; - ds_p->bsilheight = (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) ? INT32_MAX : INT32_MIN; + ds_p->bsilheight = (twosidedmidtexture) ? INT32_MAX : INT32_MIN; } } -- 2.54.0 From c1660757541440588beb1af829a6a41c4523125a Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Tue, 1 Aug 2023 19:04:47 -0300 Subject: [PATCH 015/219] Don't generate textures in R_GetColumn --- src/r_data.c | 7 ------- src/r_plane.cpp | 12 ++++-------- src/r_segs.cpp | 7 +++++++ 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index c6ffd6945..031be761b 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -535,13 +535,6 @@ static inline INT32 wrap_column(fixed_t tex, INT32 col) // UINT8 *R_GetColumn(fixed_t tex, INT32 col) { - if (!texturecache[tex]) - { - // This must be here because cache can be freed by other operations. - // To prevent must lock individual texture cache on every draw. - R_GenerateTexture(tex); - } - return texturecache[tex] + LONG(texturecolumnofs[tex][wrap_column(tex, col)]); } diff --git a/src/r_plane.cpp b/src/r_plane.cpp index e76b0374a..475e8a44d 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -785,6 +785,7 @@ static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), b } drawcolumndata_t dc = {}; + const INT32 texture = texturetranslation[skytexture]; // Reset column drawer function (note: couldn't we just call walldrawerfunc directly?) // (that is, unless we'll need to switch drawers in future for some reason) @@ -803,16 +804,13 @@ static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), b dc.colormap += COLORMAP_REMAPOFFSET; dc.texturemid = skytexturemid; - dc.texheight = textureheight[skytexture] >>FRACBITS; + dc.texheight = textureheight[texture] >>FRACBITS; dc.sourcelength = dc.texheight; x = pl->minx; // Precache the texture so we don't corrupt the zoned heap off-main thread - if (!texturecache[texturetranslation[skytexture]]) - { - R_GenerateTexture(texturetranslation[skytexture]); - } + R_CheckTextureCache(texture); #ifdef HAVE_THREADS while (x <= pl->maxx) @@ -837,9 +835,7 @@ static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), b dc.iscale = FixedMul(skyscale, FINECOSINE(xtoviewangle[x + i]>>ANGLETOFINESHIFT)); dc.x = x + i; - dc.source = - R_GetColumn(texturetranslation[skytexture], - -angle); // get negative of angle for each column to display sky correct way round! --Monster Iestyn 27/01/18 + dc.source = R_GetColumn(texture, -angle); // get negative of angle for each column to display sky correct way round! --Monster Iestyn 27/01/18 colfunc2(&dc); } diff --git a/src/r_segs.cpp b/src/r_segs.cpp index e6a603192..e62d1e4aa 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -1209,6 +1209,13 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) INT32 bottom; INT32 i; + if (midtexture) + R_CheckTextureCache(midtexture); + if (toptexture) + R_CheckTextureCache(toptexture); + if (bottomtexture) + R_CheckTextureCache(bottomtexture); + // Loop over width for (; rw_x < rw_stopx; rw_x++) { -- 2.54.0 From 0c56755e0958cbf486314418a9ae0cdde70f1892 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 5 Oct 2025 16:08:04 +0200 Subject: [PATCH 016/219] fix R_MarkSegBounds --- src/r_segs.cpp | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/r_segs.cpp b/src/r_segs.cpp index e62d1e4aa..25cf5157d 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -1221,8 +1221,9 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) { // mark floor / ceiling areas yl = (topfrac+HEIGHTUNIT-1)>>HEIGHTBITS; + yh = bottomfrac>>HEIGHTBITS; - // no space above wall? + // Mark ceiling top = ceilingclip[rw_x]+1; // no space above wall? @@ -1239,10 +1240,10 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) } } - yh = bottomfrac>>HEIGHTBITS; - + // Mark floor bottom = floorclip[rw_x]-1; + // no space below floor? if (yh > bottom) yh = bottom; @@ -1584,7 +1585,7 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) static void R_MarkSegBounds(void) { - INT32 yl, yh; + INT32 yl, yh; INT32 top, bottom; INT16 topclip, bottomclip; @@ -1593,8 +1594,9 @@ static void R_MarkSegBounds(void) { // mark floor / ceiling areas yl = (topfrac+HEIGHTUNIT-1)>>HEIGHTBITS; + yh = bottomfrac>>HEIGHTBITS; - // no space above wall? + // Mark ceiling top = ceilingclip[rw_x]+1; // no space above wall? @@ -1611,10 +1613,10 @@ static void R_MarkSegBounds(void) } } - yh = bottomfrac>>HEIGHTBITS; - + // Mark floor bottom = floorclip[rw_x]-1; + // no space below floor? if (yh > bottom) yh = bottom; @@ -1639,12 +1641,6 @@ static void R_MarkSegBounds(void) if (markfloor) // no bottom wall floorclip[rw_x] = bottomclip; - if ((markceiling || markfloor) && (floorclip[rw_x] <= ceilingclip[rw_x] + 1)) - { - solidcol[rw_x] = 1; - didsolidcol = true; - } - rw_scale += rw_scalestep; topfrac += topstep; bottomfrac += bottomstep; -- 2.54.0 From 953d9d15d6a73b73c6fc124175423b300733e8c8 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 3 Feb 2024 00:53:06 -0800 Subject: [PATCH 017/219] Clear g_dc each frame I was running into a memcpy of overlapping memory regions in R_RenderMaskedSegRange. - This is because of the reallocation of lightlists, which uses Z_Frame_Alloc. - The memory pool that Z_Frame_Alloc draws from is cleared each frame. - g_dc was not cleared though, so when the lightlists were reallocated, it'd try to copy from invalidated pointers. - Access to invalid pointers within the memory pool does not cause a segfault directly (because the memory pool is allocated once). However, a memcpy involving such an invalid pointer leads to overlap, which may cause memory corruption. --- src/d_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/d_main.c b/src/d_main.c index 39951f70c..e2bf44008 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -774,6 +774,7 @@ void D_SRB2Loop(void) precise_t capbudget; precise_t enterprecise = I_GetPreciseTime(); + memset(&g_dc, 0, sizeof(g_dc)); Z_Frame_Reset(); // Casting the return value of a function is bad practice (apparently) -- 2.54.0 From 6be5478fa84e37b3adc39270b8e65440a95d9c80 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 5 Oct 2025 16:55:56 +0200 Subject: [PATCH 018/219] dont free levelstate in D_ClearState Titledemos be damned! --- src/d_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_main.c b/src/d_main.c index e2bf44008..fd3e93649 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1027,7 +1027,7 @@ void D_ClearState(void) S_StopSounds(); S_ResetKeepAndSpecialMus(); // just in case - P_FreeLevelState(); + //P_FreeLevelState(); G_SetGamestate(GS_NULL); wipegamestate = GS_NULL; -- 2.54.0 From 48722ef59131086574dbd40502c7c8bea822aa08 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 5 Oct 2025 17:14:31 +0200 Subject: [PATCH 019/219] fix oob access in CV_AddValue and M_CanShowLevelInList lets hope this doesent break anything Zzz.... --- src/command.c | 4 ++-- src/m_menu.c | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/command.c b/src/command.c index 292c51861..341e57ce5 100644 --- a/src/command.c +++ b/src/command.c @@ -1771,7 +1771,7 @@ void CV_AddValue(consvar_t *var, INT32 increment) newvalue = var->value - 1; do { - if(increment > 0) // Going up! + if (increment > 0) // Going up! { if (++newvalue == NUMMAPS) newvalue = -1; @@ -1785,7 +1785,7 @@ void CV_AddValue(consvar_t *var, INT32 increment) if (newvalue == oldvalue) break; // don't loop forever if there's none of a certain gametype - if(!mapheaderinfo[newvalue]) + if (newvalue >= 0 && !mapheaderinfo[newvalue]) continue; // Don't allocate the header. That just makes memory usage skyrocket. } while (!M_CanShowLevelInList(newvalue, gt)); diff --git a/src/m_menu.c b/src/m_menu.c index af63de94f..95824c7dd 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -2713,6 +2713,10 @@ static void M_PrepareLevelSelect(void) // boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt) { + // invalid mapnum + if (mapnum < -1) + return false; + // Random map! if (mapnum == -1) return (gamestate != GS_TIMEATTACK && !modeattacking); @@ -7220,7 +7224,7 @@ static void M_DrawLevelSelectOnly(boolean leftfade, boolean rightfade) if (i == oldval) return; - if(!mapheaderinfo[i]) + if (i >= 0 && !mapheaderinfo[i]) continue; // Don't allocate the header. That just makes memory usage skyrocket. } while (!M_CanShowLevelInList(i, cv_newgametype.value)); @@ -7258,7 +7262,7 @@ static void M_DrawLevelSelectOnly(boolean leftfade, boolean rightfade) if (i == oldval) return; - if(!mapheaderinfo[i]) + if (i >= 0 && !mapheaderinfo[i]) continue; // Don't allocate the header. That just makes memory usage skyrocket. } while (!M_CanShowLevelInList(i, cv_newgametype.value)); -- 2.54.0 From 79140b3bdcf20115f40b876fc57dc4675e390f77 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 5 Oct 2025 17:37:58 +0200 Subject: [PATCH 020/219] fix oopsie in R_GenerateTexture --- src/r_data.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index 031be761b..5946ff336 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -241,11 +241,12 @@ static INT32 tidcachelen = 0; // R_DrawColumnInCache // Clip and draw a column from a patch into a cached post. // -static inline void R_DrawColumnInCache(column_t *patch, UINT8 *cache, INT32 originy, INT32 cacheheight) +static inline void R_DrawColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight) { INT32 count, position; UINT8 *source; INT32 topdelta, prevdelta = -1; + INT32 originy = originPatch->originy; while (patch->topdelta != 0xff) { @@ -374,7 +375,7 @@ UINT8 *R_GenerateTexture(size_t texnum) return block; } - pdata = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_LEVEL); + pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_LEVEL); realpatch = (softwarepatch_t *)pdata; // Check the patch for holes. @@ -383,7 +384,7 @@ UINT8 *R_GenerateTexture(size_t texnum) colofs = (UINT8 *)realpatch->columnofs; - for (x = 0; x < texture->width; x++) + for (x = 0; x < texture->width && !holey; x++) { column_t *col = (column_t *)((UINT8 *)realpatch + LONG(*(UINT32 *)&colofs[x<<2])); @@ -483,7 +484,7 @@ UINT8 *R_GenerateTexture(size_t texnum) // generate column ofset lookup *(UINT32 *)&colofs[x<<2] = LONG((x * texture->height) + (texture->width*4)); - R_DrawColumnInCache(patchcol, block + LONG(*(UINT32 *)&colofs[x<<2]), patch->originy, texture->height); + R_DrawColumnInCache(patchcol, block + LONG(*(UINT32 *)&colofs[x<<2]), patch, texture->height); } } -- 2.54.0 From f817676033a5234f2fe9b4b15ae690545f4637a9 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 5 Oct 2025 18:33:54 +0200 Subject: [PATCH 021/219] fix uninitialized "i" counter in R_StoreWallRange --- src/r_segs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_segs.cpp b/src/r_segs.cpp index 25cf5157d..c83b45593 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -1775,7 +1775,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) angle_t distangle, offsetangle; boolean longboi; INT32 lightnum; - INT32 i, p; + INT32 i = 0, p; lightlist_t *light; r_lightlist_t *rlight; INT32 range; -- 2.54.0 From 005af4362e76bbfad124beec4e96cd697bfa8093 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 5 Oct 2025 20:08:20 +0200 Subject: [PATCH 022/219] remove unused W_LumpLenghtPwad call from R_GenerateTexture --- src/r_data.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index 5946ff336..ec866b79e 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -375,7 +375,7 @@ UINT8 *R_GenerateTexture(size_t texnum) return block; } - pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_LEVEL); + pdata = (UINT8*)W_CacheLumpNumPwad(wadnum, lumpnum, PU_LEVEL); realpatch = (softwarepatch_t *)pdata; // Check the patch for holes. @@ -450,8 +450,7 @@ UINT8 *R_GenerateTexture(size_t texnum) { wadnum = patch->wad; lumpnum = patch->lump; - pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_LEVEL); - lumplength = W_LumpLengthPwad(wadnum, lumpnum); + pdata = (UINT8*)W_CacheLumpNumPwad(wadnum, lumpnum, PU_LEVEL); realpatch = (softwarepatch_t *)pdata; x1 = patch->originx; -- 2.54.0 From 3964d4e1880d92d256eee928f45a1353813ac091 Mon Sep 17 00:00:00 2001 From: Indev Date: Sun, 5 Oct 2025 21:12:46 +0300 Subject: [PATCH 023/219] Always initialize all column offsets inside multi-patch textures --- src/r_data.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index ec866b79e..ab704675c 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -445,6 +445,12 @@ UINT8 *R_GenerateTexture(size_t texnum) // texture data after the lookup table blocktex = block + (texture->width*4); + for (x = 0; x < texture->width; ++x) + { + // generate column ofset lookup + *(UINT32 *)&colofs[x<<2] = LONG((x * texture->height) + (texture->width*4)); + } + // Composite the columns together. for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++) { @@ -481,8 +487,6 @@ UINT8 *R_GenerateTexture(size_t texnum) { patchcol = (column_t *)((UINT8 *)realpatch + LONG(realpatch->columnofs[x-x1])); - // generate column ofset lookup - *(UINT32 *)&colofs[x<<2] = LONG((x * texture->height) + (texture->width*4)); R_DrawColumnInCache(patchcol, block + LONG(*(UINT32 *)&colofs[x<<2]), patch, texture->height); } } -- 2.54.0 From 9e8ddd5f9eb922dabbee5975de6281f33113e704 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 5 Oct 2025 20:38:58 +0200 Subject: [PATCH 024/219] add a print to Joinable_OnChange also change the other cvar messages to CONS_NOTICE --- src/command.c | 19 +++++++++---------- src/d_clisrv.c | 3 +++ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/command.c b/src/command.c index 341e57ce5..ee3b36247 100644 --- a/src/command.c +++ b/src/command.c @@ -1650,13 +1650,13 @@ static void CV_SetCVar(consvar_t *var, const char *value, boolean stealth) UINT8 *p = buf; if (!(server || (IsPlayerAdmin(consoleplayer)))) { - CONS_Printf(M_GetText("Only the server or admin can change: %s %s\n"), var->name, var->string); + CONS_Alert(CONS_NOTICE, "Only the server or admin can change: %s %s\n", var->name, var->string); return; } if (var == &cv_kartencore && !M_SecretUnlocked(SECRET_ENCORE)) { - CONS_Printf(M_GetText("You haven't unlocked Encore Mode yet!\n")); + CONS_Alert(CONS_NOTICE, "You haven't unlocked Encore Mode yet!\n"); return; } @@ -1664,7 +1664,7 @@ static void CV_SetCVar(consvar_t *var, const char *value, boolean stealth) { if (!stricmp(value, "Hard") || atoi(value) == 2) { - CONS_Printf(M_GetText("You haven't unlocked this yet!\n")); + CONS_Alert(CONS_NOTICE, "You haven't unlocked this yet!\n"); return; } } @@ -1681,14 +1681,13 @@ static void CV_SetCVar(consvar_t *var, const char *value, boolean stealth) else Setvalue(var, value, stealth); } + else if ((var->flags & CV_NOTINNET) && netgame) + { + CONS_Alert(CONS_NOTICE, "This variable can't be changed while in netgame: %s %s\n", var->name, var->string); + return; + } else - if ((var->flags & CV_NOTINNET) && netgame) - { - CONS_Printf(M_GetText("This variable can't be changed while in netgame: %s %s\n"), var->name, var->string); - return; - } - else - Setvalue(var, value, stealth); + Setvalue(var, value, stealth); } /** Sets a value to a variable without calling its callback function. diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 9c9d95322..a62ebde7c 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -4161,7 +4161,10 @@ static void Joinable_OnChange(void) UINT8 maxplayer; if (!server) + { + CONS_Alert(CONS_NOTICE, ("Only the server can change: %s %s\n"), cv_allownewplayer.name, cv_allownewplayer.string); return; + } #ifdef SATURNJOIN // disabling joins should also disable saturn joins unless its called with CV_StealthSet and vice versa to make life a bit easier -- 2.54.0 From 0bbd8246cc9c9950e7087152df25235efd9ee052 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 15 Dec 2021 14:02:56 -0800 Subject: [PATCH 025/219] Read only header bytes when creating textures list R_LoadTextures was reading in the entirety of every texture lump, now it only reads the 8 byte PNG header. This saved more than 1 second for me (1.68 s -> 0.24 s). PNG still need to be read in entirely to check their dimensions; I didn't bother looking into optimizing it since we don't have many PNG textures right now. --- src/r_data.c | 10 ++++------ src/r_patch.h | 2 ++ src/r_things.cpp | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index ab704675c..6c999d1ae 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -573,9 +573,9 @@ Rloadtextures (INT32 i, INT32 w) { UINT16 j, numlumps = 0; UINT16 texstart, texend, texturesLumpPos; - softwarepatch_t *patchlump; texpatch_t *patch; texture_t *texture; + softwarepatch_t patchlump; // Get the lump numbers for the markers in the WAD, if they exist. if (W_FileHasFolders(wadfiles[w])) @@ -615,7 +615,7 @@ Rloadtextures (INT32 i, INT32 w) continue; // If it is then SKIP IT } - patchlump = (softwarepatch_t *)W_CacheLumpNumPwad(wadnum, lumpnum, PU_STATIC); + W_ReadLumpHeaderPwad(wadnum, lumpnum, &patchlump, PNG_HEADER_SIZE, 0); //CONS_Printf("\n\"%s\" is a single patch, dimensions %d x %d",W_CheckNameForNumPwad((wadnum, lumpnum), patchlump->width, patchlump->height); texture = textures[i] = Z_Calloc(sizeof(texture_t) + sizeof(texpatch_t), PU_STATIC, NULL); @@ -624,8 +624,8 @@ Rloadtextures (INT32 i, INT32 w) M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name)); texture->hash = quickncasehash(texture->name, 8); - texture->width = SHORT(patchlump->width); - texture->height = SHORT(patchlump->height); + texture->width = SHORT(patchlump.width); + texture->height = SHORT(patchlump.height); texture->type = TEXTURETYPE_SINGLEPATCH; texture->patchcount = 1; @@ -638,8 +638,6 @@ Rloadtextures (INT32 i, INT32 w) patch->wad = wadnum; patch->lump = texstart + j; - Z_Free(patchlump); - texturewidth[i] = texture->width; textureheight[i] = texture->height << FRACBITS; i++; diff --git a/src/r_patch.h b/src/r_patch.h index 2dc9c2f4e..4d44b5416 100644 --- a/src/r_patch.h +++ b/src/r_patch.h @@ -36,6 +36,8 @@ typedef struct boolean available; } spriteinfo_t; +#define PNG_HEADER_SIZE (8) + // Patch functions patch_t *Patch_Create(softwarepatch_t *source, size_t srcsize, void *dest); void Patch_Free(patch_t *patch); diff --git a/src/r_things.cpp b/src/r_things.cpp index 8229369a7..4713bc50e 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -312,7 +312,7 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 // store sprite info in lookup tables //FIXME : numspritelumps do not duplicate sprite replacements - W_ReadLumpHeaderPwad(wadnum, l, &patch, (sizeof(INT16) *4), 0); + W_ReadLumpHeaderPwad(wadnum, l, &patch, PNG_HEADER_SIZE, 0); spritecachedinfo[numspritelumps].width = (INT32)(SHORT(patch.width))< Date: Mon, 6 Oct 2025 17:44:47 +0300 Subject: [PATCH 026/219] Don't I_Error in W_InitFileError, that causes dedicated servers to bootloop --- src/w_wad.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/w_wad.c b/src/w_wad.c index 4a993a7f4..1cfb3f616 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -45,6 +45,7 @@ #include "w_wad.h" #include "z_zone.h" #include "fastcmp.h" +#include "console.h" #include "g_game.h" // G_LoadGameData #include "d_main.h" @@ -760,11 +761,7 @@ static UINT16 W_InitFileError(const char *filename, boolean exitworthy) { if (exitworthy) { -#ifdef _DEBUG CONS_Error(va("%s was not found or not valid.\nCheck the log for more details.\n", filename)); -#else - I_Error("%s was not found or not valid.\nCheck the log for more details.\n", filename); -#endif } else CONS_Printf(M_GetText("Errors occurred while loading %s; not added.\n"), filename); -- 2.54.0 From 031e8ee47797efbd7cb2a2c20cc6def3ce13d8ca Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 6 Oct 2025 18:14:59 +0200 Subject: [PATCH 027/219] WIP: column buffering/flushing system it "works" so far no performance improvement everything but fully opague columns dont work for now until fixed really messy and needs to be templated when working from prboom & eternity engine --- src/r_draw.h | 3 + src/r_draw_column.cpp | 183 ++++++++++++- src/r_draw_flush.cpp | 599 ++++++++++++++++++++++++++++++++++++++++++ src/r_main.cpp | 4 + src/r_plane.cpp | 11 +- 5 files changed, 783 insertions(+), 17 deletions(-) create mode 100644 src/r_draw_flush.cpp diff --git a/src/r_draw.h b/src/r_draw.h index bcd734e50..232e6c8ce 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -252,6 +252,9 @@ void R_Draw2sMultiPatchTranslucentColumn(drawcolumndata_t* dc); void R_DrawFogColumn(drawcolumndata_t* dc); +void R_ResetColumnBuffer(void); +void R_DrawSkyColumn(drawcolumndata_t *dc); + // span drawers void R_DrawSpan(drawspandata_t* ds); diff --git a/src/r_draw_column.cpp b/src/r_draw_column.cpp index bae220e6d..ccb5c5403 100644 --- a/src/r_draw_column.cpp +++ b/src/r_draw_column.cpp @@ -21,6 +21,8 @@ // a has a constant z depth from top to bottom. // +#include "r_draw_flush.cpp" + enum DrawColumnType { DC_BASIC = 0x0000, @@ -69,7 +71,9 @@ static constexpr UINT8 R_DrawColumnPixel(drawcolumndata_t* dc, UINT8 * restrict } } - return R_GetColumnTranslucent(dc, dest, col, colormap); + //return R_GetColumnTranslucent(dc, dest, col, colormap); + // dont return any other shit for now + return col; } /** \brief The R_DrawColumn function @@ -150,6 +154,7 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) } R_DrawColumnTemplate(&dc_copy); + if (solid) { dc_copy.yl = bheight; @@ -184,16 +189,25 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) intptr_t frac; const intptr_t fracstep = dc->iscale; - const intptr_t heightmask = dc->sourcelength-1; + const intptr_t heightmask = dc->sourcelength-1; // CPhipps - specify type constexpr INT32 npow2min = -1; const INT32 npow2max = dc->sourcelength; - const INT32 stride = vid.width; const UINT8 * restrict source = dc->source; const lighttable_t * restrict colormap = dc->colormap; + UINT8 * restrict dest; + // Framebuffer destination address. - UINT8 * restrict dest = R_Address(dc->x, dc->yl); + // SoM: MAGIC + /*if constexpr (Type & (DrawColumnType::DC_COLORMAP | DrawColumnType::DC_TRANSMAP)) + dest = R_GetBufferColormapTrans(dc); + else if constexpr (Type & DrawColumnType::DC_TRANSMAP) + dest = R_GetBufferTrans(dc); + else if constexpr (Type & DrawColumnType::DC_COLORMAP) + dest = R_GetBufferColormap(dc); + else*/ + dest = R_GetBufferOpaque(dc); count++; @@ -205,15 +219,15 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) case 255: case 127: { - while(count--) + while (count--) { *dest = R_DrawColumnPixel(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap); - dest += stride; + dest += 4; frac += fracstep; } } break; - case -1: + case npow2min: { if (frac < 0) // adjust in case we underread @@ -223,7 +237,7 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) while (--count >= 0) { *dest = R_DrawColumnPixel(dc, dest, frac>>FRACBITS, source, colormap); - dest += stride; + dest += 4; frac += fracstep; } } @@ -235,11 +249,11 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) while ((count -= 2) >= 0) // texture height is a power of 2 -- killough { *dest = R_DrawColumnPixel(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap); - dest += stride; + dest += 4; frac += fracstep; *dest = R_DrawColumnPixel(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap); - dest += stride; + dest += 4; frac += fracstep; } @@ -277,7 +291,7 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) // and a few bytes after as well *dest = R_DrawColumnPixel(dc, dest, CLAMP((frac >> FRACBITS), npow2min, npow2max), source, colormap); - dest += stride; + dest += 4; #if __SIZEOF_POINTER__ < 8 // 64-bit systems have large enough numbers for this to be a non-issue // Avoid overflow. @@ -354,3 +368,150 @@ void R_DrawFogColumn(drawcolumndata_t* dc) dest += stride; } while (count--); } + +// blunt copy paste for now +// cant share a global buffer between threads for obvious reasons lmao +void R_DrawSkyColumn(drawcolumndata_t *dc) +{ + INT32 count; + + count = dc->yh - dc->yl; + + if (count < 0) // Zero length, column does not exceed a pixel. + { + return; + } + + if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height) + { + return; + } + + { + // Inner loop that does the actual texture mapping, + // e.g. a DDA-lile scaling. + // This is as fast as it gets. (Yeah, right!!! -- killough) + // + // killough 2/1/98: more performance tuning + + intptr_t frac; + const intptr_t fracstep = dc->iscale; + const intptr_t heightmask = dc->sourcelength-1; + constexpr INT32 npow2min = -1; + const INT32 npow2max = dc->sourcelength; + const INT32 stride = vid.width; + + const UINT8 * restrict source = dc->source; + const lighttable_t * restrict colormap = dc->colormap; + + // Framebuffer destination address. + UINT8 * restrict dest = R_Address(dc->x, dc->yl); + + count++; + + // Determine scaling, which is the only mapping to be done. + frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep)); + + switch (heightmask) + { + case 255: + case 127: + { + while(count--) + { + *dest = R_DrawColumnPixel(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap); + dest += stride; + frac += fracstep; + } + } + break; + case -1: + { + if (frac < 0) + // adjust in case we underread + frac += fracstep; + + // texture has no height, so just go + while (--count >= 0) + { + *dest = R_DrawColumnPixel(dc, dest, frac>>FRACBITS, source, colormap); + dest += stride; + frac += fracstep; + } + } + break; + default: + { + if (!(dc->sourcelength & heightmask)) // power of 2 -- killough + { + while ((count -= 2) >= 0) // texture height is a power of 2 -- killough + { + *dest = R_DrawColumnPixel(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap); + dest += stride; + frac += fracstep; + + *dest = R_DrawColumnPixel(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap); + dest += stride; + frac += fracstep; + } + + if (count & 1) + { + *dest = R_DrawColumnPixel(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap); + } + } + else + { + const intptr_t fixed_heightmask = dc->texheight << FRACBITS; + + if (frac < 0) + { + while ((frac += fixed_heightmask) < 0) + { + ; + } + } + else + { + while (frac >= fixed_heightmask) + { + frac -= fixed_heightmask; + } + } + + do + { + // Re-map color indices from wall texture column + // using a lighting/special effects LUT. + // heightmask is the Tutti-Frutti fix + + // -1 is the lower clamp bound because column posts have a "safe" byte before the real data + // and a few bytes after as well + *dest = R_DrawColumnPixel(dc, dest, CLAMP((frac >> FRACBITS), npow2min, npow2max), source, colormap); + + dest += stride; + +#if __SIZEOF_POINTER__ < 8 // 64-bit systems have large enough numbers for this to be a non-issue + // Avoid overflow. + if (fracstep > 0x7FFFFFFF - frac) + { + frac += fracstep - fixed_heightmask; + } + else +#endif + { + frac += fracstep; + } + + while (frac >= fixed_heightmask) + { + frac -= fixed_heightmask; + } + } + while (--count); + } + } + break; + } + } +} diff --git a/src/r_draw_flush.cpp b/src/r_draw_flush.cpp new file mode 100644 index 000000000..657e185b5 --- /dev/null +++ b/src/r_draw_flush.cpp @@ -0,0 +1,599 @@ +// SONIC ROBO BLAST 2 KART +//----------------------------------------------------------------------------- +// Copyright (C) 2025 by Kart Krew. +// Copyright (C) 2020 by Sonic Team Junior. +// Copyright (C) 2000 by DooM Legacy Team. +// Copyright (C) 1996 by id Software, Inc. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file r_draw_flush.cpp +/// \brief column flush functions +/// \note no includes because this is included as part of r_draw.cpp + +enum ColumnFlushType +{ + FLUSH_NONE, + FLUSH_OPAQUE, + FLUSH_TRANS, + FLUSH_COLORMAP, + FLUSH_COLORMAP_TRANS +}; + +static int temp_x = 0; +static int tempyl[4], tempyh[4]; +static UINT8 tempbuf[MAXVIDWIDTH * 4]; +static int startx = 0; +static int commontop, commonbot; +static ColumnFlushType temptype = FLUSH_NONE; +static const UINT8 *temptranmap = NULL; +static const UINT8 *temptranslation = NULL; + +static void R_FlushColumns(void); + +static void R_FlushWholeError(void) +{ + I_Error("R_FlushWholeColumns called without being initialized.\n"); +} + +static void R_FlushHTError(void) +{ + I_Error("R_FlushHTColumns called without being initialized.\n"); +} + +static void R_QuadFlushError(void) +{ + I_Error("R_FlushQuadColumn called without being initialized.\n"); +} + +// +// R_FlushWholeOpaque +// +// Flushes the entire columns in the buffer, one at a time. +// This is used when a quad flush isn't possible. +// Opaque version -- no remapping whatsoever. +// +static void R_FlushWholeOpaque(void) +{ + UINT8 *source; + UINT8 *dest; + INT32 count, yl; + const restrict INT32 stride = vid.width; + + while (--temp_x >= 0) + { + yl = tempyl[temp_x]; + source = &tempbuf[temp_x + (yl << 2)]; + dest = R_Address(startx + temp_x, yl); + count = tempyh[temp_x] - yl + 1; + + while (--count >= 0) + { + *dest = *source; + source += 4; + dest += stride; + } + } +} + +// +// R_FlushHTOpaque +// +// Flushes the head and tail of columns in the buffer in +// preparation for a quad flush. +// Opaque version -- no remapping whatsoever. +// +static void R_FlushHTOpaque(void) +{ + UINT8 *source; + UINT8 *dest; + INT32 count, colnum = 0; + INT32 yl, yh; + const restrict INT32 stride = vid.width; + + while (colnum < 4) + { + yl = tempyl[colnum]; + yh = tempyh[colnum]; + + // flush column head + if (yl < commontop) + { + source = &tempbuf[colnum + (yl << 2)]; + dest = R_Address(startx + colnum, yl); + count = commontop - yl; + + while (--count >= 0) + { + *dest = *source; + source += 4; + dest += stride; + } + } + + // flush column tail + if (yh > commonbot) + { + source = &tempbuf[colnum + ((commonbot + 1) << 2)]; + dest = R_Address(startx + colnum, commonbot + 1); + count = yh - commonbot; + + while (--count >= 0) + { + *dest = *source; + source += 4; + dest += stride; + } + } + ++colnum; + } +} + +static void R_FlushQuadOpaque(void) +{ + UINT8 *source = &tempbuf[commontop << 2]; + UINT8 *dest = R_Address(startx, commontop); + INT32 count; + const restrict INT32 stride = vid.width; + + count = commonbot - commontop + 1; + + if ((sizeof(int) == 4) && (((intptr_t)source % 4) == 0) && (((intptr_t)dest % 4) == 0)) + { + while(--count >= 0) + { + *(int *)dest = *(int *)source; + source += 4 * sizeof(UINT8); + dest += stride * sizeof(UINT8); + } + } + else + { + while(--count >= 0) + { + dest[0] = source[0]; + dest[1] = source[1]; + dest[2] = source[2]; + dest[3] = source[3]; + source += 4 * sizeof(UINT8); + dest += stride * sizeof(UINT8); + } + } + + while(--count >= 0) + { + dest[0] = source[0]; + dest[1] = source[1]; + dest[2] = source[2]; + dest[3] = source[3]; + source += 4 * sizeof(UINT8); + dest += stride * sizeof(UINT8); + } +} + +static void R_FlushWholeTrans(void) +{ + UINT8 *source; + UINT8 *dest; + INT32 count, yl; + const restrict INT32 stride = vid.width; + + while (--temp_x >= 0) + { + yl = tempyl[temp_x]; + source = &tempbuf[temp_x + (yl << 2)]; + dest = R_Address(startx + temp_x, yl); + count = tempyh[temp_x] - yl + 1; + + while (--count >= 0) + { + *dest = temptranmap[(*dest << 8) + *source]; + source += 4; + dest += stride; + } + } +} + +static void R_FlushHTTrans(void) +{ + UINT8 *source; + UINT8 *dest; + INT32 count; + INT32 colnum = 0, yl, yh; + const restrict INT32 stride = vid.width; + + while (colnum < 4) + { + yl = tempyl[colnum]; + yh = tempyh[colnum]; + + // flush column head + if (yl < commontop) + { + source = &tempbuf[colnum + (yl << 2)]; + dest = R_Address(startx + colnum, yl); + count = commontop - yl; + + while (--count >= 0) + { + *dest = temptranmap[(*dest << 8) + *source]; + source += 4; + dest += stride; + } + } + + // flush column tail + if (yh > commonbot) + { + source = &tempbuf[colnum + ((commonbot + 1) << 2)]; + dest = R_Address(startx + colnum, commonbot + 1); + count = yh - commonbot; + + while (--count >= 0) + { + *dest = temptranmap[(*dest << 8) + *source]; + source += 4; + dest += stride; + } + } + + ++colnum; + } +} + +static void R_FlushQuadTrans(void) +{ + UINT8 *source = &tempbuf[commontop << 2]; + UINT8 *dest = R_Address(startx, commontop); + INT32 count; + const restrict INT32 stride = vid.width; + + count = commonbot - commontop + 1; + + while (--count >= 0) + { + dest[0] = temptranmap[(dest[0] << 8) + source[0]]; + dest[1] = temptranmap[(dest[1] << 8) + source[1]]; + dest[2] = temptranmap[(dest[2] << 8) + source[2]]; + dest[3] = temptranmap[(dest[3] << 8) + source[3]]; + source += 4; + dest += stride; + } +} + +static void R_FlushWholeColormap(void) +{ + UINT8 *source; + UINT8 *dest; + INT32 count, yl; + const restrict INT32 stride = vid.width; + + while (--temp_x >= 0) + { + yl = tempyl[temp_x]; + source = &tempbuf[temp_x + (yl << 2)]; + dest = R_Address(startx + temp_x, yl); + count = tempyh[temp_x] - yl + 1; + + while (--count >= 0) + { + *dest = temptranslation[*source]; + source += 4; + dest += stride; + } + } +} + +static void R_FlushHTColormap(void) +{ + UINT8 *source; + UINT8 *dest; + INT32 count; + INT32 colnum = 0, yl, yh; + const restrict INT32 stride = vid.width; + + while (colnum < 4) + { + yl = tempyl[colnum]; + yh = tempyh[colnum]; + + // flush column head + if (yl < commontop) + { + source = &tempbuf[colnum + (yl << 2)]; + dest = R_Address(startx + colnum, yl); + count = commontop - yl; + + while (--count >= 0) + { + *dest = temptranslation[*source]; + source += 4; + dest += stride; + } + } + + // flush column tail + if (yh > commonbot) + { + source = &tempbuf[colnum + ((commonbot + 1) << 2)]; + dest = R_Address(startx + colnum, commonbot + 1); + count = yh - commonbot; + + while (--count >= 0) + { + *dest = temptranslation[*source]; + source += 4; + dest += stride; + } + } + + ++colnum; + } +} + +static void R_FlushQuadColormap(void) +{ + UINT8 *source = &tempbuf[commontop << 2]; + UINT8 *dest = R_Address(startx, commontop); + INT32 count; + const restrict INT32 stride = vid.width; + + count = commonbot - commontop + 1; + + while (--count >= 0) + { + dest[0] = temptranslation[source[0]]; + dest[1] = temptranslation[source[1]]; + dest[2] = temptranslation[source[2]]; + dest[3] = temptranslation[source[3]]; + source += 4; + dest += stride; + } +} + +static void R_FlushWholeColormapTrans(void) +{ + UINT8 *source; + UINT8 *dest; + INT32 count, yl; + const restrict INT32 stride = vid.width; + + while (--temp_x >= 0) + { + yl = tempyl[temp_x]; + source = &tempbuf[temp_x + (yl << 2)]; + dest = R_Address(startx + temp_x, yl); + count = tempyh[temp_x] - yl + 1; + + while (--count >= 0) + { + *dest = temptranmap[(*dest << 8) + temptranslation[*source]]; + source += 4; + dest += stride; + } + } +} + +static void R_FlushHTColormapTrans(void) +{ + UINT8 *source; + UINT8 *dest; + INT32 count; + INT32 colnum = 0, yl, yh; + const restrict INT32 stride = vid.width; + + while (colnum < 4) + { + yl = tempyl[colnum]; + yh = tempyh[colnum]; + + // flush column head + if (yl < commontop) + { + source = &tempbuf[colnum + (yl << 2)]; + dest = R_Address(startx + colnum, yl); + count = commontop - yl; + + while (--count >= 0) + { + *dest = temptranmap[(*dest << 8) + temptranslation[*source]]; + source += 4; + dest += stride; + } + } + + // flush column tail + if (yh > commonbot) + { + source = &tempbuf[colnum + ((commonbot + 1) << 2)]; + dest = R_Address(startx + colnum, commonbot + 1); + count = yh - commonbot; + + while (--count >= 0) + { + *dest = temptranmap[(*dest << 8) + temptranslation[*source]]; + source += 4; + dest += stride; + } + } + + ++colnum; + } +} + +static void R_FlushQuadColormapTrans(void) +{ + UINT8 *source = &tempbuf[commontop << 2]; + UINT8 *dest = R_Address(startx, commontop); + INT32 count; + const restrict INT32 stride = vid.width; + + count = commonbot - commontop + 1; + + while (--count >= 0) + { + dest[0] = temptranmap[(dest[0] << 8) + temptranslation[source[0]]]; + dest[1] = temptranmap[(dest[1] << 8) + temptranslation[source[1]]]; + dest[2] = temptranmap[(dest[2] << 8) + temptranslation[source[2]]]; + dest[3] = temptranmap[(dest[3] << 8) + temptranslation[source[3]]]; + source += 4; + dest += stride; + } +} + +static void (*R_FlushWholeColumns)(void) = R_FlushWholeError; +static void (*R_FlushHTColumns)(void) = R_FlushHTError; +static void (*R_FlushQuadColumn)(void) = R_QuadFlushError; + +static void R_FlushColumns(void) +{ + if (temp_x != 4 || commontop >= commonbot) + R_FlushWholeColumns(); + else + { + R_FlushHTColumns(); + R_FlushQuadColumn(); + } + + temp_x = 0; +} + +// +// R_ResetColumnBuffer +// +void R_ResetColumnBuffer(void) +{ + if (temp_x) + R_FlushColumns(); + + temptype = FLUSH_NONE; + R_FlushWholeColumns = R_FlushWholeError; + R_FlushHTColumns = R_FlushHTError; + R_FlushQuadColumn = R_QuadFlushError; +} + +static UINT8 *R_GetBufferOpaque(drawcolumndata_t *dc) +{ + if (temp_x == 4 || + (temp_x && (temptype != FLUSH_OPAQUE || temp_x + startx != dc->x))) + R_FlushColumns(); + + if (!temp_x) + { + startx = dc->x; + tempyl[0] = commontop = dc->yl; + tempyh[0] = commonbot = dc->yh; + temptype = FLUSH_OPAQUE; + R_FlushWholeColumns = R_FlushWholeOpaque; + R_FlushHTColumns = R_FlushHTOpaque; + R_FlushQuadColumn = R_FlushQuadOpaque; + temp_x += 1; + return &tempbuf[dc->yl << 2]; + } + + tempyl[temp_x] = dc->yl; + tempyh[temp_x] = dc->yh; + + if (dc->yl > commontop) + commontop = dc->yl; + if (dc->yh < commonbot) + commonbot = dc->yh; + + return &tempbuf[(dc->yl << 2) + temp_x++]; +} + +static UINT8 *R_GetBufferTrans(drawcolumndata_t *dc) +{ + if (temp_x == 4 || dc->transmap != temptranmap || + (temp_x && (temptype != FLUSH_TRANS || temp_x + startx != dc->x))) + R_FlushColumns(); + + if (!temp_x) + { + startx = dc->x; + tempyl[0] = commontop = dc->yl; + tempyh[0] = commonbot = dc->yh; + temptype = FLUSH_TRANS; + temptranmap = dc->transmap; + R_FlushWholeColumns = R_FlushWholeTrans; + R_FlushHTColumns = R_FlushHTTrans; + R_FlushQuadColumn = R_FlushQuadTrans; + temp_x += 1; + return &tempbuf[dc->yl << 2]; + } + + tempyl[temp_x] = dc->yl; + tempyh[temp_x] = dc->yh; + + if (dc->yl > commontop) + commontop = dc->yl; + if (dc->yh < commonbot) + commonbot = dc->yh; + + return &tempbuf[(dc->yl << 2) + temp_x++]; +} + +static UINT8 *R_GetBufferColormap(drawcolumndata_t *dc) +{ + if (temp_x == 4 || dc->translation != temptranslation || + (temp_x && (temptype != FLUSH_COLORMAP || temp_x + startx != dc->x))) + R_FlushColumns(); + + if (!temp_x) + { + startx = dc->x; + tempyl[0] = commontop = dc->yl; + tempyh[0] = commonbot = dc->yh; + temptype = FLUSH_COLORMAP; + temptranslation = dc->translation; + R_FlushWholeColumns = R_FlushWholeColormap; + R_FlushHTColumns = R_FlushHTColormap; + R_FlushQuadColumn = R_FlushQuadColormap; + temp_x += 1; + return &tempbuf[dc->yl << 2]; + } + + tempyl[temp_x] = dc->yl; + tempyh[temp_x] = dc->yh; + + if (dc->yl > commontop) + commontop = dc->yl; + if (dc->yh < commonbot) + commonbot = dc->yh; + + return &tempbuf[(dc->yl << 2) + temp_x++]; +} + +static UINT8 *R_GetBufferColormapTrans(drawcolumndata_t *dc) +{ + if (temp_x == 4 || dc->translation != temptranslation || dc->transmap != temptranmap || + (temp_x && (temptype != FLUSH_COLORMAP_TRANS || temp_x + startx != dc->x))) + R_FlushColumns(); + + if (!temp_x) + { + startx = dc->x; + tempyl[0] = commontop = dc->yl; + tempyh[0] = commonbot = dc->yh; + temptype = FLUSH_COLORMAP_TRANS; + temptranslation = dc->translation; + temptranmap = dc->transmap; + R_FlushWholeColumns = R_FlushWholeColormapTrans; + R_FlushHTColumns = R_FlushHTColormapTrans; + R_FlushQuadColumn = R_FlushQuadColormapTrans; + temp_x += 1; + return &tempbuf[dc->yl << 2]; + } + + tempyl[temp_x] = dc->yl; + tempyh[temp_x] = dc->yh; + + if (dc->yl > commontop) + commontop = dc->yl; + if (dc->yh < commonbot) + commonbot = dc->yh; + + return &tempbuf[(dc->yl << 2) + temp_x++]; +} diff --git a/src/r_main.cpp b/src/r_main.cpp index 08f1e68a1..132349a82 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1409,7 +1409,9 @@ void R_RenderPlayerView(player_t *player) R_ClipSprites(drawsegs, NULL); R_DrawSkyPlanes(); // draw the fucker again to prevent some artifacts R_DrawPlanes(); + //R_ResetColumnBuffer(); R_DrawMasked(masks, nummasks); + //R_ResetColumnBuffer(); } PS_STOP_TIMING(ps_skyboxtime); @@ -1493,6 +1495,7 @@ void R_RenderPlayerView(player_t *player) PS_START_TIMING(ps_sw_planetime); if (!skybox) R_DrawSkyPlanes(); + R_ResetColumnBuffer(); R_DrawPlanes(); PS_STOP_TIMING(ps_sw_planetime); // draw mid texture and sprite @@ -1500,6 +1503,7 @@ void R_RenderPlayerView(player_t *player) PS_START_TIMING(ps_sw_maskedtime); R_DrawMasked(masks, nummasks); PS_STOP_TIMING(ps_sw_maskedtime); + R_ResetColumnBuffer(); free(masks); diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 475e8a44d..16e344bdf 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -716,13 +716,10 @@ void R_DrawPlanes(void) visplane_t *pl; INT32 i; drawspandata_t ds = {}; -#ifdef HAVE_THREADS - srb2::ThreadPool::Sema tp_sema; -#endif - R_UpdatePlaneRipple(&ds); #ifdef HAVE_THREADS + srb2::ThreadPool::Sema tp_sema; srb2::g_main_threadpool->begin_sema(); #endif for (i = 0; i < MAXVISPLANES; i++, pl++) @@ -837,7 +834,8 @@ static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), b dc.x = x + i; dc.source = R_GetColumn(texture, -angle); // get negative of angle for each column to display sky correct way round! --Monster Iestyn 27/01/18 - colfunc2(&dc); + //colfunc2(&dc); + R_DrawSkyColumn(&dc); } }; @@ -874,7 +872,8 @@ static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), b R_GetColumn(texturetranslation[skytexture], -angle); // get negative of angle for each column to display sky correct way round! --Monster Iestyn 27/01/18 - colfunc2(&dc); + //colfunc2(&dc); + R_DrawSkyColumn(&dc); } #endif } -- 2.54.0 From e852c23441c74e35ab65152e6228689f1c1d6f51 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 6 Oct 2025 18:34:03 +0200 Subject: [PATCH 028/219] move the temp columndata into a struct TODO:dynamic allocate our temporary screen buffer --- src/r_draw_flush.cpp | 356 ++++++++++++++++++++++--------------------- 1 file changed, 183 insertions(+), 173 deletions(-) diff --git a/src/r_draw_flush.cpp b/src/r_draw_flush.cpp index 657e185b5..8eb1d6266 100644 --- a/src/r_draw_flush.cpp +++ b/src/r_draw_flush.cpp @@ -22,14 +22,24 @@ enum ColumnFlushType FLUSH_COLORMAP_TRANS }; -static int temp_x = 0; -static int tempyl[4], tempyh[4]; -static UINT8 tempbuf[MAXVIDWIDTH * 4]; -static int startx = 0; -static int commontop, commonbot; -static ColumnFlushType temptype = FLUSH_NONE; -static const UINT8 *temptranmap = NULL; -static const UINT8 *temptranslation = NULL; +typedef struct drawcolumndata_temp_s +{ + intptr_t x; + intptr_t yl[4], yh[4]; + + // e6y: resolution limitation is removed + // not for now kek + UINT8 buf[MAXVIDWIDTH * 4]; + + intptr_t startx; + ColumnFlushType type; + intptr_t commontop, commonbot; + const UINT8 *tranmap; + // SoM 7-28-04: Fix the fuzz problem. + const UINT8 *translation; +} drawcolumndata_temp_t; + +drawcolumndata_temp_t temp_dc = {}; static void R_FlushColumns(void); @@ -62,12 +72,12 @@ static void R_FlushWholeOpaque(void) INT32 count, yl; const restrict INT32 stride = vid.width; - while (--temp_x >= 0) + while (--temp_dc.x >= 0) { - yl = tempyl[temp_x]; - source = &tempbuf[temp_x + (yl << 2)]; - dest = R_Address(startx + temp_x, yl); - count = tempyh[temp_x] - yl + 1; + yl = temp_dc.yl[temp_dc.x]; + source = &temp_dc.buf[temp_dc.x + (yl << 2)]; + dest = R_Address(temp_dc.startx + temp_dc.x, yl); + count = temp_dc.yh[temp_dc.x] - yl + 1; while (--count >= 0) { @@ -95,15 +105,15 @@ static void R_FlushHTOpaque(void) while (colnum < 4) { - yl = tempyl[colnum]; - yh = tempyh[colnum]; + yl = temp_dc.yl[colnum]; + yh = temp_dc.yh[colnum]; // flush column head - if (yl < commontop) + if (yl < temp_dc.commontop) { - source = &tempbuf[colnum + (yl << 2)]; - dest = R_Address(startx + colnum, yl); - count = commontop - yl; + source = &temp_dc.buf[colnum + (yl << 2)]; + dest = R_Address(temp_dc.startx + colnum, yl); + count = temp_dc.commontop - yl; while (--count >= 0) { @@ -114,11 +124,11 @@ static void R_FlushHTOpaque(void) } // flush column tail - if (yh > commonbot) + if (yh > temp_dc.commonbot) { - source = &tempbuf[colnum + ((commonbot + 1) << 2)]; - dest = R_Address(startx + colnum, commonbot + 1); - count = yh - commonbot; + source = &temp_dc.buf[colnum + ((temp_dc.commonbot + 1) << 2)]; + dest = R_Address(temp_dc.startx + colnum, temp_dc.commonbot + 1); + count = yh - temp_dc.commonbot; while (--count >= 0) { @@ -133,12 +143,12 @@ static void R_FlushHTOpaque(void) static void R_FlushQuadOpaque(void) { - UINT8 *source = &tempbuf[commontop << 2]; - UINT8 *dest = R_Address(startx, commontop); + UINT8 *source = &temp_dc.buf[temp_dc.commontop << 2]; + UINT8 *dest = R_Address(temp_dc.startx, temp_dc.commontop); INT32 count; const restrict INT32 stride = vid.width; - count = commonbot - commontop + 1; + count = temp_dc.commonbot - temp_dc.commontop + 1; if ((sizeof(int) == 4) && (((intptr_t)source % 4) == 0) && (((intptr_t)dest % 4) == 0)) { @@ -180,16 +190,16 @@ static void R_FlushWholeTrans(void) INT32 count, yl; const restrict INT32 stride = vid.width; - while (--temp_x >= 0) + while (--temp_dc.x >= 0) { - yl = tempyl[temp_x]; - source = &tempbuf[temp_x + (yl << 2)]; - dest = R_Address(startx + temp_x, yl); - count = tempyh[temp_x] - yl + 1; + yl = temp_dc.yl[temp_dc.x]; + source = &temp_dc.buf[temp_dc.x + (yl << 2)]; + dest = R_Address(temp_dc.startx + temp_dc.x, yl); + count = temp_dc.yh[temp_dc.x] - yl + 1; while (--count >= 0) { - *dest = temptranmap[(*dest << 8) + *source]; + *dest = temp_dc.tranmap[(*dest << 8) + *source]; source += 4; dest += stride; } @@ -206,34 +216,34 @@ static void R_FlushHTTrans(void) while (colnum < 4) { - yl = tempyl[colnum]; - yh = tempyh[colnum]; + yl = temp_dc.yl[colnum]; + yh = temp_dc.yh[colnum]; // flush column head - if (yl < commontop) + if (yl < temp_dc.commontop) { - source = &tempbuf[colnum + (yl << 2)]; - dest = R_Address(startx + colnum, yl); - count = commontop - yl; + source = &temp_dc.buf[colnum + (yl << 2)]; + dest = R_Address(temp_dc.startx + colnum, yl); + count = temp_dc.commontop - yl; while (--count >= 0) { - *dest = temptranmap[(*dest << 8) + *source]; + *dest = temp_dc.tranmap[(*dest << 8) + *source]; source += 4; dest += stride; } } // flush column tail - if (yh > commonbot) + if (yh > temp_dc.commonbot) { - source = &tempbuf[colnum + ((commonbot + 1) << 2)]; - dest = R_Address(startx + colnum, commonbot + 1); - count = yh - commonbot; + source = &temp_dc.buf[colnum + ((temp_dc.commonbot + 1) << 2)]; + dest = R_Address(temp_dc.startx + colnum, temp_dc.commonbot + 1); + count = yh - temp_dc.commonbot; while (--count >= 0) { - *dest = temptranmap[(*dest << 8) + *source]; + *dest = temp_dc.tranmap[(*dest << 8) + *source]; source += 4; dest += stride; } @@ -245,19 +255,19 @@ static void R_FlushHTTrans(void) static void R_FlushQuadTrans(void) { - UINT8 *source = &tempbuf[commontop << 2]; - UINT8 *dest = R_Address(startx, commontop); + UINT8 *source = &temp_dc.buf[temp_dc.commontop << 2]; + UINT8 *dest = R_Address(temp_dc.startx, temp_dc.commontop); INT32 count; const restrict INT32 stride = vid.width; - count = commonbot - commontop + 1; + count = temp_dc.commonbot - temp_dc.commontop + 1; while (--count >= 0) { - dest[0] = temptranmap[(dest[0] << 8) + source[0]]; - dest[1] = temptranmap[(dest[1] << 8) + source[1]]; - dest[2] = temptranmap[(dest[2] << 8) + source[2]]; - dest[3] = temptranmap[(dest[3] << 8) + source[3]]; + dest[0] = temp_dc.tranmap[(dest[0] << 8) + source[0]]; + dest[1] = temp_dc.tranmap[(dest[1] << 8) + source[1]]; + dest[2] = temp_dc.tranmap[(dest[2] << 8) + source[2]]; + dest[3] = temp_dc.tranmap[(dest[3] << 8) + source[3]]; source += 4; dest += stride; } @@ -270,16 +280,16 @@ static void R_FlushWholeColormap(void) INT32 count, yl; const restrict INT32 stride = vid.width; - while (--temp_x >= 0) + while (--temp_dc.x >= 0) { - yl = tempyl[temp_x]; - source = &tempbuf[temp_x + (yl << 2)]; - dest = R_Address(startx + temp_x, yl); - count = tempyh[temp_x] - yl + 1; + yl = temp_dc.yl[temp_dc.x]; + source = &temp_dc.buf[temp_dc.x + (yl << 2)]; + dest = R_Address(temp_dc.startx + temp_dc.x, yl); + count = temp_dc.yh[temp_dc.x] - yl + 1; while (--count >= 0) { - *dest = temptranslation[*source]; + *dest = temp_dc.translation[*source]; source += 4; dest += stride; } @@ -296,34 +306,34 @@ static void R_FlushHTColormap(void) while (colnum < 4) { - yl = tempyl[colnum]; - yh = tempyh[colnum]; + yl = temp_dc.yl[colnum]; + yh = temp_dc.yh[colnum]; // flush column head - if (yl < commontop) + if (yl < temp_dc.commontop) { - source = &tempbuf[colnum + (yl << 2)]; - dest = R_Address(startx + colnum, yl); - count = commontop - yl; + source = &temp_dc.buf[colnum + (yl << 2)]; + dest = R_Address(temp_dc.startx + colnum, yl); + count = temp_dc.commontop - yl; while (--count >= 0) { - *dest = temptranslation[*source]; + *dest = temp_dc.translation[*source]; source += 4; dest += stride; } } // flush column tail - if (yh > commonbot) + if (yh > temp_dc.commonbot) { - source = &tempbuf[colnum + ((commonbot + 1) << 2)]; - dest = R_Address(startx + colnum, commonbot + 1); - count = yh - commonbot; + source = &temp_dc.buf[colnum + ((temp_dc.commonbot + 1) << 2)]; + dest = R_Address(temp_dc.startx + colnum, temp_dc.commonbot + 1); + count = yh - temp_dc.commonbot; while (--count >= 0) { - *dest = temptranslation[*source]; + *dest = temp_dc.translation[*source]; source += 4; dest += stride; } @@ -335,19 +345,19 @@ static void R_FlushHTColormap(void) static void R_FlushQuadColormap(void) { - UINT8 *source = &tempbuf[commontop << 2]; - UINT8 *dest = R_Address(startx, commontop); + UINT8 *source = &temp_dc.buf[temp_dc.commontop << 2]; + UINT8 *dest = R_Address(temp_dc.startx, temp_dc.commontop); INT32 count; const restrict INT32 stride = vid.width; - count = commonbot - commontop + 1; + count = temp_dc.commonbot - temp_dc.commontop + 1; while (--count >= 0) { - dest[0] = temptranslation[source[0]]; - dest[1] = temptranslation[source[1]]; - dest[2] = temptranslation[source[2]]; - dest[3] = temptranslation[source[3]]; + dest[0] = temp_dc.translation[source[0]]; + dest[1] = temp_dc.translation[source[1]]; + dest[2] = temp_dc.translation[source[2]]; + dest[3] = temp_dc.translation[source[3]]; source += 4; dest += stride; } @@ -360,16 +370,16 @@ static void R_FlushWholeColormapTrans(void) INT32 count, yl; const restrict INT32 stride = vid.width; - while (--temp_x >= 0) + while (--temp_dc.x >= 0) { - yl = tempyl[temp_x]; - source = &tempbuf[temp_x + (yl << 2)]; - dest = R_Address(startx + temp_x, yl); - count = tempyh[temp_x] - yl + 1; + yl = temp_dc.yl[temp_dc.x]; + source = &temp_dc.buf[temp_dc.x + (yl << 2)]; + dest = R_Address(temp_dc.startx + temp_dc.x, yl); + count = temp_dc.yh[temp_dc.x] - yl + 1; while (--count >= 0) { - *dest = temptranmap[(*dest << 8) + temptranslation[*source]]; + *dest = temp_dc.tranmap[(*dest << 8) + temp_dc.translation[*source]]; source += 4; dest += stride; } @@ -386,34 +396,34 @@ static void R_FlushHTColormapTrans(void) while (colnum < 4) { - yl = tempyl[colnum]; - yh = tempyh[colnum]; + yl = temp_dc.yl[colnum]; + yh = temp_dc.yh[colnum]; // flush column head - if (yl < commontop) + if (yl < temp_dc.commontop) { - source = &tempbuf[colnum + (yl << 2)]; - dest = R_Address(startx + colnum, yl); - count = commontop - yl; + source = &temp_dc.buf[colnum + (yl << 2)]; + dest = R_Address(temp_dc.startx + colnum, yl); + count = temp_dc.commontop - yl; while (--count >= 0) { - *dest = temptranmap[(*dest << 8) + temptranslation[*source]]; + *dest = temp_dc.tranmap[(*dest << 8) + temp_dc.translation[*source]]; source += 4; dest += stride; } } // flush column tail - if (yh > commonbot) + if (yh > temp_dc.commonbot) { - source = &tempbuf[colnum + ((commonbot + 1) << 2)]; - dest = R_Address(startx + colnum, commonbot + 1); - count = yh - commonbot; + source = &temp_dc.buf[colnum + ((temp_dc.commonbot + 1) << 2)]; + dest = R_Address(temp_dc.startx + colnum, temp_dc.commonbot + 1); + count = yh - temp_dc.commonbot; while (--count >= 0) { - *dest = temptranmap[(*dest << 8) + temptranslation[*source]]; + *dest = temp_dc.tranmap[(*dest << 8) + temp_dc.translation[*source]]; source += 4; dest += stride; } @@ -425,19 +435,19 @@ static void R_FlushHTColormapTrans(void) static void R_FlushQuadColormapTrans(void) { - UINT8 *source = &tempbuf[commontop << 2]; - UINT8 *dest = R_Address(startx, commontop); + UINT8 *source = &temp_dc.buf[temp_dc.commontop << 2]; + UINT8 *dest = R_Address(temp_dc.startx, temp_dc.commontop); INT32 count; const restrict INT32 stride = vid.width; - count = commonbot - commontop + 1; + count = temp_dc.commonbot - temp_dc.commontop + 1; while (--count >= 0) { - dest[0] = temptranmap[(dest[0] << 8) + temptranslation[source[0]]]; - dest[1] = temptranmap[(dest[1] << 8) + temptranslation[source[1]]]; - dest[2] = temptranmap[(dest[2] << 8) + temptranslation[source[2]]]; - dest[3] = temptranmap[(dest[3] << 8) + temptranslation[source[3]]]; + dest[0] = temp_dc.tranmap[(dest[0] << 8) + temp_dc.translation[source[0]]]; + dest[1] = temp_dc.tranmap[(dest[1] << 8) + temp_dc.translation[source[1]]]; + dest[2] = temp_dc.tranmap[(dest[2] << 8) + temp_dc.translation[source[2]]]; + dest[3] = temp_dc.tranmap[(dest[3] << 8) + temp_dc.translation[source[3]]]; source += 4; dest += stride; } @@ -449,7 +459,7 @@ static void (*R_FlushQuadColumn)(void) = R_QuadFlushError; static void R_FlushColumns(void) { - if (temp_x != 4 || commontop >= commonbot) + if (temp_dc.x != 4 || temp_dc.commontop >= temp_dc.commonbot) R_FlushWholeColumns(); else { @@ -457,7 +467,7 @@ static void R_FlushColumns(void) R_FlushQuadColumn(); } - temp_x = 0; + temp_dc.x = 0; } // @@ -465,10 +475,10 @@ static void R_FlushColumns(void) // void R_ResetColumnBuffer(void) { - if (temp_x) + if (temp_dc.x) R_FlushColumns(); - temptype = FLUSH_NONE; + temp_dc.type = FLUSH_NONE; R_FlushWholeColumns = R_FlushWholeError; R_FlushHTColumns = R_FlushHTError; R_FlushQuadColumn = R_QuadFlushError; @@ -476,124 +486,124 @@ void R_ResetColumnBuffer(void) static UINT8 *R_GetBufferOpaque(drawcolumndata_t *dc) { - if (temp_x == 4 || - (temp_x && (temptype != FLUSH_OPAQUE || temp_x + startx != dc->x))) + if (temp_dc.x == 4 || + (temp_dc.x && (temp_dc.type != FLUSH_OPAQUE || temp_dc.x + temp_dc.startx != dc->x))) R_FlushColumns(); - if (!temp_x) + if (!temp_dc.x) { - startx = dc->x; - tempyl[0] = commontop = dc->yl; - tempyh[0] = commonbot = dc->yh; - temptype = FLUSH_OPAQUE; + temp_dc.startx = dc->x; + temp_dc.yl[0] = temp_dc.commontop = dc->yl; + temp_dc.yh[0] = temp_dc.commonbot = dc->yh; + temp_dc.type = FLUSH_OPAQUE; R_FlushWholeColumns = R_FlushWholeOpaque; R_FlushHTColumns = R_FlushHTOpaque; R_FlushQuadColumn = R_FlushQuadOpaque; - temp_x += 1; - return &tempbuf[dc->yl << 2]; + temp_dc.x += 1; + return &temp_dc.buf[dc->yl << 2]; } - tempyl[temp_x] = dc->yl; - tempyh[temp_x] = dc->yh; + temp_dc.yl[temp_dc.x] = dc->yl; + temp_dc.yh[temp_dc.x] = dc->yh; - if (dc->yl > commontop) - commontop = dc->yl; - if (dc->yh < commonbot) - commonbot = dc->yh; + if (dc->yl > temp_dc.commontop) + temp_dc.commontop = dc->yl; + if (dc->yh < temp_dc.commonbot) + temp_dc.commonbot = dc->yh; - return &tempbuf[(dc->yl << 2) + temp_x++]; + return &temp_dc.buf[(dc->yl << 2) + temp_dc.x++]; } static UINT8 *R_GetBufferTrans(drawcolumndata_t *dc) { - if (temp_x == 4 || dc->transmap != temptranmap || - (temp_x && (temptype != FLUSH_TRANS || temp_x + startx != dc->x))) + if (temp_dc.x == 4 || dc->transmap != temp_dc.tranmap || + (temp_dc.x && (temp_dc.type != FLUSH_TRANS || temp_dc.x + temp_dc.startx != dc->x))) R_FlushColumns(); - if (!temp_x) + if (!temp_dc.x) { - startx = dc->x; - tempyl[0] = commontop = dc->yl; - tempyh[0] = commonbot = dc->yh; - temptype = FLUSH_TRANS; - temptranmap = dc->transmap; + temp_dc.startx = dc->x; + temp_dc.yl[0] = temp_dc.commontop = dc->yl; + temp_dc.yh[0] = temp_dc.commonbot = dc->yh; + temp_dc.type = FLUSH_TRANS; + temp_dc.tranmap = dc->transmap; R_FlushWholeColumns = R_FlushWholeTrans; R_FlushHTColumns = R_FlushHTTrans; R_FlushQuadColumn = R_FlushQuadTrans; - temp_x += 1; - return &tempbuf[dc->yl << 2]; + temp_dc.x += 1; + return &temp_dc.buf[dc->yl << 2]; } - tempyl[temp_x] = dc->yl; - tempyh[temp_x] = dc->yh; + temp_dc.yl[temp_dc.x] = dc->yl; + temp_dc.yh[temp_dc.x] = dc->yh; - if (dc->yl > commontop) - commontop = dc->yl; - if (dc->yh < commonbot) - commonbot = dc->yh; + if (dc->yl > temp_dc.commontop) + temp_dc.commontop = dc->yl; + if (dc->yh < temp_dc.commonbot) + temp_dc.commonbot = dc->yh; - return &tempbuf[(dc->yl << 2) + temp_x++]; + return &temp_dc.buf[(dc->yl << 2) + temp_dc.x++]; } static UINT8 *R_GetBufferColormap(drawcolumndata_t *dc) { - if (temp_x == 4 || dc->translation != temptranslation || - (temp_x && (temptype != FLUSH_COLORMAP || temp_x + startx != dc->x))) + if (temp_dc.x == 4 || dc->translation != temp_dc.translation || + (temp_dc.x && (temp_dc.type != FLUSH_COLORMAP || temp_dc.x + temp_dc.startx != dc->x))) R_FlushColumns(); - if (!temp_x) + if (!temp_dc.x) { - startx = dc->x; - tempyl[0] = commontop = dc->yl; - tempyh[0] = commonbot = dc->yh; - temptype = FLUSH_COLORMAP; - temptranslation = dc->translation; + temp_dc.startx = dc->x; + temp_dc.yl[0] = temp_dc.commontop = dc->yl; + temp_dc.yh[0] = temp_dc.commonbot = dc->yh; + temp_dc.type = FLUSH_COLORMAP; + temp_dc.translation = dc->translation; R_FlushWholeColumns = R_FlushWholeColormap; R_FlushHTColumns = R_FlushHTColormap; R_FlushQuadColumn = R_FlushQuadColormap; - temp_x += 1; - return &tempbuf[dc->yl << 2]; + temp_dc.x += 1; + return &temp_dc.buf[dc->yl << 2]; } - tempyl[temp_x] = dc->yl; - tempyh[temp_x] = dc->yh; + temp_dc.yl[temp_dc.x] = dc->yl; + temp_dc.yh[temp_dc.x] = dc->yh; - if (dc->yl > commontop) - commontop = dc->yl; - if (dc->yh < commonbot) - commonbot = dc->yh; + if (dc->yl > temp_dc.commontop) + temp_dc.commontop = dc->yl; + if (dc->yh < temp_dc.commonbot) + temp_dc.commonbot = dc->yh; - return &tempbuf[(dc->yl << 2) + temp_x++]; + return &temp_dc.buf[(dc->yl << 2) + temp_dc.x++]; } static UINT8 *R_GetBufferColormapTrans(drawcolumndata_t *dc) { - if (temp_x == 4 || dc->translation != temptranslation || dc->transmap != temptranmap || - (temp_x && (temptype != FLUSH_COLORMAP_TRANS || temp_x + startx != dc->x))) + if (temp_dc.x == 4 || dc->translation != temp_dc.translation || dc->transmap != temp_dc.tranmap || + (temp_dc.x && (temp_dc.type != FLUSH_COLORMAP_TRANS || temp_dc.x + temp_dc.startx != dc->x))) R_FlushColumns(); - if (!temp_x) + if (!temp_dc.x) { - startx = dc->x; - tempyl[0] = commontop = dc->yl; - tempyh[0] = commonbot = dc->yh; - temptype = FLUSH_COLORMAP_TRANS; - temptranslation = dc->translation; - temptranmap = dc->transmap; + temp_dc.startx = dc->x; + temp_dc.yl[0] = temp_dc.commontop = dc->yl; + temp_dc.yh[0] = temp_dc.commonbot = dc->yh; + temp_dc.type = FLUSH_COLORMAP_TRANS; + temp_dc.translation = dc->translation; + temp_dc.tranmap = dc->transmap; R_FlushWholeColumns = R_FlushWholeColormapTrans; R_FlushHTColumns = R_FlushHTColormapTrans; R_FlushQuadColumn = R_FlushQuadColormapTrans; - temp_x += 1; - return &tempbuf[dc->yl << 2]; + temp_dc.x += 1; + return &temp_dc.buf[dc->yl << 2]; } - tempyl[temp_x] = dc->yl; - tempyh[temp_x] = dc->yh; + temp_dc.yl[temp_dc.x] = dc->yl; + temp_dc.yh[temp_dc.x] = dc->yh; - if (dc->yl > commontop) - commontop = dc->yl; - if (dc->yh < commonbot) - commonbot = dc->yh; + if (dc->yl > temp_dc.commontop) + temp_dc.commontop = dc->yl; + if (dc->yh < temp_dc.commonbot) + temp_dc.commonbot = dc->yh; - return &tempbuf[(dc->yl << 2) + temp_x++]; + return &temp_dc.buf[(dc->yl << 2) + temp_dc.x++]; } -- 2.54.0 From e68136de3eaa7080a5533af8993468754bf2b2fa Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 6 Oct 2025 19:12:52 +0200 Subject: [PATCH 029/219] remove tempbuf resolution limit by allocating it dynamically per our actual screen resolution --- src/r_draw.cpp | 81 ++++++++++++++++++++++++++++++++++++++++++++ src/r_draw_flush.cpp | 76 ----------------------------------------- 2 files changed, 81 insertions(+), 76 deletions(-) diff --git a/src/r_draw.cpp b/src/r_draw.cpp index c8a09745a..86b9fa5e1 100644 --- a/src/r_draw.cpp +++ b/src/r_draw.cpp @@ -489,6 +489,81 @@ void R_FlushTranslationColormapCache(void) // in reality, the few routines that can work for either mode, are // put here +enum ColumnFlushType +{ + FLUSH_NONE, + FLUSH_OPAQUE, + FLUSH_TRANS, + FLUSH_COLORMAP, + FLUSH_COLORMAP_TRANS +}; + +typedef struct drawcolumndata_temp_s +{ + intptr_t x; + intptr_t yl[4], yh[4]; + + // e6y: resolution limitation is removed + UINT8 *buf; + + intptr_t startx; + ColumnFlushType type; + intptr_t commontop, commonbot; + const UINT8 *tranmap; + // SoM 7-28-04: Fix the fuzz problem. + const UINT8 *translation; +} drawcolumndata_temp_t; + +drawcolumndata_temp_t temp_dc = {}; + +static void R_FlushColumns(void); + +static void R_FlushWholeError(void) +{ + I_Error("R_FlushWholeColumns called without being initialized.\n"); +} + +static void R_FlushHTError(void) +{ + I_Error("R_FlushHTColumns called without being initialized.\n"); +} + +static void R_QuadFlushError(void) +{ + I_Error("R_FlushQuadColumn called without being initialized.\n"); +} + +static void (*R_FlushWholeColumns)(void) = R_FlushWholeError; +static void (*R_FlushHTColumns)(void) = R_FlushHTError; +static void (*R_FlushQuadColumn)(void) = R_QuadFlushError; + +static void R_FlushColumns(void) +{ + if (temp_dc.x != 4 || temp_dc.commontop >= temp_dc.commonbot) + R_FlushWholeColumns(); + else + { + R_FlushHTColumns(); + R_FlushQuadColumn(); + } + + temp_dc.x = 0; +} + +// +// R_ResetColumnBuffer +// +void R_ResetColumnBuffer(void) +{ + if (temp_dc.x) + R_FlushColumns(); + + temp_dc.type = FLUSH_NONE; + R_FlushWholeColumns = R_FlushWholeError; + R_FlushHTColumns = R_FlushHTError; + R_FlushQuadColumn = R_QuadFlushError; +} + /** \brief The R_InitViewBuffer function Creates lookup tables for getting the framebuffer address @@ -536,6 +611,12 @@ void R_InitViewBuffer(INT32 width, INT32 height) linesize = vid.width; // killough 11/98 renderscreen = vid.screens[0]; // haleyjd 07/02/14 + + if (temp_dc.buf) + Z_Free(temp_dc.buf); + + memset(&temp_dc, 0, sizeof(temp_dc)); + temp_dc.buf = static_cast(Z_Calloc((vid.height * 4) * sizeof(*temp_dc.buf), PU_STATIC, NULL)); } /** \brief viewborder patches lump numbers diff --git a/src/r_draw_flush.cpp b/src/r_draw_flush.cpp index 8eb1d6266..b9b5ef04e 100644 --- a/src/r_draw_flush.cpp +++ b/src/r_draw_flush.cpp @@ -13,51 +13,6 @@ /// \brief column flush functions /// \note no includes because this is included as part of r_draw.cpp -enum ColumnFlushType -{ - FLUSH_NONE, - FLUSH_OPAQUE, - FLUSH_TRANS, - FLUSH_COLORMAP, - FLUSH_COLORMAP_TRANS -}; - -typedef struct drawcolumndata_temp_s -{ - intptr_t x; - intptr_t yl[4], yh[4]; - - // e6y: resolution limitation is removed - // not for now kek - UINT8 buf[MAXVIDWIDTH * 4]; - - intptr_t startx; - ColumnFlushType type; - intptr_t commontop, commonbot; - const UINT8 *tranmap; - // SoM 7-28-04: Fix the fuzz problem. - const UINT8 *translation; -} drawcolumndata_temp_t; - -drawcolumndata_temp_t temp_dc = {}; - -static void R_FlushColumns(void); - -static void R_FlushWholeError(void) -{ - I_Error("R_FlushWholeColumns called without being initialized.\n"); -} - -static void R_FlushHTError(void) -{ - I_Error("R_FlushHTColumns called without being initialized.\n"); -} - -static void R_QuadFlushError(void) -{ - I_Error("R_FlushQuadColumn called without being initialized.\n"); -} - // // R_FlushWholeOpaque // @@ -453,37 +408,6 @@ static void R_FlushQuadColormapTrans(void) } } -static void (*R_FlushWholeColumns)(void) = R_FlushWholeError; -static void (*R_FlushHTColumns)(void) = R_FlushHTError; -static void (*R_FlushQuadColumn)(void) = R_QuadFlushError; - -static void R_FlushColumns(void) -{ - if (temp_dc.x != 4 || temp_dc.commontop >= temp_dc.commonbot) - R_FlushWholeColumns(); - else - { - R_FlushHTColumns(); - R_FlushQuadColumn(); - } - - temp_dc.x = 0; -} - -// -// R_ResetColumnBuffer -// -void R_ResetColumnBuffer(void) -{ - if (temp_dc.x) - R_FlushColumns(); - - temp_dc.type = FLUSH_NONE; - R_FlushWholeColumns = R_FlushWholeError; - R_FlushHTColumns = R_FlushHTError; - R_FlushQuadColumn = R_QuadFlushError; -} - static UINT8 *R_GetBufferOpaque(drawcolumndata_t *dc) { if (temp_dc.x == 4 || -- 2.54.0 From 3c9292c13756f5ebfae337a33f8a6f0ffa702233 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 6 Oct 2025 19:22:45 +0200 Subject: [PATCH 030/219] reorder column flush functions also add some comments that used to be in drawcolumn X) --- src/r_draw.cpp | 13 +- src/r_draw_column.cpp | 12 +- src/r_draw_flush.cpp | 308 +++++++++++++++++++++--------------------- 3 files changed, 175 insertions(+), 158 deletions(-) diff --git a/src/r_draw.cpp b/src/r_draw.cpp index 86b9fa5e1..b2cad26e0 100644 --- a/src/r_draw.cpp +++ b/src/r_draw.cpp @@ -516,8 +516,10 @@ typedef struct drawcolumndata_temp_s drawcolumndata_temp_t temp_dc = {}; -static void R_FlushColumns(void); - +// +// Error functions that will abort if R_FlushColumns tries to flush +// columns without a column type. +// static void R_FlushWholeError(void) { I_Error("R_FlushWholeColumns called without being initialized.\n"); @@ -553,10 +555,17 @@ static void R_FlushColumns(void) // // R_ResetColumnBuffer // +// haleyjd 09/13/04: new function to call from main rendering loop +// which gets rid of the unnecessary reset of various variables during +// column drawing. +// void R_ResetColumnBuffer(void) { + // haleyjd 10/06/05: this must not be done if x == 0! if (temp_dc.x) + { R_FlushColumns(); + } temp_dc.type = FLUSH_NONE; R_FlushWholeColumns = R_FlushWholeError; diff --git a/src/r_draw_column.cpp b/src/r_draw_column.cpp index ccb5c5403..cef7f85cd 100644 --- a/src/r_draw_column.cpp +++ b/src/r_draw_column.cpp @@ -84,8 +84,18 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) { INT32 count; + // leban 1/17/99: + // removed the + 1 here, adjusted the if test, and added an increment + // later. this helps a compiler pipeline a bit better. the x86 + // assembler also does this. count = dc->yh - dc->yl; + // leban 1/17/99: + // this case isn't executed too often. depending on how many instructions + // there are between here and the second if test below, this case could + // be moved down and might save instructions overall. since there are + // probably different wads that favor one way or the other, i'll leave + // this alone for now. if (count < 0) // Zero length, column does not exceed a pixel. { return; @@ -285,7 +295,7 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) { // Re-map color indices from wall texture column // using a lighting/special effects LUT. - // heightmask is the Tutti-Frutti fix + // heightmask is the Tutti-Frutti fix -- killough // -1 is the lower clamp bound because column posts have a "safe" byte before the real data // and a few bytes after as well diff --git a/src/r_draw_flush.cpp b/src/r_draw_flush.cpp index b9b5ef04e..b77ece5d5 100644 --- a/src/r_draw_flush.cpp +++ b/src/r_draw_flush.cpp @@ -14,11 +14,10 @@ /// \note no includes because this is included as part of r_draw.cpp // -// R_FlushWholeOpaque +// R_FlushWhole // // Flushes the entire columns in the buffer, one at a time. // This is used when a quad flush isn't possible. -// Opaque version -- no remapping whatsoever. // static void R_FlushWholeOpaque(void) { @@ -43,12 +42,80 @@ static void R_FlushWholeOpaque(void) } } +static void R_FlushWholeTrans(void) +{ + UINT8 *source; + UINT8 *dest; + INT32 count, yl; + const restrict INT32 stride = vid.width; + + while (--temp_dc.x >= 0) + { + yl = temp_dc.yl[temp_dc.x]; + source = &temp_dc.buf[temp_dc.x + (yl << 2)]; + dest = R_Address(temp_dc.startx + temp_dc.x, yl); + count = temp_dc.yh[temp_dc.x] - yl + 1; + + while (--count >= 0) + { + *dest = temp_dc.tranmap[(*dest << 8) + *source]; + source += 4; + dest += stride; + } + } +} + +static void R_FlushWholeColormap(void) +{ + UINT8 *source; + UINT8 *dest; + INT32 count, yl; + const restrict INT32 stride = vid.width; + + while (--temp_dc.x >= 0) + { + yl = temp_dc.yl[temp_dc.x]; + source = &temp_dc.buf[temp_dc.x + (yl << 2)]; + dest = R_Address(temp_dc.startx + temp_dc.x, yl); + count = temp_dc.yh[temp_dc.x] - yl + 1; + + while (--count >= 0) + { + *dest = temp_dc.translation[*source]; + source += 4; + dest += stride; + } + } +} + +static void R_FlushWholeColormapTrans(void) +{ + UINT8 *source; + UINT8 *dest; + INT32 count, yl; + const restrict INT32 stride = vid.width; + + while (--temp_dc.x >= 0) + { + yl = temp_dc.yl[temp_dc.x]; + source = &temp_dc.buf[temp_dc.x + (yl << 2)]; + dest = R_Address(temp_dc.startx + temp_dc.x, yl); + count = temp_dc.yh[temp_dc.x] - yl + 1; + + while (--count >= 0) + { + *dest = temp_dc.tranmap[(*dest << 8) + temp_dc.translation[*source]]; + source += 4; + dest += stride; + } + } +} + // -// R_FlushHTOpaque +// R_FlushHT // // Flushes the head and tail of columns in the buffer in // preparation for a quad flush. -// Opaque version -- no remapping whatsoever. // static void R_FlushHTOpaque(void) { @@ -96,71 +163,6 @@ static void R_FlushHTOpaque(void) } } -static void R_FlushQuadOpaque(void) -{ - UINT8 *source = &temp_dc.buf[temp_dc.commontop << 2]; - UINT8 *dest = R_Address(temp_dc.startx, temp_dc.commontop); - INT32 count; - const restrict INT32 stride = vid.width; - - count = temp_dc.commonbot - temp_dc.commontop + 1; - - if ((sizeof(int) == 4) && (((intptr_t)source % 4) == 0) && (((intptr_t)dest % 4) == 0)) - { - while(--count >= 0) - { - *(int *)dest = *(int *)source; - source += 4 * sizeof(UINT8); - dest += stride * sizeof(UINT8); - } - } - else - { - while(--count >= 0) - { - dest[0] = source[0]; - dest[1] = source[1]; - dest[2] = source[2]; - dest[3] = source[3]; - source += 4 * sizeof(UINT8); - dest += stride * sizeof(UINT8); - } - } - - while(--count >= 0) - { - dest[0] = source[0]; - dest[1] = source[1]; - dest[2] = source[2]; - dest[3] = source[3]; - source += 4 * sizeof(UINT8); - dest += stride * sizeof(UINT8); - } -} - -static void R_FlushWholeTrans(void) -{ - UINT8 *source; - UINT8 *dest; - INT32 count, yl; - const restrict INT32 stride = vid.width; - - while (--temp_dc.x >= 0) - { - yl = temp_dc.yl[temp_dc.x]; - source = &temp_dc.buf[temp_dc.x + (yl << 2)]; - dest = R_Address(temp_dc.startx + temp_dc.x, yl); - count = temp_dc.yh[temp_dc.x] - yl + 1; - - while (--count >= 0) - { - *dest = temp_dc.tranmap[(*dest << 8) + *source]; - source += 4; - dest += stride; - } - } -} - static void R_FlushHTTrans(void) { UINT8 *source; @@ -208,49 +210,6 @@ static void R_FlushHTTrans(void) } } -static void R_FlushQuadTrans(void) -{ - UINT8 *source = &temp_dc.buf[temp_dc.commontop << 2]; - UINT8 *dest = R_Address(temp_dc.startx, temp_dc.commontop); - INT32 count; - const restrict INT32 stride = vid.width; - - count = temp_dc.commonbot - temp_dc.commontop + 1; - - while (--count >= 0) - { - dest[0] = temp_dc.tranmap[(dest[0] << 8) + source[0]]; - dest[1] = temp_dc.tranmap[(dest[1] << 8) + source[1]]; - dest[2] = temp_dc.tranmap[(dest[2] << 8) + source[2]]; - dest[3] = temp_dc.tranmap[(dest[3] << 8) + source[3]]; - source += 4; - dest += stride; - } -} - -static void R_FlushWholeColormap(void) -{ - UINT8 *source; - UINT8 *dest; - INT32 count, yl; - const restrict INT32 stride = vid.width; - - while (--temp_dc.x >= 0) - { - yl = temp_dc.yl[temp_dc.x]; - source = &temp_dc.buf[temp_dc.x + (yl << 2)]; - dest = R_Address(temp_dc.startx + temp_dc.x, yl); - count = temp_dc.yh[temp_dc.x] - yl + 1; - - while (--count >= 0) - { - *dest = temp_dc.translation[*source]; - source += 4; - dest += stride; - } - } -} - static void R_FlushHTColormap(void) { UINT8 *source; @@ -298,49 +257,6 @@ static void R_FlushHTColormap(void) } } -static void R_FlushQuadColormap(void) -{ - UINT8 *source = &temp_dc.buf[temp_dc.commontop << 2]; - UINT8 *dest = R_Address(temp_dc.startx, temp_dc.commontop); - INT32 count; - const restrict INT32 stride = vid.width; - - count = temp_dc.commonbot - temp_dc.commontop + 1; - - while (--count >= 0) - { - dest[0] = temp_dc.translation[source[0]]; - dest[1] = temp_dc.translation[source[1]]; - dest[2] = temp_dc.translation[source[2]]; - dest[3] = temp_dc.translation[source[3]]; - source += 4; - dest += stride; - } -} - -static void R_FlushWholeColormapTrans(void) -{ - UINT8 *source; - UINT8 *dest; - INT32 count, yl; - const restrict INT32 stride = vid.width; - - while (--temp_dc.x >= 0) - { - yl = temp_dc.yl[temp_dc.x]; - source = &temp_dc.buf[temp_dc.x + (yl << 2)]; - dest = R_Address(temp_dc.startx + temp_dc.x, yl); - count = temp_dc.yh[temp_dc.x] - yl + 1; - - while (--count >= 0) - { - *dest = temp_dc.tranmap[(*dest << 8) + temp_dc.translation[*source]]; - source += 4; - dest += stride; - } - } -} - static void R_FlushHTColormapTrans(void) { UINT8 *source; @@ -388,6 +304,88 @@ static void R_FlushHTColormapTrans(void) } } +static void R_FlushQuadOpaque(void) +{ + UINT8 *source = &temp_dc.buf[temp_dc.commontop << 2]; + UINT8 *dest = R_Address(temp_dc.startx, temp_dc.commontop); + INT32 count; + const restrict INT32 stride = vid.width; + + count = temp_dc.commonbot - temp_dc.commontop + 1; + + if ((sizeof(int) == 4) && (((intptr_t)source % 4) == 0) && (((intptr_t)dest % 4) == 0)) + { + while(--count >= 0) + { + *(int *)dest = *(int *)source; + source += 4 * sizeof(UINT8); + dest += stride * sizeof(UINT8); + } + } + else + { + while(--count >= 0) + { + dest[0] = source[0]; + dest[1] = source[1]; + dest[2] = source[2]; + dest[3] = source[3]; + source += 4 * sizeof(UINT8); + dest += stride * sizeof(UINT8); + } + } + + while(--count >= 0) + { + dest[0] = source[0]; + dest[1] = source[1]; + dest[2] = source[2]; + dest[3] = source[3]; + source += 4 * sizeof(UINT8); + dest += stride * sizeof(UINT8); + } +} + +static void R_FlushQuadTrans(void) +{ + UINT8 *source = &temp_dc.buf[temp_dc.commontop << 2]; + UINT8 *dest = R_Address(temp_dc.startx, temp_dc.commontop); + INT32 count; + const restrict INT32 stride = vid.width; + + count = temp_dc.commonbot - temp_dc.commontop + 1; + + while (--count >= 0) + { + dest[0] = temp_dc.tranmap[(dest[0] << 8) + source[0]]; + dest[1] = temp_dc.tranmap[(dest[1] << 8) + source[1]]; + dest[2] = temp_dc.tranmap[(dest[2] << 8) + source[2]]; + dest[3] = temp_dc.tranmap[(dest[3] << 8) + source[3]]; + source += 4; + dest += stride; + } +} + +static void R_FlushQuadColormap(void) +{ + UINT8 *source = &temp_dc.buf[temp_dc.commontop << 2]; + UINT8 *dest = R_Address(temp_dc.startx, temp_dc.commontop); + INT32 count; + const restrict INT32 stride = vid.width; + + count = temp_dc.commonbot - temp_dc.commontop + 1; + + while (--count >= 0) + { + dest[0] = temp_dc.translation[source[0]]; + dest[1] = temp_dc.translation[source[1]]; + dest[2] = temp_dc.translation[source[2]]; + dest[3] = temp_dc.translation[source[3]]; + source += 4; + dest += stride; + } +} + static void R_FlushQuadColormapTrans(void) { UINT8 *source = &temp_dc.buf[temp_dc.commontop << 2]; -- 2.54.0 From 2753052ee73e459b02c489a797ac49f1e49be5ee Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 6 Oct 2025 19:45:31 +0200 Subject: [PATCH 031/219] fix FlushColumns being called without being initialized aack --- src/r_draw_flush.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/r_draw_flush.cpp b/src/r_draw_flush.cpp index b77ece5d5..b1bbb464f 100644 --- a/src/r_draw_flush.cpp +++ b/src/r_draw_flush.cpp @@ -438,7 +438,7 @@ static UINT8 *R_GetBufferOpaque(drawcolumndata_t *dc) static UINT8 *R_GetBufferTrans(drawcolumndata_t *dc) { - if (temp_dc.x == 4 || dc->transmap != temp_dc.tranmap || + if (temp_dc.x == 4 || (temp_dc.x && (temp_dc.type != FLUSH_TRANS || temp_dc.x + temp_dc.startx != dc->x))) R_FlushColumns(); @@ -469,7 +469,7 @@ static UINT8 *R_GetBufferTrans(drawcolumndata_t *dc) static UINT8 *R_GetBufferColormap(drawcolumndata_t *dc) { - if (temp_dc.x == 4 || dc->translation != temp_dc.translation || + if (temp_dc.x == 4 || (temp_dc.x && (temp_dc.type != FLUSH_COLORMAP || temp_dc.x + temp_dc.startx != dc->x))) R_FlushColumns(); @@ -500,7 +500,7 @@ static UINT8 *R_GetBufferColormap(drawcolumndata_t *dc) static UINT8 *R_GetBufferColormapTrans(drawcolumndata_t *dc) { - if (temp_dc.x == 4 || dc->translation != temp_dc.translation || dc->transmap != temp_dc.tranmap || + if (temp_dc.x == 4 || (temp_dc.x && (temp_dc.type != FLUSH_COLORMAP_TRANS || temp_dc.x + temp_dc.startx != dc->x))) R_FlushColumns(); -- 2.54.0 From 2b6185d7d6339917e2803bb392bd84f7b18ac47f Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 6 Oct 2025 20:02:58 +0200 Subject: [PATCH 032/219] reenable colormapped / translucent columns --- src/r_draw_column.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/r_draw_column.cpp b/src/r_draw_column.cpp index cef7f85cd..d7954cf52 100644 --- a/src/r_draw_column.cpp +++ b/src/r_draw_column.cpp @@ -71,9 +71,7 @@ static constexpr UINT8 R_DrawColumnPixel(drawcolumndata_t* dc, UINT8 * restrict } } - //return R_GetColumnTranslucent(dc, dest, col, colormap); - // dont return any other shit for now - return col; + return R_GetColumnTranslucent(dc, dest, col, colormap); } /** \brief The R_DrawColumn function @@ -210,13 +208,13 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) // Framebuffer destination address. // SoM: MAGIC - /*if constexpr (Type & (DrawColumnType::DC_COLORMAP | DrawColumnType::DC_TRANSMAP)) + if constexpr (Type & (DrawColumnType::DC_COLORMAP | DrawColumnType::DC_TRANSMAP)) dest = R_GetBufferColormapTrans(dc); else if constexpr (Type & DrawColumnType::DC_TRANSMAP) dest = R_GetBufferTrans(dc); else if constexpr (Type & DrawColumnType::DC_COLORMAP) dest = R_GetBufferColormap(dc); - else*/ + else dest = R_GetBufferOpaque(dc); count++; -- 2.54.0 From e4ac394d293b9769b12a9a83bba074426b698969 Mon Sep 17 00:00:00 2001 From: Indev Date: Mon, 6 Oct 2025 21:17:36 +0300 Subject: [PATCH 033/219] Fix DC_COLORMAP and DC_TRANSMAP column drawers always using DC_COLORMAP|DC_TRANSMAP func --- src/r_draw_column.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_draw_column.cpp b/src/r_draw_column.cpp index d7954cf52..a24318a35 100644 --- a/src/r_draw_column.cpp +++ b/src/r_draw_column.cpp @@ -208,7 +208,7 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) // Framebuffer destination address. // SoM: MAGIC - if constexpr (Type & (DrawColumnType::DC_COLORMAP | DrawColumnType::DC_TRANSMAP)) + if constexpr ((Type & (DrawColumnType::DC_COLORMAP | DrawColumnType::DC_TRANSMAP)) == (DrawColumnType::DC_COLORMAP | DrawColumnType::DC_TRANSMAP)) dest = R_GetBufferColormapTrans(dc); else if constexpr (Type & DrawColumnType::DC_TRANSMAP) dest = R_GetBufferTrans(dc); -- 2.54.0 From 955812bd8d0a1824dc7abb9cd47cddc0a6195653 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 6 Oct 2025 22:09:27 +0200 Subject: [PATCH 034/219] template the flush functions --- src/r_draw_column.cpp | 7 +- src/r_draw_flush.cpp | 574 ++++++++++++++---------------------------- 2 files changed, 188 insertions(+), 393 deletions(-) diff --git a/src/r_draw_column.cpp b/src/r_draw_column.cpp index a24318a35..c2275fbd4 100644 --- a/src/r_draw_column.cpp +++ b/src/r_draw_column.cpp @@ -204,11 +204,12 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) const UINT8 * restrict source = dc->source; const lighttable_t * restrict colormap = dc->colormap; - UINT8 * restrict dest; - // Framebuffer destination address. // SoM: MAGIC - if constexpr ((Type & (DrawColumnType::DC_COLORMAP | DrawColumnType::DC_TRANSMAP)) == (DrawColumnType::DC_COLORMAP | DrawColumnType::DC_TRANSMAP)) + UINT8 * restrict dest; + + if constexpr ((Type & (DrawColumnType::DC_COLORMAP | DrawColumnType::DC_TRANSMAP)) + == (DrawColumnType::DC_COLORMAP | DrawColumnType::DC_TRANSMAP)) dest = R_GetBufferColormapTrans(dc); else if constexpr (Type & DrawColumnType::DC_TRANSMAP) dest = R_GetBufferTrans(dc); diff --git a/src/r_draw_flush.cpp b/src/r_draw_flush.cpp index b1bbb464f..23fd4beb3 100644 --- a/src/r_draw_flush.cpp +++ b/src/r_draw_flush.cpp @@ -19,10 +19,11 @@ // Flushes the entire columns in the buffer, one at a time. // This is used when a quad flush isn't possible. // -static void R_FlushWholeOpaque(void) +template +static void R_FlushWhole(void) { - UINT8 *source; - UINT8 *dest; + UINT8 * restrict source; + UINT8 * restrict dest; INT32 count, yl; const restrict INT32 stride = vid.width; @@ -35,81 +36,40 @@ static void R_FlushWholeOpaque(void) while (--count >= 0) { - *dest = *source; + if constexpr (Type & ColumnFlushType::FLUSH_OPAQUE) + { + *dest = *source; + } + else if constexpr (Type & ColumnFlushType::FLUSH_TRANS) + { + *dest = temp_dc.tranmap[(*dest << 8) + *source]; + } + else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP) + { + *dest = temp_dc.translation[*source]; + } + else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP_TRANS) + { + *dest = temp_dc.tranmap[(*dest << 8) + temp_dc.translation[*source]]; + } + source += 4; dest += stride; } } } -static void R_FlushWholeTrans(void) -{ - UINT8 *source; - UINT8 *dest; - INT32 count, yl; - const restrict INT32 stride = vid.width; - - while (--temp_dc.x >= 0) - { - yl = temp_dc.yl[temp_dc.x]; - source = &temp_dc.buf[temp_dc.x + (yl << 2)]; - dest = R_Address(temp_dc.startx + temp_dc.x, yl); - count = temp_dc.yh[temp_dc.x] - yl + 1; - - while (--count >= 0) - { - *dest = temp_dc.tranmap[(*dest << 8) + *source]; - source += 4; - dest += stride; - } +#define DEFINE_GETFLUSHWHOLE_FUNC(name, flags) \ + static inline void name(void) \ + { \ + constexpr ColumnFlushType opt = static_cast(flags); \ + R_FlushWhole(); \ } -} -static void R_FlushWholeColormap(void) -{ - UINT8 *source; - UINT8 *dest; - INT32 count, yl; - const restrict INT32 stride = vid.width; - - while (--temp_dc.x >= 0) - { - yl = temp_dc.yl[temp_dc.x]; - source = &temp_dc.buf[temp_dc.x + (yl << 2)]; - dest = R_Address(temp_dc.startx + temp_dc.x, yl); - count = temp_dc.yh[temp_dc.x] - yl + 1; - - while (--count >= 0) - { - *dest = temp_dc.translation[*source]; - source += 4; - dest += stride; - } - } -} - -static void R_FlushWholeColormapTrans(void) -{ - UINT8 *source; - UINT8 *dest; - INT32 count, yl; - const restrict INT32 stride = vid.width; - - while (--temp_dc.x >= 0) - { - yl = temp_dc.yl[temp_dc.x]; - source = &temp_dc.buf[temp_dc.x + (yl << 2)]; - dest = R_Address(temp_dc.startx + temp_dc.x, yl); - count = temp_dc.yh[temp_dc.x] - yl + 1; - - while (--count >= 0) - { - *dest = temp_dc.tranmap[(*dest << 8) + temp_dc.translation[*source]]; - source += 4; - dest += stride; - } - } -} +DEFINE_GETFLUSHWHOLE_FUNC(R_FlushWholeOpague, FLUSH_OPAQUE) +DEFINE_GETFLUSHWHOLE_FUNC(R_FlushWholeTrans, FLUSH_TRANS) +DEFINE_GETFLUSHWHOLE_FUNC(R_FlushWholeColormap, FLUSH_COLORMAP) +DEFINE_GETFLUSHWHOLE_FUNC(R_FlushWholeColormapTrans, FLUSH_COLORMAP_TRANS) // // R_FlushHT @@ -117,56 +77,11 @@ static void R_FlushWholeColormapTrans(void) // Flushes the head and tail of columns in the buffer in // preparation for a quad flush. // -static void R_FlushHTOpaque(void) +template +static void R_FlushHT(void) { - UINT8 *source; - UINT8 *dest; - INT32 count, colnum = 0; - INT32 yl, yh; - const restrict INT32 stride = vid.width; - - while (colnum < 4) - { - yl = temp_dc.yl[colnum]; - yh = temp_dc.yh[colnum]; - - // flush column head - if (yl < temp_dc.commontop) - { - source = &temp_dc.buf[colnum + (yl << 2)]; - dest = R_Address(temp_dc.startx + colnum, yl); - count = temp_dc.commontop - yl; - - while (--count >= 0) - { - *dest = *source; - source += 4; - dest += stride; - } - } - - // flush column tail - if (yh > temp_dc.commonbot) - { - source = &temp_dc.buf[colnum + ((temp_dc.commonbot + 1) << 2)]; - dest = R_Address(temp_dc.startx + colnum, temp_dc.commonbot + 1); - count = yh - temp_dc.commonbot; - - while (--count >= 0) - { - *dest = *source; - source += 4; - dest += stride; - } - } - ++colnum; - } -} - -static void R_FlushHTTrans(void) -{ - UINT8 *source; - UINT8 *dest; + UINT8 * restrict source; + UINT8 * restrict dest; INT32 count; INT32 colnum = 0, yl, yh; const restrict INT32 stride = vid.width; @@ -185,7 +100,23 @@ static void R_FlushHTTrans(void) while (--count >= 0) { - *dest = temp_dc.tranmap[(*dest << 8) + *source]; + if constexpr (Type & ColumnFlushType::FLUSH_OPAQUE) + { + *dest = *source; + } + else if constexpr (Type & ColumnFlushType::FLUSH_TRANS) + { + *dest = temp_dc.tranmap[(*dest << 8) + *source]; + } + else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP) + { + *dest = temp_dc.translation[*source]; + } + else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP_TRANS) + { + *dest = temp_dc.tranmap[(*dest << 8) + temp_dc.translation[*source]]; + } + source += 4; dest += stride; } @@ -200,7 +131,23 @@ static void R_FlushHTTrans(void) while (--count >= 0) { - *dest = temp_dc.tranmap[(*dest << 8) + *source]; + if constexpr (Type & ColumnFlushType::FLUSH_OPAQUE) + { + *dest = *source; + } + else if constexpr (Type & ColumnFlushType::FLUSH_TRANS) + { + *dest = temp_dc.tranmap[(*dest << 8) + *source]; + } + else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP) + { + *dest = temp_dc.translation[*source]; + } + else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP_TRANS) + { + *dest = temp_dc.tranmap[(*dest << 8) + temp_dc.translation[*source]]; + } + source += 4; dest += stride; } @@ -210,206 +157,107 @@ static void R_FlushHTTrans(void) } } -static void R_FlushHTColormap(void) -{ - UINT8 *source; - UINT8 *dest; - INT32 count; - INT32 colnum = 0, yl, yh; - const restrict INT32 stride = vid.width; - - while (colnum < 4) - { - yl = temp_dc.yl[colnum]; - yh = temp_dc.yh[colnum]; - - // flush column head - if (yl < temp_dc.commontop) - { - source = &temp_dc.buf[colnum + (yl << 2)]; - dest = R_Address(temp_dc.startx + colnum, yl); - count = temp_dc.commontop - yl; - - while (--count >= 0) - { - *dest = temp_dc.translation[*source]; - source += 4; - dest += stride; - } - } - - // flush column tail - if (yh > temp_dc.commonbot) - { - source = &temp_dc.buf[colnum + ((temp_dc.commonbot + 1) << 2)]; - dest = R_Address(temp_dc.startx + colnum, temp_dc.commonbot + 1); - count = yh - temp_dc.commonbot; - - while (--count >= 0) - { - *dest = temp_dc.translation[*source]; - source += 4; - dest += stride; - } - } - - ++colnum; +#define DEFINE_GETFLUSHHT_FUNC(name, flags) \ + static inline void name(void) \ + { \ + constexpr ColumnFlushType opt = static_cast(flags); \ + R_FlushHT(); \ } -} -static void R_FlushHTColormapTrans(void) +DEFINE_GETFLUSHHT_FUNC(R_FlushHTOpague, FLUSH_OPAQUE) +DEFINE_GETFLUSHHT_FUNC(R_FlushHTTrans, FLUSH_TRANS) +DEFINE_GETFLUSHHT_FUNC(R_FlushHTColormap, FLUSH_COLORMAP) +DEFINE_GETFLUSHHT_FUNC(R_FlushHTColormapTrans, FLUSH_COLORMAP_TRANS) + +template +static void R_FlushQuad(void) { - UINT8 *source; - UINT8 *dest; - INT32 count; - INT32 colnum = 0, yl, yh; - const restrict INT32 stride = vid.width; - - while (colnum < 4) - { - yl = temp_dc.yl[colnum]; - yh = temp_dc.yh[colnum]; - - // flush column head - if (yl < temp_dc.commontop) - { - source = &temp_dc.buf[colnum + (yl << 2)]; - dest = R_Address(temp_dc.startx + colnum, yl); - count = temp_dc.commontop - yl; - - while (--count >= 0) - { - *dest = temp_dc.tranmap[(*dest << 8) + temp_dc.translation[*source]]; - source += 4; - dest += stride; - } - } - - // flush column tail - if (yh > temp_dc.commonbot) - { - source = &temp_dc.buf[colnum + ((temp_dc.commonbot + 1) << 2)]; - dest = R_Address(temp_dc.startx + colnum, temp_dc.commonbot + 1); - count = yh - temp_dc.commonbot; - - while (--count >= 0) - { - *dest = temp_dc.tranmap[(*dest << 8) + temp_dc.translation[*source]]; - source += 4; - dest += stride; - } - } - - ++colnum; - } -} - -static void R_FlushQuadOpaque(void) -{ - UINT8 *source = &temp_dc.buf[temp_dc.commontop << 2]; - UINT8 *dest = R_Address(temp_dc.startx, temp_dc.commontop); + UINT8 * restrict source = &temp_dc.buf[temp_dc.commontop << 2]; + UINT8 * restrict dest = R_Address(temp_dc.startx, temp_dc.commontop); INT32 count; const restrict INT32 stride = vid.width; count = temp_dc.commonbot - temp_dc.commontop + 1; - if ((sizeof(int) == 4) && (((intptr_t)source % 4) == 0) && (((intptr_t)dest % 4) == 0)) + if constexpr (Type & ColumnFlushType::FLUSH_OPAQUE) { - while(--count >= 0) + if ((sizeof(int) == 4) && (((intptr_t)source % 4) == 0) && (((intptr_t)dest % 4) == 0)) { - *(int *)dest = *(int *)source; - source += 4 * sizeof(UINT8); - dest += stride * sizeof(UINT8); + while(--count >= 0) + { + *(int *)dest = *(int *)source; + source += 4 * sizeof(UINT8); + dest += stride * sizeof(UINT8); + } + } + else + { + while(--count >= 0) + { + dest[0] = source[0]; + dest[1] = source[1]; + dest[2] = source[2]; + dest[3] = source[3]; + source += 4 * sizeof(UINT8); + dest += stride * sizeof(UINT8); + } } } - else + else if constexpr (Type & ColumnFlushType::FLUSH_TRANS) { - while(--count >= 0) + while (--count >= 0) { - dest[0] = source[0]; - dest[1] = source[1]; - dest[2] = source[2]; - dest[3] = source[3]; - source += 4 * sizeof(UINT8); - dest += stride * sizeof(UINT8); + dest[0] = temp_dc.tranmap[(dest[0] << 8) + source[0]]; + dest[1] = temp_dc.tranmap[(dest[1] << 8) + source[1]]; + dest[2] = temp_dc.tranmap[(dest[2] << 8) + source[2]]; + dest[3] = temp_dc.tranmap[(dest[3] << 8) + source[3]]; + source += 4; + dest += stride; } } - - while(--count >= 0) + else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP) { - dest[0] = source[0]; - dest[1] = source[1]; - dest[2] = source[2]; - dest[3] = source[3]; - source += 4 * sizeof(UINT8); - dest += stride * sizeof(UINT8); + while (--count >= 0) + { + dest[0] = temp_dc.translation[source[0]]; + dest[1] = temp_dc.translation[source[1]]; + dest[2] = temp_dc.translation[source[2]]; + dest[3] = temp_dc.translation[source[3]]; + source += 4; + dest += stride; + } + } + else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP_TRANS) + { + while (--count >= 0) + { + dest[0] = temp_dc.tranmap[(dest[0] << 8) + temp_dc.translation[source[0]]]; + dest[1] = temp_dc.tranmap[(dest[1] << 8) + temp_dc.translation[source[1]]]; + dest[2] = temp_dc.tranmap[(dest[2] << 8) + temp_dc.translation[source[2]]]; + dest[3] = temp_dc.tranmap[(dest[3] << 8) + temp_dc.translation[source[3]]]; + source += 4; + dest += stride; + } } } -static void R_FlushQuadTrans(void) -{ - UINT8 *source = &temp_dc.buf[temp_dc.commontop << 2]; - UINT8 *dest = R_Address(temp_dc.startx, temp_dc.commontop); - INT32 count; - const restrict INT32 stride = vid.width; - - count = temp_dc.commonbot - temp_dc.commontop + 1; - - while (--count >= 0) - { - dest[0] = temp_dc.tranmap[(dest[0] << 8) + source[0]]; - dest[1] = temp_dc.tranmap[(dest[1] << 8) + source[1]]; - dest[2] = temp_dc.tranmap[(dest[2] << 8) + source[2]]; - dest[3] = temp_dc.tranmap[(dest[3] << 8) + source[3]]; - source += 4; - dest += stride; +#define DEFINE_GETFLUSHQUAD_FUNC(name, flags) \ + static inline void name(void) \ + { \ + constexpr ColumnFlushType opt = static_cast(flags); \ + R_FlushQuad(); \ } -} -static void R_FlushQuadColormap(void) -{ - UINT8 *source = &temp_dc.buf[temp_dc.commontop << 2]; - UINT8 *dest = R_Address(temp_dc.startx, temp_dc.commontop); - INT32 count; - const restrict INT32 stride = vid.width; +DEFINE_GETFLUSHQUAD_FUNC(R_FlushQuadOpague, FLUSH_OPAQUE) +DEFINE_GETFLUSHQUAD_FUNC(R_FlushQuadTrans, FLUSH_TRANS) +DEFINE_GETFLUSHQUAD_FUNC(R_FlushQuadColormap, FLUSH_COLORMAP) +DEFINE_GETFLUSHQUAD_FUNC(R_FlushQuadColormapTrans, FLUSH_COLORMAP_TRANS) - count = temp_dc.commonbot - temp_dc.commontop + 1; - - while (--count >= 0) - { - dest[0] = temp_dc.translation[source[0]]; - dest[1] = temp_dc.translation[source[1]]; - dest[2] = temp_dc.translation[source[2]]; - dest[3] = temp_dc.translation[source[3]]; - source += 4; - dest += stride; - } -} - -static void R_FlushQuadColormapTrans(void) -{ - UINT8 *source = &temp_dc.buf[temp_dc.commontop << 2]; - UINT8 *dest = R_Address(temp_dc.startx, temp_dc.commontop); - INT32 count; - const restrict INT32 stride = vid.width; - - count = temp_dc.commonbot - temp_dc.commontop + 1; - - while (--count >= 0) - { - dest[0] = temp_dc.tranmap[(dest[0] << 8) + temp_dc.translation[source[0]]]; - dest[1] = temp_dc.tranmap[(dest[1] << 8) + temp_dc.translation[source[1]]]; - dest[2] = temp_dc.tranmap[(dest[2] << 8) + temp_dc.translation[source[2]]]; - dest[3] = temp_dc.tranmap[(dest[3] << 8) + temp_dc.translation[source[3]]]; - source += 4; - dest += stride; - } -} - -static UINT8 *R_GetBufferOpaque(drawcolumndata_t *dc) +template +static UINT8 *R_GetBuffer(drawcolumndata_t *dc) { if (temp_dc.x == 4 || - (temp_dc.x && (temp_dc.type != FLUSH_OPAQUE || temp_dc.x + temp_dc.startx != dc->x))) + (temp_dc.x && (temp_dc.type != Type || temp_dc.x + temp_dc.startx != dc->x))) R_FlushColumns(); if (!temp_dc.x) @@ -417,10 +265,37 @@ static UINT8 *R_GetBufferOpaque(drawcolumndata_t *dc) temp_dc.startx = dc->x; temp_dc.yl[0] = temp_dc.commontop = dc->yl; temp_dc.yh[0] = temp_dc.commonbot = dc->yh; - temp_dc.type = FLUSH_OPAQUE; - R_FlushWholeColumns = R_FlushWholeOpaque; - R_FlushHTColumns = R_FlushHTOpaque; - R_FlushQuadColumn = R_FlushQuadOpaque; + temp_dc.type = Type; + + if constexpr (Type & ColumnFlushType::FLUSH_OPAQUE) + { + R_FlushWholeColumns = R_FlushWholeOpague; + R_FlushHTColumns = R_FlushHTOpague; + R_FlushQuadColumn = R_FlushQuadOpague; + } + else if constexpr (Type & ColumnFlushType::FLUSH_TRANS) + { + temp_dc.tranmap = dc->transmap; + R_FlushWholeColumns = R_FlushWholeTrans; + R_FlushHTColumns = R_FlushHTTrans; + R_FlushQuadColumn = R_FlushQuadTrans; + } + else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP) + { + temp_dc.translation = dc->translation; + R_FlushWholeColumns = R_FlushWholeColormap; + R_FlushHTColumns = R_FlushHTColormap; + R_FlushQuadColumn = R_FlushQuadColormap; + } + else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP_TRANS) + { + temp_dc.tranmap = dc->transmap; + temp_dc.translation = dc->translation; + R_FlushWholeColumns = R_FlushWholeColormapTrans; + R_FlushHTColumns = R_FlushHTColormapTrans; + R_FlushQuadColumn = R_FlushQuadColormapTrans; + } + temp_dc.x += 1; return &temp_dc.buf[dc->yl << 2]; } @@ -436,96 +311,15 @@ static UINT8 *R_GetBufferOpaque(drawcolumndata_t *dc) return &temp_dc.buf[(dc->yl << 2) + temp_dc.x++]; } -static UINT8 *R_GetBufferTrans(drawcolumndata_t *dc) -{ - if (temp_dc.x == 4 || - (temp_dc.x && (temp_dc.type != FLUSH_TRANS || temp_dc.x + temp_dc.startx != dc->x))) - R_FlushColumns(); - - if (!temp_dc.x) - { - temp_dc.startx = dc->x; - temp_dc.yl[0] = temp_dc.commontop = dc->yl; - temp_dc.yh[0] = temp_dc.commonbot = dc->yh; - temp_dc.type = FLUSH_TRANS; - temp_dc.tranmap = dc->transmap; - R_FlushWholeColumns = R_FlushWholeTrans; - R_FlushHTColumns = R_FlushHTTrans; - R_FlushQuadColumn = R_FlushQuadTrans; - temp_dc.x += 1; - return &temp_dc.buf[dc->yl << 2]; +#define DEFINE_GETBUF_FUNC(name, flags) \ + static UINT8 *name(drawcolumndata_t *dc) \ + { \ + constexpr ColumnFlushType opt = static_cast(flags); \ + return R_GetBuffer(dc); \ } - temp_dc.yl[temp_dc.x] = dc->yl; - temp_dc.yh[temp_dc.x] = dc->yh; +DEFINE_GETBUF_FUNC(R_GetBufferOpaque, FLUSH_OPAQUE) +DEFINE_GETBUF_FUNC(R_GetBufferTrans, FLUSH_TRANS) +DEFINE_GETBUF_FUNC(R_GetBufferColormap, FLUSH_COLORMAP) +DEFINE_GETBUF_FUNC(R_GetBufferColormapTrans, FLUSH_COLORMAP_TRANS) - if (dc->yl > temp_dc.commontop) - temp_dc.commontop = dc->yl; - if (dc->yh < temp_dc.commonbot) - temp_dc.commonbot = dc->yh; - - return &temp_dc.buf[(dc->yl << 2) + temp_dc.x++]; -} - -static UINT8 *R_GetBufferColormap(drawcolumndata_t *dc) -{ - if (temp_dc.x == 4 || - (temp_dc.x && (temp_dc.type != FLUSH_COLORMAP || temp_dc.x + temp_dc.startx != dc->x))) - R_FlushColumns(); - - if (!temp_dc.x) - { - temp_dc.startx = dc->x; - temp_dc.yl[0] = temp_dc.commontop = dc->yl; - temp_dc.yh[0] = temp_dc.commonbot = dc->yh; - temp_dc.type = FLUSH_COLORMAP; - temp_dc.translation = dc->translation; - R_FlushWholeColumns = R_FlushWholeColormap; - R_FlushHTColumns = R_FlushHTColormap; - R_FlushQuadColumn = R_FlushQuadColormap; - temp_dc.x += 1; - return &temp_dc.buf[dc->yl << 2]; - } - - temp_dc.yl[temp_dc.x] = dc->yl; - temp_dc.yh[temp_dc.x] = dc->yh; - - if (dc->yl > temp_dc.commontop) - temp_dc.commontop = dc->yl; - if (dc->yh < temp_dc.commonbot) - temp_dc.commonbot = dc->yh; - - return &temp_dc.buf[(dc->yl << 2) + temp_dc.x++]; -} - -static UINT8 *R_GetBufferColormapTrans(drawcolumndata_t *dc) -{ - if (temp_dc.x == 4 || - (temp_dc.x && (temp_dc.type != FLUSH_COLORMAP_TRANS || temp_dc.x + temp_dc.startx != dc->x))) - R_FlushColumns(); - - if (!temp_dc.x) - { - temp_dc.startx = dc->x; - temp_dc.yl[0] = temp_dc.commontop = dc->yl; - temp_dc.yh[0] = temp_dc.commonbot = dc->yh; - temp_dc.type = FLUSH_COLORMAP_TRANS; - temp_dc.translation = dc->translation; - temp_dc.tranmap = dc->transmap; - R_FlushWholeColumns = R_FlushWholeColormapTrans; - R_FlushHTColumns = R_FlushHTColormapTrans; - R_FlushQuadColumn = R_FlushQuadColormapTrans; - temp_dc.x += 1; - return &temp_dc.buf[dc->yl << 2]; - } - - temp_dc.yl[temp_dc.x] = dc->yl; - temp_dc.yh[temp_dc.x] = dc->yh; - - if (dc->yl > temp_dc.commontop) - temp_dc.commontop = dc->yl; - if (dc->yh < temp_dc.commonbot) - temp_dc.commonbot = dc->yh; - - return &temp_dc.buf[(dc->yl << 2) + temp_dc.x++]; -} -- 2.54.0 From b44548b7acf2a9ea254d8a2765f351ec2c99f7ef Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 6 Oct 2025 22:43:49 +0200 Subject: [PATCH 035/219] dedupe those a bit --- src/r_draw_flush.cpp | 99 ++++++++++++++++---------------------------- 1 file changed, 36 insertions(+), 63 deletions(-) diff --git a/src/r_draw_flush.cpp b/src/r_draw_flush.cpp index 23fd4beb3..18bc207b9 100644 --- a/src/r_draw_flush.cpp +++ b/src/r_draw_flush.cpp @@ -13,6 +13,27 @@ /// \brief column flush functions /// \note no includes because this is included as part of r_draw.cpp +template +static inline UINT8 R_DrawFlushColumnPixel(UINT8 dest, UINT8 source) +{ + if constexpr (Type & ColumnFlushType::FLUSH_OPAQUE) + { + return source; + } + else if constexpr (Type & ColumnFlushType::FLUSH_TRANS) + { + return temp_dc.tranmap[(dest << 8) + source]; + } + else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP) + { + return temp_dc.translation[source]; + } + else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP_TRANS) + { + return temp_dc.tranmap[(dest << 8) + temp_dc.translation[source]]; + } +} + // // R_FlushWhole // @@ -24,8 +45,8 @@ static void R_FlushWhole(void) { UINT8 * restrict source; UINT8 * restrict dest; - INT32 count, yl; - const restrict INT32 stride = vid.width; + intptr_t count, yl; + const restrict intptr_t stride = vid.width; while (--temp_dc.x >= 0) { @@ -36,23 +57,7 @@ static void R_FlushWhole(void) while (--count >= 0) { - if constexpr (Type & ColumnFlushType::FLUSH_OPAQUE) - { - *dest = *source; - } - else if constexpr (Type & ColumnFlushType::FLUSH_TRANS) - { - *dest = temp_dc.tranmap[(*dest << 8) + *source]; - } - else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP) - { - *dest = temp_dc.translation[*source]; - } - else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP_TRANS) - { - *dest = temp_dc.tranmap[(*dest << 8) + temp_dc.translation[*source]]; - } - + *dest = R_DrawFlushColumnPixel(*dest, *source); source += 4; dest += stride; } @@ -82,9 +87,9 @@ static void R_FlushHT(void) { UINT8 * restrict source; UINT8 * restrict dest; - INT32 count; - INT32 colnum = 0, yl, yh; - const restrict INT32 stride = vid.width; + intptr_t count, colnum = 0; + intptr_t yl, yh; + const restrict intptr_t stride = vid.width; while (colnum < 4) { @@ -95,28 +100,12 @@ static void R_FlushHT(void) if (yl < temp_dc.commontop) { source = &temp_dc.buf[colnum + (yl << 2)]; - dest = R_Address(temp_dc.startx + colnum, yl); - count = temp_dc.commontop - yl; + dest = R_Address(temp_dc.startx + colnum, yl); + count = temp_dc.commontop - yl; while (--count >= 0) { - if constexpr (Type & ColumnFlushType::FLUSH_OPAQUE) - { - *dest = *source; - } - else if constexpr (Type & ColumnFlushType::FLUSH_TRANS) - { - *dest = temp_dc.tranmap[(*dest << 8) + *source]; - } - else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP) - { - *dest = temp_dc.translation[*source]; - } - else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP_TRANS) - { - *dest = temp_dc.tranmap[(*dest << 8) + temp_dc.translation[*source]]; - } - + *dest = R_DrawFlushColumnPixel(*dest, *source); source += 4; dest += stride; } @@ -126,28 +115,12 @@ static void R_FlushHT(void) if (yh > temp_dc.commonbot) { source = &temp_dc.buf[colnum + ((temp_dc.commonbot + 1) << 2)]; - dest = R_Address(temp_dc.startx + colnum, temp_dc.commonbot + 1); - count = yh - temp_dc.commonbot; + dest = R_Address(temp_dc.startx + colnum, temp_dc.commonbot + 1); + count = yh - temp_dc.commonbot; while (--count >= 0) { - if constexpr (Type & ColumnFlushType::FLUSH_OPAQUE) - { - *dest = *source; - } - else if constexpr (Type & ColumnFlushType::FLUSH_TRANS) - { - *dest = temp_dc.tranmap[(*dest << 8) + *source]; - } - else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP) - { - *dest = temp_dc.translation[*source]; - } - else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP_TRANS) - { - *dest = temp_dc.tranmap[(*dest << 8) + temp_dc.translation[*source]]; - } - + *dest = R_DrawFlushColumnPixel(*dest, *source); source += 4; dest += stride; } @@ -174,8 +147,8 @@ static void R_FlushQuad(void) { UINT8 * restrict source = &temp_dc.buf[temp_dc.commontop << 2]; UINT8 * restrict dest = R_Address(temp_dc.startx, temp_dc.commontop); - INT32 count; - const restrict INT32 stride = vid.width; + intptr_t count; + const restrict intptr_t stride = vid.width; count = temp_dc.commonbot - temp_dc.commontop + 1; @@ -312,7 +285,7 @@ static UINT8 *R_GetBuffer(drawcolumndata_t *dc) } #define DEFINE_GETBUF_FUNC(name, flags) \ - static UINT8 *name(drawcolumndata_t *dc) \ + static inline UINT8 *name(drawcolumndata_t *dc) \ { \ constexpr ColumnFlushType opt = static_cast(flags); \ return R_GetBuffer(dc); \ -- 2.54.0 From 23512f0a6c102db4b6c97978e85f69e38f0f7a4f Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 6 Oct 2025 23:31:44 +0200 Subject: [PATCH 036/219] align our tempbuf --- src/r_draw.cpp | 19 +++++++++++++++++-- src/r_draw_flush.cpp | 8 ++++---- src/r_main.cpp | 10 +++++----- src/r_plane.cpp | 2 +- 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/r_draw.cpp b/src/r_draw.cpp index b2cad26e0..eb43404df 100644 --- a/src/r_draw.cpp +++ b/src/r_draw.cpp @@ -621,11 +621,26 @@ void R_InitViewBuffer(INT32 width, INT32 height) linesize = vid.width; // killough 11/98 renderscreen = vid.screens[0]; // haleyjd 07/02/14 + INT32 bufsize = (linesize * 4) * sizeof(*temp_dc.buf); + if (temp_dc.buf) - Z_Free(temp_dc.buf); + { +#if defined(__SSE__) + aligned_free(temp_dc.buf); +#else + free(temp_dc.buf); +#endif + } memset(&temp_dc, 0, sizeof(temp_dc)); - temp_dc.buf = static_cast(Z_Calloc((vid.height * 4) * sizeof(*temp_dc.buf), PU_STATIC, NULL)); + +#if defined(__SSE__) + while (bufsize & 15) + bufsize++; + temp_dc.buf = static_cast(aligned_alloc(16, bufsize)); +#else + temp_dc.buf = static_cast(Z_Calloc(bufsize, PU_STATIC, NULL)); +#endif } /** \brief viewborder patches lump numbers diff --git a/src/r_draw_flush.cpp b/src/r_draw_flush.cpp index 18bc207b9..d27fb8cd8 100644 --- a/src/r_draw_flush.cpp +++ b/src/r_draw_flush.cpp @@ -65,7 +65,7 @@ static void R_FlushWhole(void) } #define DEFINE_GETFLUSHWHOLE_FUNC(name, flags) \ - static inline void name(void) \ + FUNCINLINE static ATTRINLINE void name(void) \ { \ constexpr ColumnFlushType opt = static_cast(flags); \ R_FlushWhole(); \ @@ -131,7 +131,7 @@ static void R_FlushHT(void) } #define DEFINE_GETFLUSHHT_FUNC(name, flags) \ - static inline void name(void) \ + FUNCINLINE static ATTRINLINE void name(void) \ { \ constexpr ColumnFlushType opt = static_cast(flags); \ R_FlushHT(); \ @@ -215,7 +215,7 @@ static void R_FlushQuad(void) } #define DEFINE_GETFLUSHQUAD_FUNC(name, flags) \ - static inline void name(void) \ + FUNCINLINE static ATTRINLINE void name(void) \ { \ constexpr ColumnFlushType opt = static_cast(flags); \ R_FlushQuad(); \ @@ -285,7 +285,7 @@ static UINT8 *R_GetBuffer(drawcolumndata_t *dc) } #define DEFINE_GETBUF_FUNC(name, flags) \ - static inline UINT8 *name(drawcolumndata_t *dc) \ + FUNCINLINE static ATTRINLINE UINT8 *name(drawcolumndata_t *dc) \ { \ constexpr ColumnFlushType opt = static_cast(flags); \ return R_GetBuffer(dc); \ diff --git a/src/r_main.cpp b/src/r_main.cpp index 132349a82..dd98f747b 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1409,9 +1409,9 @@ void R_RenderPlayerView(player_t *player) R_ClipSprites(drawsegs, NULL); R_DrawSkyPlanes(); // draw the fucker again to prevent some artifacts R_DrawPlanes(); - //R_ResetColumnBuffer(); + R_ResetColumnBuffer(); R_DrawMasked(masks, nummasks); - //R_ResetColumnBuffer(); + R_ResetColumnBuffer(); } PS_STOP_TIMING(ps_skyboxtime); @@ -1495,18 +1495,18 @@ void R_RenderPlayerView(player_t *player) PS_START_TIMING(ps_sw_planetime); if (!skybox) R_DrawSkyPlanes(); - R_ResetColumnBuffer(); R_DrawPlanes(); + R_ResetColumnBuffer(); PS_STOP_TIMING(ps_sw_planetime); // draw mid texture and sprite // And now 3D floors/sides! PS_START_TIMING(ps_sw_maskedtime); R_DrawMasked(masks, nummasks); PS_STOP_TIMING(ps_sw_maskedtime); - R_ResetColumnBuffer(); - free(masks); + R_ResetColumnBuffer(); + // Check for new console commands. NetUpdate(); diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 16e344bdf..83508e16a 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -1158,7 +1158,7 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle offset = (scry*vid.width) + scrx; // No idea if this works - VID_BlitLinearScreen(renderscreen + offset, + VID_BlitLinearScreen(vid.screens[0] + offset, vid.screens[1] + (top*vid.width), // intentionally not +offset viewwidth, bottom-top, vid.width, vid.width); -- 2.54.0 From fa8901f6b06003a744080b493c5c179a61f7b26e Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 7 Oct 2025 00:25:27 +0200 Subject: [PATCH 037/219] fix ColumnFlushType enum --- src/r_draw.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/r_draw.cpp b/src/r_draw.cpp index eb43404df..5234267e8 100644 --- a/src/r_draw.cpp +++ b/src/r_draw.cpp @@ -491,11 +491,11 @@ void R_FlushTranslationColormapCache(void) enum ColumnFlushType { - FLUSH_NONE, - FLUSH_OPAQUE, - FLUSH_TRANS, - FLUSH_COLORMAP, - FLUSH_COLORMAP_TRANS + FLUSH_NONE = 0x0000, + FLUSH_OPAQUE = 0x0001, + FLUSH_TRANS = 0x0002, + FLUSH_COLORMAP = 0x0004, + FLUSH_COLORMAP_TRANS = 0x0008, }; typedef struct drawcolumndata_temp_s -- 2.54.0 From 4deebf8912b6e7fc4bdeba81eef53529bc3c87d9 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 7 Oct 2025 00:28:34 +0200 Subject: [PATCH 038/219] translucency is handled on the flush side! --- src/r_draw_column.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/r_draw_column.cpp b/src/r_draw_column.cpp index c2275fbd4..43107e721 100644 --- a/src/r_draw_column.cpp +++ b/src/r_draw_column.cpp @@ -48,11 +48,11 @@ static constexpr UINT8 R_GetColumnTranslucent(drawcolumndata_t* dc, UINT8 * rest { col = R_GetColumnTranslated(dc, col, colormap); - if constexpr (Type & DrawColumnType::DC_TRANSMAP) + /*if constexpr (Type & DrawColumnType::DC_TRANSMAP) { return *(dc->transmap + (col << 8) + (*dest)); } - else + else*/ { return col; } -- 2.54.0 From e5a03dc3bb3a29ac41a481e7718e7254b2d50d19 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 7 Oct 2025 01:01:13 +0200 Subject: [PATCH 039/219] fix translucency being only half as translucent oops lmao didnt notice in all of this doom uses the inverse of our blendlevels kek --- src/r_draw_column.cpp | 4 ++-- src/r_draw_flush.cpp | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/r_draw_column.cpp b/src/r_draw_column.cpp index 43107e721..b15294c75 100644 --- a/src/r_draw_column.cpp +++ b/src/r_draw_column.cpp @@ -44,7 +44,7 @@ static constexpr UINT8 R_GetColumnTranslated(drawcolumndata_t* dc, UINT8 col, co } template -static constexpr UINT8 R_GetColumnTranslucent(drawcolumndata_t* dc, UINT8 * restrict dest, UINT8 col, const UINT8 * restrict colormap) +static constexpr UINT8 R_GetColumnTranslucent(drawcolumndata_t* dc, UINT8 col, const UINT8 * restrict colormap) { col = R_GetColumnTranslated(dc, col, colormap); @@ -71,7 +71,7 @@ static constexpr UINT8 R_DrawColumnPixel(drawcolumndata_t* dc, UINT8 * restrict } } - return R_GetColumnTranslucent(dc, dest, col, colormap); + return R_GetColumnTranslucent(dc, col, colormap); } /** \brief The R_DrawColumn function diff --git a/src/r_draw_flush.cpp b/src/r_draw_flush.cpp index d27fb8cd8..fcc94a767 100644 --- a/src/r_draw_flush.cpp +++ b/src/r_draw_flush.cpp @@ -22,7 +22,7 @@ static inline UINT8 R_DrawFlushColumnPixel(UINT8 dest, UINT8 source) } else if constexpr (Type & ColumnFlushType::FLUSH_TRANS) { - return temp_dc.tranmap[(dest << 8) + source]; + return temp_dc.tranmap[(source << 8) + dest]; } else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP) { @@ -30,7 +30,7 @@ static inline UINT8 R_DrawFlushColumnPixel(UINT8 dest, UINT8 source) } else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP_TRANS) { - return temp_dc.tranmap[(dest << 8) + temp_dc.translation[source]]; + return temp_dc.tranmap[(temp_dc.translation[source] << 8) + dest]; } } @@ -180,10 +180,10 @@ static void R_FlushQuad(void) { while (--count >= 0) { - dest[0] = temp_dc.tranmap[(dest[0] << 8) + source[0]]; - dest[1] = temp_dc.tranmap[(dest[1] << 8) + source[1]]; - dest[2] = temp_dc.tranmap[(dest[2] << 8) + source[2]]; - dest[3] = temp_dc.tranmap[(dest[3] << 8) + source[3]]; + dest[0] = temp_dc.tranmap[(source[0] << 8) + dest[0]]; + dest[1] = temp_dc.tranmap[(source[1] << 8) + dest[1]]; + dest[2] = temp_dc.tranmap[(source[2] << 8) + dest[2]]; + dest[3] = temp_dc.tranmap[(source[3] << 8) + dest[3]]; source += 4; dest += stride; } @@ -204,10 +204,10 @@ static void R_FlushQuad(void) { while (--count >= 0) { - dest[0] = temp_dc.tranmap[(dest[0] << 8) + temp_dc.translation[source[0]]]; - dest[1] = temp_dc.tranmap[(dest[1] << 8) + temp_dc.translation[source[1]]]; - dest[2] = temp_dc.tranmap[(dest[2] << 8) + temp_dc.translation[source[2]]]; - dest[3] = temp_dc.tranmap[(dest[3] << 8) + temp_dc.translation[source[3]]]; + dest[0] = temp_dc.tranmap[(temp_dc.translation[source[0]] << 8) + dest[0]]; + dest[1] = temp_dc.tranmap[(temp_dc.translation[source[1]] << 8) + dest[1]]; + dest[2] = temp_dc.tranmap[(temp_dc.translation[source[2]] << 8) + dest[2]]; + dest[3] = temp_dc.tranmap[(temp_dc.translation[source[3]] << 8) + dest[3]]; source += 4; dest += stride; } -- 2.54.0 From 39a5165d919e333d23fcb8ada6bdecf033ca599b Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 7 Oct 2025 01:02:25 +0200 Subject: [PATCH 040/219] reset our column buffer directly after bsp traversal we do not need to wait for sky draw since the sky gets instantly drawn --- src/r_main.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/r_main.cpp b/src/r_main.cpp index dd98f747b..ac722dbdd 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1405,11 +1405,11 @@ void R_RenderPlayerView(player_t *player) R_ClearSprites(); R_RenderViewpoint(&masks[nummasks - 1], false); + R_ResetColumnBuffer(); R_ClipSprites(drawsegs, NULL); R_DrawSkyPlanes(); // draw the fucker again to prevent some artifacts R_DrawPlanes(); - R_ResetColumnBuffer(); R_DrawMasked(masks, nummasks); R_ResetColumnBuffer(); } @@ -1447,6 +1447,7 @@ void R_RenderPlayerView(player_t *player) PS_START_TIMING(ps_bsptime); R_RenderViewpoint(&masks[nummasks - 1], true); PS_STOP_TIMING(ps_bsptime); + R_ResetColumnBuffer(); PS_START_TIMING(ps_sw_spritecliptime); R_ClipSprites(drawsegs, NULL); PS_STOP_TIMING(ps_sw_spritecliptime); @@ -1496,7 +1497,6 @@ void R_RenderPlayerView(player_t *player) if (!skybox) R_DrawSkyPlanes(); R_DrawPlanes(); - R_ResetColumnBuffer(); PS_STOP_TIMING(ps_sw_planetime); // draw mid texture and sprite // And now 3D floors/sides! @@ -1504,7 +1504,6 @@ void R_RenderPlayerView(player_t *player) R_DrawMasked(masks, nummasks); PS_STOP_TIMING(ps_sw_maskedtime); free(masks); - R_ResetColumnBuffer(); // Check for new console commands. -- 2.54.0 From c9b6276a02aa46d662e6a66837bc90eb78d6259d Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 7 Oct 2025 01:31:27 +0200 Subject: [PATCH 041/219] merge sky column drawer back lets hope this is safe lulul --- src/r_draw_column.cpp | 174 +++++------------------------------------- src/r_plane.cpp | 6 +- 2 files changed, 23 insertions(+), 157 deletions(-) diff --git a/src/r_draw_column.cpp b/src/r_draw_column.cpp index b15294c75..8ec979cde 100644 --- a/src/r_draw_column.cpp +++ b/src/r_draw_column.cpp @@ -30,6 +30,7 @@ enum DrawColumnType DC_TRANSMAP = 0x0002, DC_HOLES = 0x0004, DC_LIGHTLIST = 0x0008, + DC_SKY = 0x0010, }; template @@ -208,8 +209,10 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) // SoM: MAGIC UINT8 * restrict dest; - if constexpr ((Type & (DrawColumnType::DC_COLORMAP | DrawColumnType::DC_TRANSMAP)) - == (DrawColumnType::DC_COLORMAP | DrawColumnType::DC_TRANSMAP)) + if constexpr (Type & DrawColumnType::DC_SKY) + dest = R_Address(dc->x, dc->yl); + else if constexpr ((Type & (DrawColumnType::DC_COLORMAP | DrawColumnType::DC_TRANSMAP)) + == (DrawColumnType::DC_COLORMAP | DrawColumnType::DC_TRANSMAP)) dest = R_GetBufferColormapTrans(dc); else if constexpr (Type & DrawColumnType::DC_TRANSMAP) dest = R_GetBufferTrans(dc); @@ -218,6 +221,11 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) else dest = R_GetBufferOpaque(dc); + restrict INT32 stride = 4; + + if constexpr (Type & DrawColumnType::DC_SKY) + stride = vid.width; + count++; // Determine scaling, which is the only mapping to be done. @@ -231,7 +239,8 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) while (count--) { *dest = R_DrawColumnPixel(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap); - dest += 4; + + dest += stride; frac += fracstep; } } @@ -246,7 +255,8 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) while (--count >= 0) { *dest = R_DrawColumnPixel(dc, dest, frac>>FRACBITS, source, colormap); - dest += 4; + + dest += stride; frac += fracstep; } } @@ -258,11 +268,13 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) while ((count -= 2) >= 0) // texture height is a power of 2 -- killough { *dest = R_DrawColumnPixel(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap); - dest += 4; + + dest += stride; frac += fracstep; *dest = R_DrawColumnPixel(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap); - dest += 4; + + dest += stride; frac += fracstep; } @@ -300,7 +312,7 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) // and a few bytes after as well *dest = R_DrawColumnPixel(dc, dest, CLAMP((frac >> FRACBITS), npow2min, npow2max), source, colormap); - dest += 4; + dest += stride; #if __SIZEOF_POINTER__ < 8 // 64-bit systems have large enough numbers for this to be a non-issue // Avoid overflow. @@ -341,6 +353,7 @@ DEFINE_COLUMN_FUNC(R_DrawColumnShadowed, DC_LIGHTLIST) DEFINE_COLUMN_FUNC(R_DrawTranslatedTranslucentColumn, DC_COLORMAP|DC_TRANSMAP) DEFINE_COLUMN_FUNC(R_Draw2sMultiPatchColumn, DC_HOLES) DEFINE_COLUMN_FUNC(R_Draw2sMultiPatchTranslucentColumn, DC_HOLES|DC_TRANSMAP) +DEFINE_COLUMN_FUNC(R_DrawSkyColumn, DC_SKY) /** \brief The R_DrawFogColumn function Fog wall. @@ -377,150 +390,3 @@ void R_DrawFogColumn(drawcolumndata_t* dc) dest += stride; } while (count--); } - -// blunt copy paste for now -// cant share a global buffer between threads for obvious reasons lmao -void R_DrawSkyColumn(drawcolumndata_t *dc) -{ - INT32 count; - - count = dc->yh - dc->yl; - - if (count < 0) // Zero length, column does not exceed a pixel. - { - return; - } - - if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height) - { - return; - } - - { - // Inner loop that does the actual texture mapping, - // e.g. a DDA-lile scaling. - // This is as fast as it gets. (Yeah, right!!! -- killough) - // - // killough 2/1/98: more performance tuning - - intptr_t frac; - const intptr_t fracstep = dc->iscale; - const intptr_t heightmask = dc->sourcelength-1; - constexpr INT32 npow2min = -1; - const INT32 npow2max = dc->sourcelength; - const INT32 stride = vid.width; - - const UINT8 * restrict source = dc->source; - const lighttable_t * restrict colormap = dc->colormap; - - // Framebuffer destination address. - UINT8 * restrict dest = R_Address(dc->x, dc->yl); - - count++; - - // Determine scaling, which is the only mapping to be done. - frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep)); - - switch (heightmask) - { - case 255: - case 127: - { - while(count--) - { - *dest = R_DrawColumnPixel(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap); - dest += stride; - frac += fracstep; - } - } - break; - case -1: - { - if (frac < 0) - // adjust in case we underread - frac += fracstep; - - // texture has no height, so just go - while (--count >= 0) - { - *dest = R_DrawColumnPixel(dc, dest, frac>>FRACBITS, source, colormap); - dest += stride; - frac += fracstep; - } - } - break; - default: - { - if (!(dc->sourcelength & heightmask)) // power of 2 -- killough - { - while ((count -= 2) >= 0) // texture height is a power of 2 -- killough - { - *dest = R_DrawColumnPixel(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap); - dest += stride; - frac += fracstep; - - *dest = R_DrawColumnPixel(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap); - dest += stride; - frac += fracstep; - } - - if (count & 1) - { - *dest = R_DrawColumnPixel(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap); - } - } - else - { - const intptr_t fixed_heightmask = dc->texheight << FRACBITS; - - if (frac < 0) - { - while ((frac += fixed_heightmask) < 0) - { - ; - } - } - else - { - while (frac >= fixed_heightmask) - { - frac -= fixed_heightmask; - } - } - - do - { - // Re-map color indices from wall texture column - // using a lighting/special effects LUT. - // heightmask is the Tutti-Frutti fix - - // -1 is the lower clamp bound because column posts have a "safe" byte before the real data - // and a few bytes after as well - *dest = R_DrawColumnPixel(dc, dest, CLAMP((frac >> FRACBITS), npow2min, npow2max), source, colormap); - - dest += stride; - -#if __SIZEOF_POINTER__ < 8 // 64-bit systems have large enough numbers for this to be a non-issue - // Avoid overflow. - if (fracstep > 0x7FFFFFFF - frac) - { - frac += fracstep - fixed_heightmask; - } - else -#endif - { - frac += fracstep; - } - - while (frac >= fixed_heightmask) - { - frac -= fixed_heightmask; - } - } - while (--count); - } - } - break; - } - } -} diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 83508e16a..7c2ff271d 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -739,7 +739,7 @@ void R_DrawPlanes(void) #endif } -static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), boolean allow_parallel); +static void R_DrawSkyPlane(visplane_t *pl, boolean allow_parallel); void R_DrawSkyPlanes(void) { @@ -757,7 +757,7 @@ void R_DrawSkyPlanes(void) if (pl->picnum != skyflatnum || pl->ffloor || pl->polyobj) continue; - R_DrawSkyPlane(pl, colfunc, cv_parallelsoftware.value); + R_DrawSkyPlane(pl, cv_parallelsoftware.value); } } #ifdef HAVE_THREADS @@ -767,7 +767,7 @@ void R_DrawSkyPlanes(void) #endif } -static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), boolean allow_parallel) +static void R_DrawSkyPlane(visplane_t *pl, boolean allow_parallel) { INT32 x; -- 2.54.0 From 41b78feef5b2e81382fb354dce7c095fc101bf64 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 7 Oct 2025 01:38:00 +0200 Subject: [PATCH 042/219] remove R_GetColumnTranslucent --- src/r_draw_column.cpp | 12 +++++++----- src/r_draw_flush.cpp | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/r_draw_column.cpp b/src/r_draw_column.cpp index 8ec979cde..4102035d1 100644 --- a/src/r_draw_column.cpp +++ b/src/r_draw_column.cpp @@ -44,20 +44,21 @@ static constexpr UINT8 R_GetColumnTranslated(drawcolumndata_t* dc, UINT8 col, co return colormap[col]; } -template +// translucency is handled on flush side now! +/*template static constexpr UINT8 R_GetColumnTranslucent(drawcolumndata_t* dc, UINT8 col, const UINT8 * restrict colormap) { col = R_GetColumnTranslated(dc, col, colormap); - /*if constexpr (Type & DrawColumnType::DC_TRANSMAP) + if constexpr (Type & DrawColumnType::DC_TRANSMAP) { return *(dc->transmap + (col << 8) + (*dest)); } - else*/ + else { return col; } -} +}*/ template static constexpr UINT8 R_DrawColumnPixel(drawcolumndata_t* dc, UINT8 * restrict dest, UINT32 bit, const UINT8 * restrict source, const UINT8 * restrict colormap) @@ -72,7 +73,8 @@ static constexpr UINT8 R_DrawColumnPixel(drawcolumndata_t* dc, UINT8 * restrict } } - return R_GetColumnTranslucent(dc, col, colormap); + //return R_GetColumnTranslucent(dc, col, colormap); + return R_GetColumnTranslated(dc, col, colormap); } /** \brief The R_DrawColumn function diff --git a/src/r_draw_flush.cpp b/src/r_draw_flush.cpp index fcc94a767..53ce2f3f7 100644 --- a/src/r_draw_flush.cpp +++ b/src/r_draw_flush.cpp @@ -14,7 +14,7 @@ /// \note no includes because this is included as part of r_draw.cpp template -static inline UINT8 R_DrawFlushColumnPixel(UINT8 dest, UINT8 source) +FUNCINLINE static ATTRINLINE UINT8 R_DrawFlushColumnPixel(UINT8 restrict dest, UINT8 restrict source) { if constexpr (Type & ColumnFlushType::FLUSH_OPAQUE) { -- 2.54.0 From b6943ce92ef7e8f0efc477344b856909748441bc Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 7 Oct 2025 01:48:34 +0200 Subject: [PATCH 043/219] can check on compile if sizeof int == 4 can prob remove it alltogether we dont support 16 bit cpus kek --- src/r_draw_flush.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/r_draw_flush.cpp b/src/r_draw_flush.cpp index 53ce2f3f7..ff85f351d 100644 --- a/src/r_draw_flush.cpp +++ b/src/r_draw_flush.cpp @@ -154,7 +154,8 @@ static void R_FlushQuad(void) if constexpr (Type & ColumnFlushType::FLUSH_OPAQUE) { - if ((sizeof(int) == 4) && (((intptr_t)source % 4) == 0) && (((intptr_t)dest % 4) == 0)) +#if __SIZEOF_INT__ == 4 + if ((((intptr_t)source % 4) == 0) && (((intptr_t)dest % 4) == 0)) { while(--count >= 0) { @@ -164,6 +165,7 @@ static void R_FlushQuad(void) } } else +#endif { while(--count >= 0) { -- 2.54.0 From c9f50ca0c875a0c018052b375cf94acbaaf166ec Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 7 Oct 2025 01:59:24 +0200 Subject: [PATCH 044/219] sizeof(UINT8) is 1 lel --- src/r_draw_flush.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/r_draw_flush.cpp b/src/r_draw_flush.cpp index ff85f351d..96d58cccd 100644 --- a/src/r_draw_flush.cpp +++ b/src/r_draw_flush.cpp @@ -160,21 +160,21 @@ static void R_FlushQuad(void) while(--count >= 0) { *(int *)dest = *(int *)source; - source += 4 * sizeof(UINT8); - dest += stride * sizeof(UINT8); + source += 4; + dest += stride; } } else #endif { - while(--count >= 0) + while (--count >= 0) { dest[0] = source[0]; dest[1] = source[1]; dest[2] = source[2]; dest[3] = source[3]; - source += 4 * sizeof(UINT8); - dest += stride * sizeof(UINT8); + source += 4; + dest += stride; } } } -- 2.54.0 From ba3404d823a9da695fdc24f59dc26c14942eff46 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 7 Oct 2025 16:00:12 +0200 Subject: [PATCH 045/219] cleanup + type fixes --- src/r_draw.cpp | 14 +++++----- src/r_draw_flush.cpp | 61 ++++++++++++++++++++++++-------------------- 2 files changed, 40 insertions(+), 35 deletions(-) diff --git a/src/r_draw.cpp b/src/r_draw.cpp index 5234267e8..26184c158 100644 --- a/src/r_draw.cpp +++ b/src/r_draw.cpp @@ -500,18 +500,18 @@ enum ColumnFlushType typedef struct drawcolumndata_temp_s { - intptr_t x; - intptr_t yl[4], yh[4]; + INT32 x; + INT32 yl[4], yh[4]; // e6y: resolution limitation is removed UINT8 *buf; - intptr_t startx; + INT32 startx; ColumnFlushType type; - intptr_t commontop, commonbot; - const UINT8 *tranmap; + INT32 commontop, commonbot; + UINT8 *transmap; // SoM 7-28-04: Fix the fuzz problem. - const UINT8 *translation; + UINT8 *translation; } drawcolumndata_temp_t; drawcolumndata_temp_t temp_dc = {}; @@ -628,7 +628,7 @@ void R_InitViewBuffer(INT32 width, INT32 height) #if defined(__SSE__) aligned_free(temp_dc.buf); #else - free(temp_dc.buf); + Z_Free(temp_dc.buf); #endif } diff --git a/src/r_draw_flush.cpp b/src/r_draw_flush.cpp index 96d58cccd..bed7fd1fa 100644 --- a/src/r_draw_flush.cpp +++ b/src/r_draw_flush.cpp @@ -22,7 +22,7 @@ FUNCINLINE static ATTRINLINE UINT8 R_DrawFlushColumnPixel(UINT8 restrict dest, U } else if constexpr (Type & ColumnFlushType::FLUSH_TRANS) { - return temp_dc.tranmap[(source << 8) + dest]; + return temp_dc.transmap[(source << 8) + dest]; } else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP) { @@ -30,7 +30,7 @@ FUNCINLINE static ATTRINLINE UINT8 R_DrawFlushColumnPixel(UINT8 restrict dest, U } else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP_TRANS) { - return temp_dc.tranmap[(temp_dc.translation[source] << 8) + dest]; + return temp_dc.transmap[(temp_dc.translation[source] << 8) + dest]; } } @@ -45,8 +45,8 @@ static void R_FlushWhole(void) { UINT8 * restrict source; UINT8 * restrict dest; - intptr_t count, yl; - const restrict intptr_t stride = vid.width; + INT32 count, yl; + const INT32 stride = vid.width; while (--temp_dc.x >= 0) { @@ -87,9 +87,9 @@ static void R_FlushHT(void) { UINT8 * restrict source; UINT8 * restrict dest; - intptr_t count, colnum = 0; - intptr_t yl, yh; - const restrict intptr_t stride = vid.width; + INT32 count, colnum = 0; + INT32 yl, yh; + const INT32 stride = vid.width; while (colnum < 4) { @@ -147,19 +147,17 @@ static void R_FlushQuad(void) { UINT8 * restrict source = &temp_dc.buf[temp_dc.commontop << 2]; UINT8 * restrict dest = R_Address(temp_dc.startx, temp_dc.commontop); - intptr_t count; - const restrict intptr_t stride = vid.width; - - count = temp_dc.commonbot - temp_dc.commontop + 1; + INT32 count = temp_dc.commonbot - temp_dc.commontop + 1; + const INT32 stride = vid.width; if constexpr (Type & ColumnFlushType::FLUSH_OPAQUE) { #if __SIZEOF_INT__ == 4 - if ((((intptr_t)source % 4) == 0) && (((intptr_t)dest % 4) == 0)) + if ((((uintptr_t)source | (uintptr_t)dest) & 3) == 0) { - while(--count >= 0) + while (--count >= 0) { - *(int *)dest = *(int *)source; + *(UINT32 *)dest = *(UINT32 *)source; source += 4; dest += stride; } @@ -180,36 +178,43 @@ static void R_FlushQuad(void) } else if constexpr (Type & ColumnFlushType::FLUSH_TRANS) { + const UINT8 * restrict transmap = temp_dc.transmap; + while (--count >= 0) { - dest[0] = temp_dc.tranmap[(source[0] << 8) + dest[0]]; - dest[1] = temp_dc.tranmap[(source[1] << 8) + dest[1]]; - dest[2] = temp_dc.tranmap[(source[2] << 8) + dest[2]]; - dest[3] = temp_dc.tranmap[(source[3] << 8) + dest[3]]; + dest[0] = transmap[(source[0] << 8) + dest[0]]; + dest[1] = transmap[(source[1] << 8) + dest[1]]; + dest[2] = transmap[(source[2] << 8) + dest[2]]; + dest[3] = transmap[(source[3] << 8) + dest[3]]; source += 4; dest += stride; } } else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP) { + const UINT8 * restrict translation = temp_dc.translation; + while (--count >= 0) { - dest[0] = temp_dc.translation[source[0]]; - dest[1] = temp_dc.translation[source[1]]; - dest[2] = temp_dc.translation[source[2]]; - dest[3] = temp_dc.translation[source[3]]; + dest[0] = translation[source[0]]; + dest[1] = translation[source[1]]; + dest[2] = translation[source[2]]; + dest[3] = translation[source[3]]; source += 4; dest += stride; } } else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP_TRANS) { + const UINT8 * restrict transmap = temp_dc.transmap; + const UINT8 * restrict translation = temp_dc.translation; + while (--count >= 0) { - dest[0] = temp_dc.tranmap[(temp_dc.translation[source[0]] << 8) + dest[0]]; - dest[1] = temp_dc.tranmap[(temp_dc.translation[source[1]] << 8) + dest[1]]; - dest[2] = temp_dc.tranmap[(temp_dc.translation[source[2]] << 8) + dest[2]]; - dest[3] = temp_dc.tranmap[(temp_dc.translation[source[3]] << 8) + dest[3]]; + dest[0] = transmap[(translation[source[0]] << 8) + dest[0]]; + dest[1] = transmap[(translation[source[1]] << 8) + dest[1]]; + dest[2] = transmap[(translation[source[2]] << 8) + dest[2]]; + dest[3] = transmap[(translation[source[3]] << 8) + dest[3]]; source += 4; dest += stride; } @@ -250,7 +255,7 @@ static UINT8 *R_GetBuffer(drawcolumndata_t *dc) } else if constexpr (Type & ColumnFlushType::FLUSH_TRANS) { - temp_dc.tranmap = dc->transmap; + temp_dc.transmap = dc->transmap; R_FlushWholeColumns = R_FlushWholeTrans; R_FlushHTColumns = R_FlushHTTrans; R_FlushQuadColumn = R_FlushQuadTrans; @@ -264,7 +269,7 @@ static UINT8 *R_GetBuffer(drawcolumndata_t *dc) } else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP_TRANS) { - temp_dc.tranmap = dc->transmap; + temp_dc.transmap = dc->transmap; temp_dc.translation = dc->translation; R_FlushWholeColumns = R_FlushWholeColormapTrans; R_FlushHTColumns = R_FlushHTColormapTrans; -- 2.54.0 From 32504b9e8ea568d13760b8dd6b51285f52d90930 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 7 Oct 2025 16:50:43 +0200 Subject: [PATCH 046/219] speed up Opague quad flush from eternity engine --- src/r_draw_column.cpp | 7 ++++--- src/r_draw_flush.cpp | 41 ++++++++++++++++------------------------- 2 files changed, 20 insertions(+), 28 deletions(-) diff --git a/src/r_draw_column.cpp b/src/r_draw_column.cpp index 4102035d1..aa5d03d91 100644 --- a/src/r_draw_column.cpp +++ b/src/r_draw_column.cpp @@ -199,6 +199,7 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) // killough 2/1/98: more performance tuning intptr_t frac; + // Looks familiar. const intptr_t fracstep = dc->iscale; const intptr_t heightmask = dc->sourcelength-1; // CPhipps - specify type constexpr INT32 npow2min = -1; @@ -223,12 +224,12 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) else dest = R_GetBufferOpaque(dc); - restrict INT32 stride = 4; + restrict INT32 stride = 4; //SoM: Oh, Oh it's MAGIC! You know... if constexpr (Type & DrawColumnType::DC_SKY) - stride = vid.width; + stride = vid.width; // no MAGIC for the sky here X) - count++; + count++; // killough 1/99: minor tuning // Determine scaling, which is the only mapping to be done. frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep)); diff --git a/src/r_draw_flush.cpp b/src/r_draw_flush.cpp index bed7fd1fa..f0fa37f14 100644 --- a/src/r_draw_flush.cpp +++ b/src/r_draw_flush.cpp @@ -145,39 +145,25 @@ DEFINE_GETFLUSHHT_FUNC(R_FlushHTColormapTrans, FLUSH_COLORMAP_TRANS) template static void R_FlushQuad(void) { - UINT8 * restrict source = &temp_dc.buf[temp_dc.commontop << 2]; - UINT8 * restrict dest = R_Address(temp_dc.startx, temp_dc.commontop); - INT32 count = temp_dc.commonbot - temp_dc.commontop + 1; const INT32 stride = vid.width; + INT32 count = temp_dc.commonbot - temp_dc.commontop + 1; if constexpr (Type & ColumnFlushType::FLUSH_OPAQUE) { -#if __SIZEOF_INT__ == 4 - if ((((uintptr_t)source | (uintptr_t)dest) & 3) == 0) + const INT32 *source = reinterpret_cast(temp_dc.buf + (temp_dc.commontop << 2)); + INT32 *dest = reinterpret_cast(R_Address(temp_dc.startx, temp_dc.commontop)); + INT32 deststep = stride / 4; + + while(--count >= 0) { - while (--count >= 0) - { - *(UINT32 *)dest = *(UINT32 *)source; - source += 4; - dest += stride; - } - } - else -#endif - { - while (--count >= 0) - { - dest[0] = source[0]; - dest[1] = source[1]; - dest[2] = source[2]; - dest[3] = source[3]; - source += 4; - dest += stride; - } + *dest = *source++; + dest += deststep; } } else if constexpr (Type & ColumnFlushType::FLUSH_TRANS) { + const UINT8 * restrict source = temp_dc.buf + (temp_dc.commontop << 2); + UINT8 * restrict dest = R_Address(temp_dc.startx, temp_dc.commontop); const UINT8 * restrict transmap = temp_dc.transmap; while (--count >= 0) @@ -192,6 +178,8 @@ static void R_FlushQuad(void) } else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP) { + const UINT8 * restrict source = temp_dc.buf + (temp_dc.commontop << 2); + UINT8 * restrict dest = R_Address(temp_dc.startx, temp_dc.commontop); const UINT8 * restrict translation = temp_dc.translation; while (--count >= 0) @@ -206,6 +194,8 @@ static void R_FlushQuad(void) } else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP_TRANS) { + const UINT8 * restrict source = temp_dc.buf + (temp_dc.commontop << 2); + UINT8 * restrict dest = R_Address(temp_dc.startx, temp_dc.commontop); const UINT8 * restrict transmap = temp_dc.transmap; const UINT8 * restrict translation = temp_dc.translation; @@ -236,12 +226,14 @@ DEFINE_GETFLUSHQUAD_FUNC(R_FlushQuadColormapTrans, FLUSH_COLORMAP_TRANS) template static UINT8 *R_GetBuffer(drawcolumndata_t *dc) { + // haleyjd: reordered predicates if (temp_dc.x == 4 || (temp_dc.x && (temp_dc.type != Type || temp_dc.x + temp_dc.startx != dc->x))) R_FlushColumns(); if (!temp_dc.x) { + ++temp_dc.x; temp_dc.startx = dc->x; temp_dc.yl[0] = temp_dc.commontop = dc->yl; temp_dc.yh[0] = temp_dc.commonbot = dc->yh; @@ -276,7 +268,6 @@ static UINT8 *R_GetBuffer(drawcolumndata_t *dc) R_FlushQuadColumn = R_FlushQuadColormapTrans; } - temp_dc.x += 1; return &temp_dc.buf[dc->yl << 2]; } -- 2.54.0 From 57990100c563f828848a4ec37e49a699174aa264 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 7 Oct 2025 17:18:30 +0200 Subject: [PATCH 047/219] speed up masked sprites a bit thx eternity engine! --- src/r_things.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/r_things.cpp b/src/r_things.cpp index 4713bc50e..60dba8a32 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -2810,6 +2810,11 @@ void R_ClipSprites(drawseg_t* dsstart, portal_t* portal) drawseg_t* ds; INT32 i; + if (visspritecount - clippedvissprites <= 0) + { + return; + } + // e6y // Reducing of cache misses in the following R_DrawSprite() // Makes sense for scenes with huge amount of drawsegs. @@ -2819,13 +2824,9 @@ void R_ClipSprites(drawseg_t* dsstart, portal_t* portal) drawsegs_xranges[i].count = 0; } - if (visspritecount - clippedvissprites <= 0) - { - return; - } - if (drawsegs_xrange_size < maxdrawsegs) { + // haleyjd: fix reallocation to track 2x size drawsegs_xrange_size = 2 * maxdrawsegs; for (i = 0; i < DS_RANGES_COUNT; i++) @@ -2865,6 +2866,9 @@ void R_ClipSprites(drawseg_t* dsstart, portal_t* portal) } } + // haleyjd: terminate with a nullptr user for faster loop - adds ~3 FPS + drawsegs_xranges[0].items[drawsegs_xranges[0].count].user = nullptr; + for (; clippedvissprites < visspritecount; clippedvissprites++) { vissprite_t *spr = R_GetVisSprite(clippedvissprites); -- 2.54.0 From b12989f51ca3b0614bd16be9c427aaecabae5a54 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 7 Oct 2025 17:19:07 +0200 Subject: [PATCH 048/219] lessen our manual column buffer resetting not really needed --- src/r_main.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/r_main.cpp b/src/r_main.cpp index ac722dbdd..f2ee2bc96 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1405,7 +1405,6 @@ void R_RenderPlayerView(player_t *player) R_ClearSprites(); R_RenderViewpoint(&masks[nummasks - 1], false); - R_ResetColumnBuffer(); R_ClipSprites(drawsegs, NULL); R_DrawSkyPlanes(); // draw the fucker again to prevent some artifacts @@ -1447,7 +1446,6 @@ void R_RenderPlayerView(player_t *player) PS_START_TIMING(ps_bsptime); R_RenderViewpoint(&masks[nummasks - 1], true); PS_STOP_TIMING(ps_bsptime); - R_ResetColumnBuffer(); PS_START_TIMING(ps_sw_spritecliptime); R_ClipSprites(drawsegs, NULL); PS_STOP_TIMING(ps_sw_spritecliptime); -- 2.54.0 From fe54f2fba2af916f658aea75f54caf4f2c4191cc Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 7 Oct 2025 18:15:11 +0200 Subject: [PATCH 049/219] add Column drawer context switching reasoning explained in screen.c effectively, there are cases where drawing our columns directly to the screen is the better choice --- src/r_draw.cpp | 2 ++ src/r_draw.h | 21 ++++++++++++++++-- src/r_draw_column.cpp | 50 ++++++++++++++++++++++++++++--------------- src/r_main.cpp | 5 +++++ src/r_plane.cpp | 12 +++++------ src/screen.c | 43 +++++++++++++++++++++++++++++-------- src/screen.h | 1 + 7 files changed, 99 insertions(+), 35 deletions(-) diff --git a/src/r_draw.cpp b/src/r_draw.cpp index 26184c158..93638708b 100644 --- a/src/r_draw.cpp +++ b/src/r_draw.cpp @@ -489,6 +489,8 @@ void R_FlushTranslationColormapCache(void) // in reality, the few routines that can work for either mode, are // put here +enum columncontext_e columncontext = COLUMNCONTEXT_DIRECT; + enum ColumnFlushType { FLUSH_NONE = 0x0000, diff --git a/src/r_draw.h b/src/r_draw.h index 232e6c8ce..ae9d2ef40 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -102,6 +102,16 @@ extern floatv3_t *ds_su, *ds_sv, *ds_sz; extern float focallengthf; +enum columncontext_e +{ + COLUMNCONTEXT_DIRECT = 0, + COLUMNCONTEXT_FLUSH, +}; + +extern enum columncontext_e columncontext; +void R_SetColumnContext(enum columncontext_e _columncontext); + +void R_ResetColumnBuffer(void); typedef void (coldrawfunc_t)(drawcolumndata_t*); typedef void (spandrawfunc_t)(drawspandata_t*); @@ -250,10 +260,17 @@ void R_DrawTranslatedTranslucentColumn(drawcolumndata_t* dc); void R_Draw2sMultiPatchColumn(drawcolumndata_t* dc); void R_Draw2sMultiPatchTranslucentColumn(drawcolumndata_t* dc); +// column drawers which use buffered drawing with flush +void R_DrawColumnFlush(drawcolumndata_t* dc); +void R_DrawTranslucentColumnFlush(drawcolumndata_t* dc); +void R_DrawTranslatedColumnFlush(drawcolumndata_t* dc); +void R_DrawColumnShadowedFlush(drawcolumndata_t* dc); +void R_DrawTranslatedTranslucentColumnFlush(drawcolumndata_t* dc); +void R_Draw2sMultiPatchColumnFlush(drawcolumndata_t* dc); +void R_Draw2sMultiPatchTranslucentColumnFlush(drawcolumndata_t* dc); + void R_DrawFogColumn(drawcolumndata_t* dc); -void R_ResetColumnBuffer(void); -void R_DrawSkyColumn(drawcolumndata_t *dc); // span drawers void R_DrawSpan(drawspandata_t* ds); diff --git a/src/r_draw_column.cpp b/src/r_draw_column.cpp index aa5d03d91..27b570b0b 100644 --- a/src/r_draw_column.cpp +++ b/src/r_draw_column.cpp @@ -30,7 +30,7 @@ enum DrawColumnType DC_TRANSMAP = 0x0002, DC_HOLES = 0x0004, DC_LIGHTLIST = 0x0008, - DC_SKY = 0x0010, + DC_DIRECT = 0x0010, // draw our columns directly to screen! }; template @@ -45,8 +45,8 @@ static constexpr UINT8 R_GetColumnTranslated(drawcolumndata_t* dc, UINT8 col, co } // translucency is handled on flush side now! -/*template -static constexpr UINT8 R_GetColumnTranslucent(drawcolumndata_t* dc, UINT8 col, const UINT8 * restrict colormap) +template +static constexpr UINT8 R_GetColumnTranslucent(drawcolumndata_t* dc, UINT8 * restrict dest, UINT8 col, const UINT8 * restrict colormap) { col = R_GetColumnTranslated(dc, col, colormap); @@ -58,7 +58,7 @@ static constexpr UINT8 R_GetColumnTranslucent(drawcolumndata_t* dc, UINT8 col, c { return col; } -}*/ +} template static constexpr UINT8 R_DrawColumnPixel(drawcolumndata_t* dc, UINT8 * restrict dest, UINT32 bit, const UINT8 * restrict source, const UINT8 * restrict colormap) @@ -73,8 +73,14 @@ static constexpr UINT8 R_DrawColumnPixel(drawcolumndata_t* dc, UINT8 * restrict } } - //return R_GetColumnTranslucent(dc, col, colormap); - return R_GetColumnTranslated(dc, col, colormap); + if constexpr (Type & DrawColumnType::DC_DIRECT) + { // if we dont flush our columns, we need to handle translucency again + return R_GetColumnTranslucent(dc, dest, col, colormap); + } + else + { + return R_GetColumnTranslated(dc, col, colormap); + } } /** \brief The R_DrawColumn function @@ -212,7 +218,7 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) // SoM: MAGIC UINT8 * restrict dest; - if constexpr (Type & DrawColumnType::DC_SKY) + if constexpr (Type & DrawColumnType::DC_DIRECT) dest = R_Address(dc->x, dc->yl); else if constexpr ((Type & (DrawColumnType::DC_COLORMAP | DrawColumnType::DC_TRANSMAP)) == (DrawColumnType::DC_COLORMAP | DrawColumnType::DC_TRANSMAP)) @@ -226,8 +232,8 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) restrict INT32 stride = 4; //SoM: Oh, Oh it's MAGIC! You know... - if constexpr (Type & DrawColumnType::DC_SKY) - stride = vid.width; // no MAGIC for the sky here X) + if constexpr (Type & DrawColumnType::DC_DIRECT) + stride = vid.width; count++; // killough 1/99: minor tuning @@ -349,14 +355,24 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) R_DrawColumnTemplate(dc); \ } -DEFINE_COLUMN_FUNC(R_DrawColumn, DC_BASIC) -DEFINE_COLUMN_FUNC(R_DrawTranslucentColumn, DC_TRANSMAP) -DEFINE_COLUMN_FUNC(R_DrawTranslatedColumn, DC_COLORMAP) -DEFINE_COLUMN_FUNC(R_DrawColumnShadowed, DC_LIGHTLIST) -DEFINE_COLUMN_FUNC(R_DrawTranslatedTranslucentColumn, DC_COLORMAP|DC_TRANSMAP) -DEFINE_COLUMN_FUNC(R_Draw2sMultiPatchColumn, DC_HOLES) -DEFINE_COLUMN_FUNC(R_Draw2sMultiPatchTranslucentColumn, DC_HOLES|DC_TRANSMAP) -DEFINE_COLUMN_FUNC(R_DrawSkyColumn, DC_SKY) +DEFINE_COLUMN_FUNC(R_DrawColumn, DC_DIRECT|DC_BASIC) +DEFINE_COLUMN_FUNC(R_DrawTranslucentColumn, DC_DIRECT|DC_TRANSMAP) +DEFINE_COLUMN_FUNC(R_DrawTranslatedColumn, DC_DIRECT|DC_COLORMAP) +DEFINE_COLUMN_FUNC(R_DrawColumnShadowed, DC_DIRECT|DC_LIGHTLIST) +DEFINE_COLUMN_FUNC(R_DrawTranslatedTranslucentColumn, DC_DIRECT|DC_COLORMAP|DC_TRANSMAP) +DEFINE_COLUMN_FUNC(R_Draw2sMultiPatchColumn, DC_DIRECT|DC_HOLES) +DEFINE_COLUMN_FUNC(R_Draw2sMultiPatchTranslucentColumn, DC_DIRECT|DC_HOLES|DC_TRANSMAP) + +DEFINE_COLUMN_FUNC(R_DrawColumnFlush, DC_BASIC) +DEFINE_COLUMN_FUNC(R_DrawTranslucentColumnFlush, DC_TRANSMAP) +DEFINE_COLUMN_FUNC(R_DrawTranslatedColumnFlush, DC_COLORMAP) +DEFINE_COLUMN_FUNC(R_DrawColumnShadowedFlush, DC_LIGHTLIST) +DEFINE_COLUMN_FUNC(R_DrawTranslatedTranslucentColumnFlush, DC_COLORMAP|DC_TRANSMAP) +DEFINE_COLUMN_FUNC(R_Draw2sMultiPatchColumnFlush, DC_HOLES) +DEFINE_COLUMN_FUNC(R_Draw2sMultiPatchTranslucentColumnFlush, DC_HOLES|DC_TRANSMAP) + +//skymyass +//DEFINE_COLUMN_FUNC(R_DrawSkyColumn, DC_SKY) /** \brief The R_DrawFogColumn function Fog wall. diff --git a/src/r_main.cpp b/src/r_main.cpp index f2ee2bc96..79e49438f 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1391,6 +1391,8 @@ void R_RenderPlayerView(player_t *player) R_SetFov(fov); } + R_SetColumnContext(COLUMNCONTEXT_FLUSH); + Portal_InitList(); PS_START_TIMING(ps_skyboxtime); @@ -1407,6 +1409,7 @@ void R_RenderPlayerView(player_t *player) R_RenderViewpoint(&masks[nummasks - 1], false); R_ClipSprites(drawsegs, NULL); + R_SetColumnContext(COLUMNCONTEXT_DIRECT); R_DrawSkyPlanes(); // draw the fucker again to prevent some artifacts R_DrawPlanes(); R_DrawMasked(masks, nummasks); @@ -1442,6 +1445,7 @@ void R_RenderPlayerView(player_t *player) // check for new console commands. NetUpdate(); + R_SetColumnContext(COLUMNCONTEXT_FLUSH); ps_numbspcalls.value.i = ps_numpolyobjects.value.i = ps_numdrawnodes.value.i = 0; PS_START_TIMING(ps_bsptime); R_RenderViewpoint(&masks[nummasks - 1], true); @@ -1491,6 +1495,7 @@ void R_RenderPlayerView(player_t *player) } PS_STOP_TIMING(ps_sw_portaltime); + R_SetColumnContext(COLUMNCONTEXT_DIRECT); PS_START_TIMING(ps_sw_planetime); if (!skybox) R_DrawSkyPlanes(); diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 7c2ff271d..71e6a4dca 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -739,7 +739,7 @@ void R_DrawPlanes(void) #endif } -static void R_DrawSkyPlane(visplane_t *pl, boolean allow_parallel); +static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), boolean allow_parallel); void R_DrawSkyPlanes(void) { @@ -757,7 +757,7 @@ void R_DrawSkyPlanes(void) if (pl->picnum != skyflatnum || pl->ffloor || pl->polyobj) continue; - R_DrawSkyPlane(pl, cv_parallelsoftware.value); + R_DrawSkyPlane(pl, colfunc, cv_parallelsoftware.value); } } #ifdef HAVE_THREADS @@ -767,7 +767,7 @@ void R_DrawSkyPlanes(void) #endif } -static void R_DrawSkyPlane(visplane_t *pl, boolean allow_parallel) +static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), boolean allow_parallel) { INT32 x; @@ -834,8 +834,7 @@ static void R_DrawSkyPlane(visplane_t *pl, boolean allow_parallel) dc.x = x + i; dc.source = R_GetColumn(texture, -angle); // get negative of angle for each column to display sky correct way round! --Monster Iestyn 27/01/18 - //colfunc2(&dc); - R_DrawSkyColumn(&dc); + colfunc2(&dc); } }; @@ -872,8 +871,7 @@ static void R_DrawSkyPlane(visplane_t *pl, boolean allow_parallel) R_GetColumn(texturetranslation[skytexture], -angle); // get negative of angle for each column to display sky correct way round! --Monster Iestyn 27/01/18 - //colfunc2(&dc); - R_DrawSkyColumn(&dc); + colfunc2(&dc); } #endif } diff --git a/src/screen.c b/src/screen.c index 21ec0ed52..735bb88c4 100644 --- a/src/screen.c +++ b/src/screen.c @@ -84,7 +84,7 @@ UINT8 *scr_borderpatch; // flat used to fill the reduced view borders set at ST_ // ========================================================================= -static void SCR_SetDrawFuncs(void) +static void SCR_SetDrawFuncs(enum columncontext_e _columncontext) { // // setup the right draw routines @@ -103,13 +103,27 @@ static void SCR_SetDrawFuncs(void) spanfuncs[SPANDRAWFUNC_FOG] = R_DrawFogSpan; spanfuncs[SPANDRAWFUNC_TILTEDFOG] = R_DrawFogSpan_Tilted; - colfuncs[BASEDRAWFUNC] = R_DrawColumn; - colfuncs[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn; - colfuncs[COLDRAWFUNC_TRANS] = R_DrawTranslatedColumn; - colfuncs[COLDRAWFUNC_SHADOWED] = R_DrawColumnShadowed; - colfuncs[COLDRAWFUNC_TRANSTRANS] = R_DrawTranslatedTranslucentColumn; - colfuncs[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn; - colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS] = R_Draw2sMultiPatchTranslucentColumn; + if (_columncontext == COLUMNCONTEXT_FLUSH) + { + colfuncs[BASEDRAWFUNC] = R_DrawColumnFlush; + colfuncs[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumnFlush; + colfuncs[COLDRAWFUNC_TRANS] = R_DrawTranslatedColumnFlush; + colfuncs[COLDRAWFUNC_SHADOWED] = R_DrawColumnShadowedFlush; + colfuncs[COLDRAWFUNC_TRANSTRANS] = R_DrawTranslatedTranslucentColumnFlush; + colfuncs[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumnFlush; + colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS] = R_Draw2sMultiPatchTranslucentColumnFlush; + } + else + { + colfuncs[BASEDRAWFUNC] = R_DrawColumn; + colfuncs[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn; + colfuncs[COLDRAWFUNC_TRANS] = R_DrawTranslatedColumn; + colfuncs[COLDRAWFUNC_SHADOWED] = R_DrawColumnShadowed; + colfuncs[COLDRAWFUNC_TRANSTRANS] = R_DrawTranslatedTranslucentColumn; + colfuncs[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn; + colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS] = R_Draw2sMultiPatchTranslucentColumn; + } + colfuncs[COLDRAWFUNC_FOG] = R_DrawFogColumn; R_SetColumnFunc(BASEDRAWFUNC); @@ -131,12 +145,23 @@ void SCR_SetMode(void) V_SetPalette(0); - SCR_SetDrawFuncs(); + SCR_SetDrawFuncs(COLUMNCONTEXT_DIRECT); // set the apprpriate drawer for the sky (tall or INT16) setmodeneeded = 0; } +// used to switch between column buffering and drawing them directly to screen +// our sky "plane" drawer cannot handle the buffer system due to multithreading +// (that would require alot of extra complexity for smth with massive diminishing results) +// Our masked drawing step draws things in a very particular order, which results in alot of flushing to screen +// effectively adding massive overhead during buffering, so we draw our masked thing directly to screen instead +void R_SetColumnContext(enum columncontext_e _columncontext) +{ + columncontext = _columncontext; + SCR_SetDrawFuncs(_columncontext); // set our column drawers +} + void R_SetColumnFunc(size_t id) { I_Assert(id < COLDRAWFUNC_MAX); diff --git a/src/screen.h b/src/screen.h index ecad24a64..8cd90c23a 100644 --- a/src/screen.h +++ b/src/screen.h @@ -96,6 +96,7 @@ extern consvar_t cv_vidwait; extern consvar_t cv_votebgscaling; +//void R_SetColumnContext(enum columncontext_e _columncontext); // declared in r_draw! void R_SetColumnFunc(size_t id); void R_SetSpanFunc(size_t id); boolean R_CheckColumnFunc(size_t id); -- 2.54.0 From 55afe9be7e94967222a1ed3944c83850cfec1e74 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 7 Oct 2025 20:47:47 +0200 Subject: [PATCH 050/219] update copyright header for draw flush stuff --- src/r_draw_flush.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/r_draw_flush.cpp b/src/r_draw_flush.cpp index f0fa37f14..1baf98f31 100644 --- a/src/r_draw_flush.cpp +++ b/src/r_draw_flush.cpp @@ -4,13 +4,17 @@ // Copyright (C) 2020 by Sonic Team Junior. // Copyright (C) 2000 by DooM Legacy Team. // Copyright (C) 1996 by id Software, Inc. +// Copyright (C) 1999 by Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman +// Copyright (C) 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze +// Copyright (C) Copyright 2005, 2006 by Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko +// Copyright (C) 2013 by James Haley, Stephen McGranahan, et al. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- /// \file r_draw_flush.cpp -/// \brief column flush functions +/// \brief Optimized quad column buffer code. By SoM. /// \note no includes because this is included as part of r_draw.cpp template @@ -22,6 +26,7 @@ FUNCINLINE static ATTRINLINE UINT8 R_DrawFlushColumnPixel(UINT8 restrict dest, U } else if constexpr (Type & ColumnFlushType::FLUSH_TRANS) { + // haleyjd 09/11/04: use temptranmap here return temp_dc.transmap[(source << 8) + dest]; } else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP) @@ -30,6 +35,7 @@ FUNCINLINE static ATTRINLINE UINT8 R_DrawFlushColumnPixel(UINT8 restrict dest, U } else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP_TRANS) { + // haleyjd 09/11/04: use temptranmap here return temp_dc.transmap[(temp_dc.translation[source] << 8) + dest]; } } @@ -142,6 +148,7 @@ DEFINE_GETFLUSHHT_FUNC(R_FlushHTTrans, FLUSH_TRANS) DEFINE_GETFLUSHHT_FUNC(R_FlushHTColormap, FLUSH_COLORMAP) DEFINE_GETFLUSHHT_FUNC(R_FlushHTColormapTrans, FLUSH_COLORMAP_TRANS) +// Begin: Quad column flushing functions. template static void R_FlushQuad(void) { @@ -168,6 +175,7 @@ static void R_FlushQuad(void) while (--count >= 0) { + // haleyjd 09/11/04: use temptranmap here dest[0] = transmap[(source[0] << 8) + dest[0]]; dest[1] = transmap[(source[1] << 8) + dest[1]]; dest[2] = transmap[(source[2] << 8) + dest[2]]; @@ -201,6 +209,7 @@ static void R_FlushQuad(void) while (--count >= 0) { + // haleyjd 09/11/04: use temptranmap here dest[0] = transmap[(translation[source[0]] << 8) + dest[0]]; dest[1] = transmap[(translation[source[1]] << 8) + dest[1]]; dest[2] = transmap[(translation[source[2]] << 8) + dest[2]]; @@ -223,6 +232,9 @@ DEFINE_GETFLUSHQUAD_FUNC(R_FlushQuadTrans, FLUSH_TRANS) DEFINE_GETFLUSHQUAD_FUNC(R_FlushQuadColormap, FLUSH_COLORMAP) DEFINE_GETFLUSHQUAD_FUNC(R_FlushQuadColormapTrans, FLUSH_COLORMAP_TRANS) +// haleyjd 09/12/04: split up R_GetBuffer into various different +// functions to minimize the number of branches and take advantage +// of as much precalculated information as possible. template static UINT8 *R_GetBuffer(drawcolumndata_t *dc) { -- 2.54.0 From 8c8f96cf49758cf254d48796bd8ca1931e7d28d6 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 7 Oct 2025 21:53:01 +0200 Subject: [PATCH 051/219] force flush our column buffer directly after bsp traversal (again) TODO: actually check what portals do --- src/r_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_main.cpp b/src/r_main.cpp index 79e49438f..6dd5a8563 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1453,6 +1453,7 @@ void R_RenderPlayerView(player_t *player) PS_START_TIMING(ps_sw_spritecliptime); R_ClipSprites(drawsegs, NULL); PS_STOP_TIMING(ps_sw_spritecliptime); + R_ResetColumnBuffer(); ps_numsprites.value.i = numvisiblesprites; @@ -1507,7 +1508,6 @@ void R_RenderPlayerView(player_t *player) R_DrawMasked(masks, nummasks); PS_STOP_TIMING(ps_sw_maskedtime); free(masks); - R_ResetColumnBuffer(); // Check for new console commands. NetUpdate(); -- 2.54.0 From 0843a586f854b9fb99698c72b3b771e8c3a260e1 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 7 Oct 2025 22:45:25 +0200 Subject: [PATCH 052/219] fuckit, lets buffer 8 columns instead of 4 improves performance across the board on my ryzen 5600 cpu between 10 -15fps + in best case and around 5fps+ in worst case will need to check how this affects older cpus and 32bit builds since we do 64bit copies now (if needed can always add 32bit specific code) effectively, we also reduce the amount of flushing needed in many cases, writing more things at once during flushes --- src/r_draw.cpp | 6 ++--- src/r_draw_column.cpp | 2 +- src/r_draw_flush.cpp | 52 ++++++++++++++++++++++++++----------------- src/r_main.cpp | 2 +- 4 files changed, 37 insertions(+), 25 deletions(-) diff --git a/src/r_draw.cpp b/src/r_draw.cpp index 93638708b..288cf462d 100644 --- a/src/r_draw.cpp +++ b/src/r_draw.cpp @@ -503,7 +503,7 @@ enum ColumnFlushType typedef struct drawcolumndata_temp_s { INT32 x; - INT32 yl[4], yh[4]; + INT32 yl[8], yh[8]; // e6y: resolution limitation is removed UINT8 *buf; @@ -543,7 +543,7 @@ static void (*R_FlushQuadColumn)(void) = R_QuadFlushError; static void R_FlushColumns(void) { - if (temp_dc.x != 4 || temp_dc.commontop >= temp_dc.commonbot) + if (temp_dc.x != 8 || temp_dc.commontop >= temp_dc.commonbot) R_FlushWholeColumns(); else { @@ -623,7 +623,7 @@ void R_InitViewBuffer(INT32 width, INT32 height) linesize = vid.width; // killough 11/98 renderscreen = vid.screens[0]; // haleyjd 07/02/14 - INT32 bufsize = (linesize * 4) * sizeof(*temp_dc.buf); + INT32 bufsize = (linesize * 8) * sizeof(*temp_dc.buf); if (temp_dc.buf) { diff --git a/src/r_draw_column.cpp b/src/r_draw_column.cpp index 27b570b0b..58de4eebd 100644 --- a/src/r_draw_column.cpp +++ b/src/r_draw_column.cpp @@ -230,7 +230,7 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) else dest = R_GetBufferOpaque(dc); - restrict INT32 stride = 4; //SoM: Oh, Oh it's MAGIC! You know... + restrict INT32 stride = 8; //SoM: Oh, Oh it's MAGIC! You know... if constexpr (Type & DrawColumnType::DC_DIRECT) stride = vid.width; diff --git a/src/r_draw_flush.cpp b/src/r_draw_flush.cpp index 1baf98f31..3ef763a4e 100644 --- a/src/r_draw_flush.cpp +++ b/src/r_draw_flush.cpp @@ -57,14 +57,14 @@ static void R_FlushWhole(void) while (--temp_dc.x >= 0) { yl = temp_dc.yl[temp_dc.x]; - source = &temp_dc.buf[temp_dc.x + (yl << 2)]; + source = &temp_dc.buf[temp_dc.x + (yl << 3)]; dest = R_Address(temp_dc.startx + temp_dc.x, yl); count = temp_dc.yh[temp_dc.x] - yl + 1; while (--count >= 0) { *dest = R_DrawFlushColumnPixel(*dest, *source); - source += 4; + source += 8; dest += stride; } } @@ -97,7 +97,7 @@ static void R_FlushHT(void) INT32 yl, yh; const INT32 stride = vid.width; - while (colnum < 4) + while (colnum < 8) { yl = temp_dc.yl[colnum]; yh = temp_dc.yh[colnum]; @@ -105,14 +105,14 @@ static void R_FlushHT(void) // flush column head if (yl < temp_dc.commontop) { - source = &temp_dc.buf[colnum + (yl << 2)]; + source = &temp_dc.buf[colnum + (yl << 3)]; dest = R_Address(temp_dc.startx + colnum, yl); count = temp_dc.commontop - yl; while (--count >= 0) { *dest = R_DrawFlushColumnPixel(*dest, *source); - source += 4; + source += 8; dest += stride; } } @@ -120,14 +120,14 @@ static void R_FlushHT(void) // flush column tail if (yh > temp_dc.commonbot) { - source = &temp_dc.buf[colnum + ((temp_dc.commonbot + 1) << 2)]; + source = &temp_dc.buf[colnum + ((temp_dc.commonbot + 1) << 3)]; dest = R_Address(temp_dc.startx + colnum, temp_dc.commonbot + 1); count = yh - temp_dc.commonbot; while (--count >= 0) { *dest = R_DrawFlushColumnPixel(*dest, *source); - source += 4; + source += 8; dest += stride; } } @@ -157,11 +157,11 @@ static void R_FlushQuad(void) if constexpr (Type & ColumnFlushType::FLUSH_OPAQUE) { - const INT32 *source = reinterpret_cast(temp_dc.buf + (temp_dc.commontop << 2)); - INT32 *dest = reinterpret_cast(R_Address(temp_dc.startx, temp_dc.commontop)); - INT32 deststep = stride / 4; + const INT64 *source = reinterpret_cast(temp_dc.buf + (temp_dc.commontop << 3)); + INT64 *dest = reinterpret_cast(R_Address(temp_dc.startx, temp_dc.commontop)); + INT32 deststep = stride / 8; - while(--count >= 0) + while (--count >= 0) { *dest = *source++; dest += deststep; @@ -169,7 +169,7 @@ static void R_FlushQuad(void) } else if constexpr (Type & ColumnFlushType::FLUSH_TRANS) { - const UINT8 * restrict source = temp_dc.buf + (temp_dc.commontop << 2); + const UINT8 * restrict source = temp_dc.buf + (temp_dc.commontop << 3); UINT8 * restrict dest = R_Address(temp_dc.startx, temp_dc.commontop); const UINT8 * restrict transmap = temp_dc.transmap; @@ -180,13 +180,17 @@ static void R_FlushQuad(void) dest[1] = transmap[(source[1] << 8) + dest[1]]; dest[2] = transmap[(source[2] << 8) + dest[2]]; dest[3] = transmap[(source[3] << 8) + dest[3]]; - source += 4; + dest[4] = transmap[(source[4] << 8) + dest[4]]; + dest[5] = transmap[(source[5] << 8) + dest[5]]; + dest[6] = transmap[(source[6] << 8) + dest[6]]; + dest[7] = transmap[(source[7] << 8) + dest[7]]; + source += 8; dest += stride; } } else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP) { - const UINT8 * restrict source = temp_dc.buf + (temp_dc.commontop << 2); + const UINT8 * restrict source = temp_dc.buf + (temp_dc.commontop << 3); UINT8 * restrict dest = R_Address(temp_dc.startx, temp_dc.commontop); const UINT8 * restrict translation = temp_dc.translation; @@ -196,13 +200,17 @@ static void R_FlushQuad(void) dest[1] = translation[source[1]]; dest[2] = translation[source[2]]; dest[3] = translation[source[3]]; - source += 4; + dest[4] = translation[source[4]]; + dest[5] = translation[source[5]]; + dest[6] = translation[source[6]]; + dest[7] = translation[source[7]]; + source += 8; dest += stride; } } else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP_TRANS) { - const UINT8 * restrict source = temp_dc.buf + (temp_dc.commontop << 2); + const UINT8 * restrict source = temp_dc.buf + (temp_dc.commontop << 3); UINT8 * restrict dest = R_Address(temp_dc.startx, temp_dc.commontop); const UINT8 * restrict transmap = temp_dc.transmap; const UINT8 * restrict translation = temp_dc.translation; @@ -214,7 +222,11 @@ static void R_FlushQuad(void) dest[1] = transmap[(translation[source[1]] << 8) + dest[1]]; dest[2] = transmap[(translation[source[2]] << 8) + dest[2]]; dest[3] = transmap[(translation[source[3]] << 8) + dest[3]]; - source += 4; + dest[4] = transmap[(translation[source[4]] << 8) + dest[4]]; + dest[5] = transmap[(translation[source[5]] << 8) + dest[5]]; + dest[6] = transmap[(translation[source[6]] << 8) + dest[6]]; + dest[7] = transmap[(translation[source[7]] << 8) + dest[7]]; + source += 8; dest += stride; } } @@ -239,7 +251,7 @@ template static UINT8 *R_GetBuffer(drawcolumndata_t *dc) { // haleyjd: reordered predicates - if (temp_dc.x == 4 || + if (temp_dc.x == 8 || (temp_dc.x && (temp_dc.type != Type || temp_dc.x + temp_dc.startx != dc->x))) R_FlushColumns(); @@ -280,7 +292,7 @@ static UINT8 *R_GetBuffer(drawcolumndata_t *dc) R_FlushQuadColumn = R_FlushQuadColormapTrans; } - return &temp_dc.buf[dc->yl << 2]; + return &temp_dc.buf[dc->yl << 3]; } temp_dc.yl[temp_dc.x] = dc->yl; @@ -291,7 +303,7 @@ static UINT8 *R_GetBuffer(drawcolumndata_t *dc) if (dc->yh < temp_dc.commonbot) temp_dc.commonbot = dc->yh; - return &temp_dc.buf[(dc->yl << 2) + temp_dc.x++]; + return &temp_dc.buf[(dc->yl << 3) + temp_dc.x++]; } #define DEFINE_GETBUF_FUNC(name, flags) \ diff --git a/src/r_main.cpp b/src/r_main.cpp index 6dd5a8563..2a04c6600 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1409,11 +1409,11 @@ void R_RenderPlayerView(player_t *player) R_RenderViewpoint(&masks[nummasks - 1], false); R_ClipSprites(drawsegs, NULL); + R_ResetColumnBuffer(); R_SetColumnContext(COLUMNCONTEXT_DIRECT); R_DrawSkyPlanes(); // draw the fucker again to prevent some artifacts R_DrawPlanes(); R_DrawMasked(masks, nummasks); - R_ResetColumnBuffer(); } PS_STOP_TIMING(ps_skyboxtime); -- 2.54.0 From 48dc5461cdc9049e671ceb5dd99937f318bdfcb9 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 8 Oct 2025 16:47:01 +0200 Subject: [PATCH 053/219] cleanup column flusher stuff - properly make use of templates!, reduce code dupe - inline the "DrawPixel" stuff - use local "const" pointers everywhere --- src/r_draw_column.cpp | 11 +- src/r_draw_flush.cpp | 269 +++++++++++++++--------------------------- src/r_draw_span.cpp | 9 +- src/screen.c | 2 +- 4 files changed, 112 insertions(+), 179 deletions(-) diff --git a/src/r_draw_column.cpp b/src/r_draw_column.cpp index 58de4eebd..08cfa00a1 100644 --- a/src/r_draw_column.cpp +++ b/src/r_draw_column.cpp @@ -34,7 +34,8 @@ enum DrawColumnType }; template -static constexpr UINT8 R_GetColumnTranslated(drawcolumndata_t* dc, UINT8 col, const UINT8 * restrict colormap) +FUNCINLINE static ATTRINLINE constexpr UINT8 +R_GetColumnTranslated(const drawcolumndata_t* dc, UINT8 col, const UINT8 * restrict colormap) { if constexpr (Type & DrawColumnType::DC_COLORMAP) { @@ -46,7 +47,8 @@ static constexpr UINT8 R_GetColumnTranslated(drawcolumndata_t* dc, UINT8 col, co // translucency is handled on flush side now! template -static constexpr UINT8 R_GetColumnTranslucent(drawcolumndata_t* dc, UINT8 * restrict dest, UINT8 col, const UINT8 * restrict colormap) +FUNCINLINE static ATTRINLINE constexpr UINT8 +R_GetColumnTranslucent(const drawcolumndata_t* dc, UINT8 * restrict dest, UINT8 col, const UINT8 * restrict colormap) { col = R_GetColumnTranslated(dc, col, colormap); @@ -61,7 +63,8 @@ static constexpr UINT8 R_GetColumnTranslucent(drawcolumndata_t* dc, UINT8 * rest } template -static constexpr UINT8 R_DrawColumnPixel(drawcolumndata_t* dc, UINT8 * restrict dest, UINT32 bit, const UINT8 * restrict source, const UINT8 * restrict colormap) +FUNCINLINE static ATTRINLINE constexpr UINT8 +R_DrawColumnPixel(const drawcolumndata_t* dc, UINT8 * restrict dest, UINT32 bit, const UINT8 * restrict source, const UINT8 * restrict colormap) { UINT8 col = source[bit]; @@ -74,7 +77,7 @@ static constexpr UINT8 R_DrawColumnPixel(drawcolumndata_t* dc, UINT8 * restrict } if constexpr (Type & DrawColumnType::DC_DIRECT) - { // if we dont flush our columns, we need to handle translucency again + { // if we dont buffer our columns, we need to handle translucency again return R_GetColumnTranslucent(dc, dest, col, colormap); } else diff --git a/src/r_draw_flush.cpp b/src/r_draw_flush.cpp index 3ef763a4e..80da61705 100644 --- a/src/r_draw_flush.cpp +++ b/src/r_draw_flush.cpp @@ -18,28 +18,42 @@ /// \note no includes because this is included as part of r_draw.cpp template -FUNCINLINE static ATTRINLINE UINT8 R_DrawFlushColumnPixel(UINT8 restrict dest, UINT8 restrict source) +FUNCINLINE static ATTRINLINE constexpr UINT8 +R_GetFlushPixelTranslated(const drawcolumndata_temp_t *t_dc, UINT8 col) { - if constexpr (Type & ColumnFlushType::FLUSH_OPAQUE) + if constexpr (Type & (ColumnFlushType::FLUSH_COLORMAP | ColumnFlushType::FLUSH_COLORMAP_TRANS)) { - return source; + col = t_dc->translation[col]; } - else if constexpr (Type & ColumnFlushType::FLUSH_TRANS) + + return col; +} + +template +FUNCINLINE static ATTRINLINE constexpr UINT8 +R_GetFlushPixelTranslucent(const drawcolumndata_temp_t *t_dc, UINT8 * restrict dest, UINT8 col) +{ + col = R_GetFlushPixelTranslated(t_dc, col); + + if constexpr (Type & (ColumnFlushType::FLUSH_TRANS | ColumnFlushType::FLUSH_COLORMAP_TRANS)) { // haleyjd 09/11/04: use temptranmap here - return temp_dc.transmap[(source << 8) + dest]; + return *(t_dc->transmap + (col << 8) + (*dest)); } - else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP) + else { - return temp_dc.translation[source]; - } - else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP_TRANS) - { - // haleyjd 09/11/04: use temptranmap here - return temp_dc.transmap[(temp_dc.translation[source] << 8) + dest]; + return col; } } +template +FUNCINLINE static ATTRINLINE constexpr UINT8 +R_DrawFlushPixel(const drawcolumndata_temp_t *t_dc, UINT8 * restrict dest, const UINT8 * restrict source) +{ + UINT8 col = *source; + return R_GetFlushPixelTranslucent(t_dc, dest, col); +} + // // R_FlushWhole // @@ -53,35 +67,25 @@ static void R_FlushWhole(void) UINT8 * restrict dest; INT32 count, yl; const INT32 stride = vid.width; + drawcolumndata_temp_t *t_dc = &temp_dc; + UINT8 *restrict buf = t_dc->buf; - while (--temp_dc.x >= 0) + while (--t_dc->x >= 0) { - yl = temp_dc.yl[temp_dc.x]; - source = &temp_dc.buf[temp_dc.x + (yl << 3)]; - dest = R_Address(temp_dc.startx + temp_dc.x, yl); - count = temp_dc.yh[temp_dc.x] - yl + 1; + yl = t_dc->yl[t_dc->x]; + source = &buf[t_dc->x + (yl << 3)]; + dest = R_Address(t_dc->startx + t_dc->x, yl); + count = t_dc->yh[t_dc->x] - yl + 1; while (--count >= 0) { - *dest = R_DrawFlushColumnPixel(*dest, *source); + *dest = R_DrawFlushPixel(t_dc, dest, source); source += 8; - dest += stride; + dest += stride; } } } -#define DEFINE_GETFLUSHWHOLE_FUNC(name, flags) \ - FUNCINLINE static ATTRINLINE void name(void) \ - { \ - constexpr ColumnFlushType opt = static_cast(flags); \ - R_FlushWhole(); \ - } - -DEFINE_GETFLUSHWHOLE_FUNC(R_FlushWholeOpague, FLUSH_OPAQUE) -DEFINE_GETFLUSHWHOLE_FUNC(R_FlushWholeTrans, FLUSH_TRANS) -DEFINE_GETFLUSHWHOLE_FUNC(R_FlushWholeColormap, FLUSH_COLORMAP) -DEFINE_GETFLUSHWHOLE_FUNC(R_FlushWholeColormapTrans, FLUSH_COLORMAP_TRANS) - // // R_FlushHT // @@ -96,39 +100,41 @@ static void R_FlushHT(void) INT32 count, colnum = 0; INT32 yl, yh; const INT32 stride = vid.width; + const drawcolumndata_temp_t *t_dc = &temp_dc; + UINT8 *restrict buf = t_dc->buf; while (colnum < 8) { - yl = temp_dc.yl[colnum]; - yh = temp_dc.yh[colnum]; + yl = t_dc->yl[colnum]; + yh = t_dc->yh[colnum]; // flush column head - if (yl < temp_dc.commontop) + if (yl < t_dc->commontop) { - source = &temp_dc.buf[colnum + (yl << 3)]; - dest = R_Address(temp_dc.startx + colnum, yl); - count = temp_dc.commontop - yl; + source = &buf[colnum + (yl << 3)]; + dest = R_Address(t_dc->startx + colnum, yl); + count = t_dc->commontop - yl; while (--count >= 0) { - *dest = R_DrawFlushColumnPixel(*dest, *source); + *dest = R_DrawFlushPixel(t_dc, dest, source); source += 8; - dest += stride; + dest += stride; } } // flush column tail - if (yh > temp_dc.commonbot) + if (yh > t_dc->commonbot) { - source = &temp_dc.buf[colnum + ((temp_dc.commonbot + 1) << 3)]; - dest = R_Address(temp_dc.startx + colnum, temp_dc.commonbot + 1); - count = yh - temp_dc.commonbot; + source = &buf[colnum + ((t_dc->commonbot + 1) << 3)]; + dest = R_Address(t_dc->startx + colnum, t_dc->commonbot + 1); + count = yh - t_dc->commonbot; while (--count >= 0) { - *dest = R_DrawFlushColumnPixel(*dest, *source); + *dest = R_DrawFlushPixel(t_dc, dest, source); source += 8; - dest += stride; + dest += stride; } } @@ -136,30 +142,20 @@ static void R_FlushHT(void) } } -#define DEFINE_GETFLUSHHT_FUNC(name, flags) \ - FUNCINLINE static ATTRINLINE void name(void) \ - { \ - constexpr ColumnFlushType opt = static_cast(flags); \ - R_FlushHT(); \ - } - -DEFINE_GETFLUSHHT_FUNC(R_FlushHTOpague, FLUSH_OPAQUE) -DEFINE_GETFLUSHHT_FUNC(R_FlushHTTrans, FLUSH_TRANS) -DEFINE_GETFLUSHHT_FUNC(R_FlushHTColormap, FLUSH_COLORMAP) -DEFINE_GETFLUSHHT_FUNC(R_FlushHTColormapTrans, FLUSH_COLORMAP_TRANS) - // Begin: Quad column flushing functions. template static void R_FlushQuad(void) { const INT32 stride = vid.width; - INT32 count = temp_dc.commonbot - temp_dc.commontop + 1; + const drawcolumndata_temp_t *t_dc = &temp_dc; + INT32 count = t_dc->commonbot - t_dc->commontop + 1; + const UINT8 *restrict buf = t_dc->buf; if constexpr (Type & ColumnFlushType::FLUSH_OPAQUE) { - const INT64 *source = reinterpret_cast(temp_dc.buf + (temp_dc.commontop << 3)); - INT64 *dest = reinterpret_cast(R_Address(temp_dc.startx, temp_dc.commontop)); - INT32 deststep = stride / 8; + const INT64 *source = reinterpret_cast(buf + (t_dc->commontop << 3)); + INT64 *dest = reinterpret_cast(R_Address(t_dc->startx, t_dc->commontop)); + const INT32 deststep = stride / 8; while (--count >= 0) { @@ -167,143 +163,74 @@ static void R_FlushQuad(void) dest += deststep; } } - else if constexpr (Type & ColumnFlushType::FLUSH_TRANS) + else { - const UINT8 * restrict source = temp_dc.buf + (temp_dc.commontop << 3); - UINT8 * restrict dest = R_Address(temp_dc.startx, temp_dc.commontop); - const UINT8 * restrict transmap = temp_dc.transmap; + const UINT8 * restrict source = buf + (t_dc->commontop << 3); + UINT8 * restrict dest = R_Address(t_dc->startx, t_dc->commontop); while (--count >= 0) { - // haleyjd 09/11/04: use temptranmap here - dest[0] = transmap[(source[0] << 8) + dest[0]]; - dest[1] = transmap[(source[1] << 8) + dest[1]]; - dest[2] = transmap[(source[2] << 8) + dest[2]]; - dest[3] = transmap[(source[3] << 8) + dest[3]]; - dest[4] = transmap[(source[4] << 8) + dest[4]]; - dest[5] = transmap[(source[5] << 8) + dest[5]]; - dest[6] = transmap[(source[6] << 8) + dest[6]]; - dest[7] = transmap[(source[7] << 8) + dest[7]]; + dest[0] = R_DrawFlushPixel(t_dc, &dest[0], &source[0]); + dest[1] = R_DrawFlushPixel(t_dc, &dest[1], &source[1]); + dest[2] = R_DrawFlushPixel(t_dc, &dest[2], &source[2]); + dest[3] = R_DrawFlushPixel(t_dc, &dest[3], &source[3]); + dest[4] = R_DrawFlushPixel(t_dc, &dest[4], &source[4]); + dest[5] = R_DrawFlushPixel(t_dc, &dest[5], &source[5]); + dest[6] = R_DrawFlushPixel(t_dc, &dest[6], &source[6]); + dest[7] = R_DrawFlushPixel(t_dc, &dest[7], &source[7]); source += 8; - dest += stride; - } - } - else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP) - { - const UINT8 * restrict source = temp_dc.buf + (temp_dc.commontop << 3); - UINT8 * restrict dest = R_Address(temp_dc.startx, temp_dc.commontop); - const UINT8 * restrict translation = temp_dc.translation; - - while (--count >= 0) - { - dest[0] = translation[source[0]]; - dest[1] = translation[source[1]]; - dest[2] = translation[source[2]]; - dest[3] = translation[source[3]]; - dest[4] = translation[source[4]]; - dest[5] = translation[source[5]]; - dest[6] = translation[source[6]]; - dest[7] = translation[source[7]]; - source += 8; - dest += stride; - } - } - else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP_TRANS) - { - const UINT8 * restrict source = temp_dc.buf + (temp_dc.commontop << 3); - UINT8 * restrict dest = R_Address(temp_dc.startx, temp_dc.commontop); - const UINT8 * restrict transmap = temp_dc.transmap; - const UINT8 * restrict translation = temp_dc.translation; - - while (--count >= 0) - { - // haleyjd 09/11/04: use temptranmap here - dest[0] = transmap[(translation[source[0]] << 8) + dest[0]]; - dest[1] = transmap[(translation[source[1]] << 8) + dest[1]]; - dest[2] = transmap[(translation[source[2]] << 8) + dest[2]]; - dest[3] = transmap[(translation[source[3]] << 8) + dest[3]]; - dest[4] = transmap[(translation[source[4]] << 8) + dest[4]]; - dest[5] = transmap[(translation[source[5]] << 8) + dest[5]]; - dest[6] = transmap[(translation[source[6]] << 8) + dest[6]]; - dest[7] = transmap[(translation[source[7]] << 8) + dest[7]]; - source += 8; - dest += stride; + dest += stride; } } } -#define DEFINE_GETFLUSHQUAD_FUNC(name, flags) \ - FUNCINLINE static ATTRINLINE void name(void) \ - { \ - constexpr ColumnFlushType opt = static_cast(flags); \ - R_FlushQuad(); \ - } - -DEFINE_GETFLUSHQUAD_FUNC(R_FlushQuadOpague, FLUSH_OPAQUE) -DEFINE_GETFLUSHQUAD_FUNC(R_FlushQuadTrans, FLUSH_TRANS) -DEFINE_GETFLUSHQUAD_FUNC(R_FlushQuadColormap, FLUSH_COLORMAP) -DEFINE_GETFLUSHQUAD_FUNC(R_FlushQuadColormapTrans, FLUSH_COLORMAP_TRANS) - // haleyjd 09/12/04: split up R_GetBuffer into various different // functions to minimize the number of branches and take advantage // of as much precalculated information as possible. template static UINT8 *R_GetBuffer(drawcolumndata_t *dc) { + drawcolumndata_temp_t *t_dc = &temp_dc; + // haleyjd: reordered predicates - if (temp_dc.x == 8 || - (temp_dc.x && (temp_dc.type != Type || temp_dc.x + temp_dc.startx != dc->x))) + if (t_dc->x == 8 || + (t_dc->x && (t_dc->type != Type || t_dc->x + t_dc->startx != dc->x))) R_FlushColumns(); - if (!temp_dc.x) + if (!t_dc->x) { - ++temp_dc.x; - temp_dc.startx = dc->x; - temp_dc.yl[0] = temp_dc.commontop = dc->yl; - temp_dc.yh[0] = temp_dc.commonbot = dc->yh; - temp_dc.type = Type; + ++t_dc->x; + t_dc->startx = dc->x; + t_dc->yl[0] = t_dc->commontop = dc->yl; + t_dc->yh[0] = t_dc->commonbot = dc->yh; + t_dc->type = Type; - if constexpr (Type & ColumnFlushType::FLUSH_OPAQUE) + if constexpr (Type & (ColumnFlushType::FLUSH_TRANS | ColumnFlushType::FLUSH_COLORMAP_TRANS)) { - R_FlushWholeColumns = R_FlushWholeOpague; - R_FlushHTColumns = R_FlushHTOpague; - R_FlushQuadColumn = R_FlushQuadOpague; - } - else if constexpr (Type & ColumnFlushType::FLUSH_TRANS) - { - temp_dc.transmap = dc->transmap; - R_FlushWholeColumns = R_FlushWholeTrans; - R_FlushHTColumns = R_FlushHTTrans; - R_FlushQuadColumn = R_FlushQuadTrans; - } - else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP) - { - temp_dc.translation = dc->translation; - R_FlushWholeColumns = R_FlushWholeColormap; - R_FlushHTColumns = R_FlushHTColormap; - R_FlushQuadColumn = R_FlushQuadColormap; - } - else if constexpr (Type & ColumnFlushType::FLUSH_COLORMAP_TRANS) - { - temp_dc.transmap = dc->transmap; - temp_dc.translation = dc->translation; - R_FlushWholeColumns = R_FlushWholeColormapTrans; - R_FlushHTColumns = R_FlushHTColormapTrans; - R_FlushQuadColumn = R_FlushQuadColormapTrans; + t_dc->transmap = dc->transmap; } - return &temp_dc.buf[dc->yl << 3]; + if constexpr (Type & (ColumnFlushType::FLUSH_COLORMAP | ColumnFlushType::FLUSH_COLORMAP_TRANS)) + { + t_dc->translation = dc->translation; + } + + R_FlushWholeColumns = R_FlushWhole; + R_FlushHTColumns = R_FlushHT; + R_FlushQuadColumn = R_FlushQuad; + + return &t_dc->buf[dc->yl << 3]; } - temp_dc.yl[temp_dc.x] = dc->yl; - temp_dc.yh[temp_dc.x] = dc->yh; + t_dc->yl[t_dc->x] = dc->yl; + t_dc->yh[t_dc->x] = dc->yh; - if (dc->yl > temp_dc.commontop) - temp_dc.commontop = dc->yl; - if (dc->yh < temp_dc.commonbot) - temp_dc.commonbot = dc->yh; + if (dc->yl > t_dc->commontop) + t_dc->commontop = dc->yl; + if (dc->yh < t_dc->commonbot) + t_dc->commonbot = dc->yh; - return &temp_dc.buf[(dc->yl << 3) + temp_dc.x++]; + return &t_dc->buf[(dc->yl << 3) + t_dc->x++]; } #define DEFINE_GETBUF_FUNC(name, flags) \ diff --git a/src/r_draw_span.cpp b/src/r_draw_span.cpp index cfa053382..bc18382a2 100644 --- a/src/r_draw_span.cpp +++ b/src/r_draw_span.cpp @@ -50,7 +50,8 @@ enum DrawSpanType }; template -static constexpr UINT8 R_GetSpanTranslated(drawspandata_t* ds, UINT8 col) +FUNCINLINE static ATTRINLINE constexpr UINT8 +R_GetSpanTranslated(const drawspandata_t* ds, UINT8 col) { if constexpr (Type & DrawSpanType::DS_COLORMAP) { @@ -63,7 +64,8 @@ static constexpr UINT8 R_GetSpanTranslated(drawspandata_t* ds, UINT8 col) } template -static constexpr UINT8 R_GetSpanTranslucent(drawspandata_t* ds, UINT8 *dsrc, const UINT8 *colormap, UINT8 col) +FUNCINLINE static ATTRINLINE constexpr UINT8 +R_GetSpanTranslucent(const drawspandata_t* ds, UINT8 *dsrc, const UINT8 *colormap, UINT8 col) { col = colormap[R_GetSpanTranslated(ds, col)]; @@ -78,7 +80,8 @@ static constexpr UINT8 R_GetSpanTranslucent(drawspandata_t* ds, UINT8 *dsrc, con } template -static constexpr UINT8 R_DrawSpanPixel(drawspandata_t* ds, UINT8 *dsrc, const UINT8 *colormap, UINT32 bit, const UINT8 *source) +FUNCINLINE static ATTRINLINE constexpr UINT8 +R_DrawSpanPixel(const drawspandata_t* ds, UINT8 *dsrc, const UINT8 *colormap, UINT32 bit, const UINT8 *source) { UINT8 col = source[bit]; diff --git a/src/screen.c b/src/screen.c index 735bb88c4..d67ac73eb 100644 --- a/src/screen.c +++ b/src/screen.c @@ -155,7 +155,7 @@ void SCR_SetMode(void) // our sky "plane" drawer cannot handle the buffer system due to multithreading // (that would require alot of extra complexity for smth with massive diminishing results) // Our masked drawing step draws things in a very particular order, which results in alot of flushing to screen -// effectively adding massive overhead during buffering, so we draw our masked thing directly to screen instead +// effectively adding massive overhead due to excessive flushing, so we draw our masked thing directly to screen instead void R_SetColumnContext(enum columncontext_e _columncontext) { columncontext = _columncontext; -- 2.54.0 From 90c3d02dbffeac3156b608ca302317b0e46fbc75 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 8 Oct 2025 20:46:27 +0200 Subject: [PATCH 054/219] ensure columnbuffer gets flushed during portal traversal in worst case this does nothing btw --- src/r_main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/r_main.cpp b/src/r_main.cpp index 2a04c6600..1dabe4b21 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1490,6 +1490,7 @@ void R_RenderPlayerView(player_t *player) R_RenderViewpoint(&masks[nummasks - 1], true); R_ClipSprites(ds_p - (masks[nummasks - 1].drawsegs[1] - masks[nummasks - 1].drawsegs[0]), portal); + R_ResetColumnBuffer(); Portal_Remove(portal); } -- 2.54.0 From b3106d55d1c0dfaf1342ab6e97e0d5f379e36295 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 8 Oct 2025 21:36:29 +0200 Subject: [PATCH 055/219] inline R_ThingLightLevel just points to thing->lightlevel field eitherway --- src/r_things.cpp | 7 ------- src/r_things.h | 7 +++++-- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/r_things.cpp b/src/r_things.cpp index 4713bc50e..b41d44db1 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -94,13 +94,6 @@ static drawseg_xrange_item_t *drawsegs_xrange; static size_t drawsegs_xrange_size = 0; static INT32 drawsegs_xrange_count = 0; -INT32 R_ThingLightLevel(mobj_t* thing) -{ - INT32 lightlevel = thing->lightlevel; - - return lightlevel; -} - // // Sprite rotation 0 is facing the viewer, // rotation 1 is one angle turn CLOCKWISE around the axis. diff --git a/src/r_things.h b/src/r_things.h index 9cba7340d..2f9269c68 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -63,7 +63,10 @@ extern fixed_t windowtop; extern fixed_t windowbottom; extern INT32 lengthcol; -INT32 R_ThingLightLevel(mobj_t *thing); +FUNCINLINE static ATTRINLINE INT32 R_ThingLightLevel(mobj_t* thing) +{ + return (INT32)thing->lightlevel; +} fixed_t R_GetSpriteDirectionalLighting(angle_t angle); fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope); @@ -83,7 +86,7 @@ typedef struct { size_t drawsegs[2]; size_t vissprites[2]; - fixed_t viewx, viewy, viewz; /**< View z stored at the time of the BSP traversal for the view/portal. Masked sorting/drawing needs it. */ + fixed_t viewx, viewy, viewz; /**< View z stored at the time of the BSP traversal for the view/portal. Masked sorting/drawing needs it. */ sector_t* viewsector; } maskcount_t; -- 2.54.0 From 2ec467f062d086e3aad93a9cc824bf6d0c6bea0f Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 8 Oct 2025 21:38:06 +0200 Subject: [PATCH 056/219] check with "__SIZEOF_POINTER__" --- src/r_things.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/r_things.h b/src/r_things.h index 2f9269c68..fd03a6611 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -23,10 +23,10 @@ extern "C" { // number of sprite lumps for spritewidth,offset,topoffset lookup tables // Fab: this is a hack : should allocate the lookup tables per sprite -#if defined(__x86_64__) || defined(__amd64__) || defined(__aarch64__) || defined(__arm64__) // only for 64bit (idk how else to proper check lmao) -#define MAXVISSPRITES 4096 -#else +#if __SIZEOF_POINTER__ < 8 #define MAXVISSPRITES 2048 // added 2-2-98 was 128 +#else +#define MAXVISSPRITES 4096 // only for 64bit #endif #define VISSPRITECHUNKBITS 6 // 2^6 = 64 sprites per chunk -- 2.54.0 From ff80a34627d8bd1947e21b11f0107dcd90435cd6 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 9 Oct 2025 18:01:02 +0200 Subject: [PATCH 057/219] unnest fsp counter and ping display stuff --- src/hu_stuff.c | 159 ++++++++++++++++++++++++++----------------------- src/screen.c | 146 ++++++++++++++++++++++++++------------------- 2 files changed, 169 insertions(+), 136 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 0132659e4..6ca275aff 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2540,17 +2540,91 @@ Ping_conversion (UINT32 lag) // HU_drawPing // +static void HU_drawOldPing(INT32 x, INT32 y, UINT32 lag, INT32 flags, boolean gentleman) +{ + const INT32 measureid = cv_pingmeasurement.value ? 1 : 0; + + if (vid.width >= 640) // how sad, we're using a shit resolution. + { + if (measureid == 1) + { + V_DrawRightAlignedSmallString(x+12, y+13, V_ALLOWLOWERCASE|flags, va("%dms", Ping_conversion(lag))); + } + else if (measureid == 0) + { + V_DrawRightAlignedSmallString(x+12, y+13, flags, va("d%d", Ping_conversion(lag))); + } + } + + if (cv_pingicon.value) + { + UINT8 numbars = 0; // how many ping bars do we draw? + UINT8 barcolor = 31; // color we use for the bars (green, yellow, red or black) + SINT8 i = 0; + SINT8 yoffset = 6; + + switch (lag) + { + case 0 ... 1: + numbars = 3; + barcolor = 215; // Blue + break; + case 2 ... 3: + numbars = 3; + barcolor = 184; // Green + break; + case 4 ... 6: + numbars = 2; // Apparently ternaries w/ multiple statements don't look good in C so I decided against it. + barcolor = 103; // Yellow + break; + case 7 ... 9: + numbars = 1; + barcolor = 155; // Red + break; + default: // Brazil + numbars = 0; + barcolor = 31; // black + break; + } + + if (gentleman) + { + barcolor = 194; // make it purplish + // bars get indirectly set earlier + } + + for (i = 0; (i < 3); i++) // Draw the ping bar + { + V_DrawFill(x+2 *(i-1)+7, y+8+yoffset-4, 2, 8-yoffset, 31|flags); + if (i < numbars) + V_DrawFill(x+2 *(i-1)+7, y+8+yoffset-3, 1, 8-yoffset-1, barcolor|flags); + + yoffset -= 2; + } + } +} + +static void HU_drawKartPing(INT32 x, INT32 y, UINT32 lag, INT32 flags, boolean gentleman) +{ + const INT32 measureid = cv_pingmeasurement.value ? 1 : 0; + + if (measureid == 1) + V_DrawScaledPatch(x+11 - pingmeasure[measureid]->width, y+9, flags, pingmeasure[measureid]); + + if (cv_pingicon.value) + { + INT32 gfxnum = Ping_gfx_num(lag); // gfx to draw + V_DrawScaledPatch(x+2, y, flags, pinggfx[gfxnum]); + } + + x = V_DrawPingNum(x + (measureid == 1 ? 11 - pingmeasure[measureid]->width : 10), y+9, flags, Ping_conversion(lag), Ping_gfx_colormap(lag, gentleman)); + + if (measureid == 0) + V_DrawScaledPatch(x+1 - pingmeasure[measureid]->width, y+9, flags, pingmeasure[measureid]); +} + void HU_drawPlayerPing(INT32 x, INT32 y, INT32 pnum, INT32 flags) { - INT32 measureid = cv_pingmeasurement.value ? 1 : 0; - INT32 gfxnum; // gfx to draw - - //SRB2/Kart v1.0 style - UINT8 numbars = 0; // how many ping bars do we draw? - UINT8 barcolor = 31; // color we use for the bars (green, yellow, red or black) - SINT8 i = 0; - SINT8 yoffset = 6; - UINT32 lag = playerpingtable[pnum]; const boolean gentleman = (cv_mindelay.value && (lag < (tic_t)simulated_lag)); @@ -2561,74 +2635,11 @@ void HU_drawPlayerPing(INT32 x, INT32 y, INT32 pnum, INT32 flags) if (cv_pingstyle.value == 0) // kart { - gfxnum = Ping_gfx_num(lag); - - if (measureid == 1) - V_DrawScaledPatch(x+11 - pingmeasure[measureid]->width, y+9, flags, pingmeasure[measureid]); - - if (cv_pingicon.value) - V_DrawScaledPatch(x+2, y, flags, pinggfx[gfxnum]); - - x = V_DrawPingNum(x + (measureid == 1 ? 11 - pingmeasure[measureid]->width : 10), y+9, flags, Ping_conversion(lag), Ping_gfx_colormap(lag, gentleman)); - - if (measureid == 0) - V_DrawScaledPatch(x+1 - pingmeasure[measureid]->width, y+9, flags, pingmeasure[measureid]); + HU_drawKartPing(x, y, lag, flags, gentleman); } else if (cv_pingstyle.value == 1) // old style ping { - if (vid.width >= 640) // how sad, we're using a shit resolution. - { - if (measureid == 1) - { - V_DrawRightAlignedSmallString(x+12, y+13, V_ALLOWLOWERCASE|flags, va("%dms", Ping_conversion(lag))); - } - else if (measureid == 0) - { - V_DrawRightAlignedSmallString(x+12, y+13, flags, va("d%d", Ping_conversion(lag))); - } - } - - if (cv_pingicon.value) - { - switch (lag) - { - case 0 ... 1: - numbars = 3; - barcolor = 215; // Blue - break; - case 2 ... 3: - numbars = 3; - barcolor = 184; // Green - break; - case 4 ... 6: - numbars = 2; // Apparently ternaries w/ multiple statements don't look good in C so I decided against it. - barcolor = 103; // Yellow - break; - case 7 ... 9: - numbars = 1; - barcolor = 155; // Red - break; - default: // Brazil - numbars = 0; - barcolor = 31; // black - break; - } - - if (gentleman) - { - barcolor = 194; // make it purplish - // bars get indirectly set earlier - } - - for (i = 0; (i < 3); i++) // Draw the ping bar - { - V_DrawFill(x+2 *(i-1)+7, y+8+yoffset-4, 2, 8-yoffset, 31|flags); - if (i < numbars) - V_DrawFill(x+2 *(i-1)+7, y+8+yoffset-3, 1, 8-yoffset-1, barcolor|flags); - - yoffset -= 2; - } - } + HU_drawOldPing(x, y, lag, flags, gentleman); } } diff --git a/src/screen.c b/src/screen.c index 21ec0ed52..8d2782ab8 100644 --- a/src/screen.c +++ b/src/screen.c @@ -400,74 +400,97 @@ void SCR_CalculateFPS(void) #endif } +static void SCR_DrawOldTicRate(UINT32 cap, UINT32 benchmark, double fps, INT32 fpsflags) +{ + const char *fps_string; + INT32 ticcntcolor = 0; + + if (fps > (benchmark - 5)) + ticcntcolor = V_GREENMAP; + else if (fps < 20) + ticcntcolor = V_REDMAP; + + if (cap != 0) + fps_string = va("%d/%d\x82", (INT32)fps, cap); + else + fps_string = va("%d\x82", (INT32)fps); + + // draw "FPS" + if (cv_ticrate.value == 3) + V_DrawRightAlignedString(319, 181, V_YELLOWMAP|fpsflags, "FPS"); + + V_DrawRightAlignedString(319, 190, ticcntcolor|fpsflags, fps_string); +} + +static void SCR_DrawKartTicRate(UINT32 cap, UINT32 benchmark, double fps, INT32 fpsflags) +{ + UINT8 *ticcntcolor = NULL; + INT32 x = 318; + + // draw "FPS" + if (cv_ticrate.value == 1) + { + ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_YELLOW, GTC_CACHE); + V_DrawFixedPatch(306< (benchmark - 5)) + ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_MINT, GTC_CACHE); + else if (fps < 20) + ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_RASPBERRY, GTC_CACHE); + else + ticcntcolor = NULL; + + if (cap != 0) + { + UINT32 digits = 1; + UINT32 c2 = cap; + + while (c2 > 0) + { + c2 = c2 / 10; + digits++; + } + + // draw total frame: + V_DrawPingNum(x, 190, fpsflags, cap, ticcntcolor); + + x -= digits * 4; + + // draw "/" + V_DrawFixedPatch(x< (benchmark - 5)) - ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_MINT, GTC_CACHE); - else if (fps < 20) - ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_RASPBERRY, GTC_CACHE); - - if (cap != 0) - { - UINT32 digits = 1; - UINT32 c2 = cap; - - while (c2 > 0) - { - c2 = c2 / 10; - digits++; - } - - // draw total frame: - V_DrawPingNum(x, 190, fpsflags, cap, ticcntcolor); - - x -= digits * 4; - - // draw "/" - V_DrawFixedPatch(x< (benchmark - 5)) - ticcntcolor2 = V_GREENMAP; - else if (fps < 20) - ticcntcolor2 = V_REDMAP; - - if (cap != 0) - fps_string = va("%d/%d\x82", (INT32)fps, cap); - else - fps_string = va("%d\x82", (INT32)fps); - - // draw "FPS" - if (cv_ticrate.value == 3) - V_DrawRightAlignedString(319, 181, V_YELLOWMAP|fpsflags, "FPS"); - - V_DrawRightAlignedString(319, 190, ticcntcolor2|fpsflags, fps_string); + case 1: // new kart counter + case 2: + SCR_DrawKartTicRate(cap, benchmark, fps, fpsflags); + break; + case 3: // kart v1.0/srb2 counter + case 4: + SCR_DrawOldTicRate(cap, benchmark, fps, fpsflags); + break; + default: + break; } } @@ -482,7 +505,6 @@ void SCR_DisplayLocalPing(void) if (cv_showping.value == 1 || (cv_showping.value == 2 && ping > servermaxping)) // only show 2 (warning) if our ping is at a bad level { INT32 dispy = (cv_ticrate.value == 1) ? 165 : ((cv_ticrate.value == 2 || cv_ticrate.value == 4) ? 172 : ((cv_ticrate.value == 3) ? 163 : 181)); // absolute buttpain - HU_drawPlayerPing(308, dispy, consoleplayer, pingflags); // consoleplayer's ping is everyone's ping in a splitnetgame :P } } -- 2.54.0 From 3783e30a8ae54c394d385fb3ab60e258e5809939 Mon Sep 17 00:00:00 2001 From: K J Date: Wed, 13 Aug 2025 14:11:13 -0400 Subject: [PATCH 058/219] fix: multiple additional buffer overruns found by Zwip-Zwap_Zapony --- src/android/i_system.c | 4 ++-- src/console.c | 4 ++-- src/sdl/i_system.cpp | 4 ++-- src/win32/win_dbg.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/android/i_system.c b/src/android/i_system.c index b20625587..102bff461 100644 --- a/src/android/i_system.c +++ b/src/android/i_system.c @@ -110,7 +110,7 @@ void I_Error(const char *error, ...) char logbuf[8192]; va_start(argptr, error); - vsprintf(logbuf, error, argptr); + vsnprintf(logbuf, 8192, error, argptr); va_end(argptr); LOGE(logbuf); @@ -166,7 +166,7 @@ void I_OutputMsg(const char *fmt, ...) char logbuf[8192]; va_start(argptr, fmt); - vsprintf(logbuf, fmt, argptr); + vsnprintf(logbuf, 8192, fmt, argptr); va_end(argptr); LOGD(logbuf); diff --git a/src/console.c b/src/console.c index a01c72062..fe91df0f3 100644 --- a/src/console.c +++ b/src/console.c @@ -1282,7 +1282,7 @@ void CONS_Alert(alerttype_t level, const char *fmt, ...) txt = malloc(8192); va_start(argptr, fmt); - vsprintf(txt, fmt, argptr); + vsnprintf(txt, 8192, fmt, argptr); va_end(argptr); switch (level) @@ -1318,7 +1318,7 @@ void CONS_Debug(INT32 debugflags, const char *fmt, ...) txt = malloc(8192); va_start(argptr, fmt); - vsprintf(txt, fmt, argptr); + vsnprintf(txt, 8192, fmt, argptr); va_end(argptr); // Again I am lazy, oh well diff --git a/src/sdl/i_system.cpp b/src/sdl/i_system.cpp index 7314995e8..2663887d6 100644 --- a/src/sdl/i_system.cpp +++ b/src/sdl/i_system.cpp @@ -2021,7 +2021,7 @@ FUNCIERROR void ATTRNORETURN I_Error(const char *error, ...) if (errorcount > 20) { va_start(argptr, error); - vsprintf(buffer, error, argptr); + vsnprintf(buffer, 8192, error, argptr); va_end(argptr); // Implement message box with SDL_ShowSimpleMessageBox, // which should fail gracefully if it can't put a message box up @@ -2039,7 +2039,7 @@ FUNCIERROR void ATTRNORETURN I_Error(const char *error, ...) // Display error message in the console before we start shutting it down va_start(argptr, error); - vsprintf(buffer, error, argptr); + vsnprintf(buffer, 8192, error, argptr); va_end(argptr); I_OutputMsg("\nI_Error(): %s\n", buffer); diff --git a/src/win32/win_dbg.c b/src/win32/win_dbg.c index 290227b09..a5d1adc3f 100644 --- a/src/win32/win_dbg.c +++ b/src/win32/win_dbg.c @@ -118,7 +118,7 @@ static VOID FPrintf(HANDLE fileHandle, LPCSTR lpFmt, ...) DWORD bytesWritten; va_start(arglist, lpFmt); - vsprintf(str, lpFmt, arglist); + vsnprintf(str, 1999, lpFmt, arglist); va_end(arglist); WriteFile(fileHandle, str, (DWORD)strlen(str), &bytesWritten, NULL); -- 2.54.0 From f2afc5135c340b69d2c3de64d9423d03d0df07fa Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 9 Oct 2025 18:16:57 +0200 Subject: [PATCH 059/219] fix buffer overflows in dedi build too --- src/dedicated/i_system.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dedicated/i_system.c b/src/dedicated/i_system.c index d0914be56..865ae4584 100644 --- a/src/dedicated/i_system.c +++ b/src/dedicated/i_system.c @@ -1468,7 +1468,7 @@ void I_Error(const char *error, ...) if (errorcount > 20) { va_start(argptr, error); - vsprintf(buffer, error, argptr); + vsnprintf(buffer, 8192, error, argptr); va_end(argptr); I_OutputMsg("SRB2Kart %s Recursive Error", buffer); @@ -1482,7 +1482,7 @@ void I_Error(const char *error, ...) // Display error message in the console before we start shutting it down va_start(argptr, error); - vsprintf(buffer, error, argptr); + vsnprintf(buffer, 8192, error, argptr); va_end(argptr); I_OutputMsg("\nI_Error(): %s\n", buffer); -- 2.54.0 From 513613d83b8aaba7d8f56f2582b23d26df076b2b Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 9 Oct 2025 19:13:00 +0200 Subject: [PATCH 060/219] dont update hud during skipped frames this was to fix issues with some lua huds looking really bad during frameskip but this causes issues with the hud flashing during gif recording --- src/d_main.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index fd3e93649..dd13c7b77 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -890,12 +890,6 @@ void D_SRB2Loop(void) // always update console and hud // otherwise it may take minutes to open it CON_Drawer(); - - if (gamestate == GS_LEVEL) - { - ST_Drawer(); - HU_Drawer(); - } } } -- 2.54.0 From b7f1a0b631ff21475d6d8b66b48bba8cb9797ff8 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 7 Oct 2025 17:18:30 +0200 Subject: [PATCH 061/219] speed up masked sprites a bit thx eternity engine! --- src/r_things.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/r_things.cpp b/src/r_things.cpp index b41d44db1..12d02d329 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -2819,6 +2819,7 @@ void R_ClipSprites(drawseg_t* dsstart, portal_t* portal) if (drawsegs_xrange_size < maxdrawsegs) { + // haleyjd: fix reallocation to track 2x size drawsegs_xrange_size = 2 * maxdrawsegs; for (i = 0; i < DS_RANGES_COUNT; i++) @@ -2858,6 +2859,9 @@ void R_ClipSprites(drawseg_t* dsstart, portal_t* portal) } } + // haleyjd: terminate with a nullptr user for faster loop - adds ~3 FPS + drawsegs_xranges[0].items[drawsegs_xranges[0].count].user = nullptr; + for (; clippedvissprites < visspritecount; clippedvissprites++) { vissprite_t *spr = R_GetVisSprite(clippedvissprites); -- 2.54.0 From b0b048c703b9b10d957667d814bd65f1fa401c57 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 10 Oct 2025 23:37:13 +0200 Subject: [PATCH 062/219] move "newview sky" check before skyplane loop saves us some pointless work going through all planes if we dont need to draw the sky --- src/r_plane.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 475e8a44d..de713dc9c 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -749,6 +749,13 @@ void R_DrawSkyPlanes(void) visplane_t *pl; INT32 i; + // If we're not supposed to draw the sky (e.g. for skyboxes), don't do anything! + // This probably utterly ruins sky rendering for FOFs and polyobjects, unfortunately + if (!newview->sky) + { + return; + } + #ifdef HAVE_THREADS srb2::ThreadPool::Sema tp_sema; srb2::g_main_threadpool->begin_sema(); @@ -777,13 +784,6 @@ static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), b if (!(pl->minx <= pl->maxx)) return; - // If we're not supposed to draw the sky (e.g. for skyboxes), don't do anything! - // This probably utterly ruins sky rendering for FOFs and polyobjects, unfortunately - if (!newview->sky) - { - return; - } - drawcolumndata_t dc = {}; const INT32 texture = texturetranslation[skytexture]; -- 2.54.0 From c82495f48b97706014e5d8e7f10228567e0a8ed8 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 12 Oct 2025 22:03:04 +0200 Subject: [PATCH 063/219] tiny optimization span drawers if we dont "ripple" our spans, we dont need to increment an additional pointer for them --- src/r_draw_span.cpp | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/src/r_draw_span.cpp b/src/r_draw_span.cpp index bc18382a2..983a89698 100644 --- a/src/r_draw_span.cpp +++ b/src/r_draw_span.cpp @@ -160,14 +160,18 @@ static void R_DrawSpanTemplate(drawspandata_t* ds) { bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[i] = R_DrawSpanPixel(ds, &dsrc[i], colormap, bit, source); + if constexpr (Type & DS_RIPPLE) + dest[i] = R_DrawSpanPixel(ds, &dsrc[i], colormap, bit, source); + else + dest[i] = R_DrawSpanPixel(ds, &dest[i], colormap, bit, source); xposition += xstep; yposition += ystep; } dest += 8; - dsrc += 8; + if constexpr (Type & DS_RIPPLE) + dsrc += 8; count -= 8; } @@ -176,10 +180,14 @@ static void R_DrawSpanTemplate(drawspandata_t* ds) { bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - *dest = R_DrawSpanPixel(ds, dsrc, colormap, bit, source); + if constexpr (Type & DS_RIPPLE) + *dest = R_DrawSpanPixel(ds, dsrc, colormap, bit, source); + else + *dest = R_DrawSpanPixel(ds, dest, colormap, bit, source); dest++; - dsrc++; + if constexpr (Type & DS_RIPPLE) + dsrc++; xposition += xstep; yposition += ystep; @@ -321,7 +329,8 @@ static void R_DrawTiltedSpanTemplate(drawspandata_t* ds) ds->x1 += SPANSIZE; dest += SPANSIZE; - dsrc += SPANSIZE; + if constexpr (Type & DS_RIPPLE) + dsrc += SPANSIZE; startu = endu; startv = endv; width -= SPANSIZE; @@ -335,7 +344,10 @@ static void R_DrawTiltedSpanTemplate(drawspandata_t* ds) v = (INT64)(startv); bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); colormap = ds->planezlight[tiltlighting[ds->x1]] + (ds->colormap - colormaps); - *dest = R_DrawSpanPixel(ds, dsrc, colormap, bit, source); + if constexpr (Type & DS_RIPPLE) + *dest = R_DrawSpanPixel(ds, dsrc, colormap, bit, source); + else + *dest = R_DrawSpanPixel(ds, dest, colormap, bit, source); ds->x1++; } else @@ -358,10 +370,14 @@ static void R_DrawTiltedSpanTemplate(drawspandata_t* ds) { bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); colormap = ds->planezlight[tiltlighting[ds->x1]] + (ds->colormap - colormaps); - *dest = R_DrawSpanPixel(ds, dsrc, colormap, bit, source); + if constexpr (Type & DS_RIPPLE) + *dest = R_DrawSpanPixel(ds, dsrc, colormap, bit, source); + else + *dest = R_DrawSpanPixel(ds, dest, colormap, bit, source); dest++; + if constexpr (Type & DS_RIPPLE) + dsrc++; ds->x1++; - dsrc++; u += stepu; v += stepv; } @@ -404,7 +420,7 @@ void R_DrawFogSpan(drawspandata_t* ds) dest[2] = colormap[dest[2]]; dest[3] = colormap[dest[3]]; - dest += 4; + dest += 4; count -= 4; } -- 2.54.0 From 8488da4b1ae8ce7eb13243cfbcacd9bb82445580 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 12 Oct 2025 22:03:30 +0200 Subject: [PATCH 064/219] smol style adjustment span stuff --- src/r_draw_span.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/r_draw_span.cpp b/src/r_draw_span.cpp index 983a89698..aa14785a0 100644 --- a/src/r_draw_span.cpp +++ b/src/r_draw_span.cpp @@ -254,15 +254,14 @@ static void R_DrawTiltedSpanTemplate(drawspandata_t* ds) local_for_thread std::vector tiltlighting; iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); + uz = ds->sup.z + ds->sup.y*(centery-ds->y) + ds->sup.x*(ds->x1-centerx); + vz = ds->svp.z + ds->svp.y*(centery-ds->y) + ds->svp.x*(ds->x1-centerx); // Lighting is simple. It's just linear interpolation from start to end R_GetTiltedLighting(tiltlighting, ds, iz, width, stride); - uz = ds->sup.z + ds->sup.y*(centery-ds->y) + ds->sup.x*(ds->x1-centerx); - vz = ds->svp.z + ds->svp.y*(centery-ds->y) + ds->svp.x*(ds->x1-centerx); - - const UINT8 *source = ds->source; - const UINT8 *colormap = ds->colormap; + const UINT8 * restrict source = ds->source; + const UINT8 * restrict colormap = ds->colormap; if constexpr (Type & DS_RIPPLE) { @@ -408,11 +407,11 @@ DEFINE_SPAN_COMBO(R_DrawTranslucentWaterSpan, DS_TRANSMAP|DS_RIPPLE) */ void R_DrawFogSpan(drawspandata_t* ds) { + INT32 count = ds->x2 - ds->x1 + 1; + const UINT8 * restrict colormap = ds->colormap; UINT8 * restrict dest = R_Address(ds->x1, ds->y); - intptr_t count = ds->x2 - ds->x1 + 1; - while (count >= 4) { dest[0] = colormap[dest[0]]; -- 2.54.0 From 5765f3df5a635bef4738a2ee94506eef17161877 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 12 Oct 2025 22:30:16 +0200 Subject: [PATCH 065/219] this does not need marked as restrict --- src/r_draw_column.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_draw_column.cpp b/src/r_draw_column.cpp index 08cfa00a1..3ac814e8d 100644 --- a/src/r_draw_column.cpp +++ b/src/r_draw_column.cpp @@ -233,7 +233,7 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) else dest = R_GetBufferOpaque(dc); - restrict INT32 stride = 8; //SoM: Oh, Oh it's MAGIC! You know... + INT32 stride = 8; //SoM: Oh, Oh it's MAGIC! You know... if constexpr (Type & DrawColumnType::DC_DIRECT) stride = vid.width; -- 2.54.0 From 459b2e62ce642940b7e9a896e989c1a0bee679a3 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 12 Oct 2025 23:12:18 +0200 Subject: [PATCH 066/219] oops missed this case --- src/r_draw_span.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/r_draw_span.cpp b/src/r_draw_span.cpp index aa14785a0..b1870685c 100644 --- a/src/r_draw_span.cpp +++ b/src/r_draw_span.cpp @@ -323,7 +323,10 @@ static void R_DrawTiltedSpanTemplate(drawspandata_t* ds) { bit = (((v + stepv * i) >> nflatyshift) & nflatmask) | ((u + stepu * i) >> nflatxshift); colormap = ds->planezlight[tiltlighting[x1 + i]] + (ds->colormap - colormaps); - dest[i] = R_DrawSpanPixel(ds, &dsrc[i], colormap, bit, source); + if constexpr (Type & DS_RIPPLE) + dest[i] = R_DrawSpanPixel(ds, &dsrc[i], colormap, bit, source); + else + dest[i] = R_DrawSpanPixel(ds, &dest[i], colormap, bit, source); } ds->x1 += SPANSIZE; -- 2.54.0 From 6f4dfb35fabe9ec6596b5e12cfeb3ed9b6410c34 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Sun, 12 Oct 2025 14:28:06 -0500 Subject: [PATCH 067/219] Calculate staging buffer maximum size in Picture_Convert --- src/r_patch.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/r_patch.c b/src/r_patch.c index e774c1c2e..cac31bff0 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -458,17 +458,23 @@ static UINT8 *imgbuf = NULL; void *R_PixelsToPatch(UINT8 *raw, INT16 width, INT16 height, INT16 leftoffset, INT16 topoffset, size_t *destsize) { INT16 x, y; - UINT8 *img; + UINT8 *img, *imgptr; UINT8 *colpointers, *startofspan; size_t size = 0; if (!raw) return NULL; - if (!imgbuf) - imgbuf = Z_Malloc(1<<26, PU_STATIC, NULL); + // Allocate a staging buffer with the maximum size needed for a patch of the same size as the input. - UINT8 *imgptr = imgbuf; + // round up to nearest multiple of 254-pixel posts, plus 1 more 254-pixel post for paranoia reasons + size_t maxcolumnsize = (2 + (height - 1) / 256) * 256; + // the patch header, and width columns of the max column size + size_t maxoutsize = maxcolumnsize * width + (8 + 4 * width); + // so, a 512x512 flat should maximally need 393,760 (384.53 KiB) bytes. + // quite a bit smaller than 64 megabytes, and much less annoying to the windows debug allocator! + imgbuf = Z_Malloc(maxoutsize, PU_STATIC, NULL); + imgptr = imgbuf; // Write image size and offset WRITEINT16(imgptr, width); @@ -582,17 +588,23 @@ void *R_PixelsToPatch(UINT8 *raw, INT16 width, INT16 height, INT16 leftoffset, I void *R_MaskedFlatToPatch(UINT16 *raw, INT16 width, INT16 height, INT16 leftoffset, INT16 topoffset, size_t *destsize) { INT16 x, y; - UINT8 *img; + UINT8 *img, *imgptr; UINT8 *colpointers, *startofspan; size_t size = 0; if (!raw) return NULL; - if (!imgbuf) - imgbuf = Z_Malloc(1<<26, PU_STATIC, NULL); + // Allocate a staging buffer with the maximum size needed for a patch of the same size as the input. - UINT8 *imgptr = imgbuf; + // round up to nearest multiple of 254-pixel posts, plus 1 more 254-pixel post for paranoia reasons + size_t maxcolumnsize = (2 + (height - 1) / 256) * 256; + // the patch header, and width columns of the max column size + size_t maxoutsize = maxcolumnsize * width + (8 + 4 * width); + // so, a 512x512 flat should maximally need 393,760 (384.53 KiB) bytes. + // quite a bit smaller than 64 megabytes, and much less annoying to the windows debug allocator! + imgbuf = Z_Malloc(maxoutsize, PU_STATIC, NULL); + imgptr = imgbuf; // Write image size and offset WRITEINT16(imgptr, width); -- 2.54.0 From 6a9aea4dd1c46728c970bce96d1ccbcd706ddfbf Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 13 Oct 2025 19:19:33 +0200 Subject: [PATCH 068/219] use std::vector for our image buffers this is just to have it cleaner and less code bloat the resizing loop will almost never trigger, 1meg is enough to even rotate gigantamax eevee without needing to grow --- src/Sourcefile | 2 +- src/{r_patch.c => r_patch.cpp} | 52 +++++++++++-------- src/r_patch.h | 8 +++ ...{r_patchrotation.c => r_patchrotation.cpp} | 52 ++++++------------- 4 files changed, 57 insertions(+), 57 deletions(-) rename src/{r_patch.c => r_patch.cpp} (93%) rename src/{r_patchrotation.c => r_patchrotation.cpp} (83%) diff --git a/src/Sourcefile b/src/Sourcefile index 9474b797d..352081bc5 100644 --- a/src/Sourcefile +++ b/src/Sourcefile @@ -53,7 +53,7 @@ r_data.c r_draw.c r_fps.cpp r_main.cpp -r_patch.c +r_patch.cpp r_patchrotation.c r_plane.cpp r_segs.cpp diff --git a/src/r_patch.c b/src/r_patch.cpp similarity index 93% rename from src/r_patch.c rename to src/r_patch.cpp index cac31bff0..09aca078a 100644 --- a/src/r_patch.c +++ b/src/r_patch.cpp @@ -19,6 +19,7 @@ #include "r_skins.h" #include "z_zone.h" #include "w_wad.h" +#include #ifdef HWRENDER #include "hardware/hw_glob.h" @@ -37,7 +38,7 @@ static void R_ParseSpriteInfoFrame(spriteinfo_t *info) UINT8 frameFrame = 0xFF; INT16 frameXPivot = 0; INT16 frameYPivot = 0; - rotaxis_t frameRotAxis = 0; + rotaxis_t frameRotAxis = ROTAXIS_X; // Sprite identifier sprinfoToken = M_GetToken(NULL); @@ -158,14 +159,14 @@ static void R_ParseSpriteInfo(boolean spr2) I_Error("Error parsing SPRTINFO lump: Unknown sprite name \"%s\"", newSpriteName); if (!memcmp(newSpriteName,sprnames[i],4)) { - sprnum = i; + sprnum = static_cast(i); break; } } } // allocate a spriteinfo - info = Z_Calloc(sizeof(spriteinfo_t), PU_STATIC, NULL); + info = static_cast(Z_Calloc(sizeof(spriteinfo_t), PU_STATIC, NULL)); info->available = true; // Left Curly Brace @@ -329,7 +330,7 @@ void R_LoadSpriteInfoLumps(UINT16 wadnum, UINT16 numlumps) patch_t *Patch_Create(softwarepatch_t *source, size_t srcsize, void *dest) { - patch_t *patch = (dest == NULL) ? Z_Calloc(sizeof(patch_t), PU_PATCH, NULL) : (patch_t *)(dest); + patch_t *patch = static_cast((dest == NULL) ? Z_Calloc(sizeof(patch_t), PU_PATCH, NULL) : dest); if (source) { @@ -341,7 +342,7 @@ patch_t *Patch_Create(softwarepatch_t *source, size_t srcsize, void *dest) patch->height = SHORT(source->height); patch->leftoffset = SHORT(source->leftoffset); patch->topoffset = SHORT(source->topoffset); - patch->columnofs = Z_Calloc(size, PU_PATCH_DATA, NULL); + patch->columnofs = static_cast(Z_Calloc(size, PU_PATCH_DATA, NULL)); for (col = 0; col < source->width; col++) { @@ -357,7 +358,7 @@ patch_t *Patch_Create(softwarepatch_t *source, size_t srcsize, void *dest) if (colsize <= 0) I_Error("Patch_Create: no column data!"); - patch->columns = Z_Calloc(colsize, PU_PATCH_DATA, NULL); + patch->columns = static_cast(Z_Calloc(colsize, PU_PATCH_DATA, NULL)); M_Memcpy(patch->columns, ((UINT8 *)source + LONG(source->columnofs[0])), colsize); } @@ -429,8 +430,8 @@ void *Patch_AllocateHardwarePatch(patch_t *patch) { if (!patch->hardware) { - GLPatch_t *glPatch = Z_Calloc(sizeof(GLPatch_t), PU_HWRPATCHINFO, &patch->hardware); - glPatch->mipmap = Z_Calloc(sizeof(GLMipmap_t), PU_HWRPATCHINFO, &glPatch->mipmap); + GLPatch_t *glPatch = static_cast(Z_Calloc(sizeof(GLPatch_t), PU_HWRPATCHINFO, &patch->hardware)); + glPatch->mipmap = static_cast(Z_Calloc(sizeof(GLMipmap_t), PU_HWRPATCHINFO, &glPatch->mipmap)); } return (void *)(patch->hardware); } @@ -448,7 +449,8 @@ void *Patch_CreateGL(patch_t *patch) } #endif // HWRENDER -static UINT8 *imgbuf = NULL; +// 1 MB should be enough for most cases +static std::vector imgbuf(1024 * 1024); // // R_MaskedFlatToPatch @@ -473,8 +475,12 @@ void *R_PixelsToPatch(UINT8 *raw, INT16 width, INT16 height, INT16 leftoffset, I size_t maxoutsize = maxcolumnsize * width + (8 + 4 * width); // so, a 512x512 flat should maximally need 393,760 (384.53 KiB) bytes. // quite a bit smaller than 64 megabytes, and much less annoying to the windows debug allocator! - imgbuf = Z_Malloc(maxoutsize, PU_STATIC, NULL); - imgptr = imgbuf; + while (imgbuf.size() < maxoutsize) + { + imgbuf.resize(imgbuf.size() * 2); + } + + imgptr = imgbuf.data(); // Write image size and offset WRITEINT16(imgptr, width); @@ -494,7 +500,7 @@ void *R_PixelsToPatch(UINT8 *raw, INT16 width, INT16 height, INT16 leftoffset, I startofspan = NULL; // Write column pointer - WRITEINT32(colpointers, imgptr - imgbuf); + WRITEINT32(colpointers, imgptr - imgbuf.data()); // Write pixels for (y = 0; y < height; y++) @@ -563,9 +569,9 @@ void *R_PixelsToPatch(UINT8 *raw, INT16 width, INT16 height, INT16 leftoffset, I WRITEUINT8(imgptr, 0xFF); } - size = imgptr-imgbuf; - img = Z_Malloc(size, PU_STATIC, NULL); - memcpy(img, imgbuf, size); + size = imgptr-imgbuf.data(); + img = static_cast(Z_Malloc(size, PU_STATIC, NULL)); + memcpy(img, imgbuf.data(), size); if (destsize != NULL) *destsize = size; @@ -603,8 +609,12 @@ void *R_MaskedFlatToPatch(UINT16 *raw, INT16 width, INT16 height, INT16 leftoffs size_t maxoutsize = maxcolumnsize * width + (8 + 4 * width); // so, a 512x512 flat should maximally need 393,760 (384.53 KiB) bytes. // quite a bit smaller than 64 megabytes, and much less annoying to the windows debug allocator! - imgbuf = Z_Malloc(maxoutsize, PU_STATIC, NULL); - imgptr = imgbuf; + while (imgbuf.size() < maxoutsize) + { + imgbuf.resize(imgbuf.size() * 2); + } + + imgptr = imgbuf.data(); // Write image size and offset WRITEINT16(imgptr, width); @@ -624,7 +634,7 @@ void *R_MaskedFlatToPatch(UINT16 *raw, INT16 width, INT16 height, INT16 leftoffs startofspan = NULL; // Write column pointer - WRITEINT32(colpointers, imgptr - imgbuf); + WRITEINT32(colpointers, imgptr - imgbuf.data()); // Write pixels for (y = 0; y < height; y++) @@ -694,9 +704,9 @@ void *R_MaskedFlatToPatch(UINT16 *raw, INT16 width, INT16 height, INT16 leftoffs WRITEUINT8(imgptr, 0xFF); } - size = imgptr-imgbuf; - img = Z_Malloc(size, PU_STATIC, NULL); - memcpy(img, imgbuf, size); + size = imgptr-imgbuf.data(); + img = static_cast(Z_Malloc(size, PU_STATIC, NULL)); + memcpy(img, imgbuf.data(), size); if (destsize != NULL) *destsize = size; diff --git a/src/r_patch.h b/src/r_patch.h index 4d44b5416..266e4a563 100644 --- a/src/r_patch.h +++ b/src/r_patch.h @@ -14,6 +14,10 @@ #ifndef __R_PATCH__ #define __R_PATCH__ +#ifdef __cplusplus +extern "C" { +#endif + #include "r_defs.h" // Structs @@ -63,4 +67,8 @@ void *R_PixelsToPatch(UINT8 *raw, INT16 width, INT16 height, INT16 leftoffset, I UINT16 R_GetPatchPixel(patch_t *patch, INT32 x, INT32 y, boolean flip); void R_PatchToPixels(patch_t *patch, UINT8 *dst); // Important: dst must have enough space for patch->width*patch->height pixels! +#ifdef __cplusplus +} // extern "C" +#endif + #endif // __R_PATCH__ diff --git a/src/r_patchrotation.c b/src/r_patchrotation.cpp similarity index 83% rename from src/r_patchrotation.c rename to src/r_patchrotation.cpp index 862febf2f..ebf8960e6 100644 --- a/src/r_patchrotation.c +++ b/src/r_patchrotation.cpp @@ -15,6 +15,7 @@ #include "r_patchrotation.h" #include "z_zone.h" #include "w_wad.h" +#include #ifdef ROTSPRITE // @@ -89,14 +90,14 @@ patch_t *Patch_GetRotatedSprite(spriteframe_t *sprite, size_t frame, size_t spri RotatedPatch_DoRotation(rotsprite, patch, rotationangle, xpivot, ypivot, flip); } - return rotsprite->patches[idx]; + return static_cast(rotsprite->patches[idx]); } rotsprite_t *RotatedPatch_Create(INT32 numangles) { - rotsprite_t *rotsprite = Z_Calloc(sizeof(rotsprite_t), PU_STATIC, NULL); + rotsprite_t *rotsprite = static_cast(Z_Calloc(sizeof(rotsprite_t), PU_STATIC, NULL)); rotsprite->angles = numangles; - rotsprite->patches = Z_Calloc(rotsprite->angles * 2 * sizeof(void *), PU_STATIC, NULL); + rotsprite->patches = static_cast(Z_Calloc(rotsprite->angles * 2 * sizeof(void *), PU_STATIC, NULL)); return rotsprite; } @@ -118,30 +119,8 @@ static void RotatedPatch_CalculateDimensions( h1 = FixedInt(FixedCeil(h1 + (FRACUNIT/2))); h2 = FixedInt(FixedCeil(h2 + (FRACUNIT/2))); - *newwidth = max(width, max(w1, w2)); - *newheight = max(height, max(h1, h2)); -} - -static void RotatedPatch_AllocImgBuf(UINT16 **buf, size_t size, size_t *capacity) -{ - if (!*buf) - { - *buf = Z_Malloc(*capacity, PU_STATIC, NULL); - } - - size_t allocsize = size * sizeof(UINT16); - - // make sure our buffer always fits with what we need - if (allocsize > *capacity) - { - while (*capacity < allocsize) - *capacity *= 2; - - Z_Free(*buf); - *buf = Z_Malloc(*capacity, PU_STATIC, NULL); - } - - //CONS_Printf("RotatedPatch_AllocBuf: Allocated %.2f KB\n", *capacity / 1024.0); + *newwidth = std::max(width, std::max(w1, w2)); + *newheight = std::max(height, std::max(h1, h2)); } void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle, INT32 xpivot, INT32 ypivot, boolean flip) @@ -149,10 +128,10 @@ void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle UINT32 i; patch_t *rotated; - static UINT16 *rawdst = NULL, *rawconv = NULL; + static std::vector rawdst(1024 * 1024), rawconv(1024 * 1024); // 1 MB should be enough for most cases + UINT16 *rawout; size_t size; - static size_t dst_capacity = (1024 * 1024), conv_capacity = (1024 * 1024); // 1 MB should be enough for most cases INT32 bflip = (flip != 0x00); INT32 width = patch->width; @@ -206,7 +185,10 @@ void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle if (!size) size = (width * height); - RotatedPatch_AllocImgBuf(&rawdst, size, &dst_capacity); + while (rawdst.size() < size) + { + rawdst.resize(rawdst.size() * 2); + } for (i = 0; i < size; i++) rawdst[i] = 0xFF00; @@ -250,11 +232,11 @@ void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle size = (width * height); - RotatedPatch_AllocImgBuf(&rawconv, size, &conv_capacity); - memset(rawconv, 0, conv_capacity * sizeof(UINT16)); + rawconv.resize(size); + memset(rawconv.data(), 0, size * sizeof(UINT16)); src = &rawdst[(miny * newwidth) + minx]; - dest = rawconv; + dest = rawconv.data(); dy = height; while (dy--) @@ -267,14 +249,14 @@ void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle ox -= minx; oy -= miny; - rawout = rawconv; + rawout = rawconv.data(); } else { width = newwidth; height = newheight; - rawout = rawdst; + rawout = rawdst.data(); } // make patch -- 2.54.0 From b2260bbebbe974dd87f5476cbe098f1ee16c4616 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 13 Oct 2025 21:26:53 +0200 Subject: [PATCH 069/219] move R_SetColumnContext call we set this later to flush eitherway for non skybox draw --- src/r_main.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/r_main.cpp b/src/r_main.cpp index 1dabe4b21..88435ba93 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1391,8 +1391,6 @@ void R_RenderPlayerView(player_t *player) R_SetFov(fov); } - R_SetColumnContext(COLUMNCONTEXT_FLUSH); - Portal_InitList(); PS_START_TIMING(ps_skyboxtime); @@ -1406,6 +1404,7 @@ void R_RenderPlayerView(player_t *player) R_ClearPlanes(); R_ClearSprites(); + R_SetColumnContext(COLUMNCONTEXT_FLUSH); R_RenderViewpoint(&masks[nummasks - 1], false); R_ClipSprites(drawsegs, NULL); -- 2.54.0 From 89b81212821fcb526da9a8a69f60099c1ef580c8 Mon Sep 17 00:00:00 2001 From: Hanicef Date: Sat, 30 Mar 2024 17:58:27 +0100 Subject: [PATCH 070/219] Fix vertical aim being off when using lack of perspective --- src/hardware/hw_main.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/hardware/hw_main.cpp b/src/hardware/hw_main.cpp index c88b075a1..2ccb3f6d9 100644 --- a/src/hardware/hw_main.cpp +++ b/src/hardware/hw_main.cpp @@ -5352,7 +5352,9 @@ static void HWR_SetTransformAiming(FTransform *trans) if (cv_glshearing.value) { fixed_t fixedaiming = AIMINGTODY(aimingangle); - trans->viewaiming = FixedToFloat(fixedaiming); + trans->viewaiming = FixedToFloat(fixedaiming) * ((float)vid.width / vid.height) / ((float)BASEVIDWIDTH / BASEVIDHEIGHT); + if (splitscreen == 1) // only for 2 player splitscreen + trans->viewaiming *= 2.125; // splitscreen adjusts fov with 0.8, so compensate (but only halfway, since splitscreen means only half the screen is used) trans->shearing = true; gl_aimingangle = 0; } -- 2.54.0 From 9310a68cffead926d2e429304c64993b4d72f581 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 14 Oct 2025 22:43:58 +0200 Subject: [PATCH 071/219] delet gl_viewwidth, gl_viewheight, gl_baseviewwindowx, gl_baseviewwindowy gl_basewindowcenterx, gl_basewindowcentery they were effectively unused the last two werent ever even initialized to anything, using HWR_DrawViewBorder wouldve crashed --- src/hardware/hw_draw.c | 12 ++++++---- src/hardware/hw_main.cpp | 48 +++++++--------------------------------- src/hardware/hw_main.h | 4 ---- 3 files changed, 16 insertions(+), 48 deletions(-) diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 2b8ace584..1c014ce4c 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -649,6 +649,7 @@ void HWR_DrawConsoleBack(UINT32 color, INT32 height) // ------------------ void HWR_DrawViewBorder(INT32 clearlines) { +#if 0 INT32 x, y; INT32 top, side; INT32 baseviewwidth, baseviewheight; @@ -659,10 +660,10 @@ void HWR_DrawViewBorder(INT32 clearlines) clearlines = BASEVIDHEIGHT; // refresh all // calc view size based on original game resolution - baseviewwidth = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_viewwidth), vid.fdup)); //(cv_viewsize.value * BASEVIDWIDTH/10)&~7; - baseviewheight = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_viewheight), vid.fdup)); - top = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_baseviewwindowy), vid.fdup)); - side = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_baseviewwindowx), vid.fdup)); + baseviewwidth = FixedInt(FixedDiv(viewwidth * FRACUNIT, vid.fdup)); //(cv_viewsize.value * BASEVIDWIDTH/10)&~7; + baseviewheight = FixedInt(FixedDiv(viewheight * FRACUNIT, vid.fdup)); + top = FixedInt(FixedDiv(baseviewwindowy * FRACUNIT, vid.fdup)); + side = FixedInt(FixedDiv(baseviewwindowx * FRACUNIT, vid.fdup)); // top HWR_DrawFlatFill(0, 0, @@ -759,6 +760,9 @@ void HWR_DrawViewBorder(INT32 clearlines) PU_PATCH), basewindowx + baseviewwidth, basewindowy + baseviewheight, 0); +#else + (void)clearlines; +#endif } diff --git a/src/hardware/hw_main.cpp b/src/hardware/hw_main.cpp index 2ccb3f6d9..88584a9da 100644 --- a/src/hardware/hw_main.cpp +++ b/src/hardware/hw_main.cpp @@ -77,11 +77,6 @@ boolean gl_drawing_stencil = false; static INT32 current_bsp_culling_distance = 0; -// base values set at SetViewSize -float gl_baseviewwindowy, gl_baseviewwindowx; -static float gl_viewwindowy, gl_viewwindowx; // top left corner of view window -float gl_viewwidth, gl_viewheight; // viewport clipping boundaries (screen coords) - FTransform atransform; // Float variants of viewx, viewy, viewz, etc. @@ -5316,10 +5311,10 @@ static void HWR_DrawSkyBackground(void) // -----------------+ static inline void HWR_ClearView(void) { - GL_GClipRect((INT32)gl_viewwindowx, - (INT32)gl_viewwindowy, - (INT32)(gl_viewwindowx + gl_viewwidth), - (INT32)(gl_viewwindowy + gl_viewheight), + GL_GClipRect(viewwindowx, + viewwindowy, + (viewwindowx + viewwidth), + (viewwindowy + viewheight), ZCLIP_PLANE, FAR_ZCLIP_DEFAULT); GL_ClearBuffer(false, true, true, NULL); } @@ -5329,19 +5324,6 @@ static inline void HWR_ClearView(void) // -----------------+ void HWR_SetViewSize(void) { - // setup view size - gl_viewwidth = (float)vid.width; - gl_viewheight = (float)vid.height; - - if (splitscreen) - gl_viewheight /= 2; - - if (splitscreen > 1) - gl_viewwidth /= 2; - - gl_baseviewwindowy = 0; - gl_baseviewwindowx = 0; - GL_FlushScreenTextures(); } @@ -5596,20 +5578,6 @@ extern "C" { // ========================================================================== static void HWR_RenderFrame(player_t *player, boolean skybox) { - // set window position - gl_viewwindowx = gl_baseviewwindowx; - gl_viewwindowy = gl_baseviewwindowy; - - if ((splitscreen == 1 && viewssnum == 1) || (splitscreen > 1 && viewssnum > 1)) - { - gl_viewwindowy += gl_viewheight; - } - - if (splitscreen > 1 && viewssnum & 1) - { - gl_viewwindowx += gl_viewwidth; - } - // check for new console commands. NetUpdate(); @@ -5625,10 +5593,10 @@ static void HWR_RenderFrame(player_t *player, boolean skybox) if (!skybox && cv_glrenderdistance.value) { - GL_GClipRect((INT32)gl_viewwindowx, - (INT32)gl_viewwindowy, - (INT32)(gl_viewwindowx + gl_viewwidth), - (INT32)(gl_viewwindowy + gl_viewheight), + GL_GClipRect(viewwindowx, + viewwindowy, + (viewwindowx + viewwidth), + (viewwindowy + viewheight), ZCLIP_PLANE, clipping_distances[cv_glrenderdistance.value - 1]); current_bsp_culling_distance = bsp_culling_distances[cv_glrenderdistance.value - 1]; } diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 4060b6540..43a292c57 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -42,10 +42,6 @@ extern "C" { void HWR_Startup(void); void HWR_Shutdown(void); -extern float gl_viewwidth, gl_viewheight, gl_baseviewwindowx, gl_baseviewwindowy; - -extern float gl_basewindowcenterx, gl_basewindowcentery; - extern unsigned msaa; extern boolean a2c; -- 2.54.0 From af8ce028ba8ea8b3707c4d88d0fe265ce6776bb9 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 14 Oct 2025 22:45:08 +0200 Subject: [PATCH 072/219] use stdlibs abs for CompareDrawNodePlanes we dont need our own abs for this --- src/hardware/hw_main.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/hardware/hw_main.cpp b/src/hardware/hw_main.cpp index 88584a9da..382143dcb 100644 --- a/src/hardware/hw_main.cpp +++ b/src/hardware/hw_main.cpp @@ -65,8 +65,6 @@ // Globals // ========================================================================== -#define ABS(x) ((x) < 0 ? -(x) : (x)) - // false if shaders have not been initialized yet, or if shaders are not available boolean gl_shadersavailable = false; @@ -4330,7 +4328,7 @@ static int CompareDrawNodePlanes(const void *p1, const void *p2) const INT32 n1 = *(const INT32*)p1; const INT32 n2 = *(const INT32*)p2; - return ABS(drawnodes[n2].u.plane.fixedheight - viewz) - ABS(drawnodes[n1].u.plane.fixedheight - viewz); + return abs(drawnodes[n2].u.plane.fixedheight - viewz) - abs(drawnodes[n1].u.plane.fixedheight - viewz); } // -- 2.54.0 From 37579187cc387595db217adc61f1e2c363af3f04 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 14 Oct 2025 23:13:39 +0200 Subject: [PATCH 073/219] remove dead renderer code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit remove - broken viewborder code (if we really want it back for some reason, we should rather port RR´s fixed version of it) - remove console clipping code for software (this was broken eiherway) - remove hud message clearing stuff - remove renderscreen and linesize variables (they just pointed to vid.screen and vid.widht) --- src/Makefile.d/sdl.mk | 2 +- src/console.c | 31 ------- src/console.h | 5 -- src/d_main.c | 9 -- src/doomtype.h | 1 - src/hardware/hw_draw.c | 200 +---------------------------------------- src/hardware/hw_main.h | 2 - src/hu_stuff.c | 70 --------------- src/hu_stuff.h | 1 - src/i_video.h | 2 +- src/m_menu.c | 3 +- src/r_draw.cpp | 147 +----------------------------- src/r_draw.h | 34 +------ src/r_main.cpp | 2 - src/r_plane.cpp | 2 +- src/r_segs.cpp | 5 +- src/r_things.cpp | 2 - src/screen.c | 7 +- src/screen.h | 2 - src/sdl/Srb2SDL.dsp | 4 +- src/sdl/Srb2SDL.props | 4 +- src/st_stuff.c | 4 - 22 files changed, 14 insertions(+), 525 deletions(-) diff --git a/src/Makefile.d/sdl.mk b/src/Makefile.d/sdl.mk index c704a83eb..95fe34e6a 100644 --- a/src/Makefile.d/sdl.mk +++ b/src/Makefile.d/sdl.mk @@ -10,7 +10,7 @@ makedir:=$(makedir)/SDL -opts+=-DDIRECTFULLSCREEN -DHAVE_SDL +opts+=-DHAVE_SDL sources+=$(call List,sdl/Sourcefile) NOUPNP=1 diff --git a/src/console.c b/src/console.c index fe91df0f3..3959d9b98 100644 --- a/src/console.c +++ b/src/console.c @@ -69,14 +69,9 @@ static boolean consoleready; // console prompt is ready INT32 con_destlines; // vid lines used by console at final position static INT32 con_curlines; // vid lines currently used by console - INT32 con_clipviewtop; // (useless) - static UINT8 con_hudlines; // number of console heads up message lines static UINT32 con_hudtime[MAXHUDLINES]; // remaining time of display for hud msg lines - INT32 con_clearlines; // top screen lines to refresh when view reduced - boolean con_hudupdate; // when messages scroll, we need a backgrnd refresh - // console text output static char *con_line; // console text output current line static size_t con_cx; // cursor position in current line @@ -393,9 +388,6 @@ void CON_Init(void) Lock_state(); - //note: CON_Ticker should always execute at least once before D_Display() - con_clipviewtop = -1; // -1 does not clip - con_hudlines = atoi(cons_hudlines.defaultvalue); Unlock_state(); @@ -727,7 +719,6 @@ void CON_ToggleOff(void) con_curlines = 0; CON_ClearHUD(); con_forcepic = 0; - con_clipviewtop = -1; // remove console clipping of view I_SetTextInput(false); @@ -779,18 +770,6 @@ void CON_Ticker(void) } } - // clip the view, so that the part under the console is not drawn - con_clipviewtop = -1; - if (cons_backpic.value) // clip only when using an opaque background - { - if (con_curlines > 0) - con_clipviewtop = con_curlines - viewwindowy - 1 - 10; - // NOTE: BIG HACK::SUBTRACT 10, SO THAT WATER DON'T COPY LINES OF THE CONSOLE - // WINDOW!!! (draw some more lines behind the bottom of the console) - if (con_clipviewtop < 0) - con_clipviewtop = -1; // maybe not necessary, provided it's < 0 - } - // check if console ready for prompt if (con_destlines >= minheight) { @@ -1100,9 +1079,6 @@ static void CON_Linefeed(void) con_line = &con_buffer[(con_cy%con_totallines)*con_width]; memset(con_line, ' ', con_width); - - // make sure the view borders are refreshed if hud messages scroll - con_hudupdate = true; // see HU_Erase() } // Outputs text into the console text buffer @@ -1489,9 +1465,6 @@ static void CON_DrawHudlines(void) //V_DrawCharacter(x, y, (p[c]&0xff) | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value); y += charheight; } - - // top screen lines that might need clearing when view is reduced - con_clearlines = y; // this is handled by HU_Erase(); } // draw the console background, text, and prompt if enough place @@ -1509,10 +1482,6 @@ static void CON_DrawConsole(void) if (con_curlines <= 0) return; - //FIXME: refresh borders only when console bg is translucent - con_clearlines = con_curlines; // clear console draw from view borders - con_hudupdate = true; // always refresh while console is on - // draw console background if (cons_backpic.value || con_forcepic) { diff --git a/src/console.h b/src/console.h index e704a87f1..79af2e48f 100644 --- a/src/console.h +++ b/src/console.h @@ -30,14 +30,9 @@ extern boolean con_recalc; extern boolean con_startup; -// top clip value for view render: do not draw part of view hidden by console -extern INT32 con_clipviewtop; - // 0 means console if off, or moving out extern INT32 con_destlines; -extern INT32 con_clearlines; // lines of top of screen to refresh -extern boolean con_hudupdate; // hud messages have changed, need refresh extern UINT32 con_scalefactor; // console text scale factor extern consvar_t cons_backcolor, cons_menuhighlight; diff --git a/src/d_main.c b/src/d_main.c index dd13c7b77..33dc57689 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -522,19 +522,16 @@ static boolean D_Display(void) case GS_LEVEL: if (!gametic) break; - HU_Erase(); AM_Drawer(); break; case GS_INTERMISSION: Y_IntermissionDrawer(); - HU_Erase(); HU_Drawer(); break; case GS_VOTING: Y_VoteDrawer(); - HU_Erase(); HU_Drawer(); break; @@ -549,7 +546,6 @@ static boolean D_Display(void) case GS_CUTSCENE: F_CutsceneDrawer(); - HU_Erase(); HU_Drawer(); break; @@ -559,7 +555,6 @@ static boolean D_Display(void) case GS_EVALUATION: F_GameEvaluationDrawer(); - HU_Erase(); HU_Drawer(); break; @@ -569,7 +564,6 @@ static boolean D_Display(void) case GS_CREDITS: F_CreditDrawer(); - HU_Erase(); HU_Drawer(); break; @@ -586,7 +580,6 @@ static boolean D_Display(void) { // I don't think HOM from nothing drawing is independent... F_WaitingPlayersDrawer(); - HU_Erase(); HU_Drawer(); } case GS_TIMEATTACK: @@ -1925,9 +1918,7 @@ void D_SRB2Main(void) G_LoadGameData(); -#if defined (__unix__) || defined (UNIXCOMMON) || defined (HAVE_SDL) VID_PrepareModeList(); // Regenerate Modelist according to cv_fullscreen -#endif // set user default mode or mode set at cmdline SCR_CheckDefaultMode(); diff --git a/src/doomtype.h b/src/doomtype.h index 81c09c007..78867ed69 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -43,7 +43,6 @@ extern "C" { #define UINT64 uint64_t #ifdef __APPLE_CC__ -#define DIRECTFULLSCREEN 1 #define DEBUG_LOG #define NOIPX #endif diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 1c014ce4c..cf8ab29e3 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -31,11 +31,6 @@ #include "../st_stuff.h" #include -#include "../i_video.h" // for rendermode != render_glide - -#ifndef O_BINARY -#define O_BINARY 0 -#endif typedef struct { @@ -58,68 +53,6 @@ static UINT8 softwaretranstogl_lo[11] = { 0, 12, 24, 36, 48, 60, 71, 83, 95,111 static const float FLOATBASEVIDWIDTH = (float)BASEVIDWIDTH; static const float FLOATBASEVIDHEIGHT = (float)BASEVIDHEIGHT; -// -// -----------------+ -// HWR_DrawPatch : Draw a 'tile' graphic -// Notes : x,y : positions relative to the original Doom resolution -// : textes(console+score) + menus + status bar -// -----------------+ -void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option) -{ - FOutVector v[4]; - FBITFIELD flags; - GLPatch_t *hwrPatch; - -// 3--2 -// | /| -// |/ | -// 0--1 - float sdup = FIXED_TO_FLOAT(vid.fdup)*2.0f; - float pdup = FIXED_TO_FLOAT(vid.fdup)*2.0f; - - // make patch ready in hardware cache - HWR_GetPatch(gpatch); - hwrPatch = ((GLPatch_t *)gpatch->hardware); - - switch (option & V_SCALEPATCHMASK) - { - case V_NOSCALEPATCH: - pdup = 2.0f; - break; - case V_SMALLSCALEPATCH: - pdup = 2.0f * FIXED_TO_FLOAT(vid.smalldup*FRACUNIT); - break; - case V_MEDSCALEPATCH: - pdup = 2.0f * FIXED_TO_FLOAT(vid.meddup*FRACUNIT); - break; - } - - if (option & V_NOSCALESTART) - sdup = 2.0f; - - v[0].x = v[3].x = (x*sdup-gpatch->leftoffset*pdup)/vid.width - 1; - v[2].x = v[1].x = (x*sdup+(gpatch->width - gpatch->leftoffset)*pdup)/vid.width - 1; - v[0].y = v[1].y = 1-(y*sdup-gpatch->topoffset*pdup)/vid.height; - v[2].y = v[3].y = 1-(y*sdup+(gpatch->height - gpatch->topoffset)*pdup)/vid.height; - - v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - - v[0].s = v[3].s = 0.0f; - v[2].s = v[1].s = hwrPatch->max_s; - v[0].t = v[1].t = 0.0f; - v[2].t = v[3].t = hwrPatch->max_t; - - flags = PF_Translucent|PF_NoDepthTest; - - if (option & V_WRAPX) - flags |= PF_ForceWrapX; - if (option & V_WRAPY) - flags |= PF_ForceWrapY; - - // clip it since it is used for bunny scroll in doom I - GL_DrawPolygon(NULL, v, 4, flags); -} - void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap, INT32 bflags) { FOutVector v[4]; @@ -636,137 +569,6 @@ void HWR_DrawConsoleBack(UINT32 color, INT32 height) } -// ========================================================================== -// R_DRAW.C STUFF -// ========================================================================== - -// ------------------ -// HWR_DrawViewBorder -// Fill the space around the view window with a Doom flat texture, draw the -// beveled edges. -// 'clearlines' is useful to clear the heads up messages, when the view -// window is reduced, it doesn't refresh all the view borders. -// ------------------ -void HWR_DrawViewBorder(INT32 clearlines) -{ -#if 0 - INT32 x, y; - INT32 top, side; - INT32 baseviewwidth, baseviewheight; - INT32 basewindowx, basewindowy; - patch_t *patch; - - if (!clearlines) - clearlines = BASEVIDHEIGHT; // refresh all - - // calc view size based on original game resolution - baseviewwidth = FixedInt(FixedDiv(viewwidth * FRACUNIT, vid.fdup)); //(cv_viewsize.value * BASEVIDWIDTH/10)&~7; - baseviewheight = FixedInt(FixedDiv(viewheight * FRACUNIT, vid.fdup)); - top = FixedInt(FixedDiv(baseviewwindowy * FRACUNIT, vid.fdup)); - side = FixedInt(FixedDiv(baseviewwindowx * FRACUNIT, vid.fdup)); - - // top - HWR_DrawFlatFill(0, 0, - BASEVIDWIDTH, (top < clearlines ? top : clearlines), - st_borderpatchnum); - - // left - if (top < clearlines) - HWR_DrawFlatFill(0, top, side, - (clearlines-top < baseviewheight ? clearlines-top : baseviewheight), - st_borderpatchnum); - - // right - if (top < clearlines) - HWR_DrawFlatFill(side + baseviewwidth, top, side, - (clearlines-top < baseviewheight ? clearlines-top : baseviewheight), - st_borderpatchnum); - - // bottom - if (top + baseviewheight < clearlines) - HWR_DrawFlatFill(0, top + baseviewheight, - BASEVIDWIDTH, BASEVIDHEIGHT, st_borderpatchnum); - - // - // draw the view borders - // - - basewindowx = (BASEVIDWIDTH - baseviewwidth)>>1; - if (baseviewwidth == BASEVIDWIDTH) - basewindowy = 0; - else - basewindowy = top; - - // top edge - if (clearlines > basewindowy - 8) - { - patch = W_CachePatchNum(viewborderlump[BRDR_T], PU_PATCH); - for (x = 0; x < baseviewwidth; x += 8) - HWR_DrawPatch(patch, basewindowx + x, basewindowy - 8, - 0); - } - - // bottom edge - if (clearlines > basewindowy + baseviewheight) - { - patch = W_CachePatchNum(viewborderlump[BRDR_B], PU_PATCH); - for (x = 0; x < baseviewwidth; x += 8) - HWR_DrawPatch(patch, basewindowx + x, - basewindowy + baseviewheight, 0); - } - - // left edge - if (clearlines > basewindowy) - { - patch = W_CachePatchNum(viewborderlump[BRDR_L], PU_PATCH); - for (y = 0; y < baseviewheight && basewindowy + y < clearlines; - y += 8) - { - HWR_DrawPatch(patch, basewindowx - 8, basewindowy + y, - 0); - } - } - - // right edge - if (clearlines > basewindowy) - { - patch = W_CachePatchNum(viewborderlump[BRDR_R], PU_PATCH); - for (y = 0; y < baseviewheight && basewindowy+y < clearlines; - y += 8) - { - HWR_DrawPatch(patch, basewindowx + baseviewwidth, - basewindowy + y, 0); - } - } - - // Draw beveled corners. - if (clearlines > basewindowy - 8) - HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_TL], - PU_PATCH), - basewindowx - 8, basewindowy - 8, 0); - - if (clearlines > basewindowy - 8) - HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_TR], - PU_PATCH), - basewindowx + baseviewwidth, basewindowy - 8, 0); - - if (clearlines > basewindowy+baseviewheight) - HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_BL], - PU_PATCH), - basewindowx - 8, basewindowy + baseviewheight, 0); - - if (clearlines > basewindowy + baseviewheight) - HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_BR], - PU_PATCH), - basewindowx + baseviewwidth, - basewindowy + baseviewheight, 0); -#else - (void)clearlines; -#endif -} - - - // ========================================================================== // AM_MAP.C DRAWING STUFF // ========================================================================== @@ -1172,7 +974,7 @@ static inline boolean saveTGA(const char *file_name, void *buffer, INT32 i; UINT8 *buf8 = buffer; - fd = open(file_name, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); + fd = open(file_name, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd < 0) return false; diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 43a292c57..30906b611 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -85,7 +85,6 @@ extern ps_metric_t ps_hw_batchdrawtime; extern boolean gl_shadersavailable; // hw_draw.c -void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option); void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap, INT32 bflags); void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h); void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color); @@ -94,7 +93,6 @@ void HWR_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 color); void HWR_drawAMline(const fline_t *fl, INT32 color); void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength); void HWR_DrawConsoleBack(UINT32 color, INT32 height); -void HWR_DrawViewBorder(INT32 clearlines); void HWR_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum); UINT8 *HWR_GetScreenshot(INT32 scale); diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 6ca275aff..fa7060dff 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2391,76 +2391,6 @@ void HU_Drawer(void) } } -//====================================================================== -// HUD MESSAGES CLEARING FROM SCREEN -//====================================================================== - -// Clear old messages from the borders around the view window -// (only for reduced view, refresh the borders when needed) -// -// startline: y coord to start clear, -// clearlines: how many lines to clear. -// -static INT32 oldclearlines; - -void HU_Erase(void) -{ - INT32 topline, bottomline; - INT32 y, yoffset; - -#ifdef HWRENDER - // clear hud msgs on double buffer (OpenGL mode) - boolean secondframe; - static INT32 secondframelines; -#endif - - if (con_clearlines == oldclearlines && !con_hudupdate && !chat_on) - return; - -#ifdef HWRENDER - // clear the other frame in double-buffer modes - secondframe = (con_clearlines != oldclearlines); - if (secondframe) - secondframelines = oldclearlines; -#endif - - // clear the message lines that go away, so use _oldclearlines_ - bottomline = oldclearlines; - oldclearlines = con_clearlines; - if (chat_on && OLDCHAT) - if (bottomline < 8) - bottomline = 8; // only do it for consolechat. consolechat is gay. - - if (automapactive || viewwindowx == 0) // hud msgs don't need to be cleared - return; - - // software mode copies view border pattern & beveled edges from the backbuffer - if (rendermode == render_soft) - { - topline = 0; - for (y = topline, yoffset = y*vid.width; y < bottomline; y++, yoffset += vid.width) - { - if (y < viewwindowy || y >= viewwindowy + viewheight) - R_VideoErase(yoffset, vid.width); // erase entire line - else - { - R_VideoErase(yoffset, viewwindowx); // erase left border - // erase right border - R_VideoErase(yoffset + viewwindowx + viewwidth, viewwindowx); - } - } - con_hudupdate = false; // if it was set.. - } -#ifdef HWRENDER - else if (rendermode != render_none) - { - // refresh just what is needed from the view borders - HWR_DrawViewBorder(secondframelines); - con_hudupdate = secondframe; - } -#endif -} - //====================================================================== // IN-LEVEL MULTIPLAYER RANKINGS //====================================================================== diff --git a/src/hu_stuff.h b/src/hu_stuff.h index d134f319e..64d369a33 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -117,7 +117,6 @@ void HU_TickSongCredits(void); void HU_DrawSongCredits(void); void HU_Drawer(void); char HU_dequeueChatChar(void); -void HU_Erase(void); void HU_clearChatChars(void); void HU_drawPlayerPing(INT32 x, INT32 y, INT32 pnum, INT32 flags); // Lat': Ping drawer for scoreboard. //void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer); diff --git a/src/i_video.h b/src/i_video.h index 822a1bada..852645c30 100644 --- a/src/i_video.h +++ b/src/i_video.h @@ -94,8 +94,8 @@ INT32 VID_SetMode(INT32 modenum); \return name of video mode */ const char *VID_GetModeName(INT32 modenum); -void VID_PrepareModeList(void); /// note hack for SDL +void VID_PrepareModeList(void); /** \brief can video system do fullscreen */ diff --git a/src/m_menu.c b/src/m_menu.c index 95824c7dd..ed39e053f 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -9442,9 +9442,8 @@ static void M_VideoModeMenu(INT32 choice) memset(modedescs, 0, sizeof(modedescs)); -#if defined (__unix__) || defined (UNIXCOMMON) || defined (HAVE_SDL) VID_PrepareModeList(); // FIXME: hack -#endif + vidm_nummodes = 0; vidm_selected = 0; nummodes = VID_NumModes(); diff --git a/src/r_draw.cpp b/src/r_draw.cpp index c8a09745a..91de5e102 100644 --- a/src/r_draw.cpp +++ b/src/r_draw.cpp @@ -41,8 +41,7 @@ /** \brief view info */ -INT32 linesize, viewwidth, viewheight, viewwindowx, viewwindowy; -UINT8 *renderscreen; // haleyjd +INT32 viewwidth, viewheight, viewwindowx, viewwindowy; // ========================================================================= // COLUMN DRAWING CODE STUFF @@ -521,7 +520,6 @@ static void R_AllocViewMemory(void) R_AllocVisSpriteMemory(); } - void R_InitViewBuffer(INT32 width, INT32 height) { if (width > MAXVIDWIDTH) @@ -534,27 +532,7 @@ void R_InitViewBuffer(INT32 width, INT32 height) viewwindowx = 0; viewwindowy = 0; - linesize = vid.width; // killough 11/98 - renderscreen = vid.screens[0]; // haleyjd 07/02/14 -} -/** \brief viewborder patches lump numbers -*/ -lumpnum_t viewborderlump[8]; - -/** \brief Store the lumpnumber of the viewborder patches -*/ - -void R_InitViewBorder(void) -{ - viewborderlump[BRDR_T] = W_GetNumForName("brdr_t"); - viewborderlump[BRDR_B] = W_GetNumForName("brdr_b"); - viewborderlump[BRDR_L] = W_GetNumForName("brdr_l"); - viewborderlump[BRDR_R] = W_GetNumForName("brdr_r"); - viewborderlump[BRDR_TL] = W_GetNumForName("brdr_tl"); - viewborderlump[BRDR_BL] = W_GetNumForName("brdr_bl"); - viewborderlump[BRDR_TR] = W_GetNumForName("brdr_tr"); - viewborderlump[BRDR_BR] = W_GetNumForName("brdr_br"); } /** \brief The R_VideoErase function @@ -578,129 +556,6 @@ void R_VideoErase(size_t ofs, INT32 count) M_Memcpy(vid.screens[0] + ofs, vid.screens[1] + ofs, count); } - -#if 0 -/** \brief R_FillBackScreen - - Fills the back screen with a pattern for variable screen sizes - Also draws a beveled edge. -*/ -void R_FillBackScreen(void) -{ - UINT8 *src, *dest; - patch_t *patch; - INT32 x, y, step, boff; - - // quickfix, don't cache lumps in both modes - if (rendermode != render_soft) - return; - - // draw pattern around the status bar too (when hires), - // so return only when in full-screen without status bar. - if (scaledviewwidth == vid.width && viewheight == vid.height) - return; - - src = scr_borderpatch; - dest = vid.screens[1]; - - for (y = 0; y < vid.height; y++) - { - for (x = 0; x < vid.width/128; x++) - { - M_Memcpy (dest, src+((y&127)<<7), 128); - dest += 128; - } - - if (vid.width&127) - { - M_Memcpy(dest, src+((y&127)<<7), vid.width&127); - dest += (vid.width&127); - } - } - - // don't draw the borders when viewwidth is full vid.width. - if (scaledviewwidth == vid.width) - return; - - step = 8; - boff = 8; - - patch = W_CacheLumpNum(viewborderlump[BRDR_T], PU_CACHE); - for (x = 0; x < scaledviewwidth; x += step) - V_DrawPatch(viewwindowx + x, viewwindowy - boff, 1, patch); - - patch = W_CacheLumpNum(viewborderlump[BRDR_B], PU_CACHE); - for (x = 0; x < scaledviewwidth; x += step) - V_DrawPatch(viewwindowx + x, viewwindowy + viewheight, 1, patch); - - patch = W_CacheLumpNum(viewborderlump[BRDR_L], PU_CACHE); - for (y = 0; y < viewheight; y += step) - V_DrawPatch(viewwindowx - boff, viewwindowy + y, 1, patch); - - patch = W_CacheLumpNum(viewborderlump[BRDR_R],PU_CACHE); - for (y = 0; y < viewheight; y += step) - V_DrawPatch(viewwindowx + scaledviewwidth, viewwindowy + y, 1, - patch); - - // Draw beveled corners. - V_DrawPatch(viewwindowx - boff, viewwindowy - boff, 1, - W_CacheLumpNum(viewborderlump[BRDR_TL], PU_CACHE)); - V_DrawPatch(viewwindowx + scaledviewwidth, viewwindowy - boff, 1, - W_CacheLumpNum(viewborderlump[BRDR_TR], PU_CACHE)); - V_DrawPatch(viewwindowx - boff, viewwindowy + viewheight, 1, - W_CacheLumpNum(viewborderlump[BRDR_BL], PU_CACHE)); - V_DrawPatch(viewwindowx + scaledviewwidth, viewwindowy + viewheight, 1, - W_CacheLumpNum(viewborderlump[BRDR_BR], PU_CACHE)); -} - -/** \brief The R_DrawViewBorder - - Draws the border around the view - for different size windows? -*/ -void R_DrawViewBorder(void) -{ - INT32 top, side, ofs; - - if (rendermode == render_none) - return; -#ifdef HWRENDER - if (rendermode != render_soft) - { - HWR_DrawViewBorder(0); - return; - } - else -#endif - -#ifdef DEBUG - fprintf(stderr,"RDVB: vidwidth %d vidheight %d scaledviewwidth %d viewheight %d\n", - vid.width, vid.height, scaledviewwidth, viewheight); -#endif - - if (scaledviewwidth == vid.width) - return; - - top = (vid.height - viewheight)>>1; - side = (vid.width - scaledviewwidth)>>1; - - // copy top and one line of left side - R_VideoErase(0, top*vid.width+side); - - // copy one line of right side and bottom - ofs = (viewheight+top)*vid.width - side; - R_VideoErase(ofs, top*vid.width + side); - - // copy sides using wraparound - ofs = top*vid.width + vid.width-side; - side <<= 1; - - // simpler using our VID_Blit routine - VID_BlitLinearScreen(vid.screens[1] + ofs, vid.screens[0] + ofs, side, viewheight - 1, - vid.width, vid.width); -} -#endif - // ========================================================================== // INCLUDE DRAWING CODE HERE // ========================================================================== diff --git a/src/r_draw.h b/src/r_draw.h index bcd734e50..eaee19039 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -25,12 +25,10 @@ extern "C" { // ------------------------------- // COMMON STUFF FOR 8bpp AND 16bpp // ------------------------------- -extern UINT8 *renderscreen; -extern INT32 linesize; FUNCINLINE static ATTRINLINE UINT8 *R_Address(INT32 px, INT32 py) { - return renderscreen + (py + viewwindowy) * linesize + (viewwindowx + px); + return vid.screens[0] + (py + viewwindowy) * vid.width + (viewwindowx + px); } @@ -152,27 +150,8 @@ extern spandrawfunc_t *spanfuncs[SPANDRAWFUNC_MAX]; void R_DrawMaskedColumn(drawcolumndata_t* dc, column_t *column); -/// \brief Top border -#define BRDR_T 0 -/// \brief Bottom border -#define BRDR_B 1 -/// \brief Left border -#define BRDR_L 2 -/// \brief Right border -#define BRDR_R 3 -/// \brief Topleft border -#define BRDR_TL 4 -/// \brief Topright border -#define BRDR_TR 5 -/// \brief Bottomleft border -#define BRDR_BL 6 -/// \brief Bottomright border -#define BRDR_BR 7 - -extern lumpnum_t viewborderlump[8]; - // ------------------------------------------------ -// r_draw.c COMMON ROUTINES FOR BOTH 8bpp and 16bpp +// r_draw.c // ------------------------------------------------ #define GTC_CACHE 1 @@ -221,17 +200,8 @@ boolean R_BlendLevelVisible(INT32 blendmode, INT32 alphalevel); // Custom player skin translation void R_InitViewBuffer(INT32 width, INT32 height); -void R_InitViewBorder(void); void R_VideoErase(size_t ofs, INT32 count); -// Rendering function. -#if 0 -void R_FillBackScreen(void); - -// If the view size is not full screen, draws a border around it. -void R_DrawViewBorder(void); -#endif - #define TRANSPARENTPIXEL 247 // ----------------- diff --git a/src/r_main.cpp b/src/r_main.cpp index 08f1e68a1..a392db087 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1023,8 +1023,6 @@ void R_Init(void) //I_OutputMsg("\nR_InitData"); R_InitData(); - //I_OutputMsg("\nR_InitViewBorder"); - R_InitViewBorder(); R_SetViewSize(); // setsizeneeded is set true // this is now done by SCR_Recalc() at the first mode set diff --git a/src/r_plane.cpp b/src/r_plane.cpp index de713dc9c..484aab49c 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -787,7 +787,7 @@ static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), b drawcolumndata_t dc = {}; const INT32 texture = texturetranslation[skytexture]; - // Reset column drawer function (note: couldn't we just call walldrawerfunc directly?) + // Reset column drawer function (note: couldn't we just call colfuncs[BASEDRAWFUNC] directly?) // (that is, unless we'll need to switch drawers in future for some reason) R_SetColumnFunc(BASEDRAWFUNC); diff --git a/src/r_segs.cpp b/src/r_segs.cpp index c83b45593..b4f8cdbcd 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -26,7 +26,6 @@ #include "p_local.h" // Camera... #include "p_setup.h" #include "p_slopes.h" -#include "console.h" // con_clipviewtop #include "screen.h" #include "core/memory.h" @@ -628,8 +627,6 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf sector_t tempsec; INT32 templight; INT32 i, p; - fixed_t bottombounds = viewheight << FRACBITS; - fixed_t topbounds = (con_clipviewtop - 1) << FRACBITS; fixed_t offsetvalue = 0; lightlist_t *light; r_lightlist_t *rlight; @@ -936,7 +933,7 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf bottom_frac += bottom_step; // SoM: If column is out of range, why bother with it?? - if (windowbottom < topbounds || windowtop > bottombounds) + if (windowbottom < 0 || windowtop > (viewheight << FRACBITS)) { if (dc->numlights) { diff --git a/src/r_things.cpp b/src/r_things.cpp index 12d02d329..d69e7ea4e 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -2518,8 +2518,6 @@ void R_InitDrawNodes(void) // R_DrawSprite // //Fab : 26-04-98: -// NOTE : uses con_clipviewtop, so that when console is on, -// don't draw the part of sprites hidden under the console static void R_DrawSprite(vissprite_t *spr) { mfloorclip = spr->clipbot; diff --git a/src/screen.c b/src/screen.c index 8d2782ab8..9a8109066 100644 --- a/src/screen.c +++ b/src/screen.c @@ -80,10 +80,6 @@ consvar_t cv_accuratefps = {"fpssampling", "1", CV_SAVE, accuratefps_cons_t, NUL // SCREEN VARIABLES // ========================================================================= -UINT8 *scr_borderpatch; // flat used to fill the reduced view borders set at ST_Init() - -// ========================================================================= - static void SCR_SetDrawFuncs(void) { // @@ -298,7 +294,6 @@ void SCR_SetDefaultMode(void) // Change fullscreen on/off according to cv_fullscreen void SCR_ChangeFullscreen(void) { -#ifdef DIRECTFULLSCREEN I_SetBorderlessWindow(); // Running this here so we can have borderless window at startup // allow_fullscreen is set by VID_PrepareModeList @@ -311,8 +306,8 @@ void SCR_ChangeFullscreen(void) VID_PrepareModeList(); setmodeneeded = VID_GetModeForSize(vid.width, vid.height) + 1; } + return; -#endif } boolean SCR_IsAspectCorrect(INT32 width, INT32 height) diff --git a/src/screen.h b/src/screen.h index ecad24a64..fb234324f 100644 --- a/src/screen.h +++ b/src/screen.h @@ -84,8 +84,6 @@ enum extern viddef_t vid; extern INT32 setmodeneeded; // mode number to set if needed, or 0 -extern UINT8 *scr_borderpatch; // patch used to fill the view borders - extern consvar_t cv_scr_width, cv_scr_height, cv_renderview, cv_frameskip, cv_fullscreen, cv_vhseffect, cv_shittyscreen; extern consvar_t cv_parallelsoftware; extern consvar_t cv_paralleldrawmasked; diff --git a/src/sdl/Srb2SDL.dsp b/src/sdl/Srb2SDL.dsp index 47ede4126..96d3e8418 100644 --- a/src/sdl/Srb2SDL.dsp +++ b/src/sdl/Srb2SDL.dsp @@ -45,7 +45,7 @@ MTL=midl.exe # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /G5 /W3 /GX /Zi /Ot /Og /Oi /Op /Oy /Ob1 /I "..\..\libs\libpng-src" /I "..\..\libs\zlib" /D "NDEBUG" /D "SDLMAIN" /D "NO_STDIO_REDIRECT" /D "USE_WGL_SWAP" /D "DIRECTFULLSCREEN" /D "HAVE_SDL" /D "HWRENDER" /D "HAVE_FILTER" /D "HAVE_MIXER" /D "USEASM" /D "HAVE_PNG" /FR /FD /GF /c +# ADD CPP /nologo /G5 /W3 /GX /Zi /Ot /Og /Oi /Op /Oy /Ob1 /I "..\..\libs\libpng-src" /I "..\..\libs\zlib" /D "NDEBUG" /D "SDLMAIN" /D "NO_STDIO_REDIRECT" /D "USE_WGL_SWAP" /D "HAVE_SDL" /D "HWRENDER" /D "HAVE_FILTER" /D "HAVE_MIXER" /D "USEASM" /D "HAVE_PNG" /FR /FD /GF /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" # SUBTRACT RSC /x @@ -72,7 +72,7 @@ LINK32=link.exe # PROP Target_Dir "" MTL=midl.exe # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /G6 /W4 /WX /Gm /GX /ZI /Od /Op /I "..\..\libs\libpng-src" /I "..\..\libs\zlib" /D "_DEBUG" /D "USE_WGL_SWAP" /D "DIRECTFULLSCREEN" /D "HAVE_SDL" /D "HWRENDER" /D "HAVE_FILTER" /D "HAVE_MIXER" /D "USEASM" /D "HAVE_PNG" /FR /FD /GZ /c +# ADD CPP /nologo /G6 /W4 /WX /Gm /GX /ZI /Od /Op /I "..\..\libs\libpng-src" /I "..\..\libs\zlib" /D "_DEBUG" /D "USE_WGL_SWAP" /D "HAVE_SDL" /D "HWRENDER" /D "HAVE_FILTER" /D "HAVE_MIXER" /D "USEASM" /D "HAVE_PNG" /FR /FD /GZ /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" diff --git a/src/sdl/Srb2SDL.props b/src/sdl/Srb2SDL.props index f02b9b35e..8c4799f20 100644 --- a/src/sdl/Srb2SDL.props +++ b/src/sdl/Srb2SDL.props @@ -6,9 +6,9 @@ - HAVE_ZLIB;HAVE_LIBGME;USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HAVE_FILTER;HAVE_MIXER;SDLMAIN;%(PreprocessorDefinitions) + HAVE_ZLIB;HAVE_LIBGME;USE_WGL_SWAP;HAVE_SDL;HWRENDER;HAVE_FILTER;HAVE_MIXER;SDLMAIN;%(PreprocessorDefinitions) - USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HAVE_FILTER;HAVE_MIXER;SDLMAIN;%(PreprocessorDefinitions) + USE_WGL_SWAP;HAVE_SDL;HWRENDER;HAVE_FILTER;HAVE_MIXER;SDLMAIN;%(PreprocessorDefinitions) diff --git a/src/st_stuff.c b/src/st_stuff.c index f5634423c..fade7c484 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -219,10 +219,6 @@ void ST_UnloadGraphics(void) void ST_LoadGraphics(void) { - // SRB2 border patch - //st_borderpatchnum = W_GetNumForName("GFZFLR01"); - //scr_borderpatch = W_CacheLumpNum(st_borderpatchnum, PU_HUDGFX); - // the original Doom uses 'STF' as base name for all face graphics // Graue 04-08-2004: face/name graphics are now indexed by skins // but load them in R_AddSkins, that gets called -- 2.54.0 From 9c014eb2eaadfc09f09251f6361b570d93c0cc4b Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 14 Oct 2025 22:43:58 +0200 Subject: [PATCH 074/219] delet gl_viewwidth, gl_viewheight, gl_baseviewwindowx, gl_baseviewwindowy gl_basewindowcenterx, gl_basewindowcentery they were effectively unused the last two werent ever even initialized to anything, using HWR_DrawViewBorder wouldve crashed --- src/hardware/hw_draw.c | 12 ++++++---- src/hardware/hw_main.cpp | 48 +++++++--------------------------------- src/hardware/hw_main.h | 4 ---- 3 files changed, 16 insertions(+), 48 deletions(-) diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 2b8ace584..1c014ce4c 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -649,6 +649,7 @@ void HWR_DrawConsoleBack(UINT32 color, INT32 height) // ------------------ void HWR_DrawViewBorder(INT32 clearlines) { +#if 0 INT32 x, y; INT32 top, side; INT32 baseviewwidth, baseviewheight; @@ -659,10 +660,10 @@ void HWR_DrawViewBorder(INT32 clearlines) clearlines = BASEVIDHEIGHT; // refresh all // calc view size based on original game resolution - baseviewwidth = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_viewwidth), vid.fdup)); //(cv_viewsize.value * BASEVIDWIDTH/10)&~7; - baseviewheight = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_viewheight), vid.fdup)); - top = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_baseviewwindowy), vid.fdup)); - side = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_baseviewwindowx), vid.fdup)); + baseviewwidth = FixedInt(FixedDiv(viewwidth * FRACUNIT, vid.fdup)); //(cv_viewsize.value * BASEVIDWIDTH/10)&~7; + baseviewheight = FixedInt(FixedDiv(viewheight * FRACUNIT, vid.fdup)); + top = FixedInt(FixedDiv(baseviewwindowy * FRACUNIT, vid.fdup)); + side = FixedInt(FixedDiv(baseviewwindowx * FRACUNIT, vid.fdup)); // top HWR_DrawFlatFill(0, 0, @@ -759,6 +760,9 @@ void HWR_DrawViewBorder(INT32 clearlines) PU_PATCH), basewindowx + baseviewwidth, basewindowy + baseviewheight, 0); +#else + (void)clearlines; +#endif } diff --git a/src/hardware/hw_main.cpp b/src/hardware/hw_main.cpp index c88b075a1..2b0799807 100644 --- a/src/hardware/hw_main.cpp +++ b/src/hardware/hw_main.cpp @@ -77,11 +77,6 @@ boolean gl_drawing_stencil = false; static INT32 current_bsp_culling_distance = 0; -// base values set at SetViewSize -float gl_baseviewwindowy, gl_baseviewwindowx; -static float gl_viewwindowy, gl_viewwindowx; // top left corner of view window -float gl_viewwidth, gl_viewheight; // viewport clipping boundaries (screen coords) - FTransform atransform; // Float variants of viewx, viewy, viewz, etc. @@ -5316,10 +5311,10 @@ static void HWR_DrawSkyBackground(void) // -----------------+ static inline void HWR_ClearView(void) { - GL_GClipRect((INT32)gl_viewwindowx, - (INT32)gl_viewwindowy, - (INT32)(gl_viewwindowx + gl_viewwidth), - (INT32)(gl_viewwindowy + gl_viewheight), + GL_GClipRect(viewwindowx, + viewwindowy, + (viewwindowx + viewwidth), + (viewwindowy + viewheight), ZCLIP_PLANE, FAR_ZCLIP_DEFAULT); GL_ClearBuffer(false, true, true, NULL); } @@ -5329,19 +5324,6 @@ static inline void HWR_ClearView(void) // -----------------+ void HWR_SetViewSize(void) { - // setup view size - gl_viewwidth = (float)vid.width; - gl_viewheight = (float)vid.height; - - if (splitscreen) - gl_viewheight /= 2; - - if (splitscreen > 1) - gl_viewwidth /= 2; - - gl_baseviewwindowy = 0; - gl_baseviewwindowx = 0; - GL_FlushScreenTextures(); } @@ -5594,20 +5576,6 @@ extern "C" { // ========================================================================== static void HWR_RenderFrame(player_t *player, boolean skybox) { - // set window position - gl_viewwindowx = gl_baseviewwindowx; - gl_viewwindowy = gl_baseviewwindowy; - - if ((splitscreen == 1 && viewssnum == 1) || (splitscreen > 1 && viewssnum > 1)) - { - gl_viewwindowy += gl_viewheight; - } - - if (splitscreen > 1 && viewssnum & 1) - { - gl_viewwindowx += gl_viewwidth; - } - // check for new console commands. NetUpdate(); @@ -5623,10 +5591,10 @@ static void HWR_RenderFrame(player_t *player, boolean skybox) if (!skybox && cv_glrenderdistance.value) { - GL_GClipRect((INT32)gl_viewwindowx, - (INT32)gl_viewwindowy, - (INT32)(gl_viewwindowx + gl_viewwidth), - (INT32)(gl_viewwindowy + gl_viewheight), + GL_GClipRect(viewwindowx, + viewwindowy, + (viewwindowx + viewwidth), + (viewwindowy + viewheight), ZCLIP_PLANE, clipping_distances[cv_glrenderdistance.value - 1]); current_bsp_culling_distance = bsp_culling_distances[cv_glrenderdistance.value - 1]; } diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 4060b6540..43a292c57 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -42,10 +42,6 @@ extern "C" { void HWR_Startup(void); void HWR_Shutdown(void); -extern float gl_viewwidth, gl_viewheight, gl_baseviewwindowx, gl_baseviewwindowy; - -extern float gl_basewindowcenterx, gl_basewindowcentery; - extern unsigned msaa; extern boolean a2c; -- 2.54.0 From a4684b30047589d0320f6ea7e26642f6c945bad7 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 14 Oct 2025 22:45:08 +0200 Subject: [PATCH 075/219] use stdlibs abs for CompareDrawNodePlanes we dont need our own abs for this --- src/hardware/hw_main.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/hardware/hw_main.cpp b/src/hardware/hw_main.cpp index 2b0799807..f9f11a474 100644 --- a/src/hardware/hw_main.cpp +++ b/src/hardware/hw_main.cpp @@ -65,8 +65,6 @@ // Globals // ========================================================================== -#define ABS(x) ((x) < 0 ? -(x) : (x)) - // false if shaders have not been initialized yet, or if shaders are not available boolean gl_shadersavailable = false; @@ -4330,7 +4328,7 @@ static int CompareDrawNodePlanes(const void *p1, const void *p2) const INT32 n1 = *(const INT32*)p1; const INT32 n2 = *(const INT32*)p2; - return ABS(drawnodes[n2].u.plane.fixedheight - viewz) - ABS(drawnodes[n1].u.plane.fixedheight - viewz); + return abs(drawnodes[n2].u.plane.fixedheight - viewz) - abs(drawnodes[n1].u.plane.fixedheight - viewz); } // -- 2.54.0 From 0eeacaf51ea2fc291b35159f02817bf5d6bbd6cb Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 14 Oct 2025 23:12:36 +0200 Subject: [PATCH 076/219] remove dead renderer code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit remove - broken viewborder code (if we really want it back for some reason, we should rather port RR´s fixed version of it) - remove console clipping code for software (this was broken eiherway) - remove hud message clearing stuff - remove renderscreen and linesize variables (they just pointed to vid.screen and vid.widht) --- src/Makefile.d/sdl.mk | 2 +- src/console.c | 31 ------- src/console.h | 5 -- src/d_main.c | 9 -- src/doomtype.h | 1 - src/hardware/hw_draw.c | 200 +---------------------------------------- src/hardware/hw_main.h | 2 - src/hu_stuff.c | 70 --------------- src/hu_stuff.h | 1 - src/i_video.h | 2 +- src/m_menu.c | 3 +- src/r_draw.cpp | 151 +------------------------------ src/r_draw.h | 34 +------ src/r_main.cpp | 2 - src/r_plane.cpp | 2 +- src/r_segs.cpp | 5 +- src/r_things.cpp | 2 - src/screen.c | 7 +- src/screen.h | 2 - src/sdl/Srb2SDL.dsp | 4 +- src/sdl/Srb2SDL.props | 4 +- src/st_stuff.c | 4 - 22 files changed, 15 insertions(+), 528 deletions(-) diff --git a/src/Makefile.d/sdl.mk b/src/Makefile.d/sdl.mk index c704a83eb..95fe34e6a 100644 --- a/src/Makefile.d/sdl.mk +++ b/src/Makefile.d/sdl.mk @@ -10,7 +10,7 @@ makedir:=$(makedir)/SDL -opts+=-DDIRECTFULLSCREEN -DHAVE_SDL +opts+=-DHAVE_SDL sources+=$(call List,sdl/Sourcefile) NOUPNP=1 diff --git a/src/console.c b/src/console.c index fe91df0f3..3959d9b98 100644 --- a/src/console.c +++ b/src/console.c @@ -69,14 +69,9 @@ static boolean consoleready; // console prompt is ready INT32 con_destlines; // vid lines used by console at final position static INT32 con_curlines; // vid lines currently used by console - INT32 con_clipviewtop; // (useless) - static UINT8 con_hudlines; // number of console heads up message lines static UINT32 con_hudtime[MAXHUDLINES]; // remaining time of display for hud msg lines - INT32 con_clearlines; // top screen lines to refresh when view reduced - boolean con_hudupdate; // when messages scroll, we need a backgrnd refresh - // console text output static char *con_line; // console text output current line static size_t con_cx; // cursor position in current line @@ -393,9 +388,6 @@ void CON_Init(void) Lock_state(); - //note: CON_Ticker should always execute at least once before D_Display() - con_clipviewtop = -1; // -1 does not clip - con_hudlines = atoi(cons_hudlines.defaultvalue); Unlock_state(); @@ -727,7 +719,6 @@ void CON_ToggleOff(void) con_curlines = 0; CON_ClearHUD(); con_forcepic = 0; - con_clipviewtop = -1; // remove console clipping of view I_SetTextInput(false); @@ -779,18 +770,6 @@ void CON_Ticker(void) } } - // clip the view, so that the part under the console is not drawn - con_clipviewtop = -1; - if (cons_backpic.value) // clip only when using an opaque background - { - if (con_curlines > 0) - con_clipviewtop = con_curlines - viewwindowy - 1 - 10; - // NOTE: BIG HACK::SUBTRACT 10, SO THAT WATER DON'T COPY LINES OF THE CONSOLE - // WINDOW!!! (draw some more lines behind the bottom of the console) - if (con_clipviewtop < 0) - con_clipviewtop = -1; // maybe not necessary, provided it's < 0 - } - // check if console ready for prompt if (con_destlines >= minheight) { @@ -1100,9 +1079,6 @@ static void CON_Linefeed(void) con_line = &con_buffer[(con_cy%con_totallines)*con_width]; memset(con_line, ' ', con_width); - - // make sure the view borders are refreshed if hud messages scroll - con_hudupdate = true; // see HU_Erase() } // Outputs text into the console text buffer @@ -1489,9 +1465,6 @@ static void CON_DrawHudlines(void) //V_DrawCharacter(x, y, (p[c]&0xff) | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value); y += charheight; } - - // top screen lines that might need clearing when view is reduced - con_clearlines = y; // this is handled by HU_Erase(); } // draw the console background, text, and prompt if enough place @@ -1509,10 +1482,6 @@ static void CON_DrawConsole(void) if (con_curlines <= 0) return; - //FIXME: refresh borders only when console bg is translucent - con_clearlines = con_curlines; // clear console draw from view borders - con_hudupdate = true; // always refresh while console is on - // draw console background if (cons_backpic.value || con_forcepic) { diff --git a/src/console.h b/src/console.h index e704a87f1..79af2e48f 100644 --- a/src/console.h +++ b/src/console.h @@ -30,14 +30,9 @@ extern boolean con_recalc; extern boolean con_startup; -// top clip value for view render: do not draw part of view hidden by console -extern INT32 con_clipviewtop; - // 0 means console if off, or moving out extern INT32 con_destlines; -extern INT32 con_clearlines; // lines of top of screen to refresh -extern boolean con_hudupdate; // hud messages have changed, need refresh extern UINT32 con_scalefactor; // console text scale factor extern consvar_t cons_backcolor, cons_menuhighlight; diff --git a/src/d_main.c b/src/d_main.c index dd13c7b77..33dc57689 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -522,19 +522,16 @@ static boolean D_Display(void) case GS_LEVEL: if (!gametic) break; - HU_Erase(); AM_Drawer(); break; case GS_INTERMISSION: Y_IntermissionDrawer(); - HU_Erase(); HU_Drawer(); break; case GS_VOTING: Y_VoteDrawer(); - HU_Erase(); HU_Drawer(); break; @@ -549,7 +546,6 @@ static boolean D_Display(void) case GS_CUTSCENE: F_CutsceneDrawer(); - HU_Erase(); HU_Drawer(); break; @@ -559,7 +555,6 @@ static boolean D_Display(void) case GS_EVALUATION: F_GameEvaluationDrawer(); - HU_Erase(); HU_Drawer(); break; @@ -569,7 +564,6 @@ static boolean D_Display(void) case GS_CREDITS: F_CreditDrawer(); - HU_Erase(); HU_Drawer(); break; @@ -586,7 +580,6 @@ static boolean D_Display(void) { // I don't think HOM from nothing drawing is independent... F_WaitingPlayersDrawer(); - HU_Erase(); HU_Drawer(); } case GS_TIMEATTACK: @@ -1925,9 +1918,7 @@ void D_SRB2Main(void) G_LoadGameData(); -#if defined (__unix__) || defined (UNIXCOMMON) || defined (HAVE_SDL) VID_PrepareModeList(); // Regenerate Modelist according to cv_fullscreen -#endif // set user default mode or mode set at cmdline SCR_CheckDefaultMode(); diff --git a/src/doomtype.h b/src/doomtype.h index 81c09c007..78867ed69 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -43,7 +43,6 @@ extern "C" { #define UINT64 uint64_t #ifdef __APPLE_CC__ -#define DIRECTFULLSCREEN 1 #define DEBUG_LOG #define NOIPX #endif diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 1c014ce4c..cf8ab29e3 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -31,11 +31,6 @@ #include "../st_stuff.h" #include -#include "../i_video.h" // for rendermode != render_glide - -#ifndef O_BINARY -#define O_BINARY 0 -#endif typedef struct { @@ -58,68 +53,6 @@ static UINT8 softwaretranstogl_lo[11] = { 0, 12, 24, 36, 48, 60, 71, 83, 95,111 static const float FLOATBASEVIDWIDTH = (float)BASEVIDWIDTH; static const float FLOATBASEVIDHEIGHT = (float)BASEVIDHEIGHT; -// -// -----------------+ -// HWR_DrawPatch : Draw a 'tile' graphic -// Notes : x,y : positions relative to the original Doom resolution -// : textes(console+score) + menus + status bar -// -----------------+ -void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option) -{ - FOutVector v[4]; - FBITFIELD flags; - GLPatch_t *hwrPatch; - -// 3--2 -// | /| -// |/ | -// 0--1 - float sdup = FIXED_TO_FLOAT(vid.fdup)*2.0f; - float pdup = FIXED_TO_FLOAT(vid.fdup)*2.0f; - - // make patch ready in hardware cache - HWR_GetPatch(gpatch); - hwrPatch = ((GLPatch_t *)gpatch->hardware); - - switch (option & V_SCALEPATCHMASK) - { - case V_NOSCALEPATCH: - pdup = 2.0f; - break; - case V_SMALLSCALEPATCH: - pdup = 2.0f * FIXED_TO_FLOAT(vid.smalldup*FRACUNIT); - break; - case V_MEDSCALEPATCH: - pdup = 2.0f * FIXED_TO_FLOAT(vid.meddup*FRACUNIT); - break; - } - - if (option & V_NOSCALESTART) - sdup = 2.0f; - - v[0].x = v[3].x = (x*sdup-gpatch->leftoffset*pdup)/vid.width - 1; - v[2].x = v[1].x = (x*sdup+(gpatch->width - gpatch->leftoffset)*pdup)/vid.width - 1; - v[0].y = v[1].y = 1-(y*sdup-gpatch->topoffset*pdup)/vid.height; - v[2].y = v[3].y = 1-(y*sdup+(gpatch->height - gpatch->topoffset)*pdup)/vid.height; - - v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - - v[0].s = v[3].s = 0.0f; - v[2].s = v[1].s = hwrPatch->max_s; - v[0].t = v[1].t = 0.0f; - v[2].t = v[3].t = hwrPatch->max_t; - - flags = PF_Translucent|PF_NoDepthTest; - - if (option & V_WRAPX) - flags |= PF_ForceWrapX; - if (option & V_WRAPY) - flags |= PF_ForceWrapY; - - // clip it since it is used for bunny scroll in doom I - GL_DrawPolygon(NULL, v, 4, flags); -} - void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap, INT32 bflags) { FOutVector v[4]; @@ -636,137 +569,6 @@ void HWR_DrawConsoleBack(UINT32 color, INT32 height) } -// ========================================================================== -// R_DRAW.C STUFF -// ========================================================================== - -// ------------------ -// HWR_DrawViewBorder -// Fill the space around the view window with a Doom flat texture, draw the -// beveled edges. -// 'clearlines' is useful to clear the heads up messages, when the view -// window is reduced, it doesn't refresh all the view borders. -// ------------------ -void HWR_DrawViewBorder(INT32 clearlines) -{ -#if 0 - INT32 x, y; - INT32 top, side; - INT32 baseviewwidth, baseviewheight; - INT32 basewindowx, basewindowy; - patch_t *patch; - - if (!clearlines) - clearlines = BASEVIDHEIGHT; // refresh all - - // calc view size based on original game resolution - baseviewwidth = FixedInt(FixedDiv(viewwidth * FRACUNIT, vid.fdup)); //(cv_viewsize.value * BASEVIDWIDTH/10)&~7; - baseviewheight = FixedInt(FixedDiv(viewheight * FRACUNIT, vid.fdup)); - top = FixedInt(FixedDiv(baseviewwindowy * FRACUNIT, vid.fdup)); - side = FixedInt(FixedDiv(baseviewwindowx * FRACUNIT, vid.fdup)); - - // top - HWR_DrawFlatFill(0, 0, - BASEVIDWIDTH, (top < clearlines ? top : clearlines), - st_borderpatchnum); - - // left - if (top < clearlines) - HWR_DrawFlatFill(0, top, side, - (clearlines-top < baseviewheight ? clearlines-top : baseviewheight), - st_borderpatchnum); - - // right - if (top < clearlines) - HWR_DrawFlatFill(side + baseviewwidth, top, side, - (clearlines-top < baseviewheight ? clearlines-top : baseviewheight), - st_borderpatchnum); - - // bottom - if (top + baseviewheight < clearlines) - HWR_DrawFlatFill(0, top + baseviewheight, - BASEVIDWIDTH, BASEVIDHEIGHT, st_borderpatchnum); - - // - // draw the view borders - // - - basewindowx = (BASEVIDWIDTH - baseviewwidth)>>1; - if (baseviewwidth == BASEVIDWIDTH) - basewindowy = 0; - else - basewindowy = top; - - // top edge - if (clearlines > basewindowy - 8) - { - patch = W_CachePatchNum(viewborderlump[BRDR_T], PU_PATCH); - for (x = 0; x < baseviewwidth; x += 8) - HWR_DrawPatch(patch, basewindowx + x, basewindowy - 8, - 0); - } - - // bottom edge - if (clearlines > basewindowy + baseviewheight) - { - patch = W_CachePatchNum(viewborderlump[BRDR_B], PU_PATCH); - for (x = 0; x < baseviewwidth; x += 8) - HWR_DrawPatch(patch, basewindowx + x, - basewindowy + baseviewheight, 0); - } - - // left edge - if (clearlines > basewindowy) - { - patch = W_CachePatchNum(viewborderlump[BRDR_L], PU_PATCH); - for (y = 0; y < baseviewheight && basewindowy + y < clearlines; - y += 8) - { - HWR_DrawPatch(patch, basewindowx - 8, basewindowy + y, - 0); - } - } - - // right edge - if (clearlines > basewindowy) - { - patch = W_CachePatchNum(viewborderlump[BRDR_R], PU_PATCH); - for (y = 0; y < baseviewheight && basewindowy+y < clearlines; - y += 8) - { - HWR_DrawPatch(patch, basewindowx + baseviewwidth, - basewindowy + y, 0); - } - } - - // Draw beveled corners. - if (clearlines > basewindowy - 8) - HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_TL], - PU_PATCH), - basewindowx - 8, basewindowy - 8, 0); - - if (clearlines > basewindowy - 8) - HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_TR], - PU_PATCH), - basewindowx + baseviewwidth, basewindowy - 8, 0); - - if (clearlines > basewindowy+baseviewheight) - HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_BL], - PU_PATCH), - basewindowx - 8, basewindowy + baseviewheight, 0); - - if (clearlines > basewindowy + baseviewheight) - HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_BR], - PU_PATCH), - basewindowx + baseviewwidth, - basewindowy + baseviewheight, 0); -#else - (void)clearlines; -#endif -} - - - // ========================================================================== // AM_MAP.C DRAWING STUFF // ========================================================================== @@ -1172,7 +974,7 @@ static inline boolean saveTGA(const char *file_name, void *buffer, INT32 i; UINT8 *buf8 = buffer; - fd = open(file_name, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); + fd = open(file_name, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd < 0) return false; diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 43a292c57..30906b611 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -85,7 +85,6 @@ extern ps_metric_t ps_hw_batchdrawtime; extern boolean gl_shadersavailable; // hw_draw.c -void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option); void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap, INT32 bflags); void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h); void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color); @@ -94,7 +93,6 @@ void HWR_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 color); void HWR_drawAMline(const fline_t *fl, INT32 color); void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength); void HWR_DrawConsoleBack(UINT32 color, INT32 height); -void HWR_DrawViewBorder(INT32 clearlines); void HWR_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum); UINT8 *HWR_GetScreenshot(INT32 scale); diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 6ca275aff..fa7060dff 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2391,76 +2391,6 @@ void HU_Drawer(void) } } -//====================================================================== -// HUD MESSAGES CLEARING FROM SCREEN -//====================================================================== - -// Clear old messages from the borders around the view window -// (only for reduced view, refresh the borders when needed) -// -// startline: y coord to start clear, -// clearlines: how many lines to clear. -// -static INT32 oldclearlines; - -void HU_Erase(void) -{ - INT32 topline, bottomline; - INT32 y, yoffset; - -#ifdef HWRENDER - // clear hud msgs on double buffer (OpenGL mode) - boolean secondframe; - static INT32 secondframelines; -#endif - - if (con_clearlines == oldclearlines && !con_hudupdate && !chat_on) - return; - -#ifdef HWRENDER - // clear the other frame in double-buffer modes - secondframe = (con_clearlines != oldclearlines); - if (secondframe) - secondframelines = oldclearlines; -#endif - - // clear the message lines that go away, so use _oldclearlines_ - bottomline = oldclearlines; - oldclearlines = con_clearlines; - if (chat_on && OLDCHAT) - if (bottomline < 8) - bottomline = 8; // only do it for consolechat. consolechat is gay. - - if (automapactive || viewwindowx == 0) // hud msgs don't need to be cleared - return; - - // software mode copies view border pattern & beveled edges from the backbuffer - if (rendermode == render_soft) - { - topline = 0; - for (y = topline, yoffset = y*vid.width; y < bottomline; y++, yoffset += vid.width) - { - if (y < viewwindowy || y >= viewwindowy + viewheight) - R_VideoErase(yoffset, vid.width); // erase entire line - else - { - R_VideoErase(yoffset, viewwindowx); // erase left border - // erase right border - R_VideoErase(yoffset + viewwindowx + viewwidth, viewwindowx); - } - } - con_hudupdate = false; // if it was set.. - } -#ifdef HWRENDER - else if (rendermode != render_none) - { - // refresh just what is needed from the view borders - HWR_DrawViewBorder(secondframelines); - con_hudupdate = secondframe; - } -#endif -} - //====================================================================== // IN-LEVEL MULTIPLAYER RANKINGS //====================================================================== diff --git a/src/hu_stuff.h b/src/hu_stuff.h index d134f319e..64d369a33 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -117,7 +117,6 @@ void HU_TickSongCredits(void); void HU_DrawSongCredits(void); void HU_Drawer(void); char HU_dequeueChatChar(void); -void HU_Erase(void); void HU_clearChatChars(void); void HU_drawPlayerPing(INT32 x, INT32 y, INT32 pnum, INT32 flags); // Lat': Ping drawer for scoreboard. //void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer); diff --git a/src/i_video.h b/src/i_video.h index 822a1bada..852645c30 100644 --- a/src/i_video.h +++ b/src/i_video.h @@ -94,8 +94,8 @@ INT32 VID_SetMode(INT32 modenum); \return name of video mode */ const char *VID_GetModeName(INT32 modenum); -void VID_PrepareModeList(void); /// note hack for SDL +void VID_PrepareModeList(void); /** \brief can video system do fullscreen */ diff --git a/src/m_menu.c b/src/m_menu.c index 95824c7dd..ed39e053f 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -9442,9 +9442,8 @@ static void M_VideoModeMenu(INT32 choice) memset(modedescs, 0, sizeof(modedescs)); -#if defined (__unix__) || defined (UNIXCOMMON) || defined (HAVE_SDL) VID_PrepareModeList(); // FIXME: hack -#endif + vidm_nummodes = 0; vidm_selected = 0; nummodes = VID_NumModes(); diff --git a/src/r_draw.cpp b/src/r_draw.cpp index 288cf462d..e5596e4c8 100644 --- a/src/r_draw.cpp +++ b/src/r_draw.cpp @@ -41,8 +41,7 @@ /** \brief view info */ -INT32 linesize, viewwidth, viewheight, viewwindowx, viewwindowy; -UINT8 *renderscreen; // haleyjd +INT32 viewwidth, viewheight, viewwindowx, viewwindowy; // ========================================================================= // COLUMN DRAWING CODE STUFF @@ -607,7 +606,6 @@ static void R_AllocViewMemory(void) R_AllocVisSpriteMemory(); } - void R_InitViewBuffer(INT32 width, INT32 height) { if (width > MAXVIDWIDTH) @@ -620,10 +618,7 @@ void R_InitViewBuffer(INT32 width, INT32 height) viewwindowx = 0; viewwindowy = 0; - linesize = vid.width; // killough 11/98 - renderscreen = vid.screens[0]; // haleyjd 07/02/14 - - INT32 bufsize = (linesize * 8) * sizeof(*temp_dc.buf); + INT32 bufsize = (vid.width * 8) * sizeof(*temp_dc.buf); if (temp_dc.buf) { @@ -645,25 +640,6 @@ void R_InitViewBuffer(INT32 width, INT32 height) #endif } -/** \brief viewborder patches lump numbers -*/ -lumpnum_t viewborderlump[8]; - -/** \brief Store the lumpnumber of the viewborder patches -*/ - -void R_InitViewBorder(void) -{ - viewborderlump[BRDR_T] = W_GetNumForName("brdr_t"); - viewborderlump[BRDR_B] = W_GetNumForName("brdr_b"); - viewborderlump[BRDR_L] = W_GetNumForName("brdr_l"); - viewborderlump[BRDR_R] = W_GetNumForName("brdr_r"); - viewborderlump[BRDR_TL] = W_GetNumForName("brdr_tl"); - viewborderlump[BRDR_BL] = W_GetNumForName("brdr_bl"); - viewborderlump[BRDR_TR] = W_GetNumForName("brdr_tr"); - viewborderlump[BRDR_BR] = W_GetNumForName("brdr_br"); -} - /** \brief The R_VideoErase function Copy a screen buffer. @@ -685,129 +661,6 @@ void R_VideoErase(size_t ofs, INT32 count) M_Memcpy(vid.screens[0] + ofs, vid.screens[1] + ofs, count); } - -#if 0 -/** \brief R_FillBackScreen - - Fills the back screen with a pattern for variable screen sizes - Also draws a beveled edge. -*/ -void R_FillBackScreen(void) -{ - UINT8 *src, *dest; - patch_t *patch; - INT32 x, y, step, boff; - - // quickfix, don't cache lumps in both modes - if (rendermode != render_soft) - return; - - // draw pattern around the status bar too (when hires), - // so return only when in full-screen without status bar. - if (scaledviewwidth == vid.width && viewheight == vid.height) - return; - - src = scr_borderpatch; - dest = vid.screens[1]; - - for (y = 0; y < vid.height; y++) - { - for (x = 0; x < vid.width/128; x++) - { - M_Memcpy (dest, src+((y&127)<<7), 128); - dest += 128; - } - - if (vid.width&127) - { - M_Memcpy(dest, src+((y&127)<<7), vid.width&127); - dest += (vid.width&127); - } - } - - // don't draw the borders when viewwidth is full vid.width. - if (scaledviewwidth == vid.width) - return; - - step = 8; - boff = 8; - - patch = W_CacheLumpNum(viewborderlump[BRDR_T], PU_CACHE); - for (x = 0; x < scaledviewwidth; x += step) - V_DrawPatch(viewwindowx + x, viewwindowy - boff, 1, patch); - - patch = W_CacheLumpNum(viewborderlump[BRDR_B], PU_CACHE); - for (x = 0; x < scaledviewwidth; x += step) - V_DrawPatch(viewwindowx + x, viewwindowy + viewheight, 1, patch); - - patch = W_CacheLumpNum(viewborderlump[BRDR_L], PU_CACHE); - for (y = 0; y < viewheight; y += step) - V_DrawPatch(viewwindowx - boff, viewwindowy + y, 1, patch); - - patch = W_CacheLumpNum(viewborderlump[BRDR_R],PU_CACHE); - for (y = 0; y < viewheight; y += step) - V_DrawPatch(viewwindowx + scaledviewwidth, viewwindowy + y, 1, - patch); - - // Draw beveled corners. - V_DrawPatch(viewwindowx - boff, viewwindowy - boff, 1, - W_CacheLumpNum(viewborderlump[BRDR_TL], PU_CACHE)); - V_DrawPatch(viewwindowx + scaledviewwidth, viewwindowy - boff, 1, - W_CacheLumpNum(viewborderlump[BRDR_TR], PU_CACHE)); - V_DrawPatch(viewwindowx - boff, viewwindowy + viewheight, 1, - W_CacheLumpNum(viewborderlump[BRDR_BL], PU_CACHE)); - V_DrawPatch(viewwindowx + scaledviewwidth, viewwindowy + viewheight, 1, - W_CacheLumpNum(viewborderlump[BRDR_BR], PU_CACHE)); -} - -/** \brief The R_DrawViewBorder - - Draws the border around the view - for different size windows? -*/ -void R_DrawViewBorder(void) -{ - INT32 top, side, ofs; - - if (rendermode == render_none) - return; -#ifdef HWRENDER - if (rendermode != render_soft) - { - HWR_DrawViewBorder(0); - return; - } - else -#endif - -#ifdef DEBUG - fprintf(stderr,"RDVB: vidwidth %d vidheight %d scaledviewwidth %d viewheight %d\n", - vid.width, vid.height, scaledviewwidth, viewheight); -#endif - - if (scaledviewwidth == vid.width) - return; - - top = (vid.height - viewheight)>>1; - side = (vid.width - scaledviewwidth)>>1; - - // copy top and one line of left side - R_VideoErase(0, top*vid.width+side); - - // copy one line of right side and bottom - ofs = (viewheight+top)*vid.width - side; - R_VideoErase(ofs, top*vid.width + side); - - // copy sides using wraparound - ofs = top*vid.width + vid.width-side; - side <<= 1; - - // simpler using our VID_Blit routine - VID_BlitLinearScreen(vid.screens[1] + ofs, vid.screens[0] + ofs, side, viewheight - 1, - vid.width, vid.width); -} -#endif - // ========================================================================== // INCLUDE DRAWING CODE HERE // ========================================================================== diff --git a/src/r_draw.h b/src/r_draw.h index ae9d2ef40..cd1356522 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -25,12 +25,10 @@ extern "C" { // ------------------------------- // COMMON STUFF FOR 8bpp AND 16bpp // ------------------------------- -extern UINT8 *renderscreen; -extern INT32 linesize; FUNCINLINE static ATTRINLINE UINT8 *R_Address(INT32 px, INT32 py) { - return renderscreen + (py + viewwindowy) * linesize + (viewwindowx + px); + return vid.screens[0] + (py + viewwindowy) * vid.width + (viewwindowx + px); } @@ -162,27 +160,8 @@ extern spandrawfunc_t *spanfuncs[SPANDRAWFUNC_MAX]; void R_DrawMaskedColumn(drawcolumndata_t* dc, column_t *column); -/// \brief Top border -#define BRDR_T 0 -/// \brief Bottom border -#define BRDR_B 1 -/// \brief Left border -#define BRDR_L 2 -/// \brief Right border -#define BRDR_R 3 -/// \brief Topleft border -#define BRDR_TL 4 -/// \brief Topright border -#define BRDR_TR 5 -/// \brief Bottomleft border -#define BRDR_BL 6 -/// \brief Bottomright border -#define BRDR_BR 7 - -extern lumpnum_t viewborderlump[8]; - // ------------------------------------------------ -// r_draw.c COMMON ROUTINES FOR BOTH 8bpp and 16bpp +// r_draw.c // ------------------------------------------------ #define GTC_CACHE 1 @@ -231,17 +210,8 @@ boolean R_BlendLevelVisible(INT32 blendmode, INT32 alphalevel); // Custom player skin translation void R_InitViewBuffer(INT32 width, INT32 height); -void R_InitViewBorder(void); void R_VideoErase(size_t ofs, INT32 count); -// Rendering function. -#if 0 -void R_FillBackScreen(void); - -// If the view size is not full screen, draws a border around it. -void R_DrawViewBorder(void); -#endif - #define TRANSPARENTPIXEL 247 // ----------------- diff --git a/src/r_main.cpp b/src/r_main.cpp index 88435ba93..37cfed8c5 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1023,8 +1023,6 @@ void R_Init(void) //I_OutputMsg("\nR_InitData"); R_InitData(); - //I_OutputMsg("\nR_InitViewBorder"); - R_InitViewBorder(); R_SetViewSize(); // setsizeneeded is set true // this is now done by SCR_Recalc() at the first mode set diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 435365f12..f4eb61410 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -784,7 +784,7 @@ static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), b drawcolumndata_t dc = {}; const INT32 texture = texturetranslation[skytexture]; - // Reset column drawer function (note: couldn't we just call walldrawerfunc directly?) + // Reset column drawer function (note: couldn't we just call colfuncs[BASEDRAWFUNC] directly?) // (that is, unless we'll need to switch drawers in future for some reason) R_SetColumnFunc(BASEDRAWFUNC); diff --git a/src/r_segs.cpp b/src/r_segs.cpp index c83b45593..b4f8cdbcd 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -26,7 +26,6 @@ #include "p_local.h" // Camera... #include "p_setup.h" #include "p_slopes.h" -#include "console.h" // con_clipviewtop #include "screen.h" #include "core/memory.h" @@ -628,8 +627,6 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf sector_t tempsec; INT32 templight; INT32 i, p; - fixed_t bottombounds = viewheight << FRACBITS; - fixed_t topbounds = (con_clipviewtop - 1) << FRACBITS; fixed_t offsetvalue = 0; lightlist_t *light; r_lightlist_t *rlight; @@ -936,7 +933,7 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf bottom_frac += bottom_step; // SoM: If column is out of range, why bother with it?? - if (windowbottom < topbounds || windowtop > bottombounds) + if (windowbottom < 0 || windowtop > (viewheight << FRACBITS)) { if (dc->numlights) { diff --git a/src/r_things.cpp b/src/r_things.cpp index a5ba974ba..673fdfc6c 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -2518,8 +2518,6 @@ void R_InitDrawNodes(void) // R_DrawSprite // //Fab : 26-04-98: -// NOTE : uses con_clipviewtop, so that when console is on, -// don't draw the part of sprites hidden under the console static void R_DrawSprite(vissprite_t *spr) { mfloorclip = spr->clipbot; diff --git a/src/screen.c b/src/screen.c index c298b0b75..78cfefd4f 100644 --- a/src/screen.c +++ b/src/screen.c @@ -80,10 +80,6 @@ consvar_t cv_accuratefps = {"fpssampling", "1", CV_SAVE, accuratefps_cons_t, NUL // SCREEN VARIABLES // ========================================================================= -UINT8 *scr_borderpatch; // flat used to fill the reduced view borders set at ST_Init() - -// ========================================================================= - static void SCR_SetDrawFuncs(enum columncontext_e _columncontext) { // @@ -323,7 +319,6 @@ void SCR_SetDefaultMode(void) // Change fullscreen on/off according to cv_fullscreen void SCR_ChangeFullscreen(void) { -#ifdef DIRECTFULLSCREEN I_SetBorderlessWindow(); // Running this here so we can have borderless window at startup // allow_fullscreen is set by VID_PrepareModeList @@ -336,8 +331,8 @@ void SCR_ChangeFullscreen(void) VID_PrepareModeList(); setmodeneeded = VID_GetModeForSize(vid.width, vid.height) + 1; } + return; -#endif } boolean SCR_IsAspectCorrect(INT32 width, INT32 height) diff --git a/src/screen.h b/src/screen.h index 8cd90c23a..0a912e97a 100644 --- a/src/screen.h +++ b/src/screen.h @@ -84,8 +84,6 @@ enum extern viddef_t vid; extern INT32 setmodeneeded; // mode number to set if needed, or 0 -extern UINT8 *scr_borderpatch; // patch used to fill the view borders - extern consvar_t cv_scr_width, cv_scr_height, cv_renderview, cv_frameskip, cv_fullscreen, cv_vhseffect, cv_shittyscreen; extern consvar_t cv_parallelsoftware; extern consvar_t cv_paralleldrawmasked; diff --git a/src/sdl/Srb2SDL.dsp b/src/sdl/Srb2SDL.dsp index 47ede4126..96d3e8418 100644 --- a/src/sdl/Srb2SDL.dsp +++ b/src/sdl/Srb2SDL.dsp @@ -45,7 +45,7 @@ MTL=midl.exe # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /G5 /W3 /GX /Zi /Ot /Og /Oi /Op /Oy /Ob1 /I "..\..\libs\libpng-src" /I "..\..\libs\zlib" /D "NDEBUG" /D "SDLMAIN" /D "NO_STDIO_REDIRECT" /D "USE_WGL_SWAP" /D "DIRECTFULLSCREEN" /D "HAVE_SDL" /D "HWRENDER" /D "HAVE_FILTER" /D "HAVE_MIXER" /D "USEASM" /D "HAVE_PNG" /FR /FD /GF /c +# ADD CPP /nologo /G5 /W3 /GX /Zi /Ot /Og /Oi /Op /Oy /Ob1 /I "..\..\libs\libpng-src" /I "..\..\libs\zlib" /D "NDEBUG" /D "SDLMAIN" /D "NO_STDIO_REDIRECT" /D "USE_WGL_SWAP" /D "HAVE_SDL" /D "HWRENDER" /D "HAVE_FILTER" /D "HAVE_MIXER" /D "USEASM" /D "HAVE_PNG" /FR /FD /GF /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" # SUBTRACT RSC /x @@ -72,7 +72,7 @@ LINK32=link.exe # PROP Target_Dir "" MTL=midl.exe # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /G6 /W4 /WX /Gm /GX /ZI /Od /Op /I "..\..\libs\libpng-src" /I "..\..\libs\zlib" /D "_DEBUG" /D "USE_WGL_SWAP" /D "DIRECTFULLSCREEN" /D "HAVE_SDL" /D "HWRENDER" /D "HAVE_FILTER" /D "HAVE_MIXER" /D "USEASM" /D "HAVE_PNG" /FR /FD /GZ /c +# ADD CPP /nologo /G6 /W4 /WX /Gm /GX /ZI /Od /Op /I "..\..\libs\libpng-src" /I "..\..\libs\zlib" /D "_DEBUG" /D "USE_WGL_SWAP" /D "HAVE_SDL" /D "HWRENDER" /D "HAVE_FILTER" /D "HAVE_MIXER" /D "USEASM" /D "HAVE_PNG" /FR /FD /GZ /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" diff --git a/src/sdl/Srb2SDL.props b/src/sdl/Srb2SDL.props index f02b9b35e..8c4799f20 100644 --- a/src/sdl/Srb2SDL.props +++ b/src/sdl/Srb2SDL.props @@ -6,9 +6,9 @@ - HAVE_ZLIB;HAVE_LIBGME;USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HAVE_FILTER;HAVE_MIXER;SDLMAIN;%(PreprocessorDefinitions) + HAVE_ZLIB;HAVE_LIBGME;USE_WGL_SWAP;HAVE_SDL;HWRENDER;HAVE_FILTER;HAVE_MIXER;SDLMAIN;%(PreprocessorDefinitions) - USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HAVE_FILTER;HAVE_MIXER;SDLMAIN;%(PreprocessorDefinitions) + USE_WGL_SWAP;HAVE_SDL;HWRENDER;HAVE_FILTER;HAVE_MIXER;SDLMAIN;%(PreprocessorDefinitions) diff --git a/src/st_stuff.c b/src/st_stuff.c index f5634423c..fade7c484 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -219,10 +219,6 @@ void ST_UnloadGraphics(void) void ST_LoadGraphics(void) { - // SRB2 border patch - //st_borderpatchnum = W_GetNumForName("GFZFLR01"); - //scr_borderpatch = W_CacheLumpNum(st_borderpatchnum, PU_HUDGFX); - // the original Doom uses 'STF' as base name for all face graphics // Graue 04-08-2004: face/name graphics are now indexed by skins // but load them in R_AddSkins, that gets called -- 2.54.0 From dd9d6de0d661a2e235ce20b474a627dfc76038c8 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 14 Oct 2025 22:43:58 +0200 Subject: [PATCH 077/219] delet gl_viewwidth, gl_viewheight, gl_baseviewwindowx, gl_baseviewwindowy gl_basewindowcenterx, gl_basewindowcentery they were effectively unused --- src/hardware/hw_draw.c | 12 ++++++---- src/hardware/hw_main.cpp | 48 +++++++--------------------------------- src/hardware/hw_main.h | 4 ---- 3 files changed, 16 insertions(+), 48 deletions(-) diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 2b8ace584..1c014ce4c 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -649,6 +649,7 @@ void HWR_DrawConsoleBack(UINT32 color, INT32 height) // ------------------ void HWR_DrawViewBorder(INT32 clearlines) { +#if 0 INT32 x, y; INT32 top, side; INT32 baseviewwidth, baseviewheight; @@ -659,10 +660,10 @@ void HWR_DrawViewBorder(INT32 clearlines) clearlines = BASEVIDHEIGHT; // refresh all // calc view size based on original game resolution - baseviewwidth = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_viewwidth), vid.fdup)); //(cv_viewsize.value * BASEVIDWIDTH/10)&~7; - baseviewheight = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_viewheight), vid.fdup)); - top = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_baseviewwindowy), vid.fdup)); - side = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_baseviewwindowx), vid.fdup)); + baseviewwidth = FixedInt(FixedDiv(viewwidth * FRACUNIT, vid.fdup)); //(cv_viewsize.value * BASEVIDWIDTH/10)&~7; + baseviewheight = FixedInt(FixedDiv(viewheight * FRACUNIT, vid.fdup)); + top = FixedInt(FixedDiv(baseviewwindowy * FRACUNIT, vid.fdup)); + side = FixedInt(FixedDiv(baseviewwindowx * FRACUNIT, vid.fdup)); // top HWR_DrawFlatFill(0, 0, @@ -759,6 +760,9 @@ void HWR_DrawViewBorder(INT32 clearlines) PU_PATCH), basewindowx + baseviewwidth, basewindowy + baseviewheight, 0); +#else + (void)clearlines; +#endif } diff --git a/src/hardware/hw_main.cpp b/src/hardware/hw_main.cpp index 2ccb3f6d9..88584a9da 100644 --- a/src/hardware/hw_main.cpp +++ b/src/hardware/hw_main.cpp @@ -77,11 +77,6 @@ boolean gl_drawing_stencil = false; static INT32 current_bsp_culling_distance = 0; -// base values set at SetViewSize -float gl_baseviewwindowy, gl_baseviewwindowx; -static float gl_viewwindowy, gl_viewwindowx; // top left corner of view window -float gl_viewwidth, gl_viewheight; // viewport clipping boundaries (screen coords) - FTransform atransform; // Float variants of viewx, viewy, viewz, etc. @@ -5316,10 +5311,10 @@ static void HWR_DrawSkyBackground(void) // -----------------+ static inline void HWR_ClearView(void) { - GL_GClipRect((INT32)gl_viewwindowx, - (INT32)gl_viewwindowy, - (INT32)(gl_viewwindowx + gl_viewwidth), - (INT32)(gl_viewwindowy + gl_viewheight), + GL_GClipRect(viewwindowx, + viewwindowy, + (viewwindowx + viewwidth), + (viewwindowy + viewheight), ZCLIP_PLANE, FAR_ZCLIP_DEFAULT); GL_ClearBuffer(false, true, true, NULL); } @@ -5329,19 +5324,6 @@ static inline void HWR_ClearView(void) // -----------------+ void HWR_SetViewSize(void) { - // setup view size - gl_viewwidth = (float)vid.width; - gl_viewheight = (float)vid.height; - - if (splitscreen) - gl_viewheight /= 2; - - if (splitscreen > 1) - gl_viewwidth /= 2; - - gl_baseviewwindowy = 0; - gl_baseviewwindowx = 0; - GL_FlushScreenTextures(); } @@ -5596,20 +5578,6 @@ extern "C" { // ========================================================================== static void HWR_RenderFrame(player_t *player, boolean skybox) { - // set window position - gl_viewwindowx = gl_baseviewwindowx; - gl_viewwindowy = gl_baseviewwindowy; - - if ((splitscreen == 1 && viewssnum == 1) || (splitscreen > 1 && viewssnum > 1)) - { - gl_viewwindowy += gl_viewheight; - } - - if (splitscreen > 1 && viewssnum & 1) - { - gl_viewwindowx += gl_viewwidth; - } - // check for new console commands. NetUpdate(); @@ -5625,10 +5593,10 @@ static void HWR_RenderFrame(player_t *player, boolean skybox) if (!skybox && cv_glrenderdistance.value) { - GL_GClipRect((INT32)gl_viewwindowx, - (INT32)gl_viewwindowy, - (INT32)(gl_viewwindowx + gl_viewwidth), - (INT32)(gl_viewwindowy + gl_viewheight), + GL_GClipRect(viewwindowx, + viewwindowy, + (viewwindowx + viewwidth), + (viewwindowy + viewheight), ZCLIP_PLANE, clipping_distances[cv_glrenderdistance.value - 1]); current_bsp_culling_distance = bsp_culling_distances[cv_glrenderdistance.value - 1]; } diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 4060b6540..43a292c57 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -42,10 +42,6 @@ extern "C" { void HWR_Startup(void); void HWR_Shutdown(void); -extern float gl_viewwidth, gl_viewheight, gl_baseviewwindowx, gl_baseviewwindowy; - -extern float gl_basewindowcenterx, gl_basewindowcentery; - extern unsigned msaa; extern boolean a2c; -- 2.54.0 From bb0a59540f037ddb40db611764b2415601df7be9 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 14 Oct 2025 22:45:08 +0200 Subject: [PATCH 078/219] use stdlibs abs for CompareDrawNodePlanes we dont need our own abs for this --- src/hardware/hw_main.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/hardware/hw_main.cpp b/src/hardware/hw_main.cpp index 88584a9da..382143dcb 100644 --- a/src/hardware/hw_main.cpp +++ b/src/hardware/hw_main.cpp @@ -65,8 +65,6 @@ // Globals // ========================================================================== -#define ABS(x) ((x) < 0 ? -(x) : (x)) - // false if shaders have not been initialized yet, or if shaders are not available boolean gl_shadersavailable = false; @@ -4330,7 +4328,7 @@ static int CompareDrawNodePlanes(const void *p1, const void *p2) const INT32 n1 = *(const INT32*)p1; const INT32 n2 = *(const INT32*)p2; - return ABS(drawnodes[n2].u.plane.fixedheight - viewz) - ABS(drawnodes[n1].u.plane.fixedheight - viewz); + return abs(drawnodes[n2].u.plane.fixedheight - viewz) - abs(drawnodes[n1].u.plane.fixedheight - viewz); } // -- 2.54.0 From 4f91a0b23460d41377292324a8fd22588c0e6d97 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 14 Oct 2025 23:13:39 +0200 Subject: [PATCH 079/219] remove dead renderer code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit remove - broken viewborder code (if we really want it back for some reason, we should rather port RR´s fixed version of it) - remove console clipping code for software (this was broken eiherway) - remove hud message clearing stuff - remove renderscreen and linesize variables (they just pointed to vid.screen and vid.widht) --- src/Makefile.d/sdl.mk | 2 +- src/console.c | 31 ------- src/console.h | 5 -- src/d_main.c | 9 -- src/doomtype.h | 1 - src/hardware/hw_draw.c | 200 +---------------------------------------- src/hardware/hw_main.h | 2 - src/hu_stuff.c | 70 --------------- src/hu_stuff.h | 1 - src/i_video.h | 2 +- src/m_menu.c | 3 +- src/r_draw.cpp | 147 +----------------------------- src/r_draw.h | 34 +------ src/r_main.cpp | 2 - src/r_plane.cpp | 2 +- src/r_segs.cpp | 5 +- src/r_things.cpp | 2 - src/screen.c | 7 +- src/screen.h | 2 - src/sdl/Srb2SDL.dsp | 4 +- src/sdl/Srb2SDL.props | 4 +- src/st_stuff.c | 4 - 22 files changed, 14 insertions(+), 525 deletions(-) diff --git a/src/Makefile.d/sdl.mk b/src/Makefile.d/sdl.mk index c704a83eb..95fe34e6a 100644 --- a/src/Makefile.d/sdl.mk +++ b/src/Makefile.d/sdl.mk @@ -10,7 +10,7 @@ makedir:=$(makedir)/SDL -opts+=-DDIRECTFULLSCREEN -DHAVE_SDL +opts+=-DHAVE_SDL sources+=$(call List,sdl/Sourcefile) NOUPNP=1 diff --git a/src/console.c b/src/console.c index fe91df0f3..3959d9b98 100644 --- a/src/console.c +++ b/src/console.c @@ -69,14 +69,9 @@ static boolean consoleready; // console prompt is ready INT32 con_destlines; // vid lines used by console at final position static INT32 con_curlines; // vid lines currently used by console - INT32 con_clipviewtop; // (useless) - static UINT8 con_hudlines; // number of console heads up message lines static UINT32 con_hudtime[MAXHUDLINES]; // remaining time of display for hud msg lines - INT32 con_clearlines; // top screen lines to refresh when view reduced - boolean con_hudupdate; // when messages scroll, we need a backgrnd refresh - // console text output static char *con_line; // console text output current line static size_t con_cx; // cursor position in current line @@ -393,9 +388,6 @@ void CON_Init(void) Lock_state(); - //note: CON_Ticker should always execute at least once before D_Display() - con_clipviewtop = -1; // -1 does not clip - con_hudlines = atoi(cons_hudlines.defaultvalue); Unlock_state(); @@ -727,7 +719,6 @@ void CON_ToggleOff(void) con_curlines = 0; CON_ClearHUD(); con_forcepic = 0; - con_clipviewtop = -1; // remove console clipping of view I_SetTextInput(false); @@ -779,18 +770,6 @@ void CON_Ticker(void) } } - // clip the view, so that the part under the console is not drawn - con_clipviewtop = -1; - if (cons_backpic.value) // clip only when using an opaque background - { - if (con_curlines > 0) - con_clipviewtop = con_curlines - viewwindowy - 1 - 10; - // NOTE: BIG HACK::SUBTRACT 10, SO THAT WATER DON'T COPY LINES OF THE CONSOLE - // WINDOW!!! (draw some more lines behind the bottom of the console) - if (con_clipviewtop < 0) - con_clipviewtop = -1; // maybe not necessary, provided it's < 0 - } - // check if console ready for prompt if (con_destlines >= minheight) { @@ -1100,9 +1079,6 @@ static void CON_Linefeed(void) con_line = &con_buffer[(con_cy%con_totallines)*con_width]; memset(con_line, ' ', con_width); - - // make sure the view borders are refreshed if hud messages scroll - con_hudupdate = true; // see HU_Erase() } // Outputs text into the console text buffer @@ -1489,9 +1465,6 @@ static void CON_DrawHudlines(void) //V_DrawCharacter(x, y, (p[c]&0xff) | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value); y += charheight; } - - // top screen lines that might need clearing when view is reduced - con_clearlines = y; // this is handled by HU_Erase(); } // draw the console background, text, and prompt if enough place @@ -1509,10 +1482,6 @@ static void CON_DrawConsole(void) if (con_curlines <= 0) return; - //FIXME: refresh borders only when console bg is translucent - con_clearlines = con_curlines; // clear console draw from view borders - con_hudupdate = true; // always refresh while console is on - // draw console background if (cons_backpic.value || con_forcepic) { diff --git a/src/console.h b/src/console.h index e704a87f1..79af2e48f 100644 --- a/src/console.h +++ b/src/console.h @@ -30,14 +30,9 @@ extern boolean con_recalc; extern boolean con_startup; -// top clip value for view render: do not draw part of view hidden by console -extern INT32 con_clipviewtop; - // 0 means console if off, or moving out extern INT32 con_destlines; -extern INT32 con_clearlines; // lines of top of screen to refresh -extern boolean con_hudupdate; // hud messages have changed, need refresh extern UINT32 con_scalefactor; // console text scale factor extern consvar_t cons_backcolor, cons_menuhighlight; diff --git a/src/d_main.c b/src/d_main.c index dd13c7b77..33dc57689 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -522,19 +522,16 @@ static boolean D_Display(void) case GS_LEVEL: if (!gametic) break; - HU_Erase(); AM_Drawer(); break; case GS_INTERMISSION: Y_IntermissionDrawer(); - HU_Erase(); HU_Drawer(); break; case GS_VOTING: Y_VoteDrawer(); - HU_Erase(); HU_Drawer(); break; @@ -549,7 +546,6 @@ static boolean D_Display(void) case GS_CUTSCENE: F_CutsceneDrawer(); - HU_Erase(); HU_Drawer(); break; @@ -559,7 +555,6 @@ static boolean D_Display(void) case GS_EVALUATION: F_GameEvaluationDrawer(); - HU_Erase(); HU_Drawer(); break; @@ -569,7 +564,6 @@ static boolean D_Display(void) case GS_CREDITS: F_CreditDrawer(); - HU_Erase(); HU_Drawer(); break; @@ -586,7 +580,6 @@ static boolean D_Display(void) { // I don't think HOM from nothing drawing is independent... F_WaitingPlayersDrawer(); - HU_Erase(); HU_Drawer(); } case GS_TIMEATTACK: @@ -1925,9 +1918,7 @@ void D_SRB2Main(void) G_LoadGameData(); -#if defined (__unix__) || defined (UNIXCOMMON) || defined (HAVE_SDL) VID_PrepareModeList(); // Regenerate Modelist according to cv_fullscreen -#endif // set user default mode or mode set at cmdline SCR_CheckDefaultMode(); diff --git a/src/doomtype.h b/src/doomtype.h index 81c09c007..78867ed69 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -43,7 +43,6 @@ extern "C" { #define UINT64 uint64_t #ifdef __APPLE_CC__ -#define DIRECTFULLSCREEN 1 #define DEBUG_LOG #define NOIPX #endif diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 1c014ce4c..cf8ab29e3 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -31,11 +31,6 @@ #include "../st_stuff.h" #include -#include "../i_video.h" // for rendermode != render_glide - -#ifndef O_BINARY -#define O_BINARY 0 -#endif typedef struct { @@ -58,68 +53,6 @@ static UINT8 softwaretranstogl_lo[11] = { 0, 12, 24, 36, 48, 60, 71, 83, 95,111 static const float FLOATBASEVIDWIDTH = (float)BASEVIDWIDTH; static const float FLOATBASEVIDHEIGHT = (float)BASEVIDHEIGHT; -// -// -----------------+ -// HWR_DrawPatch : Draw a 'tile' graphic -// Notes : x,y : positions relative to the original Doom resolution -// : textes(console+score) + menus + status bar -// -----------------+ -void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option) -{ - FOutVector v[4]; - FBITFIELD flags; - GLPatch_t *hwrPatch; - -// 3--2 -// | /| -// |/ | -// 0--1 - float sdup = FIXED_TO_FLOAT(vid.fdup)*2.0f; - float pdup = FIXED_TO_FLOAT(vid.fdup)*2.0f; - - // make patch ready in hardware cache - HWR_GetPatch(gpatch); - hwrPatch = ((GLPatch_t *)gpatch->hardware); - - switch (option & V_SCALEPATCHMASK) - { - case V_NOSCALEPATCH: - pdup = 2.0f; - break; - case V_SMALLSCALEPATCH: - pdup = 2.0f * FIXED_TO_FLOAT(vid.smalldup*FRACUNIT); - break; - case V_MEDSCALEPATCH: - pdup = 2.0f * FIXED_TO_FLOAT(vid.meddup*FRACUNIT); - break; - } - - if (option & V_NOSCALESTART) - sdup = 2.0f; - - v[0].x = v[3].x = (x*sdup-gpatch->leftoffset*pdup)/vid.width - 1; - v[2].x = v[1].x = (x*sdup+(gpatch->width - gpatch->leftoffset)*pdup)/vid.width - 1; - v[0].y = v[1].y = 1-(y*sdup-gpatch->topoffset*pdup)/vid.height; - v[2].y = v[3].y = 1-(y*sdup+(gpatch->height - gpatch->topoffset)*pdup)/vid.height; - - v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - - v[0].s = v[3].s = 0.0f; - v[2].s = v[1].s = hwrPatch->max_s; - v[0].t = v[1].t = 0.0f; - v[2].t = v[3].t = hwrPatch->max_t; - - flags = PF_Translucent|PF_NoDepthTest; - - if (option & V_WRAPX) - flags |= PF_ForceWrapX; - if (option & V_WRAPY) - flags |= PF_ForceWrapY; - - // clip it since it is used for bunny scroll in doom I - GL_DrawPolygon(NULL, v, 4, flags); -} - void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap, INT32 bflags) { FOutVector v[4]; @@ -636,137 +569,6 @@ void HWR_DrawConsoleBack(UINT32 color, INT32 height) } -// ========================================================================== -// R_DRAW.C STUFF -// ========================================================================== - -// ------------------ -// HWR_DrawViewBorder -// Fill the space around the view window with a Doom flat texture, draw the -// beveled edges. -// 'clearlines' is useful to clear the heads up messages, when the view -// window is reduced, it doesn't refresh all the view borders. -// ------------------ -void HWR_DrawViewBorder(INT32 clearlines) -{ -#if 0 - INT32 x, y; - INT32 top, side; - INT32 baseviewwidth, baseviewheight; - INT32 basewindowx, basewindowy; - patch_t *patch; - - if (!clearlines) - clearlines = BASEVIDHEIGHT; // refresh all - - // calc view size based on original game resolution - baseviewwidth = FixedInt(FixedDiv(viewwidth * FRACUNIT, vid.fdup)); //(cv_viewsize.value * BASEVIDWIDTH/10)&~7; - baseviewheight = FixedInt(FixedDiv(viewheight * FRACUNIT, vid.fdup)); - top = FixedInt(FixedDiv(baseviewwindowy * FRACUNIT, vid.fdup)); - side = FixedInt(FixedDiv(baseviewwindowx * FRACUNIT, vid.fdup)); - - // top - HWR_DrawFlatFill(0, 0, - BASEVIDWIDTH, (top < clearlines ? top : clearlines), - st_borderpatchnum); - - // left - if (top < clearlines) - HWR_DrawFlatFill(0, top, side, - (clearlines-top < baseviewheight ? clearlines-top : baseviewheight), - st_borderpatchnum); - - // right - if (top < clearlines) - HWR_DrawFlatFill(side + baseviewwidth, top, side, - (clearlines-top < baseviewheight ? clearlines-top : baseviewheight), - st_borderpatchnum); - - // bottom - if (top + baseviewheight < clearlines) - HWR_DrawFlatFill(0, top + baseviewheight, - BASEVIDWIDTH, BASEVIDHEIGHT, st_borderpatchnum); - - // - // draw the view borders - // - - basewindowx = (BASEVIDWIDTH - baseviewwidth)>>1; - if (baseviewwidth == BASEVIDWIDTH) - basewindowy = 0; - else - basewindowy = top; - - // top edge - if (clearlines > basewindowy - 8) - { - patch = W_CachePatchNum(viewborderlump[BRDR_T], PU_PATCH); - for (x = 0; x < baseviewwidth; x += 8) - HWR_DrawPatch(patch, basewindowx + x, basewindowy - 8, - 0); - } - - // bottom edge - if (clearlines > basewindowy + baseviewheight) - { - patch = W_CachePatchNum(viewborderlump[BRDR_B], PU_PATCH); - for (x = 0; x < baseviewwidth; x += 8) - HWR_DrawPatch(patch, basewindowx + x, - basewindowy + baseviewheight, 0); - } - - // left edge - if (clearlines > basewindowy) - { - patch = W_CachePatchNum(viewborderlump[BRDR_L], PU_PATCH); - for (y = 0; y < baseviewheight && basewindowy + y < clearlines; - y += 8) - { - HWR_DrawPatch(patch, basewindowx - 8, basewindowy + y, - 0); - } - } - - // right edge - if (clearlines > basewindowy) - { - patch = W_CachePatchNum(viewborderlump[BRDR_R], PU_PATCH); - for (y = 0; y < baseviewheight && basewindowy+y < clearlines; - y += 8) - { - HWR_DrawPatch(patch, basewindowx + baseviewwidth, - basewindowy + y, 0); - } - } - - // Draw beveled corners. - if (clearlines > basewindowy - 8) - HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_TL], - PU_PATCH), - basewindowx - 8, basewindowy - 8, 0); - - if (clearlines > basewindowy - 8) - HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_TR], - PU_PATCH), - basewindowx + baseviewwidth, basewindowy - 8, 0); - - if (clearlines > basewindowy+baseviewheight) - HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_BL], - PU_PATCH), - basewindowx - 8, basewindowy + baseviewheight, 0); - - if (clearlines > basewindowy + baseviewheight) - HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_BR], - PU_PATCH), - basewindowx + baseviewwidth, - basewindowy + baseviewheight, 0); -#else - (void)clearlines; -#endif -} - - - // ========================================================================== // AM_MAP.C DRAWING STUFF // ========================================================================== @@ -1172,7 +974,7 @@ static inline boolean saveTGA(const char *file_name, void *buffer, INT32 i; UINT8 *buf8 = buffer; - fd = open(file_name, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); + fd = open(file_name, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd < 0) return false; diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 43a292c57..30906b611 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -85,7 +85,6 @@ extern ps_metric_t ps_hw_batchdrawtime; extern boolean gl_shadersavailable; // hw_draw.c -void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option); void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap, INT32 bflags); void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h); void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color); @@ -94,7 +93,6 @@ void HWR_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 color); void HWR_drawAMline(const fline_t *fl, INT32 color); void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength); void HWR_DrawConsoleBack(UINT32 color, INT32 height); -void HWR_DrawViewBorder(INT32 clearlines); void HWR_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum); UINT8 *HWR_GetScreenshot(INT32 scale); diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 6ca275aff..fa7060dff 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2391,76 +2391,6 @@ void HU_Drawer(void) } } -//====================================================================== -// HUD MESSAGES CLEARING FROM SCREEN -//====================================================================== - -// Clear old messages from the borders around the view window -// (only for reduced view, refresh the borders when needed) -// -// startline: y coord to start clear, -// clearlines: how many lines to clear. -// -static INT32 oldclearlines; - -void HU_Erase(void) -{ - INT32 topline, bottomline; - INT32 y, yoffset; - -#ifdef HWRENDER - // clear hud msgs on double buffer (OpenGL mode) - boolean secondframe; - static INT32 secondframelines; -#endif - - if (con_clearlines == oldclearlines && !con_hudupdate && !chat_on) - return; - -#ifdef HWRENDER - // clear the other frame in double-buffer modes - secondframe = (con_clearlines != oldclearlines); - if (secondframe) - secondframelines = oldclearlines; -#endif - - // clear the message lines that go away, so use _oldclearlines_ - bottomline = oldclearlines; - oldclearlines = con_clearlines; - if (chat_on && OLDCHAT) - if (bottomline < 8) - bottomline = 8; // only do it for consolechat. consolechat is gay. - - if (automapactive || viewwindowx == 0) // hud msgs don't need to be cleared - return; - - // software mode copies view border pattern & beveled edges from the backbuffer - if (rendermode == render_soft) - { - topline = 0; - for (y = topline, yoffset = y*vid.width; y < bottomline; y++, yoffset += vid.width) - { - if (y < viewwindowy || y >= viewwindowy + viewheight) - R_VideoErase(yoffset, vid.width); // erase entire line - else - { - R_VideoErase(yoffset, viewwindowx); // erase left border - // erase right border - R_VideoErase(yoffset + viewwindowx + viewwidth, viewwindowx); - } - } - con_hudupdate = false; // if it was set.. - } -#ifdef HWRENDER - else if (rendermode != render_none) - { - // refresh just what is needed from the view borders - HWR_DrawViewBorder(secondframelines); - con_hudupdate = secondframe; - } -#endif -} - //====================================================================== // IN-LEVEL MULTIPLAYER RANKINGS //====================================================================== diff --git a/src/hu_stuff.h b/src/hu_stuff.h index d134f319e..64d369a33 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -117,7 +117,6 @@ void HU_TickSongCredits(void); void HU_DrawSongCredits(void); void HU_Drawer(void); char HU_dequeueChatChar(void); -void HU_Erase(void); void HU_clearChatChars(void); void HU_drawPlayerPing(INT32 x, INT32 y, INT32 pnum, INT32 flags); // Lat': Ping drawer for scoreboard. //void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer); diff --git a/src/i_video.h b/src/i_video.h index 822a1bada..852645c30 100644 --- a/src/i_video.h +++ b/src/i_video.h @@ -94,8 +94,8 @@ INT32 VID_SetMode(INT32 modenum); \return name of video mode */ const char *VID_GetModeName(INT32 modenum); -void VID_PrepareModeList(void); /// note hack for SDL +void VID_PrepareModeList(void); /** \brief can video system do fullscreen */ diff --git a/src/m_menu.c b/src/m_menu.c index 95824c7dd..ed39e053f 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -9442,9 +9442,8 @@ static void M_VideoModeMenu(INT32 choice) memset(modedescs, 0, sizeof(modedescs)); -#if defined (__unix__) || defined (UNIXCOMMON) || defined (HAVE_SDL) VID_PrepareModeList(); // FIXME: hack -#endif + vidm_nummodes = 0; vidm_selected = 0; nummodes = VID_NumModes(); diff --git a/src/r_draw.cpp b/src/r_draw.cpp index c8a09745a..91de5e102 100644 --- a/src/r_draw.cpp +++ b/src/r_draw.cpp @@ -41,8 +41,7 @@ /** \brief view info */ -INT32 linesize, viewwidth, viewheight, viewwindowx, viewwindowy; -UINT8 *renderscreen; // haleyjd +INT32 viewwidth, viewheight, viewwindowx, viewwindowy; // ========================================================================= // COLUMN DRAWING CODE STUFF @@ -521,7 +520,6 @@ static void R_AllocViewMemory(void) R_AllocVisSpriteMemory(); } - void R_InitViewBuffer(INT32 width, INT32 height) { if (width > MAXVIDWIDTH) @@ -534,27 +532,7 @@ void R_InitViewBuffer(INT32 width, INT32 height) viewwindowx = 0; viewwindowy = 0; - linesize = vid.width; // killough 11/98 - renderscreen = vid.screens[0]; // haleyjd 07/02/14 -} -/** \brief viewborder patches lump numbers -*/ -lumpnum_t viewborderlump[8]; - -/** \brief Store the lumpnumber of the viewborder patches -*/ - -void R_InitViewBorder(void) -{ - viewborderlump[BRDR_T] = W_GetNumForName("brdr_t"); - viewborderlump[BRDR_B] = W_GetNumForName("brdr_b"); - viewborderlump[BRDR_L] = W_GetNumForName("brdr_l"); - viewborderlump[BRDR_R] = W_GetNumForName("brdr_r"); - viewborderlump[BRDR_TL] = W_GetNumForName("brdr_tl"); - viewborderlump[BRDR_BL] = W_GetNumForName("brdr_bl"); - viewborderlump[BRDR_TR] = W_GetNumForName("brdr_tr"); - viewborderlump[BRDR_BR] = W_GetNumForName("brdr_br"); } /** \brief The R_VideoErase function @@ -578,129 +556,6 @@ void R_VideoErase(size_t ofs, INT32 count) M_Memcpy(vid.screens[0] + ofs, vid.screens[1] + ofs, count); } - -#if 0 -/** \brief R_FillBackScreen - - Fills the back screen with a pattern for variable screen sizes - Also draws a beveled edge. -*/ -void R_FillBackScreen(void) -{ - UINT8 *src, *dest; - patch_t *patch; - INT32 x, y, step, boff; - - // quickfix, don't cache lumps in both modes - if (rendermode != render_soft) - return; - - // draw pattern around the status bar too (when hires), - // so return only when in full-screen without status bar. - if (scaledviewwidth == vid.width && viewheight == vid.height) - return; - - src = scr_borderpatch; - dest = vid.screens[1]; - - for (y = 0; y < vid.height; y++) - { - for (x = 0; x < vid.width/128; x++) - { - M_Memcpy (dest, src+((y&127)<<7), 128); - dest += 128; - } - - if (vid.width&127) - { - M_Memcpy(dest, src+((y&127)<<7), vid.width&127); - dest += (vid.width&127); - } - } - - // don't draw the borders when viewwidth is full vid.width. - if (scaledviewwidth == vid.width) - return; - - step = 8; - boff = 8; - - patch = W_CacheLumpNum(viewborderlump[BRDR_T], PU_CACHE); - for (x = 0; x < scaledviewwidth; x += step) - V_DrawPatch(viewwindowx + x, viewwindowy - boff, 1, patch); - - patch = W_CacheLumpNum(viewborderlump[BRDR_B], PU_CACHE); - for (x = 0; x < scaledviewwidth; x += step) - V_DrawPatch(viewwindowx + x, viewwindowy + viewheight, 1, patch); - - patch = W_CacheLumpNum(viewborderlump[BRDR_L], PU_CACHE); - for (y = 0; y < viewheight; y += step) - V_DrawPatch(viewwindowx - boff, viewwindowy + y, 1, patch); - - patch = W_CacheLumpNum(viewborderlump[BRDR_R],PU_CACHE); - for (y = 0; y < viewheight; y += step) - V_DrawPatch(viewwindowx + scaledviewwidth, viewwindowy + y, 1, - patch); - - // Draw beveled corners. - V_DrawPatch(viewwindowx - boff, viewwindowy - boff, 1, - W_CacheLumpNum(viewborderlump[BRDR_TL], PU_CACHE)); - V_DrawPatch(viewwindowx + scaledviewwidth, viewwindowy - boff, 1, - W_CacheLumpNum(viewborderlump[BRDR_TR], PU_CACHE)); - V_DrawPatch(viewwindowx - boff, viewwindowy + viewheight, 1, - W_CacheLumpNum(viewborderlump[BRDR_BL], PU_CACHE)); - V_DrawPatch(viewwindowx + scaledviewwidth, viewwindowy + viewheight, 1, - W_CacheLumpNum(viewborderlump[BRDR_BR], PU_CACHE)); -} - -/** \brief The R_DrawViewBorder - - Draws the border around the view - for different size windows? -*/ -void R_DrawViewBorder(void) -{ - INT32 top, side, ofs; - - if (rendermode == render_none) - return; -#ifdef HWRENDER - if (rendermode != render_soft) - { - HWR_DrawViewBorder(0); - return; - } - else -#endif - -#ifdef DEBUG - fprintf(stderr,"RDVB: vidwidth %d vidheight %d scaledviewwidth %d viewheight %d\n", - vid.width, vid.height, scaledviewwidth, viewheight); -#endif - - if (scaledviewwidth == vid.width) - return; - - top = (vid.height - viewheight)>>1; - side = (vid.width - scaledviewwidth)>>1; - - // copy top and one line of left side - R_VideoErase(0, top*vid.width+side); - - // copy one line of right side and bottom - ofs = (viewheight+top)*vid.width - side; - R_VideoErase(ofs, top*vid.width + side); - - // copy sides using wraparound - ofs = top*vid.width + vid.width-side; - side <<= 1; - - // simpler using our VID_Blit routine - VID_BlitLinearScreen(vid.screens[1] + ofs, vid.screens[0] + ofs, side, viewheight - 1, - vid.width, vid.width); -} -#endif - // ========================================================================== // INCLUDE DRAWING CODE HERE // ========================================================================== diff --git a/src/r_draw.h b/src/r_draw.h index bcd734e50..eaee19039 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -25,12 +25,10 @@ extern "C" { // ------------------------------- // COMMON STUFF FOR 8bpp AND 16bpp // ------------------------------- -extern UINT8 *renderscreen; -extern INT32 linesize; FUNCINLINE static ATTRINLINE UINT8 *R_Address(INT32 px, INT32 py) { - return renderscreen + (py + viewwindowy) * linesize + (viewwindowx + px); + return vid.screens[0] + (py + viewwindowy) * vid.width + (viewwindowx + px); } @@ -152,27 +150,8 @@ extern spandrawfunc_t *spanfuncs[SPANDRAWFUNC_MAX]; void R_DrawMaskedColumn(drawcolumndata_t* dc, column_t *column); -/// \brief Top border -#define BRDR_T 0 -/// \brief Bottom border -#define BRDR_B 1 -/// \brief Left border -#define BRDR_L 2 -/// \brief Right border -#define BRDR_R 3 -/// \brief Topleft border -#define BRDR_TL 4 -/// \brief Topright border -#define BRDR_TR 5 -/// \brief Bottomleft border -#define BRDR_BL 6 -/// \brief Bottomright border -#define BRDR_BR 7 - -extern lumpnum_t viewborderlump[8]; - // ------------------------------------------------ -// r_draw.c COMMON ROUTINES FOR BOTH 8bpp and 16bpp +// r_draw.c // ------------------------------------------------ #define GTC_CACHE 1 @@ -221,17 +200,8 @@ boolean R_BlendLevelVisible(INT32 blendmode, INT32 alphalevel); // Custom player skin translation void R_InitViewBuffer(INT32 width, INT32 height); -void R_InitViewBorder(void); void R_VideoErase(size_t ofs, INT32 count); -// Rendering function. -#if 0 -void R_FillBackScreen(void); - -// If the view size is not full screen, draws a border around it. -void R_DrawViewBorder(void); -#endif - #define TRANSPARENTPIXEL 247 // ----------------- diff --git a/src/r_main.cpp b/src/r_main.cpp index 08f1e68a1..a392db087 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1023,8 +1023,6 @@ void R_Init(void) //I_OutputMsg("\nR_InitData"); R_InitData(); - //I_OutputMsg("\nR_InitViewBorder"); - R_InitViewBorder(); R_SetViewSize(); // setsizeneeded is set true // this is now done by SCR_Recalc() at the first mode set diff --git a/src/r_plane.cpp b/src/r_plane.cpp index de713dc9c..484aab49c 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -787,7 +787,7 @@ static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), b drawcolumndata_t dc = {}; const INT32 texture = texturetranslation[skytexture]; - // Reset column drawer function (note: couldn't we just call walldrawerfunc directly?) + // Reset column drawer function (note: couldn't we just call colfuncs[BASEDRAWFUNC] directly?) // (that is, unless we'll need to switch drawers in future for some reason) R_SetColumnFunc(BASEDRAWFUNC); diff --git a/src/r_segs.cpp b/src/r_segs.cpp index c83b45593..b4f8cdbcd 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -26,7 +26,6 @@ #include "p_local.h" // Camera... #include "p_setup.h" #include "p_slopes.h" -#include "console.h" // con_clipviewtop #include "screen.h" #include "core/memory.h" @@ -628,8 +627,6 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf sector_t tempsec; INT32 templight; INT32 i, p; - fixed_t bottombounds = viewheight << FRACBITS; - fixed_t topbounds = (con_clipviewtop - 1) << FRACBITS; fixed_t offsetvalue = 0; lightlist_t *light; r_lightlist_t *rlight; @@ -936,7 +933,7 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf bottom_frac += bottom_step; // SoM: If column is out of range, why bother with it?? - if (windowbottom < topbounds || windowtop > bottombounds) + if (windowbottom < 0 || windowtop > (viewheight << FRACBITS)) { if (dc->numlights) { diff --git a/src/r_things.cpp b/src/r_things.cpp index 12d02d329..d69e7ea4e 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -2518,8 +2518,6 @@ void R_InitDrawNodes(void) // R_DrawSprite // //Fab : 26-04-98: -// NOTE : uses con_clipviewtop, so that when console is on, -// don't draw the part of sprites hidden under the console static void R_DrawSprite(vissprite_t *spr) { mfloorclip = spr->clipbot; diff --git a/src/screen.c b/src/screen.c index 8d2782ab8..9a8109066 100644 --- a/src/screen.c +++ b/src/screen.c @@ -80,10 +80,6 @@ consvar_t cv_accuratefps = {"fpssampling", "1", CV_SAVE, accuratefps_cons_t, NUL // SCREEN VARIABLES // ========================================================================= -UINT8 *scr_borderpatch; // flat used to fill the reduced view borders set at ST_Init() - -// ========================================================================= - static void SCR_SetDrawFuncs(void) { // @@ -298,7 +294,6 @@ void SCR_SetDefaultMode(void) // Change fullscreen on/off according to cv_fullscreen void SCR_ChangeFullscreen(void) { -#ifdef DIRECTFULLSCREEN I_SetBorderlessWindow(); // Running this here so we can have borderless window at startup // allow_fullscreen is set by VID_PrepareModeList @@ -311,8 +306,8 @@ void SCR_ChangeFullscreen(void) VID_PrepareModeList(); setmodeneeded = VID_GetModeForSize(vid.width, vid.height) + 1; } + return; -#endif } boolean SCR_IsAspectCorrect(INT32 width, INT32 height) diff --git a/src/screen.h b/src/screen.h index ecad24a64..fb234324f 100644 --- a/src/screen.h +++ b/src/screen.h @@ -84,8 +84,6 @@ enum extern viddef_t vid; extern INT32 setmodeneeded; // mode number to set if needed, or 0 -extern UINT8 *scr_borderpatch; // patch used to fill the view borders - extern consvar_t cv_scr_width, cv_scr_height, cv_renderview, cv_frameskip, cv_fullscreen, cv_vhseffect, cv_shittyscreen; extern consvar_t cv_parallelsoftware; extern consvar_t cv_paralleldrawmasked; diff --git a/src/sdl/Srb2SDL.dsp b/src/sdl/Srb2SDL.dsp index 47ede4126..96d3e8418 100644 --- a/src/sdl/Srb2SDL.dsp +++ b/src/sdl/Srb2SDL.dsp @@ -45,7 +45,7 @@ MTL=midl.exe # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /G5 /W3 /GX /Zi /Ot /Og /Oi /Op /Oy /Ob1 /I "..\..\libs\libpng-src" /I "..\..\libs\zlib" /D "NDEBUG" /D "SDLMAIN" /D "NO_STDIO_REDIRECT" /D "USE_WGL_SWAP" /D "DIRECTFULLSCREEN" /D "HAVE_SDL" /D "HWRENDER" /D "HAVE_FILTER" /D "HAVE_MIXER" /D "USEASM" /D "HAVE_PNG" /FR /FD /GF /c +# ADD CPP /nologo /G5 /W3 /GX /Zi /Ot /Og /Oi /Op /Oy /Ob1 /I "..\..\libs\libpng-src" /I "..\..\libs\zlib" /D "NDEBUG" /D "SDLMAIN" /D "NO_STDIO_REDIRECT" /D "USE_WGL_SWAP" /D "HAVE_SDL" /D "HWRENDER" /D "HAVE_FILTER" /D "HAVE_MIXER" /D "USEASM" /D "HAVE_PNG" /FR /FD /GF /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" # SUBTRACT RSC /x @@ -72,7 +72,7 @@ LINK32=link.exe # PROP Target_Dir "" MTL=midl.exe # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /G6 /W4 /WX /Gm /GX /ZI /Od /Op /I "..\..\libs\libpng-src" /I "..\..\libs\zlib" /D "_DEBUG" /D "USE_WGL_SWAP" /D "DIRECTFULLSCREEN" /D "HAVE_SDL" /D "HWRENDER" /D "HAVE_FILTER" /D "HAVE_MIXER" /D "USEASM" /D "HAVE_PNG" /FR /FD /GZ /c +# ADD CPP /nologo /G6 /W4 /WX /Gm /GX /ZI /Od /Op /I "..\..\libs\libpng-src" /I "..\..\libs\zlib" /D "_DEBUG" /D "USE_WGL_SWAP" /D "HAVE_SDL" /D "HWRENDER" /D "HAVE_FILTER" /D "HAVE_MIXER" /D "USEASM" /D "HAVE_PNG" /FR /FD /GZ /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" diff --git a/src/sdl/Srb2SDL.props b/src/sdl/Srb2SDL.props index f02b9b35e..8c4799f20 100644 --- a/src/sdl/Srb2SDL.props +++ b/src/sdl/Srb2SDL.props @@ -6,9 +6,9 @@ - HAVE_ZLIB;HAVE_LIBGME;USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HAVE_FILTER;HAVE_MIXER;SDLMAIN;%(PreprocessorDefinitions) + HAVE_ZLIB;HAVE_LIBGME;USE_WGL_SWAP;HAVE_SDL;HWRENDER;HAVE_FILTER;HAVE_MIXER;SDLMAIN;%(PreprocessorDefinitions) - USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HAVE_FILTER;HAVE_MIXER;SDLMAIN;%(PreprocessorDefinitions) + USE_WGL_SWAP;HAVE_SDL;HWRENDER;HAVE_FILTER;HAVE_MIXER;SDLMAIN;%(PreprocessorDefinitions) diff --git a/src/st_stuff.c b/src/st_stuff.c index f5634423c..fade7c484 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -219,10 +219,6 @@ void ST_UnloadGraphics(void) void ST_LoadGraphics(void) { - // SRB2 border patch - //st_borderpatchnum = W_GetNumForName("GFZFLR01"); - //scr_borderpatch = W_CacheLumpNum(st_borderpatchnum, PU_HUDGFX); - // the original Doom uses 'STF' as base name for all face graphics // Graue 04-08-2004: face/name graphics are now indexed by skins // but load them in R_AddSkins, that gets called -- 2.54.0 From 64bdae5e5d37ab8f7913ffded4337c8eee9338d7 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 14 Oct 2025 23:23:04 +0200 Subject: [PATCH 080/219] delet dead code ogl models --- src/hardware/hw_model.c | 145 ---------------------------------------- src/hardware/hw_model.h | 6 -- 2 files changed, 151 deletions(-) diff --git a/src/hardware/hw_model.c b/src/hardware/hw_model.c index e77cf43ef..6a9825402 100644 --- a/src/hardware/hw_model.c +++ b/src/hardware/hw_model.c @@ -114,7 +114,6 @@ void UnloadModel(model_t *model) if (model->materials) Z_Free(model->materials); - DeleteVBOs(model); Z_Free(model); } @@ -194,7 +193,6 @@ model_t *LoadModel(const char *filename, int ztag) strcpy(model->mdlFilename, filename); Optimize(model); - GeneratePolygonNormals(model, ztag); // Default material properties for (i = 0 ; i < model->numMaterials; i++) @@ -246,13 +244,6 @@ void GenerateVertexNormals(model_t *model) M_Memcpy(newNormals, frame->normals, sizeof(float)*3*mesh->numTriangles*3); -/* if (!systemSucks) - { - memTag = Z_GetTag(frame->tangents); - float *newTangents = (float*)Z_Malloc(sizeof(float)*3*mesh->numTriangles*3, memTag); - M_Memcpy(newTangents, frame->tangents, sizeof(float)*3*mesh->numTriangles*3); - }*/ - for (k = 0; k < mesh->numVertices; k++) { float x, y, z; @@ -288,32 +279,15 @@ void GenerateVertexNormals(model_t *model) if (vCount > 1) { -// Vector::Normalize(&normal); newNormals[3 * k + 0] = (float)normal.x; newNormals[3 * k + 1] = (float)normal.y; newNormals[3 * k + 2] = (float)normal.z; - -/* if (!systemSucks) - { - Vector::vector_t tangent; - Vector::Tangent(&normal, &tangent); - newTangents[3 * k + 0] = tangent.x; - newTangents[3 * k + 1] = tangent.y; - newTangents[3 * k + 2] = tangent.z; - }*/ } } oldNormals = frame->normals; frame->normals = newNormals; Z_Free(oldNormals); - -/* if (!systemSucks) - { - float *oldTangents = frame->tangents; - frame->tangents = newTangents; - Z_Free(oldTangents); - }*/ } } } @@ -404,15 +378,11 @@ void Optimize(model_t *model) newMesh->numTriangles = numTriangles; newMesh->numVertices = numTriangles * 3; newMesh->uvs = (float*)Z_Malloc(sizeof(float)*2*numTriangles*3, memTag, 0); -// if (node->material->lightmap) -// newMesh->lightuvs = (float*)Z_Malloc(sizeof(float)*2*numTriangles*3, memTag, 0); newMesh->frames = (mdlframe_t*)Z_Calloc(sizeof(mdlframe_t), memTag, 0); curFrame = &newMesh->frames[0]; curFrame->material = curMat; curFrame->normals = (float*)Z_Malloc(sizeof(float)*3*numTriangles*3, memTag, 0); -// if (!systemSucks) -// curFrame->tangents = (float*)Z_Malloc(sizeof(float)*3*numTriangles*3, memTag, 0); curFrame->vertices = (float*)Z_Malloc(sizeof(float)*3*numTriangles*3, memTag, 0); curFrame->colors = (char*)Z_Malloc(sizeof(char)*4*numTriangles*3, memTag, 0); @@ -436,12 +406,6 @@ void Optimize(model_t *model) curMesh->uvs, sizeof(float)*2*curMesh->numTriangles*3); -/* if (node->material->lightmap) - { - M_Memcpy(&newMesh->lightuvs[uvCount], - curMesh->lightuvs, - sizeof(float)*2*curMesh->numTriangles*3); - }*/ uvCount += 2*curMesh->numTriangles*3; dest = (float*)newMesh->frames[0].vertices; @@ -456,15 +420,6 @@ void Optimize(model_t *model) src, sizeof(float)*3*curMesh->numTriangles*3); -/* if (!systemSucks) - { - dest = (float*)newMesh->frames[0].tangents; - src = (float*)curMesh->frames[0].tangents; - M_Memcpy(&dest[vertCount], - src, - sizeof(float)*3*curMesh->numTriangles*3); - }*/ - vertCount += 3 * curMesh->numTriangles * 3; destByte = (char*)newMesh->frames[0].colors; @@ -494,103 +449,3 @@ void Optimize(model_t *model) model->meshes = newMeshes; model->numMeshes = numMeshes; } - -void GeneratePolygonNormals(model_t *model, int ztag) -{ - int i; - for (i = 0; i < model->numMeshes; i++) - { - int j; - mesh_t *mesh = &model->meshes[i]; - - if (!mesh->frames) - continue; - - for (j = 0; j < mesh->numFrames; j++) - { - int k; - mdlframe_t *frame = &mesh->frames[j]; - const float *vertices = frame->vertices; - vector_t *polyNormals; - - frame->polyNormals = (vector_t*)Z_Malloc(sizeof(vector_t) * mesh->numTriangles, ztag, 0); - - polyNormals = frame->polyNormals; - - for (k = 0; k < mesh->numTriangles; k++) - { - /// TODO: normalize vectors - (void)vertices; - (void)polyNormals; -// Vector::Normal(vertices, polyNormals); - vertices += 3 * 3; - polyNormals++; - } - } - } -} - -// -// Reload -// -// Reload VBOs -// -#if 0 -static void Reload(void) -{ -/* model_t *node; - for (node = modelHead; node; node = node->next) - { - int i; - for (i = 0; i < node->numMeshes; i++) - { - mesh_t *mesh = &node->meshes[i]; - - if (mesh->frames) - { - int j; - for (j = 0; j < mesh->numFrames; j++) - CreateVBO(mesh, &mesh->frames[j]); - } - else if (mesh->tinyframes) - { - int j; - for (j = 0; j < mesh->numFrames; j++) - CreateVBO(mesh, &mesh->tinyframes[j]); - } - } - }*/ -} -#endif - -void DeleteVBOs(model_t *model) -{ - (void)model; -/* for (int i = 0; i < model->numMeshes; i++) - { - mesh_t *mesh = &model->meshes[i]; - - if (mesh->frames) - { - for (int j = 0; j < mesh->numFrames; j++) - { - mdlframe_t *frame = &mesh->frames[j]; - if (!frame->vboID) - continue; - bglDeleteBuffers(1, &frame->vboID); - frame->vboID = 0; - } - } - else if (mesh->tinyframes) - { - for (int j = 0; j < mesh->numFrames; j++) - { - tinyframe_t *frame = &mesh->tinyframes[j]; - if (!frame->vboID) - continue; - bglDeleteBuffers(1, &frame->vboID); - frame->vboID = 0; - } - } - }*/ -} diff --git a/src/hardware/hw_model.h b/src/hardware/hw_model.h index 1803f4c5c..fcd574bd4 100644 --- a/src/hardware/hw_model.h +++ b/src/hardware/hw_model.h @@ -28,8 +28,6 @@ typedef struct float ambient[4], diffuse[4], specular[4], emissive[4]; float shininess; boolean spheremap; -// Texture::texture_t *texture; -// Texture::texture_t *lightmap; } material_t; typedef struct @@ -40,7 +38,6 @@ typedef struct float *tangents; char *colors; unsigned int vboID; - vector_t *polyNormals; } mdlframe_t; typedef struct @@ -70,7 +67,6 @@ typedef struct mesh_s typedef struct tag_s { char name[64]; -// matrix_t transform; } tag_t; typedef struct model_s @@ -96,9 +92,7 @@ model_t *LoadModel(const char *filename, int ztag); void UnloadModel(model_t *model); void Optimize(model_t *model); void GenerateVertexNormals(model_t *model); -void GeneratePolygonNormals(model_t *model, int ztag); void CreateVBOTiny(mesh_t *mesh, tinyframe_t *frame); void CreateVBO(mesh_t *mesh, mdlframe_t *frame); -void DeleteVBOs(model_t *model); #endif -- 2.54.0 From da16ce3a234da75ce225bb90aac28f3bd016bcb5 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 15 Oct 2025 06:28:39 +0200 Subject: [PATCH 081/219] mark flush error functions with noreturn silences clang --- src/r_draw.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/r_draw.cpp b/src/r_draw.cpp index e5596e4c8..ed233e387 100644 --- a/src/r_draw.cpp +++ b/src/r_draw.cpp @@ -521,17 +521,17 @@ drawcolumndata_temp_t temp_dc = {}; // Error functions that will abort if R_FlushColumns tries to flush // columns without a column type. // -static void R_FlushWholeError(void) +FUNCNORETURN static ATTRNORETURN void R_FlushWholeError(void) { I_Error("R_FlushWholeColumns called without being initialized.\n"); } -static void R_FlushHTError(void) +FUNCNORETURN static ATTRNORETURN void R_FlushHTError(void) { I_Error("R_FlushHTColumns called without being initialized.\n"); } -static void R_QuadFlushError(void) +FUNCNORETURN static ATTRNORETURN void R_QuadFlushError(void) { I_Error("R_FlushQuadColumn called without being initialized.\n"); } -- 2.54.0 From a87e07155af4a8b94397a9ac2e896d4a67893c17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Sat, 19 Apr 2025 11:13:14 +0200 Subject: [PATCH 082/219] Remove WINSOCK1 support WINSOCK2 has been supported since Windows XP and is required for IPv6, so I don't see a reason to support it anymore. --- src/i_addrinfo.c | 680 ----------------------------------------------- src/i_addrinfo.h | 71 ----- src/i_tcp.c | 131 +++------ 3 files changed, 44 insertions(+), 838 deletions(-) delete mode 100644 src/i_addrinfo.c delete mode 100644 src/i_addrinfo.h diff --git a/src/i_addrinfo.c b/src/i_addrinfo.c deleted file mode 100644 index f9d860bd1..000000000 --- a/src/i_addrinfo.c +++ /dev/null @@ -1,680 +0,0 @@ -// SONIC ROBO BLAST 2 -//----------------------------------------------------------------------------- -// Copyright (C) 2011-2018 by Sonic Team Junior. -// -// This program is free software distributed under the -// terms of the GNU General Public License, version 2. -// See the 'LICENSE' file for more details. -//----------------------------------------------------------------------------- -/// \file i_addrinfo.c -/// \brief getaddr stubs, for lesser OSes -/// -/// Some systems/SDKs, like PSL1GHT v2 does not have addrinfo functions -/// So a stub is needed -#include -#include -#include -#ifdef _WIN32 -#ifdef USE_WINSOCK2 -#include -#else -#include -#endif -#else -#include -#include -#include -#endif - -#include "i_addrinfo.h" - -/* - * This addrinfo stub have a testcases: - * To test the stub, use this command to compile the stub testcase: - * gcc -g -DTESTCASE -Dtest_stub -Wall -W i_addrinfo.c -o stub - * To test the real getaddrinfo API, use this command to get real one: - * gcc -g -DTESTCASE -Utest_stub -Wall -W i_addrinfo.c -o real - * For Win32,you need the WinSock library, version 1.1 or 2.2 - * for 1.1, add -lwsock32 - * i686-w64-mingw32-gcc -g -DTESTCASE -Dtest_stub -UUSE_WINSOCK2 -Wall -W i_addrinfo.c -o stub.exe -lwsock32 - * for 2.2, add -DUSE_WINSOCK2 -lws2_32 - * i686-w64-mingw32-gcc -g -DTESTCASE -Utest_stub -DUSE_WINSOCK2 -Wall -W i_addrinfo.c -o real.exe -lws2_32 - */ - -#ifndef I_getaddrinfo - -#include - -#ifdef _WIN32 -// it seems windows doesn't define that... maybe some other OS? OS/2 -static int inet_aton(const char *cp, struct in_addr *addr) -{ - if( cp == NULL || addr == NULL ) - { - return(0); - } - if (strcmp(cp, "255.255.255.225") == 0) - { - addr->s_addr = htonl(INADDR_BROADCAST); - return 0; - } - return (addr->s_addr = inet_addr(cp)) != htonl(INADDR_NONE); -} -#endif - -#ifdef USE_WINSOCK2 -static HMODULE ipv6dll = NULL; -typedef int (WSAAPI *p_getaddrinfo) (const char *, const char *, - const struct my_addrinfo *, - struct my_addrinfo **); -typedef void (WSAAPI *p_freeaddrinfo) (struct my_addrinfo *); - -static p_getaddrinfo WS_getaddrinfo = NULL; -static p_freeaddrinfo WS_freeaddrinfo = NULL; - -static HMODULE WS_getfunctions(HMODULE tmp) -{ - if (tmp != NULL) - { - WS_getaddrinfo = (p_getaddrinfo)(LPVOID)GetProcAddress(tmp, "getaddrinfo"); - if (WS_getaddrinfo == NULL) - return NULL; - WS_freeaddrinfo = (p_freeaddrinfo)(LPVOID)GetProcAddress(tmp, "freeaddrinfo"); - if (WS_freeaddrinfo == NULL) - { - WS_getaddrinfo = NULL; - return NULL; - } - } - return tmp; -} - -static void WS_addrinfosetup(void) -{ - if (WS_getaddrinfo && WS_freeaddrinfo) - return; // already have the functions - // why not hold it into ipv6dll? becase we already link with ws2_32, silly! - if (WS_getfunctions(GetModuleHandleA("ws2_32.dll")) == NULL) - ipv6dll = WS_getfunctions(LoadLibraryA("wship6.dll")); -} - -void WS_addrinfocleanup(void) -{ - if (ipv6dll) - FreeLibrary(ipv6dll); - ipv6dll = NULL; - WS_getaddrinfo = NULL; - WS_freeaddrinfo = NULL; -} -#else -void WS_addrinfocleanup(void) {} -#endif - -int I_getaddrinfo(const char *node, const char *service, - const struct my_addrinfo *hints, - struct my_addrinfo **res) -{ - struct hostent *nodename = NULL; - bool hostlookup = true, passivemode = false; - int flags = 0; - int socktype = 0; - int sockport = 0; - struct my_addrinfo *ai; - struct sockaddr_in *addr; - struct in_addr ipv4; - size_t addrlen = 1; - size_t ailen = 1, i = 0, j; - size_t famsize = sizeof(struct sockaddr_in); -#ifdef USE_WINSOCK2 - WS_addrinfosetup(); - if (WS_getaddrinfo) - return WS_getaddrinfo(node, service, hints, res); -#endif - - // param check - if (node == NULL && service == NULL) - return EAI_NONAME; - //note: testcase show NULL as res crashes libc - if (res == NULL) - return -1; - - // check hints - if (hints) - { - // no support for IPv6 - if (hints->ai_family != AF_INET && hints->ai_family != AF_UNSPEC) - return -1; //EAI_FAMILY -#ifdef AI_NUMERICHOST - // do not look up hostnames - if ((hints->ai_flags & AI_NUMERICHOST) == AI_NUMERICHOST) - { - hostlookup = false; - flags |= AI_NUMERICHOST; - } -#endif -#ifdef AI_PASSIVE - // return loopback or any address? - if ((hints->ai_flags & AI_PASSIVE) == AI_PASSIVE) - { - passivemode = true; - flags |= AI_PASSIVE; - } -#endif - // why no support for canon names? lazy - //AI_CANONNAME - // what kind of socket? - socktype = hints->ai_socktype; - } - else - { -#ifdef AI_V4MAPPED - flags |= AI_V4MAPPED; -#endif -#ifdef AI_ADDRCONFIG - flags |= AI_ADDRCONFIG; -#endif - } - - // we need gethostbyname to convert numeric strings - if (node && hostlookup) - { - if (node == NULL) - return -1; - nodename = gethostbyname(node); - if (nodename == NULL) - { - if (inet_aton(node, &ipv4) != 0) - addrlen = 1; - else - return -1; - } - else while (nodename->h_addr_list[addrlen] != NULL) - addrlen++; - } - else if (node) - { - if (inet_aton(node, &ipv4) != 0) - addrlen = 1; - else if (!hostlookup) - return EAI_NONAME; - } - else - addrlen = 1; - - if (service) //AI_NUMERICSERV - sockport = atoi(service); - - if (socktype == 0) - ailen = addrlen*3; - else - ailen = addrlen; - - ai = calloc(ailen, sizeof(struct my_addrinfo)); - if (ai == NULL) - return -1; - else - *res = ai; - - addr = calloc(ailen*2, famsize); - if (addr == NULL) - { - free(ai); - return -1; - } - else - ai->ai_addr = memset(addr, 0x00, ailen*ai->ai_addrlen); - - for (i = 0; i < ailen; i++) - { - ai = *res+i; - ai->ai_flags = flags; - ai->ai_family = AF_INET; - ai->ai_socktype = socktype; - switch (ai->ai_socktype) - { - case SOCK_STREAM: - ai->ai_protocol = IPPROTO_TCP; - break; - case SOCK_DGRAM: - ai->ai_protocol = IPPROTO_UDP; - break; - default: - ai->ai_protocol = 0; - } - ai->ai_addrlen = famsize; - ai->ai_addr = (struct sockaddr *)&addr[i]; - //ai_cannonname - ai->ai_next = ai+1; - } - ai->ai_next = NULL; - ai = *res; - - for (i = 0, j = 0; i < ailen; i++, j++) - { - ai = *res+i; - addr[i].sin_port = htons((UINT16)sockport); - if (nodename) - { - memcpy(&addr[i].sin_addr, nodename->h_addr_list[j], ai->ai_addrlen); - addr[i].sin_family = nodename->h_addrtype; - } - else if (node) - { - memcpy(&addr[i].sin_addr, &ipv4, ai->ai_addrlen); - addr[i].sin_family = AF_INET; - } - else - { - if (passivemode) - addr[i].sin_addr.s_addr = htonl(INADDR_ANY); - else - addr[i].sin_addr.s_addr = htonl(INADDR_LOOPBACK); - addr[i].sin_family = AF_INET; - } - if (socktype == 0) - { - ai->ai_socktype = SOCK_STREAM; - ai->ai_protocol = IPPROTO_TCP; - memcpy(&addr[i+1], &addr[i], ai->ai_addrlen); - i++; ai++; - ai->ai_socktype = SOCK_DGRAM; - ai->ai_protocol = IPPROTO_UDP; - memcpy(&addr[i+1], &addr[i], ai->ai_addrlen); - i++; ai++; - ai->ai_socktype = SOCK_RAW; - ai->ai_protocol = IPPROTO_IP; - } - } - return 0; -} -#endif - -#ifndef I_freeaddrinfo -void I_freeaddrinfo(struct my_addrinfo *res) -{ -#ifdef USE_WINSOCK2 - if (WS_freeaddrinfo) - { - WS_freeaddrinfo(res); - return; - } -#endif - if (!res) - return; - free(res->ai_addr); - free(res); -} -#endif - -#ifdef TESTCASE -#include - -#ifdef USE_WINSOCK2 -#define inet_ntop inet_ntopA -#define HAVE_NTOP -static const char* inet_ntopA(int af, const void *cp, char *buf, socklen_t len) -{ - DWORD Dlen = len, AFlen = 0; - SOCKADDR_STORAGE any; - LPSOCKADDR anyp = (LPSOCKADDR)&any; - LPSOCKADDR_IN any4 = (LPSOCKADDR_IN)&any; - LPSOCKADDR_IN6 any6 = (LPSOCKADDR_IN6)&any; - - if (!buf) - { - WSASetLastError(STATUS_INVALID_PARAMETER); - return NULL; - } - - if (af != AF_INET && af != AF_INET6) - { - WSASetLastError(WSAEAFNOSUPPORT); - return NULL; - } - - ZeroMemory(&any, sizeof(SOCKADDR_STORAGE)); - any.ss_family = af; - - switch (af) - { - case AF_INET: - { - CopyMemory(&any4->sin_addr, cp, sizeof(IN_ADDR)); - AFlen = sizeof(SOCKADDR_IN); - break; - } - case AF_INET6: - { - CopyMemory(&any6->sin6_addr, cp, sizeof(IN6_ADDR)); - AFlen = sizeof(SOCKADDR_IN6); - break; - } - } - - if (WSAAddressToStringA(anyp, AFlen, NULL, buf, &Dlen) == SOCKET_ERROR) - return NULL; - return buf; -} -#elif defined (_WIN32) -// w32api, ws2tcpip.h, r1.12 -static inline char* gai_strerror(int ecode) -{ - static char message[1024+1]; - DWORD dwFlags = FORMAT_MESSAGE_FROM_SYSTEM - | FORMAT_MESSAGE_IGNORE_INSERTS - | FORMAT_MESSAGE_MAX_WIDTH_MASK; - DWORD dwLanguageId = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT); - FormatMessageA(dwFlags, NULL, ecode, dwLanguageId, message, 1024, NULL); - return message; -} -#else -#define HAVE_NTOP -#endif - -#ifndef INET_ADDRSTRLEN -#define INET_ADDRSTRLEN 16 -#endif - -static inline void printflags(int ai_flags) -{ - printf("flags: %x(", ai_flags); - if (ai_flags == 0) - printf("NONE|"); -#ifdef AI_PASSIVE - if ((ai_flags & AI_PASSIVE) == AI_PASSIVE) - printf("AI_PASSIVE|"); - ai_flags &= ~AI_PASSIVE; -#endif -#ifdef AI_CANONNAME - if ((ai_flags & AI_CANONNAME) == AI_CANONNAME) - printf("AI_CANONNAME|"); - ai_flags &= ~AI_CANONNAME; -#endif -#ifdef AI_NUMERICHOST - if ((ai_flags & AI_NUMERICHOST) == AI_NUMERICHOST) - printf("AI_NUMERICHOST|"); - ai_flags &= ~AI_NUMERICHOST; -#endif -#ifdef AI_V4MAPPED - if ((ai_flags & AI_V4MAPPED) == AI_V4MAPPED) - printf("AI_V4MAPPED|"); - ai_flags &= ~AI_V4MAPPED; -#endif -#ifdef AI_ALL - if ((ai_flags & AI_ALL) == AI_ALL) - printf("AI_ALL|"); - ai_flags &= ~AI_ALL; -#endif -#ifdef AI_ADDRCONFIG - if ((ai_flags & AI_ADDRCONFIG) == AI_ADDRCONFIG) - printf("AI_ADDRCONFIG|"); - ai_flags &= ~AI_ADDRCONFIG; -#endif -#ifdef AI_IDN - if ((ai_flags & AI_IDN) == AI_IDN) - printf("AI_IDN|"); - ai_flags &= ~AI_IDN; -#endif -#ifdef AI_CANONIDN - if ((ai_flags & AI_CANONIDN) == AI_CANONIDN) - printf("AI_CANONIDN|"); - ai_flags &= ~AI_CANONIDN; -#endif -#ifdef AI_IDN_ALLOW_UNASSIGNED - if ((ai_flags & AI_IDN_ALLOW_UNASSIGNED) == AI_IDN_ALLOW_UNASSIGNED) - printf("AI_IDN_ALLOW_UNASSIGNED|"); - ai_flags &= ~AI_IDN_ALLOW_UNASSIGNED; -#endif -#ifdef AI_IDN_USE_STD3_ASCII_RULES - if ((ai_flags & AI_IDN_USE_STD3_ASCII_RULES) == AI_IDN_USE_STD3_ASCII_RULES) - printf("AI_IDN_USE_STD3_ASCII_RULES|"); - ai_flags &= ~AI_PASSIVE; -#endif -#ifdef AI_NUMERICSERV - if ((ai_flags & AI_NUMERICSERV) == AI_NUMERICSERV) - printf("AI_NUMERICSERV|"); - ai_flags &= ~AI_NUMERICSERV; -#endif - printf("%x", ai_flags); - printf(")\n"); -} - -static inline void printsocktype(int ai_socktype) -{ - printf("socktype: %d(", ai_socktype); - switch (ai_socktype) - { - case 0: - printf("SOCK_ Woe32"); - break; - case SOCK_STREAM: - printf("SOCK_STREAM"); - break; - case SOCK_DGRAM: - printf("SOCK_DGRAM"); - break; - case SOCK_RAW: - printf("SOCK_RAW"); - break; - default: - printf("SOCK_ERROR\n"); - exit(-1); - } - printf(")\n"); -} - -static inline void printprotocol(int ai_protocol) -{ - printf("protocol: %d(", ai_protocol); - switch (ai_protocol) - { - case IPPROTO_IP: - printf("IPPROTO_IP"); - break; - case IPPROTO_TCP: - printf("IPPROTO_TCP"); - break; - case IPPROTO_UDP: - printf("IPPROTO_UDP"); - break; - default: - printf("IPPROTO_ERROR\n"); - exit(-1); - } - printf(")\n"); -} - -static inline void printaddr(int ai_family, const struct sockaddr *ai_addr) -{ - char str[INET_ADDRSTRLEN+1] = "FAKE"; - printf("family: %d(", ai_family); - switch (ai_family) - { - case AF_UNSPEC: - printf("AF_UNSPEC"); - break; - case AF_INET: - printf("AF_INET"); - break; -#ifdef AF_INET6 - case AF_INET6: - printf("AF_INET6"); - break; -#endif - default: - printf("AF_ERROR\n"); - exit(-1); - } - printf(")\n"); - if (ai_family == AF_INET && ai_addr) - { - const struct sockaddr_in *ip4 = (void *)ai_addr; -#ifdef HAVE_NTOP - inet_ntop(ai_family, &ip4->sin_addr, str, INET_ADDRSTRLEN); -#else - strncpy(str, inet_ntoa(ip4->sin_addr), INET_ADDRSTRLEN); -#endif - printf("port: %d\n", ntohs(ip4->sin_port)); - } - printf("addr: %s\n", str); -} - -void printaddrinfo(const struct my_addrinfo *data) -{ - if(data == NULL) - { - printf("no data\n"); - return; - } - else - printf("starting addrinfo dump\n"); - while (data != NULL) - { - printflags(data->ai_flags); - printsocktype(data->ai_socktype); - printaddr(data->ai_family, data->ai_addr); - printprotocol(data->ai_protocol); - //addrlen - data = data->ai_next; - } -} - -int main(int argc, char **argv) -{ - struct my_addrinfo *res = NULL, hints; - int gaie; - - (void)argc; - (void)argv; - memset(&hints, 0x00, sizeof(struct my_addrinfo)); - hints.ai_family = AF_INET; - -#ifdef _WIN32 - { -#ifdef USE_WINSOCK2 - const WORD VerNeed = MAKEWORD(2,2); -#else - const WORD VerNeed = MAKEWORD(1,1); -#endif - WSADATA WSAData; - WSAStartup(VerNeed, &WSAData); - } -#endif - printf("-----------------------------------------------------------\n"); -#ifndef _WIN32 //NULL as res crashes Win32 - gaie = I_getaddrinfo(NULL, NULL, &hints, NULL); - if (gaie != EAI_NONAME) - printf("NULLs test returned: %s(%d)\n", gai_strerror(gaie), gaie); - I_freeaddrinfo(res); -#endif -#if 0 //NULL as res crashes - gaie = I_getaddrinfo("localhost", "5029", NULL, NULL); - if (gaie == 0) - printf("NULL crashes: %s(%d)\n", gai_strerror(gaie), gaie); - I_freeaddrinfo(res); -#endif - gaie = I_getaddrinfo("localhost", NULL, &hints, &res); - //if (gaie != 0) - printf("NULL service test returned: %s(%d)\n", gai_strerror(gaie), gaie); - printaddrinfo(res); - I_freeaddrinfo(res); res = NULL; - gaie = I_getaddrinfo(NULL, "5029", &hints, &res); - //if (gaie != 0) - printf("NULLs test returned: %s(%d)\n", gai_strerror(gaie), gaie); - printaddrinfo(res); - I_freeaddrinfo(res); res = NULL; - gaie = I_getaddrinfo("localhost", "5029", &hints, &res); - //if (gaie != 0) - printf("no hints test returned: %s(%d)\n", gai_strerror(gaie), gaie); - printaddrinfo(res); - I_freeaddrinfo(res); res = NULL; - printf("-----------------------------------------------------------\n"); - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - gaie = I_getaddrinfo("localhost", NULL, &hints, &res); - //if (gaie != 0) - printf("NULL service test returned: %s(%d)\n", gai_strerror(gaie), gaie); - printaddrinfo(res); - I_freeaddrinfo(res); res = NULL; - gaie = I_getaddrinfo(NULL, "5029", &hints, &res); - //if (gaie != 0) - printf("NULLs test returned: %s(%d)\n", gai_strerror(gaie), gaie); - printaddrinfo(res); - I_freeaddrinfo(res); res = NULL; - gaie = I_getaddrinfo("localhost", "5029", &hints, &res); - //if (gaie != 0) - printf("no hints test returned: %s(%d)\n", gai_strerror(gaie), gaie); - printaddrinfo(res); - I_freeaddrinfo(res); res = NULL; - printf("-----------------------------------------------------------\n"); - hints.ai_socktype = SOCK_DGRAM; - hints.ai_protocol = IPPROTO_UDP; - gaie = I_getaddrinfo("localhost", NULL, &hints, &res); - //if (gaie != 0) - printf("NULL service test returned: %s(%d)\n", gai_strerror(gaie), gaie); - printaddrinfo(res); - I_freeaddrinfo(res); res = NULL; - gaie = I_getaddrinfo(NULL, "5029", &hints, &res); - //if (gaie != 0) - printf("NULLs test returned: %s(%d)\n", gai_strerror(gaie), gaie); - printaddrinfo(res); - I_freeaddrinfo(res); res = NULL; - gaie = I_getaddrinfo("localhost", "5029", &hints, &res); - //if (gaie != 0) - printf("no hints test returned: %s(%d)\n", gai_strerror(gaie), gaie); - printaddrinfo(res); - I_freeaddrinfo(res); res = NULL; - printf("-----------------------------------------------------------\n"); - hints.ai_flags = AI_NUMERICHOST; - gaie = I_getaddrinfo("localhost", NULL, &hints, &res); - //if (gaie != 0) - printf("NULL service test returned: %s(%d)\n", gai_strerror(gaie), gaie); - printaddrinfo(res); - I_freeaddrinfo(res); res = NULL; - gaie = I_getaddrinfo(NULL, "5029", &hints, &res); - //if (gaie != 0) - printf("NULLs test returned: %s(%d)\n", gai_strerror(gaie), gaie); - printaddrinfo(res); - I_freeaddrinfo(res); res = NULL; - gaie = I_getaddrinfo("localhost", "5029", &hints, &res); - //if (gaie != 0) - printf("no hints test returned: %s(%d)\n", gai_strerror(gaie), gaie); - printaddrinfo(res); - I_freeaddrinfo(res); res = NULL; - printf("-----------------------------------------------------------\n"); - gaie = I_getaddrinfo("127.0.0.1", NULL, &hints, &res); - //if (gaie != 0) - printf("NULL service test returned: %s(%d)\n", gai_strerror(gaie), gaie); - printaddrinfo(res); - I_freeaddrinfo(res); res = NULL; - gaie = I_getaddrinfo("127.0.0.1", "5029", &hints, &res); - //if (gaie != 0) - printf("no hints test returned: %s(%d)\n", gai_strerror(gaie), gaie); - printaddrinfo(res); - I_freeaddrinfo(res); res = NULL; - printf("-----------------------------------------------------------\n"); - gaie = I_getaddrinfo("255.255.255.255", NULL, &hints, &res); - //if (gaie != 0) - printf("NULL service test returned: %s(%d)\n", gai_strerror(gaie), gaie); - printaddrinfo(res); - I_freeaddrinfo(res); res = NULL; - gaie = I_getaddrinfo("255.255.255.255", "5029", &hints, &res); - //if (gaie != 0) - printf("no hints test returned: %s(%d)\n", gai_strerror(gaie), gaie); - printaddrinfo(res); - I_freeaddrinfo(res); res = NULL; - printf("-----------------------------------------------------------\n"); - hints.ai_flags = AI_PASSIVE; - gaie = I_getaddrinfo("0.0.0.0", NULL, &hints, &res); - //if (gaie != 0) - printf("NULL service test returned: %s(%d)\n", gai_strerror(gaie), gaie); - printaddrinfo(res); - I_freeaddrinfo(res); res = NULL; - gaie = I_getaddrinfo("0.0.0.0", "5029", &hints, &res); - //if (gaie != 0) - printf("no hints test returned: %s(%d)\n", gai_strerror(gaie), gaie); - printaddrinfo(res); - I_freeaddrinfo(res); res = NULL; - return 0; -} -#endif diff --git a/src/i_addrinfo.h b/src/i_addrinfo.h deleted file mode 100644 index 7c3afc614..000000000 --- a/src/i_addrinfo.h +++ /dev/null @@ -1,71 +0,0 @@ -// SONIC ROBO BLAST 2 -//----------------------------------------------------------------------------- -// Copyright (C) 2011-2018 by Sonic Team Junior. -// -// This program is free software distributed under the -// terms of the GNU General Public License, version 2. -// See the 'LICENSE' file for more details. -//----------------------------------------------------------------------------- -/// \file i_addrinfo.h -/// \brief getaddrinfo stub - -#ifndef __I_ADDRINFO__ -#define __I_ADDRINFO__ - -#ifdef __GNUG__ -#pragma interface -#endif - -#ifndef AI_PASSIVE -#define AI_PASSIVE 0x01 -#endif -#ifndef AI_NUMERICHOST -#define AI_NUMERICHOST 0x04 -#endif -#ifndef AI_V4MAPPED -#define AI_V4MAPPED 0x08 -#endif -#ifndef AI_ADDRCONFIG -#define AI_ADDRCONFIG 0x20 -#endif - -#ifdef _WIN32 -#ifndef EAI_NONAME -#define EAI_NONAME WSAHOST_NOT_FOUND -#endif -#endif - -#ifndef EAI_NONAME -#define EAI_NONAME -2 -#endif - -#ifdef _WIN32 // already use the stub for Win32 -// w32api, ws2tcpip.h, r1.12 -struct my_addrinfo { - int ai_flags; - int ai_family; - int ai_socktype; - int ai_protocol; - size_t ai_addrlen; - char *ai_canonname; - struct sockaddr *ai_addr; - struct my_addrinfo *ai_next; -}; -#else -#define my_addrinfo addrinfo -#endif - -void WS_addrinfocleanup(void); - -#ifndef my_addrinfo -void I_freeaddrinfo(struct my_addrinfo *res); -int I_getaddrinfo(const char *node, const char *service, - const struct my_addrinfo *hints, - struct my_addrinfo **res); -#elif !defined (test_stub) -#define I_getaddrinfo getaddrinfo -#define I_freeaddrinfo freeaddrinfo -#endif - - -#endif diff --git a/src/i_tcp.c b/src/i_tcp.c index f6152e3cd..09cba908f 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -29,42 +29,36 @@ #ifdef _WIN32 #define USE_WINSOCK -#if defined (_WIN64) || defined (HAVE_IPV6) -#define USE_WINSOCK2 -#else //_WIN64/HAVE_IPV6 -#define USE_WINSOCK1 -#endif #endif //WIN32 OS -#ifdef USE_WINSOCK2 +#ifdef USE_WINSOCK #include +#define addrinfo_t ADDRINFOA +#else +#define addrinfo_t struct addrinfo #endif #include "doomdef.h" +#ifndef USE_WINSOCK + #include + #ifdef __APPLE_CC__ + #ifndef _BSD_SOCKLEN_T_ + #define _BSD_SOCKLEN_T_ + #endif //_BSD_SOCKLEN_T_ + #endif //__APPLE_CC__ + #include + #include + #include + #include +#endif //normal BSD API + +#include #include -#ifdef USE_WINSOCK1 - #include -#else - #ifndef USE_WINSOCK - #include - #ifdef __APPLE_CC__ - #ifndef _BSD_SOCKLEN_T_ - #define _BSD_SOCKLEN_T_ - #endif //_BSD_SOCKLEN_T_ - #endif //__APPLE_CC__ - #include - #include - #include - #include - #endif //normal BSD API - #include - - #if defined (__unix__) || defined (__APPLE__) || defined (UNIXCOMMON) - #include - #endif // UNIXCOMMON -#endif +#if defined (__unix__) || defined (__APPLE__) || defined (UNIXCOMMON) + #include +#endif // UNIXCOMMON #ifdef USE_WINSOCK // some undefined under win32 @@ -152,7 +146,6 @@ static UINT8 UPNP_support = TRUE; #define close closesocket #endif -#include "i_addrinfo.h" #define DEFAULTPORT "5029" #if defined (USE_WINSOCK) @@ -169,10 +162,6 @@ typedef unsigned long SOCKET_TYPE; #define IPV6_MULTICAST_ADDRESS "ff15::57e1:1a12" -#ifdef USE_WINSOCK1 -typedef int socklen_t; -#endif - typedef struct { mysockaddr_t address; @@ -232,9 +221,8 @@ static char *get_WSAErrorStr(int e) #define strerror get_WSAErrorStr #endif -#ifdef USE_WINSOCK2 +#ifdef USE_WINSOCK #define inet_ntop inet_ntopA -#define HAVE_NTOP static const char* inet_ntopA(short af, const void *cp, char *buf, socklen_t len) { DWORD Dlen = len, AFlen = 0; @@ -278,8 +266,6 @@ static const char* inet_ntopA(short af, const void *cp, char *buf, socklen_t len return NULL; return buf; } -#elif !defined (USE_WINSOCK1) -#define HAVE_NTOP #endif #ifdef HAVE_MINIUPNPC // based on old XChat patch @@ -360,7 +346,6 @@ static const char *SOCK_AddrToStr(mysockaddr_t *sk) static char s[64]; // 255.255.255.255:65535 or // [ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535 -#ifdef HAVE_NTOP #ifdef HAVE_IPV6 int v6 = (sk->any.sa_family == AF_INET6); #else @@ -398,15 +383,7 @@ static const char *SOCK_AddrToStr(mysockaddr_t *sk) #endif else if(sk->any.sa_family == AF_INET && sk->ip4.sin_port != 0) strcat(s, va(":%d", ntohs(sk->ip4.sin_port))); -#else - if (sk->any.sa_family == AF_INET) - { - strcpy(s, inet_ntoa(sk->ip4.sin_addr)); - if (sk->ip4.sin_port != 0) strcat(s, va(":%d", ntohs(sk->ip4.sin_port))); - } - else - sprintf(s, "Unknown type"); -#endif + return s; } @@ -868,15 +845,11 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen #ifdef USE_WINSOCK { // Alam_GBC: disable the new UDP connection reset behavior for Win2k and up -#ifdef USE_WINSOCK2 DWORD dwBytesReturned = 0; BOOL bfalse = FALSE; rc = WSAIoctl(s, SIO_UDP_CONNRESET, &bfalse, sizeof(bfalse), NULL, 0, &dwBytesReturned, NULL, NULL); -#else - unsigned long falseval = false; - rc = ioctl(s, SIO_UDP_CONNRESET, &falseval); -#endif + if (rc == -1) { e = errno; @@ -1046,7 +1019,7 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen static boolean UDP_Socket(void) { size_t s; - struct my_addrinfo *ai, *runp, hints; + addrinfo_t *ai, *runp, hints; int gaie; #ifdef HAVE_IPV6 const INT32 b_ipv6 = M_CheckParm("-ipv6"); @@ -1075,7 +1048,7 @@ static boolean UDP_Socket(void) { while (M_IsNextParm()) { - gaie = I_getaddrinfo(M_GetNextParm(), serv, &hints, &ai); + gaie = getaddrinfo(M_GetNextParm(), serv, &hints, &ai); if (gaie == 0) { runp = ai; @@ -1089,13 +1062,13 @@ static boolean UDP_Socket(void) } runp = runp->ai_next; } - I_freeaddrinfo(ai); + freeaddrinfo(ai); } } } else { - gaie = I_getaddrinfo("0.0.0.0", serv, &hints, &ai); + gaie = getaddrinfo("0.0.0.0", serv, &hints, &ai); if (gaie == 0) { runp = ai; @@ -1116,7 +1089,7 @@ static boolean UDP_Socket(void) } runp = runp->ai_next; } - I_freeaddrinfo(ai); + freeaddrinfo(ai); } } @@ -1128,7 +1101,7 @@ static boolean UDP_Socket(void) { while (M_IsNextParm()) { - gaie = I_getaddrinfo(M_GetNextParm(), serv, &hints, &ai); + gaie = getaddrinfo(M_GetNextParm(), serv, &hints, &ai); if (gaie == 0) { runp = ai; @@ -1142,13 +1115,13 @@ static boolean UDP_Socket(void) } runp = runp->ai_next; } - I_freeaddrinfo(ai); + freeaddrinfo(ai); } } } else { - gaie = I_getaddrinfo("::", serv, &hints, &ai); + gaie = getaddrinfo("::", serv, &hints, &ai); if (gaie == 0) { runp = ai; @@ -1162,7 +1135,7 @@ static boolean UDP_Socket(void) } runp = runp->ai_next; } - I_freeaddrinfo(ai); + freeaddrinfo(ai); } } } @@ -1216,11 +1189,7 @@ boolean I_InitTcpDriver(void) if (!init_tcp_driver) { #ifdef USE_WINSOCK -#ifdef USE_WINSOCK2 const WORD VerNeed = MAKEWORD(2,2); -#else - const WORD VerNeed = MAKEWORD(1,1); -#endif WSADATA WSAData; const int WSAresult = WSAStartup(VerNeed, &WSAData); if (WSAresult != 0) @@ -1247,21 +1216,14 @@ boolean I_InitTcpDriver(void) if (WSAresult != WSAVERNOTSUPPORTED) CONS_Debug(DBG_NETPLAY, "WinSock(TCP/IP) error: %s\n",WSError); } -#ifdef USE_WINSOCK2 - if(LOBYTE(WSAData.wVersion) != 2 || + + if (LOBYTE(WSAData.wVersion) != 2 || HIBYTE(WSAData.wVersion) != 2) { WSACleanup(); CONS_Debug(DBG_NETPLAY, "No WinSock(TCP/IP) 2.2 driver detected\n"); } -#else - if (LOBYTE(WSAData.wVersion) != 1 || - HIBYTE(WSAData.wVersion) != 1) - { - WSACleanup(); - CONS_Debug(DBG_NETPLAY, "No WinSock(TCP/IP) 1.1 driver detected\n"); - } -#endif + CONS_Debug(DBG_NETPLAY, "WinSock description: %s\n",WSAData.szDescription); CONS_Debug(DBG_NETPLAY, "WinSock System Status: %s\n",WSAData.szSystemStatus); #endif @@ -1301,7 +1263,6 @@ void I_ShutdownTcpDriver(void) CONS_Printf("I_ShutdownTcpDriver: "); #ifdef USE_WINSOCK - WS_addrinfocleanup(); WSACleanup(); #endif CONS_Printf("shut down\n"); @@ -1310,24 +1271,24 @@ void I_ShutdownTcpDriver(void) static boolean SOCK_GetAddr(struct sockaddr_in *sin, const char *address, const char *port, boolean test) { - struct my_addrinfo *ai = NULL, *runp, hints; + addrinfo_t *ai = NULL, *runp, hints; int gaie; size_t i; if (!port || !port[0]) port = DEFAULTPORT; - memset (&hints, 0x00, sizeof (hints)); + memset(&hints, 0x00, sizeof (hints)); hints.ai_flags = AI_ADDRCONFIG; hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; - gaie = I_getaddrinfo(address, port, &hints, &ai); + gaie = getaddrinfo(address, port, &hints, &ai); if (gaie != 0) { - I_freeaddrinfo(ai); + freeaddrinfo(ai); return false; } @@ -1356,7 +1317,7 @@ static boolean SOCK_GetAddr(struct sockaddr_in *sin, const char *address, const if (runp != NULL) memcpy(sin, runp->ai_addr, runp->ai_addrlen); - I_freeaddrinfo(ai); + freeaddrinfo(ai); return (runp != NULL); } @@ -1554,7 +1515,7 @@ static boolean SOCK_SetUnbanTime(time_t timestamp) static boolean SOCK_SetBanAddress(const char *address, const char *mask) { - struct my_addrinfo *ai, *runp, hints; + addrinfo_t *ai, *runp, hints; int gaie; if (!address) @@ -1566,7 +1527,7 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask) hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; - gaie = I_getaddrinfo(address, "0", &hints, &ai); + gaie = getaddrinfo(address, "0", &hints, &ai); if (gaie != 0) return false; @@ -1611,7 +1572,7 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask) runp = runp->ai_next; } - I_freeaddrinfo(ai); + freeaddrinfo(ai); return true; } @@ -1660,8 +1621,6 @@ boolean I_InitTcpNetwork(void) // FIXME: for dedicated server, numnodes needs to be set to 0 upon start if (dedicated) doomcom->numnodes = 0; -/* else if (M_IsNextParm()) - doomcom->numnodes = (INT16)atoi(M_GetNextParm());*/ else doomcom->numnodes = 1; @@ -1746,5 +1705,3 @@ boolean I_InitTcpNetwork(void) return ret; } - -#include "i_addrinfo.c" -- 2.54.0 From 951c090b35b6096fbafd316bbff2a50bddaebfe6 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sat, 12 Apr 2025 15:24:54 +0000 Subject: [PATCH 083/219] set CURLOPT_MAXREDIRS to 30 --- src/http-mserv.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/http-mserv.c b/src/http-mserv.c index 18690f28a..8e35f905d 100644 --- a/src/http-mserv.c +++ b/src/http-mserv.c @@ -253,6 +253,9 @@ HMS_connect (const char *format, ...) cc = curl_easy_setopt(curl, CURLOPT_TIMEOUT, (long)cv_masterserver_timeout.value); if (cc != CURLE_OK) I_OutputMsg("libcurl: %s\n", buffer->errbuf); + cc = curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 30L); + if (cc != CURLE_OK) I_OutputMsg("libcurl: %s\n", buffer->errbuf); + cc = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HMS_on_read); if (cc != CURLE_OK) I_OutputMsg("libcurl: %s\n", buffer->errbuf); -- 2.54.0 From e180918e48c70eff5b86309fab41d35f8e8a1c45 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sat, 30 Aug 2025 13:22:56 +0200 Subject: [PATCH 084/219] Do not archive nil table keys --- src/lua_script.c | 68 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 58 insertions(+), 10 deletions(-) diff --git a/src/lua_script.c b/src/lua_script.c index cd9ba1f85..a7ce910ba 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -797,8 +797,12 @@ static UINT8 ArchiveValue(UINT8 **p, int TABLESINDEX, int myindex) { mobj_t *mobj = *((mobj_t **)lua_touserdata(gL, myindex)); if (!mobj) + { WRITEUINT8(*p, ARCH_NULL); - else { + return 3; + } + else + { WRITEUINT8(*p, ARCH_MOBJ); WRITEUINT32(*p, mobj->mobjnum); } @@ -808,8 +812,12 @@ static UINT8 ArchiveValue(UINT8 **p, int TABLESINDEX, int myindex) { player_t *player = *((player_t **)lua_touserdata(gL, myindex)); if (!player) + { WRITEUINT8(*p, ARCH_NULL); - else { + return 3; + } + else + { WRITEUINT8(*p, ARCH_PLAYER); WRITEUINT8(*p, player - players); } @@ -819,8 +827,12 @@ static UINT8 ArchiveValue(UINT8 **p, int TABLESINDEX, int myindex) { mapthing_t *mapthing = *((mapthing_t **)lua_touserdata(gL, myindex)); if (!mapthing) + { WRITEUINT8(*p, ARCH_NULL); - else { + return 3; + } + else + { WRITEUINT8(*p, ARCH_MAPTHING); WRITEUINT16(*p, mapthing - mapthings); } @@ -830,8 +842,12 @@ static UINT8 ArchiveValue(UINT8 **p, int TABLESINDEX, int myindex) { vertex_t *vertex = *((vertex_t **)lua_touserdata(gL, myindex)); if (!vertex) + { WRITEUINT8(*p, ARCH_NULL); - else { + return 3; + } + else + { WRITEUINT8(*p, ARCH_VERTEX); WRITEUINT16(*p, vertex - vertexes); } @@ -841,8 +857,12 @@ static UINT8 ArchiveValue(UINT8 **p, int TABLESINDEX, int myindex) { line_t *line = *((line_t **)lua_touserdata(gL, myindex)); if (!line) + { WRITEUINT8(*p, ARCH_NULL); - else { + return 3; + } + else + { WRITEUINT8(*p, ARCH_LINE); WRITEUINT16(*p, line - lines); } @@ -852,8 +872,12 @@ static UINT8 ArchiveValue(UINT8 **p, int TABLESINDEX, int myindex) { side_t *side = *((side_t **)lua_touserdata(gL, myindex)); if (!side) + { WRITEUINT8(*p, ARCH_NULL); - else { + return 3; + } + else + { WRITEUINT8(*p, ARCH_SIDE); WRITEUINT16(*p, side - sides); } @@ -863,8 +887,12 @@ static UINT8 ArchiveValue(UINT8 **p, int TABLESINDEX, int myindex) { subsector_t *subsector = *((subsector_t **)lua_touserdata(gL, myindex)); if (!subsector) + { WRITEUINT8(*p, ARCH_NULL); - else { + return 3; + } + else + { WRITEUINT8(*p, ARCH_SUBSECTOR); WRITEUINT16(*p, subsector - subsectors); } @@ -874,8 +902,12 @@ static UINT8 ArchiveValue(UINT8 **p, int TABLESINDEX, int myindex) { sector_t *sector = *((sector_t **)lua_touserdata(gL, myindex)); if (!sector) + { WRITEUINT8(*p, ARCH_NULL); - else { + return 3; + } + else + { WRITEUINT8(*p, ARCH_SECTOR); WRITEUINT16(*p, sector - sectors); } @@ -885,8 +917,12 @@ static UINT8 ArchiveValue(UINT8 **p, int TABLESINDEX, int myindex) { pslope_t *slope = *((pslope_t **)lua_touserdata(gL, myindex)); if (!slope) + { WRITEUINT8(*p, ARCH_NULL); - else { + return 3; + } + else + { WRITEUINT8(*p, ARCH_SLOPE); WRITEUINT16(*p, slope->id); } @@ -896,8 +932,12 @@ static UINT8 ArchiveValue(UINT8 **p, int TABLESINDEX, int myindex) { mapheader_t *header = *((mapheader_t **)lua_touserdata(gL, myindex)); if (!header) + { WRITEUINT8(*p, ARCH_NULL); - else { + return 3; + } + else + { WRITEUINT8(*p, ARCH_MAPHEADER); WRITEUINT16(*p, header - *mapheaderinfo); } @@ -1007,10 +1047,18 @@ static void ArchiveTables(UINT8 **p) CONS_Alert(CONS_ERROR, "Index '%s' (%s) of table %d could not be archived!\n", lua_tostring(gL, -1), luaL_typename(gL, -1), i); lua_pop(gL, 1); } + else if (e == 3) // nil key due to invalid userdata. NOT an error. + { + lua_pop(gL, 1); + continue; + } + // Write value e = ArchiveValue(p, TABLESINDEX, -1); if (e == 1) + { n++; // the table contained a new table we'll have to archive. :( + } else if (e == 2) // invalid value type { lua_pushvalue(gL, -2); -- 2.54.0 From 68f69049d44e5fe3f691d8059950c087241c5d95 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Tue, 10 Aug 2021 00:15:44 +0200 Subject: [PATCH 085/219] Fix incorrect error message during Lua archiving --- src/lua_script.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/lua_script.c b/src/lua_script.c index a7ce910ba..723624ee2 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -1043,9 +1043,7 @@ static void ArchiveTables(UINT8 **p) e = ArchiveValue(p, TABLESINDEX, -2); // key should be either a number or a string, ArchiveValue can handle this. if (e == 2) // invalid key type (function, thread, lightuserdata, or anything we don't recognise) { - lua_pushvalue(gL, -2); - CONS_Alert(CONS_ERROR, "Index '%s' (%s) of table %d could not be archived!\n", lua_tostring(gL, -1), luaL_typename(gL, -1), i); - lua_pop(gL, 1); + CONS_Alert(CONS_ERROR, "Index '%s' (%s) of table %d could not be archived!\n", lua_tostring(gL, -2), luaL_typename(gL, -2), i); } else if (e == 3) // nil key due to invalid userdata. NOT an error. { @@ -1061,9 +1059,7 @@ static void ArchiveTables(UINT8 **p) } else if (e == 2) // invalid value type { - lua_pushvalue(gL, -2); - CONS_Alert(CONS_ERROR, "Type of value for table %d entry '%s' (%s) could not be archived!\n", i, lua_tostring(gL, -1), luaL_typename(gL, -1)); - lua_pop(gL, 1); + CONS_Alert(CONS_ERROR, "Type of value for table %d entry '%s' (%s) could not be archived!\n", i, lua_tostring(gL, -2), luaL_typename(gL, -1)); } lua_pop(gL, 1); -- 2.54.0 From ae456fee3158ab691fa447d2064a5db3c581c0c5 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 15 Oct 2025 17:02:24 +0200 Subject: [PATCH 086/219] force inline savegame archive stuff --- src/p_saveg.c | 64 +++++++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index a4b343554..d158cf91b 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -61,7 +61,7 @@ typedef enum // // P_ArchivePlayer // -static inline void P_ArchivePlayer(savebuffer_t *save) +FUNCINLINE static ATTRINLINE void P_ArchivePlayer(savebuffer_t *save) { const player_t *player = &players[consoleplayer]; INT32 pllives = player->lives; @@ -85,7 +85,7 @@ static inline void P_ArchivePlayer(savebuffer_t *save) // // P_UnArchivePlayer // -static inline void P_UnArchivePlayer(savebuffer_t *save) +FUNCINLINE static ATTRINLINE void P_UnArchivePlayer(savebuffer_t *save) { savedata.skincolor = READUINT8(save->p); savedata.skin = READUINT8(save->p); @@ -1043,25 +1043,25 @@ typedef enum tc_end } specials_e; -static inline UINT32 SaveMobjnum(const mobj_t *mobj) +FUNCINLINE static ATTRINLINE UINT32 SaveMobjnum(const mobj_t *mobj) { if (mobj) return mobj->mobjnum; return 0; } -static inline UINT32 SaveSector(const sector_t *sector) +FUNCINLINE static ATTRINLINE UINT32 SaveSector(const sector_t *sector) { if (sector) return (UINT32)(sector - sectors); return 0xFFFFFFFF; } -static inline UINT32 SaveLine(const line_t *line) +FUNCINLINE static ATTRINLINE UINT32 SaveLine(const line_t *line) { if (line) return (UINT32)(line - lines); return 0xFFFFFFFF; } -static inline UINT32 SavePlayer(const player_t *player) +FUNCINLINE static ATTRINLINE UINT32 SavePlayer(const player_t *player) { if (player) return (UINT32)(player - players); return 0xFFFFFFFF; @@ -1476,7 +1476,7 @@ static void SaveElevatorThinker(savebuffer_t *save, const thinker_t *th, const U // // Saves a scroll_t thinker // -static inline void SaveScrollThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +FUNCINLINE static ATTRINLINE void SaveScrollThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) { const scroll_t *ht = (const void *)th; WRITEUINT8(save->p, type); @@ -1497,7 +1497,7 @@ static inline void SaveScrollThinker(savebuffer_t *save, const thinker_t *th, co // // Saves a friction_t thinker // -static inline void SaveFrictionThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +FUNCINLINE static ATTRINLINE void SaveFrictionThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) { const friction_t *ht = (const void *)th; WRITEUINT8(save->p, type); @@ -1513,7 +1513,7 @@ static inline void SaveFrictionThinker(savebuffer_t *save, const thinker_t *th, // // Saves a pusher_t thinker // -static inline void SavePusherThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +FUNCINLINE static ATTRINLINE void SavePusherThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) { const pusher_t *ht = (const void *)th; WRITEUINT8(save->p, type); @@ -1598,7 +1598,7 @@ static void SaveDisappearThinker(savebuffer_t *save, const thinker_t *th, const // // Saves a polyrotate_t thinker // -static inline void SavePolyrotatetThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +FUNCINLINE static ATTRINLINE void SavePolyrotatetThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) { const polyrotate_t *ht = (const void *)th; WRITEUINT8(save->p, type); @@ -1935,25 +1935,25 @@ mobj_t *P_FindNewPosition(UINT32 oldposition) return NULL; } -static inline mobj_t *LoadMobj(UINT32 mobjnum) +FUNCINLINE static ATTRINLINE mobj_t *LoadMobj(UINT32 mobjnum) { if (mobjnum == 0) return NULL; return (mobj_t *)(size_t)mobjnum; } -static inline sector_t *LoadSector(UINT32 sector) +FUNCINLINE static ATTRINLINE sector_t *LoadSector(UINT32 sector) { if (sector >= numsectors) return NULL; return §ors[sector]; } -static inline line_t *LoadLine(UINT32 line) +FUNCINLINE static ATTRINLINE line_t *LoadLine(UINT32 line) { if (line >= numlines) return NULL; return &lines[line]; } -static inline player_t *LoadPlayer(UINT32 player) +FUNCINLINE static ATTRINLINE player_t *LoadPlayer(UINT32 player) { if (player >= MAXPLAYERS) return NULL; return &players[player]; @@ -2529,7 +2529,7 @@ static void LoadScrollThinker(savebuffer_t *save, actionf_p1 thinker) // // Loads a friction_t from a save game // -static inline void LoadFrictionThinker(savebuffer_t *save, actionf_p1 thinker) +FUNCINLINE static ATTRINLINE void LoadFrictionThinker(savebuffer_t *save, actionf_p1 thinker) { friction_t *ht = (friction_t*)Z_LevelPoolMalloc(sizeof (*ht)); ht->thinker.alloctype = TAT_LEVELPOOL; @@ -2576,7 +2576,7 @@ static void LoadPusherThinker(savebuffer_t *save, actionf_p1 thinker) // // Loads a laserthink_t from a save game // -static inline void LoadLaserThinker(savebuffer_t *save, actionf_p1 thinker) +FUNCINLINE static ATTRINLINE void LoadLaserThinker(savebuffer_t *save, actionf_p1 thinker) { laserthink_t *ht = (laserthink_t*)Z_LevelPoolMalloc(sizeof (*ht)); ht->thinker.alloctype = TAT_LEVELPOOL; @@ -2621,7 +2621,7 @@ FUNCINLINE static ATTRINLINE void LoadLightlevelThinker(savebuffer_t *save, acti // // Loads a executor_t from a save game // -static inline void LoadExecutorThinker(savebuffer_t *save, actionf_p1 thinker) +FUNCINLINE static ATTRINLINE void LoadExecutorThinker(savebuffer_t *save, actionf_p1 thinker) { executor_t *ht = (executor_t*)Z_LevelPoolMalloc(sizeof (*ht)); ht->thinker.alloctype = TAT_LEVELPOOL; @@ -2639,7 +2639,7 @@ static inline void LoadExecutorThinker(savebuffer_t *save, actionf_p1 thinker) // // Loads a disappear_t thinker // -static inline void LoadDisappearThinker(savebuffer_t *save, actionf_p1 thinker) +FUNCINLINE static ATTRINLINE void LoadDisappearThinker(savebuffer_t *save, actionf_p1 thinker) { disappear_t *ht = (disappear_t*)Z_LevelPoolMalloc(sizeof (*ht)); ht->thinker.alloctype = TAT_LEVELPOOL; @@ -2660,7 +2660,7 @@ static inline void LoadDisappearThinker(savebuffer_t *save, actionf_p1 thinker) // // Loads a polyrotate_t thinker // -static inline void LoadPolyrotatetThinker(savebuffer_t *save, actionf_p1 thinker) +FUNCINLINE static ATTRINLINE void LoadPolyrotatetThinker(savebuffer_t *save, actionf_p1 thinker) { polyrotate_t *ht = (polyrotate_t*)Z_LevelPoolMalloc(sizeof (*ht)); ht->thinker.alloctype = TAT_LEVELPOOL; @@ -2720,7 +2720,7 @@ static void LoadPolymoveThinker(savebuffer_t *save, actionf_p1 thinker) // // Loads a polywaypoint_t thinker // -static inline void LoadPolywaypointThinker(savebuffer_t *save, actionf_p1 thinker) +FUNCINLINE static ATTRINLINE void LoadPolywaypointThinker(savebuffer_t *save, actionf_p1 thinker) { polywaypoint_t *ht = (polywaypoint_t*)Z_LevelPoolMalloc(sizeof (*ht)); ht->thinker.alloctype = TAT_LEVELPOOL; @@ -2776,7 +2776,7 @@ static inline void LoadPolywaypointThinker(savebuffer_t *save, actionf_p1 thinke // // loads a polyslidedoor_t thinker // -static inline void LoadPolyslidedoorThinker(savebuffer_t *save, actionf_p1 thinker) +FUNCINLINE static ATTRINLINE void LoadPolyslidedoorThinker(savebuffer_t *save, actionf_p1 thinker) { polyslidedoor_t *ht = (polyslidedoor_t*)Z_LevelPoolMalloc(sizeof (*ht)); ht->thinker.alloctype = TAT_LEVELPOOL; @@ -2814,7 +2814,7 @@ static inline void LoadPolyslidedoorThinker(savebuffer_t *save, actionf_p1 think // // Loads a polyswingdoor_t thinker // -static inline void LoadPolyswingdoorThinker(savebuffer_t *save, actionf_p1 thinker) +FUNCINLINE static ATTRINLINE void LoadPolyswingdoorThinker(savebuffer_t *save, actionf_p1 thinker) { polyswingdoor_t *ht = (polyswingdoor_t*)Z_LevelPoolMalloc(sizeof (*ht)); ht->thinker.alloctype = TAT_LEVELPOOL; @@ -2847,7 +2847,7 @@ static inline void LoadPolyswingdoorThinker(savebuffer_t *save, actionf_p1 think // // Loads a polydisplace_t thinker // -static inline void LoadPolydisplaceThinker(savebuffer_t *save, actionf_p1 thinker) +FUNCINLINE static ATTRINLINE void LoadPolydisplaceThinker(savebuffer_t *save, actionf_p1 thinker) { polydisplace_t *ht = (polydisplace_t*)Z_LevelPoolMalloc(sizeof (*ht)); ht->thinker.alloctype = TAT_LEVELPOOL; @@ -3115,7 +3115,7 @@ static void P_NetUnArchiveThinkers(savebuffer_t *save) #define PD_FLAGS 0x01 #define PD_TRANS 0x02 -static inline void P_ArchivePolyObj(savebuffer_t *save, polyobj_t *po) +FUNCINLINE static ATTRINLINE void P_ArchivePolyObj(savebuffer_t *save, polyobj_t *po) { UINT8 diff = 0; WRITEINT32(save->p, po->id); @@ -3137,7 +3137,7 @@ static inline void P_ArchivePolyObj(savebuffer_t *save, polyobj_t *po) WRITEINT32(save->p, po->translucency); } -static inline void P_UnArchivePolyObj(savebuffer_t *save, polyobj_t *po) +FUNCINLINE static ATTRINLINE void P_UnArchivePolyObj(savebuffer_t *save, polyobj_t *po) { INT32 id; UINT32 angle; @@ -3172,7 +3172,7 @@ static inline void P_UnArchivePolyObj(savebuffer_t *save, polyobj_t *po) Polyobj_MoveOnLoad(po, angle, x, y); } -static inline void P_ArchivePolyObjects(savebuffer_t *save) +FUNCINLINE static ATTRINLINE void P_ArchivePolyObjects(savebuffer_t *save) { INT32 i; @@ -3185,7 +3185,7 @@ static inline void P_ArchivePolyObjects(savebuffer_t *save) P_ArchivePolyObj(save, &PolyObjects[i]); } -static inline void P_UnArchivePolyObjects(savebuffer_t *save) +FUNCINLINE static ATTRINLINE void P_UnArchivePolyObjects(savebuffer_t *save) { INT32 i, numSavedPolys; @@ -3203,7 +3203,7 @@ static inline void P_UnArchivePolyObjects(savebuffer_t *save) // // P_FinishMobjs // -static inline void P_FinishMobjs(void) +FUNCINLINE static ATTRINLINE void P_FinishMobjs(void) { thinker_t *currentthinker; mobj_t *mobj; @@ -3220,7 +3220,7 @@ static inline void P_FinishMobjs(void) } } -static inline mobj_t *RelinkMobj(mobj_t **ptr) +FUNCINLINE static ATTRINLINE mobj_t *RelinkMobj(mobj_t **ptr) { UINT32 temp = (UINT32)(size_t)*ptr; *ptr = NULL; @@ -3269,7 +3269,7 @@ static void P_RelinkPointers(void) // // P_NetArchiveSpecials // -static inline void P_NetArchiveSpecials(savebuffer_t *save) +FUNCINLINE static ATTRINLINE void P_NetArchiveSpecials(savebuffer_t *save) { size_t i, z; @@ -3347,7 +3347,7 @@ static void P_NetUnArchiveSpecials(savebuffer_t *save) // ======================================================================= // Misc // ======================================================================= -static inline void P_ArchiveMisc(savebuffer_t *save) +FUNCINLINE static ATTRINLINE void P_ArchiveMisc(savebuffer_t *save) { if (gamecomplete) WRITEINT16(save->p, gamemap | 8192); @@ -3360,7 +3360,7 @@ static inline void P_ArchiveMisc(savebuffer_t *save) WRITESTRINGN(save->p, timeattackfolder, sizeof(timeattackfolder)); } -static inline void P_UnArchiveSPGame(savebuffer_t *save, INT16 mapoverride) +FUNCINLINE static ATTRINLINE void P_UnArchiveSPGame(savebuffer_t *save, INT16 mapoverride) { char testname[sizeof(timeattackfolder)]; -- 2.54.0 From c262d3f532bf02a428afd23e97a9a95db2a5a897 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 15 Oct 2025 20:36:29 +0200 Subject: [PATCH 087/219] prevent potential 0 division in CV_AddValue as repoted by clang-tidy --- src/command.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/command.c b/src/command.c index ee3b36247..47bd521b0 100644 --- a/src/command.c +++ b/src/command.c @@ -1913,13 +1913,14 @@ void CV_AddValue(consvar_t *var, INT32 increment) max = (M_SecretUnlocked(SECRET_HARDSPEED) ? 3 : 2); } #ifdef PARANOIA - if (currentindice == -1) - I_Error("CV_AddValue: current value %d not found in possible value\n", - var->value); + if (currentindice == -1 || max == 0) + I_Error("CV_AddValue: current value %d not found in possible value\n", var->value); #endif - - newindice = (currentindice + increment + max) % max; - CV_Set(var, var->PossibleValue[newindice].strvalue); + if (max > 0) + { + newindice = (currentindice + increment + max) % max; + CV_Set(var, var->PossibleValue[newindice].strvalue); + } } } else -- 2.54.0 From 1ed616dcef13f97fee0e17052bf96ef9c80d1b9d Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 16 Oct 2025 13:38:24 +0200 Subject: [PATCH 088/219] pass rover directly to check_fof_offscreen --- src/r_segs.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/r_segs.cpp b/src/r_segs.cpp index b4f8cdbcd..d1cbbf9c2 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -2236,7 +2236,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) lowcutslope = std::max(worldbottomslope, worldlowslope) + viewz; highcutslope = std::min(worldtopslope, worldhighslope) + viewz; - auto check_fof_offscreen = [&](INT32 bottom, INT32 bottomslope, INT32 top, INT32 topslope) + auto check_fof_offscreen = [&](ffloor_t* rover, INT32 bottom, INT32 bottomslope, INT32 top, INT32 topslope) { return ((P_GetFFloorTopZAt (rover, segleft .x, segleft .y) <= bottom + viewz && P_GetFFloorTopZAt (rover, segright.x, segright.y) <= bottomslope + viewz) @@ -2376,7 +2376,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) continue; // Oy vey. - if (check_fof_offscreen(worldbottom, worldbottomslope, worldtop, worldtopslope)) + if (check_fof_offscreen(rover, worldbottom, worldbottomslope, worldtop, worldtopslope)) continue; ds_p->thicksides[i] = rover; @@ -2394,10 +2394,10 @@ void R_StoreWallRange(INT32 start, INT32 stop) continue; // Oy vey. - if (check_fof_offscreen(worldbottom, worldbottomslope, worldtop, worldtopslope)) + if (check_fof_offscreen(rover, worldbottom, worldbottomslope, worldtop, worldtopslope)) continue; - if (check_fof_offscreen(worldlow, worldlowslope, worldhigh, worldhighslope)) + if (check_fof_offscreen(rover, worldlow, worldlowslope, worldhigh, worldhighslope)) continue; ds_p->thicksides[i] = rover; -- 2.54.0 From 2b39d137b435a68fdece543acfc1d136664987a6 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 16 Oct 2025 13:39:08 +0200 Subject: [PATCH 089/219] guard against null string in stringwidth functions hud drawlists may actually pass null to them --- src/v_video.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/v_video.c b/src/v_video.c index ab3d05b91..0826f508b 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -3094,6 +3094,9 @@ INT32 V_SubStringWidth(const char *string, INT32 length, INT32 option) INT32 spacewidth = 4, charwidth = 0; ssize_t i; + if (!string) + return 0; + if (length < 0) length = strlen(string); @@ -3136,6 +3139,9 @@ INT32 V_SmallSubStringWidth(const char *string, INT32 length, INT32 option) INT32 spacewidth = 2, charwidth = 0; ssize_t i; + if (!string) + return 0; + if (length < 0) length = strlen(string); @@ -3176,9 +3182,14 @@ INT32 V_ThinSubStringWidth(const char *string, INT32 length, INT32 option) { INT32 c, w = 0; INT32 spacewidth = 2, charwidth = 0; - boolean lowercase = (option & V_ALLOWLOWERCASE); + boolean lowercase; ssize_t i; + if (!string) + return 0; + + lowercase = (option & V_ALLOWLOWERCASE); + if (length < 0) length = strlen(string); @@ -3233,6 +3244,9 @@ INT32 V_SubStringLengthToFit(const char *string, INT32 width, INT32 option) INT32 spacewidth = 4, charwidth = 0; INT32 i; + if (!string) + return 0; + switch (option & V_SPACINGMASK) { case V_MONOSPACE: -- 2.54.0 From 66ce745e9149c4bc5744259fcc21f308c6fc3abd Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 16 Oct 2025 13:39:35 +0200 Subject: [PATCH 090/219] add allocation failure case in R_DrawMasked --- src/r_things.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/r_things.cpp b/src/r_things.cpp index 673fdfc6c..76cc91254 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -3064,6 +3064,9 @@ void R_DrawMasked(maskcount_t* masks, INT32 nummasks) heads = static_cast(calloc(nummasks, sizeof(drawnode_t))); + if (!heads) + I_Error("R_DrawMasked: No more free memory\n"); + for (i = 0; i < nummasks; i++) { heads[i].next = heads[i].prev = &heads[i]; -- 2.54.0 From 638e95325a616e89cefc1298f1dce6f03b431552 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 1 May 2024 19:54:09 +0100 Subject: [PATCH 091/219] G_SaveDemo: Resolve memory errors that could result in crashes - Empty `demo.titlename` case - Don't try to save demo of name `.lmp` - Doesn't fall back to anything, because emptying out the name field can be reasonably treated as not wanting to save - `demo.titlename` consists only of invalid characters - Don't try to save demo of name `-.lmp` - Falls back to the default demo title, because the user clearly wanted to save and just happened to provide invalid text --- src/g_demo.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/src/g_demo.c b/src/g_demo.c index 87ae0b61f..fc92d61fe 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -3584,7 +3584,7 @@ void G_SaveDemo(void) strindex++; dash = false; } - else if (!dash) + else if (strindex && !dash) { demo_slug[strindex] = '-'; strindex++; @@ -3592,12 +3592,31 @@ void G_SaveDemo(void) } } - demo_slug[strindex] = 0; - if (dash) demo_slug[strindex-1] = 0; + if (dash && strindex) + { + strindex--; + } + demo_slug[strindex] = '\0'; - writepoint = strstr(demoname, "-") + 1; - demo_slug[128 - (writepoint - demoname) - 4] = 0; - sprintf(writepoint, "%s.lmp", demo_slug); + if (demo_slug[0] != '\0') + { + // Slug is valid, write the chosen filename. + writepoint = strstr(demoname, "-") + 1; + demo_slug[128 - (writepoint - demoname) - 4] = 0; + sprintf(writepoint, "%s.lmp", demo_slug); + } + else if (demo.titlename[0] == '\0') + { + // Slug is completely blank? Will crash if we attempt to save + // No bailout because empty seems like a good "no thanks" choice + G_ResetDemoRecording(); + return; + } + // If a title that is invalid is provided, the user clearly wanted + // to save. But we can't do so at that name, so we only apply the + // title INSIDE the file, not in the naked filesystem. + // (A hypothetical example is bamboozling bot behaviour causing + // a player to write "?????????".) ~toast 010524 } length = *(UINT32 *)demoinfo_p; -- 2.54.0 From c73c1af2d514ae5cc3427e52e2ea0da9407402fa Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 16 Oct 2025 13:52:05 +0200 Subject: [PATCH 092/219] let replays with empty name save this does not crash for us --- src/g_demo.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/g_demo.c b/src/g_demo.c index fc92d61fe..e93ba712a 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -3605,18 +3605,6 @@ void G_SaveDemo(void) demo_slug[128 - (writepoint - demoname) - 4] = 0; sprintf(writepoint, "%s.lmp", demo_slug); } - else if (demo.titlename[0] == '\0') - { - // Slug is completely blank? Will crash if we attempt to save - // No bailout because empty seems like a good "no thanks" choice - G_ResetDemoRecording(); - return; - } - // If a title that is invalid is provided, the user clearly wanted - // to save. But we can't do so at that name, so we only apply the - // title INSIDE the file, not in the naked filesystem. - // (A hypothetical example is bamboozling bot behaviour causing - // a player to write "?????????".) ~toast 010524 } length = *(UINT32 *)demoinfo_p; -- 2.54.0 From 66f67c91e8614e44ec7eb330f22d0be1cf2534b3 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 16 Oct 2025 13:54:42 +0200 Subject: [PATCH 093/219] G_SaveDemo: fix oob reads/writes for replay names demo.titlename has a size of 65! not 128! also handles memory failure and checks bounds for the remaining lenght in the demo slug --- src/g_demo.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/g_demo.c b/src/g_demo.c index e93ba712a..2018d8a8d 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -3569,7 +3569,8 @@ void G_SaveDemo(void) size_t i, strindex = 0; boolean dash = true; - for (i = 0; demo.titlename[i] && i < 127; i++) + //for (i = 0; demo.titlename[i] && i < 127; i++) ????? + for (i = 0; i < 64 && demo.titlename[i]; i++) { if ((demo.titlename[i] >= 'a' && demo.titlename[i] <= 'z') || (demo.titlename[i] >= '0' && demo.titlename[i] <= '9')) @@ -3601,9 +3602,18 @@ void G_SaveDemo(void) if (demo_slug[0] != '\0') { // Slug is valid, write the chosen filename. - writepoint = strstr(demoname, "-") + 1; - demo_slug[128 - (writepoint - demoname) - 4] = 0; - sprintf(writepoint, "%s.lmp", demo_slug); + writepoint = strstr(demoname, "-"); + if (!writepoint) + return; + + writepoint++; + + size_t flen = 128 - (writepoint - demoname) - 4; + if (flen > 0 && flen < 128) + { + demo_slug[flen] = '\0'; + sprintf(writepoint, "%s.lmp", demo_slug); + } } } -- 2.54.0 From 0030367649004f53c977f0ee5fa85fac8bf200c0 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 16 Oct 2025 14:08:17 +0200 Subject: [PATCH 094/219] fix UB in R_PointOnSide by not shifting a 32bit int by 31 bits this is more in line with the original function eitherways --- src/r_main.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_main.h b/src/r_main.h index 4ec43a2f3..850101e64 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -97,7 +97,7 @@ FUNCINLINE static ATTRINLINE PUREFUNC INT32 R_PointOnSide(fixed_t x, fixed_t y, // 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; + INT32 mask = (((node->dy ^ node->dx ^ x ^ y) < 0) ? -1 : 0); return (mask & ((node->dy ^ x) < 0)) | // (left is negative) (~mask & (FixedMul(y, node->dx>>FRACBITS) >= FixedMul(node->dy>>FRACBITS, x))); } -- 2.54.0 From 6096822cbbfacd0905a29afe6a959baa9d831ef7 Mon Sep 17 00:00:00 2001 From: Indev Date: Thu, 16 Oct 2025 15:16:23 +0300 Subject: [PATCH 095/219] Use str.resize(size) instead of str = str.substr(0, size) (ty lug <3) --- src/m_emotes.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/m_emotes.cpp b/src/m_emotes.cpp index 9ae434547..57058ef23 100644 --- a/src/m_emotes.cpp +++ b/src/m_emotes.cpp @@ -92,7 +92,7 @@ void M_LoadEmotes(UINT16 wadnum) if (emote_name.size() > MAXEMOTENAME) { CONS_Alert(CONS_WARNING, "EMOTES: Emote name is too long, truncating. (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum); - emote_name = emote_name.substr(0, MAXEMOTENAME); + emote_name.resize(MAXEMOTENAME); } emote = &emotes[emote_name]; @@ -139,7 +139,7 @@ void M_LoadEmotes(UINT16 wadnum) if (framelumpname.size() > 8) { CONS_Alert(CONS_WARNING, "EMOTES: Frame %d name is too long. (file %s, line %d)", numframes, wadfiles[wadnum]->filename, linenum); - framelumpname = framelumpname.substr(0, 8); + framelumpname.resize(8); } std::strncpy(emote->frames[numframes], framelumpname.c_str(), framelumpname.size()+1); -- 2.54.0 From d5aa9ae0f141194e2b9ad33a15c0ae4deffd62fa Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 16 Oct 2025 15:07:35 +0100 Subject: [PATCH 096/219] fix 32bit windoze compile again...... --- src/Makefile.d/win32.mk | 4 +++- src/doomdef.h | 6 ------ src/win32/Sourcefile | 1 + 3 files changed, 4 insertions(+), 7 deletions(-) create mode 100644 src/win32/Sourcefile diff --git a/src/Makefile.d/win32.mk b/src/Makefile.d/win32.mk index 8c5e75b8e..4adcfe6e8 100644 --- a/src/Makefile.d/win32.mk +++ b/src/Makefile.d/win32.mk @@ -2,6 +2,8 @@ # Mingw, if you don't know, that's Win32/Win64 # +sources+=$(call List,win32/Sourcefile) + ifndef MINGW64 EXENAME?=srb2kart-saturn_32bit.exe else @@ -95,7 +97,7 @@ LIBBACKTRACE_libs:=-L$(lib)/lib/x86_64 -lbacktrace $(eval $(call _set,LIBBACKTRACE)) else lib:=../libs/drmingw -opts+=-I$(lib)/include +opts+=-I$(lib)/include -DHAVE_DRMINGW libs+=-L$(lib)/lib/win32 -lmgwhelp -lexchndl endif diff --git a/src/doomdef.h b/src/doomdef.h index 30419978b..00b4bc1f0 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -90,12 +90,6 @@ extern FILE *logstream; extern char logfilename[1024]; #endif -// not sure if this belongs here lul -// TODO: figure out whats preventing 32bit windows from working with libbacktrace -#if defined(_WIN32) && !defined(__MINGW64__) -#define HAVE_DRMINGW -#endif - #if defined (HAVE_LIBBACKTRACE) #define CRASH_LOGFILE_NAME "srb2kart-crash-log.txt" #elif defined (HAVE_DRMINGW) diff --git a/src/win32/Sourcefile b/src/win32/Sourcefile new file mode 100644 index 000000000..0122059d8 --- /dev/null +++ b/src/win32/Sourcefile @@ -0,0 +1 @@ +win_dbg.c -- 2.54.0 From 5c2a87dea670cca5354b8a761da096c09f1a91a6 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 16 Oct 2025 21:28:48 +0200 Subject: [PATCH 097/219] fix off by one when playing with controller sticks also simplify driftturn handling --- src/g_game.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 7470f3fc9..bc22e6939 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1024,30 +1024,26 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) // let movement keys cancel each other out if (turnright && !(turnleft)) { - cmd->angleturn = (INT16)(cmd->angleturn - (angleturn[tspeed])); - cmd->driftturn = (INT16)(cmd->driftturn - (angleturn[tspeed])); + cmd->angleturn -= angleturn[tspeed]; side += sidemove[1]; } else if (turnleft && !(turnright)) { - cmd->angleturn = (INT16)(cmd->angleturn + (angleturn[tspeed])); - cmd->driftturn = (INT16)(cmd->driftturn + (angleturn[tspeed])); + cmd->angleturn += angleturn[tspeed]; side -= sidemove[1]; } if (analogjoystickmove && axis != 0) { - // JOYAXISRANGE should be 1023 (divide by 1024) - cmd->angleturn = (INT16)(cmd->angleturn - (((axis * angleturn[1]) >> 10))); // ANALOG! - cmd->driftturn = (INT16)(cmd->driftturn - (((axis * angleturn[1]) >> 10))); - side += ((axis * sidemove[0]) >> 10); + cmd->angleturn -= (axis * KART_FULLTURN) / JOYAXISRANGE; + side += (axis * sidemove[0]) / JOYAXISRANGE; } if (cv_mouseturn.value) { //THIS WORKS WTF???????? - cmd->angleturn = (INT16)(cmd->angleturn - ((mousex*(encoremode ? -1 : 1)*8))); - cmd->driftturn = (INT16)(cmd->driftturn - ((mousex*(encoremode ? -1 : 1)*8))); + cmd->angleturn -= (mousex*(encoremode ? -1 : 1)*8); + } } if (objectplacing) // SRB2Kart: spectators need special controls // not anymore huehuehue @@ -1160,10 +1156,8 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) else if (cmd->angleturn < (-angleturn[1])) cmd->angleturn = (-angleturn[1]); - if (cmd->driftturn > (angleturn[1])) - cmd->driftturn = (angleturn[1]); - else if (cmd->driftturn < (-angleturn[1])) - cmd->driftturn = (-angleturn[1]); + // until here both are the very same + cmd->driftturn = cmd->angleturn; if (player->mo) cmd->angleturn = K_GetKartTurnValue(player, cmd->angleturn); -- 2.54.0 From f4aec1d59126ac04ea0f14d13d7a7af21b6578d4 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 16 Oct 2025 21:53:24 +0200 Subject: [PATCH 098/219] port "Lite Steer" from RR took me a while to realize RR makes everything go though "analogue" input handlers --- src/d_netcmd.c | 2 ++ src/g_game.c | 13 +++++++++++++ src/g_game.h | 2 ++ src/m_menudefs.c | 17 ++++++++++++++--- src/st_stuff.c | 4 ++-- 5 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 6f97cb819..02b6c40ff 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -984,6 +984,8 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_xdeadzone[i]); CV_RegisterVar(&cv_ydeadzone[i]); + CV_RegisterVar(&cv_litesteer[i]); + CV_RegisterVar(&cv_usejoystick[i]); CV_RegisterVar(&cv_joyscale[i]); CV_RegisterVar(&cv_rumble[i]); diff --git a/src/g_game.c b/src/g_game.c index bc22e6939..d3775fc6d 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -452,6 +452,13 @@ consvar_t cv_ydeadzone[MAXSPLITSCREENPLAYERS] = { {"joy4_ydeadzone", "0.5", CV_FLOAT|CV_SAVE, deadzone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL} }; +consvar_t cv_litesteer[MAXSPLITSCREENPLAYERS] = { + {"litesteer", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}, + {"litesteer2", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}, + {"litesteer3", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}, + {"litesteer4", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL} +}; + static CV_PossibleValue_t driftsparkpulse_t[] = {{0, "MIN"}, {FRACUNIT*3, "MAX"}, {0, NULL}}; consvar_t cv_driftsparkpulse = {"driftsparkpulse", "1.4", CV_FLOAT | CV_SAVE, driftsparkpulse_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -1044,6 +1051,12 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) //THIS WORKS WTF???????? cmd->angleturn -= (mousex*(encoremode ? -1 : 1)*8); } + + // Digital users can input diagonal-back for shallow turns. + if (cv_litesteer[forplayer].value && InputDown(gc_aimbackward, ssplayer) + && abs(cmd->angleturn) == KART_FULLTURN) // My keyboard hits 1024 but my keyboard only hits 1023, video games + { + cmd->angleturn /= 2; } if (objectplacing) // SRB2Kart: spectators need special controls // not anymore huehuehue diff --git a/src/g_game.h b/src/g_game.h index 4812a2c1f..6b5d1c8cc 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -72,6 +72,8 @@ extern consvar_t cv_custom3axis[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_xdeadzone[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_ydeadzone[MAXSPLITSCREENPLAYERS]; +extern consvar_t cv_litesteer[MAXSPLITSCREENPLAYERS]; + extern consvar_t cv_ghost_besttime, cv_ghost_bestlap, cv_ghost_last, cv_ghost_guest, cv_ghost_staff; // Hud offsets diff --git a/src/m_menudefs.c b/src/m_menudefs.c index 74ee714dd..ca17cafa8 100644 --- a/src/m_menudefs.c +++ b/src/m_menudefs.c @@ -645,10 +645,16 @@ static menuitem_t OP_ControlsMenu[] = {IT_CALL | IT_STRING, NULL, "Player 3 Controls...", &M_Setup3PControlsMenu, 30}, {IT_CALL | IT_STRING, NULL, "Player 4 Controls...", &M_Setup4PControlsMenu, 40}, - {IT_SUBMENU | IT_STRING, NULL, "Mouse Options...", &OP_MouseOptionsDef, 60}, + {IT_SUBMENU | IT_STRING, NULL, "Mouse Options...", &OP_MouseOptionsDef, 60}, - {IT_STRING | IT_CVAR, NULL, "Controls per key", &cv_controlperkey, 80}, - {IT_STRING | IT_CVAR, NULL, "Digital turn easing", &cv_turnsmooth, 90}, + {IT_STRING | IT_CVAR, NULL, "Controls per key", &cv_controlperkey, 80}, + {IT_STRING | IT_CVAR, NULL, "Digital turn easing", &cv_turnsmooth, 90}, + + // i hate our menus sincerly + {IT_STRING | IT_CVAR, NULL, "Lite Steer (P1)", &cv_litesteer[0], 110}, + {IT_STRING | IT_CVAR, NULL, "Lite Steer (P2)", &cv_litesteer[1], 120}, + {IT_STRING | IT_CVAR, NULL, "Lite Steer (P3)", &cv_litesteer[2], 130}, + {IT_STRING | IT_CVAR, NULL, "Lite Steer (P4)", &cv_litesteer[3], 140}, }; static const char* OP_ControlsTooltips[] = @@ -660,6 +666,11 @@ static const char* OP_ControlsTooltips[] = "Options for mouse control.", "Allowed amount of controls per key.", "Turn smoothing for non-analog turning.", + + "Hold DOWN on d-pad/keyboard for shallow turns (Player 1).", + "Hold DOWN on d-pad/keyboard for shallow turns (Player 2).", + "Hold DOWN on d-pad/keyboard for shallow turns (Player 3).", + "Hold DOWN on d-pad/keyboard for shallow turns (Player 4).", }; static menuitem_t OP_AllControlsMenu[] = diff --git a/src/st_stuff.c b/src/st_stuff.c index fade7c484..a4b3d0465 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -790,7 +790,7 @@ void ST_Drawer(void) LUA_HUD_DrawList(luahuddrawlist_game[i]); // draw Midnight Channel's overlay ontop - if (mapheaderinfo[gamemap-1]->typeoflevel & TOL_TV) // Very specific Midnight Channel stuff. + if (mapheaderinfo[gamemap-1]->typeoflevel & TOL_TV) // Very specific Midnight Channel stuff. ST_MayonakaStatic(); } @@ -798,7 +798,7 @@ void ST_Drawer(void) if (timeinmap < 15) { if (timeinmap <= 5) - V_DrawFill(0,0,BASEVIDWIDTH,BASEVIDHEIGHT,120); // Pure white on first few frames, to hide SRB2's awful level load artifacts + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 120); // Pure white on first few frames, to hide SRB2's awful level load artifacts else V_DrawFadeScreen(120, 15-timeinmap); // Then gradually fade out from there } -- 2.54.0 From 02f6fa06654c181125798103191a1848265f69c2 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 16 Oct 2025 22:21:21 +0200 Subject: [PATCH 099/219] HACK: call texture precache when toggling a setting that flushes opengl textures workaround for batching sort issues should be good eitherway to reduce stutters after toggling them --- src/hardware/hw_cache.c | 2 +- src/hardware/hw_main.cpp | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index e48e2772a..edbd83b77 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -804,7 +804,7 @@ static void HWR_PrecacheLevelSprites(void) void HWR_PrecacheLevel(void) { - if (rendermode != render_opengl) + if (gamestate != GS_LEVEL) return; // Precache flats. diff --git a/src/hardware/hw_main.cpp b/src/hardware/hw_main.cpp index 382143dcb..af797af11 100644 --- a/src/hardware/hw_main.cpp +++ b/src/hardware/hw_main.cpp @@ -277,6 +277,7 @@ static void CV_glshaders_OnChange(void) { // can't do palette rendering without shaders, so update the state if needed HWR_TogglePaletteRendering(); + HWR_PrecacheLevel(); } M_UpdateOGLMenu(); } @@ -294,18 +295,21 @@ static void CV_gltextureformat_OnChange(void) { ONLY_IF_GL_LOADED GL_SetSpecialState(HWD_SET_TEXTURE_FORMAT, cv_gltexturedepth.value); + HWR_PrecacheLevel(); } static void CV_filtermode_OnChange(void) { ONLY_IF_GL_LOADED GL_SetSpecialState(HWD_SET_TEXTUREFILTERMODE, cv_glfiltermode.value); + HWR_PrecacheLevel(); } static void CV_anisotropic_OnChange(void) { ONLY_IF_GL_LOADED GL_SetSpecialState(HWD_SET_TEXTUREANISOTROPICMODE, cv_glanisotropicmode.value); + HWR_PrecacheLevel(); } static void CV_glpaletterendering_OnChange(void) @@ -318,7 +322,9 @@ static void CV_glpaletterendering_OnChange(void) { HWR_CompileShaders(); HWR_TogglePaletteRendering(); + HWR_PrecacheLevel(); } + M_UpdateOGLMenu(); } -- 2.54.0 From 3ba1596976460242bb90c57a707a6ced518277c7 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 16 Oct 2025 23:15:33 +0200 Subject: [PATCH 100/219] change wheel input "sensitivity" 200 maps perfectly to our turn values so the wheel now actually better reflects the inputs and does not turn fully super early uhh --- src/k_hud.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_hud.c b/src/k_hud.c index 71af43f5d..54b81a0f4 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -4333,7 +4333,7 @@ static void K_drawInput(void) target = 0; else // turning of multiple strengths! { - target = ((abs(cmd->driftturn) - 1)/125)+1; + target = ((abs(cmd->driftturn) - 1)/200)+1; // was 125, do we need another toggle for this? Zzz... if (target > 4) target = 4; if (cmd->driftturn < 0) -- 2.54.0 From 278f3c3ef66e53c3dbcb7774e0c36f3efab89dcc Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 17 Oct 2025 09:24:24 +0200 Subject: [PATCH 101/219] turnsmoothing splitscreen player support i hate our menus Zzz.... --- src/d_netcmd.c | 3 ++- src/g_game.c | 4 ++-- src/g_game.h | 1 - src/g_input.c | 8 +++++++- src/g_input.h | 3 ++- src/m_menudefs.c | 25 ++++++++++++++++--------- 6 files changed, 29 insertions(+), 15 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 02b6c40ff..c1d4718ca 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -964,10 +964,11 @@ void D_RegisterClientCommands(void) // g_input.c CV_RegisterVar(&cv_controlperkey); - CV_RegisterVar(&cv_turnsmooth); for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) { + CV_RegisterVar(&cv_turnsmooth[i]); + CV_RegisterVar(&cv_turnaxis[i]); CV_RegisterVar(&cv_moveaxis[i]); CV_RegisterVar(&cv_camturnaxis[i]); diff --git a/src/g_game.c b/src/g_game.c index d3775fc6d..5c984ad87 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1021,8 +1021,8 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) else th = 0; - if (th < SLOWTURNTICS) - tspeed = cv_turnsmooth.value == 2 ? 2 : 0; // slow turn + if (th < (cv_turnsmooth[forplayer].value * 3)) + tspeed = cv_turnsmooth[forplayer].value == 2 ? 2 : 0; // slow turn else tspeed = 1; diff --git a/src/g_game.h b/src/g_game.h index 6b5d1c8cc..249ecbff1 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -155,7 +155,6 @@ typedef enum // mouseaiming (looking up/down with the mouse or keyboard) #define KB_LOOKSPEED (1<<25) #define MAXPLMOVE (50) -#define SLOWTURNTICS (cv_turnsmooth.value * 3) // build an internal map name MAPxx from map number const char *G_BuildMapName(INT32 map); diff --git a/src/g_input.c b/src/g_input.c index 09ed3303a..e8bc8223e 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -37,7 +37,13 @@ static CV_PossibleValue_t turnsmooth_cons_t[] = {{2, "Slow"}, {1, "Fast"}, {0, " consvar_t cv_mousesens = {"mousesens", "20", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_mouseysens = {"mouseysens", "20", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_controlperkey = {"controlperkey", "One", CV_SAVE, onecontrolperkey_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_turnsmooth = {"turnsmoothing", "Slow", CV_SAVE, turnsmooth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + +consvar_t cv_turnsmooth[MAXSPLITSCREENPLAYERS] = { + {"turnsmoothing", "Slow", CV_SAVE, turnsmooth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}, + {"turnsmoothing2", "Slow", CV_SAVE, turnsmooth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}, + {"turnsmoothing3", "Slow", CV_SAVE, turnsmooth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}, + {"turnsmoothing4", "Slow", CV_SAVE, turnsmooth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL} +}; static void G_ResetPlayerDeviceRumble(INT32 player); static void rumble_off_handle(void); diff --git a/src/g_input.h b/src/g_input.h index 970560a35..ec4a9d795 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -110,7 +110,8 @@ typedef enum // mouse values are used once extern consvar_t cv_mousesens, cv_mouseysens; -extern consvar_t cv_controlperkey, cv_turnsmooth; +extern consvar_t cv_controlperkey; +extern consvar_t cv_turnsmooth[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_rumble[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_gamepadled[MAXSPLITSCREENPLAYERS]; diff --git a/src/m_menudefs.c b/src/m_menudefs.c index ca17cafa8..e02113026 100644 --- a/src/m_menudefs.c +++ b/src/m_menudefs.c @@ -645,16 +645,20 @@ static menuitem_t OP_ControlsMenu[] = {IT_CALL | IT_STRING, NULL, "Player 3 Controls...", &M_Setup3PControlsMenu, 30}, {IT_CALL | IT_STRING, NULL, "Player 4 Controls...", &M_Setup4PControlsMenu, 40}, - {IT_SUBMENU | IT_STRING, NULL, "Mouse Options...", &OP_MouseOptionsDef, 60}, + {IT_SUBMENU | IT_STRING, NULL, "Mouse Options...", &OP_MouseOptionsDef, 55}, - {IT_STRING | IT_CVAR, NULL, "Controls per key", &cv_controlperkey, 80}, - {IT_STRING | IT_CVAR, NULL, "Digital turn easing", &cv_turnsmooth, 90}, + {IT_STRING | IT_CVAR, NULL, "Controls per key", &cv_controlperkey, 75}, + + {IT_STRING | IT_CVAR, NULL, "Digital turn easing (P1)", &cv_turnsmooth[0], 85}, + {IT_STRING | IT_CVAR, NULL, "Digital turn easing (P2)", &cv_turnsmooth[1], 95}, + {IT_STRING | IT_CVAR, NULL, "Digital turn easing (P3)", &cv_turnsmooth[2], 105}, + {IT_STRING | IT_CVAR, NULL, "Digital turn easing (P4)", &cv_turnsmooth[3], 115}, // i hate our menus sincerly - {IT_STRING | IT_CVAR, NULL, "Lite Steer (P1)", &cv_litesteer[0], 110}, - {IT_STRING | IT_CVAR, NULL, "Lite Steer (P2)", &cv_litesteer[1], 120}, - {IT_STRING | IT_CVAR, NULL, "Lite Steer (P3)", &cv_litesteer[2], 130}, - {IT_STRING | IT_CVAR, NULL, "Lite Steer (P4)", &cv_litesteer[3], 140}, + {IT_STRING | IT_CVAR, NULL, "Lite Steer (P1)", &cv_litesteer[0], 135}, + {IT_STRING | IT_CVAR, NULL, "Lite Steer (P2)", &cv_litesteer[1], 145}, + {IT_STRING | IT_CVAR, NULL, "Lite Steer (P3)", &cv_litesteer[2], 155}, + {IT_STRING | IT_CVAR, NULL, "Lite Steer (P4)", &cv_litesteer[3], 165}, }; static const char* OP_ControlsTooltips[] = @@ -665,7 +669,10 @@ static const char* OP_ControlsTooltips[] = "Setup player 4 controls.", "Options for mouse control.", "Allowed amount of controls per key.", - "Turn smoothing for non-analog turning.", + "Turn smoothing for non-analog turning (Player 1).", + "Turn smoothing for non-analog turning (Player 2).", + "Turn smoothing for non-analog turning (Player 3).", + "Turn smoothing for non-analog turning (Player 4).", "Hold DOWN on d-pad/keyboard for shallow turns (Player 1).", "Hold DOWN on d-pad/keyboard for shallow turns (Player 2).", @@ -2435,7 +2442,7 @@ menu_t OP_MainDef = NULL }; -menu_t OP_ControlsDef = DEFAULTMENUSTYLE("M_CONTRO", OP_ControlsMenu, &OP_MainDef, 60, 30, OP_ControlsTooltips); +menu_t OP_ControlsDef = DEFAULTMENUSTYLE("M_CONTRO", OP_ControlsMenu, &OP_MainDef, 40, 15, OP_ControlsTooltips); //WTF menu_t OP_MouseOptionsDef = DEFAULTMENUSTYLE("M_CONTRO", OP_MouseOptionsMenu, &OP_ControlsDef, 60, 30, OP_MouseTooltips); menu_t OP_AllControlsDef = CONTROLMENUSTYLE(OP_AllControlsMenu, &OP_ControlsDef); -- 2.54.0 From 59628377fad5f0acd7f962d52b8217e4e89f6626 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 5 Jan 2023 04:24:18 -0800 Subject: [PATCH 102/219] Resize menudemo_t filepath to fix -Wformat-truncation --- src/g_demo.h | 2 +- src/m_menu.c | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/g_demo.h b/src/g_demo.h index 36458b240..3ce32c054 100644 --- a/src/g_demo.h +++ b/src/g_demo.h @@ -67,7 +67,7 @@ typedef enum { } menudemotype_e; typedef struct menudemo_s { - char filepath[256]; + char filepath[1023 + 256]; // see M_PrepReplayList and sizeof menupath menudemotype_e type; char title[65]; // Null-terminated for string prints diff --git a/src/m_menu.c b/src/m_menu.c index ed39e053f..a882ca3fe 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -3958,9 +3958,7 @@ static void PrepReplayList(boolean reset) Lock_search_state(); - if (demolist_all) - Z_Free(demolist_all); - + Z_Free(demolist_all); demolist_all = Z_Calloc(sizeof(menudemo_t) * sizedirmenu, PU_STATIC, NULL); for (i = 0; i < sizedirmenu; i++) @@ -3978,9 +3976,9 @@ static void PrepReplayList(boolean reset) else { demolist_all[i].type = MD_NOTLOADED; - // FIXME - do something with buffer sizes. menupath is 1024 chars but filepath is only - // 256. I'm not really sure what to do here but don't want to leave warnings... - snprintf(demolist_all[i].filepath, 255, "%.254s%s", menupath, dirmenu[i] + DIR_STRING); + snprintf(demolist_all[i].filepath, sizeof(demolist_all[i].filepath), + // 255 = UINT8 limit. dirmenu entries are restricted to this length (see DIR_LEN). + "%s%.255s", menupath, dirmenu[i] + DIR_STRING); sprintf(demolist_all[i].title, "....."); } } -- 2.54.0 From 5c613f6c8fe38d2462a7e6f9917afc48335e29f0 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Fri, 17 Oct 2025 12:21:54 -0400 Subject: [PATCH 103/219] Use a constant for file path stuff --- src/filesrch.c | 4 ++-- src/filesrch.h | 3 ++- src/m_menu.c | 6 +++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/filesrch.c b/src/filesrch.c index 088911e54..628a221c2 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -44,7 +44,7 @@ consvar_t cv_addons_search_case = {"addons_search_case", "No", CV_SAVE, CV_YesNo static CV_PossibleValue_t addons_search_type_cons_t[] = {{0, "Start"}, {1, "Anywhere"}, {0, NULL}}; consvar_t cv_addons_search_type = {"addons_search_type", "Anywhere", CV_SAVE, addons_search_type_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -char menupath[1024]; +char menupath[MAXFILEPATH]; size_t menupathindex[menudepth]; size_t menudepthleft = menudepth; @@ -111,7 +111,7 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want int found = 0; char *searchname; int depthleft = maxsearchdepth; - char searchpath[1024]; + char searchpath[MAXFILEPATH]; size_t *searchpathindex; dirhandle = (DIR**)malloc(maxsearchdepth * sizeof(DIR*)); diff --git a/src/filesrch.h b/src/filesrch.h index 697020c54..0a2da67b8 100644 --- a/src/filesrch.h +++ b/src/filesrch.h @@ -34,7 +34,8 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want #define menudepth 20 -extern char menupath[1024]; +#define MAXFILEPATH 1024 +extern char menupath[MAXFILEPATH]; extern size_t menupathindex[menudepth]; extern size_t menudepthleft; diff --git a/src/m_menu.c b/src/m_menu.c index a882ca3fe..0588ccf64 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -3107,7 +3107,7 @@ static void M_AddonsInternal(void) break; } - strlcpy(menupath, pathname, 1024); + strlcpy(menupath, pathname, MAXFILEPATH); menupathindex[(menudepthleft = menudepth-1)] = strlen(menupath) + 1; if (menupath[menupathindex[menudepthleft]-2] != PATHSEP[0]) @@ -3220,9 +3220,9 @@ static void M_DrawTemperature(INT32 x, fixed_t t) static char *M_AddonsHeaderPath(void) { UINT32 len; - static char header[1024]; + static char header[MAXFILEPATH]; - strlcpy(header, va("%s folder%s", cv_addons_option.string, menupath+menupathindex[menudepth-1]-1), 1024); + strlcpy(header, va("%s folder%s", cv_addons_option.string, menupath+menupathindex[menudepth-1]-1), MAXFILEPATH); len = strlen(header); if (len > 34) { -- 2.54.0 From de99a3036d23a31e452a534b750935fae2767fa2 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Fri, 17 Oct 2025 09:13:59 -0400 Subject: [PATCH 104/219] Update Discord RPC Based on some of the changes from RR. Accounts for the fact discord does not have tags anymore and makes skin code easier to manage --- src/d_netcmd.c | 5 ----- src/discord.c | 28 +++++++++++++++++++++++++++- src/discord.h | 11 +++++++++++ src/m_menu.c | 4 ++-- src/r_skins.c | 8 ++++++++ 5 files changed, 48 insertions(+), 8 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index c1d4718ca..002195ec1 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1994,11 +1994,6 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum) } else SetPlayerSkinByNum(playernum, skin); - -#ifdef HAVE_DISCORDRPC - if (playernum == consoleplayer) - DRPC_UpdatePresence(); -#endif } void SendWeaponPref(void) diff --git a/src/discord.c b/src/discord.c index 207a249a6..f94cd574d 100644 --- a/src/discord.c +++ b/src/discord.c @@ -49,6 +49,27 @@ discordRequest_t *discordRequestList = NULL; static char self_ip[IP_SIZE+1]; +/*-------------------------------------------------- + * const char *DRPC_HideUsername(const char *input) + * + * See header file for description. + * --------------------------------------------------*/ +const char *DRPC_HideUsername(const char *input) +{ + static char buffer[5]; + int i; + + buffer[0] = input[0]; + + for (i = 1; i < 4; ++i) + { + buffer[i] = '.'; + } + + buffer[4] = '\0'; + return buffer; +} + boolean drpc_init = false; /*-------------------------------------------------- @@ -105,7 +126,7 @@ static void DRPC_HandleReady(const DiscordUser *user) } else { - CONS_Printf("Discord: connected to %s#%s (%s)\n", user->username, user->discriminator, user->userId); + CONS_Printf("Discord: connected to %s (%s)\n", user->username, user->userId); } } @@ -241,8 +262,10 @@ static void DRPC_HandleJoinRequest(const DiscordUser *requestUser) newRequest->username = Z_Calloc(344, PU_STATIC, NULL); snprintf(newRequest->username, 344, "%s", requestUser->username); +#if 0 newRequest->discriminator = Z_Calloc(8, PU_STATIC, NULL); snprintf(newRequest->discriminator, 8, "%s", requestUser->discriminator); +#endif newRequest->userID = Z_Calloc(32, PU_STATIC, NULL); snprintf(newRequest->userID, 32, "%s", requestUser->userId); @@ -308,6 +331,9 @@ void DRPC_RemoveRequest(discordRequest_t *removeRequest) } Z_Free(removeRequest->username); +#if 0 + Z_Free(removeRequest->discriminator); +#endif Z_Free(removeRequest->userID); Z_Free(removeRequest); } diff --git a/src/discord.h b/src/discord.h index 131dc05f9..fa37c306b 100644 --- a/src/discord.h +++ b/src/discord.h @@ -29,7 +29,9 @@ extern struct discordInfo_s { typedef struct discordRequest_s { char *username; // Discord user name. +#if 0 // Good night, sweet prince... char *discriminator; // Discord discriminator (The little hashtag thing after the username). Separated for a "hide discriminators" cvar. +#endif char *userID; // The ID of the Discord user, gets used with Discord_Respond() // HAHAHA, no. @@ -44,6 +46,15 @@ typedef struct discordRequest_s { extern discordRequest_t *discordRequestList; +/*-------------------------------------------------- + * const char *DRPC_HideUsername(const char *input); + * + * Handle usernames while cv_discordstreamer is activated. + * (The loss of discriminators is still a dumbass regression + * that I will never forgive the Discord developers for.) + * --------------------------------------------------*/ + +const char *DRPC_HideUsername(const char *input); /*-------------------------------------------------- void DRPC_RemoveRequest(void); diff --git a/src/m_menu.c b/src/m_menu.c index 0588ccf64..3d8857b9a 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -10332,9 +10332,9 @@ static const char *M_GetDiscordName(discordRequest_t *r) return ""; if (cv_discordstreamer.value) - return r->username; + return DRPC_HideUsername(r->username); - return va("%s#%s", r->username, r->discriminator); + return r->username; } // (this goes in k_hud.c when merged into v2) diff --git a/src/r_skins.c b/src/r_skins.c index f0fbfcfd1..9d289f936 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -35,6 +35,8 @@ CV_PossibleValue_t Forceskin_cons_t[MAXSKINS+2]; +#include "discord.h" + INT32 numskins = 0; INT32 numallskins = 0; INT32 numlocalskins = 0; @@ -328,8 +330,14 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) if (player->mo) P_SetScale(player->mo, player->mo->scale); + // for replays: We have changed our skin mid-game; let the game know so it can do the same in the replay! demo_extradata[playernum] |= DXD_SKIN; +#ifdef HAVE_DISCORDRPC + if (player - players == consoleplayer) + DRPC_UpdatePresence(); +#endif + return; } -- 2.54.0 From 178d8b7b532faa295603bd32a9e71c0296c94c28 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 18 Oct 2025 16:14:58 +0200 Subject: [PATCH 105/219] fix demo_slug compiler warning Zzz.... --- src/g_demo.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/g_demo.c b/src/g_demo.c index 2018d8a8d..4b63a1578 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -3609,11 +3609,7 @@ void G_SaveDemo(void) writepoint++; size_t flen = 128 - (writepoint - demoname) - 4; - if (flen > 0 && flen < 128) - { - demo_slug[flen] = '\0'; - sprintf(writepoint, "%s.lmp", demo_slug); - } + snprintf(writepoint, flen, "%s.lmp", demo_slug); } } -- 2.54.0 From af03b511914c92b3d6ec0edb353e7d5bff4c4920 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 18 Oct 2025 21:26:23 +0200 Subject: [PATCH 106/219] add guard to vid.screens free not super necessary but better safe than sorry --- src/r_draw.h | 1 - src/v_video.c | 8 ++++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/r_draw.h b/src/r_draw.h index cd1356522..175781e4c 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -31,7 +31,6 @@ FUNCINLINE static ATTRINLINE UINT8 *R_Address(INT32 px, INT32 py) return vid.screens[0] + (py + viewwindowy) * vid.width + (viewwindowx + px); } - typedef struct { float x, y, z; } floatv3_t; diff --git a/src/v_video.c b/src/v_video.c index 0826f508b..0104cf78c 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -3828,11 +3828,15 @@ void V_Init(void) for (i = 0; i < NUMSCREENS; i++) { + if (vid.screens[i]) + { #if defined(__SSE__) - aligned_free(vid.screens[i]); + aligned_free(vid.screens[i]); #else - free(vid.screens[i]); + free(vid.screens[i]); #endif + } + vid.screens[i] = NULL; } -- 2.54.0 From 8c6893cff6ecdae6d95a2ddfa2edae8e3d803da4 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 18 Oct 2025 23:04:09 +0200 Subject: [PATCH 107/219] init taglists in P_LoadMapData no reason to init them in P_SpawnSpecials fixes join crashes on some maps --- src/p_setup.c | 1 + src/p_spec.c | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_setup.c b/src/p_setup.c index 2ccbd1821..5cf9fef39 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1983,6 +1983,7 @@ static void P_LoadMapData(const virtres_t* virt) P_LoadLinedefs(virtlinedefs->data); P_LoadSidedefs(virtsidedefs->data); P_LoadThings(virtthings->data); + P_InitTagLists(); // Create xref tables for tags // Copy relevant map data for NetArchive purposes. spawnsectors = Z_Calloc(numsectors * sizeof(*sectors), PU_LEVEL, NULL); diff --git a/src/p_spec.c b/src/p_spec.c index 7b4b45358..cf2ca3e3e 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -5387,7 +5387,6 @@ void P_SpawnSpecials(INT32 fromnetsave, boolean reloadinggamestate) // set current weather curWeather = mapheaderinfo[gamemap-1]->weather; - P_InitTagLists(); // Create xref tables for tags P_SearchForDisableLinedefs(); // Disable linedefs are now allowed to disable *any* line P_SpawnScrollers(); // Add generalized scrollers -- 2.54.0 From a6438da531224bc3d1372d25115404af249b29a5 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 18 Oct 2025 23:10:51 +0200 Subject: [PATCH 108/219] use spawn sector and line tags for P_ReloadSaveLevelData should speed up resynch a little, now that we properly save them --- src/p_saveg.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index d158cf91b..d3a162e2d 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -3531,7 +3531,8 @@ static void P_ReloadSaveLevelData(void) ss->floorpic_angle = spawnss->floorpic_angle; ss->ceilingpic_angle = spawnss->ceilingpic_angle; ss->tag = spawnss->tag; - ss->firsttag = ss->nexttag = -1; + ss->firsttag = spawnss->firsttag; + ss->nexttag = spawnss->nexttag; if (ss->ffloors) { @@ -3556,7 +3557,8 @@ static void P_ReloadSaveLevelData(void) li->callcount = 0; li->tag = spawnli->tag; - li->firsttag = li->nexttag = -1; + li->firsttag = spawnli->firsttag; + li->nexttag = spawnli->nexttag; if (li->sidenum[0] != 0xffff) { @@ -3580,8 +3582,6 @@ static void P_ReloadSaveLevelData(void) si->midtexture = spawnsi->midtexture; } } - - P_InitTagLists(); } FUNCINLINE static ATTRINLINE boolean P_NetUnArchiveMisc(savebuffer_t *save, boolean reloading) -- 2.54.0 From 7555d689db88df5a48b9db6da55c55ea81ce59b0 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 19 Oct 2025 20:57:19 +0200 Subject: [PATCH 109/219] clear our column buffer after allocation --- src/r_draw.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/r_draw.cpp b/src/r_draw.cpp index ed233e387..2297d1035 100644 --- a/src/r_draw.cpp +++ b/src/r_draw.cpp @@ -636,8 +636,10 @@ void R_InitViewBuffer(INT32 width, INT32 height) bufsize++; temp_dc.buf = static_cast(aligned_alloc(16, bufsize)); #else - temp_dc.buf = static_cast(Z_Calloc(bufsize, PU_STATIC, NULL)); + temp_dc.buf = static_cast(Z_Malloc(bufsize, PU_STATIC, NULL)); #endif + + memset(temp_dc.buf, 0, bufsize); } /** \brief The R_VideoErase function -- 2.54.0 From e044db73f5e2dc5bd0d3f164eeaf82510ab95715 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 19 Oct 2025 20:57:39 +0200 Subject: [PATCH 110/219] those should be initialised to something --- src/r_things.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/r_things.cpp b/src/r_things.cpp index 76cc91254..e7eae525d 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -2801,11 +2801,6 @@ void R_ClipSprites(drawseg_t* dsstart, portal_t* portal) drawseg_t* ds; INT32 i; - if (visspritecount - clippedvissprites <= 0) - { - return; - } - // e6y // Reducing of cache misses in the following R_DrawSprite() // Makes sense for scenes with huge amount of drawsegs. @@ -2815,6 +2810,11 @@ void R_ClipSprites(drawseg_t* dsstart, portal_t* portal) drawsegs_xranges[i].count = 0; } + if (visspritecount - clippedvissprites <= 0) + { + return; + } + if (drawsegs_xrange_size < maxdrawsegs) { // haleyjd: fix reallocation to track 2x size -- 2.54.0 From 349bf06e4b81e4ab56b42606c831496a52ee2990 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 19 Oct 2025 21:02:04 +0200 Subject: [PATCH 111/219] macrofy column function definitions --- src/r_draw.h | 15 +++++++-------- src/r_draw_column.cpp | 26 ++++++++++---------------- src/screen.c | 14 +++++++------- 3 files changed, 24 insertions(+), 31 deletions(-) diff --git a/src/r_draw.h b/src/r_draw.h index 175781e4c..83ec33d56 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -230,17 +230,16 @@ void R_Draw2sMultiPatchColumn(drawcolumndata_t* dc); void R_Draw2sMultiPatchTranslucentColumn(drawcolumndata_t* dc); // column drawers which use buffered drawing with flush -void R_DrawColumnFlush(drawcolumndata_t* dc); -void R_DrawTranslucentColumnFlush(drawcolumndata_t* dc); -void R_DrawTranslatedColumnFlush(drawcolumndata_t* dc); -void R_DrawColumnShadowedFlush(drawcolumndata_t* dc); -void R_DrawTranslatedTranslucentColumnFlush(drawcolumndata_t* dc); -void R_Draw2sMultiPatchColumnFlush(drawcolumndata_t* dc); -void R_Draw2sMultiPatchTranslucentColumnFlush(drawcolumndata_t* dc); +void R_DrawColumn_Flush(drawcolumndata_t* dc); +void R_DrawTranslucentColumn_Flush(drawcolumndata_t* dc); +void R_DrawTranslatedColumn_Flush(drawcolumndata_t* dc); +void R_DrawColumnShadowed_Flush(drawcolumndata_t* dc); +void R_DrawTranslatedTranslucentColumn_Flush(drawcolumndata_t* dc); +void R_Draw2sMultiPatchColumn_Flush(drawcolumndata_t* dc); +void R_Draw2sMultiPatchTranslucentColumn_Flush(drawcolumndata_t* dc); void R_DrawFogColumn(drawcolumndata_t* dc); - // span drawers void R_DrawSpan(drawspandata_t* ds); diff --git a/src/r_draw_column.cpp b/src/r_draw_column.cpp index 3ac814e8d..b2ad1c3f4 100644 --- a/src/r_draw_column.cpp +++ b/src/r_draw_column.cpp @@ -358,24 +358,18 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) R_DrawColumnTemplate(dc); \ } -DEFINE_COLUMN_FUNC(R_DrawColumn, DC_DIRECT|DC_BASIC) -DEFINE_COLUMN_FUNC(R_DrawTranslucentColumn, DC_DIRECT|DC_TRANSMAP) -DEFINE_COLUMN_FUNC(R_DrawTranslatedColumn, DC_DIRECT|DC_COLORMAP) -DEFINE_COLUMN_FUNC(R_DrawColumnShadowed, DC_DIRECT|DC_LIGHTLIST) -DEFINE_COLUMN_FUNC(R_DrawTranslatedTranslucentColumn, DC_DIRECT|DC_COLORMAP|DC_TRANSMAP) -DEFINE_COLUMN_FUNC(R_Draw2sMultiPatchColumn, DC_DIRECT|DC_HOLES) -DEFINE_COLUMN_FUNC(R_Draw2sMultiPatchTranslucentColumn, DC_DIRECT|DC_HOLES|DC_TRANSMAP) +#define DEFINE_COLUMN_COMBO(name, flags) \ + DEFINE_COLUMN_FUNC(name, flags|DC_DIRECT) \ + DEFINE_COLUMN_FUNC(name ## _Flush, flags) -DEFINE_COLUMN_FUNC(R_DrawColumnFlush, DC_BASIC) -DEFINE_COLUMN_FUNC(R_DrawTranslucentColumnFlush, DC_TRANSMAP) -DEFINE_COLUMN_FUNC(R_DrawTranslatedColumnFlush, DC_COLORMAP) -DEFINE_COLUMN_FUNC(R_DrawColumnShadowedFlush, DC_LIGHTLIST) -DEFINE_COLUMN_FUNC(R_DrawTranslatedTranslucentColumnFlush, DC_COLORMAP|DC_TRANSMAP) -DEFINE_COLUMN_FUNC(R_Draw2sMultiPatchColumnFlush, DC_HOLES) -DEFINE_COLUMN_FUNC(R_Draw2sMultiPatchTranslucentColumnFlush, DC_HOLES|DC_TRANSMAP) +DEFINE_COLUMN_COMBO(R_DrawColumn, DC_BASIC) +DEFINE_COLUMN_COMBO(R_DrawTranslucentColumn, DC_TRANSMAP) +DEFINE_COLUMN_COMBO(R_DrawTranslatedColumn, DC_COLORMAP) +DEFINE_COLUMN_COMBO(R_DrawColumnShadowed, DC_LIGHTLIST) +DEFINE_COLUMN_COMBO(R_DrawTranslatedTranslucentColumn, DC_COLORMAP|DC_TRANSMAP) +DEFINE_COLUMN_COMBO(R_Draw2sMultiPatchColumn, DC_HOLES) +DEFINE_COLUMN_COMBO(R_Draw2sMultiPatchTranslucentColumn, DC_HOLES|DC_TRANSMAP) -//skymyass -//DEFINE_COLUMN_FUNC(R_DrawSkyColumn, DC_SKY) /** \brief The R_DrawFogColumn function Fog wall. diff --git a/src/screen.c b/src/screen.c index 78cfefd4f..4a38ef97d 100644 --- a/src/screen.c +++ b/src/screen.c @@ -101,13 +101,13 @@ static void SCR_SetDrawFuncs(enum columncontext_e _columncontext) if (_columncontext == COLUMNCONTEXT_FLUSH) { - colfuncs[BASEDRAWFUNC] = R_DrawColumnFlush; - colfuncs[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumnFlush; - colfuncs[COLDRAWFUNC_TRANS] = R_DrawTranslatedColumnFlush; - colfuncs[COLDRAWFUNC_SHADOWED] = R_DrawColumnShadowedFlush; - colfuncs[COLDRAWFUNC_TRANSTRANS] = R_DrawTranslatedTranslucentColumnFlush; - colfuncs[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumnFlush; - colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS] = R_Draw2sMultiPatchTranslucentColumnFlush; + colfuncs[BASEDRAWFUNC] = R_DrawColumn_Flush; + colfuncs[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn_Flush; + colfuncs[COLDRAWFUNC_TRANS] = R_DrawTranslatedColumn_Flush; + colfuncs[COLDRAWFUNC_SHADOWED] = R_DrawColumnShadowed_Flush; + colfuncs[COLDRAWFUNC_TRANSTRANS] = R_DrawTranslatedTranslucentColumn_Flush; + colfuncs[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn_Flush; + colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS] = R_Draw2sMultiPatchTranslucentColumn_Flush; } else { -- 2.54.0 From 1f028f523e35254ee681e9d665b23737d17f3a5e Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 19 Oct 2025 21:56:17 +0200 Subject: [PATCH 112/219] R_FlushQuad: fix unaligned memory access --- src/r_draw_flush.cpp | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/src/r_draw_flush.cpp b/src/r_draw_flush.cpp index 80da61705..e729243e9 100644 --- a/src/r_draw_flush.cpp +++ b/src/r_draw_flush.cpp @@ -151,23 +151,43 @@ static void R_FlushQuad(void) INT32 count = t_dc->commonbot - t_dc->commontop + 1; const UINT8 *restrict buf = t_dc->buf; + const UINT8 * restrict source = buf + (t_dc->commontop << 3); + UINT8 * restrict dest = R_Address(t_dc->startx, t_dc->commontop); + if constexpr (Type & ColumnFlushType::FLUSH_OPAQUE) { - const INT64 *source = reinterpret_cast(buf + (t_dc->commontop << 3)); - INT64 *dest = reinterpret_cast(R_Address(t_dc->startx, t_dc->commontop)); - const INT32 deststep = stride / 8; - - while (--count >= 0) + // aligned copy + if (((uintptr_t)dest & 7) == 0) { - *dest = *source++; - dest += deststep; + const INT64 *source64 = reinterpret_cast(source); + INT64 *dest64 = reinterpret_cast(dest); + const INT32 deststep = stride / 8; + + while (--count >= 0) + { + *dest64 = *source64++; + dest64 += deststep; + } + } + else + { + while (--count >= 0) + { + dest[0] = source[0]; + dest[1] = source[1]; + dest[2] = source[2]; + dest[3] = source[3]; + dest[4] = source[4]; + dest[5] = source[5]; + dest[6] = source[6]; + dest[7] = source[7]; + source += 8; + dest += stride; + } } } else { - const UINT8 * restrict source = buf + (t_dc->commontop << 3); - UINT8 * restrict dest = R_Address(t_dc->startx, t_dc->commontop); - while (--count >= 0) { dest[0] = R_DrawFlushPixel(t_dc, &dest[0], &source[0]); -- 2.54.0 From 28aec6cad55e432f7f989c293847f156ed680b2f Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 19 Oct 2025 21:59:14 +0200 Subject: [PATCH 113/219] add USEUBSAN compiler flag to compile with ubsan duh --- src/Makefile | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Makefile b/src/Makefile index 3422a0cf7..fd3176aa0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -69,6 +69,7 @@ # VALGRIND=1 - Enable Valgrind memory debugging support. # PROFILEMODE=1 - Enable performance profiling (gprof). # USEASAN=1 - Enable building with Address Sanitizer. +# USEUBSAN=1 - Enable building with Undefined Behavior Sanitizer. # NOLIBBACKTRACE=1 - Disable using Libbacktrace for crashlog traces. # # General flags for building: @@ -277,6 +278,17 @@ libs+=-fsanitize=address endif endif +ifdef USEUBSAN +# compile with asan +ifdef MINGW +opts+=-fsanitize=undefined -g +libs+=-fsanitize=undefined -g +else +opts+=-fsanitize=undefined +libs+=-fsanitize=undefined +endif +endif + ifeq ($(CC),clang) LDFLAGS+= -fuse-ld=lld endif -- 2.54.0 From 6d77672ee3fb2ef66bd2e222288266d98f419a88 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 19 Oct 2025 22:19:11 +0200 Subject: [PATCH 114/219] no need to pass anything to R_InitViewBuffer --- src/r_draw.cpp | 7 +------ src/r_draw.h | 5 +++-- src/r_main.cpp | 2 +- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/r_draw.cpp b/src/r_draw.cpp index 2297d1035..39f8918bb 100644 --- a/src/r_draw.cpp +++ b/src/r_draw.cpp @@ -606,13 +606,8 @@ static void R_AllocViewMemory(void) R_AllocVisSpriteMemory(); } -void R_InitViewBuffer(INT32 width, INT32 height) +void R_InitViewBuffer(void) { - if (width > MAXVIDWIDTH) - width = MAXVIDWIDTH; - if (height > MAXVIDHEIGHT) - height = MAXVIDHEIGHT; - R_AllocViewMemory(); viewwindowx = 0; diff --git a/src/r_draw.h b/src/r_draw.h index 83ec33d56..a472b5537 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -163,6 +163,8 @@ void R_DrawMaskedColumn(drawcolumndata_t* dc, column_t *column); // r_draw.c // ------------------------------------------------ +// Custom player skin translation + #define GTC_CACHE 1 #define GTC_MENUCACHE GTC_CACHE //@TODO Add a separate caching mechanism for menu colormaps distinct from in-level GTC_CACHE. For now this is still preferable to memory leaks... @@ -207,8 +209,7 @@ UINT8 *R_GetBlendTable(int style, INT32 alphalevel); boolean R_BlendLevelVisible(INT32 blendmode, INT32 alphalevel); -// Custom player skin translation -void R_InitViewBuffer(INT32 width, INT32 height); +void R_InitViewBuffer(void); void R_VideoErase(size_t ofs, INT32 count); #define TRANSPARENTPIXEL 247 diff --git a/src/r_main.cpp b/src/r_main.cpp index 37cfed8c5..50185d016 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1003,7 +1003,7 @@ static void R_InitViewMapping(void) static void R_SetupViewBuffers(void) { R_CalcFov(cv_fov.value); - R_InitViewBuffer(viewwidth, viewheight); + R_InitViewBuffer(); R_InitViewMapping(); } -- 2.54.0 From fdcbd276e961c73ccfe2838df86b40bb72851502 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 19 Oct 2025 22:59:39 +0200 Subject: [PATCH 115/219] remove unessecaary template branch in R_DrawColumnPixel --- src/r_draw_column.cpp | 10 ++-------- src/r_things.cpp | 1 - 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/r_draw_column.cpp b/src/r_draw_column.cpp index b2ad1c3f4..51690fbb0 100644 --- a/src/r_draw_column.cpp +++ b/src/r_draw_column.cpp @@ -76,14 +76,8 @@ R_DrawColumnPixel(const drawcolumndata_t* dc, UINT8 * restrict dest, UINT32 bit, } } - if constexpr (Type & DrawColumnType::DC_DIRECT) - { // if we dont buffer our columns, we need to handle translucency again - return R_GetColumnTranslucent(dc, dest, col, colormap); - } - else - { - return R_GetColumnTranslated(dc, col, colormap); - } + // if we dont buffer our columns, we need to handle translucency again + return R_GetColumnTranslucent(dc, dest, col, colormap); } /** \brief The R_DrawColumn function diff --git a/src/r_things.cpp b/src/r_things.cpp index e7eae525d..f27b7e6a2 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -730,7 +730,6 @@ static void R_DrawFlippedMaskedColumn(drawcolumndata_t* dc, column_t *column) dc->texturemid = basetexturemid; } - // Based off of R_GetLinedefTransTable transnum_t R_GetThingTransTable(fixed_t alpha, transnum_t transmap) { -- 2.54.0 From ece8d9e80cd8186cb43e2678390bbad304708d7e Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 20 Oct 2025 00:56:21 +0200 Subject: [PATCH 116/219] R_FlushQuad: fix column flush on odd width resolutions --- src/r_draw_flush.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/r_draw_flush.cpp b/src/r_draw_flush.cpp index e729243e9..1382c3ec1 100644 --- a/src/r_draw_flush.cpp +++ b/src/r_draw_flush.cpp @@ -156,8 +156,8 @@ static void R_FlushQuad(void) if constexpr (Type & ColumnFlushType::FLUSH_OPAQUE) { - // aligned copy - if (((uintptr_t)dest & 7) == 0) + // aligned copy -- make sure our dest ptr AND viewwidth are a multiple of 8! + if (((uintptr_t)dest & 7) == 0 && (stride & 7) == 0) { const INT64 *source64 = reinterpret_cast(source); INT64 *dest64 = reinterpret_cast(dest); -- 2.54.0 From c6c1dbd066ebd5baab5a33010a9b15e0c5bad8c9 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 20 Oct 2025 16:03:52 +0200 Subject: [PATCH 117/219] R_FlushQuad: also check "source" for alignment --- src/r_draw_flush.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/r_draw_flush.cpp b/src/r_draw_flush.cpp index 1382c3ec1..bc88ccca4 100644 --- a/src/r_draw_flush.cpp +++ b/src/r_draw_flush.cpp @@ -156,8 +156,8 @@ static void R_FlushQuad(void) if constexpr (Type & ColumnFlushType::FLUSH_OPAQUE) { - // aligned copy -- make sure our dest ptr AND viewwidth are a multiple of 8! - if (((uintptr_t)dest & 7) == 0 && (stride & 7) == 0) + // 8 byte aligned copy -- make sure our dest ptr, source ptr AND stride are a multiple of 8! + if ((((uintptr_t)dest | (uintptr_t)source | stride) & 7) == 0) { const INT64 *source64 = reinterpret_cast(source); INT64 *dest64 = reinterpret_cast(dest); -- 2.54.0 From 50ce3c44318b0ba297bcb7c072f7468fff6b04e2 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 20 Oct 2025 16:32:39 +0200 Subject: [PATCH 118/219] R_FlushQuad: dont use 64bit/8byte copy on 32bit targets on 32bit targets this will just compile into two 32bit copies which gcc cant optimize as well as it can with the byte copy (it seems to love to do some AVX stuff atleast in my tests) so this is only useful for 64bit capable platforms (compiler does not seem to do 64bit copys for the byte copy case, so this ends up being faster) --- src/r_draw_flush.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/r_draw_flush.cpp b/src/r_draw_flush.cpp index bc88ccca4..b135c6125 100644 --- a/src/r_draw_flush.cpp +++ b/src/r_draw_flush.cpp @@ -156,6 +156,7 @@ static void R_FlushQuad(void) if constexpr (Type & ColumnFlushType::FLUSH_OPAQUE) { +#if __SIZEOF_POINTER__ >= 8 // does not make much sense on 32bit targets // 8 byte aligned copy -- make sure our dest ptr, source ptr AND stride are a multiple of 8! if ((((uintptr_t)dest | (uintptr_t)source | stride) & 7) == 0) { @@ -170,6 +171,7 @@ static void R_FlushQuad(void) } } else +#endif { while (--count >= 0) { -- 2.54.0 From 0e9ec096c29a65b71aba9f5923ddf2b0d2ac3ef8 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 20 Oct 2025 18:36:51 +0200 Subject: [PATCH 119/219] slightly clean up makefile - pass "-g" on mingw builds generally after everything (needs testing) -use "libs" instead of "LDFLAGS" (identical purpose) - pass "mno-ms-bitfields" on gcc, shouldnt be really needed but just in case --- src/Makefile | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/src/Makefile b/src/Makefile index fd3176aa0..a75fe2656 100644 --- a/src/Makefile +++ b/src/Makefile @@ -244,10 +244,15 @@ ifdef STATIC libs+=-static endif +ifeq ($(CC),gcc) + opts+=-mno-ms-bitfields + libs+=-mno-ms-bitfields +endif + # build with profiling information ifdef PROFILEMODE opts+=-pg -LDFLAGS+=-pg +libs+=-pg endif ifdef DEBUGMODE @@ -257,40 +262,32 @@ debug_opts=-DNDEBUG opts+=-O3 ifdef USELTO # compile with LTO -ifdef MINGW -opts+=-flto=auto -g -LDFLAGS+=-flto=auto -g -else opts+=-flto=auto -LDFLAGS+=-flto=auto -endif +libs+=-flto=auto endif endif ifdef USEASAN # compile with asan -ifdef MINGW -opts+=-fsanitize=address -g -libs+=-fsanitize=address -g -else opts+=-fsanitize=address libs+=-fsanitize=address endif -endif ifdef USEUBSAN # compile with asan -ifdef MINGW -opts+=-fsanitize=undefined -g -libs+=-fsanitize=undefined -g -else opts+=-fsanitize=undefined libs+=-fsanitize=undefined endif -endif ifeq ($(CC),clang) - LDFLAGS+= -fuse-ld=lld + libs+=-fuse-ld=lld +endif + +ifdef MINGW +# mingw needs this passed AFTER lto and the likes were passed +# otherwise libbacktrace may break +opts+=-g +libs+=-g endif # debug_opts also get passed to windres -- 2.54.0 From aef6dcdbc9a91fdf86d826e05c3f91423ca3cfe9 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 20 Oct 2025 19:21:59 +0200 Subject: [PATCH 120/219] handle ceepeepee --- src/Makefile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Makefile b/src/Makefile index a75fe2656..d7a8345cd 100644 --- a/src/Makefile +++ b/src/Makefile @@ -244,9 +244,8 @@ ifdef STATIC libs+=-static endif -ifeq ($(CC),gcc) +ifneq (,$(filter $(CC) $(CXX),gcc g++)) opts+=-mno-ms-bitfields - libs+=-mno-ms-bitfields endif # build with profiling information @@ -279,7 +278,7 @@ opts+=-fsanitize=undefined libs+=-fsanitize=undefined endif -ifeq ($(CC),clang) +ifneq (,$(filter $(CC) $(CXX),clang clang++)) libs+=-fuse-ld=lld endif -- 2.54.0 From 4a786449c41065bc5e872acd0156bfc5ba5af68a Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 20 Oct 2025 19:48:18 +0200 Subject: [PATCH 121/219] fix NIGHTS hoop hoopcenter fixes visual issues when going through them --- src/p_mobj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index c16d5ce4c..2bd58e8cf 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11889,7 +11889,7 @@ void P_SpawnHoops(mapthing_t *mthing) z += P_GetSectorFloorZAt(sec, x, y); - hoopcenter->z -= hoopcenter->height/2; + hoopcenter->z = z - hoopcenter->height/2; P_UnsetThingPosition(hoopcenter); hoopcenter->x = x; -- 2.54.0 From b99cd88947ea419b3a6b347114b16f31ba373da1 Mon Sep 17 00:00:00 2001 From: Indev Date: Tue, 21 Oct 2025 01:46:29 +0300 Subject: [PATCH 122/219] Fix possible buffer overflow in M_TextInputSetString when string length is greatter than buffer length --- src/m_textinput.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/m_textinput.c b/src/m_textinput.c index 882d35e35..049222701 100644 --- a/src/m_textinput.c +++ b/src/m_textinput.c @@ -239,8 +239,8 @@ void M_TextInputClear(textinput_t *input) void M_TextInputSetString(textinput_t *input, const char *c) { memset(input->buffer, 0, input->buffer_size); - strcpy(input->buffer, c); - input->cursor = input->select = input->length = strlen(c); + strncpy(input->buffer, c, input->buffer_size); + input->cursor = input->select = input->length = strlen(input->buffer); } static boolean M_TextInputHandleBase(textinput_t *input, INT32 key, boolean emotes) -- 2.54.0 From 4c04d09d1895259d0d744cdd2f9226fd67b06c2c Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 21 Oct 2025 00:49:05 +0200 Subject: [PATCH 123/219] rename --- src/r_plane.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/r_plane.cpp b/src/r_plane.cpp index f4eb61410..bab6fcb6b 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -739,7 +739,7 @@ void R_DrawPlanes(void) #endif } -static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), boolean allow_parallel); +static void R_DrawSkyPlane(visplane_t *pl, void(*skycolfunc)(drawcolumndata_t*), boolean allow_parallel); void R_DrawSkyPlanes(void) { @@ -774,7 +774,7 @@ void R_DrawSkyPlanes(void) #endif } -static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), boolean allow_parallel) +static void R_DrawSkyPlane(visplane_t *pl, void(*skycolfunc)(drawcolumndata_t*), boolean allow_parallel) { INT32 x; @@ -834,7 +834,7 @@ static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), b dc.x = x + i; dc.source = R_GetColumn(texture, -angle); // get negative of angle for each column to display sky correct way round! --Monster Iestyn 27/01/18 - colfunc2(&dc); + skycolfunc(&dc); } }; @@ -868,10 +868,9 @@ static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), b dc.iscale = FixedMul(skyscale, FINECOSINE(xtoviewangle[x]>>ANGLETOFINESHIFT)); dc.x = x; dc.source = - R_GetColumn(texturetranslation[skytexture], - -angle); // get negative of angle for each column to display sky correct way round! --Monster Iestyn 27/01/18 + R_GetColumn(texturetranslation[skytexture], -angle); // get negative of angle for each column to display sky correct way round! --Monster Iestyn 27/01/18 - colfunc2(&dc); + skycolfunc(&dc); } #endif } -- 2.54.0 From 1acae3e4af2da4f36063847abda286953dbe14d2 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 21 Oct 2025 00:55:18 +0200 Subject: [PATCH 124/219] use malloc for spawnstate mapdata copies they might be somewhat large and get completely overwritten eitherway so save us the 0 init --- src/p_setup.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 5cf9fef39..73445b6b3 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1986,9 +1986,9 @@ static void P_LoadMapData(const virtres_t* virt) P_InitTagLists(); // Create xref tables for tags // Copy relevant map data for NetArchive purposes. - spawnsectors = Z_Calloc(numsectors * sizeof(*sectors), PU_LEVEL, NULL); - spawnlines = Z_Calloc(numlines * sizeof(*lines), PU_LEVEL, NULL); - spawnsides = Z_Calloc(numsides * sizeof(*sides), PU_LEVEL, NULL); + spawnsectors = Z_Malloc(numsectors * sizeof(*sectors), PU_LEVEL, NULL); + spawnlines = Z_Malloc(numlines * sizeof(*lines), PU_LEVEL, NULL); + spawnsides = Z_Malloc(numsides * sizeof(*sides), PU_LEVEL, NULL); memcpy(spawnsectors, sectors, numsectors * sizeof(*sectors)); memcpy(spawnlines, lines, numlines * sizeof(*lines)); -- 2.54.0 From 71e9c4f5af0a5feeebf8853be67b7e5945cf960b Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 21 Oct 2025 01:25:00 +0200 Subject: [PATCH 125/219] use "viewssnum" for shadowdir stuff --- src/hardware/hw_main.cpp | 46 +++++++++++++++++----------------------- src/r_main.cpp | 2 +- 2 files changed, 21 insertions(+), 27 deletions(-) diff --git a/src/hardware/hw_main.cpp b/src/hardware/hw_main.cpp index af797af11..45f25c2a6 100644 --- a/src/hardware/hw_main.cpp +++ b/src/hardware/hw_main.cpp @@ -3376,6 +3376,9 @@ static void HWR_DrawSpriteShadow(gl_vissprite_t *spr, patch_t *gpatch, GLPatch_t fixed_t slopez; float offset = 0; + if (!spr->mobj) + return; + R_GetShadowZ(spr->mobj, &floorslope); mobjfloor = HWR_OpaqueFloorAtPos( @@ -3387,14 +3390,7 @@ static void HWR_DrawSpriteShadow(gl_vissprite_t *spr, patch_t *gpatch, GLPatch_t angle_t shadowdir; // Set direction - if (splitscreen && R_GetViewNumber() == 1) - shadowdir = localangle[1] + FixedAngle(cv_cam_rotate[1].value); - else if (splitscreen > 1 && R_GetViewNumber() == 2) - shadowdir = localangle[2] + FixedAngle(cv_cam_rotate[2].value); - else if (splitscreen > 2 && R_GetViewNumber() == 3) - shadowdir = localangle[3] + FixedAngle(cv_cam_rotate[3].value); - else - shadowdir = localangle[0] + FixedAngle(cv_cam_rotate[0].value); + shadowdir = localangle[viewssnum] + FixedAngle(cv_cam_rotate[viewssnum].value); // Find floorheight floorheight = HWR_OpaqueFloorAtPos( @@ -3406,18 +3402,17 @@ static void HWR_DrawSpriteShadow(gl_vissprite_t *spr, patch_t *gpatch, GLPatch_t // Don't draw it, then! if (spr->mobj->z < floorheight) return; - else - { - fixed_t floorz; - floorz = HWR_OpaqueFloorAtPos( - spr->mobj->x + P_ReturnThrustX(spr->mobj, shadowdir, spr->mobj->z - floorheight), - spr->mobj->y + P_ReturnThrustY(spr->mobj, shadowdir, spr->mobj->z - floorheight), - spr->mobj->z, spr->mobj->height); - // The shadow would be falling on a wall? Don't draw it, then. - // Would draw midair otherwise. - if (floorz < floorheight) - return; - } + + fixed_t floorz; + floorz = HWR_OpaqueFloorAtPos( + spr->mobj->x + P_ReturnThrustX(spr->mobj, shadowdir, spr->mobj->z - floorheight), + spr->mobj->y + P_ReturnThrustY(spr->mobj, shadowdir, spr->mobj->z - floorheight), + spr->mobj->z, spr->mobj->height); + + // The shadow would be falling on a wall? Don't draw it, then. + // Would draw midair otherwise. + if (floorz < floorheight) + return; floorheight = FixedInt(spr->mobj->z - floorheight); @@ -3427,12 +3422,11 @@ static void HWR_DrawSpriteShadow(gl_vissprite_t *spr, patch_t *gpatch, GLPatch_t floorheight = FixedInt(spr->mobj->z - mobjfloor); // technically this_scale gets multiplied and added to sprite y/x scale, but this thing needs it for some crap so ill just throw it in here again - const boolean hires = (spr->mobj && spr->mobj->skin && K_GetMobjSkin(spr->mobj)->flags & SF_HIRES); + this_scale = FixedToFloat(spr->mobj->scale); - if (spr->mobj) - this_scale = FixedToFloat(spr->mobj->scale); - if (hires) - this_scale = this_scale * FixedToFloat(K_GetMobjSkin(spr->mobj)->highresscale); + const skin_t *moskin = K_GetMobjSkin(spr->mobj); + if (moskin && moskin->flags & SF_HIRES) + this_scale *= FixedToFloat(moskin->highresscale); // create the sprite billboard // @@ -4053,7 +4047,7 @@ static void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr) const precipmobj_t *sprmo = spr->precip; - if (UNLIKELY(!sprmo || !sprmo->subsector)) + if (UNLIKELY(!sprmo->subsector)) return; // cache sprite graphics diff --git a/src/r_main.cpp b/src/r_main.cpp index 50185d016..4686036a7 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -63,7 +63,7 @@ size_t loopcount; fixed_t viewx, viewy, viewz; angle_t viewangle, aimingangle, viewroll; -UINT8 viewssnum; +UINT8 viewssnum = 0; fixed_t viewcos, viewsin; boolean skyVisible; boolean skyVisiblePerPlayer[MAXSPLITSCREENPLAYERS]; // saved values of skyVisible for each splitscreen player -- 2.54.0 From 51b8dc9101c60fcce8531c3b03954d937a930a2e Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 21 Oct 2025 14:44:43 +0200 Subject: [PATCH 126/219] m_menu: add textinput special case for playername string itself it already checks to not write out of bounds, this is mostly just to fix visual issues kind hacky, but works for now --- src/m_menu.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index 3d8857b9a..86045dfcd 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -702,7 +702,13 @@ static void M_CheckStringItem(void) // Just in case memset(menu_text_input_buf, 0, sizeof menu_text_input_buf); - M_TextInputInit(&menuinput, menu_text_input_buf, sizeof menu_text_input_buf); + + // special case: name input, cap it to prevent writing outside the textbox + // kinda ugly but itll work + if (cv == &cv_playername) + M_TextInputInit(&menuinput, menu_text_input_buf, MAXPLAYERNAME +1); + else + M_TextInputInit(&menuinput, menu_text_input_buf, sizeof menu_text_input_buf); M_TextInputSetString(&menuinput, cv->string); } -- 2.54.0 From f2314174652d9345dd5cfb48467b7b9edb9dcbd7 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 21 Oct 2025 15:25:33 +0200 Subject: [PATCH 127/219] fix splitscreen view in gl --- src/d_main.c | 60 +++++++++++++++++++++++----------------------------- 1 file changed, 26 insertions(+), 34 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 33dc57689..5bbfee406 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -363,16 +363,36 @@ static void D_Renderview(void) for (i = 0; i <= splitscreen; i++) { - const boolean issplitscreen = (i > 0); - if (!P_MobjWasRemoved(players[displayplayers[i]].mo) || players[displayplayers[i]].playerstate == PST_DEAD) { viewssnum = i; - if (!issplitscreen) // Initialize for P1 + switch (i) { - viewwindowy = viewwindowx = 0; - objectsdrawn = 0; + case 1: + if (splitscreen > 1) + { + viewwindowx = viewwidth; + viewwindowy = 0; + } + else + { + viewwindowx = 0; + viewwindowy = viewheight; + } + break; + case 2: + viewwindowx = 0; + viewwindowy = viewheight; + break; + case 3: + viewwindowx = viewwidth; + viewwindowy = viewheight; + break; + default: // Initialize for P1 + viewwindowy = viewwindowx = 0; + objectsdrawn = 0; + break; } #ifdef HWRENDER @@ -383,38 +403,10 @@ static void D_Renderview(void) continue; } #endif - if (issplitscreen) // Splitscreen-specific - { - switch (i) - { - case 1: - if (splitscreen > 1) - { - viewwindowx = viewwidth; - viewwindowy = 0; - } - else - { - viewwindowx = 0; - viewwindowy = viewheight; - } - break; - case 2: - viewwindowx = 0; - viewwindowy = viewheight; - break; - case 3: - viewwindowx = viewwidth; - viewwindowy = viewheight; - default: - break; - } - } - R_RenderPlayerView(&players[displayplayers[i]]); } - if (!issplitscreen) + if (i == 0) R_ApplyViewMorph(); V_DoPostProcessor(i, postimgparam[i]); -- 2.54.0 From 0dad927c0530e43a81e497e344c9329084eb5066 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 21 Oct 2025 15:42:23 +0200 Subject: [PATCH 128/219] fix 4th player background not drawin in gl in 3 player splitscreen --- src/d_main.c | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 5bbfee406..1bc346deb 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -347,20 +347,6 @@ static void D_Renderview(void) } } - // Draw over the fourth screen so you don't have to stare at a HOM :V - if (splitscreen == 2) - { - // V_DrawPatchFill, but for the fourth screen only - patch_t *pat = W_CachePatchName("SRB2BACK", PU_CACHE); - INT32 x, y, pw = SHORT(pat->width) * vid.dup, ph = SHORT(pat->height) * vid.dup; - - for (x = vid.width>>1; x < vid.width; x += pw) - { - for (y = vid.height>>1; y < vid.height; y += ph) - V_DrawScaledPatch(x, y, V_NOSCALESTART, pat); - } - } - for (i = 0; i <= splitscreen; i++) { if (!P_MobjWasRemoved(players[displayplayers[i]].mo) || players[displayplayers[i]].playerstate == PST_DEAD) @@ -399,17 +385,34 @@ static void D_Renderview(void) if (rendermode == render_opengl) { HWR_RenderPlayerView(); - R_RestoreLevelInterpolators(); - continue; } + else if (rendermode == render_soft) #endif + R_RenderPlayerView(&players[displayplayers[i]]); } - if (i == 0) - R_ApplyViewMorph(); + if (rendermode == render_soft) + { + if (i == 0) + R_ApplyViewMorph(); - V_DoPostProcessor(i, postimgparam[i]); + V_DoPostProcessor(i, postimgparam[i]); + } + } + + // Draw over the fourth screen so you don't have to stare at a HOM :V + if (splitscreen == 2) + { + // V_DrawPatchFill, but for the fourth screen only + patch_t *pat = W_CachePatchName("SRB2BACK", PU_PATCH); + INT32 x, y, pw = SHORT(pat->width) * vid.dup, ph = SHORT(pat->height) * vid.dup; + + for (x = vid.width>>1; x < vid.width; x += pw) + { + for (y = vid.height>>1; y < vid.height; y += ph) + V_DrawScaledPatch(x, y, V_NOSCALESTART, pat); + } } R_RestoreLevelInterpolators(); -- 2.54.0 From 4c5d34e82c0a275fd76dfcc8ae61e4899d336344 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 21 Oct 2025 16:09:02 +0200 Subject: [PATCH 129/219] Revert "Fix ghost hitlist causing zone errors (closes #118)" This reverts commit ab13b2810669a77e6e1c5f06189a93c71b8448ec. --- src/g_demo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_demo.c b/src/g_demo.c index 4b63a1578..6b2c8f1c9 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -630,7 +630,7 @@ void G_GhostAddHit(INT32 playernum, mobj_t *victim) ghostext[playernum].flags |= EZT_HIT; ghostext[playernum].hits++; - Z_Realloc(ghostext[playernum].hitlist, ghostext[playernum].hits * sizeof(mobj_t *), PU_STATIC, &ghostext[playernum].hitlist); + ghostext[playernum].hitlist = Z_Realloc(ghostext[playernum].hitlist, ghostext[playernum].hits * sizeof(mobj_t *), PU_LEVEL, &ghostext[playernum].hitlist); P_SetTarget(ghostext[playernum].hitlist + (ghostext[playernum].hits-1), victim); } -- 2.54.0 From f5e7b65ae0f76141e7b4c41a0453b7b177b84b8d Mon Sep 17 00:00:00 2001 From: Indev Date: Tue, 21 Oct 2025 17:11:25 +0300 Subject: [PATCH 130/219] Fix replay names not displaying if you have more than INT16_MAX replays --- src/m_menu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 86045dfcd..6822dd499 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4339,7 +4339,7 @@ static void DrawReplayHutReplayInfo(void) static void M_DrawReplayHut(void) { INT32 x, y, cursory = 0; - INT16 i; + INT32 i; INT16 replaylistitem = currentMenu->numitems-2; boolean processed_one_this_frame = false; const INT32 scaledviewheight = (vid.height/vid.dup); @@ -4412,7 +4412,7 @@ static void M_DrawReplayHut(void) V_DrawCenteredString(160, 100, V_ALLOWLOWERCASE, msg); } - for (i = 0; i < (INT16)replayqueryfound; i++) + for (i = 0; i < (INT32)replayqueryfound; i++) { INT32 localy = y+i*10; INT32 localx = x; -- 2.54.0 From 1ac7852bd2b162283fdbd11042503b3c6172bcdb Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 21 Oct 2025 17:49:52 +0200 Subject: [PATCH 131/219] initialize a bunch of stuff that gets passed to realloc --- src/r_bsp.cpp | 2 +- src/r_data.c | 12 ++++++------ src/r_main.cpp | 2 +- src/r_plane.cpp | 18 +++++++++--------- src/r_things.cpp | 24 ++++++++++++------------ 5 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/r_bsp.cpp b/src/r_bsp.cpp index 6ef63739f..87d775c87 100644 --- a/src/r_bsp.cpp +++ b/src/r_bsp.cpp @@ -77,7 +77,7 @@ void R_ClearDrawSegs(void) // CPhipps - // Instead of clipsegs, let's try using an array with one entry for each column, // indicating whether it's blocked by a solid wall yet or not. -UINT8 *solidcol; +UINT8 *solidcol = NULL; void R_AllocClipSegMemory(void) { diff --git a/src/r_data.c b/src/r_data.c index 6c999d1ae..7afa1be73 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -94,17 +94,17 @@ static UINT32 **texturecolumnofs; // column offset lookup table for each texture UINT8 **texturecache; // graphics data for each generated full-size texture // texture width is a power of 2, so it can easily repeat along sidedefs using a simple mask -static INT32 *texturewidth; +static INT32 *texturewidth = NULL; -fixed_t *textureheight; // needed for texture pegging +fixed_t *textureheight = NULL; // needed for texture pegging -INT32 *texturetranslation; +INT32 *texturetranslation = NULL; // needed for pre rendering -sprcache_t *spritecachedinfo; +sprcache_t *spritecachedinfo = NULL; -lighttable_t *colormaps; -UINT8 *encoremap; +lighttable_t *colormaps = NULL; +UINT8 *encoremap = NULL; #ifdef HASINVERT UINT8 invertmap[256]; #endif diff --git a/src/r_main.cpp b/src/r_main.cpp index 4686036a7..33569fe80 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -88,7 +88,7 @@ INT32 viewangletox[FINEANGLES/2]; // The xtoviewangleangle[] table maps a screen pixel // to the lowest viewangle that maps back to x ranges // from clipangle to -clipangle. -angle_t *xtoviewangle; +angle_t *xtoviewangle = NULL; lighttable_t *scalelight[LIGHTLEVELS][MAXLIGHTSCALE]; lighttable_t *scalelightfixed[MAXLIGHTSCALE]; diff --git a/src/r_plane.cpp b/src/r_plane.cpp index bab6fcb6b..1adccfba1 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -46,15 +46,15 @@ // good night sweet prince //#define SHITPLANESPARENCY -visplane_t *visplanes[MAXVISPLANES]; +visplane_t *visplanes[MAXVISPLANES] = {}; static visplane_t *freetail; static visplane_t **freehead = &freetail; visplane_t *floorplane; visplane_t *ceilingplane; -visffloor_t visffloor[MAXFFLOORS]; -INT32 numffloors; +visffloor_t visffloor[MAXFFLOORS] = {}; +INT32 numffloors = 0; //SoM: 3/23/2000: Boom visplane hashing routine. #define visplane_hash(picnum,lightlevel,height) \ @@ -65,8 +65,8 @@ INT32 numffloors; // floorclip starts out SCREENHEIGHT // ceilingclip starts out -1 // -INT16 *floorclip, *ceilingclip; -fixed_t *frontscale; +INT16 *floorclip = NULL, *ceilingclip = NULL; +fixed_t *frontscale = NULL; // // spanstart holds the start of a plane span @@ -81,13 +81,13 @@ static INT32 *spanstart; // (this is to calculate yslopes only when really needed) // (when mouselookin', yslope is moving into yslopetab) // Check R_SetupFrame, R_SetViewSize for more... -fixed_t *yslopetab; -fixed_t *yslope; +fixed_t *yslopetab = NULL; +fixed_t *yslope = NULL; fixed_t basexscale, baseyscale; -static INT16 *ffloor_f_clip; -static INT16 *ffloor_c_clip; +static INT16 *ffloor_f_clip = NULL; +static INT16 *ffloor_c_clip = NULL; static void R_SetTiltedSpan(drawspandata_t* ds, INT32 span); static void R_SetSlopePlaneVectors(drawspandata_t* ds, visplane_t *pl, INT32 y, fixed_t xoff, fixed_t yoff); diff --git a/src/r_things.cpp b/src/r_things.cpp index f27b7e6a2..796f6c4a2 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -60,8 +60,8 @@ typedef struct static lighttable_t **spritelights; // constant arrays used for psprite clipping and initializing clipping -INT16 *negonearray; -INT16 *screenheightarray; +INT16 *negonearray = NULL; +INT16 *screenheightarray = NULL; // // INITIALIZATION FUNCTIONS @@ -539,8 +539,8 @@ void R_ClearSprites(void) visspritecount = numvisiblesprites = clippedvissprites = 0; } -static INT16 *vissprite_clipbot[MAXVISSPRITES >> VISSPRITECHUNKBITS]; -static INT16 *vissprite_cliptop[MAXVISSPRITES >> VISSPRITECHUNKBITS]; +static INT16 *vissprite_clipbot[MAXVISSPRITES >> VISSPRITECHUNKBITS] = {0}; +static INT16 *vissprite_cliptop[MAXVISSPRITES >> VISSPRITECHUNKBITS] = {0}; static void R_AllocVisSpriteChunkMemory(UINT32 chunk) { @@ -574,16 +574,16 @@ static vissprite_t overflowsprite; static vissprite_t *R_GetVisSprite(UINT32 num) { - UINT32 chunk = num >> VISSPRITECHUNKBITS; + UINT32 chunk = num >> VISSPRITECHUNKBITS; - // Allocate chunk if necessary - if (!visspritechunks[chunk]) - { - Z_Malloc(sizeof(vissprite_t) * VISSPRITESPERCHUNK, PU_LEVEL, &visspritechunks[chunk]); - R_AllocVisSpriteChunkMemory(chunk); - } + // Allocate chunk if necessary + if (!visspritechunks[chunk]) + { + Z_Malloc(sizeof(vissprite_t) * VISSPRITESPERCHUNK, PU_LEVEL, &visspritechunks[chunk]); + R_AllocVisSpriteChunkMemory(chunk); + } - return visspritechunks[chunk] + (num & VISSPRITEINDEXMASK); + return visspritechunks[chunk] + (num & VISSPRITEINDEXMASK); } static vissprite_t *R_NewVisSprite(void) -- 2.54.0 From 0f43f19b71f1ae24c9102c8271594fd5bbc147bd Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 21 Oct 2025 18:00:54 +0200 Subject: [PATCH 132/219] remove unused maskdraw_t struct --- src/r_data.c | 4 ++-- src/r_things.cpp | 11 ++--------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index 7afa1be73..a796de138 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -90,8 +90,8 @@ INT32 numtextures = 0; // total number of textures found, // size of following tables texture_t **textures = NULL; -static UINT32 **texturecolumnofs; // column offset lookup table for each texture -UINT8 **texturecache; // graphics data for each generated full-size texture +static UINT32 **texturecolumnofs = NULL; // column offset lookup table for each texture +UINT8 **texturecache = NULL; // graphics data for each generated full-size texture // texture width is a power of 2, so it can easily repeat along sidedefs using a simple mask static INT32 *texturewidth = NULL; diff --git a/src/r_things.cpp b/src/r_things.cpp index 796f6c4a2..75c333cd4 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -43,13 +43,6 @@ #define MINZ (FRACUNIT*16) #define BASEYCENTER (BASEVIDHEIGHT/2) -typedef struct -{ - INT32 x1, x2; - INT32 column; - INT32 topclip, bottomclip; -} maskdraw_t; - // // Sprite rotation 0 is facing the viewer, // rotation 1 is one angle turn CLOCKWISE around the axis. @@ -600,8 +593,8 @@ static vissprite_t *R_NewVisSprite(void) // Masked means: partly transparent, i.e. stored // in posts/runs of opaque pixels. // -INT16 *mfloorclip; -INT16 *mceilingclip; +INT16 *mfloorclip = NULL; +INT16 *mceilingclip = NULL; fixed_t spryscale = 0, sprtopscreen = 0, sprbotscreen = 0; fixed_t windowtop = 0, windowbottom = 0; -- 2.54.0 From 2009cdeaeb2c730c58e59050467598c8ee4ba80e Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 21 Oct 2025 18:24:14 +0200 Subject: [PATCH 133/219] init few more things --- src/r_plane.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 1adccfba1..543faec77 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -50,8 +50,8 @@ visplane_t *visplanes[MAXVISPLANES] = {}; static visplane_t *freetail; static visplane_t **freehead = &freetail; -visplane_t *floorplane; -visplane_t *ceilingplane; +visplane_t *floorplane = NULL; +visplane_t *ceilingplane = NULL; visffloor_t visffloor[MAXFFLOORS] = {}; INT32 numffloors = 0; @@ -84,7 +84,7 @@ static INT32 *spanstart; fixed_t *yslopetab = NULL; fixed_t *yslope = NULL; -fixed_t basexscale, baseyscale; +fixed_t basexscale = 0, baseyscale = 0; static INT16 *ffloor_f_clip = NULL; static INT16 *ffloor_c_clip = NULL; -- 2.54.0 From f8e5049d7659de589ca7adbf33a72c22d1f991cc Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 21 Oct 2025 19:24:56 +0200 Subject: [PATCH 134/219] fix R_MakeSpans accessing "spanstart" out of bounds when in splitscreen it gets allocated for viewheight not vid.height! --- src/r_plane.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 543faec77..8ef47f722 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -616,14 +616,12 @@ void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop) // static void R_MakeSpans(void (*mapfunc)(drawspandata_t* ds, void(*spanfunc)(drawspandata_t*), INT32, INT32, INT32, boolean), spandrawfunc_t* localspanfunc, drawspandata_t* ds, INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2, boolean allow_parallel) { - const INT32 vidheight = vid.height; - // Alam: from r_splats's R_RenderFloorSplat - if (t1 >= vidheight) t1 = vidheight-1; - if (b1 >= vidheight) b1 = vidheight-1; - if (t2 >= vidheight) t2 = vidheight-1; - if (b2 >= vidheight) b2 = vidheight-1; - if (x-1 >= vid.width) x = vid.width; + if (t1 >= viewheight) t1 = viewheight-1; + if (b1 >= viewheight) b1 = viewheight-1; + if (t2 >= viewheight) t2 = viewheight-1; + if (b2 >= viewheight) b2 = viewheight-1; + if (x-1 >= viewwidth) x = viewwidth; #ifdef HAVE_THREADS // We want to draw N spans per subtask to ensure the work is -- 2.54.0 From 27433f6fb5ebbb27cca1528db908e78e63ebea71 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 21 Oct 2025 19:26:01 +0200 Subject: [PATCH 135/219] call R_SetupFreelook in R_ExecuteSetViewSize to instantly update our now stale yslope pointer! fixes random crashes when switching numbers of splitviews in replays --- src/r_fps.cpp | 2 +- src/r_fps.h | 1 + src/r_main.cpp | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/r_fps.cpp b/src/r_fps.cpp index ad8c97aed..98bfaf68b 100644 --- a/src/r_fps.cpp +++ b/src/r_fps.cpp @@ -172,7 +172,7 @@ static vector3_t *R_LerpVector3(const vector3_t *from, const vector3_t *to, fixe // recalc necessary stuff for mouseaiming // slopes are already calculated for the full possible view (which is 4*viewheight). // 18/08/18: (No it's actually 16*viewheight, thanks Lactozilla for finding this out) -static void R_SetupFreelook(void) +void R_SetupFreelook(void) { // clip it in the case we are looking a hardware 90 degrees full aiming // (lmps, network and use F12...) diff --git a/src/r_fps.h b/src/r_fps.h index 49ca669d3..7ad5e9f16 100644 --- a/src/r_fps.h +++ b/src/r_fps.h @@ -151,6 +151,7 @@ typedef struct levelinterpolator_s { }; } levelinterpolator_t; +void R_SetupFreelook(void); // Interpolates the current view variables (r_state.h) against the selected view context in R_SetViewContext void R_InterpolateView(fixed_t frac, boolean forceinvalid); // Special function just for software diff --git a/src/r_main.cpp b/src/r_main.cpp index 33569fe80..a340ef29c 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -960,6 +960,8 @@ void R_ExecuteSetViewSize(void) } } + R_SetupFreelook(); + am_recalc = true; } -- 2.54.0 From 93d0106c28bcb9d2becabd9fd677ca16f54f6a47 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 22 Oct 2025 10:38:22 +0200 Subject: [PATCH 136/219] remove erronous ";" --- src/d_netcmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 002195ec1..a99ece58a 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -4472,7 +4472,7 @@ static void Command_Addfile(void) if (IsPlayerAdmin(consoleplayer) && (!server)) // Request to add file SendNetXCmd(XD_REQADDFILE, buf, buf_p - buf); else - SendNetXCmd(XD_ADDFILE, buf, buf_p - buf);; + SendNetXCmd(XD_ADDFILE, buf, buf_p - buf); } /** Adds something at runtime. -- 2.54.0 From ab27090ecf985c461a933d68a40447fa2ab4900e Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 21 Oct 2025 20:48:22 +0100 Subject: [PATCH 137/219] Don't send a netxcmd when using addfile outside of netgame Was supposed to be happening already, but `multiplayer` is a useless variable... --- src/d_netcmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index a99ece58a..65dd1d4cf 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -4429,7 +4429,7 @@ static void Command_Addfile(void) } // Add file on your client directly if it is trivial, or you aren't in a netgame. - if (!(netgame || multiplayer) || musiconly) + if (!netgame || musiconly) { P_AddWadFile(fn, false); return; -- 2.54.0 From a94740f5e9b9cb9cb4fd91ad668c4d04c8e5afa6 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Sun, 26 Feb 2023 04:29:13 -0700 Subject: [PATCH 138/219] Fix unsteady camera movement in demos --- src/p_user.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index a5c01152a..b99998844 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3315,7 +3315,7 @@ static ticcmd_t *P_CameraCmd(camera_t *cam, UINT8 num) cmd->sidemove = (SINT8)(cmd->sidemove + side); } - lang += (cmd->angleturn<<16); + lang += (cmd->angleturn << 16); cam->localangle = lang; if (!cam->reset_aiming) @@ -3821,7 +3821,13 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (demo.playback) { - focusangle = mo->angle; + // Hack-adjacent. + // Sometimes stale ticcmds send a weird angle at the start of the race. + // P_UpdatePlayerAngle knows to ignore cmd angle when you literally can't turn, so we do the same here. + if (leveltime > starttime) + focusangle = player->cmd.angleturn << 16; + else + focusangle = mo->angle; // Just use something known sane. focusaiming = 0; } else if (P_IsLocalPlayer(player)) -- 2.54.0 From 77f4d4ef3bd55528043cfcc52b730bc023b03364 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 22 Oct 2025 13:42:33 +0200 Subject: [PATCH 139/219] fix replays occasionally crashing when stopping due to R_ReInitColormaps our extra_colormaps pointer may be freed so ensure it only gets called after gamestate has been set to GS_NULL so we dont risk doing this mid renderframe fixes crashes in software and palette render mode --- src/g_demo.c | 11 ++++++----- src/r_main.cpp | 3 ++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/g_demo.c b/src/g_demo.c index 6b2c8f1c9..de8523ae9 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -3411,11 +3411,6 @@ void G_StopDemo(void) demo.rewinding = false; CL_ClearRewinds(); - if (gamestate == GS_LEVEL && rendermode != render_none) - { - V_SetPaletteLump("PLAYPAL"); // Reset the palette - R_ReInitColormaps(0, LUMPERROR); - } if (gamestate == GS_INTERMISSION) Y_EndIntermission(); // cleanup if (gamestate == GS_VOTING) @@ -3427,6 +3422,12 @@ void G_StopDemo(void) wipegamestate = GS_NULL; SV_StopServer(); SV_ResetServer(); + + if (gamestate == GS_LEVEL && rendermode != render_none) + { + V_SetPaletteLump("PLAYPAL"); // Reset the palette + R_ReInitColormaps(0, LUMPERROR); + } } // Stops timing a demo. diff --git a/src/r_main.cpp b/src/r_main.cpp index a340ef29c..5313357d6 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -943,9 +943,10 @@ void R_ExecuteSetViewSize(void) memset(scalelight, 0xFF, sizeof(scalelight)); // Calculate the light levels to use for each level/scale combination. - for (i = 0; i< LIGHTLEVELS; i++) + for (i = 0; i < LIGHTLEVELS; i++) { startmapl = ((LIGHTLEVELS - 1 - i)*2)*NUMCOLORMAPS/LIGHTLEVELS; + for (j = 0; j < MAXLIGHTSCALE; j++) { level = startmapl - j*vid.width/(viewwidth)/DISTMAP; -- 2.54.0 From 5289027272dce5cbd2179da4427a1feeb63476f1 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 22 Oct 2025 15:32:38 +0200 Subject: [PATCH 140/219] uninline ctf resynch stuff this wont ever be used and just makes lto and others complain occasionally (maybe frenmod uses ctf? forgor) --- src/d_clisrv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index a62ebde7c..61afc0eb7 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -823,7 +823,7 @@ static void resynch_read_player(resynch_pak *rsp) P_SetThingPosition(players[i].mo); } -static inline void resynch_write_ctf(resynchend_pak *rst) +static void resynch_write_ctf(resynchend_pak *rst) { mobj_t *mflag; UINT8 i, j; @@ -863,7 +863,7 @@ static inline void resynch_write_ctf(resynchend_pak *rst) } } -static inline void resynch_read_ctf(resynchend_pak *p) +static void resynch_read_ctf(resynchend_pak *p) { UINT8 i; -- 2.54.0 From f74980027613ade10f50fa4c4dfa9ad81e9fde28 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 22 Oct 2025 15:33:09 +0200 Subject: [PATCH 141/219] fix playersetup skin speen reading out of bounds reported by ubsan --- src/m_menu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 6822dd499..e9915cb9c 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -8279,12 +8279,12 @@ static void M_DrawSetupMultiPlayerMenu(void) sprframe = &sprdef->spriteframes[frame]; - //minenice's speen css, it's a piece of shit but hey + // minenice's speen css, it's a piece of shit but hey 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 - if ((sprframe->lumppat[speenframe] == sprframe->lumppat[8-speenframe]) && (speenframe > 4)) + // this is a very shitty solution for checking if a sprite needs flipping + // but it works + if ((speenframe > 4) && (sprframe->lumppat[speenframe] == sprframe->lumppat[8-speenframe])) flags = V_FLIP; // This sprite is left/right flipped! patch = (patch_t *)W_CachePatchNum(sprframe->lumppat[speenframe], PU_PATCH); -- 2.54.0 From e5bae89d0f716de6f1e52bcafb2d855f26179818 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 22 Oct 2025 15:34:24 +0200 Subject: [PATCH 142/219] fix namescrollbuf and mapmusic.name copies ensure those are properly null terminated as reported by ubsan --- src/m_menu.c | 8 ++++++-- src/p_spec.c | 3 +-- src/w_wad.c | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index e9915cb9c..a7be33c42 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -7179,17 +7179,21 @@ static void M_DrawLevelSelectOnly(boolean leftfade, boolean rightfade) namescroll = 0; } - if (renderisnewtic) namescroll++; + if (renderisnewtic) + namescroll++; char *addonname = wadfiles[mapwads[cv_nextmap.value-1]]->filename; INT32 len; INT32 charlimit = min((size_t)(21 + (dupadjust/5)), sizeof(namescrollbuf)-1); + nameonly(addonname); len = strlen(addonname); + if (len > charlimit) M_ScrollString(addonname, len, namescrollbuf, charlimit, namescroll); else - strncpy(namescrollbuf, addonname, sizeof(namescrollbuf)); + strncpy(namescrollbuf, addonname, sizeof(namescrollbuf) - 1); + V_DrawThinString(x+w+5, y+i-8, V_TRANSLUCENT|MENUCAPS, namescrollbuf); // variable reuse... } diff --git a/src/p_spec.c b/src/p_spec.c index cf2ca3e3e..e7b032131 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2091,8 +2091,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) // Change the music and apply position/fade operations else { - strncpy(mapmusic.name, sides[line->sidenum[0]].text, 7); - mapmusic.name[6] = 0; + strlcpy(mapmusic.name, sides[line->sidenum[0]].text, sizeof(mapmusic.name)); mapmusic.flags = tracknum & MUSIC_TRACKMASK; if (!(line->flags & ML_BLOCKMONSTERS)) diff --git a/src/w_wad.c b/src/w_wad.c index 1cfb3f616..95992fb42 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -261,7 +261,7 @@ static inline void W_LoadDehackedLumpsPK3(UINT16 wadnum) sprintf(name, "%s|%s", wadfiles[wadnum]->filename, lump_p->fullname); name[length] = '\0'; - CONS_Printf(M_GetText("Loading SOC from %s\n"), name); + CONS_Printf("Loading SOC from %s\n", name); DEH_LoadDehackedLumpPwad(wadnum, posStart); free(name); } -- 2.54.0 From 5f394cd938a89685ad1dfa20404363b626a7b101 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 22 Oct 2025 16:02:24 +0200 Subject: [PATCH 143/219] handle more memory allocation failure cases reported with -Wformat-overflow --- src/command.c | 2 ++ src/d_netcmd.c | 23 ++++++++++++++++++----- src/dedicated/i_system.c | 2 +- src/g_game.c | 4 ++++ src/lua_script.c | 4 ++++ src/sdl/i_system.cpp | 9 ++++++++- src/w_wad.c | 6 ++++++ 7 files changed, 43 insertions(+), 7 deletions(-) diff --git a/src/command.c b/src/command.c index 47bd521b0..463325e60 100644 --- a/src/command.c +++ b/src/command.c @@ -938,6 +938,8 @@ static void COM_Find_f(void) } help = COM_Argv(1); + if (!help) + return; helplen = strlen(help); CONS_Printf("\x82""Variables:\n"); matchesany = false; diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 65dd1d4cf..d62be9daa 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2596,14 +2596,18 @@ ConcatCommandArgv (int start, int end) size += strlen(COM_Argv(i)) + 1; } - final = ZZ_Alloc(size); - p = final; + p = final = ZZ_Alloc(size); + + if (!p) + I_Error("ConcatCommandArgv: Out of memory!\n"); --end;/* handle the final argument separately */ + for (i = start; i < end; ++i) { p += sprintf(p, "%s ", COM_Argv(i)); } + /* at this point "end" is actually the last argument's position */ strcpy(p, COM_Argv(end)); @@ -4214,23 +4218,32 @@ static void Command_MotD_f(void) mymotd = Z_Malloc(sizeof(motd), PU_STATIC, NULL); - strlcpy(mymotd, COM_Argv(1), sizeof motd); + if (!mymotd) + return; + //I_Error("Command_MotD_f: Out of memory!\n"); // idk if this aint a bit too much lel + + strlcpy(mymotd, COM_Argv(1), sizeof(motd)); + for (i = 2; i < j; i++) { - strlcat(mymotd, " ", sizeof motd); - strlcat(mymotd, COM_Argv(i), sizeof motd); + strlcat(mymotd, " ", sizeof(motd)); + strlcat(mymotd, COM_Argv(i), sizeof(motd)); } // Disallow non-printing characters and semicolons. for (i = 0; mymotd[i] != '\0'; i++) + { if (!isprint(mymotd[i]) || mymotd[i] == ';') { Z_Free(mymotd); return; } + } if ((netgame || multiplayer) && client) + { SendNetXCmd(XD_SETMOTD, mymotd, i); // send the actual size of the motd string, not the full buffer's size + } else { strcpy(motd, mymotd); diff --git a/src/dedicated/i_system.c b/src/dedicated/i_system.c index 865ae4584..78f265e2a 100644 --- a/src/dedicated/i_system.c +++ b/src/dedicated/i_system.c @@ -1442,7 +1442,7 @@ static INT32 errorcount = 0; */ static boolean shutdowning = false; -void I_Error(const char *error, ...) +FUNCIERROR void ATTRNORETURN I_Error(const char *error, ...) { va_list argptr; char buffer[8192]; diff --git a/src/g_game.c b/src/g_game.c index 5c984ad87..796c154d5 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4061,7 +4061,11 @@ char *G_BuildMapTitle(INT32 mapnum) title = Z_Malloc(len, PU_STATIC, NULL); + if (!title) + return NULL; + sprintf(title, "%s", mapheaderinfo[mapnum-1]->lvlttl); + if (zonetext) sprintf(title + strlen(title), " %s", zonetext); if (actnum) sprintf(title + strlen(title), " %s", actnum); } diff --git a/src/lua_script.c b/src/lua_script.c index 723624ee2..e59841940 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -288,6 +288,10 @@ void LUA_LoadLump(UINT16 wad, UINT16 lump) lumpinfo_t *lump_p = &wadfiles[wad]->lumpinfo[lump]; len += 1 + strlen(lump_p->fullname); // length of file name, '|', and lump name name = malloc(len+1); + + if (!name) + I_Error("LUA_LoadLump: Out of memory!\n"); + sprintf(name, "%s|%s", wadfiles[wad]->filename, lump_p->fullname); name[len] = '\0'; } diff --git a/src/sdl/i_system.cpp b/src/sdl/i_system.cpp index 2663887d6..4e9e54d72 100644 --- a/src/sdl/i_system.cpp +++ b/src/sdl/i_system.cpp @@ -545,7 +545,7 @@ static inline void I_ShutdownConsole(void){} // -//I_OutputMsg +// I_OutputMsg // void I_OutputMsg(const char *fmt, ...) { @@ -553,6 +553,9 @@ void I_OutputMsg(const char *fmt, ...) char *txt; va_list argptr; + if (!fmt) + return; + va_start(argptr,fmt); len = vsnprintf(NULL, 0, fmt, argptr); va_end(argptr); @@ -560,6 +563,10 @@ void I_OutputMsg(const char *fmt, ...) return; txt = static_cast(malloc(len+1)); + + if (!txt) + I_Error("I_OutputMsg: Out of memory!\n"); + va_start(argptr,fmt); vsprintf(txt, fmt, argptr); va_end(argptr); diff --git a/src/w_wad.c b/src/w_wad.c index 95992fb42..756dee4a6 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -259,6 +259,9 @@ static inline void W_LoadDehackedLumpsPK3(UINT16 wadnum) size_t length = len + 1 + strlen(lump_p->fullname); // length of file name, '|', and lump name char *name = malloc(length + 1); + if (!name) + I_Error("W_LoadDehackedLumpsPK3: Out of memory!\n"); + sprintf(name, "%s|%s", wadfiles[wadnum]->filename, lump_p->fullname); name[length] = '\0'; CONS_Printf("Loading SOC from %s\n", name); @@ -292,6 +295,9 @@ static inline void W_LoadDehackedLumps(UINT16 wadnum) size_t length = len + 1 + strlen(lump_p->fullname); // length of file name, '|', and lump name char *name = malloc(length + 1); + if (!name) + I_Error("W_LoadDehackedLumps: Out of memory!\n"); + sprintf(name, "%s|%s", wadfiles[wadnum]->filename, lump_p->fullname); name[length] = '\0'; -- 2.54.0 From 41407538d4cbb4f3266db9edb6b3022a54724402 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 22 Oct 2025 22:52:06 +0200 Subject: [PATCH 144/219] cleanup + optimizations mixer_sound thx indev for the better ms rounding code <3 --- src/sdl/mixer_sound.c | 356 +++++++++++++++++++++++++++--------------- 1 file changed, 234 insertions(+), 122 deletions(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index cbc3f5334..646d44135 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -123,13 +123,12 @@ static int result; static void var_cleanup(void) { song_length = loop_point = 0.0f; - music_bytes = fading_source = fading_target =\ - fading_timer = fading_duration = 0; + music_bytes = fading_source = fading_target = + fading_timer = fading_duration = 0; music_end_bytes = 0; music_stutter_bytes = 0; - songpaused = is_looping =\ - is_fading = false; + songpaused = is_looping = is_fading = false; fading_callback = NULL; fading_do_callback = false; @@ -229,6 +228,7 @@ void I_ShutdownSound(void) { if (!sound_started) return; // not an error condition + sound_started = false; Mix_CloseAudio(); @@ -254,6 +254,7 @@ void I_UpdateSound(void) { if (fading_callback) (*fading_callback)(); + fading_callback = NULL; fading_do_callback = false; } @@ -280,6 +281,7 @@ static Mix_Chunk *ds2chunk(void *stream) ver = READUINT16(stream); // sound version format? if (ver != 3) // It should be 3 if it's a doomsound... return NULL; // onos! it's not a doomsound! + freq = READUINT16(stream); samples = READUINT32(stream); @@ -287,91 +289,100 @@ static Mix_Chunk *ds2chunk(void *stream) return NULL; // division by zero // convert from signed 8bit ???hz to signed 16bit 44100hz. - switch(freq) + switch (freq) { - case 44100: - if (samples >= UINT32_MAX>>2) - return NULL; // would wrap, can't store. - newsamples = samples; - break; - case 22050: - if (samples >= UINT32_MAX>>3) - return NULL; // would wrap, can't store. - newsamples = samples<<1; - break; - case 11025: - if (samples >= UINT32_MAX>>4) - return NULL; // would wrap, can't store. - newsamples = samples<<2; - break; - default: - frac = (44100 << FRACBITS) / (UINT32)freq; - if (!(frac & 0xFFFF)) // other solid multiples (change if FRACBITS != 16) - newsamples = samples * (frac >> FRACBITS); - else // strange and unusual fractional frequency steps, plus anything higher than 44100hz. - newsamples = FixedMul(FixedDiv(samples, freq), 44100) + 1; // add 1 to counter truncation. - if (newsamples >= UINT32_MAX>>2) - return NULL; // would and/or did wrap, can't store. - break; + case 44100: + if (samples >= UINT32_MAX>>2) + return NULL; // would wrap, can't store. + + newsamples = samples; + break; + case 22050: + if (samples >= UINT32_MAX>>3) + return NULL; // would wrap, can't store. + + newsamples = samples<<1; + break; + case 11025: + if (samples >= UINT32_MAX>>4) + return NULL; // would wrap, can't store. + + newsamples = samples<<2; + break; + default: + frac = (44100 << FRACBITS) / (UINT32)freq; + + if (!(frac & 0xFFFF)) // other solid multiples (change if FRACBITS != 16) + newsamples = samples * (frac >> FRACBITS); + else // strange and unusual fractional frequency steps, plus anything higher than 44100hz. + newsamples = FixedMul(FixedDiv(samples, freq), 44100) + 1; // add 1 to counter truncation. + + if (newsamples >= UINT32_MAX>>2) + return NULL; // would and/or did wrap, can't store. + + break; } + sound = Z_Malloc(newsamples<<2, PU_SOUND, NULL); // samples * frequency shift * bytes per sample * channels s = (SINT8 *)stream; d = (INT16 *)sound; i = 0; + switch(freq) { - case 44100: // already at the same rate? well that makes it simple. - while(i++ < samples) - { - o = ((INT16)(*s++)+0x80)<<8; // changed signedness and shift up to 16 bits - *d++ = o; // left channel - *d++ = o; // right channel - } - break; - case 22050: // unwrap 2x - while(i++ < samples) - { - o = ((INT16)(*s++)+0x80)<<8; // changed signedness and shift up to 16 bits - *d++ = o; // left channel - *d++ = o; // right channel - *d++ = o; // left channel - *d++ = o; // right channel - } - break; - case 11025: // unwrap 4x - while(i++ < samples) - { - o = ((INT16)(*s++)+0x80)<<8; // changed signedness and shift up to 16 bits - *d++ = o; // left channel - *d++ = o; // right channel - *d++ = o; // left channel - *d++ = o; // right channel - *d++ = o; // left channel - *d++ = o; // right channel - *d++ = o; // left channel - *d++ = o; // right channel - } - break; - default: // convert arbitrary hz to 44100. - step = 0; - frac = ((UINT32)freq << FRACBITS) / 44100 + 1; //Add 1 to counter truncation. - while (i < samples) - { - o = (INT16)(*s+0x80)<<8; // changed signedness and shift up to 16 bits - while (step < FRACUNIT) // this is as fast as I can make it. + case 44100: // already at the same rate? well that makes it simple. + while(i++ < samples) { + o = ((INT16)(*s++)+0x80)<<8; // changed signedness and shift up to 16 bits *d++ = o; // left channel *d++ = o; // right channel - step += frac; } - do { - i++; s++; - step -= FRACUNIT; - } while (step >= FRACUNIT); - } - break; + break; + case 22050: // unwrap 2x + while(i++ < samples) + { + o = ((INT16)(*s++)+0x80)<<8; // changed signedness and shift up to 16 bits + *d++ = o; // left channel + *d++ = o; // right channel + *d++ = o; // left channel + *d++ = o; // right channel + } + break; + case 11025: // unwrap 4x + while(i++ < samples) + { + o = ((INT16)(*s++)+0x80)<<8; // changed signedness and shift up to 16 bits + *d++ = o; // left channel + *d++ = o; // right channel + *d++ = o; // left channel + *d++ = o; // right channel + *d++ = o; // left channel + *d++ = o; // right channel + *d++ = o; // left channel + *d++ = o; // right channel + } + break; + default: // convert arbitrary hz to 44100. + step = 0; + frac = ((UINT32)freq << FRACBITS) / 44100 + 1; //Add 1 to counter truncation. + + while (i < samples) + { + o = (INT16)(*s+0x80)<<8; // changed signedness and shift up to 16 bits + while (step < FRACUNIT) // this is as fast as I can make it. + { + *d++ = o; // left channel + *d++ = o; // right channel + step += frac; + } + do { + i++; s++; + step -= FRACUNIT; + } while (step >= FRACUNIT); + } + break; } // return Mixer Chunk. @@ -390,12 +401,14 @@ void *I_GetSfx(sfxinfo_t *sfx) if (sfx->lumpnum == LUMPERROR) sfx->lumpnum = S_GetSfxLumpNum(sfx); + sfx->length = W_LumpLength(sfx->lumpnum); lump = W_CacheLumpNum(sfx->lumpnum, PU_SOUND); // convert from standard DoomSound format. chunk = ds2chunk(lump); + if (chunk) { Z_Free(lump); @@ -415,6 +428,7 @@ void *I_GetSfx(sfxinfo_t *sfx) int zErr; // Somewhere to handle any error messages zlib tosses out memset(&stream, 0x00, sizeof (z_stream)); // Init zlib stream + // Begin the inflation process inflatedLen = *(UINT32 *)lump + (sfx->length-4); // Last 4 bytes are the decompressed size, typically inflatedData = (UINT8 *)Z_Malloc(inflatedLen, PU_SOUND, NULL); // Make room for the decompressed data @@ -424,10 +438,13 @@ void *I_GetSfx(sfxinfo_t *sfx) stream.next_out = inflatedData; zErr = inflateInit2(&stream, 32 + MAX_WBITS); + if (zErr == Z_OK) // We're good to go { zErr = inflate(&stream, Z_FINISH); - if (zErr == Z_STREAM_END) { + + if (zErr == Z_STREAM_END) + { // Run GME on new data if (!gme_open_data(inflatedData, inflatedLen, &emu, SAMPLERATE)) { @@ -444,6 +461,7 @@ void *I_GetSfx(sfxinfo_t *sfx) len = (info->play_length * 441 / 10) << 2; mem = Z_Malloc(len, PU_SOUND, 0); + gme_play(emu, len >> 1, mem); gme_free_info(info); gme_delete(emu); @@ -453,10 +471,14 @@ void *I_GetSfx(sfxinfo_t *sfx) } else CONS_Alert(CONS_ERROR,"Encountered %s when running inflate: %s\n", get_zlib_error(zErr), stream.msg); + (void)inflateEnd(&stream); } else // Hold up, zlib's got a problem + { CONS_Alert(CONS_ERROR,"Encountered %s when running inflateInit: %s\n", get_zlib_error(zErr), stream.msg); + } + Z_Free(inflatedData); // GME didn't open jack, but don't let that stop us from freeing this up #else return NULL; // No zlib support @@ -477,6 +499,7 @@ void *I_GetSfx(sfxinfo_t *sfx) len = (info->play_length * 441 / 10) << 2; mem = Z_Malloc(len, PU_SOUND, 0); + gme_play(emu, len >> 1, mem); gme_free_info(info); gme_delete(emu); @@ -487,6 +510,7 @@ void *I_GetSfx(sfxinfo_t *sfx) // Try to load it as a WAVE or OGG using Mixer. rw = SDL_RWFromMem(lump, sfx->length); + if (rw != NULL) { chunk = Mix_LoadWAV_RW(rw, 1); @@ -502,19 +526,23 @@ void I_FreeSfx(sfxinfo_t *sfx) { Mix_Chunk *chunk = (Mix_Chunk*)sfx->data; UINT8 *abufdata = NULL; + if (chunk->allocated == 0) { // We allocated the data in this chunk, so get the abuf from mixer, then let it free the chunk, THEN we free the data // I believe this should ensure the sound is not playing when we free it abufdata = chunk->abuf; } + Mix_FreeChunk(sfx->data); + if (abufdata) { // I'm going to assume we used Z_Malloc to allocate this data. Z_Free(abufdata); } } + sfx->data = NULL; sfx->lumpnum = LUMPERROR; } @@ -572,9 +600,12 @@ static UINT32 get_adjusted_position(UINT32 position) { // all in milliseconds UINT32 length = I_GetSongLength(); - UINT32 looppoint = I_GetSongLoopPoint(); + if (length) + { + UINT32 looppoint = I_GetSongLoopPoint(); return position >= length ? (position % (length-looppoint)) : position; + } else return position; } @@ -589,8 +620,7 @@ static void do_fading_callback(void) /// Music Hooks /// ------------------------ -static void -Countstutter (int len) +static void Countstutter(int len) { UINT32 bytes; @@ -617,7 +647,7 @@ Countstutter (int len) else bytes = ( music_bytes - music_stutter_bytes ); - I_SetSongPosition((int)( (float)bytes/4/44100.0f*1000 )); + I_SetSongPosition((int)((float)bytes/4/44100.0f*1000)); } } } @@ -628,7 +658,9 @@ static void count_music_bytes(int chan, void *stream, int len, void *udata) (void)stream; (void)udata; - if (!music || I_SongType() == MU_GME || I_SongType() == MU_MOD || I_SongType() == MU_MID) + const musictype_t mustype = I_SongType(); + + if (!music || mustype == MU_GME || mustype == MU_MOD || mustype == MU_MID) return; music_bytes += len; @@ -662,7 +694,9 @@ static UINT32 music_fade(UINT32 interval, void *param) return 0; } else if (songpaused) // don't decrement timer + { return interval; + } else if ((fading_timer -= 10) <= 0) { internal_volume = fading_target; @@ -675,11 +709,14 @@ static UINT32 music_fade(UINT32 interval, void *param) { UINT8 delta = abs(fading_target - fading_source); fixed_t factor = FixedDiv(fading_duration - fading_timer, fading_duration); + if (fading_target < fading_source) internal_volume = max(min(internal_volume, fading_source - FixedMul(delta, factor)), fading_target); else if (fading_target > fading_source) internal_volume = min(max(internal_volume, fading_source + FixedMul(delta, factor)), fading_target); + Mix_VolumeMusic(get_real_volume(music_volume)); + return interval; } } @@ -763,14 +800,22 @@ musictype_t I_SongType(void) #endif if (!music) return MU_NONE; - else if (Mix_GetMusicType(music) == MUS_MID) - return MU_MID; - else if (Mix_GetMusicType(music) == MUS_MOD || Mix_GetMusicType(music) == MUS_MODPLUG) - return MU_MOD; - else if (Mix_GetMusicType(music) == MUS_MP3 || Mix_GetMusicType(music) == MUS_MP3_MAD) - return MU_MP3; - else - return (musictype_t)Mix_GetMusicType(music); + + const Mix_MusicType mustype = Mix_GetMusicType(music); + + switch (mustype) + { + case MUS_MID: + return MU_MID; + case MUS_MOD: + case MUS_MODPLUG: + return MU_MOD; + case MUS_MP3: + case MUS_MP3_MAD: + return MU_MP3; + default: + return (musictype_t)mustype; + } } boolean I_SongPlaying(void) @@ -799,6 +844,7 @@ boolean I_SetSongSpeed(float speed) { if (speed > 250.0f) speed = 250.0f; //limit speed up to 250x + #ifdef HAVE_LIBGME if (gme) { @@ -857,51 +903,63 @@ UINT32 I_GetSongLength(void) // reconstruct info->play_length, from GME source // we only want intro + 1 loop, not 2 length = info->length; + if (length <= 0) { length = info->intro_length + info->loop_length; // intro + 1 loop + if (length <= 0) length = 150 * 1000; // 2.5 minutes } } gme_free_info(info); + return max(length, 0); } else #endif #ifdef HAVE_OPENMPT if (openmpt_mhandle) + { return (UINT32)(openmpt_module_get_duration_seconds(openmpt_mhandle) * 1000.); + } else #endif if (!music || I_SongType() == MU_MOD || I_SongType() == MU_MID) + { return 0; + } else { // VERY IMPORTANT to set your LENGTHMS= in your song files, folks! // SDL mixer can't read music length itself. length = (UINT32)(song_length*1000); + if (!length) CONS_Debug(DBG_DETAILED, "Getting music length: music is missing LENGTHMS= tag. Needed for seeking.\n"); + return length; } } boolean I_SetSongLoopPoint(UINT32 looppoint) { - if (!music || I_SongType() == MU_GME || I_SongType() == MU_MOD || I_SongType() == MU_MID || !is_looping) + if (!music|| !is_looping) return false; - else - { - UINT32 length = I_GetSongLength(); - if (length > 0) - looppoint %= length; + const musictype_t mustype = I_SongType(); - loop_point = max((float)(looppoint / 1000.0L), 0); - return true; - } + if (mustype == MU_GME || mustype == MU_MOD || mustype == MU_MID) + return false; + + UINT32 length = I_GetSongLength(); + + if (length > 0) + looppoint %= length; + + loop_point = max((float)(looppoint / 1000.0L), 0); + return true; } UINT32 I_GetSongLoopPoint(void) @@ -927,14 +985,19 @@ UINT32 I_GetSongLoopPoint(void) else #endif if (!music || I_SongType() == MU_MOD || I_SongType() == MU_MID) + { return 0; + } else + { return (UINT32)(loop_point * 1000); + } } boolean I_SetSongPosition(UINT32 position) { UINT32 length; + #ifdef HAVE_LIBGME if (gme) { @@ -971,9 +1034,13 @@ boolean I_SetSongPosition(UINT32 position) else #endif if (!music || I_SongType() == MU_MID) + { return false; + } else if (I_SongType() == MU_MOD) + { return Mix_SetMusicPosition(position); // Goes by channels + } else { // Because SDL mixer can't identify song length, if you have @@ -981,11 +1048,13 @@ boolean I_SetSongPosition(UINT32 position) // music_bytes becomes inaccurate. length = I_GetSongLength(); // get it in MS + if (length) position = get_adjusted_position(position); Mix_RewindMusic(); // needed for mp3 - if(Mix_SetMusicPosition((float)(position/1000.0L)) == 0) + + if (Mix_SetMusicPosition((float)(position/1000.0L)) == 0) music_bytes = (UINT32)(position/1000.0L*44100.0L*4); //assume 44.1khz, 4-byte length (see I_GetSongPosition) else // NOTE: This block fires on incorrect song format, @@ -1025,6 +1094,7 @@ UINT32 I_GetSongPosition(void) } gme_free_info(info); + return max(position, 0); } else @@ -1038,12 +1108,16 @@ UINT32 I_GetSongPosition(void) else #endif if (!music || I_SongType() == MU_MID) + { return 0; + } else + { return (UINT32)(music_bytes/44100.0L*1000.0L/4); //assume 44.1khz // 4 = byte length for 16-bit samples (AUDIO_S16SYS), stereo (2-channel) // This is hardcoded in I_StartupSound. Other formats for factor: // 8M: 1 | 8S: 2 | 16M: 2 | 16S: 4 + } } void I_UpdateSongLagThreshold(void) @@ -1057,12 +1131,16 @@ void I_UpdateSongLagThreshold(void) boolean I_LoadSong(char *data, size_t len) { - const char *key1 = "LOOP"; - const char *key2 = "POINT="; - const char *key3 = "MS="; - const size_t key1len = strlen(key1); - const size_t key2len = strlen(key2); - const size_t key3len = strlen(key3); + static const char *key1 = "LOOP"; + static const char *key2 = "POINT="; + static const char *key3 = "MS="; + static const size_t key1len = sizeof("LOOP")-1; + static const size_t key2len = sizeof("POINT=")-1; + static const size_t key3len = sizeof("MS=")-1; + //const size_t key1len = strlen(key1); + //const size_t key2len = strlen(key2); + //const size_t key3len = strlen(key3); + char *p = data; SDL_RWops *rw; @@ -1099,6 +1177,7 @@ boolean I_LoadSong(char *data, size_t len) stream.next_out = inflatedData; zErr = inflateInit2(&stream, 32 + MAX_WBITS); + if (zErr == Z_OK) // We're good to go { zErr = inflate(&stream, Z_FINISH); @@ -1114,10 +1193,12 @@ boolean I_LoadSong(char *data, size_t len) } else CONS_Alert(CONS_ERROR, "Encountered %s when running inflate: %s\n", get_zlib_error(zErr), stream.msg); + (void)inflateEnd(&stream); } else // Hold up, zlib's got a problem CONS_Alert(CONS_ERROR, "Encountered %s when running inflateInit: %s\n", get_zlib_error(zErr), stream.msg); + Z_Free(inflatedData); // GME didn't open jack, but don't let that stop us from freeing this up return false; #else @@ -1146,6 +1227,7 @@ boolean I_LoadSong(char *data, size_t len) if (result == OPENMPT_PROBE_FILE_HEADER_RESULT_SUCCESS) // We only cared if it succeeded, continue on if not. { openmpt_mhandle = openmpt_module_create_from_memory2(data, len, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + if (!openmpt_mhandle) // Failed to create module handle? Show error and return! { mod_err = openmpt_module_error_get_last(openmpt_mhandle); @@ -1160,10 +1242,12 @@ boolean I_LoadSong(char *data, size_t len) // Let's see if Mixer is able to load this. rw = SDL_RWFromMem(data, len); + if (rw != NULL) { music = Mix_LoadMUS_RW(rw, 1); } + if (!music) { CONS_Alert(CONS_ERROR, "Mix_LoadMUS_RW: %s\n", Mix_GetError()); @@ -1191,7 +1275,7 @@ boolean I_LoadSong(char *data, size_t len) else if (!strncmp(p, key3, key3len)) // is it LOOPMS=? { p += key3len; // skip MS= - loop_point = (float)(atoi(p) / 1000.0L); // LOOPMS works by real time, as miliseconds. + loop_point = (float)(atof(p) / 1000.0); // LOOPMS works by real time, as miliseconds. // Everything that uses LOOPMS will work perfectly with SDL_Mixer. } } @@ -1201,6 +1285,7 @@ boolean I_LoadSong(char *data, size_t len) else // continue searching p++; } + return true; } @@ -1243,6 +1328,7 @@ boolean I_PlaySong(boolean looping) gme_start_track(gme, 0); current_track = 0; Mix_HookMusic(mix_gme, gme); + return true; } else @@ -1282,15 +1368,17 @@ boolean I_PlaySong(boolean looping) if (!music) return false; - if (fpclassify(song_length) == FP_ZERO && (I_SongType() == MU_OGG || I_SongType() == MU_MP3 || I_SongType() == MU_FLAC)) + const musictype_t mustype = I_SongType(); + + if (fpclassify(song_length) == FP_ZERO && (mustype == MU_OGG || mustype == MU_MP3 || mustype == MU_FLAC)) CONS_Debug(DBG_DETAILED, "This song is missing a LENGTHMS= tag! Required to make seeking work properly.\n"); - if (I_SongType() != MU_MOD && I_SongType() != MU_MID && Mix_PlayMusic(music, 0) == -1) + if (mustype != MU_MOD && mustype != MU_MID && Mix_PlayMusic(music, 0) == -1) { CONS_Alert(CONS_ERROR, "Mix_PlayMusic: %s\n", Mix_GetError()); return false; } - else if ((I_SongType() == MU_MOD || I_SongType() == MU_MID) && Mix_PlayMusic(music, looping ? -1 : 0) == -1) // if MOD, loop forever + else if ((mustype == MU_MOD || mustype == MU_MID) && Mix_PlayMusic(music, looping ? -1 : 0) == -1) // if MOD, loop forever { CONS_Alert(CONS_ERROR, "Mix_PlayMusic: %s\n", Mix_GetError()); return false; @@ -1300,10 +1388,10 @@ boolean I_PlaySong(boolean looping) I_SetMusicVolume(music_volume); - if (I_SongType() != MU_MOD && I_SongType() != MU_MID) + if (mustype != MU_MOD && mustype != MU_MID) Mix_HookMusicFinished(music_loop); // don't bother counting if MOD - if(I_SongType() != MU_MOD && I_SongType() != MU_MID && !Mix_RegisterEffect(MIX_CHANNEL_POST, count_music_bytes, NULL, NULL)) + if (mustype != MU_MOD && mustype != MU_MID && !Mix_RegisterEffect(MIX_CHANNEL_POST, count_music_bytes, NULL, NULL)) CONS_Alert(CONS_WARNING, "Error registering SDL music position counter: %s\n", Mix_GetError()); return true; @@ -1339,10 +1427,12 @@ void I_StopSong(void) void I_PauseSong(void) { - if(I_SongType() == MU_MID) // really, SDL Mixer? why can't you pause MIDI??? + const musictype_t mustype = I_SongType(); + + if (mustype == MU_MID) // really, SDL Mixer? why can't you pause MIDI??? return; - if(I_SongType() != MU_GME && I_SongType() != MU_MOD && I_SongType() != MU_MID) + if (mustype != MU_GME && mustype != MU_MOD && mustype != MU_MID) Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes); Mix_PauseMusic(); @@ -1351,15 +1441,17 @@ void I_PauseSong(void) void I_ResumeSong(void) { - if (I_SongType() == MU_MID) + const musictype_t mustype = I_SongType(); + + if (mustype == MU_MID) return; - if (I_SongType() != MU_GME && I_SongType() != MU_MOD && I_SongType() != MU_MID) + if (mustype != MU_GME && mustype != MU_MOD && mustype != MU_MID) { - while(Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes) != 0) { } + while (Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes) != 0) { } // HACK: fixes issue of multiple effect callbacks being registered - if(music && I_SongType() != MU_MOD && I_SongType() != MU_MID && !Mix_RegisterEffect(MIX_CHANNEL_POST, count_music_bytes, NULL, NULL)) + if (music && mustype != MU_MOD && mustype != MU_MID && !Mix_RegisterEffect(MIX_CHANNEL_POST, count_music_bytes, NULL, NULL)) CONS_Alert(CONS_WARNING, "Error registering SDL music position counter: %s\n", Mix_GetError()); } @@ -1392,20 +1484,24 @@ boolean I_SetSongTrack(INT32 track) { if (current_track == track) return false; + SDL_LockAudio(); if (track >= 0 && track < gme_track_count(gme)-1) { gme_err_t gme_e = gme_start_track(gme, track); + if (gme_e != NULL) { CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e); return false; } + current_track = track; SDL_UnlockAudio(); return true; } SDL_UnlockAudio(); + return false; } else @@ -1415,6 +1511,7 @@ boolean I_SetSongTrack(INT32 track) { if (current_subsong == track) return false; + SDL_LockAudio(); if (track >= 0 && track < openmpt_module_get_num_subsongs(openmpt_mhandle)) { @@ -1428,8 +1525,10 @@ boolean I_SetSongTrack(INT32 track) return false; } #endif + if (I_SongType() == MU_MOD) return !Mix_SetMusicPosition(track); + (void)track; return false; } @@ -1441,8 +1540,10 @@ boolean I_SetSongTrack(INT32 track) void I_SetInternalMusicVolume(UINT8 volume) { internal_volume = volume; + if (!I_SongPlaying()) return; + Mix_VolumeMusic(get_real_volume(music_volume)); } @@ -1450,6 +1551,7 @@ void I_StopFadingSong(void) { if (fading_id) SDL_RemoveTimer(fading_id); + is_fading = false; fading_source = fading_target = fading_timer = fading_duration = fading_id = 0; } @@ -1466,8 +1568,10 @@ boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms if (!ms && volume_delta) { I_SetInternalMusicVolume(target_volume); + if (callback) (*callback)(); + return true; } @@ -1475,20 +1579,28 @@ boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms { if (callback) (*callback)(); + return true; } // Round MS to nearest 10 // If n - lower > higher - n, then round up - ms = (ms - ((ms / 10) * 10) > (((ms / 10) * 10) + 10) - ms) ? - (((ms / 10) * 10) + 10) // higher - : ((ms / 10) * 10); // lower + //ms = (ms - ((ms / 10) * 10) > (((ms / 10) * 10) + 10) - ms) ? + // (((ms / 10) * 10) + 10) // higher + // : ((ms / 10) * 10); // lower + + const int lower = (ms / 10) * 10; + const int upper = lower + 10; + ms = (ms - lower > upper - ms) ? upper : lower; if (!ms) + { I_SetInternalMusicVolume(target_volume); + } else if (source_volume != target_volume) { fading_id = SDL_AddTimer(10, music_fade, NULL); + if (fading_id) { is_fading = true; @@ -1519,7 +1631,7 @@ boolean I_FadeInPlaySong(UINT32 ms, boolean looping) { if (I_PlaySong(looping)) return I_FadeSongFromVolume(100, 0, ms, NULL); - else - return false; + + return false; } #endif -- 2.54.0 From ed16c4fd9ffd3031547871d5709c7da53a69e2c8 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 13 Oct 2022 13:12:07 +0100 Subject: [PATCH 145/219] Simplify intermission timer code - We had two ways of ending the intermission, but only one would actually be used, and it resulted in code duplication. - Combine the two ways. - Disable the reached-but-didn't-do-anything-before-now code path for setting endtic. --- src/y_inter.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/y_inter.c b/src/y_inter.c index c1bdafd32..9abbccbd8 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -552,18 +552,8 @@ void Y_Ticker(void) intertic++; - // multiplayer uses timer (based on cv_inttime) - if (timer) - { - if (!--timer) - { - Y_EndIntermission(); - Y_FollowIntermission(); - return; - } - } - // single player is hardcoded to go away after awhile - else if (intertic == endtic) + if ((timer && !--timer) + || (intertic == endtic)) { Y_EndIntermission(); Y_FollowIntermission(); -- 2.54.0 From f751161693e3b067eae7b9adfb1ddbe5e9cbf6b2 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 23 Oct 2025 20:37:23 +0200 Subject: [PATCH 146/219] fix CECHO text being overwritten with nothing strlcat not strlcpy --- src/command.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/command.c b/src/command.c index 463325e60..e73125649 100644 --- a/src/command.c +++ b/src/command.c @@ -700,6 +700,7 @@ static void COM_Echo_f(void) for (i = 1; i < COM_Argc(); i++) CONS_Printf("%s ", COM_Argv(i)); + CONS_Printf("\n"); } @@ -708,11 +709,11 @@ static void COM_Echo_f(void) static void COM_CEcho_f(void) { size_t i; - char cechotext[1024] = ""; + char cechotext[1024] = {0}; for (i = 1; i < COM_Argc(); i++) { - strlcpy(cechotext, COM_Argv(i), sizeof(cechotext)-1); + strlcat(cechotext, COM_Argv(i), sizeof(cechotext)-1); strlcat(cechotext, " ", sizeof(cechotext)-1); } -- 2.54.0 From c07502bf5a26848fa520acda86fb538b7cd09b76 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 23 Oct 2025 20:51:11 +0200 Subject: [PATCH 147/219] use strl instead of strn stuff to copy cecho text ALOT safer than whatever this did before --- src/hu_stuff.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index fa7060dff..3a01aedc0 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2845,12 +2845,8 @@ void HU_SetCEchoFlags(INT32 flags) void HU_DoCEcho(const char *msg) { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstringop-truncation" // This is fine, we set null byte later - strncpy(cechotext, msg, sizeof(cechotext)); -#pragma GCC diagnostic pop - strncat(cechotext, "\\", sizeof(cechotext) - strlen(cechotext) - 1); - cechotext[sizeof(cechotext) - 1] = '\0'; + strlcpy(cechotext, msg, sizeof(cechotext)); + strlcat(cechotext, "\\", sizeof(cechotext)); // just print it to console if (cv_cechotoggle.value == 2) -- 2.54.0 From aa06459c09550ac7fb9a92ef3ba11e35f26c809e Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 23 Oct 2025 11:23:13 +0200 Subject: [PATCH 148/219] set special case for console key when using native keyboard input ALWAYS make sure that remains in the same physical place otherwise things might get very annoying it already does so with my german layout --- src/sdl/i_video.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 9ce860cb4..df4b80e20 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -412,6 +412,10 @@ static INT32 GetTypedChar(SDL_Keysym keysym) break; } + // Special case for console key + if (scancode == SDL_SCANCODE_GRAVE) + return '`'; + if (SDL_PeepEvents(&next_event, 1, SDL_PEEKEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT) == 1 && next_event.type == SDL_TEXTINPUT) { if (next_event.text.text[1] == '\0') // limit to ASCII -- 2.54.0 From 852aa74d62dd7dae75f55a56b77a716cac17c792 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 23 Oct 2025 11:24:32 +0200 Subject: [PATCH 149/219] random style fixes and stuff --- src/hu_stuff.c | 22 +++++++++++----------- src/k_kart.c | 3 --- src/v_video.c | 4 ++-- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 3a01aedc0..7f034f8ad 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -431,7 +431,7 @@ void HU_Start(void) void HU_Shiftform(void) { - shiftxform = cv_keyboardlayout.value == 3 ? french_shiftxform : english_shiftxform; + shiftxform = (cv_keyboardlayout.value == 3) ? french_shiftxform : english_shiftxform; } //====================================================================== @@ -465,8 +465,8 @@ static INT16 addy = 0; // use this to make the messages scroll smoothly when one static void HU_removeChatText_Mini(void) { // MPC: Don't create new arrays, just iterate through an existing one - size_t i; - for(i=0;i 0) stop_spamming[i]--; } // handle chat timers - for (i=0; (i 0) chat_timers[i]--; @@ -1231,7 +1231,7 @@ static void HU_SendChatMessage(void) nodenum[2] = '\0'; // check for undesirable characters in our "number" - if (((nodenum[0] < '0') || (nodenum[0] > '9')) || ((nodenum[1] < '0') || (nodenum[1] > '9'))) + if (((nodenum[0] < '0') || (nodenum[0] > '9')) || ((nodenum[1] < '0') || (nodenum[1] > '9'))) { // check if nodenum[1] is a space if (nodenum[1] == ' ') @@ -1499,7 +1499,7 @@ static void HU_drawMiniChat(void) if (splitscreen > 1) boxw = max(64, boxw/2); - for (; i>0; i--) + for (; i > 0; i--) { char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i-1]); size_t j = 0; @@ -1572,7 +1572,7 @@ static void HU_drawMiniChat(void) i = 0; prev_linereturn = false; - for (; i<=(chat_nummsg_min-1); i++) // iterate through our hot messages + for (; i <= (chat_nummsg_min-1); i++) // iterate through our hot messages { INT32 clrflag = 0; INT32 timer = ((cv_chattime.value*TICRATE)-chat_timers[i]) - cv_chattime.value*TICRATE+9; // see below... @@ -1749,7 +1749,6 @@ static void HU_drawChatLog(INT32 offset) Z_Free(msg); } - if (((chat_scroll >= chat_maxscroll) || (chat_scrollmedown)) && !(justscrolleddown || justscrolledup || chat_scrolltime)) // was already at the bottom of the page before new maxscroll calculation and was NOT scrolling. { atbottom = true; // we should scroll @@ -2284,6 +2283,7 @@ static void HU_DrawSongCreditsBox(void) V_DrawFill(x, y, strwidth*dup, BOXCREDITHEIGHT*dup, 28|flags|(bgt<= MAXTRANSLATIONS) I_Error("Invalid skin color #%hu.", (UINT16)color); - if (skinnum < 0 && skinnum > TC_DEFAULT) - I_Error("Invalid translation colormap index %d.", skinnum); - starttranscolor = (skinnum != TC_DEFAULT) ? K_GetSkinArray(local)[skinnum].starttranscolor : DEFAULT_STARTTRANSCOLOR; if (starttranscolor >= NUM_PALETTE_ENTRIES) diff --git a/src/v_video.c b/src/v_video.c index 0104cf78c..9e7ece0d1 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -641,8 +641,8 @@ void VID_BlitLinearScreen(const UINT8 *restrict srcptr, UINT8 *restrict destptr, } } -static UINT8 hudplusalpha[11] = { 10, 8, 6, 4, 2, 0, 0, 0, 0, 0, 0}; -static UINT8 hudminusalpha[11] = { 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5}; +static const UINT8 hudplusalpha[11] = { 10, 8, 6, 4, 2, 0, 0, 0, 0, 0, 0}; +static const UINT8 hudminusalpha[11] = { 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5}; UINT8 hudtrans = 0; static const UINT8 *v_colormap = NULL; -- 2.54.0 From b84d1013374bdcbfeb42ba5e0c94bb9d5659ea75 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 24 Oct 2025 01:52:53 +0200 Subject: [PATCH 150/219] initialize sdl window,renderer and texture to something --- src/sdl/i_video.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index df4b80e20..7393d8e4b 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -156,9 +156,9 @@ static SDL_bool usesdl2soft = SDL_FALSE; static SDL_bool borderlesswindow = SDL_FALSE; // SDL2 vars -SDL_Window *window; -SDL_Renderer *renderer; -static SDL_Texture *texture; +SDL_Window *window = NULL; +SDL_Renderer *renderer = NULL; +static SDL_Texture *texture = NULL; static SDL_bool havefocus = SDL_TRUE; static const char *fallback_resolution_name = "Fallback"; @@ -909,6 +909,7 @@ static void Impl_HandleControllerAddedEvent(SDL_Event evt) cv_usejoystick[i].value = 0; else if (atoi(cv_usejoystick[i].string) <= I_NumJoys() // don't mess if we intentionally set higher than NumJoys && cv_usejoystick[i].value) // update the cvar ONLY if a device exists + CV_SetValue(&cv_usejoystick[i], cv_usejoystick[i].value); } @@ -1111,9 +1112,11 @@ void I_OsPolling(void) I_GetEvent(); mod = SDL_GetModState(); + /* Handle here so that our state is always synched with the system. */ shiftdown = ctrldown = altdown = 0; capslock = false; + if (mod & KMOD_LSHIFT) shiftdown |= 1; if (mod & KMOD_RSHIFT) shiftdown |= 2; if (mod & KMOD_LCTRL) ctrldown |= 1; @@ -1147,7 +1150,7 @@ static void VID_Command_Mode_f (void) { INT32 modenum; - if (COM_Argc()!= 2) + if (COM_Argc() != 2) { CONS_Printf("vid_mode : set video mode, current video mode %i\n", vid.modenum); return; @@ -1292,8 +1295,8 @@ static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen) #endif OglSdlSurface(vid.width, vid.height); } + else #endif - if (rendermode == render_soft) { SDL_RenderClear(renderer); @@ -1358,7 +1361,8 @@ void I_FinishUpdate(void) const boolean isserverplayer = consoleplayer == serverplayer; - if (cv_showping.value && ((netgame && !isserverplayer) || (simulated_lag != 0 && isserverplayer && Playing()))) + if (cv_showping.value && ((netgame && !isserverplayer) || + (simulated_lag != 0 && isserverplayer && Playing()))) SCR_DisplayLocalPing(); } @@ -1625,11 +1629,13 @@ static SDL_bool Impl_CreateContext(void) if (!renderer) renderer = SDL_CreateRenderer(window, -1, flags); + if (renderer == NULL) { CONS_Printf(M_GetText("Couldn't create rendering context: %s\n"), SDL_GetError()); return SDL_FALSE; } + SDL_RenderSetLogicalSize(renderer, BASEVIDWIDTH, BASEVIDHEIGHT); } @@ -1732,6 +1738,7 @@ void I_StartupGraphics(void) #endif { const char *vd = SDL_GetCurrentVideoDriver(); + //CONS_Printf(M_GetText("Starting up with video driver: %s\n"), vd); if (vd && (strncasecmp(vd, "fbcon", 6) == 0)) framebuffer = SDL_TRUE; @@ -1962,7 +1969,7 @@ static void Impl_SetVsync(void) #endif #ifdef HWRENDER if (!renderer && rendermode == render_opengl && - sdlglcontext != NULL && SDL_GL_GetCurrentContext() == sdlglcontext) + sdlglcontext != NULL && SDL_GL_GetCurrentContext() == sdlglcontext) { SDL_GL_SetSwapInterval(cv_vidwait.value ? 1 : 0); } -- 2.54.0 From 0e2ffdeb1dedfd9954ddd4897d8d180ead70a014 Mon Sep 17 00:00:00 2001 From: "James R." Date: Sat, 30 Sep 2023 16:07:53 -0700 Subject: [PATCH 151/219] SDLSetMode: render immediately after resolution change to avoid 1-frame of texture presented at wrong size --- src/sdl/i_video.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 7393d8e4b..229008352 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1313,6 +1313,11 @@ static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen) texture = SDL_CreateTexture(renderer, sw_texture_format, SDL_TEXTUREACCESS_STREAMING, width, height); } + + if (graphics_started) + { + I_UpdateNoVsync(); + } } // -- 2.54.0 From 383d55cac669d1e76ef170410fe9bd68fdbb8c89 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 24 Oct 2025 03:37:45 +0200 Subject: [PATCH 152/219] smol cleanup V_DrawVhsEffect dont need to assign all the software stuff in gl mode --- src/hardware/hw_draw.c | 57 +++++++++++++++++++++--------------------- src/r_data.c | 1 + src/r_main.cpp | 2 ++ src/v_video.c | 43 +++++++++++++++++++++---------- 4 files changed, 62 insertions(+), 41 deletions(-) diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index cf8ab29e3..4797f21de 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -46,9 +46,9 @@ typedef struct UINT8 image_descriptor; //18 } ATTRPACK TGAHeader; // sizeof is 18 -static UINT8 softwaretranstogl[11] = { 0, 25, 51, 76,102,127,153,178,204,229,255}; -static UINT8 softwaretranstogl_hi[11] = { 0, 51,102,153,204,255,255,255,255,255,255}; -static UINT8 softwaretranstogl_lo[11] = { 0, 12, 24, 36, 48, 60, 71, 83, 95,111,127}; +static const UINT8 softwaretranstogl[11] = { 0, 25, 51, 76,102,127,153,178,204,229,255}; +static const UINT8 softwaretranstogl_hi[11] = { 0, 51,102,153,204,255,255,255,255,255,255}; +static const UINT8 softwaretranstogl_lo[11] = { 0, 12, 24, 36, 48, 60, 71, 83, 95,111,127}; static const float FLOATBASEVIDWIDTH = (float)BASEVIDWIDTH; static const float FLOATBASEVIDHEIGHT = (float)BASEVIDHEIGHT; @@ -87,15 +87,15 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p switch (option & V_SCALEPATCHMASK) { - case V_NOSCALEPATCH: - dup = 1.0f; - break; - case V_SMALLSCALEPATCH: - dup = (float)vid.smalldup; - break; - case V_MEDSCALEPATCH: - dup = (float)vid.meddup; - break; + case V_NOSCALEPATCH: + dup = 1.0f; + break; + case V_SMALLSCALEPATCH: + dup = (float)vid.smalldup; + break; + case V_MEDSCALEPATCH: + dup = (float)vid.meddup; + break; } fscalew = fscaleh = FIXED_TO_FLOAT(pscale); @@ -269,15 +269,15 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, switch (option & V_SCALEPATCHMASK) { - case V_NOSCALEPATCH: - dup = 1.0f; - break; - case V_SMALLSCALEPATCH: - dup = (float)vid.smalldup; - break; - case V_MEDSCALEPATCH: - dup = (float)vid.meddup; - break; + case V_NOSCALEPATCH: + dup = 1.0f; + break; + case V_SMALLSCALEPATCH: + dup = (float)vid.smalldup; + break; + case V_MEDSCALEPATCH: + dup = (float)vid.meddup; + break; } fscale = FIXED_TO_FLOAT(pscale); @@ -506,7 +506,7 @@ void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength) if (color & 0xFF00) // Do COLORMAP fade. { - if (HWR_ShouldUsePaletteRendering() && cv_glscreentextures.value) + if (cv_glscreentextures.value && HWR_ShouldUsePaletteRendering()) { const hwdscreentexture_t scr_tex = HWD_SCREENTEXTURE_GENERIC2; @@ -518,12 +518,10 @@ void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength) GL_UnSetShader(); return; } - else - { - Surf.PolyColor.rgba = UINT2RGBA(0x01010160); - Surf.PolyColor.s.alpha = (strength*8); - poly_flags |= PF_Translucent; - } + + Surf.PolyColor.rgba = UINT2RGBA(0x01010160); + Surf.PolyColor.s.alpha = (strength*8); + poly_flags |= PF_Translucent; } else // Do TRANSMAP** fade. { @@ -890,11 +888,13 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color) if (fx >= vid.width || fy >= vid.height) return; + if (fx < 0) { fw += fx; fx = 0; } + if (fy < 0) { fh += fy; @@ -906,6 +906,7 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color) if (fx + fw > vid.width) fw = fvw - fx; + if (fy + fh > vid.height) fh = fvh - fy; diff --git a/src/r_data.c b/src/r_data.c index a796de138..93ad621fa 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1391,6 +1391,7 @@ void R_ReInitColormaps(UINT16 num, lumpnum_t newencoremap) // Load in the light tables, now 64k aligned for smokie... lump = W_GetNumForName(colormap); + if (lump == LUMPERROR) lump = basecolormaplump; else diff --git a/src/r_main.cpp b/src/r_main.cpp index 5313357d6..339e34548 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -253,6 +253,7 @@ void SplitScreen_OnChange(void) if (playeringame[i] && i != consoleplayer) { UINT8 j; + for (j = 1; j < MAXSPLITSCREENPLAYERS; j++) { if (displayplayers[j] == consoleplayer) @@ -268,6 +269,7 @@ void SplitScreen_OnChange(void) } } } + static void Fov_OnChange(void) { R_SetViewSize(); diff --git a/src/v_video.c b/src/v_video.c index 9e7ece0d1..dd5091fa1 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1739,22 +1739,24 @@ void V_DrawHorizontallyScaledFullScreenPatch(patch_t *patch) void V_DrawVhsEffect(boolean rewind) { + fixed_t uby, dby; static fixed_t upbary = 100*FRACUNIT, downbary = 150*FRACUNIT; - UINT8 *buf = vid.screens[0], *tmp = vid.screens[4]; - UINT16 y; - UINT32 x, pos = 0; + UINT8 barsize, updistort, downdistort; - UINT8 *normalmapstart = ((UINT8 *)transtables + (8<>1; + barsize = vid.dup << 5; + updistort = vid.dup << (rewind ? 5 : 3); + downdistort = updistort >> 1; if (rewind) V_DrawVhsEffect(false); // experimentation @@ -1763,11 +1765,12 @@ void V_DrawVhsEffect(boolean rewind) downbary += renderdeltatics * (vid.dup * (rewind ? 2 : 1)); if (upbary < -barsize*FRACUNIT) - upbary = vid.height< vid.height< vid.height << FRACBITS) downbary = -barsize*FRACUNIT; - fixed_t uby = upbary>>FRACBITS, dby = downbary>>FRACBITS; + uby = upbary >> FRACBITS; + dby = downbary >> FRACBITS; #ifdef HWRENDER if (rendermode == render_opengl) @@ -1777,6 +1780,16 @@ void V_DrawVhsEffect(boolean rewind) } #endif + buf = vid.screens[0]; + tmp = vid.screens[4]; + + normalmapstart = ((UINT8 *)transtables + (8<> V_CHARCOLORSHIFT); + if (!colorflags || colorflags > 15) // INT32 is signed, but V_CHARCOLORMASK is a very restrictive mask. return NULL; + return (purplemap+((colorflags-1)<<8)); #endif } @@ -1920,7 +1935,6 @@ UINT8 *V_GetStringColormap(INT32 colorflags) void V_DrawCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed) { INT32 w, flags; - const UINT8 *colormap = V_GetStringColormap(c); flags = c & ~(V_CHARCOLORMASK | V_PARAMMASK); c &= 0x7f; @@ -1936,6 +1950,8 @@ void V_DrawCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed) if (x + w > vid.width) return; + const UINT8 *colormap = V_GetStringColormap(c); + if (colormap != NULL) V_DrawMappedPatch(x, y, flags, hu_font[c], colormap); else @@ -2000,6 +2016,7 @@ char *V_WordWrap(INT32 x, INT32 w, INT32 option, const char *string) for (i = 0; i < slen; ++i) { c = newstring[i]; + if ((UINT8)c >= 0x80 && (UINT8)c <= 0x8F) //color parsing! -Inuyasha 2.16.09 continue; -- 2.54.0 From ca27dad6c117e364d5e3b13112662035092f0fc4 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 24 Oct 2025 03:34:47 +0200 Subject: [PATCH 153/219] use D_ClearState in G_StopDemo actually fixes issues with crashes AND palette reset also resets a bunch of more stuff which def is good --- src/d_main.c | 27 ++++++++++++++++++++++++--- src/f_finale.c | 1 + src/g_demo.c | 13 +------------ 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 1bc346deb..992fc59db 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -954,6 +954,24 @@ void D_SRB2Loop(void) // D_SRB2Main // ========================================================================= +static void ResetSplitScreen(void) +{ + UINT8 i; + + // recompute screen size + R_ExecuteSetViewSize(); + + if (!demo.playback && !botingame) + { + for (i = 1; i < MAXSPLITSCREENPLAYERS; i++) + { + if (i > splitscreen) + CL_RemoveSplitscreenPlayer(displayplayers[i]); + else + CL_AddSplitscreenPlayer(); + } + } +} // // D_ClearState // @@ -963,6 +981,7 @@ void D_ClearState(void) // okay, stop now // (otherwise the game still thinks we're playing!) + CURLAbortFile(); SV_StopServer(); SV_ResetServer(); serverlistultimatecount = 0; @@ -971,7 +990,8 @@ void D_ClearState(void) CL_ClearPlayer(i); splitscreen = 0; - SplitScreen_OnChange(); + ResetSplitScreen(); // splitscreen onchange resets us to singleplayer :chaosleep: + botingame = false; botskin = 0; cv_debug = 0; @@ -990,7 +1010,6 @@ void D_ClearState(void) gameaction = ga_nothing; memset(displayplayers, 0, sizeof(displayplayers)); consoleplayer = 0; - //demosequence = -1; gametype = GT_RACE; // SRB2kart paused = false; @@ -1013,6 +1032,8 @@ void D_ClearState(void) G_SetGamestate(GS_NULL); wipegamestate = GS_NULL; + + M_ClearMenus(true); } // @@ -1022,8 +1043,8 @@ void D_StartTitle(void) { demo.title = false; D_ClearState(); + multiplayer = false; // reset manually netgame = false; // title menu shouldnt be a netgame lmao - M_ClearMenus(true); F_StartTitleScreen(); D_ResetDeviceLED(); } diff --git a/src/f_finale.c b/src/f_finale.c index 0fe0effc4..ca22349a0 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -963,6 +963,7 @@ void F_StartTitleScreen(void) finalecount = 0; else wipegamestate = GS_TITLESCREEN; + G_SetGamestate(GS_TITLESCREEN); CON_ClearHUD(); diff --git a/src/g_demo.c b/src/g_demo.c index de8523ae9..f779c26d8 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -3416,18 +3416,7 @@ void G_StopDemo(void) if (gamestate == GS_VOTING) Y_EndVote(); - M_ClearMenus(true); - - G_SetGamestate(GS_NULL); - wipegamestate = GS_NULL; - SV_StopServer(); - SV_ResetServer(); - - if (gamestate == GS_LEVEL && rendermode != render_none) - { - V_SetPaletteLump("PLAYPAL"); // Reset the palette - R_ReInitColormaps(0, LUMPERROR); - } + D_ClearState(); } // Stops timing a demo. -- 2.54.0 From 7c507c7b3bd33980022d79f55c1f441f082d21b0 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 24 Oct 2025 03:37:03 +0200 Subject: [PATCH 154/219] do some cleanup g_demo :shook: use the CLEANUP macro everywhere init some things that may not be initialized and make this more readable lets hope didnt break anything Zzz... TODO: if there are still issues with demo records and stuff crashing might consider porting some of the fixes from RR --- src/g_demo.c | 680 +++++++++++++++++++++++++++++---------------------- 1 file changed, 381 insertions(+), 299 deletions(-) diff --git a/src/g_demo.c b/src/g_demo.c index f779c26d8..96ff33e65 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -74,7 +74,7 @@ static tic_t demostarttime; // for comparative timing purposes //@TODO put these all in a struct for namespacing purposes? static char demoname[128]; -savebuffer_t demobuf; +savebuffer_t demobuf = {0}; static UINT8 *demotime_p, *demoinfo_p; static UINT8 *demoend; static UINT8 demoflags; @@ -85,7 +85,8 @@ struct demovars_s demo; consvar_t cv_resyncdemo = {"resyncdemo", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; // extra data stuff (events registered this frame while recording) -static struct { +static struct +{ UINT8 flags; // EZT flags // EZT_COLOR @@ -156,8 +157,8 @@ consvar_t cv_demodateformat = {"netdemo_dateformat", "Automatic", CV_SAVE, demod #define ZT_LATENCY 0x40 #define DEMOMARKER 0x80 // demoend -UINT8 demo_extradata[MAXPLAYERS]; -UINT8 demo_writerng; // 0=no, 1=yes, 2=yes but on a timeout +UINT8 demo_extradata[MAXPLAYERS] = {0}; +UINT8 demo_writerng = 0; // 0=no, 1=yes, 2=yes but on a timeout static ticcmd_t oldcmd[MAXPLAYERS]; #define DW_END 0xFF // End of extradata block @@ -192,7 +193,7 @@ static ticcmd_t oldcmd[MAXPLAYERS]; static mobj_t oldghost[MAXPLAYERS]; -static void G_ResetDemoPlayback(char *pdemoname); +static void G_ResetDemoPlayback(void); // Finds a skin with the closest stats if the expected skin doesn't exist. static INT32 GetSkinNumClosestToStats(UINT8 kartspeed, UINT8 kartweight) @@ -203,6 +204,7 @@ static INT32 GetSkinNumClosestToStats(UINT8 kartspeed, UINT8 kartweight) for (i = 0; i < numskins; i++) { stat_diff = abs(skins[i].kartspeed - kartspeed) + abs(skins[i].kartweight - kartweight); + if (stat_diff < closest_stats) { closest_stats = stat_diff; @@ -249,6 +251,7 @@ void G_ReadDemoExtraData(void) if (players[p].mo) P_DamageMobj(players[p].mo, NULL, NULL, DMG_INSTAKILL); // Is this how this should work..? } + if (extradata & DXD_SKIN) { UINT8 kartspeed, kartweight; @@ -267,6 +270,7 @@ void G_ReadDemoExtraData(void) players[p].kartspeed = kartspeed; players[p].kartweight = kartweight; } + if (extradata & DXD_COLOR) { // Color @@ -281,47 +285,49 @@ void G_ReadDemoExtraData(void) break; } } + if (extradata & DXD_NAME) { // Name M_Memcpy(player_names[p],demobuf.p,16); demobuf.p += 16; } + if (extradata & DXD_PLAYSTATE) { extradata = READUINT8(demobuf.p); - switch (extradata) { - case DXD_PST_PLAYING: - players[p].pflags |= PF_WANTSTOJOIN; // fuck you - break; + switch (extradata) + { + case DXD_PST_PLAYING: + players[p].pflags |= PF_WANTSTOJOIN; // fuck you + break; + case DXD_PST_SPECTATING: + players[p].pflags &= ~PF_WANTSTOJOIN; // double-fuck you - case DXD_PST_SPECTATING: - players[p].pflags &= ~PF_WANTSTOJOIN; // double-fuck you - if (!playeringame[p]) - { - CL_ClearPlayer(p); - playeringame[p] = true; - G_AddPlayer(p); - players[p].spectator = true; + if (!playeringame[p]) + { + CL_ClearPlayer(p); + playeringame[p] = true; + G_AddPlayer(p); + players[p].spectator = true; - // There's likely an off-by-one error in timing recording or playback of joins. This hacks around it so I don't have to find out where that is. \o/ - if (oldcmd[p].forwardmove) - P_RandomByte(); - } - else - { - players[p].spectator = true; - if (players[p].mo) - P_DamageMobj(players[p].mo, NULL, NULL, DMG_INSTAKILL); + // There's likely an off-by-one error in timing recording or playback of joins. This hacks around it so I don't have to find out where that is. \o/ + if (oldcmd[p].forwardmove) + P_RandomByte(); + } else - players[p].playerstate = PST_REBORN; - } - break; - - case DXD_PST_LEFT: - CL_RemovePlayer(p, 0); - break; + { + players[p].spectator = true; + if (players[p].mo) + P_DamageMobj(players[p].mo, NULL, NULL, DMG_INSTAKILL); + else + players[p].playerstate = PST_REBORN; + } + break; + case DXD_PST_LEFT: + CL_RemovePlayer(p, 0); + break; } G_ResetViews(); @@ -333,7 +339,6 @@ void G_ReadDemoExtraData(void) P_CheckRacers(); // also SRB2Kart } - p = READUINT8(demobuf.p); } @@ -342,11 +347,11 @@ void G_ReadDemoExtraData(void) UINT32 rng; UINT32 checkrng; - switch (p) + if (p == DW_RNG) { - case DW_RNG: rng = READUINT32(demobuf.p); checkrng = P_GetRandSeed(); + if (checkrng != rng) { if (demosynced) @@ -354,6 +359,7 @@ void G_ReadDemoExtraData(void) CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced (RNG)!\n")); CONS_Printf("expected rng %d got %d\n", rng, checkrng); } + demosynced = false; P_SetRandSeed(rng); @@ -395,6 +401,7 @@ void G_WriteDemoExtraData(void) WRITEUINT8(demobuf.p, skins[players[i].skin].kartspeed); WRITEUINT8(demobuf.p, skins[players[i].skin].kartweight); } + if (demo_extradata[i] & DXD_COLOR) { // Color @@ -403,6 +410,7 @@ void G_WriteDemoExtraData(void) M_Memcpy(demobuf.p,name,16); demobuf.p += 16; } + if (demo_extradata[i] & DXD_NAME) { // Name @@ -411,6 +419,7 @@ void G_WriteDemoExtraData(void) M_Memcpy(demobuf.p,name,16); demobuf.p += 16; } + if (demo_extradata[i] & DXD_PLAYSTATE) { demo_writerng = 1; @@ -866,8 +875,8 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum) } Z_Free(ghostext[playernum].hitlist); - ghostext[playernum].hits = 0; ghostext[playernum].hitlist = NULL; + ghostext[playernum].hits = 0; } if (ghostext[playernum].flags & EZT_SPRITE) @@ -973,6 +982,7 @@ void G_ConsGhostTic(INT32 playernum) if (ziptic & GZT_EXTRA) { // But wait, there's more! ziptic = READUINT8(demobuf.p); + if (ziptic & EZT_COLOR) demobuf.p++; @@ -981,7 +991,8 @@ void G_ConsGhostTic(INT32 playernum) if (ziptic & EZT_HIT) { // Resync mob damage. - UINT16 i, count = READUINT16(demobuf.p); + UINT16 i; + UINT16 count = READUINT16(demobuf.p); thinker_t *th; mobj_t *mobj; @@ -1006,9 +1017,12 @@ void G_ConsGhostTic(INT32 playernum) { if (th->function != (actionf_p1)P_MobjThinker) continue; + mobj = (mobj_t *)th; + if (mobj->type == (mobjtype_t)type && mobj->x == x && mobj->y == y && mobj->z == z) break; + mobj = NULL; // wasn't this one, keep searching. } @@ -1055,6 +1069,7 @@ void G_ConsGhostTic(INT32 playernum) { if (demosynced) CONS_Alert(CONS_WARNING, "Demo playback has desynced (player %s)!\n", player_names[playernum]); + demosynced = false; if (cv_resyncdemo.value) @@ -1092,6 +1107,7 @@ void G_ConsGhostTic(INT32 playernum) CONS_Printf("expected item type %d got %d\n", ghostext[playernum].kartitem, players[playernum].kartstuff[k_itemtype]); CONS_Printf("expected item amount %d got %d\n", ghostext[playernum].kartamount, players[playernum].kartstuff[k_itemamount]); } + demosynced = false; players[playernum].kartstuff[k_itemtype] = ghostext[playernum].kartitem; @@ -1110,7 +1126,7 @@ void G_ConsGhostTic(INT32 playernum) void G_GhostTicker(void) { - demoghost *g,*p; + demoghost *g, *p; for (g = ghosts, p = NULL; g; g = g->next) { @@ -1126,12 +1142,16 @@ void G_GhostTicker(void) if (ziptic == 0) // Only support player 0 info for now { ziptic = READUINT8(g->p); + if (ziptic & DXD_SKIN) g->p += 18; // We _could_ read this info, but it shouldn't change anything in record attack... + if (ziptic & DXD_COLOR) g->p += 16; // Same tbh + if (ziptic & DXD_NAME) g->p += 16; // yea + if (ziptic & DXD_PLAYSTATE && READUINT8(g->p) != DXD_PST_PLAYING) I_Error("Ghost is not a record attack ghost"); //@TODO lmao don't blow up like this } @@ -1191,14 +1211,18 @@ void G_GhostTicker(void) g->oldmo.momx = READINT16(g->p)<<8; g->oldmo.momy = READINT16(g->p)<<8; } + if (ziptic & GZT_MOMZ) g->oldmo.momz = READINT16(g->p)<<8; + g->oldmo.x += g->oldmo.momx; g->oldmo.y += g->oldmo.momy; g->oldmo.z += g->oldmo.momz; } + if (ziptic & GZT_ANGLE) g->oldmo.angle = READUINT8(g->p)<<24; + if (ziptic & GZT_SPRITE) g->oldmo.frame = READUINT8(g->p); @@ -1214,36 +1238,42 @@ void G_GhostTicker(void) if (ziptic & GZT_EXTRA) { // But wait, there's more! ziptic = READUINT8(g->p); + if (ziptic & EZT_COLOR) { g->color = READUINT8(g->p); - switch(g->color) + + switch (g->color) { - default: - case GHC_NORMAL: // Go back to skin color - g->mo->color = g->oldmo.color; - break; - // Handled below - case GHC_SUPER: - case GHC_INVINCIBLE: - break; - case GHC_FIREFLOWER: // Fireflower - g->mo->color = SKINCOLOR_WHITE; - break; + default: + case GHC_NORMAL: // Go back to skin color + g->mo->color = g->oldmo.color; + break; + // Handled below + case GHC_SUPER: + case GHC_INVINCIBLE: + break; + case GHC_FIREFLOWER: // Fireflower + g->mo->color = SKINCOLOR_WHITE; + break; } } + if (ziptic & EZT_FLIP) g->mo->eflags ^= MFE_VERTICALFLIP; + if (ziptic & EZT_SCALE) { g->mo->destscale = READFIXED(g->p); if (g->mo->destscale != g->mo->scale) P_SetScale(g->mo, g->mo->destscale); } + if (ziptic & EZT_THOKMASK) { // Let's only spawn ONE of these per frame, thanks. mobj_t *mobj; INT32 type = -1; + if (g->mo->skin) { switch (ziptic & EZT_THOKMASK) @@ -1273,14 +1303,17 @@ void G_GhostTicker(void) mobj->frame = (states[mobjinfo[type].spawnstate].frame & FF_FRAMEMASK) | tr_trans60<tics = -1; // nope. mobj->color = g->mo->color; + if (g->mo->eflags & MFE_VERTICALFLIP) { mobj->flags2 |= MF2_OBJECTFLIP; mobj->eflags |= MFE_VERTICALFLIP; } + P_SetScale(mobj, g->mo->scale); mobj->destscale = g->mo->scale; } + mobj->floorz = mobj->z; mobj->ceilingz = mobj->z+mobj->height; P_UnsetThingPosition(mobj); @@ -1290,13 +1323,16 @@ void G_GhostTicker(void) P_SetTarget(&mobj->target, g->mo); } } + if (ziptic & EZT_HIT) { // Spawn hit poofs for killing things! - UINT16 i, count = READUINT16(g->p), health; + UINT16 i, health; + UINT16 count = READUINT16(g->p); //UINT32 type; fixed_t x,y,z; angle_t angle; mobj_t *poof; + for (i = 0; i < count; i++) { g->p += 4; // reserved @@ -1306,8 +1342,10 @@ void G_GhostTicker(void) y = READFIXED(g->p); z = READFIXED(g->p); angle = READANGLE(g->p); + if (health != 0 || i >= 4) // only spawn for the first 4 hits per frame, to prevent ghosts from splode-spamming too bad. continue; + poof = P_SpawnMobj(x, y, z, MT_GHOST); poof->angle = angle; poof->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up... @@ -1333,30 +1371,33 @@ void G_GhostTicker(void) skippedghosttic: // Tick ghost colors (Super and Mario Invincibility flashing) - switch(g->color) + switch (g->color) { - case GHC_SUPER: // Super Sonic (P_DoSuperStuff) - g->mo->color = SKINCOLOR_SUPER1; - g->mo->color += abs( ( (signed)( (unsigned)leveltime >> 1 ) % 9) - 4); - break; - case GHC_INVINCIBLE: // Mario invincibility (P_CheckInvincibilityTimer) - g->mo->color = (UINT8)(leveltime % MAXSKINCOLORS); - break; - default: - break; + case GHC_SUPER: // Super Sonic (P_DoSuperStuff) + g->mo->color = SKINCOLOR_SUPER1; + g->mo->color += abs( ( (signed)( (unsigned)leveltime >> 1 ) % 9) - 4); + break; + case GHC_INVINCIBLE: // Mario invincibility (P_CheckInvincibilityTimer) + g->mo->color = (UINT8)(leveltime % MAXSKINCOLORS); + break; + default: + break; } // Demo ends after ghost data. if (*g->p == DEMOMARKER) { g->mo->momx = g->mo->momy = g->mo->momz = 0; + if (p) p->next = g->next; else ghosts = g->next; + Z_Free(g); continue; } + p = g; } } @@ -1399,6 +1440,7 @@ void G_StoreRewindInfo(void) if (timetolog-- > 0) return; + timetolog = 8; info = Z_Calloc(sizeof(rewindinfo_t), PU_STATIC, NULL); @@ -1413,6 +1455,7 @@ void G_StoreRewindInfo(void) info->playerinfo[i].ingame = true; memcpy(&info->playerinfo[i].player, &players[i], sizeof(player_t)); + if (players[i].mo) memcpy(&info->playerinfo[i].mobj, players[i].mo, sizeof(mobj_t)); } @@ -1437,10 +1480,10 @@ void G_PreviewRewind(tic_t previewtime) next_info = info; info = info->prev; } + if (info != next_info) tweenvalue = FixedDiv(previewtime - info->leveltime, next_info->leveltime - info->leveltime); - for (i = 0; i < MAXPLAYERS; i++) { if (!playeringame[i] || players[i].spectator) @@ -1481,6 +1524,7 @@ void G_PreviewRewind(tic_t previewtime) players[i].mo->frame = info->playerinfo[i].mobj.frame; players[i].realtime = info->playerinfo[i].player.realtime; + for (j = 0; j < NUMKARTSTUFF; j++) players[i].kartstuff[j] = info->playerinfo[i].player.kartstuff[j]; } @@ -1669,10 +1713,13 @@ void G_BeginRecording(void) demobuf.p += 1; totalfiles = 0; - for (i = mainwads; ++i < numwadfiles; ) - if (wadfiles[i]->important) + + for (i = mainwads; ++i < numwadfiles;) { - nameonly(( filename = va("%s", wadfiles[i]->filename) )); + if (!wadfiles[i]->important) + continue; + + nameonly((filename = va("%s", wadfiles[i]->filename))); WRITESTRINGL(demobuf.p, filename, MAX_WADPATH); WRITEMEM(demobuf.p, wadfiles[i]->md5sum, 16); @@ -1681,17 +1728,17 @@ void G_BeginRecording(void) WRITEUINT8(m, totalfiles); - switch ((demoflags & DF_ATTACKMASK)>>DF_ATTACKSHIFT) + switch ((demoflags & DF_ATTACKMASK) >> DF_ATTACKSHIFT) { - case ATTACKING_NONE: // 0 - break; - case ATTACKING_RECORD: // 1 - demotime_p = demobuf.p; - WRITEUINT32(demobuf.p,UINT32_MAX); // time - WRITEUINT32(demobuf.p,UINT32_MAX); // lap - break; - default: // 3 - break; + case ATTACKING_NONE: // 0 + break; + case ATTACKING_RECORD: // 1 + demotime_p = demobuf.p; + WRITEUINT32(demobuf.p,UINT32_MAX); // time + WRITEUINT32(demobuf.p,UINT32_MAX); // lap + break; + default: // 3 + break; } WRITEUINT32(demobuf.p, P_GetInitSeed()); @@ -1810,6 +1857,7 @@ void G_SetDemoTime(UINT32 ptime, UINT32 plap) { if (!demo.recording || !demotime_p) return; + if (demoflags & DF_RECORDATTACK) { WRITEUINT32(demotime_p, ptime); @@ -1828,7 +1876,8 @@ static void G_LoadDemoExtraFiles(UINT8 **pp) boolean alreadyloaded; UINT8 i, j; - totalfiles = READUINT8((*pp)); + totalfiles = READUINT8((*pp)); // i like pp uwu + for (i = 0; i < totalfiles; ++i) { if (toomany) @@ -1838,6 +1887,7 @@ static void G_LoadDemoExtraFiles(UINT8 **pp) strlcpy(filename, (char *)(*pp), sizeof filename); SKIPSTRING((*pp)); } + READMEM((*pp), md5sum, 16); if (!toomany) @@ -1917,6 +1967,7 @@ static UINT8 G_CheckDemoExtraFiles(UINT8 **pp, boolean quick) totalfiles = READUINT8((*pp)); filesloaded = 0; + for (i = 0; i < totalfiles; ++i) { if (toomany) @@ -1926,7 +1977,8 @@ static UINT8 G_CheckDemoExtraFiles(UINT8 **pp, boolean quick) strlcpy(filename, (char *)(*pp), sizeof filename); SKIPSTRING((*pp)); } - READMEM((*pp), md5sum, 16); + + READMEM((*pp), md5sum, 16); // hue hue peepee if (!toomany) { @@ -1971,8 +2023,10 @@ static UINT8 G_CheckDemoExtraFiles(UINT8 **pp, boolean quick) nmusfilecount = 0; for (j = 0; j < numwadfiles; ++j) + { if (wadfiles[j]->important && j > mainwads) nmusfilecount++; + } if (!error && filesloaded < nmusfilecount) error = DFILE_ERROR_EXTRAFILES; @@ -1986,7 +2040,8 @@ static UINT8 G_CheckDemoExtraFiles(UINT8 **pp, boolean quick) // 4 == new demo has higher rings UINT8 G_CmpDemoTime(char *oldname, char *newname) { - UINT8 *buffer,*p; + CLEANUP(Z_Pfree) UINT8 *buffer = NULL; + UINT8 *p; UINT8 flags; UINT32 oldtime, newtime, oldlap, newlap; UINT16 oldversion; @@ -2018,10 +2073,12 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) p += 16; // map md5 flags = READUINT8(p); // demoflags p++; // gametype + G_SkipDemoExtraFiles(&p); aflags = flags & (DF_RECORDATTACK|DF_NIGHTSATTACK); I_Assert(aflags); + if (flags & DF_RECORDATTACK) { newtime = READUINT32(p); @@ -2031,62 +2088,69 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) return 0; Z_Free(buffer); + buffer = NULL; // load old file FIL_DefaultExtension(oldname, ".lmp"); + if (!FIL_ReadFile(oldname, &buffer)) { CONS_Alert(CONS_ERROR, M_GetText("Failed to read file '%s'.\n"), oldname); return UINT8_MAX; } + p = buffer; // read demo header if (memcmp(p, DEMOHEADER, 12)) { CONS_Alert(CONS_NOTICE, M_GetText("File '%s' invalid format. It will be overwritten.\n"), oldname); - Z_Free(buffer); return UINT8_MAX; - } p += 12; // DEMOHEADER + } + + p += 12; // DEMOHEADER p++; // VERSION p++; // SUBVERSION oldversion = READUINT16(p); - switch(oldversion) // demoversion + + switch (oldversion) // demoversion { - case DEMOVERSION: // latest always supported - p += 64; // full demo title - break; -#ifdef DEMO_COMPAT_100 - case 0x0001: - // Old replays gotta go :] - CONS_Alert(CONS_NOTICE, M_GetText("File '%s' outdated version. It will be overwritten. Nyeheheh.\n"), oldname); - Z_Free(buffer); - return UINT8_MAX; + case DEMOVERSION: // latest always supported + p += 64; // full demo title + break; + #ifdef DEMO_COMPAT_100 + case 0x0001: + // Old replays gotta go :] + CONS_Alert(CONS_NOTICE, M_GetText("File '%s' outdated version. It will be overwritten. Nyeheheh.\n"), oldname); + return UINT8_MAX; #endif - // too old, cannot support. - default: - CONS_Alert(CONS_NOTICE, M_GetText("File '%s' invalid format. It will be overwritten.\n"), oldname); - Z_Free(buffer); - return UINT8_MAX; + // too old, cannot support. + default: + CONS_Alert(CONS_NOTICE, M_GetText("File '%s' invalid format. It will be overwritten.\n"), oldname); + return UINT8_MAX; } + p += 16; // demo checksum + if (memcmp(p, "PLAY", 4)) { CONS_Alert(CONS_NOTICE, M_GetText("File '%s' invalid format. It will be overwritten.\n"), oldname); - Z_Free(buffer); return UINT8_MAX; - } p += 4; // "PLAY" + } + + p += 4; // "PLAY" p += 2; // gamemap p += 16; // mapmd5 flags = READUINT8(p); p++; // gametype G_SkipDemoExtraFiles(&p); + if (!(flags & aflags)) { CONS_Alert(CONS_NOTICE, M_GetText("File '%s' not from same game mode. It will be overwritten.\n"), oldname); - Z_Free(buffer); return UINT8_MAX; } + if (flags & DF_RECORDATTACK) { oldtime = READUINT32(p); @@ -2095,21 +2159,23 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) else // appease compiler return UINT8_MAX; - Z_Free(buffer); - c = 0; + if (newtime < oldtime || (newtime == oldtime && (newlap < oldlap))) c |= 1; // Better time + if (newlap < oldlap || (newlap == oldlap && newtime < oldtime)) c |= 1<<1; // Better lap time + return c; } void G_LoadDemoInfo(menudemo_t *pdemo) { - UINT8 *infobuffer, *info_p, *extrainfo_p; + UINT8 *info_p, *extrainfo_p; + CLEANUP(Z_Pfree) UINT8 *infobuffer = NULL; UINT8 version, subversion, pdemoflags; UINT16 pdemoversion, count; @@ -2118,7 +2184,6 @@ void G_LoadDemoInfo(menudemo_t *pdemo) CONS_Alert(CONS_ERROR, M_GetText("Failed to read file '%s'.\n"), pdemo->filepath); pdemo->type = MD_INVALID; sprintf(pdemo->title, "INVALID REPLAY"); - return; } @@ -2129,7 +2194,6 @@ void G_LoadDemoInfo(menudemo_t *pdemo) CONS_Alert(CONS_ERROR, M_GetText("%s is not a SRB2Kart replay file.\n"), pdemo->filepath); pdemo->type = MD_INVALID; sprintf(pdemo->title, "INVALID REPLAY"); - Z_Free(infobuffer); return; } @@ -2144,41 +2208,40 @@ void G_LoadDemoInfo(menudemo_t *pdemo) memset(pdemo->version, 0, sizeof(pdemo->version)); snprintf(pdemo->version, sizeof(pdemo->version), "v%d.%d", version, subversion); - switch(pdemoversion) + switch (pdemoversion) { - case DEMOVERSION: // latest always supported - // demo title - M_Memcpy(pdemo->title, info_p, 64); - info_p += 64; - - break; + case DEMOVERSION: // latest always supported + // demo title + M_Memcpy(pdemo->title, info_p, 64); + info_p += 64; + break; #ifdef DEMO_COMPAT_100 - case 0x0001: - pdemo->type = MD_OUTDATED; - sprintf(pdemo->title, "Legacy Replay"); - break; + case 0x0001: + pdemo->type = MD_OUTDATED; + sprintf(pdemo->title, "Legacy Replay"); + break; #endif - // too old, cannot support. - default: - CONS_Alert(CONS_ERROR, M_GetText("%s is an incompatible replay format and cannot be played.\n"), pdemo->filepath); - pdemo->type = MD_INVALID; - sprintf(pdemo->title, "INVALID REPLAY"); - Z_Free(infobuffer); - return; + // too old, cannot support. + default: + CONS_Alert(CONS_ERROR, M_GetText("%s is an incompatible replay format and cannot be played.\n"), pdemo->filepath); + pdemo->type = MD_INVALID; + sprintf(pdemo->title, "INVALID REPLAY"); + return; } if (version != VERSION || subversion != SUBVERSION) pdemo->type = MD_OUTDATED; info_p += 16; // demo checksum + if (memcmp(info_p, "PLAY", 4)) { CONS_Alert(CONS_ERROR, M_GetText("%s is the wrong type of recording and cannot be played.\n"), pdemo->filepath); pdemo->type = MD_INVALID; sprintf(pdemo->title, "INVALID REPLAY"); - Z_Free(infobuffer); return; } + info_p += 4; // "PLAY" pdemo->map = READINT16(info_p); info_p += 16; // mapmd5 @@ -2189,7 +2252,6 @@ void G_LoadDemoInfo(menudemo_t *pdemo) if (!(pdemoflags & DF_MULTIPLAYER)) { CONS_Alert(CONS_ERROR, M_GetText("%s is not a multiplayer replay and can't be listed on this menu fully yet.\n"), pdemo->filepath); - Z_Free(infobuffer); return; } #ifdef DEMO_COMPAT_100 @@ -2198,7 +2260,6 @@ void G_LoadDemoInfo(menudemo_t *pdemo) CONS_Alert(CONS_ERROR, M_GetText("%s is a legacy multiplayer replay and cannot be played.\n"), pdemo->filepath); pdemo->type = MD_INVALID; sprintf(pdemo->title, "INVALID REPLAY"); - Z_Free(infobuffer); return; } #endif @@ -2213,6 +2274,7 @@ void G_LoadDemoInfo(menudemo_t *pdemo) // Pared down version of CV_LoadNetVars to find the kart speed pdemo->kartspeed = 1; // Default to normal speed count = READUINT16(info_p); + while (count--) { UINT16 netid; @@ -2225,10 +2287,11 @@ void G_LoadDemoInfo(menudemo_t *pdemo) if (netid == cv_kartspeed.netid) { - UINT8 j; - for (j = 0; kartspeed_cons_t[j].strvalue; j++) + for (UINT8 j = 0; kartspeed_cons_t[j].strvalue; j++) + { if (!stricmp(kartspeed_cons_t[j].strvalue, svalue)) pdemo->kartspeed = kartspeed_cons_t[j].value; + } } else if (netid == cv_basenumlaps.netid && pdemo->gametype == GT_RACE) pdemo->numlaps = atoi(svalue); @@ -2255,22 +2318,28 @@ void G_LoadDemoInfo(menudemo_t *pdemo) M_Memcpy(temp,extrainfo_p,16); extrainfo_p += 16; pdemo->standings[count].skin = UINT8_MAX; + for (i = 0; i < numskins; i++) + { if (stricmp(skins[i].name, temp) == 0) { pdemo->standings[count].skin = i; break; } + } // Color M_Memcpy(temp,extrainfo_p,16); extrainfo_p += 16; + for (i = 0; i < MAXSKINCOLORS; i++) + { if (!stricmp(KartColor_Names[i],temp)) // SRB2kart { pdemo->standings[count].color = i; break; } + } // Score/time/whatever pdemo->standings[count].timeorscore = READUINT32(extrainfo_p); @@ -2282,7 +2351,6 @@ void G_LoadDemoInfo(menudemo_t *pdemo) } // I think that's everything we need? - Z_Free(infobuffer); } #if defined (_WIN32) @@ -2422,28 +2490,30 @@ void G_LoadDemoTitle(menudemo_t *pdemo) memset(pdemo->date, 0, sizeof(pdemo->date)); - switch(pdemoversion) + switch (pdemoversion) { - case DEMOVERSION: // latest always supported - // demo title - M_Memcpy(pdemo->title, info_p, 64); + case DEMOVERSION: // latest always supported + // demo title + M_Memcpy(pdemo->title, info_p, 64); - // demo date - char *demodate; - demodate = G_GetDemoDate(pdemo); - if (demodate) - strncpy(pdemo->date, demodate, sizeof(pdemo->date)); - free(demodate); - break; + // demo date + char *demodate; + demodate = G_GetDemoDate(pdemo); + + if (demodate) + strncpy(pdemo->date, demodate, sizeof(pdemo->date)); + + free(demodate); + break; #ifdef DEMO_COMPAT_100 - case 0x0001: - sprintf(pdemo->title, "Legacy Replay"); - break; + case 0x0001: + sprintf(pdemo->title, "Legacy Replay"); + break; #endif - // too old, cannot support. - default: - CONS_Alert(CONS_ERROR, M_GetText("%s is an incompatible replay format and cannot be played.\n"), pdemo->filepath); - sprintf(pdemo->title, "INVALID REPLAY"); + // too old, cannot support. + default: + CONS_Alert(CONS_ERROR, M_GetText("%s is an incompatible replay format and cannot be played.\n"), pdemo->filepath); + sprintf(pdemo->title, "INVALID REPLAY"); } } @@ -2465,8 +2535,9 @@ void G_DoPlayDemo(char *defdemoname) { UINT8 i, p; lumpnum_t l; - char skin[17],color[17],*n,*pdemoname; - UINT8 version,subversion; + char skin[17], color[17], *n; + CLEANUP(Z_Pfree) char *pdemoname; + UINT8 version, subversion; UINT32 randseed; char msg[1024]; #if defined(SKIPERRORS) && !defined(DEVELOP) @@ -2488,11 +2559,13 @@ void G_DoPlayDemo(char *defdemoname) } else { - n = defdemoname+strlen(defdemoname); + n = defdemoname + strlen(defdemoname); + while (*n != '/' && *n != '\\' && n != defdemoname) n--; if (n != defdemoname) n++; + pdemoname = ZZ_Alloc(strlen(n)+1); strcpy(pdemoname,n); @@ -2510,6 +2583,7 @@ void G_DoPlayDemo(char *defdemoname) M_StartMessage(msg, NULL, MM_NOTHING); return; } + demobuf.p = demobuf.buffer; } // load demo resource from WAD @@ -2533,53 +2607,58 @@ void G_DoPlayDemo(char *defdemoname) // read demo header gameaction = ga_nothing; demo.playback = true; + if (memcmp(demobuf.p, DEMOHEADER, 12)) { snprintf(msg, 1024, M_GetText("%s is not a SRB2Kart replay file.\n"), pdemoname); CONS_Alert(CONS_ERROR, "%s", msg); M_StartMessage(msg, NULL, MM_NOTHING); - G_ResetDemoPlayback(pdemoname); + G_ResetDemoPlayback(); return; } + demobuf.p += 12; // DEMOHEADER version = READUINT8(demobuf.p); subversion = READUINT8(demobuf.p); demo.version = READUINT16(demobuf.p); - switch(demo.version) - { - case DEMOVERSION: // latest always supported - // demo title - M_Memcpy(demo.titlename, demobuf.p, 64); - demobuf.p += 64; - break; + switch (demo.version) + { + case DEMOVERSION: // latest always supported + // demo title + M_Memcpy(demo.titlename, demobuf.p, 64); + demobuf.p += 64; + break; #ifdef DEMO_COMPAT_100 - case 0x0001: - break; + case 0x0001: + break; #endif - // too old, cannot support. - default: - snprintf(msg, 1024, M_GetText("%s is an incompatible replay format and cannot be played.\n"), pdemoname); - CONS_Alert(CONS_ERROR, "%s", msg); - M_StartMessage(msg, NULL, MM_NOTHING); - G_ResetDemoPlayback(pdemoname); - return; + // too old, cannot support. + default: + snprintf(msg, 1024, M_GetText("%s is an incompatible replay format and cannot be played.\n"), pdemoname); + CONS_Alert(CONS_ERROR, "%s", msg); + M_StartMessage(msg, NULL, MM_NOTHING); + G_ResetDemoPlayback(); + return; } + demobuf.p += 16; // demo checksum + if (memcmp(demobuf.p, "PLAY", 4)) { snprintf(msg, 1024, M_GetText("%s is the wrong type of recording and cannot be played.\n"), pdemoname); CONS_Alert(CONS_ERROR, "%s", msg); M_StartMessage(msg, NULL, MM_NOTHING); - G_ResetDemoPlayback(pdemoname); + G_ResetDemoPlayback(); return; } + demobuf.p += 4; // "PLAY" gamemap = READINT16(demobuf.p); demobuf.p += 16; // mapmd5 - demoflags = READUINT8(demobuf.p); + #ifdef DEMO_COMPAT_100 if (demo.version == 0x0001) { @@ -2588,7 +2667,7 @@ void G_DoPlayDemo(char *defdemoname) snprintf(msg, 1024, M_GetText("%s is an alpha multiplayer replay and cannot be played.\n"), pdemoname); CONS_Alert(CONS_ERROR, "%s", msg); M_StartMessage(msg, NULL, MM_NOTHING); - G_ResetDemoPlayback(pdemoname); + G_ResetDemoPlayback(); return; } } @@ -2611,41 +2690,43 @@ void G_DoPlayDemo(char *defdemoname) { switch (error) { - case DFILE_ERROR_NOTLOADED: - snprintf(msg, 1024, - M_GetText("Required files for this demo are not loaded.\n\nUse\n\"playdemo %s -addfiles\"\nto load them and play the demo.\n"), - pdemoname); - break; + case DFILE_ERROR_NOTLOADED: + snprintf(msg, 1024, + "Required files for this demo are not loaded.\n\nUse\n\"playdemo %s -addfiles\"\nto load them and play the demo.\n", + pdemoname); + break; - case DFILE_ERROR_OUTOFORDER: - snprintf(msg, 1024, - M_GetText("Required files for this demo are loaded out of order.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n"), - pdemoname); - break; + case DFILE_ERROR_OUTOFORDER: + snprintf(msg, 1024, + "Required files for this demo are loaded out of order.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n", + pdemoname); + break; - case DFILE_ERROR_INCOMPLETEOUTOFORDER: - snprintf(msg, 1024, - M_GetText("Required files for this demo are not loaded, and some are out of order.\n\nUse\n\"playdemo %s -addfiles\"\nto load needed files and play the demo.\n"), - pdemoname); - break; + case DFILE_ERROR_INCOMPLETEOUTOFORDER: + snprintf(msg, 1024, + "Required files for this demo are not loaded, and some are out of order.\n\nUse\n\"playdemo %s -addfiles\"\nto load needed files and play the demo.\n", + pdemoname); + break; - case DFILE_ERROR_CANNOTLOAD: - snprintf(msg, 1024, - M_GetText("Required files for this demo cannot be loaded.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n"), - pdemoname); - break; + case DFILE_ERROR_CANNOTLOAD: + snprintf(msg, 1024, + "Required files for this demo cannot be loaded.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n", + pdemoname); + break; - case DFILE_ERROR_EXTRAFILES: - snprintf(msg, 1024, - M_GetText("You have additional files loaded beyond the demo's file list.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n"), - pdemoname); - break; + case DFILE_ERROR_EXTRAFILES: + snprintf(msg, 1024, + "You have additional files loaded beyond the demo's file list.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n", + pdemoname); + break; } CONS_Alert(CONS_ERROR, "%s", msg); + if (!CON_Ready()) // In the console they'll just see the notice there! No point pulling them out. M_StartMessage(msg, NULL, MM_NOTHING); - G_ResetDemoPlayback(pdemoname); + + G_ResetDemoPlayback(); return; } } @@ -2662,19 +2743,20 @@ void G_DoPlayDemo(char *defdemoname) switch (modeattacking) { - case ATTACKING_NONE: // 0 - break; - case ATTACKING_RECORD: // 1 - hu_demotime = READUINT32(demobuf.p); - hu_demolap = READUINT32(demobuf.p); - break; - default: // 3 - modeattacking = ATTACKING_NONE; - break; + case ATTACKING_NONE: // 0 + break; + case ATTACKING_RECORD: // 1 + hu_demotime = READUINT32(demobuf.p); + hu_demolap = READUINT32(demobuf.p); + break; + default: // 3 + modeattacking = ATTACKING_NONE; + break; } // Random seed randseed = READUINT32(demobuf.p); + #ifdef DEMO_COMPAT_100 if (demo.version != 0x0001) #endif @@ -2708,7 +2790,7 @@ void G_DoPlayDemo(char *defdemoname) snprintf(msg, 1024, M_GetText("%s features a character that is not currently loaded.\n"), pdemoname); CONS_Alert(CONS_ERROR, "%s", msg); M_StartMessage(msg, NULL, MM_NOTHING); - G_ResetDemoPlayback(pdemoname); + G_ResetDemoPlayback(); return; } @@ -2718,17 +2800,19 @@ void G_DoPlayDemo(char *defdemoname) snprintf(msg, 1024, M_GetText("%s features a course that is not currently loaded.\n"), pdemoname); CONS_Alert(CONS_ERROR, "%s", msg); M_StartMessage(msg, NULL, MM_NOTHING); - G_ResetDemoPlayback(pdemoname); + G_ResetDemoPlayback(); return; } // Set color for (i = 0; i < MAXSKINCOLORS; i++) + { if (!stricmp(KartColor_Names[i],color)) // SRB2kart { players[0].skincolor = i; break; } + } // net var data CV_LoadNetVars(&demobuf.p); @@ -2739,12 +2823,10 @@ void G_DoPlayDemo(char *defdemoname) snprintf(msg, 1024, M_GetText("%s contains no data to be played.\n"), pdemoname); CONS_Alert(CONS_ERROR, "%s", msg); M_StartMessage(msg, NULL, MM_NOTHING); - G_ResetDemoPlayback(pdemoname); + G_ResetDemoPlayback(); return; } - Z_Free(pdemoname); - memset(&oldcmd,0,sizeof(oldcmd)); memset(&oldghost,0,sizeof(oldghost)); memset(&ghostext,0,sizeof(ghostext)); @@ -2779,15 +2861,13 @@ void G_DoPlayDemo(char *defdemoname) snprintf(msg, 1024, M_GetText("%s contains no data to be played.\n"), pdemoname); CONS_Alert(CONS_ERROR, "%s", msg); M_StartMessage(msg, NULL, MM_NOTHING); - G_ResetDemoPlayback(pdemoname); + G_ResetDemoPlayback(); return; } - Z_Free(pdemoname); - - memset(&oldcmd,0,sizeof(oldcmd)); - memset(&oldghost,0,sizeof(oldghost)); - memset(&ghostext,0,sizeof(ghostext)); + memset(&oldcmd, 0, sizeof(oldcmd)); + memset(&oldghost, 0, sizeof(oldghost)); + memset(&ghostext, 0, sizeof(ghostext)); #if defined(SKIPERRORS) && !defined(DEVELOP) if ((VERSION != version || SUBVERSION != subversion) && !skiperrors) @@ -2819,6 +2899,7 @@ void G_DoPlayDemo(char *defdemoname) while (p != 0xFF) { spectator = false; + if (p & DEMO_SPECTATOR) { spectator = true; @@ -2829,10 +2910,11 @@ void G_DoPlayDemo(char *defdemoname) snprintf(msg, 1024, M_GetText("%s is a Record Attack replay with spectators, and is thus invalid.\n"), pdemoname); CONS_Alert(CONS_ERROR, "%s", msg); M_StartMessage(msg, NULL, MM_NOTHING); - G_ResetDemoPlayback(pdemoname); + G_ResetDemoPlayback(); return; } } + slots[numslots] = p; numslots++; if (modeattacking && numslots > 1) @@ -2840,7 +2922,7 @@ void G_DoPlayDemo(char *defdemoname) snprintf(msg, 1024, M_GetText("%s is a Record Attack replay with multiple players, and is thus invalid.\n"), pdemoname); CONS_Alert(CONS_ERROR, "%s", msg); M_StartMessage(msg, NULL, MM_NOTHING); - G_ResetDemoPlayback(pdemoname); + G_ResetDemoPlayback(); return; } @@ -2862,12 +2944,15 @@ void G_DoPlayDemo(char *defdemoname) // Color M_Memcpy(color,demobuf.p,16); demobuf.p += 16; + for (i = 0; i < MAXSKINCOLORS; i++) + { if (!stricmp(KartColor_Names[i],color)) // SRB2kart { players[p].skincolor = i; break; } + } // Score, since Kart uses this to determine where you start on the map players[p].score = READUINT32(demobuf.p); @@ -2885,9 +2970,9 @@ void G_DoPlayDemo(char *defdemoname) // end of player read (the 0xFF marker) // so this is where we are to read our lua variables (if possible!) - if (demoflags & DF_LUAVARS) // again, used for compability, lua shit will be saved to replays regardless of if it's even been loaded + if (demoflags & DF_LUAVARS) // again, used for compability, lua shit will be saved to replays regardless of if it's even been loaded { - if (!gL) // No Lua state! ...I guess we'll just start one... + if (!gL) // No Lua state! ...I guess we'll just start one... LUA_ClearState(); // No modeattacking check, DF_LUAVARS won't be present here. @@ -2942,10 +3027,12 @@ void G_AddGhost(char *defdemoname) { INT32 i; lumpnum_t l; - char name[17],skin[17],color[17],*n,*pdemoname,md5[16]; + char name[17], skin[17], color[17], *n, md5[16]; + CLEANUP(Z_Pfree) char *pdemoname = NULL; demoghost *gh; + UINT8 *p; UINT8 flags; - UINT8 *buffer,*p; + CLEANUP(Z_Pfree) UINT8 *buffer = NULL; mapthing_t *mthing; UINT16 count, ghostversion; skin_t *ghskin = &skins[0]; @@ -2955,13 +3042,15 @@ void G_AddGhost(char *defdemoname) skin[16] = '\0'; color[16] = '\0'; - n = defdemoname+strlen(defdemoname); + n = defdemoname + strlen(defdemoname); + while (*n != '/' && *n != '\\' && n != defdemoname) n--; if (n != defdemoname) n++; + pdemoname = ZZ_Alloc(strlen(n)+1); - strcpy(pdemoname,n); + strcpy(pdemoname, n); // Internal if no extension, external if one exists if (FIL_CheckExtension(defdemoname)) @@ -2970,16 +3059,15 @@ void G_AddGhost(char *defdemoname) if (!FIL_ReadFileTag(defdemoname, &buffer, PU_LEVEL)) { CONS_Alert(CONS_ERROR, M_GetText("Failed to read file '%s'.\n"), defdemoname); - Z_Free(pdemoname); return; } + p = buffer; } // load demo resource from WAD else if ((l = W_CheckNumForName(defdemoname)) == LUMPERROR) { CONS_Alert(CONS_ERROR, M_GetText("Failed to read lump '%s'.\n"), defdemoname); - Z_Free(pdemoname); return; } else // it's an internal demo @@ -2989,8 +3077,6 @@ void G_AddGhost(char *defdemoname) if (memcmp(p, DEMOHEADER, 12)) { CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Not a SRB2Kart replay.\n"), pdemoname); - Z_Free(pdemoname); - Z_Free(buffer); return; } @@ -2999,38 +3085,36 @@ void G_AddGhost(char *defdemoname) p++; // SUBVERSION ghostversion = READUINT16(p); - switch(ghostversion) + + switch (ghostversion) { - case DEMOVERSION: // latest always supported - p += 64; // title - break; + case DEMOVERSION: // latest always supported + p += 64; // title + break; #ifdef DEMO_COMPAT_100 - case 0x0001: - break; + case 0x0001: + break; #endif - // too old, cannot support. - default: - CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Demo version incompatible.\n"), pdemoname); - Z_Free(pdemoname); - Z_Free(buffer); - return; + // too old, cannot support. + default: + CONS_Alert(CONS_NOTICE, "Ghost %s: Demo version incompatible.\n", pdemoname); + return; } M_Memcpy(md5, p, 16); p += 16; // demo checksum + for (gh = ghosts; gh; gh = gh->next) + { if (!memcmp(md5, gh->checksum, 16)) // another ghost in the game already has this checksum? { // Don't add another one, then! CONS_Debug(DBG_SETUP, "Rejecting duplicate ghost %s (MD5 was matched)\n", pdemoname); - Z_Free(pdemoname); - Z_Free(buffer); return; } + } if (memcmp(p, "PLAY", 4)) { - CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Demo format unacceptable.\n"), pdemoname); - Z_Free(pdemoname); - Z_Free(buffer); + CONS_Alert(CONS_NOTICE, "Ghost %s: Demo format unacceptable.\n", pdemoname); return; } @@ -3042,9 +3126,7 @@ void G_AddGhost(char *defdemoname) if (!(flags & DF_GHOST)) { - CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: No ghost data in this demo.\n"), pdemoname); - Z_Free(pdemoname); - Z_Free(buffer); + CONS_Alert(CONS_NOTICE, "Ghost %s: No ghost data in this demo.\n", pdemoname); return; } @@ -3057,15 +3139,16 @@ void G_AddGhost(char *defdemoname) if (ghostversion != 0x0001) #endif G_SkipDemoExtraFiles(&p); // Don't wanna modify the file list for ghosts. - switch ((flags & DF_ATTACKMASK)>>DF_ATTACKSHIFT) + + switch ((flags & DF_ATTACKMASK) >> DF_ATTACKSHIFT) { - case ATTACKING_NONE: // 0 - break; - case ATTACKING_RECORD: // 1 - p += 8; // demo time, lap - break; - default: // 3 - break; + case ATTACKING_NONE: // 0 + break; + case ATTACKING_RECORD: // 1 + p += 8; // demo time, lap + break; + default: // 3 + break; } p += 4; // random seed @@ -3118,8 +3201,6 @@ void G_AddGhost(char *defdemoname) if (*p == DEMOMARKER) { CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Replay is empty.\n"), pdemoname); - Z_Free(pdemoname); - Z_Free(buffer); return; } @@ -3130,8 +3211,6 @@ void G_AddGhost(char *defdemoname) if (READUINT8(p) != 0) { CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Invalid player slot.\n"), pdemoname); - Z_Free(pdemoname); - Z_Free(buffer); return; } @@ -3155,8 +3234,6 @@ void G_AddGhost(char *defdemoname) if (READUINT8(p) != 0xFF) { CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Invalid player slot.\n"), pdemoname); - Z_Free(pdemoname); - Z_Free(buffer); return; } #ifdef DEMO_COMPAT_100 @@ -3164,11 +3241,13 @@ void G_AddGhost(char *defdemoname) #endif for (i = 0; i < numskins; i++) + { if (!stricmp(skins[i].name,skin)) { ghskin = &skins[i]; break; } + } if (i == numskins) { @@ -3183,21 +3262,26 @@ void G_AddGhost(char *defdemoname) gh->buffer = buffer; M_Memcpy(gh->checksum, md5, 16); gh->p = p; + buffer = NULL; // buffer can't be freed now! ghosts = gh; gh->version = ghostversion; mthing = playerstarts[0]; I_Assert(mthing); + { // A bit more complex than P_SpawnPlayer because ghosts aren't solid and won't just push themselves out of the ceiling. - fixed_t z,f,c; + fixed_t z, f, c; + gh->mo = P_SpawnMobj(mthing->x << FRACBITS, mthing->y << FRACBITS, 0, MT_GHOST); gh->mo->angle = FixedAngle(mthing->angle*FRACUNIT); f = gh->mo->floorz; c = gh->mo->ceilingz - mobjinfo[MT_PLAYER].height; + if (!!(mthing->options & MTF_AMBUSH) ^ !!(mthing->options & MTF_OBJECTFLIP)) { z = c; + if (mthing->options >> ZSHIFT) z -= ((mthing->options >> ZSHIFT) << FRACBITS); if (z < f) @@ -3206,13 +3290,16 @@ void G_AddGhost(char *defdemoname) else { z = f; + if (mthing->options >> ZSHIFT) z += ((mthing->options >> ZSHIFT) << FRACBITS); if (z > c) z = c; } + gh->mo->z = z; } + gh->mo->state = states+S_KART_STND1; // SRB2kart - was S_PLAY_STND gh->mo->sprite = gh->mo->state->sprite; gh->mo->frame = (gh->mo->state->frame & FF_FRAMEMASK) | tr_trans20<mo->color = ((skin_t*)gh->mo->skin)->prefcolor; + for (i = 0; i < MAXSKINCOLORS; i++) + { if (!stricmp(KartColor_Names[i],color)) // SRB2kart { gh->mo->color = (UINT8)i; break; } + } + gh->oldmo.color = gh->mo->color; CONS_Printf(M_GetText("Added ghost %s from %s\n"), name, pdemoname); - Z_Free(pdemoname); } // A simplified version of G_AddGhost... void G_UpdateStaffGhostName(lumpnum_t l) { - UINT8 *buffer,*p; + UINT8 *p; + CLEANUP(Z_Pfree) UINT8 *buffer = NULL; UINT16 ghostversion; UINT8 flags; @@ -3251,7 +3342,7 @@ void G_UpdateStaffGhostName(lumpnum_t l) // read demo header if (memcmp(p, DEMOHEADER, 12)) { - goto fail; + return; } p += 12; // DEMOHEADER @@ -3259,27 +3350,25 @@ void G_UpdateStaffGhostName(lumpnum_t l) p++; // SUBVERSION ghostversion = READUINT16(p); - switch(ghostversion) + switch (ghostversion) { - case DEMOVERSION: // latest always supported - p += 64; // full demo title - break; - + case DEMOVERSION: // latest always supported + p += 64; // full demo title + break; #ifdef DEMO_COMPAT_100 - case 0x0001: - break; + case 0x0001: + break; #endif - - // too old, cannot support. - default: - goto fail; + // too old, cannot support. + default: + return; } p += 16; // demo checksum if (memcmp(p, "PLAY", 4)) { - goto fail; + return; } p += 4; // "PLAY" @@ -3289,7 +3378,7 @@ void G_UpdateStaffGhostName(lumpnum_t l) flags = READUINT8(p); if (!(flags & DF_GHOST)) { - goto fail; // we don't NEED to do it here, but whatever + return; // we don't NEED to do it here, but whatever } #ifdef DEMO_COMPAT_100 @@ -3304,13 +3393,13 @@ void G_UpdateStaffGhostName(lumpnum_t l) switch ((flags & DF_ATTACKMASK)>>DF_ATTACKSHIFT) { - case ATTACKING_NONE: // 0 - break; - case ATTACKING_RECORD: // 1 - p += 8; // demo time, lap - break; - default: // 3 - break; + case ATTACKING_NONE: // 0 + break; + case ATTACKING_RECORD: // 1 + p += 8; // demo time, lap + break; + default: // 3 + break; } p += 4; // random seed @@ -3322,7 +3411,7 @@ void G_UpdateStaffGhostName(lumpnum_t l) // Player name M_Memcpy(dummystaffname, p,16); dummystaffname[16] = '\0'; - goto fail; // Not really a failure but whatever + return; // Not really a failure but whatever } #endif @@ -3330,6 +3419,7 @@ void G_UpdateStaffGhostName(lumpnum_t l) // Ehhhh don't need ghostversion here (?) so I'll reuse the var here ghostversion = READUINT16(p); + while (ghostversion--) { p += 2; @@ -3339,14 +3429,12 @@ void G_UpdateStaffGhostName(lumpnum_t l) // Assert first player is in and then read name if (READUINT8(p) != 0) - goto fail; - M_Memcpy(dummystaffname, p,16); + return; + + M_Memcpy(dummystaffname, p, 16); dummystaffname[16] = '\0'; // Ok, no longer any reason to care, bye -fail: - Z_Free(buffer); - return; } // @@ -3390,12 +3478,7 @@ void G_DoneLevelLoad(void) // called from stopdemo command, map command, and g_checkdemoStatus. void G_StopDemo(void) { - Z_Free(demobuf.buffer); - demobuf.buffer = NULL; - demo.playback = false; - if (demo.title) - modeattacking = ATTACKING_NONE; - demo.title = false; + G_ResetDemoPlayback(); demo.timing = false; singletics = false; @@ -3508,9 +3591,8 @@ void G_ResetDemoRecording(void) demo.recording = false; } -static void G_ResetDemoPlayback(char *pdemoname) +static void G_ResetDemoPlayback(void) { - Z_Free(pdemoname); Z_Free(demobuf.buffer); demobuf.buffer = NULL; demo.playback = false; -- 2.54.0 From 8a305d3c797fe0b9af8fcde38f920095103a327a Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 24 Oct 2025 03:47:50 +0200 Subject: [PATCH 155/219] move those to D_ClearState --- src/d_main.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 992fc59db..d4cef24c3 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -979,6 +979,8 @@ void D_ClearState(void) { INT32 i; + demo.title = false; + // okay, stop now // (otherwise the game still thinks we're playing!) CURLAbortFile(); @@ -1034,6 +1036,9 @@ void D_ClearState(void) wipegamestate = GS_NULL; M_ClearMenus(true); + + // map palettes affect this + D_ResetDeviceLED(); } // @@ -1041,12 +1046,9 @@ void D_ClearState(void) // void D_StartTitle(void) { - demo.title = false; D_ClearState(); - multiplayer = false; // reset manually - netgame = false; // title menu shouldnt be a netgame lmao + multiplayer = netgame = false; // title menu shouldnt be a netgame or multiplayer lmao F_StartTitleScreen(); - D_ResetDeviceLED(); } // -- 2.54.0 From 82c41915161650fa0a15fed5d05a2ff537a4ae97 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 24 Oct 2025 04:09:43 +0200 Subject: [PATCH 156/219] Revert "SDLSetMode: render immediately after resolution change to avoid 1-frame of texture presented at wrong size" This reverts commit 0e2ffdeb1dedfd9954ddd4897d8d180ead70a014. --- src/sdl/i_video.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 229008352..7393d8e4b 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1313,11 +1313,6 @@ static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen) texture = SDL_CreateTexture(renderer, sw_texture_format, SDL_TEXTUREACCESS_STREAMING, width, height); } - - if (graphics_started) - { - I_UpdateNoVsync(); - } } // -- 2.54.0 From 59470ddbd451a07074df3b5a87c612aff5cc382f Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 24 Oct 2025 14:24:08 +0200 Subject: [PATCH 157/219] fix oob access in D_SetupVote check if luamaps was set before --- src/d_netcmd.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index d62be9daa..92d9fb935 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2487,15 +2487,18 @@ void D_SetupVote(void) INT32 i; UINT8 gt = (cv_kartgametypepreference.value == -1) ? gametype : cv_kartgametypepreference.value; UINT8 secondgt = G_SometimesGetDifferentGametype(gt); - INT16 votebuffer[4] = {-1,-1,-1,0}; + INT16 votebuffer[4] = {-1,-1,-1, 0}; INT16 luamaps[4] = {0, 0, 0, 0}; LUA_HookSetupVote(luamaps, sizeof(luamaps)/sizeof(luamaps[0]), gt, secondgt); // Correct secondgt if needed - UINT8 typeoflevel = mapheaderinfo[luamaps[2]-1]->typeoflevel; - if (luamaps[2] && (typeoflevel & G_TOLFlag(secondgt&(~0x80))) == 0) - secondgt = ((typeoflevel & TOL_RACE) ? GT_RACE : GT_MATCH)|(secondgt&0x80); + if (luamaps[2]) + { + UINT8 typeoflevel = mapheaderinfo[luamaps[2]-1]->typeoflevel; + if ((typeoflevel & G_TOLFlag(secondgt&(~0x80))) == 0) + secondgt = ((typeoflevel & TOL_RACE) ? GT_RACE : GT_MATCH)|(secondgt&0x80); + } if (cv_kartencore.value && gt == GT_RACE) WRITEUINT8(p, (gt|0x80)); -- 2.54.0 From ba5b79e48a5dff68fae9b93112d4aee79373f1e3 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 24 Oct 2025 15:33:44 +0200 Subject: [PATCH 158/219] dont double print kitchen sink message to log we already handle this in HU_DoCEcho --- src/p_map.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 4a880ad42..9e428d999 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -708,7 +708,7 @@ static boolean PIT_CheckThing(mobj_t *thing) HU_SetCEchoFlags(0); HU_SetCEchoDuration(5); HU_DoCEcho(va("%s\\was hit by a kitchen sink.\\\\\\\\", player_names[thing->player-players])); - I_OutputMsg("%s was hit by a kitchen sink.\n", player_names[thing->player-players]); + //I_OutputMsg("%s was hit by a kitchen sink.\n", player_names[thing->player-players]); P_DamageMobj(thing, tmthing, tmthing->target, DMG_INSTAKILL); P_KillMobj(tmthing, thing, thing); } @@ -977,7 +977,7 @@ static boolean PIT_CheckThing(mobj_t *thing) HU_SetCEchoFlags(0); HU_SetCEchoDuration(5); HU_DoCEcho(va("%s\\was hit by a kitchen sink.\\\\\\\\", player_names[tmthing->player-players])); - I_OutputMsg("%s was hit by a kitchen sink.\n", player_names[tmthing->player-players]); + //I_OutputMsg("%s was hit by a kitchen sink.\n", player_names[tmthing->player-players]); P_DamageMobj(tmthing, thing, thing->target, DMG_INSTAKILL); P_KillMobj(thing, tmthing, tmthing); } -- 2.54.0 From 16a531272fa839d99ff8946d6ec68aa91485291b Mon Sep 17 00:00:00 2001 From: Indev Date: Fri, 24 Oct 2025 16:36:07 +0300 Subject: [PATCH 159/219] Skip repeating backslashes in HU_DoCEcho when printing to console --- src/hu_stuff.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 7f034f8ad..0e29a5124 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2855,8 +2855,20 @@ void HU_DoCEcho(const char *msg) strncpy(temp, cechotext, sizeof(temp)); for (char *p = temp; *p != '\0'; ++p) + { if (*p == '\\') + { *p = '\n'; + ++p; + char *skip_p = p; // Point at which we will move part of string after all \'s + + while (*p == '\\') + ++p; + + memmove(skip_p, p, strlen(p)+1); // move the rest of string with null byte + p = skip_p; // Restore p + } + } CONS_Printf("%s\n", temp); -- 2.54.0 From bb3dd435f02c63d6f35eb6ab9a922ab20322061a Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 24 Oct 2025 15:39:30 +0200 Subject: [PATCH 160/219] oop didnt mean to move this --- src/v_video.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/v_video.c b/src/v_video.c index dd5091fa1..031971326 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1935,6 +1935,7 @@ UINT8 *V_GetStringColormap(INT32 colorflags) void V_DrawCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed) { INT32 w, flags; + const UINT8 *colormap = V_GetStringColormap(c); flags = c & ~(V_CHARCOLORMASK | V_PARAMMASK); c &= 0x7f; @@ -1950,8 +1951,6 @@ void V_DrawCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed) if (x + w > vid.width) return; - const UINT8 *colormap = V_GetStringColormap(c); - if (colormap != NULL) V_DrawMappedPatch(x, y, flags, hu_font[c], colormap); else -- 2.54.0 From 26fc417555c83ff4665768e208d817c98cf22ed8 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 24 Oct 2025 16:09:43 +0200 Subject: [PATCH 161/219] forgor about localskin menu Zzz.... --- 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 a7be33c42..6eaccdce0 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -9643,7 +9643,7 @@ static void M_DrawLocalSkinMenu(void) //this is a very shitty solution for checking if a sprite needs flipping //but it works - if ((sprframe->lumppat[speenframe] == sprframe->lumppat[8-speenframe]) && (speenframe > 4)) + if ((speenframe > 4) && (sprframe->lumppat[speenframe] == sprframe->lumppat[8-speenframe])) { flags = V_FLIP; // This sprite is left/right flipped! } -- 2.54.0 From a69df8807dcb513d2324a2d5d42c20c89621b511 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 24 Oct 2025 21:56:52 +0200 Subject: [PATCH 162/219] fix some messed up whitespaces lel --- src/m_argv.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/m_argv.c b/src/m_argv.c index a3708d033..2ec1b188a 100644 --- a/src/m_argv.c +++ b/src/m_argv.c @@ -69,16 +69,18 @@ INT32 M_CheckProtoParam(const char *check) for (i = 1; i < myargc; i++) { - if (strncmp(myargv[i], "srb2kart://", 11) == 0) + if (strncmp(myargv[i], "srb2kart://", 11) == 0) { - if (strncmp(myargv[i]+11, check, strlen(check))==0) + if (strncmp(myargv[i]+11, check, strlen(check)) == 0) { found = i; return i; } } } + found = 0; + return 0; } @@ -93,7 +95,7 @@ const char *M_GetProtoParam(void) for (i = 1; i < myargc; i++) { - if (strncmp(myargv[i], "srb2kart://", 11) == 0) + if (strncmp(myargv[i], "srb2kart://", 11) == 0) { string = strchr(myargv[i], '/'); string = strchr(string+1, '/'); -- 2.54.0 From 28685ea6582221db9faadd60b3ab22da0d20eaf7 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 25 Oct 2025 20:38:51 +0200 Subject: [PATCH 163/219] fix some tooltips issues, wording and inconsistencies fbo also now supports from gl 2.1 --- src/m_menudefs.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/m_menudefs.c b/src/m_menudefs.c index e02113026..6bda9c733 100644 --- a/src/m_menudefs.c +++ b/src/m_menudefs.c @@ -968,16 +968,16 @@ static const char* OP_ExpTooltips[] = NULL, "How far Mobj interpolation should take effect.", "When weather is on this will cut the object amount used in half.", - "Sets minimum sector brightness, useful for dark areas", + "Sets minimum sector brightness, useful for dark areas.", //"Should the directional lightning be randomized each map?\nTakes effect on next map load.", "Toggle being able to see the sky.", - "Change the FPS counter sampling method\nInaccurate updates slower and might miss frame drops and such\nAccurate updates faster and is more accurate, but might be less readable", // how to ingles?? - "Skips rendering frames if game logic takes too long preventing issues during performance drops." // idk im shit as describing things + "Change the FPS counter sampling method\nInaccurate updates slower\nand might miss sudden framerate changes and drops,\nproviding a more averaged result.\nAccurate updates faster, but might be less readable.", // how to ingles?? + "Skips rendering frames if game logic takes too long\npreventing gameplay issues during performance drops.", // idk im shit as describing things "Different methods of scaling the votescreen backgrounds.", #ifdef HWRENDER "Should the game do Screen Textures? Provides a good boost to frames\nat the cost of some visual effects not working when disabled.", #ifdef USE_FBO_OGL - "Allows the game to downsample from a higher resolution than your display\nin OpenGL renderer mode. Requires a GPU with atleast OpenGL 3.0 support.", + "Allows the game to downsample from a higher resolution\nthan your display in OpenGL renderer mode.\nRequires a GPU with atleast OpenGL 2.1 support.", #endif "Change the bit depth of the Lookup Palette in Palette rendering mode\n 16 bits is like software looks ingame\nwhile 24 bits is how software looks in screenshots.", #endif @@ -1375,15 +1375,15 @@ static menuitem_t OP_Player4CamOptionsMenu[] = static const char* OP_PlayerCamOptionsTooltips[] = { NULL, - "Should the Camera flip on gravity flipped sections?.", + "Should the Camera flip on gravity flipped sections?", "Camera distance relative to the Player.", - "Height of the Camera", - "Pitch Camera on Upwards or Downhill Slopes", - "Speed of the Camera", - "Should looking back inherit the Players Momentum?\nEither inherit Player Momentum or double of it\nmay make looking back while boosting or going in high speed less jarring", + "Height of the Camera.", + "Pitch Camera on Upwards or Downhill Slopes.", + "Speed of the Camera.", + "Should looking back inherit the Players Momentum?\nEither inherit Player Momentum or double of it\nmay make looking back while boosting or going in high speed less jarring.", "Allows looking up/down by holding\naim forward/backward while standing still.", - "Speed of the Freecam/Spectator Camera", - "Toggle between Third or First Person camera", + "Speed of the Freecam/Spectator Camera.", + "Toggle between Third or First Person camera.", }; // Ok it's still called chatoptions but we'll put ping display in here to be clean @@ -1763,7 +1763,7 @@ static const char* OP_PlayerDistortTooltips[] = "Distance object rotation should be visable.", "Player rotation when sliptiding.", "Rotation of a player's boost trails and drift sparks.", - "Should banans rotate when thrown?\nAnd should they stay rotated when on the ground?.", + "Should banans rotate when thrown?\nAnd should they stay rotated when on the ground?", "Player squash and stretch.", "Player landing sound effect.", "Kart hopping while drifting. This is purely visual.", -- 2.54.0 From e26fb91350230a906e18d773d0ad4a91c75b81f1 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 25 Oct 2025 22:32:43 +0200 Subject: [PATCH 164/219] simplify vhs effect interpolation --- src/v_video.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/v_video.c b/src/v_video.c index 031971326..9805e910c 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1739,8 +1739,7 @@ void V_DrawHorizontallyScaledFullScreenPatch(patch_t *patch) void V_DrawVhsEffect(boolean rewind) { - fixed_t uby, dby; - static fixed_t upbary = 100*FRACUNIT, downbary = 150*FRACUNIT; + static fixed_t upbary = 100, downbary = 150; UINT8 barsize, updistort, downdistort; @@ -1761,21 +1760,19 @@ void V_DrawVhsEffect(boolean rewind) if (rewind) V_DrawVhsEffect(false); // experimentation - upbary -= renderdeltatics * (vid.dup * (rewind ? 3 : 1.8f)); - downbary += renderdeltatics * (vid.dup * (rewind ? 2 : 1)); + upbary -= FixedMul(vid.dup * (rewind ? 3 : 1.8f), renderdeltatics); + downbary += FixedMul(vid.dup * (rewind ? 2 : 1), renderdeltatics); - if (upbary < -barsize*FRACUNIT) - upbary = vid.height << FRACBITS; - if (downbary > vid.height << FRACBITS) - downbary = -barsize*FRACUNIT; + if (upbary < -barsize) + upbary = vid.height; - uby = upbary >> FRACBITS; - dby = downbary >> FRACBITS; + if (downbary > vid.height) + downbary = -barsize; #ifdef HWRENDER if (rendermode == render_opengl) { - HWR_RenderVhsEffect(uby, dby, updistort, downdistort, barsize); + HWR_RenderVhsEffect(upbary, downbary, updistort, downdistort, barsize); return; } #endif @@ -1795,16 +1792,16 @@ void V_DrawVhsEffect(boolean rewind) thismapstart = normalmapstart; offs = 0; - if (y >= uby && y < uby+barsize) + if (y >= upbary && y < upbary+barsize) { thismapstart -= (2<= dby && y < dby+barsize) + if (y >= downbary && y < downbary+barsize) { thismapstart -= (2< Date: Sun, 26 Oct 2025 14:04:38 +0100 Subject: [PATCH 165/219] drawspan: some type fixes, mark const and reordering --- src/r_draw_column.cpp | 2 +- src/r_draw_span.cpp | 25 +++++++++++-------------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/r_draw_column.cpp b/src/r_draw_column.cpp index 51690fbb0..67dbf94e3 100644 --- a/src/r_draw_column.cpp +++ b/src/r_draw_column.cpp @@ -260,7 +260,7 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) // texture has no height, so just go while (--count >= 0) { - *dest = R_DrawColumnPixel(dc, dest, frac>>FRACBITS, source, colormap); + *dest = R_DrawColumnPixel(dc, dest, (frac>>FRACBITS), source, colormap); dest += stride; frac += fracstep; diff --git a/src/r_draw_span.cpp b/src/r_draw_span.cpp index b1870685c..377115b64 100644 --- a/src/r_draw_span.cpp +++ b/src/r_draw_span.cpp @@ -208,15 +208,15 @@ static void R_CalcTiltedLighting(std::vector& lightbuffer, INT32 x1, INT3 for (i = x1; i <= x2; i++) { - fixed_t light = start >> FRACBITS; + const fixed_t light = start >> FRACBITS; lightbuffer[i] = CLAMP(light, 0, MAXLIGHTSCALE - 1); start += step; } } -static void R_GetTiltedLighting(std::vector& tiltlighting, const drawspandata_t* ds, const float iz, const int width, const INT32 stride) +static void R_GetTiltedLighting(std::vector& tiltlighting, const drawspandata_t* ds, const float iz, const INT32 width, const INT32 stride) { - float planelightfloat = PLANELIGHTFLOAT; + const float planelightfloat = PLANELIGHTFLOAT; const fixed_t lightstart = FloatToFixed(iz * planelightfloat); const fixed_t lightend = FloatToFixed((iz + ds->szp.x * width) * planelightfloat); @@ -232,7 +232,7 @@ static void R_GetTiltedLighting(std::vector& tiltlighting, const drawspan template static void R_DrawTiltedSpanTemplate(drawspandata_t* ds) { - int width = ds->x2 - ds->x1; + INT32 width = ds->x2 - ds->x1; float iz, uz, vz; UINT32 u, v; int i; @@ -246,7 +246,6 @@ static void R_DrawTiltedSpanTemplate(drawspandata_t* ds) UINT32 stepu, stepv; UINT32 bit; - INT32 x1 = ds->x1; const INT32 nflatxshift = ds->nflatxshift; const INT32 nflatyshift = ds->nflatyshift; const INT32 nflatmask = ds->nflatmask; @@ -300,7 +299,6 @@ static void R_DrawTiltedSpanTemplate(drawspandata_t* ds) izstep = ds->szp.x * SPANSIZE; uzstep = ds->sup.x * SPANSIZE; vzstep = ds->svp.x * SPANSIZE; - //x1 = 0; width++; while (width >= SPANSIZE) @@ -317,7 +315,7 @@ static void R_DrawTiltedSpanTemplate(drawspandata_t* ds) u = (INT64)(startu); v = (INT64)(startv); - x1 = ds->x1; + const INT32 x1 = ds->x1; for (i = 0; i < SPANSIZE; i++) { @@ -410,7 +408,7 @@ DEFINE_SPAN_COMBO(R_DrawTranslucentWaterSpan, DS_TRANSMAP|DS_RIPPLE) */ void R_DrawFogSpan(drawspandata_t* ds) { - INT32 count = ds->x2 - ds->x1 + 1; + intptr_t count = ds->x2 - ds->x1 + 1; const UINT8 * restrict colormap = ds->colormap; UINT8 * restrict dest = R_Address(ds->x1, ds->y); @@ -435,13 +433,12 @@ void R_DrawFogSpan(drawspandata_t* ds) void R_DrawFogSpan_Tilted(drawspandata_t* ds) { - int width = ds->x2 - ds->x1; - float iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); - UINT8 * restrict dest; - local_for_thread std::vector tiltlighting; - - dest = R_Address(ds->x1, ds->y); + INT32 width = ds->x2 - ds->x1; const INT32 stride = vid.width; + const float iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); + UINT8 * restrict dest = R_Address(ds->x1, ds->y); + + local_for_thread std::vector tiltlighting; // Lighting is simple. It's just linear interpolation from start to end R_GetTiltedLighting(tiltlighting, ds, iz, width, stride); -- 2.54.0 From 056f919bbeae8d068b854c1c1675d3062623dd36 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 27 Oct 2025 00:50:30 +0100 Subject: [PATCH 166/219] DrawTiltedSpan: more micro optimize - do pointerdiff outside the loops, no need to do them 16 times per span - cache tiltilighting and planezlight, mark as const and restrict --- src/r_draw_span.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/r_draw_span.cpp b/src/r_draw_span.cpp index 377115b64..11415d2d5 100644 --- a/src/r_draw_span.cpp +++ b/src/r_draw_span.cpp @@ -262,6 +262,11 @@ static void R_DrawTiltedSpanTemplate(drawspandata_t* ds) const UINT8 * restrict source = ds->source; const UINT8 * restrict colormap = ds->colormap; + const ptrdiff_t colormap_diff = (colormap - colormaps); + + const INT32 * restrict tiltlight = tiltlighting.data(); + lighttable_t * const * restrict planezlight = ds->planezlight; + if constexpr (Type & DS_RIPPLE) { dsrc = vid.screens[1] + (ds->y + ds->bgofs) * stride + ds->x1; @@ -320,7 +325,7 @@ static void R_DrawTiltedSpanTemplate(drawspandata_t* ds) for (i = 0; i < SPANSIZE; i++) { bit = (((v + stepv * i) >> nflatyshift) & nflatmask) | ((u + stepu * i) >> nflatxshift); - colormap = ds->planezlight[tiltlighting[x1 + i]] + (ds->colormap - colormaps); + colormap = planezlight[tiltlight[x1 + i]] + colormap_diff; if constexpr (Type & DS_RIPPLE) dest[i] = R_DrawSpanPixel(ds, &dsrc[i], colormap, bit, source); else @@ -343,7 +348,7 @@ static void R_DrawTiltedSpanTemplate(drawspandata_t* ds) u = (INT64)(startu); v = (INT64)(startv); bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); - colormap = ds->planezlight[tiltlighting[ds->x1]] + (ds->colormap - colormaps); + colormap = planezlight[tiltlight[ds->x1]] + colormap_diff; if constexpr (Type & DS_RIPPLE) *dest = R_DrawSpanPixel(ds, dsrc, colormap, bit, source); else @@ -369,7 +374,7 @@ static void R_DrawTiltedSpanTemplate(drawspandata_t* ds) for (; width != 0; width--) { bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); - colormap = ds->planezlight[tiltlighting[ds->x1]] + (ds->colormap - colormaps); + colormap = planezlight[tiltlight[ds->x1]] + colormap_diff; if constexpr (Type & DS_RIPPLE) *dest = R_DrawSpanPixel(ds, dsrc, colormap, bit, source); else @@ -437,15 +442,19 @@ void R_DrawFogSpan_Tilted(drawspandata_t* ds) const INT32 stride = vid.width; const float iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); UINT8 * restrict dest = R_Address(ds->x1, ds->y); + const ptrdiff_t colormap_diff = (ds->colormap - colormaps); local_for_thread std::vector tiltlighting; // Lighting is simple. It's just linear interpolation from start to end R_GetTiltedLighting(tiltlighting, ds, iz, width, stride); + const INT32 * restrict tiltlight = tiltlighting.data(); + lighttable_t * const * restrict planezlight = ds->planezlight; + do { - UINT8 *colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); + UINT8 *colormap = planezlight[tiltlight[ds->x1++]] + colormap_diff; *dest = colormap[*dest]; dest++; } -- 2.54.0 From 509e7140e3ba7144832fcf60f06bc49fcfdfb730 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 27 Oct 2025 21:20:39 +0100 Subject: [PATCH 167/219] use strlcpy for filling playerinfo names MAXPLAYERNAME+1 so it copies 21 and null terminates the last --- src/d_clisrv.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 61afc0eb7..a88954867 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1656,12 +1656,7 @@ static void SV_SendPlayerInfo(INT32 node) netbuffer->u.playerinfo[i].node = i; - // Can't really change this because net compatibility, but the warning is annoying -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstringop-truncation" - strncpy(netbuffer->u.playerinfo[i].name, (const char *)&player_names[i], MAXPLAYERNAME+1); -#pragma GCC diagnostic pop - netbuffer->u.playerinfo[i].name[MAXPLAYERNAME] = '\0'; + strlcpy(netbuffer->u.playerinfo[i].name, (const char *)&player_names[i], MAXPLAYERNAME+1); //fetch IP address //No, don't do that, you fuckface. -- 2.54.0 From 88363cf45d819047f93f9656909620c781e4a206 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 27 Oct 2025 22:58:42 +0100 Subject: [PATCH 168/219] add NOHOLEPUNCH flag to disable holepunch entirely --- src/Makefile | 1 + src/Makefile.d/features.mk | 3 ++- src/doomdef.h | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index d7a8345cd..0456990f3 100644 --- a/src/Makefile +++ b/src/Makefile @@ -49,6 +49,7 @@ # Already enabled by default for 32-bit # Windows. # NOCURL=1 - Disable libcurl--HTTP capability. +# NOHOLEPUNCH=1 - Disable holepunch capability. # NOLIBGME=1 - Disable game music emu, retro VGM support. # NOOPENMPT=1 - Disable module (tracker) music support. # NOMIXER=1 - Disable SDL Mixer (audio playback). diff --git a/src/Makefile.d/features.mk b/src/Makefile.d/features.mk index fc1e8b69f..b191ae2c1 100644 --- a/src/Makefile.d/features.mk +++ b/src/Makefile.d/features.mk @@ -6,7 +6,8 @@ passthru_opts+=\ NOHW NOMD5 NOPOSTPROCESSING\ MOBJCONSISTANCY PACKETDROP ZDEBUG\ HAVE_MINIUPNPC\ - HAVE_DISCORDRPC DEVELOP + HAVE_DISCORDRPC DEVELOP\ + NOHOLEPUNCH\ # build with debugging information ifdef DEBUGMODE diff --git a/src/doomdef.h b/src/doomdef.h index 00b4bc1f0..a0c76fa61 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -651,7 +651,9 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; #if defined (HAVE_CURL) #define MASTERSERVER +#ifndef NOHOLEPUNCH #define HOLEPUNCH +#endif #else #undef UPDATE_ALERT #endif -- 2.54.0 From 908bba2c8a3b35a872398600ab6c65452d2785b9 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 28 Oct 2025 00:11:49 +0100 Subject: [PATCH 169/219] rename subsector variable in P_TryCameraMove to be more descriptive --- src/p_map.c | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 9e428d999..c24e338af 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2189,7 +2189,7 @@ static boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam) // boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam) { - subsector_t *s; + subsector_t *subsec; UINT8 i; floatok = false; @@ -2198,9 +2198,9 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam) return false; if (thiscam->x != x || thiscam->y != y || thiscam->subsector == NULL) - s = R_PointInSubsectorFast(x, y); + subsec = R_PointInSubsectorFast(x, y); else - s = thiscam->subsector; + subsec = thiscam->subsector; if (players[displayplayers[0]].mo) { @@ -2220,7 +2220,7 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam) thiscam->ceilingz = thiscam->z + thiscam->height; thiscam->x = x; thiscam->y = y; - thiscam->subsector = s; + thiscam->subsector = subsec; return true; } } @@ -2232,6 +2232,7 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam) tryx -= MAXRADIUS; else tryx = x; + if (y-tryy > MAXRADIUS) tryy += MAXRADIUS; else if (y-tryy < -MAXRADIUS) @@ -2249,14 +2250,14 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam) if (tmceilingz - thiscam->z < thiscam->height) { - if (s == thiscam->subsector && tmceilingz >= thiscam->z) + if (subsec == thiscam->subsector && tmceilingz >= thiscam->z) { floatok = true; thiscam->floorz = tmfloorz; thiscam->ceilingz = tmfloorz + thiscam->height; thiscam->x = x; thiscam->y = y; - thiscam->subsector = s; + thiscam->subsector = subsec; return true; } else @@ -2281,7 +2282,7 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam) thiscam->ceilingz = tmceilingz; thiscam->x = x; thiscam->y = y; - thiscam->subsector = s; + thiscam->subsector = subsec; return true; } @@ -2394,6 +2395,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) tryx -= radius; else tryx = x; + if (y-tryy > radius) tryy += radius; else if (y-tryy < -radius) @@ -2425,12 +2427,15 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) } if (thing->type == MT_SKIM) + { maxstep = 0; + } if (tmceilingz - tmfloorz < thing->height) { if (tmfloorthing) tmhitthing = tmfloorthing; + return false; // doesn't fit } @@ -2489,10 +2494,14 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) if (thing->eflags & MFE_VERTICALFLIP) { if (tmdrpoffceilz - tmceilingz > maxstep) + { return false; + } } else if (tmfloorz - tmdropoffz > maxstep) + { return false; // don't stand over a dropoff + } } } } while (tryx != x || tryy != y); @@ -2568,6 +2577,7 @@ boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y) tryx = thing->x; tryy = thing->y; + do { if (x-tryx > MAXRADIUS) tryx += MAXRADIUS; @@ -2575,6 +2585,7 @@ boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y) tryx -= MAXRADIUS; else tryx = x; + if (y-tryy > MAXRADIUS) tryy += MAXRADIUS; else if (y-tryy < -MAXRADIUS) @@ -2928,6 +2939,7 @@ static boolean PTR_SlideTraverse(intercept_t *in) { if (P_PointOnLineSide(slidemo->x, slidemo->y, li)) return true; // don't hit the back side + goto isblocking; } @@ -3346,10 +3358,12 @@ void P_BouncePlayerMove(mobj_t *mo) { mobj_t *fx = P_SpawnMobj(mo->x, mo->y, mo->z, MT_BUMP); + if (mo->eflags & MFE_VERTICALFLIP) fx->eflags |= MFE_VERTICALFLIP; else fx->eflags &= ~MFE_VERTICALFLIP; + fx->scale = mo->scale; S_StartSound(mo, sfx_s3k49); @@ -3363,7 +3377,8 @@ void P_BouncePlayerMove(mobj_t *mo) mo->player->cmomx = tmxmove; mo->player->cmomy = tmymove; - if (!P_TryMove(mo, mo->x + tmxmove, mo->y + tmymove, true)) { + if (!P_TryMove(mo, mo->x + tmxmove, mo->y + tmymove, true)) + { P_TryMove(mo, mo->x - oldmomx, mo->y - oldmomy, true); } } @@ -3740,6 +3755,7 @@ boolean P_CheckSector(sector_t *sector, boolean crunch) { size_t i; sector_t *sec; + for (i = 0; i < sector->numattached; i++) { sec = §ors[sector->attached[i]]; @@ -3946,6 +3962,7 @@ static msecnode_t *P_DelSecnode(msecnode_t *node) tp = node->m_sectorlist_prev; tn = node->m_sectorlist_next; + if (tp) tp->m_sectorlist_next = tn; if (tn) @@ -3956,6 +3973,7 @@ static msecnode_t *P_DelSecnode(msecnode_t *node) sp = node->m_thinglist_prev; sn = node->m_thinglist_next; + if (sp) sp->m_thinglist_next = sn; else @@ -4003,7 +4021,7 @@ static inline boolean PIT_GetSectors(line_t *ld) // allowed to move to this position, then the sector_list // will be attached to the Thing's mobj_t at touching_sectorlist. - sector_list = P_AddSecnode(ld->frontsector,tmthing,sector_list); + sector_list = P_AddSecnode(ld->frontsector, tmthing, sector_list); // Don't assume all lines are 2-sided, since some Things // like MT_TFOG are allowed regardless of whether their radius takes -- 2.54.0 From 694a8eeb69f3e8e92d48cdea204599161508bbfd Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 28 Oct 2025 00:47:12 +0100 Subject: [PATCH 170/219] P_TryMove: save one R_PointInSubsector call per player by reusing the special sector calculated earlier, this didnt change for when its checked another time also one fixedmul in P_SceneryTryMove in some cases --- src/p_map.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index c24e338af..aea01c6a7 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2411,19 +2411,22 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) { //All things are affected by their scale. fixed_t maxstep = FixedMul(MAXSTEPMOVE, mapobjectscale); + INT32 special = 0; if (thing->player) { - const INT32 special = GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1); + special = GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1); // If using type Section1:13, double the maxstep. - if (P_PlayerTouchingSectorSpecial(thing->player, 1, 13) - || special == 13) + if (P_PlayerTouchingSectorSpecial(thing->player, 1, 13) || special == 13) + { maxstep <<= 1; + } // If using type Section1:12, no maxstep. For ledges you don't want the player to climb! (see: Egg Zeppelin & SMK port walls) - else if (P_PlayerTouchingSectorSpecial(thing->player, 1, 12) - || special == 12) + else if (P_PlayerTouchingSectorSpecial(thing->player, 1, 12) || special == 12) + { maxstep = 0; + } } if (thing->type == MT_SKIM) @@ -2468,11 +2471,8 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) return false; // mobj must lower itself to fit } } - else if (maxstep > 0 && !( - thing->player && ( - P_PlayerTouchingSectorSpecial(thing->player, 1, 14) - || GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 14) - )) // Step down + else if (maxstep > 0 && !(thing->player && + (P_PlayerTouchingSectorSpecial(thing->player, 1, 14) || special == 14))) // Step down { // If the floor difference is MAXSTEPMOVE or less, and the sector isn't Section1:14, ALWAYS // step down! Formerly required a Section1:13 sector for the full MAXSTEPMOVE, but no more. @@ -2598,14 +2598,14 @@ boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y) if (!(thing->flags & MF_NOCLIP)) { - const fixed_t maxstep = FixedMul(MAXSTEPMOVE, mapobjectscale); - if (tmceilingz - tmfloorz < thing->height) return false; // doesn't fit if (tmceilingz - thing->z < thing->height) return false; // mobj must lower itself to fit + const fixed_t maxstep = FixedMul(MAXSTEPMOVE, mapobjectscale); + if (tmfloorz - thing->z > maxstep) return false; // too big a step up } -- 2.54.0 From 45ee50b47d02fd64e64c8f6c2ae475e538ed22e6 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 28 Oct 2025 01:21:26 +0100 Subject: [PATCH 171/219] remove reduntant stuff from D_ClearState and G_StopDemo we only need R_ExecuteSetViewSize from splitscreen_onchange, the rest doesent do anything due to SV_StopServer call earlier setting cl_mode to CL_ABORTED SV_StopServer also calls Y_EndIntermission and Y_EndVote if necessary --- src/d_main.c | 22 +++------------------- src/g_demo.c | 5 ----- 2 files changed, 3 insertions(+), 24 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index d4cef24c3..ca2ffa4f7 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -954,24 +954,6 @@ void D_SRB2Loop(void) // D_SRB2Main // ========================================================================= -static void ResetSplitScreen(void) -{ - UINT8 i; - - // recompute screen size - R_ExecuteSetViewSize(); - - if (!demo.playback && !botingame) - { - for (i = 1; i < MAXSPLITSCREENPLAYERS; i++) - { - if (i > splitscreen) - CL_RemoveSplitscreenPlayer(displayplayers[i]); - else - CL_AddSplitscreenPlayer(); - } - } -} // // D_ClearState // @@ -992,7 +974,9 @@ void D_ClearState(void) CL_ClearPlayer(i); splitscreen = 0; - ResetSplitScreen(); // splitscreen onchange resets us to singleplayer :chaosleep: + + // recompute screen size + R_ExecuteSetViewSize(); botingame = false; botskin = 0; diff --git a/src/g_demo.c b/src/g_demo.c index 96ff33e65..bd3905160 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -3494,11 +3494,6 @@ void G_StopDemo(void) demo.rewinding = false; CL_ClearRewinds(); - if (gamestate == GS_INTERMISSION) - Y_EndIntermission(); // cleanup - if (gamestate == GS_VOTING) - Y_EndVote(); - D_ClearState(); } -- 2.54.0 From db2062ed1d3552728741a88a502dfdd357e2f254 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 29 Oct 2025 15:59:25 +0100 Subject: [PATCH 172/219] some i_tcp fixes - SOCK_Get return true when receiving good packet from a lan player - SOCK_GetAddr fix handling of ipv6 addresses, so ipv6 servers can be found in the serverlist taken from srb2/classic --- src/d_net.c | 5 ++--- src/i_tcp.c | 52 ++++++++++++++++++++++++++-------------------------- 2 files changed, 28 insertions(+), 29 deletions(-) diff --git a/src/d_net.c b/src/d_net.c index 05df1320c..61492f2a8 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -1127,9 +1127,7 @@ boolean HGetPacket(void) while (true) { - I_NetGet(); - - if (doomcom->remotenode == -1) // No packet received + if (!I_NetGet()) // No packets received return false; getbytes += packetheaderlength + doomcom->datalength; // For stat @@ -1165,6 +1163,7 @@ boolean HGetPacket(void) GotAcks(); continue; } + doomcom->datalength -= BASEPACKETSIZE; break; } diff --git a/src/i_tcp.c b/src/i_tcp.c index 09cba908f..2690bbc7e 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -28,14 +28,14 @@ #endif #ifdef _WIN32 -#define USE_WINSOCK + #define USE_WINSOCK #endif //WIN32 OS #ifdef USE_WINSOCK -#include -#define addrinfo_t ADDRINFOA + #include + #define addrinfo_t ADDRINFOA #else -#define addrinfo_t struct addrinfo + #define addrinfo_t struct addrinfo #endif #include "doomdef.h" @@ -148,16 +148,16 @@ static UINT8 UPNP_support = TRUE; #define DEFAULTPORT "5029" -#if defined (USE_WINSOCK) -typedef SOCKET SOCKET_TYPE; -#define ERRSOCKET (SOCKET_ERROR) +#ifdef USE_WINSOCK + typedef SOCKET SOCKET_TYPE; + #define ERRSOCKET (SOCKET_ERROR) #else -#if defined (__unix__) || defined (__APPLE__) || defined (__HAIKU__) -typedef int SOCKET_TYPE; -#else -typedef unsigned long SOCKET_TYPE; -#endif -#define ERRSOCKET (-1) + #if defined (__unix__) || defined (__APPLE__) || defined (__HAIKU__) + typedef int SOCKET_TYPE; + #else + typedef unsigned long SOCKET_TYPE; + #endif + #define ERRSOCKET (-1) #endif #define IPV6_MULTICAST_ADDRESS "ff15::57e1:1a12" @@ -345,17 +345,15 @@ static const char *SOCK_AddrToStr(mysockaddr_t *sk) { static char s[64]; // 255.255.255.255:65535 or // [ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535 - #ifdef HAVE_IPV6 int v6 = (sk->any.sa_family == AF_INET6); #else int v6 = 0; #endif - void *addr; int e = 0; // save error code so it can't be modified later code and avoid calling WSAGetLastError() more then once - if(sk->any.sa_family == AF_INET) + if (sk->any.sa_family == AF_INET) addr = &sk->ip4.sin_addr; #ifdef HAVE_IPV6 else if(sk->any.sa_family == AF_INET6) @@ -364,9 +362,11 @@ static const char *SOCK_AddrToStr(mysockaddr_t *sk) else addr = NULL; - if(addr == NULL) + if (addr == NULL) + { sprintf(s, "No address"); - else if(inet_ntop(sk->any.sa_family, addr, &s[v6], sizeof (s) - v6) == NULL) + } + else if (inet_ntop(sk->any.sa_family, addr, &s[v6], sizeof (s) - v6) == NULL) { e = errno; sprintf(s, "Unknown family type, error #%u: %s", e, strerror(e)); @@ -381,7 +381,7 @@ static const char *SOCK_AddrToStr(mysockaddr_t *sk) strcat(s, va(":%d", ntohs(sk->ip6.sin6_port))); } #endif - else if(sk->any.sa_family == AF_INET && sk->ip4.sin_port != 0) + else if (sk->any.sa_family == AF_INET && sk->ip4.sin_port != 0) strcat(s, va(":%d", ntohs(sk->ip4.sin_port))); return s; @@ -481,7 +481,6 @@ static boolean SOCK_cmpaddr(mysockaddr_t *a, mysockaddr_t *b, UINT8 mask) return false; } - // This is a hack. For some reason, nodes aren't being freed properly. // This goes through and cleans up what nodes were supposed to be freed. /** \warning This function causes the file downloading to stop if someone joins. @@ -636,7 +635,7 @@ static boolean SOCK_Get(void) c = recvfrom(mysockets[n], (char *)&doomcom->data, MAXPACKETLENGTH, 0, (void *)&fromaddress, &fromlen); - if (c > 0) + if (c != ERRSOCKET) { #ifdef USE_STUN if (STUN_got_response(doomcom->data, c)) @@ -652,20 +651,21 @@ static boolean SOCK_Get(void) #endif // find remote node number - for (j = 1; j <= MAXNETNODES; j++) //include LAN + for (j = 1; j <= MAXNETNODES; j++) // include LAN { if (SOCK_cmpaddr(&fromaddress, &clientaddress[j], 0)) { doomcom->remotenode = (INT16)j; // good packet from a game player doomcom->datalength = (INT16)c; nodesocket[j] = mysockets[n]; - return false; + return true; } } // not found // find a free slot j = getfreenode(); + if (j > 0) { const time_t curTime = time(NULL); @@ -1269,7 +1269,7 @@ void I_ShutdownTcpDriver(void) init_tcp_driver = false; } -static boolean SOCK_GetAddr(struct sockaddr_in *sin, const char *address, const char *port, boolean test) +static boolean SOCK_GetAddr(mysockaddr_t *sin, const char *address, const char *port, boolean test) { addrinfo_t *ai = NULL, *runp, hints; int gaie; @@ -1330,7 +1330,7 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port) if (newnode != -1) { - if (!SOCK_GetAddr(&clientaddress[newnode].ip4, address, port, true)) + if (!SOCK_GetAddr(&clientaddress[newnode], address, port, true)) { nodeconnected[newnode] = false; return -1; @@ -1358,7 +1358,7 @@ static void rendezvous(int size) if (tic != refreshtic) { - if (SOCK_GetAddr(&rzv.ip4, host, (port ? port : "7777"), false)) + if (SOCK_GetAddr(&rzv, host, (port ? port : "7777"), false)) { refreshtic = tic; } -- 2.54.0 From cb5c4e482e95e646c68fd0ab80f8a00e4371199c Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 29 Oct 2025 16:24:44 +0100 Subject: [PATCH 173/219] SOCK_GetAddr: freeaddrinfo does not need to be called on getaddrinfo failure --- src/i_tcp.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/i_tcp.c b/src/i_tcp.c index 2690bbc7e..18c20dd5d 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -1271,7 +1271,7 @@ void I_ShutdownTcpDriver(void) static boolean SOCK_GetAddr(mysockaddr_t *sin, const char *address, const char *port, boolean test) { - addrinfo_t *ai = NULL, *runp, hints; + addrinfo_t *ai, *runp, hints; int gaie; size_t i; @@ -1287,10 +1287,7 @@ static boolean SOCK_GetAddr(mysockaddr_t *sin, const char *address, const char * gaie = getaddrinfo(address, port, &hints, &ai); if (gaie != 0) - { - freeaddrinfo(ai); return false; - } runp = ai; -- 2.54.0 From 129f88b6a779b9e618a1c9ac8f82f8015bd44606 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Tue, 28 Oct 2025 23:01:02 +0100 Subject: [PATCH 174/219] Fix buffer underflow when querying invalid nodes --- src/i_tcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i_tcp.c b/src/i_tcp.c index 18c20dd5d..b58c134c1 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -752,7 +752,7 @@ static void SOCK_Send(void) int e = 0; // save error code so it can't be modified later code and avoid calling WSAGetLastError() more then once size_t i, j; - if (!nodeconnected[doomcom->remotenode]) + if (doomcom->remotenode < 0 || !nodeconnected[doomcom->remotenode]) return; if (doomcom->remotenode == BROADCASTADDR) -- 2.54.0 From 24895874ed840a0a5a52d8a31fb143994d976854 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 29 Oct 2025 22:53:09 +0100 Subject: [PATCH 175/219] UDP_Bind: check socket send buffer size aswell if to small than adjust, like receive buffer --- src/i_tcp.c | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/src/i_tcp.c b/src/i_tcp.c index b58c134c1..531db4ab9 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -970,7 +970,7 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen e = errno; I_OutputMsg("getting SO_RCVBUF failed: #%u, %s\n", e, strerror(e)); } - CONS_Printf(M_GetText("Network system buffer: %dKb\n"), opt>>10); + CONS_Printf(M_GetText("Network receive buffer: %dKb\n"), opt>>10); if (opt < 64<<10) // 64k { @@ -991,9 +991,44 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen } if (opt < 64<<10) - CONS_Alert(CONS_WARNING, M_GetText("Can't set buffer length to 64k, file transfer will be bad\n")); + CONS_Alert(CONS_WARNING, M_GetText("Can't set receive buffer length to 64k, file transfer will be bad\n")); else - CONS_Printf(M_GetText("Network system buffer set to: %dKb\n"), opt>>10); + CONS_Printf(M_GetText("Network receive buffer set to: %dKb\n"), opt>>10); + } + + opt = 0; + opts = (socklen_t)sizeof(opt); + rc = getsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&opt, &opts); + if (rc <= -1) + { + e = errno; + I_OutputMsg("getting SO_SNDBUF failed: #%u, %s\n", e, strerror(e)); + } + CONS_Printf(M_GetText("Network send buffer: %dKb\n"), opt>>10); + + if (opt < 64<<10) // 64k + { + opt = 64<<10; + opts = (socklen_t)sizeof(opt); + rc = setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&opt, opts); + if (rc <= -1) + { + e = errno; + I_OutputMsg("setting SO_SNDBUF to %dKb failed: #%u, %s\n", opt>>10, e, strerror(e)); + } + + opt = 0; + rc = getsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&opt, &opts); + if (rc <= -1) + { + e = errno; + I_OutputMsg("getting SO_SNDBUF failed: #%u, %s\n", e, strerror(e)); + } + + if (opt < 64<<10) + CONS_Alert(CONS_WARNING, M_GetText("Can't set send buffer length to 64k, file transfer will be bad\n")); + else + CONS_Printf(M_GetText("Network send system buffer set to: %dKb\n"), opt>>10); } rc = getsockname(s, &straddr.any, &len); -- 2.54.0 From f34a47c50d9554318ba992da779537dbdd08e30d Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 31 Oct 2025 02:01:30 +0100 Subject: [PATCH 176/219] HWR_PrecacheLevelFlats: only run flat encore case when having an "encoremap" not when its just encore mode might save some time on some maps, as we dont need to check for remapping --- src/hardware/hw_cache.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index edbd83b77..339cce3f9 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -603,7 +603,7 @@ static void HWR_PrecacheLevelFlats(void) // special case for encore #ifdef GLENCORE - if (encoremode) + if (encoremap) { // go through all sectors to determine if it should be remapped for encore for (i = 0; i < numsectors; i++) @@ -678,8 +678,6 @@ static void HWR_PrecacheLevelTextures(void) const line_t *line = &lines[i]; #ifdef GLENCORE const int noencoremap = ((encoremap && (line->flags & ML_TFERLINE)) ? 2 : 1); -#else - const int noencoremap = 1; #endif // two sides for (j = 0; j < 2; j++) @@ -695,11 +693,14 @@ static void HWR_PrecacheLevelTextures(void) for (f = 0; f < 3; f++) { const INT32 texnum = sidetex[f]; + if (texnum < 0 || texnum >= numtextures || texturepresent[texnum]) continue; - +#ifdef GLENCORE texturepresent[texnum] = 1|noencoremap; - +#else + texturepresent[texnum] = 1; +#endif HWR_GetTexture(texnum, false); #ifdef GLENCORE if (noencoremap & 2) -- 2.54.0 From 36c43d89e6454dc05078bd77ab551758e894b6fe Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 31 Oct 2025 02:20:53 +0100 Subject: [PATCH 177/219] GL encore: use struct for encore texture handling struct with two sets of maptextures, one for normal another for encore textures functionally identical, hopefully also performancewise more explicit than doing this with just one set and indexing stuff :bloblcatpats: --- src/hardware/hw_cache.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 339cce3f9..e58169e14 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -437,8 +437,16 @@ void HWR_MakePatch(const patch_t *patch, GLPatch_t *glPatch, GLMipmap_t *glMipma // CACHING HANDLING // ================================================= +typedef struct +{ + GLMapTexture_t normal; +#ifdef GLENCORE + GLMapTexture_t encore; +#endif +} GLMapTextureSet_t; // idk i suck at naming things + static size_t gl_numtextures = 0; // Texture count -static GLMapTexture_t *gl_textures; // For all textures +static GLMapTextureSet_t *gl_textures; // For all textures static void HWR_FreeTextureData(patch_t *patch) { @@ -578,13 +586,12 @@ void HWR_FreeMapTextures(void) { size_t i; -#ifdef GLENCORE - for (i = 0; i < gl_numtextures*2; i++) -#else for (i = 0; i < gl_numtextures; i++) -#endif { - FreeMapTexture(&gl_textures[i]); + FreeMapTexture(&gl_textures[i].normal); +#ifdef GLENCORE + FreeMapTexture(&gl_textures[i].encore); +#endif } // now the heap don't have any 'user' pointing to our @@ -824,11 +831,8 @@ void HWR_LoadMapTextures(size_t pnumtextures) HWR_FreeMapTextures(); gl_numtextures = pnumtextures; -#ifdef GLENCORE - gl_textures = calloc(gl_numtextures, sizeof (*gl_textures)*2); // *2 - 1 for encore-remapped texture and another for noencore texture (unused when not in encore) -#else - gl_textures = calloc(gl_numtextures, sizeof (*gl_textures)); -#endif + gl_textures = calloc(gl_numtextures, sizeof(*gl_textures)); // *2 - 1 for encore-remapped texture and another for noencore texture (unused when not in encore), see: GLMapTextureSet_t + if (gl_textures == NULL) I_Error("HWR_LoadMapTextures: ran out of memory for OpenGL textures. Sad!"); } @@ -852,7 +856,7 @@ GLMapTexture_t *HWR_GetTexture(INT32 tex, boolean noencore) // Every texture in memory, stored in the // hardware renderer's bit depth format. Wow! #ifdef GLENCORE - gltex = &gl_textures[tex*2 + (encoremap && !noencore ? 0 : 1)]; + gltex = (encoremap && !noencore) ? &gl_textures[tex].encore : &gl_textures[tex].normal; #else gltex = &gl_textures[tex]; #endif -- 2.54.0 From e45c72f5253b3b14d5f6174caacbbaa011564dca Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 5 Nov 2023 18:50:33 +0000 Subject: [PATCH 178/219] SV_StopServer: Use G_SetGamestate instead of a direct write An apparent oversight identified while working on the previous commit. --- src/d_clisrv.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index a88954867..ef4112018 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -4649,7 +4649,9 @@ void SV_StopServer(void) Y_EndIntermission(); if (gamestate == GS_VOTING) Y_EndVote(); - gamestate = wipegamestate = GS_NULL; + + G_SetGamestate(GS_NULL); + wipegamestate = GS_NULL; for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) localtextcmd[i][0] = 0; -- 2.54.0 From 03de30df3e2b10ba072c50f3c7622738e2958d06 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 1 Nov 2025 03:00:19 +0100 Subject: [PATCH 179/219] SV_StopServer: reset textcmdbuf fixes an issue where in some rare cases, the game may get stuck in a weird limbo state due to the text command buffer being full and never be cleared, so net commands can never be executed --- src/d_clisrv.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index ef4112018..aed5ee347 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -4654,8 +4654,17 @@ void SV_StopServer(void) wipegamestate = GS_NULL; for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { localtextcmd[i][0] = 0; + while (textcmdbuf[i] != NULL) + { + textcmdbuf_t *buf = textcmdbuf[i]; + textcmdbuf[i] = textcmdbuf[i]->next; + Z_Free(buf); + } + } + for (i = firstticstosend; i < firstticstosend + BACKUPTICS; i++) D_Clearticcmd(i); -- 2.54.0 From ae306351ba469682f345339e74922bbc2dd1bec8 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 1 Nov 2025 16:25:43 +0100 Subject: [PATCH 180/219] add cv_precachetextures to advanced video options --- src/m_menudefs.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/m_menudefs.c b/src/m_menudefs.c index 6bda9c733..6633085bf 100644 --- a/src/m_menudefs.c +++ b/src/m_menudefs.c @@ -944,21 +944,23 @@ static menuitem_t OP_ExpOptionsMenu[] = {IT_STRING | IT_CVAR, NULL, "Skyboxes", &cv_skybox, 40}, - {IT_STRING | IT_CVAR, NULL, "FPS counter sampling", &cv_accuratefps, 50}, + {IT_STRING | IT_CVAR, NULL, "Precache Level Textures", &cv_precachetextures, 50}, - {IT_STRING | IT_CVAR, NULL, "Frameskip", &cv_frameskip, 60}, + {IT_STRING | IT_CVAR, NULL, "FPS counter sampling", &cv_accuratefps, 60}, - {IT_STRING | IT_CVAR, NULL, "Votescreen Scaling", &cv_votebgscaling, 70}, + {IT_STRING | IT_CVAR, NULL, "Frameskip", &cv_frameskip, 70}, + + {IT_STRING | IT_CVAR, NULL, "Votescreen Scaling", &cv_votebgscaling, 80}, #ifdef HWRENDER - {IT_STRING | IT_CVAR, NULL, "Screen Textures", &cv_glscreentextures, 80}, + {IT_STRING | IT_CVAR, NULL, "Screen Textures", &cv_glscreentextures, 90}, #ifdef USE_FBO_OGL - {IT_STRING | IT_CVAR, NULL, "FBO Downsampling support", &cv_glframebuffer, 85}, - {IT_STRING | IT_CVAR, NULL, "Palette Depth", &cv_glpalettedepth, 95}, - {IT_DISABLED, NULL, "", NULL, 105}, // dummy text + {IT_STRING | IT_CVAR, NULL, "FBO Downsampling support", &cv_glframebuffer, 95}, + {IT_STRING | IT_CVAR, NULL, "Palette Depth", &cv_glpalettedepth, 105}, + {IT_DISABLED, NULL, "", NULL, 115}, // dummy text #else - {IT_STRING | IT_CVAR, NULL, "Palette Depth", &cv_glpalettedepth, 90}, - {IT_DISABLED, NULL, "", NULL, 100}, // dummy text + {IT_STRING | IT_CVAR, NULL, "Palette Depth", &cv_glpalettedepth, 100}, + {IT_DISABLED, NULL, "", NULL, 110}, // dummy text #endif #endif }; @@ -971,6 +973,7 @@ static const char* OP_ExpTooltips[] = "Sets minimum sector brightness, useful for dark areas.", //"Should the directional lightning be randomized each map?\nTakes effect on next map load.", "Toggle being able to see the sky.", + "Preload all level textures on level load.\nMassively reduces texture related stuttering during gameplay\nat the cost of longer level loading times.\nDisable this if you experience timeouts during level switches.", "Change the FPS counter sampling method\nInaccurate updates slower\nand might miss sudden framerate changes and drops,\nproviding a more averaged result.\nAccurate updates faster, but might be less readable.", // how to ingles?? "Skips rendering frames if game logic takes too long\npreventing gameplay issues during performance drops.", // idk im shit as describing things "Different methods of scaling the votescreen backgrounds.", @@ -991,6 +994,7 @@ enum op_exp_secbright, //op_exp_dirlight, op_exp_skybox, + op_exp_texcache, op_exp_accuratefps, op_exp_frameskip, op_exp_votescrn, -- 2.54.0 From feff5a7c17487681b0a1680ebdb4d105303e70b3 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 1 Nov 2025 16:32:04 +0100 Subject: [PATCH 181/219] make a toggle for using angleturn in replays while this is more accurate to how the player experienced stuff in the actual game, this also can be somewhat jittery and stuttery depending on the net conditions the replay was recorded in, so make this toggable if someone wants it --- src/d_netcmd.c | 5 +++++ src/d_netcmd.h | 2 ++ src/p_user.c | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 92d9fb935..86c9b12b1 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -292,6 +292,10 @@ consvar_t cv_mouseturn = {"mouseturn", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, // Lagless camera! Yay! consvar_t cv_laglesscam = {"lagless_camera", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +// makes the camera use the saved angleturn in replays instead of the players angle +// more accurate to how the recording player seen things in game, but may be jittery if they encountered net issues +consvar_t cv_demoangturn = {"useangleturninreplays", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; + consvar_t cv_verticallook[MAXSPLITSCREENPLAYERS] = { {"verticallook", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}, {"verticallook2", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}, @@ -1043,6 +1047,7 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_betainterscreen); CV_RegisterVar(&cv_laglesscam); + CV_RegisterVar(&cv_demoangturn); for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) { diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 52f777e2b..6b7382403 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -209,6 +209,8 @@ extern consvar_t cv_betainterscreen; extern consvar_t cv_laglesscam; +extern consvar_t cv_demoangturn; + typedef enum { SKINMENUTYPE_SCROLL = 0, diff --git a/src/p_user.c b/src/p_user.c index b99998844..5ccc43f0a 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3824,7 +3824,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall // Hack-adjacent. // Sometimes stale ticcmds send a weird angle at the start of the race. // P_UpdatePlayerAngle knows to ignore cmd angle when you literally can't turn, so we do the same here. - if (leveltime > starttime) + if (cv_demoangturn.value && leveltime > starttime) focusangle = player->cmd.angleturn << 16; else focusangle = mo->angle; // Just use something known sane. -- 2.54.0 From c428472c6f919f1981c52b81b1ad262b72676e56 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 1 Nov 2025 16:12:05 +0100 Subject: [PATCH 182/219] dont precache anything ever in HWR_PrecacheLevel if disabled before some cvar callbacks called this unconditionally --- src/hardware/hw_cache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index e58169e14..1a09ee33f 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -812,7 +812,7 @@ static void HWR_PrecacheLevelSprites(void) void HWR_PrecacheLevel(void) { - if (gamestate != GS_LEVEL) + if (gamestate != GS_LEVEL || !cv_precachetextures.value) return; // Precache flats. -- 2.54.0 From 456a380e3a975311ecfbc898635a17232e12e8f3 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 1 Nov 2025 15:39:21 +0100 Subject: [PATCH 183/219] HWR_PrecacheLevel: disable sprite precaching in some cases this may lead to crashes, its mostly useless in gl eitherway due to how colourmapped sprites work --- src/hardware/hw_cache.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 1a09ee33f..4d9fdb54c 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -745,7 +745,7 @@ static void HWR_PrecacheLevelTextures(void) free(texturepresent); } -static void HWR_PrecacheLevelSprites(void) +/*static void HWR_PrecacheLevelSprites(void) { patch_t *spritepatch; char *spritepresent; @@ -808,7 +808,7 @@ static void HWR_PrecacheLevelSprites(void) } } free(spritepresent); -} +}*/ void HWR_PrecacheLevel(void) { @@ -822,7 +822,7 @@ void HWR_PrecacheLevel(void) HWR_PrecacheLevelTextures(); // Precache sprites. - HWR_PrecacheLevelSprites(); + //HWR_PrecacheLevelSprites(); } void HWR_LoadMapTextures(size_t pnumtextures) -- 2.54.0 From eaee95a026244cc793cd8c6eb60adee9b0cb8cb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Tue, 29 Jul 2025 13:10:44 +0200 Subject: [PATCH 184/219] Add -workdir --- src/d_main.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index ca2ffa4f7..50b3330e9 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1721,8 +1721,14 @@ void D_SRB2Main(void) else { // use user specific config file + if (M_CheckParm("-workdir") && M_IsNextParm()) + snprintf(srb2home, sizeof srb2home, "%s", M_GetNextParm()); + else #ifdef DEFAULTDIR - snprintf(srb2home, sizeof srb2home, "%s" PATHSEP DEFAULTDIR, userhome); + snprintf(srb2home, sizeof srb2home, "%s" PATHSEP DEFAULTDIR, userhome); +#else // DEFAULTDIR + snprintf(srb2home, sizeof srb2home, "%s", userhome); +#endif // DEFAULTDIR snprintf(downloaddir, sizeof downloaddir, "%s" PATHSEP "DOWNLOAD", srb2home); if (dedicated) snprintf(configfile, sizeof configfile, "%s" PATHSEP "d"CONFIGFILENAME, srb2home); @@ -1731,17 +1737,6 @@ void D_SRB2Main(void) // can't use sprintf since there is %u in savegamename strcatbf(savegamename, srb2home, PATHSEP); -#else - snprintf(srb2home, sizeof srb2home, "%s", userhome); - snprintf(downloaddir, sizeof downloaddir, "%s", userhome); - if (dedicated) - snprintf(configfile, sizeof configfile, "%s" PATHSEP "d"CONFIGFILENAME, userhome); - else - snprintf(configfile, sizeof configfile, "%s" PATHSEP CONFIGFILENAME, userhome); - - // can't use sprintf since there is %u in savegamename - strcatbf(savegamename, userhome, PATHSEP); -#endif } configfile[sizeof configfile - 1] = '\0'; @@ -1767,6 +1762,9 @@ void D_SRB2Main(void) } } + // make sure workdir exists + I_mkdir(srb2home, 0755); + // Create addons dir snprintf(addonsdir, sizeof addonsdir, "%s%s%s", srb2home, PATHSEP, "addons"); I_mkdir(addonsdir, 0755); -- 2.54.0 From 908e07362872c132ebb4c8360d318194ef37918c Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 1 Nov 2025 18:28:47 +0100 Subject: [PATCH 185/219] removed unused autoload variables M_ConnectMenuModChecks been checking an uninitialized bool the whole time Zzz... --- src/d_main.c | 10 ++++------ src/d_main.h | 2 -- src/m_menu.c | 4 ++-- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 50b3330e9..1f425a468 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -102,10 +102,8 @@ static char *startuppwads[MAX_WADFILES]; // autoloading static char *autoloadwadfiles[MAX_WADFILES]; static char *autoloadwadfilespost[MAX_WADFILES]; -boolean autoloading; -boolean autoloaded; +static boolean autoloaded = false; boolean postautoloaded = false; -boolean wasautoloaded = false; // boolean devparm = false; // started game with -devparm @@ -1158,7 +1156,7 @@ static void D_FindAddonsToAutoload(void) // If the file is found, run our shit if (!autoloadconfigfile) // nope outta here { - wasautoloaded = postautoloaded = true; // so D_AddAutoloadFiles can skip everything since nothings there to autoload + autoloaded = postautoloaded = true; // so D_AddAutoloadFiles can skip everything since nothings there to autoload return; } @@ -1206,7 +1204,7 @@ static void D_FindAddonsToAutoload(void) static void D_AddAutoloadFiles(void) { - if (wasautoloaded) + if (autoloaded) return; CONS_Printf("D_AutoloadFile(): Loading autoloaded addons...\n"); @@ -1214,7 +1212,7 @@ static void D_AddAutoloadFiles(void) CONS_Printf("D_AutoloadFile(): Are you sure you put in valid files or what?\n"); D_CleanFile(autoloadwadfiles); - wasautoloaded = true; + autoloaded = true; } void D_AddPostloadFiles(void) diff --git a/src/d_main.h b/src/d_main.h index 86c79a63c..deeca4c07 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -61,8 +61,6 @@ extern boolean minilighticon; // mkwii-style minimap headlight // // autoload stuff -extern boolean autoloading; -extern boolean autoloaded; extern boolean postautoloaded; void D_AddPostloadFiles(void); diff --git a/src/m_menu.c b/src/m_menu.c index 6eaccdce0..49398df34 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6956,9 +6956,9 @@ static void M_ConnectMenuModChecks(INT32 choice) (void)choice; // okay never mind we want to COMMUNICATE to the player pre-emptively instead of letting them try and then get confused when it doesn't work - if (modifiedgame || autoloaded) + if (modifiedgame) { - M_StartMessage(M_GetText("You have addons loaded.\nYou won't be able to join netgames!\n\nTo play online, restart the game\nand don't load any addons.\nSRB2Kart will automatically add\neverything you need when you join.\n\n(Press a key)\n"),M_ConnectMenu,MM_EVENTHANDLER); + M_StartMessage("You have addons loaded.\nYou won't be able to join netgames!\n\nTo play online, restart the game\nand don't load any addons.\nSRB2Kart will automatically add\neverything you need when you join.\n\n(Press a key)\n", M_ConnectMenu, MM_EVENTHANDLER); return; } -- 2.54.0 From de73c536658a8f3b479ba5123967f0f42418128d Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 1 Nov 2025 19:20:04 +0100 Subject: [PATCH 186/219] optimize addon autoload handling --- src/d_main.c | 73 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 48 insertions(+), 25 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 1f425a468..1fde58a7b 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -102,6 +102,8 @@ static char *startuppwads[MAX_WADFILES]; // autoloading static char *autoloadwadfiles[MAX_WADFILES]; static char *autoloadwadfilespost[MAX_WADFILES]; +static size_t autoloadcount = 0; +static size_t postloadcount = 0; static boolean autoloaded = false; boolean postautoloaded = false; // @@ -1057,6 +1059,7 @@ static void D_AddFile(const char *file, char **filearray) static void D_CleanFile(char **filearray) { size_t pnumwadfiles; + for (pnumwadfiles = 0; filearray[pnumwadfiles]; pnumwadfiles++) { free(filearray[pnumwadfiles]); @@ -1064,6 +1067,17 @@ static void D_CleanFile(char **filearray) } } +static void D_CleanAutoloadFile(char **filearray, size_t count) +{ + size_t i; + + for (i = 0; i < count; i++) + { + free(filearray[i]); + filearray[i] = NULL; + } +} + // Taken from TSoURDt3rd // https://github.com/StarManiaKG/The-Story-of-Uncapped-Revengence-Discord-the-3rd/blob/main/src/STAR/star_functions.c static INT32 D_DetectFileType(const char* filename) @@ -1092,9 +1106,8 @@ static INT32 D_DetectFileType(const char* filename) } // autoload that shit -static void D_AutoloadFile(const char *file, char **filearray) +static void D_AutoloadFile(const char *file, char **filearray, size_t count) { - size_t pnumwadfiles; char *newfile; INT32 fileType = D_DetectFileType(file); @@ -1104,9 +1117,6 @@ static void D_AutoloadFile(const char *file, char **filearray) return; } - for (pnumwadfiles = 0; filearray[pnumwadfiles]; pnumwadfiles++) - ; - if (fileType <= 6) { newfile = malloc(strlen(file) + 1); @@ -1114,7 +1124,7 @@ static void D_AutoloadFile(const char *file, char **filearray) I_Error("No more free memory to AutoloadFile %s",file); strcpy(newfile, file); - filearray[pnumwadfiles] = newfile; + filearray[count] = newfile; } else { @@ -1144,13 +1154,14 @@ static void D_FindAddonsToAutoload(void) { FILE *autoloadconfigfile; const char *autoloadpath; + char *newline; + boolean postload; - INT32 i; char wadsToAutoload[256] = ""; // does it exist tho - autoloadpath = va("%s"PATHSEP"%s",srb2home,AUTOLOADCONFIGFILENAME); + autoloadpath = va("%s"PATHSEP"%s", srb2home, AUTOLOADCONFIGFILENAME); autoloadconfigfile = fopen(autoloadpath, "r"); // If the file is found, run our shit @@ -1160,26 +1171,27 @@ static void D_FindAddonsToAutoload(void) return; } - while (fgets(wadsToAutoload, sizeof wadsToAutoload, autoloadconfigfile) != NULL) + while (fgets(wadsToAutoload, sizeof(wadsToAutoload), autoloadconfigfile) != NULL) { postload = false; + // skip if commented or empty - if ((wadsToAutoload[1] == '\0' || wadsToAutoload[1] == '\n') - || (wadsToAutoload[0] == '#')) + if (wadsToAutoload[0] == '\n' || + wadsToAutoload[0] == '#' || + wadsToAutoload[0] == '\0') continue; + // this marks it so that it loads after loading server addons - else if (fastncmp(wadsToAutoload, "postload ", 9)) + if (fastncmp(wadsToAutoload, "postload ", 9)) { strremove(wadsToAutoload, "postload "); postload = true; } // Remove Any Empty or Skipped Lines - for (i = 0; wadsToAutoload[i] != '\0'; i++) - { - if (wadsToAutoload[i] == '\n') - wadsToAutoload[i] = '\0'; - } + newline = strchr(wadsToAutoload, '\n'); + if (newline) + *newline = '\0'; if (!postload && W_CheckPostLoadList(wadsToAutoload)) { @@ -1189,15 +1201,20 @@ static void D_FindAddonsToAutoload(void) // LOAD IT if (!postload) - D_AutoloadFile(wadsToAutoload, autoloadwadfiles); + { + D_AutoloadFile(wadsToAutoload, autoloadwadfiles, autoloadcount); + autoloadcount++; + } else - D_AutoloadFile(wadsToAutoload, autoloadwadfilespost); - - // end it here - for (i = 0; wadsToAutoload[i] != '\0'; i++) - wadsToAutoload[i] = '\0'; + { + D_AutoloadFile(wadsToAutoload, autoloadwadfilespost, postloadcount); + postloadcount++; + } } + autoloadwadfiles[autoloadcount] = NULL; + autoloadwadfilespost[postloadcount] = NULL; + // we dont want memory leaks around here do we? fclose(autoloadconfigfile); } @@ -1208,10 +1225,13 @@ static void D_AddAutoloadFiles(void) return; CONS_Printf("D_AutoloadFile(): Loading autoloaded addons...\n"); + if (W_AddAutoloadedLocalFiles(autoloadwadfiles) == 0) CONS_Printf("D_AutoloadFile(): Are you sure you put in valid files or what?\n"); - D_CleanFile(autoloadwadfiles); + D_CleanAutoloadFile(autoloadwadfiles, autoloadcount); + + autoloadcount = 0; autoloaded = true; } @@ -1221,10 +1241,13 @@ void D_AddPostloadFiles(void) return; CONS_Printf("D_AddPostloadFiles(): Loading postloaded addons...\n"); + if (W_AddAutoloadedLocalFiles(autoloadwadfilespost) == 0) CONS_Printf("D_AddPostloadFiles(): Are you sure you put in valid files or what?\n"); - D_CleanFile(autoloadwadfilespost); + D_CleanAutoloadFile(autoloadwadfilespost, postloadcount); + + postloadcount = 0; postautoloaded = true; } -- 2.54.0 From c0f24ebbbcdacde32f0753ba4a7bee6a247561c6 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 1 Nov 2025 19:36:28 +0100 Subject: [PATCH 187/219] postautoloaded can be static not used outside of d_main --- src/d_main.c | 2 +- src/d_main.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 1fde58a7b..f3b2486c8 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -105,7 +105,7 @@ static char *autoloadwadfilespost[MAX_WADFILES]; static size_t autoloadcount = 0; static size_t postloadcount = 0; static boolean autoloaded = false; -boolean postautoloaded = false; +static boolean postautoloaded = false; // boolean devparm = false; // started game with -devparm diff --git a/src/d_main.h b/src/d_main.h index deeca4c07..d9954a5b0 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -61,7 +61,6 @@ extern boolean minilighticon; // mkwii-style minimap headlight // // autoload stuff -extern boolean postautoloaded; void D_AddPostloadFiles(void); // the infinite loop of D_SRB2Loop() called from win_main for windows version -- 2.54.0 From 42b1f849c030e35f5db44b905e4a808920f0ca3d Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 1 Nov 2025 20:00:43 +0100 Subject: [PATCH 188/219] cleanup and optimize startup wad handling --- src/d_main.c | 102 ++++++++++++++++++++++++--------------------------- 1 file changed, 47 insertions(+), 55 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index f3b2486c8..b7704318b 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -97,7 +97,9 @@ UINT8 window_notinfocus = false; static char *startupiwadfiles[MAX_WADFILES]; +static size_t startupiwadcount = 0; static char *startuppwads[MAX_WADFILES]; +static size_t startuppwadcount = 0; // autoloading static char *autoloadwadfiles[MAX_WADFILES]; @@ -1038,14 +1040,10 @@ void D_StartTitle(void) // // D_AddFile // -static void D_AddFile(const char *file, char **filearray) +static void D_AddFile(const char *file, char **filearray, size_t count) { - size_t pnumwadfiles; char *newfile; - for (pnumwadfiles = 0; filearray[pnumwadfiles]; pnumwadfiles++) - ; - newfile = malloc(strlen(file) + 1); if (!newfile) { @@ -1053,21 +1051,10 @@ static void D_AddFile(const char *file, char **filearray) } strcpy(newfile, file); - filearray[pnumwadfiles] = newfile; + filearray[count] = newfile; } -static void D_CleanFile(char **filearray) -{ - size_t pnumwadfiles; - - for (pnumwadfiles = 0; filearray[pnumwadfiles]; pnumwadfiles++) - { - free(filearray[pnumwadfiles]); - filearray[pnumwadfiles] = NULL; - } -} - -static void D_CleanAutoloadFile(char **filearray, size_t count) +static void D_CleanFile(char **filearray, size_t count) { size_t i; @@ -1229,7 +1216,7 @@ static void D_AddAutoloadFiles(void) if (W_AddAutoloadedLocalFiles(autoloadwadfiles) == 0) CONS_Printf("D_AutoloadFile(): Are you sure you put in valid files or what?\n"); - D_CleanAutoloadFile(autoloadwadfiles, autoloadcount); + D_CleanFile(autoloadwadfiles, autoloadcount); autoloadcount = 0; autoloaded = true; @@ -1245,7 +1232,7 @@ void D_AddPostloadFiles(void) if (W_AddAutoloadedLocalFiles(autoloadwadfilespost) == 0) CONS_Printf("D_AddPostloadFiles(): Are you sure you put in valid files or what?\n"); - D_CleanAutoloadFile(autoloadwadfilespost, postloadcount); + D_CleanFile(autoloadwadfilespost, postloadcount); postloadcount = 0; postautoloaded = true; @@ -1255,13 +1242,13 @@ void D_AddPostloadFiles(void) // Identify the SRB2 version, and IWAD file to use. // ========================================================================== -static boolean AddIWAD(void) +static boolean AddIWAD(const char * file, const char *dir) { - char * path = va(pandf, srb2path, "srb2.srb"); + char * path = va(pandf, dir, file); if (FIL_ReadFileOK(path)) { - D_AddFile(path, startupiwadfiles); + D_AddFile(path, startupiwadfiles, startupiwadcount++); return true; } @@ -1304,7 +1291,7 @@ static void IdentifyVersion(void) } // Load the IWAD - if (!AddIWAD()) + if (!AddIWAD("srb2.srb", srb2path)) // not sure why this uses srb2path and not srb2waddir? { I_Error("SRB2.SRB not found! Expected in %s\n", srb2waddir); } @@ -1318,48 +1305,51 @@ static void IdentifyVersion(void) #ifdef USE_PATCH_DTA // Add our crappy patches to fix our bugs - D_AddFile(va(pandf,srb2waddir,"patch.dta")); + if (!AddIWAD("patch.dta", srb2waddir)) + { + I_Error("patch.dta not found! Expected in %s\n", srb2waddir); + } #endif + if (!AddIWAD("gfx.kart", srb2waddir)) + { + I_Error("gfx.kart not found! Expected in %s\n", srb2waddir); + } - D_AddFile(va(pandf, srb2waddir, "gfx.kart"), startupiwadfiles); - D_AddFile(va(pandf, srb2waddir, "textures.kart"), startupiwadfiles); - D_AddFile(va(pandf, srb2waddir, "chars.kart"), startupiwadfiles); - D_AddFile(va(pandf, srb2waddir, "maps.kart"), startupiwadfiles); + if (!AddIWAD("textures.kart", srb2waddir)) + { + I_Error("textures.kart not found! Expected in %s\n", srb2waddir); + } + + if (!AddIWAD("chars.kart", srb2waddir)) + { + I_Error("chars.kart not found! Expected in %s\n", srb2waddir); + } + + if (!AddIWAD("maps.kart", srb2waddir)) + { + I_Error("maps.kart not found! Expected in %s\n", srb2waddir); + } #ifdef USE_PATCH_KART - D_AddFile(va(pandf,srb2waddir,"patch.kart"), startupiwadfiles); + if (!AddIWAD("patch.kart", srb2waddir)) + { + I_Error("patch.kart not found! Expected in %s\n", srb2waddir); + } #endif - const char *path = NULL; - - path = va(pandf, srb2waddir, "extra.kart"); - // completely optional - if (FIL_ReadFileOK(path)) - { - D_AddFile(path, startupiwadfiles); + if (AddIWAD("extra.kart", srb2waddir)) found_extra_kart = true; - } - - path = va(pandf, srb2waddir, "extra2.kart"); // completely optional 2: Back with a vengence - if (FIL_ReadFileOK(path)) - { - D_AddFile(path, startupiwadfiles); + if (AddIWAD("extra2.kart", srb2waddir)) found_extra2_kart = true; - } - path = va(pandf, srb2waddir, "extra3.kart"); - - if (FIL_ReadFileOK(path)) - { - D_AddFile(path, startupiwadfiles); + if (AddIWAD("extra3.kart", srb2waddir)) found_extra3_kart = true; - } #if !defined (HAVE_SDL) || defined (HAVE_MIXER) #define MUSICTEST(str) \ - musicpath = va(pandf,srb2waddir,str);\ + musicpath = va(pandf, srb2waddir, str);\ handle = W_OpenWadFile(&musicpath, false); \ if (handle) \ {\ @@ -1368,7 +1358,7 @@ static void IdentifyVersion(void) if (ms == 0) \ I_Error("File " str " has been modified with non-music/sound lumps"); \ if (ms == 1) \ - D_AddFile(musicpath, startupiwadfiles); \ + D_AddFile(musicpath, startupiwadfiles, startupiwadcount++); \ } { const char *musicpath; @@ -1814,7 +1804,7 @@ void D_SRB2Main(void) const char *s = M_GetNextParm(); if (s) // Check for NULL? - D_AddFile(s, startuppwads); + D_AddFile(s, startuppwads, startuppwadcount++); } } } @@ -1848,7 +1838,8 @@ void D_SRB2Main(void) CONS_Printf("W_InitMultipleFiles(): Adding IWAD and main PWADs.\n"); W_InitMultipleFiles(startupiwadfiles, false); - D_CleanFile(startupiwadfiles); + D_CleanFile(startupiwadfiles, startupiwadcount); + startupiwadcount = 0; mainwads = 0; #ifndef DEVELOP @@ -1895,7 +1886,8 @@ void D_SRB2Main(void) D_CheckMaps(true); } - D_CleanFile(startuppwads); + D_CleanFile(startuppwads, startuppwadcount); + startuppwadcount = 0; cht_Init(); -- 2.54.0 From c8ae4a89d9a7b73210a17301f094786b99050c15 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 1 Nov 2025 19:28:41 +0100 Subject: [PATCH 189/219] throw motion blur effect stuff behind an ifdef so we can get rid of the unused array prob could just remove it at this point, but maybe ill fix it someday for the funnis --- src/d_main.c | 6 ++++++ src/doomstat.h | 3 +++ src/p_user.c | 14 +++++++++----- src/v_video.c | 11 +++++++++-- 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index b7704318b..ee587cfdc 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -115,7 +115,9 @@ boolean devparm = false; // started game with -devparm boolean singletics = false; // timedemo boolean lastdraw = false; +#ifdef MOTIONBLUR INT32 postimgparam[MAXSPLITSCREENPLAYERS]; +#endif // These variables are only true if // whether the respective sound system is disabled @@ -399,7 +401,11 @@ static void D_Renderview(void) if (i == 0) R_ApplyViewMorph(); +#ifdef MOTIONBLUR V_DoPostProcessor(i, postimgparam[i]); +#else + V_DoPostProcessor(i, 0); +#endif } } diff --git a/src/doomstat.h b/src/doomstat.h index 46c3d61f9..a9bd9bbac 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -116,7 +116,10 @@ extern UINT8 window_notinfocus; // are we in focus? (backend independant -- hand extern boolean nodrawers; extern boolean noblit; extern boolean lastdraw; + +#ifdef MOTIONBLUR extern INT32 postimgparam[MAXSPLITSCREENPLAYERS]; +#endif extern INT32 viewwindowx, viewwindowy; extern INT32 viewwidth; diff --git a/src/p_user.c b/src/p_user.c index 5ccc43f0a..481cd6060 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4315,17 +4315,19 @@ static void P_CalcPostImg(player_t *player, camera_t *thiscam) { sector_t *sector = NULL; UINT8 postimgtype = 0; - //INT32 *param; fixed_t pviewheight = 0; +#ifdef MOTIONBLUR + INT32 *param; - /*for (i = 0; i <= splitscreen; i++) + for (i = 0; i <= splitscreen; i++) { if (player == &players[displayplayers[i]]) { param = &postimgparam[i]; break; } - }*/ + } +#endif if (encoremode) // srb2kart postimgtype |= POSTIMG_MIRROR; @@ -4361,16 +4363,18 @@ static void P_CalcPostImg(player_t *player, camera_t *thiscam) else if (P_CameraCheckHeatFirstperson(player, sector, pviewheight)) postimgtype |= POSTIMG_HEAT; +#ifdef MOTIONBLUR // Motion blur // unused - /*if (player->speed > (35<speed > (35<speed - 32)/4; if (*param > 5) *param = 5; - }*/ + } +#endif thiscam->postimg = postimgtype; } diff --git a/src/v_video.c b/src/v_video.c index 9805e910c..e7d9a87ca 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -3581,6 +3581,9 @@ boolean *heatshifter = NULL; INT32 lastheight = 0; INT32 heatindex[MAXSPLITSCREENPLAYERS] = {0, 0, 0, 0}; +// unused motion blur effect, probably non functional +//#define MOTIONBLUR + // // V_DoPostProcessor // @@ -3595,7 +3598,9 @@ void V_DoPostProcessor(INT32 view, INT32 param) (void)type; (void)param; #else +#ifndef MOTIONBLUR (void)param; // unused motion blur stuff +#endif INT32 yoffset, xoffset; #ifdef HWRENDER @@ -3730,7 +3735,8 @@ void V_DoPostProcessor(INT32 view, INT32 param) srcscr = tmp; } - /*if (thiscam->postimg & POSTIMG_MOTION) // Motion Blur! +#ifdef MOTIONBLUR + if (thiscam->postimg & POSTIMG_MOTION) // Motion Blur! { INT32 x, y; @@ -3742,7 +3748,8 @@ void V_DoPostProcessor(INT32 view, INT32 param) for (x = xoffset; x < xoffset+viewwidth; x++) tmpscr[y*vid.width + x] = colormaps[*(transme + (srcscr [(y*vid.width)+x ] <<8) + (tmpscr[(y*vid.width)+x]))]; } - }*/ + } +#endif if ((thiscam->postimg & POSTIMG_FLIP) && !(thiscam->postimg & POSTIMG_MIRROR)) // Flip the screen upside-down { -- 2.54.0 From 7c1f17bb8dcbc2dc6ea8ace3c11e9e80368720c0 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 1 Nov 2025 20:47:19 +0100 Subject: [PATCH 190/219] pass our file counts to W_InitMultipleFiles smol opzimiation, skips some ptr deref --- src/d_main.c | 17 +++++++++-------- src/w_wad.c | 13 +++++++------ src/w_wad.h | 2 +- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index ee587cfdc..7bb932b1b 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1046,7 +1046,7 @@ void D_StartTitle(void) // // D_AddFile // -static void D_AddFile(const char *file, char **filearray, size_t count) +static void D_AddFile(const char *file, char **filearray, size_t index) { char *newfile; @@ -1057,14 +1057,14 @@ static void D_AddFile(const char *file, char **filearray, size_t count) } strcpy(newfile, file); - filearray[count] = newfile; + filearray[index] = newfile; } -static void D_CleanFile(char **filearray, size_t count) +static void D_CleanFile(char **filearray, size_t index) { size_t i; - for (i = 0; i < count; i++) + for (i = 0; i < index; i++) { free(filearray[i]); filearray[i] = NULL; @@ -1358,7 +1358,7 @@ static void IdentifyVersion(void) musicpath = va(pandf, srb2waddir, str);\ handle = W_OpenWadFile(&musicpath, false); \ if (handle) \ - {\ + { \ int ms = W_VerifyNMUSlumps(musicpath, handle, false); \ fclose(handle); \ if (ms == 0) \ @@ -1843,7 +1843,8 @@ void D_SRB2Main(void) // load wad, including the main wad file CONS_Printf("W_InitMultipleFiles(): Adding IWAD and main PWADs.\n"); - W_InitMultipleFiles(startupiwadfiles, false); + W_InitMultipleFiles(startupiwadfiles, startupiwadcount, false); + //mainwads = startupiwadcount - musicwads; D_CleanFile(startupiwadfiles, startupiwadcount); startupiwadcount = 0; mainwads = 0; @@ -1884,10 +1885,10 @@ void D_SRB2Main(void) D_CheckMaps(false); - W_InitMultipleFiles(startuppwads, true); + W_InitMultipleFiles(startuppwads, startuppwadcount, true); // Only search for pwad maps if we actually have a pwad added - if (startuppwads[0] != NULL) + if (startuppwadcount > 0) { D_CheckMaps(true); } diff --git a/src/w_wad.c b/src/w_wad.c index 756dee4a6..f9eb9b361 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -971,24 +971,25 @@ UINT16 W_InitFile(const char *filename, boolean local, boolean startup) * \return 1 if all files were loaded, 0 if at least one was missing or * invalid. */ -INT32 W_InitMultipleFiles(char **filenames, boolean addons) +INT32 W_InitMultipleFiles(char **filenames, size_t count, boolean addons) { INT32 rc = 1; INT32 overallrc = 1; - + size_t i; (void)addons; - // will be realloced as lumps are added - for (; *filenames; filenames++) + for (i = 0; i < count; i++) { + const char *filename = filenames[i]; + // Previously, W_VerifyNMUSlumps was called to mark game modified // for addons... but W_InitFile already does exactly that! //CONS_Debug(DBG_SETUP, "Loading %s\n", *filenames); - rc = W_InitFile(*filenames, false, true); + rc = W_InitFile(filename, false, true); if (rc == INT16_MAX) - CONS_Printf(M_GetText("Errors occurred while loading %s; not added.\n"), *filenames); + CONS_Printf(M_GetText("Errors occurred while loading %s; not added.\n"), filename); overallrc &= (rc != INT16_MAX) ? 1 : 0; } diff --git a/src/w_wad.h b/src/w_wad.h index c3cae627f..6240c31f3 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -167,7 +167,7 @@ UINT16 W_InitFile(const char *filename, boolean local, boolean startup); // W_InitMultipleFiles returns 1 if all is okay, 0 otherwise, // so that it stops with a message if a file was not found, but not if all is okay. -INT32 W_InitMultipleFiles(char **filenames, boolean addons); +INT32 W_InitMultipleFiles(char **filenames, size_t count, boolean addons); // Used for autoload. Uses P_AddWadFileLocal instead of W_InitFiles. INT32 W_AddAutoloadedLocalFiles(char **filenames); -- 2.54.0 From 3e0150d4f31be79d30c99d0d6f8b00a02e85360b Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 1 Nov 2025 20:53:21 +0100 Subject: [PATCH 191/219] remove auto/postload check variables we can just check our counts since D_FindAddonsToAutoload will never be called again --- src/d_main.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 7bb932b1b..aa6c905c2 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -106,8 +106,6 @@ static char *autoloadwadfiles[MAX_WADFILES]; static char *autoloadwadfilespost[MAX_WADFILES]; static size_t autoloadcount = 0; static size_t postloadcount = 0; -static boolean autoloaded = false; -static boolean postautoloaded = false; // boolean devparm = false; // started game with -devparm @@ -1160,7 +1158,7 @@ static void D_FindAddonsToAutoload(void) // If the file is found, run our shit if (!autoloadconfigfile) // nope outta here { - autoloaded = postautoloaded = true; // so D_AddAutoloadFiles can skip everything since nothings there to autoload + autoloadcount = postloadcount = 0; // so D_AddAutoloadFiles can skip everything since nothings there to autoload return; } @@ -1214,7 +1212,8 @@ static void D_FindAddonsToAutoload(void) static void D_AddAutoloadFiles(void) { - if (autoloaded) + // nothing to autoload + if (autoloadcount == 0) return; CONS_Printf("D_AutoloadFile(): Loading autoloaded addons...\n"); @@ -1225,12 +1224,12 @@ static void D_AddAutoloadFiles(void) D_CleanFile(autoloadwadfiles, autoloadcount); autoloadcount = 0; - autoloaded = true; } void D_AddPostloadFiles(void) { - if (postautoloaded || !netgame) + // nothing to postload + if (postloadcount == 0 || !netgame) return; CONS_Printf("D_AddPostloadFiles(): Loading postloaded addons...\n"); @@ -1241,7 +1240,6 @@ void D_AddPostloadFiles(void) D_CleanFile(autoloadwadfilespost, postloadcount); postloadcount = 0; - postautoloaded = true; } // ========================================================================== -- 2.54.0 From 4fccb48d2ab44360890e24375e7593124039fadc Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 1 Nov 2025 20:57:55 +0100 Subject: [PATCH 192/219] fix wonky variable names --- src/d_main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index aa6c905c2..032a9189e 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1058,11 +1058,11 @@ static void D_AddFile(const char *file, char **filearray, size_t index) filearray[index] = newfile; } -static void D_CleanFile(char **filearray, size_t index) +static void D_CleanFile(char **filearray, size_t count) { size_t i; - for (i = 0; i < index; i++) + for (i = 0; i < count; i++) { free(filearray[i]); filearray[i] = NULL; @@ -1097,7 +1097,7 @@ static INT32 D_DetectFileType(const char* filename) } // autoload that shit -static void D_AutoloadFile(const char *file, char **filearray, size_t count) +static void D_AutoloadFile(const char *file, char **filearray, size_t index) { char *newfile; INT32 fileType = D_DetectFileType(file); @@ -1115,7 +1115,7 @@ static void D_AutoloadFile(const char *file, char **filearray, size_t count) I_Error("No more free memory to AutoloadFile %s",file); strcpy(newfile, file); - filearray[count] = newfile; + filearray[index] = newfile; } else { -- 2.54.0 From cae5e73d7dd681881a42026a2aa822cae3967ae1 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 30 Oct 2025 18:04:46 +0100 Subject: [PATCH 193/219] LUA_RawPushUserdata "Same as LUA_PushUserdata but don't set a metatable yet." from RR --- src/lua_script.c | 25 ++++++++++++++++++++++--- src/lua_script.h | 8 ++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/lua_script.c b/src/lua_script.c index e59841940..448d7221d 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -492,25 +492,37 @@ void LUA_InvalidateMathlibCache(const char *name) // Pushes it to the stack and stores it in the registry. void LUA_PushUserdata(lua_State *L, void *data, const char *meta) { + if (LUA_RawPushUserdata(L, data) == LPUSHED_NEW) + { + luaL_getmetatable(L, meta); + lua_setmetatable(L, -2); + } +} + +// Same as LUA_PushUserdata but don't set a metatable yet. +lpushed_t LUA_RawPushUserdata(lua_State *L, void *data) +{ + lpushed_t status = LPUSHED_NIL; + void **userdata; if (!data) { // push a NULL lua_pushnil(L); - return; + return status; } lua_getfield(L, LUA_REGISTRYINDEX, LREG_VALID); I_Assert(lua_istable(L, -1)); + lua_pushlightuserdata(L, data); lua_rawget(L, -2); + if (lua_isnil(L, -1)) { // no userdata? deary me, we'll have to make one. lua_pop(L, 1); // pop the nil // create the userdata userdata = lua_newuserdata(L, sizeof(void *)); *userdata = data; - luaL_getmetatable(L, meta); - lua_setmetatable(L, -2); // Set it in the registry so we can find it again lua_pushlightuserdata(L, data); // k (store the userdata via the data's pointer) @@ -518,8 +530,15 @@ void LUA_PushUserdata(lua_State *L, void *data, const char *meta) lua_rawset(L, -4); // stack is left with the userdata on top, as if getting it had originally succeeded. + + status = LPUSHED_NEW; } + else + status = LPUSHED_EXISTING; + lua_remove(L, -2); // remove LREG_VALID + + return status; } // When userdata is freed, use this function to remove it from Lua. diff --git a/src/lua_script.h b/src/lua_script.h index af218978d..a7edf89ca 100644 --- a/src/lua_script.h +++ b/src/lua_script.h @@ -59,7 +59,15 @@ fixed_t LUA_GetConstant(const char *word); // Need better name for this ;-; void LUA_InvalidateMathlibCache(const char *name); +typedef enum { + LPUSHED_NIL, + LPUSHED_NEW, + LPUSHED_EXISTING, +} lpushed_t; + void LUA_PushUserdata(lua_State *L, void *data, const char *meta); +lpushed_t LUA_RawPushUserdata(lua_State *L, void *data); + void LUA_InvalidateUserdata(void *data); void LUA_InvalidateLevel(void); void LUA_InvalidateMapthings(void); -- 2.54.0 From f53d37052af1fd0fcb3c250bbbfa19985da34386 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 2 May 2021 21:59:23 -0700 Subject: [PATCH 194/219] Replace LUA_PushLightUserdata with LUA_PushUserdata See c92378fa and a7e20f70. I didn't realize that light userdata's metatable is shared--like numbers or strings. So it cannot be paired with a metatable. I also made a few minor tweaks to Lua cvars, other than accounting for the double pointer in the userdata. --- src/command.c | 2 +- src/lua_consolelib.c | 65 ++++++++++++-------------------------------- src/lua_script.h | 2 +- 3 files changed, 19 insertions(+), 50 deletions(-) diff --git a/src/command.c b/src/command.c index e73125649..eae29f07f 100644 --- a/src/command.c +++ b/src/command.c @@ -1474,7 +1474,7 @@ finish: var->flags |= CV_MODIFIED; // raise 'on change' code - LUA_CVarChanged(var->name); // let consolelib know what cvar this is. + LUA_CVarChanged(var); // let consolelib know what cvar this is. if (var->flags & CV_CALL && !stealth) var->func(); diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index 36c3a6c45..f148a8dcb 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -28,7 +28,7 @@ #define NOHUD if (hud_running) return luaL_error(L, "HUD rendering code should not call this function!"); -static const char *cvname = NULL; +static consvar_t *this_cvar; void Got_Luacmd(UINT8 **cp, INT32 playernum) { @@ -284,16 +284,13 @@ static int lib_comBufInsertText(lua_State *L) return 0; } -void LUA_CVarChanged(const char *name) +void LUA_CVarChanged(void *cvar) { - cvname = name; + this_cvar = cvar; } static void Lua_OnChange(void) { - I_Assert(gL != NULL); - I_Assert(cvname != NULL); - /// \todo Network this! XD_LUAVAR // Why?.. @@ -305,13 +302,10 @@ static void Lua_OnChange(void) // From CV_OnChange registry field, get the function for this cvar by name. lua_getfield(gL, LUA_REGISTRYINDEX, "CV_OnChange"); I_Assert(lua_istable(gL, -1)); - lua_getfield(gL, -1, cvname); // get function + lua_pushlightuserdata(gL, this_cvar); + lua_rawget(gL, -2); // get function - // From the CV_Vars registry field, get the cvar's userdata by name. - lua_getfield(gL, LUA_REGISTRYINDEX, "CV_Vars"); - I_Assert(lua_istable(gL, -1)); - lua_getfield(gL, -1, cvname); // get consvar_t* userdata. - lua_remove(gL, -2); // pop the CV_Vars table. + LUA_RawPushUserdata(gL, this_cvar); LUA_Call(gL, 1, 0, error_handler_i); // call function(cvar) lua_pop(gL, 2); // pop CV_OnChange table and error handler @@ -329,9 +323,8 @@ static int lib_cvRegisterVar(lua_State *L) luaL_checktype(L, 1, LUA_TTABLE); lua_settop(L, 1); // Clear out all other possible arguments, leaving only the first one. NOHUD - cvar = lua_newuserdata(L, sizeof(consvar_t)); - luaL_getmetatable(L, META_CVAR); - lua_setmetatable(L, -2); + cvar = ZZ_Calloc(sizeof(consvar_t)); + LUA_PushUserdata(L, cvar, META_CVAR); #define FIELDERROR(f, e) luaL_error(L, "bad value for " LUA_QL(f) " in table passed to " LUA_QL("CV_RegisterVar") " (%s)", e); #define TYPEERROR(f, t) FIELDERROR(f, va("%s expected, got %s", lua_typename(L, t), luaL_typename(L, -1))) @@ -384,7 +377,7 @@ static int lib_cvRegisterVar(lua_State *L) lua_getfield(L, LUA_REGISTRYINDEX, "CV_PossibleValue"); I_Assert(lua_istable(L, 5)); - lua_pushvalue(L, 2); // cvar userdata + lua_pushlightuserdata(L, cvar); cvpv = lua_newuserdata(L, sizeof(CV_PossibleValue_t) * (count+1)); lua_rawset(L, 5); lua_pop(L, 1); // pop CV_PossibleValue registry table @@ -412,13 +405,14 @@ static int lib_cvRegisterVar(lua_State *L) TYPEERROR("func", LUA_TFUNCTION) lua_getfield(L, LUA_REGISTRYINDEX, "CV_OnChange"); I_Assert(lua_istable(L, 5)); + lua_pushlightuserdata(L, cvar); lua_pushvalue(L, 4); - lua_setfield(L, 5, cvar->name); + lua_rawset(L, 5); lua_pop(L, 1); cvar->func = Lua_OnChange; } else if (((i == 5 && !(cvar->flags & CV_CALL)) - || (cvar->flags & CV_CALL && i == 6)) + || (cvar->flags & CV_CALL && i == 6)) || (k && fasticmp(k, "category"))) { category = lua_isnoneornil(L, 4) ? NULL : lua_tostring(L, 4); @@ -434,19 +428,6 @@ static int lib_cvRegisterVar(lua_State *L) #undef FIELDERROR #undef TYPEERROR - // stack: cvar table, cvar userdata - lua_getfield(L, LUA_REGISTRYINDEX, "CV_Vars"); - I_Assert(lua_istable(L, 3)); - - lua_getfield(L, 3, cvar->name); - if (lua_type(L, -1) != LUA_TNIL) - return luaL_error(L, M_GetText("Variable %s is already defined\n"), cvar->name); - lua_pop(L, 1); - - lua_pushvalue(L, 2); - lua_setfield(L, 3, cvar->name); - lua_pop(L, 1); - // actually time to register it to the console now! Finally! cvar->flags |= CV_MODIFIED; CV_RegisterVar(cvar); @@ -477,22 +458,9 @@ static int lib_cvRegisterVar(lua_State *L) static int lib_cvFindVar(lua_State *L) { - consvar_t *cv; - if (( cv = CV_FindVar(luaL_checkstring(L,1)) )) - { - lua_settop(L,1);/* We only want one argument in the stack. */ - lua_pushlightuserdata(L, cv);/* Now the second value on stack. */ - luaL_getmetatable(L, META_CVAR); - /* - The metatable is the last value on the stack, so this - applies it to the second value, which is the cvar. - */ - lua_setmetatable(L,2); - lua_pushvalue(L,2); - return 1; - } - else - return 0; + const char *name = luaL_checkstring(L, 1); + LUA_PushUserdata(L, CV_FindVar(name), META_CVAR); + return 1; } static int CVarSetFunction @@ -501,7 +469,7 @@ static int CVarSetFunction void (*Set)(consvar_t *, const char *), void (*SetValue)(consvar_t *, INT32) ){ - consvar_t *cvar = (consvar_t *)luaL_checkudata(L, 1, META_CVAR); + consvar_t *cvar = *(consvar_t **)luaL_checkudata(L, 1, META_CVAR); switch (lua_type(L, 2)) { @@ -531,6 +499,7 @@ static int lib_cvStealthSet(lua_State *L) static int lib_cvAddValue(lua_State *L) { consvar_t *cvar = (consvar_t *)luaL_checkudata(L, 1, META_CVAR); + CV_AddValue(cvar, (INT32)luaL_checknumber(L, 2)); return 0; } diff --git a/src/lua_script.h b/src/lua_script.h index a7edf89ca..f1b58cced 100644 --- a/src/lua_script.h +++ b/src/lua_script.h @@ -77,7 +77,7 @@ void LUA_Archive(savebuffer_t *save, boolean network); void LUA_UnArchive(savebuffer_t *save, boolean network); void Got_Luacmd(UINT8 **cp, INT32 playernum); // lua_consolelib.c -void LUA_CVarChanged(const char *name); // lua_consolelib.c +void LUA_CVarChanged(void *cvar); // lua_consolelib.c int Lua_optoption(lua_State *L, int narg, int def, int list_ref); int Lua_CreateFieldTable(lua_State *L, const char *const lst[]); void LUA_HookNetArchive(lua_CFunction archFunc, savebuffer_t *save); -- 2.54.0 From 1d0fb17da4e72e41d325e8c0a631e04c8d2f49e2 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 20 Aug 2019 18:18:29 +0100 Subject: [PATCH 195/219] Fixes for lib_cvRegisterVar (the Lua version of CV_RegisterVar): * Make sure the consvar's properties are all initialised to zeros as defaults * Error if the consvar is not given a name * Error if the consvar has CV_CALL but no call function * Error if the consvar has CV_NOINIT but not CV_CALL --- src/lua_consolelib.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index f148a8dcb..260ba6532 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -428,6 +428,13 @@ static int lib_cvRegisterVar(lua_State *L) #undef FIELDERROR #undef TYPEERROR + if (!cvar->name) + return luaL_error(L, M_GetText("Variable has no name!\n")); + if ((cvar->flags & CV_NOINIT) && !(cvar->flags & CV_CALL)) + return luaL_error(L, M_GetText("Variable %s has CV_NOINIT without CV_CALL\n"), cvar->name); + if ((cvar->flags & CV_CALL) && !cvar->func) + return luaL_error(L, M_GetText("Variable %s has CV_CALL without a function\n"), cvar->name); + // actually time to register it to the console now! Finally! cvar->flags |= CV_MODIFIED; CV_RegisterVar(cvar); -- 2.54.0 From 5675eefeb22336031715ac197baa33d80f947dd7 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 11 Feb 2024 05:33:20 -0800 Subject: [PATCH 196/219] Got_Luacmd: ensure lua stack is large enough for command arguments --- src/lua_consolelib.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index 260ba6532..f54349206 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -30,6 +30,12 @@ static consvar_t *this_cvar; +static void clear_lua_stack(void) +{ + if (gL) // check if Lua is actually turned on first, you dummmy -- Monster Iestyn 04/07/18 + lua_settop(gL, 0); // clear stack +} + void Got_Luacmd(UINT8 **cp, INT32 playernum) { UINT8 i, argc, flags; @@ -74,6 +80,13 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum) lua_remove(gL, -2); // pop command info table + if (!lua_checkstack(gL, argc)) // player + command arguments + { + clear_lua_stack(); + CONS_Alert(CONS_WARNING, "lua command stack overflow from %s (%d, need %d more)\n", player_names[playernum], lua_gettop(gL), argc); + return; + } + LUA_PushUserdata(gL, &players[playernum], META_PLAYER); for (i = 1; i < argc; i++) { @@ -88,8 +101,7 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum) deny: //must be hacked/buggy client - if (gL) // check if Lua is actually turned on first, you dummmy -- Monster Iestyn 04/07/18 - lua_settop(gL, 0); // clear stack + clear_lua_stack(); CONS_Alert(CONS_WARNING, M_GetText("Illegal lua command received from %s\n"), player_names[playernum]); if (server) -- 2.54.0 From f603106ac84859035d16ed0b412092fa65db6760 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Sun, 11 Feb 2024 15:10:51 -0600 Subject: [PATCH 197/219] Check Lua stack before pushing cons args Prevents a Lua stack overrun when executing absurd console commands for local-only lua commands. --- src/lua_consolelib.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index f54349206..c69fdcc10 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -190,6 +190,11 @@ void COM_Lua_f(void) I_Assert(lua_isfunction(gL, -1)); lua_remove(gL, -2); // pop command info table + if (!lua_checkstack(gL, COM_Argc() + 1)) + { + CONS_Alert(CONS_WARNING, "lua command stack overflow (%d, need %s more)\n", lua_gettop(gL), sizeu1(COM_Argc() + 1)); + return; + } LUA_PushUserdata(gL, &players[playernum], META_PLAYER); for (i = 1; i < COM_Argc(); i++) lua_pushstring(gL, COM_Argv(i)); -- 2.54.0 From 81f7335b05c0ea2d8cc9134f5a1f61433660448a Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 11 Feb 2024 15:40:04 -0800 Subject: [PATCH 198/219] Got_Luacmd: always read netxcmd data, even if command is not executed --- src/lua_consolelib.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index c69fdcc10..ead7c16a9 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -39,8 +39,18 @@ static void clear_lua_stack(void) void Got_Luacmd(UINT8 **cp, INT32 playernum) { UINT8 i, argc, flags; + const char *argv[256]; char buf[256]; + argc = READUINT8(*cp); + argv[0] = (const char*)*cp; + SKIPSTRINGN(*cp, 255); + for (i = 1; i < argc; i++) + { + argv[i] = (const char*)*cp; + SKIPSTRINGN(*cp, 255); + } + // don't use I_Assert here, goto the deny code below // to clean up and kick people who try nefarious exploits // like sending random junk lua commands to crash the server @@ -53,8 +63,7 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum) lua_getfield(gL, LUA_REGISTRYINDEX, "COM_Command"); // push COM_Command if (!lua_istable(gL, -1)) goto deny; - argc = READUINT8(*cp); - READSTRINGN(*cp, buf, 255); + strlcpy(buf, argv[0], 255); strlwr(buf); // must lowercase buffer lua_getfield(gL, -1, buf); // push command info table if (!lua_istable(gL, -1)) goto deny; @@ -90,7 +99,7 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum) LUA_PushUserdata(gL, &players[playernum], META_PLAYER); for (i = 1; i < argc; i++) { - READSTRINGN(*cp, buf, 255); + strlcpy(buf, argv[i], 255); lua_pushstring(gL, buf); } LUA_Call(gL, (int)argc, 0, 1); // argc is 1-based, so this will cover the player we passed too. -- 2.54.0 From 26b26b8f254ff2bdc947325e53ff65115e1e57f3 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 30 Oct 2025 15:58:03 +0100 Subject: [PATCH 199/219] consolelib: fix some early returns not properly cleaning lua stack --- src/lua_consolelib.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index ead7c16a9..979179ab6 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -154,7 +154,7 @@ void COM_Lua_f(void) { if (!splitscreen) { - lua_pop(gL, 1); // pop command info table + lua_pop(gL, 2); // pop command info table and LUA_GetErrorMessage return; // can't execute splitscreen command without player 2! } @@ -202,8 +202,10 @@ void COM_Lua_f(void) if (!lua_checkstack(gL, COM_Argc() + 1)) { CONS_Alert(CONS_WARNING, "lua command stack overflow (%d, need %s more)\n", lua_gettop(gL), sizeu1(COM_Argc() + 1)); + lua_pop(gL, 2); // pop function and LUA_GetErrorMessage return; } + LUA_PushUserdata(gL, &players[playernum], META_PLAYER); for (i = 1; i < COM_Argc(); i++) lua_pushstring(gL, COM_Argv(i)); @@ -547,6 +549,7 @@ static int lib_consPrintf(lua_State *L) if (n < 2) return luaL_error(L, "CONS_Printf requires at least two arguments: player and text."); //HUDSAFE + plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); if (!plr) return LUA_ErrInvalid(L, "player_t"); -- 2.54.0 From 52a9486974d26f441e16c1b94c080d65795fb2d4 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 3 Jan 2023 20:20:22 +0000 Subject: [PATCH 200/219] Remove heinous pointer-sent-over-the-network hack remnants This used to be used for `P_RelinkPointers()`, but was superseded by the far saner mobjnum. HOWEVER, its lingering effect was to leave `mobj->info` in an invalid state until a later `P_FinishMobjs()` was called. This is memory unsafety :D After removing the last remnants of this ancient hack, it is now once again possible to connect to a server without crashing immediately. However, I did get a crash after a few seconds, so there is definitely still *something* nasty going on under the hood. --- src/p_saveg.c | 28 +++------------------------- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index d3a162e2d..65b15ec8e 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1203,7 +1203,7 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8 if (diff & MD_MORE) WRITEUINT16(save->p, diff2); - // save pointer, at load time we will search this pointer to reinitilize pointers + // keep here for vanilla compat WRITEUINT32(save->p, (size_t)mobj); WRITEFIXED(save->p, mobj->z); // Force this so 3dfloor problems don't arise. @@ -1982,7 +1982,6 @@ static void CalculateDoomednumToMobjtype(void) static void LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker) { - thinker_t *next; mobj_t *mobj; UINT32 diff; UINT16 diff2; @@ -1995,7 +1994,8 @@ static void LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker) else diff2 = 0; - next = (void *)(size_t)READUINT32(save->p); + // here for vanilla compat + save->p += sizeof(UINT32); z = READFIXED(save->p); // Force this so 3dfloor problems don't arise. floorz = READFIXED(save->p); @@ -2234,8 +2234,6 @@ static void LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker) if (diff2 & MD2_WAYPOINTCAP) P_SetTarget(&waypointcap, mobj); - mobj->info = (mobjinfo_t *)next; // temporarily, set when leave this function - R_AddMobjInterpolator(mobj); } @@ -3200,25 +3198,6 @@ FUNCINLINE static ATTRINLINE void P_UnArchivePolyObjects(savebuffer_t *save) for (i = 0; i < numSavedPolys; ++i) P_UnArchivePolyObj(save, &PolyObjects[i]); } -// -// P_FinishMobjs -// -FUNCINLINE static ATTRINLINE void P_FinishMobjs(void) -{ - thinker_t *currentthinker; - mobj_t *mobj; - - // put info field there real value - for (currentthinker = thinkercap.next; currentthinker != &thinkercap; - currentthinker = currentthinker->next) - { - if (currentthinker->function != (actionf_p1)P_MobjThinker) - continue; - - mobj = (mobj_t *)currentthinker; - mobj->info = &mobjinfo[mobj->type]; - } -} FUNCINLINE static ATTRINLINE mobj_t *RelinkMobj(mobj_t **ptr) { @@ -3807,7 +3786,6 @@ boolean P_LoadNetGame(savebuffer_t *save, boolean reloading) P_NetUnArchiveThinkers(save); P_NetUnArchiveSpecials(save); P_RelinkPointers(); - P_FinishMobjs(); } LUA_UnArchive(save, true); -- 2.54.0 From e00783da82565062ac1ba7df765cd1dd7018b568 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 30 Oct 2025 16:06:26 +0100 Subject: [PATCH 201/219] fix stuff from merge conflict --- src/lua_consolelib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index 979179ab6..ee5de8356 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -533,7 +533,7 @@ static int lib_cvStealthSet(lua_State *L) static int lib_cvAddValue(lua_State *L) { - consvar_t *cvar = (consvar_t *)luaL_checkudata(L, 1, META_CVAR); + consvar_t *cvar = *(consvar_t **)luaL_checkudata(L, 1, META_CVAR); CV_AddValue(cvar, (INT32)luaL_checknumber(L, 2)); return 0; @@ -610,7 +610,7 @@ static int cvar_fields_ref = LUA_NOREF; static int cvar_get(lua_State *L) { - consvar_t *cvar = (consvar_t *)luaL_checkudata(L, 1, META_CVAR); + consvar_t *cvar = *(consvar_t **)luaL_checkudata(L, 1, META_CVAR); enum cvar_e field = Lua_optoption(L, 2, -1, cvar_fields_ref); switch (field) -- 2.54.0 From ec757ceb2cebfc04563c7d8b95a541f7edb55d76 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 11 Feb 2024 05:40:52 -0800 Subject: [PATCH 202/219] Pass const pointer to all netxcmd handlers Ensure buffer data is read-only and not modified by handler --- src/byteptr.h | 62 +++++++++++++++--------------- src/command.c | 18 +++++---- src/command.h | 2 +- src/d_clisrv.c | 22 +++++------ src/d_clisrv.h | 2 +- src/d_netcmd.c | 88 ++++++++++++++++++++++--------------------- src/g_demo.c | 4 +- src/hu_stuff.c | 9 +++-- src/lua_consolelib.c | 2 +- src/lua_script.h | 2 +- src/p_saveg.c | 2 +- src/sdl/mixer_sound.c | 6 +-- 12 files changed, 114 insertions(+), 105 deletions(-) diff --git a/src/byteptr.h b/src/byteptr.h index 058e81b25..85141c21c 100644 --- a/src/byteptr.h +++ b/src/byteptr.h @@ -1,7 +1,8 @@ -// SONIC ROBO BLAST 2 +// SONIC ROBO BLAST 2 KART //----------------------------------------------------------------------------- -// Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2025 by Sonic Team Junior. +// Copyright (C) 2025 by Kart Krew. +// Copyright (C) 2020 by Sonic Team Junior. +// Copyright (C) 2000 by DooM Legacy Team. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -24,6 +25,7 @@ extern "C" { // // Little-endian machines // + #define WRITEUINT8(p,b) do { UINT8 *p_tmp = ( UINT8 *)p; const UINT8 tv = ( UINT8)(b); memcpy(p, &tv, sizeof( UINT8)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) #define WRITESINT8(p,b) do { SINT8 *p_tmp = ( SINT8 *)p; const SINT8 tv = ( UINT8)(b); memcpy(p, &tv, sizeof( UINT8)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) #define WRITEINT16(p,b) do { INT16 *p_tmp = ( INT16 *)p; const INT16 tv = ( INT16)(b); memcpy(p, &tv, sizeof( INT16)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) @@ -36,25 +38,25 @@ extern "C" { // what is this? #if defined (__GNUC__) -#define READUINT8(p) ({ UINT8 *p_tmp = (UINT8 *)p; UINT8 b; memcpy(&b, p, sizeof( UINT8)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; b; }) -#define READSINT8(p) ({ SINT8 *p_tmp = (SINT8 *)p; SINT8 b; memcpy(&b, p, sizeof( SINT8)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; b; }) -#define READINT16(p) ({ INT16 *p_tmp = (INT16 *)p; INT16 b; memcpy(&b, p, sizeof( INT16)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; b; }) -#define READUINT16(p) ({ UINT16 *p_tmp = (UINT16 *)p; UINT16 b; memcpy(&b, p, sizeof( UINT16)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; b; }) -#define READINT32(p) ({ INT32 *p_tmp = (INT32 *)p; INT32 b; memcpy(&b, p, sizeof( INT32)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; b; }) -#define READUINT32(p) ({ UINT32 *p_tmp = (UINT32 *)p; UINT32 b; memcpy(&b, p, sizeof( UINT32)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; b; }) -#define READCHAR(p) ({ char *p_tmp = (char *)p; char b; memcpy(&b, p, sizeof( char)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; b; }) -#define READFIXED(p) ({ fixed_t *p_tmp = (fixed_t *)p; fixed_t b; memcpy(&b, p, sizeof(fixed_t)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; b; }) -#define READANGLE(p) ({ angle_t *p_tmp = (angle_t *)p; angle_t b; memcpy(&b, p, sizeof(angle_t)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; b; }) +#define READUINT8(p) ({ const UINT8 *p_tmp = (const UINT8 *)p; UINT8 b; memcpy(&b, p, sizeof( UINT8)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; }) +#define READSINT8(p) ({ const SINT8 *p_tmp = (const SINT8 *)p; SINT8 b; memcpy(&b, p, sizeof( SINT8)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; }) +#define READINT16(p) ({ const INT16 *p_tmp = (const INT16 *)p; INT16 b; memcpy(&b, p, sizeof( INT16)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; }) +#define READUINT16(p) ({ const UINT16 *p_tmp = (const UINT16 *)p; UINT16 b; memcpy(&b, p, sizeof( UINT16)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; }) +#define READINT32(p) ({ const INT32 *p_tmp = (const INT32 *)p; INT32 b; memcpy(&b, p, sizeof( INT32)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; }) +#define READUINT32(p) ({ const UINT32 *p_tmp = (const UINT32 *)p; UINT32 b; memcpy(&b, p, sizeof( UINT32)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; }) +#define READCHAR(p) ({ const char *p_tmp = (const char *)p; char b; memcpy(&b, p, sizeof( char)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; }) +#define READFIXED(p) ({ const fixed_t *p_tmp = (const fixed_t *)p; fixed_t b; memcpy(&b, p, sizeof(fixed_t)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; }) +#define READANGLE(p) ({ const angle_t *p_tmp = (const angle_t *)p; angle_t b; memcpy(&b, p, sizeof(angle_t)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; }) #else -#define READUINT8(p) ((UINT8*)(*(void**)(&(p)) = (void*)&((UINT8*)(p))[1]))[-1] -#define READSINT8(p) ((SINT8*)(*(void**)(&(p)) = (void*)&((SINT8*)(p))[1]))[-1] -#define READINT16(p) ((INT16*)(*(void**)(&(p)) = (void*)&((INT16*)(p))[1]))[-1] -#define READUINT16(p) ((UINT16*)(*(void**)(&(p)) = (void*)&((UINT16*)(p))[1]))[-1] -#define READINT32(p) ((INT32*)(*(void**)(&(p)) = (void*)&((INT32*)(p))[1]))[-1] -#define READUINT32(p) ((UINT32*)(*(void**)(&(p)) = (void*)&((UINT32*)(p))[1]))[-1] -#define READCHAR(p) ((char*)(*(void**)(&(p)) = (void*)&((char*)(p))[1]))[-1] -#define READFIXED(p) ((fixed_t*)(*(void**)(&(p)) = (void*)&((fixed_t*)(p))[1]))[-1] -#define READANGLE(p) ((angle_t*)(*(void**)(&(p)) = (void*)&((angle_t*)(p))[1]))[-1] +#define READUINT8(p) ((const UINT8*) (*(const void**)(&(p)) = (const void*)&((const UINT8*) (p))[1]))[-1] +#define READSINT8(p) ((const SINT8*) (*(const void**)(&(p)) = (const void*)&((const SINT8*) (p))[1]))[-1] +#define READINT16(p) ((const INT16*) (*(const void**)(&(p)) = (const void*)&((const INT16*) (p))[1]))[-1] +#define READUINT16(p) ((const UINT16*) (*(const void**)(&(p)) = (const void*)&((const UINT16*) (p))[1]))[-1] +#define READINT32(p) ((const INT32*) (*(const void**)(&(p)) = (const void*)&((const INT32*) (p))[1]))[-1] +#define READUINT32(p) ((const UINT32*) (*(const void**)(&(p)) = (const void*)&((const UINT32*) (p))[1]))[-1] +#define READCHAR(p) ((const char*) (*(const void**)(&(p)) = (const void*)&((const char*) (p))[1]))[-1] +#define READFIXED(p) ((const fixed_t*)(*(const void**)(&(p)) = (const void*)&((const fixed_t*)(p))[1]))[-1] +#define READANGLE(p) ((const angle_t*)(*(const void**)(&(p)) = (const void*)&((const angle_t*)(p))[1]))[-1] #endif #else //SRB2_BIG_ENDIAN @@ -117,15 +119,15 @@ FUNCINLINE static ATTRINLINE UINT32 readulong(void *ptr) return (ucp[3] << 24) | (ucp[2] << 16) | (ucp[1] << 8) | ucp[0]; } -#define READUINT8(p) ((UINT8*)(p = (void*)&((UINT8*)p)[1]))[-1] -#define READSINT8(p) ((SINT8*)(p = (void*)&((SINT8*)p)[1]))[-1] -#define READINT16(p) readshort(&((INT16*)(p = (void*)&((INT16*)p)[1]))[-1]) -#define READUINT16(p) readushort(&((UINT16*)(p = (void*)&((UINT16*)p)[1]))[-1]) -#define READINT32(p) readlong(&((INT32*)(p = (void*)&((INT32*)p)[1]))[-1]) -#define READUINT32(p) readulong(&((UINT32*)(p = (void*)&((UINT32*)p)[1])) -#define READCHAR(p) ((char*)(p = (void*)&((char*)p)[1]))[-1] -#define READFIXED(p) readlong(&((fixed_t*)(p = (void*)&((fixed_t*)p)[1]))[-1]) -#define READANGLE(p) readulong(&((angle_t*)(p = (void*)&((angle_t*)p)[1]))[-1]) +#define READUINT8(p) ((const UINT8*)(p = (const void*)&((const UINT8*)p)[1]))[-1] +#define READSINT8(p) ((const SINT8*)(p = (const void*)&((const SINT8*)p)[1]))[-1] +#define READINT16(p) readshort(&((const INT16*)(p = (const void*)&((const INT16*)p)[1]))[-1]) +#define READUINT16(p) readushort(&((const UINT16*)(p = (const void*)&((const UINT16*)p)[1]))[-1]) +#define READINT32(p) readlong(&((const INT32*)(p = (const void*)&((const INT32*)p)[1]))[-1]) +#define READUINT32(p) readulong(&((const UINT32*)(p = (const void*)&((const UINT32*)p)[1])) +#define READCHAR(p) ((const char*)(p = (const void*)&((const char*)p)[1]))[-1] +#define READFIXED(p) readlong(&((const fixed_t*)(p = (const void*)&((const fixed_t*)p)[1]))[-1]) +#define READANGLE(p) readulong(&((const angle_t*)(p = (const void*)&((const angle_t*)p)[1]))[-1]) #endif //SRB2_BIG_ENDIAN #define WRITESTRINGN(p, s, n) do { \ diff --git a/src/command.c b/src/command.c index eae29f07f..ba93a592a 100644 --- a/src/command.c +++ b/src/command.c @@ -281,7 +281,7 @@ char *com_argv[MAX_ARGS]; static const char *com_null_string = ""; static char *com_args = NULL; // current command args or NULL -static void Got_NetVar(UINT8 **p, INT32 playernum); +static void Got_NetVar(const UINT8 **p, INT32 playernum); /** Initializes command buffer and adds basic commands. */ @@ -1500,11 +1500,11 @@ badinput: static boolean serverloading = false; -static void Got_NetVar(UINT8 **p, INT32 playernum) +static void Got_NetVar(const UINT8 **p, INT32 playernum) { consvar_t *cvar; UINT16 netid; - char *svalue; + const char *svalue; UINT8 stealth = false; if (playernum != serverplayer && !IsPlayerAdmin(playernum) && !serverloading) @@ -1518,9 +1518,10 @@ static void Got_NetVar(UINT8 **p, INT32 playernum) } return; } + netid = READUINT16(*p); cvar = CV_FindNetVar(netid); - svalue = (char *)*p; + svalue = (const char *)*p; SKIPSTRING(*p); stealth = READUINT8(*p); @@ -1576,8 +1577,9 @@ void CV_SaveNetVars(UINT8 **p, boolean isdemorecording) WRITEUINT16(count_p, count); } -void CV_LoadNetVars(UINT8 **p) +size_t CV_LoadNetVars(const UINT8 *bufstart) { + const UINT8 *p = bufstart; consvar_t *cvar; UINT16 count; @@ -1588,11 +1590,13 @@ void CV_LoadNetVars(UINT8 **p) if (cvar->flags & CV_NETVAR) Setvalue(cvar, cvar->defaultvalue, true); - count = READUINT16(*p); + count = READUINT16(p); while (count--) - Got_NetVar(p, 0); + Got_NetVar(&p, 0); serverloading = false; + + return p - bufstart; } static void CV_SetCVar(consvar_t *var, const char *value, boolean stealth); diff --git a/src/command.h b/src/command.h index 6d1944f9a..7074158e1 100644 --- a/src/command.h +++ b/src/command.h @@ -182,7 +182,7 @@ void CV_SaveVariables(FILE *f); // load/save gamesate (load and save option and for network join in game) void CV_SaveNetVars(UINT8 **p, boolean isdemorecording); -void CV_LoadNetVars(UINT8 **p); +size_t CV_LoadNetVars(const UINT8 *p); // reset cheat netvars after cheats is deactivated void CV_ResetCheatNetVars(void); diff --git a/src/d_clisrv.c b/src/d_clisrv.c index aed5ee347..5bc5b6d5e 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -312,9 +312,9 @@ static inline tic_t ExpandTics(INT32 low, tic_t basetic) // Some extra data function for handle textcmd buffer // ----------------------------------------------------------------- -static void (*listnetxcmd[MAXNETXCMD])(UINT8 **p, INT32 playernum); +static void (*listnetxcmd[MAXNETXCMD])(const UINT8 **p, INT32 playernum); -void RegisterNetXCmd(netxcmd_t id, void (*cmd_f)(UINT8 **p, INT32 playernum)) +void RegisterNetXCmd(netxcmd_t id, void (*cmd_f)(const UINT8 **p, INT32 playernum)) { #ifdef PARANOIA if (id >= MAXNETXCMD) @@ -460,12 +460,12 @@ static void ExtraDataTicker(void) { if (playeringame[i] || i == 0) { - UINT8 *bufferstart = D_GetExistingTextcmd(gametic, i); + const UINT8 *bufferstart = D_GetExistingTextcmd(gametic, i); if (bufferstart) { - UINT8 *curpos = bufferstart; - UINT8 *bufferend = &curpos[curpos[0]+1]; + const UINT8 *curpos = bufferstart; + const UINT8 *bufferend = &curpos[curpos[0]+1]; curpos++; while (curpos < bufferend) @@ -3756,7 +3756,7 @@ static void Command_Kick(void) CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n")); } -static void Got_KickCmd(UINT8 **p, INT32 playernum) +static void Got_KickCmd(const UINT8 **p, INT32 playernum) { INT32 pnum, msg; char buf[3 + MAX_REASONLENGTH]; @@ -4146,8 +4146,8 @@ consvar_t cv_connectawaittime = {"connectawaittime", "5", CV_SAVE, connectawaitt consvar_t cv_serverinfoscreen = {"serverinfoscreen", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -static void Got_AddPlayer(UINT8 **p, INT32 playernum); -static void Got_RemovePlayer(UINT8 **p, INT32 playernum); +static void Got_AddPlayer(const UINT8 **p, INT32 playernum); +static void Got_RemovePlayer(const UINT8 **p, INT32 playernum); static void Joinable_OnChange(void) { @@ -4399,7 +4399,7 @@ static inline void SV_AddNode(INT32 node) } // Xcmd XD_ADDPLAYER -static void Got_AddPlayer(UINT8 **p, INT32 playernum) +static void Got_AddPlayer(const UINT8 **p, INT32 playernum) { INT16 node, newplayernum; UINT8 splitscreenplayer = 0; @@ -4486,7 +4486,7 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) } // Xcmd XD_REMOVEPLAYER -static void Got_RemovePlayer(UINT8 **p, INT32 playernum) +static void Got_RemovePlayer(const UINT8 **p, INT32 playernum) { SINT8 pnum, reason; @@ -5226,7 +5226,7 @@ static void PT_ServerCFG(SINT8 node) scp = netbuffer->u.servercfg.varlengthinputs; CV_LoadPlayerNames(&scp); - CV_LoadNetVars(&scp); + scp += CV_LoadNetVars(scp); /// \note Wait. What if a Lua script uses some global custom variables synched with the NetVars hook? /// Shouldn't them be downloaded even at intermission time? diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 74bed4cdb..91074af63 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -604,7 +604,7 @@ extern consvar_t cv_serverinfoscreen; void D_ClientServerInit(void); // Initialise the other field -void RegisterNetXCmd(netxcmd_t id, void (*cmd_f)(UINT8 **p, INT32 playernum)); +void RegisterNetXCmd(netxcmd_t id, void (*cmd_f)(const UINT8 **p, INT32 playernum)); void SendNetXCmdForPlayer(UINT8 playerid, netxcmd_t id, const void *param, size_t nparam); #define SendNetXCmd(id, param, nparam) SendNetXCmdForPlayer(0, id, param, nparam) // Shortcut for P1 void SendKick(UINT8 playernum, UINT8 msg); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 86c9b12b1..2b334d048 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -68,22 +68,22 @@ // protos // ------ -static void Got_NameAndColor(UINT8 **cp, INT32 playernum); -static void Got_WeaponPref(UINT8 **cp, INT32 playernum); -static void Got_Mapcmd(UINT8 **cp, INT32 playernum); -static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum); -static void Got_SetupVotecmd(UINT8 **cp, INT32 playernum); -static void Got_ModifyVotecmd(UINT8 **cp, INT32 playernum); -static void Got_PickVotecmd(UINT8 **cp, INT32 playernum); -static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum); -static void Got_Addfilecmd(UINT8 **cp, INT32 playernum); -static void Got_Pause(UINT8 **cp, INT32 playernum); -static void Got_Respawn(UINT8 **cp, INT32 playernum); -static void Got_RandomSeed(UINT8 **cp, INT32 playernum); -static void Got_RunSOCcmd(UINT8 **cp, INT32 playernum); -static void Got_Teamchange(UINT8 **cp, INT32 playernum); -static void Got_Clearscores(UINT8 **cp, INT32 playernum); -static void Got_DiscordInfo(UINT8 **cp, INT32 playernum); +static void Got_NameAndColor(const UINT8 **cp, INT32 playernum); +static void Got_WeaponPref(const UINT8 **cp, INT32 playernum); +static void Got_Mapcmd(const UINT8 **cp, INT32 playernum); +static void Got_ExitLevelcmd(const UINT8 **cp, INT32 playernum); +static void Got_SetupVotecmd(const UINT8 **cp, INT32 playernum); +static void Got_ModifyVotecmd(const UINT8 **cp, INT32 playernum); +static void Got_PickVotecmd(const UINT8 **cp, INT32 playernum); +static void Got_RequestAddfilecmd(const UINT8 **cp, INT32 playernum); +static void Got_Addfilecmd(const UINT8 **cp, INT32 playernum); +static void Got_Pause(const UINT8 **cp, INT32 playernum); +static void Got_Respawn(const UINT8 **cp, INT32 playernum); +static void Got_RandomSeed(const UINT8 **cp, INT32 playernum); +static void Got_RunSOCcmd(const UINT8 **cp, INT32 playernum); +static void Got_Teamchange(const UINT8 **cp, INT32 playernum); +static void Got_Clearscores(const UINT8 **cp, INT32 playernum); +static void Got_DiscordInfo(const UINT8 **cp, INT32 playernum); static void PointLimit_OnChange(void); static void TimeLimit_OnChange(void); @@ -178,13 +178,13 @@ static void Command_Clearscores_f(void); // Remote Administration static void Command_Changepassword_f(void); static void Command_Login_f(void); -static void Got_Login(UINT8 **cp, INT32 playernum); -static void Got_Verification(UINT8 **cp, INT32 playernum); -static void Got_Removal(UINT8 **cp, INT32 playernum); +static void Got_Login(const UINT8 **cp, INT32 playernum); +static void Got_Verification(const UINT8 **cp, INT32 playernum); +static void Got_Removal(const UINT8 **cp, INT32 playernum); static void Command_Verify_f(void); static void Command_RemoveAdmin_f(void); static void Command_MotD_f(void); -static void Got_MotD_f(UINT8 **cp, INT32 playernum); +static void Got_MotD_f(const UINT8 **cp, INT32 playernum); static void Command_ShowScores_f(void); static void Command_ShowTime_f(void); @@ -1913,7 +1913,7 @@ static void SendNameAndColor4(void) SendNetXCmdForPlayer(3, XD_NAMEANDCOLOR, buf, p - buf); } -static void Got_NameAndColor(UINT8 **cp, INT32 playernum) +static void Got_NameAndColor(const UINT8 **cp, INT32 playernum) { player_t *p = &players[playernum]; char name[MAXPLAYERNAME+1]; @@ -2041,15 +2041,17 @@ void SendWeaponPref4(void) SendNetXCmdForPlayer(3, XD_WEAPONPREF, buf, 1); } -static void Got_WeaponPref(UINT8 **cp,INT32 playernum) +static void Got_WeaponPref(const UINT8 **cp, INT32 playernum) { + player_t *player = &players[playernum]; + UINT8 prefs = READUINT8(*cp); - players[playernum].pflags &= ~(PF_FLIPCAM|PF_ANALOGMODE); + player->pflags &= ~(PF_FLIPCAM|PF_ANALOGMODE); if (prefs & 1) - players[playernum].pflags |= PF_FLIPCAM; + player->pflags |= PF_FLIPCAM; if (prefs & 2) - players[playernum].pflags |= PF_ANALOGMODE; + player->pflags |= PF_ANALOGMODE; } void D_SendPlayerConfig(void) @@ -2848,7 +2850,7 @@ static void Command_Map_f(void) * ::serverplayer or ::adminplayer. * \sa D_MapChange */ -static void Got_Mapcmd(UINT8 **cp, INT32 playernum) +static void Got_Mapcmd(const UINT8 **cp, INT32 playernum) { char mapname[MAX_WADPATH+1]; UINT8 flags; @@ -2967,7 +2969,7 @@ static void Command_Pause(void) CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n")); } -static void Got_Pause(UINT8 **cp, INT32 playernum) +static void Got_Pause(const UINT8 **cp, INT32 playernum) { UINT8 dedicatedpause = false; const char *playername; @@ -3079,7 +3081,7 @@ static void Command_Respawn(void) SendNetXCmd(XD_RESPAWN, &buf, 4); } -static void Got_Respawn(UINT8 **cp, INT32 playernum) +static void Got_Respawn(const UINT8 **cp, INT32 playernum) { INT32 respawnplayer = READINT32(*cp); @@ -3114,7 +3116,7 @@ static void Got_Respawn(UINT8 **cp, INT32 playernum) * \param playernum Player responsible for the message. Must be ::serverplayer. * \author Graue */ -static void Got_RandomSeed(UINT8 **cp, INT32 playernum) +static void Got_RandomSeed(const UINT8 **cp, INT32 playernum) { UINT32 seed; @@ -3149,7 +3151,7 @@ static void Command_Clearscores_f(void) * \sa XD_CLEARSCORES, Command_Clearscores_f * \author SSNTails */ -static void Got_Clearscores(UINT8 **cp, INT32 playernum) +static void Got_Clearscores(const UINT8 **cp, INT32 playernum) { INT32 i; @@ -3666,7 +3668,7 @@ static void Command_ServerTeamChange_f(void) } //todo: This and the other teamchange functions are getting too long and messy. Needs cleaning. -static void Got_Teamchange(UINT8 **cp, INT32 playernum) +static void Got_Teamchange(const UINT8 **cp, INT32 playernum) { changeteam_union NetPacket; boolean error = false, wasspectator = false; @@ -4023,7 +4025,7 @@ static void Command_Login_f(void) #endif } -static void Got_Login(UINT8 **cp, INT32 playernum) +static void Got_Login(const UINT8 **cp, INT32 playernum) { #ifdef NOMD5 // If we have no MD5 support then completely disable XD_LOGIN responses for security. @@ -4133,7 +4135,7 @@ static void Command_Verify_f(void) SendNetXCmd(XD_VERIFIED, buf, 1); } -static void Got_Verification(UINT8 **cp, INT32 playernum) +static void Got_Verification(const UINT8 **cp, INT32 playernum) { INT16 num = READUINT8(*cp); @@ -4185,7 +4187,7 @@ static void Command_RemoveAdmin_f(void) SendNetXCmd(XD_DEMOTED, buf, 1); } -static void Got_Removal(UINT8 **cp, INT32 playernum) +static void Got_Removal(const UINT8 **cp, INT32 playernum) { INT16 num = READUINT8(*cp); @@ -4261,7 +4263,7 @@ static void Command_MotD_f(void) Z_Free(mymotd); } -static void Got_MotD_f(UINT8 **cp, INT32 playernum) +static void Got_MotD_f(const UINT8 **cp, INT32 playernum) { char *mymotd = Z_Malloc(sizeof(motd), PU_STATIC, NULL); INT32 i; @@ -4328,7 +4330,7 @@ static void Command_RunSOC(void) SendNetXCmd(XD_RUNSOC, buf, length); } -static void Got_RunSOCcmd(UINT8 **cp, INT32 playernum) +static void Got_RunSOCcmd(const UINT8 **cp, INT32 playernum) { char filename[256]; filestatus_t ncs = FS_NOTCHECKED; @@ -4606,7 +4608,7 @@ static void Command_GLocalSkin (void) } } -static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum) +static void Got_RequestAddfilecmd(const UINT8 **cp, INT32 playernum) { char filename[241]; filestatus_t ncs = FS_NOTCHECKED; @@ -4665,7 +4667,7 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum) COM_BufAddText(va("addfile %s\n", filename)); } -static void Got_Addfilecmd(UINT8 **cp, INT32 playernum) +static void Got_Addfilecmd(const UINT8 **cp, INT32 playernum) { char filename[241]; filestatus_t ncs = FS_NOTCHECKED; @@ -5465,7 +5467,7 @@ static void Command_ExitLevel_f(void) SendNetXCmd(XD_EXITLEVEL, NULL, 0); } -static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum) +static void Got_ExitLevelcmd(const UINT8 **cp, INT32 playernum) { (void)cp; @@ -5486,7 +5488,7 @@ static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum) G_ExitLevel(); } -static void Got_SetupVotecmd(UINT8 **cp, INT32 playernum) +static void Got_SetupVotecmd(const UINT8 **cp, INT32 playernum) { INT32 i; UINT8 gt, secondgt; @@ -5538,7 +5540,7 @@ static void Got_SetupVotecmd(UINT8 **cp, INT32 playernum) Y_StartVote(); } -static void Got_ModifyVotecmd(UINT8 **cp, INT32 playernum) +static void Got_ModifyVotecmd(const UINT8 **cp, INT32 playernum) { SINT8 voted = READSINT8(*cp); UINT8 p = READUINT8(*cp); @@ -5547,7 +5549,7 @@ static void Got_ModifyVotecmd(UINT8 **cp, INT32 playernum) votes[p] = voted; } -static void Got_PickVotecmd(UINT8 **cp, INT32 playernum) +static void Got_PickVotecmd(const UINT8 **cp, INT32 playernum) { SINT8 pick = READSINT8(*cp); SINT8 level = READSINT8(*cp); @@ -6187,7 +6189,7 @@ static void KartEliminateLast_OnChange(void) P_CheckRacers(); } -void Got_DiscordInfo(UINT8 **p, INT32 playernum) +void Got_DiscordInfo(const UINT8 **p, INT32 playernum) { if (playernum != serverplayer /*&& !IsPlayerAdmin(playernum)*/) { diff --git a/src/g_demo.c b/src/g_demo.c index bd3905160..f5268ad02 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -2815,7 +2815,7 @@ void G_DoPlayDemo(char *defdemoname) } // net var data - CV_LoadNetVars(&demobuf.p); + demobuf.p += CV_LoadNetVars(demobuf.p); // Sigh ... it's an empty demo. if (*demobuf.p == DEMOMARKER) @@ -2853,7 +2853,7 @@ void G_DoPlayDemo(char *defdemoname) #endif // net var data - CV_LoadNetVars(&demobuf.p); + demobuf.p += CV_LoadNetVars(demobuf.p); // Sigh ... it's an empty demo. if (*demobuf.p == DEMOMARKER) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 0e29a5124..955bebb2f 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -280,7 +280,7 @@ static void Command_Say_f(void); static void Command_Sayto_f(void); static void Command_Sayteam_f(void); static void Command_CSay_f(void); -static void Got_Saycmd(UINT8 **p, INT32 playernum); +static void Got_Saycmd(const UINT8 **p, INT32 playernum); void HU_LoadGraphics(void) { @@ -879,11 +879,12 @@ const char *HU_SkinColorToConsoleColor(skincolors_t color) * \sa DoSayCommand * \author Graue */ -static void Got_Saycmd(UINT8 **p, INT32 playernum) +static void Got_Saycmd(const UINT8 **p, INT32 playernum) { SINT8 target; UINT8 flags; const char *dispname; + char buf[HU_MAXMSGLEN + 1]; char *msg; boolean action = false; char *ptr; @@ -893,8 +894,8 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) target = READSINT8(*p); flags = READUINT8(*p); - msg = (char *)*p; - SKIPSTRINGL(*p, HU_MAXMSGLEN + 1); + msg = buf; + READSTRINGL(*p, msg, HU_MAXMSGLEN + 1); if ((cv_mute.value || flags & (HU_CSAY|HU_SERVER_SAY)) && playernum != serverplayer && !(IsPlayerAdmin(playernum))) { diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index ee5de8356..9a89361a8 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -36,7 +36,7 @@ static void clear_lua_stack(void) lua_settop(gL, 0); // clear stack } -void Got_Luacmd(UINT8 **cp, INT32 playernum) +void Got_Luacmd(const UINT8 **cp, INT32 playernum) { UINT8 i, argc, flags; const char *argv[256]; diff --git a/src/lua_script.h b/src/lua_script.h index f1b58cced..35dd5b364 100644 --- a/src/lua_script.h +++ b/src/lua_script.h @@ -76,7 +76,7 @@ void LUA_InvalidatePlayer(player_t *player); void LUA_Archive(savebuffer_t *save, boolean network); void LUA_UnArchive(savebuffer_t *save, boolean network); -void Got_Luacmd(UINT8 **cp, INT32 playernum); // lua_consolelib.c +void Got_Luacmd(const UINT8 **cp, INT32 playernum); // lua_consolelib.c void LUA_CVarChanged(void *cvar); // lua_consolelib.c int Lua_optoption(lua_State *L, int narg, int def, int list_ref); int Lua_CreateFieldTable(lua_State *L, const char *const lst[]); diff --git a/src/p_saveg.c b/src/p_saveg.c index 65b15ec8e..9b7ff7776 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -3772,7 +3772,7 @@ boolean P_LoadGame(savebuffer_t *save, INT16 mapoverride) boolean P_LoadNetGame(savebuffer_t *save, boolean reloading) { - CV_LoadNetVars(&save->p); + save->p += CV_LoadNetVars(save->p); if (!P_NetUnArchiveMisc(save, reloading)) return false; diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 646d44135..e4e21949b 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -266,13 +266,13 @@ void I_UpdateSound(void) // this is as fast as I can possibly make it. // sorry. more asm needed. -static Mix_Chunk *ds2chunk(void *stream) +static Mix_Chunk *ds2chunk(const void *stream) { UINT16 ver, freq; UINT32 samples, i, newsamples; UINT8 *sound; - SINT8 *s; + const SINT8 *s; INT16 *d; INT16 o; fixed_t step, frac; @@ -325,7 +325,7 @@ static Mix_Chunk *ds2chunk(void *stream) sound = Z_Malloc(newsamples<<2, PU_SOUND, NULL); // samples * frequency shift * bytes per sample * channels - s = (SINT8 *)stream; + s = (const SINT8 *)stream; d = (INT16 *)sound; i = 0; -- 2.54.0 From aeb172f2abd858d19b5a4d1eaaa09d0d84ba21fd Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 1 Nov 2025 22:35:34 +0100 Subject: [PATCH 203/219] do some smol cleanup r_skins mostly style fixes, some minor caching for some things --- src/r_skins.c | 228 +++++++++++++++++++++++++++----------------------- 1 file changed, 124 insertions(+), 104 deletions(-) diff --git a/src/r_skins.c b/src/r_skins.c index 9d289f936..bf731f708 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -33,7 +33,7 @@ #include "qs22j.h" -CV_PossibleValue_t Forceskin_cons_t[MAXSKINS+2]; +CV_PossibleValue_t Forceskin_cons_t[MAXSKINS+2]; // huehuehuehuehue #include "discord.h" @@ -41,6 +41,7 @@ INT32 numskins = 0; INT32 numallskins = 0; INT32 numlocalskins = 0; skin_t skins[MAXSKINS]; + UINT8 skinstats[9][9][MAXSKINS]; UINT8 skinstatscount[9][9] = { {0, 0, 0, 0, 0, 0, 0, 0, 0}, @@ -53,6 +54,7 @@ UINT8 skinstatscount[9][9] = { {0, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0} }; + UINT8 skinsorted[MAXSKINS]; skin_t localskins[MAXLOCALSKINS]; skin_t allskins[MAXSKINS+MAXLOCALSKINS]; @@ -71,12 +73,13 @@ static void Sk_SetDefaultValue(skin_t *skin, boolean local) // set default skin values // memset(skin, 0, sizeof (skin_t)); + snprintf(skin->name, sizeof skin->name, "skin %u", K_GetMobjSkinNum(skin, local)); skin->name[sizeof skin->name - 1] = '\0'; - skin->wadnum = INT16_MAX; - strcpy(skin->sprite, ""); - skin->flags = 0; + skin->wadnum = INT16_MAX; + + strcpy(skin->sprite, ""); strcpy(skin->realname, "Someone"); strcpy(skin->hudname, "???"); @@ -95,8 +98,12 @@ static void Sk_SetDefaultValue(skin_t *skin, boolean local) skin->highresscale = FRACUNIT>>1; for (i = 0; i < sfx_skinsoundslot0; i++) - if (S_sfx[i].skinsound != -1) - skin->soundsid[S_sfx[i].skinsound] = i; + { + const INT32 skinsound = S_sfx[i].skinsound; + + if (skinsound != -1) + skin->soundsid[skinsound] = i; + } } // @@ -124,6 +131,7 @@ void R_InitSkins(void) skin = &skins[0]; numskins = 1; Sk_SetDefaultValue(skin, false); + memset(skinstats, 0, sizeof(skinstats)); memset(skinsorted, 0, sizeof(skinsorted)); @@ -132,13 +140,16 @@ void R_InitSkins(void) #ifdef SKINVALUES skin_cons_t[0].strvalue = skins[0].name; #endif - skin->flags = 0; + strcpy(skin->realname, "Sonic"); strcpy(skin->hudname, "SONIC"); strncpy(skin->facerank, "PLAYRANK", 9); strncpy(skin->facewant, "PLAYWANT", 9); strncpy(skin->facemmap, "PLAYMMAP", 9); + + skin->flags = 0; + skin->wadnum = 0; // god what have you brought to this world skin->prefcolor = SKINCOLOR_BLUE; skin->localskin = false; @@ -177,9 +188,10 @@ INT32 R_SkinAvailable(const char *name) for (i = 0; i < numskins; i++) { - if (stricmp(skins[i].name,name) == 0) + if (stricmp(skins[i].name, name) == 0) return i; } + return -1; } @@ -191,9 +203,10 @@ INT32 R_AnySkinAvailable(const char *name) for (i = 0; i < numallskins; i++) { - if (stricmp(allskins[i].name,name) == 0) + if (stricmp(allskins[i].name, name) == 0) return i; } + return -1; } @@ -205,20 +218,20 @@ INT32 R_LocalSkinAvailable(const char *name, boolean local) { for (i = 0; i < numlocalskins; i++) { - if (stricmp(localskins[i].name,name) == 0) + if (stricmp(localskins[i].name, name) == 0) return i; } + return -1; } - else - return R_SkinAvailable(name); + + return R_SkinAvailable(name); } // network code calls this when a 'skin change' is received boolean SetPlayerSkin(INT32 playernum, const char *skinname) { INT32 i; - player_t *player = &players[playernum]; for (i = 0; i < numskins; i++) { @@ -230,7 +243,7 @@ boolean SetPlayerSkin(INT32 playernum, const char *skinname) } } - if (P_IsLocalPlayer(player)) + if (P_IsLocalPlayer(&players[playernum])) CONS_Alert(CONS_WARNING, M_GetText("Skin '%s' not found.\n"), skinname); else if (server || IsPlayerAdmin(consoleplayer)) CONS_Alert(CONS_WARNING, M_GetText("Player %d (%s) skin '%s' not found\n"), playernum, player_names[playernum], skinname); @@ -253,6 +266,7 @@ void SetLocalPlayerSkin(INT32 playernum, const char *skinname, consvar_t *cvar) { player->localskin = 1 + i; player->skinlocal = true; + if (player->mo) { player->mo->localskin = &localskins[i]; @@ -270,6 +284,7 @@ void SetLocalPlayerSkin(INT32 playernum, const char *skinname, consvar_t *cvar) { player->localskin = 1 + i; player->skinlocal = false; + if (player->mo) { player->mo->localskin = &skins[i]; @@ -284,6 +299,7 @@ void SetLocalPlayerSkin(INT32 playernum, const char *skinname, consvar_t *cvar) { player->localskin = 0; player->skinlocal = false; + if (player->mo) { player->mo->localskin = 0; @@ -318,6 +334,7 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) if (skinnum >= 0 && skinnum < numskins) // Make sure it exists! { player->skin = skinnum; + if (player->mo) player->mo->skin = skin; @@ -360,117 +377,97 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) static UINT16 W_CheckForSkinMarkerInPwad(UINT16 wadid, UINT16 startlump) { UINT16 i; - const char *S_SKIN = "S_SKIN"; lumpinfo_t *lump_p; // scan forward, start at if (startlump < wadfiles[wadid]->numlumps) { lump_p = wadfiles[wadid]->lumpinfo + startlump; + for (i = startlump; i < wadfiles[wadid]->numlumps; i++, lump_p++) - if (memcmp(lump_p->name,S_SKIN,6)==0) + { + if (memcmp(lump_p->name, "S_SKIN", 6) == 0) return i; + } } + return INT16_MAX; // not found } //sort function for sorting skin names -static int skinSortFunc(const void *a, const void *b) //tbh i have no clue what the naming conventions for local functions are +static int skinSortFunc(const void *a, const void *b) // tbh i have no clue what the naming conventions for local functions are { - const skin_t *in1 = &skins[*(const UINT8 *)a]; - const skin_t *in2 = &skins[*(const UINT8 *)b]; - INT32 temp = 0; - const UINT8 val_a = *((const UINT8 *)a); - const UINT8 val_b = *((const UINT8 *)b); + int diff = 0; + const UINT8 val_a = *(const UINT8 *)a; + const UINT8 val_b = *(const UINT8 *)b; + const skin_t *in1 = &skins[val_a]; + const skin_t *in2 = &skins[val_b]; - //return (strcmp(in1->realname, in2->realname) < 0) || (strcmp(in1->realname, in2->realname) ==); + // return (strcmp(in1->realname, in2->realname) < 0) || (strcmp(in1->realname, in2->realname) ==); switch (cv_skinselectgridsort.value) { case SKINMENUSORT_REALNAME: - //CONS_Printf("Sorting by realname\n"); + // CONS_Printf("Sorting by realname\n"); // check name - if ((temp = strcmp(in1->realname, in2->realname))) - return temp; - // sort by internal name - return strcmp(in1->name, in2->name); - break; + diff = strcmp(in1->realname, in2->realname); + if (diff != 0) return diff; - case SKINMENUSORT_NAME: - //CONS_Printf("Sorting by name\n"); - return strcmp(in1->name, in2->name); break; - case SKINMENUSORT_SPEED: - //CONS_Printf("Sorting by speed\n"); + // CONS_Printf("Sorting by speed\n"); // check speed - if (in1->kartspeed < in2->kartspeed) - return -1; - else if (in2->kartspeed < in1->kartspeed) - return 1; + diff = in1->kartspeed - in2->kartspeed; + if (diff != 0) return diff; + // then check weight - if (in1->kartweight < in2->kartweight) - return -1; - else if (in2->kartweight < in1->kartweight) - return 1; - // then check name - if ((temp = strcmp(in1->realname, in2->realname))) - return temp; - // sort by internal name - return strcmp(in1->name, in2->name); - break; + diff = in1->kartweight - in2->kartweight; + if (diff != 0) return diff; + // then check name + diff = strcmp(in1->realname, in2->realname); + if (diff != 0) return diff; + + break; case SKINMENUSORT_WEIGHT: - //CONS_Printf("Sorting by weight\n"); + // CONS_Printf("Sorting by weight\n"); // check weight - if (in1->kartweight < in2->kartweight) - return -1; - else if (in2->kartweight < in1->kartweight) - return 1; + diff = in1->kartweight - in2->kartweight; + if (diff != 0) return diff; + // then check speed - if (in1->kartspeed < in2->kartspeed) - return -1; - else if (in2->kartspeed < in1->kartspeed) - return 1; - // then check name - if ((temp = strcmp(in1->realname, in2->realname))) - return temp; - // sort by internal name - return strcmp(in1->name, in2->name); - break; + diff = in1->kartspeed - in2->kartspeed; + if (diff != 0) return diff; + // then check name + diff = strcmp(in1->realname, in2->realname); + if (diff != 0) return diff; + + break; case SKINMENUSORT_PREFCOLOR: - //CONS_Printf("Sorting by prefcolor\n"); + // CONS_Printf("Sorting by prefcolor\n"); // check prefcolor - if (in1->prefcolor < in2->prefcolor) - return -1; - else if (in2->prefcolor < in1->prefcolor) - return 1; + diff = in1->prefcolor - in2->prefcolor; + if (diff != 0) return diff; + // then check name - if ((temp = strcmp(in1->realname, in2->realname))) - return temp; - // sort by internal name - return strcmp(in1->name, in2->name); + diff = strcmp(in1->realname, in2->realname); + if (diff != 0) return diff; + break; - case SKINMENUSORT_ID: - //CONS_Printf("Sorting by id\n"); - //how do i do by ID????? - //wait why dont i just convert the inputs to UINT32s - //please tell me im allowed to define variables in here since its a block - - if (val_a == val_b) - return 0; - else if (val_a < val_b) - return -1; - else - return 1; - + // CONS_Printf("Sorting by id\n"); + // how do i do by ID????? + // wait why dont i just convert the inputs to UINT32s + // please tell me im allowed to define variables in here since its a block + return (int)val_a - (int)val_b; + case SKINMENUSORT_NAME: default: - return strcmp(in1->name, in2->name); break; } - //im scared this somehow will sometimes end up here so im gonna add this here just to be safe + + // im scared this somehow will sometimes end up here so im gonna add this here just to be safe + // now it will often end up here >:3 return strcmp(in1->name, in2->name); } @@ -531,6 +528,7 @@ void R_AddSkins(UINT16 wadnum, boolean local) Sk_SetDefaultValue(skin, local); skin->wadnum = wadnum; hudname = realname = false; + // parse stoken = strtok (buf2, "\r\n= "); while (stoken) @@ -562,18 +560,18 @@ void R_AddSkins(UINT16 wadnum, boolean local) // using the default skin name's number set above else { - const size_t stringspace = - strlen(value) + sizeof lnumskins + 1; + const size_t stringspace = strlen(value) + sizeof lnumskins + 1; char *value2 = Z_Malloc(stringspace, PU_STATIC, NULL); - snprintf(value2, stringspace, - "%s%d", value, lnumskins); + + snprintf(value2, stringspace, "%s%d", value, lnumskins); value2[stringspace - 1] = '\0'; + if (R_LocalSkinAvailable(value2, local) == -1) { - STRBUFCPY(skin->name, - value2); + STRBUFCPY(skin->name, value2); strlwr(skin->name); } + Z_Free(value2); } @@ -589,6 +587,7 @@ void R_AddSkins(UINT16 wadnum, boolean local) { STRBUFCPY(skin->hudname, skin->name); strupr(skin->hudname); + for (value = skin->hudname; *value; value++) if (*value == '_') *value = ' '; // turn _ into spaces. } @@ -597,8 +596,10 @@ void R_AddSkins(UINT16 wadnum, boolean local) { // Display name (eg. "Knuckles") realname = true; STRBUFCPY(skin->realname, value); + for (value = skin->realname; *value; value++) if (*value == '_') *value = ' '; // turn _ into spaces. + if (!hudname) STRBUFCPY(skin->hudname, skin->realname); } @@ -606,12 +607,13 @@ void R_AddSkins(UINT16 wadnum, boolean local) { // Life icon name (eg. "K.T.E") hudname = true; STRBUFCPY(skin->hudname, value); + for (value = skin->hudname; *value; value++) if (*value == '_') *value = ' '; // turn _ into spaces. + if (!realname) STRBUFCPY(skin->realname, skin->hudname); } - else if (!stricmp(stoken, "sprite")) { strupr(value); @@ -642,6 +644,7 @@ void R_AddSkins(UINT16 wadnum, boolean local) else if (!stricmp(stoken, "kartspeed")) { skin->kartspeed = atoi(value); + if (skin->kartspeed < 1) skin->kartspeed = 1; if (skin->kartspeed > 9) @@ -650,6 +653,7 @@ void R_AddSkins(UINT16 wadnum, boolean local) else if (!stricmp(stoken, "kartweight")) { skin->kartweight = atoi(value); + if (skin->kartweight < 1) skin->kartweight = 1; if (skin->kartweight > 9) @@ -657,47 +661,60 @@ void R_AddSkins(UINT16 wadnum, boolean local) } // custom translation table else if (!stricmp(stoken, "startcolor")) + { skin->starttranscolor = atoi(value); + } else if (!stricmp(stoken, "prefcolor")) + { skin->prefcolor = K_GetKartColorByName(value); + } else if (!stricmp(stoken, "highresscale")) + { skin->highresscale = FLOAT_TO_FIXED(atof(value)); + } else { INT32 found = false; sfxenum_t i; + // copy name of sounds that are remapped // for this skin for (i = 0; i < sfx_skinsoundslot0; i++) { - if (!S_sfx[i].name) + const sfxinfo_t *sfx = &S_sfx[i]; + + if (!sfx->name) continue; - if (S_sfx[i].skinsound != -1 - && !stricmp(S_sfx[i].name, - stoken + 2)) + + if (sfx->skinsound != -1 + && !stricmp(sfx->name, stoken + 2)) { - skin->soundsid[S_sfx[i].skinsound] = - S_AddSoundFx(value+2, S_sfx[i].singularity, S_sfx[i].pitch, true); + skin->soundsid[sfx->skinsound] = S_AddSoundFx(value+2, sfx->singularity, sfx->pitch, true); found = true; } } + if (!found) CONS_Debug(DBG_SETUP, "R_AddSkins: Unknown keyword '%s' in S_SKIN lump# %d (WAD %s)\n", stoken, lump, wadfiles[wadnum]->filename); } stoken = strtok(NULL, "\r\n= "); } + free(buf2); lump++; // if no sprite defined use spirte just after this one + if (skin->sprite[0] == '\0') { const char *csprname = W_CheckNameForNumPwad(wadnum, lump); // skip to end of this skin's frames lastlump = lump; + while (W_CheckNameForNumPwad(wadnum, lastlump) && memcmp(W_CheckNameForNumPwad(wadnum, lastlump), csprname,4)==0) lastlump++; + // allocate (or replace) sprite frames, and set spritedef R_AddSingleSpriteDef(csprname, &skin->spritedef, wadnum, lump, lastlump); } @@ -707,12 +724,15 @@ void R_AddSkins(UINT16 wadnum, boolean local) size_t name; boolean found = false; const char *sprname = skin->sprite; - for (name = 0;sprnames[name][0] != '\0';name++) + + for (name = 0; sprnames[name][0] != '\0'; name++) + { if (strncmp(sprnames[name], sprname, 4) == 0) { - found = true; skin->spritedef = sprites[name]; + found = true; } + } // not found so make a new one // go through the entire current wad looking for our sprite @@ -726,7 +746,7 @@ void R_AddSkins(UINT16 wadnum, boolean local) while ((lname = W_CheckNameForNumPwad(wadnum, localllump))) { // If this is a valid sprite... - if (!memcmp(lname, sprname,4) && lname[4] && lname[5] && lname[5] >= '0' && lname[5] <= '8') + if (!memcmp(lname, sprname, 4) && lname[4] && lname[5] && lname[5] >= '0' && lname[5] <= '8') { if (lstart == UINT16_MAX) lstart = localllump; @@ -741,6 +761,7 @@ void R_AddSkins(UINT16 wadnum, boolean local) } // If not already set do nothing } + ++localllump; } @@ -760,7 +781,6 @@ void R_AddSkins(UINT16 wadnum, boolean local) (local ? localskin_cons_t : skin_cons_t)[lnumskins].value = lnumskins; (local ? localskin_cons_t : skin_cons_t)[lnumskins].strvalue = skin->name; #endif - if (!local) { // Update the forceskin possiblevalues -- 2.54.0 From 871545024d13b48643f6cc91b03758f347c1486b Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 1 Nov 2025 23:15:21 +0100 Subject: [PATCH 204/219] experiment: replace every strcmp with fastcmp did some profiling and in basically every single test fastcmp was twice as fast as strcmp maybe this speeds up some things --- src/blua/lauxlib.c | 6 ++++-- src/blua/lfastcmp.h | 32 ++++++++++++++++++++++++++++++++ src/command.c | 10 +++++----- src/console.c | 2 +- src/d_clisrv.c | 4 ++-- src/d_main.c | 2 +- src/d_netcmd.c | 12 ++++++------ src/d_netfil.c | 28 ++++++++++++++-------------- src/d_protocol.c | 4 ++-- src/dedicated/i_system.c | 4 ++-- src/discord.c | 6 +++--- src/doomdef.h | 2 ++ src/filesrch.c | 10 +++++----- src/g_game.c | 11 +++++++---- src/hardware/hw_main.cpp | 2 +- src/hardware/hw_model.c | 8 ++++---- src/lua_hooklib.c | 6 +++--- src/m_aatree.c | 4 ++-- src/m_menu.c | 22 +++++++++++----------- src/m_perfstats.c | 2 +- src/p_saveg.c | 2 +- src/r_data.c | 15 ++++++++------- src/r_patch.cpp | 8 ++++---- src/sdl/hwsym_sdl.c | 3 --- src/sdl/i_system.cpp | 3 ++- src/sdl/i_video.c | 4 ++-- src/sdl/ogl_sdl.c | 4 ++-- src/v_video.c | 5 ++--- 28 files changed, 129 insertions(+), 92 deletions(-) create mode 100644 src/blua/lfastcmp.h diff --git a/src/blua/lauxlib.c b/src/blua/lauxlib.c index e898e38d6..eacce9b44 100644 --- a/src/blua/lauxlib.c +++ b/src/blua/lauxlib.c @@ -24,6 +24,8 @@ #include "lauxlib.h" +#include "lfastcmp.h" + #define FREELIST_REF 0 /* free list of references */ @@ -40,7 +42,7 @@ LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ return luaL_error(L, "bad argument #%d (%s)", narg, extramsg); lua_getinfo(L, "n", &ar); - if (strcmp(ar.namewhat, "method") == 0) { + if (fastcmp(ar.namewhat, "method")) { narg--; /* do not count `self' */ if (narg == 0) /* error is in the self argument itself? */ return luaL_error(L, "calling " LUA_QS " on bad self (%s)", @@ -97,7 +99,7 @@ LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def, luaL_checkstring(L, narg); int i; for (i=0; lst[i]; i++) - if (strcmp(lst[i], name) == 0) + if (fastcmp(lst[i], name)) return i; return luaL_argerror(L, narg, lua_pushfstring(L, "invalid option " LUA_QS, name)); diff --git a/src/blua/lfastcmp.h b/src/blua/lfastcmp.h new file mode 100644 index 000000000..f25c59896 --- /dev/null +++ b/src/blua/lfastcmp.h @@ -0,0 +1,32 @@ +#ifndef __FASTCMP_H__ +#define __FASTCMP_H__ + +#include +#include + +// same as fastcmp but we cant use our fancy macros + +// returns false if s != c +// returns true if s == c +__attribute__((always_inline)) static inline bool fasticmp(const char *s, const char *c) +{ + for (; *s && toupper(*s) == toupper(*c); s++, c++) ; + return (*s == *c); // make sure both strings ended +} + +// case-sensitive of the above +__attribute__((always_inline)) static inline bool fastcmp(const char *s, const char *c) +{ + for (; *s && *s == *c; s++, c++) ; + return (*s == *c); // make sure both strings ended +} + +// length-limited of the above +// only true if both strings are at least l characters long AND match, case-sensitively! +__attribute__((always_inline)) static inline bool fastncmp(const char *s, const char *c, uint16_t l) +{ + for (; *s && *s == *c && --l; s++, c++) ; + return !l; // make sure you reached the end +} + +#endif diff --git a/src/command.c b/src/command.c index e73125649..676212703 100644 --- a/src/command.c +++ b/src/command.c @@ -879,7 +879,7 @@ static void COM_Help_f(void) { for (cmd = com_commands; cmd; cmd = cmd->next) { - if (strcmp(cmd->name, help)) + if (!fastcmp(cmd->name, help)) continue; CONS_Printf("\x82""Command %s:\n", cmd->name); @@ -1610,7 +1610,7 @@ void CV_ResetCheatNetVars(void) // Returns true if the variable's current value is its default value boolean CV_IsSetToDefault(consvar_t *v) { - return (!(strcmp(v->defaultvalue, v->string))); + return (fastcmp(v->defaultvalue, v->string)); } // If any cheats CVars are not at their default settings, return true. @@ -1622,7 +1622,7 @@ UINT8 CV_CheatsEnabled(void) consvar_t *cvar; for (cvar = consvar_vars; cvar; cvar = cvar->next) - if ((cvar->flags & CV_CHEAT) && strcmp(cvar->defaultvalue, cvar->string)) + if ((cvar->flags & CV_CHEAT) && !fastcmp(cvar->defaultvalue, cvar->string)) return 1; return 0; } @@ -1799,7 +1799,7 @@ void CV_AddValue(consvar_t *var, INT32 increment) } #define MINVAL 0 #define MAXVAL 1 - else if (var->PossibleValue[MINVAL].strvalue && !strcmp(var->PossibleValue[MINVAL].strvalue, "MIN")) + else if (var->PossibleValue[MINVAL].strvalue && fastcmp(var->PossibleValue[MINVAL].strvalue, "MIN")) { // SRB2Kart #ifdef PARANOIA if (!var->PossibleValue[MAXVAL].strvalue) @@ -2139,7 +2139,7 @@ void CV_SaveVariables(FILE *f) char stringtowrite[MAXTEXTCMD+1]; // Silly hack for Min/Max vars - if (!strcmp(cvar->string, "MAX") || !strcmp(cvar->string, "MIN")) + if (fastcmp(cvar->string, "MAX") || fastcmp(cvar->string, "MIN")) { if (cvar->flags & CV_FLOAT) sprintf(stringtowrite, "%f", FixedToFloat(cvar->value)); diff --git a/src/console.c b/src/console.c index 3959d9b98..062e6ebf3 100644 --- a/src/console.c +++ b/src/console.c @@ -1010,7 +1010,7 @@ boolean CON_Responder(event_t *ev) Lock_state(); // Only add command to history if it differs from previous one - if (strcmp(input.buffer, inputlines[(inputline-1) & 31])) + if (!fastcmp(input.buffer, inputlines[(inputline-1) & 31])) { inputline = (inputline+1) & 31; M_TextInputInit(&input, inputlines[inputline], CON_MAXPROMPTCHARS); diff --git a/src/d_clisrv.c b/src/d_clisrv.c index aed5ee347..2ca42df65 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2174,7 +2174,7 @@ static void SL_InsertServer(serverinfo_pak* info, SINT8 node) if (info->subversion != SUBVERSION) return; // Close, but no cigar. - if (strcmp(info->application, SRB2APPLICATION)) + if (!fastcmp(info->application, SRB2APPLICATION)) return;/* that's a different mod */ i = serverlistcount++; @@ -2219,7 +2219,7 @@ void CL_QueryServerList (msg_server_t *server_list) // thwart nefarious servers who lie to the MS. /* lol bruh, that version COMES from the servers */ - //if (strcmp(version, server_list[i].version) == 0) + //if (fastcmp(version, server_list[i].version)) { INT32 node = I_NetMakeNodewPort(server_list[i].ip, server_list[i].port); if (node == -1) diff --git a/src/d_main.c b/src/d_main.c index 032a9189e..fd643213c 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1288,7 +1288,7 @@ static void IdentifyVersion(void) } #if (1) // reduce the amount of findfile by only using full cwd in this func - if (strcmp(tempsrb2path, srb2waddir)) + if (!fastcmp(tempsrb2path, srb2waddir)) #endif { strlcpy(srb2path, srb2waddir, sizeof (srb2path)); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 86c9b12b1..3a5e0ca7e 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1508,9 +1508,9 @@ static void SendNameAndColor(void) CV_StealthSet(&cv_playercolor, cv_playercolor.defaultvalue); } - if (!strcmp(cv_playername.string, player_names[consoleplayer]) + if (fastcmp(cv_playername.string, player_names[consoleplayer]) && cv_playercolor.value == players[consoleplayer].skincolor - && !strcmp(cv_skin.string, skins[players[consoleplayer].skin].name)) + && fastcmp(cv_skin.string, skins[players[consoleplayer].skin].name)) return; // We'll handle it later if we're not playing. @@ -2322,8 +2322,8 @@ static void Command_Playdemo_f(void) CONS_Printf(M_GetText("Playing back demo '%s'.\n"), name); - demo.loadfiles = strcmp(COM_Argv(2), "-addfiles") == 0; - demo.ignorefiles = strcmp(COM_Argv(2), "-force") == 0; + demo.loadfiles = fastcmp(COM_Argv(2), "-addfiles"); + demo.ignorefiles = fastcmp(COM_Argv(2), "-force"); // Internal if no extension, external if one exists // If external, convert the file name to a path in SRB2's home directory @@ -5209,14 +5209,14 @@ static void Ringslinger_OnChange(void) static void Gravity_OnChange(void) { if (!M_SecretUnlocked(SECRET_PANDORA) && !netgame && !cv_debug - && strcmp(cv_gravity.string, cv_gravity.defaultvalue)) + && !fastcmp(cv_gravity.string, cv_gravity.defaultvalue)) { CONS_Printf(M_GetText("You haven't earned this yet.\n")); CV_StealthSet(&cv_gravity, cv_gravity.defaultvalue); return; } #ifndef NETGAME_GRAVITY - if(netgame) + if (netgame) { CV_StealthSet(&cv_gravity, cv_gravity.defaultvalue); return; diff --git a/src/d_netfil.c b/src/d_netfil.c index 5a1272172..f279eaee0 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -946,17 +946,17 @@ void Got_Filetxpak(void) char *filename = file->filename; static INT32 filetime = 0; - if (!(strcmp(filename, "srb2.srb") - //&& strcmp(filename, "srb2.wad") - //&& strcmp(filename, "patch.dta") - //&& strcmp(filename, "music.dta") - && strcmp(filename, "gfx.kart") - && strcmp(filename, "textures.kart") - && strcmp(filename, "chars.kart") - && strcmp(filename, "maps.kart") - && strcmp(filename, "sounds.kart") - && strcmp(filename, "music.kart") - && strcmp(filename, "patch.kart") + if ((fastcmp(filename, "srb2.srb") + //|| fastcmp(filename, "srb2.wad") + //|| fastcmp(filename, "patch.dta") + //|| fastcmp(filename, "music.dta") + || fastcmp(filename, "gfx.kart") + || fastcmp(filename, "textures.kart") + || fastcmp(filename, "chars.kart") + || fastcmp(filename, "maps.kart") + || fastcmp(filename, "sounds.kart") + || fastcmp(filename, "music.kart") + || fastcmp(filename, "patch.kart") )) I_Error("Tried to download \"%s\"", filename); @@ -1197,7 +1197,7 @@ filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean complet } // next, check SRB2's "home" directory (if non-'.') - if (strcmp(srb2home, ".")) + if (!fastcmp(srb2home, ".")) { homecheck = filesearch(filename, srb2home, wantedmd5sum, completepath, 10); @@ -1209,7 +1209,7 @@ filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean complet } // next, check SRB2's "path" directory (also if non-'.') - if (strcmp(srb2path, ".")) + if (!fastcmp(srb2path, ".")) { homecheck = filesearch(filename, srb2path, wantedmd5sum, completepath, 10); @@ -1554,7 +1554,7 @@ CURLGetLogin (const char *url, HTTP_login ***return_prev_next) ( login = (*prev_next)); prev_next = &login->next ){ - if (strcmp(login->url, url) == 0) + if (fastcmp(login->url, url) != 0) { if (return_prev_next) (*return_prev_next) = prev_next; diff --git a/src/d_protocol.c b/src/d_protocol.c index 6ceb05100..963d8e587 100644 --- a/src/d_protocol.c +++ b/src/d_protocol.c @@ -211,12 +211,12 @@ void D_SetupProtocol(void) if (result) { - if (strcmp(buffer, "no") == 0) + if (!fastcmp(buffer, "no")) { fclose(fp); return; } - else if (strcmp(buffer, exe_path) != 0) + else if (fastcmp(buffer, exe_path)) { // overwrite fclose(fp); diff --git a/src/dedicated/i_system.c b/src/dedicated/i_system.c index 78f265e2a..d2ffa12ad 100644 --- a/src/dedicated/i_system.c +++ b/src/dedicated/i_system.c @@ -1709,9 +1709,9 @@ char *I_GetUserName(void) strncpy(username, p, MAXPLAYERNAME); } - - if (strcmp(username, "") != 0) + if (!fastcmp(username, "")) return username; + return NULL; // dummy for platform independent version } diff --git a/src/discord.c b/src/discord.c index f94cd574d..8f937cfc1 100644 --- a/src/discord.c +++ b/src/discord.c @@ -277,7 +277,7 @@ static void DRPC_HandleJoinRequest(const DiscordUser *requestUser) while (append != NULL) { // CHECK FOR DUPES!! Ignore any that already exist from the same user. - if (!strcmp(newRequest->userID, append->userID)) + if (fastcmp(newRequest->userID, append->userID)) { Discord_Respond(newRequest->userID, DISCORD_REPLY_IGNORE); DRPC_RemoveRequest(newRequest); @@ -419,7 +419,7 @@ static const char *DRPC_GetServerIP(void) // If you're connected if (I_GetNodeAddress && (address = I_GetNodeAddress(servernode)) != NULL) { - if (strcmp(address, "self")) + if (!fastcmp(address, "self")) { // We're not the server, so we could successfully get the IP! // No need to do anything else :) @@ -684,7 +684,7 @@ void DRPC_UpdatePresence(void) // Character image while (supportedSkins[checkSkin] != NULL) { - if (!strcmp(skins[players[consoleplayer].skin].name, supportedSkins[checkSkin])) + if (fastcmp(skins[players[consoleplayer].skin].name, supportedSkins[checkSkin])) { snprintf(charimg, 21, "char%s", supportedSkins[checkSkin]); discordPresence.smallImageKey = charimg; diff --git a/src/doomdef.h b/src/doomdef.h index a0c76fa61..0329eb7f8 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -69,6 +69,8 @@ extern "C" { #include #include +#include "fastcmp.h" + #ifdef _WIN32 #include #endif diff --git a/src/filesrch.c b/src/filesrch.c index 628a221c2..b9821d368 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -353,7 +353,7 @@ void searchfilemenu(char *tempname) { for (i = first; i < sizedirmenu; i++) { - if (!strcmp(dirmenu[i]+DIR_STRING, tempname)) + if (fastcmp(dirmenu[i]+DIR_STRING, tempname)) { dir_on[menudepthleft] = i; break; @@ -400,7 +400,7 @@ void searchfilemenu(char *tempname) { if (filemenucmp(coredirmenu[i]+DIR_STRING, localmenusearch)) { - if (tempname && !strcmp(coredirmenu[i]+DIR_STRING, tempname)) + if (tempname && fastcmp(coredirmenu[i]+DIR_STRING, tempname)) { dir_on[menudepthleft] = sizedirmenu; Z_Free(tempname); @@ -587,7 +587,7 @@ boolean preparefilemenu(boolean samedepth, boolean replayhut) nameonly(filenamebuf[i]); } - if (strcmp(dent->d_name, filenamebuf[i])) + if (!fastcmp(dent->d_name, filenamebuf[i])) continue; if (cv_addons_md5.value && !checkfilemd5(menupath, wadfiles[i]->md5sum)) @@ -598,11 +598,11 @@ boolean preparefilemenu(boolean samedepth, boolean replayhut) } else if (ext == EXT_TXT) { - if (!strncmp(dent->d_name, "log-", 4) || !strcmp(dent->d_name, "errorlog.txt")) + if (!strncmp(dent->d_name, "log-", 4) || fastcmp(dent->d_name, "errorlog.txt")) ext |= EXT_LOADED; } - if (!strcmp(dent->d_name, configfile)) + if (fastcmp(dent->d_name, configfile)) ext |= EXT_LOADED; } diff --git a/src/g_game.c b/src/g_game.c index 796c154d5..05615df78 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3463,7 +3463,8 @@ void G_LoadGameData(void) if (READUINT32(save.p) != 0xFCAFE211) { const char *gdfolder = "the SRB2Kart folder"; - if (strcmp(srb2home,".")) + + if (!fastcmp(srb2home,".")) gdfolder = srb2home; Z_Free(save.buffer); @@ -3547,7 +3548,8 @@ void G_LoadGameData(void) datacorrupt: { const char *gdfolder = "the SRB2Kart folder"; - if (strcmp(srb2home,".")) + + if (!fastcmp(srb2home,".")) gdfolder = srb2home; Z_Free(save.buffer); @@ -3758,7 +3760,8 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride) memset(vcheck, 0, sizeof (vcheck)); sprintf(vcheck, "version %d", VERSION); - if (strcmp((const char *)save.p, (const char *)vcheck)) + + if (!fastcmp((const char *)save.p, (const char *)vcheck)) { #ifdef SAVEGAME_OTHERVERSIONS M_StartMessage(M_GetText("Save game from different version.\nYou can load this savegame, but\nsaving afterwards will be disabled.\n\nDo you want to continue anyway?\n\n(Press 'Y' to confirm)\n"), @@ -4036,7 +4039,7 @@ char *G_BuildMapTitle(INT32 mapnum) if (!mapheaderinfo[mapnum-1]) P_AllocMapHeader(mapnum-1); - if (strcmp(mapheaderinfo[mapnum-1]->lvlttl, "")) + if (!fastcmp(mapheaderinfo[mapnum-1]->lvlttl, "")) { size_t len = 1; const char *zonetext = NULL; diff --git a/src/hardware/hw_main.cpp b/src/hardware/hw_main.cpp index 45f25c2a6..be96fc901 100644 --- a/src/hardware/hw_main.cpp +++ b/src/hardware/hw_main.cpp @@ -5840,7 +5840,7 @@ static void COM_HWR_glinfo(void) { argv = COM_Argv(i); - if (strcmp(argv, "--list-extensions") == 0 || strcmp(argv, "-l") == 0) + if (fastcmp(argv, "--list-extensions")|| fastcmp(argv, "-l")) { list_extensions = 1; } diff --git a/src/hardware/hw_model.c b/src/hardware/hw_model.c index 6a9825402..77a995ed0 100644 --- a/src/hardware/hw_model.c +++ b/src/hardware/hw_model.c @@ -163,22 +163,22 @@ model_t *LoadModel(const char *filename, int ztag) return NULL; } - if (!strcmp(extension, ".md3")) + if (fastcmp(extension, ".md3")) { if (!(model = MD3_LoadModel(filename, ztag, false))) return NULL; } - else if (!strcmp(extension, ".md3s")) // MD3 that will be converted in memory to use full floats + else if (fastcmp(extension, ".md3s")) // MD3 that will be converted in memory to use full floats { if (!(model = MD3_LoadModel(filename, ztag, true))) return NULL; } - else if (!strcmp(extension, ".md2")) + else if (fastcmp(extension, ".md2")) { if (!(model = MD2_LoadModel(filename, ztag, false))) return NULL; } - else if (!strcmp(extension, ".md2s")) + else if (fastcmp(extension, ".md2s")) { if (!(model = MD2_LoadModel(filename, ztag, true))) return NULL; diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 6d04b6154..50dd46c61 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -83,7 +83,7 @@ FUNCINLINE static ATTRINLINE unsigned hook_in_list for (type = 0; list[type] != NULL; ++type) { - if (strcmp(name, list[type]) == 0) + if (fastcmp(name, list[type])) break; } @@ -240,7 +240,7 @@ static int lib_addHook(lua_State *L) { add_hook(&hookIds[type]); } - /*else if (strcmp(name, "HUD") == 0) // ehh this is cool and all, but i dont want modders potentially breaking vanilla clients lol + /*else if (fastcmp(name, "HUD")) // ehh this is cool and all, but i dont want modders potentially breaking vanilla clients lol { add_hud_hook(L, 3); }*/ @@ -818,7 +818,7 @@ typedef struct { FUNCINLINE static ATTRINLINE boolean checkbotkey(const char *field) { - return lua_toboolean(gL, -1) && strcmp(lua_tostring(gL, -2), field) == 0; + return lua_toboolean(gL, -1) && fastcmp(lua_tostring(gL, -2), field); } static void res_botai(Hook_State *hook) diff --git a/src/m_aatree.c b/src/m_aatree.c index 34e8e1d87..f78355eaf 100644 --- a/src/m_aatree.c +++ b/src/m_aatree.c @@ -183,7 +183,7 @@ static aatree_node_t *M_AATreeSetString_Node(aatree_node_t *node, UINT32 flags, else { aatree_entry_t *entry = node->value; - if (entry != NULL && strcmp(entry->key, key) != 0) + if (entry != NULL && !fastcmp(entry->key, key)) entry = entry->next; if (entry != NULL) { @@ -252,7 +252,7 @@ void *M_AATreeGetString(aatree_t *aatree, const char *key) I_Assert((aatree->flags & AATREE_STRING) == AATREE_STRING); UINT32 hash = FNV1a_HashString(key); aatree_entry_t *entry = M_AATreeGet_Node(aatree->root, hash); - while (entry != NULL && strcmp(entry->key, key) != 0) + while (entry != NULL && !fastcmp(entry->key, key)) entry = entry->next; return entry != NULL ? entry->value : NULL; } diff --git a/src/m_menu.c b/src/m_menu.c index 49398df34..bd79ec80c 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -3719,10 +3719,10 @@ static void M_HandleAddons(INT32 choice) break; case EXT_TXT: case EXT_CFG: - if ((strcmp(dirmenu[dir_on[menudepthleft]]+DIR_STRING, CONFIGFILENAME) == 0) - || (strcmp(dirmenu[dir_on[menudepthleft]]+DIR_STRING, AUTOLOADCONFIGFILENAME) == 0) - || (strcmp(dirmenu[dir_on[menudepthleft]]+DIR_STRING, "kartserv.cfg") == 0) - || (strcmp(dirmenu[dir_on[menudepthleft]]+DIR_STRING, "kartexec.cfg") == 0)) + if (fastcmp(dirmenu[dir_on[menudepthleft]]+DIR_STRING, CONFIGFILENAME) + || fastcmp(dirmenu[dir_on[menudepthleft]]+DIR_STRING, AUTOLOADCONFIGFILENAME) + || fastcmp(dirmenu[dir_on[menudepthleft]]+DIR_STRING, "kartserv.cfg") + || fastcmp(dirmenu[dir_on[menudepthleft]]+DIR_STRING, "kartexec.cfg")) { M_StartMessage(va("%c%s\x80\nYou can't autoload this builds' base console scripts, silly!\n They're already autoloaded on startup! \n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), dirmenu[dir_on[menudepthleft]]+DIR_STRING),NULL,MM_NOTHING); S_StartSound(NULL, sfx_s26d); @@ -3830,7 +3830,7 @@ static void ReplayNamesLoadThread(void* userdata) Lock_search_state(); - if (strcmp(menupath, replaydirpath) == 0) + if (fastcmp(menupath, replaydirpath)) { memcpy(demolist_all, demolist_all_local, sizeof(menudemo_t)*sizedirmenu); replaynamesloaded = true; @@ -6799,7 +6799,7 @@ static int ServerListEntryComparator_##key(const void *entry1, const void *entry const serverelem_t *sa = (const serverelem_t*)entry1, *sb = (const serverelem_t*)entry2; \ if (sa->info.key != sb->info.key) \ return sa->info.key - sb->info.key; \ - return strcmp(sa->info.servername, sb->info.servername); \ + return !fastcmp(sa->info.servername, sb->info.servername); \ } // This does descending instead of ascending. @@ -6809,7 +6809,7 @@ static int ServerListEntryComparator_##key##_reverse(const void *entry1, const v const serverelem_t *sa = (const serverelem_t*)entry1, *sb = (const serverelem_t*)entry2; \ if (sb->info.key != sa->info.key) \ return sb->info.key - sa->info.key; \ - return strcmp(sb->info.servername, sa->info.servername); \ + return !fastcmp(sb->info.servername, sa->info.servername); \ } SERVER_LIST_ENTRY_COMPARATOR(time) @@ -6830,8 +6830,8 @@ static int ServerListEntryComparator_modified(const void *entry1, const void *en if (modstate_a != modstate_b) return modstate_a - modstate_b; - // Default to strcmp. - return strcmp(sa->info.servername, sb->info.servername); + // Default to !fastcmp. + return !fastcmp(sa->info.servername, sb->info.servername); } void M_SortServerList(void) @@ -8808,7 +8808,7 @@ static boolean M_QuitMultiPlayerMenu(void) size_t l; // send name if changed - if (strcmp(setupm_name, setupm_cvname->string)) + if (!fastcmp(setupm_name, setupm_cvname->string)) { // remove trailing whitespaces for (l= strlen(setupm_name)-1; @@ -9469,7 +9469,7 @@ static void M_VideoModeMenu(INT32 choice) // VESA mode, which is always a higher modenum for (j = 0; j < vidm_nummodes; j++) { - if (!strcmp(modedescs[j].desc, desc)) + if (fastcmp(modedescs[j].desc, desc)) { // mode(0): 320x200 is always standard VGA, not vesa if (modedescs[j].modenum) diff --git a/src/m_perfstats.c b/src/m_perfstats.c index 7384a6086..75aad72e2 100644 --- a/src/m_perfstats.c +++ b/src/m_perfstats.c @@ -916,7 +916,7 @@ static void draw_think_frame_stats(int hook_length, ps_hookinfo_t *hook) int len = (int)strlen(str); char* str_ptr; - if (strcmp(".lua", str + len - 4) == 0) + if (fastcmp(".lua", str + len - 4)) { str[len-4] = '\0'; // remove .lua at end } diff --git a/src/p_saveg.c b/src/p_saveg.c index d3a162e2d..570e8e1f0 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -3391,7 +3391,7 @@ FUNCINLINE static ATTRINLINE void P_UnArchiveSPGame(savebuffer_t *save, INT16 ma READSTRINGN(save->p, testname, sizeof(testname)); - if (strcmp(testname, timeattackfolder)) + if (!fastcmp(testname, timeattackfolder)) { if (modifiedgame) I_Error("Save game not for this modification."); diff --git a/src/r_data.c b/src/r_data.c index 93ad621fa..893252571 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -867,7 +867,7 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) I_Error("Error parsing TEXTURES lump: Unexpected end of file where comma after \"%s\"'s patch name should be",patchName); } - if (strcmp(texturesToken,",")!=0) + if (!fastcmp(texturesToken,",")) { I_Error("Error parsing TEXTURES lump: Expected \",\" after %s's patch name, got \"%s\"",patchName,texturesToken); } @@ -907,7 +907,7 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) I_Error("Error parsing TEXTURES lump: Unexpected end of file where comma after patch \"%s\"'s x coordinate should be",patchName); } - if (strcmp(texturesToken,",")!=0) + if (!fastcmp(texturesToken,",")) { I_Error("Error parsing TEXTURES lump: Expected \",\" after patch \"%s\"'s x coordinate, got \"%s\"",patchName,texturesToken); } @@ -996,7 +996,7 @@ static texture_t *R_ParseTexture(boolean actuallyLoadTexture) { I_Error("Error parsing TEXTURES lump: Unexpected end of file where comma after texture \"%s\"'s name should be",newTextureName); } - else if (strcmp(texturesToken,",")!=0) + else if (!fastcmp(texturesToken,",")) { I_Error("Error parsing TEXTURES lump: Expected \",\" after texture \"%s\"'s name, got \"%s\"",newTextureName,texturesToken); } @@ -1030,7 +1030,7 @@ static texture_t *R_ParseTexture(boolean actuallyLoadTexture) { I_Error("Error parsing TEXTURES lump: Unexpected end of file where comma after texture \"%s\"'s width should be",newTextureName); } - if (strcmp(texturesToken,",")!=0) + if (!fastcmp(texturesToken,",")) { I_Error("Error parsing TEXTURES lump: Expected \",\" after texture \"%s\"'s width, got \"%s\"",newTextureName,texturesToken); } @@ -1066,7 +1066,7 @@ static texture_t *R_ParseTexture(boolean actuallyLoadTexture) I_Error("Error parsing TEXTURES lump: Unexpected end of file where open curly brace for texture \"%s\" should be",newTextureName); } - if (strcmp(texturesToken,"{")==0) + if (fastcmp(texturesToken,"{")) { if (actuallyLoadTexture) { @@ -1084,7 +1084,7 @@ static texture_t *R_ParseTexture(boolean actuallyLoadTexture) { I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch definition for texture \"%s\" should be",newTextureName); } - while (strcmp(texturesToken,"}")!=0) + while (!fastcmp(texturesToken,"}")) { if (stricmp(texturesToken, "PATCH")==0) { @@ -1334,8 +1334,9 @@ lumpnum_t R_GetFlatNumForName(const char *name) if (lump == LUMPERROR) { - if (strcmp(name, SKYFLATNAME)) + if (!fastcmp(name, SKYFLATNAME)) CONS_Debug(DBG_SETUP, "R_GetFlatNumForName: Could not find flat %.8s\n", name); + lump = W_CheckNumForName("REDFLR"); } diff --git a/src/r_patch.cpp b/src/r_patch.cpp index 09aca078a..1e09ae7bb 100644 --- a/src/r_patch.cpp +++ b/src/r_patch.cpp @@ -63,7 +63,7 @@ static void R_ParseSpriteInfoFrame(spriteinfo_t *info) I_Error("Error parsing SPRTINFO lump: Missing sprite info"); else { - if (strcmp(sprinfoToken,"{")==0) + if (fastcmp(sprinfoToken,"{")) { Z_Free(sprinfoToken); sprinfoToken = M_GetToken(NULL); @@ -71,7 +71,7 @@ static void R_ParseSpriteInfoFrame(spriteinfo_t *info) { I_Error("Error parsing SPRTINFO lump: Unexpected end of file where sprite info should be"); } - while (strcmp(sprinfoToken,"}")!=0) + while (!fastcmp(sprinfoToken,"}")) { if (stricmp(sprinfoToken, "XPIVOT")==0) { @@ -175,7 +175,7 @@ static void R_ParseSpriteInfo(boolean spr2) { I_Error("Error parsing SPRTINFO lump: Unexpected end of file where open curly brace for sprite \"%s\" should be",newSpriteName); } - if (strcmp(sprinfoToken,"{")==0) + if (fastcmp(sprinfoToken,"{")) { Z_Free(sprinfoToken); sprinfoToken = M_GetToken(NULL); @@ -183,7 +183,7 @@ static void R_ParseSpriteInfo(boolean spr2) { I_Error("Error parsing SPRTINFO lump: Unexpected end of file where definition for sprite \"%s\" should be",newSpriteName); } - while (strcmp(sprinfoToken,"}")!=0) + while (!fastcmp(sprinfoToken,"}")) { if (stricmp(sprinfoToken, "SKIN")==0) { diff --git a/src/sdl/hwsym_sdl.c b/src/sdl/hwsym_sdl.c index a528796eb..edd685327 100644 --- a/src/sdl/hwsym_sdl.c +++ b/src/sdl/hwsym_sdl.c @@ -35,9 +35,6 @@ #define _CREATE_DLL_ // necessary for Unix AND Windows -#define GETFUNC(func) \ - else if (0 == strcmp(#func, funcName)) \ - funcPointer = &func \ // // /** \brief The *hwSym function diff --git a/src/sdl/i_system.cpp b/src/sdl/i_system.cpp index 4e9e54d72..5281a7f01 100644 --- a/src/sdl/i_system.cpp +++ b/src/sdl/i_system.cpp @@ -2288,8 +2288,9 @@ char *I_GetUserName(void) } - if (strcmp(username, "") != 0) + if (!fastcmp(username, "")) return username; + return NULL; // dummy for platform independent version } diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 7393d8e4b..5bccceaff 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -905,7 +905,7 @@ static void Impl_HandleControllerAddedEvent(SDL_Event evt) for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) { - if (!strcmp(cv_usejoystick[i].string, "0") || !cv_usejoystick[i].value) + if (fastcmp(cv_usejoystick[i].string, "0") || !cv_usejoystick[i].value) cv_usejoystick[i].value = 0; else if (atoi(cv_usejoystick[i].string) <= I_NumJoys() // don't mess if we intentionally set higher than NumJoys && cv_usejoystick[i].value) // update the cvar ONLY if a device exists @@ -977,7 +977,7 @@ static void Impl_HandleControllerRemovedEvent(void) for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) { - if (!strcmp(cv_usejoystick[i].string, "0")) + if (fastcmp(cv_usejoystick[i].string, "0")) { cv_usejoystick[i].value = 0; } diff --git a/src/sdl/ogl_sdl.c b/src/sdl/ogl_sdl.c index 4e60801b3..1b8d54fef 100644 --- a/src/sdl/ogl_sdl.c +++ b/src/sdl/ogl_sdl.c @@ -170,8 +170,8 @@ boolean OglSdlSurface(INT32 w, INT32 h) } } - if (strcmp((const char*)gl_renderer, "GDI Generic") == 0 && - strcmp((const char*)gl_version, "1.1.0") == 0) + if (fastcmp((const char*)gl_renderer, "GDI Generic") && + fastcmp((const char*)gl_version, "1.1.0")) { // Oh no... Windows gave us the GDI Generic rasterizer, so something is wrong... // The game will crash later on when unsupported OpenGL commands are encountered. diff --git a/src/v_video.c b/src/v_video.c index e7d9a87ca..893a39b20 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -23,7 +23,6 @@ #include "r_main.h" #include "r_fps.h" #include "console.h" - #include "i_video.h" // rendermode #include "z_zone.h" #include "m_misc.h" @@ -134,7 +133,7 @@ static boolean InitCube(void) if (!loaded_config) return false; -#define diffcons(cv) (strcmp(cv.string, cv.defaultvalue)) +#define diffcons(cv) (!fastcmp(cv.string, cv.defaultvalue)) #define diffconsgamma(cv) (cv.value != 0) #define diffconssat(cv) (cv.value != 10) @@ -596,7 +595,7 @@ void V_ResetPaletteCVars(void) if (!loaded_config) return; -#define diffcons(cv) (strcmp(cv.string, cv.defaultvalue)) +#define diffcons(cv) (!fastcmp(cv.string, cv.defaultvalue)) if diffcons(cv_palette) CV_StealthSetValue(&cv_palette, atoi(cv_palette.defaultvalue)); if diffcons(cv_palettenum) -- 2.54.0 From dc6bf05f351aca99bb3bf082dca82927c9d29e0f Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 24 Oct 2025 21:50:12 +0200 Subject: [PATCH 205/219] experiment: replace every strcasecmp with fasticmp same as before, tho this is not twice as fast but atleast 1/3 faster --- src/command.c | 2 +- src/d_main.c | 5 +++- src/d_netcmd.c | 66 +++++++++++++++++++++++------------------------ src/doomtype.h | 2 +- src/filesrch.c | 14 +++++----- src/m_argv.c | 2 +- src/s_sound.c | 10 +++---- src/sdl/i_video.c | 8 +++--- 8 files changed, 56 insertions(+), 53 deletions(-) diff --git a/src/command.c b/src/command.c index 676212703..d5cbf8041 100644 --- a/src/command.c +++ b/src/command.c @@ -359,7 +359,7 @@ size_t COM_CheckParm(const char *check) size_t i; for (i = 1; i < com_argc; i++) - if (!strcasecmp(check, com_argv[i])) + if (fasticmp(check, com_argv[i])) return i; return 0; } diff --git a/src/d_main.c b/src/d_main.c index fd643213c..ef1855d05 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -2156,11 +2156,14 @@ void D_SRB2Main(void) const char *sskill = M_GetNextParm(); for (j = 0; kartspeed_cons_t[j].strvalue; j++) - if (!strcasecmp(kartspeed_cons_t[j].strvalue, sskill)) + { + if (fasticmp(kartspeed_cons_t[j].strvalue, sskill)) { newskill = (INT16)kartspeed_cons_t[j].value; break; } + } + if (!kartspeed_cons_t[j].strvalue) // reached end of the list with no match { j = atoi(sskill); // assume they gave us a skill number, which is okay too diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 3a5e0ca7e..4998069c1 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1219,7 +1219,7 @@ static boolean EnsurePlayerNameIsGood(char *name, INT32 playernum) for (ix = 0; ix < MAXPLAYERS; ix++) { if (ix != playernum && playeringame[ix] - && strcasecmp(name, player_names[ix]) == 0) + && fasticmp(name, player_names[ix])) { // We shouldn't kick people out just because // they joined the game with the same name @@ -1336,7 +1336,7 @@ static void CleanupPlayerName(INT32 playernum, const char *newname) for (i = 0; i < MAXPLAYERS; i++) { if (i != playernum && playeringame[i] - && strcasecmp(tmpname, player_names[i]) == 0) + && fasticmp(tmpname, player_names[i])) { break; } @@ -1386,7 +1386,7 @@ static void SetPlayerName(INT32 playernum, char *newname) { if (EnsurePlayerNameIsGood(newname, playernum)) { - if (strcasecmp(newname, player_names[playernum]) != 0) + if (fasticmp(newname, player_names[playernum])) { if (netgame) HU_AddChatText(va("\x82*%s renamed to %s", player_names[playernum], newname), false); @@ -1945,7 +1945,7 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum) // set name if (player_name_changes[playernum] < MAXNAMECHANGES) { - if (strcasecmp(player_names[playernum], name) != 0) + if (!fasticmp(player_names[playernum], name)) SetPlayerName(playernum, name); } @@ -3194,20 +3194,20 @@ static void Command_Teamchange_f(void) if (G_GametypeHasTeams()) { - if (!strcasecmp(COM_Argv(1), "red") || !strcasecmp(COM_Argv(1), "1")) + if (fasticmp(COM_Argv(1), "red") || fasticmp(COM_Argv(1), "1")) NetPacket.packet.newteam = 1; - else if (!strcasecmp(COM_Argv(1), "blue") || !strcasecmp(COM_Argv(1), "2")) + else if (fasticmp(COM_Argv(1), "blue") || fasticmp(COM_Argv(1), "2")) NetPacket.packet.newteam = 2; - else if (!strcasecmp(COM_Argv(1), "spectator") || !strcasecmp(COM_Argv(1), "0")) + else if (fasticmp(COM_Argv(1), "spectator") || fasticmp(COM_Argv(1), "0")) NetPacket.packet.newteam = 0; else error = true; } else if (G_GametypeHasSpectators()) { - if (!strcasecmp(COM_Argv(1), "spectator") || !strcasecmp(COM_Argv(1), "0")) + if (fasticmp(COM_Argv(1), "spectator") || fasticmp(COM_Argv(1), "0")) NetPacket.packet.newteam = 0; - else if (!strcasecmp(COM_Argv(1), "playing") || !strcasecmp(COM_Argv(1), "1")) + else if (fasticmp(COM_Argv(1), "playing") || fasticmp(COM_Argv(1), "1")) NetPacket.packet.newteam = 3; else error = true; @@ -3284,20 +3284,20 @@ static void Command_Teamchange2_f(void) if (G_GametypeHasTeams()) { - if (!strcasecmp(COM_Argv(1), "red") || !strcasecmp(COM_Argv(1), "1")) + if (fasticmp(COM_Argv(1), "red") || fasticmp(COM_Argv(1), "1")) NetPacket.packet.newteam = 1; - else if (!strcasecmp(COM_Argv(1), "blue") || !strcasecmp(COM_Argv(1), "2")) + else if (fasticmp(COM_Argv(1), "blue") || fasticmp(COM_Argv(1), "2")) NetPacket.packet.newteam = 2; - else if (!strcasecmp(COM_Argv(1), "spectator") || !strcasecmp(COM_Argv(1), "0")) + else if (fasticmp(COM_Argv(1), "spectator") || fasticmp(COM_Argv(1), "0")) NetPacket.packet.newteam = 0; else error = true; } else if (G_GametypeHasSpectators()) { - if (!strcasecmp(COM_Argv(1), "spectator") || !strcasecmp(COM_Argv(1), "0")) + if (fasticmp(COM_Argv(1), "spectator") || fasticmp(COM_Argv(1), "0")) NetPacket.packet.newteam = 0; - else if (!strcasecmp(COM_Argv(1), "playing") || !strcasecmp(COM_Argv(1), "1")) + else if (fasticmp(COM_Argv(1), "playing") || fasticmp(COM_Argv(1), "1")) NetPacket.packet.newteam = 3; else error = true; @@ -3375,20 +3375,20 @@ static void Command_Teamchange3_f(void) if (G_GametypeHasTeams()) { - if (!strcasecmp(COM_Argv(1), "red") || !strcasecmp(COM_Argv(1), "1")) + if (fasticmp(COM_Argv(1), "red") || fasticmp(COM_Argv(1), "1")) NetPacket.packet.newteam = 1; - else if (!strcasecmp(COM_Argv(1), "blue") || !strcasecmp(COM_Argv(1), "2")) + else if (fasticmp(COM_Argv(1), "blue") || fasticmp(COM_Argv(1), "2")) NetPacket.packet.newteam = 2; - else if (!strcasecmp(COM_Argv(1), "spectator") || !strcasecmp(COM_Argv(1), "0")) + else if (fasticmp(COM_Argv(1), "spectator") || fasticmp(COM_Argv(1), "0")) NetPacket.packet.newteam = 0; else error = true; } else if (G_GametypeHasSpectators()) { - if (!strcasecmp(COM_Argv(1), "spectator") || !strcasecmp(COM_Argv(1), "0")) + if (fasticmp(COM_Argv(1), "spectator") || fasticmp(COM_Argv(1), "0")) NetPacket.packet.newteam = 0; - else if (!strcasecmp(COM_Argv(1), "playing") || !strcasecmp(COM_Argv(1), "1")) + else if (fasticmp(COM_Argv(1), "playing") || fasticmp(COM_Argv(1), "1")) NetPacket.packet.newteam = 3; else error = true; @@ -3466,20 +3466,20 @@ static void Command_Teamchange4_f(void) if (G_GametypeHasTeams()) { - if (!strcasecmp(COM_Argv(1), "red") || !strcasecmp(COM_Argv(1), "1")) + if (fasticmp(COM_Argv(1), "red") || fasticmp(COM_Argv(1), "1")) NetPacket.packet.newteam = 1; - else if (!strcasecmp(COM_Argv(1), "blue") || !strcasecmp(COM_Argv(1), "2")) + else if (fasticmp(COM_Argv(1), "blue") || fasticmp(COM_Argv(1), "2")) NetPacket.packet.newteam = 2; - else if (!strcasecmp(COM_Argv(1), "spectator") || !strcasecmp(COM_Argv(1), "0")) + else if (fasticmp(COM_Argv(1), "spectator") || fasticmp(COM_Argv(1), "0")) NetPacket.packet.newteam = 0; else error = true; } else if (G_GametypeHasSpectators()) { - if (!strcasecmp(COM_Argv(1), "spectator") || !strcasecmp(COM_Argv(1), "0")) + if (fasticmp(COM_Argv(1), "spectator") || fasticmp(COM_Argv(1), "0")) NetPacket.packet.newteam = 0; - else if (!strcasecmp(COM_Argv(1), "playing") || !strcasecmp(COM_Argv(1), "1")) + else if (fasticmp(COM_Argv(1), "playing") || fasticmp(COM_Argv(1), "1")) NetPacket.packet.newteam = 3; else error = true; @@ -3565,33 +3565,33 @@ static void Command_ServerTeamChange_f(void) if (G_TagGametype()) { - if (!strcasecmp(COM_Argv(2), "it") || !strcasecmp(COM_Argv(2), "1")) + if (fasticmp(COM_Argv(2), "it") || fasticmp(COM_Argv(2), "1")) NetPacket.packet.newteam = 1; - else if (!strcasecmp(COM_Argv(2), "notit") || !strcasecmp(COM_Argv(2), "2")) + else if (fasticmp(COM_Argv(2), "notit") || fasticmp(COM_Argv(2), "2")) NetPacket.packet.newteam = 2; - else if (!strcasecmp(COM_Argv(2), "playing") || !strcasecmp(COM_Argv(2), "3")) + else if (fasticmp(COM_Argv(2), "playing") || fasticmp(COM_Argv(2), "3")) NetPacket.packet.newteam = 3; - else if (!strcasecmp(COM_Argv(2), "spectator") || !strcasecmp(COM_Argv(2), "0")) + else if (fasticmp(COM_Argv(2), "spectator") || fasticmp(COM_Argv(2), "0")) NetPacket.packet.newteam = 0; else error = true; } else if (G_GametypeHasTeams()) { - if (!strcasecmp(COM_Argv(2), "red") || !strcasecmp(COM_Argv(2), "1")) + if (fasticmp(COM_Argv(2), "red") || fasticmp(COM_Argv(2), "1")) NetPacket.packet.newteam = 1; - else if (!strcasecmp(COM_Argv(2), "blue") || !strcasecmp(COM_Argv(2), "2")) + else if (fasticmp(COM_Argv(2), "blue") || fasticmp(COM_Argv(2), "2")) NetPacket.packet.newteam = 2; - else if (!strcasecmp(COM_Argv(2), "spectator") || !strcasecmp(COM_Argv(2), "0")) + else if (fasticmp(COM_Argv(2), "spectator") || fasticmp(COM_Argv(2), "0")) NetPacket.packet.newteam = 0; else error = true; } else if (G_GametypeHasSpectators()) { - if (!strcasecmp(COM_Argv(2), "spectator") || !strcasecmp(COM_Argv(2), "0")) + if (fasticmp(COM_Argv(2), "spectator") || fasticmp(COM_Argv(2), "0")) NetPacket.packet.newteam = 0; - else if (!strcasecmp(COM_Argv(2), "playing") || !strcasecmp(COM_Argv(2), "1")) + else if (fasticmp(COM_Argv(2), "playing") || fasticmp(COM_Argv(2), "1")) NetPacket.packet.newteam = 3; else error = true; diff --git a/src/doomtype.h b/src/doomtype.h index 78867ed69..7b0df4841 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -63,7 +63,7 @@ extern "C" { #endif #if defined (__unix__) || defined (__APPLE__) || defined (UNIXCOMMON) #undef stricmp - #define stricmp(x,y) strcasecmp(x,y) + #define stricmp(x,y) !fasticmp(x,y) #undef strnicmp #define strnicmp(x,y,n) strncasecmp(x,y,n) #endif diff --git a/src/filesrch.c b/src/filesrch.c index b9821d368..eb68222e2 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -198,7 +198,7 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want for (; *path != NULL; path++) { - if (strcasecmp(*path, dent->d_name) == 0) + if (fasticmp(*path, dent->d_name)) { skipfolder = true; break; @@ -212,7 +212,7 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want } } - if (strcasecmp(".git", dent->d_name) // sanity if you're weird like me + if (!fasticmp(".git", dent->d_name) // sanity if you're weird like me && (dirhandle[depthleft-1] = opendir(searchpath)) != NULL) { // Got read permissions! @@ -227,7 +227,7 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want // I am a file! - if (strcasecmp(searchname, dent->d_name)) + if (!fasticmp(searchname, dent->d_name)) continue; // Not what we're looking for! switch (checkfilemd5(searchpath, wantedmd5sum)) @@ -478,14 +478,14 @@ boolean preparefilemenu(boolean samedepth, boolean replayhut) if (replayhut) { - if (strcasecmp(".lmp", dent->d_name+len-5)) + if (!fasticmp(".lmp", dent->d_name+len-5)) continue; // Not a replay } else if (!cv_addons_showall.value) { UINT8 ext; for (ext = 0; ext < NUM_EXT_TABLE; ext++) - if (!strcasecmp(exttable[ext]+1, dent->d_name+len-(exttable[ext][0]))) + if (fasticmp(exttable[ext]+1, dent->d_name+len-(exttable[ext][0]))) break; // extension comparison if (ext == NUM_EXT_TABLE) @@ -559,7 +559,7 @@ boolean preparefilemenu(boolean samedepth, boolean replayhut) if (replayhut) { - if (strcasecmp(".lmp", dent->d_name+len-5)) + if (!fasticmp(".lmp", dent->d_name+len-5)) continue; // Not a replay ext = EXT_TXT; // This isn't used anywhere but better safe than sorry for messing with this... @@ -567,7 +567,7 @@ boolean preparefilemenu(boolean samedepth, boolean replayhut) else { for (; ext < NUM_EXT_TABLE; ext++) - if (!strcasecmp(exttable[ext]+1, dent->d_name+len-(exttable[ext][0]))) + if (fasticmp(exttable[ext]+1, dent->d_name+len-(exttable[ext][0]))) break; // extension comparison if (ext == NUM_EXT_TABLE && !cv_addons_showall.value) diff --git a/src/m_argv.c b/src/m_argv.c index 2ec1b188a..b62d390d9 100644 --- a/src/m_argv.c +++ b/src/m_argv.c @@ -49,7 +49,7 @@ INT32 M_CheckParm(const char *check) for (i = 1; i < myargc; i++) { - if (!strcasecmp(check, myargv[i])) + if (fasticmp(check, myargv[i])) { found = i; return i; diff --git a/src/s_sound.c b/src/s_sound.c index 1bac40a46..e3e86c5b0 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1828,7 +1828,7 @@ void S_StopMusic(void) || demo.title) // SRB2Kart: Demos don't interrupt title screen music return; - mapmusic.resume = (cv_birdmusic.value && (strcasecmp(music.name, mapmusic.name) == 0)) ? I_GetSongPosition() : 0; + mapmusic.resume = (cv_birdmusic.value && fasticmp(music.name, mapmusic.name)) ? I_GetSongPosition() : 0; S_SetKeepMusResume(); @@ -1964,7 +1964,7 @@ static void S_SetKeepMusResume(void) { keepmusic.resume = 0; - if (strcasecmp(music.name, mapmusic.name) == 0) + if (fasticmp(music.name, mapmusic.name)) { keepmusic.resume = I_GetSongPosition(); } @@ -2148,19 +2148,19 @@ static void Command_Tunes_f(void) tunenum = (UINT16)atoi(tunearg); track = 0; - if (!strcasecmp(tunearg, "-show")) + if (fasticmp(tunearg, "-show")) { CONS_Printf(M_GetText("The current tune is: %s [track %d]\n"), mapmusic.name, (mapmusic.flags & MUSIC_TRACKMASK)); return; } - if (!strcasecmp(tunearg, "-none")) + if (fasticmp(tunearg, "-none")) { S_StopMusic(); return; } - else if (!strcasecmp(tunearg, "-default")) + else if (fasticmp(tunearg, "-default")) { tunearg = mapheaderinfo[gamemap-1]->musname; track = mapheaderinfo[gamemap-1]->mustrack; diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 5bccceaff..2ea66dbc2 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1785,11 +1785,11 @@ void I_StartupGraphics(void) if (rendermode == render_none) { - if (strcasecmp(word, "software") == 0) + if (fasticmp(word, "software")) { rendermode = render_soft; } - else if (strcasecmp(word, "opengl") == 0) + else if (fasticmp(word, "opengl")) { rendermode = render_opengl; } @@ -1802,7 +1802,7 @@ void I_StartupGraphics(void) if (!msaa_set) { - if (strcasecmp(word, "msaa") == 0) + if (fasticmp(word, "msaa")) { const char *nextword = strtok(NULL, " \n"); @@ -1819,7 +1819,7 @@ void I_StartupGraphics(void) if (!a2c_set) { - if (strcasecmp(word, "a2c") == 0) + if (fasticmp(word, "a2c")) { a2c = true; CONS_Printf("Using a2c because it was specified to be used earlier\n"); -- 2.54.0 From df1085548399eb2c1e6e023b45cae671a632b953 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 25 Oct 2025 14:25:30 +0200 Subject: [PATCH 206/219] fix oopsie that broke name change --- src/d_netcmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 4998069c1..f0601d9fa 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1386,7 +1386,7 @@ static void SetPlayerName(INT32 playernum, char *newname) { if (EnsurePlayerNameIsGood(newname, playernum)) { - if (fasticmp(newname, player_names[playernum])) + if (!fasticmp(newname, player_names[playernum])) { if (netgame) HU_AddChatText(va("\x82*%s renamed to %s", player_names[playernum], newname), false); -- 2.54.0 From 30cea37248b10c96f0e73392bba40f2ea92f6c61 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 18 Oct 2025 16:52:31 +0200 Subject: [PATCH 207/219] use npow2 screen textures if GL_ARB_texture_non_power_of_two is supported apparently some gl drivers may use a slower path for streamed textures that only get partly updated, this tricks them into thinking this did a "full update" and resulting in using a faster renderpath --- src/hardware/r_opengl/r_opengl.c | 23 +++++++++++++++-------- src/hardware/r_opengl/r_opengl.h | 1 + src/sdl/ogl_sdl.c | 3 +++ 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 23c2a8da0..3a5fd059a 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -110,6 +110,7 @@ GLint screen_texsizew = 512; // Power-of-two screen texture render resolution GLint screen_texsizeh = 512; // Power-of-two screen texture render resolution GLbyte screen_depth = 0; GLint maximumAnisotropy = 0; +boolean supportNPO2tex = false; static GLboolean MipMap = GL_FALSE; static GLint min_filter = GL_LINEAR; static GLint mag_filter = GL_LINEAR; @@ -1176,12 +1177,20 @@ void GL_SetModelView(GLint w, GLint h) screen_texsizew = screen_texsizeh = 512; - // look for power of two that is large enough for the screen - while (screen_texsizew < w) - screen_texsizew <<= 1; + if (supportNPO2tex) + { + screen_texsizew = screen_width; + screen_texsizeh = screen_height; + } + else + { + // look for power of two that is large enough for the screen + while (screen_texsizew < w) + screen_texsizew <<= 1; - while (screen_texsizeh < h) - screen_texsizeh <<= 1; + while (screen_texsizeh < h) + screen_texsizeh <<= 1; + } pglGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxtexsize); // Get the maximum supported texture size if ((screen_texsizew > maxtexsize || screen_texsizeh > maxtexsize) && maxtexsize > 0) @@ -3692,7 +3701,6 @@ void GL_DrawScreenFinalTexture(int tex, INT32 width, INT32 height, boolean usesh float xfix, yfix; float origaspect, newaspect; float xoff = 1, yoff = 1; // xoffset and yoffset for the polygon to have black bars around the screen - FRGBAFloat clearColour; static float off[12]; static float fix[8]; @@ -3743,8 +3751,7 @@ void GL_DrawScreenFinalTexture(int tex, INT32 width, INT32 height, boolean usesh pglViewport(0, 0, width, height); - clearColour.red = clearColour.green = clearColour.blue = 0; - clearColour.alpha = 1; + FRGBAFloat clearColour = {0, 0, 0, 1}; GL_ClearBuffer(true, false, false, &clearColour); GL_SetBlend(PF_NoDepthTest); diff --git a/src/hardware/r_opengl/r_opengl.h b/src/hardware/r_opengl/r_opengl.h index 4cf2b2e46..34d4b9da3 100644 --- a/src/hardware/r_opengl/r_opengl.h +++ b/src/hardware/r_opengl/r_opengl.h @@ -124,6 +124,7 @@ extern GLint screen_width; extern GLint screen_height; extern GLbyte screen_depth; extern GLint maximumAnisotropy; +extern boolean supportNPO2tex; extern boolean supportMipMap; /** \brief OpenGL flags for video driver diff --git a/src/sdl/ogl_sdl.c b/src/sdl/ogl_sdl.c index 4e60801b3..0816ecfec 100644 --- a/src/sdl/ogl_sdl.c +++ b/src/sdl/ogl_sdl.c @@ -197,6 +197,9 @@ boolean OglSdlSurface(INT32 w, INT32 h) else maximumAnisotropy = 1; + if (GL_isExtAvailable("GL_ARB_texture_non_power_of_two", gl_extensions)) + supportNPO2tex = true; + glanisotropicmode_cons_t[1].value = maximumAnisotropy; #if defined (__unix__) -- 2.54.0 From 467688552184e38c2935a9e7ab3a93ea00d4238d Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 1 Nov 2025 23:15:52 +0100 Subject: [PATCH 208/219] fixup: replace stricmp with fasticmp actually replace everything correctly my dumbass forgor about the fast both strcmp and stricmp matter in sort stuff so we cannot use the fastcmp stuff there, which means we should not redifine stricmp as fasticmp in case something relies on that behaviour ugh --- src/blua/lauxlib.c | 2 +- src/blua/lfastcmp.h | 32 ------------ src/blua/liolib.c | 8 +-- src/command.c | 72 +++++++++++++------------- src/d_clisrv.c | 7 +-- src/d_main.c | 14 ++--- src/d_netfil.c | 5 +- src/doomtype.h | 2 +- src/g_demo.c | 20 ++++---- src/g_game.c | 2 +- src/g_input.c | 7 +-- src/hardware/hw_md2.c | 12 +++-- src/hardware/hw_model.c | 2 +- src/hardware/hw_shaders.c | 8 +-- src/k_kart.c | 5 +- src/lua_consolelib.c | 2 +- src/lua_mobjlib.c | 6 +-- src/m_emotes.cpp | 4 +- src/m_menu.c | 8 +-- src/m_misc.c | 2 +- src/p_spec.c | 52 ++++++++++++++----- src/r_data.c | 36 +++++++++---- src/r_patch.cpp | 104 +++++++++++++++++++++----------------- src/r_skins.c | 46 ++++++++--------- src/s_sound.c | 31 +++++++----- src/w_wad.c | 10 ++-- 26 files changed, 267 insertions(+), 232 deletions(-) delete mode 100644 src/blua/lfastcmp.h diff --git a/src/blua/lauxlib.c b/src/blua/lauxlib.c index eacce9b44..e91faa182 100644 --- a/src/blua/lauxlib.c +++ b/src/blua/lauxlib.c @@ -24,7 +24,7 @@ #include "lauxlib.h" -#include "lfastcmp.h" +#include "../doomdef.h" #define FREELIST_REF 0 /* free list of references */ diff --git a/src/blua/lfastcmp.h b/src/blua/lfastcmp.h deleted file mode 100644 index f25c59896..000000000 --- a/src/blua/lfastcmp.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef __FASTCMP_H__ -#define __FASTCMP_H__ - -#include -#include - -// same as fastcmp but we cant use our fancy macros - -// returns false if s != c -// returns true if s == c -__attribute__((always_inline)) static inline bool fasticmp(const char *s, const char *c) -{ - for (; *s && toupper(*s) == toupper(*c); s++, c++) ; - return (*s == *c); // make sure both strings ended -} - -// case-sensitive of the above -__attribute__((always_inline)) static inline bool fastcmp(const char *s, const char *c) -{ - for (; *s && *s == *c; s++, c++) ; - return (*s == *c); // make sure both strings ended -} - -// length-limited of the above -// only true if both strings are at least l characters long AND match, case-sensitively! -__attribute__((always_inline)) static inline bool fastncmp(const char *s, const char *c, uint16_t l) -{ - for (; *s && *s == *c && --l; s++, c++) ; - return !l; // make sure you reached the end -} - -#endif diff --git a/src/blua/liolib.c b/src/blua/liolib.c index 40e3e4582..929937e2e 100644 --- a/src/blua/liolib.c +++ b/src/blua/liolib.c @@ -161,12 +161,13 @@ static int io_tostring (lua_State *L) { static int StartsWith(const char *a, const char *b) // this is wolfs being lazy yet again { - if(strncmp(a, b, strlen(b)) == 0) return 1; + if (strncmp(a, b, strlen(b)) == 0) return 1; return 0; } -static int io_open (lua_State *L) { +static int io_open(lua_State *L) +{ FILE **pf; const char *filename = luaL_checkstring(L, 1); int pass = 0; @@ -178,12 +179,13 @@ static int io_open (lua_State *L) { for (i = 0; i < (sizeof (whitelist) / sizeof(const char *)); i++) { - if (!stricmp(&filename[length - strlen(whitelist[i])], whitelist[i])) + if (fasticmp(&filename[length - strlen(whitelist[i])], whitelist[i])) { pass = 1; break; } } + if (l_unlikely(strstr(filename, "..") || strchr(filename, ':') || StartsWith(filename, "\\") || StartsWith(filename, "/") || !pass)) { diff --git a/src/command.c b/src/command.c index d5cbf8041..9f9b39500 100644 --- a/src/command.c +++ b/src/command.c @@ -456,7 +456,7 @@ void COM_AddCommand(const char *name, com_func_t func) // fail if the command already exists for (cmd = com_commands; cmd; cmd = cmd->next) { - if (!stricmp(name, cmd->name)) //case insensitive now that we have lower and uppercase! + if (fasticmp(name, cmd->name)) //case insensitive now that we have lower and uppercase! { // don't I_Error for Lua commands // Lua commands can replace game commands, and they have priority. @@ -492,7 +492,7 @@ int COM_AddLuaCommand(const char *name) // command already exists for (cmd = com_commands; cmd; cmd = cmd->next) { - if (!stricmp(name, cmd->name)) //case insensitive now that we have lower and uppercase! + if (fasticmp(name, cmd->name)) //case insensitive now that we have lower and uppercase! { // replace the built in command. cmd->function = COM_Lua_f; @@ -519,7 +519,7 @@ static boolean COM_Exists(const char *com_name) xcommand_t *cmd; for (cmd = com_commands; cmd; cmd = cmd->next) - if (!stricmp(com_name, cmd->name)) + if (fasticmp(com_name, cmd->name)) return true; return false; @@ -571,7 +571,7 @@ static void COM_ExecuteString(char *ptext) // check functions for (cmd = com_commands; cmd; cmd = cmd->next) { - if (!stricmp(com_argv[0], cmd->name)) //case insensitive now that we have lower and uppercase! + if (fasticmp(com_argv[0], cmd->name)) //case insensitive now that we have lower and uppercase! { cmd->function(); return; @@ -581,7 +581,7 @@ static void COM_ExecuteString(char *ptext) // check aliases for (a = com_alias; a; a = a->next) { - if (!stricmp(com_argv[0], a->name)) + if (fasticmp(com_argv[0], a->name)) { if (recursion > MAX_ALIAS_RECURSION) CONS_Alert(CONS_WARNING, M_GetText("Alias recursion cycle detected!\n")); @@ -836,7 +836,7 @@ static void COM_Help_f(void) if (cvar->PossibleValue) { { - if (!stricmp(cvar->PossibleValue[0].strvalue, "MIN") && !stricmp(cvar->PossibleValue[1].strvalue, "MAX")) + if (fasticmp(cvar->PossibleValue[0].strvalue, "MIN") && fasticmp(cvar->PossibleValue[1].strvalue, "MAX")) { if (floatmode) { @@ -1176,7 +1176,7 @@ consvar_t *CV_FindVar(const char *name) consvar_t *cvar; for (cvar = consvar_vars; cvar; cvar = cvar->next) - if (!stricmp(name,cvar->name)) + if (fasticmp(name,cvar->name)) return cvar; return NULL; @@ -1366,7 +1366,7 @@ static void Setvalue(consvar_t *var, const char *valstr, boolean stealth) v = INT32_MIN; // Invalid integer trigger } - if (var->PossibleValue[0].strvalue && !stricmp(var->PossibleValue[0].strvalue, "MIN")) // bounded cvar + if (var->PossibleValue[0].strvalue && fasticmp(var->PossibleValue[0].strvalue, "MIN")) // bounded cvar { #define MINVAL 0 #define MAXVAL 1 @@ -1379,21 +1379,21 @@ static void Setvalue(consvar_t *var, const char *valstr, boolean stealth) // search for other for (i = MAXVAL+1; var->PossibleValue[i].strvalue; i++) - if (v == var->PossibleValue[i].value || !stricmp(var->PossibleValue[i].strvalue, valstr)) + if (v == var->PossibleValue[i].value || fasticmp(var->PossibleValue[i].strvalue, valstr)) { var->value = var->PossibleValue[i].value; var->string = var->PossibleValue[i].strvalue; goto finish; } - if ((v != INT32_MIN && v < var->PossibleValue[MINVAL].value) || !stricmp(valstr, "MIN")) + if ((v != INT32_MIN && v < var->PossibleValue[MINVAL].value) || fasticmp(valstr, "MIN")) { v = var->PossibleValue[MINVAL].value; valstr = var->PossibleValue[MINVAL].strvalue; override = true; overrideval = v; } - else if ((v != INT32_MIN && v > var->PossibleValue[MAXVAL].value) || !stricmp(valstr, "MAX")) + else if ((v != INT32_MIN && v > var->PossibleValue[MAXVAL].value) || fasticmp(valstr, "MAX")) { v = var->PossibleValue[MAXVAL].value; valstr = var->PossibleValue[MAXVAL].strvalue; @@ -1411,7 +1411,7 @@ static void Setvalue(consvar_t *var, const char *valstr, boolean stealth) // check first strings for (i = 0; var->PossibleValue[i].strvalue; i++) - if (!stricmp(var->PossibleValue[i].strvalue, valstr)) + if (fasticmp(var->PossibleValue[i].strvalue, valstr)) goto found; if (v != INT32_MIN) { @@ -1424,9 +1424,9 @@ static void Setvalue(consvar_t *var, const char *valstr, boolean stealth) if (var->PossibleValue == CV_OnOff || var->PossibleValue == CV_YesNo) { overrideval = -1; - if (!stricmp(valstr, "on") || !stricmp(valstr, "yes")) + if (fasticmp(valstr, "on") || fasticmp(valstr, "yes")) overrideval = 1; - else if (!stricmp(valstr, "off") || !stricmp(valstr, "no")) + else if (fasticmp(valstr, "off") || fasticmp(valstr, "no")) overrideval = 0; if (overrideval != -1) @@ -1643,7 +1643,7 @@ static void CV_SetCVar(consvar_t *var, const char *value, boolean stealth) if (!var->string) I_Error("CV_Set: %s no string set!\n", var->name); #endif - if (!var || !var->string || !value || !stricmp(var->string, value)) + if (!var || !var->string || !value || fasticmp(var->string, value)) return; // no changes if (var->flags & CV_NETVAR) @@ -1665,7 +1665,7 @@ static void CV_SetCVar(consvar_t *var, const char *value, boolean stealth) if (var == &cv_kartspeed && !M_SecretUnlocked(SECRET_HARDSPEED)) { - if (!stricmp(value, "Hard") || atoi(value) == 2) + if (fasticmp(value, "Hard") || atoi(value) == 2) { CONS_Alert(CONS_NOTICE, "You haven't unlocked this yet!\n"); return; @@ -1971,12 +1971,12 @@ static boolean CV_FilterJoyAxisVars(consvar_t *v, const char *valstr) { if (joyaxis_default[i]) { - if (!stricmp(v->name, "joyaxis_fire")) + if (fasticmp(v->name, "joyaxis_fire")) { if (joyaxis_count[i] > 7) return false; else if (joyaxis_count[i] == 7) return true; - if (!stricmp(valstr, "None")) joyaxis_count[i]++; + if (fasticmp(valstr, "None")) joyaxis_count[i]++; else joyaxis_default[i] = false; } // reset all axis settings to defaults @@ -2008,37 +2008,37 @@ static boolean CV_FilterJoyAxisVars(consvar_t *v, const char *valstr) // Block the Xbox DInput default axes and reset to the current defaults static boolean CV_FilterJoyAxisVars2(consvar_t *v, const char *valstr) { - if (!stricmp(v->name, "joyaxis_turn") && !stricmp(valstr, "X-Axis")) + if (fasticmp(v->name, "joyaxis_turn") && fasticmp(valstr, "X-Axis")) return false; - if (!stricmp(v->name, "joyaxis2_turn") && !stricmp(valstr, "X-Axis")) + if (fasticmp(v->name, "joyaxis2_turn") && fasticmp(valstr, "X-Axis")) return false; - if (!stricmp(v->name, "joyaxis3_turn") && !stricmp(valstr, "X-Axis")) + if (fasticmp(v->name, "joyaxis3_turn") && fasticmp(valstr, "X-Axis")) return false; - if (!stricmp(v->name, "joyaxis4_turn") && !stricmp(valstr, "X-Axis")) + if (fasticmp(v->name, "joyaxis4_turn") && fasticmp(valstr, "X-Axis")) return false; - if (!stricmp(v->name, "joyaxis_aim") && !stricmp(valstr, "Y-Axis")) + if (fasticmp(v->name, "joyaxis_aim") && fasticmp(valstr, "Y-Axis")) return false; - if (!stricmp(v->name, "joyaxis2_aim") && !stricmp(valstr, "Y-Axis")) + if (fasticmp(v->name, "joyaxis2_aim") && fasticmp(valstr, "Y-Axis")) return false; - if (!stricmp(v->name, "joyaxis3_aim") && !stricmp(valstr, "Y-Axis")) + if (fasticmp(v->name, "joyaxis3_aim") && fasticmp(valstr, "Y-Axis")) return false; - if (!stricmp(v->name, "joyaxis4_aim") && !stricmp(valstr, "Y-Axis")) + if (fasticmp(v->name, "joyaxis4_aim") && fasticmp(valstr, "Y-Axis")) return false; - if (!stricmp(v->name, "joyaxis_fire") && !stricmp(valstr, "None")) + if (fasticmp(v->name, "joyaxis_fire") && fasticmp(valstr, "None")) return false; - if (!stricmp(v->name, "joyaxis2_fire") && !stricmp(valstr, "None")) + if (fasticmp(v->name, "joyaxis2_fire") && fasticmp(valstr, "None")) return false; - if (!stricmp(v->name, "joyaxis3_fire") && !stricmp(valstr, "None")) + if (fasticmp(v->name, "joyaxis3_fire") && fasticmp(valstr, "None")) return false; - if (!stricmp(v->name, "joyaxis4_fire") && !stricmp(valstr, "None")) + if (fasticmp(v->name, "joyaxis4_fire") && fasticmp(valstr, "None")) return false; - if (!stricmp(v->name, "joyaxis_drift") && !stricmp(valstr, "None")) + if (fasticmp(v->name, "joyaxis_drift") && fasticmp(valstr, "None")) return false; - if (!stricmp(v->name, "joyaxis2_drift") && !stricmp(valstr, "None")) + if (fasticmp(v->name, "joyaxis2_drift") && fasticmp(valstr, "None")) return false; - if (!stricmp(v->name, "joyaxis3_drift") && !stricmp(valstr, "None")) + if (fasticmp(v->name, "joyaxis3_drift") && fasticmp(valstr, "None")) return false; - if (!stricmp(v->name, "joyaxis4_drift") && !stricmp(valstr, "None")) + if (fasticmp(v->name, "joyaxis4_drift") && fasticmp(valstr, "None")) return false; return true; @@ -2055,8 +2055,8 @@ static boolean CV_FilterVarByVersion(consvar_t *v, const char *valstr) if (GETMAJOREXECVERSION(cv_execversion.value) < 8) // 8 = 1.4 { - if (!stricmp(v->name, "masterserver") // Replaces a hack in MasterServer_OnChange for the original SRB2 MS. - || !stricmp(v->name, "gamma")) // Too easy to accidentially change in prior versions. + if (fasticmp(v->name, "masterserver") // Replaces a hack in MasterServer_OnChange for the original SRB2 MS. + || fasticmp(v->name, "gamma")) // Too easy to accidentially change in prior versions. return false; } diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 2ca42df65..255e7ce8e 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -3215,7 +3215,7 @@ static void Command_connect(void) server = false; - if (!stricmp(COM_Argv(1), "self")) + if (fasticmp(COM_Argv(1), "self")) { servernode = 0; server = true; @@ -3225,7 +3225,7 @@ static void Command_connect(void) else { // used in menu to connect to a server in the list - if (netgame && !stricmp(COM_Argv(1), "node")) + if (netgame && fasticmp(COM_Argv(1), "node")) { servernode = (SINT8)atoi(COM_Argv(2)); } @@ -3240,7 +3240,7 @@ static void Command_connect(void) netgame = true; multiplayer = true; - if (!stricmp(COM_Argv(1), "any")) + if (fasticmp(COM_Argv(1), "any")) servernode = BROADCASTADDR; else if (I_NetMakeNodewPort && COM_Argc() >= 3) servernode = I_NetMakeNodewPort(COM_Argv(1), COM_Argv(2)); @@ -3264,6 +3264,7 @@ static void Command_connect(void) splitscreen = cv_splitplayers.value-1; SplitScreen_OnChange(); } + botingame = false; botskin = 0; CL_ConnectToServer(); diff --git a/src/d_main.c b/src/d_main.c index ef1855d05..bafc110e1 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1078,19 +1078,19 @@ static INT32 D_DetectFileType(const char* filename) const size_t len = strlen(filename); - if (!stricmp(&filename[len - 4], ".wad")) + if (fasticmp(&filename[len - 4], ".wad")) return 2; - else if (!stricmp(&filename[len - 4], ".pk3")) + else if (fasticmp(&filename[len - 4], ".pk3")) return 3; - else if (!stricmp(&filename[len - 5], ".kart")) + else if (fasticmp(&filename[len - 5], ".kart")) return 4; - else if (!stricmp(&filename[len - 4], ".lua")) + else if (fasticmp(&filename[len - 4], ".lua")) return 5; - else if (!stricmp(&filename[len - 4], ".soc")) + else if (fasticmp(&filename[len - 4], ".soc")) return 6; - else if (!stricmp(&filename[len - 4], ".cfg")) + else if (fasticmp(&filename[len - 4], ".cfg")) return 7; - else if (!stricmp(&filename[len - 4], ".txt")) + else if (fasticmp(&filename[len - 4], ".txt")) return 8; return 0; diff --git a/src/d_netfil.c b/src/d_netfil.c index f279eaee0..c82165788 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -550,7 +550,8 @@ INT32 CL_CheckFiles(void) for (j = mainwads+1; j < numwadfiles; j++) { nameonly(strcpy(wadfilename, wadfiles[j]->filename)); - if (!stricmp(wadfilename, fileneeded[i].filename) && + + if (fasticmp(wadfilename, fileneeded[i].filename) && !memcmp(wadfiles[j]->md5sum, fileneeded[i].md5sum, 16)) { CONS_Debug(DBG_NETPLAY, "already loaded\n"); @@ -665,7 +666,7 @@ static boolean SV_SendFile(INT32 node, const char *filename, UINT8 fileid) strlcpy(wadfilename, wadfiles[wadnum]->filename, MAX_WADPATH); nameonly(wadfilename); - if (!stricmp(wadfilename, p->id.filename)) + if (fasticmp(wadfilename, p->id.filename)) { // Copy file name with full path strlcpy(p->id.filename, wadfiles[wadnum]->filename, MAX_WADPATH); diff --git a/src/doomtype.h b/src/doomtype.h index 7b0df4841..78867ed69 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -63,7 +63,7 @@ extern "C" { #endif #if defined (__unix__) || defined (__APPLE__) || defined (UNIXCOMMON) #undef stricmp - #define stricmp(x,y) !fasticmp(x,y) + #define stricmp(x,y) strcasecmp(x,y) #undef strnicmp #define strnicmp(x,y,n) strncasecmp(x,y,n) #endif diff --git a/src/g_demo.c b/src/g_demo.c index bd3905160..7ee773b1f 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -264,7 +264,7 @@ void G_ReadDemoExtraData(void) kartspeed = READUINT8(demobuf.p); kartweight = READUINT8(demobuf.p); - if (stricmp(skins[players[p].skin].name, name) != 0) + if (!fasticmp(skins[players[p].skin].name, name)) FindClosestSkinForStats(p, kartspeed, kartweight); players[p].kartspeed = kartspeed; @@ -277,7 +277,7 @@ void G_ReadDemoExtraData(void) M_Memcpy(name, demobuf.p, 16); demobuf.p += 16; for (i = 0; i < MAXSKINCOLORS; i++) - if (!stricmp(KartColor_Names[i], name)) // SRB2kart + if (fasticmp(KartColor_Names[i], name)) // SRB2kart { players[p].skincolor = i; if (players[p].mo) @@ -2289,7 +2289,7 @@ void G_LoadDemoInfo(menudemo_t *pdemo) { for (UINT8 j = 0; kartspeed_cons_t[j].strvalue; j++) { - if (!stricmp(kartspeed_cons_t[j].strvalue, svalue)) + if (fasticmp(kartspeed_cons_t[j].strvalue, svalue)) pdemo->kartspeed = kartspeed_cons_t[j].value; } } @@ -2321,7 +2321,7 @@ void G_LoadDemoInfo(menudemo_t *pdemo) for (i = 0; i < numskins; i++) { - if (stricmp(skins[i].name, temp) == 0) + if (fasticmp(skins[i].name, temp)) { pdemo->standings[count].skin = i; break; @@ -2334,7 +2334,7 @@ void G_LoadDemoInfo(menudemo_t *pdemo) for (i = 0; i < MAXSKINCOLORS; i++) { - if (!stricmp(KartColor_Names[i],temp)) // SRB2kart + if (fasticmp(KartColor_Names[i],temp)) // SRB2kart { pdemo->standings[count].color = i; break; @@ -2807,7 +2807,7 @@ void G_DoPlayDemo(char *defdemoname) // Set color for (i = 0; i < MAXSKINCOLORS; i++) { - if (!stricmp(KartColor_Names[i],color)) // SRB2kart + if (fasticmp(KartColor_Names[i],color)) // SRB2kart { players[0].skincolor = i; break; @@ -2947,7 +2947,7 @@ void G_DoPlayDemo(char *defdemoname) for (i = 0; i < MAXSKINCOLORS; i++) { - if (!stricmp(KartColor_Names[i],color)) // SRB2kart + if (fasticmp(KartColor_Names[i],color)) // SRB2kart { players[p].skincolor = i; break; @@ -2961,7 +2961,7 @@ void G_DoPlayDemo(char *defdemoname) kartspeed[p] = READUINT8(demobuf.p); kartweight[p] = READUINT8(demobuf.p); - if (stricmp(skins[players[p].skin].name, skin) != 0) + if (!fasticmp(skins[players[p].skin].name, skin)) FindClosestSkinForStats(p, kartspeed[p], kartweight[p]); // Look for the next player @@ -3242,7 +3242,7 @@ void G_AddGhost(char *defdemoname) for (i = 0; i < numskins; i++) { - if (!stricmp(skins[i].name,skin)) + if (fasticmp(skins[i].name, skin)) { ghskin = &skins[i]; break; @@ -3317,7 +3317,7 @@ void G_AddGhost(char *defdemoname) for (i = 0; i < MAXSKINCOLORS; i++) { - if (!stricmp(KartColor_Names[i],color)) // SRB2kart + if (fasticmp(KartColor_Names[i],color)) // SRB2kart { gh->mo->color = (UINT8)i; break; diff --git a/src/g_game.c b/src/g_game.c index 05615df78..125c88067 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2768,7 +2768,7 @@ INT32 G_GetGametypeByName(const char *gametypestr) INT32 i; for (i = 0; i < NUMGAMETYPES; i++) - if (!stricmp(gametypestr, Gametype_Names[i])) + if (fasticmp(gametypestr, Gametype_Names[i])) return i; return -1; // unknown gametype diff --git a/src/g_input.c b/src/g_input.c index e8bc8223e..e5cd04668 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -1033,7 +1033,7 @@ INT32 G_KeyStringtoNum(const char *keystr) return atoi(&keystr[3]); for (j = 0; j < NUMKEYNAMES; j++) - if (!stricmp(keynames[j].name, keystr)) + if (fasticmp(keynames[j].name, keystr)) return keynames[j].keynum; return 0; @@ -1333,14 +1333,15 @@ static void setcontrol(INT32 (*gc)[2]) player = 0; namectrl = COM_Argv(1); - for (numctrl = 0; numctrl < num_gamecontrols && stricmp(namectrl, gamecontrolname[numctrl]); - numctrl++) + for (numctrl = 0; numctrl < num_gamecontrols && !fasticmp(namectrl, gamecontrolname[numctrl]); numctrl++) ; + if (numctrl == num_gamecontrols) { CONS_Printf(M_GetText("Control '%s' unknown\n"), namectrl); return; } + keynum1 = G_KeyStringtoNum(COM_Argv(2)); keynum2 = G_KeyStringtoNum(COM_Argv(3)); keynum = G_FilterKeyByVersion(numctrl, 0, player, &keynum1, &keynum2, &nestedoverride); diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index f3db532e9..10e5e4e1b 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -549,7 +549,7 @@ void HWR_InitMD2(void) { for (i = 0; i < NUMSPRITES; i++) { - if (stricmp(name, sprnames[i]) == 0) + if (fasticmp(name, sprnames[i])) { md2_models[i].scale = scale; md2_models[i].offset = offset; @@ -561,7 +561,7 @@ void HWR_InitMD2(void) for (s = 0; s < MAXSKINS; s++) { - if (stricmp(name, skins[s].name) == 0) + if (fasticmp(name, skins[s].name)) { md2_playermodels[s].skin = s; md2_playermodels[s].scale = scale; @@ -607,11 +607,12 @@ void HWR_AddPlayerMD2(int skin, boolean local) // For MD2's that were added afte } } - md2s = ( (local) ? md2_localplayermodels : md2_playermodels ); + md2s = (local ? md2_localplayermodels : md2_playermodels); + // Check for any MD2s that match the names of player skins! while (fscanf(f, "%19s %31s %f %f", name, filename, &scale, &offset) == 4) { - if (stricmp(name, K_GetSkinArray(local)[skin].name) == 0) + if (fasticmp(name, K_GetSkinArray(local)[skin].name)) { md2s[skin].skin = skin; md2s[skin].scale = scale; @@ -650,6 +651,7 @@ void HWR_AddSpriteMD2(size_t spritenum) // For MD2s that were added after startu if (!f) { f = fopen(va("%s"PATHSEP"%s", srb2path, "mdls.dat"), "rt"); + if (!f) { CONS_Printf("%s %s\n", M_GetText("Error while loading mdls.dat:"), strerror(errno)); @@ -661,7 +663,7 @@ void HWR_AddSpriteMD2(size_t spritenum) // For MD2s that were added after startu // Check for any MD2s that match the names of sprite names! while (fscanf(f, "%19s %31s %f %f", name, filename, &scale, &offset) == 4) { - if (stricmp(name, sprnames[spritenum]) == 0) + if (fasticmp(name, sprnames[spritenum])) { md2_models[spritenum].scale = scale; md2_models[spritenum].offset = offset; diff --git a/src/hardware/hw_model.c b/src/hardware/hw_model.c index 77a995ed0..811ac3b67 100644 --- a/src/hardware/hw_model.c +++ b/src/hardware/hw_model.c @@ -126,7 +126,7 @@ tag_t *GetTagByName(model_t *model, char *name, int frame) int i; for (i = 0; i < model->numTags; i++) { - if (!stricmp(iterator[i].name, name)) + if (fasticmp(iterator[i].name, name)) return &iterator[i]; } } diff --git a/src/hardware/hw_shaders.c b/src/hardware/hw_shaders.c index 9724378fe..19aea915e 100644 --- a/src/hardware/hw_shaders.c +++ b/src/hardware/hw_shaders.c @@ -586,7 +586,7 @@ void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3) goto skip_field; } - if (!stricmp(stoken, "GLSL")) + if (fasticmp(stoken, "GLSL")) { value = strtok(NULL, "\r\n "); if (!value) @@ -596,9 +596,9 @@ void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3) goto skip_lump; } - if (!stricmp(value, "VERTEX")) + if (fasticmp(value, "VERTEX")) shadertype = 1; - else if (!stricmp(value, "FRAGMENT")) + else if (fasticmp(value, "FRAGMENT")) shadertype = 2; skip_lump: @@ -624,7 +624,7 @@ skip_lump: for (i = 0; shaderxlat[i].type; i++) { - if (!stricmp(shaderxlat[i].type, stoken)) + if (fasticmp(shaderxlat[i].type, stoken)) { size_t shader_string_length; char *shader_source; diff --git a/src/k_kart.c b/src/k_kart.c index 7f755e235..3f335a5bb 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -637,11 +637,14 @@ void K_GenerateKartColormap(UINT8 *dest_colormap, INT32 skinnum, UINT8 color, bo UINT8 K_GetKartColorByName(const char *name) { UINT8 color = (UINT8)atoi(name); + if (color > 0 && color < MAXSKINCOLORS) return color; + for (color = 1; color < MAXSKINCOLORS; color++) - if (!stricmp(KartColor_Names[color], name)) + if (fasticmp(KartColor_Names[color], name)) return color; + return 0; } diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index 36c3a6c45..df45e3e07 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -453,7 +453,7 @@ static int lib_cvRegisterVar(lua_State *L) if (cvar->flags & CV_MODIFIED) return luaL_error(L, "failed to register cvar (probable conflict with internal variable/command names)"); - if (!(((cvar->flags & CV_HIDEN)) || (cvar->flags & CV_NOSHOWHELP)) && (cvar->PossibleValue || !(cvar->value == 0 && stricmp(cvar->string, "0")))) + if (!(((cvar->flags & CV_HIDEN)) || (cvar->flags & CV_NOSHOWHELP)) && (cvar->PossibleValue || !(cvar->value == 0 && !fasticmp(cvar->string, "0")))) { if (!category) { diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 5ffbcb34e..fef27f563 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -455,12 +455,12 @@ int mobj_localskin_setter(lua_State *L) strlcpy(skin, luaL_optstring(L, 2, "none"), sizeof skin); strlwr(skin); // all skin names are lowercase - if (stricmp(skin, "none")) + if (!fasticmp(skin, "none")) { // Try localskins for (i = 0; i < numlocalskins; i++) { - if (stricmp(localskins[i].name, skin) == 0) + if (fasticmp(localskins[i].name, skin)) { mo->localskin = &localskins[i]; mo->skinlocal = true; @@ -471,7 +471,7 @@ int mobj_localskin_setter(lua_State *L) // Try other skins for (i = 0; i < numskins; i++) { - if (stricmp(skins[i].name, skin) == 0) + if (fasticmp(skins[i].name, skin)) { mo->localskin = &skins[i]; mo->skinlocal = false; diff --git a/src/m_emotes.cpp b/src/m_emotes.cpp index 57058ef23..45fd78804 100644 --- a/src/m_emotes.cpp +++ b/src/m_emotes.cpp @@ -112,7 +112,7 @@ void M_LoadEmotes(UINT16 wadnum) trim(field); trim(value); - if (stricmp(field.c_str(), "frames") == 0) + if (fasticmp(field.c_str(), "frames")) { UINT8 numframes = 0; @@ -158,7 +158,7 @@ void M_LoadEmotes(UINT16 wadnum) emote->numframes = numframes; } - else if (stricmp(field.c_str(), "timeperframe") == 0) + else if (fasticmp(field.c_str(), "timeperframe")) { emote->timeperframe = std::stoi(value); diff --git a/src/m_menu.c b/src/m_menu.c index bd79ec80c..09a0c6350 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6799,7 +6799,7 @@ static int ServerListEntryComparator_##key(const void *entry1, const void *entry const serverelem_t *sa = (const serverelem_t*)entry1, *sb = (const serverelem_t*)entry2; \ if (sa->info.key != sb->info.key) \ return sa->info.key - sb->info.key; \ - return !fastcmp(sa->info.servername, sb->info.servername); \ + return strcmp(sa->info.servername, sb->info.servername); \ } // This does descending instead of ascending. @@ -6809,7 +6809,7 @@ static int ServerListEntryComparator_##key##_reverse(const void *entry1, const v const serverelem_t *sa = (const serverelem_t*)entry1, *sb = (const serverelem_t*)entry2; \ if (sb->info.key != sa->info.key) \ return sb->info.key - sa->info.key; \ - return !fastcmp(sb->info.servername, sa->info.servername); \ + return strcmp(sb->info.servername, sa->info.servername); \ } SERVER_LIST_ENTRY_COMPARATOR(time) @@ -6830,8 +6830,8 @@ static int ServerListEntryComparator_modified(const void *entry1, const void *en if (modstate_a != modstate_b) return modstate_a - modstate_b; - // Default to !fastcmp. - return !fastcmp(sa->info.servername, sb->info.servername); + // Default to strcmp. + return strcmp(sa->info.servername, sb->info.servername); } void M_SortServerList(void) diff --git a/src/m_misc.c b/src/m_misc.c index 4a0a163aa..58e4b191e 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -423,7 +423,7 @@ void Command_SaveConfig_f(void) FIL_ForceExtension(tmpstr, ".cfg"); M_SaveConfig(tmpstr); - if (stricmp(COM_Argv(2), "-silent")) + if (!fasticmp(COM_Argv(2), "-silent")) CONS_Printf(M_GetText("config saved as %s\n"), configfile); } diff --git a/src/p_spec.c b/src/p_spec.c index e7b032131..e08030e9e 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -324,6 +324,7 @@ void P_InitPicAnims(void) lastanim->speed = LONG(animdefs[i].speed); lastanim++; } + lastanim->istexture = -1; R_ClearTextureNumCache(false); @@ -331,6 +332,7 @@ void P_InitPicAnims(void) // We'll only be using anims from now on. if (animdefs != harddefs) Z_Free(animdefs); + animdefs = NULL; } @@ -361,20 +363,21 @@ void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum) // Now, let's start parsing this thing p = animdefsText; + animdefsToken = M_GetToken(p); while (animdefsToken != NULL) { - if (stricmp(animdefsToken, "TEXTURE") == 0) + if (fasticmp(animdefsToken, "TEXTURE")) { Z_Free(animdefsToken); P_ParseAnimationDefintion(1); } - else if (stricmp(animdefsToken, "FLAT") == 0) + else if (fasticmp(animdefsToken, "FLAT")) { Z_Free(animdefsToken); P_ParseAnimationDefintion(0); } - else if (stricmp(animdefsToken, "OSCILLATE") == 0) + else if (fasticmp(animdefsToken, "OSCILLATE")) { // This probably came off the tail of an earlier definition. It's technically legal syntax, but we don't support it. I_Error("Error parsing ANIMDEFS lump: Animation definitions utilizing \"OSCILLATE\" (the animation plays in reverse when it reaches the end) are not supported by SRB2"); @@ -383,11 +386,17 @@ void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum) { I_Error("Error parsing ANIMDEFS lump: Expected \"TEXTURE\" or \"FLAT\", got \"%s\"",animdefsToken); } + // parse next line - while (*p != '\0' && *p != '\n') ++p; - if (*p == '\n') ++p; + while (*p != '\0' && *p != '\n') + ++p; + + if (*p == '\n') + ++p; + animdefsToken = M_GetToken(p); } + Z_Free(animdefsToken); Z_Free((void *)animdefsText); } @@ -406,7 +415,8 @@ void P_ParseAnimationDefintion(SINT8 istexture) { I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where start texture/flat name should be"); } - if (stricmp(animdefsToken, "OPTIONAL") == 0) + + if (fasticmp(animdefsToken, "OPTIONAL")) { // This is meaningful to ZDoom - it tells the program NOT to bomb out // if the textures can't be found - but it's useless in SRB2, so we'll @@ -418,7 +428,7 @@ void P_ParseAnimationDefintion(SINT8 istexture) { I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where start texture/flat name should be"); } - else if (stricmp(animdefsToken, "RANGE") == 0) + else if (fasticmp(animdefsToken, "RANGE")) { // Oh. Um. Apparently "OPTIONAL" is a texture name. Naughty. // I should probably handle this more gracefully, but right now @@ -427,15 +437,17 @@ void P_ParseAnimationDefintion(SINT8 istexture) I_Error("Error parsing ANIMDEFS lump: \"OPTIONAL\" is a keyword; you cannot use it as the startname of an animation"); } } + animdefsTokenLength = strlen(animdefsToken); - if (animdefsTokenLength>8) + if (animdefsTokenLength > 8) { I_Error("Error parsing ANIMDEFS lump: lump name \"%s\" exceeds 8 characters", animdefsToken); } // Search for existing animdef for (i = 0; i < maxanims; i++) - if (stricmp(animdefsToken, animdefs[i].startname) == 0) + { + if (fasticmp(animdefsToken, animdefs[i].startname)) { //CONS_Alert(CONS_NOTICE, "Duplicate animation: %s\n", animdefsToken); @@ -444,6 +456,7 @@ void P_ParseAnimationDefintion(SINT8 istexture) Z_Free(animdefsToken); return; } + } // Not found if (i == maxanims) @@ -467,21 +480,25 @@ void P_ParseAnimationDefintion(SINT8 istexture) { I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"RANGE\" after \"%s\"'s startname should be", animdefs[i].startname); } - if (stricmp(animdefsToken, "ALLOWDECALS") == 0) + + if (fasticmp(animdefsToken, "ALLOWDECALS")) { // Another ZDoom keyword, ho-hum. Skip it, move on to the next token. Z_Free(animdefsToken); animdefsToken = M_GetToken(NULL); } - if (stricmp(animdefsToken, "PIC") == 0) + + if (fasticmp(animdefsToken, "PIC")) { // This is technically legitimate ANIMDEFS syntax, but SRB2 doesn't support it. I_Error("Error parsing ANIMDEFS lump: Animation definitions utilizing \"PIC\" (specific frames instead of a consecutive range) are not supported by SRB2"); } - if (stricmp(animdefsToken, "RANGE") != 0) + + if (!fasticmp(animdefsToken, "RANGE")) { I_Error("Error parsing ANIMDEFS lump: Expected \"RANGE\" after \"%s\"'s startname, got \"%s\"", animdefs[i].startname, animdefsToken); } + Z_Free(animdefsToken); // Endname @@ -490,11 +507,13 @@ void P_ParseAnimationDefintion(SINT8 istexture) { I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"%s\"'s end texture/flat name should be", animdefs[i].startname); } + animdefsTokenLength = strlen(animdefsToken); if (animdefsTokenLength>8) { I_Error("Error parsing ANIMDEFS lump: lump name \"%s\" exceeds 8 characters", animdefsToken); } + strncpy(animdefs[i].endname, animdefsToken, 9); Z_Free(animdefsToken); @@ -504,15 +523,18 @@ void P_ParseAnimationDefintion(SINT8 istexture) { I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"%s\"'s \"TICS\" should be", animdefs[i].startname); } - if (stricmp(animdefsToken, "RAND") == 0) + + if (fasticmp(animdefsToken, "RAND")) { // This is technically legitimate ANIMDEFS syntax, but SRB2 doesn't support it. I_Error("Error parsing ANIMDEFS lump: Animation definitions utilizing \"RAND\" (random duration per frame) are not supported by SRB2"); } - if (stricmp(animdefsToken, "TICS") != 0) + + if (!fasticmp(animdefsToken, "TICS")) { I_Error("Error parsing ANIMDEFS lump: Expected \"TICS\" in animation definition for \"%s\", got \"%s\"", animdefs[i].startname, animdefsToken); } + Z_Free(animdefsToken); // Speed @@ -521,6 +543,7 @@ void P_ParseAnimationDefintion(SINT8 istexture) { I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"%s\"'s animation speed should be", animdefs[i].startname); } + endPos = NULL; #ifndef AVOID_ERRNO errno = 0; @@ -535,6 +558,7 @@ void P_ParseAnimationDefintion(SINT8 istexture) { I_Error("Error parsing ANIMDEFS lump: Expected a positive integer for \"%s\"'s animation speed, got \"%s\"", animdefs[i].startname, animdefsToken); } + animdefs[i].speed = animSpeed; Z_Free(animdefsToken); } diff --git a/src/r_data.c b/src/r_data.c index 893252571..3077326ad 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -976,8 +976,9 @@ static texture_t *R_ParseTexture(boolean actuallyLoadTexture) { I_Error("Error parsing TEXTURES lump: Unexpected end of file where texture name should be"); } + texturesTokenLength = strlen(texturesToken); - if (texturesTokenLength>8) + if (texturesTokenLength > 8) { I_Error("Error parsing TEXTURES lump: Texture name \"%s\" exceeds 8 characters",texturesToken); } @@ -988,6 +989,7 @@ static texture_t *R_ParseTexture(boolean actuallyLoadTexture) // ^^ we've confirmed that the token is <= 8 characters so it will never overflow a 9 byte char buffer strupr(newTextureName); // Just do this now so we don't have to worry about it } + Z_Free(texturesToken); // Comma 1 @@ -996,10 +998,11 @@ static texture_t *R_ParseTexture(boolean actuallyLoadTexture) { I_Error("Error parsing TEXTURES lump: Unexpected end of file where comma after texture \"%s\"'s name should be",newTextureName); } - else if (!fastcmp(texturesToken,",")) + else if (!fastcmp(texturesToken, ",")) { I_Error("Error parsing TEXTURES lump: Expected \",\" after texture \"%s\"'s name, got \"%s\"",newTextureName,texturesToken); } + Z_Free(texturesToken); // Width @@ -1030,10 +1033,12 @@ static texture_t *R_ParseTexture(boolean actuallyLoadTexture) { I_Error("Error parsing TEXTURES lump: Unexpected end of file where comma after texture \"%s\"'s width should be",newTextureName); } - if (!fastcmp(texturesToken,",")) + + if (!fastcmp(texturesToken, ",")) { I_Error("Error parsing TEXTURES lump: Expected \",\" after texture \"%s\"'s width, got \"%s\"",newTextureName,texturesToken); } + Z_Free(texturesToken); // Height @@ -1066,7 +1071,7 @@ static texture_t *R_ParseTexture(boolean actuallyLoadTexture) I_Error("Error parsing TEXTURES lump: Unexpected end of file where open curly brace for texture \"%s\" should be",newTextureName); } - if (fastcmp(texturesToken,"{")) + if (fastcmp(texturesToken, "{")) { if (actuallyLoadTexture) { @@ -1078,15 +1083,18 @@ static texture_t *R_ParseTexture(boolean actuallyLoadTexture) resultTexture->height = newTextureHeight; resultTexture->type = TEXTURETYPE_COMPOSITE; } + Z_Free(texturesToken); + texturesToken = M_GetToken(NULL); if (texturesToken == NULL) { I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch definition for texture \"%s\" should be",newTextureName); } - while (!fastcmp(texturesToken,"}")) + + while (!fastcmp(texturesToken, "}")) { - if (stricmp(texturesToken, "PATCH")==0) + if (fasticmp(texturesToken, "PATCH")) { Z_Free(texturesToken); if (resultTexture) @@ -1118,6 +1126,7 @@ static texture_t *R_ParseTexture(boolean actuallyLoadTexture) I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch declaration or right curly brace for texture \"%s\" should be",newTextureName); } } + if (resultTexture && resultTexture->patchcount == 0) { I_Error("Error parsing TEXTURES lump: Texture \"%s\" must have at least one patch",newTextureName); @@ -1127,10 +1136,13 @@ static texture_t *R_ParseTexture(boolean actuallyLoadTexture) { I_Error("Error parsing TEXTURES lump: Expected \"{\" for texture \"%s\", got \"%s\"",newTextureName,texturesToken); } + Z_Free(texturesToken); - if (actuallyLoadTexture) return resultTexture; - else return NULL; + if (actuallyLoadTexture) + return resultTexture; + + return NULL; } // Parses the TEXTURES lump... but just to count the number of textures. @@ -1162,7 +1174,7 @@ int R_CountTexturesInTEXTURESLump(UINT16 wadNum, UINT16 lumpNum) texturesToken = M_GetToken(texturesText); while (texturesToken != NULL) { - if (stricmp(texturesToken, "WALLTEXTURE")==0) + if (fasticmp(texturesToken, "WALLTEXTURE")) { numTexturesInLump++; Z_Free(texturesToken); @@ -1172,8 +1184,10 @@ int R_CountTexturesInTEXTURESLump(UINT16 wadNum, UINT16 lumpNum) { I_Error("Error parsing TEXTURES lump: Expected \"WALLTEXTURE\", got \"%s\"",texturesToken); } + texturesToken = M_GetToken(NULL); } + Z_Free(texturesToken); Z_Free((void *)texturesText); @@ -1211,7 +1225,7 @@ void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *texindex) texturesToken = M_GetToken(texturesText); while (texturesToken != NULL) { - if (stricmp(texturesToken, "WALLTEXTURE")==0) + if (fasticmp(texturesToken, "WALLTEXTURE")) { Z_Free(texturesToken); // Get the new texture @@ -1227,8 +1241,10 @@ void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *texindex) { I_Error("Error parsing TEXTURES lump: Expected \"WALLTEXTURE\", got \"%s\"",texturesToken); } + texturesToken = M_GetToken(NULL); } + Z_Free(texturesToken); Z_Free((void *)texturesText); } diff --git a/src/r_patch.cpp b/src/r_patch.cpp index 1e09ae7bb..7510520dd 100644 --- a/src/r_patch.cpp +++ b/src/r_patch.cpp @@ -46,13 +46,14 @@ static void R_ParseSpriteInfoFrame(spriteinfo_t *info) { I_Error("Error parsing SPRTINFO lump: Unexpected end of file where sprite frame should be"); } + sprinfoTokenLength = strlen(sprinfoToken); if (sprinfoTokenLength != 1) { I_Error("Error parsing SPRTINFO lump: Invalid frame \"%s\"",sprinfoToken); } - else - frameChar = sprinfoToken; + + frameChar = sprinfoToken; frameFrame = R_Char2Frame(frameChar[0]); Z_Free(sprinfoToken); @@ -61,53 +62,53 @@ static void R_ParseSpriteInfoFrame(spriteinfo_t *info) sprinfoToken = M_GetToken(NULL); if (sprinfoToken == NULL) I_Error("Error parsing SPRTINFO lump: Missing sprite info"); - else + + if (fastcmp(sprinfoToken, "{")) { - if (fastcmp(sprinfoToken,"{")) + Z_Free(sprinfoToken); + sprinfoToken = M_GetToken(NULL); + if (sprinfoToken == NULL) { + I_Error("Error parsing SPRTINFO lump: Unexpected end of file where sprite info should be"); + } + while (!fastcmp(sprinfoToken, "}")) + { + if (fasticmp(sprinfoToken, "XPIVOT")) + { + Z_Free(sprinfoToken); + sprinfoToken = M_GetToken(NULL); + frameXPivot = atoi(sprinfoToken); + } + else if (fasticmp(sprinfoToken, "YPIVOT")) + { + Z_Free(sprinfoToken); + sprinfoToken = M_GetToken(NULL); + frameYPivot = atoi(sprinfoToken); + } + else if (fasticmp(sprinfoToken, "ROTAXIS")) + { + Z_Free(sprinfoToken); + sprinfoToken = M_GetToken(NULL); + if (fasticmp(sprinfoToken, "X") || fasticmp(sprinfoToken, "XAXIS") || fasticmp(sprinfoToken, "ROLL")) + frameRotAxis = ROTAXIS_X; + else if (fasticmp(sprinfoToken, "Y") || fasticmp(sprinfoToken, "YAXIS") || fasticmp(sprinfoToken, "PITCH")) + frameRotAxis = ROTAXIS_Y; + else if (fasticmp(sprinfoToken, "Z") || fasticmp(sprinfoToken, "ZAXIS") || fasticmp(sprinfoToken, "YAW")) + frameRotAxis = ROTAXIS_Z; + } + Z_Free(sprinfoToken); + sprinfoToken = M_GetToken(NULL); if (sprinfoToken == NULL) { - I_Error("Error parsing SPRTINFO lump: Unexpected end of file where sprite info should be"); - } - while (!fastcmp(sprinfoToken,"}")) - { - if (stricmp(sprinfoToken, "XPIVOT")==0) - { - Z_Free(sprinfoToken); - sprinfoToken = M_GetToken(NULL); - frameXPivot = atoi(sprinfoToken); - } - else if (stricmp(sprinfoToken, "YPIVOT")==0) - { - Z_Free(sprinfoToken); - sprinfoToken = M_GetToken(NULL); - frameYPivot = atoi(sprinfoToken); - } - else if (stricmp(sprinfoToken, "ROTAXIS")==0) - { - Z_Free(sprinfoToken); - sprinfoToken = M_GetToken(NULL); - if ((stricmp(sprinfoToken, "X")==0) || (stricmp(sprinfoToken, "XAXIS")==0) || (stricmp(sprinfoToken, "ROLL")==0)) - frameRotAxis = ROTAXIS_X; - else if ((stricmp(sprinfoToken, "Y")==0) || (stricmp(sprinfoToken, "YAXIS")==0) || (stricmp(sprinfoToken, "PITCH")==0)) - frameRotAxis = ROTAXIS_Y; - else if ((stricmp(sprinfoToken, "Z")==0) || (stricmp(sprinfoToken, "ZAXIS")==0) || (stricmp(sprinfoToken, "YAW")==0)) - frameRotAxis = ROTAXIS_Z; - } - Z_Free(sprinfoToken); - - sprinfoToken = M_GetToken(NULL); - if (sprinfoToken == NULL) - { - I_Error("Error parsing SPRTINFO lump: Unexpected end of file where sprite info or right curly brace should be"); - } + I_Error("Error parsing SPRTINFO lump: Unexpected end of file where sprite info or right curly brace should be"); } } - Z_Free(sprinfoToken); } + Z_Free(sprinfoToken); + // set fields info->pivot[frameFrame].x = frameXPivot; info->pivot[frameFrame].y = frameYPivot; @@ -137,6 +138,7 @@ static void R_ParseSpriteInfo(boolean spr2) { I_Error("Error parsing SPRTINFO lump: Unexpected end of file where sprite name should be"); } + sprinfoTokenLength = strlen(sprinfoToken); if (sprinfoTokenLength != 4) { @@ -149,6 +151,7 @@ static void R_ParseSpriteInfo(boolean spr2) // ^^ we've confirmed that the token is == 4 characters so it will never overflow a 5 byte char buffer strupr(newSpriteName); // Just do this now so we don't have to worry about it } + Z_Free(sprinfoToken); if (!spr2) @@ -157,7 +160,8 @@ static void R_ParseSpriteInfo(boolean spr2) { if (i == NUMSPRITES) I_Error("Error parsing SPRTINFO lump: Unknown sprite name \"%s\"", newSpriteName); - if (!memcmp(newSpriteName,sprnames[i],4)) + + if (!memcmp(newSpriteName,sprnames[i], 4)) { sprnum = static_cast(i); break; @@ -175,17 +179,20 @@ static void R_ParseSpriteInfo(boolean spr2) { I_Error("Error parsing SPRTINFO lump: Unexpected end of file where open curly brace for sprite \"%s\" should be",newSpriteName); } - if (fastcmp(sprinfoToken,"{")) + + if (fastcmp(sprinfoToken, "{")) { Z_Free(sprinfoToken); + sprinfoToken = M_GetToken(NULL); if (sprinfoToken == NULL) { I_Error("Error parsing SPRTINFO lump: Unexpected end of file where definition for sprite \"%s\" should be",newSpriteName); } - while (!fastcmp(sprinfoToken,"}")) + + while (!fastcmp(sprinfoToken, "}")) { - if (stricmp(sprinfoToken, "SKIN")==0) + if (fasticmp(sprinfoToken, "SKIN")) { INT32 skinnum; char *skinName = NULL; @@ -216,10 +223,11 @@ static void R_ParseSpriteInfo(boolean spr2) skinnumbers[foundskins] = skinnum; foundskins++; } - else if (stricmp(sprinfoToken, "FRAME")==0) + else if (fasticmp(sprinfoToken, "FRAME")) { R_ParseSpriteInfoFrame(info); Z_Free(sprinfoToken); + if (spr2) { if (!foundskins) @@ -254,6 +262,7 @@ static void R_ParseSpriteInfo(boolean spr2) { I_Error("Error parsing SPRTINFO lump: Expected \"{\" for sprite \"%s\", got \"%s\"",newSpriteName,sprinfoToken); } + Z_Free(sprinfoToken); Z_Free(info); } @@ -291,15 +300,18 @@ void R_ParseSPRTINFOLump(UINT16 wadNum, UINT16 lumpNum) while (sprinfoToken != NULL) { CONS_Printf("Attempting to parse le SPRTINFO lump for ya..\n"); - if (!stricmp(sprinfoToken, "SPRITE")) + + if (fasticmp(sprinfoToken, "SPRITE")) R_ParseSpriteInfo(false); - else if (!stricmp(sprinfoToken, "SPRITE2")) + else if (fasticmp(sprinfoToken, "SPRITE2")) R_ParseSpriteInfo(true); else I_Error("Error parsing SPRTINFO lump: Unknown keyword \"%s\"", sprinfoToken); + Z_Free(sprinfoToken); sprinfoToken = M_GetToken(NULL); } + Z_Free((void *)sprinfoText); } diff --git a/src/r_skins.c b/src/r_skins.c index bf731f708..53765e269 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -72,7 +72,7 @@ static void Sk_SetDefaultValue(skin_t *skin, boolean local) // // set default skin values // - memset(skin, 0, sizeof (skin_t)); + memset(skin, 0, sizeof(skin_t)); snprintf(skin->name, sizeof skin->name, "skin %u", K_GetMobjSkinNum(skin, local)); skin->name[sizeof skin->name - 1] = '\0'; @@ -188,7 +188,7 @@ INT32 R_SkinAvailable(const char *name) for (i = 0; i < numskins; i++) { - if (stricmp(skins[i].name, name) == 0) + if (fasticmp(skins[i].name, name)) return i; } @@ -203,7 +203,7 @@ INT32 R_AnySkinAvailable(const char *name) for (i = 0; i < numallskins; i++) { - if (stricmp(allskins[i].name, name) == 0) + if (fasticmp(allskins[i].name, name)) return i; } @@ -218,7 +218,7 @@ INT32 R_LocalSkinAvailable(const char *name, boolean local) { for (i = 0; i < numlocalskins; i++) { - if (stricmp(localskins[i].name, name) == 0) + if (fasticmp(localskins[i].name, name)) return i; } @@ -236,7 +236,7 @@ boolean SetPlayerSkin(INT32 playernum, const char *skinname) for (i = 0; i < numskins; i++) { // search in the skin list - if (stricmp(skins[i].name, skinname) == 0) + if (fasticmp(skins[i].name, skinname)) { SetPlayerSkinByNum(playernum, i); return true; @@ -257,12 +257,12 @@ void SetLocalPlayerSkin(INT32 playernum, const char *skinname, consvar_t *cvar) INT32 i; player_t *player = &players[playernum]; - if (stricmp(skinname, "none")) + if (!fasticmp(skinname, "none")) { for (i = 0; i < numlocalskins; i++) { // search in the localskin list - if (stricmp(localskins[i].name, skinname) == 0) + if (fasticmp(localskins[i].name, skinname)) { player->localskin = 1 + i; player->skinlocal = true; @@ -280,7 +280,7 @@ void SetLocalPlayerSkin(INT32 playernum, const char *skinname, consvar_t *cvar) for (i = 0; i < numskins; i++) { // search in the skin list - if (stricmp(skins[i].name, skinname) == 0) + if (fasticmp(skins[i].name, skinname)) { player->localskin = 1 + i; player->skinlocal = false; @@ -530,7 +530,7 @@ void R_AddSkins(UINT16 wadnum, boolean local) hudname = realname = false; // parse - stoken = strtok (buf2, "\r\n= "); + stoken = strtok(buf2, "\r\n= "); while (stoken) { if ((stoken[0] == '/' && stoken[1] == '/') @@ -546,7 +546,7 @@ void R_AddSkins(UINT16 wadnum, boolean local) if (!value) I_Error("R_AddSkins: syntax error in S_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename); - if (!stricmp(stoken, "name")) + if (fasticmp(stoken, "name")) { // the skin name must uniquely identify a single skin // I'm lazy so if name is already used I leave the 'skin x' @@ -592,7 +592,7 @@ void R_AddSkins(UINT16 wadnum, boolean local) if (*value == '_') *value = ' '; // turn _ into spaces. } } - else if (!stricmp(stoken, "realname")) + else if (fasticmp(stoken, "realname")) { // Display name (eg. "Knuckles") realname = true; STRBUFCPY(skin->realname, value); @@ -603,7 +603,7 @@ void R_AddSkins(UINT16 wadnum, boolean local) if (!hudname) STRBUFCPY(skin->hudname, skin->realname); } - else if (!stricmp(stoken, "hudname")) + else if (fasticmp(stoken, "hudname")) { // Life icon name (eg. "K.T.E") hudname = true; STRBUFCPY(skin->hudname, value); @@ -614,34 +614,34 @@ void R_AddSkins(UINT16 wadnum, boolean local) if (!realname) STRBUFCPY(skin->realname, skin->hudname); } - else if (!stricmp(stoken, "sprite")) + else if (fasticmp(stoken, "sprite")) { strupr(value); memcpy(skin->sprite, value, sizeof skin->sprite); } - else if (!stricmp(stoken, "facerank")) + else if (fasticmp(stoken, "facerank")) { strupr(value); memcpy(skin->facerank, value, sizeof(skin->facerank)-1); skin->facerank[sizeof(skin->facerank)-1] = '\0'; } - else if (!stricmp(stoken, "facewant")) + else if (fasticmp(stoken, "facewant")) { strupr(value); memcpy(skin->facewant, value, sizeof(skin->facewant)-1); skin->facewant[sizeof(skin->facewant)-1] = '\0'; } - else if (!stricmp(stoken, "facemmap")) + else if (fasticmp(stoken, "facemmap")) { strupr(value); strncpy(skin->facemmap, value, sizeof(skin->facemmap)-1); skin->facemmap[sizeof(skin->facemmap)-1] = '\0'; } - else if (!stricmp(stoken, "flags")) // character type identification + else if (fasticmp(stoken, "flags")) // character type identification { skin->flags = get_number(value); } - else if (!stricmp(stoken, "kartspeed")) + else if (fasticmp(stoken, "kartspeed")) { skin->kartspeed = atoi(value); @@ -650,7 +650,7 @@ void R_AddSkins(UINT16 wadnum, boolean local) if (skin->kartspeed > 9) skin->kartspeed = 9; } - else if (!stricmp(stoken, "kartweight")) + else if (fasticmp(stoken, "kartweight")) { skin->kartweight = atoi(value); @@ -660,15 +660,15 @@ void R_AddSkins(UINT16 wadnum, boolean local) skin->kartweight = 9; } // custom translation table - else if (!stricmp(stoken, "startcolor")) + else if (fasticmp(stoken, "startcolor")) { skin->starttranscolor = atoi(value); } - else if (!stricmp(stoken, "prefcolor")) + else if (fasticmp(stoken, "prefcolor")) { skin->prefcolor = K_GetKartColorByName(value); } - else if (!stricmp(stoken, "highresscale")) + else if (fasticmp(stoken, "highresscale")) { skin->highresscale = FLOAT_TO_FIXED(atof(value)); } @@ -687,7 +687,7 @@ void R_AddSkins(UINT16 wadnum, boolean local) continue; if (sfx->skinsound != -1 - && !stricmp(sfx->name, stoken + 2)) + && fasticmp(sfx->name, stoken + 2)) { skin->soundsid[sfx->skinsound] = S_AddSoundFx(value+2, sfx->singularity, sfx->pitch, true); found = true; diff --git a/src/s_sound.c b/src/s_sound.c index e3e86c5b0..1e3f8bf7a 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1095,9 +1095,12 @@ void S_StartSoundName(void *mo, const char *soundname) // Search existing sounds... for (i = sfx_None + 1; i < NUMSFX; i++) { - if (!S_sfx[i].name) + const sfxinfo_t *sfx = &S_sfx[i]; + + if (!sfx->name) continue; - if (!stricmp(S_sfx[i].name, soundname)) + + if (fasticmp(sfx->name, soundname)) { soundnum = i; break; @@ -1110,6 +1113,7 @@ void S_StartSoundName(void *mo, const char *soundname) { if (newsounds[i] == 0) break; + if (!S_IdPlaying(newsounds[i])) { S_RemoveSoundFx(newsounds[i]); @@ -1266,7 +1270,7 @@ ReadMusicDefFields (UINT16 wadnum, int line, char *stoken, musicdef_t **defp) char *value; char *textline; - if (!stricmp(stoken, "lump")) + if (fasticmp(stoken, "lump")) { value = strtok(NULL, " "); @@ -1341,24 +1345,24 @@ skip_lump: for (textline = def->field; *textline; textline++)\ if (*textline == '_') *textline = ' '; - if (!stricmp(stoken, "usage")) + if (fasticmp(stoken, "usage")) { ADDDEF(usage); } - else if (!stricmp(stoken, "source")) + else if (fasticmp(stoken, "source")) { ADDDEF(source); } - else if (!stricmp(stoken, "title")) + else if (fasticmp(stoken, "title")) { def->use_info = true; ADDDEF(title); } - else if (!stricmp(stoken, "alttitle")) + else if (fasticmp(stoken, "alttitle")) { ADDDEF(alttitle); } - else if (!stricmp(stoken, "authors")) + else if (fasticmp(stoken, "authors")) { ADDDEF(authors); } @@ -1479,7 +1483,8 @@ musicdef_t *S_FindMusicCredit(const char *musname) if (hash != def->hash) continue; - if (stricmp(def->name, musname)) + + if (!fasticmp(def->name, musname)) continue; return def; @@ -1934,7 +1939,7 @@ static const char *musicexception_list[] = { // check if the current music is smth we dont want to keep (vote music, etc) static boolean S_CheckMusicException(void) { - if (stricmp(music.name, mapmusic.name)) + if (!fasticmp(music.name, mapmusic.name)) return true; // dumb hack but dont keepmusic music that is supposed to reset @@ -1944,7 +1949,7 @@ static boolean S_CheckMusicException(void) // in case somehow the mapmusic was replaced with smth we dont want to keep for (size_t i = 0; i < sizeof(musicexception_list)/sizeof(musicexception_list[0]); i++) { - if (!stricmp(music.name, musicexception_list[i]) || !stricmp(checkmusic, musicexception_list[i])) + if (fasticmp(music.name, musicexception_list[i]) || fasticmp(checkmusic, musicexception_list[i])) { return true; } @@ -2030,12 +2035,12 @@ static boolean S_SkipIntroMusic(void) return false; // check if menu music is playing, otherwise it may continue playing - if (!stricmp(music.name, "titles")) + if (fasticmp(music.name, "titles")) return false; char *maptitle = G_BuildMapTitle(gamemap); // Zzz... - if (maptitle && !stricmp(maptitle, "Wandering Falls")) // wandering balls changes its song when the race starts Zzz... + if (maptitle && fasticmp(maptitle, "Wandering Falls")) // wandering balls changes its song when the race starts Zzz... { Z_Free(maptitle); return false; diff --git a/src/w_wad.c b/src/w_wad.c index f9eb9b361..96fe56303 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -375,11 +375,11 @@ static restype_t ResourceFileDetect(const char* filename) { size_t len = strlen(filename) - 4; - if (!stricmp(&filename[len], ".pk3")) + if (fasticmp(&filename[len], ".pk3")) return RET_PK3; - if (!stricmp(&filename[len], ".soc")) + if (fasticmp(&filename[len], ".soc")) return RET_SOC; - if (!stricmp(&filename[len], ".lua")) + if (fasticmp(&filename[len], ".lua")) return RET_LUA; return RET_WAD; @@ -1130,7 +1130,7 @@ UINT16 W_CheckNumForLongNamePwad(const char *name, UINT16 wad, UINT16 startlump) { if (lump_p->longnamelength == namelen && lump_p->hash.longname == hash - && !stricmp(lump_p->longname, name)) + && fasticmp(lump_p->longname, name)) return i; } } @@ -1230,7 +1230,7 @@ static lumpnum_t CheckLumpInCache(const char *name, boolean longname) for (INT32 i = lumpnumcacheindex + LUMPNUMCACHESIZE; i > lumpnumcacheindex; i--) { if (lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].hash == hash - && stricmp(lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname, name) == 0) + && fasticmp(lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname, name)) { lumpnumcacheindex = i & (LUMPNUMCACHESIZE - 1); return lumpnumcache[lumpnumcacheindex].lumpnum; -- 2.54.0 From 3095303a4ba65f9fe13d187b711860d56554b5da Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 2 Nov 2025 14:35:28 +0100 Subject: [PATCH 209/219] Revert "simplify vhs effect interpolation" This reverts commit e26fb91350230a906e18d773d0ad4a91c75b81f1. --- src/v_video.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/v_video.c b/src/v_video.c index 893a39b20..3b9880942 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1738,7 +1738,8 @@ void V_DrawHorizontallyScaledFullScreenPatch(patch_t *patch) void V_DrawVhsEffect(boolean rewind) { - static fixed_t upbary = 100, downbary = 150; + fixed_t uby, dby; + static fixed_t upbary = 100*FRACUNIT, downbary = 150*FRACUNIT; UINT8 barsize, updistort, downdistort; @@ -1759,19 +1760,21 @@ void V_DrawVhsEffect(boolean rewind) if (rewind) V_DrawVhsEffect(false); // experimentation - upbary -= FixedMul(vid.dup * (rewind ? 3 : 1.8f), renderdeltatics); - downbary += FixedMul(vid.dup * (rewind ? 2 : 1), renderdeltatics); + upbary -= renderdeltatics * (vid.dup * (rewind ? 3 : 1.8f)); + downbary += renderdeltatics * (vid.dup * (rewind ? 2 : 1)); - if (upbary < -barsize) - upbary = vid.height; + if (upbary < -barsize*FRACUNIT) + upbary = vid.height << FRACBITS; + if (downbary > vid.height << FRACBITS) + downbary = -barsize*FRACUNIT; - if (downbary > vid.height) - downbary = -barsize; + uby = upbary >> FRACBITS; + dby = downbary >> FRACBITS; #ifdef HWRENDER if (rendermode == render_opengl) { - HWR_RenderVhsEffect(upbary, downbary, updistort, downdistort, barsize); + HWR_RenderVhsEffect(uby, dby, updistort, downdistort, barsize); return; } #endif @@ -1791,16 +1794,16 @@ void V_DrawVhsEffect(boolean rewind) thismapstart = normalmapstart; offs = 0; - if (y >= upbary && y < upbary+barsize) + if (y >= uby && y < uby+barsize) { thismapstart -= (2<= downbary && y < downbary+barsize) + if (y >= dby && y < dby+barsize) { thismapstart -= (2< Date: Fri, 31 Oct 2025 13:07:37 +0000 Subject: [PATCH 210/219] Optimise padding algorithm --- src/hardware/r_opengl/r_opengl.c | 99 ++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 37 deletions(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 3a5fd059a..650e39e13 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1823,47 +1823,72 @@ static void GL_AllocTextureBuffer(GLMipmap_t *pTexInfo) } } -#define PADDING_CHECK(offset, alphaCheck) { from = to + (offset); if ((alphaCheck)) from = NULL; else goto foundFrom; } - -static void PadRGBABitmap(RGBA_t *tex, UINT16 w, UINT16 h) +static void PadRGBABitmap(RGBA_t *tex, UINT16 w, UINT16 h, UINT32 flags) { - INT32 i; - boolean notLeft, notRight, notTop, notBottom; - RGBA_t *to = tex - 1, *from; + INT32 i, c1, c2, idxAdd; + UINT16 c1size, c2size; + RGBA_t *current, *prev, *next, *first; + boolean ignorePrev, wrap; - for (i = 0; i < w * h; i++) + for (i = 1; i >= 0; i--) { - to++; - if (to->rgba != 0) - continue; - from = NULL; + c1size = i ? w : h; + c2size = i ? h : w; + idxAdd = i ? w : 1; + wrap = i ? flags & TF_WRAPY : flags & TF_WRAPX; - notLeft = i % w != 0; - notRight = i % w != w - 1; - notTop = i / w != 0; - notBottom = i / w != h - 1; - - if (notRight) PADDING_CHECK(1, from->s.alpha == 0) // Check +X - if (notBottom) PADDING_CHECK(w, from->s.alpha == 0) // Check +Y - if (notLeft) PADDING_CHECK(-1, from->s.alpha == 0) // Check -X - if (notTop) PADDING_CHECK(-w, from->s.alpha == 0) // Check -Y - if (notRight && notBottom) PADDING_CHECK(1 + w, from->s.alpha == 0) // Check +X+Y - if (notLeft && notBottom) PADDING_CHECK(-1 + w, from->s.alpha == 0) // Check -X+Y - if (notLeft && notTop) PADDING_CHECK(-1 - w, from->s.alpha == 0) // Check -X-Y - if (notRight && notTop) PADDING_CHECK(1 - w, from->s.alpha == 0) // Check +X-Y - -foundFrom: - if (from != NULL) + for (c1 = 0; c1 < c1size; c1++) { - *to = *from; - to->s.alpha = 0; + if (i) + { + first = current = tex + c1; + prev = wrap ? tex + (c1 + (h - 1) * w) : current; + next = tex + (c1 + w); + } + else + { + first = current = tex + (c1 * w); + prev = wrap ? tex + (w - 1 + c1 * w) : current; + next = tex + (1 + c1 * w); + } + + ignorePrev = false; + + for (c2 = 0; c2 < c2size; c2++) + { + if (c2 == c2size - 1) + next = wrap ? first : current; + + if (current->rgba) + { + ignorePrev = false; + } + else if (prev->rgba && !ignorePrev) + { + *current = *prev; + current->s.alpha = 0; + ignorePrev = true; + } + else if (next->rgba) + { + *current = *next; + current->s.alpha = 0; + ignorePrev = false; + } + else + { + ignorePrev = false; + } + + prev = current; + current = next; + next += idxAdd; + } } } } -#undef PADDING_CHECK - -static void GenerateMipmaps(INT32 w, INT32 h, RGBA_t *tex, INT32 maxLOD) +static void GenerateMipmaps(INT32 w, INT32 h, RGBA_t *tex, INT32 maxLOD, UINT32 flags) { if (tex == NULL) { @@ -1925,7 +1950,7 @@ static void GenerateMipmaps(INT32 w, INT32 h, RGBA_t *tex, INT32 maxLOD) h /= 2; if (padTexture) - PadRGBABitmap(tex, w, h); + PadRGBABitmap(tex, w, h, flags); pglTexSubImage2D(GL_TEXTURE_2D, m + 1, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, tex); } @@ -1939,7 +1964,7 @@ void GL_UpdateTexture(GLMipmap_t *pTexInfo) // Upload a texture GLuint num = pTexInfo->downloaded; boolean update = true; - const boolean applyPadding = mag_filter == GL_LINEAR || min_filter == GL_LINEAR; + const boolean applyPadding = mag_filter == GL_LINEAR || min_filter == GL_LINEAR || true; INT32 w = pTexInfo->width, h = pTexInfo->height; INT32 i, j; @@ -2000,7 +2025,7 @@ void GL_UpdateTexture(GLMipmap_t *pTexInfo) } if (applyPadding) - PadRGBABitmap(tex, w, h); + PadRGBABitmap(tex, w, h, pTexInfo->flags); break; case GL_TEXFMT_RGBA: @@ -2016,7 +2041,7 @@ void GL_UpdateTexture(GLMipmap_t *pTexInfo) ptex = tex; if (applyPadding) - PadRGBABitmap(tex, w, h); + PadRGBABitmap(tex, w, h, pTexInfo->flags); } break; @@ -2087,7 +2112,7 @@ void GL_UpdateTexture(GLMipmap_t *pTexInfo) // Control the mipmap level of detail pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 5); - GenerateMipmaps(w, h, tex, 5); + GenerateMipmaps(w, h, tex, 5, pTexInfo->flags); } else { -- 2.54.0 From 326a28ec36ce9aa88afa04856a42980d9633b3ac Mon Sep 17 00:00:00 2001 From: Blue Staggo Date: Fri, 31 Oct 2025 13:10:15 +0000 Subject: [PATCH 211/219] Oops, forgot to disable padding for nearest texture mode --- src/hardware/r_opengl/r_opengl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 650e39e13..7601de06d 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1964,7 +1964,7 @@ void GL_UpdateTexture(GLMipmap_t *pTexInfo) // Upload a texture GLuint num = pTexInfo->downloaded; boolean update = true; - const boolean applyPadding = mag_filter == GL_LINEAR || min_filter == GL_LINEAR || true; + const boolean applyPadding = mag_filter == GL_LINEAR || min_filter == GL_LINEAR; INT32 w = pTexInfo->width, h = pTexInfo->height; INT32 i, j; -- 2.54.0 From 23ba82772622bacebf2a53a139fd5b18d1c8f4ad Mon Sep 17 00:00:00 2001 From: Blue Staggo Date: Fri, 31 Oct 2025 14:04:49 +0000 Subject: [PATCH 212/219] Give midtextures filtering without ugly borders + Clean up padding code Couldn't do proper translucent blending on midtextures because of wrapping. --- src/hardware/hw_main.cpp | 2 +- src/hardware/r_opengl/r_opengl.c | 39 ++++++++++++-------------------- 2 files changed, 15 insertions(+), 26 deletions(-) diff --git a/src/hardware/hw_main.cpp b/src/hardware/hw_main.cpp index be96fc901..dcefdaec2 100644 --- a/src/hardware/hw_main.cpp +++ b/src/hardware/hw_main.cpp @@ -1237,7 +1237,7 @@ static void HWR_DrawSkyWall(FOutVector *wallVerts, FSurfaceInfo *Surf) // Returns true if the midtexture is visible, and false if... it isn't... static inline boolean HWR_BlendMidtextureSurface(FSurfaceInfo *pSurf) { - FUINT blendmode = PF_Masked; + FUINT blendmode = PF_Masked | PF_Translucent; pSurf->PolyColor.s.alpha = 0xFF; diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 7601de06d..d481b56db 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1830,27 +1830,27 @@ static void PadRGBABitmap(RGBA_t *tex, UINT16 w, UINT16 h, UINT32 flags) RGBA_t *current, *prev, *next, *first; boolean ignorePrev, wrap; - for (i = 1; i >= 0; i--) + for (i = 0; i < 2; i++) { - c1size = i ? w : h; - c2size = i ? h : w; - idxAdd = i ? w : 1; - wrap = i ? flags & TF_WRAPY : flags & TF_WRAPX; + c1size = i ? h : w; + c2size = i ? w : h; + idxAdd = i ? 1 : w; + wrap = i ? flags & TF_WRAPX : flags & TF_WRAPY; for (c1 = 0; c1 < c1size; c1++) { if (i) - { - first = current = tex + c1; - prev = wrap ? tex + (c1 + (h - 1) * w) : current; - next = tex + (c1 + w); - } - else { first = current = tex + (c1 * w); prev = wrap ? tex + (w - 1 + c1 * w) : current; next = tex + (1 + c1 * w); } + else + { + first = current = tex + c1; + prev = wrap ? tex + (c1 + (h - 1) * w) : current; + next = tex + (c1 + w); + } ignorePrev = false; @@ -2086,21 +2086,10 @@ void GL_UpdateTexture(GLMipmap_t *pTexInfo) pglBindTexture(GL_TEXTURE_2D, num); tex_downloaded = num; - const int transparent = (pTexInfo->flags & TF_TRANSPARENT); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter); - // disable texture filtering on any texture that has holes so there's no dumb borders or blending issues - if (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 (MipMap && !transparent) // No mipmaps on transparent stuff + if (MipMap && !(pTexInfo->flags & TF_TRANSPARENT)) // No mipmaps on transparent stuff { pglTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); -- 2.54.0 From 2b7f2da5ee252e52e521a59a926167e70b32a630 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 1 Nov 2025 15:33:13 +0100 Subject: [PATCH 213/219] Mipmaps: fix translucent textures turning black i.e. since we allow texture filtering on translucent textures now, the min filter may specifcy one of the mipmap filters, this means we NEED to call GL_GENERATE_MIPMAP and set the LODs for them, otherwise no texture will be generated alternatively we could do a bunch of special cases for the mipmap filters, but this is simpler --- src/hardware/hw_main.cpp | 4 ---- src/hardware/r_opengl/r_opengl.c | 14 +++++++++++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/hardware/hw_main.cpp b/src/hardware/hw_main.cpp index dcefdaec2..c45404159 100644 --- a/src/hardware/hw_main.cpp +++ b/src/hardware/hw_main.cpp @@ -1259,8 +1259,6 @@ static inline boolean HWR_BlendMidtextureSurface(FSurfaceInfo *pSurf) case 256: if (gl_linedef->blendmode) blendmode = HWR_SurfaceBlend(gl_linedef->blendmode, R_GetLinedefTransTable(gl_linedef->alpha), pSurf); - else - blendmode = PF_Translucent; break; default: if (gl_linedef->blendmode) @@ -1272,8 +1270,6 @@ static inline boolean HWR_BlendMidtextureSurface(FSurfaceInfo *pSurf) } else if (gl_linedef->alpha >= 0 && gl_linedef->alpha < FRACUNIT) blendmode = HWR_TranstableToAlpha(R_GetLinedefTransTable(gl_linedef->alpha), pSurf); - else - blendmode = PF_Masked; break; } } diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index d481b56db..09f460c34 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -2089,7 +2089,7 @@ void GL_UpdateTexture(GLMipmap_t *pTexInfo) pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter); pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter); - if (MipMap && !(pTexInfo->flags & TF_TRANSPARENT)) // No mipmaps on transparent stuff + if (MipMap) { pglTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); @@ -2100,8 +2100,16 @@ void GL_UpdateTexture(GLMipmap_t *pTexInfo) // Control the mipmap level of detail pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 5); - GenerateMipmaps(w, h, tex, 5, pTexInfo->flags); + + if (pTexInfo->flags & TF_TRANSPARENT) + { + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mipmaps on transparent stuff + } + else + { + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4); + GenerateMipmaps(w, h, tex, 4, pTexInfo->flags); + } } else { -- 2.54.0 From bbbd42e6536099a787415c0202d47dd1a653099e Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 5 Nov 2025 21:27:35 +0100 Subject: [PATCH 214/219] use "offsetof" for skydome vbo offsets silences UBSAN complaining about accessing struct members through null ptr --- src/hardware/r_opengl/r_opengl.c | 38 ++++++++++++-------------------- 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 09f460c34..566d2458c 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -2490,12 +2490,10 @@ void GL_DrawIndexedTriangles(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT i // the DrawPolygon variant of this has some code about polyflags and wrapping here but havent noticed any problems from omitting it? } -static const boolean gl_ext_arb_vertex_buffer_object = true; - -#define NULL_VBO_VERTEX ((gl_skyvertex_t*)NULL) -#define sky_vbo_x (gl_ext_arb_vertex_buffer_object ? &NULL_VBO_VERTEX->x : &sky->data[0].x) -#define sky_vbo_u (gl_ext_arb_vertex_buffer_object ? &NULL_VBO_VERTEX->u : &sky->data[0].u) -#define sky_vbo_r (gl_ext_arb_vertex_buffer_object ? &NULL_VBO_VERTEX->r : &sky->data[0].r) +//#define NULL_VBO_VERTEX ((gl_skyvertex_t*)NULL) +#define sky_vbo_x ((void*)offsetof(gl_skyvertex_t, x)) +#define sky_vbo_u ((void*)offsetof(gl_skyvertex_t, u)) +#define sky_vbo_r ((void*)offsetof(gl_skyvertex_t, r)) void GL_RenderSkyDome(gl_sky_t *sky) { @@ -2507,30 +2505,23 @@ void GL_RenderSkyDome(gl_sky_t *sky) if (sky->rebuild) { // delete VBO when already exists - if (gl_ext_arb_vertex_buffer_object) - { - if (sky->vbo) - pglDeleteBuffers(1, &sky->vbo); - } + if (sky->vbo) + pglDeleteBuffers(1, &sky->vbo); - if (gl_ext_arb_vertex_buffer_object) - { - // generate a new VBO and get the associated ID - pglGenBuffers(1, &sky->vbo); + // generate a new VBO and get the associated ID + pglGenBuffers(1, &sky->vbo); - // bind VBO in order to use - pglBindBuffer(GL_ARRAY_BUFFER, sky->vbo); + // bind VBO in order to use + pglBindBuffer(GL_ARRAY_BUFFER, sky->vbo); - // upload data to VBO - pglBufferData(GL_ARRAY_BUFFER, sky->vertex_count * sizeof(sky->data[0]), sky->data, GL_STATIC_DRAW); - } + // upload data to VBO + pglBufferData(GL_ARRAY_BUFFER, sky->vertex_count * sizeof(sky->data[0]), sky->data, GL_STATIC_DRAW); sky->rebuild = false; } // bind VBO in order to use - if (gl_ext_arb_vertex_buffer_object) - pglBindBuffer(GL_ARRAY_BUFFER, sky->vbo); + pglBindBuffer(GL_ARRAY_BUFFER, sky->vbo); // activate and specify pointers to arrays pglVertexPointer(3, GL_FLOAT, sizeof(sky->data[0]), sky_vbo_x); @@ -2574,8 +2565,7 @@ void GL_RenderSkyDome(gl_sky_t *sky) pglColor4ubv(white); // bind with 0, so, switch back to normal pointer operation - if (gl_ext_arb_vertex_buffer_object) - pglBindBuffer(GL_ARRAY_BUFFER, 0); + pglBindBuffer(GL_ARRAY_BUFFER, 0); // deactivate color array pglDisableClientState(GL_COLOR_ARRAY); -- 2.54.0 From 9dd1a479696662761b2d12d0276e2b9bab9ae54b Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 5 Nov 2025 21:28:24 +0100 Subject: [PATCH 215/219] fix SINT8 write macro, fix big endian READUINT32 macro --- src/byteptr.h | 4 ++-- src/g_demo.c | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/byteptr.h b/src/byteptr.h index 85141c21c..0c82e6f40 100644 --- a/src/byteptr.h +++ b/src/byteptr.h @@ -27,7 +27,7 @@ extern "C" { // #define WRITEUINT8(p,b) do { UINT8 *p_tmp = ( UINT8 *)p; const UINT8 tv = ( UINT8)(b); memcpy(p, &tv, sizeof( UINT8)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) -#define WRITESINT8(p,b) do { SINT8 *p_tmp = ( SINT8 *)p; const SINT8 tv = ( UINT8)(b); memcpy(p, &tv, sizeof( UINT8)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) +#define WRITESINT8(p,b) do { SINT8 *p_tmp = ( SINT8 *)p; const SINT8 tv = ( SINT8)(b); memcpy(p, &tv, sizeof( SINT8)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) #define WRITEINT16(p,b) do { INT16 *p_tmp = ( INT16 *)p; const INT16 tv = ( INT16)(b); memcpy(p, &tv, sizeof( INT16)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) #define WRITEUINT16(p,b) do { UINT16 *p_tmp = ( UINT16 *)p; const UINT16 tv = ( UINT16)(b); memcpy(p, &tv, sizeof( UINT16)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) #define WRITEINT32(p,b) do { INT32 *p_tmp = ( INT32 *)p; const INT32 tv = ( INT32)(b); memcpy(p, &tv, sizeof( INT32)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) @@ -124,7 +124,7 @@ FUNCINLINE static ATTRINLINE UINT32 readulong(void *ptr) #define READINT16(p) readshort(&((const INT16*)(p = (const void*)&((const INT16*)p)[1]))[-1]) #define READUINT16(p) readushort(&((const UINT16*)(p = (const void*)&((const UINT16*)p)[1]))[-1]) #define READINT32(p) readlong(&((const INT32*)(p = (const void*)&((const INT32*)p)[1]))[-1]) -#define READUINT32(p) readulong(&((const UINT32*)(p = (const void*)&((const UINT32*)p)[1])) +#define READUINT32(p) readulong(&((const UINT32*)(p = (const void*)&((const UINT32*)p)[1]))[-1]) #define READCHAR(p) ((const char*)(p = (const void*)&((const char*)p)[1]))[-1] #define READFIXED(p) readlong(&((const fixed_t*)(p = (const void*)&((const fixed_t*)p)[1]))[-1]) #define READANGLE(p) readulong(&((const angle_t*)(p = (const void*)&((const angle_t*)p)[1]))[-1]) diff --git a/src/g_demo.c b/src/g_demo.c index 8c3bbe1c6..3b1f5fce3 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -395,7 +395,7 @@ void G_WriteDemoExtraData(void) // Skin memset(name, 0, 16); strncpy(name, skins[players[i].skin].name, 16); - M_Memcpy(demobuf.p,name,16); + M_Memcpy(demobuf.p, name, 16); demobuf.p += 16; WRITEUINT8(demobuf.p, skins[players[i].skin].kartspeed); @@ -407,7 +407,7 @@ void G_WriteDemoExtraData(void) // Color memset(name, 0, 16); strncpy(name, KartColor_Names[players[i].skincolor], 16); - M_Memcpy(demobuf.p,name,16); + M_Memcpy(demobuf.p, name, 16); demobuf.p += 16; } @@ -416,7 +416,7 @@ void G_WriteDemoExtraData(void) // Name memset(name, 0, 16); memcpy(name, player_names[i], 15); // Keeping 1 null byte for safety, sorry players with name containing more than 15 characters - M_Memcpy(demobuf.p,name,16); + M_Memcpy(demobuf.p, name, 16); demobuf.p += 16; } @@ -1763,19 +1763,19 @@ void G_BeginRecording(void) // Name memset(name, 0, 16); memcpy(name, player_names[p], 15); - M_Memcpy(demobuf.p,name,16); + M_Memcpy(demobuf.p, name, 16); demobuf.p += 16; // Skin memset(name, 0, 16); strncpy(name, skins[player->skin].name, 16); - M_Memcpy(demobuf.p,name,16); + M_Memcpy(demobuf.p, name, 16); demobuf.p += 16; // Color memset(name, 0, 16); strncpy(name, KartColor_Names[player->skincolor], 16); - M_Memcpy(demobuf.p,name,16); + M_Memcpy(demobuf.p, name, 16); demobuf.p += 16; // Score, since Kart uses this to determine where you start on the map -- 2.54.0 From a7c5254a32b84b7278e1ac2f5e394d754c630c8d Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 5 Nov 2025 21:29:01 +0100 Subject: [PATCH 216/219] set "-Wno-cast-qual" for clang see comment --- src/Makefile.d/versions.mk | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Makefile.d/versions.mk b/src/Makefile.d/versions.mk index 83600d735..451ff72e7 100644 --- a/src/Makefile.d/versions.mk +++ b/src/Makefile.d/versions.mk @@ -144,8 +144,10 @@ ifdef GCC81 WFLAGS+=-Wno-error=multistatement-macros endif -ifeq ($(CC),clang) - WFLAGS+= -Wno-unknown-pragmas -Wno-cast-align +ifneq (,$(filter $(CC) $(CXX),clang clang++)) + WFLAGS+= -Wno-unknown-pragmas + WFLAGS+= -Wno-cast-align + WFLAGS+= -Wno-cast-qual # not a fan, but clang really hates our read macros endif ifdef NONX86 -- 2.54.0 From b017a7202660a1e015868b7fb54fa990f585c05c Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 5 Nov 2025 22:04:56 +0100 Subject: [PATCH 217/219] R_DrawPlanes: dont increment garbage ptr does not need to be there at all eitherways --- src/r_plane.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 8ef47f722..b2d30185d 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -720,7 +720,7 @@ void R_DrawPlanes(void) srb2::ThreadPool::Sema tp_sema; srb2::g_main_threadpool->begin_sema(); #endif - for (i = 0; i < MAXVISPLANES; i++, pl++) + for (i = 0; i < MAXVISPLANES; i++) { for (pl = visplanes[i]; pl; pl = pl->next) { @@ -755,7 +755,7 @@ void R_DrawSkyPlanes(void) srb2::ThreadPool::Sema tp_sema; srb2::g_main_threadpool->begin_sema(); #endif - for (i = 0; i < MAXVISPLANES; i++, pl++) + for (i = 0; i < MAXVISPLANES; i++) { for (pl = visplanes[i]; pl; pl = pl->next) { -- 2.54.0 From 80613a8a49a87084c7fe173aa7aa34cdd824b6de Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 5 Nov 2025 22:53:10 +0100 Subject: [PATCH 218/219] R_AllocClippingTables & R_AllocTextureColumnTables: fix nullptr arithmetic --- src/r_segs.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/r_segs.cpp b/src/r_segs.cpp index d1cbbf9c2..414221686 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -1718,7 +1718,7 @@ static void R_AllocClippingTables(size_t range) { // Check if it's in range of the openings #define CHECK(which) \ - if (which + drawseg->x1 >= oldopenings && which + drawseg->x1 <= oldlast) \ + if (which != NULL && which + drawseg->x1 >= oldopenings && which + drawseg->x1 <= oldlast) \ which = (which - oldopenings) + openings CHECK(drawseg->sprtopclip); CHECK(drawseg->sprbottomclip); @@ -1752,7 +1752,7 @@ static void R_AllocTextureColumnTables(size_t range) { // Check if it's in range of the tables #define CHECK(which) \ - if (which + drawseg->x1 >= oldtable && which + drawseg->x1 <= oldlast) \ + if (which != NULL && which + drawseg->x1 >= oldtable && which + drawseg->x1 <= oldlast) \ which = (which - oldtable) + texturecolumntable CHECK(drawseg->maskedtexturecol); CHECK(drawseg->thicksidecol); -- 2.54.0 From 67e1793f49951f69d2e88fe143d785e0c26d81fa Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 5 Nov 2025 23:03:25 +0100 Subject: [PATCH 219/219] software renderer: handle some float type related issues with slope drawers there were a bunch of cases where inf and nan float results were casted and used with integer things, which is undefined in c yes i did use ceepeepee for that crap, cause this wouldve been really annoying without templating if someone really wants that crap to use outside ceepeepee, feel free to make a bunch of wrappers cause im too lazy for that stuff --- src/cxxutil.hpp | 67 +++++++++++++++++++++++++++++++++++++++++++++ src/r_draw_span.cpp | 22 ++++++++------- src/r_segs.cpp | 10 ++++--- 3 files changed, 85 insertions(+), 14 deletions(-) diff --git a/src/cxxutil.hpp b/src/cxxutil.hpp index 591d7aa4d..91c1a8641 100644 --- a/src/cxxutil.hpp +++ b/src/cxxutil.hpp @@ -147,6 +147,73 @@ public: template NotNull(T) -> NotNull; +// does a super safe cast from floating point to interger types +// this prob could be better since i suck at ceepeepee +// but atleast we can just template shit to our desired types +template +static inline IntT floattoint(FloatT val) +{ + // :chaosleep: + static_assert(std::is_floating_point_v, "Input must be a floating-point type"); + static_assert(std::is_integral_v, "Output must be a integer type"); + + if (std::fpclassify(val) == FP_NAN) + return 0; // if stuffs not a number we sure screwed up lmao + + // treat inifinity as "int min/max" + if (std::fpclassify(val) == FP_INFINITE) + { + // yes infinity can be signed kek + if (std::signbit(val)) + return std::numeric_limits::min(); // negative infinity, so return min + else + return std::numeric_limits::max(); + } + + // make sure we fit into our targettype uwu + if (val > static_cast(std::numeric_limits::max())) + return std::numeric_limits::max(); + else if (val < static_cast(std::numeric_limits::min())) + return std::numeric_limits::min(); + + return static_cast(val); +} + +// safe float to fixed +// which handles nan and inf +// pretty much the same stuff as the above, but uh, idk how id use the above with this +template // can use both float and doubles yay +static inline int32_t floattofixed(FloatT val) +{ + // :chaosleep: + static_assert(std::is_floating_point_v, "Input must be a floating-point type"); + + // fixed_t is just an int32_t, i dont wanna include doomtype here if it can be avoided + + if (std::fpclassify(val) == FP_NAN) + return 0; // if stuffs not a number we sure screwed up lmao + + // treat inifinity as "int min/max" + if (std::fpclassify(val) == FP_INFINITE) + { + // yes infinity can be signed kek + if (std::signbit(val)) + return std::numeric_limits::min(); // negative infinity, so return min + else + return std::numeric_limits::max(); + } + + const FloatT ret = (val * 65536.0); + + // make sure we fit into our targettype uwu + if (ret > static_cast(std::numeric_limits::max())) + return std::numeric_limits::max(); + else if (ret < static_cast(std::numeric_limits::min())) + return std::numeric_limits::min(); + + return static_cast(ret); +} + } // namespace srb2 #endif // __SRB2_CXXUTIL_HPP__ diff --git a/src/r_draw_span.cpp b/src/r_draw_span.cpp index 11415d2d5..e5ee15463 100644 --- a/src/r_draw_span.cpp +++ b/src/r_draw_span.cpp @@ -28,6 +28,8 @@ #include #include +#include "cxxutil.hpp" + // ========================================================================== // SPANS // ========================================================================== @@ -315,10 +317,10 @@ static void R_DrawTiltedSpanTemplate(drawspandata_t* ds) endz = 1.f/iz; endu = uz*endz; endv = vz*endz; - stepu = (INT64)((endu - startu) * INVSPAN); - stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu); - v = (INT64)(startv); + stepu = srb2::floattoint((endu - startu) * INVSPAN); + stepv = srb2::floattoint((endv - startv) * INVSPAN); + u = srb2::floattoint(startu); + v = srb2::floattoint(startv); const INT32 x1 = ds->x1; @@ -345,8 +347,8 @@ static void R_DrawTiltedSpanTemplate(drawspandata_t* ds) { if (width == 1) { - u = (INT64)(startu); - v = (INT64)(startv); + u = srb2::floattoint(startu); + v = srb2::floattoint(startv); bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); colormap = planezlight[tiltlight[ds->x1]] + colormap_diff; if constexpr (Type & DS_RIPPLE) @@ -366,10 +368,10 @@ static void R_DrawTiltedSpanTemplate(drawspandata_t* ds) endu = uz*endz; endv = vz*endz; left = 1.f/left; - stepu = (INT64)((endu - startu) * left); - stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu); - v = (INT64)(startv); + stepu = srb2::floattoint((endu - startu) * left); + stepv = srb2::floattoint((endv - startv) * left); + u = srb2::floattoint(startu); + v = srb2::floattoint(startv); for (; width != 0; width--) { diff --git a/src/r_segs.cpp b/src/r_segs.cpp index 414221686..121920a69 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -30,6 +30,8 @@ #include "core/memory.h" +#include "cxxutil.hpp" + #define HEIGHTBITS 12 #define HEIGHTUNIT (1<leftpos.x = segleft.x = DoubleToFixed((b2*c1 - b1*c2)/det); - ds_p->leftpos.y = segleft.y = DoubleToFixed((a1*c2 - a2*c1)/det); + ds_p->leftpos.x = segleft.x = srb2::floattofixed((b2*c1 - b1*c2)/det); + ds_p->leftpos.y = segleft.y = srb2::floattofixed((a1*c2 - a2*c1)/det); // right temp = xtoviewangle[stop]+viewangle; @@ -1902,8 +1904,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) det = a1*b2 - a2*b1; - ds_p->rightpos.x = segright.x = DoubleToFixed((b2*c1 - b1*c2)/det); - ds_p->rightpos.y = segright.y = DoubleToFixed((a1*c2 - a2*c1)/det); + ds_p->rightpos.x = segright.x = srb2::floattofixed((b2*c1 - b1*c2)/det); + ds_p->rightpos.y = segright.y = srb2::floattofixed((a1*c2 - a2*c1)/det); } #define SLOPEPARAMS(slope, end1, end2, normalheight) \ -- 2.54.0