Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • 21-installer-nodd
  • 2210-pre1
  • 2210-pre2
  • 2210-rc1
  • 2210-rc2
  • 2210-rc3
  • 2211-pre1
  • 2211-pre2
  • 2211-rc1
  • 2212-pre1
  • 2212-pre2
  • 2212-pre3
  • 2212-rc1
  • 2213
  • 2214-pre1
  • 2214-pre2
  • 2214-pre3
  • 2214-pre4
  • 2_2_12
  • 64-gl-log
  • COM_ImmedExecute-lua
  • DJGPP
  • accel-momentum
  • acs
  • action-args
  • alpha-fixes
  • any-resolution
  • appveyor
  • better-distance-math
  • blend-locking
  • blentran
  • blua-unary-not-fix
  • boost-tickrate
  • bustablesoundz
  • classic-netcode-fixes
  • cleanup-opengl
  • cleanupmusic
  • clipmidtex
  • cmake-valgrind
  • crawlacommander-sprites
  • custom-map-names
  • custom-teams
  • cutscene-cleanup
  • dd-music-bypass
  • dd-music-fix
  • delfile2
  • deprecate-lua-dedicated-server
  • dpl-2
  • dropshadows-spawning
  • dynabsp
  • emblem-drawing
  • exchndl-xp-fix
  • extra-textures
  • few-kart-lua-changes
  • ffloorclip
  • fix-167
  • fix-cvar-conflicts
  • fix-dedi-pthread
  • fix-enemy-target
  • fix-opengl-parameter-crash
  • fix-opengl-shear-roll
  • flipfuncpointers
  • fof-lightlist-fixes
  • font-FUCK
  • frictionrefactor
  • fuck-macros-1
  • gamepad-luakeydown
  • gamepad-morefixes
  • gamepad_experiments
  • gametype-refactor
  • gametype-refactor-1
  • gametype-refactor-player-spawns
  • ghost-networking
  • gif-splitting
  • grr-lj
  • hitboxviewer
  • hwr-texture-cache-refactor
  • hwrender2
  • improve-439
  • increase-maxconditionsets
  • increase-packet-tics
  • input-display
  • input-display-translucency
  • io
  • joystick-juggling-maz
  • just-in-case
  • keycodes-only
  • ksf-wadfiles
  • ld413-mp-fix
  • levelstruct
  • libpng-version-support
  • linedef-actions
  • lj-test
  • lol-states
  • loopedsounds
  • lower-unpegged-fix
  • lua-change-gametype
  • lua-command-netids
  • lua-gfx-2
  • lua-gfx-sprites
  • SRB2_release_2.1
  • SRB2_release_2.1.1
  • SRB2_release_2.1.10
  • SRB2_release_2.1.11
  • SRB2_release_2.1.12
  • SRB2_release_2.1.14
  • SRB2_release_2.1.15
  • SRB2_release_2.1.16
  • SRB2_release_2.1.16a
  • SRB2_release_2.1.17
  • SRB2_release_2.1.18
  • SRB2_release_2.1.19
  • SRB2_release_2.1.2
  • SRB2_release_2.1.20
  • SRB2_release_2.1.21
  • SRB2_release_2.1.22
  • SRB2_release_2.1.23
  • SRB2_release_2.1.24
  • SRB2_release_2.1.25
  • SRB2_release_2.1.3
  • SRB2_release_2.1.4
  • SRB2_release_2.1.5
  • SRB2_release_2.1.6
  • SRB2_release_2.1.7
  • SRB2_release_2.1.8
  • SRB2_release_2.1.9
  • SRB2_release_2.2.0
  • SRB2_release_2.2.1
  • SRB2_release_2.2.10
  • SRB2_release_2.2.11
  • SRB2_release_2.2.12
  • SRB2_release_2.2.13
  • SRB2_release_2.2.15
  • SRB2_release_2.2.2
  • SRB2_release_2.2.3
  • SRB2_release_2.2.4
  • SRB2_release_2.2.5
  • SRB2_release_2.2.6
  • SRB2_release_2.2.7
  • SRB2_release_2.2.8
  • SRB2_release_2.2.9
  • td-release-v1.0.0
142 results

Target

Select target project
  • STJr/SRB2
  • Sryder/SRB2
  • wolfy852/SRB2
  • Alpha2244/SRB2
  • Inuyasha/SRB2
  • yoshibot/SRB2
  • TehRealSalt/SRB2
  • PrisimaTF/SRB2
  • Hatninja/SRB2
  • SteelT/SRB2
  • james/SRB2
  • ShaderWraith/SRB2
  • SinnamonLat/SRB2
  • mazmazz_/SRB2
  • filpAM/SRB2
  • chaoloveicemdboy/SRB2
  • Whooa21/SRB2
  • Machturne/SRB2
  • Golden/SRB2
  • Tatsuru/SRB2
  • Snu/SRB2
  • Zwip-Zwap_Zapony/SRB2
  • fickleheart/SRB2
  • alphaRexJames/SRB2
  • JJK/SRB2
  • diskpoppy/SRB2
  • Hannu_Hanhi/SRB2
  • ZipperQR/SRB2
  • kays/SRB2
  • spherallic/SRB2
  • Zippy_Zolton/SRB2
  • namiishere/SRB2
  • Ors/SRB2
  • SMS_Alfredo/SRB2
  • sonic_edge/SRB2
  • lavla/SRB2
  • ashi/SRB2
  • X.organic/SRB2
  • Fafabis/SRB2
  • Meziu/SRB2
  • v-rob/SRB2
  • tertu/SRB2
  • bitten2up/SRB2
  • flarn2006/SRB2
  • Krabs/SRB2
  • clairebun/SRB2
  • Lactozilla/SRB2
  • thehackstack/SRB2
  • Spice/SRB2
  • win8linux/SRB2
  • JohnFrostFox/SRB2
  • talktoneon726/SRB2
  • Wane/SRB2
  • Lamibe/SRB2
  • spectrumuk2/srb-2
  • nerdyminer18/srb-2
  • 256nil/SRB2
  • ARJr/SRB2
  • Alam/SRB2
  • Zenya/srb-2-marathon-demos
  • Acelite/srb-2-archivedmodifications
  • MIDIMan/SRB2
  • Lach/SRB2
  • Frostiikin/bounce-tweaks
  • Jaden/SRB2
  • Tyron/SRB2
  • Astronight/SRB2
  • Mari0shi06/SRB2
  • aiire/SRB2
  • Galactice/SRB2
  • srb2-ports/srb2-dreamcast
  • sdasdas/SRB2
  • chreas/srb-2-vr
  • StarManiaKG/the-story-of-sinically-rocketing-and-botching-the-2nd
  • LoganAir/SRB2
  • NepDisk/srb-2
  • alufolie91/SRB2
  • Felicia.iso/SRB2
  • twi/SRB2
  • BarrelsOFun/SRB2
  • Speed2411/SRB2
  • Leather_Realms/SRB2
  • Ayemar/SRB2
  • Acelite/SRB2
  • VladDoc/SRB2
  • kaldrum/model-features
  • strawberryfox417/SRB2
  • Lugent/SRB2
  • Rem/SRB2
  • Refrag/SRB2
  • Henry_3230/srb-3230
  • TehPuertoRicanSpartan2/tprs-srb2
  • Leminn/srb-2-marathon-stuff
  • chromaticpipe2/SRB2
  • MiguelGustavo15/SRB2
  • Maru/srb-2-tests
  • SilicDev/SRB2
  • UnmatchedBracket/SRB2
  • HybridDog/SRB2
  • xordspar0/SRB2
  • jsjhbewfhh/SRB2
  • Fancy2209/SRB2
  • Lorsoen/SRB2
  • shindoukin/SRB2
  • GamerOfDays/SRB2
  • Craftyawesome/SRB2
  • tenshi-tensai-tennoji/SRB2
  • Scarfdudebalder/SRB2
  • luigi-budd/srb-2-fix-interplag-lockon
  • mskluesner/SRB2
  • johnpetersa19/SRB2
  • Pheazant/SRB2
  • chromaticpipe2/srb2classic
  • romoney5/SRB2
  • PAS/SRB2Classic
  • BlueStaggo/SRB2
  • Jisk/srb-2-beef-jerky
  • voltybystorm/SRB2
  • ZenithNeko/srb-2-xp
  • Nep2Disk/SRB2
  • Cloudeon/SRB2
  • mushe/srb-2-ps-b
122 results
Select Git revision
  • 21-installer-nodd
  • 2210-pre1
  • 2210-pre2
  • 2210-rc1
  • 2210-rc2
  • 2210-rc3
  • 2211-pre1
  • 2211-pre2
  • 2211-rc1
  • 2212-pre1
  • 2212-pre2
  • 2212-pre3
  • 2212-rc1
  • 2213
  • 2_2_12
  • 64-gl-log
  • COM_ImmedExecute-lua
  • DJGPP
  • accel-momentum
  • action-args
  • alpha-fixes
  • any-resolution
  • appveyor
  • better-player-states
  • blend-locking
  • blentran
  • blua-unary-not-fix
  • boost-tickrate
  • bustablesoundz
  • cleanup-opengl
  • cleanupmusic
  • cmake-valgrind
  • crawlacommander-sprites
  • custom-map-names
  • custom-teams
  • cutscene-cleanup
  • dd-music-bypass
  • dd-music-fix
  • delfile2
  • deprecate-lua-dedicated-server
  • dpl-2
  • dropshadows-spawning
  • dynabsp
  • emblem-drawing
  • exchndl-xp-fix
  • few-kart-lua-changes
  • ffloorclip
  • fix-1215
  • fix-167
  • fix-cvar-conflicts
  • fix-equation-slopes-near-edges
  • fix-opengl-shear-roll
  • flipfuncpointers
  • fof-lightlist-fixes
  • font-FUCK
  • frictionrefactor
  • fuck-macros-1
  • gamepad-luakeydown
  • gamepad-morefixes
  • gamepad_experiments
  • gametype-refactor
  • gametype-refactor-1
  • gametype-refactor-player-spawns
  • ghost-networking
  • gif-splitting
  • gitlab-ci
  • grr-lj
  • hitboxviewer
  • hwr-texture-cache-refactor
  • hwrender2
  • improve-439
  • increase-packet-tics
  • input-display
  • input-display-translucency
  • io
  • joystick-juggling-maz
  • keycodes-only
  • ksf-wadfiles
  • ld413-mp-fix
  • levelstruct
  • libpng-version-support
  • linedef-actions
  • lj-test
  • lol-states
  • loopedsounds
  • lower-unpegged-fix
  • lua-change-gametype
  • lua-command-netids
  • lua-debug-library
  • lua-gfx-2
  • lua-gfx-sprites
  • lua-local
  • makefile-auto-mingw-gcc
  • makefile-tinkering
  • map-components-signedness-fixes
  • master
  • menu-edits
  • mobj-dispoffset
  • more-cleanup
  • movie
  • SRB2_release_2.1
  • SRB2_release_2.1.1
  • SRB2_release_2.1.10
  • SRB2_release_2.1.11
  • SRB2_release_2.1.12
  • SRB2_release_2.1.14
  • SRB2_release_2.1.15
  • SRB2_release_2.1.16
  • SRB2_release_2.1.16a
  • SRB2_release_2.1.17
  • SRB2_release_2.1.18
  • SRB2_release_2.1.19
  • SRB2_release_2.1.2
  • SRB2_release_2.1.20
  • SRB2_release_2.1.21
  • SRB2_release_2.1.22
  • SRB2_release_2.1.23
  • SRB2_release_2.1.24
  • SRB2_release_2.1.25
  • SRB2_release_2.1.3
  • SRB2_release_2.1.4
  • SRB2_release_2.1.5
  • SRB2_release_2.1.6
  • SRB2_release_2.1.7
  • SRB2_release_2.1.8
  • SRB2_release_2.1.9
  • SRB2_release_2.2.0
  • SRB2_release_2.2.1
  • SRB2_release_2.2.10
  • SRB2_release_2.2.11
  • SRB2_release_2.2.12
  • SRB2_release_2.2.13
  • SRB2_release_2.2.2
  • SRB2_release_2.2.3
  • SRB2_release_2.2.4
  • SRB2_release_2.2.5
  • SRB2_release_2.2.6
  • SRB2_release_2.2.7
  • SRB2_release_2.2.8
  • SRB2_release_2.2.9
  • td-release-v1.0.0
