From 3675fdd3613e0a378ac0642a564b0f41fde1912c Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Tue, 5 Sep 2023 09:13:12 +0200 Subject: [PATCH 1/9] smoother slope rotation for players dont snap player directly to whatever theyre standing on instead make the sprite rotate a bit smoother see: https://git.do.srb2.org/haya_/Kart-Public/-/commit/8448d75b031fa86cdb854d13eda4712352d35a89 --- src/d_player.h | 1 + src/k_kart.c | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/d_player.h b/src/d_player.h index d7bfb80eb..a12fff93b 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -371,6 +371,7 @@ typedef struct player_s angle_t viewrollangle; angle_t tilt; + angle_t tilt_sprite; // Mouse aiming, where the guy is looking at! // It is updated with cmd->aiming. diff --git a/src/k_kart.c b/src/k_kart.c index fd3a46afe..ffd759bbb 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3132,6 +3132,7 @@ static angle_t K_GetSlopeRollAngle(player_t *p, boolean dontflip, boolean useRes angle_t zangle = 0; angle_t xydirection = 0; angle_t an; + angle_t final_slope; INT32 pNum = K_FindPlayerNum(p); I_Assert(p != NULL); @@ -3171,7 +3172,14 @@ static angle_t K_GetSlopeRollAngle(player_t *p, boolean dontflip, boolean useRes zangle = InvAngle(zangle); an = (lookAngle - xydirection); - return FixedMul(zangle, FINESINE(an>>ANGLETOFINESHIFT)); + final_slope = -(FixedMul(FINESINE(an>>ANGLETOFINESHIFT), zangle)); + an = (INT32)(final_slope - p->tilt_sprite) / 2; // instead of just a direct snap + + if (an) + p->tilt_sprite += an; + else + p->tilt_sprite = final_slope; + return -p->tilt_sprite; } static void K_RollPlayerBySlopes(player_t *p, boolean usedistance) -- 2.54.0 From 78d50e4c43f1e85af6ae54c23d28da05e0c8455e Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Tue, 5 Sep 2023 23:01:03 +0200 Subject: [PATCH 2/9] just a bit more looks even better like this imo --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index ffd759bbb..04dcb4cb7 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3173,7 +3173,7 @@ static angle_t K_GetSlopeRollAngle(player_t *p, boolean dontflip, boolean useRes an = (lookAngle - xydirection); final_slope = -(FixedMul(FINESINE(an>>ANGLETOFINESHIFT), zangle)); - an = (INT32)(final_slope - p->tilt_sprite) / 2; // instead of just a direct snap + an = (INT32)(final_slope - p->tilt_sprite) / 3; // instead of just a direct snap if (an) p->tilt_sprite += an; -- 2.54.0 From 71ce5be570bfb2ba593b5f1c507c51647be139d9 Mon Sep 17 00:00:00 2001 From: lug420 Date: Thu, 7 Sep 2023 23:54:22 +0200 Subject: [PATCH 3/9] me wondering why the hw sprite perfstats were broken + removing some stuff we dont need --- src/hardware/hw_main.c | 102 +++++++++++++++++++++-------------------- src/hardware/hw_main.h | 2 +- 2 files changed, 53 insertions(+), 51 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 834f617bf..258573578 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -196,8 +196,6 @@ FTransform atransform; static float gr_viewx, gr_viewy, gr_viewz; float gr_viewsin, gr_viewcos; -static fixed_t dup_viewx, dup_viewy, dup_viewz; - static angle_t gr_aimingangle; static float gr_viewludsin, gr_viewludcos; @@ -528,7 +526,7 @@ static FUINT HWR_CalcWallLight(FUINT lightnum, fixed_t v1x, fixed_t v1y, fixed_t // HWR_RenderPlane // Render a floor or ceiling convex polygon -void HWR_RenderPlane(extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, UINT8 alpha, extracolormap_t *planecolormap, subsector_t *subsector) +void HWR_RenderPlane(extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, UINT8 alpha, extracolormap_t *planecolormap) { polyvertex_t * pv; float height; //constant y for all points on the convex flat polygon @@ -629,6 +627,9 @@ void HWR_RenderPlane(extrasubsector_t *xsub, boolean isceiling, fixed_t fixedhei // reference point for flat texture coord for each vertex around the polygon flatxref = (float)(((fixed_t)pv->x & (~flatflag)) / fflatsize); flatyref = (float)(((fixed_t)pv->y & (~flatflag)) / fflatsize); + + // transform + v3d = planeVerts; if (FOFsector != NULL) { @@ -681,32 +682,39 @@ void HWR_RenderPlane(extrasubsector_t *xsub, boolean isceiling, fixed_t fixedhei flatyref = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle)))); } -#define SETUP3DVERT(vert, vx, vy) {\ - /* Hurdler: add scrolling texture on floor/ceiling */\ - vert->s = (float)(((vx) / fflatsize) - flatxref + scrollx);\ - vert->t = (float)(flatyref - ((vy) / fflatsize) + scrolly);\ -\ - /* Need to rotate before translate */\ - if (angle) /* Only needs to be done if there's an altered angle */\ - {\ - tempxsow = FLOAT_TO_FIXED(vert->s);\ - tempytow = FLOAT_TO_FIXED(vert->t);\ - vert->s = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));\ - vert->t = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));\ - }\ -\ - vert->x = (vx);\ - vert->y = height;\ - vert->z = (vy);\ -\ - if (slope)\ - {\ - fixedheight = P_GetZAt(slope, FLOAT_TO_FIXED((vx)), FLOAT_TO_FIXED((vy)));\ - vert->y = FIXED_TO_FLOAT(fixedheight);\ - }\ -} - for (i = 0, v3d = planeVerts; i < nrPlaneVerts; i++,v3d++,pv++) - SETUP3DVERT(v3d, pv->x, pv->y); + for (i = 0; i < nrPlaneVerts; i++,v3d++,pv++) + { + // Hurdler: add scrolling texture on floor/ceiling + v3d->s = (float)((pv->x / fflatsize) - flatxref + scrollx); + v3d->t = (float)(flatyref - (pv->y / fflatsize) + scrolly); + + //v3d->s = (float)(pv->x / fflatsize); + //v3d->t = (float)(pv->y / fflatsize); + + // Need to rotate before translate + if (angle) // Only needs to be done if there's an altered angle + { + tempxsow = FLOAT_TO_FIXED(v3d->s); + tempytow = FLOAT_TO_FIXED(v3d->t); + v3d->s = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); + v3d->t = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle)))); + } + + //v3d->s = (float)(v3d->s - flatxref + scrollx); + //v3d->t = (float)(flatyref - v3d->t + scrolly); + + v3d->x = pv->x; + v3d->y = height; + v3d->z = pv->y; + +#ifdef ESLOPE + if (slope) + { + fixedheight = P_GetZAt(slope, FLOAT_TO_FIXED(pv->x), FLOAT_TO_FIXED(pv->y)); + v3d->y = FIXED_TO_FLOAT(fixedheight); + } +#endif + } HWR_Lighting(&Surf, lightlevel, planecolormap); @@ -3172,7 +3180,7 @@ void HWR_Subsector(size_t num) // Hack to make things continue to work around slopes. locFloorHeight == cullFloorHeight ? locFloorHeight : gr_frontsector->floorheight, // We now return you to your regularly scheduled rendering. - PF_Occlude, floorlightlevel, levelflats[gr_frontsector->floorpic].lumpnum, NULL, 255, floorcolormap, sub); + PF_Occlude, floorlightlevel, levelflats[gr_frontsector->floorpic].lumpnum, NULL, 255, floorcolormap); } } } @@ -3188,7 +3196,7 @@ void HWR_Subsector(size_t num) // Hack to make things continue to work around slopes. locCeilingHeight == cullCeilingHeight ? locCeilingHeight : gr_frontsector->ceilingheight, // We now return you to your regularly scheduled rendering. - PF_Occlude, ceilinglightlevel, levelflats[gr_frontsector->ceilingpic].lumpnum,NULL, 255, ceilingcolormap, sub); + PF_Occlude, ceilinglightlevel, levelflats[gr_frontsector->ceilingpic].lumpnum,NULL, 255, ceilingcolormap); } } } @@ -3254,7 +3262,7 @@ void HWR_Subsector(size_t num) HWR_GetFlat(levelflats[*rover->bottompic].lumpnum, R_NoEncore(gr_frontsector, false)); light = R_GetPlaneLight(gr_frontsector, centerHeight, viewz < cullHeight ? true : false); HWR_RenderPlane(&extrasubsectors[num], false, *rover->bottomheight, (rover->flags & FF_RIPPLE ? PF_Ripple : 0)|PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->bottompic].lumpnum, - rover->master->frontsector, 255, gr_frontsector->lightlist[light].extra_colormap, sub); + rover->master->frontsector, 255, gr_frontsector->lightlist[light].extra_colormap); } } @@ -3306,7 +3314,7 @@ void HWR_Subsector(size_t num) HWR_GetFlat(levelflats[*rover->toppic].lumpnum, R_NoEncore(gr_frontsector, true)); light = R_GetPlaneLight(gr_frontsector, centerHeight, viewz < cullHeight ? true : false); HWR_RenderPlane(&extrasubsectors[num], true, *rover->topheight, (rover->flags & FF_RIPPLE ? PF_Ripple : 0)|PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->toppic].lumpnum, - rover->master->frontsector, 255, gr_frontsector->lightlist[light].extra_colormap, sub); + rover->master->frontsector, 255, gr_frontsector->lightlist[light].extra_colormap, sub); } } } @@ -5453,11 +5461,6 @@ void HWR_SetTransform(float fpov, player_t *player) postimg_t *postprocessor = &postimgtype[0]; INT32 i; - // copy view cam position for local use - dup_viewx = viewx; - dup_viewy = viewy; - dup_viewz = viewz; - gr_viewx = FIXED_TO_FLOAT(viewx); gr_viewy = FIXED_TO_FLOAT(viewy); gr_viewz = FIXED_TO_FLOAT(viewz); @@ -5657,7 +5660,6 @@ void RecursivePortalRendering(portal_t *rootportal, const float fpov, player_t * HWR_PortalFrame(rootportal);// for portalclipsector, it could have gone null from search HWR_PortalClipping(rootportal); } - //drawcount = 0; validcount++; if (cv_grbatching.value) HWD.pfnStartBatching(); @@ -5696,8 +5698,18 @@ void RecursivePortalRendering(portal_t *rootportal, const float fpov, player_t * HWR_SetTransform(fpov, player);// restore transform } gr_collect_skywalls = false; + + ps_numsprites.value.i = gr_visspritecount; + PS_START_TIMING(ps_hw_spritesorttime); HWR_SortVisSprites(); + PS_STOP_TIMING(ps_hw_spritesorttime); + PS_START_TIMING(ps_hw_spritedrawtime); HWR_DrawSprites(); + PS_STOP_TIMING(ps_hw_spritedrawtime); + + ps_numdrawnodes.value.i = 0; + ps_hw_nodesorttime.value.p = 0; + ps_hw_nodedrawtime.value.p = 0; HWR_RenderDrawNodes(); } // free memory from portal list allocated by calls to Add2Lines @@ -5713,6 +5725,7 @@ void RecursivePortalRendering(portal_t *rootportal, const float fpov, player_t * // TODO: is it okay if stencil test is on all the time even when its not needed? } + // ========================================================================== // Render the current frame. // ========================================================================== @@ -5870,19 +5883,8 @@ void HWR_RenderSinglePortal(portal_t *portal, size_t portalnum, float fpov, play // Render the BSP from the new viewpoint. portalcullsector = gr_portalcullsectors[portalnum]; HWR_RenderBSPNode((INT32)numnodes - 1); - - // Draw MD2 and sprites - ps_numsprites.value.i = gr_visspritecount; - PS_START_TIMING(ps_hw_spritesorttime); HWR_SortVisSprites(); - PS_STOP_TIMING(ps_hw_spritesorttime); - PS_START_TIMING(ps_hw_spritedrawtime); HWR_DrawSprites(); - PS_STOP_TIMING(ps_hw_spritedrawtime); - - ps_numdrawnodes.value.i = 0; - ps_hw_nodesorttime.value.p = 0; - ps_hw_nodedrawtime.value.p = 0; HWR_RenderDrawNodes(); } diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 51a362c9e..4c1f893c1 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -111,7 +111,7 @@ void HWR_MakeScreenFinalTexture(void); void HWR_DrawScreenFinalTexture(int width, int height); // hw_main.c: Planes -void HWR_RenderPlane(extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, UINT8 alpha, extracolormap_t *planecolormap, subsector_t *subsector); +void HWR_RenderPlane(extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, UINT8 alpha, extracolormap_t *planecolormap); void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap); #ifdef POLYOBJECTS -- 2.54.0 From 8737a40a4de107ffc0770f360111539670030ef4 Mon Sep 17 00:00:00 2001 From: lug420 Date: Thu, 7 Sep 2023 23:55:26 +0200 Subject: [PATCH 4/9] bleh --- src/hardware/hw_main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 258573578..9e91e53cd 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5846,7 +5846,6 @@ void HWR_RenderFrame(INT32 viewnumber, player_t *player, boolean skybox) HWD.pfnSetSpecialState(HWD_SET_SHADERS, cv_grshaders.value); HWD.pfnSetShader(0); - //drawcount = 0; validcount++; portalclipline = NULL; -- 2.54.0 From b1b592f88d4ed15ad01a0d219eb201a3525a873d Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Fri, 8 Sep 2023 10:38:48 +0200 Subject: [PATCH 5/9] readd the stuff blubuabb --- src/hardware/hw_main.c | 101 ++++++++++++++++++++--------------------- src/hardware/hw_main.h | 2 +- 2 files changed, 51 insertions(+), 52 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 9e91e53cd..2db41707f 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -196,6 +196,8 @@ FTransform atransform; static float gr_viewx, gr_viewy, gr_viewz; float gr_viewsin, gr_viewcos; +static fixed_t dup_viewx, dup_viewy, dup_viewz; + static angle_t gr_aimingangle; static float gr_viewludsin, gr_viewludcos; @@ -526,7 +528,7 @@ static FUINT HWR_CalcWallLight(FUINT lightnum, fixed_t v1x, fixed_t v1y, fixed_t // HWR_RenderPlane // Render a floor or ceiling convex polygon -void HWR_RenderPlane(extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, UINT8 alpha, extracolormap_t *planecolormap) +void HWR_RenderPlane(extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, UINT8 alpha, extracolormap_t *planecolormap, subsector_t *subsector) { polyvertex_t * pv; float height; //constant y for all points on the convex flat polygon @@ -627,9 +629,6 @@ void HWR_RenderPlane(extrasubsector_t *xsub, boolean isceiling, fixed_t fixedhei // reference point for flat texture coord for each vertex around the polygon flatxref = (float)(((fixed_t)pv->x & (~flatflag)) / fflatsize); flatyref = (float)(((fixed_t)pv->y & (~flatflag)) / fflatsize); - - // transform - v3d = planeVerts; if (FOFsector != NULL) { @@ -682,39 +681,32 @@ void HWR_RenderPlane(extrasubsector_t *xsub, boolean isceiling, fixed_t fixedhei flatyref = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle)))); } - for (i = 0; i < nrPlaneVerts; i++,v3d++,pv++) - { - // Hurdler: add scrolling texture on floor/ceiling - v3d->s = (float)((pv->x / fflatsize) - flatxref + scrollx); - v3d->t = (float)(flatyref - (pv->y / fflatsize) + scrolly); - - //v3d->s = (float)(pv->x / fflatsize); - //v3d->t = (float)(pv->y / fflatsize); - - // Need to rotate before translate - if (angle) // Only needs to be done if there's an altered angle - { - tempxsow = FLOAT_TO_FIXED(v3d->s); - tempytow = FLOAT_TO_FIXED(v3d->t); - v3d->s = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); - v3d->t = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle)))); - } - - //v3d->s = (float)(v3d->s - flatxref + scrollx); - //v3d->t = (float)(flatyref - v3d->t + scrolly); - - v3d->x = pv->x; - v3d->y = height; - v3d->z = pv->y; - -#ifdef ESLOPE - if (slope) - { - fixedheight = P_GetZAt(slope, FLOAT_TO_FIXED(pv->x), FLOAT_TO_FIXED(pv->y)); - v3d->y = FIXED_TO_FLOAT(fixedheight); - } -#endif - } +#define SETUP3DVERT(vert, vx, vy) {\ + /* Hurdler: add scrolling texture on floor/ceiling */\ + vert->s = (float)(((vx) / fflatsize) - flatxref + scrollx);\ + vert->t = (float)(flatyref - ((vy) / fflatsize) + scrolly);\ +\ + /* Need to rotate before translate */\ + if (angle) /* Only needs to be done if there's an altered angle */\ + {\ + tempxsow = FLOAT_TO_FIXED(vert->s);\ + tempytow = FLOAT_TO_FIXED(vert->t);\ + vert->s = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));\ + vert->t = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));\ + }\ +\ + vert->x = (vx);\ + vert->y = height;\ + vert->z = (vy);\ +\ + if (slope)\ + {\ + fixedheight = P_GetZAt(slope, FLOAT_TO_FIXED((vx)), FLOAT_TO_FIXED((vy)));\ + vert->y = FIXED_TO_FLOAT(fixedheight);\ + }\ +} + for (i = 0, v3d = planeVerts; i < nrPlaneVerts; i++,v3d++,pv++) + SETUP3DVERT(v3d, pv->x, pv->y); HWR_Lighting(&Surf, lightlevel, planecolormap); @@ -3180,7 +3172,7 @@ void HWR_Subsector(size_t num) // Hack to make things continue to work around slopes. locFloorHeight == cullFloorHeight ? locFloorHeight : gr_frontsector->floorheight, // We now return you to your regularly scheduled rendering. - PF_Occlude, floorlightlevel, levelflats[gr_frontsector->floorpic].lumpnum, NULL, 255, floorcolormap); + PF_Occlude, floorlightlevel, levelflats[gr_frontsector->floorpic].lumpnum, NULL, 255, floorcolormap, sub); } } } @@ -3196,7 +3188,7 @@ void HWR_Subsector(size_t num) // Hack to make things continue to work around slopes. locCeilingHeight == cullCeilingHeight ? locCeilingHeight : gr_frontsector->ceilingheight, // We now return you to your regularly scheduled rendering. - PF_Occlude, ceilinglightlevel, levelflats[gr_frontsector->ceilingpic].lumpnum,NULL, 255, ceilingcolormap); + PF_Occlude, ceilinglightlevel, levelflats[gr_frontsector->ceilingpic].lumpnum,NULL, 255, ceilingcolormap, sub); } } } @@ -3262,7 +3254,7 @@ void HWR_Subsector(size_t num) HWR_GetFlat(levelflats[*rover->bottompic].lumpnum, R_NoEncore(gr_frontsector, false)); light = R_GetPlaneLight(gr_frontsector, centerHeight, viewz < cullHeight ? true : false); HWR_RenderPlane(&extrasubsectors[num], false, *rover->bottomheight, (rover->flags & FF_RIPPLE ? PF_Ripple : 0)|PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->bottompic].lumpnum, - rover->master->frontsector, 255, gr_frontsector->lightlist[light].extra_colormap); + rover->master->frontsector, 255, gr_frontsector->lightlist[light].extra_colormap, sub); } } @@ -3314,7 +3306,7 @@ void HWR_Subsector(size_t num) HWR_GetFlat(levelflats[*rover->toppic].lumpnum, R_NoEncore(gr_frontsector, true)); light = R_GetPlaneLight(gr_frontsector, centerHeight, viewz < cullHeight ? true : false); HWR_RenderPlane(&extrasubsectors[num], true, *rover->topheight, (rover->flags & FF_RIPPLE ? PF_Ripple : 0)|PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->toppic].lumpnum, - rover->master->frontsector, 255, gr_frontsector->lightlist[light].extra_colormap, sub); + rover->master->frontsector, 255, gr_frontsector->lightlist[light].extra_colormap, sub); } } } @@ -5461,6 +5453,11 @@ void HWR_SetTransform(float fpov, player_t *player) postimg_t *postprocessor = &postimgtype[0]; INT32 i; + // copy view cam position for local use + dup_viewx = viewx; + dup_viewy = viewy; + dup_viewz = viewz; + gr_viewx = FIXED_TO_FLOAT(viewx); gr_viewy = FIXED_TO_FLOAT(viewy); gr_viewz = FIXED_TO_FLOAT(viewz); @@ -5660,6 +5657,7 @@ void RecursivePortalRendering(portal_t *rootportal, const float fpov, player_t * HWR_PortalFrame(rootportal);// for portalclipsector, it could have gone null from search HWR_PortalClipping(rootportal); } + //drawcount = 0; validcount++; if (cv_grbatching.value) HWD.pfnStartBatching(); @@ -5698,18 +5696,8 @@ void RecursivePortalRendering(portal_t *rootportal, const float fpov, player_t * HWR_SetTransform(fpov, player);// restore transform } gr_collect_skywalls = false; - - ps_numsprites.value.i = gr_visspritecount; - PS_START_TIMING(ps_hw_spritesorttime); HWR_SortVisSprites(); - PS_STOP_TIMING(ps_hw_spritesorttime); - PS_START_TIMING(ps_hw_spritedrawtime); HWR_DrawSprites(); - PS_STOP_TIMING(ps_hw_spritedrawtime); - - ps_numdrawnodes.value.i = 0; - ps_hw_nodesorttime.value.p = 0; - ps_hw_nodedrawtime.value.p = 0; HWR_RenderDrawNodes(); } // free memory from portal list allocated by calls to Add2Lines @@ -5882,8 +5870,19 @@ void HWR_RenderSinglePortal(portal_t *portal, size_t portalnum, float fpov, play // Render the BSP from the new viewpoint. portalcullsector = gr_portalcullsectors[portalnum]; HWR_RenderBSPNode((INT32)numnodes - 1); + + // Draw MD2 and sprites + ps_numsprites.value.i = gr_visspritecount; + PS_START_TIMING(ps_hw_spritesorttime); HWR_SortVisSprites(); + PS_STOP_TIMING(ps_hw_spritesorttime); + PS_START_TIMING(ps_hw_spritedrawtime); HWR_DrawSprites(); + PS_STOP_TIMING(ps_hw_spritedrawtime); + + ps_numdrawnodes.value.i = 0; + ps_hw_nodesorttime.value.p = 0; + ps_hw_nodedrawtime.value.p = 0; HWR_RenderDrawNodes(); } diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 4c1f893c1..51a362c9e 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -111,7 +111,7 @@ void HWR_MakeScreenFinalTexture(void); void HWR_DrawScreenFinalTexture(int width, int height); // hw_main.c: Planes -void HWR_RenderPlane(extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, UINT8 alpha, extracolormap_t *planecolormap); +void HWR_RenderPlane(extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, UINT8 alpha, extracolormap_t *planecolormap, subsector_t *subsector); void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap); #ifdef POLYOBJECTS -- 2.54.0 From 7beab3b582f0c7455a9676f3ae15ebe987e8aa23 Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Fri, 8 Sep 2023 10:42:31 +0200 Subject: [PATCH 6/9] fix the sprite renderstats again aAAaaa --- src/hardware/hw_main.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 2db41707f..49bdaa499 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5696,8 +5696,18 @@ void RecursivePortalRendering(portal_t *rootportal, const float fpov, player_t * HWR_SetTransform(fpov, player);// restore transform } gr_collect_skywalls = false; + + ps_numsprites.value.i = gr_visspritecount; + PS_START_TIMING(ps_hw_spritesorttime); HWR_SortVisSprites(); + PS_STOP_TIMING(ps_hw_spritesorttime); + PS_START_TIMING(ps_hw_spritedrawtime); HWR_DrawSprites(); + PS_STOP_TIMING(ps_hw_spritedrawtime); + + ps_numdrawnodes.value.i = 0; + ps_hw_nodesorttime.value.p = 0; + ps_hw_nodedrawtime.value.p = 0; HWR_RenderDrawNodes(); } // free memory from portal list allocated by calls to Add2Lines @@ -5871,18 +5881,8 @@ void HWR_RenderSinglePortal(portal_t *portal, size_t portalnum, float fpov, play portalcullsector = gr_portalcullsectors[portalnum]; HWR_RenderBSPNode((INT32)numnodes - 1); - // Draw MD2 and sprites - ps_numsprites.value.i = gr_visspritecount; - PS_START_TIMING(ps_hw_spritesorttime); HWR_SortVisSprites(); - PS_STOP_TIMING(ps_hw_spritesorttime); - PS_START_TIMING(ps_hw_spritedrawtime); HWR_DrawSprites(); - PS_STOP_TIMING(ps_hw_spritedrawtime); - - ps_numdrawnodes.value.i = 0; - ps_hw_nodesorttime.value.p = 0; - ps_hw_nodedrawtime.value.p = 0; HWR_RenderDrawNodes(); } -- 2.54.0 From cdedf1349cd4e797a8e8ffcac3a9032d3278e888 Mon Sep 17 00:00:00 2001 From: Indev Date: Fri, 8 Sep 2023 11:47:19 +0300 Subject: [PATCH 7/9] Attempt to fix non-ansii filenames on windows --- src/w_wad.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/src/w_wad.c b/src/w_wad.c index 31977bea8..6f16b3477 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -148,6 +148,38 @@ void W_Shutdown(void) static char filenamebuf[MAX_WADPATH]; +// This #if is copied from filesrch.c, so not sure if it is 100% suitable for +// this +#if defined (_WIN32) && !defined (_XBOX) +//#define WIN32_LEAN_AND_MEAN +#define RPC_NO_WINDOWS_H +#include + +// Windows can't open utf-8 path so it must be converted to utf-16 +FILE* fopen_utf8(const char* filename, const char* mode) +{ + static const int MY_PATH_MAX = 2048; + WCHAR nameW[MY_PATH_MAX] = { 0 }; + WCHAR modeW[16] = { 0 }; + // the following function converts the UTF-8 filename to UTF-16 (WCHAR) nameW + int len = MultiByteToWideChar(CP_UTF8, 0, filename, -1, nameW, MY_PATH_MAX); + if(len > 0 && MultiByteToWideChar(CP_UTF8, 0, mode, -1, modeW, 16) > 0) + { + // using _wfopen_s() shuts up MSVC's complaints + // about _wfopen() being unsafe.. + FILE* ret = NULL; + if(_wfopen_s(&ret, nameW, modeW) == 0) + return ret; + } + return NULL; +} + +#else + +#define fopen_utf8 fopen + +#endif + // W_OpenWadFile // Helper function for opening the WAD file. // Returns the FILE * handle for the file, or NULL if not found or could not be opened @@ -165,7 +197,7 @@ FILE *W_OpenWadFile(const char **filename, boolean useerrors) *filename = filenamebuf; // open wad file - if ((handle = fopen(*filename, "rb")) == NULL) + if ((handle = fopen_utf8(*filename, "rb")) == NULL) { // If we failed to load the file with the path as specified by // the user, strip the directories and search for the file. @@ -175,7 +207,7 @@ FILE *W_OpenWadFile(const char **filename, boolean useerrors) // in filenamebuf == *filename. if (findfile(filenamebuf, NULL, true)) { - if ((handle = fopen(*filename, "rb")) == NULL) + if ((handle = fopen_utf8(*filename, "rb")) == NULL) { if (useerrors) CONS_Alert(CONS_ERROR, M_GetText("Can't open %s\n"), *filename); -- 2.54.0 From 9cd0e6c38512e56ca2e0c4c34e886b7e5db49cca Mon Sep 17 00:00:00 2001 From: Indev Date: Fri, 8 Sep 2023 12:00:10 +0300 Subject: [PATCH 8/9] Why is this 'variable-sized' and can't be initialized like that??? --- src/w_wad.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/w_wad.c b/src/w_wad.c index 6f16b3477..f715c26cb 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -159,8 +159,10 @@ static char filenamebuf[MAX_WADPATH]; FILE* fopen_utf8(const char* filename, const char* mode) { static const int MY_PATH_MAX = 2048; - WCHAR nameW[MY_PATH_MAX] = { 0 }; - WCHAR modeW[16] = { 0 }; + WCHAR nameW[MY_PATH_MAX]; + memset(nameW, 0, sizeof(WCHAR)*MY_PATH_MAX); + WCHAR modeW[16]; + memset(modeW, 0, sizeof(WCHAR)*16); // the following function converts the UTF-8 filename to UTF-16 (WCHAR) nameW int len = MultiByteToWideChar(CP_UTF8, 0, filename, -1, nameW, MY_PATH_MAX); if(len > 0 && MultiByteToWideChar(CP_UTF8, 0, mode, -1, modeW, 16) > 0) -- 2.54.0 From 1c9ea1eb2e9bb9e210d93f568dc5797083198cf7 Mon Sep 17 00:00:00 2001 From: lug420 Date: Sat, 9 Sep 2023 01:38:23 +0200 Subject: [PATCH 9/9] fix a crash with rotsprites + clean up this absolute mess --- src/hardware/hw_main.c | 2 +- src/r_patch.c | 2120 +++++++++++++++++++--------------------- src/r_patch.h | 137 ++- src/r_things.c | 2 +- 4 files changed, 1088 insertions(+), 1173 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 49bdaa499..aa9a921e2 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5065,7 +5065,7 @@ void HWR_ProjectSprite(mobj_t *thing) rollsum = (thing->rollangle)+(thing->sloperoll); rollangle = R_GetRollAngle(rollsum); - rotsprite = Patch_GetRotatedSprite(sprframe, (thing->frame & FF_FRAMEMASK), rot, flip, sprinfo, rollangle); + rotsprite = Patch_GetRotatedSprite(sprframe, (thing->frame & FF_FRAMEMASK), rot, flip, false, sprinfo, rollangle); if (rotsprite != NULL) { diff --git a/src/r_patch.c b/src/r_patch.c index 881ca41de..efd49f5e2 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -1,1102 +1,1018 @@ -// SONIC ROBO BLAST 2 -//----------------------------------------------------------------------------- -// Copyright (C) 1993-1996 by id Software, Inc. -// Copyright (C) 2005-2009 by Andrey "entryway" Budko. -// Copyright (C) 2018-2020 by Jaime "Lactozilla" Passos. -// Copyright (C) 2019-2020 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 r_patch.c -/// \brief Patch generation. - -#include "byteptr.h" -#include "dehacked.h" -#include "i_video.h" -#include "r_data.h" -#include "r_draw.h" -#include "r_patch.h" -#include "r_things.h" -#include "z_zone.h" -#include "w_wad.h" - -#ifdef HWRENDER -#include "hardware/hw_glob.h" -#endif - -static unsigned char imgbuf[1<<26]; - -// -// R_CheckIfPatch -// -// Returns true if the lump is a valid patch. -// -boolean R_CheckIfPatch(lumpnum_t lump) -{ - size_t size; - INT16 width, height; - patch_t *patch; - boolean result; - - size = W_LumpLength(lump); - - // minimum length of a valid Doom patch - if (size < 13) - return false; - - patch = (patch_t *)W_CacheLumpNum(lump, PU_STATIC); - - width = patch->width; - height = patch->height; - - result = (height > 0 && height <= 16384 && width > 0 && width <= 16384 && width < (INT16)(size / 4)); - - if (result) - { - // The dimensions seem like they might be valid for a patch, so - // check the column directory for extra security. All columns - // must begin after the column directory, and none of them must - // point past the end of the patch. - INT16 x; - - for (x = 0; x < width; x++) - { - UINT32 ofs = LONG(patch->columnofs[x]); - - // Need one byte for an empty column (but there's patches that don't know that!) - if (ofs < (UINT32)width * 4 + 8 || ofs >= (UINT32)size) - { - result = false; - break; - } - } - } - - return result; -} - -// -// R_TextureToFlat -// -// Convert a texture to a flat. -// -void R_TextureToFlat(size_t tex, UINT8 *flat) -{ - texture_t *texture = textures[tex]; - - fixed_t col, ofs; - column_t *column; - UINT8 *desttop, *dest, *deststop; - UINT8 *source; - - // yea - R_CheckTextureCache(tex); - - desttop = flat; - deststop = desttop + (texture->width * texture->height); - - for (col = 0; col < texture->width; col++, desttop++) - { - // no post_t info - if (!texture->holes) - { - column = (column_t *)(R_GetColumn(tex, col)); - source = (UINT8 *)(column); - dest = desttop; - for (ofs = 0; dest < deststop && ofs < texture->height; ofs++) - { - if (source[ofs] != TRANSPARENTPIXEL) - *dest = source[ofs]; - dest += texture->width; - } - } - else - { - INT32 topdelta, prevdelta = -1; - column = (column_t *)((UINT8 *)R_GetColumn(tex, col) - 3); - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - - dest = desttop + (topdelta * texture->width); - source = (UINT8 *)column + 3; - for (ofs = 0; dest < deststop && ofs < column->length; ofs++) - { - if (source[ofs] != TRANSPARENTPIXEL) - *dest = source[ofs]; - dest += texture->width; - } - column = (column_t *)((UINT8 *)column + column->length + 4); - } - } - } -} - -// -// R_PatchToFlat -// -// Convert a patch to a flat. -// -void R_PatchToFlat(patch_t *patch, UINT8 *flat) -{ - fixed_t col, ofs; - column_t *column; - UINT8 *desttop, *dest, *deststop; - UINT8 *source; - - desttop = flat; - deststop = desttop + (SHORT(patch->width) * SHORT(patch->height)); - - for (col = 0; col < SHORT(patch->width); col++, desttop++) - { - INT32 topdelta, prevdelta = -1; - column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[col])); - - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - - dest = desttop + (topdelta * SHORT(patch->width)); - source = (UINT8 *)(column) + 3; - for (ofs = 0; dest < deststop && ofs < column->length; ofs++) - { - *dest = source[ofs]; - dest += SHORT(patch->width); - } - column = (column_t *)((UINT8 *)column + column->length + 4); - } - } -} - -// -// R_PatchToMaskedFlat -// -// Convert a patch to a masked flat. -// Now, what is a "masked" flat anyway? -// It means the flat uses two bytes to store image data. -// The upper byte is used to store the transparent pixel, -// and the lower byte stores a palette index. -// -void R_PatchToMaskedFlat(patch_t *patch, UINT16 *raw, boolean flip) -{ - fixed_t col, ofs; - column_t *column; - UINT16 *desttop, *dest, *deststop; - UINT8 *source; - - desttop = raw; - deststop = desttop + (SHORT(patch->width) * SHORT(patch->height)); - - for (col = 0; col < SHORT(patch->width); col++, desttop++) - { - INT32 topdelta, prevdelta = -1; - column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[flip ? (patch->width-1-col) : col])); - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - dest = desttop + (topdelta * SHORT(patch->width)); - source = (UINT8 *)(column) + 3; - for (ofs = 0; dest < deststop && ofs < column->length; ofs++) - { - *dest = source[ofs]; - dest += SHORT(patch->width); - } - column = (column_t *)((UINT8 *)column + column->length + 4); - } - } -} - -// -// R_FlatToPatch -// -// Convert a flat to a patch. -// -patch_t *R_FlatToPatch(UINT8 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize, boolean transparency) -{ - UINT32 x, y; - UINT8 *img; - UINT8 *imgptr = imgbuf; - UINT8 *colpointers, *startofspan; - size_t size = 0; - - if (!raw) - return NULL; - - // Write image size and offset - WRITEINT16(imgptr, width); - WRITEINT16(imgptr, height); - WRITEINT16(imgptr, leftoffset); - WRITEINT16(imgptr, topoffset); - - // Leave placeholder to column pointers - colpointers = imgptr; - imgptr += width*4; - - // Write columns - for (x = 0; x < width; x++) - { - int lastStartY = 0; - int spanSize = 0; - startofspan = NULL; - - // Write column pointer - WRITEINT32(colpointers, imgptr - imgbuf); - - // Write pixels - for (y = 0; y < height; y++) - { - UINT8 paletteIndex = raw[((y * width) + x)]; - boolean opaque = transparency ? (paletteIndex != TRANSPARENTPIXEL) : true; - - // End span if we have a transparent pixel - if (!opaque) - { - if (startofspan) - WRITEUINT8(imgptr, 0); - startofspan = NULL; - continue; - } - - // Start new column if we need to - if (!startofspan || spanSize == 255) - { - int writeY = y; - - // If we reached the span size limit, finish the previous span - if (startofspan) - WRITEUINT8(imgptr, 0); - - if (y > 254) - { - // Make sure we're aligned to 254 - if (lastStartY < 254) - { - WRITEUINT8(imgptr, 254); - WRITEUINT8(imgptr, 0); - imgptr += 2; - lastStartY = 254; - } - - // Write stopgap empty spans if needed - writeY = y - lastStartY; - - while (writeY > 254) - { - WRITEUINT8(imgptr, 254); - WRITEUINT8(imgptr, 0); - imgptr += 2; - writeY -= 254; - } - } - - startofspan = imgptr; - WRITEUINT8(imgptr, writeY); - imgptr += 2; - spanSize = 0; - - lastStartY = y; - } - - // Write the pixel - WRITEUINT8(imgptr, paletteIndex); - spanSize++; - startofspan[1] = spanSize; - } - - if (startofspan) - WRITEUINT8(imgptr, 0); - - WRITEUINT8(imgptr, 0xFF); - } - - size = imgptr-imgbuf; - img = Z_Malloc(size, PU_STATIC, NULL); - memcpy(img, imgbuf, size); - - Z_Free(raw); - - if (destsize != NULL) - *destsize = size; - return (patch_t *)img; -} - -// -// R_MaskedFlatToPatch -// -// Convert a masked flat to a patch. -// Explanation of "masked" flats in R_PatchToMaskedFlat. -// -patch_t *R_MaskedFlatToPatch(UINT16 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize) -{ - UINT32 x, y; - UINT8 *img; - UINT8 *imgptr = imgbuf; - UINT8 *colpointers, *startofspan; - size_t size = 0; - - if (!raw) - return NULL; - - // Write image size and offset - WRITEINT16(imgptr, width); - WRITEINT16(imgptr, height); - WRITEINT16(imgptr, leftoffset); - WRITEINT16(imgptr, topoffset); - - // Leave placeholder to column pointers - colpointers = imgptr; - imgptr += width*4; - - // Write columns - for (x = 0; x < width; x++) - { - int lastStartY = 0; - int spanSize = 0; - startofspan = NULL; - - // Write column pointer - WRITEINT32(colpointers, imgptr - imgbuf); - - // Write pixels - for (y = 0; y < height; y++) - { - UINT16 pixel = raw[((y * width) + x)]; - UINT8 paletteIndex = (pixel & 0xFF); - UINT8 opaque = (pixel != 0xFF00); // If 1, we have a pixel - - // End span if we have a transparent pixel - if (!opaque) - { - if (startofspan) - WRITEUINT8(imgptr, 0); - startofspan = NULL; - continue; - } - - // Start new column if we need to - if (!startofspan || spanSize == 255) - { - int writeY = y; - - // If we reached the span size limit, finish the previous span - if (startofspan) - WRITEUINT8(imgptr, 0); - - if (y > 254) - { - // Make sure we're aligned to 254 - if (lastStartY < 254) - { - WRITEUINT8(imgptr, 254); - WRITEUINT8(imgptr, 0); - imgptr += 2; - lastStartY = 254; - } - - // Write stopgap empty spans if needed - writeY = y - lastStartY; - - while (writeY > 254) - { - WRITEUINT8(imgptr, 254); - WRITEUINT8(imgptr, 0); - imgptr += 2; - writeY -= 254; - } - } - - startofspan = imgptr; - WRITEUINT8(imgptr, writeY); - imgptr += 2; - spanSize = 0; - - lastStartY = y; - } - - // Write the pixel - WRITEUINT8(imgptr, paletteIndex); - spanSize++; - startofspan[1] = spanSize; - } - - if (startofspan) - WRITEUINT8(imgptr, 0); - - WRITEUINT8(imgptr, 0xFF); - } - - size = imgptr-imgbuf; - img = Z_Malloc(size, PU_STATIC, NULL); - memcpy(img, imgbuf, size); - - if (destsize != NULL) - *destsize = size; - return (patch_t *)img; -} - -// -// R_ParseSpriteInfoFrame -// -// Parse a SPRTINFO frame. -// -static void R_ParseSpriteInfoFrame(spriteinfo_t *info) -{ - char *sprinfoToken; - size_t sprinfoTokenLength; - char *frameChar = NULL; - UINT8 frameFrame = 0xFF; - INT16 frameXPivot = 0; - INT16 frameYPivot = 0; - rotaxis_t frameRotAxis = 0; - - // Sprite identifier - sprinfoToken = M_GetToken(NULL); - if (sprinfoToken == NULL) - { - 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; - - frameFrame = R_Char2Frame(frameChar[0]); - Z_Free(sprinfoToken); - - // Left Curly Brace - sprinfoToken = M_GetToken(NULL); - if (sprinfoToken == NULL) - I_Error("Error parsing SPRTINFO lump: Missing sprite info"); - else - { - if (strcmp(sprinfoToken,"{")==0) - { - 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 (strcmp(sprinfoToken,"}")!=0) - { - 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"); - } - } - } - Z_Free(sprinfoToken); - } - - // set fields - info->pivot[frameFrame].x = frameXPivot; - info->pivot[frameFrame].y = frameYPivot; - info->pivot[frameFrame].rotaxis = frameRotAxis; -} - -// -// R_ParseSpriteInfo -// -// Parse a SPRTINFO lump. -// -static void R_ParseSpriteInfo(boolean spr2) -{ - spriteinfo_t *info; - char *sprinfoToken; - size_t sprinfoTokenLength; - char newSpriteName[5]; // no longer dynamically allocated - spritenum_t sprnum = NUMSPRITES; - //playersprite_t spr2num = NUMPLAYERSPRITES; - INT32 i; - INT32 skinnumbers[MAXSKINS]; // >variable 'skinnumbers' set but not used >compile error when commented out - INT32 foundskins = 0; - - // Sprite name - sprinfoToken = M_GetToken(NULL); - if (sprinfoToken == NULL) - { - I_Error("Error parsing SPRTINFO lump: Unexpected end of file where sprite name should be"); - } - sprinfoTokenLength = strlen(sprinfoToken); - if (sprinfoTokenLength != 4) - { - I_Error("Error parsing SPRTINFO lump: Sprite name \"%s\" isn't 4 characters long",sprinfoToken); - } - else - { - memset(&newSpriteName, 0, 5); - M_Memcpy(newSpriteName, sprinfoToken, sprinfoTokenLength); - // ^^ 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) - { - for (i = 0; i <= NUMSPRITES; i++) - { - if (i == NUMSPRITES) - I_Error("Error parsing SPRTINFO lump: Unknown sprite name \"%s\"", newSpriteName); - if (!memcmp(newSpriteName,sprnames[i],4)) - { - sprnum = i; - break; - } - } - } - else - { - /*for (i = 0; i <= NUMPLAYERSPRITES; i++) - { - if (i == NUMPLAYERSPRITES) - I_Error("Error parsing SPRTINFO lump: Unknown sprite2 name \"%s\"", newSpriteName); - if (!memcmp(newSpriteName,spr2names[i],4)) - { - spr2num = i; - break; - } - }*/ - // Fuckal: 2.1; playersprites don't exist - } - - // allocate a spriteinfo - info = Z_Calloc(sizeof(spriteinfo_t), PU_STATIC, NULL); - info->available = true; - - // Left Curly Brace - sprinfoToken = M_GetToken(NULL); - if (sprinfoToken == NULL) - { - I_Error("Error parsing SPRTINFO lump: Unexpected end of file where open curly brace for sprite \"%s\" should be",newSpriteName); - } - if (strcmp(sprinfoToken,"{")==0) - { - 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 (strcmp(sprinfoToken,"}")!=0) - { - if (stricmp(sprinfoToken, "SKIN")==0) - { - INT32 skinnum; - char *skinName = NULL; - if (!spr2) - I_Error("Error parsing SPRTINFO lump: \"SKIN\" token found outside of a sprite2 definition"); - - Z_Free(sprinfoToken); - - // Skin name - sprinfoToken = M_GetToken(NULL); - if (sprinfoToken == NULL) - { - I_Error("Error parsing SPRTINFO lump: Unexpected end of file where skin frame should be"); - } - - // copy skin name yada yada - sprinfoTokenLength = strlen(sprinfoToken); - skinName = (char *)Z_Malloc((sprinfoTokenLength+1)*sizeof(char),PU_STATIC,NULL); - M_Memcpy(skinName,sprinfoToken,sprinfoTokenLength*sizeof(char)); - skinName[sprinfoTokenLength] = '\0'; - strlwr(skinName); - Z_Free(sprinfoToken); - - skinnum = R_SkinAvailable(skinName); - if (skinnum == -1) - I_Error("Error parsing SPRTINFO lump: Unknown skin \"%s\"", skinName); - - skinnumbers[foundskins] = skinnum; - foundskins++; - } - else if (stricmp(sprinfoToken, "FRAME")==0) - { - R_ParseSpriteInfoFrame(info); - Z_Free(sprinfoToken); - /*if (spr2) - { - if (!foundskins) - I_Error("Error parsing SPRTINFO lump: No skins specified in this sprite2 definition"); - for (i = 0; i < foundskins; i++) - { - size_t skinnum = skinnumbers[i]; - skin_t *skin = &skins[skinnum]; - spriteinfo_t *sprinfo = skin->sprinfo; -#ifdef ROTSPRITE - R_FreeSkinRotSprite(skinnum); -#endif - M_Memcpy(&sprinfo[spr2num], info, sizeof(spriteinfo_t)); - } - } - else*/ - M_Memcpy(&spriteinfo[sprnum], info, sizeof(spriteinfo_t)); - } - else - { - I_Error("Error parsing SPRTINFO lump: Unknown keyword \"%s\" in sprite %s",sprinfoToken,newSpriteName); - } - - sprinfoToken = M_GetToken(NULL); - if (sprinfoToken == NULL) - { - I_Error("Error parsing SPRTINFO lump: Unexpected end of file where sprite info or right curly brace for sprite \"%s\" should be",newSpriteName); - } - } - } - else - { - I_Error("Error parsing SPRTINFO lump: Expected \"{\" for sprite \"%s\", got \"%s\"",newSpriteName,sprinfoToken); - } - Z_Free(sprinfoToken); - Z_Free(info); -} - -// -// R_ParseSPRTINFOLump -// -// Read a SPRTINFO lump. -// -void R_ParseSPRTINFOLump(UINT16 wadNum, UINT16 lumpNum) -{ - char *sprinfoLump; - size_t sprinfoLumpLength; - char *sprinfoText; - char *sprinfoToken; - - // Since lumps AREN'T \0-terminated like I'd assumed they should be, I'll - // need to make a space of memory where I can ensure that it will terminate - // correctly. Start by loading the relevant data from the WAD. - sprinfoLump = (char *)W_CacheLumpNumPwad(wadNum, lumpNum, PU_STATIC); - // If that didn't exist, we have nothing to do here. - if (sprinfoLump == NULL) return; - // If we're still here, then it DOES exist; figure out how long it is, and allot memory accordingly. - sprinfoLumpLength = W_LumpLengthPwad(wadNum, lumpNum); - sprinfoText = (char *)Z_Malloc((sprinfoLumpLength+1)*sizeof(char),PU_STATIC,NULL); - // Now move the contents of the lump into this new location. - memmove(sprinfoText,sprinfoLump,sprinfoLumpLength); - // Make damn well sure the last character in our new memory location is \0. - sprinfoText[sprinfoLumpLength] = '\0'; - // Finally, free up the memory from the first data load, because we really - // don't need it. - Z_Free(sprinfoLump); - - sprinfoToken = M_GetToken(sprinfoText); - while (sprinfoToken != NULL) - { - if (!stricmp(sprinfoToken, "SPRITE")) - R_ParseSpriteInfo(false); - else if (!stricmp(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); -} - -// -// R_LoadSpriteInfoLumps -// -// Load and read every SPRTINFO lump from the specified file. -// -void R_LoadSpriteInfoLumps(UINT16 wadnum, UINT16 numlumps) -{ - lumpinfo_t *lumpinfo = wadfiles[wadnum]->lumpinfo; - UINT16 i; - char *name; - - for (i = 0; i < numlumps; i++, lumpinfo++) - { - name = lumpinfo->name; - // Load SPRTINFO and SPR_ lumps as SpriteInfo - if (!memcmp(name, "SPRTINFO", 8) || !memcmp(name, "SPR_", 4)) - R_ParseSPRTINFOLump(wadnum, i); - } -} - -static UINT16 GetPatchPixel(patch_t *patch, INT32 x, INT32 y, boolean flip) -{ - fixed_t ofs; - column_t *column; - UINT8 *source; - - if (x >= 0 && x < SHORT(patch->width)) - { - INT32 topdelta, prevdelta = -1; - column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[flip ? (patch->width-1-x) : x])); - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (UINT8 *)(column) + 3; - for (ofs = 0; ofs < column->length; ofs++) - { - if ((topdelta + ofs) == y) - return source[ofs]; - } - column = (column_t *)((UINT8 *)column + column->length + 4); - } - } - - return 0xFF00; -} - -#ifdef ROTSPRITE -// -// R_GetRollAngle -// -// Angles precalculated in R_InitSprites. -// -fixed_t rollcosang[ROTANGLES]; -fixed_t rollsinang[ROTANGLES]; -INT32 R_GetRollAngle(angle_t rollangle) -{ - INT32 ra = AngleFixed(rollangle)>>FRACBITS; -#if (ROTANGDIFF > 1) - ra += (ROTANGDIFF/2); -#endif - ra /= ROTANGDIFF; - ra %= ROTANGLES; - return ra; -} - -patch_t *Patch_GetRotatedSprite( - spriteframe_t *sprite, - size_t frame, size_t spriteangle, - boolean flip, void *info, - INT32 rotationangle) -{ - rotsprite_t *rotsprite; - spriteinfo_t *sprinfo = (spriteinfo_t *)info; - boolean adjustfeet; - - adjustfeet = (rendermode == render_none); - - INT32 idx = rotationangle; - UINT8 type = (adjustfeet ? 1 : 0); - - if (rotationangle < 1 || rotationangle >= ROTANGLES) - return NULL; - - rotsprite = sprite->rotated[type][spriteangle]; - - if (rotsprite == NULL) - { - rotsprite = RotatedPatch_Create(ROTANGLES); - sprite->rotated[type][spriteangle] = rotsprite; - } - - if (flip) - idx += rotsprite->angles; - - if (rotsprite->patches[idx] == NULL) - { - patch_t *patch; - INT32 xpivot = 0, ypivot = 0; - lumpnum_t lump = sprite->lumppat[spriteangle]; - - if (lump == LUMPERROR) - return NULL; - - patch = (patch_t *)W_CacheLumpNum(lump, PU_STATIC); - - if (sprinfo->available) - { - xpivot = sprinfo->pivot[frame].x; - ypivot = sprinfo->pivot[frame].y; - } - else - { - xpivot = patch->leftoffset; - ypivot = patch->height / 2; - } - - RotatedPatch_DoRotation(rotsprite, patch, rotationangle, xpivot, ypivot, flip); - - //BP: we cannot use special tric in hardware mode because feet in ground caused by z-buffer - if (adjustfeet) - ((patch_t *)rotsprite->patches[idx])->topoffset += FEETADJUST>>FRACBITS; - - // free image data - Z_Free(patch); - } - - return rotsprite->patches[idx]; -} - -rotsprite_t *RotatedPatch_Create(INT32 numangles) -{ - rotsprite_t *rotsprite = Z_Calloc(sizeof(rotsprite_t), PU_STATIC, NULL); - rotsprite->angles = numangles; - rotsprite->patches = Z_Calloc(rotsprite->angles * 2 * sizeof(void *), PU_STATIC, NULL); - return rotsprite; -} - -static void RotatedPatch_CalculateDimensions( - INT32 width, INT32 height, - fixed_t ca, fixed_t sa, - INT32 *newwidth, INT32 *newheight) -{ - fixed_t fixedwidth = (width * FRACUNIT); - fixed_t fixedheight = (height * FRACUNIT); - - fixed_t w1 = abs(FixedMul(fixedwidth, ca) - FixedMul(fixedheight, sa)); - fixed_t w2 = abs(FixedMul(-fixedwidth, ca) - FixedMul(fixedheight, sa)); - fixed_t h1 = abs(FixedMul(fixedwidth, sa) + FixedMul(fixedheight, ca)); - fixed_t h2 = abs(FixedMul(-fixedwidth, sa) + FixedMul(fixedheight, ca)); - - w1 = FixedInt(FixedCeil(w1 + (FRACUNIT/2))); - w2 = FixedInt(FixedCeil(w2 + (FRACUNIT/2))); - 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 patch_t *R_CreateHardwarePatch(patch_t *patch) -{ - GLPatch_t *grPatch = Z_Calloc(sizeof(GLPatch_t), PU_HWRPATCHINFO, NULL); - grPatch->mipmap = Z_Calloc(sizeof(GLMipmap_t), PU_HWRPATCHINFO, NULL); - grPatch->rawpatch = patch; - //sprframe->rotsprite.patch[rot][angle] = (patch_t *)grPatch; - HWR_MakePatch(patch, grPatch, grPatch->mipmap, false); - return (patch_t *)grPatch; -} - -// -// R_CacheRotSprite -// -// Create a rotated sprite. -// -void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle, INT32 xpivot, INT32 ypivot, UINT8 flip) -{ - UINT32 i; - patch_t *rotated, *hwpatch; - UINT16 *rawdst, *rawconv; - size_t size; - INT32 bflip = (flip != 0x00); - - INT32 width = patch->width; - INT32 height = patch->height; - INT32 leftoffset = patch->leftoffset; - INT32 newwidth, newheight; - - fixed_t ca = rollcosang[angle]; - fixed_t sa = rollsinang[angle]; - fixed_t xcenter, ycenter; - INT32 idx = angle; - INT32 x, y; - INT32 sx, sy; - INT32 dx, dy; - INT32 ox, oy; - INT32 minx, miny, maxx, maxy; - - // Don't cache angle = 0 - if (angle < 1 || angle >= ROTANGLES) - return; - - if (flip) - { - idx += rotsprite->angles; - xpivot = width - xpivot; - leftoffset = width - leftoffset; - } - - - if (rotsprite->patches[idx]) - return; - - // Find the dimensions of the rotated patch. - RotatedPatch_CalculateDimensions(width, height, ca, sa, &newwidth, &newheight); - - xcenter = (xpivot * FRACUNIT); - ycenter = (ypivot * FRACUNIT); - - if (xpivot != width / 2 || ypivot != height / 2) - { - newwidth *= 2; - newheight *= 2; - } - - minx = newwidth; - miny = newheight; - maxx = 0; - maxy = 0; - - - // Draw the rotated sprite to a temporary buffer. - size = (newwidth * newheight); - if (!size) - size = (width * height); - - rawdst = Z_Malloc(size * sizeof(UINT16), PU_STATIC, NULL); - for (i = 0; i < size; i++) - rawdst[i] = 0xFF00; - - for (dy = 0; dy < newheight; dy++) - { - for (dx = 0; dx < newwidth; dx++) - { - x = (dx - (newwidth / 2)) * FRACUNIT; - y = (dy - (newheight / 2)) * FRACUNIT; - sx = FixedMul(x, ca) + FixedMul(y, sa) + xcenter; - sy = -FixedMul(x, sa) + FixedMul(y, ca) + ycenter; - - sx >>= FRACBITS; - sy >>= FRACBITS; - - if (sx >= 0 && sy >= 0 && sx < width && sy < height) - rawdst[(dy*newwidth)+dx] = GetPatchPixel(patch, sx, sy, bflip); - } - } - - - ox = (newwidth / 2) + (leftoffset - xpivot); - oy = (newheight / 2) + (patch->topoffset - ypivot); - width = (maxx+1 - minx); - height = (maxy+1 - miny); - - if ((unsigned)(width * height) > size) - { - UINT16 *src, *dest; - - - size = (width * height); - rawconv = Z_Malloc(size * sizeof(UINT16), PU_STATIC, NULL); - - src = &rawdst[(miny * newwidth) + minx]; - dest = rawconv; - dy = height; - - - while (dy--) - { - M_Memcpy(dest, src, width * sizeof(UINT16)); - dest += width; - src += newwidth; - } - - - ox -= minx; - oy -= miny; - - - Z_Free(rawdst); - } - else - { - rawconv = rawdst; - width = newwidth; - height = newheight; - } - - // make patch - rotated = R_MaskedFlatToPatch(rawconv, width, height, 0, 0, &size); - { - rotated->leftoffset = ox; - rotated->topoffset = oy; - } -#ifdef HWRENDER - if (rendermode == render_opengl) - { - hwpatch = R_CreateHardwarePatch(rotated); - } -#endif // HWRENDER - - //Z_ChangeTag(rotated, PU_PATCH_ROTATED); // important for memory clearing -#ifdef HWRENDER - if (rendermode == render_opengl) - Z_SetUser(hwpatch, (void **)(&rotsprite->patches[idx])); - else -#endif - Z_SetUser(rotated, (void **)(&rotsprite->patches[idx])); - - Z_Free(rawconv); - - //rotated->leftoffset = ox; - //rotated->topoffset = oy; - -} - -// -// R_FreeSingleRotSprite -// -// IS DEAD BECAUSE OF SIGSEG HELL -// - -// -// R_FreeSkinRotSprite -// -// Free sprite rotation data from memory, for a skin. -// Calls R_FreeSingleRotSprite. -// -/*void R_FreeSkinRotSprite(size_t skinnum) -{ - size_t i; - skin_t *skin = &skins[skinnum]; - spritedef_t *skinsprites = skin->sprites; - for (i = 0; i < NUMPLAYERSPRITES*2; i++) - { - R_FreeSingleRotSprite(skinsprites); - skinsprites++; - } -}*/ - -// -// R_FreeAllRotSprite -// -// Free ALL sprite rotation data from memory. -// -void R_FreeAllRotSprite(void) -{ - //INT32 i; - size_t s; - /*for (i = 0; i < numskins; ++i) - R_FreeSkinRotSprite(i);*/ -} -#endif +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1993-1996 by id Software, Inc. +// Copyright (C) 2005-2009 by Andrey "entryway" Budko. +// Copyright (C) 2018-2020 by Jaime "Lactozilla" Passos. +// Copyright (C) 2019-2020 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 r_patch.c +/// \brief Patch generation. + +#include "byteptr.h" +#include "dehacked.h" +#include "i_video.h" +#include "r_data.h" +#include "r_draw.h" +#include "r_patch.h" +#include "r_things.h" +#include "z_zone.h" +#include "w_wad.h" + +#ifdef HWRENDER +#include "hardware/hw_glob.h" +#endif + +static unsigned char imgbuf[1<<26]; + +// +// R_CheckIfPatch +// +// Returns true if the lump is a valid patch. +// +boolean R_CheckIfPatch(lumpnum_t lump) +{ + size_t size; + INT16 width, height; + patch_t *patch; + boolean result; + + size = W_LumpLength(lump); + + // minimum length of a valid Doom patch + if (size < 13) + return false; + + patch = (patch_t *)W_CacheLumpNum(lump, PU_STATIC); + + width = patch->width; + height = patch->height; + + result = (height > 0 && height <= 16384 && width > 0 && width <= 16384 && width < (INT16)(size / 4)); + + if (result) + { + // The dimensions seem like they might be valid for a patch, so + // check the column directory for extra security. All columns + // must begin after the column directory, and none of them must + // point past the end of the patch. + INT16 x; + + for (x = 0; x < width; x++) + { + UINT32 ofs = LONG(patch->columnofs[x]); + + // Need one byte for an empty column (but there's patches that don't know that!) + if (ofs < (UINT32)width * 4 + 8 || ofs >= (UINT32)size) + { + result = false; + break; + } + } + } + + return result; +} + +// +// R_TextureToFlat +// +// Convert a texture to a flat. +// +void R_TextureToFlat(size_t tex, UINT8 *flat) +{ + texture_t *texture = textures[tex]; + + fixed_t col, ofs; + column_t *column; + UINT8 *desttop, *dest, *deststop; + UINT8 *source; + + // yea + R_CheckTextureCache(tex); + + desttop = flat; + deststop = desttop + (texture->width * texture->height); + + for (col = 0; col < texture->width; col++, desttop++) + { + // no post_t info + if (!texture->holes) + { + column = (column_t *)(R_GetColumn(tex, col)); + source = (UINT8 *)(column); + dest = desttop; + for (ofs = 0; dest < deststop && ofs < texture->height; ofs++) + { + if (source[ofs] != TRANSPARENTPIXEL) + *dest = source[ofs]; + dest += texture->width; + } + } + else + { + INT32 topdelta, prevdelta = -1; + column = (column_t *)((UINT8 *)R_GetColumn(tex, col) - 3); + while (column->topdelta != 0xff) + { + topdelta = column->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + + dest = desttop + (topdelta * texture->width); + source = (UINT8 *)column + 3; + for (ofs = 0; dest < deststop && ofs < column->length; ofs++) + { + if (source[ofs] != TRANSPARENTPIXEL) + *dest = source[ofs]; + dest += texture->width; + } + column = (column_t *)((UINT8 *)column + column->length + 4); + } + } + } +} + +// +// R_PatchToFlat +// +// Convert a patch to a flat. +// +void R_PatchToFlat(patch_t *patch, UINT8 *flat) +{ + fixed_t col, ofs; + column_t *column; + UINT8 *desttop, *dest, *deststop; + UINT8 *source; + + desttop = flat; + deststop = desttop + (SHORT(patch->width) * SHORT(patch->height)); + + for (col = 0; col < SHORT(patch->width); col++, desttop++) + { + INT32 topdelta, prevdelta = -1; + column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[col])); + + while (column->topdelta != 0xff) + { + topdelta = column->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + + dest = desttop + (topdelta * SHORT(patch->width)); + source = (UINT8 *)(column) + 3; + for (ofs = 0; dest < deststop && ofs < column->length; ofs++) + { + *dest = source[ofs]; + dest += SHORT(patch->width); + } + column = (column_t *)((UINT8 *)column + column->length + 4); + } + } +} + +// +// R_PatchToMaskedFlat +// +// Convert a patch to a masked flat. +// Now, what is a "masked" flat anyway? +// It means the flat uses two bytes to store image data. +// The upper byte is used to store the transparent pixel, +// and the lower byte stores a palette index. +// +void R_PatchToMaskedFlat(patch_t *patch, UINT16 *raw, boolean flip) +{ + fixed_t col, ofs; + column_t *column; + UINT16 *desttop, *dest, *deststop; + UINT8 *source; + + desttop = raw; + deststop = desttop + (SHORT(patch->width) * SHORT(patch->height)); + + for (col = 0; col < SHORT(patch->width); col++, desttop++) + { + INT32 topdelta, prevdelta = -1; + column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[flip ? (patch->width-1-col) : col])); + while (column->topdelta != 0xff) + { + topdelta = column->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + dest = desttop + (topdelta * SHORT(patch->width)); + source = (UINT8 *)(column) + 3; + for (ofs = 0; dest < deststop && ofs < column->length; ofs++) + { + *dest = source[ofs]; + dest += SHORT(patch->width); + } + column = (column_t *)((UINT8 *)column + column->length + 4); + } + } +} + +// +// R_FlatToPatch +// +// Convert a flat to a patch. +// +patch_t *R_FlatToPatch(UINT8 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize, boolean transparency) +{ + UINT32 x, y; + UINT8 *img; + UINT8 *imgptr = imgbuf; + UINT8 *colpointers, *startofspan; + size_t size = 0; + + if (!raw) + return NULL; + + // Write image size and offset + WRITEINT16(imgptr, width); + WRITEINT16(imgptr, height); + WRITEINT16(imgptr, leftoffset); + WRITEINT16(imgptr, topoffset); + + // Leave placeholder to column pointers + colpointers = imgptr; + imgptr += width*4; + + // Write columns + for (x = 0; x < width; x++) + { + int lastStartY = 0; + int spanSize = 0; + startofspan = NULL; + + // Write column pointer + WRITEINT32(colpointers, imgptr - imgbuf); + + // Write pixels + for (y = 0; y < height; y++) + { + UINT8 paletteIndex = raw[((y * width) + x)]; + boolean opaque = transparency ? (paletteIndex != TRANSPARENTPIXEL) : true; + + // End span if we have a transparent pixel + if (!opaque) + { + if (startofspan) + WRITEUINT8(imgptr, 0); + startofspan = NULL; + continue; + } + + // Start new column if we need to + if (!startofspan || spanSize == 255) + { + int writeY = y; + + // If we reached the span size limit, finish the previous span + if (startofspan) + WRITEUINT8(imgptr, 0); + + if (y > 254) + { + // Make sure we're aligned to 254 + if (lastStartY < 254) + { + WRITEUINT8(imgptr, 254); + WRITEUINT8(imgptr, 0); + imgptr += 2; + lastStartY = 254; + } + + // Write stopgap empty spans if needed + writeY = y - lastStartY; + + while (writeY > 254) + { + WRITEUINT8(imgptr, 254); + WRITEUINT8(imgptr, 0); + imgptr += 2; + writeY -= 254; + } + } + + startofspan = imgptr; + WRITEUINT8(imgptr, writeY); + imgptr += 2; + spanSize = 0; + + lastStartY = y; + } + + // Write the pixel + WRITEUINT8(imgptr, paletteIndex); + spanSize++; + startofspan[1] = spanSize; + } + + if (startofspan) + WRITEUINT8(imgptr, 0); + + WRITEUINT8(imgptr, 0xFF); + } + + size = imgptr-imgbuf; + img = Z_Malloc(size, PU_STATIC, NULL); + memcpy(img, imgbuf, size); + + Z_Free(raw); + + if (destsize != NULL) + *destsize = size; + return (patch_t *)img; +} + +// +// R_MaskedFlatToPatch +// +// Convert a masked flat to a patch. +// Explanation of "masked" flats in R_PatchToMaskedFlat. +// +patch_t *R_MaskedFlatToPatch(UINT16 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize) +{ + UINT32 x, y; + UINT8 *img; + UINT8 *imgptr = imgbuf; + UINT8 *colpointers, *startofspan; + size_t size = 0; + + if (!raw) + return NULL; + + // Write image size and offset + WRITEINT16(imgptr, width); + WRITEINT16(imgptr, height); + WRITEINT16(imgptr, leftoffset); + WRITEINT16(imgptr, topoffset); + + // Leave placeholder to column pointers + colpointers = imgptr; + imgptr += width*4; + + // Write columns + for (x = 0; x < width; x++) + { + int lastStartY = 0; + int spanSize = 0; + startofspan = NULL; + + // Write column pointer + WRITEINT32(colpointers, imgptr - imgbuf); + + // Write pixels + for (y = 0; y < height; y++) + { + UINT16 pixel = raw[((y * width) + x)]; + UINT8 paletteIndex = (pixel & 0xFF); + UINT8 opaque = (pixel != 0xFF00); // If 1, we have a pixel + + // End span if we have a transparent pixel + if (!opaque) + { + if (startofspan) + WRITEUINT8(imgptr, 0); + startofspan = NULL; + continue; + } + + // Start new column if we need to + if (!startofspan || spanSize == 255) + { + int writeY = y; + + // If we reached the span size limit, finish the previous span + if (startofspan) + WRITEUINT8(imgptr, 0); + + if (y > 254) + { + // Make sure we're aligned to 254 + if (lastStartY < 254) + { + WRITEUINT8(imgptr, 254); + WRITEUINT8(imgptr, 0); + imgptr += 2; + lastStartY = 254; + } + + // Write stopgap empty spans if needed + writeY = y - lastStartY; + + while (writeY > 254) + { + WRITEUINT8(imgptr, 254); + WRITEUINT8(imgptr, 0); + imgptr += 2; + writeY -= 254; + } + } + + startofspan = imgptr; + WRITEUINT8(imgptr, writeY); + imgptr += 2; + spanSize = 0; + + lastStartY = y; + } + + // Write the pixel + WRITEUINT8(imgptr, paletteIndex); + spanSize++; + startofspan[1] = spanSize; + } + + if (startofspan) + WRITEUINT8(imgptr, 0); + + WRITEUINT8(imgptr, 0xFF); + } + + size = imgptr-imgbuf; + img = Z_Malloc(size, PU_STATIC, NULL); + memcpy(img, imgbuf, size); + + if (destsize != NULL) + *destsize = size; + return (patch_t *)img; +} + +// +// R_ParseSpriteInfoFrame +// +// Parse a SPRTINFO frame. +// +static void R_ParseSpriteInfoFrame(spriteinfo_t *info) +{ + char *sprinfoToken; + size_t sprinfoTokenLength; + char *frameChar = NULL; + UINT8 frameFrame = 0xFF; + INT16 frameXPivot = 0; + INT16 frameYPivot = 0; + rotaxis_t frameRotAxis = 0; + + // Sprite identifier + sprinfoToken = M_GetToken(NULL); + if (sprinfoToken == NULL) + { + 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; + + frameFrame = R_Char2Frame(frameChar[0]); + Z_Free(sprinfoToken); + + // Left Curly Brace + sprinfoToken = M_GetToken(NULL); + if (sprinfoToken == NULL) + I_Error("Error parsing SPRTINFO lump: Missing sprite info"); + else + { + if (strcmp(sprinfoToken,"{")==0) + { + 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 (strcmp(sprinfoToken,"}")!=0) + { + 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"); + } + } + } + Z_Free(sprinfoToken); + } + + // set fields + info->pivot[frameFrame].x = frameXPivot; + info->pivot[frameFrame].y = frameYPivot; + info->pivot[frameFrame].rotaxis = frameRotAxis; +} + +// +// R_ParseSpriteInfo +// +// Parse a SPRTINFO lump. +// +static void R_ParseSpriteInfo(boolean spr2) +{ + spriteinfo_t *info; + char *sprinfoToken; + size_t sprinfoTokenLength; + char newSpriteName[5]; // no longer dynamically allocated + spritenum_t sprnum = NUMSPRITES; + //playersprite_t spr2num = NUMPLAYERSPRITES; + INT32 i; + INT32 skinnumbers[MAXSKINS]; // >variable 'skinnumbers' set but not used >compile error when commented out + INT32 foundskins = 0; + + // Sprite name + sprinfoToken = M_GetToken(NULL); + if (sprinfoToken == NULL) + { + I_Error("Error parsing SPRTINFO lump: Unexpected end of file where sprite name should be"); + } + sprinfoTokenLength = strlen(sprinfoToken); + if (sprinfoTokenLength != 4) + { + I_Error("Error parsing SPRTINFO lump: Sprite name \"%s\" isn't 4 characters long",sprinfoToken); + } + else + { + memset(&newSpriteName, 0, 5); + M_Memcpy(newSpriteName, sprinfoToken, sprinfoTokenLength); + // ^^ 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) + { + for (i = 0; i <= NUMSPRITES; i++) + { + if (i == NUMSPRITES) + I_Error("Error parsing SPRTINFO lump: Unknown sprite name \"%s\"", newSpriteName); + if (!memcmp(newSpriteName,sprnames[i],4)) + { + sprnum = i; + break; + } + } + } + + // allocate a spriteinfo + info = Z_Calloc(sizeof(spriteinfo_t), PU_STATIC, NULL); + info->available = true; + + // Left Curly Brace + sprinfoToken = M_GetToken(NULL); + if (sprinfoToken == NULL) + { + I_Error("Error parsing SPRTINFO lump: Unexpected end of file where open curly brace for sprite \"%s\" should be",newSpriteName); + } + if (strcmp(sprinfoToken,"{")==0) + { + 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 (strcmp(sprinfoToken,"}")!=0) + { + if (stricmp(sprinfoToken, "SKIN")==0) + { + INT32 skinnum; + char *skinName = NULL; + if (!spr2) + I_Error("Error parsing SPRTINFO lump: \"SKIN\" token found outside of a sprite2 definition"); + + Z_Free(sprinfoToken); + + // Skin name + sprinfoToken = M_GetToken(NULL); + if (sprinfoToken == NULL) + { + I_Error("Error parsing SPRTINFO lump: Unexpected end of file where skin frame should be"); + } + + // copy skin name yada yada + sprinfoTokenLength = strlen(sprinfoToken); + skinName = (char *)Z_Malloc((sprinfoTokenLength+1)*sizeof(char),PU_STATIC,NULL); + M_Memcpy(skinName,sprinfoToken,sprinfoTokenLength*sizeof(char)); + skinName[sprinfoTokenLength] = '\0'; + strlwr(skinName); + Z_Free(sprinfoToken); + + skinnum = R_SkinAvailable(skinName); + if (skinnum == -1) + I_Error("Error parsing SPRTINFO lump: Unknown skin \"%s\"", skinName); + + skinnumbers[foundskins] = skinnum; + foundskins++; + } + else if (stricmp(sprinfoToken, "FRAME")==0) + { + R_ParseSpriteInfoFrame(info); + Z_Free(sprinfoToken); + M_Memcpy(&spriteinfo[sprnum], info, sizeof(spriteinfo_t)); + } + else + { + I_Error("Error parsing SPRTINFO lump: Unknown keyword \"%s\" in sprite %s",sprinfoToken,newSpriteName); + } + + sprinfoToken = M_GetToken(NULL); + if (sprinfoToken == NULL) + { + I_Error("Error parsing SPRTINFO lump: Unexpected end of file where sprite info or right curly brace for sprite \"%s\" should be",newSpriteName); + } + } + } + else + { + I_Error("Error parsing SPRTINFO lump: Expected \"{\" for sprite \"%s\", got \"%s\"",newSpriteName,sprinfoToken); + } + Z_Free(sprinfoToken); + Z_Free(info); +} + +// +// R_ParseSPRTINFOLump +// +// Read a SPRTINFO lump. +// +void R_ParseSPRTINFOLump(UINT16 wadNum, UINT16 lumpNum) +{ + char *sprinfoLump; + size_t sprinfoLumpLength; + char *sprinfoText; + char *sprinfoToken; + + // Since lumps AREN'T \0-terminated like I'd assumed they should be, I'll + // need to make a space of memory where I can ensure that it will terminate + // correctly. Start by loading the relevant data from the WAD. + sprinfoLump = (char *)W_CacheLumpNumPwad(wadNum, lumpNum, PU_STATIC); + // If that didn't exist, we have nothing to do here. + if (sprinfoLump == NULL) return; + // If we're still here, then it DOES exist; figure out how long it is, and allot memory accordingly. + sprinfoLumpLength = W_LumpLengthPwad(wadNum, lumpNum); + sprinfoText = (char *)Z_Malloc((sprinfoLumpLength+1)*sizeof(char),PU_STATIC,NULL); + // Now move the contents of the lump into this new location. + memmove(sprinfoText,sprinfoLump,sprinfoLumpLength); + // Make damn well sure the last character in our new memory location is \0. + sprinfoText[sprinfoLumpLength] = '\0'; + // Finally, free up the memory from the first data load, because we really + // don't need it. + Z_Free(sprinfoLump); + + sprinfoToken = M_GetToken(sprinfoText); + while (sprinfoToken != NULL) + { + if (!stricmp(sprinfoToken, "SPRITE")) + R_ParseSpriteInfo(false); + else if (!stricmp(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); +} + +// +// R_LoadSpriteInfoLumps +// +// Load and read every SPRTINFO lump from the specified file. +// +void R_LoadSpriteInfoLumps(UINT16 wadnum, UINT16 numlumps) +{ + lumpinfo_t *lumpinfo = wadfiles[wadnum]->lumpinfo; + UINT16 i; + char *name; + + for (i = 0; i < numlumps; i++, lumpinfo++) + { + name = lumpinfo->name; + // Load SPRTINFO and SPR_ lumps as SpriteInfo + if (!memcmp(name, "SPRTINFO", 8) || !memcmp(name, "SPR_", 4)) + R_ParseSPRTINFOLump(wadnum, i); + } +} + +static UINT16 GetPatchPixel(patch_t *patch, INT32 x, INT32 y, boolean flip) +{ + fixed_t ofs; + column_t *column; + UINT8 *source; + + if (x >= 0 && x < SHORT(patch->width)) + { + INT32 topdelta, prevdelta = -1; + column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[flip ? (patch->width-1-x) : x])); + while (column->topdelta != 0xff) + { + topdelta = column->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + source = (UINT8 *)(column) + 3; + for (ofs = 0; ofs < column->length; ofs++) + { + if ((topdelta + ofs) == y) + return source[ofs]; + } + column = (column_t *)((UINT8 *)column + column->length + 4); + } + } + + return 0xFF00; +} + +#ifdef ROTSPRITE +// +// R_GetRollAngle +// +// Angles precalculated in R_InitSprites. +// +fixed_t rollcosang[ROTANGLES]; +fixed_t rollsinang[ROTANGLES]; + +INT32 R_GetRollAngle(angle_t rollangle) +{ + INT32 ra = AngleFixed(rollangle)>>FRACBITS; +#if (ROTANGDIFF > 1) + ra += (ROTANGDIFF/2); +#endif + ra /= ROTANGDIFF; + ra %= ROTANGLES; + return ra; +} + +patch_t *Patch_GetRotatedSprite( + spriteframe_t *sprite, + size_t frame, size_t spriteangle, + boolean flip, boolean adjustfeet, + void *info, INT32 rotationangle) +{ + rotsprite_t *rotsprite; + spriteinfo_t *sprinfo = (spriteinfo_t *)info; + INT32 idx = rotationangle; + UINT8 type = (adjustfeet ? 1 : 0); + + if (rotationangle < 1 || rotationangle >= ROTANGLES) + return NULL; + + rotsprite = sprite->rotated[type][spriteangle]; + + if (rotsprite == NULL) + { + rotsprite = RotatedPatch_Create(ROTANGLES); + sprite->rotated[type][spriteangle] = rotsprite; + } + + if (flip) + idx += rotsprite->angles; + + if (rotsprite->patches[idx] == NULL) + { + patch_t *patch; + INT32 xpivot = 0, ypivot = 0; + lumpnum_t lump = sprite->lumppat[spriteangle]; + + if (lump == LUMPERROR) + return NULL; + + patch = (patch_t *)W_CacheLumpNum(lump, PU_STATIC); + + if (sprinfo->available) + { + xpivot = sprinfo->pivot[frame].x; + ypivot = sprinfo->pivot[frame].y; + } + else + { + xpivot = patch->leftoffset; + ypivot = patch->height / 2; + } + + RotatedPatch_DoRotation(rotsprite, patch, rotationangle, xpivot, ypivot, flip); + + //BP: we cannot use special tric in hardware mode because feet in ground caused by z-buffer + if (adjustfeet) + ((patch_t *)rotsprite->patches[idx])->topoffset += FEETADJUST>>FRACBITS; + + // free image data + Z_Free(patch); + } + + return rotsprite->patches[idx]; +} + +rotsprite_t *RotatedPatch_Create(INT32 numangles) +{ + rotsprite_t *rotsprite = Z_Calloc(sizeof(rotsprite_t), PU_STATIC, NULL); + rotsprite->angles = numangles; + rotsprite->patches = Z_Calloc(rotsprite->angles * 2 * sizeof(void *), PU_STATIC, NULL); + return rotsprite; +} + +static void RotatedPatch_CalculateDimensions( + INT32 width, INT32 height, + fixed_t ca, fixed_t sa, + INT32 *newwidth, INT32 *newheight) +{ + fixed_t fixedwidth = (width * FRACUNIT); + fixed_t fixedheight = (height * FRACUNIT); + + fixed_t w1 = abs(FixedMul(fixedwidth, ca) - FixedMul(fixedheight, sa)); + fixed_t w2 = abs(FixedMul(-fixedwidth, ca) - FixedMul(fixedheight, sa)); + fixed_t h1 = abs(FixedMul(fixedwidth, sa) + FixedMul(fixedheight, ca)); + fixed_t h2 = abs(FixedMul(-fixedwidth, sa) + FixedMul(fixedheight, ca)); + + w1 = FixedInt(FixedCeil(w1 + (FRACUNIT/2))); + w2 = FixedInt(FixedCeil(w2 + (FRACUNIT/2))); + 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 patch_t *R_CreateHardwarePatch(patch_t *patch) +{ + GLPatch_t *grPatch = Z_Calloc(sizeof(GLPatch_t), PU_HWRPATCHINFO, NULL); + grPatch->mipmap = Z_Calloc(sizeof(GLMipmap_t), PU_HWRPATCHINFO, NULL); + grPatch->rawpatch = patch; + HWR_MakePatch(patch, grPatch, grPatch->mipmap, false); + return (patch_t *)grPatch; +} + +void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle, INT32 xpivot, INT32 ypivot, boolean flip) +{ + UINT32 i; + patch_t *rotated, *hwpatch; + UINT16 *rawdst, *rawconv; + size_t size; + INT32 bflip = (flip != 0x00); + + INT32 width = patch->width; + INT32 height = patch->height; + INT32 leftoffset = patch->leftoffset; + INT32 newwidth, newheight; + + fixed_t ca = rollcosang[angle]; + fixed_t sa = rollsinang[angle]; + fixed_t xcenter, ycenter; + INT32 idx = angle; + INT32 x, y; + INT32 sx, sy; + INT32 dx, dy; + INT32 ox, oy; + INT32 minx, miny, maxx, maxy; + + // Don't cache angle = 0 + if (angle < 1 || angle >= ROTANGLES) + return; + + if (flip) + { + idx += rotsprite->angles; + xpivot = width - xpivot; + leftoffset = width - leftoffset; + } + + if (rotsprite->patches[idx]) + return; + + // Find the dimensions of the rotated patch. + RotatedPatch_CalculateDimensions(width, height, ca, sa, &newwidth, &newheight); + + xcenter = (xpivot * FRACUNIT); + ycenter = (ypivot * FRACUNIT); + + if (xpivot != width / 2 || ypivot != height / 2) + { + newwidth *= 2; + newheight *= 2; + } + + minx = newwidth; + miny = newheight; + maxx = 0; + maxy = 0; + + // Draw the rotated sprite to a temporary buffer. + size = (newwidth * newheight); + if (!size) + size = (width * height); + rawdst = Z_Calloc(size * sizeof(UINT16), PU_STATIC, NULL); + + for (i = 0; i < size; i++) + rawdst[i] = 0xFF00; + + for (dy = 0; dy < newheight; dy++) + { + for (dx = 0; dx < newwidth; dx++) + { + x = (dx - (newwidth / 2)) * FRACUNIT; + y = (dy - (newheight / 2)) * FRACUNIT; + sx = FixedMul(x, ca) + FixedMul(y, sa) + xcenter; + sy = -FixedMul(x, sa) + FixedMul(y, ca) + ycenter; + + sx >>= FRACBITS; + sy >>= FRACBITS; + + if (sx >= 0 && sy >= 0 && sx < width && sy < height) + rawdst[(dy*newwidth)+dx] = GetPatchPixel(patch, sx, sy, bflip); + } + } + + ox = (newwidth / 2) + (leftoffset - xpivot); + oy = (newheight / 2) + (patch->topoffset - ypivot); + width = (maxx - minx); + height = (maxy - miny); + + if ((unsigned)(width * height) > size) + { + UINT16 *src, *dest; + + size = (width * height); + rawconv = Z_Calloc(size * sizeof(UINT16), PU_STATIC, NULL); + + src = &rawdst[(miny * newwidth) + minx]; + dest = rawconv; + dy = height; + + while (dy--) + { + M_Memcpy(dest, src, width * sizeof(UINT16)); + dest += width; + src += newwidth; + } + + ox -= minx; + oy -= miny; + + Z_Free(rawdst); + } + else + { + rawconv = rawdst; + width = newwidth; + height = newheight; + } + + // make patch + rotated = R_MaskedFlatToPatch(rawconv, width, height, 0, 0, &size); + { + rotated->leftoffset = ox; + rotated->topoffset = oy; + } +#ifdef HWRENDER + if (rendermode == render_opengl) + { + hwpatch = R_CreateHardwarePatch(rotated); + } +#endif // HWRENDER + + //Z_ChangeTag(rotated, PU_PATCH_ROTATED); // important for memory clearing +#ifdef HWRENDER + if (rendermode == render_opengl) + Z_SetUser(hwpatch, (void **)(&rotsprite->patches[idx])); + else +#endif + Z_SetUser(rotated, (void **)(&rotsprite->patches[idx])); + + Z_Free(rawconv); + + rotated->leftoffset = ox; + rotated->topoffset = oy; +} +#endif diff --git a/src/r_patch.h b/src/r_patch.h index 054e28e11..ac8072a43 100644 --- a/src/r_patch.h +++ b/src/r_patch.h @@ -1,69 +1,68 @@ -// SONIC ROBO BLAST 2 -//----------------------------------------------------------------------------- -// Copyright (C) 1993-1996 by id Software, Inc. -// Copyright (C) 2018-2019 by Jaime "Lactozilla" Passos. -// Copyright (C) 2019 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 r_patch.h -/// \brief Patch generation. - -#ifndef __R_PATCH__ -#define __R_PATCH__ - -#include "r_defs.h" -#include "doomdef.h" - -// Structs -typedef enum -{ - ROTAXIS_X, // Roll (the default) - ROTAXIS_Y, // Pitch - ROTAXIS_Z // Yaw -} rotaxis_t; - -typedef struct -{ - INT32 x, y; - rotaxis_t rotaxis; -} spriteframepivot_t; - -typedef struct -{ - spriteframepivot_t pivot[64]; - boolean available; -} spriteinfo_t; - -// Conversions between patches / flats / textures... -boolean R_CheckIfPatch(lumpnum_t lump); -void R_TextureToFlat(size_t tex, UINT8 *flat); -void R_PatchToFlat(patch_t *patch, UINT8 *flat); -void R_PatchToMaskedFlat(patch_t *patch, UINT16 *raw, boolean flip); -patch_t *R_FlatToPatch(UINT8 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize, boolean transparency); -patch_t *R_MaskedFlatToPatch(UINT16 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize); - -// SpriteInfo -extern spriteinfo_t spriteinfo[NUMSPRITES]; -void R_LoadSpriteInfoLumps(UINT16 wadnum, UINT16 numlumps); -void R_ParseSPRTINFOLump(UINT16 wadNum, UINT16 lumpNum); - -// Sprite rotation -#ifdef ROTSPRITE -INT32 R_GetRollAngle(angle_t rollangle); -patch_t *Patch_GetRotatedSprite( - spriteframe_t *sprite, - size_t frame, size_t spriteangle, - boolean flip, void *info, - INT32 rotationangle); -rotsprite_t *RotatedPatch_Create(INT32 numangles); -void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle, INT32 xpivot, INT32 ypivot, UINT8 flip); -//void R_FreeSkinRotSprite(size_t skinnum); -extern fixed_t rollcosang[ROTANGLES]; -extern fixed_t rollsinang[ROTANGLES]; -void R_FreeAllRotSprite(void); -#endif - -#endif // __R_PATCH__ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1993-1996 by id Software, Inc. +// Copyright (C) 2018-2019 by Jaime "Lactozilla" Passos. +// Copyright (C) 2019 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 r_patch.h +/// \brief Patch generation. + +#ifndef __R_PATCH__ +#define __R_PATCH__ + +#include "r_defs.h" +#include "doomdef.h" + +// Structs +typedef enum +{ + ROTAXIS_X, // Roll (the default) + ROTAXIS_Y, // Pitch + ROTAXIS_Z // Yaw +} rotaxis_t; + +typedef struct +{ + INT32 x, y; + rotaxis_t rotaxis; +} spriteframepivot_t; + +typedef struct +{ + spriteframepivot_t pivot[64]; + boolean available; +} spriteinfo_t; + +// Conversions between patches / flats / textures... +boolean R_CheckIfPatch(lumpnum_t lump); +void R_TextureToFlat(size_t tex, UINT8 *flat); +void R_PatchToFlat(patch_t *patch, UINT8 *flat); +void R_PatchToMaskedFlat(patch_t *patch, UINT16 *raw, boolean flip); +patch_t *R_FlatToPatch(UINT8 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize, boolean transparency); +patch_t *R_MaskedFlatToPatch(UINT16 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize); + +// SpriteInfo +extern spriteinfo_t spriteinfo[NUMSPRITES]; +void R_LoadSpriteInfoLumps(UINT16 wadnum, UINT16 numlumps); +void R_ParseSPRTINFOLump(UINT16 wadNum, UINT16 lumpNum); + +// Sprite rotation +#ifdef ROTSPRITE +INT32 R_GetRollAngle(angle_t rollangle); +patch_t *Patch_GetRotatedSprite( + spriteframe_t *sprite, + size_t frame, size_t spriteangle, + boolean flip, boolean adjustfeet, + void *info, INT32 rotationangle); +rotsprite_t *RotatedPatch_Create(INT32 numangles); +void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle, INT32 xpivot, INT32 ypivot, boolean flip); + +extern fixed_t rollcosang[ROTANGLES]; +extern fixed_t rollsinang[ROTANGLES]; +#endif + +#endif // __R_PATCH__ diff --git a/src/r_things.c b/src/r_things.c index 26dad2f0b..66c583259 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1373,7 +1373,7 @@ static void R_ProjectSprite(mobj_t *thing) rollsum = (thing->rollangle) + (thing->sloperoll); rollangle = R_GetRollAngle(rollsum); - rotsprite = Patch_GetRotatedSprite(sprframe, (thing->frame & FF_FRAMEMASK), rot, flip, sprinfo, rollangle); + rotsprite = Patch_GetRotatedSprite(sprframe, (thing->frame & FF_FRAMEMASK), rot, flip, false, sprinfo, rollangle); if (rotsprite != NULL) { -- 2.54.0