141 results
Show changes
...@@ -48,7 +48,7 @@ typedef struct visplane_s ...@@ -48,7 +48,7 @@ typedef struct visplane_s
UINT16 padbottomstart, bottom[MAXVIDWIDTH], padbottomend; UINT16 padbottomstart, bottom[MAXVIDWIDTH], padbottomend;
INT32 high, low; // R_PlaneBounds should set these. INT32 high, low; // R_PlaneBounds should set these.
fixed_t xoffs, yoffs; // Scrolling flats. INT64 xoffs, yoffs; // Scrolling flats.
fixed_t xscale, yscale; fixed_t xscale, yscale;
sector_t *sector; sector_t *sector;
...@@ -85,7 +85,7 @@ void R_DrawSinglePlane(visplane_t *pl); ...@@ -85,7 +85,7 @@ void R_DrawSinglePlane(visplane_t *pl);
// Calculates the slope vectors needed for tilted span drawing. // Calculates the slope vectors needed for tilted span drawing.
void R_SetSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle); void R_SetSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle);
void R_SetScaledSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xs, fixed_t ys, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle); void R_SetScaledSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xs, fixed_t ys, INT64 xoff, INT64 yoff, angle_t angle, angle_t plangle);
typedef struct planemgr_s typedef struct planemgr_s
{ {
......
...@@ -101,7 +101,7 @@ void Portal_ClipApply (const portal_t* portal) ...@@ -101,7 +101,7 @@ void Portal_ClipApply (const portal_t* portal)
static portal_t* Portal_Add (const INT16 x1, const INT16 x2) static portal_t* Portal_Add (const INT16 x1, const INT16 x2)
{ {
portal_t *portal = Z_Malloc(sizeof(portal_t), PU_LEVEL, NULL); portal_t *portal = Z_Calloc(sizeof(portal_t), PU_LEVEL, NULL);
INT16 *ceilingclipsave = Z_Malloc(sizeof(INT16)*(x2-x1 + 1), PU_LEVEL, NULL); INT16 *ceilingclipsave = Z_Malloc(sizeof(INT16)*(x2-x1 + 1), PU_LEVEL, NULL);
INT16 *floorclipsave = Z_Malloc(sizeof(INT16)*(x2-x1 + 1), PU_LEVEL, NULL); INT16 *floorclipsave = Z_Malloc(sizeof(INT16)*(x2-x1 + 1), PU_LEVEL, NULL);
fixed_t *frontscalesave = Z_Malloc(sizeof(fixed_t)*(x2-x1 + 1), PU_LEVEL, NULL); fixed_t *frontscalesave = Z_Malloc(sizeof(fixed_t)*(x2-x1 + 1), PU_LEVEL, NULL);
...@@ -117,7 +117,7 @@ static portal_t* Portal_Add (const INT16 x1, const INT16 x2) ...@@ -117,7 +117,7 @@ static portal_t* Portal_Add (const INT16 x1, const INT16 x2)
portal_cap->next = portal; portal_cap->next = portal;
portal_cap = portal; portal_cap = portal;
} }
portal->next = NULL; portal->clipline = -1;
// Store clipping values so they can be restored once the portal is rendered. // Store clipping values so they can be restored once the portal is rendered.
portal->ceilingclip = ceilingclipsave; portal->ceilingclip = ceilingclipsave;
...@@ -142,11 +142,9 @@ void Portal_Remove (portal_t* portal) ...@@ -142,11 +142,9 @@ void Portal_Remove (portal_t* portal)
Z_Free(portal); Z_Free(portal);
} }
static void Portal_GetViewpointForLine(portal_t *portal, line_t *start, line_t *dest) static void Portal_GetViewpointForLine(portal_t *portal, line_t *start, line_t *dest, angle_t dangle)
{ {
// Offset the portal view by the linedef centers // Offset the portal view by the linedef centers
angle_t dangle = R_PointToAngle2(0,0,dest->dx,dest->dy) - R_PointToAngle2(start->dx,start->dy,0,0);
fixed_t disttopoint; fixed_t disttopoint;
angle_t angtopoint; angle_t angtopoint;
...@@ -168,7 +166,6 @@ static void Portal_GetViewpointForLine(portal_t *portal, line_t *start, line_t * ...@@ -168,7 +166,6 @@ static void Portal_GetViewpointForLine(portal_t *portal, line_t *start, line_t *
portal->viewx = dest_c.x + FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint); portal->viewx = dest_c.x + FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
portal->viewy = dest_c.y + FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint); portal->viewy = dest_c.y + FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
portal->viewz = viewz + dest->frontsector->floorheight - start->frontsector->floorheight;
portal->viewangle = viewangle + dangle; portal->viewangle = viewangle + dangle;
} }
...@@ -189,12 +186,13 @@ void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, con ...@@ -189,12 +186,13 @@ void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, con
line_t* start = &lines[line1]; line_t* start = &lines[line1];
line_t* dest = &lines[line2]; line_t* dest = &lines[line2];
Portal_GetViewpointForLine(portal, start, dest); angle_t dangle = R_PointToAngle2(0,0,dest->dx,dest->dy) - R_PointToAngle2(start->dx,start->dy,0,0);
Portal_GetViewpointForLine(portal, start, dest, dangle);
portal->viewz = viewz + dest->frontsector->floorheight - start->frontsector->floorheight;
portal->clipline = line2; portal->clipline = line2;
portal->is_skybox = false;
portal->is_horizon = false;
portal->horizon_sector = NULL;
Portal_ClipRange(portal); Portal_ClipRange(portal);
...@@ -317,10 +315,7 @@ static boolean Portal_AddSkybox (const visplane_t* plane) ...@@ -317,10 +315,7 @@ static boolean Portal_AddSkybox (const visplane_t* plane)
Portal_ClipVisplane(plane, portal); Portal_ClipVisplane(plane, portal);
portal->clipline = -1;
portal->is_skybox = true; portal->is_skybox = true;
portal->is_horizon = false;
portal->horizon_sector = NULL;
Portal_GetViewpointForSkybox(portal); Portal_GetViewpointForSkybox(portal);
...@@ -332,14 +327,28 @@ static void Portal_GetViewpointForSecPortal(portal_t *portal, sectorportal_t *se ...@@ -332,14 +327,28 @@ static void Portal_GetViewpointForSecPortal(portal_t *portal, sectorportal_t *se
fixed_t x, y, z; fixed_t x, y, z;
angle_t angle; angle_t angle;
sector_t *target = secportal->target;
fixed_t target_x = target->soundorg.x;
fixed_t target_y = target->soundorg.y;
fixed_t target_z;
if (secportal->ceiling)
target_z = P_GetSectorCeilingZAt(target, target_x, target_y);
else
target_z = P_GetSectorFloorZAt(target, target_x, target_y);
switch (secportal->type) switch (secportal->type)
{ {
case SECPORTAL_LINE: case SECPORTAL_LINE:
Portal_GetViewpointForLine(portal, secportal->line.start, secportal->line.dest); angle = secportal->line.dest->angle - secportal->line.start->angle;
Portal_GetViewpointForLine(portal, secportal->line.start, secportal->line.dest, angle);
portal->viewz = viewz; // Apparently it just works like that. Not going to question it.
return; return;
case SECPORTAL_OBJECT: case SECPORTAL_OBJECT:
if (!secportal->mobj || P_MobjWasRemoved(secportal->mobj)) if (P_MobjWasRemoved(secportal->mobj))
return; return;
portal->viewmobj = secportal->mobj;
x = secportal->mobj->x; x = secportal->mobj->x;
y = secportal->mobj->y; y = secportal->mobj->y;
z = secportal->mobj->z; z = secportal->mobj->z;
...@@ -373,8 +382,9 @@ static void Portal_GetViewpointForSecPortal(portal_t *portal, sectorportal_t *se ...@@ -373,8 +382,9 @@ static void Portal_GetViewpointForSecPortal(portal_t *portal, sectorportal_t *se
return; return;
} }
fixed_t refx = secportal->origin.x - viewx; fixed_t refx = target_x - viewx;
fixed_t refy = secportal->origin.y - viewy; fixed_t refy = target_y - viewy;
fixed_t refz = target_z - viewz;
// Rotate the X/Y to match the target angle // Rotate the X/Y to match the target angle
if (angle != 0) if (angle != 0)
...@@ -387,7 +397,7 @@ static void Portal_GetViewpointForSecPortal(portal_t *portal, sectorportal_t *se ...@@ -387,7 +397,7 @@ static void Portal_GetViewpointForSecPortal(portal_t *portal, sectorportal_t *se
portal->viewx = x - refx; portal->viewx = x - refx;
portal->viewy = y - refy; portal->viewy = y - refy;
portal->viewz = z + viewz; portal->viewz = z - refz;
portal->viewangle = angle + viewangle; portal->viewangle = angle + viewangle;
} }
...@@ -413,11 +423,6 @@ static boolean Portal_AddSectorPortal (const visplane_t* plane) ...@@ -413,11 +423,6 @@ static boolean Portal_AddSectorPortal (const visplane_t* plane)
Portal_ClipVisplane(plane, portal); Portal_ClipVisplane(plane, portal);
portal->clipline = -1;
portal->is_horizon = false;
portal->is_skybox = false;
portal->horizon_sector = NULL;
Portal_GetViewpointForSecPortal(portal, secportal); Portal_GetViewpointForSecPortal(portal, secportal);
return true; return true;
...@@ -425,7 +430,7 @@ static boolean Portal_AddSectorPortal (const visplane_t* plane) ...@@ -425,7 +430,7 @@ static boolean Portal_AddSectorPortal (const visplane_t* plane)
/** Creates a transferred sector portal. /** Creates a transferred sector portal.
*/ */
void Portal_AddTransferred (UINT32 secportalnum, const INT32 x1, const INT32 x2) void Portal_AddTransferred (const UINT32 secportalnum, const INT32 x1, const INT32 x2)
{ {
if (secportalnum >= secportalcount) if (secportalnum >= secportalcount)
return; return;
...@@ -435,9 +440,6 @@ void Portal_AddTransferred (UINT32 secportalnum, const INT32 x1, const INT32 x2) ...@@ -435,9 +440,6 @@ void Portal_AddTransferred (UINT32 secportalnum, const INT32 x1, const INT32 x2)
return; return;
portal_t* portal = Portal_Add(x1, x2); portal_t* portal = Portal_Add(x1, x2);
portal->is_skybox = false;
portal->is_horizon = false;
portal->horizon_sector = NULL;
if (secportal->type == SECPORTAL_SKYBOX) if (secportal->type == SECPORTAL_SKYBOX)
Portal_GetViewpointForSkybox(portal); Portal_GetViewpointForSkybox(portal);
......
...@@ -36,6 +36,8 @@ typedef struct portal_s ...@@ -36,6 +36,8 @@ typedef struct portal_s
boolean is_skybox; boolean is_skybox;
mobj_t *viewmobj;
UINT8 pass; /**< Keeps track of the portal's recursion depth. */ UINT8 pass; /**< Keeps track of the portal's recursion depth. */
INT32 clipline; /**< Optional clipline for line-based portals. */ INT32 clipline; /**< Optional clipline for line-based portals. */
...@@ -58,7 +60,7 @@ extern INT32 portalclipstart, portalclipend; ...@@ -58,7 +60,7 @@ extern INT32 portalclipstart, portalclipend;
void Portal_InitList (void); void Portal_InitList (void);
void Portal_Remove (portal_t* portal); void Portal_Remove (portal_t* portal);
void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, const INT32 x2); void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, const INT32 x2);
void Portal_AddTransferred (UINT32 secportalnum, const INT32 x1, const INT32 x2); void Portal_AddTransferred (const UINT32 secportalnum, const INT32 x1, const INT32 x2);
void Portal_ClipRange (portal_t* portal); void Portal_ClipRange (portal_t* portal);
void Portal_ClipApply (const portal_t* portal); void Portal_ClipApply (const portal_t* portal);
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include "r_sky.h" #include "r_sky.h"
#include "r_portal.h" #include "r_portal.h"
#include "r_splats.h"
#include "w_wad.h" #include "w_wad.h"
#include "z_zone.h" #include "z_zone.h"
...@@ -75,6 +74,8 @@ static fixed_t *maskedtextureheight = NULL; ...@@ -75,6 +74,8 @@ static fixed_t *maskedtextureheight = NULL;
static fixed_t *thicksidecol = NULL; static fixed_t *thicksidecol = NULL;
static fixed_t *invscale = NULL; static fixed_t *invscale = NULL;
static boolean texcoltables;
//SoM: 3/23/2000: Use boom opening limit removal //SoM: 3/23/2000: Use boom opening limit removal
static size_t numopenings; static size_t numopenings;
static INT16 *openings, *lastopening; static INT16 *openings, *lastopening;
...@@ -88,15 +89,129 @@ void R_ClearSegTables(void) ...@@ -88,15 +89,129 @@ void R_ClearSegTables(void)
curtexturecolumntable = texturecolumntable; curtexturecolumntable = texturecolumntable;
} }
// ==========================================================================
// R_RenderMaskedSegRange
// ==========================================================================
transnum_t R_GetLinedefTransTable(fixed_t alpha) transnum_t R_GetLinedefTransTable(fixed_t alpha)
{ {
return (20*(FRACUNIT - alpha - 1) + FRACUNIT) >> (FRACBITS+1); return (20*(FRACUNIT - alpha - 1) + FRACUNIT) >> (FRACBITS+1);
} }
static UINT8 R_SideLightLevel(side_t *side, INT16 base_lightlevel)
{
return max(0, min(255, side->light +
((side->lightabsolute) ? 0 : base_lightlevel)));
}
/* TODO: implement per-texture lighting
static UINT8 R_TopLightLevel(side_t *side, INT16 base_lightlevel)
{
return max(0, min(255, side->light_top +
((side->lightabsolute_top) ? 0 : R_SideLightLevel(side, base_lightlevel))));
}
static UINT8 R_MidLightLevel(side_t *side, INT16 base_lightlevel)
{
return max(0, min(255, side->light_mid +
((side->lightabsolute_mid) ? 0 : R_SideLightLevel(side, base_lightlevel))));
}
static UINT8 R_BottomLightLevel(side_t *side, INT16 base_lightlevel)
{
return max(0, min(255, side->light_bottom +
((side->lightabsolute_bottom) ? 0 : R_SideLightLevel(side, base_lightlevel))));
}
*/
// If we have a multi-patch texture on a 2sided wall (rare) then we draw
// it using R_DrawColumn, else we draw it using R_DrawMaskedColumn, this
// way we don't have to store extra post_t info with each column for
// multi-patch textures. They are not normally needed as multi-patch
// textures don't have holes in it. At least not for now.
static void R_Render2sidedMultiPatchColumn(column_t *column, unsigned lengthcol)
{
INT32 topscreen, bottomscreen;
post_t *post = &column->posts[0];
if (!post->length)
return;
topscreen = sprtopscreen;
bottomscreen = topscreen + spryscale * lengthcol;
dc_yl = (sprtopscreen+FRACUNIT-1)>>FRACBITS;
dc_yh = (bottomscreen-1)>>FRACBITS;
if (windowtop != INT32_MAX && windowbottom != INT32_MAX)
{
dc_yl = ((windowtop + FRACUNIT)>>FRACBITS);
dc_yh = (windowbottom - 1)>>FRACBITS;
}
if (dc_yh >= mfloorclip[dc_x])
dc_yh = mfloorclip[dc_x] - 1;
if (dc_yl <= mceilingclip[dc_x])
dc_yl = mceilingclip[dc_x] + 1;
if (dc_yl >= vid.height || dc_yh < 0)
return;
if (dc_yl <= dc_yh && dc_yh < vid.height && dc_yh > 0)
{
dc_source = column->pixels + post->data_offset;
dc_postlength = post->length;
if (colfunc == colfuncs[BASEDRAWFUNC])
(colfuncs[COLDRAWFUNC_TWOSMULTIPATCH])();
else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY])
(colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS])();
else
colfunc();
}
}
static void R_RenderFlipped2sidedMultiPatchColumn(column_t *column, unsigned lengthcol)
{
INT32 topscreen, bottomscreen;
void (*localcolfunc)(void);
post_t *post = &column->posts[0];
if (!post->length)
return;
topscreen = sprtopscreen;
bottomscreen = topscreen + spryscale * lengthcol;
dc_yl = (sprtopscreen+FRACUNIT-1)>>FRACBITS;
dc_yh = (bottomscreen-1)>>FRACBITS;
if (windowtop != INT32_MAX && windowbottom != INT32_MAX)
{
dc_yl = ((windowtop + FRACUNIT)>>FRACBITS);
dc_yh = (windowbottom - 1)>>FRACBITS;
}
if (dc_yh >= mfloorclip[dc_x])
dc_yh = mfloorclip[dc_x] - 1;
if (dc_yl <= mceilingclip[dc_x])
dc_yl = mceilingclip[dc_x] + 1;
if (dc_yl >= vid.height || dc_yh < 0)
return;
if (dc_yl <= dc_yh && dc_yh < vid.height && dc_yh > 0)
{
dc_postlength = post->length;
if (colfunc == colfuncs[BASEDRAWFUNC])
localcolfunc = colfuncs[COLDRAWFUNC_TWOSMULTIPATCH];
else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY])
localcolfunc = colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS];
else
localcolfunc = colfunc;
R_DrawFlippedPost(column->pixels + post->data_offset, post->length, localcolfunc);
}
}
void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
{ {
size_t pindex; size_t pindex;
...@@ -111,10 +226,12 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) ...@@ -111,10 +226,12 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
INT32 times, repeats; INT32 times, repeats;
INT64 overflow_test; INT64 overflow_test;
INT32 range; INT32 range;
UINT8 vertflip;
unsigned lengthcol; unsigned lengthcol;
if (!cv_renderwalls.value) fixed_t wall_scaley;
return; fixed_t scalestep;
fixed_t scale1;
// Calculate light table. // Calculate light table.
// Use different light tables // Use different light tables
...@@ -163,9 +280,17 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) ...@@ -163,9 +280,17 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
colfunc = colfuncs[COLDRAWFUNC_FUZZY]; colfunc = colfuncs[COLDRAWFUNC_FUZZY];
} }
fixed_t wall_scaley = sidedef->scaley_mid; vertflip = textures[texnum]->flip & 2;
fixed_t scalestep = FixedDiv(ds->scalestep, wall_scaley);
fixed_t scale1 = FixedDiv(ds->scale1, wall_scaley); wall_scaley = sidedef->scaley_mid;
if (wall_scaley < 0)
{
wall_scaley = -wall_scaley;
vertflip = !vertflip;
}
scalestep = FixedDiv(ds->scalestep, wall_scaley);
scale1 = FixedDiv(ds->scale1, wall_scaley);
range = max(ds->x2-ds->x1, 1); range = max(ds->x2-ds->x1, 1);
rw_scalestep = scalestep; rw_scalestep = scalestep;
...@@ -174,7 +299,16 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) ...@@ -174,7 +299,16 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
// Texture must be cached // Texture must be cached
R_CheckTextureCache(texnum); R_CheckTextureCache(texnum);
if (textures[texnum]->flip & 2) // vertically flipped? // handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures
// are not stored per-column with post info in SRB2
if (!textures[texnum]->transparency)
{
if (vertflip) // vertically flipped?
colfunc_2s = R_RenderFlipped2sidedMultiPatchColumn;
else
colfunc_2s = R_Render2sidedMultiPatchColumn;
}
else if (vertflip) // vertically flipped?
colfunc_2s = R_DrawFlippedMaskedColumn; colfunc_2s = R_DrawFlippedMaskedColumn;
else else
colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture
...@@ -216,7 +350,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) ...@@ -216,7 +350,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
if ((colfunc != colfuncs[COLDRAWFUNC_FUZZY]) if ((colfunc != colfuncs[COLDRAWFUNC_FUZZY])
|| (rlight->flags & FOF_FOG) || (rlight->flags & FOF_FOG)
|| (rlight->extra_colormap && (rlight->extra_colormap->flags & CMF_FOG))) || (rlight->extra_colormap && (rlight->extra_colormap->flags & CMF_FOG)))
lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT); lightnum = R_SideLightLevel(curline->sidedef, rlight->lightlevel) >> LIGHTSEGSHIFT;
else else
lightnum = LIGHTLEVELS - 1; lightnum = LIGHTLEVELS - 1;
...@@ -234,7 +368,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) ...@@ -234,7 +368,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
{ {
if ((colfunc != colfuncs[COLDRAWFUNC_FUZZY]) if ((colfunc != colfuncs[COLDRAWFUNC_FUZZY])
|| (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG))) || (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG)))
lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); lightnum = R_SideLightLevel(curline->sidedef, frontsector->lightlevel) >> LIGHTSEGSHIFT;
else else
lightnum = LIGHTLEVELS - 1; lightnum = LIGHTLEVELS - 1;
...@@ -435,26 +569,75 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) ...@@ -435,26 +569,75 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
} }
// Loop through R_DrawMaskedColumn calls // Loop through R_DrawMaskedColumn calls
static fixed_t repeatscroll = 0;
static void R_DrawRepeatMaskedColumn(column_t *col, unsigned lengthcol) static void R_DrawRepeatMaskedColumn(column_t *col, unsigned lengthcol)
{ {
while (sprtopscreen < sprbotscreen) { fixed_t topscreen = sprtopscreen;
fixed_t bottomscreen = sprbotscreen;
fixed_t texheight = dc_texheight*spryscale;
fixed_t scroll = -repeatscroll;
if (scroll < 0)
{
scroll = -FixedMul((abs(scroll) % (dc_texheight*FRACUNIT)), spryscale);
bottomscreen += texheight; // Draw an extra time
}
else if (scroll)
{
scroll = FixedMul(scroll % (dc_texheight*FRACUNIT), spryscale);
topscreen -= texheight; // Draw an extra time
}
while (topscreen < bottomscreen)
{
sprtopscreen = topscreen + scroll;
R_DrawMaskedColumn(col, lengthcol); R_DrawMaskedColumn(col, lengthcol);
if ((INT64)sprtopscreen + (INT64)dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow if ((INT64)sprtopscreen + (INT64)dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow
sprtopscreen = INT32_MAX; break;
else
sprtopscreen += dc_texheight*spryscale; topscreen += texheight;
} }
sprtopscreen = sprbotscreen;
} }
static void R_DrawRepeatFlippedMaskedColumn(column_t *col, unsigned lengthcol) static void R_DrawRepeatFlippedMaskedColumn(column_t *col, unsigned lengthcol)
{ {
while (sprtopscreen < sprbotscreen) { fixed_t topscreen = sprtopscreen;
fixed_t bottomscreen = sprbotscreen;
fixed_t texheight = dc_texheight*spryscale;
fixed_t scroll = -repeatscroll;
if (scroll < 0)
{
scroll = -FixedMul((abs(scroll) % (dc_texheight*FRACUNIT)), spryscale);
bottomscreen += texheight; // Draw an extra time
}
else if (scroll)
{
scroll = FixedMul(scroll % (dc_texheight*FRACUNIT), spryscale);
topscreen -= texheight; // Draw an extra time
}
while (topscreen < bottomscreen)
{
sprtopscreen = topscreen + scroll;
sprbotscreen = bottomscreen + scroll;
R_DrawFlippedMaskedColumn(col, lengthcol); R_DrawFlippedMaskedColumn(col, lengthcol);
if ((INT64)sprtopscreen + (INT64)dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow if ((INT64)sprtopscreen + (INT64)dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow
sprtopscreen = INT32_MAX; break;
else
sprtopscreen += dc_texheight*spryscale; topscreen += texheight;
} }
sprtopscreen = sprbotscreen;
} }
// Returns true if a fake floor is translucent. // Returns true if a fake floor is translucent.
...@@ -470,6 +653,11 @@ static boolean R_IsFFloorTranslucent(visffloor_t *pfloor) ...@@ -470,6 +653,11 @@ static boolean R_IsFFloorTranslucent(visffloor_t *pfloor)
return false; return false;
} }
static fixed_t R_GetSlopeTextureSlide(pslope_t *slope, angle_t lineangle)
{
return FixedMul(slope->zdelta, FINECOSINE((lineangle-slope->xydirection)>>ANGLETOFINESHIFT));
}
// //
// R_RenderThickSideRange // R_RenderThickSideRange
// Renders all the thick sides in the given range. // Renders all the thick sides in the given range.
...@@ -485,7 +673,6 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) ...@@ -485,7 +673,6 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
sector_t tempsec; sector_t tempsec;
INT32 templight; INT32 templight;
INT32 i, p; INT32 i, p;
fixed_t offsetvalue;
lightlist_t *light; lightlist_t *light;
r_lightlist_t *rlight; r_lightlist_t *rlight;
INT32 range; INT32 range;
...@@ -494,19 +681,20 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) ...@@ -494,19 +681,20 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
INT64 top_frac, top_step, bottom_frac, bottom_step; INT64 top_frac, top_step, bottom_frac, bottom_step;
// skew FOF walls with slopes? // skew FOF walls with slopes?
fixed_t ffloortextureslide = 0; fixed_t ffloortextureslide = 0;
INT32 oldx = -1; fixed_t oldtexturecolumn = -1;
fixed_t left_top, left_bottom; // needed here for slope skewing fixed_t left_top, left_bottom; // needed here for slope skewing
pslope_t *skewslope = NULL; pslope_t *skewslope = NULL;
boolean do_texture_skew; boolean do_texture_skew;
boolean dont_peg_bottom; boolean dont_peg_bottom;
fixed_t wall_offsetx;
fixed_t wall_scalex, wall_scaley; fixed_t wall_scalex, wall_scaley;
UINT8 vertflip;
unsigned lengthcol; unsigned lengthcol;
boolean fog = false;
boolean fuzzy = false;
void (*colfunc_2s) (column_t *, unsigned); void (*colfunc_2s) (column_t *, unsigned);
if (!cv_renderwalls.value)
return;
// Calculate light table. // Calculate light table.
// Use different light tables // Use different light tables
// for horizontal / vertical / diagonal. Diagonal? // for horizontal / vertical / diagonal. Diagonal?
...@@ -515,15 +703,11 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) ...@@ -515,15 +703,11 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
curline = ds->curline; curline = ds->curline;
backsector = pfloor->target; backsector = pfloor->target;
frontsector = curline->frontsector == pfloor->target ? curline->backsector : curline->frontsector; frontsector = curline->frontsector == pfloor->target ? curline->backsector : curline->frontsector;
sidedef = &sides[pfloor->master->sidenum[0]]; sidedef = R_GetFFloorSide(curline->linedef, pfloor, pfloor->target);
colfunc = colfuncs[BASEDRAWFUNC];
if (pfloor->master->flags & ML_TFERLINE) if (pfloor->master->flags & ML_TFERLINE)
{ {
size_t linenum = curline->linedef-backsector->lines[0]; line_t *newline = R_GetFFloorLine(curline->linedef, pfloor, pfloor->target);
line_t *newline = pfloor->master->frontsector->lines[0] + linenum;
sidedef = &sides[newline->sidenum[0]];
do_texture_skew = newline->flags & ML_SKEWTD; do_texture_skew = newline->flags & ML_SKEWTD;
dont_peg_bottom = newline->flags & ML_DONTPEGBOTTOM; dont_peg_bottom = newline->flags & ML_DONTPEGBOTTOM;
} }
...@@ -534,10 +718,11 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) ...@@ -534,10 +718,11 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
} }
texnum = R_GetTextureNum(sidedef->midtexture); texnum = R_GetTextureNum(sidedef->midtexture);
vertflip = textures[texnum]->flip & 2;
if (pfloor->fofflags & FOF_TRANSLUCENT) if (pfloor->fofflags & FOF_TRANSLUCENT)
{ {
boolean fuzzy = true; fuzzy = true;
// Hacked up support for alpha value in software mode Tails 09-24-2002 // Hacked up support for alpha value in software mode Tails 09-24-2002
// ...unhacked by toaster 04-01-2021, re-hacked a little by sphere 19-11-2021 // ...unhacked by toaster 04-01-2021, re-hacked a little by sphere 19-11-2021
...@@ -550,17 +735,14 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) ...@@ -550,17 +735,14 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
else if (!(dc_transmap = R_GetTranslucencyTable(trans)) || trans == 0) else if (!(dc_transmap = R_GetTranslucencyTable(trans)) || trans == 0)
fuzzy = false; // Opaque fuzzy = false; // Opaque
} }
if (fuzzy)
colfunc = colfuncs[COLDRAWFUNC_FUZZY];
} }
else if (pfloor->fofflags & FOF_FOG) else if (pfloor->fofflags & FOF_FOG)
{
colfunc = colfuncs[COLDRAWFUNC_FOG]; colfunc = colfuncs[COLDRAWFUNC_FOG];
fog = true;
}
range = max(ds->x2-ds->x1, 1); range = max(ds->x2-ds->x1, 1);
//SoM: Moved these up here so they are available for my lightlist calculations
rw_scalestep = ds->scalestep;
spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep;
dc_numlights = 0; dc_numlights = 0;
if (frontsector->numlights) if (frontsector->numlights)
...@@ -642,9 +824,9 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) ...@@ -642,9 +824,9 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
// Check if the current light effects the colormap/lightlevel // Check if the current light effects the colormap/lightlevel
if (pfloor->fofflags & FOF_FOG) if (pfloor->fofflags & FOF_FOG)
rlight->lightnum = (pfloor->master->frontsector->lightlevel >> LIGHTSEGSHIFT); rlight->lightnum = R_SideLightLevel(curline->sidedef, pfloor->master->frontsector->lightlevel) >> LIGHTSEGSHIFT;
else else
rlight->lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT); rlight->lightnum = R_SideLightLevel(curline->sidedef, rlight->lightlevel) >> LIGHTSEGSHIFT;
if (pfloor->fofflags & FOF_FOG || rlight->flags & FOF_FOG || (rlight->extra_colormap && (rlight->extra_colormap->flags & CMF_FOG))) if (pfloor->fofflags & FOF_FOG || rlight->flags & FOF_FOG || (rlight->extra_colormap && (rlight->extra_colormap->flags & CMF_FOG)))
; ;
...@@ -662,14 +844,13 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) ...@@ -662,14 +844,13 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
{ {
// Get correct light level! // Get correct light level!
if ((frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG))) if ((frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG)))
lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); lightnum = R_SideLightLevel(curline->sidedef, frontsector->lightlevel) >> LIGHTSEGSHIFT;
else if (pfloor->fofflags & FOF_FOG) else if (fog)
lightnum = (pfloor->master->frontsector->lightlevel >> LIGHTSEGSHIFT); lightnum = R_SideLightLevel(curline->sidedef, pfloor->master->frontsector->lightlevel) >> LIGHTSEGSHIFT;
else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY]) else if (fuzzy)
lightnum = LIGHTLEVELS-1; lightnum = LIGHTLEVELS-1;
else else
lightnum = R_FakeFlat(frontsector, &tempsec, &templight, &templight, false) lightnum = R_SideLightLevel(curline->sidedef, R_FakeFlat(frontsector, &tempsec, &templight, &templight, false)->lightlevel) >> LIGHTSEGSHIFT;
->lightlevel >> LIGHTSEGSHIFT;
if (pfloor->fofflags & FOF_FOG || (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG))); if (pfloor->fofflags & FOF_FOG || (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG)));
else if (curline->v1->y == curline->v2->y) else if (curline->v1->y == curline->v2->y)
...@@ -687,18 +868,33 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) ...@@ -687,18 +868,33 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
wall_scalex = FixedDiv(FRACUNIT, sidedef->scalex_mid); wall_scalex = FixedDiv(FRACUNIT, sidedef->scalex_mid);
wall_scaley = sidedef->scaley_mid; wall_scaley = sidedef->scaley_mid;
if (wall_scaley < 0)
{
wall_scaley = -wall_scaley;
vertflip = !vertflip;
}
//SoM: Moved these up here so they are available for my lightlist calculations
// Lactozilla: Moved them back down
// This uses floating point math now, because the fixed-point imprecisions
// become more severe the bigger the texture is scaled.
double dwall_scaley = FixedToDouble(wall_scaley);
double scalestep = FixedToDouble(ds->scalestep) / dwall_scaley;
double yscale = (FixedToDouble(ds->scale1) + (x1 - ds->x1)*scalestep) / dwall_scaley;
thicksidecol = ffloortexturecolumn; thicksidecol = ffloortexturecolumn;
wall_offsetx = ds->offsetx + sidedef->offsetx_mid;
if (wall_scalex == FRACUNIT) if (wall_scalex == FRACUNIT)
{ {
for (INT32 x = x1; x <= x2; x++) for (INT32 x = x1; x <= x2; x++)
thicksidecol[x] = ds->thicksidecol[x] + ds->offsetx; thicksidecol[x] = ds->thicksidecol[x];
} }
else else
{ {
for (INT32 x = x1; x <= x2; x++) for (INT32 x = x1; x <= x2; x++)
thicksidecol[x] = FixedDiv(ds->thicksidecol[x], wall_scalex) + ds->offsetx; thicksidecol[x] = FixedDiv(ds->thicksidecol[x], wall_scalex);
} }
mfloorclip = ds->sprbottomclip; mfloorclip = ds->sprbottomclip;
...@@ -717,7 +913,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) ...@@ -717,7 +913,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
else else
dc_texturemid = FixedMul(*pfloor->topheight - viewz, wall_scaley); dc_texturemid = FixedMul(*pfloor->topheight - viewz, wall_scaley);
offsetvalue = sidedef->rowoffset + sidedef->offsety_mid; repeatscroll = sidedef->rowoffset + sidedef->offsety_mid;
if (dont_peg_bottom) if (dont_peg_bottom)
{ {
...@@ -727,21 +923,30 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) ...@@ -727,21 +923,30 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
dc_texturemid = FixedMul(left_bottom, wall_scaley); dc_texturemid = FixedMul(left_bottom, wall_scaley);
} }
else else
offsetvalue -= FixedMul(*pfloor->topheight - *pfloor->bottomheight, wall_scaley); repeatscroll -= FixedMul(*pfloor->topheight - *pfloor->bottomheight, wall_scaley);
} }
if (skewslope) if (skewslope)
{ {
angle_t lineangle = R_PointToAngle2(curline->v1->x, curline->v1->y, curline->v2->x, curline->v2->y); angle_t lineangle = R_PointToAngle2(curline->v1->x, curline->v1->y, curline->v2->x, curline->v2->y);
ffloortextureslide = FixedMul(skewslope->zdelta, FINECOSINE((lineangle-skewslope->xydirection)>>ANGLETOFINESHIFT)); ffloortextureslide = FixedMul(R_GetSlopeTextureSlide(skewslope, lineangle), wall_scaley);
} }
dc_texturemid += offsetvalue; dc_texturemid += repeatscroll;
// Texture must be cached // Texture must be cached
R_CheckTextureCache(texnum); R_CheckTextureCache(texnum);
if (textures[texnum]->flip & 2) // vertically flipped? // handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures
// are not stored per-column with post info in SRB2
if (!textures[texnum]->transparency)
{
if (vertflip) // vertically flipped?
colfunc_2s = R_RenderFlipped2sidedMultiPatchColumn;
else
colfunc_2s = R_Render2sidedMultiPatchColumn;
}
else if (vertflip) // vertically flipped?
colfunc_2s = R_DrawRepeatFlippedMaskedColumn; colfunc_2s = R_DrawRepeatFlippedMaskedColumn;
else else
colfunc_2s = R_DrawRepeatMaskedColumn; colfunc_2s = R_DrawRepeatMaskedColumn;
...@@ -775,9 +980,9 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) ...@@ -775,9 +980,9 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
// skew FOF walls // skew FOF walls
if (ffloortextureslide) if (ffloortextureslide)
{ {
if (oldx != -1) if (oldtexturecolumn != -1)
dc_texturemid += FixedMul(ffloortextureslide, thicksidecol[oldx]-thicksidecol[dc_x]); dc_texturemid += FixedMul(ffloortextureslide, oldtexturecolumn-ds->thicksidecol[dc_x]);
oldx = dc_x; oldtexturecolumn = ds->thicksidecol[dc_x];
} }
// Calculate bounds // Calculate bounds
...@@ -807,14 +1012,40 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) ...@@ -807,14 +1012,40 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
rlight->botheight += rlight->botheightstep; rlight->botheight += rlight->botheightstep;
} }
} }
spryscale += rw_scalestep; yscale += scalestep;
continue; continue;
} }
dc_iscale = FixedMul(0xffffffffu / (unsigned)spryscale, wall_scaley);
// Get data for the column // Get data for the column
col = R_GetColumn(texnum, (thicksidecol[dc_x] >> FRACBITS)); col = R_GetColumn(texnum, ((thicksidecol[dc_x] + wall_offsetx) >> FRACBITS));
spryscale = DoubleToFixed(yscale);
// Eh. I tried fixing the scaling artifacts but it still wasn't perfect.
// So this checks if the column has gaps in it or not, and if it does, uses a version of the column drawers
// that prevents the artifacts from being visible.
// Note that if rendering fog then none of this matters because there's no texture mapping to be done
if (!fog)
{
dc_iscale = 0xffffffffu / (unsigned)spryscale;
// Column has a single post and it matches the texture height, use regular column drawers
if (col->num_posts == 1 && col->posts[0].topdelta == 0 && col->posts[0].length == (unsigned)dc_texheight)
{
if (fuzzy)
colfunc = colfuncs[COLDRAWFUNC_FUZZY];
else
colfunc = colfuncs[BASEDRAWFUNC];
}
else
{
// Otherwise use column drawers with extra checks
if (fuzzy)
colfunc = colfuncs[COLDRAWFUNC_CLAMPEDTRANS];
else
colfunc = colfuncs[COLDRAWFUNC_CLAMPED];
}
}
// SoM: New code does not rely on R_DrawColumnShadowed_8 which // SoM: New code does not rely on R_DrawColumnShadowed_8 which
// will (hopefully) put less strain on the stack. // will (hopefully) put less strain on the stack.
...@@ -930,7 +1161,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) ...@@ -930,7 +1161,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
if (windowtop < windowbottom) if (windowtop < windowbottom)
colfunc_2s (col, lengthcol); colfunc_2s (col, lengthcol);
spryscale += rw_scalestep; yscale += scalestep;
continue; continue;
} }
...@@ -949,7 +1180,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) ...@@ -949,7 +1180,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
// draw the texture // draw the texture
colfunc_2s (col, lengthcol); colfunc_2s (col, lengthcol);
spryscale += rw_scalestep; yscale += scalestep;
} }
colfunc = colfuncs[BASEDRAWFUNC]; colfunc = colfuncs[BASEDRAWFUNC];
...@@ -988,17 +1219,24 @@ static boolean R_FFloorCanClip(visffloor_t *pfloor) ...@@ -988,17 +1219,24 @@ static boolean R_FFloorCanClip(visffloor_t *pfloor)
#define HEIGHTBITS 12 #define HEIGHTBITS 12
#define HEIGHTUNIT (1<<HEIGHTBITS) #define HEIGHTUNIT (1<<HEIGHTBITS)
static void R_DrawRegularWall(UINT8 *source, INT32 height)
{
dc_source = source;
dc_texheight = height;
colfunc();
}
//profile stuff --------------------------------------------------------- static void R_DrawFlippedWall(UINT8 *source, INT32 height)
//#define TIMING {
#ifdef TIMING dc_texheight = height;
#include "p5prof.h" R_DrawFlippedPost(source, (unsigned)height, colfunc);
INT64 mycount; }
INT64 mytotal = 0;
UINT32 nombre = 100000; static void R_DrawNoWall(UINT8 *source, INT32 height)
//static char runtest[10][80]; {
#endif (void)source;
//profile stuff --------------------------------------------------------- (void)height;
}
static void R_RenderSegLoop (void) static void R_RenderSegLoop (void)
{ {
...@@ -1019,6 +1257,40 @@ static void R_RenderSegLoop (void) ...@@ -1019,6 +1257,40 @@ static void R_RenderSegLoop (void)
INT32 bottom; INT32 bottom;
INT32 i; INT32 i;
fixed_t topscaley = rw_toptexturescaley;
fixed_t midscaley = rw_midtexturescaley;
fixed_t bottomscaley = rw_bottomtexturescaley;
void (*drawtop)(UINT8 *, INT32) = R_DrawRegularWall;
void (*drawmiddle)(UINT8 *, INT32) = R_DrawRegularWall;
void (*drawbottom)(UINT8 *, INT32) = R_DrawRegularWall;
if (dc_numlights)
colfunc = colfuncs[COLDRAWFUNC_SHADOWED];
if (toptexture && topscaley < 0)
{
topscaley = -topscaley;
drawtop = R_DrawFlippedWall;
}
if (midtexture && midscaley < 0)
{
midscaley = -midscaley;
drawmiddle = R_DrawFlippedWall;
}
if (bottomtexture && bottomscaley < 0)
{
bottomscaley = -bottomscaley;
drawbottom = R_DrawFlippedWall;
}
if (!r_renderwalls)
{
drawtop = R_DrawNoWall;
drawmiddle = R_DrawNoWall;
drawbottom = R_DrawNoWall;
}
if (midtexture) if (midtexture)
R_CheckTextureCache(midtexture); R_CheckTextureCache(midtexture);
if (toptexture) if (toptexture)
...@@ -1216,7 +1488,7 @@ static void R_RenderSegLoop (void) ...@@ -1216,7 +1488,7 @@ static void R_RenderSegLoop (void)
for (i = 0; i < dc_numlights; i++) for (i = 0; i < dc_numlights; i++)
{ {
INT32 lightnum; INT32 lightnum;
lightnum = (dc_lightlist[i].lightlevel >> LIGHTSEGSHIFT); lightnum = R_SideLightLevel(curline->sidedef, dc_lightlist[i].lightlevel) >> LIGHTSEGSHIFT;
if (dc_lightlist[i].extra_colormap) if (dc_lightlist[i].extra_colormap)
; ;
...@@ -1251,33 +1523,15 @@ static void R_RenderSegLoop (void) ...@@ -1251,33 +1523,15 @@ static void R_RenderSegLoop (void)
{ {
// single sided line // single sided line
if (yl <= yh && yh >= 0 && yl < viewheight) if (yl <= yh && yh >= 0 && yl < viewheight)
{
if (cv_renderwalls.value)
{ {
fixed_t offset = texturecolumn + rw_offsetx; fixed_t offset = texturecolumn + rw_offsetx;
dc_yl = yl; dc_yl = yl;
dc_yh = yh; dc_yh = yh;
dc_texturemid = rw_midtexturemid; dc_texturemid = rw_midtexturemid;
dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, rw_midtexturescaley);
dc_source = R_GetColumn(midtexture, offset >> FRACBITS)->pixels;
dc_texheight = textureheight[midtexture]>>FRACBITS; dc_texheight = textureheight[midtexture]>>FRACBITS;
dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, midscaley);
//profile stuff --------------------------------------------------------- drawmiddle(R_GetColumn(midtexture, offset >> FRACBITS)->pixels, dc_texheight);
#ifdef TIMING
ProfZeroTimer();
#endif
colfunc();
#ifdef TIMING
RDMSR(0x10,&mycount);
mytotal += mycount; //64bit add
if (nombre--==0)
I_Error("R_DrawColumn CPU Spy reports: 0x%d %d\n", *((INT32 *)&mytotal+1),
(INT32)mytotal);
#endif
//profile stuff ---------------------------------------------------------
}
// dont draw anything more for this column, since // dont draw anything more for this column, since
// a midtexture blocks the view // a midtexture blocks the view
...@@ -1320,8 +1574,6 @@ static void R_RenderSegLoop (void) ...@@ -1320,8 +1574,6 @@ static void R_RenderSegLoop (void)
ceilingclip[rw_x] = (INT16)viewheight; ceilingclip[rw_x] = (INT16)viewheight;
} }
else if (mid >= 0) // safe to draw top texture else if (mid >= 0) // safe to draw top texture
{
if (cv_renderwalls.value)
{ {
fixed_t offset = rw_offset_top; fixed_t offset = rw_offset_top;
if (rw_toptexturescalex < 0) if (rw_toptexturescalex < 0)
...@@ -1331,11 +1583,9 @@ static void R_RenderSegLoop (void) ...@@ -1331,11 +1583,9 @@ static void R_RenderSegLoop (void)
dc_yl = yl; dc_yl = yl;
dc_yh = mid; dc_yh = mid;
dc_texturemid = rw_toptexturemid; dc_texturemid = rw_toptexturemid;
dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, rw_toptexturescaley);
dc_source = R_GetColumn(toptexture, offset >> FRACBITS)->pixels;
dc_texheight = textureheight[toptexture]>>FRACBITS; dc_texheight = textureheight[toptexture]>>FRACBITS;
colfunc(); dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, topscaley);
} drawtop(R_GetColumn(toptexture, offset >> FRACBITS)->pixels, dc_texheight);
ceilingclip[rw_x] = (INT16)mid; ceilingclip[rw_x] = (INT16)mid;
} }
else if (!rw_ceilingmarked) // entirely off top of screen else if (!rw_ceilingmarked) // entirely off top of screen
...@@ -1345,8 +1595,8 @@ static void R_RenderSegLoop (void) ...@@ -1345,8 +1595,8 @@ static void R_RenderSegLoop (void)
ceilingclip[rw_x] = topclip; ceilingclip[rw_x] = topclip;
if (oldtexturecolumn_top != -1) if (oldtexturecolumn_top != -1)
rw_toptexturemid += FixedMul(rw_toptextureslide, oldtexturecolumn_top-toptexturecolumn); rw_toptexturemid += FixedMul(rw_toptextureslide, oldtexturecolumn_top-textureoffset);
oldtexturecolumn_top = toptexturecolumn; oldtexturecolumn_top = textureoffset;
} }
else if (markceiling && (!rw_ceilingmarked)) // no top wall else if (markceiling && (!rw_ceilingmarked)) // no top wall
ceilingclip[rw_x] = topclip; ceilingclip[rw_x] = topclip;
...@@ -1371,8 +1621,6 @@ static void R_RenderSegLoop (void) ...@@ -1371,8 +1621,6 @@ static void R_RenderSegLoop (void)
floorclip[rw_x] = -1; floorclip[rw_x] = -1;
} }
else if (mid < viewheight) // safe to draw bottom texture else if (mid < viewheight) // safe to draw bottom texture
{
if (cv_renderwalls.value)
{ {
fixed_t offset = rw_offset_bottom; fixed_t offset = rw_offset_bottom;
if (rw_bottomtexturescalex < 0) if (rw_bottomtexturescalex < 0)
...@@ -1382,11 +1630,9 @@ static void R_RenderSegLoop (void) ...@@ -1382,11 +1630,9 @@ static void R_RenderSegLoop (void)
dc_yl = mid; dc_yl = mid;
dc_yh = yh; dc_yh = yh;
dc_texturemid = rw_bottomtexturemid; dc_texturemid = rw_bottomtexturemid;
dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, rw_bottomtexturescaley);
dc_source = R_GetColumn(bottomtexture, offset >> FRACBITS)->pixels;
dc_texheight = textureheight[bottomtexture]>>FRACBITS; dc_texheight = textureheight[bottomtexture]>>FRACBITS;
colfunc(); dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, bottomscaley);
} drawbottom(R_GetColumn(bottomtexture, offset >> FRACBITS)->pixels, dc_texheight);
floorclip[rw_x] = (INT16)mid; floorclip[rw_x] = (INT16)mid;
} }
else if (!rw_floormarked) // entirely off bottom of screen else if (!rw_floormarked) // entirely off bottom of screen
...@@ -1396,8 +1642,8 @@ static void R_RenderSegLoop (void) ...@@ -1396,8 +1642,8 @@ static void R_RenderSegLoop (void)
floorclip[rw_x] = bottomclip; floorclip[rw_x] = bottomclip;
if (oldtexturecolumn_bottom != -1) if (oldtexturecolumn_bottom != -1)
rw_bottomtexturemid += FixedMul(rw_bottomtextureslide, oldtexturecolumn_bottom-bottomtexturecolumn); rw_bottomtexturemid += FixedMul(rw_bottomtextureslide, oldtexturecolumn_bottom-textureoffset);
oldtexturecolumn_bottom = bottomtexturecolumn; oldtexturecolumn_bottom = textureoffset;
} }
else if (markfloor && (!rw_floormarked)) // no bottom wall else if (markfloor && (!rw_floormarked)) // no bottom wall
floorclip[rw_x] = bottomclip; floorclip[rw_x] = bottomclip;
...@@ -1421,11 +1667,14 @@ static void R_RenderSegLoop (void) ...@@ -1421,11 +1667,14 @@ static void R_RenderSegLoop (void)
{ {
if (oldtexturecolumn != -1) if (oldtexturecolumn != -1)
{ {
rw_midtexturemid += FixedMul(rw_midtextureslide, oldtexturecolumn-texturecolumn); INT32 diff = oldtexturecolumn-textureoffset;
rw_midtextureback += FixedMul(rw_midtexturebackslide, oldtexturecolumn-texturecolumn); if (rw_invmidtexturescalex < 0)
diff = -diff;
rw_midtexturemid += FixedMul(rw_midtextureslide, diff);
rw_midtextureback += FixedMul(rw_midtexturebackslide, diff);
} }
oldtexturecolumn = texturecolumn; oldtexturecolumn = textureoffset;
} }
if (invscale) if (invscale)
...@@ -1464,6 +1713,70 @@ static void R_RenderSegLoop (void) ...@@ -1464,6 +1713,70 @@ static void R_RenderSegLoop (void)
} }
} }
static void R_MarkSegBounds(void)
{
INT32 top, bottom;
INT16 topclip, bottomclip;
for (; rw_x < rw_stopx; rw_x++)
{
// mark floor / ceiling areas
INT32 yl = (topfrac+HEIGHTUNIT-1)>>HEIGHTBITS;
INT32 yh = bottomfrac>>HEIGHTBITS;
// Mark ceiling
top = ceilingclip[rw_x]+1;
// no space above wall?
if (yl < top)
yl = top;
if (markceiling)
{
if (yl > floorclip[rw_x])
bottom = floorclip[rw_x] - 1;
else
bottom = yl - 1;
if (ceilingplane && top <= bottom)
R_ExpandPlaneY(ceilingplane, rw_x, top, bottom);
}
// Mark floor
bottom = floorclip[rw_x]-1;
// no space below floor?
if (yh > bottom)
yh = bottom;
if (markfloor)
{
if (yh < ceilingclip[rw_x])
top = ceilingclip[rw_x] + 1;
else
top = yh + 1;
if (floorplane && top <= bottom)
R_ExpandPlaneY(floorplane, rw_x, top, bottom);
}
frontscale[rw_x] = rw_scale;
topclip = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1;
bottomclip = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight;
if (markceiling) // no top wall
ceilingclip[rw_x] = topclip;
if (markfloor) // no bottom wall
floorclip[rw_x] = bottomclip;
rw_scale += rw_scalestep;
topfrac += topstep;
bottomfrac += bottomstep;
}
}
// Uses precalculated seg->length // Uses precalculated seg->length
static INT64 R_CalcSegDist(seg_t* seg, INT64 x2, INT64 y2) static INT64 R_CalcSegDist(seg_t* seg, INT64 x2, INT64 y2)
{ {
...@@ -1519,7 +1832,7 @@ static void R_AllocClippingTables(size_t range) ...@@ -1519,7 +1832,7 @@ static void R_AllocClippingTables(size_t range)
static void R_AllocTextureColumnTables(size_t range) static void R_AllocTextureColumnTables(size_t range)
{ {
size_t pos = curtexturecolumntable - texturecolumntable; size_t pos = curtexturecolumntable - texturecolumntable;
size_t need = range * 3; size_t need = range * 4;
if (pos + need < texturecolumntablesize) if (pos + need < texturecolumntablesize)
return; return;
...@@ -1540,13 +1853,46 @@ static void R_AllocTextureColumnTables(size_t range) ...@@ -1540,13 +1853,46 @@ static void R_AllocTextureColumnTables(size_t range)
for (drawseg_t *ds = drawsegs; ds < ds_p; ds++) for (drawseg_t *ds = drawsegs; ds < ds_p; ds++)
{ {
// Check if it's in range of the tables // Check if it's in range of the tables
if (ds->maskedtexturecol + ds->x1 >= oldtable && ds->maskedtexturecol + ds->x1 <= oldlast) #define CHECK(which) \
ds->maskedtexturecol = (ds->maskedtexturecol - oldtable) + texturecolumntable; if (which + ds->x1 >= oldtable && which + ds->x1 <= oldlast) \
if (ds->thicksidecol + ds->x1 >= oldtable && ds->thicksidecol + ds->x1 <= oldlast) which = (which - oldtable) + texturecolumntable
ds->thicksidecol = (ds->thicksidecol - oldtable) + texturecolumntable;
if (ds->invscale + ds->x1 >= oldtable && ds->invscale + ds->x1 <= oldlast) CHECK(ds->maskedtexturecol);
ds->invscale = (ds->invscale - oldtable) + texturecolumntable; CHECK(ds->maskedtextureheight);
CHECK(ds->thicksidecol);
CHECK(ds->invscale);
#undef CHECK
}
}
//
// R_ScaleFromGlobalAngle
// Returns the texture mapping scale for the current line (horizontal span)
// at the given angle.
// rw_distance must be calculated first.
//
// killough 5/2/98: reformatted, cleaned up
//
// note: THIS IS USED ONLY FOR WALLS!
static fixed_t R_ScaleFromGlobalAngle(angle_t visangle)
{
angle_t anglea = ANGLE_90 + (visangle-viewangle);
angle_t angleb = ANGLE_90 + (visangle-rw_normalangle);
fixed_t den = FixedMul(rw_distance, FINESINE(anglea>>ANGLETOFINESHIFT));
// proff 11/06/98: Changed for high-res
fixed_t num = FixedMul(projectiony, FINESINE(angleb>>ANGLETOFINESHIFT));
if (den > num>>16)
{
num = FixedDiv(num, den);
if (num > 64*FRACUNIT)
return 64*FRACUNIT;
if (num < 256)
return 256;
return num;
} }
return 64*FRACUNIT;
} }
// //
...@@ -1720,11 +2066,14 @@ void R_StoreWallRange(INT32 start, INT32 stop) ...@@ -1720,11 +2066,14 @@ void R_StoreWallRange(INT32 start, INT32 stop)
midtexture = toptexture = bottomtexture = maskedtexture = 0; midtexture = toptexture = bottomtexture = maskedtexture = 0;
ds_p->maskedtexturecol = NULL; ds_p->maskedtexturecol = NULL;
ds_p->maskedtextureheight = NULL;
ds_p->numthicksides = numthicksides = 0; ds_p->numthicksides = numthicksides = 0;
ds_p->thicksidecol = NULL; ds_p->thicksidecol = NULL;
ds_p->invscale = NULL; ds_p->invscale = NULL;
ds_p->tsilheight = 0; ds_p->tsilheight = 0;
texcoltables = false;
numbackffloors = 0; numbackffloors = 0;
for (i = 0; i < MAXFFLOORS; i++) for (i = 0; i < MAXFFLOORS; i++)
...@@ -1750,16 +2099,19 @@ void R_StoreWallRange(INT32 start, INT32 stop) ...@@ -1750,16 +2099,19 @@ void R_StoreWallRange(INT32 start, INT32 stop)
angle_t lineangle = R_PointToAngle2(curline->v1->x, curline->v1->y, curline->v2->x, curline->v2->y); angle_t lineangle = R_PointToAngle2(curline->v1->x, curline->v1->y, curline->v2->x, curline->v2->y);
if (frontsector->f_slope) if (frontsector->f_slope)
floorfrontslide = FixedMul(frontsector->f_slope->zdelta, FINECOSINE((lineangle-frontsector->f_slope->xydirection)>>ANGLETOFINESHIFT)); floorfrontslide = R_GetSlopeTextureSlide(frontsector->f_slope, lineangle);
if (frontsector->c_slope) if (frontsector->c_slope)
ceilingfrontslide = FixedMul(frontsector->c_slope->zdelta, FINECOSINE((lineangle-frontsector->c_slope->xydirection)>>ANGLETOFINESHIFT)); ceilingfrontslide = R_GetSlopeTextureSlide(frontsector->c_slope, lineangle);
if (backsector && backsector->f_slope) if (backsector)
floorbackslide = FixedMul(backsector->f_slope->zdelta, FINECOSINE((lineangle-backsector->f_slope->xydirection)>>ANGLETOFINESHIFT)); {
if (backsector->f_slope)
floorbackslide = R_GetSlopeTextureSlide(backsector->f_slope, lineangle);
if (backsector && backsector->c_slope) if (backsector->c_slope)
ceilingbackslide = FixedMul(backsector->c_slope->zdelta, FINECOSINE((lineangle-backsector->c_slope->xydirection)>>ANGLETOFINESHIFT)); ceilingbackslide = R_GetSlopeTextureSlide(backsector->c_slope, lineangle);
}
} }
rw_midtexturescalex = sidedef->scalex_mid; rw_midtexturescalex = sidedef->scalex_mid;
...@@ -1775,26 +2127,27 @@ void R_StoreWallRange(INT32 start, INT32 stop) ...@@ -1775,26 +2127,27 @@ void R_StoreWallRange(INT32 start, INT32 stop)
fixed_t rowoffset = sidedef->rowoffset + sidedef->offsety_mid; fixed_t rowoffset = sidedef->rowoffset + sidedef->offsety_mid;
fixed_t texheight = textureheight[midtexture]; fixed_t texheight = textureheight[midtexture];
fixed_t scaley = abs(rw_midtexturescaley);
if (rw_midtexturescaley > 0) if (rw_midtexturescaley > 0)
{ {
if (linedef->flags & ML_NOSKEW) if (linedef->flags & ML_NOSKEW)
{ {
if (linedef->flags & ML_DONTPEGBOTTOM) if (linedef->flags & ML_DONTPEGBOTTOM)
rw_midtexturemid = FixedMul(frontsector->floorheight - viewz, rw_midtexturescaley) + texheight; rw_midtexturemid = FixedMul(frontsector->floorheight - viewz, scaley) + texheight;
else else
rw_midtexturemid = FixedMul(frontsector->ceilingheight - viewz, rw_midtexturescaley); rw_midtexturemid = FixedMul(frontsector->ceilingheight - viewz, scaley);
} }
else if (linedef->flags & ML_DONTPEGBOTTOM) else if (linedef->flags & ML_DONTPEGBOTTOM)
{ {
rw_midtexturemid = FixedMul(worldbottom, rw_midtexturescaley) + texheight; rw_midtexturemid = FixedMul(worldbottom, scaley) + texheight;
rw_midtextureslide = floorfrontslide; rw_midtextureslide = FixedMul(floorfrontslide, scaley);
} }
else else
{ {
// top of texture at top // top of texture at top
rw_midtexturemid = FixedMul(worldtop, rw_midtexturescaley); rw_midtexturemid = FixedMul(worldtop, scaley);
rw_midtextureslide = ceilingfrontslide; rw_midtextureslide = FixedMul(ceilingfrontslide, scaley);
} }
} }
else else
...@@ -1805,20 +2158,20 @@ void R_StoreWallRange(INT32 start, INT32 stop) ...@@ -1805,20 +2158,20 @@ void R_StoreWallRange(INT32 start, INT32 stop)
if (linedef->flags & ML_NOSKEW) if (linedef->flags & ML_NOSKEW)
{ {
if (linedef->flags & ML_DONTPEGBOTTOM) if (linedef->flags & ML_DONTPEGBOTTOM)
rw_midtexturemid = FixedMul(frontsector->floorheight - viewz, rw_midtexturescaley); rw_midtexturemid = FixedMul(frontsector->floorheight - viewz, scaley);
else else
rw_midtexturemid = FixedMul(frontsector->ceilingheight - viewz, rw_midtexturescaley) + texheight; rw_midtexturemid = FixedMul(frontsector->ceilingheight - viewz, scaley) + texheight;
} }
else if (linedef->flags & ML_DONTPEGBOTTOM) else if (linedef->flags & ML_DONTPEGBOTTOM)
{ {
rw_midtexturemid = FixedMul(worldbottom, rw_midtexturescaley); rw_midtexturemid = FixedMul(worldbottom, scaley);
rw_midtextureslide = floorfrontslide; rw_midtextureslide = FixedMul(floorfrontslide, scaley);
} }
else else
{ {
// top of texture at top // top of texture at top
rw_midtexturemid = FixedMul(worldtop, rw_midtexturescaley) + texheight; rw_midtexturemid = FixedMul(worldtop, scaley) + texheight;
rw_midtextureslide = ceilingfrontslide; rw_midtextureslide = FixedMul(ceilingfrontslide, scaley);
} }
} }
...@@ -2027,15 +2380,16 @@ void R_StoreWallRange(INT32 start, INT32 stop) ...@@ -2027,15 +2380,16 @@ void R_StoreWallRange(INT32 start, INT32 stop)
{ {
// top of texture at top // top of texture at top
rw_toptexturemid = worldtop; rw_toptexturemid = worldtop;
rw_toptextureslide = ceilingfrontslide; rw_toptextureslide = FixedMul(ceilingfrontslide, abs(rw_toptexturescaley));
} }
else else
{ {
rw_toptexturemid = worldhigh + texheight; rw_toptexturemid = worldhigh + texheight;
rw_toptextureslide = ceilingbackslide; rw_toptextureslide = FixedMul(ceilingbackslide, abs(rw_toptexturescaley));
} }
rw_toptexturemid = FixedMul(rw_toptexturemid, rw_toptexturescaley); rw_toptexturemid = FixedMul(rw_toptexturemid, abs(rw_toptexturescaley));
rw_toptexturemid += toprowoffset;
} }
// check BOTTOM TEXTURE // check BOTTOM TEXTURE
...@@ -2066,24 +2420,24 @@ void R_StoreWallRange(INT32 start, INT32 stop) ...@@ -2066,24 +2420,24 @@ void R_StoreWallRange(INT32 start, INT32 stop)
// bottom of texture at bottom // bottom of texture at bottom
// top of texture at top // top of texture at top
rw_bottomtexturemid = worldbottom; rw_bottomtexturemid = worldbottom;
rw_bottomtextureslide = floorfrontslide; rw_bottomtextureslide = FixedMul(floorfrontslide, abs(rw_bottomtexturescaley));
} }
else else
{ {
// top of texture at top // top of texture at top
rw_bottomtexturemid = worldlow; rw_bottomtexturemid = worldlow;
rw_bottomtextureslide = floorbackslide; rw_bottomtextureslide = FixedMul(floorbackslide, abs(rw_bottomtexturescaley));
}
rw_bottomtexturemid = FixedMul(rw_bottomtexturemid, rw_bottomtexturescaley);
} }
rw_toptexturemid += toprowoffset; rw_bottomtexturemid = FixedMul(rw_bottomtexturemid, abs(rw_bottomtexturescaley));
rw_bottomtexturemid += botrowoffset; rw_bottomtexturemid += botrowoffset;
}
// allocate space for masked texture tables // allocate space for masked texture tables
R_AllocTextureColumnTables(rw_stopx - start); R_AllocTextureColumnTables(rw_stopx - start);
texcoltables = true;
if (frontsector && backsector && !Tag_Compare(&frontsector->tags, &backsector->tags) && (backsector->ffloors || frontsector->ffloors)) if (frontsector && backsector && !Tag_Compare(&frontsector->tags, &backsector->tags) && (backsector->ffloors || frontsector->ffloors))
{ {
ffloor_t *rover; ffloor_t *rover;
...@@ -2282,7 +2636,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) ...@@ -2282,7 +2636,8 @@ void R_StoreWallRange(INT32 start, INT32 stop)
ds_p->maskedtexturecol = maskedtexturecol = curtexturecolumntable - rw_x; ds_p->maskedtexturecol = maskedtexturecol = curtexturecolumntable - rw_x;
curtexturecolumntable += rw_stopx - rw_x; curtexturecolumntable += rw_stopx - rw_x;
maskedtextureheight = ds_p->maskedtextureheight; // note to red, this == &(ds_p->maskedtextureheight[0]) ds_p->maskedtextureheight = maskedtextureheight = curtexturecolumntable - rw_x;
curtexturecolumntable += rw_stopx - rw_x;
maskedtexture = true; maskedtexture = true;
...@@ -2324,13 +2679,14 @@ void R_StoreWallRange(INT32 start, INT32 stop) ...@@ -2324,13 +2679,14 @@ void R_StoreWallRange(INT32 start, INT32 stop)
} }
} }
rw_midtexturemid = FixedMul(rw_midtexturemid, rw_midtexturescaley); rw_midtexturemid = FixedMul(rw_midtexturemid, abs(rw_midtexturescaley));
rw_midtextureback = FixedMul(rw_midtextureback, rw_midtexturescaley); rw_midtextureback = FixedMul(rw_midtextureback, abs(rw_midtexturescaley));
rw_midtextureslide = FixedMul(rw_midtextureslide, abs(rw_midtexturescaley));
rw_midtexturebackslide = FixedMul(rw_midtexturebackslide, abs(rw_midtexturescaley));
rw_midtexturemid += sidedef->rowoffset + sidedef->offsety_mid; rw_midtexturemid += sidedef->rowoffset + sidedef->offsety_mid;
rw_midtextureback += sidedef->rowoffset + sidedef->offsety_mid; rw_midtextureback += sidedef->rowoffset + sidedef->offsety_mid;
maskedtexture = true;
} }
} }
...@@ -2383,7 +2739,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) ...@@ -2383,7 +2739,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
// use different light tables // use different light tables
// for horizontal / vertical / diagonal // for horizontal / vertical / diagonal
// OPTIMIZE: get rid of LIGHTSEGSHIFT globally // OPTIMIZE: get rid of LIGHTSEGSHIFT globally
lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); lightnum = R_SideLightLevel(curline->sidedef, frontsector->lightlevel) >> LIGHTSEGSHIFT;
if (curline->v1->y == curline->v2->y) if (curline->v1->y == curline->v2->y)
lightnum--; lightnum--;
...@@ -2798,11 +3154,28 @@ void R_StoreWallRange(INT32 start, INT32 stop) ...@@ -2798,11 +3154,28 @@ void R_StoreWallRange(INT32 start, INT32 stop)
} }
} }
rw_silhouette = &(ds_p->silhouette); if (!segtextured && !numffloors && !numbackffloors)
rw_tsilheight = &(ds_p->tsilheight); {
rw_bsilheight = &(ds_p->bsilheight); if (markfloor || markceiling)
R_MarkSegBounds();
else
{
for (; rw_x < rw_stopx; rw_x++)
{
frontscale[rw_x] = rw_scale;
rw_scale += rw_scalestep;
}
}
}
else
{
rw_silhouette = &ds_p->silhouette;
rw_tsilheight = &ds_p->tsilheight;
rw_bsilheight = &ds_p->bsilheight;
R_RenderSegLoop(); R_RenderSegLoop();
}
colfunc = colfuncs[BASEDRAWFUNC]; colfunc = colfuncs[BASEDRAWFUNC];
if (portalline) // if curline is a portal, set portalrender for drawseg if (portalline) // if curline is a portal, set portalrender for drawseg
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2025 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "p_local.h" #include "p_local.h"
#include "dehacked.h" // get_number (for thok) #include "dehacked.h" // get_number (for thok)
#include "m_cond.h" #include "m_cond.h"
#include "deh_tables.h"
#ifdef HWRENDER #ifdef HWRENDER
#include "hardware/hw_md2.h" #include "hardware/hw_md2.h"
#endif #endif
...@@ -35,30 +36,95 @@ ...@@ -35,30 +36,95 @@
INT32 numskins = 0; INT32 numskins = 0;
skin_t **skins = NULL; skin_t **skins = NULL;
// // Gets the animation ID of a state
// P_GetSkinSprite2 UINT16 P_GetStateSprite2(state_t *state)
// For non-super players, tries each sprite2's immediate predecessor until it finds one with a number of frames or ends up at standing. {
// For super players, does the same as above - but tries the super equivalent for each sprite2 before the non-super version. if (state->sprite2)
// return state->sprite2;
else
UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player)
{ {
UINT8 super = 0, i = 0; // Transform the state frame into an animation ID
UINT16 spr2 = state->frame & FF_FRAMEMASK;
if (!skin) if (state->frame & SPR2F_SUPER)
spr2 |= SPR2F_SUPER;
return spr2;
}
}
// Gets the starting frame of an animation
UINT16 P_GetSprite2StateFrame(state_t *state)
{
if (state->sprite2)
return state->frame & FF_FRAMEMASK;
else
return 0; return 0;
}
// Checks if a state should use the "super" variant of the animation
boolean P_IsStateSprite2Super(state_t *state)
{
if (state->sprite2)
{
if (state->sprite2 & SPR2F_SUPER)
return true;
}
else if (state->frame & SPR2F_SUPER)
return true;
return false;
}
// Applies SPR2F_SUPER to an animation based on the actor's state
UINT16 P_ApplySuperFlagToSprite2(UINT16 spr2, mobj_t *mobj)
{
if (mobj->player)
{
boolean is_nights = mobj->player->powers[pw_carry] == CR_NIGHTSMODE;
if (mobj->player->charflags & SF_NOSUPERSPRITES || (is_nights && (mobj->player->charflags & SF_NONIGHTSSUPER)))
spr2 &= ~SPR2F_SUPER;
else if (mobj->player->powers[pw_super] || (is_nights && (mobj->player->charflags & SF_SUPER)))
spr2 |= SPR2F_SUPER;
// Special case for transforming when you are NiGHTS.
// Do NOT apply the super sprites in this situation, even if they exist.
if (is_nights && mobj->state >= &states[S_PLAY_NIGHTS_TRANS1] && mobj->state <= &states[S_PLAY_NIGHTS_TRANS6])
{
spr2 &= ~SPR2F_SUPER;
}
}
if (spr2 & SPR2F_SUPER)
{
if (mobj->eflags & MFE_FORCENOSUPER)
spr2 &= ~SPR2F_SUPER;
}
else if (mobj->eflags & MFE_FORCESUPER)
spr2 |= SPR2F_SUPER;
return spr2;
}
if ((playersprite_t)(spr2 & ~FF_SPR2SUPER) >= free_spr2) // For non-super players, this tries each sprite2's immediate predecessor until it finds one with a number of frames or ends up at standing.
// For super players, does the same as above - but tries the super equivalent for each sprite2 before the non-super version.
UINT16 P_GetSkinSprite2(skin_t *skin, UINT16 spr2, player_t *player)
{
UINT16 super = 0;
UINT8 i = 0;
if (!skin)
return 0; return 0;
while (!skin->sprites[spr2].numframes while (!P_IsValidSprite2(skin, spr2)
&& spr2 != SPR2_STND && spr2 != SPR2_STND
&& ++i < 32) // recursion limiter && ++i < 32) // recursion limiter
{ {
if (spr2 & FF_SPR2SUPER) if (spr2 & SPR2F_SUPER)
{ {
super = FF_SPR2SUPER; super = SPR2F_SUPER;
spr2 &= ~FF_SPR2SUPER; spr2 &= ~SPR2F_SUPER;
continue; continue;
} }
...@@ -92,6 +158,51 @@ UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player) ...@@ -92,6 +158,51 @@ UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player)
return spr2; return spr2;
} }
// Gets the spritedef of a skin animation
spritedef_t *P_GetSkinSpritedef(skin_t *skin, UINT16 spr2)
{
if (!skin)
return NULL;
boolean is_super = spr2 & SPR2F_SUPER;
spr2 &= SPR2F_MASK;
if (spr2 >= free_spr2)
return NULL;
if (is_super)
return &skin->super.sprites[spr2];
else
return &skin->sprites[spr2];
}
// Gets the spriteinfo of a skin animation
spriteinfo_t *P_GetSkinSpriteInfo(skin_t *skin, UINT16 spr2)
{
if (!skin)
return NULL;
boolean is_super = spr2 & SPR2F_SUPER;
spr2 &= SPR2F_MASK;
if (spr2 >= free_spr2)
return NULL;
if (is_super)
return &skin->super.sprinfo[spr2];
else
return &skin->sprinfo[spr2];
}
// Checks if a skin animation is valid
boolean P_IsValidSprite2(skin_t *skin, UINT16 spr2)
{
spritedef_t *sprdef = P_GetSkinSpritedef(skin, spr2);
return sprdef && sprdef->numframes;
}
static void Sk_SetDefaultValue(skin_t *skin) static void Sk_SetDefaultValue(skin_t *skin)
{ {
INT32 i; INT32 i;
...@@ -376,7 +487,7 @@ static void SetSkin(player_t *player, INT32 skinnum) ...@@ -376,7 +487,7 @@ static void SetSkin(player_t *player, INT32 skinnum)
player->mo->skin = skin; player->mo->skin = skin;
if (newcolor) if (newcolor)
player->mo->color = newcolor; player->mo->color = newcolor;
P_SetScale(player->mo, player->mo->scale); P_SetScale(player->mo, player->mo->scale, false);
player->mo->radius = radius; player->mo->radius = radius;
P_SetMobjState(player->mo, player->mo->state-states); // Prevent visual errors when switching between skins with differing number of frames P_SetMobjState(player->mo, player->mo->state-states); // Prevent visual errors when switching between skins with differing number of frames
...@@ -500,10 +611,10 @@ static UINT16 W_CheckForPatchSkinMarkerInPwad(UINT16 wadid, UINT16 startlump) ...@@ -500,10 +611,10 @@ static UINT16 W_CheckForPatchSkinMarkerInPwad(UINT16 wadid, UINT16 startlump)
return INT16_MAX; // not found return INT16_MAX; // not found
} }
static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, skin_t *skin, UINT8 start_spr2) static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, skin_t *skin, UINT16 start_spr2)
{ {
UINT16 newlastlump; UINT16 newlastlump;
UINT8 sprite2; UINT16 sprite2;
*lump += 1; // start after S_SKIN *lump += 1; // start after S_SKIN
*lastlump = W_CheckNumForNamePwad("S_END",wadnum,*lump); // stop at S_END *lastlump = W_CheckNumForNamePwad("S_END",wadnum,*lump); // stop at S_END
...@@ -523,7 +634,7 @@ static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, ski ...@@ -523,7 +634,7 @@ static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, ski
newlastlump++; newlastlump++;
// load all sprite sets we are aware of... for super! // load all sprite sets we are aware of... for super!
for (sprite2 = start_spr2; sprite2 < free_spr2; sprite2++) for (sprite2 = start_spr2; sprite2 < free_spr2; sprite2++)
R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[FF_SPR2SUPER|sprite2], wadnum, newlastlump, *lastlump); R_AddSingleSpriteDef(spr2names[sprite2], &skin->super.sprites[sprite2], wadnum, newlastlump, *lastlump, false);
newlastlump--; newlastlump--;
*lastlump = newlastlump; // okay, make the normal sprite set loading end there *lastlump = newlastlump; // okay, make the normal sprite set loading end there
...@@ -531,10 +642,18 @@ static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, ski ...@@ -531,10 +642,18 @@ static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, ski
// load all sprite sets we are aware of... for normal stuff. // load all sprite sets we are aware of... for normal stuff.
for (sprite2 = start_spr2; sprite2 < free_spr2; sprite2++) for (sprite2 = start_spr2; sprite2 < free_spr2; sprite2++)
R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[sprite2], wadnum, *lump, *lastlump); R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[sprite2], wadnum, *lump, *lastlump, false);
if (skin->sprites[0].numframes == 0) if (skin->sprites[0].numframes == 0)
CONS_Alert(CONS_ERROR, M_GetText("No frames found for sprite SPR2_%s\n"), spr2names[0]); CONS_Alert(CONS_ERROR, M_GetText("No frames found for sprite SPR2_%s\n"), spr2names[0]);
// TODO: 2.3: Delete
memcpy(&skin->sprites_compat[start_spr2],
&skin->sprites[start_spr2],
sizeof(spritedef_t) * (free_spr2 - start_spr2));
memcpy(&skin->sprites_compat[start_spr2 + NUMPLAYERSPRITES],
&skin->super.sprites[start_spr2],
sizeof(spritedef_t) * (free_spr2 - start_spr2));
} }
// returns whether found appropriate property // returns whether found appropriate property
...@@ -621,6 +740,8 @@ static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value) ...@@ -621,6 +740,8 @@ static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value)
GETFLAG(MACHINE) GETFLAG(MACHINE)
GETFLAG(DASHMODE) GETFLAG(DASHMODE)
GETFLAG(FASTEDGE) GETFLAG(FASTEDGE)
GETFLAG(FASTWAIT)
GETFLAG(JETFUME)
GETFLAG(MULTIABILITY) GETFLAG(MULTIABILITY)
GETFLAG(NONIGHTSROTATION) GETFLAG(NONIGHTSROTATION)
GETFLAG(NONIGHTSSUPER) GETFLAG(NONIGHTSSUPER)
...@@ -671,6 +792,88 @@ static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value) ...@@ -671,6 +792,88 @@ static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value)
return true; return true;
} }
// e.g. "RUN" => S_PLAY_RUN, "RUN1" => S_PLAY_RUN, "RUN8" => S_PLAY_RUN
static statenum_t GetCanonicalPlayerStateNumByName(const char *name)
{
if (startswith(name, "STAND")) return S_PLAY_STND;
else if (startswith(name, "STND")) return S_PLAY_STND;
else if (startswith(name, "WAIT")) return S_PLAY_WAIT;
else if (startswith(name, "WALK")) return S_PLAY_WALK;
else if (startswith(name, "SKID")) return S_PLAY_SKID;
else if (startswith(name, "RUN")) return S_PLAY_RUN;
else if (startswith(name, "DASH")) return S_PLAY_DASH;
else if (startswith(name, "PAIN")) return S_PLAY_PAIN;
else if (startswith(name, "STUN")) return S_PLAY_STUN;
else if (startswith(name, "DEAD")) return S_PLAY_DEAD;
else if (startswith(name, "DRWN")) return S_PLAY_DRWN;
else if (startswith(name, "ROLL")) return S_PLAY_ROLL;
else if (startswith(name, "GASP")) return S_PLAY_GASP;
else if (startswith(name, "JUMP")) return S_PLAY_JUMP;
else if (startswith(name, "SPRING")) return S_PLAY_SPRING;
else if (startswith(name, "FALL")) return S_PLAY_FALL;
else if (startswith(name, "EDGE")) return S_PLAY_EDGE;
else if (startswith(name, "RIDE")) return S_PLAY_RIDE;
else if (startswith(name, "SPINDASH")) return S_PLAY_SPINDASH;
else if (startswith(name, "FLY")) return S_PLAY_FLY;
else if (startswith(name, "SWIM")) return S_PLAY_SWIM;
else if (startswith(name, "FLY_TIRED")) return S_PLAY_FLY_TIRED;
else if (startswith(name, "GLIDE")) return S_PLAY_GLIDE;
else if (startswith(name, "GLIDE_LANDING")) return S_PLAY_GLIDE_LANDING;
else if (startswith(name, "CLING")) return S_PLAY_CLING;
else if (startswith(name, "CLIMB")) return S_PLAY_CLIMB;
else if (startswith(name, "FLOAT")) return S_PLAY_FLOAT;
else if (startswith(name, "FLOAT_RUN")) return S_PLAY_FLOAT_RUN;
else if (startswith(name, "BOUNCE")) return S_PLAY_BOUNCE;
else if (startswith(name, "BOUNCE_LANDING")) return S_PLAY_BOUNCE_LANDING;
else if (startswith(name, "FIRE")) return S_PLAY_FIRE;
else if (startswith(name, "FIRE_FINISH")) return S_PLAY_FIRE_FINISH;
else if (startswith(name, "TWINSPIN")) return S_PLAY_TWINSPIN;
else if (startswith(name, "MELEE")) return S_PLAY_MELEE;
else if (startswith(name, "MELEE_FINISH")) return S_PLAY_MELEE_FINISH;
else if (startswith(name, "MELEE_LANDING")) return S_PLAY_MELEE_LANDING;
else if (startswith(name, "NIGHTS_STAND")) return S_PLAY_NIGHTS_STAND;
else if (startswith(name, "NIGHTS_FLOAT")) return S_PLAY_NIGHTS_FLOAT;
else if (startswith(name, "NIGHTS_FLY")) return S_PLAY_NIGHTS_FLY;
else if (startswith(name, "NIGHTS_DRILL")) return S_PLAY_NIGHTS_DRILL;
else if (startswith(name, "NIGHTS_STUN")) return S_PLAY_NIGHTS_STUN;
else if (startswith(name, "NIGHTS_PULL")) return S_PLAY_NIGHTS_PULL;
else if (startswith(name, "NIGHTS_ATTACK")) return S_PLAY_NIGHTS_ATTACK;
else return S_NULL;
}
static void CacheCustomSkinStates(skin_t *skin)
{
SIMPLEHASH_CLEAR(skin->defaulttocustomstate, hashentry_int32_int32_t)
SIMPLEHASH_CLEAR(skin->customtodefaultstate, hashentry_int32_int32_t)
char *skinstateprefix = va("SKIN_%s_", skin->name);
strupr(skinstateprefix);
size_t skinstateprefixlen = strlen(skinstateprefix);
for (INT32 state = S_FIRSTFREESLOT; state <= S_LASTFREESLOT; state++)
{
const char *statename = FREE_STATES[state - S_FIRSTFREESLOT];
if (!statename)
continue;
if (strncmp(statename, skinstateprefix, skinstateprefixlen))
continue;
statenum_t defaultstate = GetCanonicalPlayerStateNumByName(&statename[skinstateprefixlen]);
if (defaultstate)
{
// If a default state is overriden by multiple custom states, use the first one as reference
// e.g. WALK+WALK2+WALK3+WALK4 instead of just WALK
statenum_t alreadyoverriden;
SIMPLEHASH_FIND_INT(skin->defaulttocustomstate, hashentry_int32_int32_t, defaultstate, S_NULL, alreadyoverriden)
if (!alreadyoverriden)
SIMPLEHASH_REPLACE_INT(skin->defaulttocustomstate, hashentry_int32_int32_t, defaultstate, state)
SIMPLEHASH_REPLACE_INT(skin->customtodefaultstate, hashentry_int32_int32_t, state, defaultstate)
}
}
}
// //
// Find skin sprites, sounds & optional status bar face, & add them // Find skin sprites, sounds & optional status bar face, & add them
// //
...@@ -825,6 +1028,8 @@ next_token: ...@@ -825,6 +1028,8 @@ next_token:
R_FlushTranslationColormapCache(); R_FlushTranslationColormapCache();
CacheCustomSkinStates(skin);
if (mainfile == false) if (mainfile == false)
CONS_Printf(M_GetText("Added skin '%s'\n"), skin->name); CONS_Printf(M_GetText("Added skin '%s'\n"), skin->name);
...@@ -962,6 +1167,8 @@ next_token: ...@@ -962,6 +1167,8 @@ next_token:
R_FlushTranslationColormapCache(); R_FlushTranslationColormapCache();
CacheCustomSkinStates(skin);
if (mainfile == false) if (mainfile == false)
CONS_Printf(M_GetText("Patched skin '%s'\n"), skin->name); CONS_Printf(M_GetText("Patched skin '%s'\n"), skin->name);
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "r_patch.h" #include "r_patch.h"
#include "r_picformats.h" // spriteinfo_t #include "r_picformats.h" // spriteinfo_t
#include "r_defs.h" // spritedef_t #include "r_defs.h" // spritedef_t
#include "simple_hashmap.h"
/// Defaults /// Defaults
#define SKINNAMESIZE 16 #define SKINNAMESIZE 16
...@@ -80,9 +81,20 @@ typedef struct ...@@ -80,9 +81,20 @@ typedef struct
// specific sounds per skin // specific sounds per skin
sfxenum_t soundsid[NUMSKINSOUNDS]; // sound # in S_sfx table sfxenum_t soundsid[NUMSKINSOUNDS]; // sound # in S_sfx table
spritedef_t sprites[NUMPLAYERSPRITES];
spriteinfo_t sprinfo[NUMPLAYERSPRITES];
// contains super versions too // contains super versions too
spritedef_t sprites[NUMPLAYERSPRITES*2]; struct {
spriteinfo_t sprinfo[NUMPLAYERSPRITES*2]; spritedef_t sprites[NUMPLAYERSPRITES];
spriteinfo_t sprinfo[NUMPLAYERSPRITES];
} super;
hashentry_int32_int32_t *defaulttocustomstate; // e.g. S_PLAY_WALK => S_SKIN_BIGTHECAT_WALK
hashentry_int32_int32_t *customtodefaultstate; // e.g. S_SKIN_BIGTHECAT_WALK => S_PLAY_WALK
// TODO: 2.3: Delete
spritedef_t sprites_compat[NUMPLAYERSPRITES * 2];
} skin_t; } skin_t;
/// Externs /// Externs
...@@ -102,7 +114,14 @@ INT32 R_GetForcedSkin(INT32 playernum); ...@@ -102,7 +114,14 @@ INT32 R_GetForcedSkin(INT32 playernum);
void R_AddSkins(UINT16 wadnum, boolean mainfile); void R_AddSkins(UINT16 wadnum, boolean mainfile);
void R_PatchSkins(UINT16 wadnum, boolean mainfile); void R_PatchSkins(UINT16 wadnum, boolean mainfile);
UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player); UINT16 P_GetStateSprite2(state_t *state);
UINT16 P_GetSprite2StateFrame(state_t *state);
UINT16 P_GetSkinSprite2(skin_t *skin, UINT16 spr2, player_t *player);
UINT16 P_ApplySuperFlagToSprite2(UINT16 spr2, mobj_t *mobj);
spritedef_t *P_GetSkinSpritedef(skin_t *skin, UINT16 spr2);
spriteinfo_t *P_GetSkinSpriteInfo(skin_t *skin, UINT16 spr2);
boolean P_IsValidSprite2(skin_t *skin, UINT16 spr2);
boolean P_IsStateSprite2Super(state_t *state);
void R_RefreshSprite2(void); void R_RefreshSprite2(void);
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
......
// SONIC ROBO BLAST 2 // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -53,7 +53,7 @@ static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32 ...@@ -53,7 +53,7 @@ static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32
if (dir == 0) if (dir == 0)
{ {
for (;;) for (; count > 0; count--)
{ {
rastertab[y1].maxx = xs; rastertab[y1].maxx = xs;
rastertab[y1].tx2 = xe; rastertab[y1].tx2 = xe;
...@@ -62,13 +62,11 @@ static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32 ...@@ -62,13 +62,11 @@ static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32
xs += dx0; xs += dx0;
xe += dx1; xe += dx1;
y1++; y1++;
if (count-- < 1) break;
} }
} }
else else
{ {
for (;;) for (; count > 0; count--)
{ {
rastertab[y1].maxx = xs; rastertab[y1].maxx = xs;
rastertab[y1].tx2 = tc; rastertab[y1].tx2 = tc;
...@@ -77,8 +75,6 @@ static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32 ...@@ -77,8 +75,6 @@ static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32
xs += dx0; xs += dx0;
xe += dx1; xe += dx1;
y1++; y1++;
if (count-- < 1) break;
} }
} }
} }
...@@ -95,7 +91,7 @@ static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32 ...@@ -95,7 +91,7 @@ static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32
if (dir == 0) if (dir == 0)
{ {
for (;;) for (; count > 0; count--)
{ {
rastertab[y2].minx = xs; rastertab[y2].minx = xs;
rastertab[y2].tx1 = xe; rastertab[y2].tx1 = xe;
...@@ -104,13 +100,11 @@ static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32 ...@@ -104,13 +100,11 @@ static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32
xs += dx0; xs += dx0;
xe += dx1; xe += dx1;
y2++; y2++;
if (count-- < 1) break;
} }
} }
else else
{ {
for (;;) for (; count > 0; count--)
{ {
rastertab[y2].minx = xs; rastertab[y2].minx = xs;
rastertab[y2].tx1 = tc; rastertab[y2].tx1 = tc;
...@@ -119,8 +113,6 @@ static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32 ...@@ -119,8 +113,6 @@ static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32
xs += dx0; xs += dx0;
xe += dx1; xe += dx1;
y2++; y2++;
if (count-- < 1) break;
} }
} }
} }
...@@ -381,7 +373,7 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr ...@@ -381,7 +373,7 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
if (pSplat->slope) if (pSplat->slope)
{ {
R_SetScaledSlopePlane(pSplat->slope, vis->viewpoint.x, vis->viewpoint.y, vis->viewpoint.z, pSplat->xscale, pSplat->yscale, -pSplat->verts[0].x, pSplat->verts[0].y, vis->viewpoint.angle, pSplat->angle); R_SetScaledSlopePlane(pSplat->slope, vis->viewpoint.x, vis->viewpoint.y, vis->viewpoint.z, (INT64)pSplat->xscale, (INT64)pSplat->yscale, -pSplat->verts[0].x, pSplat->verts[0].y, vis->viewpoint.angle, pSplat->angle);
} }
else if (!ds_solidcolor) else if (!ds_solidcolor)
{ {
......
...@@ -71,7 +71,7 @@ extern size_t numsubsectors; ...@@ -71,7 +71,7 @@ extern size_t numsubsectors;
extern subsector_t *subsectors; extern subsector_t *subsectors;
extern size_t numnodes; extern size_t numnodes;
extern node_t *nodes; extern bspnode_t *nodes;
extern size_t numlines; extern size_t numlines;
extern line_t *lines; extern line_t *lines;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -147,9 +147,9 @@ static void R_DrawFlippedColumnInCache(column_t *column, UINT8 *cache, texpatch_ ...@@ -147,9 +147,9 @@ static void R_DrawFlippedColumnInCache(column_t *column, UINT8 *cache, texpatch_
if (count > 0) if (count > 0)
{ {
for (; dest < cache + position + count; --source, is_opaque++) for (; dest < cache + position + count; --source, dest++, is_opaque++)
{ {
*dest++ = *source; *dest = *source;
*is_opaque = true; *is_opaque = true;
} }
} }
...@@ -295,7 +295,6 @@ UINT8 *R_GenerateTexture(size_t texnum) ...@@ -295,7 +295,6 @@ UINT8 *R_GenerateTexture(size_t texnum)
UINT16 lumpnum = patch->lump; UINT16 lumpnum = patch->lump;
UINT8 *pdata; UINT8 *pdata;
softwarepatch_t *realpatch; softwarepatch_t *realpatch;
boolean holey = false;
#ifndef NO_PNG_LUMPS #ifndef NO_PNG_LUMPS
UINT8 header[PNG_HEADER_SIZE]; UINT8 header[PNG_HEADER_SIZE];
...@@ -310,9 +309,11 @@ UINT8 *R_GenerateTexture(size_t texnum) ...@@ -310,9 +309,11 @@ UINT8 *R_GenerateTexture(size_t texnum)
pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
realpatch = (softwarepatch_t *)pdata; realpatch = (softwarepatch_t *)pdata;
texture->transparency = false;
// Check the patch for holes. // Check the patch for holes.
if (texture->width > SHORT(realpatch->width) || texture->height > SHORT(realpatch->height)) if (texture->width > SHORT(realpatch->width) || texture->height > SHORT(realpatch->height))
holey = true; texture->transparency = true;
else else
{ {
UINT8 *colofs = (UINT8 *)realpatch->columnofs; UINT8 *colofs = (UINT8 *)realpatch->columnofs;
...@@ -332,12 +333,12 @@ UINT8 *R_GenerateTexture(size_t texnum) ...@@ -332,12 +333,12 @@ UINT8 *R_GenerateTexture(size_t texnum)
col = (doompost_t *)((UINT8 *)col + col->length + 4); col = (doompost_t *)((UINT8 *)col + col->length + 4);
} }
if (y < texture->height) if (y < texture->height)
holey = true; // this texture is HOLEy! D: texture->transparency = true; // this texture is HOLEy! D:
} }
} }
// If the patch uses transparency, we have to save it this way. // If the patch uses transparency, we have to save it this way.
if (holey) if (texture->transparency)
{ {
texture->flip = patch->flip; texture->flip = patch->flip;
...@@ -378,6 +379,15 @@ UINT8 *R_GenerateTexture(size_t texnum) ...@@ -378,6 +379,15 @@ UINT8 *R_GenerateTexture(size_t texnum)
temp_columns = Z_Calloc(sizeof(column_t) * texture->width, PU_STATIC, NULL); temp_columns = Z_Calloc(sizeof(column_t) * texture->width, PU_STATIC, NULL);
temp_block = Z_Calloc(total_pixels, PU_STATIC, NULL); temp_block = Z_Calloc(total_pixels, PU_STATIC, NULL);
#ifdef TEXTURE_255_IS_TRANSPARENT
texture->transparency = false;
// Transparency hack
memset(temp_block, TRANSPARENTPIXEL, total_pixels);
#else
texture->transparency = true;
#endif
for (x = 0; x < texture->width; x++) for (x = 0; x < texture->width; x++)
{ {
column_t *column = &temp_columns[x]; column_t *column = &temp_columns[x];
...@@ -420,6 +430,10 @@ UINT8 *R_GenerateTexture(size_t texnum) ...@@ -420,6 +430,10 @@ UINT8 *R_GenerateTexture(size_t texnum)
realpatch = W_CachePatchNumPwad(wadnum, lumpnum, PU_PATCH); realpatch = W_CachePatchNumPwad(wadnum, lumpnum, PU_PATCH);
} }
// Well, it's not valid...
if (realpatch == NULL)
continue;
x1 = patch->originx; x1 = patch->originx;
width = realpatch->width; width = realpatch->width;
height = realpatch->height; height = realpatch->height;
...@@ -474,13 +488,27 @@ UINT8 *R_GenerateTexture(size_t texnum) ...@@ -474,13 +488,27 @@ UINT8 *R_GenerateTexture(size_t texnum)
// Now write the columns // Now write the columns
column_posts = Z_Calloc(sizeof(unsigned) * texture->width, PU_STATIC, NULL); column_posts = Z_Calloc(sizeof(unsigned) * texture->width, PU_STATIC, NULL);
#ifdef TEXTURE_255_IS_TRANSPARENT
total_posts = texture->width;
temp_posts = Z_Realloc(temp_posts, sizeof(post_t) * total_posts, PU_CACHE, NULL);
#endif
for (x = 0; x < texture->width; x++) for (x = 0; x < texture->width; x++)
{ {
post_t *post = NULL; post_t *post = NULL;
boolean was_opaque = false;
column_t *column = &temp_columns[x]; column_t *column = &temp_columns[x];
#ifdef TEXTURE_255_IS_TRANSPARENT
post = &temp_posts[x];
post->topdelta = 0;
post->length = texture->height;
post->data_offset = 0;
column_posts[x] = x;
column->num_posts = 1;
#else
boolean was_opaque = false;
column_posts[x] = (unsigned)-1; column_posts[x] = (unsigned)-1;
for (INT32 y = 0; y < texture->height; y++) for (INT32 y = 0; y < texture->height; y++)
...@@ -510,6 +538,7 @@ UINT8 *R_GenerateTexture(size_t texnum) ...@@ -510,6 +538,7 @@ UINT8 *R_GenerateTexture(size_t texnum)
post->length++; post->length++;
} }
#endif
} }
blocksize = (sizeof(column_t) * texture->width) + (sizeof(post_t) * total_posts) + (sizeof(UINT8) * total_pixels); blocksize = (sizeof(column_t) * texture->width) + (sizeof(post_t) * total_posts) + (sizeof(UINT8) * total_pixels);
...@@ -821,8 +850,8 @@ Rloadflats (INT32 i, INT32 w) ...@@ -821,8 +850,8 @@ Rloadflats (INT32 i, INT32 w)
UINT8 *flatlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); UINT8 *flatlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
if (Picture_PNGDimensions((UINT8 *)flatlump, &texw, &texh, NULL, NULL, lumplength)) if (Picture_PNGDimensions((UINT8 *)flatlump, &texw, &texh, NULL, NULL, lumplength))
{ {
width = (INT16)width; width = (INT16)texw;
height = (INT16)height; height = (INT16)texh;
} }
else else
{ {
...@@ -900,7 +929,7 @@ Rloadtextures (INT32 i, INT32 w) ...@@ -900,7 +929,7 @@ Rloadtextures (INT32 i, INT32 w)
// printf("\"%s\" (wad: %u, lump: %u) is a single patch, dimensions %d x %d\n",W_CheckNameForNumPwad(wadnum,lumpnum),wadnum,lumpnum,width,height); // printf("\"%s\" (wad: %u, lump: %u) is a single patch, dimensions %d x %d\n",W_CheckNameForNumPwad(wadnum,lumpnum),wadnum,lumpnum,width,height);
R_AddSinglePatchTexture(i, wadnum, lumpnum, width, height, TEXTURETYPE_SINGLEPATCH); R_AddSinglePatchTexture(i, wadnum, lumpnum, width, height, TEXTURETYPE_TEXTURE);
i++; i++;
} }
...@@ -1068,6 +1097,98 @@ void R_LoadTexturesPwad(UINT16 wadnum) ...@@ -1068,6 +1097,98 @@ void R_LoadTexturesPwad(UINT16 wadnum)
R_FinishLoadingTextures(newtextures); R_FinishLoadingTextures(newtextures);
} }
static lumpnum_t W_GetTexPatchLumpNum(const char *name)
{
// Flats as a texture patch crashes horribly, and flats
// can share the same name as textures.
// But even if they worked, we want to prioritize:
// Patches -> Textures -> anything else
enum
{
USE_PATCHES,
USE_TEXTURES,
USE__MAX,
};
lumpnum_t lump = LUMPERROR;
INT32 lump_type_it;
for (lump_type_it = 0; lump_type_it < USE__MAX; lump_type_it++)
{
INT32 i;
for (i = numwadfiles - 1; i >= 0; i--) // Scan wad files backwards so patched lumps take precedent
{
lumpnum_t start = LUMPERROR;
lumpnum_t end = LUMPERROR;
switch (wadfiles[i]->type)
{
case RET_WAD:
if (lump_type_it == USE_PATCHES)
{
if ((start = W_CheckNumForMarkerStartPwad("P_START", (UINT16)i, 0)) == INT16_MAX)
continue;
else if ((end = W_CheckNumForNamePwad("P_END", (UINT16)i, start)) == INT16_MAX)
continue;
}
else if (lump_type_it == USE_TEXTURES)
{
if ((start = W_CheckNumForMarkerStartPwad("TX_START", (UINT16)i, 0)) == INT16_MAX)
continue;
else if ((end = W_CheckNumForNamePwad("TX_END", (UINT16)i, start)) == INT16_MAX)
continue;
}
break;
case RET_PK3:
case RET_FOLDER:
if (lump_type_it == USE_PATCHES)
{
if ((start = W_CheckNumForFolderStartPK3("Patches/", i, 0)) == INT16_MAX)
continue;
if ((end = W_CheckNumForFolderEndPK3("Patches/", i, start)) == INT16_MAX)
continue;
}
else if (lump_type_it == USE_TEXTURES)
{
if ((start = W_CheckNumForFolderStartPK3("Textures/", i, 0)) == INT16_MAX)
continue;
if ((end = W_CheckNumForFolderEndPK3("Textures/", i, start)) == INT16_MAX)
continue;
}
break;
default:
continue;
}
// Now find lump with specified name in that range.
lump = W_CheckNumForNamePwad(name, (UINT16)i, start);
if (lump < end)
{
lump += (i<<16); // found it, in our constraints
break;
}
lump = LUMPERROR;
}
if (lump != LUMPERROR)
{
break;
}
}
if (lump == LUMPERROR)
{
// Use whatever else you can find.
return W_CheckNumForPatchName(name);
}
return lump;
}
static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch)
{ {
char *texturesToken; char *texturesToken;
...@@ -1240,13 +1361,13 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) ...@@ -1240,13 +1361,13 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch)
if (actuallyLoadPatch == true) if (actuallyLoadPatch == true)
{ {
// Check lump exists // Check lump exists
patchLumpNum = W_GetNumForName(patchName); patchLumpNum = W_GetTexPatchLumpNum(patchName);
// If so, allocate memory for texpatch_t and fill 'er up // If so, allocate memory for texpatch_t and fill 'er up
resultPatch = (texpatch_t *)Z_Malloc(sizeof(texpatch_t),PU_STATIC,NULL); resultPatch = (texpatch_t *)Z_Malloc(sizeof(texpatch_t),PU_STATIC,NULL);
resultPatch->originx = patchXPos; resultPatch->originx = patchXPos;
resultPatch->originy = patchYPos; resultPatch->originy = patchYPos;
resultPatch->lump = patchLumpNum & 65535; resultPatch->lump = LUMPNUM(patchLumpNum);
resultPatch->wad = patchLumpNum>>16; resultPatch->wad = WADFILENUM(patchLumpNum);
resultPatch->flip = flip; resultPatch->flip = flip;
resultPatch->alpha = alpha; resultPatch->alpha = alpha;
resultPatch->style = style; resultPatch->style = style;
...@@ -1377,7 +1498,7 @@ static texture_t *R_ParseTexture(boolean actuallyLoadTexture) ...@@ -1377,7 +1498,7 @@ static texture_t *R_ParseTexture(boolean actuallyLoadTexture)
resultTexture->hash = quickncasehash(newTextureName, 8); resultTexture->hash = quickncasehash(newTextureName, 8);
resultTexture->width = newTextureWidth; resultTexture->width = newTextureWidth;
resultTexture->height = newTextureHeight; resultTexture->height = newTextureHeight;
resultTexture->type = TEXTURETYPE_COMPOSITE; resultTexture->type = TEXTURETYPE_TEXTURE;
} }
Z_Free(texturesToken); Z_Free(texturesToken);
texturesToken = M_GetToken(NULL); texturesToken = M_GetToken(NULL);
...@@ -1563,7 +1684,7 @@ static void AddTextureToCache(const char *name, UINT32 hash, INT32 id, UINT8 typ ...@@ -1563,7 +1684,7 @@ static void AddTextureToCache(const char *name, UINT32 hash, INT32 id, UINT8 typ
// //
// Check whether texture is available. Filter out NoTexture indicator. // Check whether texture is available. Filter out NoTexture indicator.
// //
INT32 R_CheckTextureNumForName(const char *name) INT32 R_CheckTextureNumForName(const char *name, UINT8 type)
{ {
INT32 i; INT32 i;
UINT32 hash; UINT32 hash;
...@@ -1575,14 +1696,14 @@ INT32 R_CheckTextureNumForName(const char *name) ...@@ -1575,14 +1696,14 @@ INT32 R_CheckTextureNumForName(const char *name)
hash = quickncasehash(name, 8); hash = quickncasehash(name, 8);
for (i = 0; i < tidcachelen; i++) for (i = 0; i < tidcachelen; i++)
if (tidcache[i].hash == hash && !strncasecmp(tidcache[i].name, name, 8)) if (tidcache[i].type == type && tidcache[i].hash == hash && !strncasecmp(tidcache[i].name, name, 8))
return tidcache[i].id; return tidcache[i].id;
// Need to parse the list backwards, so textures loaded more recently are used in lieu of ones loaded earlier // Need to parse the list backwards, so textures loaded more recently are used in lieu of ones loaded earlier
for (i = numtextures - 1; i >= 0; i--) for (i = numtextures - 1; i >= 0; i--)
if (textures[i]->hash == hash && !strncasecmp(textures[i]->name, name, 8)) if (textures[i]->type == type && textures[i]->hash == hash && !strncasecmp(textures[i]->name, name, 8))
{ {
AddTextureToCache(name, hash, i, textures[i]->type); AddTextureToCache(name, hash, i, type);
return i; return i;
} }
...@@ -1621,47 +1742,29 @@ const char *R_TextureNameForNum(INT32 num) ...@@ -1621,47 +1742,29 @@ const char *R_TextureNameForNum(INT32 num)
// //
// R_TextureNumForName // R_TextureNumForName
// //
// Calls R_CheckTextureNumForName, aborts with error message. // Calls R_CheckTextureNumForName. Returns REDWALL if not found.
// //
INT32 R_TextureNumForName(const char *name) INT32 R_TextureNumForName(const char *name)
{ {
const INT32 i = R_CheckTextureNumForName(name); INT32 i = R_CheckTextureNumForName(name, TEXTURETYPE_TEXTURE);
// Didn't find it, so look for a flat
if (i == -1)
{
i = R_CheckTextureNumForName(name, TEXTURETYPE_FLAT);
}
// Still didn't find it, so return REDWALL
if (i == -1) if (i == -1)
{ {
static INT32 redwall = -2; static INT32 redwall = -2;
CONS_Debug(DBG_SETUP, "WARNING: R_TextureNumForName: %.8s not found\n", name); CONS_Debug(DBG_SETUP, "WARNING: R_TextureNumForName: %.8s not found\n", name);
if (redwall == -2) if (redwall == -2)
redwall = R_CheckTextureNumForName("REDWALL"); redwall = R_CheckTextureNumForName("REDWALL", TEXTURETYPE_TEXTURE);
if (redwall != -1) if (redwall != -1)
return redwall; return redwall;
return 1; return 1;
} }
return i;
}
// Like R_CheckTextureNumForName, but only looks in the flat namespace specifically.
INT32 R_CheckFlatNumForName(const char *name)
{
INT32 i;
UINT32 hash;
// "NoTexture" marker.
if (name[0] == '-')
return 0;
hash = quickncasehash(name, 8);
for (i = 0; i < tidcachelen; i++)
if (tidcache[i].type == TEXTURETYPE_FLAT && tidcache[i].hash == hash && !strncasecmp(tidcache[i].name, name, 8))
return tidcache[i].id;
for (i = numtextures - 1; i >= 0; i--)
if (textures[i]->hash == hash && !strncasecmp(textures[i]->name, name, 8) && textures[i]->type == TEXTURETYPE_FLAT)
{
AddTextureToCache(name, hash, i, TEXTURETYPE_FLAT);
return i; return i;
} }
return -1;
}
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -40,8 +40,7 @@ typedef struct ...@@ -40,8 +40,7 @@ typedef struct
enum enum
{ {
TEXTURETYPE_UNKNOWN, TEXTURETYPE_UNKNOWN,
TEXTURETYPE_SINGLEPATCH, TEXTURETYPE_TEXTURE,
TEXTURETYPE_COMPOSITE,
TEXTURETYPE_FLAT TEXTURETYPE_FLAT
}; };
...@@ -54,6 +53,7 @@ typedef struct ...@@ -54,6 +53,7 @@ typedef struct
char name[8]; char name[8];
UINT32 hash; UINT32 hash;
UINT8 type; // TEXTURETYPE_* UINT8 type; // TEXTURETYPE_*
boolean transparency;
INT16 width, height; INT16 width, height;
UINT8 flip; // 1 = flipx, 2 = flipy, 3 = both UINT8 flip; // 1 = flipx, 2 = flipy, 3 = both
void *flat; // The texture, as a flat. void *flat; // The texture, as a flat.
...@@ -99,8 +99,7 @@ void R_SetFlatVars(size_t length); ...@@ -99,8 +99,7 @@ void R_SetFlatVars(size_t length);
// Returns the texture number for the texture name. // Returns the texture number for the texture name.
INT32 R_TextureNumForName(const char *name); INT32 R_TextureNumForName(const char *name);
INT32 R_CheckTextureNumForName(const char *name); INT32 R_CheckTextureNumForName(const char *name, UINT8 type);
INT32 R_CheckFlatNumForName(const char *name);
// Returns the texture name for the texture number (in case you ever needed it) // Returns the texture name for the texture number (in case you ever needed it)
const char *R_CheckTextureNameForNum(INT32 num); const char *R_CheckTextureNameForNum(INT32 num);
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -77,7 +77,7 @@ spriteinfo_t spriteinfo[NUMSPRITES]; ...@@ -77,7 +77,7 @@ spriteinfo_t spriteinfo[NUMSPRITES];
spritedef_t *sprites; spritedef_t *sprites;
size_t numsprites; size_t numsprites;
static spriteframe_t sprtemp[64]; static spriteframe_t sprtemp[MAXFRAMENUM];
static size_t maxframe; static size_t maxframe;
static const char *spritename; static const char *spritename;
...@@ -116,6 +116,14 @@ static INT32 drawsegs_xrange_count = 0; ...@@ -116,6 +116,14 @@ static INT32 drawsegs_xrange_count = 0;
// //
// ========================================================================== // ==========================================================================
spritenum_t R_GetSpriteNumByName(const char *name)
{
for (spritenum_t i = 0; i < NUMSPRITES; i++)
if (!strcmp(name, sprnames[i]))
return i;
return NUMSPRITES;
}
// //
// //
// //
...@@ -128,10 +136,14 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch ...@@ -128,10 +136,14 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch
{ {
char cn = R_Frame2Char(frame), cr = R_Rotation2Char(rotation); // for debugging char cn = R_Frame2Char(frame), cr = R_Rotation2Char(rotation); // for debugging
char framedescription[256];
if (cn != '\xFF')
sprintf(framedescription, "%s frame %d (%c)", spritename, frame, cn);
else
sprintf(framedescription, "%s frame %d", spritename, frame);
INT32 r; INT32 r;
lumpnum_t lumppat = wad; lumpnum_t lumppat = (wad << 16) + lump;
lumppat <<= 16;
lumppat += lump;
if (maxframe ==(size_t)-1 || frame > maxframe) if (maxframe ==(size_t)-1 || frame > maxframe)
maxframe = frame; maxframe = frame;
...@@ -147,9 +159,9 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch ...@@ -147,9 +159,9 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch
{ {
// the lump should be used for all rotations // the lump should be used for all rotations
if (sprtemp[frame].rotate == SRF_SINGLE) if (sprtemp[frame].rotate == SRF_SINGLE)
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has multiple rot = 0 lump\n", spritename, cn); CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s has multiple rot = 0 lump\n", framedescription);
else if (sprtemp[frame].rotate != SRF_NONE) // Let's bundle 1-8/16 and L/R rotations into one debug message. else if (sprtemp[frame].rotate != SRF_NONE) // Let's bundle 1-8/16 and L/R rotations into one debug message.
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has rotations and a rot = 0 lump\n", spritename, cn); CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s has rotations and a rot = 0 lump\n", framedescription);
sprtemp[frame].rotate = SRF_SINGLE; sprtemp[frame].rotate = SRF_SINGLE;
for (r = 0; r < 16; r++) for (r = 0; r < 16; r++)
...@@ -169,15 +181,15 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch ...@@ -169,15 +181,15 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch
if (sprtemp[frame].rotate == SRF_NONE) if (sprtemp[frame].rotate == SRF_NONE)
sprtemp[frame].rotate = SRF_SINGLE; sprtemp[frame].rotate = SRF_SINGLE;
else if (sprtemp[frame].rotate == SRF_SINGLE) else if (sprtemp[frame].rotate == SRF_SINGLE)
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has L/R rotations and a rot = 0 lump\n", spritename, cn); CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s has L/R rotations and a rot = 0 lump\n", framedescription);
else if (sprtemp[frame].rotate == SRF_3D) else if (sprtemp[frame].rotate == SRF_3D)
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has both L/R and 1-8 rotations\n", spritename, cn); CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s has both L/R and 1-8 rotations\n", framedescription);
else if (sprtemp[frame].rotate == SRF_3DGE) else if (sprtemp[frame].rotate == SRF_3DGE)
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has both L/R and 1-G rotations\n", spritename, cn); CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s has both L/R and 1-G rotations\n", framedescription);
else if ((sprtemp[frame].rotate & SRF_LEFT) && (rotation == ROT_L)) else if ((sprtemp[frame].rotate & SRF_LEFT) && (rotation == ROT_L))
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has multiple L rotations\n", spritename, cn); CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s has multiple L rotations\n", framedescription);
else if ((sprtemp[frame].rotate & SRF_RIGHT) && (rotation == ROT_R)) else if ((sprtemp[frame].rotate & SRF_RIGHT) && (rotation == ROT_R))
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has multiple R rotations\n", spritename, cn); CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s has multiple R rotations\n", framedescription);
sprtemp[frame].rotate |= ((rotation == ROT_R) ? SRF_RIGHT : SRF_LEFT); sprtemp[frame].rotate |= ((rotation == ROT_R) ? SRF_RIGHT : SRF_LEFT);
if ((sprtemp[frame].rotate & SRF_2D) == SRF_2D) if ((sprtemp[frame].rotate & SRF_2D) == SRF_2D)
...@@ -204,9 +216,9 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch ...@@ -204,9 +216,9 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch
if (sprtemp[frame].rotate == SRF_NONE) if (sprtemp[frame].rotate == SRF_NONE)
sprtemp[frame].rotate = SRF_SINGLE; sprtemp[frame].rotate = SRF_SINGLE;
else if (sprtemp[frame].rotate == SRF_SINGLE) else if (sprtemp[frame].rotate == SRF_SINGLE)
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has 1-8/G rotations and a rot = 0 lump\n", spritename, cn); CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s has 1-8/G rotations and a rot = 0 lump\n", framedescription);
else if (sprtemp[frame].rotate & SRF_2D) else if (sprtemp[frame].rotate & SRF_2D)
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has both L/R and 1-8/G rotations\n", spritename, cn); CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s has both L/R and 1-8/G rotations\n", framedescription);
// make 0 based // make 0 based
rotation--; rotation--;
...@@ -226,7 +238,12 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch ...@@ -226,7 +238,12 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch
} }
if (sprtemp[frame].lumppat[rotation] != LUMPERROR) if (sprtemp[frame].lumppat[rotation] != LUMPERROR)
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s: %c%c has two lumps mapped to it\n", spritename, cn, cr); {
if (cn != '\xFF')
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s: %d_%c (%c%c) has two lumps mapped to it\n", spritename, frame, cr, cn, cr);
else
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s: %d_%c has two lumps mapped to it\n", spritename, frame, cr);
}
// lumppat & lumpid are the same for original Doom, but different // lumppat & lumpid are the same for original Doom, but different
// when using sprites in pwad : the lumppat points the new graphics // when using sprites in pwad : the lumppat points the new graphics
...@@ -238,24 +255,209 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch ...@@ -238,24 +255,209 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch
sprtemp[frame].flip &= ~(1<<rotation); sprtemp[frame].flip &= ~(1<<rotation);
} }
static boolean GetFramesAndRotationsFromShortLumpName(
const char *name,
INT32 *ret_frame,
UINT8 *ret_rotation,
INT32 *ret_frame2,
UINT8 *ret_rotation2
)
{
size_t namelen = strlen(name);
if (namelen != 6 && namelen != 8)
return false;
*ret_frame = R_Char2Frame(name[4]);
*ret_rotation = R_Char2Rotation(name[5]);
if (*ret_frame >= 64 || *ret_rotation == 255)
return false;
if (namelen == 8)
{
*ret_frame2 = R_Char2Frame(name[6]);
*ret_rotation2 = R_Char2Rotation(name[7]);
if (*ret_frame2 >= 64 || *ret_rotation2 == 255)
return false;
// TRNSLATE is a valid but extremely unlikely sprite name:
// * The sprite name is "TRNS"
// * The frame is L, rotation A; mirrored to frame T, rotation E
// In the very unfortunate event that TRNSLATE is found between sprite lumps,
// this name check prevents it from being added as a sprite, when it actually isn't.
if (memcmp(name, "TRNSLATE", 8) == 0)
return false;
}
else
{
*ret_frame2 = -1;
*ret_rotation2 = 255;
}
return true;
}
static boolean GetSingleFrameAndRotation(
const char *name,
size_t len,
INT32 *ret_frame,
UINT8 *ret_rotation
)
{
const char *underscore = strchr(name, '_');
// Found but past the part of the name we are parsing
if ((size_t)(underscore - name) >= len)
underscore = NULL;
size_t framelen = underscore ? (size_t)(underscore - name) : len;
if (framelen < 1 || framelen > 4)
return false;
char framepart[4 + 1]; // Max 9999
strlcpy(framepart, name, framelen + 1);
for (size_t i = 0; i < framelen; i++)
if (!isdigit(framepart[i]))
return false;
*ret_frame = atoi(framepart);
*ret_rotation = underscore ? R_Char2Rotation(*(underscore + 1)) : 0;
if (*ret_frame >= MAXFRAMENUM || *ret_rotation == 255)
return false;
return true;
}
static boolean GetFramesAndRotationsFromLongLumpName(
const char *name,
INT32 *ret_frame,
UINT8 *ret_rotation,
INT32 *ret_frame2,
UINT8 *ret_rotation2
)
{
const char *plus = strchr(name, '+');
if (plus)
{
size_t len1 = plus - name;
if (!GetSingleFrameAndRotation(name, len1, ret_frame, ret_rotation))
return false;
if (!GetSingleFrameAndRotation(plus + 1, strlen(name) - len1 - 1, ret_frame2, ret_rotation2))
return false;
}
else
{
if (!GetSingleFrameAndRotation(name, strlen(name), ret_frame, ret_rotation))
return false;
*ret_frame2 = -1;
*ret_rotation2 = 255;
}
return true;
}
static UINT8 GetOppositeRotation(UINT8 rotation, UINT8 flags)
{
if (flags & ~SRF_3DMASK)
I_Error("GetOppositeRotation: rotation type not supported");
UINT8 numrotations = (flags == SRF_3D) ? 8 : 16;
return (rotation == 1) ? 1 : numrotations + 2 - rotation;
}
static void MirrorMissingRotations(void)
{
for (UINT32 framenum = 0; framenum < maxframe; framenum++)
{
spriteframe_t *frame = &sprtemp[framenum];
if (frame->rotate == SRF_NONE || !(frame->rotate & (SRF_3DMASK | SRF_2D)))
continue;
UINT8 numrotations = frame->rotate == SRF_3D ? 8 : 16;
for (UINT8 rotation = 1; rotation <= numrotations; rotation++)
{
if (frame->lumppat[rotation - 1] != LUMPERROR)
continue;
UINT8 baserotation = GetOppositeRotation(rotation, frame->rotate);
UINT32 lumpnum = frame->lumppat[baserotation - 1];
R_InstallSpriteLump(WADFILENUM(lumpnum), LUMPNUM(lumpnum), frame->lumpid[baserotation - 1], framenum, rotation, 1);
}
}
}
// Some checks to help development
static void CheckFrame(const char *sprname)
{
for (UINT32 frame = 0; frame < maxframe; frame++)
{
spriteframe_t *spriteframe = &sprtemp[frame];
char framedescription[256];
if (frame < 64)
sprintf(framedescription, "%s frame %d (%c)", sprname, frame, R_Frame2Char(frame));
else
sprintf(framedescription, "%s frame %d", sprname, frame);
switch (spriteframe->rotate)
{
case SRF_NONE:
// no rotations were found for that frame at all
I_Error("R_AddSingleSpriteDef: No patches found for %s", framedescription);
break;
case SRF_SINGLE:
// only the first rotation is needed
break;
case SRF_2D: // both Left and Right rotations
// we test to see whether the left and right slots are present
if ((spriteframe->lumppat[2] == LUMPERROR) || (spriteframe->lumppat[6] == LUMPERROR))
I_Error("R_AddSingleSpriteDef: Sprite %s is missing rotations (L-R mode)",
framedescription);
break;
default:
{
// must have all 8/16 frames
UINT8 rotation = ((spriteframe->rotate & SRF_3DGE) ? 16 : 8);
while (rotation--)
{
// we test the patch lump, or the id lump whatever
// if it was not loaded the two are LUMPERROR
if (spriteframe->lumppat[rotation] == LUMPERROR)
I_Error("R_AddSingleSpriteDef: Sprite %s is missing rotations (1-%c mode)",
framedescription, ((spriteframe->rotate & SRF_3DGE) ? 'G' : '8'));
}
}
break;
}
}
}
// Install a single sprite, given its identifying name (4 chars) // Install a single sprite, given its identifying name (4 chars)
// //
// (originally part of R_AddSpriteDefs) // (originally part of R_AddSpriteDefs)
// //
// Pass: name of sprite : 4 chars // Pass: name of sprite
// spritedef_t // spritedef_t
// wadnum : wad number, indexes wadfiles[], where patches // wadnum : wad number, indexes wadfiles[], where patches
// for frames are found // for frames are found
// startlump : first lump to search for sprite frames // startlump : first lump to search for sprite frames
// endlump : AFTER the last lump to search // endlump : AFTER the last lump to search
// longname : whether to use long sprite names or 4-char names
// //
// Returns true if the sprite was succesfully added // Returns true if the sprite was succesfully added
// //
boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 wadnum, UINT16 startlump, UINT16 endlump) boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 wadnum, UINT16 startlump, UINT16 endlump, boolean longname)
{ {
UINT16 l; UINT16 l;
UINT8 frame;
UINT8 rotation;
lumpinfo_t *lumpinfo; lumpinfo_t *lumpinfo;
UINT16 numadded = 0; UINT16 numadded = 0;
...@@ -282,15 +484,23 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 ...@@ -282,15 +484,23 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16
for (l = startlump; l < endlump; l++) for (l = startlump; l < endlump; l++)
{ {
if (memcmp(lumpinfo[l].name,sprname,4)==0) if (longname && W_IsLumpFolder(wadnum, l))
I_Error("R_AddSingleSpriteDef: all frame lumps for a sprite should be contained inside a single folder\n");
// For long sprites, the startlump-endlump range only includes
// relevant lumps, so no check needed in that case
if (longname || (strlen(sprname) == 4 && !memcmp(lumpinfo[l].name, sprname, 4)))
{ {
INT16 width, height; INT16 width, height;
INT16 topoffset, leftoffset; INT16 topoffset, leftoffset;
INT32 frame, frame2;
UINT8 rotation, rotation2;
frame = R_Char2Frame(lumpinfo[l].name[4]); boolean good = longname ?
rotation = R_Char2Rotation(lumpinfo[l].name[5]); GetFramesAndRotationsFromLongLumpName(lumpinfo[l].longname, &frame, &rotation, &frame2, &rotation2) :
GetFramesAndRotationsFromShortLumpName(lumpinfo[l].name, &frame, &rotation, &frame2, &rotation2);
if (frame >= 64 || rotation == 255) // Give an actual NAME error -_-... if (!good) // Give an actual NAME error -_-...
{ {
CONS_Alert(CONS_WARNING, M_GetText("Bad sprite name: %s\n"), W_CheckNameForNumPwad(wadnum,l)); CONS_Alert(CONS_WARNING, M_GetText("Bad sprite name: %s\n"), W_CheckNameForNumPwad(wadnum,l));
continue; continue;
...@@ -322,19 +532,8 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 ...@@ -322,19 +532,8 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16
//---------------------------------------------------- //----------------------------------------------------
R_InstallSpriteLump(wadnum, l, numspritelumps, frame, rotation, 0); R_InstallSpriteLump(wadnum, l, numspritelumps, frame, rotation, 0);
if (frame2 != -1)
if (lumpinfo[l].name[6]) R_InstallSpriteLump(wadnum, l, numspritelumps, frame2, rotation2, 1);
{
frame = R_Char2Frame(lumpinfo[l].name[6]);
rotation = R_Char2Rotation(lumpinfo[l].name[7]);
if (frame >= 64 || rotation == 255) // Give an actual NAME error -_-...
{
CONS_Alert(CONS_WARNING, M_GetText("Bad sprite name: %s\n"), W_CheckNameForNumPwad(wadnum,l));
continue;
}
R_InstallSpriteLump(wadnum, l, numspritelumps, frame, rotation, 1);
}
if (++numspritelumps >= max_spritelumps) if (++numspritelumps >= max_spritelumps)
{ {
...@@ -374,41 +573,10 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 ...@@ -374,41 +573,10 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16
maxframe++; maxframe++;
// if (longname)
// some checks to help development MirrorMissingRotations();
//
for (frame = 0; frame < maxframe; frame++)
{
switch (sprtemp[frame].rotate)
{
case SRF_NONE:
// no rotations were found for that frame at all
I_Error("R_AddSingleSpriteDef: No patches found for %.4s frame %c", sprname, R_Frame2Char(frame));
break;
case SRF_SINGLE: CheckFrame(sprname);
// only the first rotation is needed
break;
case SRF_2D: // both Left and Right rotations
// we test to see whether the left and right slots are present
if ((sprtemp[frame].lumppat[2] == LUMPERROR) || (sprtemp[frame].lumppat[6] == LUMPERROR))
I_Error("R_AddSingleSpriteDef: Sprite %.4s frame %c is missing rotations (L-R mode)",
sprname, R_Frame2Char(frame));
break;
default:
// must have all 8/16 frames
rotation = ((sprtemp[frame].rotate & SRF_3DGE) ? 16 : 8);
while (rotation--)
// we test the patch lump, or the id lump whatever
// if it was not loaded the two are LUMPERROR
if (sprtemp[frame].lumppat[rotation] == LUMPERROR)
I_Error("R_AddSingleSpriteDef: Sprite %.4s frame %c is missing rotations (1-%c mode)",
sprname, R_Frame2Char(frame), ((sprtemp[frame].rotate & SRF_3DGE) ? 'G' : '8'));
break;
}
}
// allocate space for the frames present and copy sprtemp to it // allocate space for the frames present and copy sprtemp to it
if (spritedef->numframes && // has been allocated if (spritedef->numframes && // has been allocated
...@@ -429,14 +597,10 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 ...@@ -429,14 +597,10 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16
return true; return true;
} }
// static void AddShortSpriteDefs(UINT16 wadnum, size_t *ptr_spritesadded, size_t *ptr_framesadded)
// Search for sprites replacements in a wad whose names are in namelist
//
void R_AddSpriteDefs(UINT16 wadnum)
{ {
size_t i, addsprites = 0; size_t i;
UINT16 start, end; UINT16 start, end;
char wadname[MAX_WADPATH];
// Find the sprites section in this resource file. // Find the sprites section in this resource file.
switch (wadfiles[wadnum]->type) switch (wadfiles[wadnum]->type)
...@@ -474,27 +638,90 @@ void R_AddSpriteDefs(UINT16 wadnum) ...@@ -474,27 +638,90 @@ void R_AddSpriteDefs(UINT16 wadnum)
return; return;
} }
// //
// scan through lumps, for each sprite, find all the sprite frames // scan through lumps, for each sprite, find all the sprite frames
// //
for (i = 0; i < numsprites; i++) for (i = 0; i < numsprites; i++)
{ {
if (sprnames[i][4] && wadnum >= (UINT16)sprnames[i][4]) if (R_AddSingleSpriteDef(sprnames[i], &sprites[i], wadnum, start, end, false))
continue;
if (R_AddSingleSpriteDef(sprnames[i], &sprites[i], wadnum, start, end))
{ {
// if a new sprite was added (not just replaced) // if a new sprite was added (not just replaced)
addsprites++; (*ptr_spritesadded)++;
#ifndef ZDEBUG #ifndef ZDEBUG
CONS_Debug(DBG_SETUP, "sprite %s set in pwad %d\n", sprnames[i], wadnum); CONS_Debug(DBG_SETUP, "sprite %s set in pwad %d\n", sprnames[i], wadnum);
#endif #endif
} }
} }
*ptr_framesadded += end - start;
}
static void AddLongSpriteDefs(UINT16 wadnum, size_t *ptr_spritesadded, size_t *ptr_framesadded)
{
if (!W_FileHasFolders(wadfiles[wadnum]))
return;
UINT16 start = W_CheckNumForFolderStartPK3("LongSprites/", wadnum, 0);
UINT16 end = W_CheckNumForFolderEndPK3("LongSprites/", wadnum, start);
if (start == INT16_MAX || end == INT16_MAX || start >= end)
return;
size_t lumpnum = start;
while (lumpnum < end)
{
if (W_IsLumpFolder(wadnum, lumpnum))
{
lumpnum++;
continue;
}
UINT16 folderstart, folderend;
char *folderpath = W_GetLumpFolderPathPK3(wadnum, lumpnum);
folderstart = lumpnum;
folderend = W_CheckNumForFolderEndPK3(folderpath, wadnum, lumpnum);
Z_Free(folderpath);
spritenum_t sprnum;
char *sprname = W_GetLumpFolderNamePK3(wadnum, lumpnum);
strupr(sprname);
sprnum = R_GetSpriteNumByName(sprname);
if (sprnum != NUMSPRITES && R_AddSingleSpriteDef(sprname, &sprites[sprnum], wadnum, folderstart, folderend, true))
{
// A new sprite was added (not just replaced)
(*ptr_spritesadded)++;
#ifndef ZDEBUG
CONS_Debug(DBG_SETUP, "long sprite %s set in pwad %d\n", sprname, wadnum);
#endif
}
Z_Free(sprname);
lumpnum = folderend;
}
*ptr_framesadded += end - start;
}
//
// Search for sprites replacements in a wad whose names are in namelist
//
void R_AddSpriteDefs(UINT16 wadnum)
{
char wadname[MAX_WADPATH];
size_t spritesadded = 0;
size_t framesadded = 0;
AddShortSpriteDefs(wadnum, &spritesadded, &framesadded);
AddLongSpriteDefs(wadnum, &spritesadded, &framesadded);
if (spritesadded || framesadded)
{
nameonly(strcpy(wadname, wadfiles[wadnum]->filename)); nameonly(strcpy(wadname, wadfiles[wadnum]->filename));
CONS_Printf(M_GetText("%s added %d frames in %s sprites\n"), wadname, end-start, sizeu1(addsprites)); CONS_Printf(M_GetText("%s added %s frames in %s sprites\n"), wadname, sizeu1(framesadded), sizeu2(spritesadded));
}
} }
// //
...@@ -620,8 +847,10 @@ void R_DrawMaskedColumn(column_t *column, unsigned lengthcol) ...@@ -620,8 +847,10 @@ void R_DrawMaskedColumn(column_t *column, unsigned lengthcol)
{ {
post_t *post = &column->posts[i]; post_t *post = &column->posts[i];
dc_postlength = post->length;
INT32 topscreen = sprtopscreen + spryscale*post->topdelta; INT32 topscreen = sprtopscreen + spryscale*post->topdelta;
INT32 bottomscreen = topscreen + spryscale*post->length; INT32 bottomscreen = topscreen + spryscale*dc_postlength;
dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS; dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS;
dc_yh = (bottomscreen-1)>>FRACBITS; dc_yh = (bottomscreen-1)>>FRACBITS;
...@@ -658,12 +887,31 @@ void R_DrawMaskedColumn(column_t *column, unsigned lengthcol) ...@@ -658,12 +887,31 @@ void R_DrawMaskedColumn(column_t *column, unsigned lengthcol)
static UINT8 *flippedcol = NULL; static UINT8 *flippedcol = NULL;
static size_t flippedcolsize = 0; static size_t flippedcolsize = 0;
void R_DrawFlippedPost(UINT8 *source, unsigned length, void (*drawcolfunc)(void))
{
if (!length)
return;
if (!flippedcolsize || length > flippedcolsize)
{
flippedcolsize = length;
flippedcol = Z_Realloc(flippedcol, length, PU_STATIC, NULL);
}
dc_source = flippedcol;
for (UINT8 *s = (UINT8 *)source, *d = flippedcol+length-1; d >= flippedcol; s++)
*d-- = *s;
drawcolfunc();
}
void R_DrawFlippedMaskedColumn(column_t *column, unsigned lengthcol) void R_DrawFlippedMaskedColumn(column_t *column, unsigned lengthcol)
{ {
INT32 topscreen; INT32 topscreen;
INT32 bottomscreen; INT32 bottomscreen;
fixed_t basetexturemid = dc_texturemid; fixed_t basetexturemid = dc_texturemid;
UINT8 *d,*s; INT32 topdelta;
for (unsigned i = 0; i < column->num_posts; i++) for (unsigned i = 0; i < column->num_posts; i++)
{ {
...@@ -671,10 +919,12 @@ void R_DrawFlippedMaskedColumn(column_t *column, unsigned lengthcol) ...@@ -671,10 +919,12 @@ void R_DrawFlippedMaskedColumn(column_t *column, unsigned lengthcol)
if (!post->length) if (!post->length)
continue; continue;
INT32 topdelta = lengthcol-post->length-post->topdelta; dc_postlength = post->length;
topdelta = lengthcol-dc_postlength-post->topdelta;
topscreen = sprtopscreen + spryscale*topdelta; topscreen = sprtopscreen + spryscale*topdelta;
bottomscreen = sprbotscreen == INT32_MAX ? topscreen + spryscale*post->length bottomscreen = sprbotscreen == INT32_MAX ? topscreen + spryscale*dc_postlength
: sprbotscreen + spryscale*post->length; : sprbotscreen + spryscale*dc_postlength;
dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS; dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS;
dc_yh = (bottomscreen-1)>>FRACBITS; dc_yh = (bottomscreen-1)>>FRACBITS;
...@@ -698,18 +948,9 @@ void R_DrawFlippedMaskedColumn(column_t *column, unsigned lengthcol) ...@@ -698,18 +948,9 @@ void R_DrawFlippedMaskedColumn(column_t *column, unsigned lengthcol)
if (dc_yl <= dc_yh && dc_yh > 0) if (dc_yl <= dc_yh && dc_yh > 0)
{ {
if (post->length > flippedcolsize)
{
flippedcolsize = post->length;
flippedcol = Z_Realloc(flippedcol, flippedcolsize, PU_STATIC, NULL);
}
for (s = column->pixels+post->data_offset+post->length, d = flippedcol; d < flippedcol+post->length; --s)
*d++ = *s;
dc_source = flippedcol;
dc_texturemid = basetexturemid - (topdelta<<FRACBITS); dc_texturemid = basetexturemid - (topdelta<<FRACBITS);
colfunc(); R_DrawFlippedPost(column->pixels + post->data_offset, post->length, colfunc);
} }
} }
...@@ -727,7 +968,9 @@ UINT8 *R_GetTranslationForThing(mobj_t *mobj, skincolornum_t color, UINT16 trans ...@@ -727,7 +968,9 @@ UINT8 *R_GetTranslationForThing(mobj_t *mobj, skincolornum_t color, UINT16 trans
if (color != SKINCOLOR_NONE) if (color != SKINCOLOR_NONE)
{ {
// New colormap stuff for skins Tails 06-07-2002 // New colormap stuff for skins Tails 06-07-2002
if (mobj->colorized) if ((mobj->state-states == S_METALSONIC_DASH || mobj->state-states == S_METALSONIC_BOUNCE) && (((leveltime/2) & 1))) // Metal boss doing attack
skinnum = TC_DASHMODE;
else if (mobj->colorized)
skinnum = TC_RAINBOW; skinnum = TC_RAINBOW;
else if (mobj->player && mobj->player->dashmode >= DASHMODE_THRESHOLD else if (mobj->player && mobj->player->dashmode >= DASHMODE_THRESHOLD
&& (mobj->player->charflags & SF_DASHMODE) && (mobj->player->charflags & SF_DASHMODE)
...@@ -763,6 +1006,12 @@ UINT8 *R_GetTranslationForThing(mobj_t *mobj, skincolornum_t color, UINT16 trans ...@@ -763,6 +1006,12 @@ UINT8 *R_GetTranslationForThing(mobj_t *mobj, skincolornum_t color, UINT16 trans
return NULL; return NULL;
} }
// Based off of R_GetLinedefTransTable
transnum_t R_GetThingTransTable(fixed_t alpha, transnum_t transmap)
{
return (20*(FRACUNIT - ((alpha * (10 - transmap))/10) - 1) + FRACUNIT) >> (FRACBITS+1);
}
// //
// R_DrawVisSprite // R_DrawVisSprite
// mfloorclip and mceilingclip should also be set. // mfloorclip and mceilingclip should also be set.
...@@ -1268,6 +1517,7 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, ...@@ -1268,6 +1517,7 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
floordiff = abs((isflipped ? interp.height : 0) + interp.z - groundz); floordiff = abs((isflipped ? interp.height : 0) + interp.z - groundz);
trans = floordiff / (100*FRACUNIT) + 3; trans = floordiff / (100*FRACUNIT) + 3;
trans = R_GetThingTransTable(thing->alpha, trans);
if (trans >= 9) return; if (trans >= 9) return;
scalemul = FixedMul(FRACUNIT - floordiff/640, scale); scalemul = FixedMul(FRACUNIT - floordiff/640, scale);
...@@ -1527,7 +1777,7 @@ static void R_ProjectSprite(mobj_t *thing) ...@@ -1527,7 +1777,7 @@ static void R_ProjectSprite(mobj_t *thing)
// uncapped/interpolation // uncapped/interpolation
interpmobjstate_t interp = {0}; interpmobjstate_t interp = {0};
if (!cv_renderthings.value) if (!r_renderthings)
return; return;
// do interpolation // do interpolation
...@@ -1541,6 +1791,10 @@ static void R_ProjectSprite(mobj_t *thing) ...@@ -1541,6 +1791,10 @@ static void R_ProjectSprite(mobj_t *thing)
} }
this_scale = interp.scale; this_scale = interp.scale;
if (this_scale < 1)
return;
radius = interp.radius; // For drop shadows radius = interp.radius; // For drop shadows
height = interp.height; // Ditto height = interp.height; // Ditto
...@@ -1577,12 +1831,14 @@ static void R_ProjectSprite(mobj_t *thing) ...@@ -1577,12 +1831,14 @@ static void R_ProjectSprite(mobj_t *thing)
//Fab : 02-08-98: 'skin' override spritedef currently used for skin //Fab : 02-08-98: 'skin' override spritedef currently used for skin
if (thing->skin && thing->sprite == SPR_PLAY) if (thing->skin && thing->sprite == SPR_PLAY)
{ {
sprdef = &((skin_t *)thing->skin)->sprites[thing->sprite2]; sprdef = P_GetSkinSpritedef(thing->skin, thing->sprite2);
#ifdef ROTSPRITE #ifdef ROTSPRITE
sprinfo = &((skin_t *)thing->skin)->sprinfo[thing->sprite2]; sprinfo = P_GetSkinSpriteInfo(thing->skin, thing->sprite2);
#endif #endif
if (frame >= sprdef->numframes) {
CONS_Alert(CONS_ERROR, M_GetText("R_ProjectSprite: invalid skins[\"%s\"].sprites[%sSPR2_%s] frame %s\n"), ((skin_t *)thing->skin)->name, ((thing->sprite2 & FF_SPR2SUPER) ? "FF_SPR2SUPER|": ""), spr2names[(thing->sprite2 & ~FF_SPR2SUPER)], sizeu5(frame)); if (frame >= sprdef->numframes)
{
CONS_Alert(CONS_ERROR, M_GetText("R_ProjectSprite: invalid skins[\"%s\"].sprites[SPR2_%s] %sframe %s\n"), ((skin_t *)thing->skin)->name, spr2names[thing->sprite2 & SPR2F_MASK], (thing->sprite2 & SPR2F_SUPER) ? "super ": "", sizeu5(frame));
thing->sprite = states[S_UNKNOWN].sprite; thing->sprite = states[S_UNKNOWN].sprite;
thing->frame = states[S_UNKNOWN].frame; thing->frame = states[S_UNKNOWN].frame;
sprdef = &sprites[thing->sprite]; sprdef = &sprites[thing->sprite];
...@@ -1953,6 +2209,11 @@ static void R_ProjectSprite(mobj_t *thing) ...@@ -1953,6 +2209,11 @@ static void R_ProjectSprite(mobj_t *thing)
else else
trans = 0; trans = 0;
if ((oldthing->flags2 & MF2_LINKDRAW) && oldthing->tracer)
trans = R_GetThingTransTable(oldthing->tracer->alpha, trans);
else
trans = R_GetThingTransTable(oldthing->alpha, trans);
// Check if this sprite needs to be rendered like a shadow // Check if this sprite needs to be rendered like a shadow
shadowdraw = (!!(thing->renderflags & RF_SHADOWDRAW) && !(papersprite || splat)); shadowdraw = (!!(thing->renderflags & RF_SHADOWDRAW) && !(papersprite || splat));
shadoweffects = (thing->renderflags & RF_SHADOWEFFECTS); shadoweffects = (thing->renderflags & RF_SHADOWEFFECTS);
...@@ -2684,7 +2945,7 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps ...@@ -2684,7 +2945,7 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps
// Add the 3D floors, thicksides, and masked textures... // Add the 3D floors, thicksides, and masked textures...
for (ds = drawsegs + mask->drawsegs[1]; ds-- > drawsegs + mask->drawsegs[0];) for (ds = drawsegs + mask->drawsegs[1]; ds-- > drawsegs + mask->drawsegs[0];)
{ {
if (ds->numthicksides) if (ds->numthicksides && r_renderwalls)
{ {
for (i = 0; i < ds->numthicksides; i++) for (i = 0; i < ds->numthicksides; i++)
{ {
...@@ -2703,17 +2964,19 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps ...@@ -2703,17 +2964,19 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps
else { else {
// Put it in! // Put it in!
entry = R_CreateDrawNode(head); entry = R_CreateDrawNode(head);
entry->plane = plane; if (r_renderwalls)
entry->seg = ds; entry->seg = ds;
if (r_renderfloors)
entry->plane = plane;
} }
ds->curline->polyseg->visplane = NULL; ds->curline->polyseg->visplane = NULL;
} }
if (ds->maskedtexturecol) if (ds->maskedtexturecol && r_renderwalls)
{ {
entry = R_CreateDrawNode(head); entry = R_CreateDrawNode(head);
entry->seg = ds; entry->seg = ds;
} }
if (ds->numffloorplanes) if (ds->numffloorplanes && r_renderfloors)
{ {
for (i = 0; i < ds->numffloorplanes; i++) for (i = 0; i < ds->numffloorplanes; i++)
{ {
...@@ -3180,9 +3443,6 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* port ...@@ -3180,9 +3443,6 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* port
(lowscale < spr->sortscale && (lowscale < spr->sortscale &&
!R_PointOnSegSide (spr->gx, spr->gy, ds->curline))) !R_PointOnSegSide (spr->gx, spr->gy, ds->curline)))
{ {
// masked mid texture?
/*if (ds->maskedtexturecol)
R_RenderMaskedSegRange (ds, r1, r2);*/
// seg is behind sprite // seg is behind sprite
continue; continue;
} }
...@@ -3414,6 +3674,7 @@ boolean R_ThingVisible (mobj_t *thing) ...@@ -3414,6 +3674,7 @@ boolean R_ThingVisible (mobj_t *thing)
(thing->sprite == SPR_NULL) || // Don't draw null-sprites (thing->sprite == SPR_NULL) || // Don't draw null-sprites
(thing->flags2 & MF2_DONTDRAW) || // Don't draw MF2_LINKDRAW objects (thing->flags2 & MF2_DONTDRAW) || // Don't draw MF2_LINKDRAW objects
(thing->drawonlyforplayer && thing->drawonlyforplayer != viewplayer) || // Don't draw other players' personal objects (thing->drawonlyforplayer && thing->drawonlyforplayer != viewplayer) || // Don't draw other players' personal objects
(!R_BlendLevelVisible(thing->blendmode, R_GetThingTransTable(thing->alpha, 0))) ||
(!P_MobjWasRemoved(r_viewmobj) && ( (!P_MobjWasRemoved(r_viewmobj) && (
(r_viewmobj == thing) || // Don't draw first-person players or awayviewmobj objects (r_viewmobj == thing) || // Don't draw first-person players or awayviewmobj objects
(r_viewmobj->player && r_viewmobj->player->followmobj == thing) || // Don't draw first-person players' followmobj (r_viewmobj->player && r_viewmobj->player->followmobj == thing) || // Don't draw first-person players' followmobj
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -27,7 +27,9 @@ ...@@ -27,7 +27,9 @@
#define FEETADJUST (4<<FRACBITS) // R_AddSingleSpriteDef #define FEETADJUST (4<<FRACBITS) // R_AddSingleSpriteDef
boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 wadnum, UINT16 startlump, UINT16 endlump); spritenum_t R_GetSpriteNumByName(const char *name);
boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 wadnum, UINT16 startlump, UINT16 endlump, boolean longname);
//faB: find sprites in wadfile, replace existing, add new ones //faB: find sprites in wadfile, replace existing, add new ones
// (only sprites from namelist are added or replaced) // (only sprites from namelist are added or replaced)
...@@ -48,6 +50,7 @@ extern fixed_t windowbottom; ...@@ -48,6 +50,7 @@ extern fixed_t windowbottom;
void R_DrawMaskedColumn(column_t *column, unsigned lengthcol); void R_DrawMaskedColumn(column_t *column, unsigned lengthcol);
void R_DrawFlippedMaskedColumn(column_t *column, unsigned lengthcol); void R_DrawFlippedMaskedColumn(column_t *column, unsigned lengthcol);
void R_DrawFlippedPost(UINT8 *source, unsigned length, void (*drawcolfunc)(void));
// ---------------- // ----------------
// SPRITE RENDERING // SPRITE RENDERING
...@@ -90,6 +93,7 @@ boolean R_ThingIsFullDark (mobj_t *thing); ...@@ -90,6 +93,7 @@ boolean R_ThingIsFullDark (mobj_t *thing);
boolean R_ThingIsFlashing (mobj_t *thing); boolean R_ThingIsFlashing (mobj_t *thing);
UINT8 *R_GetTranslationForThing(mobj_t *mobj, skincolornum_t color, UINT16 translation); UINT8 *R_GetTranslationForThing(mobj_t *mobj, skincolornum_t color, UINT16 translation);
transnum_t R_GetThingTransTable(fixed_t alpha, transnum_t transmap);
void R_ThingOffsetOverlay (mobj_t *thing, fixed_t *outx, fixed_t *outy); void R_ThingOffsetOverlay (mobj_t *thing, fixed_t *outx, fixed_t *outy);
......
// SONIC ROBO BLAST 2 // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1998-2006 by Randy Heit. // Copyright (C) 1998-2006 by Randy Heit.
// Copyright (C) 2023 by Sonic Team Junior. // Copyright (C) 2023-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -556,7 +556,7 @@ static boolean ParseDecimal(tokenizer_t *sc, double *out) ...@@ -556,7 +556,7 @@ static boolean ParseDecimal(tokenizer_t *sc, double *out)
return M_StringToDecimal(tkn, out); return M_StringToDecimal(tkn, out);
} }
static struct PaletteRemapParseResult *ThrowError(const char *format, ...) FUNCPRINTF static struct PaletteRemapParseResult *ThrowError(const char *format, ...)
{ {
const size_t err_size = 512 * sizeof(char); const size_t err_size = 512 * sizeof(char);
...@@ -792,7 +792,7 @@ static struct PaletteRemapParseResult *PaletteRemap_ParseTranslation(const char ...@@ -792,7 +792,7 @@ static struct PaletteRemapParseResult *PaletteRemap_ParseTranslation(const char
return result; return result;
} }
static void PrintError(const char *name, const char *format, ...) FUNCDEBUG static void PrintError(const char *name, const char *format, ...)
{ {
char error[256]; char error[256];
......
// SONIC ROBO BLAST 2 // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1998-2006 by Randy Heit. // Copyright (C) 1998-2006 by Randy Heit.
// Copyright (C) 2023 by Sonic Team Junior. // Copyright (C) 2023-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -82,7 +82,7 @@ static void Captioning_OnChange(void) ...@@ -82,7 +82,7 @@ static void Captioning_OnChange(void)
{ {
S_ResetCaptions(); S_ResetCaptions();
if (cv_closedcaptioning.value) if (cv_closedcaptioning.value)
S_StartSound(NULL, sfx_menu1); S_StartSoundFromEverywhere(sfx_menu1);
} }
consvar_t cv_closedcaptioning = CVAR_INIT ("closedcaptioning", "Off", CV_SAVE|CV_CALL, CV_OnOff, Captioning_OnChange); consvar_t cv_closedcaptioning = CVAR_INIT ("closedcaptioning", "Off", CV_SAVE|CV_CALL, CV_OnOff, Captioning_OnChange);
...@@ -516,14 +516,17 @@ void S_StartCaption(sfxenum_t sfx_id, INT32 cnum, UINT16 lifespan) ...@@ -516,14 +516,17 @@ void S_StartCaption(sfxenum_t sfx_id, INT32 cnum, UINT16 lifespan)
closedcaptions[set].b = 3; // bob closedcaptions[set].b = 3; // bob
} }
void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) void S_StartSoundAtVolume(void *origin_p, sfxenum_t sfx_id, INT32 volume, soundorigin_t soundorigin)
{ {
const INT32 initial_volume = volume; const INT32 initial_volume = volume;
INT32 sep, pitch, priority, cnum; INT32 sep, pitch, priority, cnum;
const sfxenum_t actual_id = sfx_id;
sfxinfo_t *sfx; sfxinfo_t *sfx;
const mobj_t *origin = (const mobj_t *)origin_p; mobj_t *origin = NULL;
if (soundorigin == SOUNDORIGIN_MOBJ)
origin = (mobj_t *)origin_p;
else if (soundorigin == SOUNDORIGIN_SECTOR)
origin = (mobj_t *)&((sector_t *)origin_p)->soundorg;
listener_t listener = {0,0,0,0}; listener_t listener = {0,0,0,0};
listener_t listener2 = {0,0,0,0}; listener_t listener2 = {0,0,0,0};
...@@ -538,6 +541,71 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) ...@@ -538,6 +541,71 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
if (sfx_id == sfx_None) if (sfx_id == sfx_None)
return; return;
if (mariomode) // Sounds change in Mario mode!
{
switch (sfx_id)
{
// case sfx_altow1:
// case sfx_altow2:
// case sfx_altow3:
// case sfx_altow4:
// sfx_id = sfx_mario8;
// break;
case sfx_thok:
case sfx_wepfir:
sfx_id = sfx_mario7;
break;
case sfx_pop:
sfx_id = sfx_mario5;
break;
case sfx_jump:
sfx_id = sfx_mario6;
break;
case sfx_shield:
case sfx_wirlsg:
case sfx_forcsg:
case sfx_elemsg:
case sfx_armasg:
case sfx_attrsg:
case sfx_s3k3e:
case sfx_s3k3f:
case sfx_s3k41:
sfx_id = sfx_mario3;
break;
case sfx_itemup:
sfx_id = sfx_mario4;
break;
// case sfx_tink:
// sfx_id = sfx_mario1;
// break;
// case sfx_cgot:
// sfx_id = sfx_mario9;
// break;
// case sfx_lose:
// sfx_id = sfx_mario2;
// break;
default:
break;
}
}
if (maptol & TOL_XMAS) // Some sounds change for xmas
{
switch (sfx_id)
{
case sfx_ideya:
case sfx_nbmper:
case sfx_ncitem:
case sfx_ngdone:
++sfx_id;
default:
break;
}
}
const sfxenum_t actual_id = sfx_id =
LUA_HookSoundPlay(sfx_id, origin, soundorigin);
if (players[displayplayer].awayviewtics) if (players[displayplayer].awayviewtics)
listenmobj = players[displayplayer].awayviewmobj; listenmobj = players[displayplayer].awayviewmobj;
...@@ -720,79 +788,48 @@ dontplay: ...@@ -720,79 +788,48 @@ dontplay:
channels[cnum].handle = I_StartSound(sfx_id, volume, sep, pitch, priority, cnum); channels[cnum].handle = I_StartSound(sfx_id, volume, sep, pitch, priority, cnum);
} }
void S_StartSound(const void *origin, sfxenum_t sfx_id) void S_StartSoundFromEverywhereVol(sfxenum_t sfx_id, INT32 volume)
{ {
if (S_SoundDisabled()) S_StartSoundAtVolume(NULL, sfx_id, volume, SOUNDORIGIN_EVERYWHERE);
return; }
if (mariomode) // Sounds change in Mario mode! void S_StartSoundFromMobjVol(mobj_t* origin, sfxenum_t sfx_id, INT32 volume)
{ {
switch (sfx_id) S_StartSoundAtVolume(origin, sfx_id, volume, SOUNDORIGIN_MOBJ);
{
// case sfx_altow1:
// case sfx_altow2:
// case sfx_altow3:
// case sfx_altow4:
// sfx_id = sfx_mario8;
// break;
case sfx_thok:
case sfx_wepfir:
sfx_id = sfx_mario7;
break;
case sfx_pop:
sfx_id = sfx_mario5;
break;
case sfx_jump:
sfx_id = sfx_mario6;
break;
case sfx_shield:
case sfx_wirlsg:
case sfx_forcsg:
case sfx_elemsg:
case sfx_armasg:
case sfx_attrsg:
case sfx_s3k3e:
case sfx_s3k3f:
case sfx_s3k41:
sfx_id = sfx_mario3;
break;
case sfx_itemup:
sfx_id = sfx_mario4;
break;
// case sfx_tink:
// sfx_id = sfx_mario1;
// break;
// case sfx_cgot:
// sfx_id = sfx_mario9;
// break;
// case sfx_lose:
// sfx_id = sfx_mario2;
// break;
default:
break;
}
} }
if (maptol & TOL_XMAS) // Some sounds change for xmas
{ void S_StartSoundFromSectorVol(sector_t* origin, sfxenum_t sfx_id, INT32 volume)
switch (sfx_id)
{ {
case sfx_ideya: S_StartSoundAtVolume(origin, sfx_id, volume, SOUNDORIGIN_SECTOR);
case sfx_nbmper:
case sfx_ncitem:
case sfx_ngdone:
++sfx_id;
default:
break;
}
} }
void S_StartSound(void *origin, sfxenum_t sfx_id, soundorigin_t soundorigin)
{
if (S_SoundDisabled())
return;
// the volume is handled 8 bits // the volume is handled 8 bits
#ifdef HW3SOUND #ifdef HW3SOUND
if (hws_mode != HWS_DEFAULT_MODE) if (hws_mode != HWS_DEFAULT_MODE)
HW3S_StartSound(origin, sfx_id); HW3S_StartSound(origin, sfx_id);
else else
#endif #endif
S_StartSoundAtVolume(origin, sfx_id, 255); S_StartSoundAtVolume(origin, sfx_id, 255, soundorigin);
}
void S_StartSoundFromEverywhere(sfxenum_t sfx_id)
{
S_StartSound(NULL, sfx_id, SOUNDORIGIN_EVERYWHERE);
}
void S_StartSoundFromMobj(mobj_t* origin, sfxenum_t sfx_id)
{
S_StartSound(origin, sfx_id, SOUNDORIGIN_MOBJ);
}
void S_StartSoundFromSector(sector_t* origin, sfxenum_t sfx_id)
{
S_StartSound(origin, sfx_id, SOUNDORIGIN_SECTOR);
} }
void S_StopSound(void *origin) void S_StopSound(void *origin)
...@@ -1308,7 +1345,7 @@ void S_StartSoundName(void *mo, const char *soundname) ...@@ -1308,7 +1345,7 @@ void S_StartSoundName(void *mo, const char *soundname)
newsounds[i] = soundnum; newsounds[i] = soundnum;
} }
S_StartSound(mo, soundnum); S_StartSoundFromMobj(mo, soundnum);
} }
// //
...@@ -1801,6 +1838,27 @@ UINT32 S_GetMusicLength(void) ...@@ -1801,6 +1838,27 @@ UINT32 S_GetMusicLength(void)
return I_GetSongLength(); return I_GetSongLength();
} }
//
// S_MusicInfo
//
// Returns metadata about supplied music
// If name is NULL, returns the currently playing music (if any)
//
musicdef_t *S_MusicInfo(const char *name)
{
if (!name)
name = music_name;
musicdef_t *def;
for (def = musicdefstart; def; def = def->next)
{
if (strcasecmp(def->name, name) == 0)
return def;
}
return NULL;
}
boolean S_SetMusicLoopPoint(UINT32 looppoint) boolean S_SetMusicLoopPoint(UINT32 looppoint)
{ {
return I_SetSongLoopPoint(looppoint); return I_SetSongLoopPoint(looppoint);
...@@ -1910,7 +1968,7 @@ static void S_AddMusicStackEntry(const char *mname, UINT16 mflags, boolean loopi ...@@ -1910,7 +1968,7 @@ static void S_AddMusicStackEntry(const char *mname, UINT16 mflags, boolean loopi
if (!music_stacks) if (!music_stacks)
{ {
music_stacks = Z_Calloc(sizeof (*mst), PU_MUSIC, NULL); music_stacks = Z_Calloc(sizeof (*mst), PU_MUSIC, NULL);
strncpy(music_stacks->musname, (status == JT_MASTER ? mname : (S_CheckQueue() ? queue_name : mapmusname)), 7); strncpy(music_stacks->musname, (status == JT_MASTER ? mname : (S_CheckQueue() ? queue_name : mapmusname)), sizeof(music_stacks->musname)-1);
music_stacks->musflags = (status == JT_MASTER ? mflags : (S_CheckQueue() ? queue_flags : mapmusflags)); music_stacks->musflags = (status == JT_MASTER ? mflags : (S_CheckQueue() ? queue_flags : mapmusflags));
music_stacks->looping = (status == JT_MASTER ? looping : (S_CheckQueue() ? queue_looping : true)); music_stacks->looping = (status == JT_MASTER ? looping : (S_CheckQueue() ? queue_looping : true));
music_stacks->position = (status == JT_MASTER ? position : (S_CheckQueue() ? queue_position : S_GetMusicPosition())); music_stacks->position = (status == JT_MASTER ? position : (S_CheckQueue() ? queue_position : S_GetMusicPosition()));
...@@ -2033,7 +2091,7 @@ boolean S_RecallMusic(UINT16 status, boolean fromfirst) ...@@ -2033,7 +2091,7 @@ boolean S_RecallMusic(UINT16 status, boolean fromfirst)
if (result) if (result)
{ {
*entry = *result; *entry = *result;
strncpy(entry->musname, result->musname, 7); memcpy(entry->musname, result->musname, sizeof(entry->musname));
} }
// no result, just grab mapmusname // no result, just grab mapmusname
...@@ -2227,7 +2285,8 @@ static boolean S_CheckQueue(void) ...@@ -2227,7 +2285,8 @@ static boolean S_CheckQueue(void)
static void S_ClearQueue(void) static void S_ClearQueue(void)
{ {
queue_name[0] = queue_flags = queue_looping = queue_position = queue_fadeinms = 0; queue_name[0] = queue_flags = queue_position = queue_fadeinms = 0;
queue_looping = false;
} }
static void S_ChangeMusicToQueue(void) static void S_ChangeMusicToQueue(void)
...@@ -2255,10 +2314,10 @@ void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 ...@@ -2255,10 +2314,10 @@ void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32
if (S_MusicDisabled()) if (S_MusicDisabled())
return; return;
strncpy(newmusic, mmusic, 7); strncpy(newmusic, mmusic, sizeof(newmusic)-1);
newmusic[6] = 0;
if (LUA_HookMusicChange(music_name, &hook_param)) if (LUA_HookMusicChange(music_name, &hook_param))
return; return;
newmusic[6] = 0;
// No Music (empty string) // No Music (empty string)
if (newmusic[0] == 0) if (newmusic[0] == 0)
...@@ -2494,11 +2553,11 @@ static void Command_Tunes_f(void) ...@@ -2494,11 +2553,11 @@ static void Command_Tunes_f(void)
track = (UINT16)atoi(COM_Argv(2))-1; track = (UINT16)atoi(COM_Argv(2))-1;
strncpy(mapmusname, tunearg, 7); strncpy(mapmusname, tunearg, 7);
mapmusname[6] = 0;
if (argc > 4) if (argc > 4)
position = (UINT32)atoi(COM_Argv(4)); position = (UINT32)atoi(COM_Argv(4));
mapmusname[6] = 0;
mapmusflags = (track & MUSIC_TRACKMASK); mapmusflags = (track & MUSIC_TRACKMASK);
mapmusposition = position; mapmusposition = position;
...@@ -2539,7 +2598,7 @@ void GameSounds_OnChange(void) ...@@ -2539,7 +2598,7 @@ void GameSounds_OnChange(void)
sound_disabled = false; sound_disabled = false;
I_StartupSound(); // will return early if initialised I_StartupSound(); // will return early if initialised
S_InitSfxChannels(cv_soundvolume.value); S_InitSfxChannels(cv_soundvolume.value);
S_StartSound(NULL, sfx_strpst); S_StartSoundFromEverywhere(sfx_strpst);
} }
else else
{ {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
#include "m_fixed.h" #include "m_fixed.h"
#include "command.h" #include "command.h"
#include "tables.h" // angle_t #include "tables.h" // angle_t
#include "r_defs.h" // S_StartSoundFromSector
#include "p_mobj.h" // S_StartSoundFromMobj
#ifdef HAVE_OPENMPT #ifdef HAVE_OPENMPT
#include "libopenmpt/libopenmpt.h" #include "libopenmpt/libopenmpt.h"
...@@ -74,6 +76,14 @@ typedef enum ...@@ -74,6 +76,14 @@ typedef enum
SF_X2AWAYSOUND = 64, // Hear it from 2x the distance away SF_X2AWAYSOUND = 64, // Hear it from 2x the distance away
} soundflags_t; } soundflags_t;
typedef enum
{
SOUNDORIGIN_EVERYWHERE = -1, //Null
SOUNDORIGIN_MOBJ = 0, //Mobj
SOUNDORIGIN_SECTOR = 1, //Sector
} soundorigin_t;
typedef struct { typedef struct {
fixed_t x, y, z; fixed_t x, y, z;
angle_t angle; angle_t angle;
...@@ -142,10 +152,16 @@ boolean S_SoundDisabled(void); ...@@ -142,10 +152,16 @@ boolean S_SoundDisabled(void);
// //
// Start sound for thing at <origin> using <sound_id> from sounds.h // Start sound for thing at <origin> using <sound_id> from sounds.h
// //
void S_StartSound(const void *origin, sfxenum_t sound_id); void S_StartSound(void *origin, sfxenum_t sound_id, soundorigin_t soundorigin);
void S_StartSoundFromEverywhere(sfxenum_t sound_id);
void S_StartSoundFromMobj(mobj_t *origin, sfxenum_t sound_id);
void S_StartSoundFromSector(sector_t *origin, sfxenum_t sound_id);
// Will start a sound at a given volume. // Will start a sound at a given volume.
void S_StartSoundAtVolume(const void *origin, sfxenum_t sound_id, INT32 volume); void S_StartSoundAtVolume(void *origin, sfxenum_t sound_id, INT32 volume, soundorigin_t soundorigin);
void S_StartSoundFromEverywhereVol(sfxenum_t sfx_id, INT32 volume);
void S_StartSoundFromMobjVol(mobj_t* origin, sfxenum_t sfx_id, INT32 volume);
void S_StartSoundFromSectorVol(sector_t* origin, sfxenum_t sfx_id, INT32 volume);
// Stop sound for thing at <origin> // Stop sound for thing at <origin>
void S_StopSound(void *origin); void S_StopSound(void *origin);
...@@ -220,6 +236,9 @@ boolean S_PrepareSoundTest(void); ...@@ -220,6 +236,9 @@ boolean S_PrepareSoundTest(void);
// Get Length of Music // Get Length of Music
UINT32 S_GetMusicLength(void); UINT32 S_GetMusicLength(void);
// Get MUSICDEF of Music
musicdef_t *S_MusicInfo(const char *name);
// Set LoopPoint of Music // Set LoopPoint of Music
boolean S_SetMusicLoopPoint(UINT32 looppoint); boolean S_SetMusicLoopPoint(UINT32 looppoint);
...@@ -238,7 +257,7 @@ UINT32 S_GetMusicPosition(void); ...@@ -238,7 +257,7 @@ UINT32 S_GetMusicPosition(void);
typedef struct musicstack_s typedef struct musicstack_s
{ {
char musname[7]; char musname[7+1];
UINT16 musflags; UINT16 musflags;
boolean looping; boolean looping;
UINT32 position; UINT32 position;
...@@ -325,8 +344,8 @@ void S_StopSoundByID(void *origin, sfxenum_t sfx_id); ...@@ -325,8 +344,8 @@ void S_StopSoundByID(void *origin, sfxenum_t sfx_id);
void S_StopSoundByNum(sfxenum_t sfxnum); void S_StopSoundByNum(sfxenum_t sfxnum);
#ifndef HW3SOUND #ifndef HW3SOUND
#define S_StartAttackSound S_StartSound #define S_StartAttackSound S_StartSoundFromMobj
#define S_StartScreamSound S_StartSound #define S_StartScreamSound S_StartSoundFromMobj
#endif #endif
#endif #endif
// SONIC ROBO BLAST 2 // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -44,6 +44,8 @@ ...@@ -44,6 +44,8 @@
// SRB2Kart // SRB2Kart
#include "r_fps.h" // R_GetFramerateCap #include "r_fps.h" // R_GetFramerateCap
#include "lua_hud.h" // LUA_HudEnabled
// -------------------------------------------- // --------------------------------------------
// assembly or c drawer routines for 8bpp/16bpp // assembly or c drawer routines for 8bpp/16bpp
// -------------------------------------------- // --------------------------------------------
...@@ -70,11 +72,6 @@ consvar_t cv_scr_width_w = CVAR_INIT ("scr_width_w", "640", CV_SAVE, CV_Unsigned ...@@ -70,11 +72,6 @@ consvar_t cv_scr_width_w = CVAR_INIT ("scr_width_w", "640", CV_SAVE, CV_Unsigned
consvar_t cv_scr_height_w = CVAR_INIT ("scr_height_w", "400", CV_SAVE, CV_Unsigned, NULL); consvar_t cv_scr_height_w = CVAR_INIT ("scr_height_w", "400", CV_SAVE, CV_Unsigned, NULL);
consvar_t cv_scr_depth = CVAR_INIT ("scr_depth", "16 bits", CV_SAVE, scr_depth_cons_t, NULL); consvar_t cv_scr_depth = CVAR_INIT ("scr_depth", "16 bits", CV_SAVE, scr_depth_cons_t, NULL);
consvar_t cv_renderview = CVAR_INIT ("renderview", "On", 0, CV_OnOff, NULL);
consvar_t cv_renderwalls = CVAR_INIT ("renderwalls", "On", CV_NOTINNET|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_renderfloors = CVAR_INIT ("renderfloors", "On", CV_NOTINNET|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_renderthings = CVAR_INIT ("renderthings", "On", CV_NOTINNET|CV_CHEAT, CV_OnOff, NULL);
CV_PossibleValue_t cv_renderer_t[] = { CV_PossibleValue_t cv_renderer_t[] = {
{1, "Software"}, {1, "Software"},
#ifdef HWRENDER #ifdef HWRENDER
...@@ -115,6 +112,10 @@ void SCR_SetDrawFuncs(void) ...@@ -115,6 +112,10 @@ void SCR_SetDrawFuncs(void)
colfuncs[COLDRAWFUNC_SHADE] = R_DrawShadeColumn_8; colfuncs[COLDRAWFUNC_SHADE] = R_DrawShadeColumn_8;
colfuncs[COLDRAWFUNC_SHADOWED] = R_DrawColumnShadowed_8; colfuncs[COLDRAWFUNC_SHADOWED] = R_DrawColumnShadowed_8;
colfuncs[COLDRAWFUNC_TRANSTRANS] = R_DrawTranslatedTranslucentColumn_8; colfuncs[COLDRAWFUNC_TRANSTRANS] = R_DrawTranslatedTranslucentColumn_8;
colfuncs[COLDRAWFUNC_CLAMPED] = R_DrawColumnClamped_8;
colfuncs[COLDRAWFUNC_CLAMPEDTRANS] = R_DrawTranslucentColumnClamped_8;
colfuncs[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn_8;
colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS] = R_Draw2sMultiPatchTranslucentColumn_8;
colfuncs[COLDRAWFUNC_FOG] = R_DrawFogColumn_8; colfuncs[COLDRAWFUNC_FOG] = R_DrawFogColumn_8;
spanfuncs[SPANDRAWFUNC_TRANS] = R_DrawTranslucentSpan_8; spanfuncs[SPANDRAWFUNC_TRANS] = R_DrawTranslucentSpan_8;
...@@ -123,6 +124,7 @@ void SCR_SetDrawFuncs(void) ...@@ -123,6 +124,7 @@ void SCR_SetDrawFuncs(void)
spanfuncs[SPANDRAWFUNC_SPLAT] = R_DrawSplat_8; spanfuncs[SPANDRAWFUNC_SPLAT] = R_DrawSplat_8;
spanfuncs[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_8; spanfuncs[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_8;
spanfuncs[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawTiltedSplat_8; spanfuncs[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawTiltedSplat_8;
spanfuncs[SPANDRAWFUNC_TILTEDTRANSSPLAT] = R_DrawTiltedTranslucentSplat_8;
spanfuncs[SPANDRAWFUNC_SPRITE] = R_DrawFloorSprite_8; spanfuncs[SPANDRAWFUNC_SPRITE] = R_DrawFloorSprite_8;
spanfuncs[SPANDRAWFUNC_TRANSSPRITE] = R_DrawTranslucentFloorSprite_8; spanfuncs[SPANDRAWFUNC_TRANSSPRITE] = R_DrawTranslucentFloorSprite_8;
spanfuncs[SPANDRAWFUNC_TILTEDSPRITE] = R_DrawTiltedFloorSprite_8; spanfuncs[SPANDRAWFUNC_TILTEDSPRITE] = R_DrawTiltedFloorSprite_8;
...@@ -145,6 +147,7 @@ void SCR_SetDrawFuncs(void) ...@@ -145,6 +147,7 @@ void SCR_SetDrawFuncs(void)
spanfuncs_npo2[SPANDRAWFUNC_SPLAT] = R_DrawSplat_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_SPLAT] = R_DrawSplat_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawTiltedSplat_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawTiltedSplat_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TILTEDTRANSSPLAT] = R_DrawTiltedTranslucentSplat_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_SPRITE] = R_DrawFloorSprite_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_SPRITE] = R_DrawFloorSprite_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TRANSSPRITE] = R_DrawTranslucentFloorSprite_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TRANSSPRITE] = R_DrawTranslucentFloorSprite_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TILTEDSPRITE] = R_DrawTiltedFloorSprite_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TILTEDSPRITE] = R_DrawTiltedFloorSprite_NPO2_8;
...@@ -492,10 +495,9 @@ void SCR_ClosedCaptions(void) ...@@ -492,10 +495,9 @@ void SCR_ClosedCaptions(void)
basey -= 42; basey -= 42;
else if (splitscreen) else if (splitscreen)
basey -= 8; basey -= 8;
else if ((modeattacking == ATTACKING_NIGHTS) else if (LUA_HudEnabled(hud_powerups)
|| (!(maptol & TOL_NIGHTS)
&& ((cv_powerupdisplay.value == 2) // "Always" && ((cv_powerupdisplay.value == 2) // "Always"
|| (cv_powerupdisplay.value == 1 && !camera.chase)))) // "First-person only" || (cv_powerupdisplay.value == 1 && !camera.chase))) // "First-person only"
basey -= 16; basey -= 16;
} }
......
// SONIC ROBO BLAST 2 // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -30,10 +30,6 @@ ...@@ -30,10 +30,6 @@
#define NUMSCREENS 5 #define NUMSCREENS 5
#endif #endif
// Size of statusbar.
#define ST_HEIGHT 32
#define ST_WIDTH 320
// used now as a maximum video mode size for extra vesa modes. // used now as a maximum video mode size for extra vesa modes.
// we try to re-allocate a minimum of buffers for stability of the memory, // we try to re-allocate a minimum of buffers for stability of the memory,
...@@ -97,6 +93,10 @@ enum ...@@ -97,6 +93,10 @@ enum
COLDRAWFUNC_SHADE, COLDRAWFUNC_SHADE,
COLDRAWFUNC_SHADOWED, COLDRAWFUNC_SHADOWED,
COLDRAWFUNC_TRANSTRANS, COLDRAWFUNC_TRANSTRANS,
COLDRAWFUNC_CLAMPED,
COLDRAWFUNC_CLAMPEDTRANS,
COLDRAWFUNC_TWOSMULTIPATCH,
COLDRAWFUNC_TWOSMULTIPATCHTRANS,
COLDRAWFUNC_FOG, COLDRAWFUNC_FOG,
COLDRAWFUNC_MAX COLDRAWFUNC_MAX
...@@ -115,6 +115,7 @@ enum ...@@ -115,6 +115,7 @@ enum
SPANDRAWFUNC_SPLAT, SPANDRAWFUNC_SPLAT,
SPANDRAWFUNC_TRANSSPLAT, SPANDRAWFUNC_TRANSSPLAT,
SPANDRAWFUNC_TILTEDSPLAT, SPANDRAWFUNC_TILTEDSPLAT,
SPANDRAWFUNC_TILTEDTRANSSPLAT,
SPANDRAWFUNC_SPRITE, SPANDRAWFUNC_SPRITE,
SPANDRAWFUNC_TRANSSPRITE, SPANDRAWFUNC_TRANSSPRITE,
...@@ -157,9 +158,7 @@ extern CV_PossibleValue_t cv_renderer_t[]; ...@@ -157,9 +158,7 @@ extern CV_PossibleValue_t cv_renderer_t[];
extern INT32 scr_bpp; extern INT32 scr_bpp;
extern consvar_t cv_scr_width, cv_scr_height, cv_scr_width_w, cv_scr_height_w, cv_scr_depth, cv_fullscreen; extern consvar_t cv_scr_width, cv_scr_height, cv_scr_width_w, cv_scr_height_w, cv_scr_depth, cv_fullscreen;
extern consvar_t cv_renderwalls, cv_renderfloors, cv_renderthings; extern consvar_t cv_renderer;
extern consvar_t cv_renderview, cv_renderer;
extern consvar_t cv_renderhitbox, cv_renderhitboxinterpolation, cv_renderhitboxgldepth;
// wait for page flipping to end or not // wait for page flipping to end or not
extern consvar_t cv_vidwait; extern consvar_t cv_vidwait;
extern consvar_t cv_timescale; extern consvar_t cv_timescale;
......
# Declare SDL2 interface sources # Declare SDL2 interface sources
target_sources(SRB2SDL2 PRIVATE target_sources(SRB2SDL2 PRIVATE
mixer_sound.c
ogl_sdl.c ogl_sdl.c
i_threads.c i_threads.c
i_net.c i_net.c
...@@ -13,6 +12,164 @@ target_sources(SRB2SDL2 PRIVATE ...@@ -13,6 +12,164 @@ target_sources(SRB2SDL2 PRIVATE
hwsym_sdl.c hwsym_sdl.c
) )
# Compatibility flag with later versions of GCC
# We should really fix our code to not need this
if (NOT SRB2_CONFIG_FORCE_NO_MS_BITFIELDS)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
check_cxx_compiler_flag("-mno-ms-bitfields" HAS_NO_MS_BITFIELDS)
if(HAS_NO_MS_BITFIELDS)
target_compile_options(SRB2SDL2 PRIVATE -mno-ms-bitfields)
endif()
endif()
endif()
# Yes we know we use insecure CRT functions...
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
target_compile_definitions(SRB2SDL2 PRIVATE -D_CRT_SECURE_NO_WARNINGS)
endif()
# Compiler warnings configuration
target_compile_options(SRB2SDL2 PRIVATE
# Using generator expressions to handle per-language compile options
# C, GNU
# This is a direct translation from versions.mk
$<$<AND:$<COMPILE_LANGUAGE:C>,$<C_COMPILER_ID:GNU>>:
-Wall
-Wno-trigraphs
-W # Was controlled by RELAXWARNINGS
-Wfloat-equal
-Wundef
-Wpointer-arith
-Wbad-function-cast
-Wcast-qual
-Wcast-align # Was controlled by NOCASTALIGNWARN
-Wwrite-strings
-Wsign-compare
-Wmissing-prototypes
-Wmissing-declarations
-Wmissing-noreturn
-Winline
-Wformat-y2k
-Wformat-security
$<$<VERSION_LESS:$<C_COMPILER_VERSION>,2.9.5>:
-Wno-div-by-zero
-Wendif-labels
-Wdisabled-optimization
>
$<$<VERSION_GREATER_EQUAL:$<C_COMPILER_VERSION>,4.0.0>:
-Wold-style-definition
-Wmissing-field-initializers
>
$<$<VERSION_GREATER_EQUAL:$<C_COMPILER_VERSION>,4.1.0>:
-Wshadow
>
$<$<VERSION_GREATER_EQUAL:$<C_COMPILER_VERSION>,4.3.0>:
-funit-at-a-time
-Wlogical-op
>
$<$<VERSION_GREATER_EQUAL:$<C_COMPILER_VERSION>,4.5.0>:
-Wlogical-op
-Wno-error=array-bounds
>
$<$<VERSION_GREATER_EQUAL:$<C_COMPILER_VERSION>,4.6.0>:
-Wno-suggest-attribute=noreturn
-Wno-error=suggest-attribute=noreturn
-Werror=vla
>
$<$<VERSION_GREATER_EQUAL:$<C_COMPILER_VERSION>,5.4.0>:
-Wno-logical-op
-Wno-error=logical-op
>
$<$<VERSION_GREATER_EQUAL:$<C_COMPILER_VERSION>,6.1.0>:
-Wno-tautological-compare
-Wno-error=tautological-compare
>
$<$<VERSION_GREATER_EQUAL:$<C_COMPILER_VERSION>,7.1.0>:
-Wno-error=format-overflow=2
-Wimplicit-fallthrough=4
>
$<$<VERSION_GREATER_EQUAL:$<C_COMPILER_VERSION>,8.1.0>:
-Wno-error=format-overflow
-Wno-error=stringop-truncation
-Wno-error=stringop-overflow
-Wno-format-overflow
-Wno-stringop-truncation
-Wno-stringop-overflow
-Wno-error=multistatement-macros
>
$<$<VERSION_GREATER_EQUAL:$<C_COMPILER_VERSION>,9.1.0>:
-Wno-error=address-of-packed-member
>
>
# C, Clang and Apple Clang
$<$<AND:$<COMPILE_LANGUAGE:C>,$<OR:$<C_COMPILER_ID:AppleClang>,$<C_COMPILER_ID:Clang>>>:
-Wall
-Wno-absolute-value
-Wno-trigraphs
-Wno-error=non-literal-null-conversion
-Wno-error=constant-conversion
-Wno-unused-but-set-variable
-Wno-error=unused-but-set-variable
-Wno-shorten-64-to-32
>
# C, MSVC
$<$<AND:$<COMPILE_LANGUAGE:C>,$<C_COMPILER_ID:MSVC>>:
# All warnings at and before Visual Studio 2019 RTM
# https://learn.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warnings-by-compiler-version?view=msvc-170
/Wv:19.20.27004.0
>
# C++, GNU, Clang and Apple Clang
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<OR:$<C_COMPILER_ID:GNU>,$<C_COMPILER_ID:AppleClang>,$<C_COMPILER_ID:Clang>>>:
-Wall
-Wno-unused-function
-Wno-unused-but-set-variable
-Wno-unused-private-field
>
# C++, MSVC
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<C_COMPILER_ID:MSVC>>:
/Wv:19.20.27004.0
>
# GNU
$<$<C_COMPILER_ID:GNU>:
-fmax-errors=5
>
)
if(SRB2_CONFIG_ERRORMODE)
target_compile_options(SRB2SDL2 PRIVATE
$<$<OR:$<C_COMPILER_ID:GNU>,$<C_COMPILER_ID:AppleClang>,$<C_COMPILER_ID:Clang>>:
-Werror
>
$<$<C_COMPILER_ID:MSVC>:
/WX
>
)
endif()
# Link warnings configuration
target_link_options(SRB2SDL2 PRIVATE
$<$<C_COMPILER_ID:GNU>:
# -Wl,--as-needed - Was controlled by NOLDWARNING
>
)
if("${CMAKE_SYSTEM_NAME}" MATCHES Windows) if("${CMAKE_SYSTEM_NAME}" MATCHES Windows)
target_sources(SRB2SDL2 PRIVATE target_sources(SRB2SDL2 PRIVATE
../win32/win_dbg.c ../win32/win_dbg.c
...@@ -62,12 +219,6 @@ if("${CMAKE_SYSTEM_NAME}" MATCHES Windows) ...@@ -62,12 +219,6 @@ if("${CMAKE_SYSTEM_NAME}" MATCHES Windows)
target_link_libraries(SRB2SDL2 PRIVATE SDL2::SDL2main) target_link_libraries(SRB2SDL2 PRIVATE SDL2::SDL2main)
endif() endif()
if(NOT "${SRB2_CONFIG_SYSTEM_LIBRARIES}" AND NOT "${SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES}")
target_link_libraries(SRB2SDL2 PRIVATE SDL2::SDL2-static SDL2_mixer::SDL2_mixer-static)
else()
target_link_libraries(SRB2SDL2 PRIVATE SDL2::SDL2 SDL2_mixer::SDL2_mixer)
endif()
if("${CMAKE_SYSTEM_NAME}" MATCHES Linux) if("${CMAKE_SYSTEM_NAME}" MATCHES Linux)
target_link_libraries(SRB2SDL2 PRIVATE m rt) target_link_libraries(SRB2SDL2 PRIVATE m rt)
endif() endif()
...@@ -81,8 +232,84 @@ if("${CMAKE_SYSTEM_NAME}" MATCHES Windows) ...@@ -81,8 +232,84 @@ if("${CMAKE_SYSTEM_NAME}" MATCHES Windows)
) )
endif() endif()
target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_MIXER -DSOUND=SOUND_MIXER) find_package(SDL2 CONFIG REQUIRED)
find_package(SDL2 REQUIRED)
if(TARGET SDL2main)
target_link_libraries(SRB2SDL2 PRIVATE SDL2main)
endif()
target_compile_definitions(SRB2SDL2 PRIVATE -DDIRECTFULLSCREEN -DHAVE_SDL) target_compile_definitions(SRB2SDL2 PRIVATE -DDIRECTFULLSCREEN -DHAVE_SDL)
target_include_directories(SRB2SDL2 PRIVATE ${SDL2_INCLUDE_DIR})
find_package(SDL2_mixer_ext CONFIG QUIET)
find_package(SDL2_mixer_ext QUIET)
if(TARGET SDL2_mixer_ext::SDL2_mixer_ext OR TARGET SDL2_mixer_ext::SDL2_mixer_ext_Static OR TARGET SDL2_mixer_ext OR TARGET SDL2_mixer_ext_Static)
if(NOT TARGET SDL2_mixer_ext::SDL2_mixer_ext_Static AND TARGET SDL2_mixer_ext_Static)
add_library(SDL2_mixer_ext::SDL2_mixer_ext_Static ALIAS SDL2_mixer_ext_Static)
endif()
if(NOT TARGET SDL2_mixer_ext::SDL2_mixer_ext AND TARGET SDL2_mixer_ext)
add_library(SDL2_mixer_ext::SDL2_mixer_ext ALIAS SDL2_mixer_ext)
endif()
if(TARGET SDL2_mixer_ext::SDL2_mixer_ext OR TARGET SDL2_mixer_ext::SDL2_mixer_ext_Static)
if(TARGET SDL2_mixer_ext::SDL2_mixer_ext_Static)
target_link_libraries(SRB2SDL2 PRIVATE SDL2_mixer_ext::SDL2_mixer_ext_Static)
else()
target_link_libraries(SRB2SDL2 PRIVATE SDL2_mixer_ext::SDL2_mixer_ext)
endif()
target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_MIXER -DHAVE_MIXERX -DSOUND=SOUND_MIXER)
endif()
endif()
if(TARGET SDL2_mixer_ext::SDL2_mixer_ext OR TARGET SDL2_mixer_ext::SDL2_mixer_ext_Static)
message(STATUS "SDL2_mixer_ext found, skipping SDL2_mixer")
else()
message(STATUS "SDL2_mixer_ext not found, going to try SDL2_mixer")
find_package(SDL2_mixer CONFIG QUIET)
find_package(SDL2_mixer QUIET)
if(TARGET SDL2_mixer::SDL2_mixer OR TARGET SDL2_mixer::SDL2_mixer-static OR TARGET SDL2_mixer OR TARGET SDL2_mixer_Static)
if(NOT TARGET SDL2_mixer::SDL2_mixer-static AND TARGET SDL2_mixer_Static)
add_library(SDL2_mixer::SDL2_mixer-static ALIAS SDL2_mixer_Static)
endif()
if(NOT TARGET SDL2_mixer::SDL2_mixer AND TARGET SDL2_mixer)
add_library(SDL2_mixer::SDL2_mixer ALIAS SDL2_mixer)
endif()
if(TARGET SDL2_mixer::SDL2_mixer OR TARGET SDL2_mixer::SDL2_mixer-static)
if(TARGET SDL2_mixer::SDL2_mixer-static)
target_link_libraries(SRB2SDL2 PRIVATE SDL2_mixer::SDL2_mixer-static)
else()
target_link_libraries(SRB2SDL2 PRIVATE SDL2_mixer::SDL2_mixer)
endif()
target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_MIXER -DSOUND=SOUND_MIXER)
endif()
endif()
endif()
if(TARGET SDL2_mixer_ext::SDL2_mixer_ext OR TARGET SDL2_mixer_ext::SDL2_mixer_ext_Static OR TARGET SDL2_mixer::SDL2_mixer OR TARGET SDL2_mixer::SDL2_mixer-static)
target_sources(SRB2SDL2 PRIVATE mixer_sound.c)
target_link_libraries(SRB2SDL2 PRIVATE SDL2::SDL2)
else()
target_sources(SRB2SDL2 PRIVATE sdl_sound.c)
target_link_libraries(SRB2SDL2 PRIVATE SDL2::SDL2)
endif()
if(TARGET SDL2::SDL2)
message(STATUS "SDL2 Found")
else()
message(STATUS "no SDL2 Found")
endif()
if(TARGET SDL2::SDL2main)
message(STATUS "SDL2main Found")
else()
message(STATUS "No SDL2main Found")
endif()
if(TARGET SDL2_mixer_ext::SDL2_mixer_ext OR TARGET SDL2_mixer_ext::SDL2_mixer_ext_Static)
message(STATUS "SDL2_mixer_ext Found")
elseif(TARGET SDL2_mixer::SDL2_mixer OR TARGET SDL2_mixer::SDL2_mixer-static)
message(STATUS "SDL2_mixer found")
else()
message(STATUS "no SDL2_mixer_ext or SDL2_mixer Found")
endif()
#### Installation #### #### Installation ####
if("${CMAKE_SYSTEM_NAME}" MATCHES Darwin) if("${CMAKE_SYSTEM_NAME}" MATCHES Darwin)
......