From d280b39f9f1f65b637012a1e7ae70ef46c71dc17 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 4 Jun 2025 15:52:20 +0200 Subject: [PATCH 001/141] use floats flor slope drawing idea from srb2classic --- src/r_draw8.c | 51 ++++++++++++++++++++++++--------------------------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/src/r_draw8.c b/src/r_draw8.c index 6edc9d6a6..48e9564de 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -766,8 +766,7 @@ void R_DrawSpan_8 (void) UINT8 *restrict dest = ylookup[ds_y] + columnofs[ds_x1]; const UINT8 *restrict deststop = screens[0] + vid.rowbytes * vid.height; - register size_t count = (ds_x2 - ds_x1 + 1); - size_t i; + register intptr_t count = (ds_x2 - ds_x1 + 1); xposition = ds_xfrac; yposition = ds_yfrac; xstep = ds_xstep; ystep = ds_ystep; @@ -851,7 +850,7 @@ void R_CalcTiltedLighting(fixed_t start, fixed_t end) void R_DrawTiltedSpan_8(void) { int width = ds_x2 - ds_x1; - double iz, uz, vz; + float iz, uz, vz; UINT32 u, v; int i; @@ -859,9 +858,9 @@ void R_DrawTiltedSpan_8(void) UINT8 *colormap; register UINT8 *dest; - double startz, startu, startv; - double izstep, uzstep, vzstep; - double endz, endu, endv; + float startz, startu, startv; + float izstep, uzstep, vzstep; + float endz, endu, endv; UINT32 stepu, stepv; register UINT32 bit; @@ -954,7 +953,7 @@ void R_DrawTiltedSpan_8(void) } else { - double left = width; + float left = width; iz += ds_szp->x * left; uz += ds_sup->x * left; vz += ds_svp->x * left; @@ -989,7 +988,7 @@ void R_DrawTiltedSpan_8(void) void R_DrawTiltedTranslucentSpan_8(void) { int width = ds_x2 - ds_x1; - double iz, uz, vz; + float iz, uz, vz; UINT32 u, v; int i; @@ -997,9 +996,9 @@ void R_DrawTiltedTranslucentSpan_8(void) UINT8 *colormap; register UINT8 *dest; - double startz, startu, startv; - double izstep, uzstep, vzstep; - double endz, endu, endv; + float startz, startu, startv; + float izstep, uzstep, vzstep; + float endz, endu, endv; UINT32 stepu, stepv; register UINT32 bit; @@ -1092,7 +1091,7 @@ void R_DrawTiltedTranslucentSpan_8(void) } else { - double left = width; + float left = width; iz += ds_szp->x * left; uz += ds_sup->x * left; vz += ds_svp->x * left; @@ -1128,7 +1127,7 @@ void R_DrawTiltedTranslucentSpan_8(void) void R_DrawTiltedTranslucentWaterSpan_8(void) { int width = ds_x2 - ds_x1; - double iz, uz, vz; + float iz, uz, vz; UINT32 u, v; int i; @@ -1137,9 +1136,9 @@ void R_DrawTiltedTranslucentWaterSpan_8(void) register UINT8 *dest; UINT8 *dsrc; - double startz, startu, startv; - double izstep, uzstep, vzstep; - double endz, endu, endv; + float startz, startu, startv; + float izstep, uzstep, vzstep; + float endz, endu, endv; UINT32 stepu, stepv; register UINT32 bit; @@ -1233,7 +1232,7 @@ void R_DrawTiltedTranslucentWaterSpan_8(void) } else { - double left = width; + float left = width; iz += ds_szp->x * left; uz += ds_sup->x * left; vz += ds_svp->x * left; @@ -1267,7 +1266,7 @@ void R_DrawTiltedSplat_8(void) { // x1, x2 = ds_x1, ds_x2 int width = ds_x2 - ds_x1; - double iz, uz, vz; + float iz, uz, vz; UINT32 u, v; int i; @@ -1277,9 +1276,9 @@ void R_DrawTiltedSplat_8(void) UINT8 val; - double startz, startu, startv; - double izstep, uzstep, vzstep; - double endz, endu, endv; + float startz, startu, startv; + float izstep, uzstep, vzstep; + float endz, endu, endv; UINT32 stepu, stepv; register UINT32 bit; @@ -1385,7 +1384,7 @@ void R_DrawTiltedSplat_8(void) } else { - double left = width; + float left = width; iz += ds_szp->x * left; uz += ds_sup->x * left; vz += ds_svp->x * left; @@ -1567,8 +1566,7 @@ void R_DrawTranslucentSpan_8 (void) register UINT8 *dest; const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; - register size_t count = (ds_x2 - ds_x1 + 1); - size_t i; + register intptr_t count = (ds_x2 - ds_x1 + 1); xposition = ds_xfrac; yposition = ds_yfrac; xstep = ds_xstep; ystep = ds_ystep; @@ -1626,8 +1624,7 @@ void R_DrawTranslucentWaterSpan_8(void) register UINT8 *dest; UINT8 *dsrc; - register size_t count; - size_t i; + register intptr_t count; // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest // can be used for the fraction part. This allows calculation of the memory address in the @@ -1680,7 +1677,7 @@ void R_DrawFogSpan_8(void) UINT8 *colormap; register UINT8 *dest; - register size_t count; + register intptr_t count; colormap = ds_colormap; dest = &topleft[ds_y *vid.width + ds_x1]; -- 2.54.0 From 6153733df4598851cc4eeef5591eb618321187b8 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 4 Jun 2025 15:52:37 +0200 Subject: [PATCH 002/141] unroll span drawer loops --- src/r_draw8.c | 140 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 117 insertions(+), 23 deletions(-) diff --git a/src/r_draw8.c b/src/r_draw8.c index 48e9564de..f78ca59fe 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -785,29 +785,59 @@ void R_DrawSpan_8 (void) { return; } - while (count >= 8) { // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // have the uber complicated math to calculate it now, so that was a memory write we didn't // need! - for (i = 0; i < 8; i++) - { - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - dest[i] = colormap[source[bit]]; + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + dest[0] = colormap[source[bit]]; + xposition += xstep; + yposition += ystep; - xposition += xstep; - yposition += ystep; - } + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + dest[1] = colormap[source[bit]]; + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + dest[2] = colormap[source[bit]]; + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + dest[3] = colormap[source[bit]]; + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + dest[4] = colormap[source[bit]]; + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + dest[5] = colormap[source[bit]]; + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + dest[6] = colormap[source[bit]]; + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + dest[7] = colormap[source[bit]]; + xposition += xstep; + yposition += ystep; dest += 8; count -= 8; } + while (count-- && dest <= deststop) { bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); *dest++ = colormap[source[bit]]; - xposition += xstep; yposition += ystep; } @@ -1590,13 +1620,45 @@ void R_DrawTranslucentSpan_8 (void) // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // have the uber complicated math to calculate it now, so that was a memory write we didn't // need! - for (i = 0; i < 8; i++) - { - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - dest[i] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[i]); - xposition += xstep; - yposition += ystep; - } + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + dest[0] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[0]); + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + dest[1] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[1]); + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + dest[2] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[2]); + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + dest[3] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[3]); + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + dest[4] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[4]); + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + dest[5] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[5]); + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + dest[6] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[6]); + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + dest[7] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[7]); + xposition += xstep; + yposition += ystep; dest += 8; count -= 8; @@ -1647,13 +1709,45 @@ void R_DrawTranslucentWaterSpan_8(void) // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // have the uber complicated math to calculate it now, so that was a memory write we didn't // need! - for (i = 0; i < 8; i++) - { - bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - dest[i] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - } + bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + dest[0] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; + + bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + dest[1] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; + + bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + dest[2] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; + + bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + dest[3] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; + + bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + dest[4] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; + + bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + dest[5] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; + + bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + dest[6] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; + + bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + dest[7] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; dest += 8; count -= 8; -- 2.54.0 From 2da89f1946eee11bcdf8af81511d02060d189263 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 4 Jun 2025 15:50:33 +0200 Subject: [PATCH 003/141] remove ylookup, columnofs and topleft lookups move screens array to "vid" struct remove a bunch of unused stuff this speeds up 4 player splitscreen ever so slighty mostly just alot cleaner than the mess it was before --- src/am_map.c | 2 +- src/android/i_video.c | 1 - src/console.c | 7 -- src/d_main.c | 15 +--- src/f_wipe.c | 6 +- src/hardware/hw_draw.c | 8 +- src/m_anigif.c | 8 +- src/m_misc.c | 4 +- src/r_draw.c | 180 +++++++---------------------------------- src/r_draw.h | 14 ++-- src/r_draw8.c | 44 +++++----- src/r_main.c | 7 +- src/r_plane.c | 10 +-- src/r_things.c | 18 +---- src/screen.c | 25 ------ src/screen.h | 64 +++------------ src/sdl/i_video.c | 31 +++---- src/v_video.c | 71 +++++++--------- src/v_video.h | 5 -- src/y_inter.c | 2 +- 20 files changed, 138 insertions(+), 384 deletions(-) diff --git a/src/am_map.c b/src/am_map.c index 11b3796b0..fe0b5e9a5 100644 --- a/src/am_map.c +++ b/src/am_map.c @@ -341,7 +341,7 @@ static void AM_FrameBufferInit(void) f_x = f_y = 0; f_w = vid.width; f_h = vid.height; - am_buf = screens[0]; + am_buf = vid.screens[0]; } // diff --git a/src/android/i_video.c b/src/android/i_video.c index 8b4bee314..4db66afe0 100644 --- a/src/android/i_video.c +++ b/src/android/i_video.c @@ -46,7 +46,6 @@ INT32 VID_SetMode(INT32 modenum) vid.modenum = 0; vid.width = 320; vid.height = 240; - vid.bpp = 1; vid.buffer = android_surface; return 0; } diff --git a/src/console.c b/src/console.c index 8c1824456..bb86d444b 100644 --- a/src/console.c +++ b/src/console.c @@ -1321,13 +1321,6 @@ void CONS_Debug(INT32 debugflags, const char *fmt, ...) // void CONS_Error(const char *msg) { -#ifdef RPC_NO_WINDOWS_H - if (!graphics_started) - { - MessageBoxA(vid.WndParent, msg, "SRB2Kart Warning", MB_OK); - return; - } -#endif CONS_Printf("\x82%s", msg); // write error msg in different colour CONS_Printf(M_GetText("Press ENTER to continue\n")); diff --git a/src/d_main.c b/src/d_main.c index a47c8b756..0e93fd4b1 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -336,7 +336,6 @@ static void D_Renderview(void) if (!issplitscreen) // Initialize for P1 { viewwindowy = viewwindowx = 0; - topleft = screens[0]; objectsdrawn = 0; } @@ -350,8 +349,6 @@ static void D_Renderview(void) #endif if (issplitscreen) // Splitscreen-specific { - const INT32 len = viewheight*sizeof(ylookup[0]); - switch (i) { case 1: @@ -365,28 +362,20 @@ static void D_Renderview(void) viewwindowx = 0; viewwindowy = viewheight; } - M_Memcpy(ylookup, ylookup2, len); break; case 2: viewwindowx = 0; viewwindowy = viewheight; - M_Memcpy(ylookup, ylookup3, len); break; case 3: viewwindowx = viewwidth; viewwindowy = viewheight; - M_Memcpy(ylookup, ylookup4, len); default: break; } - - topleft = screens[0] + viewwindowy*vid.width + viewwindowx; } R_RenderPlayerView(&players[displayplayers[i]]); - - if (issplitscreen) - M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0])); } if (!issplitscreen) @@ -584,7 +573,7 @@ static boolean D_Display(void) { if (rendermode == render_soft) { - VID_BlitLinearScreen(screens[0], screens[1], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes); + VID_BlitLinearScreen(vid.screens[0], vid.screens[1], vid.width, vid.height, vid.width, vid.rowbytes); } lastdraw = false; @@ -618,7 +607,7 @@ static boolean D_Display(void) V_DrawFadeScreen(TC_RAINBOW, (leveltime & 0x20) ? SKINCOLOR_PASTEL : SKINCOLOR_MOONSLAM); // vid size change is now finished if it was on... - vid.recalc = 0; + vid.recalc = false; #ifdef HAVE_THREADS I_lock_mutex(&m_menu_mutex); diff --git a/src/f_wipe.c b/src/f_wipe.c index 1523ca1d3..cbb411b8b 100644 --- a/src/f_wipe.c +++ b/src/f_wipe.c @@ -313,7 +313,7 @@ void F_WipeStartScreen(void) return; } #endif - wipe_scr_start = screens[3]; + wipe_scr_start = vid.screens[3]; I_ReadScreen(wipe_scr_start); #endif } @@ -330,7 +330,7 @@ void F_WipeEndScreen(void) return; } #endif - wipe_scr_end = screens[4]; + wipe_scr_end = vid.screens[4]; I_ReadScreen(wipe_scr_end); V_DrawBlock(0, 0, 0, vid.width, vid.height, wipe_scr_start); #endif @@ -353,7 +353,7 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu) // Init the wipe WipeInAction = true; - wipe_scr = screens[0]; + wipe_scr = vid.screens[0]; // lastwipetic should either be 0 or the tic we last wiped // on for fade-to-black diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 7e996e083..5c13cf9ff 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -96,12 +96,12 @@ void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option) pdupx = pdupy = 2.0f; break; case V_SMALLSCALEPATCH: - pdupx = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupx); - pdupy = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupy); + pdupx = 2.0f * FIXED_TO_FLOAT(vid.smalldupx*FRACUNIT); + pdupy = 2.0f * FIXED_TO_FLOAT(vid.smalldupy*FRACUNIT); break; case V_MEDSCALEPATCH: - pdupx = 2.0f * FIXED_TO_FLOAT(vid.fmeddupx); - pdupy = 2.0f * FIXED_TO_FLOAT(vid.fmeddupy); + pdupx = 2.0f * FIXED_TO_FLOAT(vid.meddupx*FRACUNIT); + pdupy = 2.0f * FIXED_TO_FLOAT(vid.meddupx*FRACUNIT); break; } diff --git a/src/m_anigif.c b/src/m_anigif.c index 05b1f8287..2d3f9c4e6 100644 --- a/src/m_anigif.c +++ b/src/m_anigif.c @@ -495,7 +495,7 @@ static void GIF_rgbconvert(UINT8 *linear, UINT8 *scr) static void GIF_framewrite(void) { UINT8 *p; - UINT8 *movie_screen = screens[2]; + UINT8 *movie_screen = vid.screens[2]; INT32 blitx, blity, blitw, blith; if (!gifframe_data) @@ -509,7 +509,7 @@ static void GIF_framewrite(void) if (gif_optimize && gif_frames > 0) { // before blit movie_screen points to last frame, cur_screen points to this frame - UINT8 *cur_screen = screens[0]; + UINT8 *cur_screen = vid.screens[0]; GIF_optimizeregion(cur_screen, movie_screen, &blitx, &blity, &blitw, &blith); // blit to temp screen @@ -535,7 +535,7 @@ static void GIF_framewrite(void) if (rendermode == render_opengl) { UINT8 *linear = HWR_GetScreenshot(); - GIF_rgbconvert(linear, screens[0]); + GIF_rgbconvert(linear, vid.screens[0]); //free(linear); // Allocated 'statically', no need to free now } #endif @@ -545,7 +545,7 @@ static void GIF_framewrite(void) if (gif_frames == 0 && rendermode == render_soft) I_ReadScreen(movie_screen); - movie_screen = screens[0]; + movie_screen = vid.screens[0]; } // screen regions are handled in GIF_lzw diff --git a/src/m_misc.c b/src/m_misc.c index c44086f4c..62da72038 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -1236,7 +1236,7 @@ void M_SaveFrame(void) if (rendermode == render_soft) { // munge planar buffer to linear - linear = screens[2]; + linear = vid.screens[2]; I_ReadScreen(linear); } #ifdef HWRENDER @@ -1538,7 +1538,7 @@ void M_DoScreenShot(void) if (rendermode == render_soft) { // munge planar buffer to linear - linear = screens[2]; + linear = vid.screens[2]; I_ReadScreen(linear); } diff --git a/src/r_draw.c b/src/r_draw.c index d54fe90ce..f4b38e45e 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -38,34 +38,8 @@ /** \brief view info */ -INT32 viewwidth, scaledviewwidth, viewheight, viewwindowx, viewwindowy; - -/** \brief pointer to the start of each line of the screen, -*/ -UINT8 *ylookup[MAXVIDHEIGHT*4]; - -/** \brief pointer to the start of each line of the screen, for view1 (splitscreen) -*/ -UINT8 *ylookup1[MAXVIDHEIGHT*4]; - -/** \brief pointer to the start of each line of the screen, for view2 (splitscreen) -*/ -UINT8 *ylookup2[MAXVIDHEIGHT*4]; - -/** \brief pointer to the start of each line of the screen, for view3 (splitscreen) -*/ -UINT8 *ylookup3[MAXVIDHEIGHT*4]; - -/** \brief pointer to the start of each line of the screen, for view4 (splitscreen) -*/ -UINT8 *ylookup4[MAXVIDHEIGHT*4]; - -/** \brief x byte offset for columns inside the viewwindow, - so the first column starts at (SCRWIDTH - VIEWWIDTH)/2 -*/ -INT32 columnofs[MAXVIDWIDTH*4]; - -UINT8 *topleft; +INT32 linesize, viewwidth, scaledviewwidth, viewheight, viewwindowx, viewwindowy; +UINT8 *renderscreen; // haleyjd // ========================================================================= // COLUMN DRAWING CODE STUFF @@ -147,71 +121,6 @@ UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask; static UINT8 **translationtablecache[TT_CACHE_SIZE] = {NULL}; static UINT8 **localtranslationtablecache[MAXLOCALSKINS] = {NULL}; - -// See also the enum skincolors_t -// TODO Callum: Can this be translated? -/* -const char *Color_Names[MAXSKINCOLORS] = -{ - "None", // SKINCOLOR_NONE - "White", // SKINCOLOR_WHITE - "Silver", // SKINCOLOR_SILVER - "Grey", // SKINCOLOR_GREY - "Black", // SKINCOLOR_BLACK - "Cyan", // SKINCOLOR_CYAN - "Teal", // SKINCOLOR_TEAL - "Steel_Blue",// SKINCOLOR_STEEL - "Blue", // SKINCOLOR_BLUE - "Peach", // SKINCOLOR_PEACH - "Tan", // SKINCOLOR_TAN - "Pink", // SKINCOLOR_PINK - "Lavender", // SKINCOLOR_LAVENDER - "Purple", // SKINCOLOR_PURPLE - "Orange", // SKINCOLOR_ORANGE - "Rosewood", // SKINCOLOR_ROSEWOOD - "Beige", // SKINCOLOR_BEIGE - "Brown", // SKINCOLOR_BROWN - "Red", // SKINCOLOR_RED - "Dark_Red", // SKINCOLOR_DARKRED - "Neon_Green",// SKINCOLOR_NEONGREEN - "Green", // SKINCOLOR_GREEN - "Zim", // SKINCOLOR_ZIM - "Olive", // SKINCOLOR_OLIVE - "Yellow", // SKINCOLOR_YELLOW - "Gold" // SKINCOLOR_GOLD -}; - -const UINT8 Color_Opposite[MAXSKINCOLORS*2] = -{ - SKINCOLOR_NONE,8, // SKINCOLOR_NONE - SKINCOLOR_BLACK,10, // SKINCOLOR_WHITE - SKINCOLOR_GREY,4, // SKINCOLOR_SILVER - SKINCOLOR_SILVER,12,// SKINCOLOR_GREY - SKINCOLOR_WHITE,8, // SKINCOLOR_BLACK - SKINCOLOR_NONE,8, // SKINCOLOR_CYAN - SKINCOLOR_NONE,8, // SKINCOLOR_TEAL - SKINCOLOR_NONE,8, // SKINCOLOR_STEEL - SKINCOLOR_ORANGE,9, // SKINCOLOR_BLUE - SKINCOLOR_NONE,8, // SKINCOLOR_PEACH - SKINCOLOR_NONE,8, // SKINCOLOR_TAN - SKINCOLOR_NONE,8, // SKINCOLOR_PINK - SKINCOLOR_NONE,8, // SKINCOLOR_LAVENDER - SKINCOLOR_NONE,8, // SKINCOLOR_PURPLE - SKINCOLOR_BLUE,12, // SKINCOLOR_ORANGE - SKINCOLOR_NONE,8, // SKINCOLOR_ROSEWOOD - SKINCOLOR_NONE,8, // SKINCOLOR_BEIGE - SKINCOLOR_NONE,8, // SKINCOLOR_BROWN - SKINCOLOR_GREEN,5, // SKINCOLOR_RED - SKINCOLOR_NONE,8, // SKINCOLOR_DARKRED - SKINCOLOR_NONE,8, // SKINCOLOR_NEONGREEN - SKINCOLOR_RED,11, // SKINCOLOR_GREEN - SKINCOLOR_PURPLE,3, // SKINCOLOR_ZIM - SKINCOLOR_NONE,8, // SKINCOLOR_OLIVE - SKINCOLOR_NONE,8, // SKINCOLOR_YELLOW - SKINCOLOR_NONE,8 // SKINCOLOR_GOLD -}; -*/ - CV_PossibleValue_t Color_cons_t[MAXSKINCOLORS+1]; /** \brief Initializes the translucency tables used by the Software renderer. @@ -540,19 +449,6 @@ void R_FlushTranslationColormapCache(void) memset(localtranslationtablecache[i], 0, MAXTRANSLATIONS * sizeof(UINT8**)); } -/* -UINT8 R_GetColorByName(const char *name) -{ - UINT8 color = (UINT8)atoi(name); - if (color > 0 && color < MAXSKINCOLORS) - return color; - for (color = 1; color < MAXSKINCOLORS; color++) - if (!stricmp(Color_Names[color], name)) - return color; - return 0; -} -*/ - // ========================================================================== // COMMON DRAWER FOR 8 AND 16 BIT COLOR MODES // ========================================================================== @@ -572,39 +468,20 @@ UINT8 R_GetColorByName(const char *name) \param height hieght of buffer \return void - - */ void R_InitViewBuffer(INT32 width, INT32 height) { - INT32 i, bytesperpixel = vid.bpp; - if (width > MAXVIDWIDTH) width = MAXVIDWIDTH; if (height > MAXVIDHEIGHT) height = MAXVIDHEIGHT; - if (bytesperpixel < 1 || bytesperpixel > 4) - I_Error("R_InitViewBuffer: wrong bytesperpixel value %d\n", bytesperpixel); viewwindowx = 0; viewwindowy = 0; - // Column offset for those columns of the view window, but relative to the entire screen - for (i = 0; i < width; i++) - columnofs[i] = (viewwindowx + i) * bytesperpixel; - - // Precalculate all row offsets. - for (i = 0; i < height; i++) - { - ylookup[i] = ylookup1[i] = screens[0] + i*vid.width*bytesperpixel; - if (splitscreen == 1) - ylookup2[i] = screens[0] + (i+viewheight)*vid.width*bytesperpixel; - else - ylookup2[i] = screens[0] + i*vid.width*bytesperpixel + (viewwidth*bytesperpixel); - ylookup3[i] = screens[0] + (i+viewheight)*vid.width*bytesperpixel; - ylookup4[i] = screens[0] + (i+viewheight)*vid.width*bytesperpixel + (viewwidth*bytesperpixel); - } + linesize = vid.width; // killough 11/98 + renderscreen = vid.screens[0]; // haleyjd 07/02/14 } /** \brief viewborder patches lump numbers @@ -626,6 +503,28 @@ void R_InitViewBorder(void) viewborderlump[BRDR_BR] = W_GetNumForName("brdr_br"); } +/** \brief The R_VideoErase function + + Copy a screen buffer. + + \param ofs offest from buffer + \param count bytes to erase + + \return void + + +*/ +void R_VideoErase(size_t ofs, INT32 count) +{ + // LFB copy. + // This might not be a good idea if memcpy + // is not optimal, e.g. byte by byte on + // a 32bit CPU, as GNU GCC/Linux libc did + // at one point. + M_Memcpy(vid.screens[0] + ofs, vid.screens[1] + ofs, count); +} + + #if 0 /** \brief R_FillBackScreen @@ -648,7 +547,7 @@ void R_FillBackScreen(void) return; src = scr_borderpatch; - dest = screens[1]; + dest = vid.screens[1]; for (y = 0; y < vid.height; y++) { @@ -699,30 +598,7 @@ void R_FillBackScreen(void) V_DrawPatch(viewwindowx + scaledviewwidth, viewwindowy + viewheight, 1, W_CacheLumpNum(viewborderlump[BRDR_BR], PU_CACHE)); } -#endif -/** \brief The R_VideoErase function - - Copy a screen buffer. - - \param ofs offest from buffer - \param count bytes to erase - - \return void - - -*/ -void R_VideoErase(size_t ofs, INT32 count) -{ - // LFB copy. - // This might not be a good idea if memcpy - // is not optimal, e.g. byte by byte on - // a 32bit CPU, as GNU GCC/Linux libc did - // at one point. - M_Memcpy(screens[0] + ofs, screens[1] + ofs, count); -} - -#if 0 /** \brief The R_DrawViewBorder Draws the border around the view @@ -766,7 +642,7 @@ void R_DrawViewBorder(void) side <<= 1; // simpler using our VID_Blit routine - VID_BlitLinearScreen(screens[1] + ofs, screens[0] + ofs, side, viewheight - 1, + VID_BlitLinearScreen(vid.screens[1] + ofs, vid.screens[0] + ofs, side, viewheight - 1, vid.width, vid.width); } #endif diff --git a/src/r_draw.h b/src/r_draw.h index 6e5758dd5..f99c1d892 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -20,13 +20,13 @@ // ------------------------------- // COMMON STUFF FOR 8bpp AND 16bpp // ------------------------------- -extern UINT8 *ylookup[MAXVIDHEIGHT*4]; -extern UINT8 *ylookup1[MAXVIDHEIGHT*4]; -extern UINT8 *ylookup2[MAXVIDHEIGHT*4]; -extern UINT8 *ylookup3[MAXVIDHEIGHT*4]; -extern UINT8 *ylookup4[MAXVIDHEIGHT*4]; -extern INT32 columnofs[MAXVIDWIDTH*4]; -extern UINT8 *topleft; +extern UINT8 *renderscreen; +extern INT32 linesize; + +FUNCINLINE static ATTRINLINE UINT8 *R_Address(INT32 px, INT32 py) +{ + return renderscreen + (py + viewwindowy) * linesize + (viewwindowx + px); +} // ------------------------- // COLUMN DRAWING CODE STUFF diff --git a/src/r_draw8.c b/src/r_draw8.c index f78ca59fe..c98203a9e 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -47,7 +47,7 @@ void R_DrawColumn_8(void) // Framebuffer destination address. // Use ylookup LUT to avoid multiply with ScreenWidth. // Use columnofs LUT for subwindows? - dest = &topleft[dc_yl*vid.width + dc_x]; + dest = R_Address(dc_x, dc_yl); count++; @@ -172,7 +172,7 @@ void R_Draw2sMultiPatchColumn_8(void) // Framebuffer destination address. // Use ylookup LUT to avoid multiply with ScreenWidth. // Use columnofs LUT for subwindows? - dest = &topleft[dc_yl*vid.width + dc_x]; + dest = R_Address(dc_x, dc_yl); count++; @@ -314,7 +314,7 @@ void R_Draw2sMultiPatchTranslucentColumn_8(void) // Framebuffer destination address. // Use ylookup LUT to avoid multiply with ScreenWidth. // Use columnofs LUT for subwindows? - dest = &topleft[dc_yl*vid.width + dc_x]; + dest = R_Address(dc_x, dc_yl); count++; @@ -458,7 +458,7 @@ void R_DrawShadeColumn_8(void) } // FIXME. As above. - dest = &topleft[dc_yl*vid.width + dc_x]; + dest = R_Address(dc_x, dc_yl); // Looks familiar. fracstep = dc_iscale; @@ -501,7 +501,7 @@ void R_DrawTranslucentColumn_8(void) } // FIXME. As above. - dest = &topleft[dc_yl*vid.width + dc_x]; + dest = R_Address(dc_x, dc_yl); // Looks familiar. fracstep = dc_iscale; @@ -613,7 +613,7 @@ void R_DrawTranslatedTranslucentColumn_8(void) } // FIXME. As above. - dest = &topleft[dc_yl*vid.width + dc_x]; + dest = R_Address(dc_x, dc_yl); // Looks familiar. fracstep = dc_iscale; @@ -719,7 +719,7 @@ void R_DrawTranslatedColumn_8(void) } // FIXME. As above. - dest = &topleft[dc_yl*vid.width + dc_x]; + dest = R_Address(dc_x, dc_yl); // Looks familiar. fracstep = dc_iscale; @@ -763,8 +763,8 @@ void R_DrawSpan_8 (void) UINT8 *restrict source = ds_source; UINT8 *restrict colormap = ds_colormap; - UINT8 *restrict dest = ylookup[ds_y] + columnofs[ds_x1]; - const UINT8 *restrict deststop = screens[0] + vid.rowbytes * vid.height; + UINT8 *restrict dest = R_Address(ds_x1, ds_y); + const UINT8 *restrict deststop = vid.screens[0] + vid.rowbytes * vid.height; register intptr_t count = (ds_x2 - ds_x1 + 1); @@ -911,7 +911,7 @@ void R_DrawTiltedSpan_8(void) uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = R_Address(ds_x1, ds_y); source = ds_source; @@ -1049,7 +1049,7 @@ void R_DrawTiltedTranslucentSpan_8(void) uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = R_Address(ds_x1, ds_y); source = ds_source; @@ -1189,8 +1189,8 @@ void R_DrawTiltedTranslucentWaterSpan_8(void) uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); - dest = ylookup[ds_y] + columnofs[ds_x1]; - dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1; + dest = R_Address(ds_x1, ds_y); + dsrc = vid.screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1; source = ds_source; @@ -1329,7 +1329,7 @@ void R_DrawTiltedSplat_8(void) uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = R_Address(ds_x1, ds_y); source = ds_source; //colormap = ds_colormap; @@ -1476,7 +1476,7 @@ void R_DrawSplat_8 (void) source = ds_source; colormap = ds_colormap; - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = R_Address(ds_x1, ds_y); count = ds_x2 - ds_x1 + 1; while (count >= 8) @@ -1546,7 +1546,7 @@ void R_DrawTranslucentSplat_8 (void) source = ds_source; colormap = ds_colormap; - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = R_Address(ds_x1, ds_y); count = ds_x2 - ds_x1 + 1; while (count >= 8) @@ -1594,7 +1594,7 @@ void R_DrawTranslucentSpan_8 (void) UINT8 *source; UINT8 *colormap; register UINT8 *dest; - const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; + const UINT8 *deststop = vid.screens[0] + vid.rowbytes * vid.height; register intptr_t count = (ds_x2 - ds_x1 + 1); @@ -1613,7 +1613,7 @@ void R_DrawTranslucentSpan_8 (void) source = ds_source; colormap = ds_colormap; - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = R_Address(ds_x1, ds_y); while (count >= 8) { @@ -1700,8 +1700,8 @@ void R_DrawTranslucentWaterSpan_8(void) source = ds_source; colormap = ds_colormap; - dest = ylookup[ds_y] + columnofs[ds_x1]; - dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1; + dest = R_Address(ds_x1, ds_y); + dsrc = vid.screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1; count = ds_x2 - ds_x1 + 1; while (count >= 8) @@ -1774,7 +1774,7 @@ void R_DrawFogSpan_8(void) register intptr_t count; colormap = ds_colormap; - dest = &topleft[ds_y *vid.width + ds_x1]; + dest = R_Address(dc_x, dc_yl); count = ds_x2 - ds_x1 + 1; @@ -1819,7 +1819,7 @@ void R_DrawFogColumn_8(void) // Use ylookup LUT to avoid multiply with ScreenWidth. // Use columnofs LUT for subwindows? //dest = ylookup[dc_yl] + columnofs[dc_x]; - dest = &topleft[dc_yl*vid.width + dc_x]; + dest = R_Address(dc_x, dc_yl); // Determine scaling, which is the only mapping to be done. do diff --git a/src/r_main.c b/src/r_main.c index 15f17db9d..36933b630 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -799,8 +799,8 @@ void R_CheckViewMorph(void) void R_ApplyViewMorph(void) { - UINT8 *tmpscr = screens[4]; - UINT8 *srcscr = screens[0]; + UINT8 *tmpscr = vid.screens[4]; + UINT8 *srcscr = vid.screens[0]; INT32 p, end = vid.width * vid.height; if (!viewmorph.use) @@ -835,8 +835,7 @@ void R_ApplyViewMorph(void) for (p = 0; p < end; p++) tmpscr[p] = srcscr[viewmorph.scrmap[p]]; - VID_BlitLinearScreen(tmpscr, screens[0], - vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.width); + VID_BlitLinearScreen(tmpscr, vid.screens[0], vid.width, vid.height, vid.width, vid.width); } angle_t R_ViewRollAngle(const player_t *player) diff --git a/src/r_plane.c b/src/r_plane.c index 03dea56be..154d94bc8 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -894,16 +894,16 @@ void R_DrawSinglePlane(visplane_t *pl) bottom = vid.height; if (splitscreen > 2 && viewplayer == &players[displayplayers[3]]) // Only copy the part of the screen we need - scr = (screens[0] + (top+(viewheight))*vid.width + viewwidth); + scr = (vid.screens[0] + (top+(viewheight))*vid.width + viewwidth); else if ((splitscreen == 1 && viewplayer == &players[displayplayers[1]]) || (splitscreen > 1 && viewplayer == &players[displayplayers[2]])) - scr = (screens[0] + (top+(viewheight))*vid.width); + scr = (vid.screens[0] + (top+(viewheight))*vid.width); else if (splitscreen > 1 && viewplayer == &players[displayplayers[1]]) - scr = (screens[0] + ((top)*vid.width) + viewwidth); + scr = (vid.screens[0] + ((top)*vid.width) + viewwidth); else - scr = (screens[0] + ((top)*vid.width)); + scr = (vid.screens[0] + ((top)*vid.width)); - VID_BlitLinearScreen(scr, screens[1]+((top)*vid.width), + VID_BlitLinearScreen(scr, vid.screens[1]+((top)*vid.width), vid.width, bottom-top, vid.width, vid.width); } diff --git a/src/r_things.c b/src/r_things.c index 585274bd3..71fb42948 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -634,15 +634,7 @@ void R_DrawMaskedColumn(column_t *column) dc_texturemid = basetexturemid - (topdelta<length + 4); } @@ -702,12 +694,8 @@ static void R_DrawFlippedMaskedColumn(column_t *column) dc_texturemid = basetexturemid - (topdelta<length + 4); diff --git a/src/screen.c b/src/screen.c index e41b5360f..305ca11b7 100644 --- a/src/screen.c +++ b/src/screen.c @@ -89,7 +89,6 @@ consvar_t cv_accuratefps = {"fpssampling", "1", CV_SAVE, accuratefps_cons_t, NUL // SCREEN VARIABLES // ========================================================================= -INT32 scr_bpp; // current video mode bytes per pixel UINT8 *scr_borderpatch; // flat used to fill the reduced view borders set at ST_Init() // ========================================================================= @@ -148,19 +147,9 @@ void SCR_Startup(void) vid.meddupx = (UINT8)(vid.dupx >> 1) + 1; vid.meddupy = (UINT8)(vid.dupy >> 1) + 1; -#ifdef HWRENDER - vid.fmeddupx = vid.meddupx*FRACUNIT; - vid.fmeddupy = vid.meddupy*FRACUNIT; -#endif vid.smalldupx = (UINT8)(vid.dupx / 3) + 1; vid.smalldupy = (UINT8)(vid.dupy / 3) + 1; -#ifdef HWRENDER - vid.fsmalldupx = vid.smalldupx*FRACUNIT; - vid.fsmalldupy = vid.smalldupy*FRACUNIT; -#endif - - vid.baseratio = FRACUNIT; V_Init(); CV_RegisterVar(&cv_highreshudscale); @@ -205,9 +194,6 @@ void SCR_Recalc(void) if (dedicated) return; - // bytes per pixel quick access - scr_bpp = vid.bpp; - // scale 1,2,3 times in x and y the patches for the menus and overlays... // calculated once and for all, used by routines in v_video.c vid.dupx = vid.width / BASEVIDWIDTH; @@ -226,22 +212,11 @@ void SCR_Recalc(void) vid.fdupx = vid.fdupy = (vid.fdupx < vid.fdupy ? vid.fdupx : vid.fdupy); - //vid.baseratio = FixedDiv(vid.height << FRACBITS, BASEVIDHEIGHT << FRACBITS); - vid.baseratio = FRACUNIT; - vid.meddupx = (UINT8)(vid.dupx >> 1) + 1; vid.meddupy = (UINT8)(vid.dupy >> 1) + 1; -#ifdef HWRENDER - vid.fmeddupx = vid.meddupx*FRACUNIT; - vid.fmeddupy = vid.meddupy*FRACUNIT; -#endif vid.smalldupx = (UINT8)(vid.dupx / 3) + 1; vid.smalldupy = (UINT8)(vid.dupy / 3) + 1; -#ifdef HWRENDER - vid.fsmalldupx = vid.smalldupx*FRACUNIT; - vid.fsmalldupy = vid.smalldupy*FRACUNIT; -#endif // toggle off (then back on) the automap because some screensize-dependent values will // be calculated next time the automap is activated. diff --git a/src/screen.h b/src/screen.h index 224897def..e339e3adc 100644 --- a/src/screen.h +++ b/src/screen.h @@ -53,71 +53,35 @@ typedef struct viddef_s { INT32 modenum; // vidmode num indexes videomodes list + // Each screen is [vid.width*vid.height]; + UINT8 *screens[5]; + // screens[0] = main display window + // screens[1] = back screen, alternative blitting + // screens[2] = screenshot buffer, gif movie buffer + // screens[3] = fade screen start + // screens[4] = fade screen end, postimage tempoarary buffer + UINT8 *buffer; // invisible screens buffer size_t rowbytes; // bytes per scanline of the VIDEO mode INT32 width; // PIXELS per scanline INT32 height; - union { // don't need numpages for OpenGL, so we can use it for fullscreen/windowed mode - INT32 numpages; // always 1, page flipping todo - INT32 windowed; // windowed or fullscren mode? - } u; - INT32 recalc; // if true, recalc vid-based stuff - UINT8 *direct; // linear frame buffer, or vga base mem. + boolean recalc; // if true, recalc vid-based stuff INT32 dupx, dupy; // scale 1, 2, 3 value for menus & overlays INT32/*fixed_t*/ fdupx, fdupy; // same as dupx, dupy, but exact value when aspect ratio isn't 320/200 - INT32 bpp; // BYTES per pixel: 1 = 256color, 2 = highcolor - INT32 baseratio; // Used to get the correct value for lighting walls - - // for Win32 version - DNWH WndParent; // handle of the application's window UINT8 smalldupx, smalldupy; // factor for a little bit of scaling UINT8 meddupx, meddupy; // factor for moderate, but not full, scaling #ifdef HWRENDER - INT32/*fixed_t*/ fsmalldupx, fsmalldupy; - INT32/*fixed_t*/ fmeddupx, fmeddupy; INT32 glstate; #endif } viddef_t; -#define VIDWIDTH vid.width -#define VIDHEIGHT vid.height enum { - VID_GL_LIBRARY_LOADED = 1, + VID_GL_LIBRARY_LOADED = 1, VID_GL_LIBRARY_ERROR = -1, }; -// internal additional info for vesa modes only -typedef struct -{ - INT32 vesamode; // vesa mode number plus LINEAR_MODE bit - void *plinearmem; // linear address of start of frame buffer -} vesa_extra_t; - -// a video modes from the video modes list, -// note: video mode 0 is always standard VGA320x200. -typedef struct vmode_s -{ - struct vmode_s *pnext; - char *name; - UINT32 width, height; - UINT32 rowbytes; // bytes per scanline - UINT32 bytesperpixel; // 1 for 256c, 2 for highcolor - INT32 windowed; // if true this is a windowed mode - INT32 numpages; - vesa_extra_t *pextradata; // vesa mode extra data -#ifdef _WIN32 - INT32 (WINAPI *setmode)(viddef_t *lvid, struct vmode_s *pcurrentmode); -#else - INT32 (*setmode)(viddef_t *lvid, struct vmode_s *pcurrentmode); -#endif - INT32 misc; // misc for display driver (r_opengl.dll etc) -} vmode_t; - -#define NUMSPECIALMODES 4 -extern vmode_t specialmodes[NUMSPECIALMODES]; - // --------------------------------------------- // color mode dependent drawer function pointers // --------------------------------------------- @@ -135,14 +99,15 @@ extern void (*transtransfunc)(void); extern void (*twosmultipatchfunc)(void); extern void (*twosmultipatchtransfunc)(void); +// quick fix for tall/short skies, depending on bytesperpixel +extern void (*walldrawerfunc)(void); + // ---------------- // screen variables // ---------------- extern viddef_t vid; extern INT32 setmodeneeded; // mode number to set if needed, or 0 -extern double averageFPS; -extern INT32 scr_bpp; extern UINT8 *scr_borderpatch; // patch used to fill the view borders extern consvar_t cv_scr_width, cv_scr_height, cv_renderview, cv_fullscreen, cv_vhseffect, cv_shittyscreen; @@ -155,9 +120,6 @@ extern consvar_t cv_alwaysgrabmouse; extern consvar_t cv_votebgscaling; -// quick fix for tall/short skies, depending on bytesperpixel -extern void (*walldrawerfunc)(void); - // Change video mode, only at the start of a refresh. void SCR_SetMode(void); // Recalc screen size dependent stuff diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index faf4c67f7..26a6d84db 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1497,7 +1497,7 @@ void I_FinishUpdate(void) ST_AskToJoinEnvelope(); #endif - if (rendermode == render_soft && screens[0]) + if (rendermode == render_soft && vid.screens[0]) { if (!bufSurface) //Double-Check { @@ -1547,9 +1547,7 @@ void I_ReadScreen(UINT8 *scr) if (rendermode != render_soft) I_Error ("I_ReadScreen: called while in non-software mode"); else - VID_BlitLinearScreen(screens[0], scr, - vid.width*vid.bpp, vid.height, - vid.rowbytes, vid.rowbytes); + VID_BlitLinearScreen(vid.screens[0], scr, vid.width, vid.height, vid.rowbytes, vid.rowbytes); } // @@ -1753,8 +1751,7 @@ INT32 VID_SetMode(INT32 modeNum) { SDLdoUngrabMouse(); - vid.recalc = 1; - vid.bpp = 1; + vid.recalc = true; if (modeNum >= 0 && modeNum < MAXWINMODES) { @@ -1944,16 +1941,9 @@ static void Impl_VideoSetupSDLBuffer(void) bufSurface = NULL; } // Set up the SDL palletized buffer (copied to vidbuffer before being rendered to texture) - if (vid.bpp == 1) - { - bufSurface = SDL_CreateRGBSurfaceFrom(screens[0],vid.width,vid.height,8, - (int)vid.rowbytes,0x00000000,0x00000000,0x00000000,0x00000000); // 256 mode - } - else if (vid.bpp == 2) // Fury -- don't think this is used at all anymore - { - bufSurface = SDL_CreateRGBSurfaceFrom(screens[0],vid.width,vid.height,15, - (int)vid.rowbytes,0x00007C00,0x000003E0,0x0000001F,0x00000000); // 555 mode - } + bufSurface = SDL_CreateRGBSurfaceFrom(vid.screens[0], vid.width, vid.height, 8, + (int)vid.rowbytes, 0x00000000, 0x00000000, 0x00000000, 0x00000000); // 256 mode + if (bufSurface) { SDL_SetPaletteColors(bufSurface->format->palette, localPalette, 0, 256); @@ -1969,11 +1959,13 @@ static void Impl_VideoSetupBuffer(void) // Set up game's software render buffer //if (rendermode == render_soft) { - vid.rowbytes = vid.width * vid.bpp; - vid.direct = NULL; + vid.rowbytes = vid.width; + if (vid.buffer) free(vid.buffer); + vid.buffer = calloc(vid.rowbytes*vid.height, NUMSCREENS); + if (!vid.buffer) { I_Error("%s", M_GetText("Not enough memory for video buffer\n")); @@ -2184,9 +2176,6 @@ void I_StartupGraphics(void) vid.width = BASEVIDWIDTH; // Default size for startup vid.height = BASEVIDHEIGHT; // BitsPerPixel is the SDL interface's vid.recalc = true; // Set up the console stufff - vid.direct = NULL; // Maybe direct access? - vid.bpp = 1; // This is the game engine's Bpp - vid.WndParent = NULL; //For the window? #ifdef HAVE_TTF I_ShutdownTTF(); diff --git a/src/v_video.c b/src/v_video.c index 7df5cacea..f7e706093 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -35,14 +35,6 @@ #include "hardware/r_opengl/r_opengl.h" #endif -// Each screen is [vid.width*vid.height]; -UINT8 *screens[5]; -// screens[0] = main display window -// screens[1] = back screen, alternative blitting -// screens[2] = screenshot buffer, gif movie buffer -// screens[3] = fade screen start -// screens[4] = fade screen end, postimage tempoarary buffer - static CV_PossibleValue_t fps_cons_t[] = {{0, "No"}, {1, "Normal"}, {2, "Compact"}, {3, "Old"}, {4, "Old Compact"}, {0, NULL}}; consvar_t cv_ticrate = {"showfps", "No", CV_SAVE, fps_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -786,7 +778,7 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca if (scrn & V_HORZSCREEN) x += (BASEVIDWIDTH/2)<>FRACBITS) < column->length; ofs += rowfrac) { - if (dest >= screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION) + if (dest >= vid.screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION) *dest = patchdrawfunc(dest, source, ofs); dest += vid.width; } @@ -959,7 +951,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_ y -= FixedMul(patch->topoffset<leftoffset<>FRACBITS) < column->length && (((ofs>>FRACBITS) - sy) + topdelta) < h; ofs += rowfrac) { - if (dest >= screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION) + if (dest >= vid.screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION) *dest = patchdrawfunc(dest, source, ofs); dest += vid.width; } @@ -1076,8 +1068,8 @@ void V_DrawBlock(INT32 x, INT32 y, INT32 scrn, INT32 width, INT32 height, const I_Error("Bad V_DrawBlock"); #endif - dest = screens[scrn] + y*vid.width + x; - deststop = screens[scrn] + vid.rowbytes * vid.height; + dest = vid.screens[scrn] + y*vid.width + x; + deststop = vid.screens[scrn] + vid.rowbytes * vid.height; while (height--) { @@ -1117,7 +1109,7 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT) { // Clear the entire screen, from dest to deststop. Yes, this really works. - memset(screens[0], (c&255), vid.width * vid.height * vid.bpp); + memset(vid.screens[0], (c&255), vid.width * vid.height); return; } @@ -1172,8 +1164,8 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) if (y + h > vid.height) h = vid.height-y; - dest = screens[0] + y*vid.width + x; - deststop = screens[0] + vid.rowbytes * vid.height; + dest = vid.screens[0] + y*vid.width + x; + deststop = vid.screens[0] + vid.rowbytes * vid.height; if (alphalevel) { @@ -1202,7 +1194,7 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) else { for (;(--h >= 0) && dest < deststop; dest += vid.width) - memset(dest, c, w * vid.bpp); + memset(dest, c, w); } } @@ -1270,7 +1262,7 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT) { // Clear the entire screen, from dest to deststop. Yes, this really works. - memset(screens[0], (UINT8)(c&255), vid.width * vid.height * vid.bpp); + memset(vid.screens[0], (UINT8)(c&255), vid.width * vid.height); return; } @@ -1317,7 +1309,7 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) if (y + h > vid.height) h = vid.height-y; - dest = screens[0] + y*vid.width + x; + dest = vid.screens[0] + y*vid.width + x; if ((alphalevel = ((c & V_ALPHAMASK) >> V_ALPHASHIFT))) { @@ -1440,14 +1432,14 @@ void V_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 c) if (h > w) h = w; - dest = screens[0] + y*vid.width + x; - deststop = screens[0] + vid.rowbytes * vid.height; + dest = vid.screens[0] + y*vid.width + x; + deststop = vid.screens[0] + vid.rowbytes * vid.height; c &= 255; for (;(--h >= 0) && dest < deststop; dest += vid.width) { - memset(dest, c, w * vid.bpp); + memset(dest, c, w); if (wait) wait--; else @@ -1512,8 +1504,8 @@ void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum) dupx = dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); - dest = screens[0] + y*dupy*vid.width + x*dupx; - deststop = screens[0] + vid.rowbytes * vid.height; + dest = vid.screens[0] + y*dupy*vid.width + x*dupx; + deststop = vid.screens[0] + vid.rowbytes * vid.height; // from V_DrawScaledPatch if (vid.width != BASEVIDWIDTH * dupx) @@ -1614,7 +1606,7 @@ void V_DrawVhsEffect(boolean rewind) { static fixed_t upbary = 100*FRACUNIT, downbary = 150*FRACUNIT; - UINT8 *buf = screens[0], *tmp = screens[4]; + UINT8 *buf = vid.screens[0], *tmp = vid.screens[4]; UINT16 y; UINT32 x, pos = 0; @@ -1707,8 +1699,8 @@ void V_DrawFadeScreen(UINT16 color, UINT8 strength) : ((color & 0xFF00) // Color is not palette index? ? ((UINT8 *)colormaps + strength*256) // Do COLORMAP fade. : ((UINT8 *)transtables + ((9-strength)<postimg & POSTIMG_WATER) { @@ -3482,7 +3474,7 @@ void V_DoPostProcessor(INT32 view, INT32 param) /* Unoptimized version - for (x = 0; x < vid.width*vid.bpp; x++) + for (x = 0; x < vid.width; x++) { newpix = (x + sine); @@ -3579,7 +3571,7 @@ void V_DoPostProcessor(INT32 view, INT32 param) INT32 y, x, x2; for (y = yoffset; y < yoffset+viewheight; y++) - for (x = xoffset, x2 = xoffset+((viewwidth*vid.bpp)-1); x < xoffset+(viewwidth*vid.bpp); x++, x2--) + for (x = xoffset, x2 = xoffset+(viewwidth-1); x < xoffset+viewwidth; x++, x2--) tmpscr[y*vid.width + x2] = srcscr[y*vid.width + x]; UINT8 *tmp = tmpscr; @@ -3599,8 +3591,8 @@ void V_DoPostProcessor(INT32 view, INT32 param) srcscr = tmp; } - VID_BlitLinearScreen(srcscr+vid.width*vid.bpp*yoffset+xoffset, tmpscr+vid.width*vid.bpp*yoffset+xoffset, - viewwidth*vid.bpp, viewheight, vid.width*vid.bpp, vid.width); + VID_BlitLinearScreen(srcscr+vid.width*yoffset+xoffset, tmpscr+vid.width*yoffset+xoffset, + viewwidth, viewheight, vid.width, vid.width); #endif } @@ -3660,18 +3652,15 @@ void V_Init(void) const INT32 screensize = vid.rowbytes * vid.height; for (i = 0; i < NUMSCREENS; i++) - screens[i] = NULL; + vid.screens[i] = NULL; // start address of NUMSCREENS * width*height vidbuffers if (base) { for (i = 0; i < NUMSCREENS; i++) - screens[i] = base + i*screensize; + vid.screens[i] = base + i*screensize; } - if (vid.direct) - screens[0] = vid.direct; - #ifdef DEBUG CONS_Debug(DBG_RENDER, "V_Init done:\n"); for (i = 0; i < NUMSCREENS; i++) diff --git a/src/v_video.h b/src/v_video.h index 3a8cf7396..d60496dfb 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -23,11 +23,6 @@ // VIDEO // -// Screen 0 is the screen updated by I_Update screen. -// Screen 1 is an extra buffer. - -extern UINT8 *screens[5]; - extern consvar_t cv_ticrate, cv_accuratefps, cv_allcaps, cv_constextsize, cv_menucaps, cv_globalgamma, cv_globalsaturation, cv_rhue, cv_yhue, cv_ghue, cv_chue, cv_bhue, cv_mhue, diff --git a/src/y_inter.c b/src/y_inter.c index 3c0a77ac1..e89224aa0 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -512,7 +512,7 @@ void Y_IntermissionDrawer(void) else { if (rendermode == render_soft) - VID_BlitLinearScreen(screens[1], screens[0], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes); + VID_BlitLinearScreen(vid.screens[1], vid.screens[0], vid.width, vid.height, vid.width, vid.rowbytes); #ifdef HWRENDER else if (rendermode == render_opengl) HWR_DrawIntermissionBG(); -- 2.54.0 From f2d3432bf51d8503a29c473fbab74c8e687dbeae Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 4 Jun 2025 18:48:23 +0200 Subject: [PATCH 004/141] make software ripple splitscreen checks less awful to look at --- src/r_plane.c | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/src/r_plane.c b/src/r_plane.c index 154d94bc8..1d3cdbbf9 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -893,15 +893,34 @@ void R_DrawSinglePlane(visplane_t *pl) if (bottom > vid.height) bottom = vid.height; - if (splitscreen > 2 && viewplayer == &players[displayplayers[3]]) // Only copy the part of the screen we need - scr = (vid.screens[0] + (top+(viewheight))*vid.width + viewwidth); - else if ((splitscreen == 1 && viewplayer == &players[displayplayers[1]]) - || (splitscreen > 1 && viewplayer == &players[displayplayers[2]])) - scr = (vid.screens[0] + (top+(viewheight))*vid.width); - else if (splitscreen > 1 && viewplayer == &players[displayplayers[1]]) - scr = (vid.screens[0] + ((top)*vid.width) + viewwidth); - else - scr = (vid.screens[0] + ((top)*vid.width)); + // Only copy the part of the screen we need + scr = (renderscreen + (top*vid.width)); + + for (UINT8 i = 1; i <= splitscreen; i++) + { + if (viewplayer == &players[displayplayers[i]]) + { + switch (i) + { + case 1: + if (splitscreen == 1) + scr = (renderscreen + (top + viewheight) * vid.width); + else if (splitscreen > 1) + scr = (renderscreen + (top * vid.width) + viewwidth); + break; + case 2: + scr = (renderscreen + (top + viewheight) * vid.width); + break; + case 3: + scr = (renderscreen + (top + viewheight) * vid.width + viewwidth); + break; + default: + break; + } + + break; + } + } VID_BlitLinearScreen(scr, vid.screens[1]+((top)*vid.width), vid.width, bottom-top, -- 2.54.0 From 268ccce95575d3810d1a1bdecc13d8152a99557d Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 4 Jun 2025 19:59:58 +0200 Subject: [PATCH 005/141] move ripple blit stuff into own function --- src/r_plane.c | 121 ++++++++++++++++++++++++++------------------------ 1 file changed, 62 insertions(+), 59 deletions(-) diff --git a/src/r_plane.c b/src/r_plane.c index 1d3cdbbf9..309ec6aed 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -146,6 +146,67 @@ static void R_UpdatePlaneRipple(void) ds_waterofs = (leveltime & 1)*16384; planeripple.offset = ((leveltime-1)*140) + ((rendertimefrac*140) / FRACUNIT); } + +static void R_HandleRipplePlane(visplane_t *pl) +{ + INT32 top, bottom; + UINT8 *scr; + + if (!cv_ripplewater.value) + { + planeripple.active = false; + return; + } + + planeripple.active = true; + + if (spanfunc == R_DrawTranslucentSpan_8) + { + spanfunc = R_DrawTranslucentWaterSpan_8; + + // Copy the current scene, ugh + top = pl->high-8; + bottom = pl->low+8; + + if (top < 0) + top = 0; + if (bottom > vid.height) + bottom = vid.height; + + // Only copy the part of the screen we need + scr = (renderscreen + (top*vid.width)); + + for (UINT8 i = 1; i <= splitscreen; i++) + { + if (viewplayer != &players[displayplayers[i]]) + continue; + + switch (i) + { + case 1: + if (splitscreen == 1) + scr = (renderscreen + (top + viewheight) * vid.width); + else if (splitscreen > 1) + scr = (renderscreen + (top * vid.width) + viewwidth); + break; + case 2: + scr = (renderscreen + (top + viewheight) * vid.width); + break; + case 3: + scr = (renderscreen + (top + viewheight) * vid.width + viewwidth); + break; + default: + break; + } + + break; + } + + VID_BlitLinearScreen(scr, vid.screens[1]+((top)*vid.width), + vid.width, bottom-top, + vid.width, vid.width); + } +} #endif // @@ -773,7 +834,6 @@ static void R_SetSlopePlaneVectors(visplane_t *pl, INT32 y, fixed_t xoff, fixed_ R_CalculateSlopeVectors(pl->slope, pl->viewx, pl->viewy, pl->viewz, FRACUNIT, FRACUNIT, xoff, yoff, pl->viewangle, pl->plangle, fudge); } - void R_DrawSinglePlane(visplane_t *pl) { INT32 light = 0; @@ -873,64 +933,7 @@ void R_DrawSinglePlane(visplane_t *pl) #ifndef NOWATER if (pl->ffloor->flags & FF_RIPPLE) { - INT32 top, bottom; - UINT8 *scr; - - if (cv_ripplewater.value) - { - planeripple.active = true; - - if (spanfunc == R_DrawTranslucentSpan_8) - { - spanfunc = R_DrawTranslucentWaterSpan_8; - - // Copy the current scene, ugh - top = pl->high-8; - bottom = pl->low+8; - - if (top < 0) - top = 0; - if (bottom > vid.height) - bottom = vid.height; - - // Only copy the part of the screen we need - scr = (renderscreen + (top*vid.width)); - - for (UINT8 i = 1; i <= splitscreen; i++) - { - if (viewplayer == &players[displayplayers[i]]) - { - switch (i) - { - case 1: - if (splitscreen == 1) - scr = (renderscreen + (top + viewheight) * vid.width); - else if (splitscreen > 1) - scr = (renderscreen + (top * vid.width) + viewwidth); - break; - case 2: - scr = (renderscreen + (top + viewheight) * vid.width); - break; - case 3: - scr = (renderscreen + (top + viewheight) * vid.width + viewwidth); - break; - default: - break; - } - - break; - } - } - - VID_BlitLinearScreen(scr, vid.screens[1]+((top)*vid.width), - vid.width, bottom-top, - vid.width, vid.width); - } - } - else - { - planeripple.active = false; - } + R_HandleRipplePlane(pl); } #endif } -- 2.54.0 From e75943194885dfccd3c4188d59abfbee0a2a01ce Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 4 Jun 2025 20:43:26 +0200 Subject: [PATCH 006/141] clamp shit so vhs effect doesent do oob writes on some resolutions shoddy way but fuckit --- src/v_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/v_video.c b/src/v_video.c index f7e706093..c826d70f5 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1662,7 +1662,7 @@ void V_DrawVhsEffect(boolean rewind) if (y == 0 && offs < 0) offs = 0; else if (y >= vid.height-2 && offs > 0) offs = 0; - for (x = pos+vid.rowbytes*2; pos < x; pos++) + for (x = min(pos+vid.rowbytes*2, vid.rowbytes*vid.height); pos < x; pos++) { tmp[pos] = thismapstart[buf[pos+offs]]; #ifdef HQ_VHS -- 2.54.0 From 7808159d23a238dde50ea9ca92e8f5ee43064029 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 4 Jun 2025 22:59:26 +0200 Subject: [PATCH 007/141] get rid of static screen size buffers, alloc em to current screen size instead mostly taken from srb2s any-resolution branch --- src/doomstat.h | 2 +- src/r_bsp.c | 204 +++++++++++++------------------------------------ src/r_bsp.h | 2 + src/r_defs.h | 4 +- src/r_draw.c | 32 +++++++- src/r_draw8.c | 1 - src/r_fps.c | 2 +- src/r_main.c | 28 ++++--- src/r_plane.c | 130 ++++++++++++++++++------------- src/r_plane.h | 19 ++--- src/r_segs.c | 35 ++++++++- src/r_segs.h | 5 +- src/r_splats.c | 11 ++- src/r_splats.h | 2 + src/r_state.h | 2 +- src/r_things.c | 66 +++++++++++----- src/r_things.h | 8 +- 17 files changed, 293 insertions(+), 260 deletions(-) diff --git a/src/doomstat.h b/src/doomstat.h index f8a3899ca..171b49edc 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -125,7 +125,7 @@ extern boolean lastdraw; extern INT32 postimgparam[MAXSPLITSCREENPLAYERS]; extern INT32 viewwindowx, viewwindowy; -extern INT32 viewwidth, scaledviewwidth; +extern INT32 viewwidth; extern boolean gamedataloaded; diff --git a/src/r_bsp.c b/src/r_bsp.c index 427a6367c..e5b82a151 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -73,145 +73,54 @@ void R_ClearDrawSegs(void) ds_p = drawsegs; } -// Fix from boom. -#define MAXSEGS (MAXVIDWIDTH/2+1) +// CPhipps - +// Instead of clipsegs, let's try using an array with one entry for each column, +// indicating whether it's blocked by a solid wall yet or not. +UINT8 *solidcol; -// newend is one past the last valid seg -static cliprange_t *newend; -static cliprange_t solidsegs[MAXSEGS]; - -// -// R_ClipSolidWallSegment -// Does handle solid walls, -// e.g. single sided LineDefs (middle texture) -// that entirely block the view. -// -static void R_ClipSolidWallSegment(INT32 first, INT32 last) +void R_AllocClipSegMemory(void) { - cliprange_t *next; - cliprange_t *start; - - // Find the first range that touches the range (adjacent pixels are touching). - start = solidsegs; - while (start->last < first - 1) - start++; - - if (first < start->first) - { - if (last < start->first - 1) - { - // Post is entirely visible (above start), so insert a new clippost. - R_StoreWallRange(first, last); - next = newend; - newend++; - // NO MORE CRASHING! - if (newend - solidsegs > MAXSEGS) - I_Error("R_ClipSolidWallSegment: Solid Segs overflow!\n"); - - while (next != start) - { - *next = *(next-1); - next--; - } - next->first = first; - next->last = last; - return; - } - - // There is a fragment above *start. - R_StoreWallRange(first, start->first - 1); - // Now adjust the clip size. - start->first = first; - } - - // Bottom contained in start? - if (last <= start->last) - return; - - next = start; - while (last >= (next+1)->first - 1) - { - // There is a fragment between two posts. - R_StoreWallRange(next->last + 1, (next+1)->first - 1); - next++; - - if (last <= next->last) - { - // Bottom is contained in next. - // Adjust the clip size. - start->last = next->last; - goto crunch; - } - } - - // There is a fragment after *next. - R_StoreWallRange(next->last + 1, last); - // Adjust the clip size. - start->last = last; - - // Remove start+1 to next from the clip list, because start now covers their area. -crunch: - if (next == start) - return; // Post just extended past the bottom of one post. - - while (next++ != newend) - *++start = *next; // Remove a post. - - newend = start + 1; - - // NO MORE CRASHING! - if (newend - solidsegs > MAXSEGS) - I_Error("R_ClipSolidWallSegment: Solid Segs overflow!\n"); + solidcol = Z_Realloc(solidcol, sizeof(*solidcol) * viewwidth, PU_STATIC, NULL); } +// CPhipps - +// R_ClipWallSegment // -// R_ClipPassWallSegment -// Clips the given range of columns, but does not include it in the clip list. -// Does handle windows, e.g. LineDefs with upper and lower texture. -// -static inline void R_ClipPassWallSegment(INT32 first, INT32 last, boolean soliddontrender) +// Replaces the old R_Clip*WallSegment functions. It draws bits of walls in those +// columns which aren't solid, and updates the solidcol[] array appropriately +static void R_ClipWallSegment(int first, int last, boolean solid, boolean soliddontrender) { - cliprange_t *start; - - // Find the first range that touches the range - // (adjacent pixels are touching). - start = solidsegs; - while (start->last < first - 1) - start++; - - if (first < start->first) + while (first < last) { - if (last < start->first - 1) + UINT8 *p; + + if (solidcol[first]) { - // Post is entirely visible (above start). - if (!soliddontrender) - R_StoreWallRange(first, last); - return; + p = memchr(solidcol+first, 0, last-first); + if (!p) + return; // All solid + + first = p - solidcol; } + else + { + p = memchr(solidcol+first, 1, last-first); - // There is a fragment above *start. - if (!soliddontrender) - R_StoreWallRange(first, start->first - 1); + int to; + if (!p) + to = last; + else + to = p - solidcol; + + if (!soliddontrender) + R_StoreWallRange(first, to-1); + + if (solid) + memset(solidcol+first, 1, to-first); + + first = to; + } } - - // Bottom contained in start? - if (last <= start->last) - return; - - while (last >= (start+1)->first - 1) - { - // There is a fragment between two posts. - if (!soliddontrender) - R_StoreWallRange(start->last + 1, (start+1)->first - 1); - start++; - - if (last <= start->last) - return; - } - - // There is a fragment after *next. - if (!soliddontrender) - R_StoreWallRange(start->last + 1, last); } // @@ -219,19 +128,18 @@ static inline void R_ClipPassWallSegment(INT32 first, INT32 last, boolean solidd // void R_ClearClipSegs(void) { - solidsegs[0].first = -0x7fffffff; - solidsegs[0].last = -1; - solidsegs[1].first = viewwidth; - solidsegs[1].last = 0x7fffffff; - newend = solidsegs + 2; + memset(solidcol, 0, viewwidth); } + void R_PortalClearClipSegs(INT32 start, INT32 end) { - solidsegs[0].first = -0x7fffffff; - solidsegs[0].last = start-1; - solidsegs[1].first = end; - solidsegs[1].last = 0x7fffffff; - newend = solidsegs + 2; + R_ClearClipSegs(); + + for (INT32 x = 0; x < start; x++) + solidcol[x] = 1; + + for (INT32 x = end; x < viewwidth; x++) + solidcol[x] = 1; } // @@ -405,7 +313,7 @@ static void R_AddLine(seg_t *line) span = angle1 - angle2; // Back side? i.e. backface culling? - if (span >= ANGLE_180 || !line->linedef) + if (span >= ANGLE_180) return; // Global angle needed by segcalc. @@ -540,15 +448,15 @@ static void R_AddLine(seg_t *line) clippass: g_walloffscreen = false; - R_ClipPassWallSegment(x1, x2 - 1, false); + R_ClipWallSegment(x1, x2, false, false); if (g_walloffscreen) - R_ClipPassWallSegment(x1, x2 - 1, true); + R_ClipWallSegment(x1, x2, false, true); return; clipsolid: g_walloffscreen = false; - R_ClipSolidWallSegment(x1, x2 - 1); + R_ClipWallSegment(x1, x2, true, false); } // @@ -581,7 +489,6 @@ static boolean R_CheckBBox(const fixed_t *bspcoord) angle_t angle1, angle2; INT32 sx1, sx2, boxpos; const INT32* check; - cliprange_t *start; // Find the corners of the box that define the edges from current viewpoint. if (viewx <= bspcoord[BOXLEFT]) @@ -630,12 +537,11 @@ static boolean R_CheckBBox(const fixed_t *bspcoord) if (sx1 >= sx2) return false; - start = solidsegs; - while (start->last < sx2) - start++; - - if (sx1 >= start->first && sx2 <= start->last) - return false; // The clippost contains the new span. + if (!memchr(solidcol+sx1, 0, sx2-sx1)) + { + // All columns it covers are already solidly covered + return false; + } return true; } diff --git a/src/r_bsp.h b/src/r_bsp.h index 7ba6c330c..b5eb6b6cc 100644 --- a/src/r_bsp.h +++ b/src/r_bsp.h @@ -35,11 +35,13 @@ extern INT32 checkcoord[12][4]; extern drawseg_t *drawsegs; extern drawseg_t *ds_p; extern INT32 doorclosed; +extern UINT8 *solidcol; extern boolean g_walloffscreen; // BSP? void R_ClearClipSegs(void); void R_PortalClearClipSegs(INT32 start, INT32 end); +void R_AllocClipSegMemory(void); void R_ClearDrawSegs(void); void R_RenderBSPNode(INT32 bspnum); diff --git a/src/r_defs.h b/src/r_defs.h index a202b49ef..fd733a97c 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -610,11 +610,11 @@ typedef struct drawseg_s struct ffloor_s *thicksides[MAXFFLOORS]; INT16 *thicksidecol; INT32 numthicksides; - fixed_t frontscale[MAXVIDWIDTH]; + fixed_t *frontscale; UINT8 portalpass; // if > 0 and <= portalrender, do not affect sprite clipping - fixed_t maskedtextureheight[MAXVIDWIDTH]; // For handling sloped midtextures + fixed_t *maskedtextureheight; // For handling sloped midtextures vertex_t leftpos, rightpos; // Used for rendering FOF walls with slopes } drawseg_t; diff --git a/src/r_draw.c b/src/r_draw.c index f4b38e45e..cecb931c6 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -38,7 +38,7 @@ /** \brief view info */ -INT32 linesize, viewwidth, scaledviewwidth, viewheight, viewwindowx, viewwindowy; +INT32 linesize, viewwidth, viewheight, viewwindowx, viewwindowy; UINT8 *renderscreen; // haleyjd // ========================================================================= @@ -99,6 +99,10 @@ float focallengthf, zeroheight; UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask; +// For, uh, tilted lighting, duh. +static INT32 *tiltlighting; + + // ========================================================================== // OLD DOOM FUZZY EFFECT // ========================================================================== @@ -470,6 +474,30 @@ void R_FlushTranslationColormapCache(void) \return void */ +static void R_AllocViewMemory(void) +{ + negonearray = Z_Realloc(negonearray, sizeof(*negonearray) * viewwidth, PU_STATIC, NULL); + screenheightarray = Z_Realloc(screenheightarray, sizeof(*screenheightarray) * viewwidth, PU_STATIC, NULL); + + floorclip = Z_Realloc(floorclip, sizeof(*floorclip) * viewwidth, PU_STATIC, NULL); + ceilingclip = Z_Realloc(ceilingclip, sizeof(*ceilingclip) * viewwidth, PU_STATIC, NULL); + + frontscale = Z_Realloc(frontscale, sizeof(*frontscale) * viewwidth, PU_STATIC, NULL); + + xtoviewangle = Z_Realloc(xtoviewangle, sizeof(*xtoviewangle) * (viewwidth + 1), PU_STATIC, NULL); + + tiltlighting = Z_Realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth, PU_STATIC, NULL); + + R_AllocSegMemory(); + R_AllocClipSegMemory(); + R_AllocPlaneMemory(); +#ifdef FLOORSPLATS + R_AllocFloorSpriteTables(); +#endif + R_AllocVisSpriteMemory(); +} + + void R_InitViewBuffer(INT32 width, INT32 height) { if (width > MAXVIDWIDTH) @@ -477,6 +505,8 @@ void R_InitViewBuffer(INT32 width, INT32 height) if (height > MAXVIDHEIGHT) height = MAXVIDHEIGHT; + R_AllocViewMemory(); + viewwindowx = 0; viewwindowy = 0; diff --git a/src/r_draw8.c b/src/r_draw8.c index c98203a9e..74d32a356 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -845,7 +845,6 @@ void R_DrawSpan_8 (void) // R_CalcTiltedLighting // Exactly what it says on the tin. I wish I wasn't too lazy to explain things properly. -static INT32 tiltlighting[MAXVIDWIDTH]; void R_CalcTiltedLighting(fixed_t start, fixed_t end) { // ZDoom uses a different lighting setup to us, and I couldn't figure out how to adapt their version diff --git a/src/r_fps.c b/src/r_fps.c index 4938988dc..5dcaf90da 100644 --- a/src/r_fps.c +++ b/src/r_fps.c @@ -173,7 +173,7 @@ static vector3_t *R_LerpVector3(const vector3_t *from, const vector3_t *to, fixe // recalc necessary stuff for mouseaiming // slopes are already calculated for the full possible view (which is 4*viewheight). -// 18/08/18: (No it's actually 16*viewheight, thanks Jimita for finding this out) +// 18/08/18: (No it's actually 16*viewheight, thanks Lactozilla for finding this out) static void R_SetupFreelook(void) { // clip it in the case we are looking a hardware 90 degrees full aiming diff --git a/src/r_main.c b/src/r_main.c index 36933b630..f08f4b5f6 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -88,7 +88,7 @@ INT32 viewangletox[FINEANGLES/2]; // The xtoviewangleangle[] table maps a screen pixel // to the lowest viewangle that maps back to x ranges // from clipangle to -clipangle. -angle_t xtoviewangle[MAXVIDWIDTH+1]; +angle_t *xtoviewangle; lighttable_t *scalelight[LIGHTLEVELS][MAXLIGHTSCALE]; lighttable_t *scalelightfixed[MAXLIGHTSCALE]; @@ -631,7 +631,7 @@ static struct { INT32 scrmapsize; INT32 x1; // clip rendering horizontally for efficiency - INT16 ceilingclip[MAXVIDWIDTH], floorclip[MAXVIDWIDTH]; + INT16 *ceilingclip, *floorclip; boolean use; } viewmorph = { @@ -642,7 +642,7 @@ static struct { 0, 0, - {}, {}, + NULL, NULL, false }; @@ -680,10 +680,10 @@ void R_CheckViewMorph(void) if (viewmorph.scrmapsize != vid.width*vid.height) { - if (viewmorph.scrmap) - free(viewmorph.scrmap); - viewmorph.scrmap = malloc(vid.width*vid.height * sizeof(INT32)); viewmorph.scrmapsize = vid.width*vid.height; + viewmorph.scrmap = realloc(viewmorph.scrmap, vid.width*vid.height * sizeof(INT32)); + viewmorph.ceilingclip = realloc(viewmorph.ceilingclip, vid.width * sizeof(INT16)); + viewmorph.floorclip = realloc(viewmorph.floorclip, vid.width * sizeof(INT16)); } temp = FINECOSINE(rollangle); @@ -906,18 +906,15 @@ void R_ExecuteSetViewSize(void) // status bar overlay st_overlay = cv_showhud.value; - scaledviewwidth = vid.width; + viewwidth = vid.width; viewheight = vid.height; if (splitscreen) viewheight >>= 1; - viewwidth = scaledviewwidth; - if (splitscreen > 1) { viewwidth >>= 1; - scaledviewwidth >>= 1; } centerx = viewwidth/2; @@ -925,9 +922,9 @@ void R_ExecuteSetViewSize(void) centerxfrac = centerx<top_memory = Z_Realloc(pl->top_memory, sizeof(UINT16) * (viewwidth + 2), PU_STATIC, NULL); + pl->bottom_memory = Z_Realloc(pl->bottom_memory, sizeof(UINT16) * (viewwidth + 2), PU_STATIC, NULL); + pl->top = pl->top_memory + 1; + pl->bottom = pl->bottom_memory + 1; +} + +void R_AllocPlaneMemory(void) +{ + visplane_t *check; + + // Alloc visplane top/bottom bounds + for (unsigned i = 0; i < MAXVISPLANES; i++) + { + check = visplanes[i]; + + while (check) + { + R_ReallocPlaneBounds(check); + check = check->next; + } + } + + // Need to do it for "freed" visplanes too + check = freetail; + while (check) + { + R_ReallocPlaneBounds(check); + check = check->next; + } + + // Alloc ffloor clip tables + ffloor_f_clip = Z_Realloc(ffloor_f_clip, sizeof(*ffloor_f_clip) * (viewwidth * MAXFFLOORS), PU_STATIC, NULL); + ffloor_c_clip = Z_Realloc(ffloor_c_clip, sizeof(*ffloor_c_clip) * (viewwidth * MAXFFLOORS), PU_STATIC, NULL); + + for (unsigned i = 0; i < MAXFFLOORS; i++) + { + ffloor[i].f_clip = ffloor_f_clip + (i * viewwidth); + ffloor[i].c_clip = ffloor_c_clip + (i * viewwidth); + } + + yslopetab = Z_Realloc(yslopetab, sizeof(*yslopetab) * (viewheight * 16), PU_STATIC, NULL); + spanstart = Z_Realloc(spanstart, sizeof(*spanstart) * viewheight, PU_STATIC, NULL); } // @@ -241,31 +276,20 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2) planecos = FINECOSINE(angle); planesin = FINESINE(angle); - if (planeheight != cachedheight[y]) + // [RH] Notice that I dumped the caching scheme used by Doom. + // It did not offer any appreciable speedup. + distance = FixedMul(planeheight, yslope[y]); + span = abs(centery - y); + + if (span) // don't divide by zero { - cachedheight[y] = planeheight; - cacheddistance[y] = distance = FixedMul(planeheight, yslope[y]); - span = abs(centery - y); - - if (span) // don't divide by zero - { - ds_xstep = FixedMul(planesin, planeheight) / span; - ds_ystep = FixedMul(planecos, planeheight) / span; - } - else - { - ds_xstep = FixedMul(distance, basexscale); - ds_ystep = FixedMul(distance, baseyscale); - } - - cachedxstep[y] = ds_xstep; - cachedystep[y] = ds_ystep; + ds_xstep = FixedMul(planesin, planeheight) / span; + ds_ystep = FixedMul(planecos, planeheight) / span; } else { - distance = cacheddistance[y]; - ds_xstep = cachedxstep[y]; - ds_ystep = cachedystep[y]; + ds_xstep = FixedMul(distance, basexscale); + ds_ystep = FixedMul(distance, baseyscale); } ds_xfrac = xoffs + FixedMul(planecos, distance) + (x1 - centerx) * ds_xstep; @@ -358,28 +382,23 @@ void R_ClearPlanes(void) } } - numffloors = 0; - for (i = 0; i < MAXVISPLANES; i++) - { for (*freehead = visplanes[i], visplanes[i] = NULL; freehead && *freehead ;) { freehead = &(*freehead)->next; } - } + + numffloors = 0; lastopening = openings; - // texture calculation - memset(cachedheight, 0, sizeof (cachedheight)); - // left to right mapping angle = (viewangle-ANGLE_90)>>ANGLETOFINESHIFT; // scale will be unit scale at SCREENWIDTH/2 distance - basexscale = FixedDiv (FINECOSINE(angle),centerxfrac); - baseyscale = -FixedDiv (FINESINE(angle),centerxfrac); + basexscale = FixedDiv (FINECOSINE(angle), centerxfrac); + baseyscale = -FixedDiv (FINESINE(angle), centerxfrac); } static visplane_t *new_visplane(unsigned hash) @@ -387,8 +406,13 @@ static visplane_t *new_visplane(unsigned hash) visplane_t *check = freetail; if (!check) { - check = malloc(sizeof (*check)); - if (check == NULL) I_Error("%s: Out of memory", "new_visplane"); // FIXME: ugly + check = calloc(1, sizeof (*check)); + if (check == NULL) + I_Error("new_visplane: Out of memory"); + check->top_memory = Z_Malloc(sizeof(UINT16) * (viewwidth + 2), PU_STATIC, NULL); + check->bottom_memory = Z_Malloc(sizeof(UINT16) * (viewwidth + 2), PU_STATIC, NULL); + check->top = check->top_memory + 1; + check->bottom = check->bottom_memory + 1; } else { @@ -514,8 +538,8 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, check->slope = slope; check->noencore = noencore; - memset(check->top, 0xff, sizeof (check->top)); - memset(check->bottom, 0x00, sizeof (check->bottom)); + memset(check->top, 0xff, sizeof(*check->top) * viewwidth); + memset(check->bottom, 0x00, sizeof(*check->bottom) * viewwidth); return check; } @@ -592,8 +616,8 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop) pl = new_pl; pl->minx = start; pl->maxx = stop; - memset(pl->top, 0xff, sizeof pl->top); - memset(pl->bottom, 0x00, sizeof pl->bottom); + memset(pl->top, 0xff, sizeof(*pl->top) * viewwidth); + memset(pl->bottom, 0x00, sizeof(*pl->bottom) * viewwidth); } return pl; } @@ -940,9 +964,9 @@ void R_DrawSinglePlane(visplane_t *pl) else light = (pl->lightlevel >> LIGHTSEGSHIFT); } - if (!pl->slope && viewangle != pl->viewangle+pl->plangle) // Don't mess with angle on slopes! We'll handle this ourselves later + // Don't mess with angle on slopes! We'll handle this ourselves later + if (!pl->slope && viewangle != pl->viewangle+pl->plangle) { - memset(cachedheight, 0, sizeof (cachedheight)); angle = (pl->viewangle+pl->plangle-ANGLE_90)>>ANGLETOFINESHIFT; basexscale = FixedDiv(FINECOSINE(angle),centerxfrac); baseyscale = -FixedDiv(FINESINE(angle),centerxfrac); diff --git a/src/r_plane.h b/src/r_plane.h index 5f0db2c7c..2cb01a1c8 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -43,9 +43,8 @@ typedef struct visplane_s // colormaps per sector extracolormap_t *extra_colormap; - // leave pads for [minx-1]/[maxx+1] - UINT16 padtopstart, top[MAXVIDWIDTH], padtopend; - UINT16 padbottomstart, bottom[MAXVIDWIDTH], padbottomend; + UINT16 *top, *top_memory; + UINT16 *bottom, *bottom_memory; INT32 high, low; // R_PlaneBounds should set these. fixed_t xoffs, yoffs; // Scrolling flats. @@ -64,18 +63,14 @@ extern visplane_t *ceilingplane; extern INT16 *lastopening, *openings; extern size_t maxopenings; -extern INT16 floorclip[MAXVIDWIDTH], ceilingclip[MAXVIDWIDTH]; -extern fixed_t frontscale[MAXVIDWIDTH], yslopetab[MAXVIDHEIGHT*16]; -extern fixed_t cachedheight[MAXVIDHEIGHT]; -extern fixed_t cacheddistance[MAXVIDHEIGHT]; -extern fixed_t cachedxstep[MAXVIDHEIGHT]; -extern fixed_t cachedystep[MAXVIDHEIGHT]; +extern INT16 *floorclip, *ceilingclip; +extern fixed_t *frontscale, *yslopetab; extern fixed_t basexscale, baseyscale; extern fixed_t *yslope; extern lighttable_t **planezlight; -void R_InitPlanes(void); +void R_AllocPlaneMemory(void); void R_ClearPlanes(void); void R_ClearFFloorClips (void); @@ -104,8 +99,8 @@ typedef struct planemgr_s fixed_t b_pos; // B for Back sector fixed_t f_frac, f_step; fixed_t b_frac, b_step; - INT16 f_clip[MAXVIDWIDTH]; - INT16 c_clip[MAXVIDWIDTH]; + INT16 *f_clip; + INT16 *c_clip; // For slope rendering; the height at the other end fixed_t f_pos_slope; diff --git a/src/r_segs.c b/src/r_segs.c index f1954f0e7..e0c85fb49 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -1591,6 +1591,33 @@ static INT64 R_CalcSegDist(seg_t* seg, INT64 x2, INT64 y2) } } +static size_t maxdrawsegs = 0; + +static fixed_t *frontscaletable = NULL; +static fixed_t *maskedheighttable = NULL; + +void R_AllocSegMemory(void) +{ + if (!maxdrawsegs) + return; + + frontscaletable = Z_Realloc(frontscaletable, sizeof(*frontscaletable) * (maxdrawsegs * viewwidth), PU_STATIC, NULL); + maskedheighttable = Z_Realloc(maskedheighttable, sizeof(*maskedheighttable) * (maxdrawsegs * viewwidth), PU_STATIC, NULL); + + drawseg_t *lastseg = drawsegs + maxdrawsegs; + + fixed_t *frontscale_p = frontscaletable; + fixed_t *maskedheight_p = maskedheighttable; + + for (drawseg_t *ds = drawsegs; ds < lastseg; ds++) + { + ds->frontscale = frontscale_p; + ds->maskedtextureheight = maskedheight_p; + frontscale_p += viewwidth; + maskedheight_p += viewwidth; + } +} + // // R_StoreWallRange // A wall segment will be drawn @@ -1609,7 +1636,6 @@ void R_StoreWallRange(INT32 start, INT32 stop) INT32 range; vertex_t segleft, segright; fixed_t ceilingfrontslide, floorfrontslide, ceilingbackslide, floorbackslide; - static size_t maxdrawsegs = 0; maskedtextureheight = NULL; //initialize segleft and segright @@ -1620,13 +1646,20 @@ void R_StoreWallRange(INT32 start, INT32 stop) { size_t pos = ds_p - drawsegs; size_t newmax = maxdrawsegs ? maxdrawsegs*2 : 128; + if (firstseg) firstseg = (drawseg_t *)(firstseg - drawsegs); + drawsegs = Z_Realloc(drawsegs, newmax*sizeof (*drawsegs), PU_STATIC, NULL); + ds_p = drawsegs + pos; + maxdrawsegs = newmax; + if (firstseg) firstseg = drawsegs + (size_t)firstseg; + + R_AllocSegMemory(); } sidedef = curline->sidedef; diff --git a/src/r_segs.h b/src/r_segs.h index 006e81279..23d4ec36b 100644 --- a/src/r_segs.h +++ b/src/r_segs.h @@ -18,9 +18,12 @@ #pragma interface #endif -transnum_t R_GetLinedefTransTable(fixed_t alpha); void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2); void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pffloor); void R_StoreWallRange(INT32 start, INT32 stop); +void R_AllocSegMemory(void); + +transnum_t R_GetLinedefTransTable(fixed_t alpha); + #endif diff --git a/src/r_splats.c b/src/r_splats.c index 13b092ad0..bcef8cf24 100644 --- a/src/r_splats.c +++ b/src/r_splats.c @@ -33,7 +33,16 @@ struct rastery_s fixed_t tx1, ty1; fixed_t tx2, ty2; // start/end points in texture at this line }; -static struct rastery_s rastertab[MAXVIDHEIGHT]; +static struct rastery_s *rastertab; + +static boolean *cliptable; + +void R_AllocFloorSpriteTables(void) +{ + //cliptable = Z_Realloc(cliptable, sizeof(*cliptable) * (viewwidth + 1), PU_STATIC, NULL); + rastertab = Z_Realloc(rastertab, sizeof(*rastertab) * viewheight, PU_STATIC, NULL); +} + static void prepare_rastertab(void); #endif diff --git a/src/r_splats.h b/src/r_splats.h index b76ab90b4..2dddb2523 100644 --- a/src/r_splats.h +++ b/src/r_splats.h @@ -75,4 +75,6 @@ void R_ClearVisibleFloorSplats(void); void R_AddVisibleFloorSplats(subsector_t *subsec); void R_DrawVisibleFloorSplats(void); +void R_AllocFloorSpriteTables(void); + #endif /*__R_SPLATS_H__*/ diff --git a/src/r_state.h b/src/r_state.h index b48f0268d..0431525e7 100644 --- a/src/r_state.h +++ b/src/r_state.h @@ -104,7 +104,7 @@ extern angle_t clipangle; extern angle_t doubleclipangle; extern INT32 viewangletox[FINEANGLES/2]; -extern angle_t xtoviewangle[MAXVIDWIDTH+1]; +extern angle_t *xtoviewangle; extern fixed_t rw_distance; extern angle_t rw_normalangle; diff --git a/src/r_things.c b/src/r_things.c index 71fb42948..b3d68bd30 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -69,8 +69,8 @@ typedef struct static lighttable_t **spritelights; // constant arrays used for psprite clipping and initializing clipping -INT16 negonearray[MAXVIDWIDTH]; -INT16 screenheightarray[MAXVIDWIDTH]; +INT16 *negonearray; +INT16 *screenheightarray; spriteinfo_t spriteinfo[NUMSPRITES]; @@ -498,11 +498,6 @@ void R_InitSprites(void) float fa; #endif - for (i = 0; i < MAXVIDWIDTH; i++) - { - negonearray[i] = -1; - } - #ifdef ROTSPRITE for (angle = 1; angle < ROTANGLES; angle++) { @@ -550,6 +545,34 @@ void R_ClearSprites(void) visspritecount = numvisiblesprites = clippedvissprites = 0; } +static INT16 *vissprite_clipbot[MAXVISSPRITES >> VISSPRITECHUNKBITS]; +static INT16 *vissprite_cliptop[MAXVISSPRITES >> VISSPRITECHUNKBITS]; + +static void R_AllocVisSpriteChunkMemory(UINT32 chunk) +{ + vissprite_clipbot[chunk] = Z_Realloc(vissprite_clipbot[chunk], sizeof(INT16) * (VISSPRITESPERCHUNK * viewwidth), PU_STATIC, NULL); + vissprite_cliptop[chunk] = Z_Realloc(vissprite_cliptop[chunk], sizeof(INT16) * (VISSPRITESPERCHUNK * viewwidth), PU_STATIC, NULL); + + for (unsigned i = 0; i < VISSPRITESPERCHUNK; i++) + { + vissprite_t *sprite = visspritechunks[chunk] + i; + + sprite->clipbot = vissprite_clipbot[chunk] + (viewwidth * i); + sprite->cliptop = vissprite_cliptop[chunk] + (viewwidth * i); + } +} + +void R_AllocVisSpriteMemory(void) +{ + unsigned numchunks = MAXVISSPRITES >> VISSPRITECHUNKBITS; + + for (unsigned i = 0; i < numchunks; i++) + { + if (visspritechunks[i]) + R_AllocVisSpriteChunkMemory(i); + } +} + // // R_NewVisSprite // @@ -561,7 +584,10 @@ static vissprite_t *R_GetVisSprite(UINT32 num) // Allocate chunk if necessary if (!visspritechunks[chunk]) + { Z_Malloc(sizeof(vissprite_t) * VISSPRITESPERCHUNK, PU_LEVEL, &visspritechunks[chunk]); + R_AllocVisSpriteChunkMemory(chunk); + } return visspritechunks[chunk] + (num & VISSPRITEINDEXMASK); } @@ -967,14 +993,9 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) // static void R_SplitSprite(vissprite_t *sprite) { - INT32 i, lightnum, lindex; - INT16 cutfrac; - sector_t *sector; - vissprite_t *newsprite; + sector_t *sector = sprite->sector; - sector = sprite->sector; - - for (i = 1; i < sector->numlights; i++) + for (INT32 i = 1; i < sector->numlights; i++) { fixed_t testheight; @@ -988,7 +1009,7 @@ static void R_SplitSprite(vissprite_t *sprite) if (testheight <= sprite->gz) return; - cutfrac = (INT16)((centeryfrac - FixedMul(testheight - viewz, sprite->sortscale))>>FRACBITS); + INT16 cutfrac = (INT16)((centeryfrac - FixedMul(testheight - viewz, sprite->sortscale))>>FRACBITS); if (cutfrac < 0) continue; if (cutfrac > viewheight) @@ -996,7 +1017,16 @@ static void R_SplitSprite(vissprite_t *sprite) // Found a split! Make a new sprite, copy the old sprite to it, and // adjust the heights. - newsprite = M_Memcpy(R_NewVisSprite(), sprite, sizeof (vissprite_t)); + vissprite_t *newsprite = R_NewVisSprite(); + + // Needs to keep the new sprite's clipping tables + INT16 *cliptop = newsprite->cliptop; + INT16 *clipbot = newsprite->clipbot; + + M_Memcpy(newsprite, sprite, sizeof (vissprite_t)); + + newsprite->cliptop = cliptop; + newsprite->clipbot = clipbot; sprite->cut |= SC_BOTTOM; sprite->gz = testheight; @@ -1019,7 +1049,7 @@ static void R_SplitSprite(vissprite_t *sprite) newsprite->cut |= SC_TOP; if (!(sector->lightlist[i].caster->flags & FF_NOSHADE)) { - lightnum = (*sector->lightlist[i].lightlevel >> LIGHTSEGSHIFT); + INT32 lightnum = (*sector->lightlist[i].lightlevel >> LIGHTSEGSHIFT); if (lightnum < 0) spritelights = scalelight[0]; @@ -1033,7 +1063,7 @@ static void R_SplitSprite(vissprite_t *sprite) if (!((newsprite->cut & SC_FULLBRIGHT) && (!newsprite->extra_colormap || !(newsprite->extra_colormap->fog & 1)))) { - lindex = FixedMul(sprite->xscale, LIGHTRESOLUTIONFIX)>>(LIGHTSCALESHIFT); + INT32 lindex = FixedMul(sprite->xscale, LIGHTRESOLUTIONFIX)>>(LIGHTSCALESHIFT); // Mitigate against negative xscale and arithmetic overflow lindex = CLAMP(lindex, 0, MAXLIGHTSCALE - 1); diff --git a/src/r_things.h b/src/r_things.h index fe4f532b6..afecd2041 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -44,8 +44,8 @@ // Constant arrays used for psprite clipping // and initializing clipping. -extern INT16 negonearray[MAXVIDWIDTH]; -extern INT16 screenheightarray[MAXVIDWIDTH]; +extern INT16 *negonearray; +extern INT16 *screenheightarray; // vars for R_DrawMaskedColumn extern INT16 *mfloorclip; @@ -201,7 +201,7 @@ typedef struct vissprite_s fixed_t spritexscale, spriteyscale; fixed_t spritexoffset, spriteyoffset; - INT16 clipbot[MAXVIDWIDTH], cliptop[MAXVIDWIDTH]; + INT16 *clipbot, *cliptop; boolean precip; boolean vflip; // Flip vertically @@ -213,6 +213,8 @@ extern UINT32 visspritecount, numvisiblesprites; void R_ClipSprites(void); +void R_AllocVisSpriteMemory(void); + UINT8 *R_GetSpriteTranslation(vissprite_t *vis); // ---------- -- 2.54.0 From d2878f88348f086777f4f236e9fcf171870a0e81 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 4 Jun 2025 23:03:03 +0200 Subject: [PATCH 008/141] set MAXVIDWIDTH and MAXVIDHEIGHT to 8192 should accomidate absolutely everything --- src/m_misc.c | 4 ++-- src/screen.h | 8 ++------ 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/m_misc.c b/src/m_misc.c index 62da72038..a5a0627c9 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -1059,7 +1059,7 @@ static boolean M_SetupaPNG(png_const_charp filename, png_bytep pal) png_init_io(apng_ptr, apng_FILE); #ifdef PNG_SET_USER_LIMITS_SUPPORTED - png_set_user_limits(apng_ptr, MAXPNGWIDTH, MAXPNGHEIGHT); + png_set_user_limits(apng_ptr, MAXVIDWIDTH, MAXVIDHEIGHT); #endif //png_set_filter(apng_ptr, 0, PNG_ALL_FILTERS); @@ -1374,7 +1374,7 @@ boolean M_SavePNG(const char *filename, void *data, int width, int height, const png_init_io(png_ptr, png_FILE); #ifdef PNG_SET_USER_LIMITS_SUPPORTED - png_set_user_limits(png_ptr, MAXPNGWIDTH, MAXPNGHEIGHT); + png_set_user_limits(png_ptr, MAXVIDWIDTH, MAXVIDHEIGHT); #endif //png_set_filter(png_ptr, 0, PNG_ALL_FILTERS); diff --git a/src/screen.h b/src/screen.h index e339e3adc..d78bbf8c5 100644 --- a/src/screen.h +++ b/src/screen.h @@ -39,15 +39,11 @@ // we try to re-allocate a minimum of buffers for stability of the memory, // so all the small-enough tables based on screen size, are allocated once // and for all at the maximum size. -#define MAXVIDWIDTH 5120 // don't set this too high because actually -#define MAXVIDHEIGHT 2880 // lots of tables are allocated with the MAX size. +#define MAXVIDWIDTH 8192 // don't set this too high because actually +#define MAXVIDHEIGHT 8192 // lots of tables are allocated with the MAX size. #define BASEVIDWIDTH 320 // NEVER CHANGE THIS! This is the original #define BASEVIDHEIGHT 200 // resolution of the graphics. -// max res for png capture; just here to prevent some crashes on very high resolutions; tho you should never go this high cause ogl allocs certain things with MAXVIDWIDTH and MAXVIDHEIGHT too Zzz... -#define MAXPNGWIDTH 7680 -#define MAXPNGHEIGHT 4320 - // global video state typedef struct viddef_s { -- 2.54.0 From 51d5023f297f9160f41dfe61bfdbe0502ec7e174 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 5 Jun 2025 00:44:50 +0200 Subject: [PATCH 009/141] =?UTF-8?q?those=20can=20be=20just=20"while"=20l?= =?UTF-8?q?=C3=B6=C3=B6ps?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/r_draw8.c | 12 +++--------- src/r_segs.c | 2 +- src/r_things.c | 4 ++-- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/r_draw8.c b/src/r_draw8.c index 74d32a356..e79482eaf 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -45,8 +45,6 @@ void R_DrawColumn_8(void) } // Framebuffer destination address. - // Use ylookup LUT to avoid multiply with ScreenWidth. - // Use columnofs LUT for subwindows? dest = R_Address(dc_x, dc_yl); count++; @@ -170,8 +168,6 @@ void R_Draw2sMultiPatchColumn_8(void) } // Framebuffer destination address. - // Use ylookup LUT to avoid multiply with ScreenWidth. - // Use columnofs LUT for subwindows? dest = R_Address(dc_x, dc_yl); count++; @@ -312,8 +308,6 @@ void R_Draw2sMultiPatchTranslucentColumn_8(void) } // Framebuffer destination address. - // Use ylookup LUT to avoid multiply with ScreenWidth. - // Use columnofs LUT for subwindows? dest = R_Address(dc_x, dc_yl); count++; @@ -1815,9 +1809,6 @@ void R_DrawFogColumn_8(void) #endif // Framebuffer destination address. - // Use ylookup LUT to avoid multiply with ScreenWidth. - // Use columnofs LUT for subwindows? - //dest = ylookup[dc_yl] + columnofs[dc_x]; dest = R_Address(dc_x, dc_yl); // Determine scaling, which is the only mapping to be done. @@ -1860,6 +1851,7 @@ void R_DrawColumnShadowed_8(void) solid = dc_lightlist[i].flags & FF_CUTSOLIDS; height = dc_lightlist[i].height >> LIGHTSCALESHIFT; + if (solid) { bheight = dc_lightlist[i].botheight >> LIGHTSCALESHIFT; @@ -1874,6 +1866,7 @@ void R_DrawColumnShadowed_8(void) bheight = temp; } } + if (height <= dc_yl) { dc_colormap = dc_lightlist[i].rcolormap; @@ -1883,6 +1876,7 @@ void R_DrawColumnShadowed_8(void) dc_yl = bheight; continue; } + // Found a break in the column! dc_yh = height; diff --git a/src/r_segs.c b/src/r_segs.c index e0c85fb49..ced4e7645 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -89,7 +89,7 @@ static void R_DrawSplatColumn(column_t *column) basetexturemid = dc_texturemid; - for (; column->topdelta != 0xff ;) + while (column->topdelta != 0xff) { // calculate unclipped screen coordinates for post topdelta = column->topdelta; diff --git a/src/r_things.c b/src/r_things.c index b3d68bd30..10d35abf7 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -621,7 +621,7 @@ void R_DrawMaskedColumn(column_t *column) basetexturemid = dc_texturemid; - for (; column->topdelta != 0xff ;) + while (column->topdelta != 0xff) { // calculate unclipped screen coordinates // for post @@ -678,7 +678,7 @@ static void R_DrawFlippedMaskedColumn(column_t *column) INT32 topdelta, prevdelta = -1; UINT8 *d,*s; - for (; column->topdelta != 0xff ;) + while (column->topdelta != 0xff) { // calculate unclipped screen coordinates // for post -- 2.54.0 From 41c4300ec2342eaa09772afa2d7211441e87e555 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 5 Jun 2025 00:52:40 +0200 Subject: [PATCH 010/141] split r_draw8 into r_drawcolumn and r_drawspan + remove the _8 from the "namespace" since we dont have highcolor stuff --- src/r_draw.c | 5 +- src/r_draw.h | 54 +- src/r_draw_column.c | 844 +++++++++++++++++++++++++++++ src/{r_draw8.c => r_draw_span.c} | 876 +------------------------------ src/r_plane.c | 26 +- src/r_segs.c | 10 +- src/screen.c | 20 +- 7 files changed, 930 insertions(+), 905 deletions(-) create mode 100644 src/r_draw_column.c rename src/{r_draw8.c => r_draw_span.c} (59%) diff --git a/src/r_draw.c b/src/r_draw.c index cecb931c6..32c71ca21 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -678,7 +678,8 @@ void R_DrawViewBorder(void) #endif // ========================================================================== -// INCLUDE 8bpp DRAWING CODE HERE +// INCLUDE DRAWING CODE HERE // ========================================================================== -#include "r_draw8.c" +#include "r_draw_column.c" +#include "r_draw_span.c" diff --git a/src/r_draw.h b/src/r_draw.h index f99c1d892..7c2ef289a 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -161,33 +161,45 @@ void R_DrawViewBorder(void); #define TRANSPARENTPIXEL 247 // ----------------- -// 8bpp DRAWING CODE +// DRAWING CODE // ----------------- -void R_DrawColumn_8(void); -#define R_DrawWallColumn_8 R_DrawColumn_8 -void R_DrawShadeColumn_8(void); -void R_DrawTranslucentColumn_8(void); +void R_DrawColumn(void); +#define R_DrawWallColumn R_DrawColumn +void R_DrawShadeColumn(void); + +void R_DrawTranslucentColumn(void); + +void R_DrawTranslatedColumn(void); +void R_DrawTranslatedTranslucentColumn(void); + +void R_Draw2sMultiPatchColumn(void); +void R_Draw2sMultiPatchTranslucentColumn(void); + +void R_DrawFogColumn(void); + +void R_DrawColumnShadowed(void); + +void R_DrawSpan(void); -void R_DrawTranslatedColumn_8(void); -void R_DrawTranslatedTranslucentColumn_8(void); -void R_DrawSpan_8(void); void R_CalcTiltedLighting(fixed_t start, fixed_t end); -void R_DrawTiltedSpan_8(void); -void R_DrawTiltedTranslucentSpan_8(void); + +void R_DrawTiltedSpan(void); +void R_DrawTiltedTranslucentSpan(void); + +void R_DrawTiltedSplat(void); +void R_DrawSplat(void); + +void R_DrawTranslucentSplat(void); +void R_DrawTranslucentSpan(void); +void R_DrawTranslucentWaterSpan(void); #ifndef NOWATER -void R_DrawTiltedTranslucentWaterSpan_8(void); +void R_DrawTiltedTranslucentWaterSpan(void); #endif -void R_DrawTiltedSplat_8(void); -void R_DrawSplat_8(void); -void R_DrawTranslucentSplat_8(void); -void R_DrawTranslucentSpan_8(void); -void R_DrawTranslucentWaterSpan_8(void); -void R_Draw2sMultiPatchColumn_8(void); -void R_Draw2sMultiPatchTranslucentColumn_8(void); -void R_DrawFogSpan_8(void); -void R_DrawFogColumn_8(void); -void R_DrawColumnShadowed_8(void); + +void R_DrawFogSpan(void); + + // ========================================================================= #endif // __R_DRAW__ diff --git a/src/r_draw_column.c b/src/r_draw_column.c new file mode 100644 index 000000000..60c39db56 --- /dev/null +++ b/src/r_draw_column.c @@ -0,0 +1,844 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2018 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file r_draw_column.c +/// \brief column drawer functions +/// \note no includes because this is included as part of r_draw.c + +// ========================================================================== +// COLUMNS +// ========================================================================== + +// A column is a vertical slice/span of a wall texture that uses +// a has a constant z depth from top to bottom. +// + +/** \brief The R_DrawColumn function + Experiment to make software go faster. Taken from the Boom source +*/ +void R_DrawColumn(void) +{ + INT32 count; + UINT8 *restrict dest; + intptr_t frac; + intptr_t fracstep; + INT32 npow2min; + INT32 npow2max; + + count = dc_yh - dc_yl; + + if (count < 0) // Zero length, column does not exceed a pixel. + { + return; + } + + + if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) + { + return; + } + + // Framebuffer destination address. + dest = R_Address(dc_x, dc_yl); + + count++; + + // Determine scaling, which is the only mapping to be done. + fracstep = dc_iscale; + frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep))*(!dc_hires); + + // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. + // This is as fast as it gets. + const UINT8 *restrict source = dc_source; + const lighttable_t *restrict colormap = dc_colormap; + + intptr_t heightmask = dc_sourcelength-1; + npow2min = -1; + npow2max = dc_sourcelength; + + if (dc_sourcelength & heightmask) // not a power of 2 -- killough + { + heightmask = dc_texheight << FRACBITS; + + if (frac < 0) + { + while ((frac += heightmask) < 0) + { + ; + } + } + else + { + while (frac >= heightmask) + { + frac -= heightmask; + } + } + + do + { + // Re-map color indices from wall texture column + // using a lighting/special effects LUT. + // heightmask is the Tutti-Frutti fix + + // -1 is the lower clamp bound because column posts have a "safe" byte before the real data + // and a few bytes after as well + + // jartha: faster on my AMD FX-6300 CPU. + // Faster than ternaries, faster than std::min/std::max. Don't ask me why. + // I tested by viewing a non-PO2 texture from a consistent distance so it covered the entire screen. + // The framerate difference was about 50 frames at 640x400. + INT32 n = frac >> FRACBITS; + if (n < npow2min) + n = npow2min; + if (n > npow2max) + n = npow2max; + *dest = colormap[source[n]]; + + dest += vid.width; + + +#if __SIZEOF_POINTER__ < 8 // 64-bit systems have large enough numbers for this to be a non-issue + // Avoid overflow. + if (fracstep > 0x7FFFFFFF - frac) + { + frac += fracstep - heightmask; + } + else +#endif + { + frac += fracstep; + } + + while (frac >= heightmask) + { + frac -= heightmask; + } + } while (--count); + } + else + { + while ((count -= 2) >= 0) // texture height is a power of 2 + { + *dest = colormap[source[(frac>>FRACBITS) & heightmask]]; + + dest += vid.width; + frac += fracstep; + + *dest = colormap[source[(frac>>FRACBITS) & heightmask]]; + + dest += vid.width; + frac += fracstep; + } + + if (count & 1) + { + *dest = colormap[source[(frac>>FRACBITS) & heightmask]]; + } + } +} + + +void R_Draw2sMultiPatchColumn(void) +{ + INT32 count; + UINT8 *restrict dest; + intptr_t frac; + intptr_t fracstep; + + INT32 npow2min; + INT32 npow2max; + + count = dc_yh - dc_yl; + + if (count < 0) // Zero length, column does not exceed a pixel. + { + return; + } + + if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) + { + return; + } + + // Framebuffer destination address. + dest = R_Address(dc_x, dc_yl); + + count++; + + // Determine scaling, which is the only mapping to be done. + fracstep = dc_iscale; + frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep))*(!dc_hires); + + // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. + // This is as fast as it gets. + const UINT8 *restrict source = dc_source; + const lighttable_t *restrict colormap = dc_colormap; + intptr_t heightmask = dc_sourcelength-1; + UINT8 val; + + npow2min = -1; + npow2max = dc_sourcelength; + + if (dc_sourcelength & heightmask) // not a power of 2 -- killough + { + heightmask = dc_texheight << FRACBITS; + + if (frac < 0) + { + while ((frac += heightmask) < 0) + { + ; + } + } + else + { + while (frac >= heightmask) + { + frac -= heightmask; + } + } + + do + { + // Re-map color indices from wall texture column + // using a lighting/special effects LUT. + // heightmask is the Tutti-Frutti fix + + // -1 is the lower clamp bound because column posts have a "safe" byte before the real data + // and a few bytes after as well + + // jartha: faster on my AMD FX-6300 CPU. + // Faster than ternaries, faster than std::min/std::max. Don't ask me why. + // I tested by viewing a non-PO2 texture from a consistent distance so it covered the entire screen. + // The framerate difference was about 50 frames at 640x400. + INT32 n = frac >> FRACBITS; + if (n < npow2min) + n = npow2min; + if (n > npow2max) + n = npow2max; + + val = source[n]; + + if (val != TRANSPARENTPIXEL) + { + *dest = colormap[val]; + } + + dest += vid.width; + + // Avoid overflow. +#if __SIZEOF_POINTER__ < 8 + if (fracstep > 0x7FFFFFFF - frac) + { + frac += fracstep - heightmask; + } + else +#endif + { + frac += fracstep; + } + + while (frac >= heightmask) + { + frac -= heightmask; + } + } while (--count); + } + else + { + while ((count -= 2) >= 0) // texture height is a power of 2 + { + val = source[(frac>>FRACBITS) & heightmask]; + if (val != TRANSPARENTPIXEL) + { + *dest = colormap[val]; + } + + dest += vid.width; + frac += fracstep; + + val = source[(frac>>FRACBITS) & heightmask]; + if (val != TRANSPARENTPIXEL) + { + *dest = colormap[val]; + } + + dest += vid.width; + frac += fracstep; + } + + if (count & 1) + { + val = source[(frac>>FRACBITS) & heightmask]; + if (val != TRANSPARENTPIXEL) + { + *dest = colormap[val]; + } + } + } +} + +void R_Draw2sMultiPatchTranslucentColumn(void) +{ + INT32 count; + UINT8 *restrict dest; + intptr_t frac; + intptr_t fracstep; + + INT32 npow2min; + INT32 npow2max; + + count = dc_yh - dc_yl; + + if (count < 0) // Zero length, column does not exceed a pixel. + { + return; + } + + if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) + { + return; + } + + // Framebuffer destination address. + dest = R_Address(dc_x, dc_yl); + + count++; + + // Determine scaling, which is the only mapping to be done. + fracstep = dc_iscale; + frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep))*(!dc_hires); + + // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. + // This is as fast as it gets. + const UINT8 *restrict source = dc_source; + const UINT8 *transmap = dc_transmap; + const lighttable_t *restrict colormap = dc_colormap; + intptr_t heightmask = dc_sourcelength-1; + register UINT8 val; + + npow2min = -1; + npow2max = dc_sourcelength; + + if (dc_sourcelength & heightmask) // not a power of 2 -- killough + { + heightmask = dc_texheight << FRACBITS; + + if (frac < 0) + { + while ((frac += heightmask) < 0) + { + ; + } + } + else + { + while (frac >= heightmask) + { + frac -= heightmask; + } + } + + do + { + // Re-map color indices from wall texture column + // using a lighting/special effects LUT. + // heightmask is the Tutti-Frutti fix + + // -1 is the lower clamp bound because column posts have a "safe" byte before the real data + // and a few bytes after as well + + // jartha: faster on my AMD FX-6300 CPU. + // Faster than ternaries, faster than std::min/std::max. Don't ask me why. + // I tested by viewing a non-PO2 texture from a consistent distance so it covered the entire screen. + // The framerate difference was about 50 frames at 640x400. + INT32 n = frac >> FRACBITS; + if (n < npow2min) + n = npow2min; + if (n > npow2max) + n = npow2max; + + val = source[n]; + + if (val != TRANSPARENTPIXEL) + { + *dest = *(transmap + (colormap[val]<<8) + (*dest)); + } + + dest += vid.width; + + // Avoid overflow. +#if __SIZEOF_POINTER__ < 8 + if (fracstep > 0x7FFFFFFF - frac) + { + frac += fracstep - heightmask; + } + else +#endif + { + frac += fracstep; + } + + while (frac >= heightmask) + { + frac -= heightmask; + } + } while (--count); + } + else + { + while ((count -= 2) >= 0) // texture height is a power of 2 + { + val = source[(frac>>FRACBITS) & heightmask]; + if (val != TRANSPARENTPIXEL) + { + *dest = *(transmap + (colormap[val]<<8) + (*dest)); + } + + dest += vid.width; + frac += fracstep; + + val = source[(frac>>FRACBITS) & heightmask]; + if (val != TRANSPARENTPIXEL) + { + *dest = *(transmap + (colormap[val]<<8) + (*dest)); + } + + dest += vid.width; + frac += fracstep; + } + + if (count & 1) + { + val = source[(frac>>FRACBITS) & heightmask]; + if (val != TRANSPARENTPIXEL) + { + *dest = *(transmap + (colormap[val]<<8) + (*dest)); + } + } + } +} + +/** \brief The R_DrawShadeColumn function + Experiment to make software go faster. Taken from the Boom source +*/ +void R_DrawShadeColumn(void) +{ + register INT32 count; + register UINT8 *dest; + register fixed_t frac, fracstep; + + // check out coords for src* + if ((dc_yl < 0) || (dc_x >= vid.width)) + return; + + count = dc_yh - dc_yl; + + if (count < 0) // Zero length, column does not exceed a pixel. + { + return; + } + + if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) + { + return; + } + + // FIXME. As above. + dest = R_Address(dc_x, dc_yl); + + // Looks familiar. + fracstep = dc_iscale; + frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep))*(!dc_hires); + + // Here we do an additional index re-mapping. + do + { + *dest = colormaps[(dc_source[frac>>FRACBITS] <<8) + (*dest)]; + dest += vid.width; + frac += fracstep; + } while (count--); +} + +/** \brief The R_DrawTranslucentColumn function + I've made an asm routine for the transparency, because it slows down + a lot in 640x480 with big sprites (bfg on all screen, or transparent + walls on fullscreen) +*/ +void R_DrawTranslucentColumn(void) +{ + register INT32 count; + UINT8 *restrict dest; + intptr_t frac; + intptr_t fracstep; + + INT32 npow2min; + INT32 npow2max; + + count = dc_yh - dc_yl + 1; + + if (count <= 0) // Zero length, column does not exceed a pixel. + { + return; + } + + if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) + { + return; + } + + // FIXME. As above. + dest = R_Address(dc_x, dc_yl); + + // Looks familiar. + fracstep = dc_iscale; + frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep))*(!dc_hires); + + // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. + // This is as fast as it gets. + const UINT8 *restrict source = dc_source; + const UINT8 *transmap = dc_transmap; + const lighttable_t *restrict colormap = dc_colormap; + intptr_t heightmask = dc_sourcelength-1; + + npow2min = -1; + npow2max = dc_sourcelength; + + if (dc_sourcelength & heightmask) + { + heightmask = dc_texheight << FRACBITS; + + if (frac < 0) + { + while ((frac += heightmask) < 0) + { + ; + } + } + else + { + while (frac >= heightmask) + { + frac -= heightmask; + } + } + + do + { + // Re-map color indices from wall texture column + // using a lighting/special effects LUT. + // heightmask is the Tutti-Frutti fix + + // -1 is the lower clamp bound because column posts have a "safe" byte before the real data + // and a few bytes after as well + + // jartha: faster on my AMD FX-6300 CPU. + // Faster than ternaries, faster than std::min/std::max. Don't ask me why. + // I tested by viewing a non-PO2 texture from a consistent distance so it covered the entire screen. + // The framerate difference was about 50 frames at 640x400. + INT32 n = frac >> FRACBITS; + if (n < npow2min) + n = npow2min; + if (n > npow2max) + n = npow2max; + + *dest = *(transmap + (colormap[source[n]]<<8) + (*dest)); + + dest += vid.width; + + if ((frac += fracstep) >= heightmask) + { + frac -= heightmask; + } + } + while (--count); + } + else + { + while ((count -= 2) >= 0) // texture height is a power of 2 + { + *dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); + dest += vid.width; + frac += fracstep; + + *dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); + dest += vid.width; + frac += fracstep; + } + + if (count & 1) + { + *dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); + } + } +} + +/** \brief The R_DrawTranslatedTranslucentColumn function + Spiffy function. Not only does it colormap a sprite, but does translucency as well. + Uber-kudos to Cyan Helkaraxe +*/ +void R_DrawTranslatedTranslucentColumn(void) +{ + register INT32 count; + UINT8 *restrict dest; + intptr_t frac; + intptr_t fracstep; + + INT32 npow2min; + INT32 npow2max; + + count = dc_yh - dc_yl + 1; + + if (count <= 0) // Zero length, column does not exceed a pixel. + { + return; + } + + if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) + { + return; + } + + // FIXME. As above. + dest = R_Address(dc_x, dc_yl); + + // Looks familiar. + fracstep = dc_iscale; + frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep))*(!dc_hires); + + // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. + // This is as fast as it gets. + intptr_t heightmask = dc_sourcelength-1; + + npow2min = -1; + npow2max = dc_sourcelength; + + if (dc_sourcelength & heightmask) + { + heightmask = dc_texheight << FRACBITS; + + if (frac < 0) + { + while ((frac += heightmask) < 0) + { + ; + } + } + else + { + while (frac >= heightmask) + { + frac -= heightmask; + } + } + + do + { + // Re-map color indices from wall texture column + // using a lighting/special effects LUT. + // heightmask is the Tutti-Frutti fix + + // -1 is the lower clamp bound because column posts have a "safe" byte before the real data + // and a few bytes after as well + + // jartha: faster on my AMD FX-6300 CPU. + // Faster than ternaries, faster than std::min/std::max. Don't ask me why. + // I tested by viewing a non-PO2 texture from a consistent distance so it covered the entire screen. + // The framerate difference was about 50 frames at 640x400. + INT32 n = frac >> FRACBITS; + if (n < npow2min) + n = npow2min; + if (n > npow2max) + n = npow2max; + + *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[n]]]<<8) + (*dest)); + + dest += vid.width; + + if ((frac += fracstep) >= heightmask) + { + frac -= heightmask; + } + } + while (--count); + } + else + { + while ((count -= 2) >= 0) // texture height is a power of 2 + { + *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); + dest += vid.width; + frac += fracstep; + + *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); + dest += vid.width; + frac += fracstep; + } + + if (count & 1) + { + *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); + } + } +} + +/** \brief The R_DrawTranslatedColumn function + Draw columns up to 128 high but remap the green ramp to other colors + + \warning STILL NOT IN ASM, TO DO.. +*/ +void R_DrawTranslatedColumn(void) +{ + register INT32 count; + register UINT8 *dest; + register fixed_t frac, fracstep; + + count = dc_yh - dc_yl; + + if (count < 0) + { + return; + } + + if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) + { + return; + } + + // FIXME. As above. + dest = R_Address(dc_x, dc_yl); + + // Looks familiar. + fracstep = dc_iscale; + frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep))*(!dc_hires); + + // Here we do an additional index re-mapping. + do + { + // Translation tables are used + // to map certain colorramps to other ones, + // used with PLAY sprites. + // Thus the "green" ramp of the player 0 sprite + // is mapped to gray, red, black/indigo. + *dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]; + + dest += vid.width; + + frac += fracstep; + } while (count--); +} + +/** \brief The R_DrawFogColumn function + Fog wall. +*/ +void R_DrawFogColumn(void) +{ + register INT32 count; + register UINT8 *dest; + + count = dc_yh - dc_yl; + + // Zero length, column does not exceed a pixel. + if (count < 0) + return; + +#ifdef RANGECHECK + if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) + I_Error("R_DrawFogColumn: %d to %d at %d", dc_yl, dc_yh, dc_x); +#endif + + // Framebuffer destination address. + dest = R_Address(dc_x, dc_yl); + + // Determine scaling, which is the only mapping to be done. + do + { + // Simple. Apply the colormap to what's already on the screen. + *dest = dc_colormap[*dest]; + dest += vid.width; + } while (count--); +} + +/** \brief The R_DrawShadeColumn function + This is for 3D floors that cast shadows on walls. + + This function just cuts the column up into sections and calls R_DrawColumn +*/ +void R_DrawColumnShadowed(void) +{ + register INT32 count; + INT32 realyh, i, height, bheight = 0, solid = 0; + + realyh = dc_yh; + + count = dc_yh - dc_yl; + + // Zero length, column does not exceed a pixel. + if (count < 0) + return; + +#ifdef RANGECHECK + if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) + I_Error("R_DrawColumnShadowed: %d to %d at %d", dc_yl, dc_yh, dc_x); +#endif + + // This runs through the lightlist from top to bottom and cuts up the column accordingly. + for (i = 0; i < dc_numlights; i++) + { + // If the height of the light is above the column, get the colormap + // anyway because the lighting of the top should be affected. + solid = dc_lightlist[i].flags & FF_CUTSOLIDS; + + height = dc_lightlist[i].height >> LIGHTSCALESHIFT; + + if (solid) + { + bheight = dc_lightlist[i].botheight >> LIGHTSCALESHIFT; + if (bheight < height) + { + // confounded slopes sometimes allow partial invertedness, + // even including cases where the top and bottom heights + // should actually be the same! + // swap the height values as a workaround for this quirk + INT32 temp = height; + height = bheight; + bheight = temp; + } + } + + if (height <= dc_yl) + { + dc_colormap = dc_lightlist[i].rcolormap; + if (encoremap) + dc_colormap += COLORMAP_REMAPOFFSET; + if (solid && dc_yl < bheight) + dc_yl = bheight; + continue; + } + + // Found a break in the column! + dc_yh = height; + + if (dc_yh > realyh) + dc_yh = realyh; + basecolfunc(); // R_DrawColumn for the appropriate architecture + if (solid) + dc_yl = bheight; + else + dc_yl = dc_yh + 1; + + dc_colormap = dc_lightlist[i].rcolormap; + if (encoremap) + dc_colormap += COLORMAP_REMAPOFFSET; + } + dc_yh = realyh; + if (dc_yl <= realyh) + walldrawerfunc(); // R_DrawWallColumn for the appropriate architecture +} diff --git a/src/r_draw8.c b/src/r_draw_span.c similarity index 59% rename from src/r_draw8.c rename to src/r_draw_span.c index e79482eaf..2b47ac45b 100644 --- a/src/r_draw8.c +++ b/src/r_draw_span.c @@ -7,734 +7,10 @@ // terms of the GNU General Public License, version 2. // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file r_draw8.c -/// \brief 8bpp span/column drawer functions +/// \file r_draw_span.c +/// \brief span drawer functions /// \note no includes because this is included as part of r_draw.c -// ========================================================================== -// COLUMNS -// ========================================================================== - -// A column is a vertical slice/span of a wall texture that uses -// a has a constant z depth from top to bottom. -// - -/** \brief The R_DrawColumn_8 function - Experiment to make software go faster. Taken from the Boom source -*/ -void R_DrawColumn_8(void) -{ - INT32 count; - UINT8 *restrict dest; - intptr_t frac; - intptr_t fracstep; - INT32 npow2min; - INT32 npow2max; - - count = dc_yh - dc_yl; - - if (count < 0) // Zero length, column does not exceed a pixel. - { - return; - } - - - if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) - { - return; - } - - // Framebuffer destination address. - dest = R_Address(dc_x, dc_yl); - - count++; - - // Determine scaling, which is the only mapping to be done. - fracstep = dc_iscale; - frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep))*(!dc_hires); - - // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. - // This is as fast as it gets. - const UINT8 *restrict source = dc_source; - const lighttable_t *restrict colormap = dc_colormap; - - intptr_t heightmask = dc_sourcelength-1; - npow2min = -1; - npow2max = dc_sourcelength; - - if (dc_sourcelength & heightmask) // not a power of 2 -- killough - { - heightmask = dc_texheight << FRACBITS; - - if (frac < 0) - { - while ((frac += heightmask) < 0) - { - ; - } - } - else - { - while (frac >= heightmask) - { - frac -= heightmask; - } - } - - do - { - // Re-map color indices from wall texture column - // using a lighting/special effects LUT. - // heightmask is the Tutti-Frutti fix - - // -1 is the lower clamp bound because column posts have a "safe" byte before the real data - // and a few bytes after as well - - // jartha: faster on my AMD FX-6300 CPU. - // Faster than ternaries, faster than std::min/std::max. Don't ask me why. - // I tested by viewing a non-PO2 texture from a consistent distance so it covered the entire screen. - // The framerate difference was about 50 frames at 640x400. - INT32 n = frac >> FRACBITS; - if (n < npow2min) - n = npow2min; - if (n > npow2max) - n = npow2max; - *dest = colormap[source[n]]; - - dest += vid.width; - - -#if __SIZEOF_POINTER__ < 8 // 64-bit systems have large enough numbers for this to be a non-issue - // Avoid overflow. - if (fracstep > 0x7FFFFFFF - frac) - { - frac += fracstep - heightmask; - } - else -#endif - { - frac += fracstep; - } - - while (frac >= heightmask) - { - frac -= heightmask; - } - } while (--count); - } - else - { - while ((count -= 2) >= 0) // texture height is a power of 2 - { - *dest = colormap[source[(frac>>FRACBITS) & heightmask]]; - - dest += vid.width; - frac += fracstep; - - *dest = colormap[source[(frac>>FRACBITS) & heightmask]]; - - dest += vid.width; - frac += fracstep; - } - - if (count & 1) - { - *dest = colormap[source[(frac>>FRACBITS) & heightmask]]; - } - } -} - - -void R_Draw2sMultiPatchColumn_8(void) -{ - INT32 count; - UINT8 *restrict dest; - intptr_t frac; - intptr_t fracstep; - - INT32 npow2min; - INT32 npow2max; - - count = dc_yh - dc_yl; - - if (count < 0) // Zero length, column does not exceed a pixel. - { - return; - } - - if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) - { - return; - } - - // Framebuffer destination address. - dest = R_Address(dc_x, dc_yl); - - count++; - - // Determine scaling, which is the only mapping to be done. - fracstep = dc_iscale; - frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep))*(!dc_hires); - - // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. - // This is as fast as it gets. - const UINT8 *restrict source = dc_source; - const lighttable_t *restrict colormap = dc_colormap; - intptr_t heightmask = dc_sourcelength-1; - UINT8 val; - - npow2min = -1; - npow2max = dc_sourcelength; - - if (dc_sourcelength & heightmask) // not a power of 2 -- killough - { - heightmask = dc_texheight << FRACBITS; - - if (frac < 0) - { - while ((frac += heightmask) < 0) - { - ; - } - } - else - { - while (frac >= heightmask) - { - frac -= heightmask; - } - } - - do - { - // Re-map color indices from wall texture column - // using a lighting/special effects LUT. - // heightmask is the Tutti-Frutti fix - - // -1 is the lower clamp bound because column posts have a "safe" byte before the real data - // and a few bytes after as well - - // jartha: faster on my AMD FX-6300 CPU. - // Faster than ternaries, faster than std::min/std::max. Don't ask me why. - // I tested by viewing a non-PO2 texture from a consistent distance so it covered the entire screen. - // The framerate difference was about 50 frames at 640x400. - INT32 n = frac >> FRACBITS; - if (n < npow2min) - n = npow2min; - if (n > npow2max) - n = npow2max; - - val = source[n]; - - if (val != TRANSPARENTPIXEL) - { - *dest = colormap[val]; - } - - dest += vid.width; - - // Avoid overflow. -#if __SIZEOF_POINTER__ < 8 - if (fracstep > 0x7FFFFFFF - frac) - { - frac += fracstep - heightmask; - } - else -#endif - { - frac += fracstep; - } - - while (frac >= heightmask) - { - frac -= heightmask; - } - } while (--count); - } - else - { - while ((count -= 2) >= 0) // texture height is a power of 2 - { - val = source[(frac>>FRACBITS) & heightmask]; - if (val != TRANSPARENTPIXEL) - { - *dest = colormap[val]; - } - - dest += vid.width; - frac += fracstep; - - val = source[(frac>>FRACBITS) & heightmask]; - if (val != TRANSPARENTPIXEL) - { - *dest = colormap[val]; - } - - dest += vid.width; - frac += fracstep; - } - - if (count & 1) - { - val = source[(frac>>FRACBITS) & heightmask]; - if (val != TRANSPARENTPIXEL) - { - *dest = colormap[val]; - } - } - } -} - -void R_Draw2sMultiPatchTranslucentColumn_8(void) -{ - INT32 count; - UINT8 *restrict dest; - intptr_t frac; - intptr_t fracstep; - - INT32 npow2min; - INT32 npow2max; - - count = dc_yh - dc_yl; - - if (count < 0) // Zero length, column does not exceed a pixel. - { - return; - } - - if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) - { - return; - } - - // Framebuffer destination address. - dest = R_Address(dc_x, dc_yl); - - count++; - - // Determine scaling, which is the only mapping to be done. - fracstep = dc_iscale; - frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep))*(!dc_hires); - - // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. - // This is as fast as it gets. - const UINT8 *restrict source = dc_source; - const UINT8 *transmap = dc_transmap; - const lighttable_t *restrict colormap = dc_colormap; - intptr_t heightmask = dc_sourcelength-1; - register UINT8 val; - - npow2min = -1; - npow2max = dc_sourcelength; - - if (dc_sourcelength & heightmask) // not a power of 2 -- killough - { - heightmask = dc_texheight << FRACBITS; - - if (frac < 0) - { - while ((frac += heightmask) < 0) - { - ; - } - } - else - { - while (frac >= heightmask) - { - frac -= heightmask; - } - } - - do - { - // Re-map color indices from wall texture column - // using a lighting/special effects LUT. - // heightmask is the Tutti-Frutti fix - - // -1 is the lower clamp bound because column posts have a "safe" byte before the real data - // and a few bytes after as well - - // jartha: faster on my AMD FX-6300 CPU. - // Faster than ternaries, faster than std::min/std::max. Don't ask me why. - // I tested by viewing a non-PO2 texture from a consistent distance so it covered the entire screen. - // The framerate difference was about 50 frames at 640x400. - INT32 n = frac >> FRACBITS; - if (n < npow2min) - n = npow2min; - if (n > npow2max) - n = npow2max; - - val = source[n]; - - if (val != TRANSPARENTPIXEL) - { - *dest = *(transmap + (colormap[val]<<8) + (*dest)); - } - - dest += vid.width; - - // Avoid overflow. -#if __SIZEOF_POINTER__ < 8 - if (fracstep > 0x7FFFFFFF - frac) - { - frac += fracstep - heightmask; - } - else -#endif - { - frac += fracstep; - } - - while (frac >= heightmask) - { - frac -= heightmask; - } - } while (--count); - } - else - { - while ((count -= 2) >= 0) // texture height is a power of 2 - { - val = source[(frac>>FRACBITS) & heightmask]; - if (val != TRANSPARENTPIXEL) - { - *dest = *(transmap + (colormap[val]<<8) + (*dest)); - } - - dest += vid.width; - frac += fracstep; - - val = source[(frac>>FRACBITS) & heightmask]; - if (val != TRANSPARENTPIXEL) - { - *dest = *(transmap + (colormap[val]<<8) + (*dest)); - } - - dest += vid.width; - frac += fracstep; - } - - if (count & 1) - { - val = source[(frac>>FRACBITS) & heightmask]; - if (val != TRANSPARENTPIXEL) - { - *dest = *(transmap + (colormap[val]<<8) + (*dest)); - } - } - } -} - -/** \brief The R_DrawShadeColumn_8 function - Experiment to make software go faster. Taken from the Boom source -*/ -void R_DrawShadeColumn_8(void) -{ - register INT32 count; - register UINT8 *dest; - register fixed_t frac, fracstep; - - // check out coords for src* - if ((dc_yl < 0) || (dc_x >= vid.width)) - return; - - count = dc_yh - dc_yl; - - if (count < 0) // Zero length, column does not exceed a pixel. - { - return; - } - - if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) - { - return; - } - - // FIXME. As above. - dest = R_Address(dc_x, dc_yl); - - // Looks familiar. - fracstep = dc_iscale; - frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep))*(!dc_hires); - - // Here we do an additional index re-mapping. - do - { - *dest = colormaps[(dc_source[frac>>FRACBITS] <<8) + (*dest)]; - dest += vid.width; - frac += fracstep; - } while (count--); -} - -/** \brief The R_DrawTranslucentColumn_8 function - I've made an asm routine for the transparency, because it slows down - a lot in 640x480 with big sprites (bfg on all screen, or transparent - walls on fullscreen) -*/ -void R_DrawTranslucentColumn_8(void) -{ - register INT32 count; - UINT8 *restrict dest; - intptr_t frac; - intptr_t fracstep; - - INT32 npow2min; - INT32 npow2max; - - count = dc_yh - dc_yl + 1; - - if (count <= 0) // Zero length, column does not exceed a pixel. - { - return; - } - - if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) - { - return; - } - - // FIXME. As above. - dest = R_Address(dc_x, dc_yl); - - // Looks familiar. - fracstep = dc_iscale; - frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep))*(!dc_hires); - - // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. - // This is as fast as it gets. - const UINT8 *restrict source = dc_source; - const UINT8 *transmap = dc_transmap; - const lighttable_t *restrict colormap = dc_colormap; - intptr_t heightmask = dc_sourcelength-1; - - npow2min = -1; - npow2max = dc_sourcelength; - - if (dc_sourcelength & heightmask) - { - heightmask = dc_texheight << FRACBITS; - - if (frac < 0) - { - while ((frac += heightmask) < 0) - { - ; - } - } - else - { - while (frac >= heightmask) - { - frac -= heightmask; - } - } - - do - { - // Re-map color indices from wall texture column - // using a lighting/special effects LUT. - // heightmask is the Tutti-Frutti fix - - // -1 is the lower clamp bound because column posts have a "safe" byte before the real data - // and a few bytes after as well - - // jartha: faster on my AMD FX-6300 CPU. - // Faster than ternaries, faster than std::min/std::max. Don't ask me why. - // I tested by viewing a non-PO2 texture from a consistent distance so it covered the entire screen. - // The framerate difference was about 50 frames at 640x400. - INT32 n = frac >> FRACBITS; - if (n < npow2min) - n = npow2min; - if (n > npow2max) - n = npow2max; - - *dest = *(transmap + (colormap[source[n]]<<8) + (*dest)); - - dest += vid.width; - - if ((frac += fracstep) >= heightmask) - { - frac -= heightmask; - } - } - while (--count); - } - else - { - while ((count -= 2) >= 0) // texture height is a power of 2 - { - *dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); - dest += vid.width; - frac += fracstep; - - *dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); - dest += vid.width; - frac += fracstep; - } - - if (count & 1) - { - *dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); - } - } -} - -/** \brief The R_DrawTranslatedTranslucentColumn_8 function - Spiffy function. Not only does it colormap a sprite, but does translucency as well. - Uber-kudos to Cyan Helkaraxe -*/ -void R_DrawTranslatedTranslucentColumn_8(void) -{ - register INT32 count; - UINT8 *restrict dest; - intptr_t frac; - intptr_t fracstep; - - INT32 npow2min; - INT32 npow2max; - - count = dc_yh - dc_yl + 1; - - if (count <= 0) // Zero length, column does not exceed a pixel. - { - return; - } - - if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) - { - return; - } - - // FIXME. As above. - dest = R_Address(dc_x, dc_yl); - - // Looks familiar. - fracstep = dc_iscale; - frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep))*(!dc_hires); - - // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. - // This is as fast as it gets. - intptr_t heightmask = dc_sourcelength-1; - - npow2min = -1; - npow2max = dc_sourcelength; - - if (dc_sourcelength & heightmask) - { - heightmask = dc_texheight << FRACBITS; - - if (frac < 0) - { - while ((frac += heightmask) < 0) - { - ; - } - } - else - { - while (frac >= heightmask) - { - frac -= heightmask; - } - } - - do - { - // Re-map color indices from wall texture column - // using a lighting/special effects LUT. - // heightmask is the Tutti-Frutti fix - - // -1 is the lower clamp bound because column posts have a "safe" byte before the real data - // and a few bytes after as well - - // jartha: faster on my AMD FX-6300 CPU. - // Faster than ternaries, faster than std::min/std::max. Don't ask me why. - // I tested by viewing a non-PO2 texture from a consistent distance so it covered the entire screen. - // The framerate difference was about 50 frames at 640x400. - INT32 n = frac >> FRACBITS; - if (n < npow2min) - n = npow2min; - if (n > npow2max) - n = npow2max; - - *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[n]]]<<8) + (*dest)); - - dest += vid.width; - - if ((frac += fracstep) >= heightmask) - { - frac -= heightmask; - } - } - while (--count); - } - else - { - while ((count -= 2) >= 0) // texture height is a power of 2 - { - *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); - dest += vid.width; - frac += fracstep; - - *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); - dest += vid.width; - frac += fracstep; - } - - if (count & 1) - { - *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); - } - } -} - -/** \brief The R_DrawTranslatedColumn_8 function - Draw columns up to 128 high but remap the green ramp to other colors - - \warning STILL NOT IN ASM, TO DO.. -*/ -void R_DrawTranslatedColumn_8(void) -{ - register INT32 count; - register UINT8 *dest; - register fixed_t frac, fracstep; - - count = dc_yh - dc_yl; - - if (count < 0) - { - return; - } - - if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) - { - return; - } - - // FIXME. As above. - dest = R_Address(dc_x, dc_yl); - - // Looks familiar. - fracstep = dc_iscale; - frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep))*(!dc_hires); - - // Here we do an additional index re-mapping. - do - { - // Translation tables are used - // to map certain colorramps to other ones, - // used with PLAY sprites. - // Thus the "green" ramp of the player 0 sprite - // is mapped to gray, red, black/indigo. - *dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]; - - dest += vid.width; - - frac += fracstep; - } while (count--); -} - // ========================================================================== // SPANS // ========================================================================== @@ -745,10 +21,10 @@ void R_DrawTranslatedColumn_8(void) // 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size) #define MAXFLATBYTES 4194303 -/** \brief The R_DrawSpan_8 function +/** \brief The R_DrawSpan function Draws the actual span. */ -void R_DrawSpan_8 (void) +void R_DrawSpan (void) { uintptr_t xposition; uintptr_t yposition; @@ -867,10 +143,10 @@ void R_CalcTiltedLighting(fixed_t start, fixed_t end) #define PLANELIGHTFLOAT ((float)BASEVIDWIDTH * BASEVIDWIDTH / vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f * FIXED_TO_FLOAT(fovtan)) -/** \brief The R_DrawTiltedSpan_8 function +/** \brief The R_DrawTiltedSpan function Draw slopes! Holy sheit! */ -void R_DrawTiltedSpan_8(void) +void R_DrawTiltedSpan(void) { int width = ds_x2 - ds_x1; float iz, uz, vz; @@ -1005,10 +281,10 @@ void R_DrawTiltedSpan_8(void) #endif } -/** \brief The R_DrawTiltedTranslucentSpan_8 function +/** \brief The R_DrawTiltedTranslucentSpan function Like DrawTiltedSpan, but translucent */ -void R_DrawTiltedTranslucentSpan_8(void) +void R_DrawTiltedTranslucentSpan(void) { int width = ds_x2 - ds_x1; float iz, uz, vz; @@ -1144,10 +420,10 @@ void R_DrawTiltedTranslucentSpan_8(void) } #ifndef NOWATER -/** \brief The R_DrawTiltedTranslucentWaterSpan_8 function +/** \brief The R_DrawTiltedTranslucentWaterSpan function Like DrawTiltedTranslucentSpan, but for water */ -void R_DrawTiltedTranslucentWaterSpan_8(void) +void R_DrawTiltedTranslucentWaterSpan(void) { int width = ds_x2 - ds_x1; float iz, uz, vz; @@ -1285,7 +561,7 @@ void R_DrawTiltedTranslucentWaterSpan_8(void) } #endif // NOWATER -void R_DrawTiltedSplat_8(void) +void R_DrawTiltedSplat(void) { // x1, x2 = ds_x1, ds_x2 int width = ds_x2 - ds_x1; @@ -1439,10 +715,10 @@ void R_DrawTiltedSplat_8(void) #endif } -/** \brief The R_DrawSplat_8 function - Just like R_DrawSpan_8, but skips transparent pixels. +/** \brief The R_DrawSplat function + Just like R_DrawSpan, but skips transparent pixels. */ -void R_DrawSplat_8 (void) +void R_DrawSplat (void) { UINT32 xposition; UINT32 yposition; @@ -1509,10 +785,10 @@ void R_DrawSplat_8 (void) } } -/** \brief The R_DrawTranslucentSplat_8 function - Just like R_DrawSplat_8, but is translucent! +/** \brief The R_DrawTranslucentSplat function + Just like R_DrawSplat, but is translucent! */ -void R_DrawTranslucentSplat_8 (void) +void R_DrawTranslucentSplat (void) { UINT32 xposition; UINT32 yposition; @@ -1574,10 +850,10 @@ void R_DrawTranslucentSplat_8 (void) } } -/** \brief The R_DrawTranslucentSpan_8 function +/** \brief The R_DrawTranslucentSpan function Draws the actual span with translucent. */ -void R_DrawTranslucentSpan_8 (void) +void R_DrawTranslucentSpan (void) { fixed_t xposition; fixed_t yposition; @@ -1667,7 +943,7 @@ void R_DrawTranslucentSpan_8 (void) } #ifndef NOWATER -void R_DrawTranslucentWaterSpan_8(void) +void R_DrawTranslucentWaterSpan(void) { UINT32 xposition; UINT32 yposition; @@ -1756,10 +1032,10 @@ void R_DrawTranslucentWaterSpan_8(void) } #endif -/** \brief The R_DrawFogSpan_8 function +/** \brief The R_DrawFogSpan function Draws the actual span with fogging. */ -void R_DrawFogSpan_8(void) +void R_DrawFogSpan(void) { UINT8 *colormap; register UINT8 *dest; @@ -1788,111 +1064,3 @@ void R_DrawFogSpan_8(void) dest++; } } - -/** \brief The R_DrawFogColumn_8 function - Fog wall. -*/ -void R_DrawFogColumn_8(void) -{ - register INT32 count; - register UINT8 *dest; - - count = dc_yh - dc_yl; - - // Zero length, column does not exceed a pixel. - if (count < 0) - return; - -#ifdef RANGECHECK - if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) - I_Error("R_DrawFogColumn_8: %d to %d at %d", dc_yl, dc_yh, dc_x); -#endif - - // Framebuffer destination address. - dest = R_Address(dc_x, dc_yl); - - // Determine scaling, which is the only mapping to be done. - do - { - // Simple. Apply the colormap to what's already on the screen. - *dest = dc_colormap[*dest]; - dest += vid.width; - } while (count--); -} - -/** \brief The R_DrawShadeColumn_8 function - This is for 3D floors that cast shadows on walls. - - This function just cuts the column up into sections and calls R_DrawColumn_8 -*/ -void R_DrawColumnShadowed_8(void) -{ - register INT32 count; - INT32 realyh, i, height, bheight = 0, solid = 0; - - realyh = dc_yh; - - count = dc_yh - dc_yl; - - // Zero length, column does not exceed a pixel. - if (count < 0) - return; - -#ifdef RANGECHECK - if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) - I_Error("R_DrawColumnShadowed_8: %d to %d at %d", dc_yl, dc_yh, dc_x); -#endif - - // This runs through the lightlist from top to bottom and cuts up the column accordingly. - for (i = 0; i < dc_numlights; i++) - { - // If the height of the light is above the column, get the colormap - // anyway because the lighting of the top should be affected. - solid = dc_lightlist[i].flags & FF_CUTSOLIDS; - - height = dc_lightlist[i].height >> LIGHTSCALESHIFT; - - if (solid) - { - bheight = dc_lightlist[i].botheight >> LIGHTSCALESHIFT; - if (bheight < height) - { - // confounded slopes sometimes allow partial invertedness, - // even including cases where the top and bottom heights - // should actually be the same! - // swap the height values as a workaround for this quirk - INT32 temp = height; - height = bheight; - bheight = temp; - } - } - - if (height <= dc_yl) - { - dc_colormap = dc_lightlist[i].rcolormap; - if (encoremap) - dc_colormap += COLORMAP_REMAPOFFSET; - if (solid && dc_yl < bheight) - dc_yl = bheight; - continue; - } - - // Found a break in the column! - dc_yh = height; - - if (dc_yh > realyh) - dc_yh = realyh; - basecolfunc(); // R_DrawColumn_8 for the appropriate architecture - if (solid) - dc_yl = bheight; - else - dc_yl = dc_yh + 1; - - dc_colormap = dc_lightlist[i].rcolormap; - if (encoremap) - dc_colormap += COLORMAP_REMAPOFFSET; - } - dc_yh = realyh; - if (dc_yl <= realyh) - walldrawerfunc(); // R_DrawWallColumn_8 for the appropriate architecture -} diff --git a/src/r_plane.c b/src/r_plane.c index 63155bc72..ae2a3167f 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -195,9 +195,9 @@ static void R_HandleRipplePlane(visplane_t *pl) planeripple.active = true; - if (spanfunc == R_DrawTranslucentSpan_8) + if (spanfunc == R_DrawTranslucentSpan) { - spanfunc = R_DrawTranslucentWaterSpan_8; + spanfunc = R_DrawTranslucentWaterSpan; // Copy the current scene, ugh top = pl->high-8; @@ -883,7 +883,7 @@ void R_DrawSinglePlane(visplane_t *pl) if (pl->polyobj && pl->polyobj->translucency != 0) { - spanfunc = R_DrawTranslucentSpan_8; + spanfunc = R_DrawTranslucentSpan; // Hacked up support for alpha value in software mode Tails 09-24-2002 (sidenote: ported to polys 10-15-2014, there was no time travel involved -Red) if (pl->polyobj->translucency >= 10) @@ -923,7 +923,7 @@ void R_DrawSinglePlane(visplane_t *pl) if (pl->ffloor->flags & FF_TRANSLUCENT) { - spanfunc = R_DrawTranslucentSpan_8; + spanfunc = R_DrawTranslucentSpan; // 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 @@ -949,7 +949,7 @@ void R_DrawSinglePlane(visplane_t *pl) } else if (pl->ffloor->flags & FF_FOG) { - spanfunc = R_DrawFogSpan_8; + spanfunc = R_DrawFogSpan; light = (pl->lightlevel >> LIGHTSEGSHIFT); } else light = (pl->lightlevel >> LIGHTSEGSHIFT); @@ -1115,16 +1115,16 @@ void R_DrawSinglePlane(visplane_t *pl) R_SetSlopePlaneVectors(pl, 0, xoffs, yoffs, fudgecanyon); #ifndef NOWATER - if (spanfunc == R_DrawTranslucentWaterSpan_8) - spanfunc = R_DrawTiltedTranslucentWaterSpan_8; + if (spanfunc == R_DrawTranslucentWaterSpan) + spanfunc = R_DrawTiltedTranslucentWaterSpan; else #endif - if (spanfunc == R_DrawTranslucentSpan_8) - spanfunc = R_DrawTiltedTranslucentSpan_8; + if (spanfunc == R_DrawTranslucentSpan) + spanfunc = R_DrawTiltedTranslucentSpan; else if (spanfunc == splatfunc) - spanfunc = R_DrawTiltedSplat_8; + spanfunc = R_DrawTiltedSplat; else - spanfunc = R_DrawTiltedSpan_8; + spanfunc = R_DrawTiltedSpan; planezlight = scalelight[light]; } @@ -1170,11 +1170,11 @@ a 'smoothing' of the texture while using the palette colors. */ #ifdef QUINCUNX - if (spanfunc == R_DrawSpan_8) + if (spanfunc == R_DrawSpan) { INT32 i; ds_transmap = R_GetTranslucencyTable(tr_trans50); - spanfunc = R_DrawTranslucentSpan_8; + spanfunc = R_DrawTranslucentSpan; for (i=0; i<4; i++) { xoffs = pl->xoffs; diff --git a/src/r_segs.c b/src/r_segs.c index ced4e7645..791932232 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -338,7 +338,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) } else if (ldef->special == 909) { - colfunc = R_DrawFogColumn_8; + colfunc = R_DrawFogColumn; windowtop = frontsector->ceilingheight; windowbottom = frontsector->floorheight; } @@ -431,7 +431,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) else lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); - if (colfunc == R_DrawFogColumn_8 + if (colfunc == R_DrawFogColumn || (frontsector->extra_colormap && frontsector->extra_colormap->fog)) ; else if (P_ApplyLightOffset(lightnum, frontsector)) @@ -732,7 +732,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) colfunc = fuzzcolfunc; } else if (pfloor->flags & FF_FOG) - colfunc = R_DrawFogColumn_8; + colfunc = R_DrawFogColumn; range = max(ds->x2-ds->x1, 1); //SoM: Moved these up here so they are available for my lightlist calculations @@ -1000,7 +1000,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) // Get data for the column col = (column_t *)((UINT8 *)R_GetColumn(texnum,maskedtexturecol[dc_x]) - 3); - // SoM: New code does not rely on R_DrawColumnShadowed_8 which + // SoM: New code does not rely on R_DrawColumnShadowed which // will (hopefully) put less strain on the stack. if (dc_numlights) { @@ -1410,7 +1410,7 @@ static void R_RenderSegLoop (void) else dc_lightlist[i].rcolormap = xwalllights[pindex]; - colfunc = R_DrawColumnShadowed_8; + colfunc = R_DrawColumnShadowed; } } diff --git a/src/screen.c b/src/screen.c index 305ca11b7..96b4b2c4b 100644 --- a/src/screen.c +++ b/src/screen.c @@ -108,17 +108,17 @@ void SCR_SetMode(void) V_SetPalette(0); - spanfunc = basespanfunc = R_DrawSpan_8; - splatfunc = R_DrawSplat_8; - transcolfunc = R_DrawTranslatedColumn_8; - transtransfunc = R_DrawTranslatedTranslucentColumn_8; + spanfunc = basespanfunc = R_DrawSpan; + splatfunc = R_DrawSplat; + transcolfunc = R_DrawTranslatedColumn; + transtransfunc = R_DrawTranslatedTranslucentColumn; - colfunc = basecolfunc = R_DrawColumn_8; - shadecolfunc = R_DrawShadeColumn_8; - fuzzcolfunc = R_DrawTranslucentColumn_8; - walldrawerfunc = R_DrawWallColumn_8; - twosmultipatchfunc = R_Draw2sMultiPatchColumn_8; - twosmultipatchtransfunc = R_Draw2sMultiPatchTranslucentColumn_8; + colfunc = basecolfunc = R_DrawColumn; + shadecolfunc = R_DrawShadeColumn; + fuzzcolfunc = R_DrawTranslucentColumn; + walldrawerfunc = R_DrawWallColumn; + twosmultipatchfunc = R_Draw2sMultiPatchColumn; + twosmultipatchtransfunc = R_Draw2sMultiPatchTranslucentColumn; // set the apprpriate drawer for the sky (tall or INT16) setmodeneeded = 0; -- 2.54.0 From d11521954e7b0ba4c3cf424d2a3b7be7e6593b45 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 5 Jun 2025 01:01:11 +0200 Subject: [PATCH 011/141] move those around + remove NOWATER ifdef --- src/r_draw.h | 17 +- src/r_draw_span.c | 436 +++++++++++++++++++++++----------------------- src/r_plane.c | 17 +- 3 files changed, 224 insertions(+), 246 deletions(-) diff --git a/src/r_draw.h b/src/r_draw.h index 7c2ef289a..9c31faefc 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -164,9 +164,11 @@ void R_DrawViewBorder(void); // DRAWING CODE // ----------------- +// column drawers void R_DrawColumn(void); #define R_DrawWallColumn R_DrawColumn void R_DrawShadeColumn(void); +void R_DrawColumnShadowed(void); void R_DrawTranslucentColumn(void); @@ -178,28 +180,23 @@ void R_Draw2sMultiPatchTranslucentColumn(void); void R_DrawFogColumn(void); -void R_DrawColumnShadowed(void); - +// span drawers void R_DrawSpan(void); void R_CalcTiltedLighting(fixed_t start, fixed_t end); void R_DrawTiltedSpan(void); void R_DrawTiltedTranslucentSpan(void); +void R_DrawTiltedTranslucentWaterSpan(void); -void R_DrawTiltedSplat(void); -void R_DrawSplat(void); - -void R_DrawTranslucentSplat(void); void R_DrawTranslucentSpan(void); void R_DrawTranslucentWaterSpan(void); -#ifndef NOWATER -void R_DrawTiltedTranslucentWaterSpan(void); -#endif void R_DrawFogSpan(void); - +void R_DrawTiltedSplat(void); +void R_DrawSplat(void); +void R_DrawTranslucentSplat(void); // ========================================================================= #endif // __R_DRAW__ diff --git a/src/r_draw_span.c b/src/r_draw_span.c index 2b47ac45b..2f709fefc 100644 --- a/src/r_draw_span.c +++ b/src/r_draw_span.c @@ -24,7 +24,7 @@ /** \brief The R_DrawSpan function Draws the actual span. */ -void R_DrawSpan (void) +void R_DrawSpan(void) { uintptr_t xposition; uintptr_t yposition; @@ -113,6 +113,219 @@ void R_DrawSpan (void) } } +/** \brief The R_DrawTranslucentSpan function + Draws the actual span with translucent. +*/ +void R_DrawTranslucentSpan(void) +{ + fixed_t xposition; + fixed_t yposition; + fixed_t xstep, ystep; + register UINT32 bit; + + UINT8 *source; + UINT8 *colormap; + register UINT8 *dest; + const UINT8 *deststop = vid.screens[0] + vid.rowbytes * vid.height; + + register intptr_t count = (ds_x2 - ds_x1 + 1); + + xposition = ds_xfrac; yposition = ds_yfrac; + xstep = ds_xstep; ystep = ds_ystep; + + // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest + // can be used for the fraction part. This allows calculation of the memory address in the + // texture with two shifts, an OR and one AND. (see below) + // for texture sizes > 64 the amount of precision we can allow will decrease, but only by one + // bit per power of two (obviously) + // Ok, because I was able to eliminate the variable spot below, this function is now FASTER + // than the original span renderer. Whodathunkit? + xposition <<= nflatshiftup; yposition <<= nflatshiftup; + xstep <<= nflatshiftup; ystep <<= nflatshiftup; + + source = ds_source; + colormap = ds_colormap; + dest = R_Address(ds_x1, ds_y); + + while (count >= 8) + { + // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't + // have the uber complicated math to calculate it now, so that was a memory write we didn't + // need! + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + dest[0] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[0]); + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + dest[1] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[1]); + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + dest[2] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[2]); + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + dest[3] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[3]); + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + dest[4] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[4]); + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + dest[5] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[5]); + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + dest[6] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[6]); + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + dest[7] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[7]); + xposition += xstep; + yposition += ystep; + + dest += 8; + count -= 8; + } + while (count-- && dest <= deststop) + { + bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + *dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dest); + dest++; + xposition += xstep; + yposition += ystep; + } +} + +void R_DrawTranslucentWaterSpan(void) +{ + UINT32 xposition; + UINT32 yposition; + UINT32 xstep, ystep; + register UINT32 bit; + + UINT8 *source; + UINT8 *colormap; + register UINT8 *dest; + UINT8 *dsrc; + + register intptr_t count; + + // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest + // can be used for the fraction part. This allows calculation of the memory address in the + // texture with two shifts, an OR and one AND. (see below) + // for texture sizes > 64 the amount of precision we can allow will decrease, but only by one + // bit per power of two (obviously) + // Ok, because I was able to eliminate the variable spot below, this function is now FASTER + // than the original span renderer. Whodathunkit? + xposition = ds_xfrac << nflatshiftup; yposition = (ds_yfrac + ds_waterofs) << nflatshiftup; + xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; + + source = ds_source; + colormap = ds_colormap; + dest = R_Address(ds_x1, ds_y); + dsrc = vid.screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1; + count = ds_x2 - ds_x1 + 1; + + while (count >= 8) + { + // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't + // have the uber complicated math to calculate it now, so that was a memory write we didn't + // need! + bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + dest[0] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; + + bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + dest[1] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; + + bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + dest[2] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; + + bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + dest[3] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; + + bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + dest[4] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; + + bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + dest[5] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; + + bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + dest[6] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; + + bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + dest[7] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; + + dest += 8; + count -= 8; + } + while (count--) + { + bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + *dest++ = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + + xposition += xstep; + yposition += ystep; + } +} + +/** \brief The R_DrawFogSpan function + Draws the actual span with fogging. +*/ +void R_DrawFogSpan(void) +{ + UINT8 *colormap; + register UINT8 *dest; + + register intptr_t count; + + colormap = ds_colormap; + dest = R_Address(dc_x, dc_yl); + + count = ds_x2 - ds_x1 + 1; + + while (count >= 4) + { + dest[0] = colormap[dest[0]]; + dest[1] = colormap[dest[1]]; + dest[2] = colormap[dest[2]]; + dest[3] = colormap[dest[3]]; + + dest += 4; + count -= 4; + } + + while (count--) + { + *dest = colormap[*dest]; + dest++; + } +} + // R_CalcTiltedLighting // Exactly what it says on the tin. I wish I wasn't too lazy to explain things properly. void R_CalcTiltedLighting(fixed_t start, fixed_t end) @@ -419,7 +632,6 @@ void R_DrawTiltedTranslucentSpan(void) #endif } -#ifndef NOWATER /** \brief The R_DrawTiltedTranslucentWaterSpan function Like DrawTiltedTranslucentSpan, but for water */ @@ -559,7 +771,6 @@ void R_DrawTiltedTranslucentWaterSpan(void) } #endif } -#endif // NOWATER void R_DrawTiltedSplat(void) { @@ -718,7 +929,7 @@ void R_DrawTiltedSplat(void) /** \brief The R_DrawSplat function Just like R_DrawSpan, but skips transparent pixels. */ -void R_DrawSplat (void) +void R_DrawSplat(void) { UINT32 xposition; UINT32 yposition; @@ -788,7 +999,7 @@ void R_DrawSplat (void) /** \brief The R_DrawTranslucentSplat function Just like R_DrawSplat, but is translucent! */ -void R_DrawTranslucentSplat (void) +void R_DrawTranslucentSplat(void) { UINT32 xposition; UINT32 yposition; @@ -849,218 +1060,3 @@ void R_DrawTranslucentSplat (void) yposition += ystep; } } - -/** \brief The R_DrawTranslucentSpan function - Draws the actual span with translucent. -*/ -void R_DrawTranslucentSpan (void) -{ - fixed_t xposition; - fixed_t yposition; - fixed_t xstep, ystep; - register UINT32 bit; - - UINT8 *source; - UINT8 *colormap; - register UINT8 *dest; - const UINT8 *deststop = vid.screens[0] + vid.rowbytes * vid.height; - - register intptr_t count = (ds_x2 - ds_x1 + 1); - - xposition = ds_xfrac; yposition = ds_yfrac; - xstep = ds_xstep; ystep = ds_ystep; - - // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest - // can be used for the fraction part. This allows calculation of the memory address in the - // texture with two shifts, an OR and one AND. (see below) - // for texture sizes > 64 the amount of precision we can allow will decrease, but only by one - // bit per power of two (obviously) - // Ok, because I was able to eliminate the variable spot below, this function is now FASTER - // than the original span renderer. Whodathunkit? - xposition <<= nflatshiftup; yposition <<= nflatshiftup; - xstep <<= nflatshiftup; ystep <<= nflatshiftup; - - source = ds_source; - colormap = ds_colormap; - dest = R_Address(ds_x1, ds_y); - - while (count >= 8) - { - // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't - // have the uber complicated math to calculate it now, so that was a memory write we didn't - // need! - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - dest[0] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[0]); - xposition += xstep; - yposition += ystep; - - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - dest[1] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[1]); - xposition += xstep; - yposition += ystep; - - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - dest[2] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[2]); - xposition += xstep; - yposition += ystep; - - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - dest[3] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[3]); - xposition += xstep; - yposition += ystep; - - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - dest[4] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[4]); - xposition += xstep; - yposition += ystep; - - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - dest[5] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[5]); - xposition += xstep; - yposition += ystep; - - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - dest[6] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[6]); - xposition += xstep; - yposition += ystep; - - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - dest[7] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[7]); - xposition += xstep; - yposition += ystep; - - dest += 8; - count -= 8; - } - while (count-- && dest <= deststop) - { - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - *dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dest); - dest++; - xposition += xstep; - yposition += ystep; - } -} - -#ifndef NOWATER -void R_DrawTranslucentWaterSpan(void) -{ - UINT32 xposition; - UINT32 yposition; - UINT32 xstep, ystep; - register UINT32 bit; - - UINT8 *source; - UINT8 *colormap; - register UINT8 *dest; - UINT8 *dsrc; - - register intptr_t count; - - // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest - // can be used for the fraction part. This allows calculation of the memory address in the - // texture with two shifts, an OR and one AND. (see below) - // for texture sizes > 64 the amount of precision we can allow will decrease, but only by one - // bit per power of two (obviously) - // Ok, because I was able to eliminate the variable spot below, this function is now FASTER - // than the original span renderer. Whodathunkit? - xposition = ds_xfrac << nflatshiftup; yposition = (ds_yfrac + ds_waterofs) << nflatshiftup; - xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; - - source = ds_source; - colormap = ds_colormap; - dest = R_Address(ds_x1, ds_y); - dsrc = vid.screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1; - count = ds_x2 - ds_x1 + 1; - - while (count >= 8) - { - // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't - // have the uber complicated math to calculate it now, so that was a memory write we didn't - // need! - bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - dest[0] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - dest[1] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - dest[2] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - dest[3] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - dest[4] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - dest[5] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - dest[6] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - dest[7] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest += 8; - count -= 8; - } - while (count--) - { - bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - *dest++ = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; - - xposition += xstep; - yposition += ystep; - } -} -#endif - -/** \brief The R_DrawFogSpan function - Draws the actual span with fogging. -*/ -void R_DrawFogSpan(void) -{ - UINT8 *colormap; - register UINT8 *dest; - - register intptr_t count; - - colormap = ds_colormap; - dest = R_Address(dc_x, dc_yl); - - count = ds_x2 - ds_x1 + 1; - - while (count >= 4) - { - dest[0] = colormap[dest[0]]; - dest[1] = colormap[dest[1]]; - dest[2] = colormap[dest[2]]; - dest[3] = colormap[dest[3]]; - - dest += 4; - count -= 4; - } - - while (count--) - { - *dest = colormap[*dest]; - dest++; - } -} diff --git a/src/r_plane.c b/src/r_plane.c index ae2a3167f..8e00ce437 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -148,7 +148,6 @@ void R_AllocPlaneMemory(void) // Sets planeripple.xfrac and planeripple.yfrac, added to ds_xfrac and ds_yfrac, if the span is not tilted. // -#ifndef NOWATER INT32 ds_bgofs; INT32 ds_waterofs; @@ -242,7 +241,6 @@ static void R_HandleRipplePlane(visplane_t *pl) vid.width, vid.width); } } -#endif // // R_MapPlane @@ -296,7 +294,6 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2) ds_yfrac = yoffs - FixedMul(planesin, distance) + (x1 - centerx) * ds_ystep; } -#ifndef NOWATER if (planeripple.active) { // Needed for ds_bgofs @@ -319,7 +316,6 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2) if ((y + ds_bgofs) < 0) ds_bgofs = -y; } -#endif if (currentplane->slope) ds_colormap = colormaps; @@ -716,9 +712,7 @@ void R_DrawPlanes(void) } } -#ifndef NOWATER R_UpdatePlaneRipple(); -#endif } static void R_DrawSkyPlane(visplane_t *pl) @@ -876,9 +870,7 @@ void R_DrawSinglePlane(visplane_t *pl) return; } -#ifndef NOWATER planeripple.active = false; -#endif spanfunc = basespanfunc; if (pl->polyobj && pl->polyobj->translucency != 0) @@ -954,12 +946,10 @@ void R_DrawSinglePlane(visplane_t *pl) } else light = (pl->lightlevel >> LIGHTSEGSHIFT); -#ifndef NOWATER if (pl->ffloor->flags & FF_RIPPLE) { R_HandleRipplePlane(pl); } -#endif } else light = (pl->lightlevel >> LIGHTSEGSHIFT); } @@ -1097,7 +1087,6 @@ void R_DrawSinglePlane(visplane_t *pl) xoffs = (fixed_t)(xoffs*fudgecanyon); yoffs = (fixed_t)(yoffs/fudgecanyon); -#ifndef NOWATER if (planeripple.active) { fixed_t plheight = abs(P_GetSlopeZAt(pl->slope, pl->viewx, pl->viewy) - pl->viewz); @@ -1111,15 +1100,11 @@ void R_DrawSinglePlane(visplane_t *pl) } } else -#endif R_SetSlopePlaneVectors(pl, 0, xoffs, yoffs, fudgecanyon); -#ifndef NOWATER if (spanfunc == R_DrawTranslucentWaterSpan) spanfunc = R_DrawTiltedTranslucentWaterSpan; - else -#endif - if (spanfunc == R_DrawTranslucentSpan) + else if (spanfunc == R_DrawTranslucentSpan) spanfunc = R_DrawTiltedTranslucentSpan; else if (spanfunc == splatfunc) spanfunc = R_DrawTiltedSplat; -- 2.54.0 From 185375ece1c5a3d93d32fec0c170b7e2ceed0b2b Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 5 Jun 2025 01:24:58 +0200 Subject: [PATCH 012/141] use ternaries for column clamp it is slightly faster for me lel also lets us get rid of an extra variable npow2min is also declared static as its always -1 --- src/r_draw_column.c | 100 ++++++++------------------------------------ 1 file changed, 17 insertions(+), 83 deletions(-) diff --git a/src/r_draw_column.c b/src/r_draw_column.c index 60c39db56..abfd515d4 100644 --- a/src/r_draw_column.c +++ b/src/r_draw_column.c @@ -28,8 +28,6 @@ void R_DrawColumn(void) UINT8 *restrict dest; intptr_t frac; intptr_t fracstep; - INT32 npow2min; - INT32 npow2max; count = dc_yh - dc_yl; @@ -59,8 +57,9 @@ void R_DrawColumn(void) const lighttable_t *restrict colormap = dc_colormap; intptr_t heightmask = dc_sourcelength-1; - npow2min = -1; - npow2max = dc_sourcelength; + + static const INT32 npow2min = -1; + const INT32 npow2max = dc_sourcelength; if (dc_sourcelength & heightmask) // not a power of 2 -- killough { @@ -89,17 +88,7 @@ void R_DrawColumn(void) // -1 is the lower clamp bound because column posts have a "safe" byte before the real data // and a few bytes after as well - - // jartha: faster on my AMD FX-6300 CPU. - // Faster than ternaries, faster than std::min/std::max. Don't ask me why. - // I tested by viewing a non-PO2 texture from a consistent distance so it covered the entire screen. - // The framerate difference was about 50 frames at 640x400. - INT32 n = frac >> FRACBITS; - if (n < npow2min) - n = npow2min; - if (n > npow2max) - n = npow2max; - *dest = colormap[source[n]]; + *dest = colormap[source[CLAMP(frac >> FRACBITS, npow2min, npow2max)]]; dest += vid.width; @@ -152,9 +141,6 @@ void R_Draw2sMultiPatchColumn(void) intptr_t frac; intptr_t fracstep; - INT32 npow2min; - INT32 npow2max; - count = dc_yh - dc_yl; if (count < 0) // Zero length, column does not exceed a pixel. @@ -183,8 +169,8 @@ void R_Draw2sMultiPatchColumn(void) intptr_t heightmask = dc_sourcelength-1; UINT8 val; - npow2min = -1; - npow2max = dc_sourcelength; + static const INT32 npow2min = -1; + const INT32 npow2max = dc_sourcelength; if (dc_sourcelength & heightmask) // not a power of 2 -- killough { @@ -213,18 +199,7 @@ void R_Draw2sMultiPatchColumn(void) // -1 is the lower clamp bound because column posts have a "safe" byte before the real data // and a few bytes after as well - - // jartha: faster on my AMD FX-6300 CPU. - // Faster than ternaries, faster than std::min/std::max. Don't ask me why. - // I tested by viewing a non-PO2 texture from a consistent distance so it covered the entire screen. - // The framerate difference was about 50 frames at 640x400. - INT32 n = frac >> FRACBITS; - if (n < npow2min) - n = npow2min; - if (n > npow2max) - n = npow2max; - - val = source[n]; + val = source[CLAMP(frac >> FRACBITS, npow2min, npow2max)]; if (val != TRANSPARENTPIXEL) { @@ -256,6 +231,7 @@ void R_Draw2sMultiPatchColumn(void) while ((count -= 2) >= 0) // texture height is a power of 2 { val = source[(frac>>FRACBITS) & heightmask]; + if (val != TRANSPARENTPIXEL) { *dest = colormap[val]; @@ -292,9 +268,6 @@ void R_Draw2sMultiPatchTranslucentColumn(void) intptr_t frac; intptr_t fracstep; - INT32 npow2min; - INT32 npow2max; - count = dc_yh - dc_yl; if (count < 0) // Zero length, column does not exceed a pixel. @@ -324,8 +297,8 @@ void R_Draw2sMultiPatchTranslucentColumn(void) intptr_t heightmask = dc_sourcelength-1; register UINT8 val; - npow2min = -1; - npow2max = dc_sourcelength; + static const INT32 npow2min = -1; + const INT32 npow2max = dc_sourcelength; if (dc_sourcelength & heightmask) // not a power of 2 -- killough { @@ -354,18 +327,7 @@ void R_Draw2sMultiPatchTranslucentColumn(void) // -1 is the lower clamp bound because column posts have a "safe" byte before the real data // and a few bytes after as well - - // jartha: faster on my AMD FX-6300 CPU. - // Faster than ternaries, faster than std::min/std::max. Don't ask me why. - // I tested by viewing a non-PO2 texture from a consistent distance so it covered the entire screen. - // The framerate difference was about 50 frames at 640x400. - INT32 n = frac >> FRACBITS; - if (n < npow2min) - n = npow2min; - if (n > npow2max) - n = npow2max; - - val = source[n]; + val = source[CLAMP(frac >> FRACBITS, npow2min, npow2max)]; if (val != TRANSPARENTPIXEL) { @@ -479,9 +441,6 @@ void R_DrawTranslucentColumn(void) intptr_t frac; intptr_t fracstep; - INT32 npow2min; - INT32 npow2max; - count = dc_yh - dc_yl + 1; if (count <= 0) // Zero length, column does not exceed a pixel. @@ -508,8 +467,8 @@ void R_DrawTranslucentColumn(void) const lighttable_t *restrict colormap = dc_colormap; intptr_t heightmask = dc_sourcelength-1; - npow2min = -1; - npow2max = dc_sourcelength; + static const INT32 npow2min = -1; + const INT32 npow2max = dc_sourcelength; if (dc_sourcelength & heightmask) { @@ -538,18 +497,7 @@ void R_DrawTranslucentColumn(void) // -1 is the lower clamp bound because column posts have a "safe" byte before the real data // and a few bytes after as well - - // jartha: faster on my AMD FX-6300 CPU. - // Faster than ternaries, faster than std::min/std::max. Don't ask me why. - // I tested by viewing a non-PO2 texture from a consistent distance so it covered the entire screen. - // The framerate difference was about 50 frames at 640x400. - INT32 n = frac >> FRACBITS; - if (n < npow2min) - n = npow2min; - if (n > npow2max) - n = npow2max; - - *dest = *(transmap + (colormap[source[n]]<<8) + (*dest)); + *dest = *(transmap + (colormap[source[CLAMP(frac >> FRACBITS, npow2min, npow2max)]]<<8) + (*dest)); dest += vid.width; @@ -591,9 +539,6 @@ void R_DrawTranslatedTranslucentColumn(void) intptr_t frac; intptr_t fracstep; - INT32 npow2min; - INT32 npow2max; - count = dc_yh - dc_yl + 1; if (count <= 0) // Zero length, column does not exceed a pixel. @@ -617,8 +562,8 @@ void R_DrawTranslatedTranslucentColumn(void) // This is as fast as it gets. intptr_t heightmask = dc_sourcelength-1; - npow2min = -1; - npow2max = dc_sourcelength; + static const INT32 npow2min = -1; + const INT32 npow2max = dc_sourcelength; if (dc_sourcelength & heightmask) { @@ -647,18 +592,7 @@ void R_DrawTranslatedTranslucentColumn(void) // -1 is the lower clamp bound because column posts have a "safe" byte before the real data // and a few bytes after as well - - // jartha: faster on my AMD FX-6300 CPU. - // Faster than ternaries, faster than std::min/std::max. Don't ask me why. - // I tested by viewing a non-PO2 texture from a consistent distance so it covered the entire screen. - // The framerate difference was about 50 frames at 640x400. - INT32 n = frac >> FRACBITS; - if (n < npow2min) - n = npow2min; - if (n > npow2max) - n = npow2max; - - *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[n]]]<<8) + (*dest)); + *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[CLAMP(frac >> FRACBITS, npow2min, npow2max)]]]<<8) + (*dest)); dest += vid.width; -- 2.54.0 From 4576efbe5c24abbd76be9180580eafd03af47966 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 5 Jun 2025 01:27:26 +0200 Subject: [PATCH 013/141] remove FIXMEs from draw column stuff --- src/r_draw_column.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/r_draw_column.c b/src/r_draw_column.c index abfd515d4..fb2ccb3fa 100644 --- a/src/r_draw_column.c +++ b/src/r_draw_column.c @@ -413,7 +413,7 @@ void R_DrawShadeColumn(void) return; } - // FIXME. As above. + // Framebuffer destination address. dest = R_Address(dc_x, dc_yl); // Looks familiar. @@ -453,7 +453,7 @@ void R_DrawTranslucentColumn(void) return; } - // FIXME. As above. + // Framebuffer destination address. dest = R_Address(dc_x, dc_yl); // Looks familiar. @@ -551,7 +551,7 @@ void R_DrawTranslatedTranslucentColumn(void) return; } - // FIXME. As above. + // Framebuffer destination address. dest = R_Address(dc_x, dc_yl); // Looks familiar. @@ -646,7 +646,7 @@ void R_DrawTranslatedColumn(void) return; } - // FIXME. As above. + // Framebuffer destination address. dest = R_Address(dc_x, dc_yl); // Looks familiar. -- 2.54.0 From 529b0d643a925950553f86fb65f80649b0ce1a24 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 5 Jun 2025 01:41:45 +0200 Subject: [PATCH 014/141] delet dc_hires --- src/r_draw.c | 2 -- src/r_draw.h | 1 - src/r_draw_column.c | 14 +++++++------- src/r_things.c | 3 +-- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/r_draw.c b/src/r_draw.c index 32c71ca21..53aefc827 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -49,8 +49,6 @@ lighttable_t *dc_colormap; INT32 dc_x = 0, dc_yl = 0, dc_yh = 0; fixed_t dc_iscale, dc_texturemid; -UINT8 dc_hires; // under MSVC boolean is a byte, while on other systems, it a bit, - // soo lets make it a byte on all system for the ASM code UINT8 *dc_source; INT32 dc_sourcelength; diff --git a/src/r_draw.h b/src/r_draw.h index 9c31faefc..317ca9f18 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -35,7 +35,6 @@ FUNCINLINE static ATTRINLINE UINT8 *R_Address(INT32 px, INT32 py) extern lighttable_t *dc_colormap; extern INT32 dc_x, dc_yl, dc_yh; extern fixed_t dc_iscale, dc_texturemid; -extern UINT8 dc_hires; extern UINT8 *dc_source; // first pixel in a column diff --git a/src/r_draw_column.c b/src/r_draw_column.c index fb2ccb3fa..fbc2a4386 100644 --- a/src/r_draw_column.c +++ b/src/r_draw_column.c @@ -49,7 +49,7 @@ void R_DrawColumn(void) // Determine scaling, which is the only mapping to be done. fracstep = dc_iscale; - frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep))*(!dc_hires); + frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep)); // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. // This is as fast as it gets. @@ -160,7 +160,7 @@ void R_Draw2sMultiPatchColumn(void) // Determine scaling, which is the only mapping to be done. fracstep = dc_iscale; - frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep))*(!dc_hires); + frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep)); // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. // This is as fast as it gets. @@ -287,7 +287,7 @@ void R_Draw2sMultiPatchTranslucentColumn(void) // Determine scaling, which is the only mapping to be done. fracstep = dc_iscale; - frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep))*(!dc_hires); + frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep)); // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. // This is as fast as it gets. @@ -418,7 +418,7 @@ void R_DrawShadeColumn(void) // Looks familiar. fracstep = dc_iscale; - frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep))*(!dc_hires); + frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep)); // Here we do an additional index re-mapping. do @@ -458,7 +458,7 @@ void R_DrawTranslucentColumn(void) // Looks familiar. fracstep = dc_iscale; - frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep))*(!dc_hires); + frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep)); // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. // This is as fast as it gets. @@ -556,7 +556,7 @@ void R_DrawTranslatedTranslucentColumn(void) // Looks familiar. fracstep = dc_iscale; - frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep))*(!dc_hires); + frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep)); // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. // This is as fast as it gets. @@ -651,7 +651,7 @@ void R_DrawTranslatedColumn(void) // Looks familiar. fracstep = dc_iscale; - frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep))*(!dc_hires); + frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep)); // Here we do an additional index re-mapping. do diff --git a/src/r_things.c b/src/r_things.c index 10d35abf7..56e1f8ec8 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -829,7 +829,7 @@ static void R_DrawVisSprite(vissprite_t *vis) dc_colormap = colormaps; if (encoremap && !vis->mobj->color && !(vis->mobj->flags & MF_DONTENCOREMAP)) - dc_colormap += COLORMAP_REMAPOFFSET; + dc_colormap += COLORMAP_REMAPOFFSET; dc_texturemid = vis->texturemid; dc_texheight = patch->height; @@ -918,7 +918,6 @@ static void R_DrawVisSprite(vissprite_t *vis) } colfunc = basecolfunc; - dc_hires = 0; vis->x1 = x1; vis->x2 = x2; -- 2.54.0 From 33a1540fcd2db27e752a4c43d0b84af685965b0e Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 5 Jun 2025 02:51:43 +0200 Subject: [PATCH 015/141] unglobalise drawcolumndata from RRs multithread will follow up with spandata --- src/r_defs.h | 31 ++++ src/r_draw.c | 29 +--- src/r_draw.h | 46 +++--- src/r_draw_column.c | 223 +++++++++++++------------- src/r_draw_span.c | 2 +- src/r_fps.c | 4 +- src/r_plane.c | 27 ++-- src/r_segs.c | 372 ++++++++++++++++++++++---------------------- src/r_things.c | 180 +++++++++++---------- src/r_things.h | 1 - src/screen.c | 26 ++-- src/screen.h | 13 -- 12 files changed, 481 insertions(+), 473 deletions(-) diff --git a/src/r_defs.h b/src/r_defs.h index fd733a97c..abb875fcf 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -68,6 +68,37 @@ typedef struct #endif } extracolormap_t; +typedef struct +{ + lighttable_t* colormap; + + INT32 x; + INT32 yl; + INT32 yh; + fixed_t iscale; + fixed_t texturemid; + + UINT8* source; // first pixel in a column + UINT8* lightmap; // lighting only + + // translucency stuff here + UINT8* transmap; + + // translation stuff here + UINT8* translation; + + struct r_lightlist_s* lightlist; + + INT32 numlights; + INT32 maxlights; + + //Fix TUTIFRUTI + INT32 texheight; + INT32 sourcelength; +} drawcolumndata_t; + +extern drawcolumndata_t g_dc; + // // INTERNAL MAP TYPES used by play and refresh // diff --git a/src/r_draw.c b/src/r_draw.c index 53aefc827..3b96dfc63 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -45,12 +45,7 @@ UINT8 *renderscreen; // haleyjd // COLUMN DRAWING CODE STUFF // ========================================================================= -lighttable_t *dc_colormap; -INT32 dc_x = 0, dc_yl = 0, dc_yh = 0; - -fixed_t dc_iscale, dc_texturemid; -UINT8 *dc_source; -INT32 dc_sourcelength; +drawcolumndata_t g_dc; // ----------------------- // translucency stuff here @@ -60,22 +55,6 @@ INT32 dc_sourcelength; UINT8 *transtables; // translucency tables UINT8 *blendtables[NUMBLENDMAPS]; -/** \brief R_DrawTransColumn uses this -*/ -UINT8 *dc_transmap; // one of the translucency tables - -// ---------------------- -// translation stuff here -// ---------------------- - - -/** \brief R_DrawTranslatedColumn uses this -*/ -UINT8 *dc_translation; - -struct r_lightlist_s *dc_lightlist = NULL; -INT32 dc_numlights = 0, dc_maxlights, dc_texheight; - // ========================================================================= // SPAN DRAWING CODE STUFF // ========================================================================= @@ -92,14 +71,10 @@ floatv3_t *ds_su, *ds_sv, *ds_sz; floatv3_t *ds_sup, *ds_svp, *ds_szp; float focallengthf, zeroheight; -/** \brief Variable flat sizes -*/ - -UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask; - // For, uh, tilted lighting, duh. static INT32 *tiltlighting; +UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask; // ========================================================================== // OLD DOOM FUZZY EFFECT diff --git a/src/r_draw.h b/src/r_draw.h index 317ca9f18..9e1851ac0 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -32,24 +32,21 @@ FUNCINLINE static ATTRINLINE UINT8 *R_Address(INT32 px, INT32 py) // COLUMN DRAWING CODE STUFF // ------------------------- -extern lighttable_t *dc_colormap; -extern INT32 dc_x, dc_yl, dc_yh; -extern fixed_t dc_iscale, dc_texturemid; +extern void (*wallcolfunc)(drawcolumndata_t*); +extern void (*colfunc)(drawcolumndata_t*); +extern void (*basecolfunc)(drawcolumndata_t*); +extern void (*fuzzcolfunc)(drawcolumndata_t*); +extern void (*transcolfunc)(drawcolumndata_t*); +extern void (*shadecolfunc)(drawcolumndata_t*); +extern void (*transtransfunc)(drawcolumndata_t*); -extern UINT8 *dc_source; // first pixel in a column +extern void (*twosmultipatchfunc)(drawcolumndata_t*); +extern void (*twosmultipatchtransfunc)(drawcolumndata_t*); -// translucency stuff here -extern UINT8 *dc_transmap; +// quick fix for tall/short skies, depending on bytesperpixel +extern void (*walldrawerfunc)(drawcolumndata_t*); -// translation stuff here - -extern UINT8 *dc_translation; - -extern struct r_lightlist_s *dc_lightlist; -extern INT32 dc_numlights, dc_maxlights; - -//Fix TUTIFRUTI -extern INT32 dc_texheight; +void R_DrawMaskedColumn(drawcolumndata_t* dc, column_t *column); // ----------------------- // SPAN DRAWING CODE STUFF @@ -60,7 +57,6 @@ extern lighttable_t *ds_colormap; extern fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep; extern INT32 ds_waterofs, ds_bgofs; extern UINT8 *ds_source; // start of a 64*64 tile image -extern INT32 dc_sourcelength; extern UINT8 *ds_transmap; extern INT32 ds_bgofs; @@ -164,20 +160,20 @@ void R_DrawViewBorder(void); // ----------------- // column drawers -void R_DrawColumn(void); +void R_DrawColumn(drawcolumndata_t* dc); #define R_DrawWallColumn R_DrawColumn -void R_DrawShadeColumn(void); -void R_DrawColumnShadowed(void); +void R_DrawShadeColumn(drawcolumndata_t* dc); +void R_DrawColumnShadowed(drawcolumndata_t* dc); -void R_DrawTranslucentColumn(void); +void R_DrawTranslucentColumn(drawcolumndata_t* dc); -void R_DrawTranslatedColumn(void); -void R_DrawTranslatedTranslucentColumn(void); +void R_DrawTranslatedColumn(drawcolumndata_t* dc); +void R_DrawTranslatedTranslucentColumn(drawcolumndata_t* dc); -void R_Draw2sMultiPatchColumn(void); -void R_Draw2sMultiPatchTranslucentColumn(void); +void R_Draw2sMultiPatchColumn(drawcolumndata_t* dc); +void R_Draw2sMultiPatchTranslucentColumn(drawcolumndata_t* dc); -void R_DrawFogColumn(void); +void R_DrawFogColumn(drawcolumndata_t* dc); // span drawers void R_DrawSpan(void); diff --git a/src/r_draw_column.c b/src/r_draw_column.c index fbc2a4386..8db886a7d 100644 --- a/src/r_draw_column.c +++ b/src/r_draw_column.c @@ -22,14 +22,14 @@ /** \brief The R_DrawColumn function Experiment to make software go faster. Taken from the Boom source */ -void R_DrawColumn(void) +void R_DrawColumn(drawcolumndata_t* dc) { INT32 count; UINT8 *restrict dest; intptr_t frac; intptr_t fracstep; - count = dc_yh - dc_yl; + count = dc->yh - dc->yl; if (count < 0) // Zero length, column does not exceed a pixel. { @@ -37,33 +37,33 @@ void R_DrawColumn(void) } - if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) + if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height) { return; } // Framebuffer destination address. - dest = R_Address(dc_x, dc_yl); + dest = R_Address(dc->x, dc->yl); count++; // Determine scaling, which is the only mapping to be done. - fracstep = dc_iscale; - frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep)); + fracstep = dc->iscale; + frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep)); // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. // This is as fast as it gets. - const UINT8 *restrict source = dc_source; - const lighttable_t *restrict colormap = dc_colormap; + const UINT8 *restrict source = dc->source; + const lighttable_t *restrict colormap = dc->colormap; - intptr_t heightmask = dc_sourcelength-1; + intptr_t heightmask = dc->sourcelength-1; static const INT32 npow2min = -1; - const INT32 npow2max = dc_sourcelength; + const INT32 npow2max = dc->sourcelength; - if (dc_sourcelength & heightmask) // not a power of 2 -- killough + if (dc->sourcelength & heightmask) // not a power of 2 -- killough { - heightmask = dc_texheight << FRACBITS; + heightmask = dc->texheight << FRACBITS; if (frac < 0) { @@ -133,48 +133,47 @@ void R_DrawColumn(void) } } - -void R_Draw2sMultiPatchColumn(void) +void R_Draw2sMultiPatchColumn(drawcolumndata_t* dc) { INT32 count; UINT8 *restrict dest; intptr_t frac; intptr_t fracstep; - count = dc_yh - dc_yl; + count = dc->yh - dc->yl; if (count < 0) // Zero length, column does not exceed a pixel. { return; } - if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) + if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height) { return; } // Framebuffer destination address. - dest = R_Address(dc_x, dc_yl); + dest = R_Address(dc->x, dc->yl); count++; // Determine scaling, which is the only mapping to be done. - fracstep = dc_iscale; - frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep)); + fracstep = dc->iscale; + frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep)); // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. // This is as fast as it gets. - const UINT8 *restrict source = dc_source; - const lighttable_t *restrict colormap = dc_colormap; - intptr_t heightmask = dc_sourcelength-1; + const UINT8 *restrict source = dc->source; + const lighttable_t *restrict colormap = dc->colormap; + intptr_t heightmask = dc->sourcelength-1; UINT8 val; static const INT32 npow2min = -1; - const INT32 npow2max = dc_sourcelength; + const INT32 npow2max = dc->sourcelength; - if (dc_sourcelength & heightmask) // not a power of 2 -- killough + if (dc->sourcelength & heightmask) // not a power of 2 -- killough { - heightmask = dc_texheight << FRACBITS; + heightmask = dc->texheight << FRACBITS; if (frac < 0) { @@ -252,7 +251,7 @@ void R_Draw2sMultiPatchColumn(void) if (count & 1) { - val = source[(frac>>FRACBITS) & heightmask]; + val = source[CLAMP(frac >> FRACBITS, -1, dc->sourcelength)]; if (val != TRANSPARENTPIXEL) { *dest = colormap[val]; @@ -261,48 +260,48 @@ void R_Draw2sMultiPatchColumn(void) } } -void R_Draw2sMultiPatchTranslucentColumn(void) +void R_Draw2sMultiPatchTranslucentColumn(drawcolumndata_t* dc) { INT32 count; UINT8 *restrict dest; intptr_t frac; intptr_t fracstep; - count = dc_yh - dc_yl; + count = dc->yh - dc->yl; if (count < 0) // Zero length, column does not exceed a pixel. { return; } - if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) + if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height) { return; } // Framebuffer destination address. - dest = R_Address(dc_x, dc_yl); + dest = R_Address(dc->x, dc->yl); count++; // Determine scaling, which is the only mapping to be done. - fracstep = dc_iscale; - frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep)); + fracstep = dc->iscale; + frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep)); // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. // This is as fast as it gets. - const UINT8 *restrict source = dc_source; - const UINT8 *transmap = dc_transmap; - const lighttable_t *restrict colormap = dc_colormap; - intptr_t heightmask = dc_sourcelength-1; + const UINT8 *restrict source = dc->source; + const UINT8 *transmap = dc->transmap; + const lighttable_t *restrict colormap = dc->colormap; + intptr_t heightmask = dc->sourcelength-1; register UINT8 val; static const INT32 npow2min = -1; - const INT32 npow2max = dc_sourcelength; + const INT32 npow2max = dc->sourcelength; - if (dc_sourcelength & heightmask) // not a power of 2 -- killough + if (dc->sourcelength & heightmask) // not a power of 2 -- killough { - heightmask = dc_texheight << FRACBITS; + heightmask = dc->texheight << FRACBITS; if (frac < 0) { @@ -391,39 +390,39 @@ void R_Draw2sMultiPatchTranslucentColumn(void) /** \brief The R_DrawShadeColumn function Experiment to make software go faster. Taken from the Boom source */ -void R_DrawShadeColumn(void) +void R_DrawShadeColumn(drawcolumndata_t* dc) { register INT32 count; register UINT8 *dest; register fixed_t frac, fracstep; // check out coords for src* - if ((dc_yl < 0) || (dc_x >= vid.width)) + if ((dc->yl < 0) || (dc->x >= vid.width)) return; - count = dc_yh - dc_yl; + count = dc->yh - dc->yl; if (count < 0) // Zero length, column does not exceed a pixel. { return; } - if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) + if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height) { return; } // Framebuffer destination address. - dest = R_Address(dc_x, dc_yl); + dest = R_Address(dc->x, dc->yl); // Looks familiar. - fracstep = dc_iscale; - frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep)); + fracstep = dc->iscale; + frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep)); // Here we do an additional index re-mapping. do { - *dest = colormaps[(dc_source[frac>>FRACBITS] <<8) + (*dest)]; + *dest = colormaps[(dc->source[frac>>FRACBITS] <<8) + (*dest)]; dest += vid.width; frac += fracstep; } while (count--); @@ -434,45 +433,45 @@ void R_DrawShadeColumn(void) a lot in 640x480 with big sprites (bfg on all screen, or transparent walls on fullscreen) */ -void R_DrawTranslucentColumn(void) +void R_DrawTranslucentColumn(drawcolumndata_t* dc) { register INT32 count; UINT8 *restrict dest; intptr_t frac; intptr_t fracstep; - count = dc_yh - dc_yl + 1; + count = dc->yh - dc->yl + 1; if (count <= 0) // Zero length, column does not exceed a pixel. { return; } - if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) + if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height) { return; } // Framebuffer destination address. - dest = R_Address(dc_x, dc_yl); + dest = R_Address(dc->x, dc->yl); // Looks familiar. - fracstep = dc_iscale; - frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep)); + fracstep = dc->iscale; + frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep)); // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. // This is as fast as it gets. - const UINT8 *restrict source = dc_source; - const UINT8 *transmap = dc_transmap; - const lighttable_t *restrict colormap = dc_colormap; - intptr_t heightmask = dc_sourcelength-1; + const UINT8 *restrict source = dc->source; + const UINT8 *transmap = dc->transmap; + const lighttable_t *restrict colormap = dc->colormap; + intptr_t heightmask = dc->sourcelength-1; static const INT32 npow2min = -1; - const INT32 npow2max = dc_sourcelength; + const INT32 npow2max = dc->sourcelength; - if (dc_sourcelength & heightmask) + if (dc->sourcelength & heightmask) { - heightmask = dc_texheight << FRACBITS; + heightmask = dc->texheight << FRACBITS; if (frac < 0) { @@ -532,42 +531,42 @@ void R_DrawTranslucentColumn(void) Spiffy function. Not only does it colormap a sprite, but does translucency as well. Uber-kudos to Cyan Helkaraxe */ -void R_DrawTranslatedTranslucentColumn(void) +void R_DrawTranslatedTranslucentColumn(drawcolumndata_t* dc) { register INT32 count; UINT8 *restrict dest; intptr_t frac; intptr_t fracstep; - count = dc_yh - dc_yl + 1; + count = dc->yh - dc->yl + 1; if (count <= 0) // Zero length, column does not exceed a pixel. { return; } - if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) + if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height) { return; } // Framebuffer destination address. - dest = R_Address(dc_x, dc_yl); + dest = R_Address(dc->x, dc->yl); // Looks familiar. - fracstep = dc_iscale; - frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep)); + fracstep = dc->iscale; + frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep)); // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. // This is as fast as it gets. - intptr_t heightmask = dc_sourcelength-1; + intptr_t heightmask = dc->sourcelength-1; static const INT32 npow2min = -1; - const INT32 npow2max = dc_sourcelength; + const INT32 npow2max = dc->sourcelength; - if (dc_sourcelength & heightmask) + if (dc->sourcelength & heightmask) { - heightmask = dc_texheight << FRACBITS; + heightmask = dc->texheight << FRACBITS; if (frac < 0) { @@ -592,7 +591,7 @@ void R_DrawTranslatedTranslucentColumn(void) // -1 is the lower clamp bound because column posts have a "safe" byte before the real data // and a few bytes after as well - *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[CLAMP(frac >> FRACBITS, npow2min, npow2max)]]]<<8) + (*dest)); + *dest = *(dc->transmap + (dc->colormap[dc->translation[dc->source[CLAMP(frac >> FRACBITS, npow2min, npow2max)]]]<<8) + (*dest)); dest += vid.width; @@ -607,18 +606,18 @@ void R_DrawTranslatedTranslucentColumn(void) { while ((count -= 2) >= 0) // texture height is a power of 2 { - *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); + *dest = *(dc->transmap + (dc->colormap[dc->translation[dc->source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); dest += vid.width; frac += fracstep; - *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); + *dest = *(dc->transmap + (dc->colormap[dc->translation[dc->source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); dest += vid.width; frac += fracstep; } if (count & 1) { - *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); + *dest = *(dc->transmap + (dc->colormap[dc->translation[dc->source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); } } } @@ -628,30 +627,30 @@ void R_DrawTranslatedTranslucentColumn(void) \warning STILL NOT IN ASM, TO DO.. */ -void R_DrawTranslatedColumn(void) +void R_DrawTranslatedColumn(drawcolumndata_t* dc) { register INT32 count; register UINT8 *dest; register fixed_t frac, fracstep; - count = dc_yh - dc_yl; + count = dc->yh - dc->yl; if (count < 0) { return; } - if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) + if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height) { return; } // Framebuffer destination address. - dest = R_Address(dc_x, dc_yl); + dest = R_Address(dc->x, dc->yl); // Looks familiar. - fracstep = dc_iscale; - frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep)); + fracstep = dc->iscale; + frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep)); // Here we do an additional index re-mapping. do @@ -661,7 +660,7 @@ void R_DrawTranslatedColumn(void) // used with PLAY sprites. // Thus the "green" ramp of the player 0 sprite // is mapped to gray, red, black/indigo. - *dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]; + *dest = dc->colormap[dc->translation[dc->source[frac>>FRACBITS]]]; dest += vid.width; @@ -672,30 +671,30 @@ void R_DrawTranslatedColumn(void) /** \brief The R_DrawFogColumn function Fog wall. */ -void R_DrawFogColumn(void) +void R_DrawFogColumn(drawcolumndata_t* dc) { register INT32 count; register UINT8 *dest; - count = dc_yh - dc_yl; + count = dc->yh - dc->yl; // Zero length, column does not exceed a pixel. if (count < 0) return; #ifdef RANGECHECK - if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) - I_Error("R_DrawFogColumn: %d to %d at %d", dc_yl, dc_yh, dc_x); + if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height) + I_Error("R_DrawFogColumn: %d to %d at %d", dc->yl, dc->yh, dc->x); #endif // Framebuffer destination address. - dest = R_Address(dc_x, dc_yl); + dest = R_Address(dc->x, dc->yl); // Determine scaling, which is the only mapping to be done. do { // Simple. Apply the colormap to what's already on the screen. - *dest = dc_colormap[*dest]; + *dest = dc->colormap[*dest]; dest += vid.width; } while (count--); } @@ -705,36 +704,36 @@ void R_DrawFogColumn(void) This function just cuts the column up into sections and calls R_DrawColumn */ -void R_DrawColumnShadowed(void) +void R_DrawColumnShadowed(drawcolumndata_t* dc) { register INT32 count; INT32 realyh, i, height, bheight = 0, solid = 0; - realyh = dc_yh; + realyh = dc->yh; - count = dc_yh - dc_yl; + count = dc->yh - dc->yl; // Zero length, column does not exceed a pixel. if (count < 0) return; #ifdef RANGECHECK - if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) - I_Error("R_DrawColumnShadowed: %d to %d at %d", dc_yl, dc_yh, dc_x); + if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height) + I_Error("R_DrawColumnShadowed: %d to %d at %d", dc->yl, dc->yh, dc->x); #endif // This runs through the lightlist from top to bottom and cuts up the column accordingly. - for (i = 0; i < dc_numlights; i++) + for (i = 0; i < dc->numlights; i++) { // If the height of the light is above the column, get the colormap // anyway because the lighting of the top should be affected. - solid = dc_lightlist[i].flags & FF_CUTSOLIDS; + solid = dc->lightlist[i].flags & FF_CUTSOLIDS; - height = dc_lightlist[i].height >> LIGHTSCALESHIFT; + height = dc->lightlist[i].height >> LIGHTSCALESHIFT; if (solid) { - bheight = dc_lightlist[i].botheight >> LIGHTSCALESHIFT; + bheight = dc->lightlist[i].botheight >> LIGHTSCALESHIFT; if (bheight < height) { // confounded slopes sometimes allow partial invertedness, @@ -747,32 +746,32 @@ void R_DrawColumnShadowed(void) } } - if (height <= dc_yl) + if (height <= dc->yl) { - dc_colormap = dc_lightlist[i].rcolormap; + dc->colormap = dc->lightlist[i].rcolormap; if (encoremap) - dc_colormap += COLORMAP_REMAPOFFSET; - if (solid && dc_yl < bheight) - dc_yl = bheight; + dc->colormap += COLORMAP_REMAPOFFSET; + if (solid && dc->yl < bheight) + dc->yl = bheight; continue; } // Found a break in the column! - dc_yh = height; + dc->yh = height; - if (dc_yh > realyh) - dc_yh = realyh; - basecolfunc(); // R_DrawColumn for the appropriate architecture + if (dc->yh > realyh) + dc->yh = realyh; + basecolfunc(dc); // R_DrawColumn for the appropriate architecture if (solid) - dc_yl = bheight; + dc->yl = bheight; else - dc_yl = dc_yh + 1; + dc->yl = dc->yh + 1; - dc_colormap = dc_lightlist[i].rcolormap; + dc->colormap = dc->lightlist[i].rcolormap; if (encoremap) - dc_colormap += COLORMAP_REMAPOFFSET; + dc->colormap += COLORMAP_REMAPOFFSET; } - dc_yh = realyh; - if (dc_yl <= realyh) - walldrawerfunc(); // R_DrawWallColumn for the appropriate architecture + dc->yh = realyh; + if (dc->yl <= realyh) + walldrawerfunc(dc); // R_DrawWallColumn for the appropriate architecture } diff --git a/src/r_draw_span.c b/src/r_draw_span.c index 2f709fefc..209db61f1 100644 --- a/src/r_draw_span.c +++ b/src/r_draw_span.c @@ -304,7 +304,7 @@ void R_DrawFogSpan(void) register intptr_t count; colormap = ds_colormap; - dest = R_Address(dc_x, dc_yl); + dest = R_Address(ds_x1, ds_y); count = ds_x2 - ds_x1 + 1; diff --git a/src/r_fps.c b/src/r_fps.c index 5dcaf90da..1d5cc1baf 100644 --- a/src/r_fps.c +++ b/src/r_fps.c @@ -494,8 +494,8 @@ void R_CreateInterpolator_Polyobj(thinker_t *thinker, polyobj_t *polyobj) interp->polyobj.polyobj = polyobj; interp->polyobj.vertices_size = polyobj->numVertices; - interp->polyobj.oldvertices = Z_CallocAlign(sizeof(fixed_t) * 2 * polyobj->numVertices, PU_LEVEL, NULL, 32); - interp->polyobj.bakvertices = Z_CallocAlign(sizeof(fixed_t) * 2 * polyobj->numVertices, PU_LEVEL, NULL, 32); + interp->polyobj.oldvertices = Z_Calloc(sizeof(fixed_t) * 2 * polyobj->numVertices, PU_LEVEL, NULL); + interp->polyobj.bakvertices = Z_Calloc(sizeof(fixed_t) * 2 * polyobj->numVertices, PU_LEVEL, NULL); for (size_t i = 0; i < polyobj->numVertices; i++) { interp->polyobj.oldvertices[i * 2 ] = interp->polyobj.bakvertices[i * 2 ] = polyobj->vertices[i]->x; diff --git a/src/r_plane.c b/src/r_plane.c index 8e00ce437..7c1375695 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -719,6 +719,7 @@ static void R_DrawSkyPlane(visplane_t *pl) { INT32 x; INT32 angle; + drawcolumndata_t dc = {0}; if (!newview->sky) { @@ -729,33 +730,33 @@ static void R_DrawSkyPlane(visplane_t *pl) wallcolfunc = walldrawerfunc; // use correct aspect ratio scale - dc_iscale = skyscale; + dc.iscale = skyscale; // Sky is always drawn full bright, // i.e. colormaps[0] is used. // Because of this hack, sky is not affected // by INVUL inverse mapping. - dc_colormap = colormaps; + dc.colormap = colormaps; if (encoremap) - dc_colormap += COLORMAP_REMAPOFFSET; + dc.colormap += COLORMAP_REMAPOFFSET; - dc_texturemid = skytexturemid; - dc_texheight = textureheight[skytexture] >>FRACBITS; - dc_sourcelength = dc_texheight; + dc.texturemid = skytexturemid; + dc.texheight = textureheight[skytexture] >>FRACBITS; + dc.sourcelength = dc.texheight; for (x = pl->minx; x <= pl->maxx; x++) { - dc_yl = pl->top[x]; - dc_yh = pl->bottom[x]; + dc.yl = pl->top[x]; + dc.yh = pl->bottom[x]; - if (!(dc_yl <= dc_yh)) + if (!(dc.yl <= dc.yh)) continue; angle = (pl->viewangle + xtoviewangle[x])>>ANGLETOSKYSHIFT; - dc_iscale = FixedMul(skyscale, FINECOSINE(xtoviewangle[x]>>ANGLETOFINESHIFT)); - dc_x = x; - dc_source = R_GetColumn(texturetranslation[skytexture], angle); - wallcolfunc(); + dc.iscale = FixedMul(skyscale, FINECOSINE(xtoviewangle[x]>>ANGLETOFINESHIFT)); + dc.x = x; + dc.source = R_GetColumn(texturetranslation[skytexture], angle); + wallcolfunc(&dc); } } diff --git a/src/r_segs.c b/src/r_segs.c index 791932232..2ed0b5b80 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -87,7 +87,7 @@ static void R_DrawSplatColumn(column_t *column) fixed_t basetexturemid; INT32 topdelta, prevdelta = -1; - basetexturemid = dc_texturemid; + basetexturemid = dc->texturemid; while (column->topdelta != 0xff) { @@ -99,17 +99,17 @@ static void R_DrawSplatColumn(column_t *column) topscreen = sprtopscreen + spryscale*topdelta; bottomscreen = topscreen + spryscale*column->length; - dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS; - dc_yh = (bottomscreen-1)>>FRACBITS; + dc->yl = (topscreen+FRACUNIT-1)>>FRACBITS; + dc->yh = (bottomscreen-1)>>FRACBITS; - if (dc_yh >= last_floorclip[dc_x]) - dc_yh = last_floorclip[dc_x] - 1; - if (dc_yl <= last_ceilingclip[dc_x]) - dc_yl = last_ceilingclip[dc_x] + 1; - if (dc_yl <= dc_yh && dl_yh < vid.height && yh > 0) + if (dc->yh >= last_floorclip[dc->x]) + dc->yh = last_floorclip[dc->x] - 1; + if (dc->yl <= last_ceilingclip[dc->x]) + dc->yl = last_ceilingclip[dc->x] + 1; + if (dc->yl <= dc->yh && dl_yh < vid.height && yh > 0) { - dc_source = (UINT8 *)column + 3; - dc_texturemid = basetexturemid - (topdelta<source = (UINT8 *)column + 3; + dc->texturemid = basetexturemid - (topdelta<length + 4); } - dc_texturemid = basetexturemid; + dc->texturemid = basetexturemid; } static void R_DrawWallSplats(void) @@ -173,11 +173,11 @@ static void R_DrawWallSplats(void) patch = W_CachePatchNum(splat->patch, PU_SPRITE); - dc_texturemid = splat->top + (patch->height<<(FRACBITS-1)) - viewz; + dc->texturemid = splat->top + (patch->height<<(FRACBITS-1)) - viewz; if (splat->yoffset) - dc_texturemid += *splat->yoffset; + dc->texturemid += *splat->yoffset; - sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); + sprtopscreen = centeryfrac - FixedMul(dc->texturemid, spryscale); // set drawing mode switch (splat->flags & SPLATDRAWMODE_MASK) @@ -190,7 +190,7 @@ static void R_DrawWallSplats(void) colfunc = basecolfunc; else { - dc_transmap = R_GetTranslucencyTable(tr_trans50); + dc->transmap = R_GetTranslucencyTable(tr_trans50); colfunc = fuzzcolfunc; } @@ -200,26 +200,26 @@ static void R_DrawWallSplats(void) break; } - dc_texheight = 0; + dc->texheight = 0; // draw the columns - for (dc_x = x1; dc_x <= x2; dc_x++, spryscale += rw_scalestep) + for (dc->x = x1; dc->x <= x2; dc->x++, spryscale += rw_scalestep) { pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; if (pindex >= MAXLIGHTSCALE) pindex = MAXLIGHTSCALE - 1; - dc_colormap = walllights[pindex]; + dc->colormap = walllights[pindex]; if (encoremap && !(seg->linedef->flags & ML_TFERLINE)) - dc_colormap += COLORMAP_REMAPOFFSET; + dc->colormap += COLORMAP_REMAPOFFSET; if (frontsector->extra_colormap) - dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); + dc->colormap = frontsector->extra_colormap->colormap + (dc->colormap - colormaps); - sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); - dc_iscale = 0xffffffffu / (unsigned)spryscale; + sprtopscreen = centeryfrac - FixedMul(dc->texturemid, spryscale); + dc->iscale = 0xffffffffu / (unsigned)spryscale; // find column of patch, from perspective - angle = (rw_centerangle + xtoviewangle[dc_x])>>ANGLETOFINESHIFT; + angle = (rw_centerangle + xtoviewangle[dc->x])>>ANGLETOFINESHIFT; texturecolumn = rw_offset2 - splat->offset - FixedMul(FINETANGENT(angle), rw_distance); @@ -249,41 +249,41 @@ static void R_DrawWallSplats(void) // 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) +static void R_Render2sidedMultiPatchColumn(drawcolumndata_t* dc, column_t *column) { INT32 topscreen, bottomscreen; topscreen = sprtopscreen; // + spryscale*column->topdelta; topdelta is 0 for the wall bottomscreen = topscreen + spryscale * lengthcol; - dc_yl = (sprtopscreen+FRACUNIT-1)>>FRACBITS; - dc_yh = (bottomscreen-1)>>FRACBITS; + 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; + 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->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) + if (dc->yl >= vid.height || dc->yh < 0) return; - if (dc_yl <= dc_yh && dc_yh < vid.height && dc_yh > 0) + if (dc->yl <= dc->yh && dc->yh < vid.height && dc->yh > 0) { - dc_source = (UINT8 *)column + 3; - dc_sourcelength = lengthcol; + dc->source = (UINT8 *)column + 3; + dc->sourcelength = lengthcol; if (colfunc == wallcolfunc) - twosmultipatchfunc(); + twosmultipatchfunc(dc); else if (colfunc == fuzzcolfunc) - twosmultipatchtransfunc(); + twosmultipatchtransfunc(dc); else - colfunc(); + colfunc(dc); } } @@ -300,13 +300,16 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) fixed_t height, realbot; lightlist_t *light; r_lightlist_t *rlight; - void (*colfunc_2s)(column_t *); line_t *ldef; sector_t *front, *back; INT32 times, repeats; INT64 overflow_test; INT32 range; + drawcolumndata_t *dc = &g_dc; + + void (*colfunc_2s)(drawcolumndata_t* dc, column_t *); + // Calculate light table. // Use different light tables // for horizontal / vertical / diagonal. Diagonal? @@ -326,14 +329,14 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) if (ldef->blendmode) { if (ldef->alpha == NUMTRANSMAPS || ldef->blendmode == AST_MODULATE) - dc_transmap = R_GetBlendTable(ldef->blendmode, 0); + dc->transmap = R_GetBlendTable(ldef->blendmode, 0); else - dc_transmap = R_GetBlendTable(ldef->blendmode, R_GetLinedefTransTable(ldef->alpha)); + dc->transmap = R_GetBlendTable(ldef->blendmode, R_GetLinedefTransTable(ldef->alpha)); colfunc = fuzzcolfunc; } else if (ldef->alpha > 0 && ldef->alpha < FRACUNIT) { - dc_transmap = R_GetTranslucencyTable(R_GetLinedefTransTable(ldef->alpha)); + dc->transmap = R_GetTranslucencyTable(R_GetLinedefTransTable(ldef->alpha)); colfunc = fuzzcolfunc; } else if (ldef->special == 909) @@ -352,7 +355,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) if (curline->polyseg->translucency >= NUMTRANSMAPS) return; - dc_transmap = R_GetTranslucencyTable(curline->polyseg->translucency); + dc->transmap = R_GetTranslucencyTable(curline->polyseg->translucency); colfunc = fuzzcolfunc; } @@ -374,21 +377,21 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) } // Setup lighting based on the presence/lack-of 3D floors. - dc_numlights = 0; + dc->numlights = 0; if (frontsector->numlights) { - dc_numlights = frontsector->numlights; - if (dc_numlights >= dc_maxlights) + dc->numlights = frontsector->numlights; + if (dc->numlights >= dc->maxlights) { - dc_maxlights = dc_numlights; - dc_lightlist = Z_Realloc(dc_lightlist, sizeof (*dc_lightlist) * dc_maxlights, PU_STATIC, NULL); + dc->maxlights = dc->numlights; + dc->lightlist = Z_Realloc(dc->lightlist, sizeof (*dc->lightlist) * dc->maxlights, PU_STATIC, NULL); } - for (i = 0; i < dc_numlights; i++) + for (i = 0; i < dc->numlights; i++) { fixed_t leftheight, rightheight; light = &frontsector->lightlist[i]; - rlight = &dc_lightlist[i]; + rlight = &dc->lightlist[i]; leftheight = P_GetLightZAt(light, ds-> leftpos.x, ds-> leftpos.y); rightheight = P_GetLightZAt(light, ds->rightpos.x, ds->rightpos.y); @@ -489,41 +492,41 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) { rw_scalestep = ds->scalestep; spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep; - if (dc_numlights) + if (dc->numlights) { // reset all lights to their starting heights - for (i = 0; i < dc_numlights; i++) + for (i = 0; i < dc->numlights; i++) { - rlight = &dc_lightlist[i]; + rlight = &dc->lightlist[i]; rlight->height = rlight->startheight; } } } - dc_texheight = textureheight[texnum]>>FRACBITS; + dc->texheight = textureheight[texnum]>>FRACBITS; // draw the columns - for (dc_x = x1; dc_x <= x2; dc_x++) + for (dc->x = x1; dc->x <= x2; dc->x++) { - dc_texturemid = ds->maskedtextureheight[dc_x]; + dc->texturemid = ds->maskedtextureheight[dc->x]; if (!!(curline->linedef->flags & ML_DONTPEGBOTTOM) ^ !!(curline->linedef->flags & ML_EFFECT3)) - dc_texturemid += (textureheight[texnum])*times + textureheight[texnum]; + dc->texturemid += (textureheight[texnum])*times + textureheight[texnum]; else - dc_texturemid -= (textureheight[texnum])*times; + dc->texturemid -= (textureheight[texnum])*times; // calculate lighting - if (maskedtexturecol[dc_x] != INT16_MAX) + if (maskedtexturecol[dc->x] != INT16_MAX) { // Check for overflows first - overflow_test = (INT64)centeryfrac - (((INT64)dc_texturemid*spryscale)>>FRACBITS); + overflow_test = (INT64)centeryfrac - (((INT64)dc->texturemid*spryscale)>>FRACBITS); if (overflow_test < 0) overflow_test = -overflow_test; if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) { // Eh, no, go away, don't waste our time - if (dc_numlights) + if (dc->numlights) { - for (i = 0; i < dc_numlights; i++) + for (i = 0; i < dc->numlights; i++) { - rlight = &dc_lightlist[i]; + rlight = &dc->lightlist[i]; rlight->height += rlight->heightstep; } } @@ -531,22 +534,22 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) continue; } - if (dc_numlights) + if (dc->numlights) { lighttable_t **xwalllights; sprbotscreen = INT32_MAX; - sprtopscreen = windowtop = (centeryfrac - FixedMul(dc_texturemid, spryscale)); + sprtopscreen = windowtop = (centeryfrac - FixedMul(dc->texturemid, spryscale)); realbot = windowbottom = FixedMul(textureheight[texnum], spryscale) + sprtopscreen; - dc_iscale = 0xffffffffu / (unsigned)spryscale; + dc->iscale = 0xffffffffu / (unsigned)spryscale; // draw the texture - col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3); + col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc->x]) - 3); - for (i = 0; i < dc_numlights; i++) + for (i = 0; i < dc->numlights; i++) { - rlight = &dc_lightlist[i]; + rlight = &dc->lightlist[i]; if ((rlight->flags & FF_NOSHADE)) continue; @@ -573,9 +576,9 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) if (height <= windowtop) { - dc_colormap = rlight->rcolormap; + dc->colormap = rlight->rcolormap; if (encoremap && !(ldef->flags & ML_TFERLINE)) - dc_colormap += COLORMAP_REMAPOFFSET; + dc->colormap += COLORMAP_REMAPOFFSET; continue; } @@ -583,24 +586,24 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) if (windowbottom >= realbot) { windowbottom = realbot; - colfunc_2s(col); - for (i++; i < dc_numlights; i++) + colfunc_2s(dc, col); + for (i++; i < dc->numlights; i++) { - rlight = &dc_lightlist[i]; + rlight = &dc->lightlist[i]; rlight->height += rlight->heightstep; } continue; } - colfunc_2s(col); + colfunc_2s(dc, col); windowtop = windowbottom + 1; - dc_colormap = rlight->rcolormap; + dc->colormap = rlight->rcolormap; if (encoremap && !(ldef->flags & ML_TFERLINE)) - dc_colormap += COLORMAP_REMAPOFFSET; + dc->colormap += COLORMAP_REMAPOFFSET; } windowbottom = realbot; if (windowtop < windowbottom) - colfunc_2s(col); + colfunc_2s(dc, col); spryscale += rw_scalestep; continue; @@ -612,20 +615,20 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) if (pindex >= MAXLIGHTSCALE) pindex = MAXLIGHTSCALE - 1; - dc_colormap = walllights[pindex]; + dc->colormap = walllights[pindex]; if (encoremap && !(ldef->flags & ML_TFERLINE)) - dc_colormap += COLORMAP_REMAPOFFSET; + dc->colormap += COLORMAP_REMAPOFFSET; if (frontsector->extra_colormap) - dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); + dc->colormap = frontsector->extra_colormap->colormap + (dc->colormap - colormaps); - sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); - dc_iscale = 0xffffffffu / (unsigned)spryscale; + sprtopscreen = centeryfrac - FixedMul(dc->texturemid, spryscale); + dc->iscale = 0xffffffffu / (unsigned)spryscale; // draw the texture - col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3); + col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc->x]) - 3); - colfunc_2s(col); + colfunc_2s(dc, col); } spryscale += rw_scalestep; } @@ -634,13 +637,13 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) } // Loop through R_DrawMaskedColumn calls -static void R_DrawRepeatMaskedColumn(column_t *col) +static void R_DrawRepeatMaskedColumn(drawcolumndata_t* dc, column_t *col) { INT64 z; while (sprtopscreen < sprbotscreen) { - R_DrawMaskedColumn(col); - z = sprtopscreen + (INT64)dc_texheight*spryscale; + R_DrawMaskedColumn(dc, col); + z = sprtopscreen + (INT64)dc->texheight*spryscale; if (z > (INT64)INT32_MAX) // prevent overflow sprtopscreen = INT32_MAX; else @@ -690,7 +693,9 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) fixed_t left_top, left_bottom; // needed here for slope skewing pslope_t *skewslope = NULL; - void (*colfunc_2s) (column_t *); + drawcolumndata_t *dc = &g_dc; + + void (*colfunc_2s) (drawcolumndata_t* dc, column_t *); // Calculate light table. // Use different light tables @@ -723,8 +728,8 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) if (trans >= 10) return; // Don't even draw it if (pfloor->blend) // additive, (reverse) subtractive, modulative - dc_transmap = R_GetBlendTable(pfloor->blend, trans); - else if (!(dc_transmap = R_GetTranslucencyTable(trans)) || trans == 0) + dc->transmap = R_GetBlendTable(pfloor->blend, trans); + else if (!(dc->transmap = R_GetTranslucencyTable(trans)) || trans == 0) fuzzy = false; // Opaque } @@ -739,23 +744,23 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) rw_scalestep = ds->scalestep; spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep; - dc_numlights = 0; + dc->numlights = 0; if (frontsector->numlights) { - dc_numlights = frontsector->numlights; - if (dc_numlights > dc_maxlights) + dc->numlights = frontsector->numlights; + if (dc->numlights > dc->maxlights) { - dc_maxlights = dc_numlights; - dc_lightlist = Z_Realloc(dc_lightlist, sizeof (*dc_lightlist) * dc_maxlights, PU_STATIC, NULL); + dc->maxlights = dc->numlights; + dc->lightlist = Z_Realloc(dc->lightlist, sizeof (*dc->lightlist) * dc->maxlights, PU_STATIC, NULL); } - for (i = p = 0; i < dc_numlights; i++) + for (i = p = 0; i < dc->numlights; i++) { fixed_t leftheight, rightheight; fixed_t pfloorleft, pfloorright; INT64 overflow_test; light = &frontsector->lightlist[i]; - rlight = &dc_lightlist[p]; + rlight = &dc->lightlist[p]; #define SLOPEPARAMS(slope, end1, end2, normalheight) \ end1 = P_GetZAt(slope, ds->leftpos.x, ds->leftpos.y, normalheight); \ @@ -769,7 +774,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) SLOPEPARAMS(*pfloor->t_slope, pfloorleft, pfloorright, *pfloor->topheight) - if (leftheight > pfloorleft && rightheight > pfloorright && i+1 < dc_numlights) + if (leftheight > pfloorleft && rightheight > pfloorright && i+1 < dc->numlights) { lightlist_t *nextlight = &frontsector->lightlist[i+1]; if ((P_GetLightZAt(nextlight, ds->leftpos.x, ds->leftpos.y) > pfloorleft) @@ -831,7 +836,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) p++; } - dc_numlights = p; + dc->numlights = p; } else { @@ -863,7 +868,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) mfloorclip = ds->sprbottomclip; mceilingclip = ds->sprtopclip; - dc_texheight = textureheight[texnum]>>FRACBITS; + dc->texheight = textureheight[texnum]>>FRACBITS; // calculate both left ends left_top = P_GetFFloorTopZAt (pfloor, ds->leftpos.x, ds->leftpos.y) - viewz; @@ -880,9 +885,9 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) slopeskew = true; if (slopeskew) - dc_texturemid = left_top; + dc->texturemid = left_top; else - dc_texturemid = *pfloor->topheight - viewz; + dc->texturemid = *pfloor->topheight - viewz; if (newline) { @@ -891,7 +896,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) { skewslope = *pfloor->b_slope; // skew using bottom slope if (slopeskew) - dc_texturemid = left_bottom; + dc->texturemid = left_bottom; else offsetvalue -= *pfloor->topheight - *pfloor->bottomheight; } @@ -903,7 +908,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) { skewslope = *pfloor->b_slope; // skew using bottom slope if (slopeskew) - dc_texturemid = left_bottom; + dc->texturemid = left_bottom; else offsetvalue -= *pfloor->topheight - *pfloor->bottomheight; } @@ -917,7 +922,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) ffloortextureslide = FixedMul(skewslope->zdelta, FINECOSINE((lineangle-skewslope->xydirection)>>ANGLETOFINESHIFT)); } - dc_texturemid += offsetvalue; + dc->texturemid += offsetvalue; // Texture must be cached before setting colfunc_2s, // otherwise texture[texnum]->holes may be false when it shouldn't be @@ -954,16 +959,16 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) } // draw the columns - for (dc_x = x1; dc_x <= x2; dc_x++) + for (dc->x = x1; dc->x <= x2; dc->x++) { - if (maskedtexturecol[dc_x] == INT16_MAX) + if (maskedtexturecol[dc->x] == INT16_MAX) continue; { if (ffloortextureslide) { // skew FOF walls if (oldx != -1) - dc_texturemid += FixedMul(ffloortextureslide, (maskedtexturecol[oldx]-maskedtexturecol[dc_x])<texturemid += FixedMul(ffloortextureslide, (maskedtexturecol[oldx]-maskedtexturecol[dc->x])<x; } // Calculate bounds // clamp the values if necessary to avoid overflows and rendering glitches caused by them @@ -981,11 +986,11 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) // SoM: If column is out of range, why bother with it?? if (windowbottom < topbounds || windowtop > bottombounds) { - if (dc_numlights) + if (dc->numlights) { - for (i = 0; i < dc_numlights; i++) + for (i = 0; i < dc->numlights; i++) { - rlight = &dc_lightlist[i]; + rlight = &dc->lightlist[i]; rlight->height += rlight->heightstep; if (rlight->flags & FF_CUTLEVEL) rlight->botheight += rlight->botheightstep; @@ -995,14 +1000,14 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) continue; } - dc_iscale = 0xffffffffu / (unsigned)spryscale; + dc->iscale = 0xffffffffu / (unsigned)spryscale; // Get data for the column - col = (column_t *)((UINT8 *)R_GetColumn(texnum,maskedtexturecol[dc_x]) - 3); + col = (column_t *)((UINT8 *)R_GetColumn(texnum,maskedtexturecol[dc->x]) - 3); // SoM: New code does not rely on R_DrawColumnShadowed which // will (hopefully) put less strain on the stack. - if (dc_numlights) + if (dc->numlights) { lighttable_t **xwalllights; fixed_t height; @@ -1010,11 +1015,11 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) INT32 solid = 0; INT32 lighteffect = 0; - for (i = 0; i < dc_numlights; i++) + for (i = 0; i < dc->numlights; i++) { // Check if the current light effects the colormap/lightlevel - rlight = &dc_lightlist[i]; - lighteffect = !(dc_lightlist[i].flags & FF_NOSHADE); + rlight = &dc->lightlist[i]; + lighteffect = !(dc->lightlist[i].flags & FF_NOSHADE); if (lighteffect) { @@ -1081,9 +1086,9 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) { if (lighteffect) { - dc_colormap = rlight->rcolormap; + dc->colormap = rlight->rcolormap; if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) - dc_colormap += COLORMAP_REMAPOFFSET; + dc->colormap += COLORMAP_REMAPOFFSET; } if (solid && windowtop < bheight) windowtop = bheight; @@ -1095,10 +1100,10 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) { windowbottom = sprbotscreen; // draw the texture - colfunc_2s (col); - for (i++; i < dc_numlights; i++) + colfunc_2s (dc, col); + for (i++; i < dc->numlights; i++) { - rlight = &dc_lightlist[i]; + rlight = &dc->lightlist[i]; rlight->height += rlight->heightstep; if (rlight->flags & FF_CUTLEVEL) rlight->botheight += rlight->botheightstep; @@ -1106,22 +1111,22 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) continue; } // draw the texture - colfunc_2s (col); + colfunc_2s (dc, col); if (solid) windowtop = bheight; else windowtop = windowbottom + 1; if (lighteffect) { - dc_colormap = rlight->rcolormap; + dc->colormap = rlight->rcolormap; if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) - dc_colormap += COLORMAP_REMAPOFFSET; + dc->colormap += COLORMAP_REMAPOFFSET; } } windowbottom = sprbotscreen; // draw the texture, if there is any space left if (windowtop < windowbottom) - colfunc_2s (col); + colfunc_2s (dc, col); spryscale += rw_scalestep; continue; @@ -1133,18 +1138,18 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) if (pindex >= MAXLIGHTSCALE) pindex = MAXLIGHTSCALE - 1; - dc_colormap = walllights[pindex]; + dc->colormap = walllights[pindex]; if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) - dc_colormap += COLORMAP_REMAPOFFSET; + dc->colormap += COLORMAP_REMAPOFFSET; if (pfloor->flags & FF_FOG && pfloor->master->frontsector->extra_colormap) - dc_colormap = pfloor->master->frontsector->extra_colormap->colormap + (dc_colormap - colormaps); + dc->colormap = pfloor->master->frontsector->extra_colormap->colormap + (dc->colormap - colormaps); else if (frontsector->extra_colormap) - dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); + dc->colormap = frontsector->extra_colormap->colormap + (dc->colormap - colormaps); // draw the texture - colfunc_2s (col); + colfunc_2s (dc, col); spryscale += rw_scalestep; } } @@ -1185,7 +1190,7 @@ static inline void R_ExpandPlaneY(visplane_t *pl, INT32 x, INT16 top, INT16 bott #define HEIGHTBITS 12 #define HEIGHTUNIT (1<= MAXLIGHTSCALE) pindex = MAXLIGHTSCALE-1; - dc_colormap = walllights[pindex]; + dc->colormap = walllights[pindex]; if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) - dc_colormap += COLORMAP_REMAPOFFSET; - dc_x = rw_x; - dc_iscale = 0xffffffffu / (unsigned)rw_scale; + dc->colormap += COLORMAP_REMAPOFFSET; + dc->x = rw_x; + dc->iscale = 0xffffffffu / (unsigned)rw_scale; if (frontsector->extra_colormap) - dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); + dc->colormap = frontsector->extra_colormap->colormap + (dc->colormap - colormaps); } - if (dc_numlights) + if (dc->numlights) { lighttable_t **xwalllights; - for (i = 0; i < dc_numlights; i++) + for (i = 0; i < dc->numlights; i++) { INT32 lightnum; - lightnum = (dc_lightlist[i].lightlevel >> LIGHTSEGSHIFT); + lightnum = (dc->lightlist[i].lightlevel >> LIGHTSEGSHIFT); - if (dc_lightlist[i].extra_colormap) + if (dc->lightlist[i].extra_colormap) ; else if (P_ApplyLightOffset(lightnum, curline->frontsector)) lightnum += curline->lightOffset; @@ -1405,10 +1410,10 @@ static void R_RenderSegLoop (void) if (pindex >= MAXLIGHTSCALE) pindex = MAXLIGHTSCALE-1; - if (dc_lightlist[i].extra_colormap) - dc_lightlist[i].rcolormap = dc_lightlist[i].extra_colormap->colormap + (xwalllights[pindex] - colormaps); + if (dc->lightlist[i].extra_colormap) + dc->lightlist[i].rcolormap = dc->lightlist[i].extra_colormap->colormap + (xwalllights[pindex] - colormaps); else - dc_lightlist[i].rcolormap = xwalllights[pindex]; + dc->lightlist[i].rcolormap = xwalllights[pindex]; colfunc = R_DrawColumnShadowed; } @@ -1422,13 +1427,13 @@ static void R_RenderSegLoop (void) // single sided line if (yl <= yh && yh >= 0 && yl < viewheight) { - dc_yl = yl; - dc_yh = yh; - dc_texturemid = rw_midtexturemid; - dc_source = R_GetColumn(midtexture,texturecolumn); - dc_texheight = textureheight[midtexture]>>FRACBITS; - dc_sourcelength = dc_texheight; - colfunc(); + dc->yl = yl; + dc->yh = yh; + dc->texturemid = rw_midtexturemid; + dc->source = R_GetColumn(midtexture,texturecolumn); + dc->texheight = textureheight[midtexture]>>FRACBITS; + dc->sourcelength = dc->texheight; + colfunc(dc); // dont draw anything more for this column, since // a midtexture blocks the view @@ -1470,13 +1475,13 @@ static void R_RenderSegLoop (void) } else if (mid >= 0) // safe to draw top texture { - dc_yl = yl; - dc_yh = mid; - dc_texturemid = rw_toptexturemid; - dc_source = R_GetColumn(toptexture,texturecolumn); - dc_texheight = textureheight[toptexture]>>FRACBITS; - dc_sourcelength = dc_texheight; - colfunc(); + dc->yl = yl; + dc->yh = mid; + dc->texturemid = rw_toptexturemid; + dc->source = R_GetColumn(toptexture,texturecolumn); + dc->texheight = textureheight[toptexture]>>FRACBITS; + dc->sourcelength = dc->texheight; + colfunc(dc); ceilingclip[rw_x] = (INT16)mid; } else if (!rw_ceilingmarked) // entirely off top of screen @@ -1507,14 +1512,14 @@ static void R_RenderSegLoop (void) } else if (mid < viewheight) // safe to draw bottom texture { - dc_yl = mid; - dc_yh = yh; - dc_texturemid = rw_bottomtexturemid; - dc_source = R_GetColumn(bottomtexture, + dc->yl = mid; + dc->yh = yh; + dc->texturemid = rw_bottomtexturemid; + dc->source = R_GetColumn(bottomtexture, texturecolumn); - dc_texheight = textureheight[bottomtexture]>>FRACBITS; - dc_sourcelength = dc_texheight; - colfunc(); + dc->texheight = textureheight[bottomtexture]>>FRACBITS; + dc->sourcelength = dc->texheight; + colfunc(dc); floorclip[rw_x] = (INT16)mid; } else if (!rw_floormarked) // entirely off bottom of screen @@ -1539,13 +1544,13 @@ static void R_RenderSegLoop (void) } } - if (dc_numlights) + if (dc->numlights) { - for (i = 0; i < dc_numlights; i++) + for (i = 0; i < dc->numlights; i++) { - dc_lightlist[i].height += dc_lightlist[i].heightstep; - if (dc_lightlist[i].flags & FF_CUTSOLIDS) - dc_lightlist[i].botheight += dc_lightlist[i].botheightstep; + dc->lightlist[i].height += dc->lightlist[i].heightstep; + if (dc->lightlist[i].flags & FF_CUTSOLIDS) + dc->lightlist[i].botheight += dc->lightlist[i].botheightstep; } } @@ -1636,6 +1641,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) INT32 range; vertex_t segleft, segright; fixed_t ceilingfrontslide, floorfrontslide, ceilingbackslide, floorbackslide; + drawcolumndata_t dc = {0}; maskedtextureheight = NULL; //initialize segleft and segright @@ -2441,23 +2447,23 @@ void R_StoreWallRange(INT32 start, INT32 stop) } } - dc_numlights = 0; + dc.numlights = 0; if (frontsector->numlights) { - dc_numlights = frontsector->numlights; - if (dc_numlights >= dc_maxlights) + dc.numlights = frontsector->numlights; + if (dc.numlights >= dc.maxlights) { - dc_maxlights = dc_numlights; - dc_lightlist = Z_Realloc(dc_lightlist, sizeof (*dc_lightlist) * dc_maxlights, PU_STATIC, NULL); + dc.maxlights = dc.numlights; + dc.lightlist = Z_Realloc(dc.lightlist, sizeof (*dc.lightlist) * dc.maxlights, PU_STATIC, NULL); } - for (i = p = 0; i < dc_numlights; i++) + for (i = p = 0; i < dc.numlights; i++) { fixed_t leftheight, rightheight; light = &frontsector->lightlist[i]; - rlight = &dc_lightlist[p]; + rlight = &dc.lightlist[p]; leftheight = P_GetLightZAt(light, segleft.x, segleft.y); rightheight = P_GetLightZAt(light, segright.x, segright.y); @@ -2477,7 +2483,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (leftheight < worldbottom && rightheight < worldbottomslope) continue; - if (leftheight > worldtop && rightheight > worldtopslope && i+1 < dc_numlights && frontsector->lightlist[i+1].height > frontsector->ceilingheight) + if (leftheight > worldtop && rightheight > worldtopslope && i+1 < dc.numlights && frontsector->lightlist[i+1].height > frontsector->ceilingheight) continue; } @@ -2512,7 +2518,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) p++; } - dc_numlights = p; + dc.numlights = p; } if (numffloors) @@ -2818,7 +2824,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) else #endif - R_RenderSegLoop(); + R_RenderSegLoop(&dc); colfunc = wallcolfunc; if (g_portal) // if curline is a portal, set portalrender for drawseg diff --git a/src/r_things.c b/src/r_things.c index 56e1f8ec8..0bc06f951 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -612,14 +612,14 @@ INT16 *mceilingclip; fixed_t spryscale = 0, sprtopscreen = 0, sprbotscreen = 0; fixed_t windowtop = 0, windowbottom = 0; -void R_DrawMaskedColumn(column_t *column) +void R_DrawMaskedColumn(drawcolumndata_t* dc, column_t *column) { INT32 topscreen; INT32 bottomscreen; fixed_t basetexturemid; INT32 topdelta, prevdelta = 0; - basetexturemid = dc_texturemid; + basetexturemid = dc->texturemid; while (column->topdelta != 0xff) { @@ -632,49 +632,54 @@ void R_DrawMaskedColumn(column_t *column) topscreen = sprtopscreen + spryscale*topdelta; bottomscreen = topscreen + spryscale*column->length; - dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS; - dc_yh = (bottomscreen-1)>>FRACBITS; + dc->yl = (topscreen+FRACUNIT-1)>>FRACBITS; + dc->yh = (bottomscreen-1)>>FRACBITS; if (windowtop != INT32_MAX && windowbottom != INT32_MAX) { if (windowtop > topscreen) - dc_yl = (windowtop + FRACUNIT - 1)>>FRACBITS; + dc->yl = (windowtop + FRACUNIT - 1)>>FRACBITS; if (windowbottom < bottomscreen) - dc_yh = (windowbottom - 1)>>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->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 < 0) - dc_yl = 0; - if (dc_yh >= vid.height) - dc_yh = vid.height - 1; + if (dc->yl < 0) + dc->yl = 0; + if (dc->yh >= vid.height) + dc->yh = vid.height - 1; - if (dc_yl <= dc_yh && dc_yh > 0 && column->length != 0) + if (dc->yl <= dc->yh && dc->yh > 0 && column->length != 0) { - dc_source = (UINT8 *)column + 3; - dc_sourcelength = column->length; - dc_texturemid = basetexturemid - (topdelta<source = (UINT8 *)column + 3; + dc->sourcelength = column->length; + dc->texturemid = basetexturemid - (topdelta<length + 4); } - dc_texturemid = basetexturemid; + dc->texturemid = basetexturemid; } INT32 lengthcol; // column->length : for flipped column function pointers and multi-patch on 2sided wall = texture->height -static void R_DrawFlippedMaskedColumn(column_t *column) +static void R_DrawFlippedMaskedColumn(drawcolumndata_t* dc, column_t *column) { INT32 topscreen; INT32 bottomscreen; - fixed_t basetexturemid = dc_texturemid; + fixed_t basetexturemid = dc->texturemid; INT32 topdelta, prevdelta = -1; UINT8 *d,*s; @@ -690,44 +695,49 @@ static void R_DrawFlippedMaskedColumn(column_t *column) topscreen = sprtopscreen + spryscale*topdelta; bottomscreen = sprbotscreen == INT32_MAX ? topscreen + spryscale*column->length : sprbotscreen + spryscale*column->length; - dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS; - dc_yh = (bottomscreen-1)>>FRACBITS; + dc->yl = (topscreen+FRACUNIT-1)>>FRACBITS; + dc->yh = (bottomscreen-1)>>FRACBITS; if (windowtop != INT32_MAX && windowbottom != INT32_MAX) { if (windowtop > topscreen) - dc_yl = (windowtop + FRACUNIT - 1)>>FRACBITS; + dc->yl = (windowtop + FRACUNIT - 1)>>FRACBITS; if (windowbottom < bottomscreen) - dc_yh = (windowbottom - 1)>>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 < 0) - dc_yl = 0; - if (dc_yh >= vid.height) // dc_yl must be < vid.height, so reduces number of checks in tight loop - dc_yh = vid.height - 1; + 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 < 0) + dc->yl = 0; + if (dc->yh >= vid.height) // dc->yl must be < vid.height, so reduces number of checks in tight loop + dc->yh = vid.height - 1; - if (dc_yl <= dc_yh && dc_yh > 0 && column->length != 0) + if (dc->yl <= dc->yh && dc->yh > 0 && column->length != 0) { - dc_source = ZZ_Alloc(column->length); - dc_sourcelength = column->length; + dc->source = ZZ_Alloc(column->length); + dc->sourcelength = column->length; - for (s = (UINT8 *)column+2+column->length, d = dc_source; d < dc_source+column->length; --s) + for (s = (UINT8 *)column+2+column->length, d = dc->source; d < dc->source+column->length; --s) *d++ = *s; - dc_texturemid = basetexturemid - (topdelta<texturemid = basetexturemid - (topdelta<source); } column = (column_t *)((UINT8 *)column + column->length + 4); } - dc_texturemid = basetexturemid; + dc->texturemid = basetexturemid; } // @@ -737,7 +747,7 @@ static void R_DrawFlippedMaskedColumn(column_t *column) static void R_DrawVisSprite(vissprite_t *vis) { column_t *column; - void (*localcolfunc)(column_t *); + void (*localcolfunc)(drawcolumndata_t*, column_t *); INT32 texturecolumn; INT32 pwidth; fixed_t frac; @@ -745,6 +755,7 @@ static void R_DrawVisSprite(vissprite_t *vis) fixed_t this_scale = vis->thingscale; INT32 x1, x2; INT64 overflow_test; + drawcolumndata_t dc = {0}; if (!patch) return; @@ -771,33 +782,33 @@ static void R_DrawVisSprite(vissprite_t *vis) } colfunc = basecolfunc; // hack: this isn't resetting properly somewhere. - dc_colormap = vis->colormap; + dc.colormap = vis->colormap; if ((vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && (leveltime & 1)) // Bosses "flash" { // translate certain pixels to white colfunc = transcolfunc; if (vis->mobj->type == MT_CYBRAKDEMON) - dc_translation = R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE); + dc.translation = R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE); else if (vis->mobj->type == MT_METALSONIC_BATTLE) - dc_translation = R_GetTranslationColormap(TC_METALSONIC, 0, GTC_CACHE); + dc.translation = R_GetTranslationColormap(TC_METALSONIC, 0, GTC_CACHE); else - dc_translation = R_GetTranslationColormap(TC_BOSS, 0, GTC_CACHE); + dc.translation = R_GetTranslationColormap(TC_BOSS, 0, GTC_CACHE); } else if (vis->mobj->color && vis->transmap) // Color mapping { colfunc = transtransfunc; - dc_transmap = vis->transmap; + dc.transmap = vis->transmap; if (vis->mobj->colorized) - dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); + dc.translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); else if (vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // MT_GHOST LOOKS LIKE A PLAYER SO USE THE PLAYER TRANSLATION TABLES. >_> - dc_translation = R_GetLocalTranslationColormap(vis->mobj->skin, vis->mobj->localskin, vis->mobj->color, GTC_CACHE, vis->mobj->skinlocal); + dc.translation = R_GetLocalTranslationColormap(vis->mobj->skin, vis->mobj->localskin, vis->mobj->color, GTC_CACHE, vis->mobj->skinlocal); else // Use the defaults - dc_translation = R_GetTranslationColormap(TC_DEFAULT, vis->mobj->color, GTC_CACHE); + dc.translation = R_GetTranslationColormap(TC_DEFAULT, vis->mobj->color, GTC_CACHE); } else if (vis->transmap) { colfunc = fuzzcolfunc; - dc_transmap = vis->transmap; //Fab : 29-04-98: translucency table + dc.transmap = vis->transmap; //Fab : 29-04-98: translucency table } else if (vis->mobj->color) { @@ -806,33 +817,33 @@ static void R_DrawVisSprite(vissprite_t *vis) // New colormap stuff for skins Tails 06-07-2002 if (vis->mobj->colorized) - dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); + dc.translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); else if (vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // This thing is a player! - dc_translation = R_GetLocalTranslationColormap(vis->mobj->skin, vis->mobj->localskin, vis->mobj->color, GTC_CACHE, vis->mobj->skinlocal); + dc.translation = R_GetLocalTranslationColormap(vis->mobj->skin, vis->mobj->localskin, vis->mobj->color, GTC_CACHE, vis->mobj->skinlocal); else // Use the defaults - dc_translation = R_GetTranslationColormap(TC_DEFAULT, vis->mobj->color, GTC_CACHE); + dc.translation = R_GetTranslationColormap(TC_DEFAULT, vis->mobj->color, GTC_CACHE); } else if (vis->mobj->sprite == SPR_PLAY) // Looks like a player, but doesn't have a color? Get rid of green sonic syndrome. { colfunc = transcolfunc; - dc_translation = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_BLUE, GTC_CACHE); + dc.translation = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_BLUE, GTC_CACHE); } if (vis->extra_colormap) { - if (!dc_colormap) - dc_colormap = vis->extra_colormap->colormap; + if (!dc.colormap) + dc.colormap = vis->extra_colormap->colormap; else - dc_colormap = &vis->extra_colormap->colormap[dc_colormap - colormaps]; + dc.colormap = &vis->extra_colormap->colormap[dc.colormap - colormaps]; } - if (!dc_colormap) - dc_colormap = colormaps; + if (!dc.colormap) + dc.colormap = colormaps; if (encoremap && !vis->mobj->color && !(vis->mobj->flags & MF_DONTENCOREMAP)) - dc_colormap += COLORMAP_REMAPOFFSET; + dc.colormap += COLORMAP_REMAPOFFSET; - dc_texturemid = vis->texturemid; - dc_texheight = patch->height; + dc.texturemid = vis->texturemid; + dc.texheight = patch->height; frac = vis->startfrac; windowtop = windowbottom = sprbotscreen = INT32_MAX; @@ -852,15 +863,15 @@ static void R_DrawVisSprite(vissprite_t *vis) vis->xiscale = FixedDiv(vis->xiscale, this_scale); vis->isScaled = true; } - dc_texturemid = FixedDiv(dc_texturemid, this_scale); + dc.texturemid = FixedDiv(dc.texturemid, this_scale); } spryscale = vis->scale; if (!(vis->scalestep)) { - sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); - dc_iscale = FixedDiv(FRACUNIT, vis->scale); + sprtopscreen = centeryfrac - FixedMul(dc.texturemid, spryscale); + dc.iscale = FixedDiv(FRACUNIT, vis->scale); } x1 = vis->x1; @@ -886,9 +897,9 @@ static void R_DrawVisSprite(vissprite_t *vis) fixed_t scalestep = FixedMul(vis->scalestep, vis->spriteyscale); // Papersprite drawing loop - for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, spryscale += scalestep) + for (dc.x = vis->x1; dc.x <= vis->x2; dc.x++, spryscale += scalestep) { - angle_t angle = ((vis->centerangle + xtoviewangle[dc_x]) >> ANGLETOFINESHIFT) & 0xFFF; + angle_t angle = ((vis->centerangle + xtoviewangle[dc.x]) >> ANGLETOFINESHIFT) & 0xFFF; texturecolumn = (vis->paperoffset - FixedMul(FINETANGENT(angle), vis->paperdistance)) / horzscale; if (texturecolumn < 0 || texturecolumn >= pwidth) @@ -897,23 +908,23 @@ static void R_DrawVisSprite(vissprite_t *vis) if (vis->xiscale < 0) // Flipped sprite texturecolumn = pwidth - 1 - texturecolumn; - sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale)); - dc_iscale = (0xffffffffu / (unsigned)spryscale); + sprtopscreen = (centeryfrac - FixedMul(dc.texturemid, spryscale)); + dc.iscale = (0xffffffffu / (unsigned)spryscale); column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); - localcolfunc (column); + localcolfunc (&dc, column); } } else { // Non-paper drawing loop - for (dc_x = vis->x1; dc_x <= vis->x2 && (frac>>FRACBITS) < pwidth; dc_x++, frac += vis->xiscale) + for (dc.x = vis->x1; dc.x <= vis->x2 && (frac>>FRACBITS) < pwidth; dc.x++, frac += vis->xiscale) { texturecolumn = CLAMP(frac >> FRACBITS, 0, pwidth - 1); column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); - localcolfunc (column); + localcolfunc (&dc, column); } } @@ -932,6 +943,7 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) patch_t *patch; fixed_t this_scale = vis->thingscale; INT64 overflow_test; + drawcolumndata_t dc = {0}; //Fab : R_InitSprites now sets a wad lump number patch = vis->patch; @@ -946,20 +958,20 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) if (vis->transmap) { colfunc = fuzzcolfunc; - dc_transmap = vis->transmap; //Fab : 29-04-98: translucency table + dc.transmap = vis->transmap; //Fab : 29-04-98: translucency table } - dc_colormap = colormaps; + dc.colormap = colormaps; if (encoremap) - dc_colormap += COLORMAP_REMAPOFFSET; + dc.colormap += COLORMAP_REMAPOFFSET; - dc_iscale = FixedDiv(FRACUNIT, vis->scale); - dc_texturemid = FixedDiv(vis->texturemid, this_scale); - dc_texheight = patch->height; + dc.iscale = FixedDiv(FRACUNIT, vis->scale); + dc.texturemid = FixedDiv(vis->texturemid, this_scale); + dc.texheight = patch->height; frac = vis->startfrac; spryscale = vis->scale; - sprtopscreen = centeryfrac - FixedMul(dc_texturemid,spryscale); + sprtopscreen = centeryfrac - FixedMul(dc.texturemid,spryscale); windowtop = windowbottom = sprbotscreen = INT32_MAX; if (vis->x1 < 0) @@ -968,7 +980,7 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) if (vis->x2 >= vid.width) vis->x2 = vid.width-1; - for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale) + for (dc.x = vis->x1; dc.x <= vis->x2; dc.x++, frac += vis->xiscale) { texturecolumn = frac>>FRACBITS; @@ -980,7 +992,7 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); - R_DrawMaskedColumn(column); + R_DrawMaskedColumn(&dc, column); } colfunc = basecolfunc; @@ -2942,7 +2954,7 @@ void R_DrawMasked(void) else if (r2->seg && r2->seg->maskedtexturecol != NULL) { next = r2->prev; - R_RenderMaskedSegRange(r2->seg, r2->seg->x1, r2->seg->x2); + R_RenderMaskedSegRange( r2->seg, r2->seg->x1, r2->seg->x2); r2->seg->maskedtexturecol = NULL; R_DoneWithNode(r2); r2 = next; diff --git a/src/r_things.h b/src/r_things.h index afecd2041..ca09b036a 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -62,7 +62,6 @@ fixed_t R_GetSpriteDirectionalLighting(angle_t angle); fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope); -void R_DrawMaskedColumn(column_t *column); void R_SortVisSprites(void); //faB: find sprites in wadfile, replace existing, add new ones diff --git a/src/screen.c b/src/screen.c index 96b4b2c4b..d781c9199 100644 --- a/src/screen.c +++ b/src/screen.c @@ -36,19 +36,24 @@ // -------------------------------------------- // assembly or c drawer routines for 8bpp/16bpp // -------------------------------------------- -void (*wallcolfunc)(void); // new wall column drawer to draw posts >128 high -void (*colfunc)(void); // standard column, up to 128 high posts +void (*wallcolfunc)(drawcolumndata_t*); // new wall column drawer to draw posts >128 high +void (*colfunc)(drawcolumndata_t*); // standard column, up to 128 high posts + +void (*basecolfunc)(drawcolumndata_t*); +void (*fuzzcolfunc)(drawcolumndata_t*); // standard fuzzy effect column drawer +void (*transcolfunc)(drawcolumndata_t*); // translation column drawer +void (*shadecolfunc)(drawcolumndata_t*); // smokie test.. + +void (*transtransfunc)(drawcolumndata_t*); // translucent translated column drawer +void (*twosmultipatchfunc)(drawcolumndata_t*); // for cols with transparent pixels +void (*twosmultipatchtransfunc)(drawcolumndata_t*); // for cols with transparent pixels AND translucency + +// Short and Tall sky drawer, for the current color mode +void (*walldrawerfunc)(drawcolumndata_t*); -void (*basecolfunc)(void); -void (*fuzzcolfunc)(void); // standard fuzzy effect column drawer -void (*transcolfunc)(void); // translation column drawer -void (*shadecolfunc)(void); // smokie test.. void (*spanfunc)(void); // span drawer, use a 64x64 tile void (*splatfunc)(void); // span drawer w/ transparency void (*basespanfunc)(void); // default span func for color mode -void (*transtransfunc)(void); // translucent translated column drawer -void (*twosmultipatchfunc)(void); // for cols with transparent pixels -void (*twosmultipatchtransfunc)(void); // for cols with transparent pixels AND translucency // ------------------ // global video state @@ -93,9 +98,6 @@ UINT8 *scr_borderpatch; // flat used to fill the reduced view borders set at ST_ // ========================================================================= -// Short and Tall sky drawer, for the current color mode -void (*walldrawerfunc)(void); - void SCR_SetMode(void) { if (dedicated) diff --git a/src/screen.h b/src/screen.h index d78bbf8c5..414ba7195 100644 --- a/src/screen.h +++ b/src/screen.h @@ -81,22 +81,9 @@ enum // --------------------------------------------- // color mode dependent drawer function pointers // --------------------------------------------- - -extern void (*wallcolfunc)(void); -extern void (*colfunc)(void); -extern void (*basecolfunc)(void); -extern void (*fuzzcolfunc)(void); -extern void (*transcolfunc)(void); -extern void (*shadecolfunc)(void); extern void (*spanfunc)(void); extern void (*basespanfunc)(void); extern void (*splatfunc)(void); -extern void (*transtransfunc)(void); -extern void (*twosmultipatchfunc)(void); -extern void (*twosmultipatchtransfunc)(void); - -// quick fix for tall/short skies, depending on bytesperpixel -extern void (*walldrawerfunc)(void); // ---------------- // screen variables -- 2.54.0 From c67bf97f7b282f7a807b6f219f6d6982d122bbfc Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 5 Jun 2025 12:24:40 +0200 Subject: [PATCH 016/141] unglobalize drawspandata --- src/r_data.c | 4 +- src/r_data.h | 3 + src/r_draw.c | 43 +++-- src/r_draw.h | 103 ++++++++--- src/r_draw_span.c | 446 +++++++++++++++++++++++----------------------- src/r_main.c | 1 - src/r_plane.c | 288 +++++++++++++++--------------- src/r_plane.h | 8 +- src/r_things.c | 7 +- src/screen.c | 22 --- src/screen.h | 7 - 11 files changed, 483 insertions(+), 449 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index 0b5b7badf..ca73e7e42 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -100,7 +100,7 @@ INT32 numtextures = 0; // total number of textures found, texture_t **textures = NULL; static UINT32 **texturecolumnofs; // column offset lookup table for each texture -static UINT8 **texturecache; // graphics data for each generated full-size texture +UINT8 **texturecache; // graphics data for each generated full-size texture // texture width is a power of 2, so it can easily repeat along sidedefs using a simple mask INT32 *texturewidthmask; @@ -296,7 +296,7 @@ static inline void R_DrawColumnInCache(column_t *patch, UINT8 *cache, INT32 orig // This is not optimised, but it's supposed to be executed only once // per level, when enough memory is available. // -static UINT8 *R_GenerateTexture(size_t texnum) +UINT8 *R_GenerateTexture(size_t texnum) { UINT8 *block; UINT8 *blocktex; diff --git a/src/r_data.h b/src/r_data.h index f27dd0822..65dd6ccbb 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -50,6 +50,7 @@ typedef struct // all loaded and prepared textures from the start of the game extern texture_t **textures; +extern UINT8 **texturecache; // graphics data for each generated full-size texture // texture width is a power of 2, so it can easily repeat along sidedefs using a simple mask extern INT32 *texturewidthmask; @@ -68,6 +69,8 @@ extern CV_PossibleValue_t Color_cons_t[]; void R_LoadTextures(void); void R_FlushTextureCache(void); +UINT8 *R_GenerateTexture(size_t texnum); + INT32 R_GetTextureNum(INT32 texnum); void R_CheckTextureCache(INT32 tex); diff --git a/src/r_draw.c b/src/r_draw.c index 3b96dfc63..7174251f8 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -55,26 +55,47 @@ drawcolumndata_t g_dc; UINT8 *transtables; // translucency tables UINT8 *blendtables[NUMBLENDMAPS]; +// -------------------------------------------- +// c drawer routines +// -------------------------------------------- + + +void (*wallcolfunc)(drawcolumndata_t*); // new wall column drawer to draw posts >128 high +void (*colfunc)(drawcolumndata_t*); // standard column, up to 128 high posts + +void (*basecolfunc)(drawcolumndata_t*); +void (*fuzzcolfunc)(drawcolumndata_t*); // standard fuzzy effect column drawer +void (*transcolfunc)(drawcolumndata_t*); // translation column drawer +void (*shadecolfunc)(drawcolumndata_t*); // smokie test.. + +void (*transtransfunc)(drawcolumndata_t*); // translucent translated column drawer +void (*twosmultipatchfunc)(drawcolumndata_t*); // for cols with transparent pixels +void (*twosmultipatchtransfunc)(drawcolumndata_t*); // for cols with transparent pixels AND translucency + +// Short and Tall sky drawer, for the current color mode +void (*walldrawerfunc)(drawcolumndata_t*); + // ========================================================================= // SPAN DRAWING CODE STUFF // ========================================================================= -INT32 ds_y, ds_x1, ds_x2; -lighttable_t *ds_colormap; -fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep; - -UINT8 *ds_source; // points to the start of a flat -UINT8 *ds_transmap; // one of the translucency tables +drawspandata_t g_ds; // Vectors for Software's tilted slope drawers floatv3_t *ds_su, *ds_sv, *ds_sz; -floatv3_t *ds_sup, *ds_svp, *ds_szp; -float focallengthf, zeroheight; + +float focallengthf; // For, uh, tilted lighting, duh. -static INT32 *tiltlighting; +//static INT32 *tiltlighting; -UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask; +// -------------------------------------------- +// c drawer routines +// -------------------------------------------- + +void (*spanfunc)(drawspandata_t*); // span drawer, use a 64x64 tile +void (*splatfunc)(drawspandata_t*); // span drawer w/ transparency +void (*basespanfunc)(drawspandata_t*); // default span func for color mode // ========================================================================== // OLD DOOM FUZZY EFFECT @@ -459,7 +480,7 @@ static void R_AllocViewMemory(void) xtoviewangle = Z_Realloc(xtoviewangle, sizeof(*xtoviewangle) * (viewwidth + 1), PU_STATIC, NULL); - tiltlighting = Z_Realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth, PU_STATIC, NULL); + //tiltlighting = Z_Realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth, PU_STATIC, NULL); R_AllocSegMemory(); R_AllocClipSegMemory(); diff --git a/src/r_draw.h b/src/r_draw.h index 9e1851ac0..3654fdeb2 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -52,29 +52,78 @@ void R_DrawMaskedColumn(drawcolumndata_t* dc, column_t *column); // SPAN DRAWING CODE STUFF // ----------------------- -extern INT32 ds_y, ds_x1, ds_x2; -extern lighttable_t *ds_colormap; -extern fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep; -extern INT32 ds_waterofs, ds_bgofs; -extern UINT8 *ds_source; // start of a 64*64 tile image -extern UINT8 *ds_transmap; - -extern INT32 ds_bgofs; - typedef struct { float x, y, z; } floatv3_t; +typedef struct +{ + INT32 y; + INT32 x1; + INT32 x2; + lighttable_t* colormap; + lighttable_t* fullbright; + lighttable_t* translation; + + fixed_t xfrac; + fixed_t yfrac; + fixed_t xstep; + fixed_t ystep; + INT32 waterofs; + INT32 bgofs; + + fixed_t xoffs; + fixed_t yoffs; + + UINT16 flatwidth; + UINT16 flatheight; + + visplane_t *currentplane; + UINT8 *source; + UINT8 *transmap; + + float zeroheight; + + // Vectors for Software's tilted slope drawers + floatv3_t sup; + floatv3_t svp; + floatv3_t szp; + + // Variable flat sizes + UINT32 nflatxshift; + UINT32 nflatyshift; + UINT32 nflatshiftup; + UINT32 nflatmask; + + fixed_t planeheight; + lighttable_t **planezlight; + + // + // Water ripple effect + // Needs the height of the plane, and the vertical position of the span. + // Sets planeripple.xfrac and planeripple.yfrac, added to ds_xfrac and ds_yfrac, if the span is not tilted. + // + struct + { + INT32 offset; + fixed_t xfrac, yfrac; + boolean active; + } planeripple; +} drawspandata_t; + +extern drawspandata_t g_ds; + +extern void (*spanfunc)(drawspandata_t*); +extern void (*basespanfunc)(drawspandata_t*); +extern void (*splatfunc)(drawspandata_t*); + +// Draws a single visplane. +void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl); + // Vectors for Software's tilted slope drawers extern floatv3_t *ds_su, *ds_sv, *ds_sz; -extern floatv3_t *ds_sup, *ds_svp, *ds_szp; -extern float focallengthf, zeroheight; -// Variable flat sizes -extern UINT32 nflatxshift; -extern UINT32 nflatyshift; -extern UINT32 nflatshiftup; -extern UINT32 nflatmask; +extern float focallengthf; /// \brief Top border #define BRDR_T 0 @@ -176,22 +225,20 @@ void R_Draw2sMultiPatchTranslucentColumn(drawcolumndata_t* dc); void R_DrawFogColumn(drawcolumndata_t* dc); // span drawers -void R_DrawSpan(void); +void R_DrawSpan(drawspandata_t* ds); -void R_CalcTiltedLighting(fixed_t start, fixed_t end); +void R_DrawTiltedSpan(drawspandata_t* ds); +void R_DrawTiltedTranslucentSpan(drawspandata_t* ds); +void R_DrawTiltedTranslucentWaterSpan(drawspandata_t* ds); -void R_DrawTiltedSpan(void); -void R_DrawTiltedTranslucentSpan(void); -void R_DrawTiltedTranslucentWaterSpan(void); +void R_DrawTranslucentSpan(drawspandata_t* ds); +void R_DrawTranslucentWaterSpan(drawspandata_t* ds); -void R_DrawTranslucentSpan(void); -void R_DrawTranslucentWaterSpan(void); +void R_DrawFogSpan(drawspandata_t* ds); -void R_DrawFogSpan(void); - -void R_DrawTiltedSplat(void); -void R_DrawSplat(void); -void R_DrawTranslucentSplat(void); +void R_DrawTiltedSplat(drawspandata_t* ds); +void R_DrawSplat(drawspandata_t* ds); +void R_DrawTranslucentSplat(drawspandata_t* ds); // ========================================================================= #endif // __R_DRAW__ diff --git a/src/r_draw_span.c b/src/r_draw_span.c index 209db61f1..5d1a08631 100644 --- a/src/r_draw_span.c +++ b/src/r_draw_span.c @@ -24,22 +24,22 @@ /** \brief The R_DrawSpan function Draws the actual span. */ -void R_DrawSpan(void) +void R_DrawSpan(drawspandata_t* ds) { uintptr_t xposition; uintptr_t yposition; uintptr_t xstep, ystep; register UINT32 bit; - UINT8 *restrict source = ds_source; - UINT8 *restrict colormap = ds_colormap; - UINT8 *restrict dest = R_Address(ds_x1, ds_y); + UINT8 *restrict source = ds->source; + UINT8 *restrict colormap = ds->colormap; + UINT8 *restrict dest = R_Address(ds->x1, ds->y); const UINT8 *restrict deststop = vid.screens[0] + vid.rowbytes * vid.height; - register intptr_t count = (ds_x2 - ds_x1 + 1); + register intptr_t count = (ds->x2 - ds->x1 + 1); - xposition = ds_xfrac; yposition = ds_yfrac; - xstep = ds_xstep; ystep = ds_ystep; + xposition = ds->xfrac; yposition = ds->yfrac; + xstep = ds->xstep; ystep = ds->ystep; // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest // can be used for the fraction part. This allows calculation of the memory address in the @@ -48,8 +48,8 @@ void R_DrawSpan(void) // bit per power of two (obviously) // Ok, because I was able to eliminate the variable spot below, this function is now FASTER // than the original span renderer. Whodathunkit? - xposition <<= nflatshiftup; yposition <<= nflatshiftup; - xstep <<= nflatshiftup; ystep <<= nflatshiftup; + xposition <<= ds->nflatshiftup; yposition <<= ds->nflatshiftup; + xstep <<= ds->nflatshiftup; ystep <<= ds->nflatshiftup; if (dest+8 > deststop) { @@ -60,42 +60,42 @@ void R_DrawSpan(void) // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // have the uber complicated math to calculate it now, so that was a memory write we didn't // need! - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); dest[0] = colormap[source[bit]]; xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); dest[1] = colormap[source[bit]]; xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); dest[2] = colormap[source[bit]]; xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); dest[3] = colormap[source[bit]]; xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); dest[4] = colormap[source[bit]]; xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); dest[5] = colormap[source[bit]]; xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); dest[6] = colormap[source[bit]]; xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); dest[7] = colormap[source[bit]]; xposition += xstep; yposition += ystep; @@ -106,7 +106,7 @@ void R_DrawSpan(void) while (count-- && dest <= deststop) { - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); *dest++ = colormap[source[bit]]; xposition += xstep; yposition += ystep; @@ -116,7 +116,7 @@ void R_DrawSpan(void) /** \brief The R_DrawTranslucentSpan function Draws the actual span with translucent. */ -void R_DrawTranslucentSpan(void) +void R_DrawTranslucentSpan(drawspandata_t* ds) { fixed_t xposition; fixed_t yposition; @@ -128,10 +128,10 @@ void R_DrawTranslucentSpan(void) register UINT8 *dest; const UINT8 *deststop = vid.screens[0] + vid.rowbytes * vid.height; - register intptr_t count = (ds_x2 - ds_x1 + 1); + register intptr_t count = (ds->x2 - ds->x1 + 1); - xposition = ds_xfrac; yposition = ds_yfrac; - xstep = ds_xstep; ystep = ds_ystep; + xposition = ds->xfrac; yposition = ds->yfrac; + xstep = ds->xstep; ystep = ds->ystep; // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest // can be used for the fraction part. This allows calculation of the memory address in the @@ -140,55 +140,55 @@ void R_DrawTranslucentSpan(void) // bit per power of two (obviously) // Ok, because I was able to eliminate the variable spot below, this function is now FASTER // than the original span renderer. Whodathunkit? - xposition <<= nflatshiftup; yposition <<= nflatshiftup; - xstep <<= nflatshiftup; ystep <<= nflatshiftup; + xposition <<= ds->nflatshiftup; yposition <<= ds->nflatshiftup; + xstep <<= ds->nflatshiftup; ystep <<= ds->nflatshiftup; - source = ds_source; - colormap = ds_colormap; - dest = R_Address(ds_x1, ds_y); + source = ds->source; + colormap = ds->colormap; + dest = R_Address(ds->x1, ds->y); while (count >= 8) { // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // have the uber complicated math to calculate it now, so that was a memory write we didn't // need! - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - dest[0] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[0]); + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + dest[0] = *(ds->transmap + (colormap[source[bit]] << 8) + dest[0]); xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - dest[1] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[1]); + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + dest[1] = *(ds->transmap + (colormap[source[bit]] << 8) + dest[1]); xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - dest[2] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[2]); + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + dest[2] = *(ds->transmap + (colormap[source[bit]] << 8) + dest[2]); xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - dest[3] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[3]); + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + dest[3] = *(ds->transmap + (colormap[source[bit]] << 8) + dest[3]); xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - dest[4] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[4]); + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + dest[4] = *(ds->transmap + (colormap[source[bit]] << 8) + dest[4]); xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - dest[5] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[5]); + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + dest[5] = *(ds->transmap + (colormap[source[bit]] << 8) + dest[5]); xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - dest[6] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[6]); + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + dest[6] = *(ds->transmap + (colormap[source[bit]] << 8) + dest[6]); xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - dest[7] = *(ds_transmap + (colormap[source[bit]] << 8) + dest[7]); + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + dest[7] = *(ds->transmap + (colormap[source[bit]] << 8) + dest[7]); xposition += xstep; yposition += ystep; @@ -197,15 +197,15 @@ void R_DrawTranslucentSpan(void) } while (count-- && dest <= deststop) { - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - *dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dest); + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + *dest = *(ds->transmap + (colormap[source[bit]] << 8) + *dest); dest++; xposition += xstep; yposition += ystep; } } -void R_DrawTranslucentWaterSpan(void) +void R_DrawTranslucentWaterSpan(drawspandata_t* ds) { UINT32 xposition; UINT32 yposition; @@ -226,57 +226,57 @@ void R_DrawTranslucentWaterSpan(void) // bit per power of two (obviously) // Ok, because I was able to eliminate the variable spot below, this function is now FASTER // than the original span renderer. Whodathunkit? - xposition = ds_xfrac << nflatshiftup; yposition = (ds_yfrac + ds_waterofs) << nflatshiftup; - xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; + xposition = ds->xfrac << ds->nflatshiftup; yposition = (ds->yfrac + ds->waterofs) << ds->nflatshiftup; + xstep = ds->xstep << ds->nflatshiftup; ystep = ds->ystep << ds->nflatshiftup; - source = ds_source; - colormap = ds_colormap; - dest = R_Address(ds_x1, ds_y); - dsrc = vid.screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1; - count = ds_x2 - ds_x1 + 1; + source = ds->source; + colormap = ds->colormap; + dest = R_Address(ds->x1, ds->y); + dsrc = vid.screens[1] + (ds->y+ds->bgofs)*vid.width + ds->x1; + count = ds->x2 - ds->x1 + 1; while (count >= 8) { // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // have the uber complicated math to calculate it now, so that was a memory write we didn't // need! - bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - dest[0] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); + dest[0] = colormap[*(ds->transmap + (source[bit] << 8) + *dsrc++)]; xposition += xstep; yposition += ystep; - bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - dest[1] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); + dest[1] = colormap[*(ds->transmap + (source[bit] << 8) + *dsrc++)]; xposition += xstep; yposition += ystep; - bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - dest[2] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); + dest[2] = colormap[*(ds->transmap + (source[bit] << 8) + *dsrc++)]; xposition += xstep; yposition += ystep; - bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - dest[3] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); + dest[3] = colormap[*(ds->transmap + (source[bit] << 8) + *dsrc++)]; xposition += xstep; yposition += ystep; - bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - dest[4] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); + dest[4] = colormap[*(ds->transmap + (source[bit] << 8) + *dsrc++)]; xposition += xstep; yposition += ystep; - bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - dest[5] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); + dest[5] = colormap[*(ds->transmap + (source[bit] << 8) + *dsrc++)]; xposition += xstep; yposition += ystep; - bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - dest[6] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); + dest[6] = colormap[*(ds->transmap + (source[bit] << 8) + *dsrc++)]; xposition += xstep; yposition += ystep; - bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - dest[7] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); + dest[7] = colormap[*(ds->transmap + (source[bit] << 8) + *dsrc++)]; xposition += xstep; yposition += ystep; @@ -285,8 +285,8 @@ void R_DrawTranslucentWaterSpan(void) } while (count--) { - bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - *dest++ = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)]; + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); + *dest++ = colormap[*(ds->transmap + (source[bit] << 8) + *dsrc++)]; xposition += xstep; yposition += ystep; @@ -296,17 +296,17 @@ void R_DrawTranslucentWaterSpan(void) /** \brief The R_DrawFogSpan function Draws the actual span with fogging. */ -void R_DrawFogSpan(void) +void R_DrawFogSpan(drawspandata_t* ds) { UINT8 *colormap; register UINT8 *dest; register intptr_t count; - colormap = ds_colormap; - dest = R_Address(ds_x1, ds_y); + colormap = ds->colormap; + dest = R_Address(ds->x1, ds->y); - count = ds_x2 - ds_x1 + 1; + count = ds->x2 - ds->x1 + 1; while (count >= 4) { @@ -328,12 +328,12 @@ void R_DrawFogSpan(void) // R_CalcTiltedLighting // Exactly what it says on the tin. I wish I wasn't too lazy to explain things properly. -void R_CalcTiltedLighting(fixed_t start, fixed_t end) +static void R_CalcTiltedLighting(INT32 *lightbuffer, INT32 x1, INT32 x2, fixed_t start, fixed_t end) { // ZDoom uses a different lighting setup to us, and I couldn't figure out how to adapt their version // of this function. Here's my own. - INT32 left = ds_x1, right = ds_x2; - fixed_t step = (end-start)/(ds_x2-ds_x1+1); + INT32 left = x1, right = x2; + fixed_t step = (end-start)/(x2 - x1 + 1); INT32 i; // I wanna do some optimizing by checking for out-of-range segments on either side to fill in all at once, @@ -341,27 +341,23 @@ void R_CalcTiltedLighting(fixed_t start, fixed_t end) for (i = left; i <= right; i++) { - tiltlighting[i] = (start += step) >> FRACBITS; + lightbuffer[i] = (start += step) >> FRACBITS; - if (tiltlighting[i] < 0) - { - tiltlighting[i] = 0; - } - else if (tiltlighting[i] >= MAXLIGHTSCALE) - { - tiltlighting[i] = MAXLIGHTSCALE-1; - } + if (lightbuffer[i] < 0) + lightbuffer[i] = 0; + else if (lightbuffer[i] >= MAXLIGHTSCALE) + lightbuffer[i] = MAXLIGHTSCALE-1; } } -#define PLANELIGHTFLOAT ((float)BASEVIDWIDTH * BASEVIDWIDTH / vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f * FIXED_TO_FLOAT(fovtan)) +#define PLANELIGHTFLOAT ((float)BASEVIDWIDTH * BASEVIDWIDTH / vid.width / (ds->zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f * FIXED_TO_FLOAT(fovtan)) /** \brief The R_DrawTiltedSpan function Draw slopes! Holy sheit! */ -void R_DrawTiltedSpan(void) +void R_DrawTiltedSpan(drawspandata_t* ds) { - int width = ds_x2 - ds_x1; + int width = ds->x2 - ds->x1; float iz, uz, vz; UINT32 u, v; int i; @@ -375,27 +371,28 @@ void R_DrawTiltedSpan(void) float endz, endu, endv; UINT32 stepu, stepv; register UINT32 bit; + INT32 tiltlighting[MAXVIDWIDTH]; // TODO: get rid of static buffer - iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); + iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); // Lighting is simple. It's just linear interpolation from start to end { float planelightfloat = PLANELIGHTFLOAT; float lightstart, lightend; - lightend = (iz + ds_szp->x*width) * planelightfloat; + lightend = (iz + ds->szp.x*width) * planelightfloat; lightstart = iz * planelightfloat; - R_CalcTiltedLighting(FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); + R_CalcTiltedLighting(tiltlighting, ds->x1, ds->x2, FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); //CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf); } - uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); - vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); + uz = ds->sup.z + ds->sup.y*(centery-ds->y) + ds->sup.x*(ds->x1-centerx); + vz = ds->svp.z + ds->svp.y*(centery-ds->y) + ds->svp.x*(ds->x1-centerx); - dest = R_Address(ds_x1, ds_y); + dest = R_Address(ds->x1, ds->y); - source = ds_source; + source = ds->source; #if 0 // The "perfect" reference version of this routine. Pretty slow. // Use it only to see how things are supposed to look. @@ -406,23 +403,23 @@ void R_DrawTiltedSpan(void) u = (INT64)(uz*z) + viewx; v = (INT64)(vz*z) + viewy; - bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); + colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); *dest = colormap[source[bit]]; dest++; - iz += ds_szp->x; - uz += ds_sup->x; - vz += ds_svp->x; + iz += ds->szp.x; + uz += ds->sup.x; + vz += ds->svp.x; } while (--width >= 0); #else startz = 1.f/iz; startu = uz*startz; startv = vz*startz; - izstep = ds_szp->x * SPANSIZE; - uzstep = ds_sup->x * SPANSIZE; - vzstep = ds_svp->x * SPANSIZE; + izstep = ds->szp.x * SPANSIZE; + uzstep = ds->sup.x * SPANSIZE; + vzstep = ds->svp.x * SPANSIZE; width++; while (width >= SPANSIZE) @@ -441,8 +438,8 @@ void R_DrawTiltedSpan(void) for (i = SPANSIZE-1; i >= 0; i--) { - bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); + colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); *dest = colormap[source[bit]]; dest++; @@ -459,16 +456,16 @@ void R_DrawTiltedSpan(void) { u = (INT64)(startu); v = (INT64)(startv); - bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); + colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); *dest = colormap[source[bit]]; } else { float left = width; - iz += ds_szp->x * left; - uz += ds_sup->x * left; - vz += ds_svp->x * left; + iz += ds->szp.x * left; + uz += ds->sup.x * left; + vz += ds->svp.x * left; endz = 1.f/iz; endu = uz*endz; @@ -481,8 +478,8 @@ void R_DrawTiltedSpan(void) for (; width != 0; width--) { - bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); + colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); *dest = colormap[source[bit]]; dest++; @@ -497,9 +494,9 @@ void R_DrawTiltedSpan(void) /** \brief The R_DrawTiltedTranslucentSpan function Like DrawTiltedSpan, but translucent */ -void R_DrawTiltedTranslucentSpan(void) +void R_DrawTiltedTranslucentSpan(drawspandata_t* ds) { - int width = ds_x2 - ds_x1; + int width = ds->x2 - ds->x1; float iz, uz, vz; UINT32 u, v; int i; @@ -513,27 +510,28 @@ void R_DrawTiltedTranslucentSpan(void) float endz, endu, endv; UINT32 stepu, stepv; register UINT32 bit; + INT32 tiltlighting[MAXVIDWIDTH]; - iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); + iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); // Lighting is simple. It's just linear interpolation from start to end { float planelightfloat = PLANELIGHTFLOAT; float lightstart, lightend; - lightend = (iz + ds_szp->x*width) * planelightfloat; + lightend = (iz + ds->szp.x*width) * planelightfloat; lightstart = iz * planelightfloat; - R_CalcTiltedLighting(FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); + R_CalcTiltedLighting(tiltlighting, ds->x1, ds->x2, FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); //CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf); } - uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); - vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); + uz = ds->sup.z + ds->sup.y*(centery-ds->y) + ds->sup.x*(ds->x1-centerx); + vz = ds->svp.z + ds->svp.y*(centery-ds->y) + ds->svp.x*(ds->x1-centerx); - dest = R_Address(ds_x1, ds_y); + dest = R_Address(ds->x1, ds->y); - source = ds_source; + source = ds->source; #if 0 // The "perfect" reference version of this routine. Pretty slow. // Use it only to see how things are supposed to look. @@ -544,23 +542,23 @@ void R_DrawTiltedTranslucentSpan(void) u = (INT64)(uz*z) + viewx; v = (INT64)(vz*z) + viewy; - bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dest); + bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); + colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); + *dest = *(ds->transmap + (colormap[source[bit]] << 8) + *dest); dest++; - iz += ds_szp->x; - uz += ds_sup->x; - vz += ds_svp->x; + iz += ds->szp.x; + uz += ds->sup.x; + vz += ds->svp.x; } while (--width >= 0); #else startz = 1.f/iz; startu = uz*startz; startv = vz*startz; - izstep = ds_szp->x * SPANSIZE; - uzstep = ds_sup->x * SPANSIZE; - vzstep = ds_svp->x * SPANSIZE; + izstep = ds->szp.x * SPANSIZE; + uzstep = ds->sup.x * SPANSIZE; + vzstep = ds->svp.x * SPANSIZE; width++; while (width >= SPANSIZE) @@ -579,9 +577,9 @@ void R_DrawTiltedTranslucentSpan(void) for (i = SPANSIZE-1; i >= 0; i--) { - bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dest); + bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); + colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); + *dest = *(ds->transmap + (colormap[source[bit]] << 8) + *dest); dest++; u += stepu; @@ -597,16 +595,16 @@ void R_DrawTiltedTranslucentSpan(void) { u = (INT64)(startu); v = (INT64)(startv); - bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dest); + bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); + colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); + *dest = *(ds->transmap + (colormap[source[bit]] << 8) + *dest); } else { float left = width; - iz += ds_szp->x * left; - uz += ds_sup->x * left; - vz += ds_svp->x * left; + iz += ds->szp.x * left; + uz += ds->sup.x * left; + vz += ds->svp.x * left; endz = 1.f/iz; endu = uz*endz; @@ -619,9 +617,9 @@ void R_DrawTiltedTranslucentSpan(void) for (; width != 0; width--) { - bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dest); + bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); + colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); + *dest = *(ds->transmap + (colormap[source[bit]] << 8) + *dest); dest++; u += stepu; @@ -635,9 +633,9 @@ void R_DrawTiltedTranslucentSpan(void) /** \brief The R_DrawTiltedTranslucentWaterSpan function Like DrawTiltedTranslucentSpan, but for water */ -void R_DrawTiltedTranslucentWaterSpan(void) +void R_DrawTiltedTranslucentWaterSpan(drawspandata_t* ds) { - int width = ds_x2 - ds_x1; + int width = ds->x2 - ds->x1; float iz, uz, vz; UINT32 u, v; int i; @@ -652,28 +650,29 @@ void R_DrawTiltedTranslucentWaterSpan(void) float endz, endu, endv; UINT32 stepu, stepv; register UINT32 bit; + INT32 tiltlighting[MAXVIDWIDTH]; - iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); + iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); // Lighting is simple. It's just linear interpolation from start to end { float planelightfloat = PLANELIGHTFLOAT; float lightstart, lightend; - lightend = (iz + ds_szp->x*width) * planelightfloat; + lightend = (iz + ds->szp.x*width) * planelightfloat; lightstart = iz * planelightfloat; - R_CalcTiltedLighting(FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); + R_CalcTiltedLighting(tiltlighting, ds->x1, ds->x2, FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); //CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf); } - uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); - vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); + uz = ds->sup.z + ds->sup.y*(centery-ds->y) + ds->sup.x*(ds->x1-centerx); + vz = ds->svp.z + ds->svp.y*(centery-ds->y) + ds->svp.x*(ds->x1-centerx); - dest = R_Address(ds_x1, ds_y); - dsrc = vid.screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1; + dest = R_Address(ds->x1, ds->y); + dsrc = vid.screens[1] + (ds->y+ds->bgofs)*vid.width + ds->x1; - source = ds_source; + source = ds->source; #if 0 // The "perfect" reference version of this routine. Pretty slow. // Use it only to see how things are supposed to look. @@ -684,23 +683,23 @@ void R_DrawTiltedTranslucentWaterSpan(void) u = (INT64)(uz*z) + viewx; v = (INT64)(vz*z) + viewy; - bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dsrc++); + bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); + colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); + *dest = *(ds->transmap + (colormap[source[bit]] << 8) + *dsrc++); dest++; - iz += ds_szp->x; - uz += ds_sup->x; - vz += ds_svp->x; + iz += ds->szp.x; + uz += ds->sup.x; + vz += ds->svp.x; } while (--width >= 0); #else startz = 1.f/iz; startu = uz*startz; startv = vz*startz; - izstep = ds_szp->x * SPANSIZE; - uzstep = ds_sup->x * SPANSIZE; - vzstep = ds_svp->x * SPANSIZE; + izstep = ds->szp.x * SPANSIZE; + uzstep = ds->sup.x * SPANSIZE; + vzstep = ds->svp.x * SPANSIZE; width++; while (width >= SPANSIZE) @@ -719,9 +718,9 @@ void R_DrawTiltedTranslucentWaterSpan(void) for (i = SPANSIZE-1; i >= 0; i--) { - bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dsrc++); + bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); + colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); + *dest = *(ds->transmap + (colormap[source[bit]] << 8) + *dsrc++); dest++; u += stepu; @@ -737,16 +736,16 @@ void R_DrawTiltedTranslucentWaterSpan(void) { u = (INT64)(startu); v = (INT64)(startv); - bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dsrc++); + bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); + colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); + *dest = *(ds->transmap + (colormap[source[bit]] << 8) + *dsrc++); } else { float left = width; - iz += ds_szp->x * left; - uz += ds_sup->x * left; - vz += ds_svp->x * left; + iz += ds->szp.x * left; + uz += ds->sup.x * left; + vz += ds->svp.x * left; endz = 1.f/iz; endu = uz*endz; @@ -759,9 +758,9 @@ void R_DrawTiltedTranslucentWaterSpan(void) for (; width != 0; width--) { - bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); - *dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dsrc++); + bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); + colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); + *dest = *(ds->transmap + (colormap[source[bit]] << 8) + *dsrc++); dest++; u += stepu; @@ -772,10 +771,10 @@ void R_DrawTiltedTranslucentWaterSpan(void) #endif } -void R_DrawTiltedSplat(void) +void R_DrawTiltedSplat(drawspandata_t* ds) { - // x1, x2 = ds_x1, ds_x2 - int width = ds_x2 - ds_x1; + // x1, x2 = ds->x1, ds->x2 + int width = ds->x2 - ds->x1; float iz, uz, vz; UINT32 u, v; int i; @@ -791,28 +790,29 @@ void R_DrawTiltedSplat(void) float endz, endu, endv; UINT32 stepu, stepv; register UINT32 bit; + INT32 tiltlighting[MAXVIDWIDTH]; - iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); + iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); // Lighting is simple. It's just linear interpolation from start to end { float planelightfloat = PLANELIGHTFLOAT; float lightstart, lightend; - lightend = (iz + ds_szp->x*width) * planelightfloat; + lightend = (iz + ds->szp.x*width) * planelightfloat; lightstart = iz * planelightfloat; - R_CalcTiltedLighting(FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); + R_CalcTiltedLighting(tiltlighting, ds->x1, ds->x2, FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); //CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf); } - uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); - vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); + uz = ds->sup.z + ds->sup.y*(centery-ds->y) + ds->sup.x*(ds->x1-centerx); + vz = ds->svp.z + ds->svp.y*(centery-ds->y) + ds->svp.x*(ds->x1-centerx); - dest = R_Address(ds_x1, ds_y); + dest = R_Address(ds->x1, ds->y); - source = ds_source; - //colormap = ds_colormap; + source = ds->source; + //colormap = ds->colormap; #if 0 // The "perfect" reference version of this routine. Pretty slow. // Use it only to see how things are supposed to look. @@ -823,27 +823,27 @@ void R_DrawTiltedSplat(void) u = (INT64)(uz*z) + viewx; v = (INT64)(vz*z) + viewy; - bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); val = source[bit]; if (val != TRANSPARENTPIXEL) { - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); *dest = colormap[val]; } dest++; - iz += ds_szp->x; - uz += ds_sup->x; - vz += ds_svp->x; + iz += ds->szp.x; + uz += ds->sup.x; + vz += ds->svp.x; } while (--width >= 0); #else startz = 1.f/iz; startu = uz*startz; startv = vz*startz; - izstep = ds_szp->x * SPANSIZE; - uzstep = ds_sup->x * SPANSIZE; - vzstep = ds_svp->x * SPANSIZE; + izstep = ds->szp.x * SPANSIZE; + uzstep = ds->sup.x * SPANSIZE; + vzstep = ds->svp.x * SPANSIZE; //x1 = 0; width++; @@ -863,11 +863,11 @@ void R_DrawTiltedSplat(void) for (i = SPANSIZE-1; i >= 0; i--) { - bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); val = source[bit]; if (val != TRANSPARENTPIXEL) { - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); *dest = colormap[val]; } dest++; @@ -884,20 +884,20 @@ void R_DrawTiltedSplat(void) { u = (INT64)(startu); v = (INT64)(startv); - bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); val = source[bit]; if (val != TRANSPARENTPIXEL) { - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); *dest = colormap[val]; } } else { float left = width; - iz += ds_szp->x * left; - uz += ds_sup->x * left; - vz += ds_svp->x * left; + iz += ds->szp.x * left; + uz += ds->sup.x * left; + vz += ds->svp.x * left; endz = 1.f/iz; endu = uz*endz; @@ -910,11 +910,11 @@ void R_DrawTiltedSplat(void) for (; width != 0; width--) { - bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); val = source[bit]; if (val != TRANSPARENTPIXEL) { - colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); *dest = colormap[val]; } dest++; @@ -929,7 +929,7 @@ void R_DrawTiltedSplat(void) /** \brief The R_DrawSplat function Just like R_DrawSpan, but skips transparent pixels. */ -void R_DrawSplat(void) +void R_DrawSplat(drawspandata_t* ds) { UINT32 xposition; UINT32 yposition; @@ -951,13 +951,13 @@ void R_DrawSplat(void) // bit per power of two (obviously) // Ok, because I was able to eliminate the variable spot below, this function is now FASTER // than the original span renderer. Whodathunkit? - xposition = ds_xfrac << nflatshiftup; yposition = ds_yfrac << nflatshiftup; - xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; + xposition = ds->xfrac << ds->nflatshiftup; yposition = ds->yfrac << ds->nflatshiftup; + xstep = ds->xstep << ds->nflatshiftup; ystep = ds->ystep << ds->nflatshiftup; - source = ds_source; - colormap = ds_colormap; - dest = R_Address(ds_x1, ds_y); - count = ds_x2 - ds_x1 + 1; + source = ds->source; + colormap = ds->colormap; + dest = R_Address(ds->x1, ds->y); + count = ds->x2 - ds->x1 + 1; while (count >= 8) { @@ -968,7 +968,7 @@ void R_DrawSplat(void) // 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size) for (i = 0; i < 8; i++) { - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); bit &= MAXFLATBYTES; val = source[bit]; if (val != TRANSPARENTPIXEL) @@ -983,7 +983,7 @@ void R_DrawSplat(void) } while (count--) { - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); val = source[bit]; if (val != TRANSPARENTPIXEL) { @@ -999,7 +999,7 @@ void R_DrawSplat(void) /** \brief The R_DrawTranslucentSplat function Just like R_DrawSplat, but is translucent! */ -void R_DrawTranslucentSplat(void) +void R_DrawTranslucentSplat(drawspandata_t* ds) { UINT32 xposition; UINT32 yposition; @@ -1021,13 +1021,13 @@ void R_DrawTranslucentSplat(void) // bit per power of two (obviously) // Ok, because I was able to eliminate the variable spot below, this function is now FASTER // than the original span renderer. Whodathunkit? - xposition = ds_xfrac << nflatshiftup; yposition = ds_yfrac << nflatshiftup; - xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; + xposition = ds->xfrac << ds->nflatshiftup; yposition = ds->yfrac << ds->nflatshiftup; + xstep = ds->xstep << ds->nflatshiftup; ystep = ds->ystep << ds->nflatshiftup; - source = ds_source; - colormap = ds_colormap; - dest = R_Address(ds_x1, ds_y); - count = ds_x2 - ds_x1 + 1; + source = ds->source; + colormap = ds->colormap; + dest = R_Address(ds->x1, ds->y); + count = ds->x2 - ds->x1 + 1; while (count >= 8) { @@ -1036,10 +1036,10 @@ void R_DrawTranslucentSplat(void) // need! for (i = 0; i < 8; i++) { - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); val = source[bit]; if (val != TRANSPARENTPIXEL) - dest[i] = *(ds_transmap + (colormap[val] << 8) + dest[i]); + dest[i] = *(ds->transmap + (colormap[val] << 8) + dest[i]); xposition += xstep; yposition += ystep; @@ -1050,10 +1050,10 @@ void R_DrawTranslucentSplat(void) } while (count--) { - bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); val = source[bit]; if (val != TRANSPARENTPIXEL) - *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + *dest = *(ds->transmap + (colormap[val] << 8) + *dest); dest++; xposition += xstep; diff --git a/src/r_main.c b/src/r_main.c index f08f4b5f6..28c372d5b 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -951,7 +951,6 @@ void R_ExecuteSetViewSize(void) Z_Free(ds_sz); ds_su = ds_sv = ds_sz = NULL; - ds_sup = ds_svp = ds_szp = NULL; memset(scalelight, 0xFF, sizeof(scalelight)); diff --git a/src/r_plane.c b/src/r_plane.c index 7c1375695..99e6dde6a 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -46,7 +46,6 @@ static visplane_t **freehead = &freetail; visplane_t *floorplane; visplane_t *ceilingplane; -static visplane_t *currentplane; visffloor_t ffloor[MAXFFLOORS]; INT32 numffloors; @@ -73,12 +72,6 @@ fixed_t *frontscale; // static INT32 *spanstart; -// -// texture mapping -// -lighttable_t **planezlight; -static fixed_t planeheight; - //added : 10-02-98: yslopetab is what yslope used to be, // yslope points somewhere into yslopetab, // now (viewheight/2) slopes are calculated above and @@ -148,51 +141,41 @@ void R_AllocPlaneMemory(void) // Sets planeripple.xfrac and planeripple.yfrac, added to ds_xfrac and ds_yfrac, if the span is not tilted. // -INT32 ds_bgofs; -INT32 ds_waterofs; - -struct -{ - INT32 offset; - fixed_t xfrac, yfrac; - boolean active; -} planeripple; - -static void R_CalculatePlaneRipple(visplane_t *plane, INT32 y, fixed_t plheight, boolean calcfrac) +static void R_CalculatePlaneRipple(drawspandata_t* ds, visplane_t *plane, INT32 y, fixed_t plheight, boolean calcfrac) { fixed_t distance = FixedMul(plheight, yslope[y]); - const INT32 yay = (planeripple.offset + (distance>>9)) & 8191; + const INT32 yay = (ds->planeripple.offset + (distance>>9)) & 8191; // ripples da water texture - ds_bgofs = FixedDiv(FINESINE(yay), (1<<12) + (distance>>11))>>FRACBITS; + ds->bgofs = FixedDiv(FINESINE(yay), (1<<12) + (distance>>11))>>FRACBITS; if (calcfrac) { angle_t angle = (plane->viewangle + plane->plangle)>>ANGLETOFINESHIFT; angle = (angle + 2048) & 8191; // 90 degrees - planeripple.xfrac = FixedMul(FINECOSINE(angle), (ds_bgofs<planeripple.xfrac = FixedMul(FINECOSINE(angle), (ds->bgofs<planeripple.yfrac = FixedMul(FINESINE(angle), (ds->bgofs<waterofs = (leveltime & 1)*16384; + ds->planeripple.offset = ((leveltime-1)*140) + ((rendertimefrac*140) / FRACUNIT); } -static void R_HandleRipplePlane(visplane_t *pl) +static void R_HandleRipplePlane(drawspandata_t* ds, visplane_t *pl) { INT32 top, bottom; UINT8 *scr; if (!cv_ripplewater.value) { - planeripple.active = false; + ds->planeripple.active = false; return; } - planeripple.active = true; + ds->planeripple.active = true; if (spanfunc == R_DrawTranslucentSpan) { @@ -254,7 +237,7 @@ static void R_HandleRipplePlane(visplane_t *pl) // viewsin // viewcos // viewheight -void R_MapPlane(INT32 y, INT32 x1, INT32 x2) +static void R_MapPlane(drawspandata_t *ds, INT32 y, INT32 x1, INT32 x2) { angle_t angle, planecos, planesin; fixed_t distance = 0, span; @@ -268,78 +251,78 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2) if (x1 >= vid.width) x1 = vid.width - 1; - if (!currentplane->slope) + if (!ds->currentplane->slope) { - angle = (currentplane->viewangle + currentplane->plangle)>>ANGLETOFINESHIFT; + angle = (ds->currentplane->viewangle + ds->currentplane->plangle)>>ANGLETOFINESHIFT; planecos = FINECOSINE(angle); planesin = FINESINE(angle); // [RH] Notice that I dumped the caching scheme used by Doom. // It did not offer any appreciable speedup. - distance = FixedMul(planeheight, yslope[y]); + distance = FixedMul(ds->planeheight, yslope[y]); span = abs(centery - y); if (span) // don't divide by zero { - ds_xstep = FixedMul(planesin, planeheight) / span; - ds_ystep = FixedMul(planecos, planeheight) / span; + ds->xstep = FixedMul(planesin, ds->planeheight) / span; + ds->ystep = FixedMul(planecos, ds->planeheight) / span; } else { - ds_xstep = FixedMul(distance, basexscale); - ds_ystep = FixedMul(distance, baseyscale); + ds->xstep = FixedMul(distance, basexscale); + ds->ystep = FixedMul(distance, baseyscale); } - ds_xfrac = xoffs + FixedMul(planecos, distance) + (x1 - centerx) * ds_xstep; - ds_yfrac = yoffs - FixedMul(planesin, distance) + (x1 - centerx) * ds_ystep; + ds->xfrac = xoffs + FixedMul(planecos, distance) + (x1 - centerx) * ds->xstep; + ds->yfrac = yoffs - FixedMul(planesin, distance) + (x1 - centerx) * ds->ystep; } - if (planeripple.active) + if (ds->planeripple.active) { // Needed for ds_bgofs - R_CalculatePlaneRipple(currentplane, y, planeheight, (!currentplane->slope)); + R_CalculatePlaneRipple(ds, ds->currentplane, y, ds->planeheight, (!ds->currentplane->slope)); - if (currentplane->slope) + if (ds->currentplane->slope) { - ds_sup = &ds_su[y]; - ds_svp = &ds_sv[y]; - ds_szp = &ds_sz[y]; + ds->sup = ds_su[y]; + ds->svp = ds_sv[y]; + ds->szp = ds_sz[y]; } else { - ds_xfrac += planeripple.xfrac; - ds_yfrac += planeripple.yfrac; + ds->xfrac += ds->planeripple.xfrac; + ds->yfrac += ds->planeripple.yfrac; } - if ((y + ds_bgofs) >= viewheight) - ds_bgofs = viewheight-y-1; - if ((y + ds_bgofs) < 0) - ds_bgofs = -y; + if ((y + ds->bgofs) >= viewheight) + ds->bgofs = viewheight-y-1; + if ((y + ds->bgofs) < 0) + ds->bgofs = -y; } - if (currentplane->slope) - ds_colormap = colormaps; + if (ds->currentplane->slope) + ds->colormap = colormaps; else { pindex = distance >> LIGHTZSHIFT; if (pindex >= MAXLIGHTZ) pindex = MAXLIGHTZ - 1; - ds_colormap = planezlight[pindex]; + ds->colormap = ds->planezlight[pindex]; } - if (encoremap && !currentplane->noencore) - ds_colormap += COLORMAP_REMAPOFFSET; + if (encoremap && !ds->currentplane->noencore) + ds->colormap += COLORMAP_REMAPOFFSET; - if (currentplane->extra_colormap) - ds_colormap = currentplane->extra_colormap->colormap + (ds_colormap - colormaps); + if (ds->currentplane->extra_colormap) + ds->colormap = ds->currentplane->extra_colormap->colormap + (ds->colormap - colormaps); - ds_y = y; - ds_x1 = x1; - ds_x2 = x2; + ds->y = y; + ds->x1 = x1; + ds->x2 = x2; - spanfunc(); + spanfunc(ds); } -void R_ClearFFloorClips (void) +void R_ClearFFloorClips(void) { INT32 i, p; @@ -667,7 +650,7 @@ void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop) // // R_MakeSpans // -void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2) +static void R_MakeSpans(drawspandata_t* ds, INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2) { // Alam: from r_splats's R_RenderFloorSplat if (t1 >= vid.height) t1 = vid.height-1; @@ -676,14 +659,16 @@ void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2) if (b2 >= vid.height) b2 = vid.height-1; if (x-1 >= vid.width) x = vid.width; + drawspandata_t dc_copy = *ds; + while (t1 < t2 && t1 <= b1) { - R_MapPlane(t1, spanstart[t1], x - 1); + R_MapPlane(&dc_copy, t1, spanstart[t1], x - 1); t1++; } while (b1 > b2 && b1 >= t1) { - R_MapPlane(b1, spanstart[b1], x - 1); + R_MapPlane(&dc_copy, b1, spanstart[b1], x - 1); b1--; } @@ -697,6 +682,7 @@ void R_DrawPlanes(void) { visplane_t *pl; INT32 i; + drawspandata_t ds = {0}; spanfunc = basespanfunc; wallcolfunc = walldrawerfunc; @@ -708,17 +694,16 @@ void R_DrawPlanes(void) if (pl->ffloor != NULL || pl->polyobj != NULL) continue; - R_DrawSinglePlane(pl); + R_DrawSinglePlane(&ds, pl); } } - R_UpdatePlaneRipple(); + R_UpdatePlaneRipple(&ds); } static void R_DrawSkyPlane(visplane_t *pl) { INT32 x; - INT32 angle; drawcolumndata_t dc = {0}; if (!newview->sky) @@ -744,25 +729,35 @@ static void R_DrawSkyPlane(visplane_t *pl) dc.texheight = textureheight[skytexture] >>FRACBITS; dc.sourcelength = dc.texheight; + // Precache the texture so we don't corrupt the zoned heap off-main thread + if (!texturecache[texturetranslation[skytexture]]) + { + R_GenerateTexture(texturetranslation[skytexture]); + } + for (x = pl->minx; x <= pl->maxx; x++) { dc.yl = pl->top[x]; dc.yh = pl->bottom[x]; - if (!(dc.yl <= dc.yh)) + if (dc.yl > dc.yh) + { continue; + } - angle = (pl->viewangle + xtoviewangle[x])>>ANGLETOSKYSHIFT; + INT32 angle = (pl->viewangle + xtoviewangle[x])>>ANGLETOSKYSHIFT; dc.iscale = FixedMul(skyscale, FINECOSINE(xtoviewangle[x]>>ANGLETOFINESHIFT)); dc.x = x; - dc.source = R_GetColumn(texturetranslation[skytexture], angle); + dc.source = + R_GetColumn(texturetranslation[skytexture], + -angle); // get negative of angle for each column to display sky correct way round! --Monster Iestyn 27/01/18 wallcolfunc(&dc); } } // Potentially override other stuff for now cus we're mean. :< But draw a slope plane! // I copied ZDoom's code and adapted it to SRB2... -Red -void R_CalculateSlopeVectors(pslope_t *slope, fixed_t planeviewx, fixed_t planeviewy, fixed_t planeviewz, fixed_t planexscale, fixed_t planeyscale, fixed_t planexoffset, fixed_t planeyoffset, angle_t planeviewangle, angle_t planeangle, float fudge) +static void R_CalculateSlopeVectors(drawspandata_t* ds, pslope_t *slope, fixed_t planeviewx, fixed_t planeviewy, fixed_t planeviewz, fixed_t planexscale, fixed_t planeyscale, fixed_t planexoffset, fixed_t planeyoffset, angle_t planeviewangle, angle_t planeangle, float fudge) { floatv3_t p, m, n; float ang; @@ -778,7 +773,7 @@ void R_CalculateSlopeVectors(pslope_t *slope, fixed_t planeviewx, fixed_t planev vz = FIXED_TO_FLOAT(planeviewz); temp = P_GetSlopeZAt(slope, planeviewx, planeviewy); - zeroheight = FIXED_TO_FLOAT(temp); + ds->zeroheight = FIXED_TO_FLOAT(temp); // p is the texture origin in view space // Don't add in the offsets at this stage, because doing so can result in @@ -800,9 +795,9 @@ void R_CalculateSlopeVectors(pslope_t *slope, fixed_t planeviewx, fixed_t planev ang = ANG2RAD(planeangle); temp = P_GetSlopeZAt(slope, planeviewx + FLOAT_TO_FIXED(yscale * sin(ang)), planeviewy + FLOAT_TO_FIXED(yscale * cos(ang))); - m.y = FIXED_TO_FLOAT(temp) - zeroheight; + m.y = FIXED_TO_FLOAT(temp) - ds->zeroheight; temp = P_GetSlopeZAt(slope, planeviewx + FLOAT_TO_FIXED(xscale * cos(ang)), planeviewy - FLOAT_TO_FIXED(xscale * sin(ang))); - n.y = FIXED_TO_FLOAT(temp) - zeroheight; + n.y = FIXED_TO_FLOAT(temp) - ds->zeroheight; m.x /= fudge; m.y /= fudge; @@ -814,30 +809,30 @@ void R_CalculateSlopeVectors(pslope_t *slope, fixed_t planeviewx, fixed_t planev // Eh. I tried making this stuff fixed-point and it exploded on me. Here's a macro for the only floating-point vector function I recall using. #define CROSS(d, v1, v2) \ -d->x = (v1.y * v2.z) - (v1.z * v2.y);\ -d->y = (v1.z * v2.x) - (v1.x * v2.z);\ -d->z = (v1.x * v2.y) - (v1.y * v2.x) - CROSS(ds_sup, p, m); - CROSS(ds_svp, p, n); - CROSS(ds_szp, m, n); +d.x = (v1.y * v2.z) - (v1.z * v2.y);\ +d.y = (v1.z * v2.x) - (v1.x * v2.z);\ +d.z = (v1.x * v2.y) - (v1.y * v2.x) + CROSS(ds->sup, p, m); + CROSS(ds->svp, p, n); + CROSS(ds->szp, m, n); #undef CROSS - ds_sup->z *= focallengthf; - ds_svp->z *= focallengthf; - ds_szp->z *= focallengthf; + ds->sup.z *= focallengthf; + ds->svp.z *= focallengthf; + ds->szp.z *= focallengthf; // Premultiply the texture vectors with the scale factors #define SFMULT 65536.f - ds_sup->x *= (SFMULT * (1<y *= (SFMULT * (1<z *= (SFMULT * (1<x *= (SFMULT * (1<y *= (SFMULT * (1<z *= (SFMULT * (1<sup.x *= (SFMULT * (1<nflatshiftup)); + ds->sup.y *= (SFMULT * (1<nflatshiftup)); + ds->sup.z *= (SFMULT * (1<nflatshiftup)); + ds->svp.x *= (SFMULT * (1<nflatshiftup)); + ds->svp.y *= (SFMULT * (1<nflatshiftup)); + ds->svp.z *= (SFMULT * (1<nflatshiftup)); #undef SFMULT } -static void R_SetSlopePlaneVectors(visplane_t *pl, INT32 y, fixed_t xoff, fixed_t yoff, float fudge) +static void R_SetSlopePlaneVectors(drawspandata_t* ds, visplane_t *pl, INT32 y, fixed_t xoff, fixed_t yoff, float fudge) { if (ds_su == NULL) ds_su = Z_Malloc(sizeof(*ds_su) * vid.height, PU_STATIC, NULL); @@ -846,14 +841,14 @@ static void R_SetSlopePlaneVectors(visplane_t *pl, INT32 y, fixed_t xoff, fixed_ if (ds_sz == NULL) ds_sz = Z_Malloc(sizeof(*ds_sz) * vid.height, PU_STATIC, NULL); - ds_sup = &ds_su[y]; - ds_svp = &ds_sv[y]; - ds_szp = &ds_sz[y]; + ds->sup = ds_su[y]; + ds->svp = ds_sv[y]; + ds->szp = ds_sz[y]; - R_CalculateSlopeVectors(pl->slope, pl->viewx, pl->viewy, pl->viewz, FRACUNIT, FRACUNIT, xoff, yoff, pl->viewangle, pl->plangle, fudge); + R_CalculateSlopeVectors(ds, pl->slope, pl->viewx, pl->viewy, pl->viewz, FRACUNIT, FRACUNIT, xoff, yoff, pl->viewangle, pl->plangle, fudge); } -void R_DrawSinglePlane(visplane_t *pl) +void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl) { INT32 light = 0; INT32 x; @@ -871,7 +866,7 @@ void R_DrawSinglePlane(visplane_t *pl) return; } - planeripple.active = false; + ds->planeripple.active = false; spanfunc = basespanfunc; if (pl->polyobj && pl->polyobj->translucency != 0) @@ -882,7 +877,7 @@ void R_DrawSinglePlane(visplane_t *pl) if (pl->polyobj->translucency >= 10) return; // Don't even draw it else if (pl->polyobj->translucency > 0) - ds_transmap = R_GetTranslucencyTable(pl->polyobj->translucency); + ds->transmap = R_GetTranslucencyTable(pl->polyobj->translucency); else // Opaque, but allow transparent flat pixels spanfunc = splatfunc; @@ -926,8 +921,8 @@ void R_DrawSinglePlane(visplane_t *pl) if (trans >= 10) return; // Don't even draw it if (pl->ffloor->blend) // additive, (reverse) subtractive, modulative - ds_transmap = R_GetBlendTable(pl->ffloor->blend, trans); - else if (!(ds_transmap = R_GetTranslucencyTable(trans)) || trans == 0) + ds->transmap = R_GetBlendTable(pl->ffloor->blend, trans); + else if (!(ds->transmap = R_GetTranslucencyTable(trans)) || trans == 0) spanfunc = splatfunc; // Opaque, but allow transparent flat pixels } @@ -949,7 +944,7 @@ void R_DrawSinglePlane(visplane_t *pl) if (pl->ffloor->flags & FF_RIPPLE) { - R_HandleRipplePlane(pl); + R_HandleRipplePlane(ds, pl); } } else light = (pl->lightlevel >> LIGHTSEGSHIFT); @@ -964,9 +959,9 @@ void R_DrawSinglePlane(visplane_t *pl) viewangle = pl->viewangle+pl->plangle; } - currentplane = pl; + ds->currentplane = pl; - ds_source = (UINT8 *) + ds->source = (UINT8 *) W_CacheLumpNum(levelflats[pl->picnum].lumpnum, PU_STATIC); // Stay here until Z_ChangeTag @@ -975,52 +970,52 @@ void R_DrawSinglePlane(visplane_t *pl) switch (size) { case 4194304: // 2048x2048 lump - nflatmask = 0x3FF800; - nflatxshift = 21; - nflatyshift = 10; - nflatshiftup = 5; + ds->nflatmask = 0x3FF800; + ds->nflatxshift = 21; + ds->nflatyshift = 10; + ds->nflatshiftup = 5; break; case 1048576: // 1024x1024 lump - nflatmask = 0xFFC00; - nflatxshift = 22; - nflatyshift = 12; - nflatshiftup = 6; + ds->nflatmask = 0xFFC00; + ds->nflatxshift = 22; + ds->nflatyshift = 12; + ds->nflatshiftup = 6; break; case 262144:// 512x512 lump' - nflatmask = 0x3FE00; - nflatxshift = 23; - nflatyshift = 14; - nflatshiftup = 7; + ds->nflatmask = 0x3FE00; + ds->nflatxshift = 23; + ds->nflatyshift = 14; + ds->nflatshiftup = 7; break; case 65536: // 256x256 lump - nflatmask = 0xFF00; - nflatxshift = 24; - nflatyshift = 16; - nflatshiftup = 8; + ds->nflatmask = 0xFF00; + ds->nflatxshift = 24; + ds->nflatyshift = 16; + ds->nflatshiftup = 8; break; case 16384: // 128x128 lump - nflatmask = 0x3F80; - nflatxshift = 25; - nflatyshift = 18; - nflatshiftup = 9; + ds->nflatmask = 0x3F80; + ds->nflatxshift = 25; + ds->nflatyshift = 18; + ds->nflatshiftup = 9; break; case 1024: // 32x32 lump - nflatmask = 0x3E0; - nflatxshift = 27; - nflatyshift = 22; - nflatshiftup = 11; + ds->nflatmask = 0x3E0; + ds->nflatxshift = 27; + ds->nflatyshift = 22; + ds->nflatshiftup = 11; break; default: // 64x64 lump - nflatmask = 0xFC0; - nflatxshift = 26; - nflatyshift = 20; - nflatshiftup = 10; + ds->nflatmask = 0xFC0; + ds->nflatxshift = 26; + ds->nflatyshift = 20; + ds->nflatshiftup = 10; break; } xoffs = pl->xoffs; yoffs = pl->yoffs; - planeheight = abs(pl->height - pl->viewz); + ds->planeheight = abs(pl->height - pl->viewz); if (light >= LIGHTLEVELS) light = LIGHTLEVELS-1; @@ -1033,7 +1028,7 @@ void R_DrawSinglePlane(visplane_t *pl) float fudgecanyon = 0; fixed_t temp; // Okay, look, don't ask me why this works, but without this setup there's a disgusting-looking misalignment with the textures. -fickle - fudgecanyon = ((1<nflatshiftup)+1.0f)/(1<nflatshiftup); angle_t hack = (pl->plangle & (ANGLE_90-1)); @@ -1055,7 +1050,7 @@ void R_DrawSinglePlane(visplane_t *pl) const fixed_t cosinecomponent = FINECOSINE(hack>>ANGLETOFINESHIFT); const fixed_t sinecomponent = FINESINE(hack>>ANGLETOFINESHIFT); - const fixed_t modmask = ((1 << (32-nflatshiftup)) - 1); + const fixed_t modmask = ((1 << (32-ds->nflatshiftup)) - 1); fixed_t ox = (FixedMul(pl->slope->o.x,cosinecomponent) & modmask) - (FixedMul(pl->slope->o.y,sinecomponent) & modmask); fixed_t oy = (-FixedMul(pl->slope->o.x,sinecomponent) & modmask) - (FixedMul(pl->slope->o.y,cosinecomponent) & modmask); @@ -1079,16 +1074,16 @@ void R_DrawSinglePlane(visplane_t *pl) } else { - xoffs &= ((1 << (32-nflatshiftup))-1); - yoffs &= ((1 << (32-nflatshiftup))-1); - xoffs -= (pl->slope->o.x + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); - yoffs += (pl->slope->o.y + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); + xoffs &= ((1 << (32-ds->nflatshiftup))-1); + yoffs &= ((1 << (32-ds->nflatshiftup))-1); + xoffs -= (pl->slope->o.x + (1 << (31-ds->nflatshiftup))) & ~((1 << (32-ds->nflatshiftup))-1); + yoffs += (pl->slope->o.y + (1 << (31-ds->nflatshiftup))) & ~((1 << (32-ds->nflatshiftup))-1); } xoffs = (fixed_t)(xoffs*fudgecanyon); yoffs = (fixed_t)(yoffs/fudgecanyon); - if (planeripple.active) + if (ds->planeripple.active) { fixed_t plheight = abs(P_GetSlopeZAt(pl->slope, pl->viewx, pl->viewy) - pl->viewz); @@ -1096,12 +1091,12 @@ void R_DrawSinglePlane(visplane_t *pl) for (x = pl->high; x < pl->low; x++) { - R_CalculatePlaneRipple(pl, x, plheight, true); - R_SetSlopePlaneVectors(pl, x, (xoffs + planeripple.xfrac), (yoffs + planeripple.yfrac), fudgecanyon); + R_CalculatePlaneRipple(ds, pl, x, plheight, true); + R_SetSlopePlaneVectors(ds, pl, x, (xoffs + ds->planeripple.xfrac), (yoffs + ds->planeripple.yfrac), fudgecanyon); } } else - R_SetSlopePlaneVectors(pl, 0, xoffs, yoffs, fudgecanyon); + R_SetSlopePlaneVectors(ds, pl, 0, xoffs, yoffs, fudgecanyon); if (spanfunc == R_DrawTranslucentWaterSpan) spanfunc = R_DrawTiltedTranslucentWaterSpan; @@ -1112,10 +1107,10 @@ void R_DrawSinglePlane(visplane_t *pl) else spanfunc = R_DrawTiltedSpan; - planezlight = scalelight[light]; + ds->planezlight = scalelight[light]; } else - planezlight = zlight[light]; + ds->planezlight = zlight[light]; // set the maximum value for unsigned pl->top[pl->maxx+1] = 0xffff; @@ -1135,8 +1130,7 @@ void R_DrawSinglePlane(visplane_t *pl) for (x = pl->minx; x <= stop; x++) { - R_MakeSpans(x, pl->top[x-1], pl->bottom[x-1], - pl->top[x], pl->bottom[x]); + R_MakeSpans(ds, x, pl->top[x-1], pl->bottom[x-1], pl->top[x], pl->bottom[x]); } /* @@ -1210,7 +1204,7 @@ using the palette colors. } #endif - Z_ChangeTag(ds_source, PU_CACHE); + Z_ChangeTag(ds->source, PU_CACHE); } void R_PlaneBounds(visplane_t *plane) diff --git a/src/r_plane.h b/src/r_plane.h index 2cb01a1c8..d840523e6 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -68,16 +68,13 @@ extern fixed_t *frontscale, *yslopetab; extern fixed_t basexscale, baseyscale; extern fixed_t *yslope; -extern lighttable_t **planezlight; void R_AllocPlaneMemory(void); void R_ClearPlanes(void); void R_ClearFFloorClips (void); -void R_MapPlane(INT32 y, INT32 x1, INT32 x2); -void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2); void R_DrawPlanes(void); -void R_CalculateSlopeVectors(pslope_t *slope, fixed_t planeviewx, fixed_t planeviewy, fixed_t planeviewz, fixed_t planexscale, fixed_t planeyscale, fixed_t planexoffset, fixed_t planeyoffset, angle_t planeviewangle, angle_t planeangle, float fudge); + visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, fixed_t xoff, fixed_t yoff, angle_t plangle, extracolormap_t *planecolormap, ffloor_t *ffloor , polyobj_t *polyobj @@ -88,9 +85,6 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop); void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop); void R_PlaneBounds(visplane_t *plane); -// Draws a single visplane. -void R_DrawSinglePlane(visplane_t *pl); - typedef struct planemgr_s { visplane_t *plane; diff --git a/src/r_things.c b/src/r_things.c index 0bc06f951..d1138a111 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2944,10 +2944,11 @@ void R_DrawMasked(void) for (r2 = nodehead.next; r2 != &nodehead; r2 = r2->next) { + drawspandata_t ds = {0}; if (r2->plane) { next = r2->prev; - R_DrawSinglePlane(r2->plane); + R_DrawSinglePlane(&ds, r2->plane); R_DoneWithNode(r2); r2 = next; } @@ -2972,9 +2973,13 @@ void R_DrawMasked(void) // Tails 08-18-2002 if (r2->sprite->precip == true) + { R_DrawPrecipitationSprite(r2->sprite); + } else + { R_DrawSprite(r2->sprite); + } R_DoneWithNode(r2); r2 = next; diff --git a/src/screen.c b/src/screen.c index d781c9199..d226ca423 100644 --- a/src/screen.c +++ b/src/screen.c @@ -33,28 +33,6 @@ // SRB2Kart #include "r_fps.h" // R_GetFramerateCap -// -------------------------------------------- -// assembly or c drawer routines for 8bpp/16bpp -// -------------------------------------------- -void (*wallcolfunc)(drawcolumndata_t*); // new wall column drawer to draw posts >128 high -void (*colfunc)(drawcolumndata_t*); // standard column, up to 128 high posts - -void (*basecolfunc)(drawcolumndata_t*); -void (*fuzzcolfunc)(drawcolumndata_t*); // standard fuzzy effect column drawer -void (*transcolfunc)(drawcolumndata_t*); // translation column drawer -void (*shadecolfunc)(drawcolumndata_t*); // smokie test.. - -void (*transtransfunc)(drawcolumndata_t*); // translucent translated column drawer -void (*twosmultipatchfunc)(drawcolumndata_t*); // for cols with transparent pixels -void (*twosmultipatchtransfunc)(drawcolumndata_t*); // for cols with transparent pixels AND translucency - -// Short and Tall sky drawer, for the current color mode -void (*walldrawerfunc)(drawcolumndata_t*); - -void (*spanfunc)(void); // span drawer, use a 64x64 tile -void (*splatfunc)(void); // span drawer w/ transparency -void (*basespanfunc)(void); // default span func for color mode - // ------------------ // global video state // ------------------ diff --git a/src/screen.h b/src/screen.h index 414ba7195..51d05111c 100644 --- a/src/screen.h +++ b/src/screen.h @@ -78,13 +78,6 @@ enum VID_GL_LIBRARY_ERROR = -1, }; -// --------------------------------------------- -// color mode dependent drawer function pointers -// --------------------------------------------- -extern void (*spanfunc)(void); -extern void (*basespanfunc)(void); -extern void (*splatfunc)(void); - // ---------------- // screen variables // ---------------- -- 2.54.0 From 99186a86db66eaad4de6cf5ec8539f02023ab677 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 5 Jun 2025 14:22:13 +0200 Subject: [PATCH 017/141] port masked drawlists for software + portal visplanes Note: need to check if we gotta readd portalcullsector for ogl portals, technically this is alot faster and fixes the occasional portal disappearing, but may introduce occasional visual bugs --- src/hardware/hw_main.c | 11 --- src/hardware/hw_portal.c | 4 -- src/r_bsp.c | 9 +-- src/r_bsp.h | 1 + src/r_main.c | 54 +++++++++++--- src/r_plane.c | 4 +- src/r_plane.h | 2 + src/r_portal.c | 150 ++++++++++++++++++++++++++++++++++++++- src/r_portal.h | 8 ++- src/r_segs.c | 4 +- src/r_things.c | 99 ++++++++++++++++---------- src/r_things.h | 17 ++++- 12 files changed, 281 insertions(+), 82 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 43cb25aed..e61580777 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3233,17 +3233,6 @@ static void HWR_RenderPortalBSPNode(INT32 bspnum) bspnum = bsp->children[side^1]; } - // PORTAL CULLING - if (portalcullsector) - { - // skip all subsectors encountered before the portal - // destination's front sector - if (portalcullsector != subsectors[bspnum & ~NF_SUBSECTOR].sector) - return; - else - portalcullsector = NULL; - } - // e6y: support for extended nodes HWR_Subsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR); } diff --git a/src/hardware/hw_portal.c b/src/hardware/hw_portal.c index 9bb5af40f..53d6f57e3 100644 --- a/src/hardware/hw_portal.c +++ b/src/hardware/hw_portal.c @@ -62,8 +62,6 @@ static gl_portal_t* HWR_Portal_Add (seg_t *seg) void HWR_FreePortalList(gl_portallist_t freelist) { - portalcullsector = NULL; - // free memory from portal list allocated by calls to Add2Lines gl_portal_t *gl_portal_temp = freelist.base; while (gl_portal_temp) @@ -125,13 +123,11 @@ void HWR_PortalFrame(gl_portal_t* portal) if (portal->clipline != -1) { portalclipline = &lines[portal->clipline]; - portalcullsector = portalclipline->frontsector; viewsector = portalclipline->frontsector; } else { portalclipline = NULL; - portalcullsector = NULL; viewsector = R_PointInSubsector(viewx, viewy)->sector; } } diff --git a/src/r_bsp.c b/src/r_bsp.c index e5b82a151..0dfba63e1 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -35,6 +35,7 @@ sector_t *backsector; // very ugly realloc() of drawsegs at run-time, I upped it to 512 // instead of 256.. and someone managed to send me a level with // 896 drawsegs! So too bad here's a limit removal a-la-Boom +drawseg_t *curdrawsegs = NULL; /**< This is used to handle multiple lists for masked drawsegs. */ drawseg_t *drawsegs = NULL; drawseg_t *ds_p = NULL; @@ -1201,13 +1202,5 @@ void R_RenderBSPNode(INT32 bspnum) bspnum = bsp->children[side^1]; } - // PORTAL CULLING - if (portalcullsector) - { - if (subsectors[bspnum & ~NF_SUBSECTOR].sector != portalcullsector) - return; - portalcullsector = NULL; - } - R_Subsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR); } diff --git a/src/r_bsp.h b/src/r_bsp.h index b5eb6b6cc..167f3311f 100644 --- a/src/r_bsp.h +++ b/src/r_bsp.h @@ -32,6 +32,7 @@ extern portal_t *g_portal; // is curline a portal seg? extern INT32 checkcoord[12][4]; +extern drawseg_t *curdrawsegs; extern drawseg_t *drawsegs; extern drawseg_t *ds_p; extern INT32 doorclosed; diff --git a/src/r_main.c b/src/r_main.c index 28c372d5b..37371d4df 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1281,21 +1281,47 @@ static void R_PortalFrame(portal_t *portal) if (portal->clipline != -1) { portalclipline = &lines[portal->clipline]; - portalcullsector = portalclipline->frontsector; viewsector = portalclipline->frontsector; } else { portalclipline = NULL; - portalcullsector = NULL; viewsector = R_PointInSubsector(viewx, viewy)->sector; } } +static void Mask_Pre (maskcount_t* m) +{ + m->drawsegs[0] = ds_p - drawsegs; + m->vissprites[0] = visspritecount; + m->viewx = viewx; + m->viewy = viewy; + m->viewz = viewz; + m->viewsector = viewsector; +} + +static void Mask_Post (maskcount_t* m) +{ + m->drawsegs[1] = ds_p - drawsegs; + m->vissprites[1] = visspritecount; +} + // ================ // R_RenderView // ================ +// viewx, viewy, viewangle, all that good stuff must be set +static void R_RenderViewpoint(maskcount_t* mask) +{ + Mask_Pre(mask); + + curdrawsegs = ds_p; + + R_RenderBSPNode((INT32)numnodes - 1); + + Mask_Post(mask); +} + // FAB NOTE FOR WIN32 PORT !! I'm not finished already, // but I suspect network may have problems with the video buffer being locked // for all duration of rendering, and being released only once at the end.. @@ -1306,6 +1332,8 @@ static fixed_t viewfov[MAXSPLITSCREENPLAYERS]; void R_RenderPlayerView(player_t *player) { + UINT8 nummasks = 1; + maskcount_t* masks = malloc(sizeof(maskcount_t)); const boolean skybox = (skyboxmo[0] && cv_skybox.value); UINT8 i; @@ -1369,13 +1397,14 @@ void R_RenderPlayerView(player_t *player) R_ClearVisibleFloorSplats(); #endif - R_RenderBSPNode((INT32)numnodes - 1); + R_RenderViewpoint(&masks[nummasks - 1]); + R_ClipSprites(); R_DrawPlanes(); #ifdef FLOORSPLATS R_DrawVisibleFloorSplats(); #endif - R_DrawMasked(); + R_DrawMasked(masks, nummasks); } PS_STOP_TIMING(ps_skyboxtime); @@ -1410,10 +1439,11 @@ void R_RenderPlayerView(player_t *player) NetUpdate(); // The head node is the last node output. + //masks = realloc(masks, (++nummasks)*sizeof(maskcount_t)); ps_numbspcalls.value.i = ps_numpolyobjects.value.i = ps_numdrawnodes.value.i = 0; PS_START_TIMING(ps_bsptime); - R_RenderBSPNode((INT32)numnodes - 1); + R_RenderViewpoint(&masks[nummasks - 1]); PS_STOP_TIMING(ps_bsptime); R_AddPrecipitationSprites(); PS_START_TIMING(ps_sw_spritecliptime); @@ -1446,14 +1476,18 @@ void R_RenderPlayerView(player_t *player) // that were previously stored. Portal_ClipApply(portal); + validcount++; + + // Render the BSP from the new viewpoint, and clip + masks = realloc(masks, (++nummasks)*sizeof(maskcount_t)); + // Render the BSP from the new viewpoint, and clip // any sprites with the new clipsegs and window. - R_RenderBSPNode((INT32)numnodes - 1); + R_RenderViewpoint(&masks[nummasks - 1]); + R_ClipSprites(); Portal_Remove(portal); - - validcount++; } } PS_STOP_TIMING(ps_sw_portaltime); @@ -1467,9 +1501,11 @@ void R_RenderPlayerView(player_t *player) // draw mid texture and sprite // And now 3D floors/sides! PS_START_TIMING(ps_sw_maskedtime); - R_DrawMasked(); + R_DrawMasked(masks, nummasks); PS_STOP_TIMING(ps_sw_maskedtime); + free(masks); + // Check for new console commands. NetUpdate(); diff --git a/src/r_plane.c b/src/r_plane.c index 99e6dde6a..d5faa122b 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -40,7 +40,7 @@ // good night sweet prince //#define SHITPLANESPARENCY -static visplane_t *visplanes[MAXVISPLANES]; +visplane_t *visplanes[MAXVISPLANES]; static visplane_t *freetail; static visplane_t **freehead = &freetail; @@ -368,8 +368,6 @@ void R_ClearPlanes(void) freehead = &(*freehead)->next; } - numffloors = 0; - lastopening = openings; // left to right mapping diff --git a/src/r_plane.h b/src/r_plane.h index d840523e6..dbaaac306 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -56,6 +56,8 @@ typedef struct visplane_s boolean noencore; } visplane_t; +extern visplane_t *visplanes[MAXVISPLANES]; + extern visplane_t *floorplane; extern visplane_t *ceilingplane; diff --git a/src/r_portal.c b/src/r_portal.c index afbcd46dd..e5a431c6e 100644 --- a/src/r_portal.c +++ b/src/r_portal.c @@ -14,7 +14,9 @@ #include "r_portal.h" #include "r_plane.h" -#include "r_main.h" // viewheight, viewwidth +#include "r_main.h" +#include "doomstat.h" +#include "p_spec.h" // Skybox viewpoints #include "z_zone.h" #include "r_things.h" #include "r_sky.h" @@ -25,7 +27,6 @@ UINT8 portalrender; /**< When rendering a portal, it establishes the depth of portal_t *portal_base, *portal_cap; line_t *portalclipline; -sector_t *portalcullsector; INT32 portalclipstart, portalclipend; portal_t *g_portal; // is curline a portal seg? @@ -133,7 +134,6 @@ static portal_t* Portal_Add (const INT16 x1, const INT16 x2) void Portal_Remove (portal_t* portal) { - portalcullsector = NULL; portal_base = portal->next; Z_Free(portal->ceilingclip); Z_Free(portal->floorclip); @@ -190,4 +190,148 @@ void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, con g_portal = portal; // this tells R_StoreWallRange that curline is a portal seg } +/** Store the clipping window for a portal using a visplane. + * + * Since visplanes top/bottom windows work in an identical way, + * it can just be copied almost directly. + */ +static void Portal_ClipVisplane (const visplane_t* plane, portal_t* portal) +{ + INT16 start = portal->start; + INT16 end = portal->end; + INT32 i; + + for (i = 0; i < end - start; i++) + { + // Invalid column. + if (plane->top[i + start] == 65535) + { + portal->ceilingclip[i] = -1; + portal->floorclip[i] = -1; + continue; + } + portal->ceilingclip[i] = plane->top[i + start] - 1; + portal->floorclip[i] = plane->bottom[i + start] + 1; + portal->frontscale[i] = INT32_MAX; + } +} + +extern INT32 viewwidth; + +static boolean TrimVisplaneBounds (const visplane_t* plane, INT16* start, INT16* end) +{ + *start = plane->minx; + *end = plane->maxx + 1; + + // Visplanes have 1-px pads on their sides (extra columns). + // Trim them, else it may render out of bounds. + if (*end > viewwidth) + *end = viewwidth; + + if (!(*start < *end)) + return true; + + + /** Trims a visplane's horizontal gap to match its render area. + * + * Visplanes' minx/maxx may sometimes exceed the area they're + * covering. This merely adjusts the boundaries to the next + * valid area. + */ + + while (plane->bottom[*start] == 0 && plane->top[*start] == 65535 && *start < *end) + { + (*start)++; + } + + + while (plane->bottom[*end - 1] == 0 && plane->top[*start] == 65535 && *end > *start) + { + (*end)--; + } + + return false; +} + +/** Creates a skybox portal out of a visplane. + * + * Applies the necessary offsets and rotation to give + * a depth illusion to the skybox. + */ +void Portal_AddSkybox(const visplane_t* plane) +{ + INT16 start, end; + mapheader_t *mh; + portal_t* portal; + + if (TrimVisplaneBounds(plane, &start, &end)) + return; + + portal = Portal_Add(start, end); + + Portal_ClipVisplane(plane, portal); + + portal->viewx = skyboxmo[0]->x; + portal->viewy = skyboxmo[0]->y; + portal->viewz = skyboxmo[0]->z; + portal->viewangle = viewangle + skyboxmo[0]->angle; + + mh = mapheaderinfo[gamemap-1]; + + // If a relative viewpoint exists, offset the viewpoint. + if (skyboxmo[1]) + { + fixed_t x = 0, y = 0; + angle_t ang = skyboxmo[0]->angle>>ANGLETOFINESHIFT; + + if (mh->skybox_scalex > 0) + x = (viewx - skyboxmo[1]->x) / mh->skybox_scalex; + else if (mh->skybox_scalex < 0) + x = (viewx - skyboxmo[1]->x) * -mh->skybox_scalex; + + if (mh->skybox_scaley > 0) + y = (viewy - skyboxmo[1]->y) / mh->skybox_scaley; + else if (mh->skybox_scaley < 0) + y = (viewy - skyboxmo[1]->y) * -mh->skybox_scaley; + + // Apply transform to account for the skybox viewport angle. + portal->viewx += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang)); + portal->viewy += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang)); + } + + if (mh->skybox_scalez > 0) + portal->viewz += viewz / mh->skybox_scalez; + else if (mh->skybox_scalez < 0) + portal->viewz += viewz * -mh->skybox_scalez; + + portal->clipline = -1; +} + +/** Creates portals for the currently existing sky visplanes. + * The visplanes are also removed and cleared from the list. + */ +void Portal_AddSkyboxPortals(void) +{ + visplane_t *pl; + INT32 i; + UINT16 count = 0; + + for (i = 0; i < MAXVISPLANES; i++, pl++) + { + for (pl = visplanes[i]; pl; pl = pl->next) + { + if (pl->picnum == skyflatnum) + { + Portal_AddSkybox(pl); + + pl->minx = 0; + pl->maxx = -1; + + count++; + } + } + } + + CONS_Debug(DBG_RENDER, "Skybox portals: %d\n", count); +} diff --git a/src/r_portal.h b/src/r_portal.h index c944f46d0..b45631e0b 100644 --- a/src/r_portal.h +++ b/src/r_portal.h @@ -15,9 +15,9 @@ #define __R_PORTAL__ #include "r_data.h" +#include "r_plane.h" // visplanes - -/** Portal structure. +/** Portal structure for the software renderer. */ typedef struct portal_s { @@ -45,7 +45,6 @@ extern portal_t* portal_cap; extern UINT8 portalrender; extern line_t *portalclipline; -extern sector_t *portalcullsector; extern INT32 portalclipstart, portalclipend; void Portal_InitList (void); @@ -54,4 +53,7 @@ void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, con void Portal_ClipApply (const portal_t* portal); +void Portal_AddSkybox(const visplane_t* plane); +void Portal_AddSkyboxPortals(void); + #endif diff --git a/src/r_segs.c b/src/r_segs.c index 2ed0b5b80..3e36db3de 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -1650,6 +1650,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (ds_p == drawsegs+maxdrawsegs) { + size_t curpos = curdrawsegs - drawsegs; size_t pos = ds_p - drawsegs; size_t newmax = maxdrawsegs ? maxdrawsegs*2 : 128; @@ -1661,6 +1662,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) ds_p = drawsegs + pos; maxdrawsegs = newmax; + curdrawsegs = drawsegs + curpos; if (firstseg) firstseg = drawsegs + (size_t)firstseg; @@ -1716,7 +1718,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) // borrowed fix from *cough* zdoom *cough* // [RH] We also need to adjust the openings pointers that // were already stored in drawsegs. - for (ds = drawsegs; ds < ds_p; ds++) + for (ds = curdrawsegs; ds < ds_p; ds++) { #define ADJUST(p) if (ds->p + ds->x1 >= oldopenings && ds->p + ds->x1 <= oldlast) ds->p = ds->p - oldopenings + openings; ADJUST(maskedtexturecol); diff --git a/src/r_things.c b/src/r_things.c index d1138a111..88433c793 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2137,9 +2137,7 @@ void R_AddPrecipitationSprites(void) // // R_SortVisSprites // -static vissprite_t vsprsortedhead; - -void R_SortVisSprites(void) +static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 end) { UINT32 i; vissprite_t *ds, *dsprev, *dsnext, *dsfirst; @@ -2148,20 +2146,17 @@ void R_SortVisSprites(void) fixed_t bestscale; INT32 bestdispoffset; - if (!visspritecount) - return; - unsorted.next = unsorted.prev = &unsorted; - dsfirst = R_GetVisSprite(0); + dsfirst = R_GetVisSprite(start); // The first's prev and last's next will be set to // nonsense, but are fixed in a moment - for (i = 0, dsnext = dsfirst, ds = NULL; i < visspritecount; i++) + for (i = start, dsnext = dsfirst, ds = NULL; i < end; i++) { dsprev = ds; ds = dsnext; - if (i < visspritecount - 1) dsnext = R_GetVisSprite(i + 1); + if (i < end - 1) dsnext = R_GetVisSprite(i + 1); ds->next = dsnext; ds->prev = dsprev; @@ -2175,8 +2170,8 @@ void R_SortVisSprites(void) unsorted.prev = ds; // pull the vissprites out by scale - vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead; - for (i = 0; i < visspritecount; i++) + vsprsortedhead->next = vsprsortedhead->prev = vsprsortedhead; + for (i = start; i < end; i++) { bestscale = bestdispoffset = INT32_MAX; for (ds = unsorted.next; ds != &unsorted; ds = ds->next) @@ -2206,10 +2201,10 @@ void R_SortVisSprites(void) { best->next->prev = best->prev; best->prev->next = best->next; - best->next = &vsprsortedhead; - best->prev = vsprsortedhead.prev; - vsprsortedhead.prev->next = best; - vsprsortedhead.prev = best; + best->next = vsprsortedhead; + best->prev = vsprsortedhead->prev; + vsprsortedhead->prev->next = best; + vsprsortedhead->prev = best; } } } @@ -2220,28 +2215,28 @@ void R_SortVisSprites(void) static drawnode_t *R_CreateDrawNode(drawnode_t *link); static drawnode_t nodebankhead; -static drawnode_t nodehead; -static void R_CreateDrawNodes(void) +static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean tempskip) { drawnode_t *entry; drawseg_t *ds; INT32 i, p, best, x1, x2; fixed_t bestdelta, delta; vissprite_t *rover; + static vissprite_t vsprsortedhead; drawnode_t *r2; visplane_t *plane; INT32 sintersect; fixed_t scale = 0; // Add the 3D floors, thicksides, and masked textures... - for (ds = ds_p; ds-- > drawsegs ;) + for (ds = drawsegs + mask->drawsegs[1]; ds-- > drawsegs + mask->drawsegs[0];) { if (ds->numthicksides) { for (i = 0; i < ds->numthicksides; i++) { - entry = R_CreateDrawNode(&nodehead); + entry = R_CreateDrawNode(head); entry->thickseg = ds; entry->ffloor = ds->thicksides[i]; } @@ -2257,7 +2252,7 @@ static void R_CreateDrawNodes(void) else { // Put it in! - entry = R_CreateDrawNode(&nodehead); + entry = R_CreateDrawNode(head); entry->plane = plane; entry->seg = ds; } @@ -2265,7 +2260,7 @@ static void R_CreateDrawNodes(void) } if (ds->maskedtexturecol) { - entry = R_CreateDrawNode(&nodehead); + entry = R_CreateDrawNode(head); entry->seg = ds; } if (ds->numffloorplanes) @@ -2297,7 +2292,7 @@ static void R_CreateDrawNodes(void) } if (best != -1) { - entry = R_CreateDrawNode(&nodehead); + entry = R_CreateDrawNode(head); entry->plane = ds->ffloorplanes[best]; entry->seg = ds; ds->ffloorplanes[best] = NULL; @@ -2308,6 +2303,9 @@ static void R_CreateDrawNodes(void) } } + if (tempskip) + return; + // find all the remaining polyobject planes and add them on the end of the list // probably this is a terrible idea if we wanted them to be sorted properly // but it works getting them in for now @@ -2325,16 +2323,17 @@ static void R_CreateDrawNodes(void) continue; } - entry = R_CreateDrawNode(&nodehead); + entry = R_CreateDrawNode(head); entry->plane = plane; // note: no seg is set, for what should be obvious reasons PolyObjects[i].visplane = NULL; } - if (visspritecount == 0) + // No vissprites in this mask? + if (mask->vissprites[1] - mask->vissprites[0] == 0) return; - R_SortVisSprites(); + R_SortVisSprites(&vsprsortedhead, mask->vissprites[0], mask->vissprites[1]); for (rover = vsprsortedhead.prev; rover != &vsprsortedhead; rover = rover->prev) { @@ -2343,7 +2342,7 @@ static void R_CreateDrawNodes(void) sintersect = (rover->x1 + rover->x2) / 2; - for (r2 = nodehead.next; r2 != &nodehead; r2 = r2->next) + for (r2 = head->next; r2 != head; r2 = r2->next) { if (r2->plane) { @@ -2469,9 +2468,9 @@ static void R_CreateDrawNodes(void) } } } - if (r2 == &nodehead) + if (r2 == head) { - entry = R_CreateDrawNode(&nodehead); + entry = R_CreateDrawNode(head); entry->sprite = rover; } } @@ -2515,25 +2514,24 @@ static void R_DoneWithNode(drawnode_t *node) (node->prev = &nodebankhead)->next = node; } -static void R_ClearDrawNodes(void) +static void R_ClearDrawNodes(drawnode_t* head) { drawnode_t *rover; drawnode_t *next; - for (rover = nodehead.next; rover != &nodehead ;) + for (rover = head->next; rover != head;) { next = rover->next; R_DoneWithNode(rover); rover = next; } - nodehead.next = nodehead.prev = &nodehead; + head->next = head->prev = head; } void R_InitDrawNodes(void) { nodebankhead.next = nodebankhead.prev = &nodebankhead; - nodehead.next = nodehead.prev = &nodehead; } // @@ -2935,14 +2933,12 @@ boolean R_ThingIsFullDark(mobj_t *thing) // // R_DrawMasked // -void R_DrawMasked(void) +static void R_DrawMaskedList (drawnode_t* head) { drawnode_t *r2; drawnode_t *next; - R_CreateDrawNodes(); - - for (r2 = nodehead.next; r2 != &nodehead; r2 = r2->next) + for (r2 = head->next; r2 != head; r2 = r2->next) { drawspandata_t ds = {0}; if (r2->plane) @@ -2985,7 +2981,36 @@ void R_DrawMasked(void) r2 = next; } } - R_ClearDrawNodes(); +} + +void R_DrawMasked(maskcount_t* masks, UINT8 nummasks) +{ + drawnode_t heads[nummasks]; /**< Drawnode lists; as many as number of views/portals. */ + UINT8 i; + + for (i = 0; i < nummasks; i++) + { + heads[i].next = heads[i].prev = &heads[i]; + + viewx = masks[i].viewx; + viewy = masks[i].viewy; + viewz = masks[i].viewz; + viewsector = masks[i].viewsector; + + + R_CreateDrawNodes(&masks[i], &heads[i], false); + } + + for (; nummasks > 0; nummasks--) + { + viewx = masks[nummasks - 1].viewx; + viewy = masks[nummasks - 1].viewy; + viewz = masks[nummasks - 1].viewz; + viewsector = masks[nummasks - 1].viewsector; + + R_DrawMaskedList(&heads[nummasks - 1]); + R_ClearDrawNodes(&heads[nummasks - 1]); + } } // ========================================================================== diff --git a/src/r_things.h b/src/r_things.h index ca09b036a..79d4dea11 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -62,8 +62,6 @@ fixed_t R_GetSpriteDirectionalLighting(angle_t angle); fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope); -void R_SortVisSprites(void); - //faB: find sprites in wadfile, replace existing, add new ones // (only sprites from namelist are added or replaced) void R_AddSpriteDefs(UINT16 wadnum); @@ -73,7 +71,20 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel); void R_AddPrecipitationSprites(void); void R_InitSprites(void); void R_ClearSprites(void); -void R_DrawMasked(void); + +/** Used to count the amount of masked elements + * per portal to later group them in separate + * drawnode lists. + */ +typedef struct +{ + size_t drawsegs[2]; + size_t vissprites[2]; + fixed_t viewx, viewy, viewz; /**< View z stored at the time of the BSP traversal for the view/portal. Masked sorting/drawing needs it. */ + sector_t* viewsector; +} maskcount_t; + +void R_DrawMasked(maskcount_t* masks, UINT8 nummasks); boolean R_ThingVisible (mobj_t *thing); boolean R_ThingWithinDist (mobj_t *thing, INT32 limit_dist); -- 2.54.0 From 8a6f4db9afac93db67e8a4646965b147cc1fea4c Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 5 Jun 2025 14:31:40 +0200 Subject: [PATCH 018/141] fix precip not drawing --- src/r_main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/r_main.c b/src/r_main.c index 37371d4df..c9e2cc6cd 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1319,6 +1319,8 @@ static void R_RenderViewpoint(maskcount_t* mask) R_RenderBSPNode((INT32)numnodes - 1); + R_AddPrecipitationSprites(); + Mask_Post(mask); } @@ -1445,7 +1447,7 @@ void R_RenderPlayerView(player_t *player) PS_START_TIMING(ps_bsptime); R_RenderViewpoint(&masks[nummasks - 1]); PS_STOP_TIMING(ps_bsptime); - R_AddPrecipitationSprites(); + PS_START_TIMING(ps_sw_spritecliptime); R_ClipSprites(); PS_STOP_TIMING(ps_sw_spritecliptime); -- 2.54.0 From 8c290d7597dcc110164b004132e257225bebf943 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 5 Jun 2025 14:45:37 +0200 Subject: [PATCH 019/141] kill static buffer for tiltlighting, again kinda ugly but gets the job done lel --- src/r_draw_span.c | 40 ++++++++++++++++++++++++++++++++++++---- src/r_main.c | 1 - 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/r_draw_span.c b/src/r_draw_span.c index 5d1a08631..fb332d252 100644 --- a/src/r_draw_span.c +++ b/src/r_draw_span.c @@ -371,7 +371,15 @@ void R_DrawTiltedSpan(drawspandata_t* ds) float endz, endu, endv; UINT32 stepu, stepv; register UINT32 bit; - INT32 tiltlighting[MAXVIDWIDTH]; // TODO: get rid of static buffer + static INT32 *tiltlighting = NULL; + static INT32 oldviewwidth = 0; + + // dont realloc every frame pls thx + if (tiltlighting == NULL || oldviewwidth != viewwidth) + { + tiltlighting = Z_Realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth, PU_STATIC, NULL); + oldviewwidth = viewwidth; + } iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); @@ -510,7 +518,15 @@ void R_DrawTiltedTranslucentSpan(drawspandata_t* ds) float endz, endu, endv; UINT32 stepu, stepv; register UINT32 bit; - INT32 tiltlighting[MAXVIDWIDTH]; + static INT32 *tiltlighting = NULL; + static INT32 oldviewwidth = 0; + + // dont realloc every frame pls thx + if (tiltlighting == NULL || oldviewwidth != viewwidth) + { + tiltlighting = Z_Realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth, PU_STATIC, NULL); + oldviewwidth = viewwidth; + } iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); @@ -650,7 +666,15 @@ void R_DrawTiltedTranslucentWaterSpan(drawspandata_t* ds) float endz, endu, endv; UINT32 stepu, stepv; register UINT32 bit; - INT32 tiltlighting[MAXVIDWIDTH]; + static INT32 *tiltlighting = NULL; + static INT32 oldviewwidth = 0; + + // dont realloc every frame pls thx + if (tiltlighting == NULL || oldviewwidth != viewwidth) + { + tiltlighting = Z_Realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth, PU_STATIC, NULL); + oldviewwidth = viewwidth; + } iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); @@ -790,7 +814,15 @@ void R_DrawTiltedSplat(drawspandata_t* ds) float endz, endu, endv; UINT32 stepu, stepv; register UINT32 bit; - INT32 tiltlighting[MAXVIDWIDTH]; + static INT32 *tiltlighting = NULL; + static INT32 oldviewwidth = 0; + + // dont realloc every frame pls thx + if (tiltlighting == NULL || oldviewwidth != viewwidth) + { + tiltlighting = Z_Realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth, PU_STATIC, NULL); + oldviewwidth = viewwidth; + } iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); diff --git a/src/r_main.c b/src/r_main.c index c9e2cc6cd..dcfa5809e 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1447,7 +1447,6 @@ void R_RenderPlayerView(player_t *player) PS_START_TIMING(ps_bsptime); R_RenderViewpoint(&masks[nummasks - 1]); PS_STOP_TIMING(ps_bsptime); - PS_START_TIMING(ps_sw_spritecliptime); R_ClipSprites(); PS_STOP_TIMING(ps_sw_spritecliptime); -- 2.54.0 From 095842f4aa12498b4aadacbfc582bb4411cdd2eb Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 5 Jun 2025 15:00:16 +0200 Subject: [PATCH 020/141] smol cleanup the splat drawers didnt knew we actually use em so kinda didnt care lel --- src/r_draw_span.c | 52 ++++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/src/r_draw_span.c b/src/r_draw_span.c index fb332d252..50612dc22 100644 --- a/src/r_draw_span.c +++ b/src/r_draw_span.c @@ -963,19 +963,22 @@ void R_DrawTiltedSplat(drawspandata_t* ds) */ void R_DrawSplat(drawspandata_t* ds) { - UINT32 xposition; - UINT32 yposition; - UINT32 xstep, ystep; + uintptr_t xposition; + uintptr_t yposition; + uintptr_t xstep, ystep; register UINT32 bit; - UINT8 *source; - UINT8 *colormap; - register UINT8 *dest; + UINT8 *restrict source = ds->source; + UINT8 *restrict colormap = ds->colormap; + UINT8 *restrict dest = R_Address(ds->x1, ds->y); - register size_t count; + register intptr_t count = (ds->x2 - ds->x1 + 1); size_t i; UINT32 val; + xposition = ds->xfrac; yposition = ds->yfrac; + xstep = ds->xstep; ystep = ds->ystep; + // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest // can be used for the fraction part. This allows calculation of the memory address in the // texture with two shifts, an OR and one AND. (see below) @@ -983,13 +986,8 @@ void R_DrawSplat(drawspandata_t* ds) // bit per power of two (obviously) // Ok, because I was able to eliminate the variable spot below, this function is now FASTER // than the original span renderer. Whodathunkit? - xposition = ds->xfrac << ds->nflatshiftup; yposition = ds->yfrac << ds->nflatshiftup; - xstep = ds->xstep << ds->nflatshiftup; ystep = ds->ystep << ds->nflatshiftup; - - source = ds->source; - colormap = ds->colormap; - dest = R_Address(ds->x1, ds->y); - count = ds->x2 - ds->x1 + 1; + xposition <<= ds->nflatshiftup; yposition <<= ds->nflatshiftup; + xstep <<= ds->nflatshiftup; ystep <<= ds->nflatshiftup; while (count >= 8) { @@ -1033,19 +1031,22 @@ void R_DrawSplat(drawspandata_t* ds) */ void R_DrawTranslucentSplat(drawspandata_t* ds) { - UINT32 xposition; - UINT32 yposition; - UINT32 xstep, ystep; + uintptr_t xposition; + uintptr_t yposition; + uintptr_t xstep, ystep; register UINT32 bit; - UINT8 *source; - UINT8 *colormap; - register UINT8 *dest; + UINT8 *restrict source = ds->source; + UINT8 *restrict colormap = ds->colormap; + UINT8 *restrict dest = R_Address(ds->x1, ds->y); - register size_t count; + register intptr_t count = (ds->x2 - ds->x1 + 1); size_t i; UINT8 val; + xposition = ds->xfrac; yposition = ds->yfrac; + xstep = ds->xstep; ystep = ds->ystep; + // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest // can be used for the fraction part. This allows calculation of the memory address in the // texture with two shifts, an OR and one AND. (see below) @@ -1053,13 +1054,8 @@ void R_DrawTranslucentSplat(drawspandata_t* ds) // bit per power of two (obviously) // Ok, because I was able to eliminate the variable spot below, this function is now FASTER // than the original span renderer. Whodathunkit? - xposition = ds->xfrac << ds->nflatshiftup; yposition = ds->yfrac << ds->nflatshiftup; - xstep = ds->xstep << ds->nflatshiftup; ystep = ds->ystep << ds->nflatshiftup; - - source = ds->source; - colormap = ds->colormap; - dest = R_Address(ds->x1, ds->y); - count = ds->x2 - ds->x1 + 1; + xposition <<= ds->nflatshiftup; yposition <<= ds->nflatshiftup; + xstep <<= ds->nflatshiftup; ystep <<= ds->nflatshiftup; while (count >= 8) { -- 2.54.0 From dbf822ced9c82e7cef618983c2ee892c328e4b5c Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 5 Jun 2025 15:05:20 +0200 Subject: [PATCH 021/141] dont draw precip in the skybox lel --- src/r_main.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/r_main.c b/src/r_main.c index dcfa5809e..a0f6361d6 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1311,7 +1311,7 @@ static void Mask_Post (maskcount_t* m) // ================ // viewx, viewy, viewangle, all that good stuff must be set -static void R_RenderViewpoint(maskcount_t* mask) +static void R_RenderViewpoint(maskcount_t* mask, boolean drawprecip) { Mask_Pre(mask); @@ -1319,7 +1319,8 @@ static void R_RenderViewpoint(maskcount_t* mask) R_RenderBSPNode((INT32)numnodes - 1); - R_AddPrecipitationSprites(); + if (drawprecip) + R_AddPrecipitationSprites(); Mask_Post(mask); } @@ -1399,7 +1400,7 @@ void R_RenderPlayerView(player_t *player) R_ClearVisibleFloorSplats(); #endif - R_RenderViewpoint(&masks[nummasks - 1]); + R_RenderViewpoint(&masks[nummasks - 1], false); R_ClipSprites(); R_DrawPlanes(); @@ -1445,7 +1446,7 @@ void R_RenderPlayerView(player_t *player) ps_numbspcalls.value.i = ps_numpolyobjects.value.i = ps_numdrawnodes.value.i = 0; PS_START_TIMING(ps_bsptime); - R_RenderViewpoint(&masks[nummasks - 1]); + R_RenderViewpoint(&masks[nummasks - 1], true); PS_STOP_TIMING(ps_bsptime); PS_START_TIMING(ps_sw_spritecliptime); R_ClipSprites(); @@ -1484,7 +1485,7 @@ void R_RenderPlayerView(player_t *player) // Render the BSP from the new viewpoint, and clip // any sprites with the new clipsegs and window. - R_RenderViewpoint(&masks[nummasks - 1]); + R_RenderViewpoint(&masks[nummasks - 1], true); R_ClipSprites(); -- 2.54.0 From 9ac6fffd4d4843e864de3b4123abf38caeb6ab65 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 5 Jun 2025 16:53:22 +0200 Subject: [PATCH 022/141] busted ass multithreading for le soft --- src/Makefile | 3 +- src/command.h | 8 + src/core/CMakeLists.txt | 1 + src/core/Sourcefile | 2 + src/core/memory.cpp | 71 +++++++ src/core/memory.h | 32 +++ src/core/spmc_queue.hpp | 192 ++++++++++++++++++ src/core/static_vec.hpp | 255 ++++++++++++++++++++++++ src/core/thread_pool.cpp | 346 +++++++++++++++++++++++++++++++++ src/core/thread_pool.h | 163 ++++++++++++++++ src/cxxutil.hpp | 152 +++++++++++++++ src/d_clisrv.h | 9 + src/d_main.c | 4 + src/d_netcmd.c | 5 - src/d_netcmd.h | 13 ++ src/doomdef.h | 10 + src/doomtype.h | 10 + src/i_system.h | 8 + src/m_argv.h | 8 + src/p_mobj.h | 9 + src/p_setup.h | 8 + src/r_bsp.h | 9 + src/r_data.h | 8 + src/r_draw.h | 10 +- src/r_fps.h | 8 + src/r_local.h | 8 + src/{r_main.c => r_main.cpp} | 70 ++++--- src/r_main.h | 11 +- src/{r_plane.c => r_plane.cpp} | 169 ++++++++++++---- src/r_plane.h | 9 + src/r_portal.h | 8 + src/r_segs.c | 126 +++++++----- src/r_segs.h | 8 + src/r_things.c | 2 +- src/r_things.h | 8 + src/sdl/i_system.c | 24 ++- src/tables.h | 8 + src/v_video.h | 8 + src/w_wad.h | 8 + src/z_zone.h | 8 + 40 files changed, 1685 insertions(+), 134 deletions(-) create mode 100644 src/core/CMakeLists.txt create mode 100644 src/core/Sourcefile create mode 100644 src/core/memory.cpp create mode 100644 src/core/memory.h create mode 100644 src/core/spmc_queue.hpp create mode 100644 src/core/static_vec.hpp create mode 100644 src/core/thread_pool.cpp create mode 100644 src/core/thread_pool.h create mode 100644 src/cxxutil.hpp rename src/{r_main.c => r_main.cpp} (94%) rename src/{r_plane.c => r_plane.cpp} (87%) diff --git a/src/Makefile b/src/Makefile index 56edb6db9..6713bc624 100644 --- a/src/Makefile +++ b/src/Makefile @@ -181,7 +181,8 @@ objdir:=$(makedir)/objs # very sophisticated dependency sources+=\ - $(call List,Sourcefile) + $(call List,Sourcefile)\ + $(call List,core/Sourcefile) sources+=\ $(call List,blua/Sourcefile) diff --git a/src/command.h b/src/command.h index 2276a0ae2..6d1944f9a 100644 --- a/src/command.h +++ b/src/command.h @@ -13,6 +13,10 @@ #ifndef __COMMAND_H__ #define __COMMAND_H__ +#ifdef __cplusplus +extern "C" { +#endif + #include #include "doomdef.h" @@ -189,4 +193,8 @@ UINT8 CV_CheatsEnabled(void); // Returns cvar by name. Exposed here for Lua. consvar_t *CV_FindVar(const char *name); +#ifdef __cplusplus +} // extern "C" +#endif + #endif // __COMMAND_H__ diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt new file mode 100644 index 000000000..db8bc5a15 --- /dev/null +++ b/src/core/CMakeLists.txt @@ -0,0 +1 @@ +target_sourcefile(cpp) diff --git a/src/core/Sourcefile b/src/core/Sourcefile new file mode 100644 index 000000000..e8701d507 --- /dev/null +++ b/src/core/Sourcefile @@ -0,0 +1,2 @@ +memory.cpp +thread_pool.cpp diff --git a/src/core/memory.cpp b/src/core/memory.cpp new file mode 100644 index 000000000..e75cf91f7 --- /dev/null +++ b/src/core/memory.cpp @@ -0,0 +1,71 @@ +// BLANKART +//----------------------------------------------------------------------------- +// Copyright (C) 2024 by Ronald "Eidolon" Kinard +// Copyright (C) 2024 by Kart Krew +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- + +#include "memory.h" + +#include +#include + +#include "../z_zone.h" + +namespace +{ + +class LinearMemory +{ + size_t size_; + size_t height_; + void* memory_; + +public: + constexpr explicit LinearMemory(size_t size) noexcept; + + void* allocate(size_t size); + void reset() noexcept; +}; + +constexpr LinearMemory::LinearMemory(size_t size) noexcept : size_(size), height_{0}, memory_{nullptr} {} + +void* LinearMemory::allocate(size_t size) +{ + size_t aligned_size = (size + 15) & ~15; + if (height_ + aligned_size > size_) + { + throw std::bad_alloc(); + } + + if (memory_ == nullptr) + { + memory_ = Z_Malloc(size_, PU_STATIC, nullptr); + } + + void* ptr = (void*)((uintptr_t)(memory_) + height_); + height_ += aligned_size; + return ptr; +} + +void LinearMemory::reset() noexcept +{ + height_ = 0; +} + +} // namespace + +static LinearMemory g_frame_memory {4 * 1024 * 1024}; + +void* Z_Frame_Alloc(size_t size) +{ + return g_frame_memory.allocate(size); +} + +void Z_Frame_Reset() +{ + g_frame_memory.reset(); +} diff --git a/src/core/memory.h b/src/core/memory.h new file mode 100644 index 000000000..ba49e3d51 --- /dev/null +++ b/src/core/memory.h @@ -0,0 +1,32 @@ +// BLANKART +//----------------------------------------------------------------------------- +// Copyright (C) 2024 by Ronald "Eidolon" Kinard +// Copyright (C) 2024 by Kart Krew +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- + +#ifndef __SRB2_CORE_MEMORY_H__ +#define __SRB2_CORE_MEMORY_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif // __cpluspplus + +/// @brief Allocate a block of memory with a lifespan of the current main-thread frame. +/// This function is NOT thread-safe, but the allocated memory may be used across threads. +/// @return a pointer to a block of memory aligned with libc malloc alignment, or null if allocation fails +void* Z_Frame_Alloc(size_t size); + +/// @brief Resets per-frame memory. Not thread safe. +void Z_Frame_Reset(void); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif // __SRB2_CORE_MEMORY_H__ diff --git a/src/core/spmc_queue.hpp b/src/core/spmc_queue.hpp new file mode 100644 index 000000000..d85e1300d --- /dev/null +++ b/src/core/spmc_queue.hpp @@ -0,0 +1,192 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +// This class is derived from Conor Williams' implementation of a concurrent deque +// https://github.com/ConorWilliams/ConcurrentDeque +// Copyright (C) 2021 Conor Williams + +// The original version was for C++23. This one has been shrunk slightly and adapted to our conventions. + +#ifndef __SRB2_CORE_SPMC_QUEUE_HPP__ +#define __SRB2_CORE_SPMC_QUEUE_HPP__ + +#include +#include +#include +#include +#include + +//#include + +#include "../cxxutil.hpp" + +namespace srb2 +{ + +template +class SpMcQueue +{ + struct RingBuff { + public: + explicit RingBuff(int64_t cap) : _cap{cap}, _mask{cap - 1} + { + SRB2_ASSERT(cap && (!(cap & (cap - 1))) && "Capacity must be buf power of 2!"); + _buff = std::unique_ptr(new T[_cap]); + } + + std::int64_t capacity() const noexcept { return _cap; } + + // Store (copy) at modulo index + void store(int64_t i, T&& x) noexcept + { + _buff[i & _mask] = std::move(x); + } + + // Load (copy) at modulo index + T load(int64_t i) const noexcept + { + return _buff[i & _mask]; + } + + // Allocates and returns a new ring buffer, copies elements in range [b, t) into the new buffer. + RingBuff* resize(std::int64_t b, std::int64_t t) const + { + //ZoneScoped; + RingBuff* ptr = new RingBuff{2 * _cap}; + for (std::int64_t i = t; i != b; ++i) { + ptr->store(i, load(i)); + } + return ptr; + } + + private: + int64_t _cap; // Capacity of the buffer + int64_t _mask; // Bit mask to perform modulo capacity operations + + std::unique_ptr _buff; + }; + + alignas(64) std::atomic bottom_; + alignas(64) std::atomic top_; + alignas(64) std::atomic buffer_; + + std::vector> garbage_; + +public: + SpMcQueue(size_t capacity) : bottom_(0), top_(0), buffer_(new RingBuff(capacity)) + { + garbage_.reserve(32); + } + ~SpMcQueue() noexcept + { + delete buffer_.load(std::memory_order_relaxed); + }; + + size_t size() const noexcept + { + int64_t bottom = bottom_.load(std::memory_order_relaxed); + int64_t top = top_.load(std::memory_order_relaxed); + return static_cast(bottom >= top ? bottom - top : 0); + } + + bool empty() const noexcept + { + return size() == 0; + } + + void push(T&& v) noexcept + { + int64_t bottom = bottom_.load(std::memory_order_relaxed); + int64_t top = top_.load(std::memory_order_acquire); + RingBuff* buf = buffer_.load(std::memory_order_relaxed); + + if (buf->capacity() < (bottom - top) + 1) + { + // Queue is full, build a new one + RingBuff* newbuf = buf->resize(bottom, top); + garbage_.emplace_back(buf); + buffer_.store(newbuf, std::memory_order_relaxed); + buf = newbuf; + } + + // Construct new object, this does not have to be atomic as no one can steal this item until after we + // store the new value of bottom, ordering is maintained by surrounding atomics. + buf->store(bottom, std::move(v)); + + std::atomic_thread_fence(std::memory_order_release); + bottom_.store(bottom + 1, std::memory_order_relaxed); + } + + std::optional pop() noexcept + { + int64_t bottom = bottom_.load(std::memory_order_relaxed) - 1; + RingBuff* buf = buffer_.load(std::memory_order_relaxed); + + bottom_.store(bottom, std::memory_order_relaxed); // Stealers can no longer steal + + std::atomic_thread_fence(std::memory_order_seq_cst); + int64_t top = top_.load(std::memory_order_relaxed); + + if (top <= bottom) + { + // Non-empty deque + if (top == bottom) + { + // The last item could get stolen, by a stealer that loaded bottom before our write above + if (!top_.compare_exchange_strong(top, top + 1, std::memory_order_seq_cst, std::memory_order_relaxed)) + { + // Failed race, thief got the last item. + bottom_.store(bottom + 1, std::memory_order_relaxed); + return std::nullopt; + } + bottom_.store(bottom + 1, std::memory_order_relaxed); + } + + // Can delay load until after acquiring slot as only this thread can push(), this load is not + // required to be atomic as we are the exclusive writer. + return buf->load(bottom); + + } + else + { + bottom_.store(bottom + 1, std::memory_order_relaxed); + return std::nullopt; + } + } + + std::optional steal() noexcept + { + int64_t top = top_.load(std::memory_order_acquire); + std::atomic_thread_fence(std::memory_order_seq_cst); + int64_t bottom = bottom_.load(std::memory_order_acquire); + + if (top < bottom) + { + // Must load *before* acquiring the slot as slot may be overwritten immediately after acquiring. + // This load is NOT required to be atomic even-though it may race with an overrite as we only + // return the value if we win the race below garanteeing we had no race during our read. If we + // loose the race then 'x' could be corrupt due to read-during-write race but as T is trivially + // destructible this does not matter. + T x = buffer_.load(std::memory_order_consume)->load(top); + + if (!top_.compare_exchange_strong(top, top + 1, std::memory_order_seq_cst, std::memory_order_relaxed)) + { + return std::nullopt; + } + + return x; + + } + else + { + return std::nullopt; + } + } +}; + +} // namespace srb2 + +#endif // __SRB2_CORE_SPMC_QUEUE_HPP__ diff --git a/src/core/static_vec.hpp b/src/core/static_vec.hpp new file mode 100644 index 000000000..a5a529564 --- /dev/null +++ b/src/core/static_vec.hpp @@ -0,0 +1,255 @@ +// BLANKART +//----------------------------------------------------------------------------- +// Copyright (C) 2024 by Ronald "Eidolon" Kinard +// Copyright (C) 2024 by Kart Krew +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- + +#ifndef __SRB2_CORE_STATIC_VEC_HPP__ +#define __SRB2_CORE_STATIC_VEC_HPP__ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../cxxutil.hpp" + +namespace srb2 +{ + +template +class StaticVec; + +template +class StaticVec +{ + std::array arr_ {{}}; + size_t size_ = 0; + +public: + using value_type = T; + + constexpr StaticVec() {} + + StaticVec(const StaticVec& rhs) + { + for (size_t i = size_; i > 0; i--) + { + arr_[i] = T(); + } + size_ = rhs.size(); + for (size_t i = 0; i < size_; i++) + { + arr_[i] = rhs.arr_[i]; + } + } + + StaticVec(StaticVec&& rhs) noexcept(std::is_nothrow_move_assignable_v) + { + for (size_t i = size_; i > 0; i--) + { + arr_[i] = T(); + } + size_ = rhs.size(); + for (size_t i = 0; i < size_; i++) + { + arr_[i] = std::move(rhs.arr_[i]); + } + while (rhs.size() > 0) + { + rhs.pop_back(); + } + } + + constexpr StaticVec(std::initializer_list list) noexcept(std::is_nothrow_move_assignable_v) + { + size_ = list.size(); + size_t i = 0; + for (auto itr = list.begin(); itr != list.end(); itr++) + { + arr_[i] = *itr; + i++; + } + } + + ~StaticVec() = default; + + StaticVec& operator=(const StaticVec& rhs) + { + for (size_t i = size_; i > 0; i--) + { + arr_[i] = T(); + } + size_ = rhs.size(); + for (size_t i = 0; i < size_; i++) + { + arr_[i] = rhs.arr_[i]; + } + return *this; + } + + StaticVec& operator=(StaticVec&& rhs) noexcept(std::is_nothrow_move_constructible_v) + { + for (size_t i = size_; i > 0; i--) + { + arr_[i] = T(); + } + size_ = rhs.size(); + for (size_t i = 0; i < size_; i++) + { + arr_[i] = std::move(rhs.arr_[i]); + } + while (rhs.size() > 0) + { + rhs.pop_back(); + } + return *this; + } + + void push_back(const T& value) { arr_[size_++] = value; } + + void pop_back() { arr_[--size_] = T(); } + + void resize(size_t size, T value = T()) + { + if (size >= Limit) + { + throw std::length_error("new size >= Capacity"); + } + + if (size == size_) + { + return; + } + else if (size < size_) + { + while (size_ > size) + { + pop_back(); + } + } + else + { + while (size_ < size) + { + push_back(value); + } + } + } + + void clear() + { + arr_ = {{}}; + size_ = 0; + } + + using iterator = typename std::array::iterator; + using const_iterator = typename std::array::const_iterator; + + constexpr iterator begin() noexcept { return arr_.begin(); } + + constexpr const_iterator begin() const noexcept { return arr_.cbegin(); } + + constexpr const_iterator cbegin() const noexcept { return arr_.cbegin(); } + + constexpr iterator end() noexcept { return std::next(arr_.begin(), size_); } + + constexpr const_iterator end() const noexcept { return cend(); } + + constexpr const_iterator cend() const noexcept { return std::next(arr_.cbegin(), size_); } + + constexpr std::reverse_iterator rbegin() noexcept { return std::reverse_iterator(this->end()); } + + constexpr std::reverse_iterator crbegin() const noexcept { return std::reverse_iterator(this->cend()); } + + constexpr std::reverse_iterator rend() noexcept { return std::reverse_iterator(this->begin()); } + + constexpr std::reverse_iterator crend() const noexcept { return std::reverse_iterator(this->cbegin()); } + + constexpr bool empty() const noexcept { return size_ == 0; } + + constexpr size_t size() const noexcept { return size_; } + + constexpr size_t capacity() const noexcept { return Limit; } + + constexpr size_t max_size() const noexcept { return Limit; } + + constexpr T& operator[](size_t index) noexcept { return arr_[index]; } + + T& at(size_t index) + { + if (index >= size_) + { + throw std::out_of_range("index >= size"); + } + return this[index]; + } + + constexpr const T& operator[](size_t index) const noexcept { return arr_[index]; } + + const T& at(size_t index) const + { + if (index >= size_) + { + throw std::out_of_range("index >= size"); + } + return this[index]; + } + + T& front() { return *arr_[0]; } + + T& back() { return *arr_[size_ - 1]; } +}; + +} // namespace srb2 + +template +bool operator==(const srb2::StaticVec& lhs, const srb2::StaticVec& rhs) +{ + const size_t size = lhs.size(); + if (size != rhs.size()) + { + return false; + } + for (size_t i = 0; i < lhs; i++) + { + if (rhs[i] != lhs[i]) + { + return false; + } + } + return true; +} + +template +bool operator!=(const srb2::StaticVec& lhs, const srb2::StaticVec& rhs) +{ + return !(lhs == rhs); +} + +template +struct std::hash> +{ + size_t operator()(const srb2::StaticVec& input) const + { + constexpr size_t prime = sizeof(size_t) == 8 ? 0x00000100000001B3 : 0x01000193; + constexpr size_t basis = sizeof(size_t) == 8 ? 0xcbf29ce484222325 : 0x811c9dc5; + + size_t ret = basis; + for (auto itr = input.begin(); itr != input.end(); itr++) + { + ret = (ret * prime) ^ std::hash(*itr); + } + return ret; + } +}; + +#endif // __SRB2_CORE_STATIC_VEC_HPP__ diff --git a/src/core/thread_pool.cpp b/src/core/thread_pool.cpp new file mode 100644 index 000000000..820f21f67 --- /dev/null +++ b/src/core/thread_pool.cpp @@ -0,0 +1,346 @@ +// BLANKART +//----------------------------------------------------------------------------- +// Copyright (C) 2024 by Ronald "Eidolon" Kinard +// Copyright (C) 2024 by Kart Krew +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- + +#include "thread_pool.h" + +#include +#include +#include +#include +#include +#include + +#include +//#include + +#include "../cxxutil.hpp" +#include "../m_argv.h" + +using namespace srb2; + +static void do_work(ThreadPool::Task& work) +{ + try + { + //ZoneScoped; + (work.thunk)(work.raw.data()); + } + catch (...) + { + // can't do anything + } + + (work.deleter)(work.raw.data()); + if (work.pseudosema) + { + work.pseudosema->fetch_sub(1, std::memory_order_relaxed); + } +} + +static void pool_executor( + int thread_index, + std::shared_ptr> pool_alive, + std::shared_ptr worker_ready_mutex, + std::shared_ptr worker_ready_condvar, + std::shared_ptr my_wq, + std::vector> other_wqs +) +{ + { + //std::string thread_name = fmt::format("Thread Pool Thread {}", thread_index); + //tracy::SetThreadName(thread_name.c_str()); + } + + int spins = 0; + while (true) + { + std::optional work = my_wq->steal(); + bool did_work = false; + if (work) + { + do_work(*work); + + did_work = true; + spins = 0; + } + else + { + for (auto& q : other_wqs) + { + work = q->steal(); + if (work) + { + do_work(*work); + + did_work = true; + spins = 0; + + // We only want to steal one work item at a time, to prioritize our own queue + break; + } + } + } + + if (!did_work) + { + // Spin a few loops to avoid yielding, then wait for the ready lock + spins += 1; + if (spins > 100) + { + std::unique_lock ready_lock {*worker_ready_mutex}; + while (my_wq->empty() && pool_alive->load()) + { + worker_ready_condvar->wait(ready_lock); + } + + if (!pool_alive->load()) + { + break; + } + } + } + } +} + +ThreadPool::ThreadPool() +{ + immediate_mode_ = true; +} + +ThreadPool::ThreadPool(size_t threads) +{ + next_queue_index_ = 0; + pool_alive_ = std::make_shared>(true); + + for (size_t i = 0; i < threads; i++) + { + std::shared_ptr wsq = std::make_shared(2048); + work_queues_.push_back(wsq); + + std::shared_ptr mutex = std::make_shared(); + worker_ready_mutexes_.push_back(std::move(mutex)); + std::shared_ptr condvar = std::make_shared(); + worker_ready_condvars_.push_back(std::move(condvar)); + } + + for (size_t i = 0; i < threads; i++) + { + std::shared_ptr my_queue = work_queues_[i]; + std::vector> other_queues; + for (size_t j = 0; j < threads; j++) + { + // Order the other queues starting from the next adjacent worker + // i.e. if this is worker 2 of 8, then other queues is 3, 4, 5, 6, 7, 0, 1 + // This tries to balance out work stealing behavior + + size_t other_index = j + i; + if (other_index >= threads) + { + other_index -= threads; + } + + if (other_index != i) + { + other_queues.push_back(work_queues_[other_index]); + } + } + + std::thread thread; + try + { + thread = std::thread + { + pool_executor, + i, + pool_alive_, + worker_ready_mutexes_[i], + worker_ready_condvars_[i], + my_queue, + other_queues + }; + } + catch (const std::system_error& error) + { + // Safe shutdown and rethrow + pool_alive_->store(false); + for (auto& t : threads_) + { + t.join(); + } + throw error; + } + + threads_.push_back(std::move(thread)); + } +} + +ThreadPool::ThreadPool(ThreadPool&&) = default; +ThreadPool::~ThreadPool() = default; + +ThreadPool& ThreadPool::operator=(ThreadPool&&) = default; + +void ThreadPool::begin_sema() +{ + sema_begun_ = true; +} + +ThreadPool::Sema ThreadPool::end_sema() +{ + Sema ret = Sema(std::move(cur_sema_)); + cur_sema_ = nullptr; + sema_begun_ = false; + return ret; +} + +void ThreadPool::notify() +{ + for (size_t i = 0; i < work_queues_.size(); i++) + { + auto& q = work_queues_[i]; + size_t count = q->size(); + if (count > 0) + { + worker_ready_condvars_[i]->notify_one(); + } + } +} + +void ThreadPool::notify_sema(const ThreadPool::Sema& sema) +{ + if (!sema.pseudosema_) + { + return; + } + notify(); +} + +void ThreadPool::wait_idle() +{ + if (immediate_mode_) + { + return; + } + + //ZoneScoped; + + for (size_t i = 0; i < work_queues_.size(); i++) + { + auto& q = work_queues_[i]; + + std::optional work; + while ((work = q->pop()).has_value()) + { + do_work(*work); + } + } +} + +void ThreadPool::wait_sema(const Sema& sema) +{ + if (!sema.pseudosema_) + { + return; + } + + //ZoneScoped; + + while (sema.pseudosema_->load(std::memory_order_seq_cst) > 0) + { + // spin to win + for (size_t i = 0; i < work_queues_.size(); i++) + { + auto& q = work_queues_[i]; + + std::optional work; + if ((work = q->pop()).has_value()) + { + do_work(*work); + break; + } + } + } + + if (sema.pseudosema_->load(std::memory_order_seq_cst) != 0) + { + throw std::exception(); + } +} + +void ThreadPool::shutdown() +{ + if (immediate_mode_) + { + return; + } + + wait_idle(); + + pool_alive_->store(false); + + for (auto& condvar : worker_ready_condvars_) + { + condvar->notify_all(); + } + for (auto& t : threads_) + { + t.join(); + } +} + +std::unique_ptr srb2::g_main_threadpool; + +void I_ThreadPoolInit(void) +{ + SRB2_ASSERT(g_main_threadpool == nullptr); + size_t thread_count = std::min(static_cast(9), std::thread::hardware_concurrency()); + if (thread_count > 1) + { + // The main thread will act as a worker when waiting for pool idle + // Make one less worker thread to avoid unnecessary context switching + thread_count -= 1; + } + + if (M_CheckParm("-singlethreaded")) + { + g_main_threadpool = std::make_unique(); + } + else + { + g_main_threadpool = std::make_unique(thread_count); + } +} + +void I_ThreadPoolShutdown(void) +{ + if (!g_main_threadpool) + { + return; + } + + g_main_threadpool->shutdown(); + g_main_threadpool = nullptr; +} + +void I_ThreadPoolSubmit(srb2cthunk_t thunk, void* data) +{ + SRB2_ASSERT(g_main_threadpool != nullptr); + + g_main_threadpool->schedule([=]() { + (thunk)(data); + }); + g_main_threadpool->notify(); +} + +void I_ThreadPoolWaitIdle(void) +{ + SRB2_ASSERT(g_main_threadpool != nullptr); + + g_main_threadpool->wait_idle(); +} diff --git a/src/core/thread_pool.h b/src/core/thread_pool.h new file mode 100644 index 000000000..75961614e --- /dev/null +++ b/src/core/thread_pool.h @@ -0,0 +1,163 @@ +// BLANKART +//----------------------------------------------------------------------------- +// Copyright (C) 2024 by Ronald "Eidolon" Kinard +// Copyright (C) 2024 by Kart Krew +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- + +#ifndef __SRB2_CORE_THREAD_POOL_H__ +#define __SRB2_CORE_THREAD_POOL_H__ + +#include + +#ifdef __cplusplus + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "spmc_queue.hpp" + +namespace srb2 +{ + +class ThreadPool +{ +public: + struct Task + { + void (*thunk)(void*); + void (*deleter)(void*); + std::shared_ptr> pseudosema; + std::array>)> raw; + }; + + using Queue = SpMcQueue; + + class Sema + { + std::shared_ptr> pseudosema_; + + explicit Sema(std::shared_ptr> sema) : pseudosema_(sema) {} + + friend class ThreadPool; + public: + Sema() = default; + }; + +private: + std::shared_ptr> pool_alive_; + std::vector> worker_ready_mutexes_; + std::vector> worker_ready_condvars_; + std::vector> work_queues_; + std::vector threads_; + size_t next_queue_index_ = 0; + std::shared_ptr> cur_sema_; + + bool immediate_mode_ = false; + bool sema_begun_ = false; + +public: + ThreadPool(); + explicit ThreadPool(size_t threads); + ThreadPool(const ThreadPool&) = delete; + ThreadPool(ThreadPool&&); + ~ThreadPool(); + + ThreadPool& operator=(const ThreadPool&) = delete; + ThreadPool& operator=(ThreadPool&&); + + void begin_sema(); + ThreadPool::Sema end_sema(); + + /// Enqueue but don't notify + template void schedule(T&& thunk); + /// Notify threads after several schedules + void notify(); + void notify_sema(const Sema& sema); + void wait_idle(); + void wait_sema(const Sema& sema); + void shutdown(); +}; + +extern std::unique_ptr g_main_threadpool; + +template +void callable_caller(F* f) +{ + (*f)(); +} + +template +void callable_destroyer(F* f) +{ + f->~F(); +} + +template +void ThreadPool::schedule(T&& thunk) +{ + static_assert(sizeof(T) <= sizeof(std::declval().raw)); + + if (immediate_mode_) + { + (thunk)(); + return; + } + + if (sema_begun_) + { + if (cur_sema_ == nullptr) + { + cur_sema_ = std::make_shared>(0); + } + cur_sema_->fetch_add(1, std::memory_order_relaxed); + } + + size_t qi = next_queue_index_; + + { + std::shared_ptr q = work_queues_[qi]; + Task task; + task.thunk = reinterpret_cast(callable_caller); + task.deleter = reinterpret_cast(callable_destroyer); + task.pseudosema = cur_sema_; + new (reinterpret_cast(task.raw.data())) T(std::move(thunk)); + + q->push(std::move(task)); + } + // worker_ready_condvars_[qi]->notify_one(); + + next_queue_index_ += 1; + if (next_queue_index_ >= threads_.size()) + { + next_queue_index_ = 0; + } +} + +} // namespace srb2 + +extern "C" { + +#endif // __cplusplus + +typedef void (*srb2cthunk_t)(void*); + +void I_ThreadPoolInit(void); +void I_ThreadPoolShutdown(void); +void I_ThreadPoolSubmit(srb2cthunk_t thunk, void* data); +void I_ThreadPoolWaitIdle(void); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // __SRB2_CORE_THREAD_POOL_H__ diff --git a/src/cxxutil.hpp b/src/cxxutil.hpp new file mode 100644 index 000000000..74349a0ff --- /dev/null +++ b/src/cxxutil.hpp @@ -0,0 +1,152 @@ +#ifndef __SRB2_CXXUTIL_HPP__ +#define __SRB2_CXXUTIL_HPP__ + +#include +#include +#include + +#include "doomdef.h" + +namespace srb2 { + +template +class Finally { +public: + explicit Finally(const F& f) noexcept : f_(f) {} + explicit Finally(F&& f) noexcept : f_(f) {} + + Finally(Finally&& from) noexcept : f_(std::move(from.f_)), call_(std::exchange(from.call_, false)) {} + + Finally(const Finally& from) = delete; + void operator=(const Finally& from) = delete; + void operator=(Finally&& from) = delete; + + ~Finally() noexcept { + if (call_) + f_(); + } + +private: + F f_; + bool call_ = true; +}; + +template +Finally> finally(F&& f) noexcept { + return Finally {std::forward(f)}; +} + +struct SourceLocation { + const char* file_name; + unsigned int line_number; +}; + +#define SRB2_SOURCE_LOCATION \ + srb2::SourceLocation { __FILE__, __LINE__ } + +#ifndef SRB2_ASSERT_HANDLER +#define SRB2_ASSERT_HANDLER srb2::IErrorAssertHandler +#endif + +#if !defined(NDEBUG) || defined(PARANOIA) +// An assertion level of 2 will activate all invocations of the SRB2_ASSERT macro +#define SRB2_ASSERTION_LEVEL 2 +#else +// The minimum assertion level is 1 +#define SRB2_ASSERTION_LEVEL 1 +#endif + +/// Assert a precondition expression in debug builds. +#define SRB2_ASSERT(expr) srb2::do_assert<2, SRB2_ASSERT_HANDLER>([&] { return (expr); }, SRB2_SOURCE_LOCATION, #expr) + +class IErrorAssertHandler { +public: + static void handle(const SourceLocation& source_location, const char* expression) { + I_Error("Assertion failed at %s:%u: %s != true", + source_location.file_name, + source_location.line_number, + expression); + } +}; + +class NoOpAssertHandler { +public: + static void handle(const SourceLocation& source_location, const char* expression) {} +}; + +/// @brief Assert a precondition expression, aborting the application if it fails. +/// @tparam Expr +/// @tparam Level the level of this assertion; if it is less than or equal to SRB2_ASSERTION_LEVEL, this overload will +/// activate. +/// @param expr a callable which returns a bool +/// @param source_location a struct containing the source location of the assertion, e.g. SRB2_SOURCE_LOCATION +/// @param expression the expression evaluated in the expression callable +/// @param message an optional message to display for the assertion +template +std::enable_if_t<(Level <= SRB2_ASSERTION_LEVEL), void> +do_assert(const Expr& expr, const SourceLocation& source_location, const char* expression = "") noexcept { + static_assert(Level > 0, "level of an assertion must not be 0"); + if (!expr()) { + Handler::handle(source_location, expression); + std::abort(); + } +} + +template +std::enable_if_t<(Level > SRB2_ASSERTION_LEVEL), void> +do_assert(const Expr&, const SourceLocation&, const char* = "") noexcept { +} + +template +class NotNull final { + T ptr_; + +public: + static_assert(std::is_convertible_v() != nullptr), bool>, + "T is not comparable with nullptr_t"); + + /// @brief Move-construct from the pointer value U, asserting that it is not null. Allows construction of a + /// NotNull from any compatible pointer U, for example with polymorphic classes. + template >> + constexpr NotNull(U&& rhs) : ptr_(std::forward(rhs)) { + SRB2_ASSERT(ptr_ != nullptr); + } + + /// @brief Wrap the pointer type T, asserting that the pointer is not null. + template >> + constexpr NotNull(T rhs) : ptr_(std::move(rhs)) { + SRB2_ASSERT(ptr_ != nullptr); + } + + /// @brief Copy construction from NotNull of convertible type U. Only if the incoming pointer is NotNull already. + template >> + constexpr NotNull(const NotNull& rhs) : NotNull(rhs.get()) { + // Value is guaranteed to be not null by construction; no assertion necessary + } + + NotNull(const NotNull& rhs) = default; + NotNull& operator=(const NotNull& rhs) = default; + + /// @brief Get the stored pointer. + constexpr T get() const { return ptr_; } + + /// @brief Convert to T (the pointer type). + constexpr operator T() const { return get(); } + + /// @brief Arrow-dereference to *T (the actual value pointed to). + constexpr decltype(auto) operator->() const { return get(); } + + /// @brief Dereference to *T (the actual value pointed to). + constexpr decltype(auto) operator*() const { return *get(); } + + // It is not allowed to construct NotNull with nullptr regardless of T. + NotNull(std::nullptr_t) = delete; + NotNull& operator=(std::nullptr_t) = delete; +}; + +template +NotNull(T) -> NotNull; + +} // namespace srb2 + +#endif // __SRB2_CXXUTIL_HPP__ diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 35c77ce12..7ba47cfd6 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -13,6 +13,10 @@ #ifndef __D_CLISRV__ #define __D_CLISRV__ +#ifdef __cplusplus +extern "C" { +#endif + #include "d_ticcmd.h" #include "d_net.h" #include "d_netcmd.h" @@ -694,4 +698,9 @@ typedef struct rewind_s { void CL_ClearRewinds(void); rewind_t *CL_SaveRewindPoint(size_t demopos); rewind_t *CL_RewindToTime(tic_t time); + +#ifdef __cplusplus +} // extern "C" +#endif + #endif diff --git a/src/d_main.c b/src/d_main.c index 38a6efb2f..abdd3fa2a 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -73,6 +73,8 @@ #include "m_perfstats.h" #include "k_kart.h" +#include "core/memory.h" + #include "lua_script.h" #ifdef CMAKECONFIG @@ -739,6 +741,8 @@ void D_SRB2Loop(void) precise_t enterprecise = I_GetPreciseTime(); precise_t finishprecise = enterprecise; + Z_Frame_Reset(); + // Casting the return value of a function is bad practice (apparently) double budget = ((R_GetFramerateCap() == 0) ? 0.0 : round((1.0 / R_GetFramerateCap()) * I_GetPrecisePrecision())); capbudget = (precise_t)budget; diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 91ea8e945..abe3dd8c9 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -204,11 +204,6 @@ static void Command_Archivetest_f(void); // CLIENT VARIABLES // ========================================================================= -void SendWeaponPref(void); -void SendWeaponPref2(void); -void SendWeaponPref3(void); -void SendWeaponPref4(void); - static CV_PossibleValue_t usemouse_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Force"}, {0, NULL}}; static CV_PossibleValue_t autobalance_cons_t[] = {{0, "MIN"}, {4, "MAX"}, {0, NULL}}; diff --git a/src/d_netcmd.h b/src/d_netcmd.h index b4ee22d93..657686af4 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -15,8 +15,17 @@ #ifndef __D_NETCMD__ #define __D_NETCMD__ +#ifdef __cplusplus +extern "C" { +#endif + #include "command.h" +void SendWeaponPref(void); +void SendWeaponPref2(void); +void SendWeaponPref3(void); +void SendWeaponPref4(void); + // console vars extern consvar_t cv_playername; extern consvar_t cv_playercolor; @@ -318,4 +327,8 @@ void D_SetPassword(const char *pw); // used for the player setup menu UINT8 CanChangeSkin(INT32 playernum); +#ifdef __cplusplus +} // extern "C" +#endif + #endif diff --git a/src/doomdef.h b/src/doomdef.h index f9467199b..dbeabce63 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -58,6 +58,9 @@ // warning C4152: nonstandard extension, function/data pointer conversion in expression // warning C4213: nonstandard extension used : cast on l-value +#ifdef __cplusplus +extern "C" { +#endif #include "doomtype.h" @@ -524,12 +527,15 @@ UINT32 quickncasehash (const char *p, size_t n) return x; } +#ifndef __cplusplus #ifndef min // Double-Check with WATTCP-32's cdefs.h #define min(x, y) (((x) < (y)) ? (x) : (y)) #endif #ifndef max // Double-Check with WATTCP-32's cdefs.h #define max(x, y) (((x) > (y)) ? (x) : (y)) #endif +#endif + #ifndef CLAMP #define CLAMP(x, y, z) ((x) < (y) ? (y) : ((x) > (z) ? (z) : (x))) #endif @@ -657,4 +663,8 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; #undef UPDATE_ALERT #endif +#ifdef __cplusplus +} // extern "C" +#endif + #endif // __DOOMDEF__ diff --git a/src/doomtype.h b/src/doomtype.h index 174bba5b1..79806365d 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -17,6 +17,10 @@ #ifndef __DOOMTYPE__ #define __DOOMTYPE__ +#ifdef __cplusplus +extern "C" { +#endif + #if defined (_WIN32) //#define WIN32_LEAN_AND_MEAN #define RPC_NO_WINDOWS_H @@ -100,8 +104,10 @@ typedef long ssize_t; #define strnicmp(x,y,n) strncasecmp(x,y,n) #endif +#ifndef __cplusplus char *strcasestr(const char *in, const char *what); #define stristr strcasestr +#endif #if defined (macintosh) //|| defined (__APPLE__) //skip all boolean/Boolean crap #define true 1 @@ -385,4 +391,8 @@ unset_bit_array (bitarray_t * const array, const int value) typedef UINT64 precise_t; +#ifdef __cplusplus +} // extern "C" +#endif + #endif //__DOOMTYPE__ diff --git a/src/i_system.h b/src/i_system.h index e7fb26a41..b26db7a82 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -14,6 +14,10 @@ #ifndef __I_SYSTEM__ #define __I_SYSTEM__ +#ifdef __cplusplus +extern "C" { +#endif + #include "d_ticcmd.h" #include "d_event.h" @@ -256,4 +260,8 @@ const char *I_ClipboardPaste(void); void I_RegisterSysCommands(void); +#ifdef __cplusplus +} // extern "C" +#endif + #endif diff --git a/src/m_argv.h b/src/m_argv.h index f31a531d0..8f1a08ec4 100644 --- a/src/m_argv.h +++ b/src/m_argv.h @@ -14,6 +14,10 @@ #ifndef __M_ARGV__ #define __M_ARGV__ +#ifdef __cplusplus +extern "C" { +#endif + // // MISC // @@ -42,4 +46,8 @@ const char *M_GetNextParm(void); // Finds and loads a response file (@moreargs.txt) void M_FindResponseFile(void); +#ifdef __cplusplus +} // extern "C" +#endif + #endif //__M_ARGV__ diff --git a/src/p_mobj.h b/src/p_mobj.h index 733153017..cd4033157 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -14,6 +14,10 @@ #ifndef __P_MOBJ__ #define __P_MOBJ__ +#ifdef __cplusplus +extern "C" { +#endif + // Basics. #include "tables.h" #include "m_fixed.h" @@ -536,4 +540,9 @@ extern mapthing_t *huntemeralds[MAXHUNTEMERALDS]; extern INT32 numhuntemeralds; extern boolean runemeraldmanager; extern INT32 numstarposts; + +#ifdef __cplusplus +} // extern "C" +#endif + #endif diff --git a/src/p_setup.h b/src/p_setup.h index 97209e154..86b958adf 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -14,6 +14,10 @@ #ifndef __P_SETUP__ #define __P_SETUP__ +#ifdef __cplusplus +extern "C" { +#endif + #include "doomdata.h" #include "doomstat.h" #include "r_defs.h" @@ -116,4 +120,8 @@ UINT8 P_GetGrade(UINT32 pscore, INT16 map, UINT8 mare); UINT8 P_HasGrades(INT16 map, UINT8 mare); UINT32 P_GetScoreForGrade(INT16 map, UINT8 mare, UINT8 grade); +#ifdef __cplusplus +} // extern "C" +#endif + #endif diff --git a/src/r_bsp.h b/src/r_bsp.h index 167f3311f..b9e4e291d 100644 --- a/src/r_bsp.h +++ b/src/r_bsp.h @@ -14,6 +14,10 @@ #ifndef __R_BSP__ #define __R_BSP__ +#ifdef __cplusplus +extern "C" { +#endif + #ifdef __GNUG__ #pragma interface #endif @@ -62,4 +66,9 @@ boolean R_IsEmptyLine(seg_t *line, const sector_t *front, const sector_t *back); INT32 R_GetPlaneLight(sector_t *sector, fixed_t planeheight, boolean underside); void R_Prep3DFloors(sector_t *sector); + +#ifdef __cplusplus +} // extern "C" +#endif + #endif diff --git a/src/r_data.h b/src/r_data.h index 65dd6ccbb..45f7ee484 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -14,6 +14,10 @@ #ifndef __R_DATA__ #define __R_DATA__ +#ifdef __cplusplus +extern "C" { +#endif + #include "r_defs.h" #include "r_state.h" @@ -111,4 +115,8 @@ UINT8 NearestPaletteColor(UINT8 r, UINT8 g, UINT8 b, RGBA_t *palette); extern INT32 numtextures; +#ifdef __cplusplus +} // extern "C" +#endif + #endif diff --git a/src/r_draw.h b/src/r_draw.h index 3654fdeb2..5a57ae978 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -14,6 +14,10 @@ #ifndef __R_DRAW__ #define __R_DRAW__ +#ifdef __cplusplus +extern "C" { +#endif + #include "r_defs.h" #include "r_things.h" @@ -118,7 +122,7 @@ extern void (*basespanfunc)(drawspandata_t*); extern void (*splatfunc)(drawspandata_t*); // Draws a single visplane. -void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl); +void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_parallel); // Vectors for Software's tilted slope drawers extern floatv3_t *ds_su, *ds_sv, *ds_sz; @@ -240,5 +244,9 @@ void R_DrawTiltedSplat(drawspandata_t* ds); void R_DrawSplat(drawspandata_t* ds); void R_DrawTranslucentSplat(drawspandata_t* ds); +#ifdef __cplusplus +} // extern "C" +#endif + // ========================================================================= #endif // __R_DRAW__ diff --git a/src/r_fps.h b/src/r_fps.h index 7ed55c848..870fa70f1 100644 --- a/src/r_fps.h +++ b/src/r_fps.h @@ -15,6 +15,10 @@ #ifndef __R_FPS_H__ #define __R_FPS_H__ +#ifdef __cplusplus +extern "C" { +#endif + #include "m_fixed.h" #include "p_local.h" #include "r_state.h" @@ -175,4 +179,8 @@ void R_UpdateMobjInterpolators(void); void R_ResetMobjInterpolationState(mobj_t *mobj); void R_ResetPrecipitationMobjInterpolationState(precipmobj_t *mobj); +#ifdef __cplusplus +} // extern "C" +#endif + #endif diff --git a/src/r_local.h b/src/r_local.h index 1d3187750..4701cb400 100644 --- a/src/r_local.h +++ b/src/r_local.h @@ -14,6 +14,10 @@ #ifndef __R_LOCAL__ #define __R_LOCAL__ +#ifdef __cplusplus +extern "C" { +#endif + // Screen size related parameters. #include "doomdef.h" @@ -38,4 +42,8 @@ extern drawseg_t *firstseg; void SplitScreen_OnChange(void); +#ifdef __cplusplus +} // extern "C" +#endif + #endif // __R_LOCAL__ diff --git a/src/r_main.c b/src/r_main.cpp similarity index 94% rename from src/r_main.c rename to src/r_main.cpp index a0f6361d6..55475c407 100644 --- a/src/r_main.c +++ b/src/r_main.cpp @@ -13,6 +13,8 @@ /// utility functions (BSP, geometry, trigonometry). /// See tables.c, too. +#include + #include "doomdef.h" #include "g_game.h" #include "g_input.h" @@ -37,6 +39,8 @@ #include "r_fps.h" // Frame interpolation/uncapped #include "tables.h" +#include "core/thread_pool.h" + #ifdef HWRENDER #include "hardware/hw_main.h" #endif @@ -157,10 +161,6 @@ static void FlipCam_OnChange(void); static void FlipCam2_OnChange(void); static void FlipCam3_OnChange(void); static void FlipCam4_OnChange(void); -void SendWeaponPref(void); -void SendWeaponPref2(void); -void SendWeaponPref3(void); -void SendWeaponPref4(void); static void DirLight_OnChange(void); @@ -504,10 +504,10 @@ void R_GetRenderBlockMapDimensions(fixed_t drawdist, INT32 *xl, INT32 *xh, INT32 const fixed_t vyright = viewy + FixedMul(drawdist, FSIN(right)); // Try to narrow the search to within only the field of view - *xl = (unsigned)(min(viewx, min(vxleft, vxright)) - bmaporgx)>>MAPBLOCKSHIFT; - *xh = (unsigned)(max(viewx, max(vxleft, vxright)) - bmaporgx)>>MAPBLOCKSHIFT; - *yl = (unsigned)(min(viewy, min(vyleft, vyright)) - bmaporgy)>>MAPBLOCKSHIFT; - *yh = (unsigned)(max(viewy, max(vyleft, vyright)) - bmaporgy)>>MAPBLOCKSHIFT; + *xl = (unsigned)(std::min(viewx, std::min(vxleft, vxright)) - bmaporgx)>>MAPBLOCKSHIFT; + *xh = (unsigned)(std::max(viewx, std::max(vxleft, vxright)) - bmaporgx)>>MAPBLOCKSHIFT; + *yl = (unsigned)(std::min(viewy, std::min(vyleft, vyright)) - bmaporgy)>>MAPBLOCKSHIFT; + *yh = (unsigned)(std::max(viewy, std::max(vyleft, vyright)) - bmaporgy)>>MAPBLOCKSHIFT; if (*xh >= bmapwidth) *xh = bmapwidth - 1; @@ -681,9 +681,9 @@ void R_CheckViewMorph(void) if (viewmorph.scrmapsize != vid.width*vid.height) { viewmorph.scrmapsize = vid.width*vid.height; - viewmorph.scrmap = realloc(viewmorph.scrmap, vid.width*vid.height * sizeof(INT32)); - viewmorph.ceilingclip = realloc(viewmorph.ceilingclip, vid.width * sizeof(INT16)); - viewmorph.floorclip = realloc(viewmorph.floorclip, vid.width * sizeof(INT16)); + viewmorph.scrmap = static_cast(realloc(viewmorph.scrmap, vid.width*vid.height * sizeof(INT32))); + viewmorph.ceilingclip = static_cast(realloc(viewmorph.ceilingclip, vid.width * sizeof(INT16))); + viewmorph.floorclip = static_cast(realloc(viewmorph.floorclip, vid.width * sizeof(INT16))); } temp = FINECOSINE(rollangle); @@ -695,7 +695,7 @@ void R_CheckViewMorph(void) x1 = (vid.width*fabsf(rollcos) + vid.height*fabsf(rollsin)) / vid.width; y1 = (vid.height*fabsf(rollcos) + vid.width*fabsf(rollsin)) / vid.height; - temp = max(x1, y1)*FRACUNIT; + temp = std::max(x1, y1)*FRACUNIT; if (temp < FRACUNIT) temp = FRACUNIT; else @@ -741,10 +741,10 @@ void R_CheckViewMorph(void) xb = vid.width-1-xa; yb = vid.height-1-ya; - viewmorph.ceilingclip[xa] = min(viewmorph.ceilingclip[xa], ya); - viewmorph.floorclip[xa] = max(viewmorph.floorclip[xa], ya); - viewmorph.ceilingclip[xb] = min(viewmorph.ceilingclip[xb], yb); - viewmorph.floorclip[xb] = max(viewmorph.floorclip[xb], yb); + viewmorph.ceilingclip[xa] = std::min(viewmorph.ceilingclip[xa], ya); + viewmorph.floorclip[xa] = std::max(viewmorph.floorclip[xa], ya); + viewmorph.ceilingclip[xb] = std::min(viewmorph.ceilingclip[xb], yb); + viewmorph.floorclip[xb] = std::max(viewmorph.floorclip[xb], yb); x2 += rollcos; y2 += rollsin; } @@ -758,10 +758,10 @@ void R_CheckViewMorph(void) xb = vid.width-1-xa; yb = vid.height-1-ya; - viewmorph.ceilingclip[xa] = min(viewmorph.ceilingclip[xa], ya); - viewmorph.floorclip[xa] = max(viewmorph.floorclip[xa], ya); - viewmorph.ceilingclip[xb] = min(viewmorph.ceilingclip[xb], yb); - viewmorph.floorclip[xb] = max(viewmorph.floorclip[xb], yb); + viewmorph.ceilingclip[xa] = std::min(viewmorph.ceilingclip[xa], ya); + viewmorph.floorclip[xa] = std::max(viewmorph.floorclip[xa], ya); + viewmorph.ceilingclip[xb] = std::min(viewmorph.ceilingclip[xb], yb); + viewmorph.floorclip[xb] = std::max(viewmorph.floorclip[xb], yb); x2 -= rollsin; y2 += rollcos; } @@ -978,7 +978,7 @@ void R_ExecuteSetViewSize(void) fixed_t R_GetPlayerFov(player_t *player) { fixed_t fov = cv_fov.value + player->fovadd; - return max(MINFOV*FRACUNIT, min(fov, MAXFOV*FRACUNIT)); + return std::max(MINFOV*FRACUNIT, std::min(fov, MAXFOV*FRACUNIT)); } static void R_SetFov(fixed_t playerfov) @@ -1095,7 +1095,7 @@ void R_SkyboxFrame(int s) camera_t *thiscam = &camera[s]; subsector_t * subsector = NULL; - R_SetViewContext(VIEWCONTEXT_SKY1 + s); + R_SetViewContext(static_cast(VIEWCONTEXT_SKY1 + s)); // cut-away view stuff newview->sky = true; @@ -1193,7 +1193,8 @@ void R_SetupFrame(int s, boolean skybox) boolean chasecam = (cv_chasecam[s].value); sector_t * sector = NULL; - R_SetViewContext(VIEWCONTEXT_PLAYER1 + s); + R_SetViewContext(static_cast(VIEWCONTEXT_PLAYER1 + s)); + if (thiscam->reset) { R_ResetViewInterpolation(s); @@ -1336,10 +1337,13 @@ static fixed_t viewfov[MAXSPLITSCREENPLAYERS]; void R_RenderPlayerView(player_t *player) { UINT8 nummasks = 1; - maskcount_t* masks = malloc(sizeof(maskcount_t)); + maskcount_t* masks = static_cast(malloc(sizeof(maskcount_t))); const boolean skybox = (skyboxmo[0] && cv_skybox.value); UINT8 i; + srb2::ThreadPool::Sema tp_sema; + srb2::g_main_threadpool->begin_sema(); + // if this is display player 1 if (cv_homremoval.value && player == &players[displayplayers[0]]) { @@ -1352,7 +1356,7 @@ void R_RenderPlayerView(player_t *player) else if (splitscreen == 2 && player == &players[displayplayers[2]]) { // V_DrawPatchFill, but for the fourth screen only - patch_t *pat = W_CachePatchName("SRB2BACK", PU_CACHE); + patch_t *pat = static_cast(W_CachePatchName("SRB2BACK", PU_CACHE)); INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); INT32 x, y, pw = SHORT(pat->width) * dupz, ph = SHORT(pat->height) * dupz; @@ -1399,7 +1403,6 @@ void R_RenderPlayerView(player_t *player) #ifdef FLOORSPLATS R_ClearVisibleFloorSplats(); #endif - R_RenderViewpoint(&masks[nummasks - 1], false); R_ClipSprites(); @@ -1407,6 +1410,11 @@ void R_RenderPlayerView(player_t *player) #ifdef FLOORSPLATS R_DrawVisibleFloorSplats(); #endif + // well sometimes synchronization is off and may result in some visual glitching, oh well + tp_sema = srb2::g_main_threadpool->end_sema(); + srb2::g_main_threadpool->notify_sema(tp_sema); + srb2::g_main_threadpool->wait_sema(tp_sema); + srb2::g_main_threadpool->begin_sema(); R_DrawMasked(masks, nummasks); } PS_STOP_TIMING(ps_skyboxtime); @@ -1446,7 +1454,12 @@ void R_RenderPlayerView(player_t *player) ps_numbspcalls.value.i = ps_numpolyobjects.value.i = ps_numdrawnodes.value.i = 0; PS_START_TIMING(ps_bsptime); + //tp_sema = srb2::g_main_threadpool->end_sema(); + //srb2::g_main_threadpool->notify_sema(tp_sema); + //srb2::g_main_threadpool->wait_sema(tp_sema); + //srb2::g_main_threadpool->begin_sema(); R_RenderViewpoint(&masks[nummasks - 1], true); + PS_STOP_TIMING(ps_bsptime); PS_START_TIMING(ps_sw_spritecliptime); R_ClipSprites(); @@ -1481,7 +1494,7 @@ void R_RenderPlayerView(player_t *player) validcount++; // Render the BSP from the new viewpoint, and clip - masks = realloc(masks, (++nummasks)*sizeof(maskcount_t)); + masks = static_cast(realloc(masks, (++nummasks)*sizeof(maskcount_t))); // Render the BSP from the new viewpoint, and clip // any sprites with the new clipsegs and window. @@ -1496,6 +1509,9 @@ void R_RenderPlayerView(player_t *player) PS_START_TIMING(ps_sw_planetime); R_DrawPlanes(); + tp_sema = srb2::g_main_threadpool->end_sema(); + srb2::g_main_threadpool->notify_sema(tp_sema); + srb2::g_main_threadpool->wait_sema(tp_sema); PS_STOP_TIMING(ps_sw_planetime); #ifdef FLOORSPLATS R_DrawVisibleFloorSplats(); diff --git a/src/r_main.h b/src/r_main.h index d3284764d..6f62855da 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -14,6 +14,10 @@ #ifndef __R_MAIN__ #define __R_MAIN__ +#ifdef __cplusplus +extern "C" { +#endif + #include "d_player.h" #include "r_data.h" #include "m_perfstats.h" @@ -84,7 +88,7 @@ extern lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ]; // // killough 5/2/98: reformatted // -FUNCINLINE static ATTRINLINE PUREFUNC INT32 R_PointOnSide(fixed_t x, fixed_t y, const node_t *restrict node) +FUNCINLINE static ATTRINLINE PUREFUNC INT32 R_PointOnSide(fixed_t x, fixed_t y, const node_t *node) { if (!node->dx) return x <= node->x ? node->dy > 0 : node->dy < 0; @@ -245,4 +249,9 @@ void R_RegisterEngineStuff(void); INT32 R_GetHudUncap(void); // same as above but keeps interpolation during pause INT32 R_GetMenuUncap(void); + +#ifdef __cplusplus +} // extern "C" +#endif + #endif diff --git a/src/r_plane.c b/src/r_plane.cpp similarity index 87% rename from src/r_plane.c rename to src/r_plane.cpp index d5faa122b..e605d1b8e 100644 --- a/src/r_plane.c +++ b/src/r_plane.cpp @@ -29,6 +29,8 @@ #include "p_tick.h" #include "r_fps.h" #include "r_portal.h" +#include "core/thread_pool.h" + // // opening @@ -91,8 +93,8 @@ static INT16 *ffloor_c_clip; static void R_ReallocPlaneBounds(visplane_t *pl) { - pl->top_memory = Z_Realloc(pl->top_memory, sizeof(UINT16) * (viewwidth + 2), PU_STATIC, NULL); - pl->bottom_memory = Z_Realloc(pl->bottom_memory, sizeof(UINT16) * (viewwidth + 2), PU_STATIC, NULL); + pl->top_memory = static_cast(Z_Realloc(pl->top_memory, sizeof(UINT16) * (viewwidth + 2), PU_STATIC, NULL)); + pl->bottom_memory = static_cast(Z_Realloc(pl->bottom_memory, sizeof(UINT16) * (viewwidth + 2), PU_STATIC, NULL)); pl->top = pl->top_memory + 1; pl->bottom = pl->bottom_memory + 1; } @@ -122,8 +124,8 @@ void R_AllocPlaneMemory(void) } // Alloc ffloor clip tables - ffloor_f_clip = Z_Realloc(ffloor_f_clip, sizeof(*ffloor_f_clip) * (viewwidth * MAXFFLOORS), PU_STATIC, NULL); - ffloor_c_clip = Z_Realloc(ffloor_c_clip, sizeof(*ffloor_c_clip) * (viewwidth * MAXFFLOORS), PU_STATIC, NULL); + ffloor_f_clip = static_cast(Z_Realloc(ffloor_f_clip, sizeof(*ffloor_f_clip) * (viewwidth * MAXFFLOORS), PU_STATIC, NULL)); + ffloor_c_clip = static_cast(Z_Realloc(ffloor_c_clip, sizeof(*ffloor_c_clip) * (viewwidth * MAXFFLOORS), PU_STATIC, NULL)); for (unsigned i = 0; i < MAXFFLOORS; i++) { @@ -131,8 +133,8 @@ void R_AllocPlaneMemory(void) ffloor[i].c_clip = ffloor_c_clip + (i * viewwidth); } - yslopetab = Z_Realloc(yslopetab, sizeof(*yslopetab) * (viewheight * 16), PU_STATIC, NULL); - spanstart = Z_Realloc(spanstart, sizeof(*spanstart) * viewheight, PU_STATIC, NULL); + yslopetab = static_cast(Z_Realloc(yslopetab, sizeof(*yslopetab) * (viewheight * 16), PU_STATIC, NULL)); + spanstart = static_cast(Z_Realloc(spanstart, sizeof(*spanstart) * viewheight, PU_STATIC, NULL)); } // @@ -225,6 +227,19 @@ static void R_HandleRipplePlane(drawspandata_t* ds, visplane_t *pl) } } + +static bool R_CheckMapPlane(const char* funcname, INT32 y, INT32 x1, INT32 x2) +{ + if (x1 == x2) + return true; + + if (x1 < x2 && x1 >= 0 && x2 < viewwidth && y >= 0 && y < viewheight) + return true; + + CONS_Debug(DBG_RENDER, "%s: x1=%d, x2=%d at y=%d\n", funcname, x1, x2, y); + return false; +} + // // R_MapPlane // @@ -237,16 +252,14 @@ static void R_HandleRipplePlane(drawspandata_t* ds, visplane_t *pl) // viewsin // viewcos // viewheight -static void R_MapPlane(drawspandata_t *ds, INT32 y, INT32 x1, INT32 x2) +static void R_MapPlane(drawspandata_t *ds, INT32 y, INT32 x1, INT32 x2, boolean allow_parallel) { angle_t angle, planecos, planesin; fixed_t distance = 0, span; size_t pindex; -#ifdef RANGECHECK - if (x2 < x1 || x1 < 0 || x2 >= viewwidth || y > viewheight) - I_Error("R_MapPlane: %d, %d at %d", x1, x2, y); -#endif + if (!R_CheckMapPlane(__func__, y, x1, x2)) + return; if (x1 >= vid.width) x1 = vid.width - 1; @@ -383,11 +396,11 @@ static visplane_t *new_visplane(unsigned hash) visplane_t *check = freetail; if (!check) { - check = calloc(1, sizeof (*check)); + check = static_cast(calloc(1, sizeof (*check))); if (check == NULL) I_Error("new_visplane: Out of memory"); - check->top_memory = Z_Malloc(sizeof(UINT16) * (viewwidth + 2), PU_STATIC, NULL); - check->bottom_memory = Z_Malloc(sizeof(UINT16) * (viewwidth + 2), PU_STATIC, NULL); + check->top_memory = static_cast(Z_Malloc(sizeof(UINT16) * (viewwidth + 2), PU_STATIC, NULL)); + check->bottom_memory = static_cast(Z_Malloc(sizeof(UINT16) * (viewwidth + 2), PU_STATIC, NULL)); check->top = check->top_memory + 1; check->bottom = check->bottom_memory + 1; } @@ -648,7 +661,7 @@ void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop) // // R_MakeSpans // -static void R_MakeSpans(drawspandata_t* ds, INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2) +static void R_MakeSpans(drawspandata_t* ds, INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2, boolean allow_parallel) { // Alam: from r_splats's R_RenderFloorSplat if (t1 >= vid.height) t1 = vid.height-1; @@ -657,17 +670,69 @@ static void R_MakeSpans(drawspandata_t* ds, INT32 x, INT32 t1, INT32 b1, INT32 t if (b2 >= vid.height) b2 = vid.height-1; if (x-1 >= vid.width) x = vid.width; + // We want to draw N spans per subtask to ensure the work is + // coarse enough to not be too slow due to task scheduling overhead. + // To safely do this, we need to copy part of spanstart to a local. + // This is essentially loop unrolling across threads. + constexpr const int kSpanTaskGranularity = 8; drawspandata_t dc_copy = *ds; - while (t1 < t2 && t1 <= b1) { - R_MapPlane(&dc_copy, t1, spanstart[t1], x - 1); - t1++; + INT32 spanstartcopy[kSpanTaskGranularity] = {0}; + INT32 taskspans = 0; + for (int i = 0; i < kSpanTaskGranularity; i++) + { + if (!((t1 + i) < t2 && (t1 + i) <= b1)) + { + break; + } + spanstartcopy[i] = spanstart[t1 + i]; + taskspans += 1; + } + auto task = [=]() mutable -> void { + for (int i = 0; i < taskspans; i++) + { + R_MapPlane(&dc_copy, t1 + i, spanstartcopy[i], x - 1, false); + } + }; + if (allow_parallel) + { + srb2::g_main_threadpool->schedule(std::move(task)); + } + else + { + (task)(); + } + t1 += taskspans; } while (b1 > b2 && b1 >= t1) { - R_MapPlane(&dc_copy, b1, spanstart[b1], x - 1); - b1--; + INT32 spanstartcopy[kSpanTaskGranularity] = {0}; + INT32 taskspans = 0; + for (int i = 0; i < kSpanTaskGranularity; i++) + { + if (!((b1 - i) > b2 && (b1 - i) >= t1)) + { + break; + } + spanstartcopy[i] = spanstart[b1 - i]; + taskspans += 1; + } + auto task = [=]() mutable -> void { + for (int i = 0; i < taskspans; i++) + { + R_MapPlane(&dc_copy, b1 - i, spanstartcopy[i], x - 1, false); + } + }; + if (allow_parallel) + { + srb2::g_main_threadpool->schedule(std::move(task)); + } + else + { + (task)(); + } + b1 -= taskspans; } while (t2 < t1 && t2 <= b2) @@ -692,14 +757,14 @@ void R_DrawPlanes(void) if (pl->ffloor != NULL || pl->polyobj != NULL) continue; - R_DrawSinglePlane(&ds, pl); + R_DrawSinglePlane(&ds, pl, true); } } R_UpdatePlaneRipple(&ds); } -static void R_DrawSkyPlane(visplane_t *pl) +static void R_DrawSkyPlane(visplane_t *pl, boolean allow_parallel) { INT32 x; drawcolumndata_t dc = {0}; @@ -727,30 +792,54 @@ static void R_DrawSkyPlane(visplane_t *pl) dc.texheight = textureheight[skytexture] >>FRACBITS; dc.sourcelength = dc.texheight; + x = pl->minx; + // Precache the texture so we don't corrupt the zoned heap off-main thread if (!texturecache[texturetranslation[skytexture]]) { R_GenerateTexture(texturetranslation[skytexture]); } - for (x = pl->minx; x <= pl->maxx; x++) + while (x <= pl->maxx) { - dc.yl = pl->top[x]; - dc.yh = pl->bottom[x]; + // Tune concurrency granularity here to maximize throughput + // The cheaper colfunc is, the more coarse the task should be + constexpr const int kSkyPlaneMacroColumns = 8; - if (dc.yl > dc.yh) + auto thunk = [=]() mutable -> void { + for (int i = 0; i < kSkyPlaneMacroColumns && i + x <= pl->maxx; i++) + { + dc.yl = pl->top[x + i]; + dc.yh = pl->bottom[x + i]; + + if (dc.yl > dc.yh) + { + continue; + } + + INT32 angle = (pl->viewangle + xtoviewangle[x + i])>>ANGLETOSKYSHIFT; + dc.iscale = FixedMul(skyscale, FINECOSINE(xtoviewangle[x + i]>>ANGLETOFINESHIFT)); + dc.x = x + i; + dc.source = + R_GetColumn(texturetranslation[skytexture], + -angle); // get negative of angle for each column to display sky correct way round! --Monster Iestyn 27/01/18 + + colfunc(&dc); + } + }; + + if (allow_parallel) { - continue; + srb2::g_main_threadpool->schedule(std::move(thunk)); + } + else + { + (thunk)(); } - INT32 angle = (pl->viewangle + xtoviewangle[x])>>ANGLETOSKYSHIFT; - dc.iscale = FixedMul(skyscale, FINECOSINE(xtoviewangle[x]>>ANGLETOFINESHIFT)); - dc.x = x; - dc.source = - R_GetColumn(texturetranslation[skytexture], - -angle); // get negative of angle for each column to display sky correct way round! --Monster Iestyn 27/01/18 - wallcolfunc(&dc); + x += kSkyPlaneMacroColumns; } + } // Potentially override other stuff for now cus we're mean. :< But draw a slope plane! @@ -833,11 +922,11 @@ d.z = (v1.x * v2.y) - (v1.y * v2.x) static void R_SetSlopePlaneVectors(drawspandata_t* ds, visplane_t *pl, INT32 y, fixed_t xoff, fixed_t yoff, float fudge) { if (ds_su == NULL) - ds_su = Z_Malloc(sizeof(*ds_su) * vid.height, PU_STATIC, NULL); + ds_su = static_cast(Z_Malloc(sizeof(*ds_su) * vid.height, PU_STATIC, NULL)); if (ds_sv == NULL) - ds_sv = Z_Malloc(sizeof(*ds_sv) * vid.height, PU_STATIC, NULL); + ds_sv = static_cast(Z_Malloc(sizeof(*ds_sv) * vid.height, PU_STATIC, NULL)); if (ds_sz == NULL) - ds_sz = Z_Malloc(sizeof(*ds_sz) * vid.height, PU_STATIC, NULL); + ds_sz = static_cast(Z_Malloc(sizeof(*ds_sz) * vid.height, PU_STATIC, NULL)); ds->sup = ds_su[y]; ds->svp = ds_sv[y]; @@ -846,7 +935,7 @@ static void R_SetSlopePlaneVectors(drawspandata_t* ds, visplane_t *pl, INT32 y, R_CalculateSlopeVectors(ds, pl->slope, pl->viewx, pl->viewy, pl->viewz, FRACUNIT, FRACUNIT, xoff, yoff, pl->viewangle, pl->plangle, fudge); } -void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl) +void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_parallel) { INT32 light = 0; INT32 x; @@ -860,7 +949,7 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl) // sky flat if (pl->picnum == skyflatnum) { - R_DrawSkyPlane(pl); + R_DrawSkyPlane(pl, allow_parallel); return; } @@ -1128,7 +1217,7 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl) for (x = pl->minx; x <= stop; x++) { - R_MakeSpans(ds, x, pl->top[x-1], pl->bottom[x-1], pl->top[x], pl->bottom[x]); + R_MakeSpans(ds, x, pl->top[x-1], pl->bottom[x-1], pl->top[x], pl->bottom[x], allow_parallel); } /* diff --git a/src/r_plane.h b/src/r_plane.h index dbaaac306..78b92cc83 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -14,6 +14,10 @@ #ifndef __R_PLANE__ #define __R_PLANE__ +#ifdef __cplusplus +extern "C" { +#endif + #include "screen.h" // needs MAXVIDWIDTH/MAXVIDHEIGHT #include "r_data.h" #include "p_polyobj.h" @@ -110,4 +114,9 @@ typedef struct planemgr_s extern visffloor_t ffloor[MAXFFLOORS]; extern INT32 numffloors; + +#ifdef __cplusplus +} // extern "C" +#endif + #endif diff --git a/src/r_portal.h b/src/r_portal.h index b45631e0b..62312da54 100644 --- a/src/r_portal.h +++ b/src/r_portal.h @@ -14,6 +14,10 @@ #ifndef __R_PORTAL__ #define __R_PORTAL__ +#ifdef __cplusplus +extern "C" { +#endif + #include "r_data.h" #include "r_plane.h" // visplanes @@ -56,4 +60,8 @@ void Portal_ClipApply (const portal_t* portal); void Portal_AddSkybox(const visplane_t* plane); void Portal_AddSkyboxPortals(void); +#ifdef __cplusplus +} // extern "C" +#endif + #endif diff --git a/src/r_segs.c b/src/r_segs.c index 3e36db3de..fb671ece4 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -27,6 +27,9 @@ #include "p_slopes.h" #include "console.h" // con_clipviewtop +#include "core/memory.h" +#include "core/thread_pool.h" + // OPTIMIZE: closed two sided lines as single sided // True if any of the segs textures might be visible. @@ -278,12 +281,20 @@ static void R_Render2sidedMultiPatchColumn(drawcolumndata_t* dc, column_t *colum dc->source = (UINT8 *)column + 3; dc->sourcelength = lengthcol; + + // Drawn by R_DrawColumn. + drawcolumndata_t dc_copy = *dc; + void (*colfunccopy)(drawcolumndata_t*); + colfunccopy = colfunc; + if (colfunc == wallcolfunc) - twosmultipatchfunc(dc); + colfunccopy = twosmultipatchfunc; else if (colfunc == fuzzcolfunc) - twosmultipatchtransfunc(dc); + colfunccopy = twosmultipatchtransfunc; else colfunc(dc); + + colfunccopy((drawcolumndata_t*)(&dc_copy)); } } @@ -292,7 +303,7 @@ transnum_t R_GetLinedefTransTable(fixed_t alpha) return (20*(FRACUNIT - alpha - 1) + FRACUNIT) >> (FRACBITS+1); } -void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) +void R_RenderMaskedSegRange(drawseg_t *drawseg, INT32 x1, INT32 x2) { size_t pindex; column_t *col; @@ -314,7 +325,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) // Use different light tables // for horizontal / vertical / diagonal. Diagonal? // OPTIMIZE: get rid of LIGHTSEGSHIFT globally - curline = ds->curline; + curline = drawseg->curline; frontsector = curline->frontsector; backsector = curline->backsector; texnum = R_GetTextureNum(curline->sidedef->midtexture); @@ -359,9 +370,9 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) colfunc = fuzzcolfunc; } - range = max(ds->x2-ds->x1, 1); - rw_scalestep = ds->scalestep; - spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep; + range = max(drawseg->x2-drawseg->x1, 1); + rw_scalestep = drawseg->scalestep; + spryscale = drawseg->scale1 + (x1 - drawseg->x1)*rw_scalestep; // Texture must be cached before setting colfunc_2s, // otherwise texture[texnum]->holes may be false when it shouldn't be @@ -383,8 +394,14 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) dc->numlights = frontsector->numlights; if (dc->numlights >= dc->maxlights) { + r_lightlist_t* old_lightlist = dc->lightlist; + INT32 old_maxlights = dc->maxlights; dc->maxlights = dc->numlights; - dc->lightlist = Z_Realloc(dc->lightlist, sizeof (*dc->lightlist) * dc->maxlights, PU_STATIC, NULL); + dc->lightlist = (Z_Frame_Alloc(sizeof (*dc->lightlist) * dc->maxlights)); + if (old_lightlist != NULL) + { + M_Memcpy(dc->lightlist, old_lightlist, sizeof (*dc->lightlist) * old_maxlights); + } } for (i = 0; i < dc->numlights; i++) @@ -393,14 +410,14 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) light = &frontsector->lightlist[i]; rlight = &dc->lightlist[i]; - leftheight = P_GetLightZAt(light, ds-> leftpos.x, ds-> leftpos.y); - rightheight = P_GetLightZAt(light, ds->rightpos.x, ds->rightpos.y); + leftheight = P_GetLightZAt(light, drawseg-> leftpos.x, drawseg-> leftpos.y); + rightheight = P_GetLightZAt(light, drawseg->rightpos.x, drawseg->rightpos.y); leftheight -= viewz; rightheight -= viewz; - rlight->height = (centeryfrac) - FixedMul(leftheight, ds->scale1); - rlight->heightstep = (centeryfrac) - FixedMul(rightheight, ds->scale2); + rlight->height = (centeryfrac) - FixedMul(leftheight, drawseg->scale1); + rlight->heightstep = (centeryfrac) - FixedMul(rightheight, drawseg->scale2); rlight->heightstep = (rlight->heightstep-rlight->height)/(range); rlight->startheight = rlight->height; // keep starting value here to reset for each repeat rlight->lightlevel = *light->lightlevel; @@ -448,10 +465,10 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) walllights = scalelight[lightnum]; } - maskedtexturecol = ds->maskedtexturecol; + maskedtexturecol = drawseg->maskedtexturecol; - mfloorclip = ds->sprbottomclip; - mceilingclip = ds->sprtopclip; + mfloorclip = drawseg->sprbottomclip; + mceilingclip = drawseg->sprtopclip; if (frontsector->heightsec != -1) front = §ors[frontsector->heightsec]; @@ -463,8 +480,8 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) else back = backsector; - if (ds->curline->sidedef->repeatcnt) - repeats = 1 + ds->curline->sidedef->repeatcnt; + if (drawseg->curline->sidedef->repeatcnt) + repeats = 1 + drawseg->curline->sidedef->repeatcnt; else if (ldef->flags & ML_EFFECT5) { fixed_t high, low; @@ -490,8 +507,8 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) { if (times > 0) { - rw_scalestep = ds->scalestep; - spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep; + rw_scalestep = drawseg->scalestep; + spryscale = drawseg->scale1 + (x1 - drawseg->x1)*rw_scalestep; if (dc->numlights) { // reset all lights to their starting heights for (i = 0; i < dc->numlights; i++) @@ -507,7 +524,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) // draw the columns for (dc->x = x1; dc->x <= x2; dc->x++) { - dc->texturemid = ds->maskedtextureheight[dc->x]; + dc->texturemid = drawseg->maskedtextureheight[dc->x]; if (!!(curline->linedef->flags & ML_DONTPEGBOTTOM) ^ !!(curline->linedef->flags & ML_EFFECT3)) dc->texturemid += (textureheight[texnum])*times + textureheight[texnum]; @@ -667,7 +684,7 @@ static boolean R_IsFFloorTranslucent(visffloor_t *pfloor) // // R_RenderThickSideRange // Renders all the thick sides in the given range. -void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) +void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pfloor) { size_t pindex = 0; column_t * col; @@ -702,7 +719,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) // for horizontal / vertical / diagonal. Diagonal? // OPTIMIZE: get rid of LIGHTSEGSHIFT globally - curline = ds->curline; + curline = drawseg->curline; backsector = pfloor->target; frontsector = curline->frontsector == pfloor->target ? curline->backsector : curline->frontsector; texnum = R_GetTextureNum(sides[pfloor->master->sidenum[0]].midtexture); @@ -739,10 +756,10 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) else if (pfloor->flags & FF_FOG) colfunc = R_DrawFogColumn; - range = max(ds->x2-ds->x1, 1); + range = max(drawseg->x2-drawseg->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; + rw_scalestep = drawseg->scalestep; + spryscale = drawseg->scale1 + (x1 - drawseg->x1)*rw_scalestep; dc->numlights = 0; if (frontsector->numlights) @@ -750,8 +767,14 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) dc->numlights = frontsector->numlights; if (dc->numlights > dc->maxlights) { + r_lightlist_t* old_lightlist = dc->lightlist; + INT32 old_maxlights = dc->maxlights; dc->maxlights = dc->numlights; - dc->lightlist = Z_Realloc(dc->lightlist, sizeof (*dc->lightlist) * dc->maxlights, PU_STATIC, NULL); + dc->lightlist = (Z_Frame_Alloc(sizeof (*dc->lightlist) * dc->maxlights)); + if (old_lightlist != NULL) + { + M_Memcpy(dc->lightlist, old_lightlist, sizeof (*dc->lightlist) * old_maxlights); + } } for (i = p = 0; i < dc->numlights; i++) @@ -763,8 +786,8 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) rlight = &dc->lightlist[p]; #define SLOPEPARAMS(slope, end1, end2, normalheight) \ - end1 = P_GetZAt(slope, ds->leftpos.x, ds->leftpos.y, normalheight); \ - end2 = P_GetZAt(slope, ds->rightpos.x, ds->rightpos.y, normalheight); + end1 = P_GetZAt(slope, drawseg->leftpos.x, drawseg->leftpos.y, normalheight); \ + end2 = P_GetZAt(slope, drawseg->rightpos.x, drawseg->rightpos.y, normalheight); SLOPEPARAMS(light->slope, leftheight, rightheight, light->height) SLOPEPARAMS(*pfloor->b_slope, pfloorleft, pfloorright, *pfloor->bottomheight) @@ -777,8 +800,8 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) if (leftheight > pfloorleft && rightheight > pfloorright && i+1 < dc->numlights) { lightlist_t *nextlight = &frontsector->lightlist[i+1]; - if ((P_GetLightZAt(nextlight, ds->leftpos.x, ds->leftpos.y) > pfloorleft) - && (P_GetLightZAt(nextlight, ds->rightpos.x, ds->rightpos.y) > pfloorright)) + if ((P_GetLightZAt(nextlight, drawseg->leftpos.x, drawseg->leftpos.y) > pfloorleft) + && (P_GetLightZAt(nextlight, drawseg->rightpos.x, drawseg->rightpos.y) > pfloorright)) continue; } @@ -788,12 +811,12 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) #define CLAMPMAX INT32_MAX #define CLAMPMIN (-INT32_MAX) // This is not INT32_MIN on purpose! INT32_MIN makes the drawers freak out. // Monster Iestyn (25/03/18): do not skip these lights if they fail overflow test, just clamp them instead so they behave. - overflow_test = (INT64)centeryfrac - (((INT64)leftheight*ds->scale1)>>FRACBITS); + overflow_test = (INT64)centeryfrac - (((INT64)leftheight*drawseg->scale1)>>FRACBITS); if (overflow_test > (INT64)CLAMPMAX) rlight->height = CLAMPMAX; else if (overflow_test > (INT64)CLAMPMIN) rlight->height = (fixed_t)overflow_test; else rlight->height = CLAMPMIN; - overflow_test = (INT64)centeryfrac - (((INT64)rightheight*ds->scale2)>>FRACBITS); + overflow_test = (INT64)centeryfrac - (((INT64)rightheight*drawseg->scale2)>>FRACBITS); if (overflow_test > (INT64)CLAMPMAX) rlight->heightstep = CLAMPMAX; else if (overflow_test > (INT64)CLAMPMIN) rlight->heightstep = (fixed_t)overflow_test; else rlight->heightstep = CLAMPMIN; @@ -807,12 +830,12 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) rightheight -= viewz; // Monster Iestyn (25/03/18): do not skip these lights if they fail overflow test, just clamp them instead so they behave. - overflow_test = (INT64)centeryfrac - (((INT64)leftheight*ds->scale1)>>FRACBITS); + overflow_test = (INT64)centeryfrac - (((INT64)leftheight*drawseg->scale1)>>FRACBITS); if (overflow_test > (INT64)CLAMPMAX) rlight->botheight = CLAMPMAX; else if (overflow_test > (INT64)CLAMPMIN) rlight->botheight = (fixed_t)overflow_test; else rlight->botheight = CLAMPMIN; - overflow_test = (INT64)centeryfrac - (((INT64)rightheight*ds->scale2)>>FRACBITS); + overflow_test = (INT64)centeryfrac - (((INT64)rightheight*drawseg->scale2)>>FRACBITS); if (overflow_test > (INT64)CLAMPMAX) rlight->botheightstep = CLAMPMAX; else if (overflow_test > (INT64)CLAMPMIN) rlight->botheightstep = (fixed_t)overflow_test; else rlight->botheightstep = CLAMPMIN; @@ -864,15 +887,15 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) walllights = scalelight[lightnum]; } - maskedtexturecol = ds->thicksidecol; + maskedtexturecol = drawseg->thicksidecol; - mfloorclip = ds->sprbottomclip; - mceilingclip = ds->sprtopclip; + mfloorclip = drawseg->sprbottomclip; + mceilingclip = drawseg->sprtopclip; dc->texheight = textureheight[texnum]>>FRACBITS; - // calculate both left ends - left_top = P_GetFFloorTopZAt (pfloor, ds->leftpos.x, ds->leftpos.y) - viewz; - left_bottom = P_GetFFloorBottomZAt(pfloor, ds->leftpos.x, ds->leftpos.y) - viewz; + // calculate both left endrawseg + left_top = P_GetFFloorTopZAt (pfloor, drawseg->leftpos.x, drawseg->leftpos.y) - viewz; + left_bottom = P_GetFFloorBottomZAt(pfloor, drawseg->leftpos.x, drawseg->leftpos.y) - viewz; skewslope = *pfloor->t_slope; // skew using top slope by default @@ -942,20 +965,20 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) fixed_t right_top, right_bottom; // calculate right ends now - right_top = P_GetFFloorTopZAt (pfloor, ds->rightpos.x, ds->rightpos.y) - viewz; - right_bottom = P_GetFFloorBottomZAt(pfloor, ds->rightpos.x, ds->rightpos.y) - viewz; + right_top = P_GetFFloorTopZAt (pfloor, drawseg->rightpos.x, drawseg->rightpos.y) - viewz; + right_bottom = P_GetFFloorBottomZAt(pfloor, drawseg->rightpos.x, drawseg->rightpos.y) - viewz; // using INT64 to avoid 32bit overflow - top_frac = (INT64)centeryfrac - (((INT64)left_top * ds->scale1) >> FRACBITS); - bottom_frac = (INT64)centeryfrac - (((INT64)left_bottom * ds->scale1) >> FRACBITS); - top_step = (INT64)centeryfrac - (((INT64)right_top * ds->scale2) >> FRACBITS); - bottom_step = (INT64)centeryfrac - (((INT64)right_bottom * ds->scale2) >> FRACBITS); + top_frac = (INT64)centeryfrac - (((INT64)left_top * drawseg->scale1) >> FRACBITS); + bottom_frac = (INT64)centeryfrac - (((INT64)left_bottom * drawseg->scale1) >> FRACBITS); + top_step = (INT64)centeryfrac - (((INT64)right_top * drawseg->scale2) >> FRACBITS); + bottom_step = (INT64)centeryfrac - (((INT64)right_bottom * drawseg->scale2) >> FRACBITS); top_step = (top_step-top_frac)/(range); bottom_step = (bottom_step-bottom_frac)/(range); - top_frac += top_step * (x1 - ds->x1); - bottom_frac += bottom_step * (x1 - ds->x1); + top_frac += top_step * (x1 - drawseg->x1); + bottom_frac += bottom_step * (x1 - drawseg->x1); } // draw the columns @@ -2454,11 +2477,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (frontsector->numlights) { dc.numlights = frontsector->numlights; - if (dc.numlights >= dc.maxlights) - { - dc.maxlights = dc.numlights; - dc.lightlist = Z_Realloc(dc.lightlist, sizeof (*dc.lightlist) * dc.maxlights, PU_STATIC, NULL); - } + dc.maxlights = dc.numlights; + dc.lightlist = (Z_Frame_Alloc(sizeof(*dc.lightlist) * dc.maxlights)); for (i = p = 0; i < dc.numlights; i++) { diff --git a/src/r_segs.h b/src/r_segs.h index 23d4ec36b..27dbbe54f 100644 --- a/src/r_segs.h +++ b/src/r_segs.h @@ -14,6 +14,10 @@ #ifndef __R_SEGS__ #define __R_SEGS__ +#ifdef __cplusplus +extern "C" { +#endif + #ifdef __GNUG__ #pragma interface #endif @@ -26,4 +30,8 @@ void R_AllocSegMemory(void); transnum_t R_GetLinedefTransTable(fixed_t alpha); +#ifdef __cplusplus +} // extern "C" +#endif + #endif diff --git a/src/r_things.c b/src/r_things.c index 88433c793..17cf5a155 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2944,7 +2944,7 @@ static void R_DrawMaskedList (drawnode_t* head) if (r2->plane) { next = r2->prev; - R_DrawSinglePlane(&ds, r2->plane); + R_DrawSinglePlane(&ds, r2->plane, false); R_DoneWithNode(r2); r2 = next; } diff --git a/src/r_things.h b/src/r_things.h index 79d4dea11..f4752d166 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -14,6 +14,10 @@ #ifndef __R_THINGS__ #define __R_THINGS__ +#ifdef __cplusplus +extern "C" { +#endif + #include "sounds.h" #include "r_plane.h" #include "r_patch.h" @@ -310,4 +314,8 @@ FUNCMATH FUNCINLINE static ATTRINLINE boolean R_ValidSpriteAngle(UINT8 rotation) return ((rotation <= 8) || (rotation == ROT_L) || (rotation == ROT_R)); } +#ifdef __cplusplus +} // extern "C" +#endif + #endif //__R_THINGS__ diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index afda0caa2..84d0fb218 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -189,6 +189,9 @@ static char returnWadPath[256]; #include "../r_main.h" // Frame interpolation/uncapped #include "../r_fps.h" +#include "../s_sound.h" +#include "../core/thread_pool.h" + #ifdef MAC_ALERT #include "macosx/mac_alert.h" #endif @@ -493,6 +496,15 @@ static void I_ReportSignal(int num, int coredumped) #ifndef NEWSIGNALHANDLER FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num) { + if (g_main_thread_id != std::this_thread::get_id()) + { + // Do not attempt any sort of recovery if this signal triggers off the main thread + signal(num, SIG_DFL); + raise(num); + exit(-2); + } + + g_in_exiting_signal_handler = true; D_QuitNetGame(); // Fix server freezes @@ -1524,7 +1536,7 @@ void I_SetGamepadIndicatorColor(INT32 playernum, UINT8 red, UINT8 green, UINT8 b #define DEG2RAD (0.017453292519943295769236907684883l) // TAU/360 or PI/180 #define MUMBLEUNIT (64.0f) // FRACUNITS in a Meter -static struct { +static struct mumble_s { #ifdef WINMUMBLE UINT32 uiVersion; DWORD uiTick; @@ -1557,7 +1569,7 @@ static void I_SetupMumble(void) if (!hMap) return; - mumble = MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(*mumble)); + mumble = static_cast(MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(*mumble))); if (!mumble) CloseHandle(hMap); #elif defined (HAVE_SHM) @@ -1570,7 +1582,7 @@ static void I_SetupMumble(void) if(shmfd < 0) return; - mumble = mmap(NULL, sizeof(*mumble), PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0); + mumble = (mmap(NULL, sizeof(*mumble), PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0)); if (mumble == MAP_FAILED) mumble = NULL; #endif @@ -1586,7 +1598,7 @@ void I_UpdateMumble(const mobj_t *mobj, const listener_t listener) return; if(mumble->uiVersion != 2) { - wcsncpy(mumble->name, L"SRB2Kart "VERSIONSTRINGW, 256); + wcsncpy(mumble->name, L"SRB2Kart " VERSIONSTRINGW, 256); wcsncpy(mumble->description, L"Sonic Robo Blast 2 Kart with integrated Mumble Link support.", 2048); mumble->uiVersion = 2; } @@ -1900,6 +1912,8 @@ INT32 I_StartupSystem(void) #ifdef HAVE_THREADS I_start_threads(); I_AddExitFunc(I_stop_threads); + I_ThreadPoolInit(); + I_AddExitFunc(I_ThreadPoolShutdown); #endif I_RegisterSignals(); I_OutputMsg("Compiled for SDL version: %d.%d.%d\n", @@ -2373,7 +2387,7 @@ const char *I_ClipboardPaste(void) */ static boolean isWadPathOk(const char *path) { - char *wad3path = malloc(256); + char *wad3path = (malloc(256)); if (!wad3path) return false; diff --git a/src/tables.h b/src/tables.h index 4856c90ea..2f492bebb 100644 --- a/src/tables.h +++ b/src/tables.h @@ -14,6 +14,10 @@ #ifndef __TABLES__ #define __TABLES__ +#ifdef __cplusplus +extern "C" { +#endif + #ifdef LINUX #include #endif @@ -134,4 +138,8 @@ void FM_Rotate(matrix_t *dest, angle_t angle, fixed_t x, fixed_t y, fixed_t z); #define FSIN(n) FINESINE(ANGLETOFINE(n)) #define FCOS(n) FINECOSINE(ANGLETOFINE(n)) +#ifdef __cplusplus +} // extern "C" +#endif + #endif diff --git a/src/v_video.h b/src/v_video.h index d60496dfb..d5a4adf5e 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -14,6 +14,10 @@ #ifndef __V_VIDEO__ #define __V_VIDEO__ +#ifdef __cplusplus +extern "C" { +#endif + #include "doomdef.h" #include "doomtype.h" #include "r_defs.h" @@ -285,4 +289,8 @@ void V_DrawHorizontallyScaledFullScreenPatch(patch_t *patch); void VID_BlitLinearScreen(const UINT8 *srcptr, UINT8 *destptr, INT32 width, INT32 height, size_t srcrowbytes, size_t destrowbytes); +#ifdef __cplusplus +} // extern "C" +#endif + #endif diff --git a/src/w_wad.h b/src/w_wad.h index 12ad8cea7..9b1035fa2 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -14,6 +14,10 @@ #ifndef __W_WAD__ #define __W_WAD__ +#ifdef __cplusplus +extern "C" { +#endif + #ifdef HWRENDER #include "hardware/hw_data.h" #endif @@ -233,4 +237,8 @@ int W_VerifyNMUSlumps(const char *filename); int W_CheckPostLoadList(const char *filename); +#ifdef __cplusplus +} // extern "C" +#endif + #endif // __W_WAD__ diff --git a/src/z_zone.h b/src/z_zone.h index 41ea1d669..ab908bfec 100644 --- a/src/z_zone.h +++ b/src/z_zone.h @@ -14,6 +14,10 @@ #ifndef __Z_ZONE__ #define __Z_ZONE__ +#ifdef __cplusplus +extern "C" { +#endif + #include #include "doomdef.h" #include "doomtype.h" @@ -153,4 +157,8 @@ size_t Z_TagsUsage(INT32 lowtag, INT32 hightag); // char *Z_StrDup(const char *in); +#ifdef __cplusplus +} // extern "C" +#endif + #endif -- 2.54.0 From 0a2eac4d3aa217820a473736ca86f88504e8894a Mon Sep 17 00:00:00 2001 From: Indev Date: Thu, 5 Jun 2025 18:28:55 +0300 Subject: [PATCH 023/141] Add ifdef __cplusplus into hardware/hw_main.h --- src/hardware/hw_main.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 6dc0d23a6..9fd4faa5d 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -34,6 +34,10 @@ #define GLENCORE +#ifdef __cplusplus +extern "C" { +#endif + // Startup & Shutdown the hardware mode renderer void HWR_Startup(void); void HWR_Shutdown(void); @@ -228,4 +232,8 @@ FUNCINLINE static ATTRINLINE boolean HWR_PalRenderFlashpal(void) return (cv_glflashpal.value && HWR_ShouldUsePaletteRendering()); } +#ifdef __cplusplus +}// extern "C" +#endif + #endif -- 2.54.0 From 1fd7e9cdac0e31076639ea347f389c53b7c57dc2 Mon Sep 17 00:00:00 2001 From: Indev Date: Thu, 5 Jun 2025 18:30:24 +0300 Subject: [PATCH 024/141] Add -lpthread into libs and cxxopts into c++ compilation flags --- src/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Makefile b/src/Makefile index 6713bc624..11e6c238e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -262,7 +262,7 @@ opts+=$(debug_opts) opts+=$(foreach v,$(passthru_opts),$(if $($(v)),-D$(v))) opts+=$(WFLAGS) $(CPPFLAGS) $(CFLAGS) -libs+=$(LDFLAGS) -lstdc++ +libs+=$(LDFLAGS) -lstdc++ -lpthread asflags:=$(ASFLAGS) -x assembler-with-cpp cxxopts:=$(opts) @@ -405,7 +405,7 @@ $(objdir)/%.$(1) : %.$(2) | $$$$(@D)/ endef $(eval $(call _recipe,o,c,$(cc) -c -o $$@ $$<)) -$(eval $(call _recipe,o,cpp,$(cxx) -c -o $$@ $$<)) +$(eval $(call _recipe,o,cpp,$(cxx) $(cxxopts) -c -o $$@ $$<)) $(eval $(call _recipe,o,s,$(cc) $(asflags) -c -o $$@ $$<)) $(eval $(call _recipe,res,rc,$(windres) -i $$< -o $$@)) -- 2.54.0 From 98cb0fdcb2fd54e9c18ade7df6ddf474f0cc4f00 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 5 Jun 2025 21:29:56 +0200 Subject: [PATCH 025/141] fix slopes and other shit --- src/r_draw.h | 3 - src/r_plane.cpp | 215 +++++++++++++++++++++++++++--------------------- 2 files changed, 121 insertions(+), 97 deletions(-) diff --git a/src/r_draw.h b/src/r_draw.h index 5a57ae978..f2e6e8050 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -79,9 +79,6 @@ typedef struct fixed_t xoffs; fixed_t yoffs; - UINT16 flatwidth; - UINT16 flatheight; - visplane_t *currentplane; UINT8 *source; UINT8 *transmap; diff --git a/src/r_plane.cpp b/src/r_plane.cpp index e605d1b8e..bc4007162 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -30,7 +30,10 @@ #include "r_fps.h" #include "r_portal.h" #include "core/thread_pool.h" +#include +static void R_SetSlopePlaneVectors(drawspandata_t* ds, visplane_t *pl, INT32 y, fixed_t xoff, fixed_t yoff, float fudge); +static void R_SetTiltedSpan(drawspandata_t* ds, INT32 span); // // opening @@ -86,8 +89,6 @@ fixed_t *yslope; fixed_t basexscale, baseyscale; -static fixed_t xoffs, yoffs; - static INT16 *ffloor_f_clip; static INT16 *ffloor_c_clip; @@ -252,7 +253,7 @@ static bool R_CheckMapPlane(const char* funcname, INT32 y, INT32 x1, INT32 x2) // viewsin // viewcos // viewheight -static void R_MapPlane(drawspandata_t *ds, INT32 y, INT32 x1, INT32 x2, boolean allow_parallel) +static void R_MapPlane(drawspandata_t *ds, void(*spanfunc2)(drawspandata_t*), INT32 y, INT32 x1, INT32 x2, boolean allow_parallel) { angle_t angle, planecos, planesin; fixed_t distance = 0, span; @@ -261,51 +262,36 @@ static void R_MapPlane(drawspandata_t *ds, INT32 y, INT32 x1, INT32 x2, boolean if (!R_CheckMapPlane(__func__, y, x1, x2)) return; - if (x1 >= vid.width) - x1 = vid.width - 1; + angle = (ds->currentplane->viewangle + ds->currentplane->plangle)>>ANGLETOFINESHIFT; + planecos = FINECOSINE(angle); + planesin = FINESINE(angle); - if (!ds->currentplane->slope) + // [RH] Notice that I dumped the caching scheme used by Doom. + // It did not offer any appreciable speedup. + distance = FixedMul(ds->planeheight, yslope[y]); + span = abs(centery - y); + + if (span) // don't divide by zero { - angle = (ds->currentplane->viewangle + ds->currentplane->plangle)>>ANGLETOFINESHIFT; - planecos = FINECOSINE(angle); - planesin = FINESINE(angle); - - // [RH] Notice that I dumped the caching scheme used by Doom. - // It did not offer any appreciable speedup. - distance = FixedMul(ds->planeheight, yslope[y]); - span = abs(centery - y); - - if (span) // don't divide by zero - { - ds->xstep = FixedMul(planesin, ds->planeheight) / span; - ds->ystep = FixedMul(planecos, ds->planeheight) / span; - } - else - { - ds->xstep = FixedMul(distance, basexscale); - ds->ystep = FixedMul(distance, baseyscale); - } - - ds->xfrac = xoffs + FixedMul(planecos, distance) + (x1 - centerx) * ds->xstep; - ds->yfrac = yoffs - FixedMul(planesin, distance) + (x1 - centerx) * ds->ystep; + ds->xstep = FixedMul(planesin, ds->planeheight) / span; + ds->ystep = FixedMul(planecos, ds->planeheight) / span; } + else + { + ds->xstep = FixedMul(distance, basexscale); + ds->ystep = FixedMul(distance, baseyscale); + } + + ds->xfrac = ds->xoffs + FixedMul(planecos, distance) + (x1 - centerx) * ds->xstep; + ds->yfrac = ds->yoffs - FixedMul(planesin, distance) + (x1 - centerx) * ds->ystep; if (ds->planeripple.active) { // Needed for ds_bgofs R_CalculatePlaneRipple(ds, ds->currentplane, y, ds->planeheight, (!ds->currentplane->slope)); - if (ds->currentplane->slope) - { - ds->sup = ds_su[y]; - ds->svp = ds_sv[y]; - ds->szp = ds_sz[y]; - } - else - { - ds->xfrac += ds->planeripple.xfrac; - ds->yfrac += ds->planeripple.yfrac; - } + ds->xfrac += ds->planeripple.xfrac; + ds->yfrac += ds->planeripple.yfrac; if ((y + ds->bgofs) >= viewheight) ds->bgofs = viewheight-y-1; @@ -313,15 +299,11 @@ static void R_MapPlane(drawspandata_t *ds, INT32 y, INT32 x1, INT32 x2, boolean ds->bgofs = -y; } - if (ds->currentplane->slope) - ds->colormap = colormaps; - else - { - pindex = distance >> LIGHTZSHIFT; - if (pindex >= MAXLIGHTZ) - pindex = MAXLIGHTZ - 1; - ds->colormap = ds->planezlight[pindex]; - } + pindex = distance >> LIGHTZSHIFT; + if (pindex >= MAXLIGHTZ) + pindex = MAXLIGHTZ - 1; + ds->colormap = ds->planezlight[pindex]; + if (encoremap && !ds->currentplane->noencore) ds->colormap += COLORMAP_REMAPOFFSET; @@ -332,7 +314,45 @@ static void R_MapPlane(drawspandata_t *ds, INT32 y, INT32 x1, INT32 x2, boolean ds->x1 = x1; ds->x2 = x2; - spanfunc(ds); + spanfunc2(ds); +} + +static void R_MapTiltedPlane(drawspandata_t *ds, void(*spanfunc2)(drawspandata_t*), INT32 y, INT32 x1, INT32 x2, boolean allow_parallel) +{ + if (!R_CheckMapPlane(__func__, y, x1, x2)) + return; + + // Water ripple effect + if (ds->planeripple.active) + { + R_SetTiltedSpan(ds, std::clamp(y, 0, viewheight)); + + R_CalculatePlaneRipple(ds, ds->currentplane, y, ds->planeheight, false); + R_SetSlopePlaneVectors(ds, ds->currentplane, y, (ds->xoffs + ds->planeripple.xfrac), (ds->yoffs + ds->planeripple.yfrac), 0); + + if ((y + ds->bgofs) >= viewheight) + ds->bgofs = viewheight-y-1; + if ((y + ds->bgofs) < 0) + ds->bgofs = -y; + } + + if (ds->currentplane->extra_colormap) + ds->colormap = ds->currentplane->extra_colormap->colormap; + else + ds->colormap = colormaps; + + ds->fullbright = colormaps; + if (encoremap && !ds->currentplane->noencore) + { + ds->colormap += COLORMAP_REMAPOFFSET; + ds->fullbright += COLORMAP_REMAPOFFSET; + } + + ds->y = y; + ds->x1 = x1; + ds->x2 = x2; + + spanfunc2(ds); } void R_ClearFFloorClips(void) @@ -661,7 +681,7 @@ void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop) // // R_MakeSpans // -static void R_MakeSpans(drawspandata_t* ds, INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2, boolean allow_parallel) +static void R_MakeSpans(void (*mapfunc)(drawspandata_t* ds, void(*spanfunc)(drawspandata_t*), INT32, INT32, INT32, boolean), void(*spanfunc2)(drawspandata_t*), drawspandata_t* ds, INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2, boolean allow_parallel) { // Alam: from r_splats's R_RenderFloorSplat if (t1 >= vid.height) t1 = vid.height-1; @@ -692,7 +712,7 @@ static void R_MakeSpans(drawspandata_t* ds, INT32 x, INT32 t1, INT32 b1, INT32 t auto task = [=]() mutable -> void { for (int i = 0; i < taskspans; i++) { - R_MapPlane(&dc_copy, t1 + i, spanstartcopy[i], x - 1, false); + mapfunc(&dc_copy, spanfunc2, t1 + i, spanstartcopy[i], x - 1, false); } }; if (allow_parallel) @@ -721,7 +741,7 @@ static void R_MakeSpans(drawspandata_t* ds, INT32 x, INT32 t1, INT32 b1, INT32 t auto task = [=]() mutable -> void { for (int i = 0; i < taskspans; i++) { - R_MapPlane(&dc_copy, b1 - i, spanstartcopy[i], x - 1, false); + mapfunc(&dc_copy, spanfunc2, b1 - i, spanstartcopy[i], x - 1, false); } }; if (allow_parallel) @@ -764,7 +784,7 @@ void R_DrawPlanes(void) R_UpdatePlaneRipple(&ds); } -static void R_DrawSkyPlane(visplane_t *pl, boolean allow_parallel) +static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), boolean allow_parallel) { INT32 x; drawcolumndata_t dc = {0}; @@ -824,7 +844,7 @@ static void R_DrawSkyPlane(visplane_t *pl, boolean allow_parallel) R_GetColumn(texturetranslation[skytexture], -angle); // get negative of angle for each column to display sky correct way round! --Monster Iestyn 27/01/18 - colfunc(&dc); + colfunc2(&dc); } }; @@ -919,19 +939,23 @@ d.z = (v1.x * v2.y) - (v1.y * v2.x) #undef SFMULT } -static void R_SetSlopePlaneVectors(drawspandata_t* ds, visplane_t *pl, INT32 y, fixed_t xoff, fixed_t yoff, float fudge) +static void R_SetTiltedSpan(drawspandata_t* ds, INT32 span) { if (ds_su == NULL) - ds_su = static_cast(Z_Malloc(sizeof(*ds_su) * vid.height, PU_STATIC, NULL)); + ds_su = static_cast(Z_Calloc(sizeof(*ds_su) * vid.height, PU_STATIC, NULL)); if (ds_sv == NULL) - ds_sv = static_cast(Z_Malloc(sizeof(*ds_sv) * vid.height, PU_STATIC, NULL)); + ds_sv = static_cast(Z_Calloc(sizeof(*ds_sv) * vid.height, PU_STATIC, NULL)); if (ds_sz == NULL) - ds_sz = static_cast(Z_Malloc(sizeof(*ds_sz) * vid.height, PU_STATIC, NULL)); + ds_sz = static_cast(Z_Calloc(sizeof(*ds_sz) * vid.height, PU_STATIC, NULL)); - ds->sup = ds_su[y]; - ds->svp = ds_sv[y]; - ds->szp = ds_sz[y]; + ds->sup = ds_su[span]; + ds->svp = ds_sv[span]; + ds->szp = ds_sz[span]; +} +static void R_SetSlopePlaneVectors(drawspandata_t* ds, visplane_t *pl, INT32 y, fixed_t xoff, fixed_t yoff, float fudge) +{ + R_SetTiltedSpan(ds, y); R_CalculateSlopeVectors(ds, pl->slope, pl->viewx, pl->viewy, pl->viewz, FRACUNIT, FRACUNIT, xoff, yoff, pl->viewangle, pl->plangle, fudge); } @@ -942,6 +966,7 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle INT32 stop, angle; size_t size; ffloor_t *rover; + void (*mapfunc)(drawspandata_t*, void(*)(drawspandata_t*), INT32, INT32, INT32, boolean) = R_MapPlane; if (!(pl->minx <= pl->maxx)) return; @@ -949,7 +974,7 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle // sky flat if (pl->picnum == skyflatnum) { - R_DrawSkyPlane(pl, allow_parallel); + R_DrawSkyPlane(pl, colfunc, allow_parallel); return; } @@ -1100,8 +1125,8 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle break; } - xoffs = pl->xoffs; - yoffs = pl->yoffs; + ds->xoffs = pl->xoffs; + ds->yoffs = pl->yoffs; ds->planeheight = abs(pl->height - pl->viewz); if (light >= LIGHTLEVELS) @@ -1119,6 +1144,8 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle angle_t hack = (pl->plangle & (ANGLE_90-1)); + mapfunc = R_MapTiltedPlane; + if (hack) { /* @@ -1147,28 +1174,28 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle ox = FixedMul(temp,cosinecomponent)+FixedMul(oy,-sinecomponent); // negative sine for opposite direction oy = -FixedMul(temp,-sinecomponent)+FixedMul(oy,cosinecomponent); - temp = xoffs; - xoffs = (FixedMul(temp,cosinecomponent) & modmask) + (FixedMul(yoffs,sinecomponent) & modmask); - yoffs = (-FixedMul(temp,sinecomponent) & modmask) + (FixedMul(yoffs,cosinecomponent) & modmask); + temp = ds->xoffs; + ds->xoffs = (FixedMul(temp,cosinecomponent) & modmask) + (FixedMul(ds->yoffs, sinecomponent) & modmask); + ds->yoffs = (-FixedMul(temp,sinecomponent) & modmask) + (FixedMul(ds->yoffs, cosinecomponent) & modmask); - temp = xoffs & modmask; - yoffs &= modmask; - xoffs = FixedMul(temp,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // ditto - yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent); + temp = ds->xoffs & modmask; + ds->yoffs &= modmask; + ds->xoffs = FixedMul(temp,cosinecomponent)+FixedMul(ds->yoffs, -sinecomponent); // ditto + ds->yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(ds->yoffs, cosinecomponent); - xoffs -= (pl->slope->o.x - ox); - yoffs += (pl->slope->o.y + oy); + ds->xoffs -= (pl->slope->o.x - ox); + ds->yoffs += (pl->slope->o.y + oy); } else { - xoffs &= ((1 << (32-ds->nflatshiftup))-1); - yoffs &= ((1 << (32-ds->nflatshiftup))-1); - xoffs -= (pl->slope->o.x + (1 << (31-ds->nflatshiftup))) & ~((1 << (32-ds->nflatshiftup))-1); - yoffs += (pl->slope->o.y + (1 << (31-ds->nflatshiftup))) & ~((1 << (32-ds->nflatshiftup))-1); + ds->xoffs &= ((1 << (32-ds->nflatshiftup))-1); + ds->yoffs &= ((1 << (32-ds->nflatshiftup))-1); + ds->xoffs -= (pl->slope->o.x + (1 << (31-ds->nflatshiftup))) & ~((1 << (32-ds->nflatshiftup))-1); + ds->yoffs += (pl->slope->o.y + (1 << (31-ds->nflatshiftup))) & ~((1 << (32-ds->nflatshiftup))-1); } - xoffs = (fixed_t)(xoffs*fudgecanyon); - yoffs = (fixed_t)(yoffs/fudgecanyon); + ds->xoffs = (fixed_t)(ds->xoffs*fudgecanyon); + ds->yoffs = (fixed_t)(ds->yoffs/fudgecanyon); if (ds->planeripple.active) { @@ -1179,11 +1206,11 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle for (x = pl->high; x < pl->low; x++) { R_CalculatePlaneRipple(ds, pl, x, plheight, true); - R_SetSlopePlaneVectors(ds, pl, x, (xoffs + ds->planeripple.xfrac), (yoffs + ds->planeripple.yfrac), fudgecanyon); + R_SetSlopePlaneVectors(ds, pl, x, (ds->xoffs + ds->planeripple.xfrac), (ds->yoffs + ds->planeripple.yfrac), fudgecanyon); } } else - R_SetSlopePlaneVectors(ds, pl, 0, xoffs, yoffs, fudgecanyon); + R_SetSlopePlaneVectors(ds, pl, 0, ds->xoffs, ds->yoffs, fudgecanyon); if (spanfunc == R_DrawTranslucentWaterSpan) spanfunc = R_DrawTiltedTranslucentWaterSpan; @@ -1217,7 +1244,7 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle for (x = pl->minx; x <= stop; x++) { - R_MakeSpans(ds, x, pl->top[x-1], pl->bottom[x-1], pl->top[x], pl->bottom[x], allow_parallel); + R_MakeSpans(mapfunc, spanfunc, ds, x, pl->top[x-1], pl->bottom[x-1], pl->top[x], pl->bottom[x], allow_parallel); } /* @@ -1244,29 +1271,29 @@ using the palette colors. spanfunc = R_DrawTranslucentSpan; for (i=0; i<4; i++) { - xoffs = pl->xoffs; - yoffs = pl->yoffs; + ds->xoffs = pl->xoffs; + ds->yoffs = pl->yoffs; switch(i) { case 0: - xoffs -= FRACUNIT/4; - yoffs -= FRACUNIT/4; + ds->xoffs -= FRACUNIT/4; + ds->yoffs -= FRACUNIT/4; break; case 1: - xoffs -= FRACUNIT/4; - yoffs += FRACUNIT/4; + ds->xoffs -= FRACUNIT/4; + ds->yoffs += FRACUNIT/4; break; case 2: - xoffs += FRACUNIT/4; - yoffs -= FRACUNIT/4; + ds->xoffs += FRACUNIT/4; + ds->yoffs -= FRACUNIT/4; break; case 3: - xoffs += FRACUNIT/4; - yoffs += FRACUNIT/4; + ds->xoffs += FRACUNIT/4; + ds->yoffs += FRACUNIT/4; break; } - planeheight = abs(pl->height - pl->viewz); + ds->planeheight = abs(pl->height - pl->viewz); if (light >= LIGHTLEVELS) light = LIGHTLEVELS-1; @@ -1274,7 +1301,7 @@ using the palette colors. if (light < 0) light = 0; - planezlight = zlight[light]; + ds->planezlight = zlight[light]; // set the maximum value for unsigned pl->top[pl->maxx+1] = 0xffff; -- 2.54.0 From 1a7ff21a045ea5ec965244c8a286560f5b0eca93 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 5 Jun 2025 22:55:27 +0200 Subject: [PATCH 026/141] fix some warnings and plane ripple --- src/core/thread_pool.cpp | 4 +-- src/cxxutil.hpp | 2 +- src/r_draw.h | 1 - src/r_main.cpp | 46 +++++++++++++++-------------- src/r_plane.cpp | 64 ++++++++++++++++++++++++---------------- 5 files changed, 66 insertions(+), 51 deletions(-) diff --git a/src/core/thread_pool.cpp b/src/core/thread_pool.cpp index 820f21f67..6917aee93 100644 --- a/src/core/thread_pool.cpp +++ b/src/core/thread_pool.cpp @@ -45,7 +45,7 @@ static void do_work(ThreadPool::Task& work) } static void pool_executor( - int thread_index, + //int thread_index, std::shared_ptr> pool_alive, std::shared_ptr worker_ready_mutex, std::shared_ptr worker_ready_condvar, @@ -158,7 +158,7 @@ ThreadPool::ThreadPool(size_t threads) thread = std::thread { pool_executor, - i, + //i, pool_alive_, worker_ready_mutexes_[i], worker_ready_condvars_[i], diff --git a/src/cxxutil.hpp b/src/cxxutil.hpp index 74349a0ff..545d38dfd 100644 --- a/src/cxxutil.hpp +++ b/src/cxxutil.hpp @@ -71,7 +71,7 @@ public: class NoOpAssertHandler { public: - static void handle(const SourceLocation& source_location, const char* expression) {} + static void handle(const SourceLocation& source_location, const char* expression) {(void)source_location; (void)expression;} }; /// @brief Assert a precondition expression, aborting the application if it fails. diff --git a/src/r_draw.h b/src/r_draw.h index f2e6e8050..12ab3f584 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -66,7 +66,6 @@ typedef struct INT32 x1; INT32 x2; lighttable_t* colormap; - lighttable_t* fullbright; lighttable_t* translation; fixed_t xfrac; diff --git a/src/r_main.cpp b/src/r_main.cpp index 55475c407..4530e6c19 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -104,23 +104,23 @@ extracolormap_t extra_colormaps[MAXCOLORMAPS]; // Performance stats precise_t ps_prevframetime = 0; -ps_metric_t ps_rendercalltime = {0}; -ps_metric_t ps_otherrendertime = {0}; -ps_metric_t ps_uitime = {0}; -ps_metric_t ps_swaptime = {0}; +ps_metric_t ps_rendercalltime = {}; +ps_metric_t ps_otherrendertime = {}; +ps_metric_t ps_uitime = {}; +ps_metric_t ps_swaptime = {}; -ps_metric_t ps_skyboxtime = {0}; -ps_metric_t ps_bsptime = {0}; +ps_metric_t ps_skyboxtime = {}; +ps_metric_t ps_bsptime = {}; -ps_metric_t ps_sw_spritecliptime = {0}; -ps_metric_t ps_sw_portaltime = {0}; -ps_metric_t ps_sw_planetime = {0}; -ps_metric_t ps_sw_maskedtime = {0}; +ps_metric_t ps_sw_spritecliptime = {}; +ps_metric_t ps_sw_portaltime = {}; +ps_metric_t ps_sw_planetime = {}; +ps_metric_t ps_sw_maskedtime = {}; -ps_metric_t ps_numbspcalls = {0}; -ps_metric_t ps_numsprites = {0}; -ps_metric_t ps_numdrawnodes = {0}; -ps_metric_t ps_numpolyobjects = {0}; +ps_metric_t ps_numbspcalls = {}; +ps_metric_t ps_numsprites = {}; +ps_metric_t ps_numdrawnodes = {}; +ps_metric_t ps_numpolyobjects = {}; static CV_PossibleValue_t drawdist_cons_t[] = { /*{256, "256"},*/ {512, "512"}, {768, "768"}, @@ -1341,9 +1341,6 @@ void R_RenderPlayerView(player_t *player) const boolean skybox = (skyboxmo[0] && cv_skybox.value); UINT8 i; - srb2::ThreadPool::Sema tp_sema; - srb2::g_main_threadpool->begin_sema(); - // if this is display player 1 if (cv_homremoval.value && player == &players[displayplayers[0]]) { @@ -1391,6 +1388,8 @@ void R_RenderPlayerView(player_t *player) Portal_InitList(); + srb2::ThreadPool::Sema tp_sema; + PS_START_TIMING(ps_skyboxtime); if (skybox && skyVisible) { @@ -1403,6 +1402,7 @@ void R_RenderPlayerView(player_t *player) #ifdef FLOORSPLATS R_ClearVisibleFloorSplats(); #endif + srb2::g_main_threadpool->begin_sema(); R_RenderViewpoint(&masks[nummasks - 1], false); R_ClipSprites(); @@ -1414,7 +1414,6 @@ void R_RenderPlayerView(player_t *player) tp_sema = srb2::g_main_threadpool->end_sema(); srb2::g_main_threadpool->notify_sema(tp_sema); srb2::g_main_threadpool->wait_sema(tp_sema); - srb2::g_main_threadpool->begin_sema(); R_DrawMasked(masks, nummasks); } PS_STOP_TIMING(ps_skyboxtime); @@ -1454,10 +1453,13 @@ void R_RenderPlayerView(player_t *player) ps_numbspcalls.value.i = ps_numpolyobjects.value.i = ps_numdrawnodes.value.i = 0; PS_START_TIMING(ps_bsptime); - //tp_sema = srb2::g_main_threadpool->end_sema(); - //srb2::g_main_threadpool->notify_sema(tp_sema); - //srb2::g_main_threadpool->wait_sema(tp_sema); - //srb2::g_main_threadpool->begin_sema(); + if (skybox && skyVisible) + { + tp_sema = srb2::g_main_threadpool->end_sema(); + srb2::g_main_threadpool->notify_sema(tp_sema); + srb2::g_main_threadpool->wait_sema(tp_sema); + } + srb2::g_main_threadpool->begin_sema(); R_RenderViewpoint(&masks[nummasks - 1], true); PS_STOP_TIMING(ps_bsptime); diff --git a/src/r_plane.cpp b/src/r_plane.cpp index bc4007162..47cac7e13 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -144,21 +144,19 @@ void R_AllocPlaneMemory(void) // Sets planeripple.xfrac and planeripple.yfrac, added to ds_xfrac and ds_yfrac, if the span is not tilted. // -static void R_CalculatePlaneRipple(drawspandata_t* ds, visplane_t *plane, INT32 y, fixed_t plheight, boolean calcfrac) +static fixed_t R_CalculateRippleOffset(drawspandata_t* ds, INT32 y) { - fixed_t distance = FixedMul(plheight, yslope[y]); + fixed_t distance = FixedMul(ds->planeheight, yslope[y]); const INT32 yay = (ds->planeripple.offset + (distance>>9)) & 8191; + return FixedDiv(FINESINE(yay), (1<<12) + (distance>>11))>>FRACBITS; +} - // ripples da water texture - ds->bgofs = FixedDiv(FINESINE(yay), (1<<12) + (distance>>11))>>FRACBITS; - - if (calcfrac) - { - angle_t angle = (plane->viewangle + plane->plangle)>>ANGLETOFINESHIFT; - angle = (angle + 2048) & 8191; // 90 degrees - ds->planeripple.xfrac = FixedMul(FINECOSINE(angle), (ds->bgofs<planeripple.yfrac = FixedMul(FINESINE(angle), (ds->bgofs<>= ANGLETOFINESHIFT; + angle = (angle + 2048) & 8191; // 90 degrees + ds->planeripple.xfrac = FixedMul(FINECOSINE(angle), ds->bgofs); + ds->planeripple.yfrac = FixedMul(FINESINE(angle), ds->bgofs); } static void R_UpdatePlaneRipple(drawspandata_t* ds) @@ -259,6 +257,8 @@ static void R_MapPlane(drawspandata_t *ds, void(*spanfunc2)(drawspandata_t*), IN fixed_t distance = 0, span; size_t pindex; + (void)allow_parallel; + if (!R_CheckMapPlane(__func__, y, x1, x2)) return; @@ -288,7 +288,10 @@ static void R_MapPlane(drawspandata_t *ds, void(*spanfunc2)(drawspandata_t*), IN if (ds->planeripple.active) { // Needed for ds_bgofs - R_CalculatePlaneRipple(ds, ds->currentplane, y, ds->planeheight, (!ds->currentplane->slope)); + + ds->bgofs = R_CalculateRippleOffset(ds, y); + + R_CalculatePlaneRipple(ds, ds->currentplane->viewangle + ds->currentplane->plangle); ds->xfrac += ds->planeripple.xfrac; ds->yfrac += ds->planeripple.yfrac; @@ -319,16 +322,24 @@ static void R_MapPlane(drawspandata_t *ds, void(*spanfunc2)(drawspandata_t*), IN static void R_MapTiltedPlane(drawspandata_t *ds, void(*spanfunc2)(drawspandata_t*), INT32 y, INT32 x1, INT32 x2, boolean allow_parallel) { + (void)allow_parallel; + if (!R_CheckMapPlane(__func__, y, x1, x2)) return; // Water ripple effect if (ds->planeripple.active) { + ds->bgofs = R_CalculateRippleOffset(ds, y); + R_SetTiltedSpan(ds, std::clamp(y, 0, viewheight)); - R_CalculatePlaneRipple(ds, ds->currentplane, y, ds->planeheight, false); - R_SetSlopePlaneVectors(ds, ds->currentplane, y, (ds->xoffs + ds->planeripple.xfrac), (ds->yoffs + ds->planeripple.yfrac), 0); + float fudgecanyon = 0; + // Okay, look, don't ask me why this works, but without this setup there's a disgusting-looking misalignment with the textures. -fickle + fudgecanyon = ((1<nflatshiftup)+1.0f)/(1<nflatshiftup); + + R_CalculatePlaneRipple(ds, ds->currentplane->viewangle + ds->currentplane->plangle); + R_SetSlopePlaneVectors(ds, ds->currentplane, y, (ds->xoffs + ds->planeripple.xfrac), (ds->yoffs + ds->planeripple.yfrac), fudgecanyon); if ((y + ds->bgofs) >= viewheight) ds->bgofs = viewheight-y-1; @@ -341,11 +352,9 @@ static void R_MapTiltedPlane(drawspandata_t *ds, void(*spanfunc2)(drawspandata_t else ds->colormap = colormaps; - ds->fullbright = colormaps; if (encoremap && !ds->currentplane->noencore) { ds->colormap += COLORMAP_REMAPOFFSET; - ds->fullbright += COLORMAP_REMAPOFFSET; } ds->y = y; @@ -765,11 +774,13 @@ void R_DrawPlanes(void) { visplane_t *pl; INT32 i; - drawspandata_t ds = {0}; + drawspandata_t ds = {}; spanfunc = basespanfunc; wallcolfunc = walldrawerfunc; + R_UpdatePlaneRipple(&ds); + for (i = 0; i < MAXVISPLANES; i++, pl++) { for (pl = visplanes[i]; pl; pl = pl->next) @@ -780,14 +791,12 @@ void R_DrawPlanes(void) R_DrawSinglePlane(&ds, pl, true); } } - - R_UpdatePlaneRipple(&ds); } static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), boolean allow_parallel) { INT32 x; - drawcolumndata_t dc = {0}; + drawcolumndata_t dc = {}; if (!newview->sky) { @@ -971,6 +980,8 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle if (!(pl->minx <= pl->maxx)) return; + R_UpdatePlaneRipple(ds); + // sky flat if (pl->picnum == skyflatnum) { @@ -986,7 +997,7 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle spanfunc = R_DrawTranslucentSpan; // Hacked up support for alpha value in software mode Tails 09-24-2002 (sidenote: ported to polys 10-15-2014, there was no time travel involved -Red) - if (pl->polyobj->translucency >= 10) + if (pl->polyobj->translucency >= NUMTRANSMAPS) return; // Don't even draw it else if (pl->polyobj->translucency > 0) ds->transmap = R_GetTranslucencyTable(pl->polyobj->translucency); @@ -1127,7 +1138,6 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle ds->xoffs = pl->xoffs; ds->yoffs = pl->yoffs; - ds->planeheight = abs(pl->height - pl->viewz); if (light >= LIGHTLEVELS) light = LIGHTLEVELS-1; @@ -1199,13 +1209,14 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle if (ds->planeripple.active) { - fixed_t plheight = abs(P_GetSlopeZAt(pl->slope, pl->viewx, pl->viewy) - pl->viewz); + ds->planeheight = abs(P_GetSlopeZAt(pl->slope, pl->viewx, pl->viewy) - pl->viewz); R_PlaneBounds(pl); for (x = pl->high; x < pl->low; x++) { - R_CalculatePlaneRipple(ds, pl, x, plheight, true); + ds->bgofs = R_CalculateRippleOffset(ds, x); + R_CalculatePlaneRipple(ds, pl->viewangle + pl->plangle); R_SetSlopePlaneVectors(ds, pl, x, (ds->xoffs + ds->planeripple.xfrac), (ds->yoffs + ds->planeripple.yfrac), fudgecanyon); } } @@ -1224,7 +1235,10 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle ds->planezlight = scalelight[light]; } else + { + ds->planeheight = abs(pl->height - pl->viewz); ds->planezlight = zlight[light]; + } // set the maximum value for unsigned pl->top[pl->maxx+1] = 0xffff; -- 2.54.0 From 006e7fe8f892d7129fa59d6dbd69990d2fb8544b Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 5 Jun 2025 23:17:28 +0200 Subject: [PATCH 027/141] move this --- src/r_things.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_things.c b/src/r_things.c index 17cf5a155..0e5a984e2 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2940,9 +2940,9 @@ static void R_DrawMaskedList (drawnode_t* head) for (r2 = head->next; r2 != head; r2 = r2->next) { - drawspandata_t ds = {0}; if (r2->plane) { + drawspandata_t ds = {0}; next = r2->prev; R_DrawSinglePlane(&ds, r2->plane, false); R_DoneWithNode(r2); -- 2.54.0 From 2a023246beff04d2f42b94700ab2652d5f74aa6e Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 5 Jun 2025 23:50:12 +0200 Subject: [PATCH 028/141] ok fuck you tiltlighting static buffer it is --- src/r_draw_span.c | 40 ++++------------------------------------ 1 file changed, 4 insertions(+), 36 deletions(-) diff --git a/src/r_draw_span.c b/src/r_draw_span.c index 50612dc22..1e6d452ce 100644 --- a/src/r_draw_span.c +++ b/src/r_draw_span.c @@ -371,15 +371,7 @@ void R_DrawTiltedSpan(drawspandata_t* ds) float endz, endu, endv; UINT32 stepu, stepv; register UINT32 bit; - static INT32 *tiltlighting = NULL; - static INT32 oldviewwidth = 0; - - // dont realloc every frame pls thx - if (tiltlighting == NULL || oldviewwidth != viewwidth) - { - tiltlighting = Z_Realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth, PU_STATIC, NULL); - oldviewwidth = viewwidth; - } + INT32 tiltlighting[MAXVIDWIDTH]; iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); @@ -518,15 +510,7 @@ void R_DrawTiltedTranslucentSpan(drawspandata_t* ds) float endz, endu, endv; UINT32 stepu, stepv; register UINT32 bit; - static INT32 *tiltlighting = NULL; - static INT32 oldviewwidth = 0; - - // dont realloc every frame pls thx - if (tiltlighting == NULL || oldviewwidth != viewwidth) - { - tiltlighting = Z_Realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth, PU_STATIC, NULL); - oldviewwidth = viewwidth; - } + INT32 tiltlighting[MAXVIDWIDTH]; iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); @@ -666,15 +650,7 @@ void R_DrawTiltedTranslucentWaterSpan(drawspandata_t* ds) float endz, endu, endv; UINT32 stepu, stepv; register UINT32 bit; - static INT32 *tiltlighting = NULL; - static INT32 oldviewwidth = 0; - - // dont realloc every frame pls thx - if (tiltlighting == NULL || oldviewwidth != viewwidth) - { - tiltlighting = Z_Realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth, PU_STATIC, NULL); - oldviewwidth = viewwidth; - } + INT32 tiltlighting[MAXVIDWIDTH]; iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); @@ -814,15 +790,7 @@ void R_DrawTiltedSplat(drawspandata_t* ds) float endz, endu, endv; UINT32 stepu, stepv; register UINT32 bit; - static INT32 *tiltlighting = NULL; - static INT32 oldviewwidth = 0; - - // dont realloc every frame pls thx - if (tiltlighting == NULL || oldviewwidth != viewwidth) - { - tiltlighting = Z_Realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth, PU_STATIC, NULL); - oldviewwidth = viewwidth; - } + INT32 tiltlighting[MAXVIDWIDTH]; iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); -- 2.54.0 From 3faab66ef4120e6315cb1ebdea8a7aef26b2ea9c Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 6 Jun 2025 00:01:48 +0200 Subject: [PATCH 029/141] add toggle for software multithread --- src/d_netcmd.c | 2 ++ src/r_plane.cpp | 2 +- src/screen.c | 2 ++ src/screen.h | 2 ++ 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index abe3dd8c9..310bac2b9 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1025,6 +1025,8 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_scr_width); CV_RegisterVar(&cv_scr_height); + CV_RegisterVar(&cv_parallelsoftware); + CV_RegisterVar(&cv_soundtest); CV_RegisterVar(&cv_perfstats); diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 47cac7e13..484f5f413 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -788,7 +788,7 @@ void R_DrawPlanes(void) if (pl->ffloor != NULL || pl->polyobj != NULL) continue; - R_DrawSinglePlane(&ds, pl, true); + R_DrawSinglePlane(&ds, pl, cv_parallelsoftware.value); } } } diff --git a/src/screen.c b/src/screen.c index d226ca423..55e00f90f 100644 --- a/src/screen.c +++ b/src/screen.c @@ -48,6 +48,8 @@ consvar_t cv_renderview = {"renderview", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, consvar_t cv_vhseffect = {"vhspause", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_shittyscreen = {"televisionsignal", "Okay", CV_NOSHOWHELP, shittyscreen_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_parallelsoftware = {"parallelsoftware", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; + static CV_PossibleValue_t votescale_cons_t[] = {{0, "Vanilla"}, {1, "Adaptive"}, {2, "VerticalFill"}, {3, "HorizontalFill"}, {0, NULL}}; consvar_t cv_votebgscaling = {"votebgscaling", "Adaptive", CV_SAVE, votescale_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; diff --git a/src/screen.h b/src/screen.h index 51d05111c..e6e3fb9bc 100644 --- a/src/screen.h +++ b/src/screen.h @@ -87,6 +87,8 @@ extern INT32 setmodeneeded; // mode number to set if needed, or 0 extern UINT8 *scr_borderpatch; // patch used to fill the view borders extern consvar_t cv_scr_width, cv_scr_height, cv_renderview, cv_fullscreen, cv_vhseffect, cv_shittyscreen; +extern consvar_t cv_parallelsoftware; + extern consvar_t cv_highreshudscale; // wait for page flipping to end or not extern consvar_t cv_vidwait; -- 2.54.0 From f07d5d381ecf5c65e005b156f21f9ba01e136ec7 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 6 Jun 2025 00:19:23 +0200 Subject: [PATCH 030/141] fix the goddamn boolean --- src/doomtype.h | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/src/doomtype.h b/src/doomtype.h index 79806365d..ac41a4413 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -162,22 +162,19 @@ size_t strlcpy(char *dst, const char *src, size_t siz); /* Boolean type definition */ -// \note __BYTEBOOL__ used to be set above if "macintosh" was defined, -// if macintosh's version of boolean type isn't needed anymore, then isn't this macro pointless now? -#ifndef __BYTEBOOL__ - #define __BYTEBOOL__ - - //faB: clean that up !! - #if defined( _MSC_VER) && (_MSC_VER >= 1800) // MSVC 2013 and forward - #include "stdbool.h" - #elif defined (_WIN32) - #define false FALSE // use windows types - #define true TRUE - #define boolean BOOL - #else - typedef enum {false, true} boolean; - #endif -#endif // __BYTEBOOL__ +#ifndef _WIN32 +#include +// dont use stdbools _BOOL type +// its smaller (1 byte) than the old interger bool (4 bytes) +// which results in packed struct sizes being mismatched between vanilla and this +// however we gotta still include stdbool cause since c23 true and false are keywords +// which we cant use as enumeration constants +typedef int32_t boolean; +#else +#define false FALSE +#define true TRUE +#define boolean BOOL +#endif /* 7.18.2.1 Limits of exact-width integer types */ #ifndef INT8_MIN -- 2.54.0 From 9a934a55e246b70f0fbdec1ff1f83183108e336f Mon Sep 17 00:00:00 2001 From: Indev Date: Fri, 6 Jun 2025 01:39:51 +0300 Subject: [PATCH 031/141] Revert "ok fuck you tiltlighting static buffer it is" This reverts commit 2a023246beff04d2f42b94700ab2652d5f74aa6e. --- src/r_draw_span.c | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/r_draw_span.c b/src/r_draw_span.c index 1e6d452ce..50612dc22 100644 --- a/src/r_draw_span.c +++ b/src/r_draw_span.c @@ -371,7 +371,15 @@ void R_DrawTiltedSpan(drawspandata_t* ds) float endz, endu, endv; UINT32 stepu, stepv; register UINT32 bit; - INT32 tiltlighting[MAXVIDWIDTH]; + static INT32 *tiltlighting = NULL; + static INT32 oldviewwidth = 0; + + // dont realloc every frame pls thx + if (tiltlighting == NULL || oldviewwidth != viewwidth) + { + tiltlighting = Z_Realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth, PU_STATIC, NULL); + oldviewwidth = viewwidth; + } iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); @@ -510,7 +518,15 @@ void R_DrawTiltedTranslucentSpan(drawspandata_t* ds) float endz, endu, endv; UINT32 stepu, stepv; register UINT32 bit; - INT32 tiltlighting[MAXVIDWIDTH]; + static INT32 *tiltlighting = NULL; + static INT32 oldviewwidth = 0; + + // dont realloc every frame pls thx + if (tiltlighting == NULL || oldviewwidth != viewwidth) + { + tiltlighting = Z_Realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth, PU_STATIC, NULL); + oldviewwidth = viewwidth; + } iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); @@ -650,7 +666,15 @@ void R_DrawTiltedTranslucentWaterSpan(drawspandata_t* ds) float endz, endu, endv; UINT32 stepu, stepv; register UINT32 bit; - INT32 tiltlighting[MAXVIDWIDTH]; + static INT32 *tiltlighting = NULL; + static INT32 oldviewwidth = 0; + + // dont realloc every frame pls thx + if (tiltlighting == NULL || oldviewwidth != viewwidth) + { + tiltlighting = Z_Realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth, PU_STATIC, NULL); + oldviewwidth = viewwidth; + } iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); @@ -790,7 +814,15 @@ void R_DrawTiltedSplat(drawspandata_t* ds) float endz, endu, endv; UINT32 stepu, stepv; register UINT32 bit; - INT32 tiltlighting[MAXVIDWIDTH]; + static INT32 *tiltlighting = NULL; + static INT32 oldviewwidth = 0; + + // dont realloc every frame pls thx + if (tiltlighting == NULL || oldviewwidth != viewwidth) + { + tiltlighting = Z_Realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth, PU_STATIC, NULL); + oldviewwidth = viewwidth; + } iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); -- 2.54.0 From 252563725dfb5d8bb367df4a172c6632ad73e9e0 Mon Sep 17 00:00:00 2001 From: Indev Date: Fri, 6 Jun 2025 01:42:15 +0300 Subject: [PATCH 032/141] Make tiltlighting buffer thread_local --- src/r_draw_span.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/r_draw_span.c b/src/r_draw_span.c index 50612dc22..655b19479 100644 --- a/src/r_draw_span.c +++ b/src/r_draw_span.c @@ -15,6 +15,8 @@ // SPANS // ========================================================================== +#include + #define SPANSIZE 16 #define INVSPAN 0.0625f @@ -371,8 +373,8 @@ void R_DrawTiltedSpan(drawspandata_t* ds) float endz, endu, endv; UINT32 stepu, stepv; register UINT32 bit; - static INT32 *tiltlighting = NULL; - static INT32 oldviewwidth = 0; + thread_local static INT32 *tiltlighting = NULL; + thread_local static INT32 oldviewwidth = 0; // dont realloc every frame pls thx if (tiltlighting == NULL || oldviewwidth != viewwidth) @@ -518,8 +520,8 @@ void R_DrawTiltedTranslucentSpan(drawspandata_t* ds) float endz, endu, endv; UINT32 stepu, stepv; register UINT32 bit; - static INT32 *tiltlighting = NULL; - static INT32 oldviewwidth = 0; + thread_local static INT32 *tiltlighting = NULL; + thread_local static INT32 oldviewwidth = 0; // dont realloc every frame pls thx if (tiltlighting == NULL || oldviewwidth != viewwidth) @@ -666,8 +668,8 @@ void R_DrawTiltedTranslucentWaterSpan(drawspandata_t* ds) float endz, endu, endv; UINT32 stepu, stepv; register UINT32 bit; - static INT32 *tiltlighting = NULL; - static INT32 oldviewwidth = 0; + thread_local static INT32 *tiltlighting = NULL; + thread_local static INT32 oldviewwidth = 0; // dont realloc every frame pls thx if (tiltlighting == NULL || oldviewwidth != viewwidth) @@ -814,8 +816,8 @@ void R_DrawTiltedSplat(drawspandata_t* ds) float endz, endu, endv; UINT32 stepu, stepv; register UINT32 bit; - static INT32 *tiltlighting = NULL; - static INT32 oldviewwidth = 0; + thread_local static INT32 *tiltlighting = NULL; + thread_local static INT32 oldviewwidth = 0; // dont realloc every frame pls thx if (tiltlighting == NULL || oldviewwidth != viewwidth) -- 2.54.0 From f3cca27448c53c464fbc270923079bcbfcda73cf Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 6 Jun 2025 00:55:06 +0200 Subject: [PATCH 033/141] cache vid.width in the column drawers shit was really slow lel --- src/r_draw_column.c | 54 ++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/src/r_draw_column.c b/src/r_draw_column.c index 8db886a7d..aef4b06ee 100644 --- a/src/r_draw_column.c +++ b/src/r_draw_column.c @@ -36,7 +36,6 @@ void R_DrawColumn(drawcolumndata_t* dc) return; } - if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height) { return; @@ -61,6 +60,8 @@ void R_DrawColumn(drawcolumndata_t* dc) static const INT32 npow2min = -1; const INT32 npow2max = dc->sourcelength; + register const INT32 stride = vid.width; + if (dc->sourcelength & heightmask) // not a power of 2 -- killough { heightmask = dc->texheight << FRACBITS; @@ -90,8 +91,7 @@ void R_DrawColumn(drawcolumndata_t* dc) // and a few bytes after as well *dest = colormap[source[CLAMP(frac >> FRACBITS, npow2min, npow2max)]]; - dest += vid.width; - + dest += stride; #if __SIZEOF_POINTER__ < 8 // 64-bit systems have large enough numbers for this to be a non-issue // Avoid overflow. @@ -117,12 +117,12 @@ void R_DrawColumn(drawcolumndata_t* dc) { *dest = colormap[source[(frac>>FRACBITS) & heightmask]]; - dest += vid.width; + dest += stride; frac += fracstep; *dest = colormap[source[(frac>>FRACBITS) & heightmask]]; - dest += vid.width; + dest += stride; frac += fracstep; } @@ -171,6 +171,8 @@ void R_Draw2sMultiPatchColumn(drawcolumndata_t* dc) static const INT32 npow2min = -1; const INT32 npow2max = dc->sourcelength; + register const INT32 stride = vid.width; + if (dc->sourcelength & heightmask) // not a power of 2 -- killough { heightmask = dc->texheight << FRACBITS; @@ -205,7 +207,7 @@ void R_Draw2sMultiPatchColumn(drawcolumndata_t* dc) *dest = colormap[val]; } - dest += vid.width; + dest += stride; // Avoid overflow. #if __SIZEOF_POINTER__ < 8 @@ -236,7 +238,7 @@ void R_Draw2sMultiPatchColumn(drawcolumndata_t* dc) *dest = colormap[val]; } - dest += vid.width; + dest += stride; frac += fracstep; val = source[(frac>>FRACBITS) & heightmask]; @@ -245,7 +247,7 @@ void R_Draw2sMultiPatchColumn(drawcolumndata_t* dc) *dest = colormap[val]; } - dest += vid.width; + dest += stride; frac += fracstep; } @@ -299,6 +301,8 @@ void R_Draw2sMultiPatchTranslucentColumn(drawcolumndata_t* dc) static const INT32 npow2min = -1; const INT32 npow2max = dc->sourcelength; + register const INT32 stride = vid.width; + if (dc->sourcelength & heightmask) // not a power of 2 -- killough { heightmask = dc->texheight << FRACBITS; @@ -333,7 +337,7 @@ void R_Draw2sMultiPatchTranslucentColumn(drawcolumndata_t* dc) *dest = *(transmap + (colormap[val]<<8) + (*dest)); } - dest += vid.width; + dest += stride; // Avoid overflow. #if __SIZEOF_POINTER__ < 8 @@ -363,7 +367,7 @@ void R_Draw2sMultiPatchTranslucentColumn(drawcolumndata_t* dc) *dest = *(transmap + (colormap[val]<<8) + (*dest)); } - dest += vid.width; + dest += stride; frac += fracstep; val = source[(frac>>FRACBITS) & heightmask]; @@ -372,7 +376,7 @@ void R_Draw2sMultiPatchTranslucentColumn(drawcolumndata_t* dc) *dest = *(transmap + (colormap[val]<<8) + (*dest)); } - dest += vid.width; + dest += stride; frac += fracstep; } @@ -419,11 +423,13 @@ void R_DrawShadeColumn(drawcolumndata_t* dc) fracstep = dc->iscale; frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep)); + register const INT32 stride = vid.width; + // Here we do an additional index re-mapping. do { *dest = colormaps[(dc->source[frac>>FRACBITS] <<8) + (*dest)]; - dest += vid.width; + dest += stride; frac += fracstep; } while (count--); } @@ -469,6 +475,8 @@ void R_DrawTranslucentColumn(drawcolumndata_t* dc) static const INT32 npow2min = -1; const INT32 npow2max = dc->sourcelength; + register const INT32 stride = vid.width; + if (dc->sourcelength & heightmask) { heightmask = dc->texheight << FRACBITS; @@ -498,7 +506,7 @@ void R_DrawTranslucentColumn(drawcolumndata_t* dc) // and a few bytes after as well *dest = *(transmap + (colormap[source[CLAMP(frac >> FRACBITS, npow2min, npow2max)]]<<8) + (*dest)); - dest += vid.width; + dest += stride; if ((frac += fracstep) >= heightmask) { @@ -512,11 +520,11 @@ void R_DrawTranslucentColumn(drawcolumndata_t* dc) while ((count -= 2) >= 0) // texture height is a power of 2 { *dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); - dest += vid.width; + dest += stride; frac += fracstep; *dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); - dest += vid.width; + dest += stride; frac += fracstep; } @@ -564,6 +572,8 @@ void R_DrawTranslatedTranslucentColumn(drawcolumndata_t* dc) static const INT32 npow2min = -1; const INT32 npow2max = dc->sourcelength; + register const INT32 stride = vid.width; + if (dc->sourcelength & heightmask) { heightmask = dc->texheight << FRACBITS; @@ -593,7 +603,7 @@ void R_DrawTranslatedTranslucentColumn(drawcolumndata_t* dc) // and a few bytes after as well *dest = *(dc->transmap + (dc->colormap[dc->translation[dc->source[CLAMP(frac >> FRACBITS, npow2min, npow2max)]]]<<8) + (*dest)); - dest += vid.width; + dest += stride; if ((frac += fracstep) >= heightmask) { @@ -607,11 +617,11 @@ void R_DrawTranslatedTranslucentColumn(drawcolumndata_t* dc) while ((count -= 2) >= 0) // texture height is a power of 2 { *dest = *(dc->transmap + (dc->colormap[dc->translation[dc->source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); - dest += vid.width; + dest += stride; frac += fracstep; *dest = *(dc->transmap + (dc->colormap[dc->translation[dc->source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); - dest += vid.width; + dest += stride; frac += fracstep; } @@ -652,6 +662,8 @@ void R_DrawTranslatedColumn(drawcolumndata_t* dc) fracstep = dc->iscale; frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep)); + register const INT32 stride = vid.width; + // Here we do an additional index re-mapping. do { @@ -662,7 +674,7 @@ void R_DrawTranslatedColumn(drawcolumndata_t* dc) // is mapped to gray, red, black/indigo. *dest = dc->colormap[dc->translation[dc->source[frac>>FRACBITS]]]; - dest += vid.width; + dest += stride; frac += fracstep; } while (count--); @@ -690,12 +702,14 @@ void R_DrawFogColumn(drawcolumndata_t* dc) // Framebuffer destination address. dest = R_Address(dc->x, dc->yl); + register const INT32 stride = vid.width; + // Determine scaling, which is the only mapping to be done. do { // Simple. Apply the colormap to what's already on the screen. *dest = dc->colormap[*dest]; - dest += vid.width; + dest += stride; } while (count--); } -- 2.54.0 From 96f8533479d2640ca605bfe229188c55280ca903 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 6 Jun 2025 01:04:11 +0200 Subject: [PATCH 034/141] dont check for wraps on 0 height textures in column drawers slight speedup thx srb2classic! --- src/r_draw_column.c | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/src/r_draw_column.c b/src/r_draw_column.c index aef4b06ee..2383de341 100644 --- a/src/r_draw_column.c +++ b/src/r_draw_column.c @@ -54,7 +54,6 @@ void R_DrawColumn(drawcolumndata_t* dc) // This is as fast as it gets. const UINT8 *restrict source = dc->source; const lighttable_t *restrict colormap = dc->colormap; - intptr_t heightmask = dc->sourcelength-1; static const INT32 npow2min = -1; @@ -62,7 +61,17 @@ void R_DrawColumn(drawcolumndata_t* dc) register const INT32 stride = vid.width; - if (dc->sourcelength & heightmask) // not a power of 2 -- killough + if (heightmask == -1) + { + // texture has no height, so just go + while (--count > 0) + { + *dest = colormap[source[frac>>FRACBITS]]; + dest += stride; + frac += fracstep; + } + } + else if (dc->sourcelength & heightmask) // not a power of 2 -- killough { heightmask = dc->texheight << FRACBITS; @@ -173,7 +182,17 @@ void R_Draw2sMultiPatchColumn(drawcolumndata_t* dc) register const INT32 stride = vid.width; - if (dc->sourcelength & heightmask) // not a power of 2 -- killough + if (heightmask == -1) + { + // texture has no height, so just go + while (--count > 0) + { + *dest = colormap[source[frac>>FRACBITS]]; + dest += stride; + frac += fracstep; + } + } + else if (dc->sourcelength & heightmask) // not a power of 2 -- killough { heightmask = dc->texheight << FRACBITS; @@ -303,7 +322,17 @@ void R_Draw2sMultiPatchTranslucentColumn(drawcolumndata_t* dc) register const INT32 stride = vid.width; - if (dc->sourcelength & heightmask) // not a power of 2 -- killough + if (heightmask == -1) + { + // texture has no height, so just go + while (--count > 0) + { + *dest = colormap[source[frac>>FRACBITS]]; + dest += stride; + frac += fracstep; + } + } + else if (dc->sourcelength & heightmask) // not a power of 2 -- killough { heightmask = dc->texheight << FRACBITS; -- 2.54.0 From 556883487de0f0b8dbe498a1b2a50351fc02f384 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 6 Jun 2025 01:17:26 +0200 Subject: [PATCH 035/141] optimize software hud drawing from srb2classic adjusted to our drawers --- src/v_video.c | 237 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 170 insertions(+), 67 deletions(-) diff --git a/src/v_video.c b/src/v_video.c index c826d70f5..b9cab620c 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -636,29 +636,17 @@ UINT8 hudtrans = 0; static const UINT8 *v_colormap = NULL; static const UINT8 *v_translevel = NULL; -FUNCINLINE static ATTRINLINE UINT8 standardpdraw(const UINT8 *dest, const UINT8 *source, fixed_t ofs) -{ - (void)dest; return source[ofs>>FRACBITS]; -} -FUNCINLINE static ATTRINLINE UINT8 mappedpdraw(const UINT8 *dest, const UINT8 *source, fixed_t ofs) -{ - (void)dest; return *(v_colormap + source[ofs>>FRACBITS]); -} -FUNCINLINE static ATTRINLINE UINT8 translucentpdraw(const UINT8 *dest, const UINT8 *source, fixed_t ofs) -{ - return *(v_translevel + ((source[ofs>>FRACBITS]<<8)&0xff00) + (*dest&0xff)); -} -FUNCINLINE static ATTRINLINE UINT8 transmappedpdraw(const UINT8 *dest, const UINT8 *source, fixed_t ofs) -{ - return *(v_translevel + (((*(v_colormap + source[ofs>>FRACBITS]))<<8)&0xff00) + (*dest&0xff)); -} +#define STANDARDDRAW 1 +#define MAPPEDDRAW 2 +#define TRANSLUCENTDRAW 3 +#define TRANSMAPPEDDRAW 4 // Draws a patch scaled to arbitrary size. void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scrn, patch_t *patch, const UINT8 *colormap, INT32 bflags) { - UINT8 (*patchdrawfunc)(const UINT8*, const UINT8*, fixed_t); - UINT32 alphalevel = ((scrn & V_ALPHAMASK) >> V_ALPHASHIFT); - UINT32 blendmode = ((bflags & V_BLENDMASK) >> V_BLENDSHIFT); + UINT8 patchdrawtype; + UINT32 alphalevel; + UINT32 blendmode; fixed_t col, ofs, colfrac, rowfrac, fdup, vdup; INT32 dupx, dupy; @@ -683,7 +671,10 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca } #endif - patchdrawfunc = standardpdraw; + alphalevel = ((scrn & V_ALPHAMASK) >> V_ALPHASHIFT); + blendmode = ((bflags & V_BLENDMASK) >> V_BLENDSHIFT); + + patchdrawtype = STANDARDDRAW; v_translevel = NULL; if (alphalevel || blendmode) @@ -701,7 +692,7 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca if (alphalevel || blendmode) { v_translevel = R_GetBlendTable(blendmode+1, alphalevel); - patchdrawfunc = translucentpdraw; + patchdrawtype = TRANSLUCENTDRAW; } } @@ -710,7 +701,7 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca if (colormap) { v_colormap = colormap; - patchdrawfunc = (v_translevel) ? transmappedpdraw : mappedpdraw; + patchdrawtype = (v_translevel) ? TRANSMAPPEDDRAW : MAPPEDDRAW; } dupx = vid.dupx; @@ -851,6 +842,8 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca deststart = desttop; destend = desttop + pwidth; + const INT32 stride = vid.width; + for (col = 0; (col>>FRACBITS) < patch->width; col += colfrac, ++offx, desttop++) { INT32 topdelta, prevdelta = -1; @@ -858,37 +851,111 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca { if (x+pwidth-offx < 0) // don't draw off the left of the screen (WRAP PREVENTION) break; - if (x+pwidth-offx >= vid.width) // don't draw off the right of the screen (WRAP PREVENTION) + if (x+pwidth-offx >= stride) // don't draw off the right of the screen (WRAP PREVENTION) continue; } else { if (x+offx < 0) // don't draw off the left of the screen (WRAP PREVENTION) continue; - if (x+offx >= vid.width) // don't draw off the right of the screen (WRAP PREVENTION) + if (x+offx >= stride) // don't draw off the right of the screen (WRAP PREVENTION) break; } column = (const column_t *)((const UINT8 *)(patch->columns) + (patch->columnofs[col>>FRACBITS])); - while (column->topdelta != 0xff) + switch (patchdrawtype) { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)(column) + 3; - dest = desttop; - if (scrn & V_FLIP) - dest = deststart + (destend - desttop); - dest += FixedInt(FixedMul(topdelta<topdelta != 0xff) + { + topdelta = column->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + source = (const UINT8 *)(column) + 3; + dest = desttop; + if (scrn & V_FLIP) + dest = deststart + (destend - desttop); + dest += FixedInt(FixedMul(topdelta<>FRACBITS) < column->length; ofs += rowfrac) - { - if (dest >= vid.screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION) - *dest = patchdrawfunc(dest, source, ofs); - dest += vid.width; - } - column = (const column_t *)((const UINT8 *)column + column->length + 4); + for (ofs = 0; dest < deststop && (ofs>>FRACBITS) < column->length; ofs += rowfrac) + { + if (dest >= vid.screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION) + *dest = source[ofs>>FRACBITS]; + dest += stride; + } + column = (const column_t *)((const UINT8 *)column + column->length + 4); + } + break; + + case MAPPEDDRAW: + while (column->topdelta != 0xff) + { + topdelta = column->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + source = (const UINT8 *)(column) + 3; + dest = desttop; + if (scrn & V_FLIP) + dest = deststart + (destend - desttop); + dest += FixedInt(FixedMul(topdelta<>FRACBITS) < column->length; ofs += rowfrac) + { + if (dest >= vid.screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION) + *dest = *(v_colormap + source[ofs>>FRACBITS]); + dest += stride; + } + column = (const column_t *)((const UINT8 *)column + column->length + 4); + } + break; + + case TRANSLUCENTDRAW: + while (column->topdelta != 0xff) + { + topdelta = column->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + source = (const UINT8 *)(column) + 3; + dest = desttop; + if (scrn & V_FLIP) + dest = deststart + (destend - desttop); + dest += FixedInt(FixedMul(topdelta<>FRACBITS) < column->length; ofs += rowfrac) + { + if (dest >= vid.screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION) + *dest = *(v_translevel + ((source[ofs>>FRACBITS]<<8)&0xff00) + (*dest&0xff)); + dest += stride; + } + column = (const column_t *)((const UINT8 *)column + column->length + 4); + } + break; + + case TRANSMAPPEDDRAW: + while (column->topdelta != 0xff) + { + topdelta = column->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + source = (const UINT8 *)(column) + 3; + dest = desttop; + if (scrn & V_FLIP) + dest = deststart + (destend - desttop); + dest += FixedInt(FixedMul(topdelta<>FRACBITS) < column->length; ofs += rowfrac) + { + if (dest >= vid.screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION) + *dest = *(v_translevel + (((*(v_colormap + source[ofs>>FRACBITS]))<<8)&0xff00) + (*dest&0xff)); + dest += stride; + } + column = (const column_t *)((const UINT8 *)column + column->length + 4); + } + break; } } } @@ -896,9 +963,8 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca // Draws a patch cropped and scaled to arbitrary size. void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t *patch, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h) { - UINT8 (*patchdrawfunc)(const UINT8*, const UINT8*, fixed_t); + UINT8 patchdrawtype; UINT32 alphalevel = 0; - // boolean flip = false; fixed_t col, ofs, colfrac, rowfrac, fdup; INT32 dupx, dupy; @@ -920,7 +986,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_ } #endif - patchdrawfunc = standardpdraw; + patchdrawtype = STANDARDDRAW; v_translevel = NULL; if ((alphalevel = ((scrn & V_ALPHAMASK) >> V_ALPHASHIFT))) @@ -938,7 +1004,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_ if (alphalevel) { v_translevel = transtables + ((alphalevel-1)<>FRACBITS) < patch->width && ((col>>FRACBITS) - sx) < w; col += colfrac, ++x, desttop++) { INT32 topdelta, prevdelta = -1; + if (x < 0) // don't draw off the left of the screen (WRAP PREVENTION) continue; - if (x >= vid.width) // don't draw off the right of the screen (WRAP PREVENTION) + + if (x >= stride) // don't draw off the right of the screen (WRAP PREVENTION) break; + column = (const column_t *)((const UINT8 *)(patch->columns) + (patch->columnofs[col>>FRACBITS])); - while (column->topdelta != 0xff) + switch (patchdrawtype) { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)(column) + 3; - dest = desttop; - if (topdelta-sy > 0) - { - dest += FixedInt(FixedMul((topdelta-sy)<topdelta != 0xff) + { + topdelta = column->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + source = (const UINT8 *)(column) + 3; + dest = desttop; + if (topdelta-sy > 0) + { + dest += FixedInt(FixedMul((topdelta-sy)<>FRACBITS) < column->length && (((ofs>>FRACBITS) - sy) + topdelta) < h; ofs += rowfrac) - { - if (dest >= vid.screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION) - *dest = patchdrawfunc(dest, source, ofs); - dest += vid.width; - } - column = (const column_t *)((const UINT8 *)column + column->length + 4); + for (; dest < deststop && (ofs>>FRACBITS) < column->length && (((ofs>>FRACBITS) - sy) + topdelta) < h; ofs += rowfrac) + { + if (dest >= vid.screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION) + *dest = source[ofs>>FRACBITS]; + dest += stride; + } + column = (const column_t *)((const UINT8 *)column + column->length + 4); + } + break; + + case TRANSLUCENTDRAW: + while (column->topdelta != 0xff) + { + topdelta = column->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + source = (const UINT8 *)(column) + 3; + dest = desttop; + if (topdelta-sy > 0) + { + dest += FixedInt(FixedMul((topdelta-sy)<>FRACBITS) < column->length && (((ofs>>FRACBITS) - sy) + topdelta) < h; ofs += rowfrac) + { + if (dest >= vid.screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION) + *dest = *(v_translevel + ((source[ofs>>FRACBITS]<<8)&0xff00) + (*dest&0xff)); + dest += stride; + } + column = (const column_t *)((const UINT8 *)column + column->length + 4); + } + break; } } } -- 2.54.0 From a27550b95b551cc6fe8fa0b0b406e0821d9e0f47 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 6 Jun 2025 14:42:18 +0200 Subject: [PATCH 036/141] fix R_ProjectSprite clipping checks overflowing was causing sprites to disappear in some angles --- src/r_things.c | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 0e5a984e2..22e12c39f 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -913,7 +913,7 @@ static void R_DrawVisSprite(vissprite_t *vis) column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); - localcolfunc (&dc, column); + localcolfunc(&dc, column); } } else @@ -1207,8 +1207,6 @@ static void R_ProjectSprite(mobj_t *thing) fixed_t offset, offset2; fixed_t paperoffset = 0, paperdistance = 0; angle_t centerangle = 0; - INT32 lightnum; - //SoM: 3/17/2000 fixed_t gz, gzt; INT32 heightsec, phs; @@ -1229,7 +1227,7 @@ static void R_ProjectSprite(mobj_t *thing) angle_t sliptiderollangle = 0; #endif - if (P_MobjWasRemoved(thing) || thing->subsector == NULL) + if (!thing || thing->subsector == NULL) return; mobj_t *oldthing = thing; @@ -1273,7 +1271,7 @@ static void R_ProjectSprite(mobj_t *thing) tx = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); // sideways distance // too far off the side? - if (!papersprite && abs(tx) > tz<<2) // papersprite clipping is handled later + if (!papersprite && abs(tx) > (INT64)FixedMul(tz, fovtan)<<2) // papersprite clipping is handled later return; // aspect ratio stuff @@ -1516,7 +1514,7 @@ static void R_ProjectSprite(mobj_t *thing) tz2 = FixedMul(MINZ, this_scale); } - if (tx2 < -(FixedMul(tz2, fovtan)<<2) || tx > FixedMul(tz, fovtan)<<2) // too far off the side? + if ((tx2 / 4) < -(FixedMul(tz2, fovtan)) || (tx / 4) > FixedMul(tz, fovtan)) // too far off the side? return; yscale = FixedDiv(projectiony, tz); @@ -1542,7 +1540,7 @@ static void R_ProjectSprite(mobj_t *thing) range++; // fencepost problem - if (range > 32767) + if (range > INT16_MAX) { // If the range happens to be too large for fixed_t, // abort the draw to avoid xscale becoming negative due to arithmetic overflow. @@ -1566,14 +1564,14 @@ static void R_ProjectSprite(mobj_t *thing) scalestep = 0; yscale = sortscale; tx += offset; - x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS; + x1 = centerx + (FixedMul(tx,xscale) / FRACUNIT); // off the right side? if (x1 > viewwidth) return; tx += offset2; - x2 = ((centerxfrac + FixedMul(tx,xscale))>>FRACBITS); x2--; + x2 = (centerx + (FixedMul(tx,xscale) / FRACUNIT)) - 1; // off the left side if (x2 < 0) @@ -1590,13 +1588,13 @@ static void R_ProjectSprite(mobj_t *thing) return; } + // Determine the blendmode and translucency value INT32 blendmode; if (oldthing->frame & FF_BLENDMASK) blendmode = ((oldthing->frame & FF_BLENDMASK) >> FF_BLENDSHIFT) + 1; else blendmode = oldthing->blendmode; - // Determine the translucency value. if (oldthing->flags2 & MF2_SHADOW || thing->flags2 & MF2_SHADOW) // actually only the player should use this (temporary invisibility) trans = tr_trans80; // because now the translucency is set through FF_TRANSMASK else if (oldthing->frame & FF_TRANSMASK) @@ -1638,10 +1636,13 @@ static void R_ProjectSprite(mobj_t *thing) } else { + INT32 lightnum; + if (thing->subsector->sector->numlights) { light = thing->subsector->sector->numlights - 1; + // R_GetPlaneLight won't work on sloped lights! for (lightnum = 1; lightnum < thing->subsector->sector->numlights; lightnum++) { fixed_t h = P_GetLightZAt(&thing->subsector->sector->lightlist[lightnum], interp.x, interp.y); @@ -1662,7 +1663,7 @@ static void R_ProjectSprite(mobj_t *thing) lightnum = (lightnum + R_ThingLightLevel(thing)) >> LIGHTSEGSHIFT; - if (maplighting.directional == true && P_SectorUsesDirectionalLighting(thing->subsector->sector)) + if (maplighting.directional && P_SectorUsesDirectionalLighting(thing->subsector->sector)) { fixed_t extralight = R_GetSpriteDirectionalLighting(papersprite ? interp.angle + (ang >= ANGLE_180 ? -ANGLE_90 : ANGLE_90) @@ -1705,23 +1706,20 @@ static void R_ProjectSprite(mobj_t *thing) } heightsec = thing->subsector->sector->heightsec; - if (viewplayer->mo && viewplayer->mo->subsector) + if (viewplayer && viewplayer->mo && viewplayer->mo->subsector) phs = viewplayer->mo->subsector->sector->heightsec; else phs = -1; if (heightsec != -1 && phs != -1) // only clip things which are in special sectors { - fixed_t top = gzt; - fixed_t bottom = interp.z; - if (viewz < sectors[phs].floorheight ? - bottom >= sectors[heightsec].floorheight : - top < sectors[heightsec].floorheight) + interp.z >= sectors[heightsec].floorheight : + gzt < sectors[heightsec].floorheight) return; if (viewz > sectors[phs].ceilingheight ? - top < sectors[heightsec].ceilingheight && viewz >= sectors[heightsec].ceilingheight : - bottom >= sectors[heightsec].ceilingheight) + gzt < sectors[heightsec].ceilingheight && viewz >= sectors[heightsec].ceilingheight : + interp.z >= sectors[heightsec].ceilingheight) return; } -- 2.54.0 From 7e9da92dbe1f327b738fd9eb9339bc0ffffebddb Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 6 Jun 2025 15:22:45 +0200 Subject: [PATCH 037/141] dont redundantly clamp the sprites texturecolumn MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit we already take care of this in the lööp header --- src/r_things.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 22e12c39f..cd92f5913 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -921,10 +921,11 @@ static void R_DrawVisSprite(vissprite_t *vis) // Non-paper drawing loop for (dc.x = vis->x1; dc.x <= vis->x2 && (frac>>FRACBITS) < pwidth; dc.x++, frac += vis->xiscale) { - texturecolumn = CLAMP(frac >> FRACBITS, 0, pwidth - 1); + //texturecolumn = CLAMP(frac >> FRACBITS, 0, pwidth - 1); + texturecolumn = (frac >> FRACBITS); column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); - localcolfunc (&dc, column); + localcolfunc(&dc, column); } } -- 2.54.0 From 5a14b09c1fe0af37ba83fec7d6f543503dfe86d2 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 6 Jun 2025 16:35:04 +0200 Subject: [PATCH 038/141] cache ds->transmap for translucent span drawers super slight speedup --- src/r_draw_span.c | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/r_draw_span.c b/src/r_draw_span.c index 655b19479..20ae9e654 100644 --- a/src/r_draw_span.c +++ b/src/r_draw_span.c @@ -149,48 +149,50 @@ void R_DrawTranslucentSpan(drawspandata_t* ds) colormap = ds->colormap; dest = R_Address(ds->x1, ds->y); + register const UINT8 *tranmap = ds->transmap; + while (count >= 8) { // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // have the uber complicated math to calculate it now, so that was a memory write we didn't // need! bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); - dest[0] = *(ds->transmap + (colormap[source[bit]] << 8) + dest[0]); + dest[0] = *(tranmap + (colormap[source[bit]] << 8) + dest[0]); xposition += xstep; yposition += ystep; bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); - dest[1] = *(ds->transmap + (colormap[source[bit]] << 8) + dest[1]); + dest[1] = *(tranmap + (colormap[source[bit]] << 8) + dest[1]); xposition += xstep; yposition += ystep; bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); - dest[2] = *(ds->transmap + (colormap[source[bit]] << 8) + dest[2]); + dest[2] = *(tranmap + (colormap[source[bit]] << 8) + dest[2]); xposition += xstep; yposition += ystep; bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); - dest[3] = *(ds->transmap + (colormap[source[bit]] << 8) + dest[3]); + dest[3] = *(tranmap + (colormap[source[bit]] << 8) + dest[3]); xposition += xstep; yposition += ystep; bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); - dest[4] = *(ds->transmap + (colormap[source[bit]] << 8) + dest[4]); + dest[4] = *(tranmap + (colormap[source[bit]] << 8) + dest[4]); xposition += xstep; yposition += ystep; bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); - dest[5] = *(ds->transmap + (colormap[source[bit]] << 8) + dest[5]); + dest[5] = *(tranmap + (colormap[source[bit]] << 8) + dest[5]); xposition += xstep; yposition += ystep; bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); - dest[6] = *(ds->transmap + (colormap[source[bit]] << 8) + dest[6]); + dest[6] = *(tranmap + (colormap[source[bit]] << 8) + dest[6]); xposition += xstep; yposition += ystep; bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); - dest[7] = *(ds->transmap + (colormap[source[bit]] << 8) + dest[7]); + dest[7] = *(tranmap + (colormap[source[bit]] << 8) + dest[7]); xposition += xstep; yposition += ystep; @@ -200,7 +202,7 @@ void R_DrawTranslucentSpan(drawspandata_t* ds) while (count-- && dest <= deststop) { bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); - *dest = *(ds->transmap + (colormap[source[bit]] << 8) + *dest); + *dest = *(tranmap + (colormap[source[bit]] << 8) + *dest); dest++; xposition += xstep; yposition += ystep; @@ -237,48 +239,50 @@ void R_DrawTranslucentWaterSpan(drawspandata_t* ds) dsrc = vid.screens[1] + (ds->y+ds->bgofs)*vid.width + ds->x1; count = ds->x2 - ds->x1 + 1; + register const UINT8 *tranmap = ds->transmap; + while (count >= 8) { // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // have the uber complicated math to calculate it now, so that was a memory write we didn't // need! bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[0] = colormap[*(ds->transmap + (source[bit] << 8) + *dsrc++)]; + dest[0] = colormap[*(tranmap + (source[bit] << 8) + *dsrc++)]; xposition += xstep; yposition += ystep; bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[1] = colormap[*(ds->transmap + (source[bit] << 8) + *dsrc++)]; + dest[1] = colormap[*(tranmap + (source[bit] << 8) + *dsrc++)]; xposition += xstep; yposition += ystep; bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[2] = colormap[*(ds->transmap + (source[bit] << 8) + *dsrc++)]; + dest[2] = colormap[*(tranmap + (source[bit] << 8) + *dsrc++)]; xposition += xstep; yposition += ystep; bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[3] = colormap[*(ds->transmap + (source[bit] << 8) + *dsrc++)]; + dest[3] = colormap[*(tranmap + (source[bit] << 8) + *dsrc++)]; xposition += xstep; yposition += ystep; bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[4] = colormap[*(ds->transmap + (source[bit] << 8) + *dsrc++)]; + dest[4] = colormap[*(tranmap + (source[bit] << 8) + *dsrc++)]; xposition += xstep; yposition += ystep; bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[5] = colormap[*(ds->transmap + (source[bit] << 8) + *dsrc++)]; + dest[5] = colormap[*(tranmap + (source[bit] << 8) + *dsrc++)]; xposition += xstep; yposition += ystep; bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[6] = colormap[*(ds->transmap + (source[bit] << 8) + *dsrc++)]; + dest[6] = colormap[*(tranmap + (source[bit] << 8) + *dsrc++)]; xposition += xstep; yposition += ystep; bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[7] = colormap[*(ds->transmap + (source[bit] << 8) + *dsrc++)]; + dest[7] = colormap[*(tranmap + (source[bit] << 8) + *dsrc++)]; xposition += xstep; yposition += ystep; @@ -288,7 +292,7 @@ void R_DrawTranslucentWaterSpan(drawspandata_t* ds) while (count--) { bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - *dest++ = colormap[*(ds->transmap + (source[bit] << 8) + *dsrc++)]; + *dest++ = colormap[*(tranmap + (source[bit] << 8) + *dsrc++)]; xposition += xstep; yposition += ystep; -- 2.54.0 From 2f66207205e0cae2d31696a8304adfbf2ca2205f Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 6 Jun 2025 16:55:28 +0200 Subject: [PATCH 039/141] make this less ugly --- src/r_segs.c | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/src/r_segs.c b/src/r_segs.c index fb671ece4..54a59c5e5 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -1294,11 +1294,11 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) bottom_w = bottom; // Polyobject-specific hack to fix plane leaking -Red - if (ffloor[i].polyobj && top_w >= bottom_w) { + if (ffloor[i].polyobj && top_w >= bottom_w) + { ffloor[i].plane->top[rw_x] = ffloor[i].plane->bottom[rw_x] = 0xFFFF; - } else - - if (top_w <= bottom_w) + } + else if (top_w <= bottom_w) { fftop = (INT16)top_w; ffbottom = (INT16)bottom_w; @@ -1338,11 +1338,11 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) bottom_w = bottom; // Polyobject-specific hack to fix plane leaking -Red - if (ffloor[i].polyobj && top_w >= bottom_w) { + if (ffloor[i].polyobj && top_w >= bottom_w) + { ffloor[i].plane->top[rw_x] = ffloor[i].plane->bottom[rw_x] = 0xFFFF; - } else - - if (top_w <= bottom_w) + } + else if (top_w <= bottom_w) { fftop = (INT16)top_w; ffbottom = (INT16)bottom_w; @@ -1356,6 +1356,7 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) { rw_ceilingmarked = true; ceilingclip[rw_x] = ffbottom; + if (yl < ffbottom) yl = ffbottom; @@ -1379,7 +1380,8 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) // Mask 4095 to guarantee this index is within bounds texturecolumn = rw_offset-FixedMul(FINETANGENT(angle & 4095),rw_distance); - if (oldtexturecolumn != -1) { + if (oldtexturecolumn != -1) + { rw_bottomtexturemid += FixedMul(rw_bottomtextureslide, oldtexturecolumn-texturecolumn); rw_midtexturemid += FixedMul(rw_midtextureslide, oldtexturecolumn-texturecolumn); rw_toptexturemid += FixedMul(rw_toptextureslide, oldtexturecolumn-texturecolumn); @@ -1399,8 +1401,10 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) pindex = MAXLIGHTSCALE-1; dc->colormap = walllights[pindex]; + if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) dc->colormap += COLORMAP_REMAPOFFSET; + dc->x = rw_x; dc->iscale = 0xffffffffu / (unsigned)rw_scale; @@ -1411,6 +1415,7 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) if (dc->numlights) { lighttable_t **xwalllights; + for (i = 0; i < dc->numlights; i++) { INT32 lightnum; @@ -1453,7 +1458,7 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) dc->yl = yl; dc->yh = yh; dc->texturemid = rw_midtexturemid; - dc->source = R_GetColumn(midtexture,texturecolumn); + dc->source = R_GetColumn(midtexture, texturecolumn); dc->texheight = textureheight[midtexture]>>FRACBITS; dc->sourcelength = dc->texheight; colfunc(dc); @@ -1470,6 +1475,7 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) // note: don't use min/max macros, since casting from INT32 to INT16 is involved here if (markceiling && (!rw_ceilingmarked)) ceilingclip[rw_x] = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1; + if (markfloor && (!rw_floormarked)) floorclip[rw_x] = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight; } @@ -1501,7 +1507,7 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) dc->yl = yl; dc->yh = mid; dc->texturemid = rw_toptexturemid; - dc->source = R_GetColumn(toptexture,texturecolumn); + dc->source = R_GetColumn(toptexture, texturecolumn); dc->texheight = textureheight[toptexture]>>FRACBITS; dc->sourcelength = dc->texheight; colfunc(dc); @@ -1538,8 +1544,7 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) dc->yl = mid; dc->yh = yh; dc->texturemid = rw_bottomtexturemid; - dc->source = R_GetColumn(bottomtexture, - texturecolumn); + dc->source = R_GetColumn(bottomtexture, texturecolumn); dc->texheight = textureheight[bottomtexture]>>FRACBITS; dc->sourcelength = dc->texheight; colfunc(dc); @@ -1560,7 +1565,8 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) // save texturecol for backdrawing of masked mid texture maskedtexturecol[rw_x] = (INT16)texturecolumn; - if (maskedtextureheight != NULL) { + if (maskedtextureheight != NULL) + { maskedtextureheight[rw_x] = (!!(curline->linedef->flags & ML_DONTPEGBOTTOM) ^ !!(curline->linedef->flags & ML_EFFECT3) ? max(rw_midtexturemid, rw_midtextureback) : min(rw_midtexturemid, rw_midtextureback)); @@ -1572,6 +1578,7 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) for (i = 0; i < dc->numlights; i++) { dc->lightlist[i].height += dc->lightlist[i].heightstep; + if (dc->lightlist[i].flags & FF_CUTSOLIDS) dc->lightlist[i].botheight += dc->lightlist[i].botheightstep; } -- 2.54.0 From 21f2032f34cff80b3013b9754a41dbc14f2cc8d6 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 6 Jun 2025 17:37:40 +0200 Subject: [PATCH 040/141] save smol amount of fixed to double conversions in R_StoreWallRange also adds those as actual functions in case we wanna use it for smth else --- src/m_fixed.h | 14 +++++ src/r_segs.c | 150 ++++++++++++++++++++++---------------------------- 2 files changed, 81 insertions(+), 83 deletions(-) diff --git a/src/m_fixed.h b/src/m_fixed.h index 3f1acd7ae..ae77c83b9 100644 --- a/src/m_fixed.h +++ b/src/m_fixed.h @@ -49,6 +49,20 @@ FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FloatToFixed(float f) return (fixed_t)(f * FRACUNIT); } +/*! + \brief convert fixed_t into double-precision floating number +*/ + +FUNCMATH FUNCINLINE static ATTRINLINE double FixedToDouble(fixed_t x) +{ + return x / (double)FRACUNIT; +} + +FUNCMATH FUNCINLINE static ATTRINLINE fixed_t DoubleToFixed(double f) +{ + return (fixed_t)(f * FRACUNIT); +} + // for backwards compat #define FIXED_TO_FLOAT(x) FixedToFloat(x) // (((float)(x)) / ((float)FRACUNIT)) #define FLOAT_TO_FIXED(f) FloatToFixed(f) // (fixed_t)((f) * ((float)FRACUNIT)) diff --git a/src/r_segs.c b/src/r_segs.c index 54a59c5e5..d0716a3b3 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -1798,57 +1798,38 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (frontsector->hasslope || (backsector && backsector->hasslope)) // Commenting this out for FOFslop. -Red { angle_t temp; + double a1, b1, c1, a2, b2, c2, det; // 1 is the seg, 2 is the view angle vector... // left temp = xtoviewangle[start]+viewangle; -#define FIXED_TO_DOUBLE(x) (((double)(x)) / ((double)FRACUNIT)) -#define DOUBLE_TO_FIXED(x) (fixed_t)((x) * ((double)FRACUNIT)) + a1 = FixedToDouble(curline->v2->y-curline->v1->y); + b1 = FixedToDouble(curline->v1->x-curline->v2->x); + c1 = a1*FixedToDouble(curline->v1->x) + b1*FixedToDouble(curline->v1->y); - { - // Both lines can be written in slope-intercept form, so figure out line intersection - double a1, b1, c1, a2, b2, c2, det; // 1 is the seg, 2 is the view angle vector... - ///TODO: convert to fixed point + // Both lines can be written in slope-intercept form, so figure out line intersection - a1 = FIXED_TO_DOUBLE(curline->v2->y-curline->v1->y); - b1 = FIXED_TO_DOUBLE(curline->v1->x-curline->v2->x); - c1 = a1*FIXED_TO_DOUBLE(curline->v1->x) + b1*FIXED_TO_DOUBLE(curline->v1->y); + // left + a2 = -FixedToDouble(FINESINE(temp>>ANGLETOFINESHIFT)); + b2 = FixedToDouble(FINECOSINE(temp>>ANGLETOFINESHIFT)); + c2 = a2*FixedToDouble(viewx) + b2*FixedToDouble(viewy); - a2 = -FIXED_TO_DOUBLE(FINESINE(temp>>ANGLETOFINESHIFT)); - b2 = FIXED_TO_DOUBLE(FINECOSINE(temp>>ANGLETOFINESHIFT)); - c2 = a2*FIXED_TO_DOUBLE(viewx) + b2*FIXED_TO_DOUBLE(viewy); + det = a1*b2 - a2*b1; - det = a1*b2 - a2*b1; - - ds_p->leftpos.x = segleft.x = DOUBLE_TO_FIXED((b2*c1 - b1*c2)/det); - ds_p->leftpos.y = segleft.y = DOUBLE_TO_FIXED((a1*c2 - a2*c1)/det); - } + ds_p->leftpos.x = segleft.x = DoubleToFixed((b2*c1 - b1*c2)/det); + ds_p->leftpos.y = segleft.y = DoubleToFixed((a1*c2 - a2*c1)/det); // right temp = xtoviewangle[stop]+viewangle; - { - // Both lines can be written in slope-intercept form, so figure out line intersection - double a1, b1, c1, a2, b2, c2, det; // 1 is the seg, 2 is the view angle vector... - ///TODO: convert to fixed point + a2 = -FixedToDouble(FINESINE(temp>>ANGLETOFINESHIFT)); + b2 = FixedToDouble(FINECOSINE(temp>>ANGLETOFINESHIFT)); + c2 = a2*FixedToDouble(viewx) + b2*FixedToDouble(viewy); - a1 = FIXED_TO_DOUBLE(curline->v2->y-curline->v1->y); - b1 = FIXED_TO_DOUBLE(curline->v1->x-curline->v2->x); - c1 = a1*FIXED_TO_DOUBLE(curline->v1->x) + b1*FIXED_TO_DOUBLE(curline->v1->y); - - a2 = -FIXED_TO_DOUBLE(FINESINE(temp>>ANGLETOFINESHIFT)); - b2 = FIXED_TO_DOUBLE(FINECOSINE(temp>>ANGLETOFINESHIFT)); - c2 = a2*FIXED_TO_DOUBLE(viewx) + b2*FIXED_TO_DOUBLE(viewy); - - det = a1*b2 - a2*b1; - - ds_p->rightpos.x = segright.x = DOUBLE_TO_FIXED((b2*c1 - b1*c2)/det); - ds_p->rightpos.y = segright.y = DOUBLE_TO_FIXED((a1*c2 - a2*c1)/det); - } - -#undef FIXED_TO_DOUBLE -#undef DOUBLE_TO_FIXED + det = a1*b2 - a2*b1; + ds_p->rightpos.x = segright.x = DoubleToFixed((b2*c1 - b1*c2)/det); + ds_p->rightpos.y = segright.y = DoubleToFixed((a1*c2 - a2*c1)/det); } #define SLOPEPARAMS(slope, end1, end2, normalheight) \ @@ -1908,11 +1889,14 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (!backsector) { fixed_t texheight; + // single sided line midtexture = R_GetTextureNum(sidedef->midtexture); texheight = textureheight[midtexture]; + // a single sided line is terminal, so it must mark ends markfloor = markceiling = true; + if (linedef->flags & ML_EFFECT2) { if (linedef->flags & ML_DONTPEGBOTTOM) @@ -2012,18 +1996,18 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (worldlow != worldbottom || worldlowslope != worldbottomslope || backsector->f_slope != frontsector->f_slope - || backsector->floorpic != frontsector->floorpic - || backsector->lightlevel != frontsector->lightlevel - //SoM: 3/22/2000: Check floor x and y offsets. - || backsector->floor_xoffs != frontsector->floor_xoffs - || backsector->floor_yoffs != frontsector->floor_yoffs - || backsector->floorpic_angle != frontsector->floorpic_angle - //SoM: 3/22/2000: Prevents bleeding. - || frontsector->heightsec != -1 - || backsector->floorlightsec != frontsector->floorlightsec - //SoM: 4/3/2000: Check for colormaps - || frontsector->extra_colormap != backsector->extra_colormap - || (frontsector->ffloors != backsector->ffloors && frontsector->tag != backsector->tag)) + || backsector->floorpic != frontsector->floorpic + || backsector->lightlevel != frontsector->lightlevel + //SoM: 3/22/2000: Check floor x and y offsets. + || backsector->floor_xoffs != frontsector->floor_xoffs + || backsector->floor_yoffs != frontsector->floor_yoffs + || backsector->floorpic_angle != frontsector->floorpic_angle + //SoM: 3/22/2000: Prevents bleeding. + || frontsector->heightsec != -1 + || backsector->floorlightsec != frontsector->floorlightsec + //SoM: 4/3/2000: Check for colormaps + || frontsector->extra_colormap != backsector->extra_colormap + || (frontsector->ffloors != backsector->ffloors && frontsector->tag != backsector->tag)) { markfloor = true; } @@ -2036,18 +2020,18 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (worldhigh != worldtop || worldhighslope != worldtopslope || backsector->c_slope != frontsector->c_slope - || backsector->ceilingpic != frontsector->ceilingpic - || backsector->lightlevel != frontsector->lightlevel - //SoM: 3/22/2000: Check floor x and y offsets. - || backsector->ceiling_xoffs != frontsector->ceiling_xoffs - || backsector->ceiling_yoffs != frontsector->ceiling_yoffs - || backsector->ceilingpic_angle != frontsector->ceilingpic_angle - //SoM: 3/22/2000: Prevents bleeding. - || (frontsector->heightsec != -1 && frontsector->ceilingpic != skyflatnum) - || backsector->ceilinglightsec != frontsector->ceilinglightsec - //SoM: 4/3/2000: Check for colormaps - || frontsector->extra_colormap != backsector->extra_colormap - || (frontsector->ffloors != backsector->ffloors && frontsector->tag != backsector->tag)) + || backsector->ceilingpic != frontsector->ceilingpic + || backsector->lightlevel != frontsector->lightlevel + //SoM: 3/22/2000: Check floor x and y offsets. + || backsector->ceiling_xoffs != frontsector->ceiling_xoffs + || backsector->ceiling_yoffs != frontsector->ceiling_yoffs + || backsector->ceilingpic_angle != frontsector->ceilingpic_angle + //SoM: 3/22/2000: Prevents bleeding. + || (frontsector->heightsec != -1 && frontsector->ceilingpic != skyflatnum) + || backsector->ceilinglightsec != frontsector->ceilinglightsec + //SoM: 4/3/2000: Check for colormaps + || frontsector->extra_colormap != backsector->extra_colormap + || (frontsector->ffloors != backsector->ffloors && frontsector->tag != backsector->tag)) { markceiling = true; } @@ -2058,7 +2042,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) } if (backsector->ceilingheight <= frontsector->floorheight || - backsector->floorheight >= frontsector->ceilingheight) + backsector->floorheight >= frontsector->ceilingheight) { // closed door markceiling = markfloor = true; @@ -2282,9 +2266,9 @@ void R_StoreWallRange(INT32 start, INT32 stop) // Oy vey. if ( ((P_GetFFloorTopZAt (rover, segleft .x, segleft .y)) <= worldbottom + viewz - && (P_GetFFloorTopZAt (rover, segright.x, segright.y)) <= worldbottomslope + viewz) - ||((P_GetFFloorBottomZAt(rover, segleft .x, segleft .y)) >= worldtop + viewz - && (P_GetFFloorBottomZAt(rover, segright.x, segright.y)) >= worldtopslope + viewz)) + && (P_GetFFloorTopZAt (rover, segright.x, segright.y)) <= worldbottomslope + viewz) + ||((P_GetFFloorBottomZAt(rover, segleft .x, segleft .y)) >= worldtop + viewz + && (P_GetFFloorBottomZAt(rover, segright.x, segright.y)) >= worldtopslope + viewz)) continue; ds_p->thicksides[i] = rover; @@ -2302,15 +2286,15 @@ void R_StoreWallRange(INT32 start, INT32 stop) // Oy vey. if ( (P_GetFFloorTopZAt (rover, segleft .x, segleft .y) <= worldbottom + viewz - && P_GetFFloorTopZAt (rover, segright.x, segright.y) <= worldbottomslope + viewz) - ||(P_GetFFloorBottomZAt(rover, segleft .x, segleft .y) >= worldtop + viewz - && P_GetFFloorBottomZAt(rover, segright.x, segright.y) >= worldtopslope + viewz)) + && P_GetFFloorTopZAt (rover, segright.x, segright.y) <= worldbottomslope + viewz) + ||(P_GetFFloorBottomZAt(rover, segleft .x, segleft .y) >= worldtop + viewz + && P_GetFFloorBottomZAt(rover, segright.x, segright.y) >= worldtopslope + viewz)) continue; if ( (P_GetFFloorTopZAt (rover, segleft .x, segleft .y) <= worldlow + viewz - && P_GetFFloorTopZAt (rover, segright.x, segright.y) <= worldlowslope + viewz) - ||(P_GetFFloorBottomZAt(rover, segleft .x, segleft .y) >= worldhigh + viewz - && P_GetFFloorBottomZAt(rover, segright.x, segright.y) >= worldhighslope + viewz)) + && P_GetFFloorTopZAt (rover, segright.x, segright.y) <= worldlowslope + viewz) + ||(P_GetFFloorBottomZAt(rover, segleft .x, segleft .y) >= worldhigh + viewz + && P_GetFFloorBottomZAt(rover, segright.x, segright.y) >= worldhighslope + viewz)) continue; ds_p->thicksides[i] = rover; @@ -2626,9 +2610,9 @@ void R_StoreWallRange(INT32 start, INT32 stop) planevistest = P_GetFFloorBottomZAt(rover, viewx, viewy); if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) && - (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) && - ((viewz < planevistest && !(rover->flags & FF_INVERTPLANES)) || - (viewz > planevistest && (rover->flags & FF_BOTHPLANES)))) + (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) && + ((viewz < planevistest && !(rover->flags & FF_INVERTPLANES)) || + (viewz > planevistest && (rover->flags & FF_BOTHPLANES)))) { //ffloor[i].slope = *rover->b_slope; ffloor[i].b_pos = roverleft; @@ -2649,9 +2633,9 @@ void R_StoreWallRange(INT32 start, INT32 stop) planevistest = P_GetFFloorTopZAt(rover, viewx, viewy); if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) && - (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) && - ((viewz > planevistest && !(rover->flags & FF_INVERTPLANES)) || - (viewz < planevistest && (rover->flags & FF_BOTHPLANES)))) + (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) && + ((viewz > planevistest && !(rover->flags & FF_INVERTPLANES)) || + (viewz < planevistest && (rover->flags & FF_BOTHPLANES)))) { //ffloor[i].slope = *rover->t_slope; ffloor[i].b_pos = roverleft; @@ -2683,9 +2667,9 @@ void R_StoreWallRange(INT32 start, INT32 stop) planevistest = P_GetFFloorBottomZAt(rover, viewx, viewy); if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) && - (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) && - ((viewz < planevistest && !(rover->flags & FF_INVERTPLANES)) || - (viewz > planevistest && (rover->flags & FF_BOTHPLANES)))) + (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) && + ((viewz < planevistest && !(rover->flags & FF_INVERTPLANES)) || + (viewz > planevistest && (rover->flags & FF_BOTHPLANES)))) { //ffloor[i].slope = *rover->b_slope; ffloor[i].b_pos = roverleft; @@ -2706,9 +2690,9 @@ void R_StoreWallRange(INT32 start, INT32 stop) planevistest = P_GetFFloorTopZAt(rover, viewx, viewy); if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) && - (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) && - ((viewz > planevistest && !(rover->flags & FF_INVERTPLANES)) || - (viewz < planevistest && (rover->flags & FF_BOTHPLANES)))) + (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) && + ((viewz > planevistest && !(rover->flags & FF_INVERTPLANES)) || + (viewz < planevistest && (rover->flags & FF_BOTHPLANES)))) { //ffloor[i].slope = *rover->t_slope; ffloor[i].b_pos = roverleft; -- 2.54.0 From 2ffe736a20ce064f3646f8f6ae6a11aba3789667 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 6 Jun 2025 21:14:53 +0200 Subject: [PATCH 041/141] smol cleanup --- src/r_main.cpp | 12 +++--------- src/r_plane.cpp | 36 ++++++++++++++---------------------- 2 files changed, 17 insertions(+), 31 deletions(-) diff --git a/src/r_main.cpp b/src/r_main.cpp index 4530e6c19..d0f9a7428 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1448,17 +1448,11 @@ void R_RenderPlayerView(player_t *player) // check for new console commands. NetUpdate(); - // The head node is the last node output. - //masks = realloc(masks, (++nummasks)*sizeof(maskcount_t)); - ps_numbspcalls.value.i = ps_numpolyobjects.value.i = ps_numdrawnodes.value.i = 0; PS_START_TIMING(ps_bsptime); - if (skybox && skyVisible) - { - tp_sema = srb2::g_main_threadpool->end_sema(); - srb2::g_main_threadpool->notify_sema(tp_sema); - srb2::g_main_threadpool->wait_sema(tp_sema); - } + tp_sema = srb2::g_main_threadpool->end_sema(); + srb2::g_main_threadpool->notify_sema(tp_sema); + srb2::g_main_threadpool->wait_sema(tp_sema); srb2::g_main_threadpool->begin_sema(); R_RenderViewpoint(&masks[nummasks - 1], true); diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 484f5f413..2a85f96a2 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -287,8 +287,6 @@ static void R_MapPlane(drawspandata_t *ds, void(*spanfunc2)(drawspandata_t*), IN if (ds->planeripple.active) { - // Needed for ds_bgofs - ds->bgofs = R_CalculateRippleOffset(ds, y); R_CalculatePlaneRipple(ds, ds->currentplane->viewangle + ds->currentplane->plangle); @@ -450,8 +448,8 @@ static visplane_t *new_visplane(unsigned hash) // If not, allocates another of them. // visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, - fixed_t xoff, fixed_t yoff, angle_t plangle, extracolormap_t *planecolormap, - ffloor_t *pfloor + fixed_t xoff, fixed_t yoff, angle_t plangle, extracolormap_t *planecolormap + , ffloor_t *pfloor , polyobj_t *polyobj , pslope_t *slope , boolean noencore @@ -460,10 +458,8 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, visplane_t *check; unsigned hash; - if (slope); else // Don't mess with this right now if a slope is involved + if (!slope) // Don't mess with this right now if a slope is involved { - xoff += viewx; - yoff -= viewy; if (plangle != 0) { // Add the view offset, rotated by the plane angle. @@ -473,6 +469,11 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, xoff = FixedMul(xoff,cosinecomponent)+FixedMul(yoff,sinecomponent); yoff = -FixedMul(oldxoff,sinecomponent)+FixedMul(yoff,cosinecomponent); } + else + { + xoff += viewx; + yoff -= viewy; + } } if (polyobj) @@ -676,14 +677,7 @@ void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop) { unionh = pl->maxx; } -/* - for (x = start; x <= stop; x++) - if (pl->top[x] != 0xffff || pl->bottom[x] != 0x0000) - break; - if (x <= stop) - I_Error("R_ExpandPlane: planes in same subsector overlap?!\nminx: %d, maxx: %d, start: %d, stop: %d\n", pl->minx, pl->maxx, start, stop); -*/ pl->minx = unionl, pl->maxx = unionh; } @@ -776,9 +770,6 @@ void R_DrawPlanes(void) INT32 i; drawspandata_t ds = {}; - spanfunc = basespanfunc; - wallcolfunc = walldrawerfunc; - R_UpdatePlaneRipple(&ds); for (i = 0; i < MAXVISPLANES; i++, pl++) @@ -804,10 +795,14 @@ static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), b return; } - wallcolfunc = walldrawerfunc; + // Reset column drawer function (note: couldn't we just call walldrawerfunc directly?) + // (that is, unless we'll need to switch drawers in future for some reason) + //wallcolfunc = walldrawerfunc; + colfunc = basecolfunc; // use correct aspect ratio scale dc.iscale = skyscale; + // Sky is always drawn full bright, // i.e. colormaps[0] is used. // Because of this hack, sky is not affected @@ -1084,10 +1079,7 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle ds->currentplane = pl; - ds->source = (UINT8 *) - W_CacheLumpNum(levelflats[pl->picnum].lumpnum, - PU_STATIC); // Stay here until Z_ChangeTag - + ds->source = (UINT8 *)W_CacheLumpNum(levelflats[pl->picnum].lumpnum, PU_STATIC); // Stay here until Z_ChangeTag size = W_LumpLength(levelflats[pl->picnum].lumpnum); switch (size) -- 2.54.0 From 97b303c3622e017e57ae2da3b96ec0cd1c2e026b Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 6 Jun 2025 23:13:33 +0200 Subject: [PATCH 042/141] split skin stuff from r_things into r_skins what a mess --- src/Sourcefile | 1 + src/lua_baselib.c | 1 + src/lua_hooklib.c | 1 + src/lua_mobjlib.c | 1 + src/lua_playerlib.c | 1 + src/lua_skinlib.c | 3 +- src/m_menu.h | 1 + src/p_enemy.c | 1 + src/p_mobj.c | 1 + src/p_saveg.c | 1 + src/r_draw.h | 1 + src/r_patch.c | 1 + src/r_skins.c | 791 ++++++++++++++++++++++++++++++++++++++++++ src/r_skins.h | 152 ++++++++ src/r_things.c | 827 ++------------------------------------------ src/r_things.h | 140 +------- 16 files changed, 998 insertions(+), 926 deletions(-) create mode 100644 src/r_skins.c create mode 100644 src/r_skins.h diff --git a/src/Sourcefile b/src/Sourcefile index 227e6c95a..8c893fc68 100644 --- a/src/Sourcefile +++ b/src/Sourcefile @@ -54,6 +54,7 @@ r_patch.c r_patchrotation.c r_plane.c r_segs.c +r_skins.c r_sky.c r_splats.c r_things.c diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 0ccc7d8ed..3e4ab9da0 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -16,6 +16,7 @@ #include "p_slopes.h" // P_GetZAt #include "z_zone.h" #include "r_main.h" +#include "r_skins.h" #include "r_things.h" #include "m_random.h" #include "s_sound.h" diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index a0f795985..401a18654 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -14,6 +14,7 @@ #include "doomstat.h" #include "p_mobj.h" #include "g_game.h" +#include "r_skins.h" #include "r_things.h" #include "b_bot.h" #include "z_zone.h" diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 504a1e130..4103bce99 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -15,6 +15,7 @@ #include "doomdef.h" #include "fastcmp.h" #include "r_things.h" +#include "r_skins.h" #include "r_main.h" #include "p_local.h" #include "g_game.h" diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 9562c5679..665512aef 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -13,6 +13,7 @@ #include "doomdef.h" #include "fastcmp.h" #include "r_main.h" +#include "r_skins.h" #include "r_things.h" #include "p_mobj.h" #include "d_player.h" diff --git a/src/lua_skinlib.c b/src/lua_skinlib.c index 403ac834e..4425f125c 100644 --- a/src/lua_skinlib.c +++ b/src/lua_skinlib.c @@ -12,6 +12,7 @@ #include "doomdef.h" #include "fastcmp.h" +#include "r_skins.h" #include "r_things.h" #include "sounds.h" @@ -277,4 +278,4 @@ int LUA_SkinLib(lua_State *L) lua_setglobal(L, "skins"); return 0; -} \ No newline at end of file +} diff --git a/src/m_menu.h b/src/m_menu.h index 126d59e1b..d14d05cbe 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -15,6 +15,7 @@ #ifndef __X_MENU__ #define __X_MENU__ +#include "r_skins.h" #include "d_event.h" #include "command.h" #include "i_threads.h" diff --git a/src/p_enemy.c b/src/p_enemy.c index d500a0cb2..8cf62935a 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -16,6 +16,7 @@ #include "g_game.h" #include "p_local.h" #include "r_main.h" +#include "r_skins.h" #include "r_state.h" #include "s_sound.h" #include "m_random.h" diff --git a/src/p_mobj.c b/src/p_mobj.c index 06cbd3b17..70f4dbacf 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -20,6 +20,7 @@ #include "p_setup.h" #include "r_fps.h" #include "r_main.h" +#include "r_skins.h" #include "r_things.h" #include "r_sky.h" #include "r_splats.h" diff --git a/src/p_saveg.c b/src/p_saveg.c index 3d17a14de..e8a5971ca 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -24,6 +24,7 @@ #include "r_fps.h" #include "r_things.h" #include "r_state.h" +#include "r_skins.h" #include "w_wad.h" #include "y_inter.h" #include "z_zone.h" diff --git a/src/r_draw.h b/src/r_draw.h index 12ab3f584..a61ce33e3 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -20,6 +20,7 @@ extern "C" { #include "r_defs.h" #include "r_things.h" +#include "r_skins.h" // ------------------------------- // COMMON STUFF FOR 8bpp AND 16bpp diff --git a/src/r_patch.c b/src/r_patch.c index 21f59401c..f48996ea4 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -16,6 +16,7 @@ #include "doomdef.h" #include "r_patch.h" #include "r_things.h" +#include "r_skins.h" #include "z_zone.h" #include "w_wad.h" diff --git a/src/r_skins.c b/src/r_skins.c new file mode 100644 index 000000000..6bda9e263 --- /dev/null +++ b/src/r_skins.c @@ -0,0 +1,791 @@ +// SONIC ROBO BLAST 2 KART +//----------------------------------------------------------------------------- +// Copyright (C) 2025 by Vivian "toastergrl" Grannell. +// Copyright (C) 2025 by Kart Krew. +// Copyright (C) 2020 by Sonic Team Junior. +// Copyright (C) 2000 by DooM Legacy Team. +// Copyright (C) 1996 by id Software, Inc. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file r_skins.c +/// \brief Loading skins + +#include "dehacked.h" // get_number (for thok) +#include "doomdef.h" +#include "console.h" +#include "r_draw.h" +#include "r_things.h" +#include "r_skins.h" +#include "g_game.h" +#include "k_kart.h" // SRB2kart +#include "p_local.h" +#include "st_stuff.h" +#include "i_video.h" // rendermode +#include "w_wad.h" +#include "z_zone.h" + +#ifdef HWRENDER +#include "hardware/hw_md2.h" +#endif + +#include "qs22j.h" + +CV_PossibleValue_t Forceskin_cons_t[MAXSKINS+2]; + +INT32 numskins = 0; +INT32 numallskins = 0; +INT32 numlocalskins = 0; +skin_t skins[MAXSKINS]; +UINT8 skinstats[9][9][MAXSKINS]; +UINT8 skinstatscount[9][9] = { + {0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0} +}; +UINT8 skinsorted[MAXSKINS]; +skin_t localskins[MAXLOCALSKINS]; +skin_t allskins[MAXSKINS+MAXLOCALSKINS]; + +// FIXTHIS: don't work because it must be inistilised before the config load +//#define SKINVALUES +#ifdef SKINVALUES +CV_PossibleValue_t skin_cons_t[MAXSKINS+1]; +CV_PossibleValue_t localskin_cons_t[MAXLOCALSKINS+1]; +#endif + +static void Sk_SetDefaultValue(skin_t *skin, boolean local) +{ + INT32 i; + // + // set default skin values + // + memset(skin, 0, sizeof (skin_t)); + snprintf(skin->name, sizeof skin->name, "skin %u", K_GetMobjSkinNum(skin, local)); + skin->name[sizeof skin->name - 1] = '\0'; + skin->wadnum = INT16_MAX; + strcpy(skin->sprite, ""); + + skin->flags = 0; + + strcpy(skin->realname, "Someone"); + strcpy(skin->hudname, "???"); + strncpy(skin->facerank, "PLAYRANK", 9); + strncpy(skin->facewant, "PLAYWANT", 9); + strncpy(skin->facemmap, "PLAYMMAP", 9); + + skin->starttranscolor = 160; + skin->prefcolor = SKINCOLOR_GREEN; + + // SRB2kart + skin->kartspeed = 5; + skin->kartweight = 5; + // + + skin->highresscale = FRACUNIT>>1; + + for (i = 0; i < sfx_skinsoundslot0; i++) + if (S_sfx[i].skinsound != -1) + skin->soundsid[S_sfx[i].skinsound] = i; +} + +// +// Initialize the basic skins +// +void R_InitSkins(void) +{ + skin_t *skin; +#ifdef SKINVALUES + INT32 i; + + for (i = 0; i <= MAXSKINS; i++) + { + skin_cons_t[i].value = 0; + skin_cons_t[i].strvalue = NULL; + } + for (i = 0; i <= MAXLOCALSKINS; i++) + { + localskin_cons_t[i].value = 0; + localskin_cons_t[i].strvalue = NULL; + } +#endif + + // skin[0] = Sonic skin + skin = &skins[0]; + numskins = 1; + Sk_SetDefaultValue(skin, false); + memset(skinstats, 0, sizeof(skinstats)); + memset(skinsorted, 0, sizeof(skinsorted)); + + // Hardcoded S_SKIN customizations for Sonic. + strcpy(skin->name, DEFAULTSKIN); +#ifdef SKINVALUES + skin_cons_t[0].strvalue = skins[0].name; +#endif + skin->flags = 0; + strcpy(skin->realname, "Sonic"); + strcpy(skin->hudname, "SONIC"); + + strncpy(skin->facerank, "PLAYRANK", 9); + strncpy(skin->facewant, "PLAYWANT", 9); + strncpy(skin->facemmap, "PLAYMMAP", 9); + skin->wadnum = 0; // god what have you brought to this world + skin->prefcolor = SKINCOLOR_BLUE; + skin->localskin = false; + skin->localnum = 0; + + // SRB2kart + skin->kartspeed = 8; + skin->kartweight = 2; + // + + skin->spritedef.numframes = sprites[SPR_PLAY].numframes; + skin->spritedef.spriteframes = sprites[SPR_PLAY].spriteframes; + skin->sprinfo = spriteinfo[SPR_PLAY]; + ST_LoadFaceGraphics(skin->facerank, skin->facewant, skin->facemmap, 0); + + // Set values for Sonic skin + Forceskin_cons_t[1].value = 0; + Forceskin_cons_t[1].strvalue = skin->name; + + //MD2 for sonic doesn't want to load in Linux. +#ifdef HWRENDER + if (rendermode == render_opengl) + HWR_AddPlayerMD2(0, false); +#endif + + // lets set it + allskins[0] = skins[0]; + numallskins = 1; +} + +// returns true if the skin name is found (loaded from pwad) +// warning return -1 if not found +INT32 R_SkinAvailable(const char *name) +{ + INT32 i; + + for (i = 0; i < numskins; i++) + { + if (stricmp(skins[i].name,name) == 0) + return i; + } + return -1; +} + +// returns true if the skin name is found (loaded from pwad) +// warning return -1 if not found +INT32 R_AnySkinAvailable(const char *name) +{ + INT32 i; + + for (i = 0; i < numallskins; i++) + { + if (stricmp(allskins[i].name,name) == 0) + return i; + } + return -1; +} + +INT32 R_LocalSkinAvailable(const char *name, boolean local) +{ + INT32 i; + + if (local) + { + for (i = 0; i < numlocalskins; i++) + { + if (stricmp(localskins[i].name,name) == 0) + return i; + } + return -1; + } + else + return R_SkinAvailable(name); +} + +// network code calls this when a 'skin change' is received +boolean SetPlayerSkin(INT32 playernum, const char *skinname) +{ + INT32 i; + player_t *player = &players[playernum]; + + for (i = 0; i < numskins; i++) + { + // search in the skin list + if (stricmp(skins[i].name, skinname) == 0) + { + SetPlayerSkinByNum(playernum, i); + return true; + } + } + + if (P_IsLocalPlayer(player)) + CONS_Alert(CONS_WARNING, M_GetText("Skin '%s' not found.\n"), skinname); + else if(server || IsPlayerAdmin(consoleplayer)) + CONS_Alert(CONS_WARNING, M_GetText("Player %d (%s) skin '%s' not found\n"), playernum, player_names[playernum], skinname); + + SetPlayerSkinByNum(playernum, 0); + return false; +} + +void SetLocalPlayerSkin(INT32 playernum, const char *skinname, consvar_t *cvar) +{ + INT32 i; + player_t *player = &players[playernum]; + + if (stricmp(skinname, "none")) + { + for (i = 0; i < numlocalskins; i++) + { + // search in the localskin list + if (stricmp(localskins[i].name, skinname) == 0) + { + player->localskin = 1 + i; + player->skinlocal = true; + if (player->mo) + { + player->mo->localskin = &localskins[i]; + player->mo->skinlocal = true; + } + + goto setcvar; + } + } + + for (i = 0; i < numskins; i++) + { + // search in the skin list + if (stricmp(skins[i].name, skinname) == 0) + { + player->localskin = 1 + i; + player->skinlocal = false; + if (player->mo) + { + player->mo->localskin = &skins[i]; + player->mo->skinlocal = false; + } + + goto setcvar; + } + } + } + else + { + player->localskin = 0; + player->skinlocal = false; + if (player->mo) + { + player->mo->localskin = 0; + player->mo->skinlocal = false; + } + } + +setcvar: + if (cvar != NULL) + { + if (player->localskin > 0) + { + CV_StealthSet(&cv_fakelocalskin, K_GetSkinArray(player->skinlocal)[player->localskin-1].name); + CV_StealthSet(cvar, K_GetSkinArray(player->skinlocal)[player->localskin-1].name); + + } + else + { + CV_StealthSet(&cv_fakelocalskin, "none"); + CV_StealthSet(cvar, "none"); + } + } +} + +// Same as SetPlayerSkin, but uses the skin #. +// network code calls this when a 'skin change' is received +void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) +{ + player_t *player = &players[playernum]; + skin_t *skin = &skins[skinnum]; + + if (skinnum >= 0 && skinnum < numskins) // Make sure it exists! + { + player->skin = skinnum; + if (player->mo) + player->mo->skin = skin; + + player->charflags = (UINT32)skin->flags; + + // SRB2kart + player->kartspeed = skin->kartspeed; + player->kartweight = skin->kartweight; + + if (player->mo) + P_SetScale(player->mo, player->mo->scale); + + demo_extradata[playernum] |= DXD_SKIN; + + return; + } + + if (P_IsLocalPlayer(player)) + CONS_Alert(CONS_WARNING, M_GetText("Skin %d not found\n"), skinnum); + else if(server || IsPlayerAdmin(consoleplayer)) + CONS_Alert(CONS_WARNING, "Player %d (%s) skin %d not found\n", playernum, player_names[playernum], skinnum); + + SetPlayerSkinByNum(playernum, 0); // not found put the sonic skin +} + +// +// Add skins from a pwad, each skin preceded by 'S_SKIN' marker +// + +// Does the same is in w_wad, but check only for +// the first 6 characters (this is so we can have S_SKIN1, S_SKIN2.. +// for wad editors that don't like multiple resources of the same name) +// +static UINT16 W_CheckForSkinMarkerInPwad(UINT16 wadid, UINT16 startlump) +{ + UINT16 i; + const char *S_SKIN = "S_SKIN"; + lumpinfo_t *lump_p; + + // scan forward, start at + if (startlump < wadfiles[wadid]->numlumps) + { + lump_p = wadfiles[wadid]->lumpinfo + startlump; + for (i = startlump; i < wadfiles[wadid]->numlumps; i++, lump_p++) + if (memcmp(lump_p->name,S_SKIN,6)==0) + return i; + } + return INT16_MAX; // not found +} + +//sort function for sorting skin names +static int skinSortFunc(const void *a, const void *b) //tbh i have no clue what the naming conventions for local functions are +{ + const skin_t *in1 = &skins[*(const UINT8 *)a]; + const skin_t *in2 = &skins[*(const UINT8 *)b]; + INT32 temp = 0; + const UINT8 val_a = *((const UINT8 *)a); + const UINT8 val_b = *((const UINT8 *)b); + + //return (strcmp(in1->realname, in2->realname) < 0) || (strcmp(in1->realname, in2->realname) ==); + + switch (cv_skinselectgridsort.value) + { + case SKINMENUSORT_REALNAME: + //CONS_Printf("Sorting by realname\n"); + // check name + if ((temp = strcmp(in1->realname, in2->realname))) + return temp; + // sort by internal name + return strcmp(in1->name, in2->name); + break; + + case SKINMENUSORT_NAME: + //CONS_Printf("Sorting by name\n"); + return strcmp(in1->name, in2->name); + break; + + case SKINMENUSORT_SPEED: + //CONS_Printf("Sorting by speed\n"); + // check speed + if (in1->kartspeed < in2->kartspeed) + return -1; + else if (in2->kartspeed < in1->kartspeed) + return 1; + // then check weight + if (in1->kartweight < in2->kartweight) + return -1; + else if (in2->kartweight < in1->kartweight) + return 1; + // then check name + if ((temp = strcmp(in1->realname, in2->realname))) + return temp; + // sort by internal name + return strcmp(in1->name, in2->name); + break; + + case SKINMENUSORT_WEIGHT: + //CONS_Printf("Sorting by weight\n"); + // check weight + if (in1->kartweight < in2->kartweight) + return -1; + else if (in2->kartweight < in1->kartweight) + return 1; + // then check speed + if (in1->kartspeed < in2->kartspeed) + return -1; + else if (in2->kartspeed < in1->kartspeed) + return 1; + // then check name + if ((temp = strcmp(in1->realname, in2->realname))) + return temp; + // sort by internal name + return strcmp(in1->name, in2->name); + break; + + case SKINMENUSORT_PREFCOLOR: + //CONS_Printf("Sorting by prefcolor\n"); + // check prefcolor + if (in1->prefcolor < in2->prefcolor) + return -1; + else if (in2->prefcolor < in1->prefcolor) + return 1; + // then check name + if ((temp = strcmp(in1->realname, in2->realname))) + return temp; + // sort by internal name + return strcmp(in1->name, in2->name); + break; + + case SKINMENUSORT_ID: + //CONS_Printf("Sorting by id\n"); + //how do i do by ID????? + //wait why dont i just convert the inputs to UINT32s + //please tell me im allowed to define variables in here since its a block + + if (val_a == val_b) + return 0; + else if (val_a < val_b) + return -1; + else + return 1; + + default: + return strcmp(in1->name, in2->name); + break; + } + //im scared this somehow will sometimes end up here so im gonna add this here just to be safe + return strcmp(in1->name, in2->name); +} + +void sortSkinGrid(void) +{ + //CONS_Printf("Sorting skin list (%d)...\n", cv_skinselectgridsort.value); + qs22j(skinsorted, numskins, sizeof(UINT8), skinSortFunc); +} + +// +// Find skin sprites, sounds & optional status bar face, & add them +// +void R_AddSkins(UINT16 wadnum, boolean local) +{ + UINT16 lump, lastlump = 0; + char *buf; + char *buf2; + char *stoken; + char *value; + size_t size; + skin_t *skin; + boolean hudname, realname; + +#define lnumskins (local ? numlocalskins : numskins) + + // + // search for all skin markers in pwad + // + + while ((lump = W_CheckForSkinMarkerInPwad(wadnum, lastlump)) != INT16_MAX) + { + // advance by default + lastlump = lump + 1; + + if (!local && numskins >= MAXSKINS) + { + CONS_Alert(CONS_WARNING, M_GetText("Unable to add skin, too many characters are loaded (%d maximum)\n"), MAXSKINS); + continue; // so we know how many skins couldn't be added + } + if (local && numlocalskins >= MAXLOCALSKINS) + { + CONS_Alert(CONS_WARNING, M_GetText("Unable to add localskin, too many localskins are loaded (%d maximum)\n"), MAXLOCALSKINS); + continue; // so we know how many skins couldn't be added + } + + buf = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE); + size = W_LumpLengthPwad(wadnum, lump); + + // for strtok + buf2 = malloc(size+1); + if (!buf2) + I_Error("R_AddSkins: No more free memory\n"); + M_Memcpy(buf2,buf,size); + buf2[size] = '\0'; + + // set defaults + skin = &K_GetSkinArray(local)[lnumskins]; + Sk_SetDefaultValue(skin, local); + skin->wadnum = wadnum; + hudname = realname = false; + // parse + stoken = strtok (buf2, "\r\n= "); + while (stoken) + { + if ((stoken[0] == '/' && stoken[1] == '/') + || (stoken[0] == '#'))// skip comments + { + stoken = strtok(NULL, "\r\n"); // skip end of line + goto next_token; // find the real next token + } + + value = strtok(NULL, "\r\n= "); + + if (!value) + I_Error("R_AddSkins: syntax error in S_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename); + + if (!stricmp(stoken, "name")) + { + // the skin name must uniquely identify a single skin + // I'm lazy so if name is already used I leave the 'skin x' + // default skin name set in Sk_SetDefaultValue + if (R_LocalSkinAvailable(value, local) == -1) + { + STRBUFCPY(skin->name, value); + strlwr(skin->name); + } + // I'm not lazy, so if the name is already used I make the name 'namex' + // using the default skin name's number set above + else + { + const size_t stringspace = + strlen(value) + sizeof lnumskins + 1; + char *value2 = Z_Malloc(stringspace, PU_STATIC, NULL); + snprintf(value2, stringspace, + "%s%d", value, lnumskins); + value2[stringspace - 1] = '\0'; + if (R_LocalSkinAvailable(value2, local) == -1) + { + STRBUFCPY(skin->name, + value2); + strlwr(skin->name); + } + Z_Free(value2); + } + + // copy to hudname and fullname as a default. + if (!realname) + { + STRBUFCPY(skin->realname, skin->name); + for (value = skin->realname; *value; value++) + if (*value == '_') *value = ' '; // turn _ into spaces. + } + if (!hudname) + { + STRBUFCPY(skin->hudname, skin->name); + strupr(skin->hudname); + for (value = skin->hudname; *value; value++) + if (*value == '_') *value = ' '; // turn _ into spaces. + } + } + else if (!stricmp(stoken, "realname")) + { // Display name (eg. "Knuckles") + realname = true; + STRBUFCPY(skin->realname, value); + for (value = skin->realname; *value; value++) + if (*value == '_') *value = ' '; // turn _ into spaces. + if (!hudname) + STRBUFCPY(skin->hudname, skin->realname); + } + else if (!stricmp(stoken, "hudname")) + { // Life icon name (eg. "K.T.E") + hudname = true; + STRBUFCPY(skin->hudname, value); + for (value = skin->hudname; *value; value++) + if (*value == '_') *value = ' '; // turn _ into spaces. + if (!realname) + STRBUFCPY(skin->realname, skin->hudname); + } + + else if (!stricmp(stoken, "sprite")) + { + strupr(value); + memcpy(skin->sprite, value, sizeof skin->sprite); + } + else if (!stricmp(stoken, "facerank")) + { + strupr(value); + memcpy(skin->facerank, value, sizeof(skin->facerank)-1); + skin->facerank[sizeof(skin->facerank)-1] = '\0'; + } + else if (!stricmp(stoken, "facewant")) + { + strupr(value); + memcpy(skin->facewant, value, sizeof(skin->facewant)-1); + skin->facewant[sizeof(skin->facewant)-1] = '\0'; + } + else if (!stricmp(stoken, "facemmap")) + { + strupr(value); + strncpy(skin->facemmap, value, sizeof(skin->facemmap)-1); + skin->facemmap[sizeof(skin->facemmap)-1] = '\0'; + } + +#define FULLPROCESS(field) else if (!stricmp(stoken, #field)) skin->field = get_number(value); + // character type identification + FULLPROCESS(flags) +#undef FULLPROCESS + +#define GETKARTSTAT(field) \ + else if (!stricmp(stoken, #field)) \ + { \ + skin->field = atoi(value); \ + if (skin->field < 1) skin->field = 1; \ + if (skin->field > 9) skin->field = 9; \ + } + GETKARTSTAT(kartspeed) + GETKARTSTAT(kartweight) +#undef GETKARTSTAT + + // custom translation table + else if (!stricmp(stoken, "startcolor")) + skin->starttranscolor = atoi(value); + + else if (!stricmp(stoken, "prefcolor")) + skin->prefcolor = K_GetKartColorByName(value); + else if (!stricmp(stoken, "highresscale")) + skin->highresscale = FLOAT_TO_FIXED(atof(value)); + else + { + INT32 found = false; + sfxenum_t i; + // copy name of sounds that are remapped + // for this skin + for (i = 0; i < sfx_skinsoundslot0; i++) + { + if (!S_sfx[i].name) + continue; + if (S_sfx[i].skinsound != -1 + && !stricmp(S_sfx[i].name, + stoken + 2)) + { + skin->soundsid[S_sfx[i].skinsound] = + S_AddSoundFx(value+2, S_sfx[i].singularity, S_sfx[i].pitch, true); + found = true; + } + } + if (!found) + CONS_Debug(DBG_SETUP, "R_AddSkins: Unknown keyword '%s' in S_SKIN lump# %d (WAD %s)\n", stoken, lump, wadfiles[wadnum]->filename); + } +next_token: + stoken = strtok(NULL, "\r\n= "); + } + free(buf2); + + lump++; // if no sprite defined use spirte just after this one + if (skin->sprite[0] == '\0') + { + const char *csprname = W_CheckNameForNumPwad(wadnum, lump); + + // skip to end of this skin's frames + lastlump = lump; + while (W_CheckNameForNumPwad(wadnum,lastlump) && memcmp(W_CheckNameForNumPwad(wadnum, lastlump),csprname,4)==0) + lastlump++; + // allocate (or replace) sprite frames, and set spritedef + R_AddSingleSpriteDef(csprname, &skin->spritedef, wadnum, lump, lastlump); + } + else + { + // search in the normal sprite tables + size_t name; + boolean found = false; + const char *sprname = skin->sprite; + for (name = 0;sprnames[name][0] != '\0';name++) + if (strncmp(sprnames[name], sprname, 4) == 0) + { + found = true; + skin->spritedef = sprites[name]; + } + + // not found so make a new one + // go through the entire current wad looking for our sprite + // don't just mass add anything beginning with our four letters. + // "HOODFACE" is not a sprite name. + if (!found) + { + UINT16 localllump = 0, lstart = UINT16_MAX, lend = UINT16_MAX; + const char *lname; + + while ((lname = W_CheckNameForNumPwad(wadnum,localllump))) + { + // If this is a valid sprite... + if (!memcmp(lname,sprname,4) && lname[4] && lname[5] && lname[5] >= '0' && lname[5] <= '8') + { + if (lstart == UINT16_MAX) + lstart = localllump; + // If already set do nothing + } + else + { + if (lstart != UINT16_MAX) + { + lend = localllump; + break; + } + // If not already set do nothing + } + ++localllump; + } + + R_AddSingleSpriteDef(sprname, &skin->spritedef, wadnum, lstart, lend); + } + + // I don't particularly care about skipping to the end of the used frames. + // We could be using frames from ANYWHERE in the current WAD file, including + // right before us, which is a terrible idea. + // So just let the function in the while loop take care of it for us. + } + + R_FlushTranslationColormapCache(); + + CONS_Printf(M_GetText("Added skin '%s'\n"), skin->name); +#ifdef SKINVALUES + (local ? localskin_cons_t : skin_cons_t)[lnumskins].value = lnumskins; + (local ? localskin_cons_t : skin_cons_t)[lnumskins].strvalue = skin->name; +#endif + + if (!local) + { + // Update the forceskin possiblevalues + Forceskin_cons_t[numskins+1].value = numskins; + Forceskin_cons_t[numskins+1].strvalue = skins[numskins].name; + skin->localskin = false; + skin->localnum = numskins; + ST_LoadFaceGraphics(skin->facerank, skin->facewant, skin->facemmap, numskins); + } + else + { + skin->localskin = true; + skin->localnum = numlocalskins; + ST_LoadLocalFaceGraphics(skin->facerank, skin->facewant, skin->facemmap, numlocalskins); + } + +#ifdef HWRENDER + if (rendermode == render_opengl) + HWR_AddPlayerMD2(lnumskins, local); +#endif + if (!local) + { + skinstats[skin->kartspeed-1][skin->kartweight-1][skinstatscount[skin->kartspeed-1][skin->kartweight-1]] = numskins; + CONS_Debug(DBG_SETUP, M_GetText("Added %d to %d, %d\n"), numskins, skin->kartweight, skin->kartweight); + skinstatscount[skin->kartspeed-1][skin->kartweight-1]++; + CONS_Debug(DBG_SETUP, M_GetText("Incremented %d, %d to %d\n"), skin->kartspeed, skin->kartweight, skinstatscount[skin->kartspeed - 1][skin->kartweight - 1]); + skinsorted[numskins] = numskins; + } + + allskins[numallskins] = K_GetSkinArray(local)[lnumskins]; + + local ? numlocalskins++ : numskins++; + numallskins++; + } + +#undef lnumskins + //sortSkinGrid(); + + return; +} diff --git a/src/r_skins.h b/src/r_skins.h new file mode 100644 index 000000000..cada396f4 --- /dev/null +++ b/src/r_skins.h @@ -0,0 +1,152 @@ +// SONIC ROBO BLAST 2 KART +//----------------------------------------------------------------------------- +// Copyright (C) 2025 by Vivian "toastergrl" Grannell. +// Copyright (C) 2025 by Kart Krew. +// Copyright (C) 2020 by Sonic Team Junior. +// Copyright (C) 2000 by DooM Legacy Team. +// Copyright (C) 1996 by id Software, Inc. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file r_skins.h +/// \brief Skins stuff + +#ifndef __R_SKINS__ +#define __R_SKINS__ +#ifdef __cplusplus +extern "C" { +#endif + +#include "d_player.h" +#include "sounds.h" +#include "r_patch.h" + +// "Left" and "Right" character symbols for additional rotation functionality +#define ROT_L ('L' - '0') +#define ROT_R ('R' - '0') + +#define SKINNAMESIZE 16 +// should be all lowercase!! S_SKIN processing does a strlwr +#define DEFAULTSKIN "sonic" +#define DEFAULTSKIN2 "tails" // secondary player +#define DEFAULTSKIN3 "knuckles" // third player +#define DEFAULTSKIN4 "eggman" // fourth player + +typedef struct +{ + char name[SKINNAMESIZE+1]; // INT16 descriptive name of the skin + spritedef_t spritedef; + spriteinfo_t sprinfo; + UINT16 wadnum; + char sprite[4]; // Sprite name, if seperated from S_SKIN. + skinflags_t flags; + + char realname[SKINNAMESIZE+1]; // Display name for level completion. + char hudname[SKINNAMESIZE+1]; // HUD name to display (officially exactly 5 characters long) + char facerank[9], facewant[9], facemmap[9]; // Arbitrarily named patch lumps + + // SRB2kart + UINT8 kartspeed; + UINT8 kartweight; + // + + // Definable color translation table + UINT8 starttranscolor; + UINT8 prefcolor; + fixed_t highresscale; // scale of highres, default is 0.5 + + // specific sounds per skin + sfxenum_t soundsid[NUMSKINSOUNDS]; // sound # in S_sfx table + + boolean localskin; + INT32 localnum; +} skin_t; + +extern CV_PossibleValue_t Forceskin_cons_t[]; + +extern INT32 numskins; +extern INT32 numlocalskins; +extern INT32 numallskins; +extern skin_t skins[MAXSKINS]; +extern UINT8 skinstats[9][9][MAXSKINS]; +extern UINT8 skinstatscount[9][9]; +extern UINT8 skinsorted[MAXSKINS]; + +extern skin_t localskins[MAXLOCALSKINS]; +extern skin_t allskins[MAXSKINS+MAXLOCALSKINS]; + +//faB: find sprites in wadfile, replace existing, add new ones +// (only sprites from namelist are added or replaced) +void R_AddSpriteDefs(UINT16 wadnum); + +void R_InitSkins(void); +void R_AddSkins(UINT16 wadnum, boolean local); + +INT32 R_SkinAvailable(const char *name); +INT32 R_AnySkinAvailable(const char *name); +INT32 R_LocalSkinAvailable(const char *name, boolean local); + +// had to move those here Zzz... +INT32 K_GetSkinNum(player_t *player); +INT32 K_GetMobjSkinNum(const skin_t *skin, boolean local); +skin_t *K_GetPlayerSkin(player_t *player); +skin_t *K_GetMobjSkin(const mobj_t *mobj); +patch_t *K_GetFacePrefix(player_t *player, INT32 skinnum); +skin_t *K_GetSkinArray(boolean local); + +void sortSkinGrid(void); + +boolean SetPlayerSkin(INT32 playernum,const char *skinname); +void SetPlayerSkinByNum(INT32 playernum,INT32 skinnum); // Tails 03-16-2002 +void SetLocalPlayerSkin(INT32 playernum,const char *skinname, consvar_t *cvar); + +char *GetPlayerFacePic(INT32 skinnum); + +// Functions to go from sprite character ID to frame number +// for 2.1 compatibility this still uses the old 'A' + frame code +// The use of symbols tends to be painful for wad editors though +// So the future version of this tries to avoid using symbols +// as much as possible while also defining all 64 slots in a sane manner +// 2.1: [[ ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ ]] +// Future: [[ ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!@ ]] +FUNCMATH FUNCINLINE static ATTRINLINE char R_Frame2Char(UINT8 frame) +{ +#if 1 // 2.1 compat + return 'A' + frame; +#else + if (frame < 26) return 'A' + frame; + if (frame < 36) return '0' + (frame - 26); + if (frame < 62) return 'a' + (frame - 36); + if (frame == 62) return '!'; + if (frame == 63) return '@'; + return '\xFF'; +#endif +} + +FUNCMATH FUNCINLINE static ATTRINLINE UINT8 R_Char2Frame(char cn) +{ +#if 1 // 2.1 compat + if (cn == '+') return '\\' - 'A'; // PK3 can't use backslash, so use + instead + return cn - 'A'; +#else + if (cn >= 'A' && cn <= 'Z') return cn - 'A'; + if (cn >= '0' && cn <= '9') return (cn - '0') + 26; + if (cn >= 'a' && cn <= 'z') return (cn - 'a') + 36; + if (cn == '!') return 62; + if (cn == '@') return 63; + return 255; +#endif +} + +FUNCMATH FUNCINLINE static ATTRINLINE boolean R_ValidSpriteAngle(UINT8 rotation) +{ + return ((rotation <= 8) || (rotation == ROT_L) || (rotation == ROT_R)); +} + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif //__R_SKINS__ diff --git a/src/r_things.c b/src/r_things.c index cd92f5913..ba098696c 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1,4 +1,4 @@ -// SONIC ROBO BLAST 2 +// SONIC ROBO BLAST 2 KART //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. @@ -17,20 +17,15 @@ #include "r_plane.h" #include "r_portal.h" #include "r_local.h" - -#include "dehacked.h" // get_number (for thok) #include "doomdef.h" #include "d_netfil.h" // blargh. for nameonly(). #include "console.h" #include "g_game.h" -#include "k_kart.h" // SRB2kart #include "p_tick.h" #include "p_local.h" #include "p_setup.h" #include "p_slopes.h" #include "st_stuff.h" -#include "m_cheat.h" // objectplace -#include "m_misc.h" #include "i_video.h" // rendermode #include "w_wad.h" #include "z_zone.h" @@ -43,12 +38,6 @@ #include "r_patchrotation.h" #endif -#include "qs22j.h" - -CV_PossibleValue_t Forceskin_cons_t[MAXSKINS+2]; - -static void R_InitSkins(void); - #define MINZ (FRACUNIT*16) #define BASEYCENTER (BASEVIDHEIGHT/2) @@ -72,20 +61,10 @@ static lighttable_t **spritelights; INT16 *negonearray; INT16 *screenheightarray; -spriteinfo_t spriteinfo[NUMSPRITES]; - // // INITIALIZATION FUNCTIONS // -// variables used to look up and range check thing_t sprites patches -spritedef_t *sprites; -size_t numsprites; - -static spriteframe_t sprtemp[64]; -static size_t maxframe; -static const char *spritename; - // // Clipping against drawsegs optimization, from prboom-plus // @@ -120,6 +99,37 @@ INT32 R_ThingLightLevel(mobj_t* thing) return lightlevel; } +// +// Sprite rotation 0 is facing the viewer, +// rotation 1 is one angle turn CLOCKWISE around the axis. +// This is not the same as the angle, +// which increases counter clockwise (protractor). +// There was a lot of stuff grabbed wrong, so I changed it... +// + +spriteinfo_t spriteinfo[NUMSPRITES]; + +// +// INITIALIZATION FUNCTIONS +// + +// variables used to look up and range check thing_t sprites patches +spritedef_t *sprites; +size_t numsprites; + +static spriteframe_t sprtemp[64]; +static size_t maxframe; +static const char *spritename; + +// +// GAME FUNCTIONS +// +UINT32 visspritecount, numvisiblesprites; + +static UINT32 clippedvissprites; +static vissprite_t *visspritechunks[MAXVISSPRITES >> VISSPRITECHUNKBITS] = {NULL}; + + // ========================================================================== // // Sprite loading routines: support sprites in pwad, dehacked sprite renaming, @@ -252,7 +262,7 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch // // Returns true if the sprite was succesfully added // -static 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) { UINT16 l; UINT8 frame; @@ -476,16 +486,6 @@ void R_AddSpriteDefs(UINT16 wadnum) CONS_Printf(M_GetText("%s added %d frames in %s sprites\n"), wadname, end-start, sizeu1(addsprites)); } - -// -// GAME FUNCTIONS -// -UINT32 visspritecount, numvisiblesprites; - -static UINT32 clippedvissprites; -static vissprite_t *visspritechunks[MAXVISSPRITES >> VISSPRITECHUNKBITS] = {NULL}; - - // // R_InitSprites // Called at program start. @@ -3011,764 +3011,3 @@ void R_DrawMasked(maskcount_t* masks, UINT8 nummasks) R_ClearDrawNodes(&heads[nummasks - 1]); } } - -// ========================================================================== -// -// SKINS CODE -// -// ========================================================================== - -INT32 numskins = 0; -INT32 numallskins = 0; -INT32 numlocalskins = 0; -skin_t skins[MAXSKINS]; -UINT8 skinstats[9][9][MAXSKINS]; -UINT8 skinstatscount[9][9] = { - {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 1, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0} -}; -UINT8 skinsorted[MAXSKINS]; -skin_t localskins[MAXLOCALSKINS]; -skin_t allskins[MAXSKINS+MAXLOCALSKINS]; - -// FIXTHIS: don't work because it must be inistilised before the config load -//#define SKINVALUES -#ifdef SKINVALUES -CV_PossibleValue_t skin_cons_t[MAXSKINS+1]; -CV_PossibleValue_t localskin_cons_t[MAXLOCALSKINS+1]; -#endif - -static void Sk_SetDefaultValue(skin_t *skin, boolean local) -{ - INT32 i; - // - // set default skin values - // - memset(skin, 0, sizeof (skin_t)); - snprintf(skin->name, sizeof skin->name, "skin %u", K_GetMobjSkinNum(skin, local)); - skin->name[sizeof skin->name - 1] = '\0'; - skin->wadnum = INT16_MAX; - strcpy(skin->sprite, ""); - - skin->flags = 0; - - strcpy(skin->realname, "Someone"); - strcpy(skin->hudname, "???"); - strncpy(skin->facerank, "PLAYRANK", 9); - strncpy(skin->facewant, "PLAYWANT", 9); - strncpy(skin->facemmap, "PLAYMMAP", 9); - - skin->starttranscolor = 160; - skin->prefcolor = SKINCOLOR_GREEN; - - // SRB2kart - skin->kartspeed = 5; - skin->kartweight = 5; - // - - skin->highresscale = FRACUNIT>>1; - - for (i = 0; i < sfx_skinsoundslot0; i++) - if (S_sfx[i].skinsound != -1) - skin->soundsid[S_sfx[i].skinsound] = i; -} - -// -// Initialize the basic skins -// -void R_InitSkins(void) -{ - skin_t *skin; -#ifdef SKINVALUES - INT32 i; - - for (i = 0; i <= MAXSKINS; i++) - { - skin_cons_t[i].value = 0; - skin_cons_t[i].strvalue = NULL; - } - for (i = 0; i <= MAXLOCALSKINS; i++) - { - localskin_cons_t[i].value = 0; - localskin_cons_t[i].strvalue = NULL; - } -#endif - - // skin[0] = Sonic skin - skin = &skins[0]; - numskins = 1; - Sk_SetDefaultValue(skin, false); - memset(skinstats, 0, sizeof(skinstats)); - memset(skinsorted, 0, sizeof(skinsorted)); - - // Hardcoded S_SKIN customizations for Sonic. - strcpy(skin->name, DEFAULTSKIN); -#ifdef SKINVALUES - skin_cons_t[0].strvalue = skins[0].name; -#endif - skin->flags = 0; - strcpy(skin->realname, "Sonic"); - strcpy(skin->hudname, "SONIC"); - - strncpy(skin->facerank, "PLAYRANK", 9); - strncpy(skin->facewant, "PLAYWANT", 9); - strncpy(skin->facemmap, "PLAYMMAP", 9); - skin->wadnum = 0; // god what have you brought to this world - skin->prefcolor = SKINCOLOR_BLUE; - skin->localskin = false; - skin->localnum = 0; - - // SRB2kart - skin->kartspeed = 8; - skin->kartweight = 2; - // - - skin->spritedef.numframes = sprites[SPR_PLAY].numframes; - skin->spritedef.spriteframes = sprites[SPR_PLAY].spriteframes; - skin->sprinfo = spriteinfo[SPR_PLAY]; - ST_LoadFaceGraphics(skin->facerank, skin->facewant, skin->facemmap, 0); - - // Set values for Sonic skin - Forceskin_cons_t[1].value = 0; - Forceskin_cons_t[1].strvalue = skin->name; - - //MD2 for sonic doesn't want to load in Linux. -#ifdef HWRENDER - if (rendermode == render_opengl) - HWR_AddPlayerMD2(0, false); -#endif - - // lets set it - allskins[0] = skins[0]; - numallskins = 1; -} - -// returns true if the skin name is found (loaded from pwad) -// warning return -1 if not found -INT32 R_SkinAvailable(const char *name) -{ - INT32 i; - - for (i = 0; i < numskins; i++) - { - if (stricmp(skins[i].name,name) == 0) - return i; - } - return -1; -} - -// returns true if the skin name is found (loaded from pwad) -// warning return -1 if not found -INT32 R_AnySkinAvailable(const char *name) -{ - INT32 i; - - for (i = 0; i < numallskins; i++) - { - if (stricmp(allskins[i].name,name) == 0) - return i; - } - return -1; -} - -INT32 R_LocalSkinAvailable(const char *name, boolean local) -{ - INT32 i; - - if (local) - { - for (i = 0; i < numlocalskins; i++) - { - if (stricmp(localskins[i].name,name) == 0) - return i; - } - return -1; - } - else - return R_SkinAvailable(name); -} - -// network code calls this when a 'skin change' is received -boolean SetPlayerSkin(INT32 playernum, const char *skinname) -{ - INT32 i; - player_t *player = &players[playernum]; - - for (i = 0; i < numskins; i++) - { - // search in the skin list - if (stricmp(skins[i].name, skinname) == 0) - { - SetPlayerSkinByNum(playernum, i); - return true; - } - } - - if (P_IsLocalPlayer(player)) - CONS_Alert(CONS_WARNING, M_GetText("Skin '%s' not found.\n"), skinname); - else if(server || IsPlayerAdmin(consoleplayer)) - CONS_Alert(CONS_WARNING, M_GetText("Player %d (%s) skin '%s' not found\n"), playernum, player_names[playernum], skinname); - - SetPlayerSkinByNum(playernum, 0); - return false; -} - -void SetLocalPlayerSkin(INT32 playernum, const char *skinname, consvar_t *cvar) -{ - INT32 i; - player_t *player = &players[playernum]; - - if (stricmp(skinname, "none")) - { - for (i = 0; i < numlocalskins; i++) - { - // search in the localskin list - if (stricmp(localskins[i].name, skinname) == 0) - { - player->localskin = 1 + i; - player->skinlocal = true; - if (player->mo) - { - player->mo->localskin = &localskins[i]; - player->mo->skinlocal = true; - } - - goto setcvar; - } - } - - for (i = 0; i < numskins; i++) - { - // search in the skin list - if (stricmp(skins[i].name, skinname) == 0) - { - player->localskin = 1 + i; - player->skinlocal = false; - if (player->mo) - { - player->mo->localskin = &skins[i]; - player->mo->skinlocal = false; - } - - goto setcvar; - } - } - } - else - { - player->localskin = 0; - player->skinlocal = false; - if (player->mo) - { - player->mo->localskin = 0; - player->mo->skinlocal = false; - } - } - -setcvar: - if (cvar != NULL) - { - if (player->localskin > 0) - { - CV_StealthSet(&cv_fakelocalskin, K_GetSkinArray(player->skinlocal)[player->localskin-1].name); - CV_StealthSet(cvar, K_GetSkinArray(player->skinlocal)[player->localskin-1].name); - - } - else - { - CV_StealthSet(&cv_fakelocalskin, "none"); - CV_StealthSet(cvar, "none"); - } - } -} - -// Same as SetPlayerSkin, but uses the skin #. -// network code calls this when a 'skin change' is received -void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) -{ - player_t *player = &players[playernum]; - skin_t *skin = &skins[skinnum]; - - if (skinnum >= 0 && skinnum < numskins) // Make sure it exists! - { - player->skin = skinnum; - if (player->mo) - player->mo->skin = skin; - - player->charflags = (UINT32)skin->flags; - - // SRB2kart - player->kartspeed = skin->kartspeed; - player->kartweight = skin->kartweight; - - if (player->mo) - P_SetScale(player->mo, player->mo->scale); - - demo_extradata[playernum] |= DXD_SKIN; - - return; - } - - if (P_IsLocalPlayer(player)) - CONS_Alert(CONS_WARNING, M_GetText("Skin %d not found\n"), skinnum); - else if(server || IsPlayerAdmin(consoleplayer)) - CONS_Alert(CONS_WARNING, "Player %d (%s) skin %d not found\n", playernum, player_names[playernum], skinnum); - - SetPlayerSkinByNum(playernum, 0); // not found put the sonic skin -} - -// -// Add skins from a pwad, each skin preceded by 'S_SKIN' marker -// - -// Does the same is in w_wad, but check only for -// the first 6 characters (this is so we can have S_SKIN1, S_SKIN2.. -// for wad editors that don't like multiple resources of the same name) -// -static UINT16 W_CheckForSkinMarkerInPwad(UINT16 wadid, UINT16 startlump) -{ - UINT16 i; - const char *S_SKIN = "S_SKIN"; - lumpinfo_t *lump_p; - - // scan forward, start at - if (startlump < wadfiles[wadid]->numlumps) - { - lump_p = wadfiles[wadid]->lumpinfo + startlump; - for (i = startlump; i < wadfiles[wadid]->numlumps; i++, lump_p++) - if (memcmp(lump_p->name,S_SKIN,6)==0) - return i; - } - return INT16_MAX; // not found -} - -//sort function for sorting skin names -static int skinSortFunc(const void *a, const void *b) //tbh i have no clue what the naming conventions for local functions are -{ - const skin_t *in1 = &skins[*(const UINT8 *)a]; - const skin_t *in2 = &skins[*(const UINT8 *)b]; - INT32 temp = 0; - const UINT8 val_a = *((const UINT8 *)a); - const UINT8 val_b = *((const UINT8 *)b); - - //return (strcmp(in1->realname, in2->realname) < 0) || (strcmp(in1->realname, in2->realname) ==); - - switch (cv_skinselectgridsort.value) - { - case SKINMENUSORT_REALNAME: - //CONS_Printf("Sorting by realname\n"); - // check name - if ((temp = strcmp(in1->realname, in2->realname))) - return temp; - // sort by internal name - return strcmp(in1->name, in2->name); - break; - - case SKINMENUSORT_NAME: - //CONS_Printf("Sorting by name\n"); - return strcmp(in1->name, in2->name); - break; - - case SKINMENUSORT_SPEED: - //CONS_Printf("Sorting by speed\n"); - // check speed - if (in1->kartspeed < in2->kartspeed) - return -1; - else if (in2->kartspeed < in1->kartspeed) - return 1; - // then check weight - if (in1->kartweight < in2->kartweight) - return -1; - else if (in2->kartweight < in1->kartweight) - return 1; - // then check name - if ((temp = strcmp(in1->realname, in2->realname))) - return temp; - // sort by internal name - return strcmp(in1->name, in2->name); - break; - - case SKINMENUSORT_WEIGHT: - //CONS_Printf("Sorting by weight\n"); - // check weight - if (in1->kartweight < in2->kartweight) - return -1; - else if (in2->kartweight < in1->kartweight) - return 1; - // then check speed - if (in1->kartspeed < in2->kartspeed) - return -1; - else if (in2->kartspeed < in1->kartspeed) - return 1; - // then check name - if ((temp = strcmp(in1->realname, in2->realname))) - return temp; - // sort by internal name - return strcmp(in1->name, in2->name); - break; - - case SKINMENUSORT_PREFCOLOR: - //CONS_Printf("Sorting by prefcolor\n"); - // check prefcolor - if (in1->prefcolor < in2->prefcolor) - return -1; - else if (in2->prefcolor < in1->prefcolor) - return 1; - // then check name - if ((temp = strcmp(in1->realname, in2->realname))) - return temp; - // sort by internal name - return strcmp(in1->name, in2->name); - break; - - case SKINMENUSORT_ID: - //CONS_Printf("Sorting by id\n"); - //how do i do by ID????? - //wait why dont i just convert the inputs to UINT32s - //please tell me im allowed to define variables in here since its a block - - if (val_a == val_b) - return 0; - else if (val_a < val_b) - return -1; - else - return 1; - - default: - return strcmp(in1->name, in2->name); - break; - } - //im scared this somehow will sometimes end up here so im gonna add this here just to be safe - return strcmp(in1->name, in2->name); -} - -void sortSkinGrid(void) -{ - //CONS_Printf("Sorting skin list (%d)...\n", cv_skinselectgridsort.value); - qs22j(skinsorted, numskins, sizeof(UINT8), skinSortFunc); -} - -// -// Find skin sprites, sounds & optional status bar face, & add them -// -void R_AddSkins(UINT16 wadnum, boolean local) -{ - UINT16 lump, lastlump = 0; - char *buf; - char *buf2; - char *stoken; - char *value; - size_t size; - skin_t *skin; - boolean hudname, realname; - -#define lnumskins (local ? numlocalskins : numskins) - - // - // search for all skin markers in pwad - // - - while ((lump = W_CheckForSkinMarkerInPwad(wadnum, lastlump)) != INT16_MAX) - { - // advance by default - lastlump = lump + 1; - - if (!local && numskins >= MAXSKINS) - { - CONS_Alert(CONS_WARNING, M_GetText("Unable to add skin, too many characters are loaded (%d maximum)\n"), MAXSKINS); - continue; // so we know how many skins couldn't be added - } - if (local && numlocalskins >= MAXLOCALSKINS) - { - CONS_Alert(CONS_WARNING, M_GetText("Unable to add localskin, too many localskins are loaded (%d maximum)\n"), MAXLOCALSKINS); - continue; // so we know how many skins couldn't be added - } - - buf = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE); - size = W_LumpLengthPwad(wadnum, lump); - - // for strtok - buf2 = malloc(size+1); - if (!buf2) - I_Error("R_AddSkins: No more free memory\n"); - M_Memcpy(buf2,buf,size); - buf2[size] = '\0'; - - // set defaults - skin = &K_GetSkinArray(local)[lnumskins]; - Sk_SetDefaultValue(skin, local); - skin->wadnum = wadnum; - hudname = realname = false; - // parse - stoken = strtok (buf2, "\r\n= "); - while (stoken) - { - if ((stoken[0] == '/' && stoken[1] == '/') - || (stoken[0] == '#'))// skip comments - { - stoken = strtok(NULL, "\r\n"); // skip end of line - goto next_token; // find the real next token - } - - value = strtok(NULL, "\r\n= "); - - if (!value) - I_Error("R_AddSkins: syntax error in S_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename); - - if (!stricmp(stoken, "name")) - { - // the skin name must uniquely identify a single skin - // I'm lazy so if name is already used I leave the 'skin x' - // default skin name set in Sk_SetDefaultValue - if (R_LocalSkinAvailable(value, local) == -1) - { - STRBUFCPY(skin->name, value); - strlwr(skin->name); - } - // I'm not lazy, so if the name is already used I make the name 'namex' - // using the default skin name's number set above - else - { - const size_t stringspace = - strlen(value) + sizeof lnumskins + 1; - char *value2 = Z_Malloc(stringspace, PU_STATIC, NULL); - snprintf(value2, stringspace, - "%s%d", value, lnumskins); - value2[stringspace - 1] = '\0'; - if (R_LocalSkinAvailable(value2, local) == -1) - { - STRBUFCPY(skin->name, - value2); - strlwr(skin->name); - } - Z_Free(value2); - } - - // copy to hudname and fullname as a default. - if (!realname) - { - STRBUFCPY(skin->realname, skin->name); - for (value = skin->realname; *value; value++) - if (*value == '_') *value = ' '; // turn _ into spaces. - } - if (!hudname) - { - STRBUFCPY(skin->hudname, skin->name); - strupr(skin->hudname); - for (value = skin->hudname; *value; value++) - if (*value == '_') *value = ' '; // turn _ into spaces. - } - } - else if (!stricmp(stoken, "realname")) - { // Display name (eg. "Knuckles") - realname = true; - STRBUFCPY(skin->realname, value); - for (value = skin->realname; *value; value++) - if (*value == '_') *value = ' '; // turn _ into spaces. - if (!hudname) - STRBUFCPY(skin->hudname, skin->realname); - } - else if (!stricmp(stoken, "hudname")) - { // Life icon name (eg. "K.T.E") - hudname = true; - STRBUFCPY(skin->hudname, value); - for (value = skin->hudname; *value; value++) - if (*value == '_') *value = ' '; // turn _ into spaces. - if (!realname) - STRBUFCPY(skin->realname, skin->hudname); - } - - else if (!stricmp(stoken, "sprite")) - { - strupr(value); - memcpy(skin->sprite, value, sizeof skin->sprite); - } - else if (!stricmp(stoken, "facerank")) - { - strupr(value); - memcpy(skin->facerank, value, sizeof(skin->facerank)-1); - skin->facerank[sizeof(skin->facerank)-1] = '\0'; - } - else if (!stricmp(stoken, "facewant")) - { - strupr(value); - memcpy(skin->facewant, value, sizeof(skin->facewant)-1); - skin->facewant[sizeof(skin->facewant)-1] = '\0'; - } - else if (!stricmp(stoken, "facemmap")) - { - strupr(value); - strncpy(skin->facemmap, value, sizeof(skin->facemmap)-1); - skin->facemmap[sizeof(skin->facemmap)-1] = '\0'; - } - -#define FULLPROCESS(field) else if (!stricmp(stoken, #field)) skin->field = get_number(value); - // character type identification - FULLPROCESS(flags) -#undef FULLPROCESS - -#define GETKARTSTAT(field) \ - else if (!stricmp(stoken, #field)) \ - { \ - skin->field = atoi(value); \ - if (skin->field < 1) skin->field = 1; \ - if (skin->field > 9) skin->field = 9; \ - } - GETKARTSTAT(kartspeed) - GETKARTSTAT(kartweight) -#undef GETKARTSTAT - - // custom translation table - else if (!stricmp(stoken, "startcolor")) - skin->starttranscolor = atoi(value); - - else if (!stricmp(stoken, "prefcolor")) - skin->prefcolor = K_GetKartColorByName(value); - else if (!stricmp(stoken, "highresscale")) - skin->highresscale = FLOAT_TO_FIXED(atof(value)); - else - { - INT32 found = false; - sfxenum_t i; - // copy name of sounds that are remapped - // for this skin - for (i = 0; i < sfx_skinsoundslot0; i++) - { - if (!S_sfx[i].name) - continue; - if (S_sfx[i].skinsound != -1 - && !stricmp(S_sfx[i].name, - stoken + 2)) - { - skin->soundsid[S_sfx[i].skinsound] = - S_AddSoundFx(value+2, S_sfx[i].singularity, S_sfx[i].pitch, true); - found = true; - } - } - if (!found) - CONS_Debug(DBG_SETUP, "R_AddSkins: Unknown keyword '%s' in S_SKIN lump# %d (WAD %s)\n", stoken, lump, wadfiles[wadnum]->filename); - } -next_token: - stoken = strtok(NULL, "\r\n= "); - } - free(buf2); - - lump++; // if no sprite defined use spirte just after this one - if (skin->sprite[0] == '\0') - { - const char *csprname = W_CheckNameForNumPwad(wadnum, lump); - - // skip to end of this skin's frames - lastlump = lump; - while (W_CheckNameForNumPwad(wadnum,lastlump) && memcmp(W_CheckNameForNumPwad(wadnum, lastlump),csprname,4)==0) - lastlump++; - // allocate (or replace) sprite frames, and set spritedef - R_AddSingleSpriteDef(csprname, &skin->spritedef, wadnum, lump, lastlump); - } - else - { - // search in the normal sprite tables - size_t name; - boolean found = false; - const char *sprname = skin->sprite; - for (name = 0;sprnames[name][0] != '\0';name++) - if (strncmp(sprnames[name], sprname, 4) == 0) - { - found = true; - skin->spritedef = sprites[name]; - } - - // not found so make a new one - // go through the entire current wad looking for our sprite - // don't just mass add anything beginning with our four letters. - // "HOODFACE" is not a sprite name. - if (!found) - { - UINT16 localllump = 0, lstart = UINT16_MAX, lend = UINT16_MAX; - const char *lname; - - while ((lname = W_CheckNameForNumPwad(wadnum,localllump))) - { - // If this is a valid sprite... - if (!memcmp(lname,sprname,4) && lname[4] && lname[5] && lname[5] >= '0' && lname[5] <= '8') - { - if (lstart == UINT16_MAX) - lstart = localllump; - // If already set do nothing - } - else - { - if (lstart != UINT16_MAX) - { - lend = localllump; - break; - } - // If not already set do nothing - } - ++localllump; - } - - R_AddSingleSpriteDef(sprname, &skin->spritedef, wadnum, lstart, lend); - } - - // I don't particularly care about skipping to the end of the used frames. - // We could be using frames from ANYWHERE in the current WAD file, including - // right before us, which is a terrible idea. - // So just let the function in the while loop take care of it for us. - } - - R_FlushTranslationColormapCache(); - - CONS_Printf(M_GetText("Added skin '%s'\n"), skin->name); -#ifdef SKINVALUES - (local ? localskin_cons_t : skin_cons_t)[lnumskins].value = lnumskins; - (local ? localskin_cons_t : skin_cons_t)[lnumskins].strvalue = skin->name; -#endif - - if (!local) - { - // Update the forceskin possiblevalues - Forceskin_cons_t[numskins+1].value = numskins; - Forceskin_cons_t[numskins+1].strvalue = skins[numskins].name; - skin->localskin = false; - skin->localnum = numskins; - ST_LoadFaceGraphics(skin->facerank, skin->facewant, skin->facemmap, numskins); - } - else - { - skin->localskin = true; - skin->localnum = numlocalskins; - ST_LoadLocalFaceGraphics(skin->facerank, skin->facewant, skin->facemmap, numlocalskins); - } - -#ifdef HWRENDER - if (rendermode == render_opengl) - HWR_AddPlayerMD2(lnumskins, local); -#endif - if (!local) - { - skinstats[skin->kartspeed-1][skin->kartweight-1][skinstatscount[skin->kartspeed-1][skin->kartweight-1]] = numskins; - CONS_Debug(DBG_SETUP, M_GetText("Added %d to %d, %d\n"), numskins, skin->kartweight, skin->kartweight); - skinstatscount[skin->kartspeed-1][skin->kartweight-1]++; - CONS_Debug(DBG_SETUP, M_GetText("Incremented %d, %d to %d\n"), skin->kartspeed, skin->kartweight, skinstatscount[skin->kartspeed - 1][skin->kartweight - 1]); - skinsorted[numskins] = numskins; - } - - allskins[numallskins] = K_GetSkinArray(local)[lnumskins]; - - local ? numlocalskins++ : numskins++; - numallskins++; - } - -#undef lnumskins - //sortSkinGrid(); - - return; -} diff --git a/src/r_things.h b/src/r_things.h index f4752d166..9892d1e43 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -1,4 +1,4 @@ -// SONIC ROBO BLAST 2 +// SONIC ROBO BLAST 2 KART //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. @@ -18,13 +18,7 @@ extern "C" { #endif -#include "sounds.h" #include "r_plane.h" -#include "r_patch.h" - -// "Left" and "Right" character symbols for additional rotation functionality -#define ROT_L ('L' - '0') -#define ROT_R ('R' - '0') // number of sprite lumps for spritewidth,offset,topoffset lookup tables // Fab: this is a hack : should allocate the lookup tables per sprite @@ -66,11 +60,8 @@ fixed_t R_GetSpriteDirectionalLighting(angle_t angle); fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope); -//faB: find sprites in wadfile, replace existing, add new ones -// (only sprites from namelist are added or replaced) -void R_AddSpriteDefs(UINT16 wadnum); - //SoM: 6/5/2000: Light sprites correctly! +boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 wadnum, UINT16 startlump, UINT16 endlump); void R_AddSprites(sector_t *sec, INT32 lightlevel); void R_AddPrecipitationSprites(void); void R_InitSprites(void); @@ -90,62 +81,12 @@ typedef struct void R_DrawMasked(maskcount_t* masks, UINT8 nummasks); -boolean R_ThingVisible (mobj_t *thing); -boolean R_ThingWithinDist (mobj_t *thing, INT32 limit_dist); +boolean R_ThingVisible(mobj_t *thing); +boolean R_ThingWithinDist(mobj_t *thing, INT32 limit_dist); -boolean R_ThingIsFullBright (mobj_t *thing); -boolean R_ThingIsSemiBright (mobj_t *thing); -boolean R_ThingIsFullDark (mobj_t *thing); - -// ----------- -// SKINS STUFF -// ----------- -#define SKINNAMESIZE 16 -// should be all lowercase!! S_SKIN processing does a strlwr -#define DEFAULTSKIN "sonic" -#define DEFAULTSKIN2 "tails" // secondary player -#define DEFAULTSKIN3 "knuckles" // third player -#define DEFAULTSKIN4 "eggman" // fourth player - -typedef struct -{ - char name[SKINNAMESIZE+1]; // INT16 descriptive name of the skin - spritedef_t spritedef; - spriteinfo_t sprinfo; - UINT16 wadnum; - char sprite[4]; // Sprite name, if seperated from S_SKIN. - skinflags_t flags; - - char realname[SKINNAMESIZE+1]; // Display name for level completion. - char hudname[SKINNAMESIZE+1]; // HUD name to display (officially exactly 5 characters long) - char facerank[9], facewant[9], facemmap[9]; // Arbitrarily named patch lumps - - // SRB2kart - UINT8 kartspeed; - UINT8 kartweight; - // - - // Definable color translation table - UINT8 starttranscolor; - UINT8 prefcolor; - fixed_t highresscale; // scale of highres, default is 0.5 - - // specific sounds per skin - sfxenum_t soundsid[NUMSKINSOUNDS]; // sound # in S_sfx table - - boolean localskin; - INT32 localnum; -} skin_t; - -extern CV_PossibleValue_t Forceskin_cons_t[]; - -// had to move those here Zzz... -INT32 K_GetSkinNum(player_t *player); -INT32 K_GetMobjSkinNum(const skin_t *skin, boolean local); -skin_t *K_GetPlayerSkin(player_t *player); -skin_t *K_GetMobjSkin(const mobj_t *mobj); -patch_t *K_GetFacePrefix(player_t *player, INT32 skinnum); -skin_t *K_GetSkinArray(boolean local); +boolean R_ThingIsFullBright(mobj_t *thing); +boolean R_ThingIsSemiBright(mobj_t *thing); +boolean R_ThingIsFullDark(mobj_t *thing); // ----------- // NOT SKINS STUFF ! @@ -231,6 +172,8 @@ void R_AllocVisSpriteMemory(void); UINT8 *R_GetSpriteTranslation(vissprite_t *vis); +void R_InitDrawNodes(void); + // ---------- // DRAW NODES // ---------- @@ -249,71 +192,6 @@ typedef struct drawnode_s struct drawnode_s *prev; } drawnode_t; -extern INT32 numskins; -extern INT32 numlocalskins; -extern INT32 numallskins; -extern skin_t skins[MAXSKINS]; -extern UINT8 skinstats[9][9][MAXSKINS]; -extern UINT8 skinstatscount[9][9]; -extern UINT8 skinsorted[MAXSKINS]; - -void sortSkinGrid(void); -extern skin_t localskins[MAXLOCALSKINS]; -extern skin_t allskins[MAXSKINS+MAXLOCALSKINS]; - -boolean SetPlayerSkin(INT32 playernum,const char *skinname); -void SetPlayerSkinByNum(INT32 playernum,INT32 skinnum); // Tails 03-16-2002 -void SetLocalPlayerSkin(INT32 playernum,const char *skinname, consvar_t *cvar); -INT32 R_SkinAvailable(const char *name); -INT32 R_AnySkinAvailable(const char *name); -INT32 R_LocalSkinAvailable(const char *name, boolean local); -void R_AddSkins(UINT16 wadnum, boolean local); - -void R_InitDrawNodes(void); - -char *GetPlayerFacePic(INT32 skinnum); - -// Functions to go from sprite character ID to frame number -// for 2.1 compatibility this still uses the old 'A' + frame code -// The use of symbols tends to be painful for wad editors though -// So the future version of this tries to avoid using symbols -// as much as possible while also defining all 64 slots in a sane manner -// 2.1: [[ ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ ]] -// Future: [[ ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!@ ]] -FUNCMATH FUNCINLINE static ATTRINLINE char R_Frame2Char(UINT8 frame) -{ -#if 1 // 2.1 compat - return 'A' + frame; -#else - if (frame < 26) return 'A' + frame; - if (frame < 36) return '0' + (frame - 26); - if (frame < 62) return 'a' + (frame - 36); - if (frame == 62) return '!'; - if (frame == 63) return '@'; - return '\xFF'; -#endif -} - -FUNCMATH FUNCINLINE static ATTRINLINE UINT8 R_Char2Frame(char cn) -{ -#if 1 // 2.1 compat - if (cn == '+') return '\\' - 'A'; // PK3 can't use backslash, so use + instead - return cn - 'A'; -#else - if (cn >= 'A' && cn <= 'Z') return cn - 'A'; - if (cn >= '0' && cn <= '9') return (cn - '0') + 26; - if (cn >= 'a' && cn <= 'z') return (cn - 'a') + 36; - if (cn == '!') return 62; - if (cn == '@') return 63; - return 255; -#endif -} - -FUNCMATH FUNCINLINE static ATTRINLINE boolean R_ValidSpriteAngle(UINT8 rotation) -{ - return ((rotation <= 8) || (rotation == ROT_L) || (rotation == ROT_R)); -} - #ifdef __cplusplus } // extern "C" #endif -- 2.54.0 From 953c0d7451a93491207675c7d52b7d31ae05792a Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 6 Jun 2025 23:36:25 +0200 Subject: [PATCH 043/141] convert r_things to ceepeepee --- src/d_netfil.h | 8 +++ src/hardware/hw_md2.h | 8 +++ src/r_patchrotation.h | 8 +++ src/{r_things.c => r_things.cpp} | 87 +++++++++++++++++--------------- 4 files changed, 69 insertions(+), 42 deletions(-) rename src/{r_things.c => r_things.cpp} (95%) diff --git a/src/d_netfil.h b/src/d_netfil.h index 464d885b3..b84c83391 100644 --- a/src/d_netfil.h +++ b/src/d_netfil.h @@ -13,6 +13,10 @@ #ifndef __D_NETFIL__ #define __D_NETFIL__ +#ifdef __cplusplus +extern "C" { +#endif + #include "d_clisrv.h" #include "w_wad.h" @@ -125,4 +129,8 @@ HTTP_login * CURLGetLogin (const char *url, HTTP_login ***return_prev_next); size_t curlwrite_data(void *ptr, size_t size, size_t nmemb, FILE *stream); #endif +#ifdef __cplusplus +} // extern "C" +#endif + #endif // __D_NETFIL__ diff --git a/src/hardware/hw_md2.h b/src/hardware/hw_md2.h index 2e3e005b7..014638f56 100644 --- a/src/hardware/hw_md2.h +++ b/src/hardware/hw_md2.h @@ -15,6 +15,10 @@ #ifndef _HW_MD2_H_ #define _HW_MD2_H_ +#ifdef __cplusplus +extern "C" { +#endif + #include "hw_glob.h" #include "hw_model.h" @@ -46,4 +50,8 @@ void HWR_DrawMD2(gl_vissprite_t *spr); void HWR_AddPlayerMD2(INT32 skin, boolean local); void HWR_AddSpriteMD2(size_t spritenum); +#ifdef __cplusplus +} // extern "C" +#endif + #endif // _HW_MD2_H_ diff --git a/src/r_patchrotation.h b/src/r_patchrotation.h index d387ae20f..b3bcd7a97 100644 --- a/src/r_patchrotation.h +++ b/src/r_patchrotation.h @@ -12,6 +12,10 @@ #ifndef __R_PATCHROTATION__ #define __R_PATCHROTATION__ +#ifdef __cplusplus +extern "C" { +#endif + #include "r_fps.h" // Sprite rotation @@ -27,4 +31,8 @@ extern fixed_t rollcosang[ROTANGLES]; extern fixed_t rollsinang[ROTANGLES]; #endif +#ifdef __cplusplus +} // extern "C" +#endif + #endif // __R_PATCHROTATION__ diff --git a/src/r_things.c b/src/r_things.cpp similarity index 95% rename from src/r_things.c rename to src/r_things.cpp index ba098696c..be7093f38 100644 --- a/src/r_things.c +++ b/src/r_things.cpp @@ -412,8 +412,7 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 // allocate this sprite's frames if (!spritedef->spriteframes) - spritedef->spriteframes = - Z_Malloc(maxframe * sizeof (*spritedef->spriteframes), PU_STATIC, NULL); + spritedef->spriteframes = static_cast(Z_Malloc(maxframe * sizeof (*spritedef->spriteframes), PU_STATIC, NULL)); spritedef->numframes = maxframe; M_Memcpy(spritedef->spriteframes, sprtemp, maxframe*sizeof (spriteframe_t)); @@ -517,7 +516,7 @@ void R_InitSprites(void) if (!numsprites) I_Error("R_AddSpriteDefs: no sprites in namelist\n"); - sprites = Z_Calloc(numsprites * sizeof (*sprites), PU_STATIC, NULL); + sprites = static_cast(Z_Calloc(numsprites * sizeof (*sprites), PU_STATIC, NULL)); // find sprites in each -file added pwad for (i = 0; i < numwadfiles; i++) @@ -550,8 +549,8 @@ static INT16 *vissprite_cliptop[MAXVISSPRITES >> VISSPRITECHUNKBITS]; static void R_AllocVisSpriteChunkMemory(UINT32 chunk) { - vissprite_clipbot[chunk] = Z_Realloc(vissprite_clipbot[chunk], sizeof(INT16) * (VISSPRITESPERCHUNK * viewwidth), PU_STATIC, NULL); - vissprite_cliptop[chunk] = Z_Realloc(vissprite_cliptop[chunk], sizeof(INT16) * (VISSPRITESPERCHUNK * viewwidth), PU_STATIC, NULL); + vissprite_clipbot[chunk] = static_cast(Z_Realloc(vissprite_clipbot[chunk], sizeof(INT16) * (VISSPRITESPERCHUNK * viewwidth), PU_STATIC, NULL)); + vissprite_cliptop[chunk] = static_cast(Z_Realloc(vissprite_cliptop[chunk], sizeof(INT16) * (VISSPRITESPERCHUNK * viewwidth), PU_STATIC, NULL)); for (unsigned i = 0; i < VISSPRITESPERCHUNK; i++) { @@ -717,7 +716,7 @@ static void R_DrawFlippedMaskedColumn(drawcolumndata_t* dc, column_t *column) if (dc->yl <= dc->yh && dc->yh > 0 && column->length != 0) { - dc->source = ZZ_Alloc(column->length); + dc->source = static_cast(ZZ_Alloc(column->length)); dc->sourcelength = column->length; for (s = (UINT8 *)column+2+column->length, d = dc->source; d < dc->source+column->length; --s) @@ -755,7 +754,7 @@ static void R_DrawVisSprite(vissprite_t *vis) fixed_t this_scale = vis->thingscale; INT32 x1, x2; INT64 overflow_test; - drawcolumndata_t dc = {0}; + drawcolumndata_t dc = {}; if (!patch) return; @@ -788,22 +787,22 @@ static void R_DrawVisSprite(vissprite_t *vis) // translate certain pixels to white colfunc = transcolfunc; if (vis->mobj->type == MT_CYBRAKDEMON) - dc.translation = R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE); + dc.translation = R_GetTranslationColormap(TC_ALLWHITE, SKINCOLOR_NONE, GTC_CACHE); else if (vis->mobj->type == MT_METALSONIC_BATTLE) - dc.translation = R_GetTranslationColormap(TC_METALSONIC, 0, GTC_CACHE); + dc.translation = R_GetTranslationColormap(TC_METALSONIC, SKINCOLOR_NONE, GTC_CACHE); else - dc.translation = R_GetTranslationColormap(TC_BOSS, 0, GTC_CACHE); + dc.translation = R_GetTranslationColormap(TC_BOSS, SKINCOLOR_NONE, GTC_CACHE); } else if (vis->mobj->color && vis->transmap) // Color mapping { colfunc = transtransfunc; dc.transmap = vis->transmap; if (vis->mobj->colorized) - dc.translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); + dc.translation = R_GetTranslationColormap(TC_RAINBOW, static_cast(vis->mobj->color), GTC_CACHE); else if (vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // MT_GHOST LOOKS LIKE A PLAYER SO USE THE PLAYER TRANSLATION TABLES. >_> - dc.translation = R_GetLocalTranslationColormap(vis->mobj->skin, vis->mobj->localskin, vis->mobj->color, GTC_CACHE, vis->mobj->skinlocal); + dc.translation = R_GetLocalTranslationColormap(static_cast(vis->mobj->skin), static_cast(vis->mobj->localskin), static_cast(vis->mobj->color), GTC_CACHE, vis->mobj->skinlocal); else // Use the defaults - dc.translation = R_GetTranslationColormap(TC_DEFAULT, vis->mobj->color, GTC_CACHE); + dc.translation = R_GetTranslationColormap(TC_DEFAULT, static_cast(vis->mobj->color), GTC_CACHE); } else if (vis->transmap) { @@ -817,11 +816,11 @@ static void R_DrawVisSprite(vissprite_t *vis) // New colormap stuff for skins Tails 06-07-2002 if (vis->mobj->colorized) - dc.translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); + dc.translation = R_GetTranslationColormap(TC_RAINBOW, static_cast(vis->mobj->color), GTC_CACHE); else if (vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // This thing is a player! - dc.translation = R_GetLocalTranslationColormap(vis->mobj->skin, vis->mobj->localskin, vis->mobj->color, GTC_CACHE, vis->mobj->skinlocal); + dc.translation = R_GetLocalTranslationColormap(static_cast(vis->mobj->skin), static_cast(vis->mobj->localskin), static_cast(vis->mobj->color), GTC_CACHE, vis->mobj->skinlocal); else // Use the defaults - dc.translation = R_GetTranslationColormap(TC_DEFAULT, vis->mobj->color, GTC_CACHE); + dc.translation = R_GetTranslationColormap(TC_DEFAULT, static_cast(vis->mobj->color), GTC_CACHE); } else if (vis->mobj->sprite == SPR_PLAY) // Looks like a player, but doesn't have a color? Get rid of green sonic syndrome. { @@ -944,10 +943,11 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) patch_t *patch; fixed_t this_scale = vis->thingscale; INT64 overflow_test; - drawcolumndata_t dc = {0}; + drawcolumndata_t dc = {}; //Fab : R_InitSprites now sets a wad lump number patch = vis->patch; + if (!patch) return; @@ -1040,7 +1040,7 @@ static void R_SplitSprite(vissprite_t *sprite) newsprite->cliptop = cliptop; newsprite->clipbot = clipbot; - sprite->cut |= SC_BOTTOM; + sprite->cut = static_cast(sprite->cut | SC_BOTTOM); sprite->gz = testheight; newsprite->gzt = sprite->gz; @@ -1058,7 +1058,8 @@ static void R_SplitSprite(vissprite_t *sprite) newsprite->szt -= 8; - newsprite->cut |= SC_TOP; + sprite->cut = static_cast(sprite->cut | SC_TOP); + if (!(sector->lightlist[i].caster->flags & FF_NOSHADE)) { INT32 lightnum = (*sector->lightlist[i].lightlevel >> LIGHTSEGSHIFT); @@ -1154,7 +1155,7 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope) fixed_t R_GetSpriteDirectionalLighting(angle_t angle) { // Copied from P_UpdateSegLightOffset - const UINT8 contrast = min(max(0, maplighting.contrast - maplighting.backlight), UINT8_MAX); + const UINT8 contrast = std::min(std::max(0, maplighting.contrast - maplighting.backlight), UINT8_MAX); const fixed_t contrastFixed = ((fixed_t)contrast) * FRACUNIT; fixed_t light = FRACUNIT; @@ -1171,6 +1172,8 @@ fixed_t R_GetSpriteDirectionalLighting(angle_t angle) return extralight; } +#define std_R_QuickCamDist(x, y) std::max(abs(((x)>>FRACBITS) - (viewx>>FRACBITS)), abs(((y)>>FRACBITS) - (viewy>>FRACBITS))) + // // R_ProjectSprite // Generates a vissprite for a thing @@ -1239,10 +1242,10 @@ static void R_ProjectSprite(mobj_t *thing) const boolean papersprite = (thing->frame & FF_PAPERSPRITE); if (cv_maxinterpdist.value) - dist = R_QuickCamDist(thing->x, thing->y); + dist = std_R_QuickCamDist(thing->x, thing->y); // uncapped/interpolation - interpmobjstate_t interp = {0}; + interpmobjstate_t interp = {}; // do interpolation if (R_UsingFrameInterpolation() && !paused && (!cv_maxinterpdist.value || dist < cv_maxinterpdist.value)) @@ -1498,7 +1501,7 @@ static void R_ProjectSprite(mobj_t *thing) tx2 = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); - if (max(tz, tz2) < FixedMul(MINZ, this_scale)) // non-papersprite clipping is handled earlier + if (std::max(tz, tz2) < FixedMul(MINZ, this_scale)) // non-papersprite clipping is handled earlier return; // Needs partially clipped @@ -1631,7 +1634,6 @@ static void R_ProjectSprite(mobj_t *thing) if (oldthing->frame & FF_ABSOLUTELIGHTLEVEL) { const UINT8 n = R_ThingLightLevel(oldthing); - // n = uint8 aka 0 - 255, so the shift will always be 0 - LIGHTLEVELS - 1 lights_array = scalelight[n >> LIGHTSEGSHIFT]; } @@ -1679,7 +1681,7 @@ static void R_ProjectSprite(mobj_t *thing) } // Less change in contrast in dark sectors - extralight = FixedMul(extralight, min(max(0, lightnum), LIGHTLEVELS - 1) * FRACUNIT / (LIGHTLEVELS - 1)); + extralight = FixedMul(extralight, std::min(std::max(0, lightnum), LIGHTLEVELS - 1) * FRACUNIT / (LIGHTLEVELS - 1)); if (papersprite) { @@ -1691,7 +1693,7 @@ static void R_ProjectSprite(mobj_t *thing) fixed_t n = FixedDiv(FixedMul(xscale, LIGHTRESOLUTIONFIX), ((MAXLIGHTSCALE-1) << LIGHTSCALESHIFT)); // Less change in contrast at further distances, to counteract DOOM diminished light - extralight = FixedMul(extralight, min(n, FRACUNIT)); + extralight = FixedMul(extralight, std::min(n, FRACUNIT)); // Contrast is stronger for normal sprites, stronger than wall lighting is at the same distance lightnum += FixedFloor((extralight / 4) + (FRACUNIT / 2)) / FRACUNIT; @@ -1793,11 +1795,11 @@ static void R_ProjectSprite(mobj_t *thing) vis->transmap = NULL; if (R_ThingIsFullBright(oldthing) || oldthing->flags2 & MF2_SHADOW || thing->flags2 & MF2_SHADOW) - vis->cut |= SC_FULLBRIGHT; + vis->cut = static_cast(vis->cut | SC_FULLBRIGHT); else if (R_ThingIsSemiBright(oldthing)) - vis->cut |= SC_SEMIBRIGHT; + vis->cut = static_cast(vis->cut | SC_SEMIBRIGHT); else if (R_ThingIsFullDark(oldthing)) - vis->cut |= SC_FULLDARK; + vis->cut = static_cast(vis->cut | SC_FULLDARK); // // determine the colormap (lightlevel & special effects) @@ -1832,7 +1834,7 @@ static void R_ProjectSprite(mobj_t *thing) vis->patch = rotsprite; else #endif - vis->patch = W_CachePatchNum(sprframe->lumppat[rot], PU_SPRITE); + vis->patch = static_cast(W_CachePatchNum(sprframe->lumppat[rot], PU_SPRITE)); vis->precip = false; @@ -1874,10 +1876,10 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) return; if (cv_maxinterpdist.value) - dist = R_QuickCamDist(thing->x, thing->y); + dist = std_R_QuickCamDist(thing->x, thing->y); // uncapped/interpolation - interpmobjstate_t interp = {0}; + interpmobjstate_t interp = {}; // okay... this is a hack, but weather isn't networked, so it should be ok if (!P_PrecipThinker(thing)) @@ -2017,7 +2019,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) //Fab: lumppat is the lump number of the patch to use, this is different // than lumpid for sprites-in-pwad : the graphics are patched - vis->patch = W_CachePatchNum(sprframe->lumppat[0], PU_SPRITE); + vis->patch = static_cast(W_CachePatchNum(sprframe->lumppat[0], PU_SPRITE)); // specific translucency if ((thing->blendmode != AST_COPY) && cv_translucency.value) @@ -2481,7 +2483,7 @@ static drawnode_t *R_CreateDrawNode(drawnode_t *link) if (node == &nodebankhead) { - node = malloc(sizeof (*node)); + node = static_cast(malloc(sizeof (*node))); if (!node) I_Error("No more free memory to CreateDrawNode"); } @@ -2569,7 +2571,7 @@ static boolean R_CheckSpriteVisible(vissprite_t *spr, INT32 x1, INT32 x2) scalestep = FixedMul(scalestep, spr->spriteyscale); if (spr->thingscale != FRACUNIT) - texturemid = FixedDiv(spr->texturemid, max(spr->thingscale, 1)); + texturemid = FixedDiv(spr->texturemid, std::max(spr->thingscale, 1)); else texturemid = spr->texturemid; } @@ -2783,7 +2785,7 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2) if (cv_spriteclip.value) { if (!R_CheckSpriteVisible(spr, x1, x2)) - spr->cut |= SC_NOTVISIBLE; + spr->cut = static_cast(spr->cut | SC_NOTVISIBLE); } } @@ -2814,11 +2816,11 @@ void R_ClipSprites(void) for (i = 0; i < DS_RANGES_COUNT; i++) { - drawsegs_xranges[i].items = Z_Realloc( + drawsegs_xranges[i].items = static_cast(Z_Realloc( drawsegs_xranges[i].items, drawsegs_xrange_size * sizeof(drawsegs_xranges[i].items[0]), PU_STATIC, NULL - ); + )); } } @@ -2856,7 +2858,7 @@ void R_ClipSprites(void) if (cv_spriteclip.value && (spr->szt > vid.height || spr->sz < 0)) { - spr->cut |= SC_NOTVISIBLE; + spr->cut = static_cast(spr->cut | SC_NOTVISIBLE); continue; } @@ -2941,7 +2943,7 @@ static void R_DrawMaskedList (drawnode_t* head) { if (r2->plane) { - drawspandata_t ds = {0}; + drawspandata_t ds = {}; next = r2->prev; R_DrawSinglePlane(&ds, r2->plane, false); R_DoneWithNode(r2); @@ -2984,8 +2986,10 @@ static void R_DrawMaskedList (drawnode_t* head) void R_DrawMasked(maskcount_t* masks, UINT8 nummasks) { - drawnode_t heads[nummasks]; /**< Drawnode lists; as many as number of views/portals. */ UINT8 i; + drawnode_t *heads; /**< Drawnode lists; as many as number of views/portals. */ + + heads = static_cast(calloc(nummasks, sizeof(drawnode_t))); for (i = 0; i < nummasks; i++) { @@ -2996,7 +3000,6 @@ void R_DrawMasked(maskcount_t* masks, UINT8 nummasks) viewz = masks[i].viewz; viewsector = masks[i].viewsector; - R_CreateDrawNodes(&masks[i], &heads[i], false); } -- 2.54.0 From e03c3766f009c14076af82a2cd69f36280c03994 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 7 Jun 2025 01:16:39 +0200 Subject: [PATCH 044/141] forgor to free the mask heads lel --- src/r_things.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/r_things.cpp b/src/r_things.cpp index be7093f38..86ae82e5d 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -3013,4 +3013,6 @@ void R_DrawMasked(maskcount_t* masks, UINT8 nummasks) R_DrawMaskedList(&heads[nummasks - 1]); R_ClearDrawNodes(&heads[nummasks - 1]); } + + free(heads); } -- 2.54.0 From b0ddde996a994b4d8ba9cfea02b7c01bdd61a9fb Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 7 Jun 2025 01:17:45 +0200 Subject: [PATCH 045/141] forgor this from removing screen size static array stuff lel --- src/r_segs.c | 348 ++++++++++++++++++++++++++++----------------------- 1 file changed, 193 insertions(+), 155 deletions(-) diff --git a/src/r_segs.c b/src/r_segs.c index d0716a3b3..dd7412439 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -950,10 +950,11 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf // Texture must be cached before setting colfunc_2s, // otherwise texture[texnum]->holes may be false when it shouldn't be R_CheckTextureCache(texnum); + //faB: handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures // are not stored per-column with post info anymore in Doom Legacy if (textures[texnum]->holes) - colfunc_2s = R_DrawRepeatMaskedColumn; //render the usual 2sided single-patch packed texture + colfunc_2s = R_DrawRepeatMaskedColumn; //render the usual 2sided single-patch packed texture else { colfunc_2s = R_Render2sidedMultiPatchColumn; //render multipatch with no holes (no post_t info) @@ -987,195 +988,201 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf if (maskedtexturecol[dc->x] == INT16_MAX) continue; + // skew FOF walls + if (ffloortextureslide) { - if (ffloortextureslide) { // skew FOF walls - if (oldx != -1) - dc->texturemid += FixedMul(ffloortextureslide, (maskedtexturecol[oldx]-maskedtexturecol[dc->x])<x; - } - // Calculate bounds - // clamp the values if necessary to avoid overflows and rendering glitches caused by them + if (oldx != -1) + dc->texturemid += FixedMul(ffloortextureslide, (maskedtexturecol[oldx]-maskedtexturecol[dc->x])<x; + } + // Calculate bounds + // clamp the values if necessary to avoid overflows and rendering glitches caused by them - if (top_frac > (INT64)CLAMPMAX) sprtopscreen = windowtop = CLAMPMAX; - else if (top_frac > (INT64)CLAMPMIN) sprtopscreen = windowtop = (fixed_t)top_frac; - else sprtopscreen = windowtop = CLAMPMIN; - if (bottom_frac > (INT64)CLAMPMAX) sprbotscreen = windowbottom = CLAMPMAX; - else if (bottom_frac > (INT64)CLAMPMIN) sprbotscreen = windowbottom = (fixed_t)bottom_frac; - else sprbotscreen = windowbottom = CLAMPMIN; + if (top_frac > (INT64)CLAMPMAX) sprtopscreen = windowtop = CLAMPMAX; + else if (top_frac > (INT64)CLAMPMIN) sprtopscreen = windowtop = (fixed_t)top_frac; + else sprtopscreen = windowtop = CLAMPMIN; + if (bottom_frac > (INT64)CLAMPMAX) sprbotscreen = windowbottom = CLAMPMAX; + else if (bottom_frac > (INT64)CLAMPMIN) sprbotscreen = windowbottom = (fixed_t)bottom_frac; + else sprbotscreen = windowbottom = CLAMPMIN; - top_frac += top_step; - bottom_frac += bottom_step; + top_frac += top_step; + bottom_frac += bottom_step; - // SoM: If column is out of range, why bother with it?? - if (windowbottom < topbounds || windowtop > bottombounds) - { - if (dc->numlights) - { - for (i = 0; i < dc->numlights; i++) - { - rlight = &dc->lightlist[i]; - rlight->height += rlight->heightstep; - if (rlight->flags & FF_CUTLEVEL) - rlight->botheight += rlight->botheightstep; - } - } - spryscale += rw_scalestep; - continue; - } - - dc->iscale = 0xffffffffu / (unsigned)spryscale; - - // Get data for the column - col = (column_t *)((UINT8 *)R_GetColumn(texnum,maskedtexturecol[dc->x]) - 3); - - // SoM: New code does not rely on R_DrawColumnShadowed which - // will (hopefully) put less strain on the stack. + // SoM: If column is out of range, why bother with it?? + if (windowbottom < topbounds || windowtop > bottombounds) + { if (dc->numlights) { - lighttable_t **xwalllights; - fixed_t height; - fixed_t bheight = 0; - INT32 solid = 0; - INT32 lighteffect = 0; - for (i = 0; i < dc->numlights; i++) { - // Check if the current light effects the colormap/lightlevel rlight = &dc->lightlist[i]; - lighteffect = !(dc->lightlist[i].flags & FF_NOSHADE); + rlight->height += rlight->heightstep; + if (rlight->flags & FF_CUTLEVEL) + rlight->botheight += rlight->botheightstep; + } + } + spryscale += rw_scalestep; + continue; + } - if (lighteffect) + dc->iscale = 0xffffffffu / (unsigned)spryscale; + + // Get data for the column + col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc->x]) - 3); + + // SoM: New code does not rely on R_DrawColumnShadowed which + // will (hopefully) put less strain on the stack. + if (dc->numlights) + { + lighttable_t **xwalllights; + fixed_t height; + fixed_t bheight = 0; + INT32 solid = 0; + INT32 lighteffect = 0; + + for (i = 0; i < dc->numlights; i++) + { + // Check if the current light effects the colormap/lightlevel + rlight = &dc->lightlist[i]; + lighteffect = !(dc->lightlist[i].flags & FF_NOSHADE); + + if (lighteffect) + { + lightnum = rlight->lightnum; + + if (lightnum < 0) + xwalllights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + xwalllights = scalelight[LIGHTLEVELS-1]; + else + xwalllights = scalelight[lightnum]; + + pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; + + if (pindex >= MAXLIGHTSCALE) + pindex = MAXLIGHTSCALE-1; + + if (pfloor->flags & FF_FOG) { - lightnum = rlight->lightnum; - - if (lightnum < 0) - xwalllights = scalelight[0]; - else if (lightnum >= LIGHTLEVELS) - xwalllights = scalelight[LIGHTLEVELS-1]; + if (pfloor->master->frontsector->extra_colormap) + rlight->rcolormap = pfloor->master->frontsector->extra_colormap->colormap + (xwalllights[pindex] - colormaps); else - xwalllights = scalelight[lightnum]; - - pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; - - if (pindex >= MAXLIGHTSCALE) - pindex = MAXLIGHTSCALE-1; - - if (pfloor->flags & FF_FOG) - { - if (pfloor->master->frontsector->extra_colormap) - rlight->rcolormap = pfloor->master->frontsector->extra_colormap->colormap + (xwalllights[pindex] - colormaps); - else - rlight->rcolormap = xwalllights[pindex]; - } - else - { - if (rlight->extra_colormap) - rlight->rcolormap = rlight->extra_colormap->colormap + (xwalllights[pindex] - colormaps); - else - rlight->rcolormap = xwalllights[pindex]; - } + rlight->rcolormap = xwalllights[pindex]; } - - solid = 0; // don't carry over solid-cutting flag from the previous light - - // Check if the current light can cut the current 3D floor. - if (rlight->flags & FF_CUTSOLIDS && !(pfloor->flags & FF_EXTRA)) - solid = 1; - else if (rlight->flags & FF_CUTEXTRA && pfloor->flags & FF_EXTRA) + else { - if (rlight->flags & FF_EXTRA) - { - // The light is from an extra 3D floor... Check the flags so - // there are no undesired cuts. - if ((rlight->flags & (FF_FOG|FF_SWIMMABLE)) == (pfloor->flags & (FF_FOG|FF_SWIMMABLE))) - solid = 1; - } + if (rlight->extra_colormap) + rlight->rcolormap = rlight->extra_colormap->colormap + (xwalllights[pindex] - colormaps); else + rlight->rcolormap = xwalllights[pindex]; + } + } + + solid = 0; // don't carry over solid-cutting flag from the previous light + + // Check if the current light can cut the current 3D floor. + if (rlight->flags & FF_CUTSOLIDS && !(pfloor->flags & FF_EXTRA)) + solid = 1; + else if (rlight->flags & FF_CUTEXTRA && pfloor->flags & FF_EXTRA) + { + if (rlight->flags & FF_EXTRA) + { + // The light is from an extra 3D floor... Check the flags so + // there are no undesired cuts. + if ((rlight->flags & (FF_FOG|FF_SWIMMABLE)) == (pfloor->flags & (FF_FOG|FF_SWIMMABLE))) solid = 1; } else - solid = 0; + solid = 1; + } + else + solid = 0; - height = rlight->height; - rlight->height += rlight->heightstep; + height = rlight->height; + rlight->height += rlight->heightstep; - if (solid) - { - bheight = rlight->botheight - (FRACUNIT >> 1); - rlight->botheight += rlight->botheightstep; - } + if (solid) + { + bheight = rlight->botheight - (FRACUNIT >> 1); + rlight->botheight += rlight->botheightstep; + } - if (height <= windowtop) - { - if (lighteffect) - { - dc->colormap = rlight->rcolormap; - if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) - dc->colormap += COLORMAP_REMAPOFFSET; - } - if (solid && windowtop < bheight) - windowtop = bheight; - continue; - } - - windowbottom = height; - if (windowbottom >= sprbotscreen) - { - windowbottom = sprbotscreen; - // draw the texture - colfunc_2s (dc, col); - for (i++; i < dc->numlights; i++) - { - rlight = &dc->lightlist[i]; - rlight->height += rlight->heightstep; - if (rlight->flags & FF_CUTLEVEL) - rlight->botheight += rlight->botheightstep; - } - continue; - } - // draw the texture - colfunc_2s (dc, col); - if (solid) - windowtop = bheight; - else - windowtop = windowbottom + 1; + if (height <= windowtop) + { if (lighteffect) { dc->colormap = rlight->rcolormap; if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) dc->colormap += COLORMAP_REMAPOFFSET; } + if (solid && windowtop < bheight) + windowtop = bheight; + continue; } - windowbottom = sprbotscreen; - // draw the texture, if there is any space left - if (windowtop < windowbottom) - colfunc_2s (dc, col); - spryscale += rw_scalestep; - continue; + windowbottom = height; + if (windowbottom >= sprbotscreen) + { + windowbottom = sprbotscreen; + + // draw the texture + colfunc_2s (dc, col); + for (i++; i < dc->numlights; i++) + { + rlight = &dc->lightlist[i]; + rlight->height += rlight->heightstep; + if (rlight->flags & FF_CUTLEVEL) + rlight->botheight += rlight->botheightstep; + } + continue; + } + + // draw the texture + colfunc_2s (dc, col); + if (solid) + windowtop = bheight; + else + windowtop = windowbottom + 1; + + if (lighteffect) + { + dc->colormap = rlight->rcolormap; + if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) + dc->colormap += COLORMAP_REMAPOFFSET; + } } - // calculate lighting - pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; + windowbottom = sprbotscreen; - if (pindex >= MAXLIGHTSCALE) - pindex = MAXLIGHTSCALE - 1; + // draw the texture, if there is any space left + if (windowtop < windowbottom) + colfunc_2s (dc, col); - dc->colormap = walllights[pindex]; - - if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) - dc->colormap += COLORMAP_REMAPOFFSET; - - if (pfloor->flags & FF_FOG && pfloor->master->frontsector->extra_colormap) - dc->colormap = pfloor->master->frontsector->extra_colormap->colormap + (dc->colormap - colormaps); - else if (frontsector->extra_colormap) - dc->colormap = frontsector->extra_colormap->colormap + (dc->colormap - colormaps); - - // draw the texture - colfunc_2s (dc, col); spryscale += rw_scalestep; + continue; } + + // calculate lighting + pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; + + if (pindex >= MAXLIGHTSCALE) + pindex = MAXLIGHTSCALE - 1; + + dc->colormap = walllights[pindex]; + + if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) + dc->colormap += COLORMAP_REMAPOFFSET; + + if (pfloor->flags & FF_FOG && pfloor->master->frontsector->extra_colormap) + dc->colormap = pfloor->master->frontsector->extra_colormap->colormap + (dc->colormap - colormaps); + else if (frontsector->extra_colormap) + dc->colormap = frontsector->extra_colormap->colormap + (dc->colormap - colormaps); + + // draw the texture + colfunc_2s (dc, col); + spryscale += rw_scalestep; } + colfunc = wallcolfunc; #undef CLAMPMAX @@ -1213,6 +1220,8 @@ static inline void R_ExpandPlaneY(visplane_t *pl, INT32 x, INT16 top, INT16 bott #define HEIGHTBITS 12 #define HEIGHTUNIT (1< fftop) yh = fftop; @@ -1461,6 +1471,7 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) dc->source = R_GetColumn(midtexture, texturecolumn); dc->texheight = textureheight[midtexture]>>FRACBITS; dc->sourcelength = dc->texheight; + colfunc(dc); // dont draw anything more for this column, since @@ -1510,7 +1521,9 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) dc->source = R_GetColumn(toptexture, texturecolumn); dc->texheight = textureheight[toptexture]>>FRACBITS; dc->sourcelength = dc->texheight; + colfunc(dc); + ceilingclip[rw_x] = (INT16)mid; } else if (!rw_ceilingmarked) // entirely off top of screen @@ -1547,7 +1560,9 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) dc->source = R_GetColumn(bottomtexture, texturecolumn); dc->texheight = textureheight[bottomtexture]>>FRACBITS; dc->sourcelength = dc->texheight; + colfunc(dc); + floorclip[rw_x] = (INT16)mid; } else if (!rw_floormarked) // entirely off bottom of screen @@ -1560,6 +1575,12 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) floorclip[rw_x] = bottomclip; } + if ((markceiling || markfloor) && (floorclip[rw_x] <= ceilingclip[rw_x] + 1)) + { + solidcol[rw_x] = 1; + didsolidcol = true; + } + if (maskedtexture || numthicksides) { // save texturecol for backdrawing of masked mid texture @@ -1607,6 +1628,7 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) } //colfunc = wallcolfunc; + colfunc = wallcolfunc; } // Uses precalculated seg->length @@ -2823,6 +2845,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) rw_tsilheight = &(ds_p->tsilheight); rw_bsilheight = &(ds_p->bsilheight); + didsolidcol = false; + #ifdef WALLSPLATS if (linedef->splats && cv_splats.value) { @@ -2838,13 +2862,27 @@ void R_StoreWallRange(INT32 start, INT32 stop) #endif R_RenderSegLoop(&dc); - colfunc = wallcolfunc; if (g_portal) // if curline is a portal, set portalrender for drawseg ds_p->portalpass = portalrender+1; else ds_p->portalpass = 0; + // cph - if a column was made solid by this wall, we _must_ save full clipping info + if (backsector && didsolidcol) + { + if (!(ds_p->silhouette & SIL_BOTTOM)) + { + ds_p->silhouette |= SIL_BOTTOM; + ds_p->bsilheight = backsector->f_slope ? INT32_MAX : backsector->floorheight; + } + if (!(ds_p->silhouette & SIL_TOP)) + { + ds_p->silhouette |= SIL_TOP; + ds_p->tsilheight = backsector->c_slope ? INT32_MIN : backsector->ceilingheight; + } + } + // save sprite clipping info if (((ds_p->silhouette & SIL_TOP) || maskedtexture) && !ds_p->sprtopclip) { -- 2.54.0 From 5868cd9777aa003f954cdf29c7dc7e6cf6899ad0 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 7 Jun 2025 01:19:38 +0200 Subject: [PATCH 046/141] make drawcolum lightlists use realloc again lel otherwise theres a crapton of overlapping memory lel --- src/r_segs.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/r_segs.c b/src/r_segs.c index dd7412439..b137238c2 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -389,19 +389,15 @@ void R_RenderMaskedSegRange(drawseg_t *drawseg, INT32 x1, INT32 x2) // Setup lighting based on the presence/lack-of 3D floors. dc->numlights = 0; + if (frontsector->numlights) { dc->numlights = frontsector->numlights; + if (dc->numlights >= dc->maxlights) { - r_lightlist_t* old_lightlist = dc->lightlist; - INT32 old_maxlights = dc->maxlights; dc->maxlights = dc->numlights; - dc->lightlist = (Z_Frame_Alloc(sizeof (*dc->lightlist) * dc->maxlights)); - if (old_lightlist != NULL) - { - M_Memcpy(dc->lightlist, old_lightlist, sizeof (*dc->lightlist) * old_maxlights); - } + dc->lightlist = Z_Realloc(dc->lightlist, sizeof (*dc->lightlist) * dc->maxlights, PU_STATIC, NULL); } for (i = 0; i < dc->numlights; i++) @@ -765,16 +761,11 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf if (frontsector->numlights) { dc->numlights = frontsector->numlights; - if (dc->numlights > dc->maxlights) + + if (dc->numlights >= dc->maxlights) { - r_lightlist_t* old_lightlist = dc->lightlist; - INT32 old_maxlights = dc->maxlights; dc->maxlights = dc->numlights; - dc->lightlist = (Z_Frame_Alloc(sizeof (*dc->lightlist) * dc->maxlights)); - if (old_lightlist != NULL) - { - M_Memcpy(dc->lightlist, old_lightlist, sizeof (*dc->lightlist) * old_maxlights); - } + dc->lightlist = Z_Realloc(dc->lightlist, sizeof (*dc->lightlist) * dc->maxlights, PU_STATIC, NULL); } for (i = p = 0; i < dc->numlights; i++) @@ -2491,7 +2482,12 @@ void R_StoreWallRange(INT32 start, INT32 stop) { dc.numlights = frontsector->numlights; dc.maxlights = dc.numlights; - dc.lightlist = (Z_Frame_Alloc(sizeof(*dc.lightlist) * dc.maxlights)); + + if (dc.numlights >= dc.maxlights) + { + dc.maxlights = dc.numlights; + dc.lightlist = Z_Realloc(dc.lightlist, sizeof (*dc.lightlist) * dc.maxlights, PU_STATIC, NULL); + } for (i = p = 0; i < dc.numlights; i++) { -- 2.54.0 From 064db977aaa8a820c9546bc318ee6f414a9e4a3b Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 7 Jun 2025 01:18:50 +0200 Subject: [PATCH 047/141] HACK: move semaphores into the drawplane loop, to fix a few visual glitches a bit of slowdown, but i have no clue what exactly causes shit, so this is the best solution for now i guess --- src/r_main.cpp | 14 -------------- src/r_plane.cpp | 9 ++++++++- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/src/r_main.cpp b/src/r_main.cpp index d0f9a7428..716e3401e 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1006,7 +1006,6 @@ static void R_SetFov(fixed_t playerfov) R_SetSkyScale(); } - // // R_Init // @@ -1388,8 +1387,6 @@ void R_RenderPlayerView(player_t *player) Portal_InitList(); - srb2::ThreadPool::Sema tp_sema; - PS_START_TIMING(ps_skyboxtime); if (skybox && skyVisible) { @@ -1402,7 +1399,6 @@ void R_RenderPlayerView(player_t *player) #ifdef FLOORSPLATS R_ClearVisibleFloorSplats(); #endif - srb2::g_main_threadpool->begin_sema(); R_RenderViewpoint(&masks[nummasks - 1], false); R_ClipSprites(); @@ -1411,9 +1407,6 @@ void R_RenderPlayerView(player_t *player) R_DrawVisibleFloorSplats(); #endif // well sometimes synchronization is off and may result in some visual glitching, oh well - tp_sema = srb2::g_main_threadpool->end_sema(); - srb2::g_main_threadpool->notify_sema(tp_sema); - srb2::g_main_threadpool->wait_sema(tp_sema); R_DrawMasked(masks, nummasks); } PS_STOP_TIMING(ps_skyboxtime); @@ -1450,10 +1443,6 @@ void R_RenderPlayerView(player_t *player) ps_numbspcalls.value.i = ps_numpolyobjects.value.i = ps_numdrawnodes.value.i = 0; PS_START_TIMING(ps_bsptime); - tp_sema = srb2::g_main_threadpool->end_sema(); - srb2::g_main_threadpool->notify_sema(tp_sema); - srb2::g_main_threadpool->wait_sema(tp_sema); - srb2::g_main_threadpool->begin_sema(); R_RenderViewpoint(&masks[nummasks - 1], true); PS_STOP_TIMING(ps_bsptime); @@ -1505,9 +1494,6 @@ void R_RenderPlayerView(player_t *player) PS_START_TIMING(ps_sw_planetime); R_DrawPlanes(); - tp_sema = srb2::g_main_threadpool->end_sema(); - srb2::g_main_threadpool->notify_sema(tp_sema); - srb2::g_main_threadpool->wait_sema(tp_sema); PS_STOP_TIMING(ps_sw_planetime); #ifdef FLOORSPLATS R_DrawVisibleFloorSplats(); diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 2a85f96a2..9dcc86aa0 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -13,6 +13,8 @@ /// while maintaining a per column clipping list only. /// Moreover, the sky areas have to be determined. +#include + #include "doomdef.h" #include "console.h" #include "g_game.h" @@ -29,8 +31,8 @@ #include "p_tick.h" #include "r_fps.h" #include "r_portal.h" + #include "core/thread_pool.h" -#include static void R_SetSlopePlaneVectors(drawspandata_t* ds, visplane_t *pl, INT32 y, fixed_t xoff, fixed_t yoff, float fudge); static void R_SetTiltedSpan(drawspandata_t* ds, INT32 span); @@ -769,11 +771,13 @@ void R_DrawPlanes(void) visplane_t *pl; INT32 i; drawspandata_t ds = {}; + srb2::ThreadPool::Sema tp_sema; R_UpdatePlaneRipple(&ds); for (i = 0; i < MAXVISPLANES; i++, pl++) { + srb2::g_main_threadpool->begin_sema(); for (pl = visplanes[i]; pl; pl = pl->next) { if (pl->ffloor != NULL || pl->polyobj != NULL) @@ -781,6 +785,9 @@ void R_DrawPlanes(void) R_DrawSinglePlane(&ds, pl, cv_parallelsoftware.value); } + tp_sema = srb2::g_main_threadpool->end_sema(); + srb2::g_main_threadpool->notify_sema(tp_sema); + srb2::g_main_threadpool->wait_sema(tp_sema); } } -- 2.54.0 From 5f8c77e752d9fe994c3fcf6d71dff4f832fb08bd Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 7 Jun 2025 01:20:14 +0200 Subject: [PATCH 048/141] test: allow multithreading for masked planes quite a neat speedup on some maps needs testing --- src/r_things.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/r_things.cpp b/src/r_things.cpp index 86ae82e5d..e27f1e825 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -30,6 +30,8 @@ #include "w_wad.h" #include "z_zone.h" +#include "core/thread_pool.h" + #ifdef HWRENDER #include "hardware/hw_md2.h" #endif @@ -2934,7 +2936,7 @@ boolean R_ThingIsFullDark(mobj_t *thing) // // R_DrawMasked // -static void R_DrawMaskedList (drawnode_t* head) +static void R_DrawMaskedList(drawnode_t* head) { drawnode_t *r2; drawnode_t *next; @@ -2945,7 +2947,12 @@ static void R_DrawMaskedList (drawnode_t* head) { drawspandata_t ds = {}; next = r2->prev; - R_DrawSinglePlane(&ds, r2->plane, false); + srb2::ThreadPool::Sema tp_sema; + srb2::g_main_threadpool->begin_sema(); + R_DrawSinglePlane(&ds, r2->plane, cv_parallelsoftware.value); + tp_sema = srb2::g_main_threadpool->end_sema(); + srb2::g_main_threadpool->notify_sema(tp_sema); + srb2::g_main_threadpool->wait_sema(tp_sema); R_DoneWithNode(r2); r2 = next; } -- 2.54.0 From c921945922a67986305bbf86290ecd81b16655de Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 7 Jun 2025 11:24:20 +0200 Subject: [PATCH 049/141] cleanup software drawer handling stuff mostly ported from rr is alot more readable and less confusing --- src/r_draw.c | 23 +-- src/r_draw.h | 85 ++++++---- src/r_draw_column.c | 51 +----- src/r_draw_span.c | 8 +- src/r_plane.cpp | 58 ++++--- src/r_segs.c | 374 ++++++++++++-------------------------------- src/r_sky.c | 5 - src/r_things.cpp | 24 ++- src/screen.c | 77 +++++++-- src/screen.h | 4 + 10 files changed, 279 insertions(+), 430 deletions(-) diff --git a/src/r_draw.c b/src/r_draw.c index 7174251f8..3b3540bc6 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -59,21 +59,9 @@ UINT8 *blendtables[NUMBLENDMAPS]; // c drawer routines // -------------------------------------------- - -void (*wallcolfunc)(drawcolumndata_t*); // new wall column drawer to draw posts >128 high -void (*colfunc)(drawcolumndata_t*); // standard column, up to 128 high posts - -void (*basecolfunc)(drawcolumndata_t*); -void (*fuzzcolfunc)(drawcolumndata_t*); // standard fuzzy effect column drawer -void (*transcolfunc)(drawcolumndata_t*); // translation column drawer -void (*shadecolfunc)(drawcolumndata_t*); // smokie test.. - -void (*transtransfunc)(drawcolumndata_t*); // translucent translated column drawer -void (*twosmultipatchfunc)(drawcolumndata_t*); // for cols with transparent pixels -void (*twosmultipatchtransfunc)(drawcolumndata_t*); // for cols with transparent pixels AND translucency - -// Short and Tall sky drawer, for the current color mode -void (*walldrawerfunc)(drawcolumndata_t*); +coldrawfunc_t *colfunc; +coldrawfunc_t *colfuncs[COLDRAWFUNC_MAX]; +int colfunctype; // ========================================================================= // SPAN DRAWING CODE STUFF @@ -93,9 +81,8 @@ float focallengthf; // c drawer routines // -------------------------------------------- -void (*spanfunc)(drawspandata_t*); // span drawer, use a 64x64 tile -void (*splatfunc)(drawspandata_t*); // span drawer w/ transparency -void (*basespanfunc)(drawspandata_t*); // default span func for color mode +spandrawfunc_t *spanfunc; +spandrawfunc_t *spanfuncs[SPANDRAWFUNC_MAX]; // ========================================================================== // OLD DOOM FUZZY EFFECT diff --git a/src/r_draw.h b/src/r_draw.h index a61ce33e3..2f5521255 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -33,29 +33,6 @@ FUNCINLINE static ATTRINLINE UINT8 *R_Address(INT32 px, INT32 py) return renderscreen + (py + viewwindowy) * linesize + (viewwindowx + px); } -// ------------------------- -// COLUMN DRAWING CODE STUFF -// ------------------------- - -extern void (*wallcolfunc)(drawcolumndata_t*); -extern void (*colfunc)(drawcolumndata_t*); -extern void (*basecolfunc)(drawcolumndata_t*); -extern void (*fuzzcolfunc)(drawcolumndata_t*); -extern void (*transcolfunc)(drawcolumndata_t*); -extern void (*shadecolfunc)(drawcolumndata_t*); -extern void (*transtransfunc)(drawcolumndata_t*); - -extern void (*twosmultipatchfunc)(drawcolumndata_t*); -extern void (*twosmultipatchtransfunc)(drawcolumndata_t*); - -// quick fix for tall/short skies, depending on bytesperpixel -extern void (*walldrawerfunc)(drawcolumndata_t*); - -void R_DrawMaskedColumn(drawcolumndata_t* dc, column_t *column); - -// ----------------------- -// SPAN DRAWING CODE STUFF -// ----------------------- typedef struct { float x, y, z; @@ -114,10 +91,6 @@ typedef struct extern drawspandata_t g_ds; -extern void (*spanfunc)(drawspandata_t*); -extern void (*basespanfunc)(drawspandata_t*); -extern void (*splatfunc)(drawspandata_t*); - // Draws a single visplane. void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_parallel); @@ -126,6 +99,54 @@ extern floatv3_t *ds_su, *ds_sv, *ds_sz; extern float focallengthf; + +typedef void (coldrawfunc_t)(drawcolumndata_t*); +typedef void (spandrawfunc_t)(drawspandata_t*); + +#define BASEDRAWFUNC 0 + +enum +{ + COLDRAWFUNC_BASE = BASEDRAWFUNC, + COLDRAWFUNC_FUZZY, + COLDRAWFUNC_TRANS, + COLDRAWFUNC_SHADOWED, + COLDRAWFUNC_TRANSTRANS, + COLDRAWFUNC_TWOSMULTIPATCH, + COLDRAWFUNC_TWOSMULTIPATCHTRANS, + COLDRAWFUNC_FOG, + + COLDRAWFUNC_MAX +}; + +extern int colfunctype; +extern coldrawfunc_t *colfunc; +extern coldrawfunc_t *colfuncs[COLDRAWFUNC_MAX]; + +enum +{ + SPANDRAWFUNC_BASE = BASEDRAWFUNC, + SPANDRAWFUNC_TRANS, + SPANDRAWFUNC_TILTED, + SPANDRAWFUNC_TILTEDTRANS, + + SPANDRAWFUNC_SPLAT, + SPANDRAWFUNC_TRANSSPLAT, + SPANDRAWFUNC_TILTEDSPLAT, + + SPANDRAWFUNC_WATER, + SPANDRAWFUNC_TILTEDWATER, + + SPANDRAWFUNC_FOG, + + SPANDRAWFUNC_MAX +}; + +extern spandrawfunc_t *spanfunc; +extern spandrawfunc_t *spanfuncs[SPANDRAWFUNC_MAX]; + +void R_DrawMaskedColumn(drawcolumndata_t* dc, column_t *column); + /// \brief Top border #define BRDR_T 0 /// \brief Bottom border @@ -211,8 +232,6 @@ void R_DrawViewBorder(void); // column drawers void R_DrawColumn(drawcolumndata_t* dc); -#define R_DrawWallColumn R_DrawColumn -void R_DrawShadeColumn(drawcolumndata_t* dc); void R_DrawColumnShadowed(drawcolumndata_t* dc); void R_DrawTranslucentColumn(drawcolumndata_t* dc); @@ -228,16 +247,16 @@ void R_DrawFogColumn(drawcolumndata_t* dc); // span drawers void R_DrawSpan(drawspandata_t* ds); -void R_DrawTiltedSpan(drawspandata_t* ds); -void R_DrawTiltedTranslucentSpan(drawspandata_t* ds); -void R_DrawTiltedTranslucentWaterSpan(drawspandata_t* ds); +void R_DrawSpan_Tilted(drawspandata_t* ds); +void R_DrawTranslucentSpan_Tilted(drawspandata_t* ds); +void R_DrawTranslucentWaterSpan_Tilted(drawspandata_t* ds); void R_DrawTranslucentSpan(drawspandata_t* ds); void R_DrawTranslucentWaterSpan(drawspandata_t* ds); void R_DrawFogSpan(drawspandata_t* ds); -void R_DrawTiltedSplat(drawspandata_t* ds); +void R_DrawSplat_Tilted(drawspandata_t* ds); void R_DrawSplat(drawspandata_t* ds); void R_DrawTranslucentSplat(drawspandata_t* ds); diff --git a/src/r_draw_column.c b/src/r_draw_column.c index 2383de341..764da111e 100644 --- a/src/r_draw_column.c +++ b/src/r_draw_column.c @@ -420,49 +420,6 @@ void R_Draw2sMultiPatchTranslucentColumn(drawcolumndata_t* dc) } } -/** \brief The R_DrawShadeColumn function - Experiment to make software go faster. Taken from the Boom source -*/ -void R_DrawShadeColumn(drawcolumndata_t* dc) -{ - register INT32 count; - register UINT8 *dest; - register fixed_t frac, fracstep; - - // check out coords for src* - if ((dc->yl < 0) || (dc->x >= vid.width)) - return; - - count = dc->yh - dc->yl; - - if (count < 0) // Zero length, column does not exceed a pixel. - { - return; - } - - if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height) - { - return; - } - - // Framebuffer destination address. - dest = R_Address(dc->x, dc->yl); - - // Looks familiar. - fracstep = dc->iscale; - frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep)); - - register const INT32 stride = vid.width; - - // Here we do an additional index re-mapping. - do - { - *dest = colormaps[(dc->source[frac>>FRACBITS] <<8) + (*dest)]; - dest += stride; - frac += fracstep; - } while (count--); -} - /** \brief The R_DrawTranslucentColumn function I've made an asm routine for the transparency, because it slows down a lot in 640x480 with big sprites (bfg on all screen, or transparent @@ -804,7 +761,9 @@ void R_DrawColumnShadowed(drawcolumndata_t* dc) if (dc->yh > realyh) dc->yh = realyh; - basecolfunc(dc); // R_DrawColumn for the appropriate architecture + + (colfuncs[BASEDRAWFUNC])(dc); // R_DrawColumn_8 for the appropriate architecture + if (solid) dc->yl = bheight; else @@ -814,7 +773,9 @@ void R_DrawColumnShadowed(drawcolumndata_t* dc) if (encoremap) dc->colormap += COLORMAP_REMAPOFFSET; } + dc->yh = realyh; + if (dc->yl <= realyh) - walldrawerfunc(dc); // R_DrawWallColumn for the appropriate architecture + (colfuncs[BASEDRAWFUNC])(dc); // R_DrawWallColumn_8 for the appropriate architecture } diff --git a/src/r_draw_span.c b/src/r_draw_span.c index 20ae9e654..b89833aee 100644 --- a/src/r_draw_span.c +++ b/src/r_draw_span.c @@ -361,7 +361,7 @@ static void R_CalcTiltedLighting(INT32 *lightbuffer, INT32 x1, INT32 x2, fixed_t /** \brief The R_DrawTiltedSpan function Draw slopes! Holy sheit! */ -void R_DrawTiltedSpan(drawspandata_t* ds) +void R_DrawSpan_Tilted(drawspandata_t* ds) { int width = ds->x2 - ds->x1; float iz, uz, vz; @@ -508,7 +508,7 @@ void R_DrawTiltedSpan(drawspandata_t* ds) /** \brief The R_DrawTiltedTranslucentSpan function Like DrawTiltedSpan, but translucent */ -void R_DrawTiltedTranslucentSpan(drawspandata_t* ds) +void R_DrawTranslucentSpan_Tilted(drawspandata_t* ds) { int width = ds->x2 - ds->x1; float iz, uz, vz; @@ -655,7 +655,7 @@ void R_DrawTiltedTranslucentSpan(drawspandata_t* ds) /** \brief The R_DrawTiltedTranslucentWaterSpan function Like DrawTiltedTranslucentSpan, but for water */ -void R_DrawTiltedTranslucentWaterSpan(drawspandata_t* ds) +void R_DrawTranslucentWaterSpan_Tilted(drawspandata_t* ds) { int width = ds->x2 - ds->x1; float iz, uz, vz; @@ -801,7 +801,7 @@ void R_DrawTiltedTranslucentWaterSpan(drawspandata_t* ds) #endif } -void R_DrawTiltedSplat(drawspandata_t* ds) +void R_DrawSplat_Tilted(drawspandata_t* ds) { // x1, x2 = ds->x1, ds->x2 int width = ds->x2 - ds->x1; diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 9dcc86aa0..cc3f14633 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -145,7 +145,6 @@ void R_AllocPlaneMemory(void) // Needs the height of the plane, and the vertical position of the span. // Sets planeripple.xfrac and planeripple.yfrac, added to ds_xfrac and ds_yfrac, if the span is not tilted. // - static fixed_t R_CalculateRippleOffset(drawspandata_t* ds, INT32 y) { fixed_t distance = FixedMul(ds->planeheight, yslope[y]); @@ -253,7 +252,7 @@ static bool R_CheckMapPlane(const char* funcname, INT32 y, INT32 x1, INT32 x2) // viewsin // viewcos // viewheight -static void R_MapPlane(drawspandata_t *ds, void(*spanfunc2)(drawspandata_t*), INT32 y, INT32 x1, INT32 x2, boolean allow_parallel) +static void R_MapPlane(drawspandata_t *ds, spandrawfunc_t *localspanfunc, INT32 y, INT32 x1, INT32 x2, boolean allow_parallel) { angle_t angle, planecos, planesin; fixed_t distance = 0, span; @@ -317,10 +316,10 @@ static void R_MapPlane(drawspandata_t *ds, void(*spanfunc2)(drawspandata_t*), IN ds->x1 = x1; ds->x2 = x2; - spanfunc2(ds); + localspanfunc(ds); } -static void R_MapTiltedPlane(drawspandata_t *ds, void(*spanfunc2)(drawspandata_t*), INT32 y, INT32 x1, INT32 x2, boolean allow_parallel) +static void R_MapTiltedPlane(drawspandata_t *ds, spandrawfunc_t *localspanfunc, INT32 y, INT32 x1, INT32 x2, boolean allow_parallel) { (void)allow_parallel; @@ -361,7 +360,7 @@ static void R_MapTiltedPlane(drawspandata_t *ds, void(*spanfunc2)(drawspandata_t ds->x1 = x1; ds->x2 = x2; - spanfunc2(ds); + localspanfunc(ds); } void R_ClearFFloorClips(void) @@ -686,7 +685,7 @@ void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop) // // R_MakeSpans // -static void R_MakeSpans(void (*mapfunc)(drawspandata_t* ds, void(*spanfunc)(drawspandata_t*), INT32, INT32, INT32, boolean), void(*spanfunc2)(drawspandata_t*), drawspandata_t* ds, INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2, boolean allow_parallel) +static void R_MakeSpans(void (*mapfunc)(drawspandata_t* ds, void(*spanfunc)(drawspandata_t*), INT32, INT32, INT32, boolean), spandrawfunc_t* localspanfunc, drawspandata_t* ds, INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2, boolean allow_parallel) { // Alam: from r_splats's R_RenderFloorSplat if (t1 >= vid.height) t1 = vid.height-1; @@ -717,7 +716,7 @@ static void R_MakeSpans(void (*mapfunc)(drawspandata_t* ds, void(*spanfunc)(draw auto task = [=]() mutable -> void { for (int i = 0; i < taskspans; i++) { - mapfunc(&dc_copy, spanfunc2, t1 + i, spanstartcopy[i], x - 1, false); + mapfunc(&dc_copy, localspanfunc, t1 + i, spanstartcopy[i], x - 1, false); } }; if (allow_parallel) @@ -746,7 +745,7 @@ static void R_MakeSpans(void (*mapfunc)(drawspandata_t* ds, void(*spanfunc)(draw auto task = [=]() mutable -> void { for (int i = 0; i < taskspans; i++) { - mapfunc(&dc_copy, spanfunc2, b1 - i, spanstartcopy[i], x - 1, false); + mapfunc(&dc_copy, localspanfunc, b1 - i, spanstartcopy[i], x - 1, false); } }; if (allow_parallel) @@ -804,8 +803,7 @@ static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), b // Reset column drawer function (note: couldn't we just call walldrawerfunc directly?) // (that is, unless we'll need to switch drawers in future for some reason) - //wallcolfunc = walldrawerfunc; - colfunc = basecolfunc; + R_SetColumnFunc(BASEDRAWFUNC); // use correct aspect ratio scale dc.iscale = skyscale; @@ -870,7 +868,6 @@ static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), b x += kSkyPlaneMacroColumns; } - } // Potentially override other stuff for now cus we're mean. :< But draw a slope plane! @@ -976,6 +973,7 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle INT32 x; INT32 stop, angle; size_t size; + INT32 spanfunctype = BASEDRAWFUNC; ffloor_t *rover; void (*mapfunc)(drawspandata_t*, void(*)(drawspandata_t*), INT32, INT32, INT32, boolean) = R_MapPlane; @@ -992,11 +990,11 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle } ds->planeripple.active = false; - spanfunc = basespanfunc; + R_SetSpanFunc(BASEDRAWFUNC); if (pl->polyobj && pl->polyobj->translucency != 0) { - spanfunc = R_DrawTranslucentSpan; + spanfunctype = SPANDRAWFUNC_TRANS; // Hacked up support for alpha value in software mode Tails 09-24-2002 (sidenote: ported to polys 10-15-2014, there was no time travel involved -Red) if (pl->polyobj->translucency >= NUMTRANSMAPS) @@ -1004,7 +1002,7 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle else if (pl->polyobj->translucency > 0) ds->transmap = R_GetTranslucencyTable(pl->polyobj->translucency); else // Opaque, but allow transparent flat pixels - spanfunc = splatfunc; + spanfunctype = SPANDRAWFUNC_SPLAT; #ifdef SHITPLANESPARENCY if (spanfunc == splatfunc || (pl->extra_colormap && pl->extra_colormap->fog)) @@ -1014,7 +1012,6 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle light = (pl->lightlevel >> LIGHTSEGSHIFT); else light = LIGHTLEVELS-1; - } else { @@ -1036,7 +1033,7 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle if (pl->ffloor->flags & FF_TRANSLUCENT) { - spanfunc = R_DrawTranslucentSpan; + spanfunctype = SPANDRAWFUNC_TRANS; // 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 @@ -1048,7 +1045,7 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle if (pl->ffloor->blend) // additive, (reverse) subtractive, modulative ds->transmap = R_GetBlendTable(pl->ffloor->blend, trans); else if (!(ds->transmap = R_GetTranslucencyTable(trans)) || trans == 0) - spanfunc = splatfunc; // Opaque, but allow transparent flat pixels + spanfunctype = SPANDRAWFUNC_SPLAT; // Opaque, but allow transparent flat pixels } #ifdef SHITPLANESPARENCY @@ -1062,7 +1059,7 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle } else if (pl->ffloor->flags & FF_FOG) { - spanfunc = R_DrawFogSpan; + spanfunctype = SPANDRAWFUNC_FOG; light = (pl->lightlevel >> LIGHTSEGSHIFT); } else light = (pl->lightlevel >> LIGHTSEGSHIFT); @@ -1222,14 +1219,21 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle else R_SetSlopePlaneVectors(ds, pl, 0, ds->xoffs, ds->yoffs, fudgecanyon); - if (spanfunc == R_DrawTranslucentWaterSpan) - spanfunc = R_DrawTiltedTranslucentWaterSpan; - else if (spanfunc == R_DrawTranslucentSpan) - spanfunc = R_DrawTiltedTranslucentSpan; - else if (spanfunc == splatfunc) - spanfunc = R_DrawTiltedSplat; - else - spanfunc = R_DrawTiltedSpan; + switch (spanfunctype) + { + case SPANDRAWFUNC_WATER: + spanfunctype = SPANDRAWFUNC_TILTEDWATER; + break; + case SPANDRAWFUNC_TRANS: + spanfunctype = SPANDRAWFUNC_TILTEDTRANS; + break; + case SPANDRAWFUNC_SPLAT: + spanfunctype = SPANDRAWFUNC_TILTEDSPLAT; + break; + default: + spanfunctype = SPANDRAWFUNC_TILTED; + break; + } ds->planezlight = scalelight[light]; } @@ -1239,6 +1243,8 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle ds->planezlight = zlight[light]; } + R_SetSpanFunc(spanfunctype); + // set the maximum value for unsigned pl->top[pl->maxx+1] = 0xffff; pl->top[pl->minx-1] = 0xffff; diff --git a/src/r_segs.c b/src/r_segs.c index b137238c2..a7222b045 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -76,172 +76,6 @@ static lighttable_t **walllights; static INT16 *maskedtexturecol; static fixed_t *maskedtextureheight = NULL; -// ========================================================================== -// R_Splats Wall Splats Drawer -// ========================================================================== - -#ifdef WALLSPLATS -static INT16 last_ceilingclip[MAXVIDWIDTH]; -static INT16 last_floorclip[MAXVIDWIDTH]; - -static void R_DrawSplatColumn(column_t *column) -{ - INT32 topscreen, bottomscreen; - fixed_t basetexturemid; - INT32 topdelta, prevdelta = -1; - - basetexturemid = dc->texturemid; - - while (column->topdelta != 0xff) - { - // calculate unclipped screen coordinates for post - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - topscreen = sprtopscreen + spryscale*topdelta; - bottomscreen = topscreen + spryscale*column->length; - - dc->yl = (topscreen+FRACUNIT-1)>>FRACBITS; - dc->yh = (bottomscreen-1)>>FRACBITS; - - if (dc->yh >= last_floorclip[dc->x]) - dc->yh = last_floorclip[dc->x] - 1; - if (dc->yl <= last_ceilingclip[dc->x]) - dc->yl = last_ceilingclip[dc->x] + 1; - if (dc->yl <= dc->yh && dl_yh < vid.height && yh > 0) - { - dc->source = (UINT8 *)column + 3; - dc->texturemid = basetexturemid - (topdelta<length + 4); - } - - dc->texturemid = basetexturemid; -} - -static void R_DrawWallSplats(void) -{ - wallsplat_t *splat; - seg_t *seg; - angle_t angle, angle1, angle2; - INT32 x1, x2; - size_t pindex; - column_t *col; - patch_t *patch; - fixed_t texturecolumn; - - splat = (wallsplat_t *)linedef->splats; - - I_Assert(splat != NULL); - - seg = ds_p->curline; - - // draw all splats from the line that touches the range of the seg - for (; splat; splat = splat->next) - { - angle1 = R_PointToAngle(splat->v1.x, splat->v1.y); - angle2 = R_PointToAngle(splat->v2.x, splat->v2.y); - angle1 = (angle1 - viewangle + ANGLE_90)>>ANGLETOFINESHIFT; - angle2 = (angle2 - viewangle + ANGLE_90)>>ANGLETOFINESHIFT; - // out of the viewangletox lut - /// \todo clip it to the screen - if (angle1 > FINEANGLES/2 || angle2 > FINEANGLES/2) - continue; - x1 = viewangletox[angle1]; - x2 = viewangletox[angle2]; - - if (x1 >= x2) - continue; // does not cross a pixel - - // splat is not in this seg range - if (x2 < ds_p->x1 || x1 > ds_p->x2) - continue; - - if (x1 < ds_p->x1) - x1 = ds_p->x1; - if (x2 > ds_p->x2) - x2 = ds_p->x2; - if (x2 <= x1) - continue; - - // calculate incremental stepping values for texture edges - rw_scalestep = ds_p->scalestep; - spryscale = ds_p->scale1 + (x1 - ds_p->x1)*rw_scalestep; - mfloorclip = floorclip; - mceilingclip = ceilingclip; - - patch = W_CachePatchNum(splat->patch, PU_SPRITE); - - dc->texturemid = splat->top + (patch->height<<(FRACBITS-1)) - viewz; - if (splat->yoffset) - dc->texturemid += *splat->yoffset; - - sprtopscreen = centeryfrac - FixedMul(dc->texturemid, spryscale); - - // set drawing mode - switch (splat->flags & SPLATDRAWMODE_MASK) - { - case SPLATDRAWMODE_OPAQUE: - colfunc = basecolfunc; - break; - case SPLATDRAWMODE_TRANS: - if (!cv_translucency.value) - colfunc = basecolfunc; - else - { - dc->transmap = R_GetTranslucencyTable(tr_trans50); - colfunc = fuzzcolfunc; - } - - break; - case SPLATDRAWMODE_SHADE: - colfunc = shadecolfunc; - break; - } - - dc->texheight = 0; - - // draw the columns - for (dc->x = x1; dc->x <= x2; dc->x++, spryscale += rw_scalestep) - { - pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; - if (pindex >= MAXLIGHTSCALE) - pindex = MAXLIGHTSCALE - 1; - dc->colormap = walllights[pindex]; - if (encoremap && !(seg->linedef->flags & ML_TFERLINE)) - dc->colormap += COLORMAP_REMAPOFFSET; - - if (frontsector->extra_colormap) - dc->colormap = frontsector->extra_colormap->colormap + (dc->colormap - colormaps); - - sprtopscreen = centeryfrac - FixedMul(dc->texturemid, spryscale); - dc->iscale = 0xffffffffu / (unsigned)spryscale; - - // find column of patch, from perspective - angle = (rw_centerangle + xtoviewangle[dc->x])>>ANGLETOFINESHIFT; - texturecolumn = rw_offset2 - splat->offset - - FixedMul(FINETANGENT(angle), rw_distance); - - // FIXME! - texturecolumn >>= FRACBITS; - if (texturecolumn < 0 || texturecolumn >= patch->width) - continue; - - // draw the texture - col = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); - R_DrawSplatColumn(col); - } - } // next splat - - colfunc = basecolfunc; -} - -#endif //WALLSPLATS - // ========================================================================== // R_RenderMaskedSegRange // ========================================================================== @@ -281,18 +115,19 @@ static void R_Render2sidedMultiPatchColumn(drawcolumndata_t* dc, column_t *colum dc->source = (UINT8 *)column + 3; dc->sourcelength = lengthcol; - // Drawn by R_DrawColumn. drawcolumndata_t dc_copy = *dc; - void (*colfunccopy)(drawcolumndata_t*); - colfunccopy = colfunc; + coldrawfunc_t* colfunccopy = colfunc; - if (colfunc == wallcolfunc) - colfunccopy = twosmultipatchfunc; - else if (colfunc == fuzzcolfunc) - colfunccopy = twosmultipatchtransfunc; - else - colfunc(dc); + // FIXME: do something better to look these up WITHOUT affecting global state... + if (R_CheckColumnFunc(BASEDRAWFUNC) == true) + { + colfunccopy = colfuncs[COLDRAWFUNC_TWOSMULTIPATCH]; + } + else if (R_CheckColumnFunc(COLDRAWFUNC_FUZZY) == true) + { + colfunccopy = colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS]; + } colfunccopy((drawcolumndata_t*)(&dc_copy)); } @@ -303,6 +138,48 @@ transnum_t R_GetLinedefTransTable(fixed_t alpha) return (20*(FRACUNIT - alpha - 1) + FRACUNIT) >> (FRACBITS+1); } +static boolean R_CheckBlendMode(drawcolumndata_t* dc, const line_t *ldef) +{ + if (!ldef->alpha) + return false; + + if (ldef->blendmode) + { + if (ldef->alpha == NUMTRANSMAPS || ldef->blendmode == AST_MODULATE) + dc->transmap = R_GetBlendTable(ldef->blendmode, 0); + else + dc->transmap = R_GetBlendTable(ldef->blendmode, R_GetLinedefTransTable(ldef->alpha)); + + R_SetColumnFunc(COLDRAWFUNC_FUZZY); + } + else if (ldef->alpha > 0 && ldef->alpha < FRACUNIT) + { + dc->transmap = R_GetTranslucencyTable(R_GetLinedefTransTable(ldef->alpha)); + R_SetColumnFunc(COLDRAWFUNC_FUZZY); + } + else if (ldef->special == 909) + { + R_SetColumnFunc(COLDRAWFUNC_FOG); + windowtop = frontsector->ceilingheight; + windowbottom = frontsector->floorheight; + } + else + { + R_SetColumnFunc(BASEDRAWFUNC); + } + + if (curline->polyseg && curline->polyseg->translucency > 0) + { + if (curline->polyseg->translucency >= NUMTRANSMAPS) + return false; + + dc->transmap = R_GetTranslucencyTable(curline->polyseg->translucency); + R_SetColumnFunc(COLDRAWFUNC_FUZZY); + } + + return true; +} + void R_RenderMaskedSegRange(drawseg_t *drawseg, INT32 x1, INT32 x2) { size_t pindex; @@ -334,40 +211,9 @@ void R_RenderMaskedSegRange(drawseg_t *drawseg, INT32 x1, INT32 x2) // hack translucent linedef types (900-909 for transtables 1-9) ldef = curline->linedef; - if (!ldef->alpha) - return; - - if (ldef->blendmode) + if (R_CheckBlendMode(dc, ldef) == false) { - if (ldef->alpha == NUMTRANSMAPS || ldef->blendmode == AST_MODULATE) - dc->transmap = R_GetBlendTable(ldef->blendmode, 0); - else - dc->transmap = R_GetBlendTable(ldef->blendmode, R_GetLinedefTransTable(ldef->alpha)); - colfunc = fuzzcolfunc; - } - else if (ldef->alpha > 0 && ldef->alpha < FRACUNIT) - { - dc->transmap = R_GetTranslucencyTable(R_GetLinedefTransTable(ldef->alpha)); - colfunc = fuzzcolfunc; - } - else if (ldef->special == 909) - { - colfunc = R_DrawFogColumn; - windowtop = frontsector->ceilingheight; - windowbottom = frontsector->floorheight; - } - else - { - colfunc = wallcolfunc; - } - - if (curline->polyseg && curline->polyseg->translucency > 0) - { - if (curline->polyseg->translucency >= NUMTRANSMAPS) - return; - - dc->transmap = R_GetTranslucencyTable(curline->polyseg->translucency); - colfunc = fuzzcolfunc; + return; // does not render } range = max(drawseg->x2-drawseg->x1, 1); @@ -409,20 +255,20 @@ void R_RenderMaskedSegRange(drawseg_t *drawseg, INT32 x1, INT32 x2) leftheight = P_GetLightZAt(light, drawseg-> leftpos.x, drawseg-> leftpos.y); rightheight = P_GetLightZAt(light, drawseg->rightpos.x, drawseg->rightpos.y); - leftheight -= viewz; + leftheight -= viewz; rightheight -= viewz; - rlight->height = (centeryfrac) - FixedMul(leftheight, drawseg->scale1); - rlight->heightstep = (centeryfrac) - FixedMul(rightheight, drawseg->scale2); - rlight->heightstep = (rlight->heightstep-rlight->height)/(range); - rlight->startheight = rlight->height; // keep starting value here to reset for each repeat - rlight->lightlevel = *light->lightlevel; + rlight->height = (centeryfrac) - FixedMul(leftheight, drawseg->scale1); + rlight->heightstep = (centeryfrac) - FixedMul(rightheight, drawseg->scale2); + rlight->heightstep = (rlight->heightstep-rlight->height)/(range); + rlight->startheight = rlight->height; // keep starting value here to reset for each repeat + rlight->lightlevel = *light->lightlevel; rlight->extra_colormap = light->extra_colormap; rlight->flags = light->flags; if (rlight->flags & FF_FOG || (rlight->extra_colormap && rlight->extra_colormap->fog)) lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT); - else if (colfunc == fuzzcolfunc) + else if (R_CheckColumnFunc(COLDRAWFUNC_FUZZY)) lightnum = LIGHTLEVELS - 1; else lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT); @@ -437,17 +283,13 @@ void R_RenderMaskedSegRange(drawseg_t *drawseg, INT32 x1, INT32 x2) } else { - if (colfunc == fuzzcolfunc) - { - if (frontsector->extra_colormap && frontsector->extra_colormap->fog) - lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); - else - lightnum = LIGHTLEVELS - 1; - } - else + if ((R_CheckColumnFunc(COLDRAWFUNC_FUZZY) == false) + || (frontsector->extra_colormap && frontsector->extra_colormap->fog)) lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); + else + lightnum = LIGHTLEVELS - 1; - if (colfunc == R_DrawFogColumn + if ((R_CheckColumnFunc(COLDRAWFUNC_FOG) == true) || (frontsector->extra_colormap && frontsector->extra_colormap->fog)) ; else if (P_ApplyLightOffset(lightnum, frontsector)) @@ -646,7 +488,7 @@ void R_RenderMaskedSegRange(drawseg_t *drawseg, INT32 x1, INT32 x2) spryscale += rw_scalestep; } } - colfunc = wallcolfunc; +} } // Loop through R_DrawMaskedColumn calls @@ -720,7 +562,7 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf frontsector = curline->frontsector == pfloor->target ? curline->backsector : curline->frontsector; texnum = R_GetTextureNum(sides[pfloor->master->sidenum[0]].midtexture); - colfunc = wallcolfunc; + R_SetColumnFunc(BASEDRAWFUNC); if (pfloor->master->flags & ML_TFERLINE) { @@ -747,10 +589,14 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf } if (fuzzy) - colfunc = fuzzcolfunc; + { + R_SetColumnFunc(COLDRAWFUNC_FUZZY); + } } else if (pfloor->flags & FF_FOG) - colfunc = R_DrawFogColumn; + { + R_SetColumnFunc(COLDRAWFUNC_FOG); + } range = max(drawseg->x2-drawseg->x1, 1); //SoM: Moved these up here so they are available for my lightlist calculations @@ -859,7 +705,7 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); else if (pfloor->flags & FF_FOG) lightnum = (pfloor->master->frontsector->lightlevel >> LIGHTSEGSHIFT); - else if (colfunc == fuzzcolfunc) + else if (R_CheckColumnFunc(COLDRAWFUNC_FUZZY) == true) lightnum = LIGHTLEVELS-1; else lightnum = R_FakeFlat(frontsector, &tempsec, &templight, &templight, false) @@ -1174,7 +1020,7 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf spryscale += rw_scalestep; } - colfunc = wallcolfunc; + R_SetColumnFunc(BASEDRAWFUNC); #undef CLAMPMAX #undef CLAMPMIN @@ -1211,6 +1057,24 @@ static inline void R_ExpandPlaneY(visplane_t *pl, INT32 x, INT16 top, INT16 bott #define HEIGHTBITS 12 #define HEIGHTUNIT (1<yl = yl; + dc->yh = yh; + dc->texturemid = mid; + dc->source = R_GetColumn(texture, texturecolumn); + dc->texheight = textureheight[texture] >> FRACBITS; + dc->sourcelength = dc->texheight; + R_SetColumnFunc(colfunctype); + coldrawfunc_t* colfunccopy = colfunc; + drawcolumndata_t dc_copy = *dc; + if (remap) + { + dc_copy.colormap += COLORMAP_REMAPOFFSET; + } + colfunccopy((drawcolumndata_t*)(&dc_copy)); +} + static boolean didsolidcol; // True if at least one column was marked solid static void R_RenderSegLoop(drawcolumndata_t* dc) @@ -1444,7 +1308,7 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) else dc->lightlist[i].rcolormap = xwalllights[pindex]; - colfunc = R_DrawColumnShadowed; + R_SetColumnFunc(COLDRAWFUNC_SHADOWED); } } @@ -1456,14 +1320,7 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) // single sided line if (yl <= yh && yh >= 0 && yl < viewheight) { - dc->yl = yl; - dc->yh = yh; - dc->texturemid = rw_midtexturemid; - dc->source = R_GetColumn(midtexture, texturecolumn); - dc->texheight = textureheight[midtexture]>>FRACBITS; - dc->sourcelength = dc->texheight; - - colfunc(dc); + R_DrawWallColumn(dc, yl, yh, rw_midtexturemid, texturecolumn, midtexture, (encoremap && !(curline->linedef->flags & ML_TFERLINE))); // dont draw anything more for this column, since // a midtexture blocks the view @@ -1506,15 +1363,7 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) } else if (mid >= 0) // safe to draw top texture { - dc->yl = yl; - dc->yh = mid; - dc->texturemid = rw_toptexturemid; - dc->source = R_GetColumn(toptexture, texturecolumn); - dc->texheight = textureheight[toptexture]>>FRACBITS; - dc->sourcelength = dc->texheight; - - colfunc(dc); - + R_DrawWallColumn(dc, yl, mid, rw_toptexturemid, texturecolumn, toptexture, topremap); ceilingclip[rw_x] = (INT16)mid; } else if (!rw_ceilingmarked) // entirely off top of screen @@ -1545,15 +1394,7 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) } else if (mid < viewheight) // safe to draw bottom texture { - dc->yl = mid; - dc->yh = yh; - dc->texturemid = rw_bottomtexturemid; - dc->source = R_GetColumn(bottomtexture, texturecolumn); - dc->texheight = textureheight[bottomtexture]>>FRACBITS; - dc->sourcelength = dc->texheight; - - colfunc(dc); - + R_DrawWallColumn(dc, mid, yh, rw_bottomtexturemid, texturecolumn, bottomtexture, bottomremap); floorclip[rw_x] = (INT16)mid; } else if (!rw_floormarked) // entirely off bottom of screen @@ -1617,9 +1458,6 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) topfrac += topstep; bottomfrac += bottomstep; } - - //colfunc = wallcolfunc; - colfunc = wallcolfunc; } // Uses precalculated seg->length @@ -2843,21 +2681,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) didsolidcol = false; -#ifdef WALLSPLATS - if (linedef->splats && cv_splats.value) - { - // Isn't a bit wasteful to copy the ENTIRE array for every drawseg? - M_Memcpy(last_ceilingclip + ds_p->x1, ceilingclip + ds_p->x1, - sizeof (INT16) * (ds_p->x2 - ds_p->x1 + 1)); - M_Memcpy(last_floorclip + ds_p->x1, floorclip + ds_p->x1, - sizeof (INT16) * (ds_p->x2 - ds_p->x1 + 1)); - R_RenderSegLoop(); - R_DrawWallSplats(); - } - else -#endif - R_RenderSegLoop(&dc); + R_SetColumnFunc(BASEDRAWFUNC); if (g_portal) // if curline is a portal, set portalrender for drawseg ds_p->portalpass = portalrender+1; @@ -2904,5 +2729,6 @@ void R_StoreWallRange(INT32 start, INT32 stop) ds_p->silhouette |= SIL_BOTTOM; ds_p->bsilheight = (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) ? INT32_MAX: INT32_MIN; } + ds_p++; } diff --git a/src/r_sky.c b/src/r_sky.c index cb21092bb..1ed47d43b 100644 --- a/src/r_sky.c +++ b/src/r_sky.c @@ -63,11 +63,6 @@ void R_SetupSkyDraw(void) { // the horizon line in a 256x128 sky texture skytexturemid = (textures[skytexture]->height/2)<colormap; if ((vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && (leveltime & 1)) // Bosses "flash" { - // translate certain pixels to white - colfunc = transcolfunc; + R_SetColumnFunc(COLDRAWFUNC_TRANS); // translate certain pixels to white if (vis->mobj->type == MT_CYBRAKDEMON) dc.translation = R_GetTranslationColormap(TC_ALLWHITE, SKINCOLOR_NONE, GTC_CACHE); else if (vis->mobj->type == MT_METALSONIC_BATTLE) @@ -797,7 +796,7 @@ static void R_DrawVisSprite(vissprite_t *vis) } else if (vis->mobj->color && vis->transmap) // Color mapping { - colfunc = transtransfunc; + R_SetColumnFunc(COLDRAWFUNC_TRANSTRANS); dc.transmap = vis->transmap; if (vis->mobj->colorized) dc.translation = R_GetTranslationColormap(TC_RAINBOW, static_cast(vis->mobj->color), GTC_CACHE); @@ -808,13 +807,13 @@ static void R_DrawVisSprite(vissprite_t *vis) } else if (vis->transmap) { - colfunc = fuzzcolfunc; + R_SetColumnFunc(COLDRAWFUNC_FUZZY); dc.transmap = vis->transmap; //Fab : 29-04-98: translucency table } else if (vis->mobj->color) { // translate green skin to another color - colfunc = transcolfunc; + R_SetColumnFunc(COLDRAWFUNC_TRANS); // New colormap stuff for skins Tails 06-07-2002 if (vis->mobj->colorized) @@ -826,7 +825,7 @@ static void R_DrawVisSprite(vissprite_t *vis) } else if (vis->mobj->sprite == SPR_PLAY) // Looks like a player, but doesn't have a color? Get rid of green sonic syndrome. { - colfunc = transcolfunc; + R_SetColumnFunc(COLDRAWFUNC_TRANS); dc.translation = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_BLUE, GTC_CACHE); } @@ -930,7 +929,7 @@ static void R_DrawVisSprite(vissprite_t *vis) } } - colfunc = basecolfunc; + R_SetColumnFunc(BASEDRAWFUNC); vis->x1 = x1; vis->x2 = x2; @@ -960,7 +959,7 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) if (vis->transmap) { - colfunc = fuzzcolfunc; + R_SetColumnFunc(COLDRAWFUNC_FUZZY); dc.transmap = vis->transmap; //Fab : 29-04-98: translucency table } @@ -998,7 +997,7 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) R_DrawMaskedColumn(&dc, column); } - colfunc = basecolfunc; + R_SetColumnFunc(BASEDRAWFUNC); } // @@ -2658,9 +2657,6 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2) (lowscale < spr->sortscale && !R_PointOnSegSide (spr->gx, spr->gy, ds->curline))) { - // masked mid texture? - /*if (ds->maskedtexturecol) - R_RenderMaskedSegRange (ds, r1, r2);*/ // seg is behind sprite continue; } @@ -2976,7 +2972,7 @@ static void R_DrawMaskedList(drawnode_t* head) next = r2->prev; // Tails 08-18-2002 - if (r2->sprite->precip == true) + if (r2->sprite->precip) { R_DrawPrecipitationSprite(r2->sprite); } diff --git a/src/screen.c b/src/screen.c index 55e00f90f..3d83d57fb 100644 --- a/src/screen.c +++ b/src/screen.c @@ -78,6 +78,36 @@ UINT8 *scr_borderpatch; // flat used to fill the reduced view borders set at ST_ // ========================================================================= +static void SCR_SetDrawFuncs(void) +{ + // + // setup the right draw routines + // + + spanfuncs[BASEDRAWFUNC] = R_DrawSpan; + spanfuncs[SPANDRAWFUNC_TRANS] = R_DrawTranslucentSpan; + spanfuncs[SPANDRAWFUNC_TILTED] = R_DrawSpan_Tilted; + spanfuncs[SPANDRAWFUNC_TILTEDTRANS] = R_DrawTranslucentSpan_Tilted; + spanfuncs[SPANDRAWFUNC_SPLAT] = R_DrawSplat; + spanfuncs[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat; + spanfuncs[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawSplat_Tilted; + spanfuncs[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan; + spanfuncs[SPANDRAWFUNC_TILTEDWATER] = R_DrawTranslucentWaterSpan_Tilted; + spanfuncs[SPANDRAWFUNC_FOG] = R_DrawFogSpan; + + colfuncs[BASEDRAWFUNC] = R_DrawColumn; + colfuncs[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn; + colfuncs[COLDRAWFUNC_TRANS] = R_DrawTranslatedColumn; + colfuncs[COLDRAWFUNC_SHADOWED] = R_DrawColumnShadowed; + colfuncs[COLDRAWFUNC_TRANSTRANS] = R_DrawTranslatedTranslucentColumn; + colfuncs[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn; + colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS] = R_Draw2sMultiPatchTranslucentColumn; + colfuncs[COLDRAWFUNC_FOG] = R_DrawFogColumn; + + R_SetColumnFunc(BASEDRAWFUNC); + R_SetSpanFunc(BASEDRAWFUNC); +} + void SCR_SetMode(void) { if (dedicated) @@ -90,22 +120,47 @@ void SCR_SetMode(void) V_SetPalette(0); - spanfunc = basespanfunc = R_DrawSpan; - splatfunc = R_DrawSplat; - transcolfunc = R_DrawTranslatedColumn; - transtransfunc = R_DrawTranslatedTranslucentColumn; - - colfunc = basecolfunc = R_DrawColumn; - shadecolfunc = R_DrawShadeColumn; - fuzzcolfunc = R_DrawTranslucentColumn; - walldrawerfunc = R_DrawWallColumn; - twosmultipatchfunc = R_Draw2sMultiPatchColumn; - twosmultipatchtransfunc = R_Draw2sMultiPatchTranslucentColumn; + SCR_SetDrawFuncs(); // set the apprpriate drawer for the sky (tall or INT16) setmodeneeded = 0; } +void R_SetColumnFunc(size_t id) +{ + I_Assert(id < COLDRAWFUNC_MAX); + + colfunctype = id; + colfunc = colfuncs[id]; +} + +void R_SetSpanFunc(size_t id) +{ + I_Assert(id < SPANDRAWFUNC_MAX); + spanfunc = spanfuncs[id]; +} + +boolean R_CheckColumnFunc(size_t id) +{ + size_t i; + + if (colfunc == NULL) + { + // Shouldn't happen. + return false; + } + + for (i = 0; i < COLDRAWFUNC_MAX; i++) + { + if (colfunc == colfuncs[id]) + { + return true; + } + } + + return false; +} + // do some initial settings for the game loading screen // void SCR_Startup(void) diff --git a/src/screen.h b/src/screen.h index e6e3fb9bc..c0a2799c1 100644 --- a/src/screen.h +++ b/src/screen.h @@ -98,6 +98,10 @@ extern consvar_t cv_alwaysgrabmouse; extern consvar_t cv_votebgscaling; +void R_SetColumnFunc(size_t id); +void R_SetSpanFunc(size_t id); +boolean R_CheckColumnFunc(size_t id); + // Change video mode, only at the start of a refresh. void SCR_SetMode(void); // Recalc screen size dependent stuff -- 2.54.0 From 43ee791d4a9f6939bb2ddc18b584afd3fd177f6e Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 7 Jun 2025 11:27:59 +0200 Subject: [PATCH 050/141] fix slopes and slope flat alignment software slopes finally are sane........ fixes certain maps like stardust speedway looking like complete butt need to test ogl, not sure if theres any real change there --- src/hardware/hw_main.c | 23 ++- src/r_draw.h | 3 + src/r_draw_span.c | 55 ++++--- src/r_plane.cpp | 334 +++++++++++++++++------------------------ 4 files changed, 184 insertions(+), 231 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index e61580777..cbd6cdece 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -548,7 +548,7 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool size_t len; float tempxsow, tempytow; - float scrollx = 0.0f, scrolly = 0.0f; + float scrollx = 0.0f, scrolly = 0.0f, anglef = 0.0f; angle_t angle = 0; static FOutVector *planeVerts = NULL; @@ -668,14 +668,11 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool if (angle) // Only needs to be done if there's an altered angle { - angle = InvAngle(angle)>>ANGLETOFINESHIFT; - - // This needs to be done so everything aligns after rotation - // It would be done so that rotation is done, THEN the translation, but I couldn't get it to rotate AND scroll like software does - tempxsow = FloatToFixed(flatxref); - tempytow = FloatToFixed(flatyref); - flatxref = (FixedToFloat(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); - flatyref = (FixedToFloat(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle)))); + tempxsow = flatxref; + tempytow = flatyref; + anglef = ANG2RAD(InvAngle(angle)); + flatxref = (tempxsow * cos(anglef)) - (tempytow * sin(anglef)); + flatyref = (tempxsow * sin(anglef)) + (tempytow * cos(anglef)); } #define SETUP3DVERT(vert, vx, vy) {\ @@ -686,10 +683,10 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool /* Need to rotate before translate */\ if (angle) /* Only needs to be done if there's an altered angle */\ {\ - tempxsow = FloatToFixed(vert->s);\ - tempytow = FloatToFixed(vert->t);\ - vert->s = (FixedToFloat(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));\ - vert->t = (FixedToFloat(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));\ + tempxsow = vert->s;\ + tempytow = vert->t;\ + vert->s = (tempxsow * cos(anglef)) - (tempytow * sin(anglef));\ + vert->t = (tempxsow * sin(anglef)) + (tempytow * cos(anglef));\ }\ \ vert->x = (vx);\ diff --git a/src/r_draw.h b/src/r_draw.h index 2f5521255..946139ac1 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -66,6 +66,9 @@ typedef struct floatv3_t sup; floatv3_t svp; floatv3_t szp; + floatv3_t slope_origin; + floatv3_t slope_u; + floatv3_t slope_v; // Variable flat sizes UINT32 nflatxshift; diff --git a/src/r_draw_span.c b/src/r_draw_span.c index b89833aee..df4fba9fe 100644 --- a/src/r_draw_span.c +++ b/src/r_draw_span.c @@ -57,6 +57,7 @@ void R_DrawSpan(drawspandata_t* ds) { return; } + while (count >= 8) { // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't @@ -350,13 +351,17 @@ static void R_CalcTiltedLighting(INT32 *lightbuffer, INT32 x1, INT32 x2, fixed_t lightbuffer[i] = (start += step) >> FRACBITS; if (lightbuffer[i] < 0) + { lightbuffer[i] = 0; + } else if (lightbuffer[i] >= MAXLIGHTSCALE) + { lightbuffer[i] = MAXLIGHTSCALE-1; + } } } -#define PLANELIGHTFLOAT ((float)BASEVIDWIDTH * BASEVIDWIDTH / vid.width / (ds->zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f * FIXED_TO_FLOAT(fovtan)) +#define PLANELIGHTFLOAT ((float)BASEVIDWIDTH * BASEVIDWIDTH / vid.width / ds->zeroheight / 21.0f * FIXED_TO_FLOAT(fovtan)) /** \brief The R_DrawTiltedSpan function Draw slopes! Holy sheit! @@ -414,8 +419,8 @@ void R_DrawSpan_Tilted(drawspandata_t* ds) do { double z = 1.f/iz; - u = (INT64)(uz*z) + viewx; - v = (INT64)(vz*z) + viewy; + u = (INT64)(uz*z); + v = (INT64)(vz*z); bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); @@ -447,8 +452,8 @@ void R_DrawSpan_Tilted(drawspandata_t* ds) endv = vz*endz; stepu = (INT64)((endu - startu) * INVSPAN); stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (i = SPANSIZE-1; i >= 0; i--) { @@ -487,8 +492,8 @@ void R_DrawSpan_Tilted(drawspandata_t* ds) left = 1.f/left; stepu = (INT64)((endu - startu) * left); stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (; width != 0; width--) { @@ -561,8 +566,8 @@ void R_DrawTranslucentSpan_Tilted(drawspandata_t* ds) do { double z = 1.f/iz; - u = (INT64)(uz*z) + viewx; - v = (INT64)(vz*z) + viewy; + u = (INT64)(uz*z); + v = (INT64)(vz*z); bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); @@ -594,8 +599,8 @@ void R_DrawTranslucentSpan_Tilted(drawspandata_t* ds) endv = vz*endz; stepu = (INT64)((endu - startu) * INVSPAN); stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (i = SPANSIZE-1; i >= 0; i--) { @@ -634,8 +639,8 @@ void R_DrawTranslucentSpan_Tilted(drawspandata_t* ds) left = 1.f/left; stepu = (INT64)((endu - startu) * left); stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (; width != 0; width--) { @@ -710,8 +715,8 @@ void R_DrawTranslucentWaterSpan_Tilted(drawspandata_t* ds) do { double z = 1.f/iz; - u = (INT64)(uz*z) + viewx; - v = (INT64)(vz*z) + viewy; + u = (INT64)(uz*z); + v = (INT64)(vz*z); bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); @@ -743,8 +748,8 @@ void R_DrawTranslucentWaterSpan_Tilted(drawspandata_t* ds) endv = vz*endz; stepu = (INT64)((endu - startu) * INVSPAN); stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (i = SPANSIZE-1; i >= 0; i--) { @@ -783,8 +788,8 @@ void R_DrawTranslucentWaterSpan_Tilted(drawspandata_t* ds) left = 1.f/left; stepu = (INT64)((endu - startu) * left); stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (; width != 0; width--) { @@ -858,8 +863,8 @@ void R_DrawSplat_Tilted(drawspandata_t* ds) do { double z = 1.f/iz; - u = (INT64)(uz*z) + viewx; - v = (INT64)(vz*z) + viewy; + u = (INT64)(uz*z); + v = (INT64)(vz*z); bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); val = source[bit]; @@ -896,8 +901,8 @@ void R_DrawSplat_Tilted(drawspandata_t* ds) endv = vz*endz; stepu = (INT64)((endu - startu) * INVSPAN); stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (i = SPANSIZE-1; i >= 0; i--) { @@ -943,8 +948,8 @@ void R_DrawSplat_Tilted(drawspandata_t* ds) left = 1.f/left; stepu = (INT64)((endu - startu) * left); stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (; width != 0; width--) { diff --git a/src/r_plane.cpp b/src/r_plane.cpp index cc3f14633..9df1af06d 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -34,9 +34,6 @@ #include "core/thread_pool.h" -static void R_SetSlopePlaneVectors(drawspandata_t* ds, visplane_t *pl, INT32 y, fixed_t xoff, fixed_t yoff, float fudge); -static void R_SetTiltedSpan(drawspandata_t* ds, INT32 span); - // // opening // @@ -94,6 +91,9 @@ fixed_t basexscale, baseyscale; static INT16 *ffloor_f_clip; static INT16 *ffloor_c_clip; +static void R_SetTiltedSpan(drawspandata_t* ds, INT32 span); +static void R_SetSlopePlaneVectors(drawspandata_t* ds, visplane_t *pl, INT32 y, fixed_t xoff, fixed_t yoff); + static void R_ReallocPlaneBounds(visplane_t *pl) { pl->top_memory = static_cast(Z_Realloc(pl->top_memory, sizeof(UINT16) * (viewwidth + 2), PU_STATIC, NULL)); @@ -166,68 +166,6 @@ static void R_UpdatePlaneRipple(drawspandata_t* ds) ds->planeripple.offset = ((leveltime-1)*140) + ((rendertimefrac*140) / FRACUNIT); } -static void R_HandleRipplePlane(drawspandata_t* ds, visplane_t *pl) -{ - INT32 top, bottom; - UINT8 *scr; - - if (!cv_ripplewater.value) - { - ds->planeripple.active = false; - return; - } - - ds->planeripple.active = true; - - if (spanfunc == R_DrawTranslucentSpan) - { - spanfunc = R_DrawTranslucentWaterSpan; - - // Copy the current scene, ugh - top = pl->high-8; - bottom = pl->low+8; - - if (top < 0) - top = 0; - if (bottom > vid.height) - bottom = vid.height; - - // Only copy the part of the screen we need - scr = (renderscreen + (top*vid.width)); - - for (UINT8 i = 1; i <= splitscreen; i++) - { - if (viewplayer != &players[displayplayers[i]]) - continue; - - switch (i) - { - case 1: - if (splitscreen == 1) - scr = (renderscreen + (top + viewheight) * vid.width); - else if (splitscreen > 1) - scr = (renderscreen + (top * vid.width) + viewwidth); - break; - case 2: - scr = (renderscreen + (top + viewheight) * vid.width); - break; - case 3: - scr = (renderscreen + (top + viewheight) * vid.width + viewwidth); - break; - default: - break; - } - - break; - } - - VID_BlitLinearScreen(scr, vid.screens[1]+((top)*vid.width), - vid.width, bottom-top, - vid.width, vid.width); - } -} - - static bool R_CheckMapPlane(const char* funcname, INT32 y, INT32 x1, INT32 x2) { if (x1 == x2) @@ -333,12 +271,8 @@ static void R_MapTiltedPlane(drawspandata_t *ds, spandrawfunc_t *localspanfunc, R_SetTiltedSpan(ds, std::clamp(y, 0, viewheight)); - float fudgecanyon = 0; - // Okay, look, don't ask me why this works, but without this setup there's a disgusting-looking misalignment with the textures. -fickle - fudgecanyon = ((1<nflatshiftup)+1.0f)/(1<nflatshiftup); - R_CalculatePlaneRipple(ds, ds->currentplane->viewangle + ds->currentplane->plangle); - R_SetSlopePlaneVectors(ds, ds->currentplane, y, (ds->xoffs + ds->planeripple.xfrac), (ds->yoffs + ds->planeripple.yfrac), fudgecanyon); + R_SetSlopePlaneVectors(ds, ds->currentplane, y, (ds->xoffs + ds->planeripple.xfrac), (ds->yoffs + ds->planeripple.yfrac)); if ((y + ds->bgofs) >= viewheight) ds->bgofs = viewheight-y-1; @@ -870,66 +804,79 @@ static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), b } } -// Potentially override other stuff for now cus we're mean. :< But draw a slope plane! -// I copied ZDoom's code and adapted it to SRB2... -Red -static void R_CalculateSlopeVectors(drawspandata_t* ds, pslope_t *slope, fixed_t planeviewx, fixed_t planeviewy, fixed_t planeviewz, fixed_t planexscale, fixed_t planeyscale, fixed_t planexoffset, fixed_t planeyoffset, angle_t planeviewangle, angle_t planeangle, float fudge) +// Returns the height of the sloped plane at (x, y) as a 32.16 fixed_t +static INT64 R_GetSlopeZAt(const pslope_t *slope, fixed_t x, fixed_t y) { - floatv3_t p, m, n; - float ang; - float vx, vy, vz; - float xscale = FIXED_TO_FLOAT(planexscale); - float yscale = FIXED_TO_FLOAT(planeyscale); - // compiler complains when P_GetSlopeZAt is used in FLOAT_TO_FIXED directly - // use this as a temp var to store P_GetSlopeZAt's return value each time - fixed_t temp; + INT64 x64 = ((INT64)x - (INT64)slope->o.x); + INT64 y64 = ((INT64)y - (INT64)slope->o.y); - vx = FIXED_TO_FLOAT(planeviewx+planexoffset); - vy = FIXED_TO_FLOAT(planeviewy-planeyoffset); - vz = FIXED_TO_FLOAT(planeviewz); + x64 = (x64 * (INT64)slope->d.x) / FRACUNIT; + y64 = (y64 * (INT64)slope->d.y) / FRACUNIT; - temp = P_GetSlopeZAt(slope, planeviewx, planeviewy); - ds->zeroheight = FIXED_TO_FLOAT(temp); + return (INT64)slope->o.z + ((x64 + y64) * (INT64)slope->zdelta) / FRACUNIT; +} + +// Sets the texture origin vector of the sloped plane. +static void R_SetSlopePlaneOrigin(drawspandata_t *ds, pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xoff, fixed_t yoff, fixed_t angle) +{ + floatv3_t *p = &ds->slope_origin; + + INT64 vx = (INT64)xpos + (INT64)xoff; + INT64 vy = (INT64)ypos - (INT64)yoff; + + float vxf = vx / (float)FRACUNIT; + float vyf = vy / (float)FRACUNIT; + float ang = ANG2RAD(ANGLE_270 - angle); // p is the texture origin in view space // Don't add in the offsets at this stage, because doing so can result in // errors if the flat is rotated. - ang = ANG2RAD(ANGLE_270 - planeviewangle); - p.x = vx * cos(ang) - vy * sin(ang); - p.z = vx * sin(ang) + vy * cos(ang); - temp = P_GetSlopeZAt(slope, -planexoffset, planeyoffset); - p.y = FIXED_TO_FLOAT(temp) - vz; + p->x = vxf * cos(ang) - vyf * sin(ang); + p->z = vxf * sin(ang) + vyf * cos(ang); + p->y = (R_GetSlopeZAt(slope, -xoff, yoff) - zpos) / (float)FRACUNIT; +} + +// This function calculates all of the vectors necessary for drawing a sloped plane. +static void R_SetSlopePlane(drawspandata_t* ds, pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle) +{ + // Potentially override other stuff for now cus we're mean. :< But draw a slope plane! + // I copied ZDoom's code and adapted it to SRB2... -Red + floatv3_t *m = &ds->slope_v, *n = &ds->slope_u; + fixed_t height, temp; + float ang; + + R_SetSlopePlaneOrigin(ds, slope, xpos, ypos, zpos, xoff, yoff, angle); + height = P_GetSlopeZAt(slope, xpos, ypos); + ds->zeroheight = FixedToFloat(height - zpos); // m is the v direction vector in view space - ang = ANG2RAD(ANGLE_180 - (planeviewangle + planeangle)); - m.x = yscale * cos(ang); - m.z = yscale * sin(ang); + ang = ANG2RAD(ANGLE_180 - (angle + plangle)); + m->x = cos(ang); + m->z = sin(ang); // n is the u direction vector in view space - n.x = xscale * sin(ang); - n.z = -xscale * cos(ang); + n->x = sin(ang); + n->z = -cos(ang); - ang = ANG2RAD(planeangle); - temp = P_GetSlopeZAt(slope, planeviewx + FLOAT_TO_FIXED(yscale * sin(ang)), planeviewy + FLOAT_TO_FIXED(yscale * cos(ang))); - m.y = FIXED_TO_FLOAT(temp) - ds->zeroheight; - temp = P_GetSlopeZAt(slope, planeviewx + FLOAT_TO_FIXED(xscale * cos(ang)), planeviewy - FLOAT_TO_FIXED(xscale * sin(ang))); - n.y = FIXED_TO_FLOAT(temp) - ds->zeroheight; + plangle >>= ANGLETOFINESHIFT; + temp = P_GetSlopeZAt(slope, xpos + FINESINE(plangle), ypos + FINECOSINE(plangle)); + m->y = FixedToFloat(temp - height); + temp = P_GetSlopeZAt(slope, xpos + FINECOSINE(plangle), ypos - FINESINE(plangle)); + n->y = FixedToFloat(temp - height); +} - m.x /= fudge; - m.y /= fudge; - m.z /= fudge; - - n.x *= fudge; - n.y *= fudge; - n.z *= fudge; +static void R_CalculateSlopeVectors(drawspandata_t* ds) +{ + float sfmult = 65536.f; // Eh. I tried making this stuff fixed-point and it exploded on me. Here's a macro for the only floating-point vector function I recall using. #define CROSS(d, v1, v2) \ d.x = (v1.y * v2.z) - (v1.z * v2.y);\ d.y = (v1.z * v2.x) - (v1.x * v2.z);\ d.z = (v1.x * v2.y) - (v1.y * v2.x) - CROSS(ds->sup, p, m); - CROSS(ds->svp, p, n); - CROSS(ds->szp, m, n); + CROSS(ds->sup, ds->slope_origin, ds->slope_v); + CROSS(ds->svp, ds->slope_origin, ds->slope_u); + CROSS(ds->szp, ds->slope_v, ds->slope_u); #undef CROSS ds->sup.z *= focallengthf; @@ -937,17 +884,17 @@ d.z = (v1.x * v2.y) - (v1.y * v2.x) ds->szp.z *= focallengthf; // Premultiply the texture vectors with the scale factors -#define SFMULT 65536.f - ds->sup.x *= (SFMULT * (1<nflatshiftup)); - ds->sup.y *= (SFMULT * (1<nflatshiftup)); - ds->sup.z *= (SFMULT * (1<nflatshiftup)); - ds->svp.x *= (SFMULT * (1<nflatshiftup)); - ds->svp.y *= (SFMULT * (1<nflatshiftup)); - ds->svp.z *= (SFMULT * (1<nflatshiftup)); -#undef SFMULT + sfmult *= (1 << ds->nflatshiftup); + + ds->sup.x *= sfmult; + ds->sup.y *= sfmult; + ds->sup.z *= sfmult; + ds->svp.x *= sfmult; + ds->svp.y *= sfmult; + ds->svp.z *= sfmult; } -static void R_SetTiltedSpan(drawspandata_t* ds, INT32 span) +void R_SetTiltedSpan(drawspandata_t* ds, INT32 span) { if (ds_su == NULL) ds_su = static_cast(Z_Calloc(sizeof(*ds_su) * vid.height, PU_STATIC, NULL)); @@ -961,17 +908,32 @@ static void R_SetTiltedSpan(drawspandata_t* ds, INT32 span) ds->szp = ds_sz[span]; } -static void R_SetSlopePlaneVectors(drawspandata_t* ds, visplane_t *pl, INT32 y, fixed_t xoff, fixed_t yoff, float fudge) +static void R_SetSlopePlaneVectors(drawspandata_t* ds, visplane_t *pl, INT32 y, fixed_t xoff, fixed_t yoff) { R_SetTiltedSpan(ds, y); - R_CalculateSlopeVectors(ds, pl->slope, pl->viewx, pl->viewy, pl->viewz, FRACUNIT, FRACUNIT, xoff, yoff, pl->viewangle, pl->plangle, fudge); + R_SetSlopePlane(ds, pl->slope, pl->viewx, pl->viewy, pl->viewz, xoff, yoff, pl->viewangle, pl->plangle); + R_CalculateSlopeVectors(ds); +} + +static inline void R_AdjustSlopeCoordinates(drawspandata_t* ds, vector3_t *origin) +{ + const fixed_t modmask = ((1 << (32-ds->nflatshiftup)) - 1); + + fixed_t ox = (origin->x & modmask); + fixed_t oy = -(origin->y & modmask); + + ds->xoffs &= modmask; + ds->yoffs &= modmask; + + ds->xoffs -= (origin->x - ox); + ds->yoffs += (origin->y + oy); } void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_parallel) { INT32 light = 0; INT32 x; - INT32 stop, angle; + INT32 stop; size_t size; INT32 spanfunctype = BASEDRAWFUNC; ffloor_t *rover; @@ -1064,9 +1026,59 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle } else light = (pl->lightlevel >> LIGHTSEGSHIFT); - if (pl->ffloor->flags & FF_RIPPLE) + if (pl->ffloor->flags & FF_RIPPLE && cv_ripplewater.value) { - R_HandleRipplePlane(ds, pl); + INT32 top, bottom; + + ds->planeripple.active = true; + + if (spanfunctype == SPANDRAWFUNC_TRANS) + { + spanfunctype = SPANDRAWFUNC_WATER; + + // Copy the current scene, ugh + top = pl->high-8; + bottom = pl->low+8; + + if (top < 0) + top = 0; + if (bottom > vid.height) + bottom = vid.height; + + // Only copy the part of the screen we need + UINT8 i = R_GetViewNumber(); + INT32 scrx = 0; + INT32 scry = top; + INT32 offset; + + if (splitscreen == 1) + { + if (i & 1) + { + scry += viewheight; + } + } + else + { + if (i & 1) + { + scrx += viewwidth; + } + + if (i / 2) + { + scry += viewheight; + } + } + + offset = (scry*vid.width) + scrx; + + // No idea if this works + VID_BlitLinearScreen(renderscreen + offset, + vid.screens[1] + (top*vid.width), // intentionally not +offset + viewwidth, bottom-top, + vid.width, vid.width); + } } } else light = (pl->lightlevel >> LIGHTSEGSHIFT); @@ -1075,9 +1087,6 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle // Don't mess with angle on slopes! We'll handle this ourselves later if (!pl->slope && viewangle != pl->viewangle+pl->plangle) { - angle = (pl->viewangle+pl->plangle-ANGLE_90)>>ANGLETOFINESHIFT; - basexscale = FixedDiv(FINECOSINE(angle),centerxfrac); - baseyscale = -FixedDiv(FINESINE(angle),centerxfrac); viewangle = pl->viewangle+pl->plangle; } @@ -1143,65 +1152,12 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle if (pl->slope) { - float fudgecanyon = 0; - fixed_t temp; - // Okay, look, don't ask me why this works, but without this setup there's a disgusting-looking misalignment with the textures. -fickle - fudgecanyon = ((1<nflatshiftup)+1.0f)/(1<nflatshiftup); - - angle_t hack = (pl->plangle & (ANGLE_90-1)); - mapfunc = R_MapTiltedPlane; - if (hack) + if (!pl->plangle) { - /* - Essentially: We can't & the components along the regular axes when the plane is rotated. - This is because the distance on each regular axis in order to loop is different. - We rotate them, & the components, add them together, & them again, and then rotate them back. - These three seperate & operations are done per axis in order to prevent overflows. - toast 10/04/17 - --- - ...of coooourse, this still isn't perfect. but it looks... merely kind of grody, rather than - completely wrong? idk. i'm just backporting this to kart right now. if anyone else wants to - ever try dig around: it's drifting towards 0,0, and no, multiplying by fudge doesn't fix it. - toast 27/09/18 - */ - - const fixed_t cosinecomponent = FINECOSINE(hack>>ANGLETOFINESHIFT); - const fixed_t sinecomponent = FINESINE(hack>>ANGLETOFINESHIFT); - - const fixed_t modmask = ((1 << (32-ds->nflatshiftup)) - 1); - - fixed_t ox = (FixedMul(pl->slope->o.x,cosinecomponent) & modmask) - (FixedMul(pl->slope->o.y,sinecomponent) & modmask); - fixed_t oy = (-FixedMul(pl->slope->o.x,sinecomponent) & modmask) - (FixedMul(pl->slope->o.y,cosinecomponent) & modmask); - - temp = ox & modmask; - oy &= modmask; - ox = FixedMul(temp,cosinecomponent)+FixedMul(oy,-sinecomponent); // negative sine for opposite direction - oy = -FixedMul(temp,-sinecomponent)+FixedMul(oy,cosinecomponent); - - temp = ds->xoffs; - ds->xoffs = (FixedMul(temp,cosinecomponent) & modmask) + (FixedMul(ds->yoffs, sinecomponent) & modmask); - ds->yoffs = (-FixedMul(temp,sinecomponent) & modmask) + (FixedMul(ds->yoffs, cosinecomponent) & modmask); - - temp = ds->xoffs & modmask; - ds->yoffs &= modmask; - ds->xoffs = FixedMul(temp,cosinecomponent)+FixedMul(ds->yoffs, -sinecomponent); // ditto - ds->yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(ds->yoffs, cosinecomponent); - - ds->xoffs -= (pl->slope->o.x - ox); - ds->yoffs += (pl->slope->o.y + oy); + R_AdjustSlopeCoordinates(ds, &pl->slope->o); } - else - { - ds->xoffs &= ((1 << (32-ds->nflatshiftup))-1); - ds->yoffs &= ((1 << (32-ds->nflatshiftup))-1); - ds->xoffs -= (pl->slope->o.x + (1 << (31-ds->nflatshiftup))) & ~((1 << (32-ds->nflatshiftup))-1); - ds->yoffs += (pl->slope->o.y + (1 << (31-ds->nflatshiftup))) & ~((1 << (32-ds->nflatshiftup))-1); - } - - ds->xoffs = (fixed_t)(ds->xoffs*fudgecanyon); - ds->yoffs = (fixed_t)(ds->yoffs/fudgecanyon); if (ds->planeripple.active) { @@ -1213,11 +1169,11 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle { ds->bgofs = R_CalculateRippleOffset(ds, x); R_CalculatePlaneRipple(ds, pl->viewangle + pl->plangle); - R_SetSlopePlaneVectors(ds, pl, x, (ds->xoffs + ds->planeripple.xfrac), (ds->yoffs + ds->planeripple.yfrac), fudgecanyon); + R_SetSlopePlaneVectors(ds, pl, x, (ds->xoffs + ds->planeripple.xfrac), (ds->yoffs + ds->planeripple.yfrac)); } } else - R_SetSlopePlaneVectors(ds, pl, 0, ds->xoffs, ds->yoffs, fudgecanyon); + R_SetSlopePlaneVectors(ds, pl, 0, ds->xoffs, ds->yoffs); switch (spanfunctype) { @@ -1253,14 +1209,6 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle stop = pl->maxx + 1; - if (viewx != pl->viewx || viewy != pl->viewy) - { - viewx = pl->viewx; - viewy = pl->viewy; - } - if (viewz != pl->viewz) - viewz = pl->viewz; - for (x = pl->minx; x <= stop; x++) { R_MakeSpans(mapfunc, spanfunc, ds, x, pl->top[x-1], pl->bottom[x-1], pl->top[x], pl->bottom[x], allow_parallel); -- 2.54.0 From d36eed3c0961c2c42e5d2237b538cf2b741c38e6 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 7 Jun 2025 11:30:03 +0200 Subject: [PATCH 051/141] convert r_segs to ceepeepee + overflow fix from RR R_DrawRepeatMaskedColumn + alot of cleanup should more or less function the same, just alot less messy --- src/{r_segs.c => r_segs.cpp} | 392 +++++++++++++++++++++-------------- 1 file changed, 237 insertions(+), 155 deletions(-) rename src/{r_segs.c => r_segs.cpp} (93%) diff --git a/src/r_segs.c b/src/r_segs.cpp similarity index 93% rename from src/r_segs.c rename to src/r_segs.cpp index a7222b045..dc59ade65 100644 --- a/src/r_segs.c +++ b/src/r_segs.cpp @@ -26,6 +26,7 @@ #include "p_setup.h" #include "p_slopes.h" #include "console.h" // con_clipviewtop +#include "screen.h" #include "core/memory.h" #include "core/thread_pool.h" @@ -39,6 +40,7 @@ static boolean markceiling; static boolean maskedtexture; static INT32 toptexture, bottomtexture, midtexture; +static bool topremap, bottomremap, midremap; static INT32 numthicksides, numbackffloors; angle_t rw_normalangle; @@ -129,109 +131,32 @@ static void R_Render2sidedMultiPatchColumn(drawcolumndata_t* dc, column_t *colum colfunccopy = colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS]; } - colfunccopy((drawcolumndata_t*)(&dc_copy)); + colfunccopy(const_cast(&dc_copy)); } } transnum_t R_GetLinedefTransTable(fixed_t alpha) { - return (20*(FRACUNIT - alpha - 1) + FRACUNIT) >> (FRACBITS+1); + return static_cast((20*(FRACUNIT - alpha - 1) + FRACUNIT) >> (FRACBITS+1)); } -static boolean R_CheckBlendMode(drawcolumndata_t* dc, const line_t *ldef) -{ - if (!ldef->alpha) - return false; - - if (ldef->blendmode) - { - if (ldef->alpha == NUMTRANSMAPS || ldef->blendmode == AST_MODULATE) - dc->transmap = R_GetBlendTable(ldef->blendmode, 0); - else - dc->transmap = R_GetBlendTable(ldef->blendmode, R_GetLinedefTransTable(ldef->alpha)); - - R_SetColumnFunc(COLDRAWFUNC_FUZZY); - } - else if (ldef->alpha > 0 && ldef->alpha < FRACUNIT) - { - dc->transmap = R_GetTranslucencyTable(R_GetLinedefTransTable(ldef->alpha)); - R_SetColumnFunc(COLDRAWFUNC_FUZZY); - } - else if (ldef->special == 909) - { - R_SetColumnFunc(COLDRAWFUNC_FOG); - windowtop = frontsector->ceilingheight; - windowbottom = frontsector->floorheight; - } - else - { - R_SetColumnFunc(BASEDRAWFUNC); - } - - if (curline->polyseg && curline->polyseg->translucency > 0) - { - if (curline->polyseg->translucency >= NUMTRANSMAPS) - return false; - - dc->transmap = R_GetTranslucencyTable(curline->polyseg->translucency); - R_SetColumnFunc(COLDRAWFUNC_FUZZY); - } - - return true; -} - -void R_RenderMaskedSegRange(drawseg_t *drawseg, INT32 x1, INT32 x2) +static void R_RenderMaskedSegLoop(drawcolumndata_t* dc, drawseg_t *drawseg, INT32 x1, INT32 x2, INT32 texnum, void (*colfunc_2s)(drawcolumndata_t*, column_t *)) { size_t pindex; column_t *col; - INT32 lightnum, texnum, i; + INT32 lightnum, i; fixed_t height, realbot; lightlist_t *light; r_lightlist_t *rlight; - line_t *ldef; sector_t *front, *back; INT32 times, repeats; INT64 overflow_test; INT32 range; + line_t *ldef; - drawcolumndata_t *dc = &g_dc; - - void (*colfunc_2s)(drawcolumndata_t* dc, column_t *); - - // Calculate light table. - // Use different light tables - // for horizontal / vertical / diagonal. Diagonal? - // OPTIMIZE: get rid of LIGHTSEGSHIFT globally - curline = drawseg->curline; - frontsector = curline->frontsector; - backsector = curline->backsector; - texnum = R_GetTextureNum(curline->sidedef->midtexture); - windowbottom = windowtop = sprbotscreen = INT32_MAX; - - // hack translucent linedef types (900-909 for transtables 1-9) ldef = curline->linedef; - if (R_CheckBlendMode(dc, ldef) == false) - { - return; // does not render - } - - range = max(drawseg->x2-drawseg->x1, 1); - rw_scalestep = drawseg->scalestep; - spryscale = drawseg->scale1 + (x1 - drawseg->x1)*rw_scalestep; - - // Texture must be cached before setting colfunc_2s, - // otherwise texture[texnum]->holes may be false when it shouldn't be - R_CheckTextureCache(texnum); - // 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]->holes) - colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture - else - { - colfunc_2s = R_Render2sidedMultiPatchColumn; // render multipatch with no holes (no post_t info) - lengthcol = textures[texnum]->height; - } + range = std::max(drawseg->x2-drawseg->x1, 1); // Setup lighting based on the presence/lack-of 3D floors. dc->numlights = 0; @@ -243,7 +168,7 @@ void R_RenderMaskedSegRange(drawseg_t *drawseg, INT32 x1, INT32 x2) if (dc->numlights >= dc->maxlights) { dc->maxlights = dc->numlights; - dc->lightlist = Z_Realloc(dc->lightlist, sizeof (*dc->lightlist) * dc->maxlights, PU_STATIC, NULL); + dc->lightlist = static_cast(Z_Realloc(dc->lightlist, sizeof (*dc->lightlist) * dc->maxlights, PU_STATIC, NULL)); } for (i = 0; i < dc->numlights; i++) @@ -264,7 +189,7 @@ void R_RenderMaskedSegRange(drawseg_t *drawseg, INT32 x1, INT32 x2) rlight->startheight = rlight->height; // keep starting value here to reset for each repeat rlight->lightlevel = *light->lightlevel; rlight->extra_colormap = light->extra_colormap; - rlight->flags = light->flags; + rlight->flags = static_cast(light->flags); if (rlight->flags & FF_FOG || (rlight->extra_colormap && rlight->extra_colormap->fog)) lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT); @@ -303,11 +228,6 @@ void R_RenderMaskedSegRange(drawseg_t *drawseg, INT32 x1, INT32 x2) walllights = scalelight[lightnum]; } - maskedtexturecol = drawseg->maskedtexturecol; - - mfloorclip = drawseg->sprbottomclip; - mceilingclip = drawseg->sprtopclip; - if (frontsector->heightsec != -1) front = §ors[frontsector->heightsec]; else @@ -368,6 +288,7 @@ void R_RenderMaskedSegRange(drawseg_t *drawseg, INT32 x1, INT32 x2) dc->texturemid += (textureheight[texnum])*times + textureheight[texnum]; else dc->texturemid -= (textureheight[texnum])*times; + // calculate lighting if (maskedtexturecol[dc->x] != INT16_MAX) { @@ -402,19 +323,18 @@ void R_RenderMaskedSegRange(drawseg_t *drawseg, INT32 x1, INT32 x2) // draw the texture col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc->x]) - 3); - for (i = 0; i < dc->numlights; i++) + auto set_light_vars = [&](INT32 k) { - rlight = &dc->lightlist[i]; + rlight = &dc->lightlist[k]; - if ((rlight->flags & FF_NOSHADE)) - continue; + lightnum = rlight->lightnum; - if (rlight->lightnum < 0) + if (lightnum < 0) xwalllights = scalelight[0]; - else if (rlight->lightnum >= LIGHTLEVELS) + else if (lightnum >= LIGHTLEVELS) xwalllights = scalelight[LIGHTLEVELS-1]; else - xwalllights = scalelight[rlight->lightnum]; + xwalllights = scalelight[lightnum]; pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; @@ -425,15 +345,34 @@ void R_RenderMaskedSegRange(drawseg_t *drawseg, INT32 x1, INT32 x2) rlight->rcolormap = rlight->extra_colormap->colormap + (xwalllights[pindex] - colormaps); else rlight->rcolormap = xwalllights[pindex]; + }; + + + auto set_colormap_below_light = [&] + { + dc->colormap = rlight->rcolormap; + if (encoremap && !(ldef->flags & ML_TFERLINE)) + dc->colormap += COLORMAP_REMAPOFFSET; + }; + + // Use the base sector's light level above the first FOF. + // You can imagine it as the sky casting its light on top of the highest FOF. + set_light_vars(0); + set_colormap_below_light(); + + for (i = 0; i < dc->numlights; i++) + { + if ((dc->lightlist[i].flags & FF_NOSHADE)) + continue; + + set_light_vars(i); height = rlight->height; rlight->height += rlight->heightstep; if (height <= windowtop) { - dc->colormap = rlight->rcolormap; - if (encoremap && !(ldef->flags & ML_TFERLINE)) - dc->colormap += COLORMAP_REMAPOFFSET; + set_colormap_below_light(); continue; } @@ -451,10 +390,9 @@ void R_RenderMaskedSegRange(drawseg_t *drawseg, INT32 x1, INT32 x2) continue; } colfunc_2s(dc, col); + windowtop = windowbottom + 1; - dc->colormap = rlight->rcolormap; - if (encoremap && !(ldef->flags & ML_TFERLINE)) - dc->colormap += COLORMAP_REMAPOFFSET; + set_colormap_below_light(); } windowbottom = realbot; if (windowtop < windowbottom) @@ -489,20 +427,141 @@ void R_RenderMaskedSegRange(drawseg_t *drawseg, INT32 x1, INT32 x2) } } } + +static boolean R_CheckBlendMode(drawcolumndata_t* dc, const line_t *ldef) +{ + if (!ldef->alpha) + return false; + + if (ldef->blendmode) + { + if (ldef->alpha == NUMTRANSMAPS || ldef->blendmode == AST_MODULATE) + dc->transmap = R_GetBlendTable(ldef->blendmode, 0); + else + dc->transmap = R_GetBlendTable(ldef->blendmode, R_GetLinedefTransTable(ldef->alpha)); + + R_SetColumnFunc(COLDRAWFUNC_FUZZY); + } + else if (ldef->alpha > 0 && ldef->alpha < FRACUNIT) + { + dc->transmap = R_GetTranslucencyTable(R_GetLinedefTransTable(ldef->alpha)); + R_SetColumnFunc(COLDRAWFUNC_FUZZY); + } + else if (ldef->special == 909) + { + R_SetColumnFunc(COLDRAWFUNC_FOG); + windowtop = frontsector->ceilingheight; + windowbottom = frontsector->floorheight; + } + else + { + R_SetColumnFunc(BASEDRAWFUNC); + } + + if (curline->polyseg && curline->polyseg->translucency > 0) + { + if (curline->polyseg->translucency >= NUMTRANSMAPS) + return false; + + dc->transmap = R_GetTranslucencyTable(curline->polyseg->translucency); + R_SetColumnFunc(COLDRAWFUNC_FUZZY); + } + + return true; +} + +void R_RenderMaskedSegRange(drawseg_t *drawseg, INT32 x1, INT32 x2) +{ + INT32 texnum; + line_t *ldef; + void (*colfunc_2s)(drawcolumndata_t* dc, column_t *); + drawcolumndata_t *dc = &g_dc; + + // Calculate light table. + // Use different light tables + // for horizontal / vertical / diagonal. Diagonal? + // OPTIMIZE: get rid of LIGHTSEGSHIFT globally + curline = drawseg->curline; + + frontsector = curline->frontsector; + backsector = curline->backsector; + texnum = R_GetTextureNum(curline->sidedef->midtexture); + windowbottom = windowtop = sprbotscreen = INT32_MAX; + + // hack translucent linedef types (900-909 for transtables 1-9) + ldef = curline->linedef; + + if (R_CheckBlendMode(dc, ldef) == false) + { + return; // does not render + } + + rw_scalestep = drawseg->scalestep; + spryscale = drawseg->scale1 + (x1 - drawseg->x1)*rw_scalestep; + + // Texture must be cached before setting colfunc_2s, + // otherwise texture[texnum]->holes may be false when it shouldn't be + R_CheckTextureCache(texnum); + + // 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]->holes) + colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture + else + { + colfunc_2s = R_Render2sidedMultiPatchColumn; // render multipatch with no holes (no post_t info) + lengthcol = textures[texnum]->height; + } + + maskedtexturecol = drawseg->maskedtexturecol; + + mfloorclip = drawseg->sprbottomclip; + mceilingclip = drawseg->sprtopclip; + + R_RenderMaskedSegLoop(dc, drawseg, x1, x2, texnum, colfunc_2s); + + R_SetColumnFunc(BASEDRAWFUNC); +} + +template +static constexpr T saturating_add(T x, T y) noexcept +{ + INT64 z; + z = static_cast(x) + static_cast(y); + if (z > static_cast(std::numeric_limits::max())) + { + z = static_cast(std::numeric_limits::max()); + } + else if (z < static_cast(std::numeric_limits::min())) + { + z = static_cast(std::numeric_limits::min()); + } + return static_cast(z); +} + +template +static constexpr T saturating_mul(T x, T y) noexcept +{ + INT64 z; + z = static_cast(x) * static_cast(y); + if (z > static_cast(std::numeric_limits::max())) + { + z = static_cast(std::numeric_limits::max()); + } + else if (z < static_cast(std::numeric_limits::min())) + { + z = static_cast(std::numeric_limits::min()); + } + return static_cast(z); } // Loop through R_DrawMaskedColumn calls static void R_DrawRepeatMaskedColumn(drawcolumndata_t* dc, column_t *col) { - INT64 z; while (sprtopscreen < sprbotscreen) { R_DrawMaskedColumn(dc, col); - z = sprtopscreen + (INT64)dc->texheight*spryscale; - if (z > (INT64)INT32_MAX) // prevent overflow - sprtopscreen = INT32_MAX; - else - sprtopscreen = z; + sprtopscreen = saturating_add(sprtopscreen, saturating_mul(dc->texheight, spryscale)); } } @@ -566,7 +625,7 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf if (pfloor->master->flags & ML_TFERLINE) { - size_t linenum = min((size_t)(curline->linedef-backsector->lines[0]), pfloor->master->frontsector->linecount); + size_t linenum = std::min((size_t)(curline->linedef-backsector->lines[0]), pfloor->master->frontsector->linecount); newline = pfloor->master->frontsector->lines[0] + linenum; texnum = R_GetTextureNum(sides[newline->sidenum[0]].midtexture); } @@ -598,7 +657,7 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf R_SetColumnFunc(COLDRAWFUNC_FOG); } - range = max(drawseg->x2-drawseg->x1, 1); + range = std::max(drawseg->x2-drawseg->x1, 1); //SoM: Moved these up here so they are available for my lightlist calculations rw_scalestep = drawseg->scalestep; spryscale = drawseg->scale1 + (x1 - drawseg->x1)*rw_scalestep; @@ -611,7 +670,7 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf if (dc->numlights >= dc->maxlights) { dc->maxlights = dc->numlights; - dc->lightlist = Z_Realloc(dc->lightlist, sizeof (*dc->lightlist) * dc->maxlights, PU_STATIC, NULL); + dc->lightlist = static_cast(Z_Realloc(dc->lightlist, sizeof (*dc->lightlist) * dc->maxlights, PU_STATIC, NULL)); } for (i = p = 0; i < dc->numlights; i++) @@ -658,7 +717,8 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf else if (overflow_test > (INT64)CLAMPMIN) rlight->heightstep = (fixed_t)overflow_test; else rlight->heightstep = CLAMPMIN; rlight->heightstep = (rlight->heightstep-rlight->height)/(range); - rlight->flags = light->flags; + rlight->flags = static_cast(light->flags); + if (light->flags & FF_CUTLEVEL) { SLOPEPARAMS(*light->caster->b_slope, leftheight, rightheight, *light->caster->bottomheight) @@ -877,11 +937,10 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf INT32 solid = 0; INT32 lighteffect = 0; - for (i = 0; i < dc->numlights; i++) + auto set_light_vars = [&](INT32 k) { - // Check if the current light effects the colormap/lightlevel - rlight = &dc->lightlist[i]; - lighteffect = !(dc->lightlist[i].flags & FF_NOSHADE); + rlight = &dc->lightlist[k]; + lighteffect = !(dc->lightlist[k].flags & FF_NOSHADE); if (lighteffect) { @@ -914,6 +973,30 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf rlight->rcolormap = xwalllights[pindex]; } } + }; + + auto set_colormap_below_light = [&] + { + dc->colormap = rlight->rcolormap; + if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) + dc->colormap += COLORMAP_REMAPOFFSET; + }; + + // Use the base sector's light level above the first FOF. + // You can imagine it as the sky casting its light on top of the highest FOF. + set_light_vars(0); + set_colormap_below_light(); + + for (i = 0; i < dc->numlights; i++) + { + // Check if the current light effects the colormap/lightlevel + rlight = &dc->lightlist[i]; + lighteffect = !(dc->lightlist[i].flags & FF_NOSHADE); + + if (lighteffect) + { + set_light_vars(i); + } solid = 0; // don't carry over solid-cutting flag from the previous light @@ -948,9 +1031,7 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf { if (lighteffect) { - dc->colormap = rlight->rcolormap; - if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) - dc->colormap += COLORMAP_REMAPOFFSET; + set_colormap_below_light(); } if (solid && windowtop < bheight) windowtop = bheight; @@ -983,9 +1064,7 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf if (lighteffect) { - dc->colormap = rlight->rcolormap; - if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) - dc->colormap += COLORMAP_REMAPOFFSET; + set_colormap_below_light(); } } @@ -1072,7 +1151,7 @@ static void R_DrawWallColumn(drawcolumndata_t* dc, INT32 yl, INT32 yh, fixed_t m { dc_copy.colormap += COLORMAP_REMAPOFFSET; } - colfunccopy((drawcolumndata_t*)(&dc_copy)); + colfunccopy(const_cast(&dc_copy)); } static boolean didsolidcol; // True if at least one column was marked solid @@ -1160,7 +1239,8 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) // Polyobject-specific hack to fix plane leaking -Red if (ffloor[i].polyobj && top_w >= bottom_w) { - ffloor[i].plane->top[rw_x] = ffloor[i].plane->bottom[rw_x] = 0xFFFF; + ffloor[i].plane->top[rw_x] = 0xFFFF; + ffloor[i].plane->bottom[rw_x] = 0x0000; // fix for sky plane drawing crashes - Monster Iestyn 25/05/18 } else if (top_w <= bottom_w) { @@ -1205,7 +1285,8 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) // Polyobject-specific hack to fix plane leaking -Red if (ffloor[i].polyobj && top_w >= bottom_w) { - ffloor[i].plane->top[rw_x] = ffloor[i].plane->bottom[rw_x] = 0xFFFF; + ffloor[i].plane->top[rw_x] = 0xFFFF; + ffloor[i].plane->bottom[rw_x] = 0x0000; // fix for sky plane drawing crashes - Monster Iestyn 25/05/18 } else if (top_w <= bottom_w) { @@ -1267,9 +1348,6 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) dc->colormap = walllights[pindex]; - if (encoremap && !(curline->linedef->flags & ML_TFERLINE)) - dc->colormap += COLORMAP_REMAPOFFSET; - dc->x = rw_x; dc->iscale = 0xffffffffu / (unsigned)rw_scale; @@ -1314,6 +1392,9 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) frontscale[rw_x] = rw_scale; + const INT16 topclip = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1; + const INT16 bottomclip = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight; + // draw the wall tiers if (midtexture) { @@ -1333,17 +1414,13 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) { // note: don't use min/max macros, since casting from INT32 to INT16 is involved here if (markceiling && (!rw_ceilingmarked)) - ceilingclip[rw_x] = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1; - + ceilingclip[rw_x] = topclip; if (markfloor && (!rw_floormarked)) - floorclip[rw_x] = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight; + floorclip[rw_x] = bottomclip; } } else { - INT16 topclip = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1; - INT16 bottomclip = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight; - // two sided line if (toptexture) { @@ -1421,8 +1498,8 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) if (maskedtextureheight != NULL) { maskedtextureheight[rw_x] = (!!(curline->linedef->flags & ML_DONTPEGBOTTOM) ^ !!(curline->linedef->flags & ML_EFFECT3) ? - max(rw_midtexturemid, rw_midtextureback) : - min(rw_midtexturemid, rw_midtextureback)); + std::max(rw_midtexturemid, rw_midtextureback) : + std::min(rw_midtexturemid, rw_midtextureback)); } } @@ -1487,8 +1564,8 @@ void R_AllocSegMemory(void) if (!maxdrawsegs) return; - frontscaletable = Z_Realloc(frontscaletable, sizeof(*frontscaletable) * (maxdrawsegs * viewwidth), PU_STATIC, NULL); - maskedheighttable = Z_Realloc(maskedheighttable, sizeof(*maskedheighttable) * (maxdrawsegs * viewwidth), PU_STATIC, NULL); + frontscaletable = static_cast(Z_Realloc(frontscaletable, sizeof(*frontscaletable) * (maxdrawsegs * viewwidth), PU_STATIC, NULL)); + maskedheighttable = static_cast(Z_Realloc(maskedheighttable, sizeof(*maskedheighttable) * (maxdrawsegs * viewwidth), PU_STATIC, NULL)); drawseg_t *lastseg = drawsegs + maxdrawsegs; @@ -1522,7 +1599,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) INT32 range; vertex_t segleft, segright; fixed_t ceilingfrontslide, floorfrontslide, ceilingbackslide, floorbackslide; - drawcolumndata_t dc = {0}; + drawcolumndata_t dc = {}; maskedtextureheight = NULL; //initialize segleft and segright @@ -1538,7 +1615,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (firstseg) firstseg = (drawseg_t *)(firstseg - drawsegs); - drawsegs = Z_Realloc(drawsegs, newmax*sizeof (*drawsegs), PU_STATIC, NULL); + drawsegs = static_cast(Z_Realloc(drawsegs, newmax*sizeof (*drawsegs), PU_STATIC, NULL)); ds_p = drawsegs + pos; @@ -1590,7 +1667,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) do maxopenings = maxopenings ? maxopenings*2 : 16384; while (need > maxopenings); - openings = Z_Realloc(openings, maxopenings * sizeof (*openings), PU_STATIC, NULL); + openings = static_cast(Z_Realloc(openings, maxopenings * sizeof (*openings), PU_STATIC, NULL)); lastopening = openings + pos; if (oldopenings == NULL) @@ -1697,6 +1774,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) worldbottomslope -= viewz; midtexture = toptexture = bottomtexture = maskedtexture = 0; + midremap = topremap = bottomremap = false; ds_p->maskedtexturecol = NULL; ds_p->numthicksides = numthicksides = 0; ds_p->thicksidecol = NULL; @@ -1743,6 +1821,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) // single sided line midtexture = R_GetTextureNum(sidedef->midtexture); + midremap = (encoremap && !(curline->linedef->flags & ML_TFERLINE)); texheight = textureheight[midtexture]; // a single sided line is terminal, so it must mark ends @@ -1904,6 +1983,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) { fixed_t texheight; // top texture + topremap = (encoremap && !(curline->linedef->flags & ML_TFERLINE)); + if ((linedef->flags & (ML_DONTPEGTOP) && (linedef->flags & ML_DONTPEGBOTTOM)) && linedef->sidenum[1] != 0xffff) { @@ -1945,6 +2026,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) { // bottom texture bottomtexture = R_GetTextureNum(sidedef->bottomtexture); + bottomremap = (encoremap && !(curline->linedef->flags & ML_TFERLINE)); if (!(linedef->flags & ML_EFFECT1)) // Ignore slopes for lower/upper textures unless flag is checked { @@ -1986,10 +2068,10 @@ void R_StoreWallRange(INT32 start, INT32 stop) ds_p->thicksidecol = maskedtexturecol = lastopening - rw_x; lastopening += rw_stopx - rw_x; - lowcut = max(worldbottom, worldlow) + viewz; - highcut = min(worldtop, worldhigh) + viewz; - lowcutslope = max(worldbottomslope, worldlowslope) + viewz; - highcutslope = min(worldtopslope, worldhighslope) + viewz; + lowcut = std::max(worldbottom, worldlow) + viewz; + highcut = std::min(worldtop, worldhigh) + viewz; + lowcutslope = std::max(worldbottomslope, worldlowslope) + viewz; + highcutslope = std::min(worldtopslope, worldhighslope) + viewz; if (frontsector->ffloors && backsector->ffloors) { @@ -2091,7 +2173,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) SLOPEPARAMS(*r2->t_slope, high2, highslope2, *r2->topheight) SLOPEPARAMS(*r2->b_slope, low2, lowslope2, *r2->bottomheight) - +#undef SLOPEPARAMS if ((high2 < lowcut || highslope2 < lowcutslope) || (low2 > highcut || lowslope2 > highcutslope)) continue; if ((high1 > high2 || highslope1 > highslope2) || (low1 < low2 || lowslope1 < lowslope2)) @@ -2174,9 +2256,9 @@ void R_StoreWallRange(INT32 start, INT32 stop) rw_midtextureslide = rw_midtexturebackslide = 0; if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) - rw_midtexturemid = rw_midtextureback = max(curline->frontsector->floorheight, curline->backsector->floorheight) - viewz; + rw_midtexturemid = rw_midtextureback = std::max(curline->frontsector->floorheight, curline->backsector->floorheight) - viewz; else - rw_midtexturemid = rw_midtextureback = min(curline->frontsector->ceilingheight, curline->backsector->ceilingheight) - viewz; + rw_midtexturemid = rw_midtextureback = std::min(curline->frontsector->ceilingheight, curline->backsector->ceilingheight) - viewz; } else { @@ -2186,9 +2268,9 @@ void R_StoreWallRange(INT32 start, INT32 stop) rw_midtextureslide = rw_midtexturebackslide = 0; if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) - rw_midtexturemid = rw_midtextureback = max(frontsector->floorheight, backsector->floorheight) - viewz; + rw_midtexturemid = rw_midtextureback = std::max(frontsector->floorheight, backsector->floorheight) - viewz; else - rw_midtexturemid = rw_midtextureback = min(frontsector->ceilingheight, backsector->ceilingheight) - viewz; + rw_midtexturemid = rw_midtextureback = std::min(frontsector->ceilingheight, backsector->ceilingheight) - viewz; } else if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) @@ -2324,7 +2406,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (dc.numlights >= dc.maxlights) { dc.maxlights = dc.numlights; - dc.lightlist = Z_Realloc(dc.lightlist, sizeof (*dc.lightlist) * dc.maxlights, PU_STATIC, NULL); + dc.lightlist = static_cast(Z_Realloc(dc.lightlist, sizeof (*dc.lightlist) * dc.maxlights, PU_STATIC, NULL)); } for (i = p = 0; i < dc.numlights; i++) @@ -2359,7 +2441,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) rlight->height = (centeryfrac>>4) - FixedMul(leftheight, rw_scale); rlight->heightstep = (centeryfrac>>4) - FixedMul(rightheight, ds_p->scale2); rlight->heightstep = (rlight->heightstep-rlight->height)/(range); - rlight->flags = light->flags; + rlight->flags = static_cast(light->flags); if (light->caster && light->caster->flags & FF_CUTSOLIDS) { @@ -2426,7 +2508,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) pixhighstep = (topfracend-pixhigh)/(range); // If the lowest part of a ceiling stretching down covers the entire screen - if (min(pixhigh, topfracend)>>HEIGHTBITS >= viewheight-1) + if (std::min(pixhigh, topfracend)>>HEIGHTBITS >= viewheight-1) g_walloffscreen = true; } @@ -2438,7 +2520,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) pixlowstep = (bottomfracend-pixlow)/(range); // If the highest part of a floor stretching up covers the entire screen - if ((max(pixlow, bottomfracend)+HEIGHTUNIT-1)>>HEIGHTBITS <= 0) + if ((std::max(pixlow, bottomfracend)+HEIGHTUNIT-1)>>HEIGHTBITS <= 0) g_walloffscreen = true; } -- 2.54.0 From b450abdf4d2976e289aea20798a51cb60e240657 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 7 Jun 2025 11:30:40 +0200 Subject: [PATCH 052/141] simplify R_ExpandPlane --- src/r_plane.cpp | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 9df1af06d..5e7aa8411 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -581,39 +581,19 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop) // // R_ExpandPlane // -// This function basically expands the visplane or I_Errors. +// This function basically expands the visplane. // The reason for this is that when creating 3D floor planes, there is no // need to create new ones with R_CheckPlane, because 3D floor planes // are created by subsector and there is no way a subsector can graphically // overlap. void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop) { - INT32 unionl, unionh; -// INT32 x; - // Don't expand polyobject planes here - we do that on our own. if (pl->polyobj) return; - if (start < pl->minx) - { - unionl = start; - } - else - { - unionl = pl->minx; - } - - if (stop > pl->maxx) - { - unionh = stop; - } - else - { - unionh = pl->maxx; - } - - pl->minx = unionl, pl->maxx = unionh; + if (pl->minx > start) pl->minx = start; + if (pl->maxx < stop) pl->maxx = stop; } // -- 2.54.0 From 221f2a956e0195e100b12247bb5f917edaeab6ca Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 7 Jun 2025 11:31:38 +0200 Subject: [PATCH 053/141] tiny optimizations --- src/r_plane.cpp | 10 +++-- src/r_things.cpp | 11 +++--- src/v_video.c | 98 ++++++++++++++++++++++++++++++------------------ 3 files changed, 73 insertions(+), 46 deletions(-) diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 5e7aa8411..4153590ba 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -601,11 +601,13 @@ void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop) // static void R_MakeSpans(void (*mapfunc)(drawspandata_t* ds, void(*spanfunc)(drawspandata_t*), INT32, INT32, INT32, boolean), spandrawfunc_t* localspanfunc, drawspandata_t* ds, INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2, boolean allow_parallel) { + const INT32 vidheight = vid.height; + // Alam: from r_splats's R_RenderFloorSplat - if (t1 >= vid.height) t1 = vid.height-1; - if (b1 >= vid.height) b1 = vid.height-1; - if (t2 >= vid.height) t2 = vid.height-1; - if (b2 >= vid.height) b2 = vid.height-1; + if (t1 >= vidheight) t1 = vidheight-1; + if (b1 >= vidheight) b1 = vidheight-1; + if (t2 >= vidheight) t2 = vidheight-1; + if (b2 >= vidheight) b2 = vidheight-1; if (x-1 >= vid.width) x = vid.width; // We want to draw N spans per subtask to ensure the work is diff --git a/src/r_things.cpp b/src/r_things.cpp index 8e592e6ed..5bd97070d 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -2230,6 +2230,7 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps visplane_t *plane; INT32 sintersect; fixed_t scale = 0; + const INT32 vidheight = vid.height; // Add the 3D floors, thicksides, and masked textures... for (ds = drawsegs + mask->drawsegs[1]; ds-- > drawsegs + mask->drawsegs[0];) @@ -2249,7 +2250,7 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps plane = ds->curline->polyseg->visplane; R_PlaneBounds(plane); - if (plane->low < 0 || plane->high > vid.height || plane->high > plane->low) + if (plane->low < 0 || plane->high > vidheight || plane->high > plane->low) ; else { @@ -2279,7 +2280,7 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps plane = ds->ffloorplanes[p]; R_PlaneBounds(plane); - if (plane->low < 0 || plane->high > vid.height || plane->high > plane->low || plane->polyobj) + if (plane->low < 0 || plane->high > vidheight || plane->high > plane->low || plane->polyobj) { ds->ffloorplanes[p] = NULL; continue; @@ -2319,7 +2320,7 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps plane = PolyObjects[i].visplane; R_PlaneBounds(plane); - if (plane->low < 0 || plane->high > vid.height || plane->high > plane->low) + if (plane->low < 0 || plane->high > vidheight || plane->high > plane->low) { PolyObjects[i].visplane = NULL; continue; @@ -2339,7 +2340,7 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps for (rover = vsprsortedhead.prev; rover != &vsprsortedhead; rover = rover->prev) { - if (rover->szt > vid.height || rover->sz < 0) + if (rover->szt > vidheight || rover->sz < 0) continue; sintersect = (rover->x1 + rover->x2) / 2; @@ -2356,7 +2357,7 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps // Effective height may be different for each comparison in the case of slopes planeobjectz = P_GetZAt(r2->plane->slope, rover->gx, rover->gy, r2->plane->height); - planecameraz = P_GetZAt(r2->plane->slope, viewx, viewy, r2->plane->height); + planecameraz = P_GetZAt(r2->plane->slope, viewx, viewy, r2->plane->height); if (rover->mobjflags & MF_NOCLIPHEIGHT) { diff --git a/src/v_video.c b/src/v_video.c index b9cab620c..247272dcb 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -656,10 +656,7 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca fixed_t pwidth; // patch width fixed_t offx = 0; // x offset - if (rendermode == render_none) - return; - - if (!patch) + if (rendermode == render_none || !patch) return; #ifdef HWRENDER @@ -679,12 +676,18 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca v_translevel = NULL; if (alphalevel || blendmode) { - if (alphalevel == 13) - alphalevel = hudminusalpha[hudtrans]; - else if (alphalevel == 14) - alphalevel = 10 - hudtrans; - else if (alphalevel == 15) - alphalevel = hudplusalpha[hudtrans]; + switch (alphalevel) + { + case 13: + alphalevel = hudminusalpha[hudtrans]; + break; + case 14: + alphalevel = (10 - hudtrans); + break; + case 15: + alphalevel = hudplusalpha[hudtrans]; + break; + } if (alphalevel >= 10) return; // invis @@ -972,10 +975,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_ UINT8 *desttop, *dest; const UINT8 *source, *deststop; - if (rendermode == render_none) - return; - - if (!patch) + if (rendermode == render_none || !patch) return; #ifdef HWRENDER @@ -991,12 +991,18 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_ v_translevel = NULL; if ((alphalevel = ((scrn & V_ALPHAMASK) >> V_ALPHASHIFT))) { - if (alphalevel == 13) - alphalevel = hudminusalpha[hudtrans]; - else if (alphalevel == 14) - alphalevel = 10 - hudtrans; - else if (alphalevel == 15) - alphalevel = hudplusalpha[hudtrans]; + switch (alphalevel) + { + case 13: + alphalevel = hudminusalpha[hudtrans]; + break; + case 14: + alphalevel = (10 - hudtrans); + break; + case 15: + alphalevel = hudplusalpha[hudtrans]; + break; + } if (alphalevel >= 10) return; // invis @@ -1239,6 +1245,7 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) else if (!(c & V_SNAPTOTOP)) y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2; } + if (c & V_SPLITSCREEN) y += (BASEVIDHEIGHT * dupy)/2; if (c & V_HORZSCREEN) @@ -1272,12 +1279,18 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) if (alphalevel) { - if (alphalevel == 13) - alphalevel = hudminusalpha[hudtrans]; - else if (alphalevel == 14) - alphalevel = 10 - hudtrans; - else if (alphalevel == 15) - alphalevel = hudplusalpha[hudtrans]; + switch (alphalevel) + { + case 13: + alphalevel = hudminusalpha[hudtrans]; + break; + case 14: + alphalevel = (10 - hudtrans); + break; + case 15: + alphalevel = hudplusalpha[hudtrans]; + break; + } if (alphalevel >= 10) return; // invis @@ -1354,7 +1367,7 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) if (rendermode == render_opengl) { UINT32 hwcolor = V_GetHWConsBackColor(); - HWR_DrawConsoleFill(x, y, w, h, hwcolor, c); // we still use the regular color stuff but only for flags. actual draw color is "hwcolor" for this. + HWR_DrawConsoleFill(x, y, w, h, hwcolor, c); // we still use the regular color stuff but only for flags. actual draw color is "hwcolor" for this. return; } #endif @@ -1416,12 +1429,18 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) if ((alphalevel = ((c & V_ALPHAMASK) >> V_ALPHASHIFT))) { - if (alphalevel == 13) - alphalevel = hudminusalpha[hudtrans]; - else if (alphalevel == 14) - alphalevel = 10 - hudtrans; - else if (alphalevel == 15) - alphalevel = hudplusalpha[hudtrans]; + switch (alphalevel) + { + case 13: + alphalevel = hudminusalpha[hudtrans]; + break; + case 14: + alphalevel = (10 - hudtrans); + break; + case 15: + alphalevel = hudplusalpha[hudtrans]; + break; + } if (alphalevel >= 10) return; // invis @@ -1429,13 +1448,18 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) c &= 255; - if (!alphalevel) { - for (v = 0; v < h; v++, dest += vid.width) { - for (u = 0; u < w; u++) { + if (!alphalevel) + { + for (v = 0; v < h; v++, dest += vid.width) + { + for (u = 0; u < w; u++) + { dest[u] = consolebgmap[dest[u]]; } } - } else { // mpc 12-04-2018 + } + else + { // mpc 12-04-2018 const UINT8 *fadetable = ((UINT8 *)transtables + ((alphalevel-1)<y) ? y : x w = clip(w,vid.width); -- 2.54.0 From 1bc18801c83963f25472997294602fa2413142a9 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 7 Jun 2025 11:32:46 +0200 Subject: [PATCH 054/141] cleanup the software drawers even more + unroll them looks pretty clean now, not sure if i want to port the templates, this is good enough for now --- src/r_draw_column.c | 20 ++- src/r_draw_span.c | 423 ++++++++++++++++++++++++++------------------ 2 files changed, 265 insertions(+), 178 deletions(-) diff --git a/src/r_draw_column.c b/src/r_draw_column.c index 764da111e..cca1f51c2 100644 --- a/src/r_draw_column.c +++ b/src/r_draw_column.c @@ -678,12 +678,14 @@ void R_DrawFogColumn(drawcolumndata_t* dc) // Zero length, column does not exceed a pixel. if (count < 0) + { return; + } -#ifdef RANGECHECK if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height) - I_Error("R_DrawFogColumn: %d to %d at %d", dc->yl, dc->yh, dc->x); -#endif + { + return; + } // Framebuffer destination address. dest = R_Address(dc->x, dc->yl); @@ -709,18 +711,20 @@ void R_DrawColumnShadowed(drawcolumndata_t* dc) register INT32 count; INT32 realyh, i, height, bheight = 0, solid = 0; - realyh = dc->yh; - count = dc->yh - dc->yl; // Zero length, column does not exceed a pixel. if (count < 0) + { return; + } -#ifdef RANGECHECK if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height) - I_Error("R_DrawColumnShadowed: %d to %d at %d", dc->yl, dc->yh, dc->x); -#endif + { + return; + } + + realyh = dc->yh; // This runs through the lightlist from top to bottom and cuts up the column accordingly. for (i = 0; i < dc->numlights; i++) diff --git a/src/r_draw_span.c b/src/r_draw_span.c index df4fba9fe..ce8ac392e 100644 --- a/src/r_draw_span.c +++ b/src/r_draw_span.c @@ -121,18 +121,20 @@ void R_DrawSpan(drawspandata_t* ds) */ void R_DrawTranslucentSpan(drawspandata_t* ds) { - fixed_t xposition; - fixed_t yposition; - fixed_t xstep, ystep; + uintptr_t xposition; + uintptr_t yposition; + uintptr_t xstep, ystep; register UINT32 bit; - UINT8 *source; - UINT8 *colormap; - register UINT8 *dest; - const UINT8 *deststop = vid.screens[0] + vid.rowbytes * vid.height; + UINT8 *restrict source = ds->source; + UINT8 *restrict colormap = ds->colormap; + UINT8 *restrict dest = R_Address(ds->x1, ds->y); + const UINT8 *restrict deststop = vid.screens[0] + vid.rowbytes * vid.height; register intptr_t count = (ds->x2 - ds->x1 + 1); + register const UINT8 *tranmap = ds->transmap; + xposition = ds->xfrac; yposition = ds->yfrac; xstep = ds->xstep; ystep = ds->ystep; @@ -146,12 +148,6 @@ void R_DrawTranslucentSpan(drawspandata_t* ds) xposition <<= ds->nflatshiftup; yposition <<= ds->nflatshiftup; xstep <<= ds->nflatshiftup; ystep <<= ds->nflatshiftup; - source = ds->source; - colormap = ds->colormap; - dest = R_Address(ds->x1, ds->y); - - register const UINT8 *tranmap = ds->transmap; - while (count >= 8) { // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't @@ -212,17 +208,22 @@ void R_DrawTranslucentSpan(drawspandata_t* ds) void R_DrawTranslucentWaterSpan(drawspandata_t* ds) { - UINT32 xposition; - UINT32 yposition; - UINT32 xstep, ystep; + uintptr_t xposition; + uintptr_t yposition; + uintptr_t xstep, ystep; register UINT32 bit; - UINT8 *source; - UINT8 *colormap; - register UINT8 *dest; - UINT8 *dsrc; + UINT8 *restrict source = ds->source; + UINT8 *restrict colormap = ds->colormap; + UINT8 *restrict dest = R_Address(ds->x1, ds->y); + const UINT8 *restrict dsrc = vid.screens[1] + (ds->y+ds->bgofs)*vid.width + ds->x1; - register intptr_t count; + register intptr_t count = (ds->x2 - ds->x1 + 1); + + register const UINT8 *tranmap = ds->transmap; + + xposition = ds->xfrac; yposition = (ds->yfrac + ds->waterofs); + xstep = ds->xstep; ystep = ds->ystep; // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest // can be used for the fraction part. This allows calculation of the memory address in the @@ -231,16 +232,8 @@ void R_DrawTranslucentWaterSpan(drawspandata_t* ds) // bit per power of two (obviously) // Ok, because I was able to eliminate the variable spot below, this function is now FASTER // than the original span renderer. Whodathunkit? - xposition = ds->xfrac << ds->nflatshiftup; yposition = (ds->yfrac + ds->waterofs) << ds->nflatshiftup; - xstep = ds->xstep << ds->nflatshiftup; ystep = ds->ystep << ds->nflatshiftup; - - source = ds->source; - colormap = ds->colormap; - dest = R_Address(ds->x1, ds->y); - dsrc = vid.screens[1] + (ds->y+ds->bgofs)*vid.width + ds->x1; - count = ds->x2 - ds->x1 + 1; - - register const UINT8 *tranmap = ds->transmap; + xposition <<= ds->nflatshiftup; yposition <<= ds->nflatshiftup; + xstep <<= ds->nflatshiftup; ystep <<= ds->nflatshiftup; while (count >= 8) { @@ -300,20 +293,241 @@ void R_DrawTranslucentWaterSpan(drawspandata_t* ds) } } +/** \brief The R_DrawSplat function + Just like R_DrawSpan, but skips transparent pixels. +*/ +void R_DrawSplat(drawspandata_t* ds) +{ + uintptr_t xposition; + uintptr_t yposition; + uintptr_t xstep, ystep; + register UINT32 bit; + register UINT32 val; + + const UINT8 *restrict source = ds->source; + const UINT8 *restrict colormap = ds->colormap; + UINT8 *restrict dest = R_Address(ds->x1, ds->y); + + register intptr_t count = (ds->x2 - ds->x1 + 1); + + xposition = ds->xfrac; yposition = ds->yfrac; + xstep = ds->xstep; ystep = ds->ystep; + + // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest + // can be used for the fraction part. This allows calculation of the memory address in the + // texture with two shifts, an OR and one AND. (see below) + // for texture sizes > 64 the amount of precision we can allow will decrease, but only by one + // bit per power of two (obviously) + // Ok, because I was able to eliminate the variable spot below, this function is now FASTER + // than the original span renderer. Whodathunkit? + xposition <<= ds->nflatshiftup; yposition <<= ds->nflatshiftup; + xstep <<= ds->nflatshiftup; ystep <<= ds->nflatshiftup; + + while (count >= 8) + { + // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't + // have the uber complicated math to calculate it now, so that was a memory write we didn't + // need! + // + // 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size) + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit &= MAXFLATBYTES; + val = source[bit]; + if (val != TRANSPARENTPIXEL) + dest[0] = colormap[val]; + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit &= MAXFLATBYTES; + val = source[bit]; + if (val != TRANSPARENTPIXEL) + dest[1] = colormap[val]; + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit &= MAXFLATBYTES; + val = source[bit]; + if (val != TRANSPARENTPIXEL) + dest[2] = colormap[val]; + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit &= MAXFLATBYTES; + val = source[bit]; + if (val != TRANSPARENTPIXEL) + dest[3] = colormap[val]; + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit &= MAXFLATBYTES; + val = source[bit]; + if (val != TRANSPARENTPIXEL) + dest[4] = colormap[val]; + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit &= MAXFLATBYTES; + val = source[bit]; + if (val != TRANSPARENTPIXEL) + dest[5] = colormap[val]; + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit &= MAXFLATBYTES; + val = source[bit]; + if (val != TRANSPARENTPIXEL) + dest[6] = colormap[val]; + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit &= MAXFLATBYTES; + val = source[bit]; + if (val != TRANSPARENTPIXEL) + dest[7] = colormap[val]; + xposition += xstep; + yposition += ystep; + + dest += 8; + count -= 8; + } + while (count--) + { + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + val = source[bit]; + if (val != TRANSPARENTPIXEL) + { + *dest = colormap[val]; + } + + dest++; + xposition += xstep; + yposition += ystep; + } +} + +/** \brief The R_DrawTranslucentSplat function + Just like R_DrawSplat, but is translucent! +*/ +void R_DrawTranslucentSplat(drawspandata_t* ds) +{ + uintptr_t xposition; + uintptr_t yposition; + uintptr_t xstep, ystep; + register UINT32 bit; + register UINT32 val; + + const UINT8 *restrict source = ds->source; + const UINT8 *restrict colormap = ds->colormap; + UINT8 *restrict dest = R_Address(ds->x1, ds->y); + + register intptr_t count = (ds->x2 - ds->x1 + 1); + + xposition = ds->xfrac; yposition = ds->yfrac; + xstep = ds->xstep; ystep = ds->ystep; + + // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest + // can be used for the fraction part. This allows calculation of the memory address in the + // texture with two shifts, an OR and one AND. (see below) + // for texture sizes > 64 the amount of precision we can allow will decrease, but only by one + // bit per power of two (obviously) + // Ok, because I was able to eliminate the variable spot below, this function is now FASTER + // than the original span renderer. Whodathunkit? + xposition <<= ds->nflatshiftup; yposition <<= ds->nflatshiftup; + xstep <<= ds->nflatshiftup; ystep <<= ds->nflatshiftup; + + while (count >= 8) + { + // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't + // have the uber complicated math to calculate it now, so that was a memory write we didn't + // need! + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + val = source[bit]; + if (val != TRANSPARENTPIXEL) + dest[0] = *(ds->transmap + (colormap[val] << 8) + dest[0]); + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + val = source[bit]; + if (val != TRANSPARENTPIXEL) + dest[1] = *(ds->transmap + (colormap[val] << 8) + dest[1]); + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + val = source[bit]; + if (val != TRANSPARENTPIXEL) + dest[2] = *(ds->transmap + (colormap[val] << 8) + dest[2]); + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + val = source[bit]; + if (val != TRANSPARENTPIXEL) + dest[3] = *(ds->transmap + (colormap[val] << 8) + dest[3]); + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + val = source[bit]; + if (val != TRANSPARENTPIXEL) + dest[4] = *(ds->transmap + (colormap[val] << 8) + dest[4]); + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + val = source[bit]; + if (val != TRANSPARENTPIXEL) + dest[5] = *(ds->transmap + (colormap[val] << 8) + dest[5]); + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + val = source[bit]; + if (val != TRANSPARENTPIXEL) + dest[6] = *(ds->transmap + (colormap[val] << 8) + dest[6]); + xposition += xstep; + yposition += ystep; + + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + val = source[bit]; + if (val != TRANSPARENTPIXEL) + dest[7] = *(ds->transmap + (colormap[val] << 8) + dest[7]); + xposition += xstep; + yposition += ystep; + + dest += 8; + count -= 8; + } + while (count--) + { + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + val = source[bit]; + if (val != TRANSPARENTPIXEL) + *dest = *(ds->transmap + (colormap[val] << 8) + *dest); + + dest++; + xposition += xstep; + yposition += ystep; + } +} + /** \brief The R_DrawFogSpan function Draws the actual span with fogging. */ void R_DrawFogSpan(drawspandata_t* ds) { - UINT8 *colormap; - register UINT8 *dest; + const UINT8 *restrict colormap = ds->colormap; + UINT8 *restrict dest = R_Address(ds->x1, ds->y); - register intptr_t count; - - colormap = ds->colormap; - dest = R_Address(ds->x1, ds->y); - - count = ds->x2 - ds->x1 + 1; + register intptr_t count = ds->x2 - ds->x1 + 1; while (count >= 4) { @@ -968,134 +1182,3 @@ void R_DrawSplat_Tilted(drawspandata_t* ds) } #endif } - -/** \brief The R_DrawSplat function - Just like R_DrawSpan, but skips transparent pixels. -*/ -void R_DrawSplat(drawspandata_t* ds) -{ - uintptr_t xposition; - uintptr_t yposition; - uintptr_t xstep, ystep; - register UINT32 bit; - - UINT8 *restrict source = ds->source; - UINT8 *restrict colormap = ds->colormap; - UINT8 *restrict dest = R_Address(ds->x1, ds->y); - - register intptr_t count = (ds->x2 - ds->x1 + 1); - size_t i; - UINT32 val; - - xposition = ds->xfrac; yposition = ds->yfrac; - xstep = ds->xstep; ystep = ds->ystep; - - // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest - // can be used for the fraction part. This allows calculation of the memory address in the - // texture with two shifts, an OR and one AND. (see below) - // for texture sizes > 64 the amount of precision we can allow will decrease, but only by one - // bit per power of two (obviously) - // Ok, because I was able to eliminate the variable spot below, this function is now FASTER - // than the original span renderer. Whodathunkit? - xposition <<= ds->nflatshiftup; yposition <<= ds->nflatshiftup; - xstep <<= ds->nflatshiftup; ystep <<= ds->nflatshiftup; - - while (count >= 8) - { - // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't - // have the uber complicated math to calculate it now, so that was a memory write we didn't - // need! - // - // 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size) - for (i = 0; i < 8; i++) - { - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); - bit &= MAXFLATBYTES; - val = source[bit]; - if (val != TRANSPARENTPIXEL) - dest[i] = colormap[val]; - - xposition += xstep; - yposition += ystep; - } - - dest += 8; - count -= 8; - } - while (count--) - { - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); - val = source[bit]; - if (val != TRANSPARENTPIXEL) - { - *dest = colormap[val]; - } - - dest++; - xposition += xstep; - yposition += ystep; - } -} - -/** \brief The R_DrawTranslucentSplat function - Just like R_DrawSplat, but is translucent! -*/ -void R_DrawTranslucentSplat(drawspandata_t* ds) -{ - uintptr_t xposition; - uintptr_t yposition; - uintptr_t xstep, ystep; - register UINT32 bit; - - UINT8 *restrict source = ds->source; - UINT8 *restrict colormap = ds->colormap; - UINT8 *restrict dest = R_Address(ds->x1, ds->y); - - register intptr_t count = (ds->x2 - ds->x1 + 1); - size_t i; - UINT8 val; - - xposition = ds->xfrac; yposition = ds->yfrac; - xstep = ds->xstep; ystep = ds->ystep; - - // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest - // can be used for the fraction part. This allows calculation of the memory address in the - // texture with two shifts, an OR and one AND. (see below) - // for texture sizes > 64 the amount of precision we can allow will decrease, but only by one - // bit per power of two (obviously) - // Ok, because I was able to eliminate the variable spot below, this function is now FASTER - // than the original span renderer. Whodathunkit? - xposition <<= ds->nflatshiftup; yposition <<= ds->nflatshiftup; - xstep <<= ds->nflatshiftup; ystep <<= ds->nflatshiftup; - - while (count >= 8) - { - // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't - // have the uber complicated math to calculate it now, so that was a memory write we didn't - // need! - for (i = 0; i < 8; i++) - { - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); - val = source[bit]; - if (val != TRANSPARENTPIXEL) - dest[i] = *(ds->transmap + (colormap[val] << 8) + dest[i]); - - xposition += xstep; - yposition += ystep; - } - - dest += 8; - count -= 8; - } - while (count--) - { - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); - val = source[bit]; - if (val != TRANSPARENTPIXEL) - *dest = *(ds->transmap + (colormap[val] << 8) + *dest); - - dest++; - xposition += xstep; - yposition += ystep; - } -} -- 2.54.0 From 9c6e32a1ab998ae79d1c1432dac9bab1455e35b0 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 7 Jun 2025 11:33:30 +0200 Subject: [PATCH 055/141] HACK: dont pass wflags to c++ silences some annoying compiler complaints lel --- src/Makefile | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Makefile b/src/Makefile index 11e6c238e..88bea5034 100644 --- a/src/Makefile +++ b/src/Makefile @@ -261,13 +261,14 @@ opts+=$(debug_opts) opts+=$(foreach v,$(passthru_opts),$(if $($(v)),-D$(v))) -opts+=$(WFLAGS) $(CPPFLAGS) $(CFLAGS) +opts+=$(CPPFLAGS) $(CFLAGS) libs+=$(LDFLAGS) -lstdc++ -lpthread asflags:=$(ASFLAGS) -x assembler-with-cpp -cxxopts:=$(opts) -cxxopts+=-std=c++17 -cxxopts+=$(CXXFLAGS) +cxxopts:=$(opts) $(CXXFLAGS) + +# pls dont pass the warning flags to ceepeepee +opts+=$(WFLAGS) cc=$(CC) cxx=$(CXX) -- 2.54.0 From 71237c5e11f392dae68f700ba5b33fcf5494c060 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 2 Nov 2020 02:33:49 -0800 Subject: [PATCH 056/141] Check that top of sprite is above plane or bottom is below This fixes slightly raised fofs drawing on top of sprites that should be in front of them. Previously would check that the bottom of the object was above the plane. Now also uses sprite offsets like the fof seg sorting does. --- src/r_things.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/r_things.cpp b/src/r_things.cpp index 5bd97070d..c0790bb70 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -2359,19 +2359,15 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps planeobjectz = P_GetZAt(r2->plane->slope, rover->gx, rover->gy, r2->plane->height); planecameraz = P_GetZAt(r2->plane->slope, viewx, viewy, r2->plane->height); - if (rover->mobjflags & MF_NOCLIPHEIGHT) + // bird: if any part of the sprite peeks in front the plane + if (planecameraz < viewz) { - //Objects with NOCLIPHEIGHT can appear halfway in. - if (planecameraz < viewz && rover->pz+(rover->thingheight/2) >= planeobjectz) - continue; - if (planecameraz > viewz && rover->pzt-(rover->thingheight/2) <= planeobjectz) + if (rover->gzt >= planeobjectz) continue; } - else + else if (planecameraz > viewz) { - if (planecameraz < viewz && rover->pz >= planeobjectz) - continue; - if (planecameraz > viewz && rover->pzt <= planeobjectz) + if (rover->gz <= planeobjectz) continue; } -- 2.54.0 From 9a00d30c0c3f56584c0e3beca66d2921d74d5cb5 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 5 Nov 2020 04:55:01 -0800 Subject: [PATCH 057/141] Do not factor height into sprite thickseg sorting --- src/r_things.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/r_things.cpp b/src/r_things.cpp index c0790bb70..6f8004e65 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -2401,7 +2401,7 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps } else if (r2->thickseg) { - fixed_t topplaneobjectz, topplanecameraz, botplaneobjectz, botplanecameraz; + //fixed_t topplaneobjectz, topplanecameraz, botplaneobjectz, botplanecameraz; if (rover->x1 > r2->thickseg->x2 || rover->x2 < r2->thickseg->x1) continue; @@ -2414,6 +2414,11 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps if (scale <= rover->sortscale) continue; + // bird: Always sort sprites behind segs. This helps the plane + // sorting above too. Basically if the sprite gets sorted behind + // the seg here, it will be behind the plane too, since planes + // are added after segs in the list. +#if 0 topplaneobjectz = P_GetFFloorTopZAt (r2->ffloor, rover->gx, rover->gy); topplanecameraz = P_GetFFloorTopZAt (r2->ffloor, viewx, viewy); botplaneobjectz = P_GetFFloorBottomZAt(r2->ffloor, rover->gx, rover->gy); @@ -2422,6 +2427,7 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps if ((topplanecameraz > viewz && botplanecameraz < viewz) || (topplanecameraz < viewz && rover->gzt < topplaneobjectz) || (botplanecameraz > viewz && rover->gz > botplaneobjectz)) +#endif { entry = R_CreateDrawNode(NULL); (entry->prev = r2->prev)->next = entry; -- 2.54.0 From 5eb4ed83918c2d77774f0cb38d47a2d5dba4c87f Mon Sep 17 00:00:00 2001 From: "James R." Date: Wed, 13 Sep 2023 00:27:06 -0700 Subject: [PATCH 058/141] R_FindPlane: fix offsets rotation overflow for non-sloped planes --- src/r_plane.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 4153590ba..5cb69f607 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -397,12 +397,20 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, { if (plangle != 0) { + // Must use 64-bit math to avoid an overflow! + INT64 vx = xoff + viewx; + INT64 vy = yoff - viewy; + // Add the view offset, rotated by the plane angle. - fixed_t cosinecomponent = FINECOSINE(plangle>>ANGLETOFINESHIFT); - fixed_t sinecomponent = FINESINE(plangle>>ANGLETOFINESHIFT); - fixed_t oldxoff = xoff; - xoff = FixedMul(xoff,cosinecomponent)+FixedMul(yoff,sinecomponent); - yoff = -FixedMul(oldxoff,sinecomponent)+FixedMul(yoff,cosinecomponent); + float ang = ANG2RAD(plangle); + float x = vx / (float)FRACUNIT; + float y = vy / (float)FRACUNIT; + + vx = (x * cos(ang) + y * sin(ang)) * FRACUNIT; + vy = (-x * sin(ang) + y * cos(ang)) * FRACUNIT; + + xoff = vx; + yoff = vy; } else { -- 2.54.0 From be528adea5abfaab21270fcbde77ed4299bfdd27 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 7 Jun 2025 10:21:25 +0100 Subject: [PATCH 059/141] thanks michaelsoft! --- src/core/thread_pool.cpp | 2 +- src/r_draw_span.c | 22 ++++++++++++++-------- src/sdl/i_system.c | 8 ++++---- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/core/thread_pool.cpp b/src/core/thread_pool.cpp index 6917aee93..11aa6f1bb 100644 --- a/src/core/thread_pool.cpp +++ b/src/core/thread_pool.cpp @@ -17,7 +17,7 @@ #include #include -#include +//#include //#include #include "../cxxutil.hpp" diff --git a/src/r_draw_span.c b/src/r_draw_span.c index ce8ac392e..90e082862 100644 --- a/src/r_draw_span.c +++ b/src/r_draw_span.c @@ -15,7 +15,13 @@ // SPANS // ========================================================================== +#ifdef _WIN32 +#include +#define local_for_thread static __thread +#else #include +#define local_for_thread thread_local static +#endif #define SPANSIZE 16 #define INVSPAN 0.0625f @@ -596,8 +602,8 @@ void R_DrawSpan_Tilted(drawspandata_t* ds) float endz, endu, endv; UINT32 stepu, stepv; register UINT32 bit; - thread_local static INT32 *tiltlighting = NULL; - thread_local static INT32 oldviewwidth = 0; + local_for_thread INT32 *tiltlighting = NULL; + local_for_thread INT32 oldviewwidth = 0; // dont realloc every frame pls thx if (tiltlighting == NULL || oldviewwidth != viewwidth) @@ -743,8 +749,8 @@ void R_DrawTranslucentSpan_Tilted(drawspandata_t* ds) float endz, endu, endv; UINT32 stepu, stepv; register UINT32 bit; - thread_local static INT32 *tiltlighting = NULL; - thread_local static INT32 oldviewwidth = 0; + local_for_thread INT32 *tiltlighting = NULL; + local_for_thread INT32 oldviewwidth = 0; // dont realloc every frame pls thx if (tiltlighting == NULL || oldviewwidth != viewwidth) @@ -891,8 +897,8 @@ void R_DrawTranslucentWaterSpan_Tilted(drawspandata_t* ds) float endz, endu, endv; UINT32 stepu, stepv; register UINT32 bit; - thread_local static INT32 *tiltlighting = NULL; - thread_local static INT32 oldviewwidth = 0; + local_for_thread INT32 *tiltlighting = NULL; + local_for_thread INT32 oldviewwidth = 0; // dont realloc every frame pls thx if (tiltlighting == NULL || oldviewwidth != viewwidth) @@ -1039,8 +1045,8 @@ void R_DrawSplat_Tilted(drawspandata_t* ds) float endz, endu, endv; UINT32 stepu, stepv; register UINT32 bit; - thread_local static INT32 *tiltlighting = NULL; - thread_local static INT32 oldviewwidth = 0; + local_for_thread INT32 *tiltlighting = NULL; + local_for_thread INT32 oldviewwidth = 0; // dont realloc every frame pls thx if (tiltlighting == NULL || oldviewwidth != viewwidth) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 84d0fb218..b74a3aa31 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -496,14 +496,13 @@ static void I_ReportSignal(int num, int coredumped) #ifndef NEWSIGNALHANDLER FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num) { - if (g_main_thread_id != std::this_thread::get_id()) + /*if (g_main_thread_id != std::this_thread::get_id()) { // Do not attempt any sort of recovery if this signal triggers off the main thread signal(num, SIG_DFL); raise(num); exit(-2); - } - + }*/ g_in_exiting_signal_handler = true; @@ -1569,7 +1568,8 @@ static void I_SetupMumble(void) if (!hMap) return; - mumble = static_cast(MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(*mumble))); + //mumble = static_cast(MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(*mumble))); + mumble = MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(*mumble)); if (!mumble) CloseHandle(hMap); #elif defined (HAVE_SHM) -- 2.54.0 From 0a936b3bba3f7d0535d773b00cb74d0403fa934e Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 7 Jun 2025 13:16:26 +0200 Subject: [PATCH 060/141] fix le sourcefile --- src/Sourcefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Sourcefile b/src/Sourcefile index 8c893fc68..4895adc1d 100644 --- a/src/Sourcefile +++ b/src/Sourcefile @@ -49,15 +49,15 @@ r_bsp.c r_data.c r_draw.c r_fps.c -r_main.c +r_main.cpp r_patch.c r_patchrotation.c -r_plane.c -r_segs.c +r_plane.cpp +r_segs.cpp r_skins.c r_sky.c r_splats.c -r_things.c +r_things.cpp r_portal.c p_ceilng.c p_enemy.c -- 2.54.0 From 2c937099d4620522061535a920c0acf04ca2771d Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 7 Jun 2025 13:31:36 +0200 Subject: [PATCH 061/141] this does nothing lel --- src/Makefile | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/Makefile b/src/Makefile index 88bea5034..bb46054e1 100644 --- a/src/Makefile +++ b/src/Makefile @@ -378,19 +378,6 @@ endif $(.)$(cc) -MM -MF $$@ -MT $(objdir)/$$*.o $(2) $$< endef -# dependency recipe template (C++) -# 1: source file suffix -# 2: extra flags to gcc -define _recipecxx = -$(depdir)/%.d : %.$(1) | $$$$(@D)/ -ifndef WINDOWSHELL -ifdef Echo_name - @printf '%-20.20s\r' $$< -endif -endif - $(.)$(cxx) -MM -MF $$@ -MT $(objdir)/$$*.o $(2) $$< -endef - $(eval $(call _recipe,c)) $(eval $(call _recipe,cpp)) $(eval $(call _recipe,s,$(asflags))) -- 2.54.0 From 1380a394c7e5ee65e7ed85fb6abba0b0a77f5fec Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 7 Jun 2025 13:32:06 +0200 Subject: [PATCH 062/141] remove duped declaration --- src/d_net.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/d_net.h b/src/d_net.h index 1b6cd905c..09825a615 100644 --- a/src/d_net.h +++ b/src/d_net.h @@ -43,8 +43,6 @@ extern SINT8 nodetoplayer4[MAXNETNODES]; // Say the numplayer for this node if a extern UINT8 playerpernode[MAXNETNODES]; // Used specially for splitscreen extern boolean nodeingame[MAXNETNODES]; // Set false as nodes leave game -extern boolean serverrunning; - void Net_AckTicker(void); // If reliable return true if packet sent, 0 else -- 2.54.0 From c508a7ea78f3c24ab2c20c0e2bf5ad3efcf6e436 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 7 Jun 2025 14:21:10 +0200 Subject: [PATCH 063/141] smol makefile stuff --- src/Makefile | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Makefile b/src/Makefile index bb46054e1..c7f524336 100644 --- a/src/Makefile +++ b/src/Makefile @@ -261,14 +261,11 @@ opts+=$(debug_opts) opts+=$(foreach v,$(passthru_opts),$(if $($(v)),-D$(v))) -opts+=$(CPPFLAGS) $(CFLAGS) -libs+=$(LDFLAGS) -lstdc++ -lpthread -asflags:=$(ASFLAGS) -x assembler-with-cpp - +opts+=$(WFLAGS) $(CPPFLAGS) $(CFLAGS) cxxopts:=$(opts) $(CXXFLAGS) -# pls dont pass the warning flags to ceepeepee -opts+=$(WFLAGS) +libs+=$(LDFLAGS) -lstdc++ -lpthread +asflags:=$(ASFLAGS) -x assembler-with-cpp cc=$(CC) cxx=$(CXX) @@ -289,6 +286,7 @@ ifndef SILENT ifndef MAKE_RESTARTS ifndef destructive $(shell $(CC) -v) +#$(shell $(CXX) -v) define flags = SHELL ..... $(SHELL) @@ -316,6 +314,7 @@ endif LD:=$(CC) cc:=$(cc) $(opts) +cxx:=$(cxx) $(cxxopts) ifdef UPX upx=$(UPX) $(UPX_OPTS) endif @@ -393,7 +392,7 @@ $(objdir)/%.$(1) : %.$(2) | $$$$(@D)/ endef $(eval $(call _recipe,o,c,$(cc) -c -o $$@ $$<)) -$(eval $(call _recipe,o,cpp,$(cxx) $(cxxopts) -c -o $$@ $$<)) +$(eval $(call _recipe,o,cpp,$(cxx) -c -o $$@ $$<)) $(eval $(call _recipe,o,s,$(cc) $(asflags) -c -o $$@ $$<)) $(eval $(call _recipe,res,rc,$(windres) -i $$< -o $$@)) -- 2.54.0 From cdd2d6323e48ade86a548e30fcc31589aab19508 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 7 Jun 2025 14:21:43 +0200 Subject: [PATCH 064/141] dont think we need this twice lel --- src/Makefile.d/dedicated.mk | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Makefile.d/dedicated.mk b/src/Makefile.d/dedicated.mk index fef452467..a421b465d 100644 --- a/src/Makefile.d/dedicated.mk +++ b/src/Makefile.d/dedicated.mk @@ -4,8 +4,6 @@ sources+=$(call List,dedicated/Sourcefile) opts+=-DDEDICATED -libs+=-lpthread - ifdef MINGW libs+=-mconsole endif -- 2.54.0 From 6374fda570a5d4ec1f850f00e0287611c5440afd Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 7 Jun 2025 20:05:48 +0200 Subject: [PATCH 065/141] convert i_system to cpp add missing exit for threading errors --- src/Makefile.d/sdl.mk | 2 +- src/byteptr.h | 2 + src/d_main.h | 8 +++ src/d_net.h | 8 +++ src/filesrch.h | 8 +++ src/g_game.h | 8 +++ src/i_joy.h | 8 +++ src/i_net.h | 8 +++ src/i_sound.h | 8 +++ src/i_threads.h | 8 +++ src/i_video.h | 8 +++ src/m_menu.h | 8 +++ src/m_misc.c | 9 ++++ src/m_misc.h | 8 +++ src/sdl/endtxt.h | 8 +++ src/sdl/{i_system.c => i_system.cpp} | 79 ++++++++++++++++++---------- src/sdl/mixer_sound.c | 2 +- src/sdl/sdlmain.h | 8 +++ 18 files changed, 167 insertions(+), 31 deletions(-) rename src/sdl/{i_system.c => i_system.cpp} (97%) diff --git a/src/Makefile.d/sdl.mk b/src/Makefile.d/sdl.mk index 9f2074d9d..c704a83eb 100644 --- a/src/Makefile.d/sdl.mk +++ b/src/Makefile.d/sdl.mk @@ -10,8 +10,8 @@ makedir:=$(makedir)/SDL -sources+=$(call List,sdl/Sourcefile) opts+=-DDIRECTFULLSCREEN -DHAVE_SDL +sources+=$(call List,sdl/Sourcefile) NOUPNP=1 diff --git a/src/byteptr.h b/src/byteptr.h index 0345038b8..205884acc 100644 --- a/src/byteptr.h +++ b/src/byteptr.h @@ -28,6 +28,7 @@ #define WRITEUINT8(p,b) do { UINT8 *p_tmp = (void *)p; const UINT8 tv = ( UINT8)(b); memcpy(p, &tv, sizeof( UINT8)); p_tmp++; p = (void *)p_tmp; } while (0) #define WRITESINT8(p,b) do { SINT8 *p_tmp = (void *)p; const SINT8 tv = ( UINT8)(b); memcpy(p, &tv, sizeof( UINT8)); p_tmp++; p = (void *)p_tmp; } while (0) #define WRITEINT16(p,b) do { INT16 *p_tmp = (void *)p; const INT16 tv = ( INT16)(b); memcpy(p, &tv, sizeof( INT16)); p_tmp++; p = (void *)p_tmp; } while (0) +#define WRITEINT16_2(p,b) do { INT16 *p_tmp = ( INT16 *)p; const INT16 tv = ( INT16)(b); memcpy(p, &tv, sizeof( INT16)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) // dumb hack for mumble #define WRITEUINT16(p,b) do { UINT16 *p_tmp = (void *)p; const UINT16 tv = ( UINT16)(b); memcpy(p, &tv, sizeof( UINT16)); p_tmp++; p = (void *)p_tmp; } while (0) #define WRITEINT32(p,b) do { INT32 *p_tmp = (void *)p; const INT32 tv = ( INT32)(b); memcpy(p, &tv, sizeof( INT32)); p_tmp++; p = (void *)p_tmp; } while (0) #define WRITEUINT32(p,b) do { UINT32 *p_tmp = (void *)p; const UINT32 tv = ( UINT32)(b); memcpy(p, &tv, sizeof( UINT32)); p_tmp++; p = (void *)p_tmp; } while (0) @@ -38,6 +39,7 @@ #define WRITEUINT8(p,b) do { UINT8 *p_tmp = ( UINT8 *)p; *p_tmp = ( UINT8)(b); p_tmp++; p = (void *)p_tmp; } while (0) #define WRITESINT8(p,b) do { SINT8 *p_tmp = ( SINT8 *)p; *p_tmp = ( SINT8)(b); p_tmp++; p = (void *)p_tmp; } while (0) #define WRITEINT16(p,b) do { INT16 *p_tmp = ( INT16 *)p; *p_tmp = ( INT16)(b); p_tmp++; p = (void *)p_tmp; } while (0) +#define WRITEINT16_2(p,b) do { INT16 *p_tmp = ( INT16 *)p; *p_tmp = ( INT16)(b); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) // dumb hack for mumble #define WRITEUINT16(p,b) do { UINT16 *p_tmp = ( UINT16 *)p; *p_tmp = ( UINT16)(b); p_tmp++; p = (void *)p_tmp; } while (0) #define WRITEINT32(p,b) do { INT32 *p_tmp = ( INT32 *)p; *p_tmp = ( INT32)(b); p_tmp++; p = (void *)p_tmp; } while (0) #define WRITEUINT32(p,b) do { UINT32 *p_tmp = ( UINT32 *)p; *p_tmp = ( UINT32)(b); p_tmp++; p = (void *)p_tmp; } while (0) diff --git a/src/d_main.h b/src/d_main.h index cb4049e54..1e2de572d 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -14,6 +14,10 @@ #ifndef __D_MAIN__ #define __D_MAIN__ +#ifdef __cplusplus +extern "C" { +#endif + #include "d_event.h" #include "w_wad.h" // for MAX_WADFILES @@ -90,4 +94,8 @@ const char *D_Home(void); // void D_StartTitle(void); +#ifdef __cplusplus +} // extern "C" +#endif + #endif //__D_MAIN__ diff --git a/src/d_net.h b/src/d_net.h index 09825a615..caeb3c83f 100644 --- a/src/d_net.h +++ b/src/d_net.h @@ -18,6 +18,10 @@ #ifndef __D_NET__ #define __D_NET__ +#ifdef __cplusplus +extern "C" { +#endif + // Max computers in a game // 127 is probably as high as this can go, because // SINT8 is used for nodes sometimes >:( @@ -63,4 +67,8 @@ void Net_SendAcks(INT32 node); void Net_WaitAllAckReceived(UINT32 timeout); const char *Net_GetPacketName(UINT8 packettype); +#ifdef __cplusplus +} // extern "C" +#endif + #endif diff --git a/src/filesrch.h b/src/filesrch.h index 76d5700c0..075895cb0 100644 --- a/src/filesrch.h +++ b/src/filesrch.h @@ -4,6 +4,10 @@ #ifndef __FILESRCH_H__ #define __FILESRCH_H__ +#ifdef __cplusplus +extern "C" { +#endif + #include "doomdef.h" #include "d_netfil.h" #include "m_menu.h" // MAXSTRINGLENGTH @@ -96,4 +100,8 @@ void closefilemenu(boolean validsize); void searchfilemenu(char *tempname); boolean preparefilemenu(boolean samedepth, boolean replayhut); +#ifdef __cplusplus +} // extern "C" +#endif + #endif // __FILESRCH_H__ diff --git a/src/g_game.h b/src/g_game.h index 5714097b2..e59ba0609 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -14,6 +14,10 @@ #ifndef __G_GAME__ #define __G_GAME__ +#ifdef __cplusplus +extern "C" { +#endif + #include "doomdef.h" #include "doomstat.h" #include "d_event.h" @@ -484,4 +488,8 @@ void G_AddMapToBuffer(INT16 map); void G_FixCamera(UINT8 view); +#ifdef __cplusplus +} // extern "C" +#endif + #endif diff --git a/src/i_joy.h b/src/i_joy.h index 01f29c2cd..20252b54d 100644 --- a/src/i_joy.h +++ b/src/i_joy.h @@ -13,6 +13,10 @@ #ifndef __I_JOY_H__ #define __I_JOY_H__ +#ifdef __cplusplus +extern "C" { +#endif + #include "g_input.h" /*! @@ -55,4 +59,8 @@ typedef struct JoyType_s JoyType_t; extern JoyType_t Joystick[MAXSPLITSCREENPLAYERS]; +#ifdef __cplusplus +} // extern "C" +#endif + #endif // __I_JOY_H__ diff --git a/src/i_net.h b/src/i_net.h index 098a6563d..70d8f0384 100644 --- a/src/i_net.h +++ b/src/i_net.h @@ -14,6 +14,10 @@ #ifndef __I_NET__ #define __I_NET__ +#ifdef __cplusplus +extern "C" { +#endif + #ifdef __GNUG__ #pragma interface #endif @@ -180,4 +184,8 @@ extern bannednode_t *bannednode; /// \brief Called by D_SRB2Main to be defined by extern network driver boolean I_InitNetwork(void); +#ifdef __cplusplus +} // extern "C" +#endif + #endif diff --git a/src/i_sound.h b/src/i_sound.h index 925be7596..9c6cf20d7 100644 --- a/src/i_sound.h +++ b/src/i_sound.h @@ -13,6 +13,10 @@ #ifndef __I_SOUND__ #define __I_SOUND__ +#ifdef __cplusplus +extern "C" { +#endif + #include "doomdef.h" #include "sounds.h" #include "command.h" @@ -241,4 +245,8 @@ boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void)); boolean I_FadeOutStopSong(UINT32 ms); boolean I_FadeInPlaySong(UINT32 ms, boolean looping); +#ifdef __cplusplus +} // extern "C" +#endif + #endif diff --git a/src/i_threads.h b/src/i_threads.h index 45a3dcc3e..17500aeca 100644 --- a/src/i_threads.h +++ b/src/i_threads.h @@ -14,6 +14,10 @@ #ifndef I_THREADS_H #define I_THREADS_H +#ifdef __cplusplus +extern "C" { +#endif + typedef void (*I_thread_fn)(void *userdata); typedef void * I_mutex; @@ -35,5 +39,9 @@ void I_hold_cond (I_cond *, I_mutex); void I_wake_one_cond (I_cond *); void I_wake_all_cond (I_cond *); +#ifdef __cplusplus +} // extern "C" +#endif + #endif/*I_THREADS_H*/ #endif/*HAVE_THREADS*/ diff --git a/src/i_video.h b/src/i_video.h index 70321d138..68042a654 100644 --- a/src/i_video.h +++ b/src/i_video.h @@ -14,6 +14,10 @@ #ifndef __I_VIDEO__ #define __I_VIDEO__ +#ifdef __cplusplus +extern "C" { +#endif + #include "doomtype.h" #ifdef __GNUG__ @@ -149,4 +153,8 @@ boolean UseScreenFBO(void); extern boolean downsample; #endif +#ifdef __cplusplus +} // extern "C" +#endif + #endif diff --git a/src/m_menu.h b/src/m_menu.h index d14d05cbe..4cea66d2c 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -15,6 +15,10 @@ #ifndef __X_MENU__ #define __X_MENU__ +#ifdef __cplusplus +extern "C" { +#endif + #include "r_skins.h" #include "d_event.h" #include "command.h" @@ -434,4 +438,8 @@ if (currentMenu == &menu)\ }\ } +#ifdef __cplusplus +} // extern "C" +#endif + #endif //__X_MENU__ diff --git a/src/m_misc.c b/src/m_misc.c index ac0266fa9..7f874c1cd 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -14,6 +14,10 @@ #ifdef __GNUC__ +#ifdef __cplusplus +extern "C" { +#endif + #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) // Ignore "argument might be clobbered by longjmp" warning in GCC // (if libpng is compiled with setjmp error handling) @@ -2191,3 +2195,8 @@ void M_MkdirEach(const char *path, int start, int mode) { M_MkdirEachUntil(path, start, -1, mode); } + + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/m_misc.h b/src/m_misc.h index 013da2235..d0a83c076 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -15,6 +15,10 @@ #ifndef __M_MISC__ #define __M_MISC__ +#ifdef __cplusplus +extern "C" { +#endif + #include "doomtype.h" #include "tables.h" @@ -110,4 +114,8 @@ FUNCMATH UINT8 M_CountBits(UINT32 num, UINT8 size); #include "w_wad.h" extern char configfile[MAX_WADPATH]; +#ifdef __cplusplus +} // extern "C" +#endif + #endif diff --git a/src/sdl/endtxt.h b/src/sdl/endtxt.h index 41f8e51ad..5691312b4 100644 --- a/src/sdl/endtxt.h +++ b/src/sdl/endtxt.h @@ -19,6 +19,14 @@ #ifndef __ENDTXT__ #define __ENDTXT__ +#ifdef __cplusplus +extern "C" { +#endif + void ShowEndTxt (void); +#ifdef __cplusplus +} // extern "C" +#endif + #endif diff --git a/src/sdl/i_system.c b/src/sdl/i_system.cpp similarity index 97% rename from src/sdl/i_system.c rename to src/sdl/i_system.cpp index b74a3aa31..4140d5f51 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.cpp @@ -204,6 +204,8 @@ static char returnWadPath[256]; #include "../byteptr.h" #endif +static std::thread::id g_main_thread_id; + INT32 numcontrollers = 0; #ifdef HAVE_LIBBACKTRACE @@ -211,11 +213,13 @@ INT32 numcontrollers = 0; // TODO - move this to some header file instead extern struct backtrace_state *bt_state; +typedef enum { + BTCRASH_SIGNAL, + BTCRASH_ERRORMSG, +} bt_crash_type_t; + typedef struct bt_crash_reason_s { - enum { - BTCRASH_SIGNAL, - BTCRASH_ERRORMSG, - } type; + bt_crash_type_t type; union { INT32 signal; @@ -496,13 +500,13 @@ static void I_ReportSignal(int num, int coredumped) #ifndef NEWSIGNALHANDLER FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num) { - /*if (g_main_thread_id != std::this_thread::get_id()) + if (g_main_thread_id != std::this_thread::get_id()) { // Do not attempt any sort of recovery if this signal triggers off the main thread signal(num, SIG_DFL); raise(num); exit(-2); - }*/ + } g_in_exiting_signal_handler = true; @@ -617,8 +621,8 @@ static void I_StartupConsole(void) signal(SIGTTIN, SIG_IGN); signal(SIGTTOU, SIG_IGN); - consolevent = !M_CheckParm("-noconsole"); - framebuffer = M_CheckParm("-framebuffer"); + consolevent = static_cast(!M_CheckParm("-noconsole")); + framebuffer = static_cast( M_CheckParm("-framebuffer")); if (framebuffer) consolevent = SDL_FALSE; @@ -658,8 +662,9 @@ static void I_StartupConsole(void) void I_GetConsoleEvents(void) { // we use this when sending back commands - event_t ev = {0,0,0,0}; + event_t ev = {}; char key = 0; + struct pollfd pfd = { .fd = STDIN_FILENO, @@ -865,6 +870,8 @@ static inline void I_ShutdownConsole(void){} // static void I_RegisterSignals (void) { + g_main_thread_id = std::this_thread::get_id(); + #ifdef SIGINT signal(SIGINT , quit_handler); #endif @@ -922,7 +929,7 @@ void I_OutputMsg(const char *fmt, ...) if (len == 0) return; - txt = malloc(len+1); + txt = static_cast(malloc(len+1)); va_start(argptr,fmt); vsprintf(txt, fmt, argptr); va_end(argptr); @@ -989,7 +996,7 @@ void I_OutputMsg(const char *fmt, ...) return; } - ReadConsoleOutputCharacter(co, oldLines, oldLength, coordNextWrite, &bytesWritten); + ReadConsoleOutputCharacter(co, (LPSTR)oldLines, oldLength, coordNextWrite, &bytesWritten); // Move to where we what to print - which is where we would've been, // had console input not been in the way, @@ -1212,7 +1219,7 @@ void I_ShutdownJoystick(UINT8 index) void I_GetJoystickEvents(UINT8 index) { - static event_t event = {0,0,0,0}; + static event_t event = {}; INT32 i = 0; UINT64 joyhats = 0; @@ -1565,11 +1572,12 @@ static void I_SetupMumble(void) { #ifdef WINMUMBLE HANDLE hMap = OpenFileMappingW(FILE_MAP_ALL_ACCESS, FALSE, L"MumbleLink"); + if (!hMap) return; - //mumble = static_cast(MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(*mumble))); - mumble = MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(*mumble)); + mumble = static_cast(MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(*mumble))); + if (!mumble) CloseHandle(hMap); #elif defined (HAVE_SHM) @@ -1579,10 +1587,11 @@ static void I_SetupMumble(void) snprintf(memname, 256, "/MumbleLink.%d", getuid()); shmfd = shm_open(memname, O_RDWR, S_IRUSR | S_IWUSR); - if(shmfd < 0) + if (shmfd < 0) return; - mumble = (mmap(NULL, sizeof(*mumble), PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0)); + mumble = static_cast(mmap(NULL, sizeof(*mumble), PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0)); + if (mumble == MAP_FAILED) mumble = NULL; #endif @@ -1597,7 +1606,8 @@ void I_UpdateMumble(const mobj_t *mobj, const listener_t listener) if (!mumble) return; - if(mumble->uiVersion != 2) { + if (mumble->uiVersion != 2) + { wcsncpy(mumble->name, L"SRB2Kart " VERSIONSTRINGW, 256); wcsncpy(mumble->description, L"Sonic Robo Blast 2 Kart with integrated Mumble Link support.", 2048); mumble->uiVersion = 2; @@ -1617,11 +1627,12 @@ void I_UpdateMumble(const mobj_t *mobj, const listener_t listener) { UINT8 *p = mumble->context; WRITEMEM(p, server_context, 8); - WRITEINT16(p, gamemap); + WRITEINT16_2(p, gamemap); mumble->context_len = (UINT32)(p - mumble->context); } - if (mobj) { + if (mobj) + { mumble->fAvatarPosition[0] = FIXED_TO_FLOAT(mobj->x) / MUMBLEUNIT; mumble->fAvatarPosition[1] = FIXED_TO_FLOAT(mobj->z) / MUMBLEUNIT; mumble->fAvatarPosition[2] = FIXED_TO_FLOAT(mobj->y) / MUMBLEUNIT; @@ -1776,8 +1787,8 @@ void I_SleepDuration(precise_t duration) #if defined(__linux__) || defined(__FreeBSD__) || defined(__HAIKU__) UINT64 precision = I_GetPrecisePrecision(); struct timespec ts = { - .tv_sec = duration / precision, - .tv_nsec = duration * 1000000000 / precision % 1000000000, + .tv_sec = static_cast<__time_t>(duration / precision), + .tv_nsec = static_cast<__syscall_slong_t>(duration * 1000000000 / precision % 1000000000), }; int status; do status = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, &ts); @@ -2004,6 +2015,12 @@ void I_Error(const char *error, ...) va_list argptr; char buffer[8192]; + if (std::this_thread::get_id() != g_main_thread_id) + { + // Do not attempt a graceful shutdown. Errors off the main thread are unresolvable. + exit(-2); + } + // recursive error detecting if (shutdowning) { @@ -2037,7 +2054,7 @@ void I_Error(const char *error, ...) // which should fail gracefully if it can't put a message box up // on the target system SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, - "SRB2Kart "VERSIONSTRING" Recursive Error", + "SRB2Kart " VERSIONSTRING " Recursive Error", buffer, NULL); W_Shutdown(); @@ -2086,7 +2103,7 @@ void I_Error(const char *error, ...) // which should fail gracefully if it can't put a message box up // on the target system SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, - "SRB2Kart "VERSIONSTRING" Error", + "SRB2Kart " VERSIONSTRING " Error", buffer, NULL); // Note that SDL_ShowSimpleMessageBox does *not* require SDL to be // initialized at the time, so calling it after SDL_Quit() is @@ -2124,7 +2141,6 @@ void I_AddExitFunc(void (*func)()) } } - // // Removes a function from the list that need to be called by // I_SystemShutdown(). @@ -2387,7 +2403,7 @@ const char *I_ClipboardPaste(void) */ static boolean isWadPathOk(const char *path) { - char *wad3path = (malloc(256)); + char *wad3path = static_cast(malloc(256)); if (!wad3path) return false; @@ -2559,7 +2575,7 @@ static const char *locateWad(void) I_OutputMsg(",HOME/" DEFAULTDIR); if ((envstr = I_GetEnv("HOME")) != NULL) { - char *tmp = malloc(strlen(envstr) + sizeof(PATHSEP) + sizeof(DEFAULTDIR)); + char *tmp = static_cast(malloc(strlen(envstr) + sizeof(PATHSEP) + sizeof(DEFAULTDIR))); strcpy(tmp, envstr); strcat(tmp, PATHSEP); strcat(tmp, DEFAULTDIR); @@ -2629,17 +2645,22 @@ const char *I_LocateWad(void) static long get_entry(const char* name, const char* buf) { long val; - char* hit = strstr(buf, name); - if (hit == NULL) { + const char* hit = strstr(buf, name); + + if (hit == NULL) + { return -1; } errno = 0; val = strtol(hit + strlen(name), NULL, 10); - if (errno != 0) { + + if (errno != 0) + { CONS_Alert(CONS_ERROR, M_GetText("get_entry: strtol() failed: %s\n"), strerror(errno)); return -1; } + return val; } #endif diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 9035e8241..9dbfdde15 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -276,7 +276,7 @@ void I_UpdateSound(void) // sorry. more asm needed. static Mix_Chunk *ds2chunk(void *stream) { - UINT16 ver,freq; + UINT16 ver, freq; UINT32 samples, i, newsamples; UINT8 *sound; diff --git a/src/sdl/sdlmain.h b/src/sdl/sdlmain.h index b0def402d..0c5bfaeff 100644 --- a/src/sdl/sdlmain.h +++ b/src/sdl/sdlmain.h @@ -19,6 +19,10 @@ #ifndef __sdlmain__ #define __sdlmain__ +#ifdef __cplusplus +extern "C" { +#endif + extern SDL_bool consolevent; extern SDL_bool framebuffer; @@ -84,4 +88,8 @@ void SDLforceUngrabMouse(void); // Needed for some WIN32 functions extern SDL_Window *window; +#ifdef __cplusplus +} // extern "C" +#endif + #endif -- 2.54.0 From 52f99dd9c1832b5d25782d5cb69b255a0d91412c Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 7 Jun 2025 20:04:43 +0200 Subject: [PATCH 066/141] fix span corruption due to wrong types being used i did not realise srb2 changed this at some point to use fixed_t --- src/r_draw_column.c | 10 ++--- src/r_draw_span.c | 102 ++++++++++++++++++++++---------------------- 2 files changed, 56 insertions(+), 56 deletions(-) diff --git a/src/r_draw_column.c b/src/r_draw_column.c index cca1f51c2..d6ae577f7 100644 --- a/src/r_draw_column.c +++ b/src/r_draw_column.c @@ -25,7 +25,7 @@ void R_DrawColumn(drawcolumndata_t* dc) { INT32 count; - UINT8 *restrict dest; + register UINT8 *restrict dest; intptr_t frac; intptr_t fracstep; @@ -145,7 +145,7 @@ void R_DrawColumn(drawcolumndata_t* dc) void R_Draw2sMultiPatchColumn(drawcolumndata_t* dc) { INT32 count; - UINT8 *restrict dest; + register UINT8 *restrict dest; intptr_t frac; intptr_t fracstep; @@ -284,7 +284,7 @@ void R_Draw2sMultiPatchColumn(drawcolumndata_t* dc) void R_Draw2sMultiPatchTranslucentColumn(drawcolumndata_t* dc) { INT32 count; - UINT8 *restrict dest; + register UINT8 *restrict dest; intptr_t frac; intptr_t fracstep; @@ -428,7 +428,7 @@ void R_Draw2sMultiPatchTranslucentColumn(drawcolumndata_t* dc) void R_DrawTranslucentColumn(drawcolumndata_t* dc) { register INT32 count; - UINT8 *restrict dest; + register UINT8 *restrict dest; intptr_t frac; intptr_t fracstep; @@ -528,7 +528,7 @@ void R_DrawTranslucentColumn(drawcolumndata_t* dc) void R_DrawTranslatedTranslucentColumn(drawcolumndata_t* dc) { register INT32 count; - UINT8 *restrict dest; + register UINT8 *restrict dest; intptr_t frac; intptr_t fracstep; diff --git a/src/r_draw_span.c b/src/r_draw_span.c index 90e082862..62cd306ef 100644 --- a/src/r_draw_span.c +++ b/src/r_draw_span.c @@ -34,9 +34,9 @@ */ void R_DrawSpan(drawspandata_t* ds) { - uintptr_t xposition; - uintptr_t yposition; - uintptr_t xstep, ystep; + UINT32 xposition; + UINT32 yposition; + UINT32 xstep, ystep; register UINT32 bit; UINT8 *restrict source = ds->source; @@ -69,42 +69,42 @@ void R_DrawSpan(drawspandata_t* ds) // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // have the uber complicated math to calculate it now, so that was a memory write we didn't // need! - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); dest[0] = colormap[source[bit]]; xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); dest[1] = colormap[source[bit]]; xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); dest[2] = colormap[source[bit]]; xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); dest[3] = colormap[source[bit]]; xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); dest[4] = colormap[source[bit]]; xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); dest[5] = colormap[source[bit]]; xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); dest[6] = colormap[source[bit]]; xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); dest[7] = colormap[source[bit]]; xposition += xstep; yposition += ystep; @@ -115,7 +115,7 @@ void R_DrawSpan(drawspandata_t* ds) while (count-- && dest <= deststop) { - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); *dest++ = colormap[source[bit]]; xposition += xstep; yposition += ystep; @@ -127,9 +127,9 @@ void R_DrawSpan(drawspandata_t* ds) */ void R_DrawTranslucentSpan(drawspandata_t* ds) { - uintptr_t xposition; - uintptr_t yposition; - uintptr_t xstep, ystep; + UINT32 xposition; + UINT32 yposition; + UINT32 xstep, ystep; register UINT32 bit; UINT8 *restrict source = ds->source; @@ -159,42 +159,42 @@ void R_DrawTranslucentSpan(drawspandata_t* ds) // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // have the uber complicated math to calculate it now, so that was a memory write we didn't // need! - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); dest[0] = *(tranmap + (colormap[source[bit]] << 8) + dest[0]); xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); dest[1] = *(tranmap + (colormap[source[bit]] << 8) + dest[1]); xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); dest[2] = *(tranmap + (colormap[source[bit]] << 8) + dest[2]); xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); dest[3] = *(tranmap + (colormap[source[bit]] << 8) + dest[3]); xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); dest[4] = *(tranmap + (colormap[source[bit]] << 8) + dest[4]); xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); dest[5] = *(tranmap + (colormap[source[bit]] << 8) + dest[5]); xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); dest[6] = *(tranmap + (colormap[source[bit]] << 8) + dest[6]); xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); dest[7] = *(tranmap + (colormap[source[bit]] << 8) + dest[7]); xposition += xstep; yposition += ystep; @@ -204,7 +204,7 @@ void R_DrawTranslucentSpan(drawspandata_t* ds) } while (count-- && dest <= deststop) { - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); *dest = *(tranmap + (colormap[source[bit]] << 8) + *dest); dest++; xposition += xstep; @@ -214,9 +214,9 @@ void R_DrawTranslucentSpan(drawspandata_t* ds) void R_DrawTranslucentWaterSpan(drawspandata_t* ds) { - uintptr_t xposition; - uintptr_t yposition; - uintptr_t xstep, ystep; + UINT32 xposition; + UINT32 yposition; + UINT32 xstep, ystep; register UINT32 bit; UINT8 *restrict source = ds->source; @@ -304,9 +304,9 @@ void R_DrawTranslucentWaterSpan(drawspandata_t* ds) */ void R_DrawSplat(drawspandata_t* ds) { - uintptr_t xposition; - uintptr_t yposition; - uintptr_t xstep, ystep; + UINT32 xposition; + UINT32 yposition; + UINT32 xstep, ystep; register UINT32 bit; register UINT32 val; @@ -336,7 +336,7 @@ void R_DrawSplat(drawspandata_t* ds) // need! // // 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size) - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); bit &= MAXFLATBYTES; val = source[bit]; if (val != TRANSPARENTPIXEL) @@ -344,7 +344,7 @@ void R_DrawSplat(drawspandata_t* ds) xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); bit &= MAXFLATBYTES; val = source[bit]; if (val != TRANSPARENTPIXEL) @@ -352,7 +352,7 @@ void R_DrawSplat(drawspandata_t* ds) xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); bit &= MAXFLATBYTES; val = source[bit]; if (val != TRANSPARENTPIXEL) @@ -360,7 +360,7 @@ void R_DrawSplat(drawspandata_t* ds) xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); bit &= MAXFLATBYTES; val = source[bit]; if (val != TRANSPARENTPIXEL) @@ -368,7 +368,7 @@ void R_DrawSplat(drawspandata_t* ds) xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); bit &= MAXFLATBYTES; val = source[bit]; if (val != TRANSPARENTPIXEL) @@ -376,7 +376,7 @@ void R_DrawSplat(drawspandata_t* ds) xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); bit &= MAXFLATBYTES; val = source[bit]; if (val != TRANSPARENTPIXEL) @@ -384,7 +384,7 @@ void R_DrawSplat(drawspandata_t* ds) xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); bit &= MAXFLATBYTES; val = source[bit]; if (val != TRANSPARENTPIXEL) @@ -392,7 +392,7 @@ void R_DrawSplat(drawspandata_t* ds) xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); bit &= MAXFLATBYTES; val = source[bit]; if (val != TRANSPARENTPIXEL) @@ -405,7 +405,7 @@ void R_DrawSplat(drawspandata_t* ds) } while (count--) { - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); val = source[bit]; if (val != TRANSPARENTPIXEL) { @@ -423,9 +423,9 @@ void R_DrawSplat(drawspandata_t* ds) */ void R_DrawTranslucentSplat(drawspandata_t* ds) { - uintptr_t xposition; - uintptr_t yposition; - uintptr_t xstep, ystep; + UINT32 xposition; + UINT32 yposition; + UINT32 xstep, ystep; register UINT32 bit; register UINT32 val; @@ -453,56 +453,56 @@ void R_DrawTranslucentSplat(drawspandata_t* ds) // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // have the uber complicated math to calculate it now, so that was a memory write we didn't // need! - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); val = source[bit]; if (val != TRANSPARENTPIXEL) dest[0] = *(ds->transmap + (colormap[val] << 8) + dest[0]); xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); val = source[bit]; if (val != TRANSPARENTPIXEL) dest[1] = *(ds->transmap + (colormap[val] << 8) + dest[1]); xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); val = source[bit]; if (val != TRANSPARENTPIXEL) dest[2] = *(ds->transmap + (colormap[val] << 8) + dest[2]); xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); val = source[bit]; if (val != TRANSPARENTPIXEL) dest[3] = *(ds->transmap + (colormap[val] << 8) + dest[3]); xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); val = source[bit]; if (val != TRANSPARENTPIXEL) dest[4] = *(ds->transmap + (colormap[val] << 8) + dest[4]); xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); val = source[bit]; if (val != TRANSPARENTPIXEL) dest[5] = *(ds->transmap + (colormap[val] << 8) + dest[5]); xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); val = source[bit]; if (val != TRANSPARENTPIXEL) dest[6] = *(ds->transmap + (colormap[val] << 8) + dest[6]); xposition += xstep; yposition += ystep; - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); val = source[bit]; if (val != TRANSPARENTPIXEL) dest[7] = *(ds->transmap + (colormap[val] << 8) + dest[7]); @@ -514,7 +514,7 @@ void R_DrawTranslucentSplat(drawspandata_t* ds) } while (count--) { - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); val = source[bit]; if (val != TRANSPARENTPIXEL) *dest = *(ds->transmap + (colormap[val] << 8) + *dest); -- 2.54.0 From 24ee56ce7ab55fd51168b7370c40cbd93caac38f Mon Sep 17 00:00:00 2001 From: Indev Date: Sat, 7 Jun 2025 23:15:55 +0300 Subject: [PATCH 067/141] ceepeepee 17 :3 --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index c7f524336..359ba3d80 100644 --- a/src/Makefile +++ b/src/Makefile @@ -262,7 +262,7 @@ opts+=$(debug_opts) opts+=$(foreach v,$(passthru_opts),$(if $($(v)),-D$(v))) opts+=$(WFLAGS) $(CPPFLAGS) $(CFLAGS) -cxxopts:=$(opts) $(CXXFLAGS) +cxxopts:=$(opts) $(CXXFLAGS) -std=c++17 libs+=$(LDFLAGS) -lstdc++ -lpthread asflags:=$(ASFLAGS) -x assembler-with-cpp -- 2.54.0 From 989a971d27c7617a783e771d6c1d4c3ce6111bc6 Mon Sep 17 00:00:00 2001 From: Indev Date: Sat, 7 Jun 2025 23:18:55 +0300 Subject: [PATCH 068/141] Fix 'C++11 requires a space between literal and string macro' warning --- src/sdl/i_system.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/sdl/i_system.cpp b/src/sdl/i_system.cpp index 4140d5f51..faf1bcbff 100644 --- a/src/sdl/i_system.cpp +++ b/src/sdl/i_system.cpp @@ -2529,43 +2529,43 @@ static const char *locateWad(void) // examine default dirs #ifdef DEFAULTWADLOCATION1 - I_OutputMsg(","DEFAULTWADLOCATION1); + I_OutputMsg("," DEFAULTWADLOCATION1); strcpy(returnWadPath, DEFAULTWADLOCATION1); if (isWadPathOk(returnWadPath)) return returnWadPath; #endif #ifdef DEFAULTWADLOCATION2 - I_OutputMsg(","DEFAULTWADLOCATION2); + I_OutputMsg("," DEFAULTWADLOCATION2); strcpy(returnWadPath, DEFAULTWADLOCATION2); if (isWadPathOk(returnWadPath)) return returnWadPath; #endif #ifdef DEFAULTWADLOCATION3 - I_OutputMsg(","DEFAULTWADLOCATION3); + I_OutputMsg("," DEFAULTWADLOCATION3); strcpy(returnWadPath, DEFAULTWADLOCATION3); if (isWadPathOk(returnWadPath)) return returnWadPath; #endif #ifdef DEFAULTWADLOCATION4 - I_OutputMsg(","DEFAULTWADLOCATION4); + I_OutputMsg("," DEFAULTWADLOCATION4); strcpy(returnWadPath, DEFAULTWADLOCATION4); if (isWadPathOk(returnWadPath)) return returnWadPath; #endif #ifdef DEFAULTWADLOCATION5 - I_OutputMsg(","DEFAULTWADLOCATION5); + I_OutputMsg("," DEFAULTWADLOCATION5); strcpy(returnWadPath, DEFAULTWADLOCATION5); if (isWadPathOk(returnWadPath)) return returnWadPath; #endif #ifdef DEFAULTWADLOCATION6 - I_OutputMsg(","DEFAULTWADLOCATION6); + I_OutputMsg("," DEFAULTWADLOCATION6); strcpy(returnWadPath, DEFAULTWADLOCATION6); if (isWadPathOk(returnWadPath)) return returnWadPath; #endif #ifdef DEFAULTWADLOCATION7 - I_OutputMsg(","DEFAULTWADLOCATION7); + I_OutputMsg("," DEFAULTWADLOCATION7); strcpy(returnWadPath, DEFAULTWADLOCATION7); if (isWadPathOk(returnWadPath)) return returnWadPath; @@ -2587,21 +2587,21 @@ static const char *locateWad(void) #endif #ifdef DEFAULTSEARCHPATH1 // find in /usr/local - I_OutputMsg(", in:"DEFAULTSEARCHPATH1); + I_OutputMsg(", in:" DEFAULTSEARCHPATH1); WadPath = searchWad(DEFAULTSEARCHPATH1); if (WadPath) return WadPath; #endif #ifdef DEFAULTSEARCHPATH2 // find in /usr/games - I_OutputMsg(", in:"DEFAULTSEARCHPATH2); + I_OutputMsg(", in:" DEFAULTSEARCHPATH2); WadPath = searchWad(DEFAULTSEARCHPATH2); if (WadPath) return WadPath; #endif #ifdef DEFAULTSEARCHPATH3 // find in ??? - I_OutputMsg(", in:"DEFAULTSEARCHPATH3); + I_OutputMsg(", in:" DEFAULTSEARCHPATH3); WadPath = searchWad(DEFAULTSEARCHPATH3); if (WadPath) return WadPath; -- 2.54.0 From 6e50710b25d849ddfb24e75cc3242114aa933423 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 7 Jun 2025 23:31:17 +0200 Subject: [PATCH 069/141] fix column data colormap shit in R_RenderThickSideRange too lazy to explain so https://git.do.srb2.org/KartKrew/RingRacers/-/commit/1ccd41c3dbb3132ce7467edf0c12c9d420b189f9 --- src/r_segs.cpp | 75 ++++++++++++++++++++++++++------------------------ 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/src/r_segs.cpp b/src/r_segs.cpp index dc59ade65..303b914bb 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -347,7 +347,6 @@ static void R_RenderMaskedSegLoop(drawcolumndata_t* dc, drawseg_t *drawseg, INT3 rlight->rcolormap = xwalllights[pindex]; }; - auto set_colormap_below_light = [&] { dc->colormap = rlight->rcolormap; @@ -935,43 +934,38 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf fixed_t height; fixed_t bheight = 0; INT32 solid = 0; - INT32 lighteffect = 0; auto set_light_vars = [&](INT32 k) { rlight = &dc->lightlist[k]; - lighteffect = !(dc->lightlist[k].flags & FF_NOSHADE); - if (lighteffect) + lightnum = rlight->lightnum; + + if (lightnum < 0) + xwalllights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + xwalllights = scalelight[LIGHTLEVELS-1]; + else + xwalllights = scalelight[lightnum]; + + pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; + + if (pindex >= MAXLIGHTSCALE) + pindex = MAXLIGHTSCALE-1; + + if (pfloor->flags & FF_FOG) { - lightnum = rlight->lightnum; - - if (lightnum < 0) - xwalllights = scalelight[0]; - else if (lightnum >= LIGHTLEVELS) - xwalllights = scalelight[LIGHTLEVELS-1]; + if (pfloor->master->frontsector->extra_colormap) + rlight->rcolormap = pfloor->master->frontsector->extra_colormap->colormap + (xwalllights[pindex] - colormaps); else - xwalllights = scalelight[lightnum]; - - pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; - - if (pindex >= MAXLIGHTSCALE) - pindex = MAXLIGHTSCALE-1; - - if (pfloor->flags & FF_FOG) - { - if (pfloor->master->frontsector->extra_colormap) - rlight->rcolormap = pfloor->master->frontsector->extra_colormap->colormap + (xwalllights[pindex] - colormaps); - else - rlight->rcolormap = xwalllights[pindex]; - } + rlight->rcolormap = xwalllights[pindex]; + } + else + { + if (rlight->extra_colormap) + rlight->rcolormap = rlight->extra_colormap->colormap + (xwalllights[pindex] - colormaps); else - { - if (rlight->extra_colormap) - rlight->rcolormap = rlight->extra_colormap->colormap + (xwalllights[pindex] - colormaps); - else - rlight->rcolormap = xwalllights[pindex]; - } + rlight->rcolormap = xwalllights[pindex]; } }; @@ -991,18 +985,18 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf { // Check if the current light effects the colormap/lightlevel rlight = &dc->lightlist[i]; - lighteffect = !(dc->lightlist[i].flags & FF_NOSHADE); + xwalllights = NULL; - if (lighteffect) - { + if (!(dc->lightlist[i].flags & FF_NOSHADE)) set_light_vars(i); - } solid = 0; // don't carry over solid-cutting flag from the previous light // Check if the current light can cut the current 3D floor. if (rlight->flags & FF_CUTSOLIDS && !(pfloor->flags & FF_EXTRA)) + { solid = 1; + } else if (rlight->flags & FF_CUTEXTRA && pfloor->flags & FF_EXTRA) { if (rlight->flags & FF_EXTRA) @@ -1029,12 +1023,16 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf if (height <= windowtop) { - if (lighteffect) + if (xwalllights) { set_colormap_below_light(); } + if (solid && windowtop < bheight) + { windowtop = bheight; + } + continue; } @@ -1049,20 +1047,23 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf { rlight = &dc->lightlist[i]; rlight->height += rlight->heightstep; + if (rlight->flags & FF_CUTLEVEL) rlight->botheight += rlight->botheightstep; } + continue; } // draw the texture colfunc_2s (dc, col); + if (solid) windowtop = bheight; else windowtop = windowbottom + 1; - if (lighteffect) + if (xwalllights) { set_colormap_below_light(); } @@ -1072,7 +1073,9 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf // draw the texture, if there is any space left if (windowtop < windowbottom) + { colfunc_2s (dc, col); + } spryscale += rw_scalestep; continue; -- 2.54.0 From a1cd19b02317de2a12d7a40796d73cad21a5a701 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 7 Jun 2025 23:54:03 +0200 Subject: [PATCH 070/141] make the fov dependant init stuff bit more safe and stuff --- src/r_main.cpp | 47 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/src/r_main.cpp b/src/r_main.cpp index 716e3401e..322dc43a9 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -888,6 +888,8 @@ void R_SetViewSize(void) setsizeneeded = true; } +static void R_SetupViewBuffers(void); + // // R_ExecuteSetViewSize // @@ -922,9 +924,7 @@ void R_ExecuteSetViewSize(void) centerxfrac = centerx<> ANGLETOFINESHIFT), viewmorph.zoomneeded); if (splitscreen == 1) // Splitscreen FOV should be adjusted to maintain expected vertical view fovtan = 17*fovtan/10; - // this is only used for planes rendering in software mode - INT32 j = viewheight*16; - - for (INT32 i = 0; i < j; i++) - { - fixed_t dy = (i - viewheight*8)< Date: Sun, 8 Jun 2025 00:24:53 +0200 Subject: [PATCH 071/141] do NOT use Z_ functions in threaded stuff shit dies --- src/r_draw_span.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/r_draw_span.c b/src/r_draw_span.c index 62cd306ef..54400fac4 100644 --- a/src/r_draw_span.c +++ b/src/r_draw_span.c @@ -608,7 +608,7 @@ void R_DrawSpan_Tilted(drawspandata_t* ds) // dont realloc every frame pls thx if (tiltlighting == NULL || oldviewwidth != viewwidth) { - tiltlighting = Z_Realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth, PU_STATIC, NULL); + tiltlighting = realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth); oldviewwidth = viewwidth; } @@ -755,7 +755,7 @@ void R_DrawTranslucentSpan_Tilted(drawspandata_t* ds) // dont realloc every frame pls thx if (tiltlighting == NULL || oldviewwidth != viewwidth) { - tiltlighting = Z_Realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth, PU_STATIC, NULL); + tiltlighting = realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth); oldviewwidth = viewwidth; } @@ -903,7 +903,7 @@ void R_DrawTranslucentWaterSpan_Tilted(drawspandata_t* ds) // dont realloc every frame pls thx if (tiltlighting == NULL || oldviewwidth != viewwidth) { - tiltlighting = Z_Realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth, PU_STATIC, NULL); + tiltlighting = realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth); oldviewwidth = viewwidth; } @@ -1051,7 +1051,7 @@ void R_DrawSplat_Tilted(drawspandata_t* ds) // dont realloc every frame pls thx if (tiltlighting == NULL || oldviewwidth != viewwidth) { - tiltlighting = Z_Realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth, PU_STATIC, NULL); + tiltlighting = realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth); oldviewwidth = viewwidth; } -- 2.54.0 From 9583bed718ddece13fb77b89902edd1c479b5371 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 8 Jun 2025 00:43:03 +0200 Subject: [PATCH 072/141] =?UTF-8?q?fix=20da=20rippled=20w=C3=B6ter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit i hate fixed point maths lmao --- src/r_plane.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 5cb69f607..5598a0d3d 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -149,7 +149,7 @@ static fixed_t R_CalculateRippleOffset(drawspandata_t* ds, INT32 y) { fixed_t distance = FixedMul(ds->planeheight, yslope[y]); const INT32 yay = (ds->planeripple.offset + (distance>>9)) & 8191; - return FixedDiv(FINESINE(yay), (1<<12) + (distance>>11))>>FRACBITS; + return FixedDiv(FINESINE(yay), (1<<12) + (distance>>11)); } static void R_CalculatePlaneRipple(drawspandata_t* ds, angle_t angle) @@ -221,6 +221,11 @@ static void R_MapPlane(drawspandata_t *ds, spandrawfunc_t *localspanfunc, INT32 ds->ystep = FixedMul(distance, baseyscale); } + // [RH] Instead of using the xtoviewangle array, I calculated the fractional values + // at the middle of the screen, then used the calculated ds_xstep and ds_ystep + // to step from those to the proper texture coordinate to start drawing at. + // That way, the texture coordinate is always calculated by its position + // on the screen and not by its position relative to the edge of the visplane. ds->xfrac = ds->xoffs + FixedMul(planecos, distance) + (x1 - centerx) * ds->xstep; ds->yfrac = ds->yoffs - FixedMul(planesin, distance) + (x1 - centerx) * ds->ystep; @@ -232,6 +237,7 @@ static void R_MapPlane(drawspandata_t *ds, spandrawfunc_t *localspanfunc, INT32 ds->xfrac += ds->planeripple.xfrac; ds->yfrac += ds->planeripple.yfrac; + ds->bgofs >>= FRACBITS; if ((y + ds->bgofs) >= viewheight) ds->bgofs = viewheight-y-1; @@ -274,6 +280,8 @@ static void R_MapTiltedPlane(drawspandata_t *ds, spandrawfunc_t *localspanfunc, R_CalculatePlaneRipple(ds, ds->currentplane->viewangle + ds->currentplane->plangle); R_SetSlopePlaneVectors(ds, ds->currentplane, y, (ds->xoffs + ds->planeripple.xfrac), (ds->yoffs + ds->planeripple.yfrac)); + ds->bgofs >>= FRACBITS; + if ((y + ds->bgofs) >= viewheight) ds->bgofs = viewheight-y-1; if ((y + ds->bgofs) < 0) -- 2.54.0 From 9d342d0f3df963b4cb915b92739874c05f58a151 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 8 Jun 2025 17:23:42 +0200 Subject: [PATCH 073/141] fix lightlist memory leak not sure if we need to copy over the old shit, but this seems to work aswell --- src/p_setup.c | 3 --- src/r_defs.h | 3 --- src/r_segs.cpp | 20 ++++++++------------ 3 files changed, 8 insertions(+), 18 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index a69390961..fc4f6d892 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -580,9 +580,6 @@ static void P_LoadRawSegs(UINT8 *data) else li->backsector = 0; - li->numlights = 0; - li->rlights = NULL; - P_UpdateSegLightOffset(li); } } diff --git a/src/r_defs.h b/src/r_defs.h index abb875fcf..c130547db 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -558,9 +558,6 @@ typedef struct seg_s float flength; // length of the seg, used by hardware renderer #endif - // Why slow things down by calculating lightlists for every thick side? - size_t numlights; - r_lightlist_t *rlights; polyobj_t *polyseg; boolean dontrenderme; diff --git a/src/r_segs.cpp b/src/r_segs.cpp index 303b914bb..ab1e67070 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -31,6 +31,9 @@ #include "core/memory.h" #include "core/thread_pool.h" +#define HEIGHTBITS 12 +#define HEIGHTUNIT (1<numlights = frontsector->numlights; - if (dc->numlights >= dc->maxlights) + if (dc->numlights > dc->maxlights) { dc->maxlights = dc->numlights; - dc->lightlist = static_cast(Z_Realloc(dc->lightlist, sizeof (*dc->lightlist) * dc->maxlights, PU_STATIC, NULL)); + dc->lightlist = static_cast(Z_Frame_Alloc(sizeof (*dc->lightlist) * dc->maxlights)); } for (i = 0; i < dc->numlights; i++) @@ -666,10 +669,10 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf { dc->numlights = frontsector->numlights; - if (dc->numlights >= dc->maxlights) + if (dc->numlights > dc->maxlights) { dc->maxlights = dc->numlights; - dc->lightlist = static_cast(Z_Realloc(dc->lightlist, sizeof (*dc->lightlist) * dc->maxlights, PU_STATIC, NULL)); + dc->lightlist = static_cast(Z_Frame_Alloc(sizeof (*dc->lightlist) * dc->maxlights)); } for (i = p = 0; i < dc->numlights; i++) @@ -1136,8 +1139,6 @@ static inline void R_ExpandPlaneY(visplane_t *pl, INT32 x, INT16 top, INT16 bott // textures. // CALLED: CORE LOOPING ROUTINE. // -#define HEIGHTBITS 12 -#define HEIGHTUNIT (1<numlights; dc.maxlights = dc.numlights; - - if (dc.numlights >= dc.maxlights) - { - dc.maxlights = dc.numlights; - dc.lightlist = static_cast(Z_Realloc(dc.lightlist, sizeof (*dc.lightlist) * dc.maxlights, PU_STATIC, NULL)); - } + dc.lightlist = static_cast(Z_Frame_Alloc(sizeof(*dc.lightlist) * dc.maxlights)); for (i = p = 0; i < dc.numlights; i++) { -- 2.54.0 From 22e65cdda81f699c0b18c32b01c77fea2145b8c3 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 8 Jun 2025 19:15:15 +0200 Subject: [PATCH 074/141] readd portalcullsector + sprite clipping improvements with portals --- src/hardware/hw_main.c | 11 ++++++ src/hardware/hw_portal.c | 6 +++- src/r_bsp.c | 10 ++++++ src/r_main.cpp | 30 +++++----------- src/r_portal.c | 6 ++-- src/r_portal.h | 1 + src/r_things.cpp | 78 ++++++++++++++++++++++++++-------------- src/r_things.h | 3 +- 8 files changed, 93 insertions(+), 52 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index cbd6cdece..06e15c1a0 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3199,6 +3199,17 @@ static void HWR_RenderBSPNode(INT32 bspnum) bspnum = bsp->children[side^1]; } + // PORTAL CULLING + if (portalcullsector) + { + // skip all subsectors encountered before the portal + // destination's front sector + if (portalcullsector != subsectors[bspnum & ~NF_SUBSECTOR].sector) + return; + else + portalcullsector = NULL; + } + // e6y: support for extended nodes HWR_Subsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR); } diff --git a/src/hardware/hw_portal.c b/src/hardware/hw_portal.c index 53d6f57e3..fe643df13 100644 --- a/src/hardware/hw_portal.c +++ b/src/hardware/hw_portal.c @@ -62,8 +62,11 @@ static gl_portal_t* HWR_Portal_Add (seg_t *seg) void HWR_FreePortalList(gl_portallist_t freelist) { + portalcullsector = NULL; + // free memory from portal list allocated by calls to Add2Lines gl_portal_t *gl_portal_temp = freelist.base; + while (gl_portal_temp) { gl_portal_t *nextportal = gl_portal_temp->next; @@ -123,11 +126,12 @@ void HWR_PortalFrame(gl_portal_t* portal) if (portal->clipline != -1) { portalclipline = &lines[portal->clipline]; - viewsector = portalclipline->frontsector; + portalcullsector = viewsector = portalclipline->frontsector; } else { portalclipline = NULL; + portalcullsector = NULL; viewsector = R_PointInSubsector(viewx, viewy)->sector; } } diff --git a/src/r_bsp.c b/src/r_bsp.c index 0dfba63e1..7fb61b882 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -364,8 +364,10 @@ static void R_AddLine(seg_t *line) { // Find the other side! INT32 line2 = P_FindSpecialLineFromTag(40, line->linedef->tag, -1); + if (line->linedef == &lines[line2]) line2 = P_FindSpecialLineFromTag(40, line->linedef->tag, line2); + if (line2 >= 0) // found it! { Portal_Add2Lines(line->linedef-lines, line2, x1, x2); // Remember the lines for later rendering @@ -1202,5 +1204,13 @@ void R_RenderBSPNode(INT32 bspnum) bspnum = bsp->children[side^1]; } + // PORTAL CULLING + if (portalcullsector) + { + if (subsectors[bspnum & ~NF_SUBSECTOR].sector != portalcullsector) + return; + portalcullsector = NULL; + } + R_Subsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR); } diff --git a/src/r_main.cpp b/src/r_main.cpp index 322dc43a9..3f77e0c08 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1291,8 +1291,8 @@ static void R_PortalFrame(portal_t *portal) viewz = portal->viewz; viewangle = portal->viewangle; - // viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT); - // viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT); + //viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT); + //viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT); portalclipstart = portal->start; portalclipend = portal->end; @@ -1300,11 +1300,12 @@ static void R_PortalFrame(portal_t *portal) if (portal->clipline != -1) { portalclipline = &lines[portal->clipline]; - viewsector = portalclipline->frontsector; + viewsector = portalcullsector = portalclipline->frontsector; } else { portalclipline = NULL; + portalcullsector = NULL; viewsector = R_PointInSubsector(viewx, viewy)->sector; } } @@ -1415,16 +1416,10 @@ void R_RenderPlayerView(player_t *player) R_ClearDrawSegs(); R_ClearPlanes(); R_ClearSprites(); -#ifdef FLOORSPLATS - R_ClearVisibleFloorSplats(); -#endif R_RenderViewpoint(&masks[nummasks - 1], false); - R_ClipSprites(); + R_ClipSprites(drawsegs, NULL); R_DrawPlanes(); -#ifdef FLOORSPLATS - R_DrawVisibleFloorSplats(); -#endif // well sometimes synchronization is off and may result in some visual glitching, oh well R_DrawMasked(masks, nummasks); } @@ -1453,9 +1448,6 @@ void R_RenderPlayerView(player_t *player) } R_ClearDrawSegs(); R_ClearSprites(); -#ifdef FLOORSPLATS - R_ClearVisibleFloorSplats(); -#endif // check for new console commands. NetUpdate(); @@ -1463,10 +1455,9 @@ void R_RenderPlayerView(player_t *player) ps_numbspcalls.value.i = ps_numpolyobjects.value.i = ps_numdrawnodes.value.i = 0; PS_START_TIMING(ps_bsptime); R_RenderViewpoint(&masks[nummasks - 1], true); - PS_STOP_TIMING(ps_bsptime); PS_START_TIMING(ps_sw_spritecliptime); - R_ClipSprites(); + R_ClipSprites(drawsegs, NULL); PS_STOP_TIMING(ps_sw_spritecliptime); ps_numsprites.value.i = numvisiblesprites; @@ -1497,14 +1488,14 @@ void R_RenderPlayerView(player_t *player) validcount++; - // Render the BSP from the new viewpoint, and clip masks = static_cast(realloc(masks, (++nummasks)*sizeof(maskcount_t))); // Render the BSP from the new viewpoint, and clip // any sprites with the new clipsegs and window. - R_RenderViewpoint(&masks[nummasks - 1], true); - R_ClipSprites(); + R_RenderViewpoint(&masks[nummasks - 1], nummasks - 1); + + R_ClipSprites(ds_p - (masks[nummasks - 1].drawsegs[1] - masks[nummasks - 1].drawsegs[0]), portal); Portal_Remove(portal); } @@ -1514,9 +1505,6 @@ void R_RenderPlayerView(player_t *player) PS_START_TIMING(ps_sw_planetime); R_DrawPlanes(); PS_STOP_TIMING(ps_sw_planetime); -#ifdef FLOORSPLATS - R_DrawVisibleFloorSplats(); -#endif // draw mid texture and sprite // And now 3D floors/sides! PS_START_TIMING(ps_sw_maskedtime); diff --git a/src/r_portal.c b/src/r_portal.c index e5a431c6e..3f3b6c185 100644 --- a/src/r_portal.c +++ b/src/r_portal.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 KART //----------------------------------------------------------------------------- -// Copyright (C) 2024 by Kart Krew. +// Copyright (C) 2025 by Kart Krew. // Copyright (C) 2020 by Sonic Team Junior. // Copyright (C) 2000 by DooM Legacy Team. // Copyright (C) 1996 by id Software, Inc. @@ -27,6 +27,7 @@ UINT8 portalrender; /**< When rendering a portal, it establishes the depth of portal_t *portal_base, *portal_cap; line_t *portalclipline; +sector_t *portalcullsector; INT32 portalclipstart, portalclipend; portal_t *g_portal; // is curline a portal seg? @@ -37,7 +38,6 @@ void Portal_InitList (void) portal_base = portal_cap = NULL; } - /** Store the clipping window for a portal in its given range. * * The window is copied from the current window at the time @@ -64,7 +64,6 @@ static void Portal_ClipRange (portal_t* portal) } } - /** Apply the clipping window from a portal. */ void Portal_ClipApply (const portal_t* portal) @@ -134,6 +133,7 @@ static portal_t* Portal_Add (const INT16 x1, const INT16 x2) void Portal_Remove (portal_t* portal) { + portalcullsector = NULL; portal_base = portal->next; Z_Free(portal->ceilingclip); Z_Free(portal->floorclip); diff --git a/src/r_portal.h b/src/r_portal.h index 62312da54..223dd83be 100644 --- a/src/r_portal.h +++ b/src/r_portal.h @@ -49,6 +49,7 @@ extern portal_t* portal_cap; extern UINT8 portalrender; extern line_t *portalclipline; +extern sector_t *portalcullsector; extern INT32 portalclipstart, portalclipend; void Portal_InitList (void); diff --git a/src/r_things.cpp b/src/r_things.cpp index 6f8004e65..ba2fa82a5 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -2600,7 +2600,7 @@ static boolean R_CheckSpriteVisible(vissprite_t *spr, INT32 x1, INT32 x2) // R_ClipVisSprite // Clips vissprites without drawing, so that portals can work. -Red -static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2) +static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* portal) { drawseg_t *ds; INT32 x; @@ -2639,31 +2639,34 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2) ds = curr->user; - if (ds->portalpass > 0 && ds->portalpass <= portalrender) - continue; // is a portal + if (ds->portalpass != 66) // unused? + { + if (ds->portalpass > 0 && ds->portalpass <= portalrender) + continue; // is a portal + + if (ds->scale1 > ds->scale2) + { + lowscale = ds->scale2; + scale = ds->scale1; + } + else + { + lowscale = ds->scale1; + scale = ds->scale2; + } + + if (scale < spr->sortscale || + (lowscale < spr->sortscale && + !R_PointOnSegSide (spr->gx, spr->gy, ds->curline))) + { + // seg is behind sprite + continue; + } + } r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1; r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2; - if (ds->scale1 > ds->scale2) - { - lowscale = ds->scale2; - scale = ds->scale1; - } - else - { - lowscale = ds->scale1; - scale = ds->scale2; - } - - if (scale < spr->sortscale || - (lowscale < spr->sortscale && - !R_PointOnSegSide (spr->gx, spr->gy, ds->curline))) - { - // seg is behind sprite - continue; - } - // clip this piece of the sprite silhouette = ds->silhouette; @@ -2788,11 +2791,34 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2) if (!R_CheckSpriteVisible(spr, x1, x2)) spr->cut = static_cast(spr->cut | SC_NOTVISIBLE); } + + if (portal) + { + INT32 start_index = std::max(portal->start, x1); + INT32 end_index = std::min(portal->start + portal->end - portal->start, x2); + for (x = x1; x < start_index; x++) + { + spr->clipbot[x] = -1; + spr->cliptop[x] = -1; + } + for (x = start_index; x <= end_index; x++) + { + if (spr->clipbot[x] > portal->floorclip[x - portal->start]) + spr->clipbot[x] = portal->floorclip[x - portal->start]; + if (spr->cliptop[x] < portal->ceilingclip[x - portal->start]) + spr->cliptop[x] = portal->ceilingclip[x - portal->start]; + } + for (x = end_index + 1; x <= x2; x++) + { + spr->clipbot[x] = -1; + spr->cliptop[x] = -1; + } + } } -void R_ClipSprites(void) +void R_ClipSprites(drawseg_t* dsstart, portal_t* portal) { - const size_t maxdrawsegs = ds_p - drawsegs; + const size_t maxdrawsegs = ds_p - dsstart; const INT32 cx = viewwidth / 2; drawseg_t* ds; INT32 i; @@ -2825,7 +2851,7 @@ void R_ClipSprites(void) } } - for (ds = ds_p; ds-- > drawsegs;) + for (ds = ds_p; ds-- > dsstart;) { if (ds->silhouette || ds->maskedtexturecol) { @@ -2879,7 +2905,7 @@ void R_ClipSprites(void) drawsegs_xrange_count = drawsegs_xranges[0].count; } - R_ClipVisSprite(spr, spr->x1, spr->x2); + R_ClipVisSprite(spr, spr->x1, spr->x2, portal); if ((spr->cut & SC_NOTVISIBLE) == 0) numvisiblesprites++; diff --git a/src/r_things.h b/src/r_things.h index 9892d1e43..e042806fa 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -19,6 +19,7 @@ extern "C" { #endif #include "r_plane.h" +#include "r_portal.h" // number of sprite lumps for spritewidth,offset,topoffset lookup tables // Fab: this is a hack : should allocate the lookup tables per sprite @@ -166,7 +167,7 @@ typedef struct vissprite_s extern UINT32 visspritecount, numvisiblesprites; -void R_ClipSprites(void); +void R_ClipSprites(drawseg_t* dsstart, portal_t* portal); void R_AllocVisSpriteMemory(void); -- 2.54.0 From 6f4b1e5125234c948fa356b6d456ef04c220ac88 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 8 Jun 2025 20:02:54 +0200 Subject: [PATCH 075/141] fix portals on slopes idk this is quite the hack, but it works this adjustment somehow got omitted from srb2 during the portal refactor --- src/r_portal.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/r_portal.c b/src/r_portal.c index 3f3b6c185..c606d82c2 100644 --- a/src/r_portal.c +++ b/src/r_portal.c @@ -166,6 +166,10 @@ void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, con vertex_t dest_c, start_c; + portal->viewx = viewx; + portal->viewy = viewy; + portal->viewz = viewz; + // looking glass center start_c.x = (start->v1->x + start->v2->x) / 2; start_c.y = (start->v1->y + start->v2->y) / 2; @@ -174,13 +178,24 @@ void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, con dest_c.x = (dest->v1->x + dest->v2->x) / 2; dest_c.y = (dest->v1->y + dest->v2->y) / 2; - disttopoint = R_PointToDist2(start_c.x, start_c.y, viewx, viewy); - angtopoint = R_PointToAngle2(start_c.x, start_c.y, viewx, viewy); - angtopoint += dangle; - - portal->viewx = dest_c.x + FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint); - portal->viewy = dest_c.y + FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint); portal->viewz = viewz + dest->frontsector->floorheight - start->frontsector->floorheight; + + if (dangle == 0) + { + // the entrance goes straight opposite the exit, so we just need to mess with the offset. + portal->viewx += dest_c.x - start_c.x; + portal->viewy += dest_c.y - start_c.y; + } + else + { + disttopoint = R_PointToDist2(start_c.x, start_c.y, viewx, viewy); + angtopoint = R_PointToAngle2(start_c.x, start_c.y, viewx, viewy); + angtopoint += dangle; + + portal->viewx = dest_c.x + FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint); + portal->viewy = dest_c.y + FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint); + } + portal->viewangle = viewangle + dangle; portal->clipline = line2; -- 2.54.0 From 42eeb7bdf55df9e4aae9995c6998924c81bc2f05 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 8 Jun 2025 21:36:28 +0200 Subject: [PATCH 076/141] fix the massive slowdown on ante due to really bad loop layout std::fill is only cause it looks fancy :3 --- src/r_plane.cpp | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 5598a0d3d..882275c59 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -307,16 +307,14 @@ static void R_MapTiltedPlane(drawspandata_t *ds, spandrawfunc_t *localspanfunc, void R_ClearFFloorClips(void) { - INT32 i, p; + INT32 p; // opening / clipping determination - for (i = 0; i < viewwidth; i++) + for (p = 0; p < MAXFFLOORS; p++) { - for (p = 0; p < MAXFFLOORS; p++) - { - ffloor[p].f_clip[i] = (INT16)viewheight; - ffloor[p].c_clip[i] = -1; - } + visffloor_t *fffloor = &ffloor[p]; + std::fill(fffloor->f_clip, fffloor->f_clip + viewwidth, static_cast(viewheight)); + std::fill(fffloor->c_clip, fffloor->c_clip + viewwidth, static_cast(-1)); } numffloors = 0; @@ -328,21 +326,15 @@ void R_ClearFFloorClips(void) // void R_ClearPlanes(void) { - INT32 i, p; + INT32 i; angle_t angle; // opening / clipping determination - for (i = 0; i < viewwidth; i++) - { - floorclip[i] = (INT16)viewheight; - ceilingclip[i] = -1; - frontscale[i] = INT32_MAX; - for (p = 0; p < MAXFFLOORS; p++) - { - ffloor[p].f_clip[i] = (INT16)viewheight; - ffloor[p].c_clip[i] = -1; - } - } + std::fill(floorclip, floorclip + viewwidth, static_cast(viewheight)); + std::fill(ceilingclip, ceilingclip + viewwidth, static_cast(-1)); + std::fill(frontscale, frontscale + viewwidth, INT32_MAX); + + R_ClearFFloorClips(); for (i = 0; i < MAXVISPLANES; i++) for (*freehead = visplanes[i], visplanes[i] = NULL; -- 2.54.0 From 6af77afc4414004e8b47495d476715f8b79352f2 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 8 Jun 2025 21:38:27 +0200 Subject: [PATCH 077/141] bring back old clipwallsegment stuff i just didnt like the flow of the new ones --- src/r_bsp.c | 206 +++++++++++++++++++++++++++++++++++++------------ src/r_bsp.h | 1 - src/r_segs.cpp | 25 ------ 3 files changed, 156 insertions(+), 76 deletions(-) diff --git a/src/r_bsp.c b/src/r_bsp.c index 7fb61b882..b82e0e87e 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -74,54 +74,156 @@ void R_ClearDrawSegs(void) ds_p = drawsegs; } -// CPhipps - -// Instead of clipsegs, let's try using an array with one entry for each column, -// indicating whether it's blocked by a solid wall yet or not. -UINT8 *solidcol; +// Fix from boom. +static UINT32 maxsegs; + +// newend is one past the last valid seg +static cliprange_t *newend; +static cliprange_t *solidsegs; void R_AllocClipSegMemory(void) { - solidcol = Z_Realloc(solidcol, sizeof(*solidcol) * viewwidth, PU_STATIC, NULL); + UINT32 newendpos = newend - solidsegs; + + maxsegs = max(BASEVIDWIDTH/2+1, viewwidth/2+1); + + solidsegs = Z_Realloc(solidsegs, sizeof(*solidsegs) * maxsegs, PU_STATIC, NULL); + + newend = solidsegs + newendpos; } -// CPhipps - -// R_ClipWallSegment // -// Replaces the old R_Clip*WallSegment functions. It draws bits of walls in those -// columns which aren't solid, and updates the solidcol[] array appropriately -static void R_ClipWallSegment(int first, int last, boolean solid, boolean soliddontrender) +// R_ClipSolidWallSegment +// Does handle solid walls, +// e.g. single sided LineDefs (middle texture) +// that entirely block the view. +// +static void R_ClipSolidWallSegment(INT32 first, INT32 last) { - while (first < last) + cliprange_t *next; + cliprange_t *start; + + // Find the first range that touches the range (adjacent pixels are touching). + start = solidsegs; + while (start->last < first - 1) + start++; + + if (first < start->first) { - UINT8 *p; - - if (solidcol[first]) + if (last < start->first - 1) { - p = memchr(solidcol+first, 0, last-first); - if (!p) - return; // All solid + // Post is entirely visible (above start), so insert a new clippost. + R_StoreWallRange(first, last); + next = newend; + newend++; + // NO MORE CRASHING! + if (newend - solidsegs > maxsegs) + I_Error("R_ClipSolidWallSegment: Solid Segs overflow!\n"); - first = p - solidcol; + while (next != start) + { + *next = *(next-1); + next--; + } + next->first = first; + next->last = last; + return; } - else + + // There is a fragment above *start. + R_StoreWallRange(first, start->first - 1); + // Now adjust the clip size. + start->first = first; + } + + // Bottom contained in start? + if (last <= start->last) + return; + + next = start; + while (last >= (next+1)->first - 1) + { + // There is a fragment between two posts. + R_StoreWallRange(next->last + 1, (next+1)->first - 1); + next++; + + if (last <= next->last) { - p = memchr(solidcol+first, 1, last-first); - - int to; - if (!p) - to = last; - else - to = p - solidcol; - - if (!soliddontrender) - R_StoreWallRange(first, to-1); - - if (solid) - memset(solidcol+first, 1, to-first); - - first = to; + // Bottom is contained in next. + // Adjust the clip size. + start->last = next->last; + goto crunch; } } + + // There is a fragment after *next. + R_StoreWallRange(next->last + 1, last); + // Adjust the clip size. + start->last = last; + + // Remove start+1 to next from the clip list, because start now covers their area. +crunch: + if (next == start) + return; // Post just extended past the bottom of one post. + + while (next++ != newend) + *++start = *next; // Remove a post. + + newend = start + 1; + + // NO MORE CRASHING! + if (newend - solidsegs > maxsegs) + I_Error("R_ClipSolidWallSegment: Solid Segs overflow!\n"); +} + +// +// R_ClipPassWallSegment +// Clips the given range of columns, but does not include it in the clip list. +// Does handle windows, e.g. LineDefs with upper and lower texture. +// +static inline void R_ClipPassWallSegment(INT32 first, INT32 last, boolean soliddontrender) +{ + cliprange_t *start; + + // Find the first range that touches the range + // (adjacent pixels are touching). + start = solidsegs; + while (start->last < first - 1) + start++; + + if (first < start->first) + { + if (last < start->first - 1) + { + // Post is entirely visible (above start). + if (!soliddontrender) + R_StoreWallRange(first, last); + return; + } + + // There is a fragment above *start. + if (!soliddontrender) + R_StoreWallRange(first, start->first - 1); + } + + // Bottom contained in start? + if (last <= start->last) + return; + + while (last >= (start+1)->first - 1) + { + // There is a fragment between two posts. + if (!soliddontrender) + R_StoreWallRange(start->last + 1, (start+1)->first - 1); + start++; + + if (last <= start->last) + return; + } + + // There is a fragment after *next. + if (!soliddontrender) + R_StoreWallRange(start->last + 1, last); } // @@ -129,18 +231,20 @@ static void R_ClipWallSegment(int first, int last, boolean solid, boolean solidd // void R_ClearClipSegs(void) { - memset(solidcol, 0, viewwidth); + solidsegs[0].first = -0x7fffffff; + solidsegs[0].last = -1; + solidsegs[1].first = viewwidth; + solidsegs[1].last = 0x7fffffff; + newend = solidsegs + 2; } void R_PortalClearClipSegs(INT32 start, INT32 end) { - R_ClearClipSegs(); - - for (INT32 x = 0; x < start; x++) - solidcol[x] = 1; - - for (INT32 x = end; x < viewwidth; x++) - solidcol[x] = 1; + solidsegs[0].first = -0x7fffffff; + solidsegs[0].last = start-1; + solidsegs[1].first = end; + solidsegs[1].last = 0x7fffffff; + newend = solidsegs + 2; } // @@ -451,15 +555,15 @@ static void R_AddLine(seg_t *line) clippass: g_walloffscreen = false; - R_ClipWallSegment(x1, x2, false, false); + R_ClipPassWallSegment(x1, x2, false); if (g_walloffscreen) - R_ClipWallSegment(x1, x2, false, true); + R_ClipPassWallSegment(x1, x2, true); return; clipsolid: g_walloffscreen = false; - R_ClipWallSegment(x1, x2, true, false); + R_ClipSolidWallSegment(x1, x2); } // @@ -492,6 +596,7 @@ static boolean R_CheckBBox(const fixed_t *bspcoord) angle_t angle1, angle2; INT32 sx1, sx2, boxpos; const INT32* check; + cliprange_t *start; // Find the corners of the box that define the edges from current viewpoint. if (viewx <= bspcoord[BOXLEFT]) @@ -540,11 +645,12 @@ static boolean R_CheckBBox(const fixed_t *bspcoord) if (sx1 >= sx2) return false; - if (!memchr(solidcol+sx1, 0, sx2-sx1)) - { - // All columns it covers are already solidly covered - return false; - } + start = solidsegs; + while (start->last < sx2) + start++; + + if (sx1 >= start->first && sx2 <= start->last) + return false; // The clippost contains the new span. return true; } diff --git a/src/r_bsp.h b/src/r_bsp.h index b9e4e291d..c3e0ff476 100644 --- a/src/r_bsp.h +++ b/src/r_bsp.h @@ -40,7 +40,6 @@ extern drawseg_t *curdrawsegs; extern drawseg_t *drawsegs; extern drawseg_t *ds_p; extern INT32 doorclosed; -extern UINT8 *solidcol; extern boolean g_walloffscreen; // BSP? diff --git a/src/r_segs.cpp b/src/r_segs.cpp index ab1e67070..1102de672 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -1158,8 +1158,6 @@ static void R_DrawWallColumn(drawcolumndata_t* dc, INT32 yl, INT32 yh, fixed_t m colfunccopy(const_cast(&dc_copy)); } -static boolean didsolidcol; // True if at least one column was marked solid - static void R_RenderSegLoop(drawcolumndata_t* dc) { angle_t angle; @@ -1488,12 +1486,6 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) floorclip[rw_x] = bottomclip; } - if ((markceiling || markfloor) && (floorclip[rw_x] <= ceilingclip[rw_x] + 1)) - { - solidcol[rw_x] = 1; - didsolidcol = true; - } - if (maskedtexture || numthicksides) { // save texturecol for backdrawing of masked mid texture @@ -2760,8 +2752,6 @@ void R_StoreWallRange(INT32 start, INT32 stop) rw_tsilheight = &(ds_p->tsilheight); rw_bsilheight = &(ds_p->bsilheight); - didsolidcol = false; - R_RenderSegLoop(&dc); R_SetColumnFunc(BASEDRAWFUNC); @@ -2770,21 +2760,6 @@ void R_StoreWallRange(INT32 start, INT32 stop) else ds_p->portalpass = 0; - // cph - if a column was made solid by this wall, we _must_ save full clipping info - if (backsector && didsolidcol) - { - if (!(ds_p->silhouette & SIL_BOTTOM)) - { - ds_p->silhouette |= SIL_BOTTOM; - ds_p->bsilheight = backsector->f_slope ? INT32_MAX : backsector->floorheight; - } - if (!(ds_p->silhouette & SIL_TOP)) - { - ds_p->silhouette |= SIL_TOP; - ds_p->tsilheight = backsector->c_slope ? INT32_MIN : backsector->ceilingheight; - } - } - // save sprite clipping info if (((ds_p->silhouette & SIL_TOP) || maskedtexture) && !ds_p->sprtopclip) { -- 2.54.0 From 5e8096f74c89e61a8aafaa16f17a9d98d383ef04 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 9 Jun 2025 00:21:23 +0200 Subject: [PATCH 078/141] move hom removal to D_Renderview removes the hwr code dupe and moves this out of the splitscreen loop --- src/d_main.c | 33 +++++++++++++++++++++++++++++++++ src/hardware/hw_main.c | 14 -------------- src/r_main.cpp | 23 ----------------------- 3 files changed, 33 insertions(+), 37 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index abdd3fa2a..198a341b7 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -327,6 +327,39 @@ static void D_Renderview(void) R_ApplyLevelInterpolators(rendertimefrac); + if (rendermode == render_soft) + { + // if this is display player 1 + if (cv_homremoval.value) + { + if (cv_homremoval.value == 1) + { + // Clear the software screen buffer to remove HOM + memset(vid.screens[0], 31, vid.width * vid.height); + } + else if (cv_homremoval.value == 2) + { + //'development' HOM removal -- makes it blindingly obvious if HOM is spotted. + memset(vid.screens[0], 32+(timeinmap&15), vid.width * vid.height); + } + } + } + + // Draw over the fourth screen so you don't have to stare at a HOM :V + if (splitscreen == 2) + { + // V_DrawPatchFill, but for the fourth screen only + patch_t *pat = W_CachePatchName("SRB2BACK", PU_CACHE); + INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); + INT32 x, y, pw = SHORT(pat->width) * dupz, ph = SHORT(pat->height) * dupz; + + for (x = vid.width>>1; x < vid.width; x += pw) + { + for (y = vid.height>>1; y < vid.height; y += ph) + V_DrawScaledPatch(x, y, V_NOSCALESTART, pat); + } + } + for (i = 0; i <= splitscreen; i++) { const boolean issplitscreen = (i > 0); diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 06e15c1a0..0e0658567 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5564,20 +5564,6 @@ static void HWR_RenderFrame(player_t *player, boolean skybox) gl_viewwindowx += gl_viewwidth; } - if (splitscreen == 2 && player == &players[displayplayers[2]]) - { - // V_DrawPatchFill, but for the fourth screen only - patch_t *gpatch = W_CachePatchName("SRB2BACK", PU_PATCH); - INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); - INT32 x, y, pw = (gpatch->width * dupz), ph = (gpatch->height * dupz); - - for (x = vid.width >> 1; x < vid.width; x += pw) - { - for (y = vid.height >> 1; y < vid.height; y += ph) - HWR_DrawStretchyFixedPatch(gpatch, (x)<(W_CachePatchName("SRB2BACK", PU_CACHE)); - INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); - INT32 x, y, pw = SHORT(pat->width) * dupz, ph = SHORT(pat->height) * dupz; - - for (x = vid.width>>1; x < vid.width; x += pw) - { - for (y = vid.height>>1; y < vid.height; y += ph) - V_DrawScaledPatch(x, y, V_NOSCALESTART, pat); - } - } - // load previous saved value of skyVisible for the player for (i = 0; i <= splitscreen; i++) { -- 2.54.0 From 7456b6e02c531d36b5223bd9b0b47d2d7cf357d2 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 9 Jun 2025 04:27:58 +0200 Subject: [PATCH 079/141] Revert "bring back old clipwallsegment stuff" This reverts commit 6af77afc4414004e8b47495d476715f8b79352f2. --- src/r_bsp.c | 202 ++++++++++++------------------------------------- src/r_bsp.h | 1 + src/r_segs.cpp | 25 ++++++ 3 files changed, 74 insertions(+), 154 deletions(-) diff --git a/src/r_bsp.c b/src/r_bsp.c index b82e0e87e..7fb61b882 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -74,156 +74,54 @@ void R_ClearDrawSegs(void) ds_p = drawsegs; } -// Fix from boom. -static UINT32 maxsegs; - -// newend is one past the last valid seg -static cliprange_t *newend; -static cliprange_t *solidsegs; +// CPhipps - +// Instead of clipsegs, let's try using an array with one entry for each column, +// indicating whether it's blocked by a solid wall yet or not. +UINT8 *solidcol; void R_AllocClipSegMemory(void) { - UINT32 newendpos = newend - solidsegs; - - maxsegs = max(BASEVIDWIDTH/2+1, viewwidth/2+1); - - solidsegs = Z_Realloc(solidsegs, sizeof(*solidsegs) * maxsegs, PU_STATIC, NULL); - - newend = solidsegs + newendpos; + solidcol = Z_Realloc(solidcol, sizeof(*solidcol) * viewwidth, PU_STATIC, NULL); } +// CPhipps - +// R_ClipWallSegment // -// R_ClipSolidWallSegment -// Does handle solid walls, -// e.g. single sided LineDefs (middle texture) -// that entirely block the view. -// -static void R_ClipSolidWallSegment(INT32 first, INT32 last) +// Replaces the old R_Clip*WallSegment functions. It draws bits of walls in those +// columns which aren't solid, and updates the solidcol[] array appropriately +static void R_ClipWallSegment(int first, int last, boolean solid, boolean soliddontrender) { - cliprange_t *next; - cliprange_t *start; - - // Find the first range that touches the range (adjacent pixels are touching). - start = solidsegs; - while (start->last < first - 1) - start++; - - if (first < start->first) + while (first < last) { - if (last < start->first - 1) - { - // Post is entirely visible (above start), so insert a new clippost. - R_StoreWallRange(first, last); - next = newend; - newend++; - // NO MORE CRASHING! - if (newend - solidsegs > maxsegs) - I_Error("R_ClipSolidWallSegment: Solid Segs overflow!\n"); + UINT8 *p; - while (next != start) - { - *next = *(next-1); - next--; - } - next->first = first; - next->last = last; - return; + if (solidcol[first]) + { + p = memchr(solidcol+first, 0, last-first); + if (!p) + return; // All solid + + first = p - solidcol; } - - // There is a fragment above *start. - R_StoreWallRange(first, start->first - 1); - // Now adjust the clip size. - start->first = first; - } - - // Bottom contained in start? - if (last <= start->last) - return; - - next = start; - while (last >= (next+1)->first - 1) - { - // There is a fragment between two posts. - R_StoreWallRange(next->last + 1, (next+1)->first - 1); - next++; - - if (last <= next->last) + else { - // Bottom is contained in next. - // Adjust the clip size. - start->last = next->last; - goto crunch; - } - } + p = memchr(solidcol+first, 1, last-first); - // There is a fragment after *next. - R_StoreWallRange(next->last + 1, last); - // Adjust the clip size. - start->last = last; + int to; + if (!p) + to = last; + else + to = p - solidcol; - // Remove start+1 to next from the clip list, because start now covers their area. -crunch: - if (next == start) - return; // Post just extended past the bottom of one post. - - while (next++ != newend) - *++start = *next; // Remove a post. - - newend = start + 1; - - // NO MORE CRASHING! - if (newend - solidsegs > maxsegs) - I_Error("R_ClipSolidWallSegment: Solid Segs overflow!\n"); -} - -// -// R_ClipPassWallSegment -// Clips the given range of columns, but does not include it in the clip list. -// Does handle windows, e.g. LineDefs with upper and lower texture. -// -static inline void R_ClipPassWallSegment(INT32 first, INT32 last, boolean soliddontrender) -{ - cliprange_t *start; - - // Find the first range that touches the range - // (adjacent pixels are touching). - start = solidsegs; - while (start->last < first - 1) - start++; - - if (first < start->first) - { - if (last < start->first - 1) - { - // Post is entirely visible (above start). if (!soliddontrender) - R_StoreWallRange(first, last); - return; + R_StoreWallRange(first, to-1); + + if (solid) + memset(solidcol+first, 1, to-first); + + first = to; } - - // There is a fragment above *start. - if (!soliddontrender) - R_StoreWallRange(first, start->first - 1); } - - // Bottom contained in start? - if (last <= start->last) - return; - - while (last >= (start+1)->first - 1) - { - // There is a fragment between two posts. - if (!soliddontrender) - R_StoreWallRange(start->last + 1, (start+1)->first - 1); - start++; - - if (last <= start->last) - return; - } - - // There is a fragment after *next. - if (!soliddontrender) - R_StoreWallRange(start->last + 1, last); } // @@ -231,20 +129,18 @@ static inline void R_ClipPassWallSegment(INT32 first, INT32 last, boolean solidd // void R_ClearClipSegs(void) { - solidsegs[0].first = -0x7fffffff; - solidsegs[0].last = -1; - solidsegs[1].first = viewwidth; - solidsegs[1].last = 0x7fffffff; - newend = solidsegs + 2; + memset(solidcol, 0, viewwidth); } void R_PortalClearClipSegs(INT32 start, INT32 end) { - solidsegs[0].first = -0x7fffffff; - solidsegs[0].last = start-1; - solidsegs[1].first = end; - solidsegs[1].last = 0x7fffffff; - newend = solidsegs + 2; + R_ClearClipSegs(); + + for (INT32 x = 0; x < start; x++) + solidcol[x] = 1; + + for (INT32 x = end; x < viewwidth; x++) + solidcol[x] = 1; } // @@ -555,15 +451,15 @@ static void R_AddLine(seg_t *line) clippass: g_walloffscreen = false; - R_ClipPassWallSegment(x1, x2, false); + R_ClipWallSegment(x1, x2, false, false); if (g_walloffscreen) - R_ClipPassWallSegment(x1, x2, true); + R_ClipWallSegment(x1, x2, false, true); return; clipsolid: g_walloffscreen = false; - R_ClipSolidWallSegment(x1, x2); + R_ClipWallSegment(x1, x2, true, false); } // @@ -596,7 +492,6 @@ static boolean R_CheckBBox(const fixed_t *bspcoord) angle_t angle1, angle2; INT32 sx1, sx2, boxpos; const INT32* check; - cliprange_t *start; // Find the corners of the box that define the edges from current viewpoint. if (viewx <= bspcoord[BOXLEFT]) @@ -645,12 +540,11 @@ static boolean R_CheckBBox(const fixed_t *bspcoord) if (sx1 >= sx2) return false; - start = solidsegs; - while (start->last < sx2) - start++; - - if (sx1 >= start->first && sx2 <= start->last) - return false; // The clippost contains the new span. + if (!memchr(solidcol+sx1, 0, sx2-sx1)) + { + // All columns it covers are already solidly covered + return false; + } return true; } diff --git a/src/r_bsp.h b/src/r_bsp.h index c3e0ff476..b9e4e291d 100644 --- a/src/r_bsp.h +++ b/src/r_bsp.h @@ -40,6 +40,7 @@ extern drawseg_t *curdrawsegs; extern drawseg_t *drawsegs; extern drawseg_t *ds_p; extern INT32 doorclosed; +extern UINT8 *solidcol; extern boolean g_walloffscreen; // BSP? diff --git a/src/r_segs.cpp b/src/r_segs.cpp index 1102de672..ab1e67070 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -1158,6 +1158,8 @@ static void R_DrawWallColumn(drawcolumndata_t* dc, INT32 yl, INT32 yh, fixed_t m colfunccopy(const_cast(&dc_copy)); } +static boolean didsolidcol; // True if at least one column was marked solid + static void R_RenderSegLoop(drawcolumndata_t* dc) { angle_t angle; @@ -1486,6 +1488,12 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) floorclip[rw_x] = bottomclip; } + if ((markceiling || markfloor) && (floorclip[rw_x] <= ceilingclip[rw_x] + 1)) + { + solidcol[rw_x] = 1; + didsolidcol = true; + } + if (maskedtexture || numthicksides) { // save texturecol for backdrawing of masked mid texture @@ -2752,6 +2760,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) rw_tsilheight = &(ds_p->tsilheight); rw_bsilheight = &(ds_p->bsilheight); + didsolidcol = false; + R_RenderSegLoop(&dc); R_SetColumnFunc(BASEDRAWFUNC); @@ -2760,6 +2770,21 @@ void R_StoreWallRange(INT32 start, INT32 stop) else ds_p->portalpass = 0; + // cph - if a column was made solid by this wall, we _must_ save full clipping info + if (backsector && didsolidcol) + { + if (!(ds_p->silhouette & SIL_BOTTOM)) + { + ds_p->silhouette |= SIL_BOTTOM; + ds_p->bsilheight = backsector->f_slope ? INT32_MAX : backsector->floorheight; + } + if (!(ds_p->silhouette & SIL_TOP)) + { + ds_p->silhouette |= SIL_TOP; + ds_p->tsilheight = backsector->c_slope ? INT32_MIN : backsector->ceilingheight; + } + } + // save sprite clipping info if (((ds_p->silhouette & SIL_TOP) || maskedtexture) && !ds_p->sprtopclip) { -- 2.54.0 From 80b301dbbed1e50e73435450183e8229ee620577 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 9 Jun 2025 17:01:20 +0200 Subject: [PATCH 080/141] unnest the overflow_test stuff its also a ternary now lul --- src/r_segs.cpp | 67 +++++++++++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 28 deletions(-) diff --git a/src/r_segs.cpp b/src/r_segs.cpp index ab1e67070..f978c19a4 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -143,6 +143,21 @@ transnum_t R_GetLinedefTransTable(fixed_t alpha) return static_cast((20*(FRACUNIT - alpha - 1) + FRACUNIT) >> (FRACBITS+1)); } +static inline boolean R_OverflowTest(drawcolumndata_t* dc) +{ + INT64 overflow_test; + + overflow_test = (INT64)centeryfrac - (((INT64)dc->texturemid*spryscale)>>FRACBITS); + + if (overflow_test < 0) + overflow_test = -overflow_test; + + if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) + return true; + + return false; +} + static void R_RenderMaskedSegLoop(drawcolumndata_t* dc, drawseg_t *drawseg, INT32 x1, INT32 x2, INT32 texnum, void (*colfunc_2s)(drawcolumndata_t*, column_t *)) { size_t pindex; @@ -153,7 +168,6 @@ static void R_RenderMaskedSegLoop(drawcolumndata_t* dc, drawseg_t *drawseg, INT3 r_lightlist_t *rlight; sector_t *front, *back; INT32 times, repeats; - INT64 overflow_test; INT32 range; line_t *ldef; @@ -296,9 +310,7 @@ static void R_RenderMaskedSegLoop(drawcolumndata_t* dc, drawseg_t *drawseg, INT3 if (maskedtexturecol[dc->x] != INT16_MAX) { // Check for overflows first - overflow_test = (INT64)centeryfrac - (((INT64)dc->texturemid*spryscale)>>FRACBITS); - if (overflow_test < 0) overflow_test = -overflow_test; - if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) + if (R_OverflowTest(dc)) { // Eh, no, go away, don't waste our time if (dc->numlights) @@ -309,6 +321,7 @@ static void R_RenderMaskedSegLoop(drawcolumndata_t* dc, drawseg_t *drawseg, INT3 rlight->height += rlight->heightstep; } } + spryscale += rw_scalestep; continue; } @@ -425,6 +438,7 @@ static void R_RenderMaskedSegLoop(drawcolumndata_t* dc, drawseg_t *drawseg, INT3 colfunc_2s(dc, col); } + spryscale += rw_scalestep; } } @@ -664,6 +678,17 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf rw_scalestep = drawseg->scalestep; spryscale = drawseg->scale1 + (x1 - drawseg->x1)*rw_scalestep; +#define CLAMPMAX INT32_MAX +#define CLAMPMIN (-INT32_MAX) // This is not INT32_MIN on purpose! INT32_MIN makes the drawers freak out. + auto overflow_clamp = [&](INT64 overflow_test) + { + return (overflow_test > (INT64)CLAMPMAX) ? CLAMPMAX : + (overflow_test > (INT64)CLAMPMIN) ? (fixed_t)overflow_test : + CLAMPMIN; + }; +#undef CLAMPMAX +#undef CLAMPMIN + dc->numlights = 0; if (frontsector->numlights) { @@ -706,18 +731,13 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf leftheight -= viewz; rightheight -= viewz; -#define CLAMPMAX INT32_MAX -#define CLAMPMIN (-INT32_MAX) // This is not INT32_MIN on purpose! INT32_MIN makes the drawers freak out. // Monster Iestyn (25/03/18): do not skip these lights if they fail overflow test, just clamp them instead so they behave. overflow_test = (INT64)centeryfrac - (((INT64)leftheight*drawseg->scale1)>>FRACBITS); - if (overflow_test > (INT64)CLAMPMAX) rlight->height = CLAMPMAX; - else if (overflow_test > (INT64)CLAMPMIN) rlight->height = (fixed_t)overflow_test; - else rlight->height = CLAMPMIN; + rlight->height = overflow_clamp(overflow_test); overflow_test = (INT64)centeryfrac - (((INT64)rightheight*drawseg->scale2)>>FRACBITS); - if (overflow_test > (INT64)CLAMPMAX) rlight->heightstep = CLAMPMAX; - else if (overflow_test > (INT64)CLAMPMIN) rlight->heightstep = (fixed_t)overflow_test; - else rlight->heightstep = CLAMPMIN; + rlight->heightstep = overflow_clamp(overflow_test); + rlight->heightstep = (rlight->heightstep-rlight->height)/(range); rlight->flags = static_cast(light->flags); @@ -730,14 +750,11 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf // Monster Iestyn (25/03/18): do not skip these lights if they fail overflow test, just clamp them instead so they behave. overflow_test = (INT64)centeryfrac - (((INT64)leftheight*drawseg->scale1)>>FRACBITS); - if (overflow_test > (INT64)CLAMPMAX) rlight->botheight = CLAMPMAX; - else if (overflow_test > (INT64)CLAMPMIN) rlight->botheight = (fixed_t)overflow_test; - else rlight->botheight = CLAMPMIN; + rlight->botheight = overflow_clamp(overflow_test); overflow_test = (INT64)centeryfrac - (((INT64)rightheight*drawseg->scale2)>>FRACBITS); - if (overflow_test > (INT64)CLAMPMAX) rlight->botheightstep = CLAMPMAX; - else if (overflow_test > (INT64)CLAMPMIN) rlight->botheightstep = (fixed_t)overflow_test; - else rlight->botheightstep = CLAMPMIN; + rlight->botheightstep = overflow_clamp(overflow_test); + rlight->botheightstep = (rlight->botheightstep-rlight->botheight)/(range); } @@ -894,15 +911,11 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf dc->texturemid += FixedMul(ffloortextureslide, (maskedtexturecol[oldx]-maskedtexturecol[dc->x])<x; } + // Calculate bounds // clamp the values if necessary to avoid overflows and rendering glitches caused by them - - if (top_frac > (INT64)CLAMPMAX) sprtopscreen = windowtop = CLAMPMAX; - else if (top_frac > (INT64)CLAMPMIN) sprtopscreen = windowtop = (fixed_t)top_frac; - else sprtopscreen = windowtop = CLAMPMIN; - if (bottom_frac > (INT64)CLAMPMAX) sprbotscreen = windowbottom = CLAMPMAX; - else if (bottom_frac > (INT64)CLAMPMIN) sprbotscreen = windowbottom = (fixed_t)bottom_frac; - else sprbotscreen = windowbottom = CLAMPMIN; + sprtopscreen = windowtop = overflow_clamp(top_frac); + sprbotscreen = windowbottom = overflow_clamp(bottom_frac); top_frac += top_step; bottom_frac += bottom_step; @@ -1106,9 +1119,6 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf } R_SetColumnFunc(BASEDRAWFUNC); - -#undef CLAMPMAX -#undef CLAMPMIN } // R_FFloorCanClip @@ -2393,6 +2403,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) fixed_t topfracend = (centeryfrac>>4) - FixedMul (worldtopslope, ds_p->scale2); topstep = (topfracend-topfrac)/(range); } + if (frontsector->f_slope) { fixed_t bottomfracend = (centeryfrac>>4) - FixedMul (worldbottomslope, ds_p->scale2); -- 2.54.0 From ccd67f621afd747c15d09c657ca7e0b5827be807 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 9 Jun 2025 17:02:12 +0200 Subject: [PATCH 081/141] dont set any texture mapped drawer when fog --- src/r_segs.cpp | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/r_segs.cpp b/src/r_segs.cpp index f978c19a4..53d155705 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -622,6 +622,8 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf INT32 oldx = -1; fixed_t left_top, left_bottom; // needed here for slope skewing pslope_t *skewslope = NULL; + boolean fog = false; + boolean fuzzy = false; drawcolumndata_t *dc = &g_dc; @@ -648,7 +650,7 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf if (pfloor->flags & FF_TRANSLUCENT) { - boolean fuzzy = true; + fuzzy = true; // 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 @@ -662,15 +664,11 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf else if (!(dc->transmap = R_GetTranslucencyTable(trans)) || trans == 0) fuzzy = false; // Opaque } - - if (fuzzy) - { - R_SetColumnFunc(COLDRAWFUNC_FUZZY); - } } else if (pfloor->flags & FF_FOG) { R_SetColumnFunc(COLDRAWFUNC_FOG); + fog = true; } range = std::max(drawseg->x2-drawseg->x1, 1); @@ -782,9 +780,9 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf // Get correct light level! if ((frontsector->extra_colormap && frontsector->extra_colormap->fog)) lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); - else if (pfloor->flags & FF_FOG) + else if (fog) lightnum = (pfloor->master->frontsector->lightlevel >> LIGHTSEGSHIFT); - else if (R_CheckColumnFunc(COLDRAWFUNC_FUZZY) == true) + else if (fuzzy) lightnum = LIGHTLEVELS-1; else lightnum = R_FakeFlat(frontsector, &tempsec, &templight, &templight, false) @@ -933,15 +931,24 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf rlight->botheight += rlight->botheightstep; } } + spryscale += rw_scalestep; continue; } - dc->iscale = 0xffffffffu / (unsigned)spryscale; - // Get data for the column col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc->x]) - 3); + if (!fog) + { + dc->iscale = 0xffffffffu / (unsigned)spryscale; + + if (fuzzy) + R_SetColumnFunc(COLDRAWFUNC_FUZZY); + else + R_SetColumnFunc(BASEDRAWFUNC); + } + // SoM: New code does not rely on R_DrawColumnShadowed which // will (hopefully) put less strain on the stack. if (dc->numlights) -- 2.54.0 From 968584a316a50b93b1c2e33f303565d882113446 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 9 Jun 2025 17:02:56 +0200 Subject: [PATCH 082/141] make skyportals account for how kart sets the viewheight no we still dont use it --- src/r_portal.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/r_portal.c b/src/r_portal.c index c606d82c2..432e3f50d 100644 --- a/src/r_portal.c +++ b/src/r_portal.c @@ -91,6 +91,7 @@ void Portal_ClipApply (const portal_t* portal) floorclip[i] = -1; ceilingclip[i] = (INT16)viewheight; } + for (i = end; i < vid.width; i++) { floorclip[i] = -1; @@ -119,11 +120,11 @@ static portal_t* Portal_Add (const INT16 x1, const INT16 x2) portal->next = NULL; // Store clipping values so they can be restored once the portal is rendered. - portal->ceilingclip = ceilingclipsave; - portal->floorclip = floorclipsave; - portal->frontscale = frontscalesave; - portal->start = x1; - portal->end = x2; + portal->ceilingclip = ceilingclipsave; + portal->floorclip = floorclipsave; + portal->frontscale = frontscalesave; + portal->start = x1; + portal->end = x2; // Increase recursion level. portal->pass = portalrender+1; @@ -289,6 +290,9 @@ void Portal_AddSkybox(const visplane_t* plane) portal->viewx = skyboxmo[0]->x; portal->viewy = skyboxmo[0]->y; portal->viewz = skyboxmo[0]->z; + if (skyboxmo[0]->spawnpoint) + portal->viewz = ((fixed_t)skyboxmo[0]->spawnpoint->angle)<viewangle = viewangle + skyboxmo[0]->angle; mh = mapheaderinfo[gamemap-1]; -- 2.54.0 From 717947843bb4568f97eb57c101b41b9dbf54f151 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 9 Jun 2025 17:03:08 +0200 Subject: [PATCH 083/141] memset those --- src/r_bsp.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/r_bsp.c b/src/r_bsp.c index 7fb61b882..1957ec862 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -136,11 +136,11 @@ void R_PortalClearClipSegs(INT32 start, INT32 end) { R_ClearClipSegs(); - for (INT32 x = 0; x < start; x++) - solidcol[x] = 1; + if (start > 0) + memset(solidcol, 1, start); - for (INT32 x = end; x < viewwidth; x++) - solidcol[x] = 1; + if (end < viewwidth) + memset(solidcol + end, 1, viewwidth - end); } // @@ -333,6 +333,7 @@ static void R_AddLine(seg_t *line) angle1 = clipangle; } + tspan = clipangle - angle2; if (tspan > doubleclipangle) { @@ -1103,6 +1104,7 @@ void R_Prep3DFloors(sector_t *sector) } } } + if (!best) { sector->numlights = i; -- 2.54.0 From 84d3d23936304c6d6bad73c65a106542d4c367c7 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 9 Jun 2025 17:03:28 +0200 Subject: [PATCH 084/141] declare fracstep as const --- src/r_draw_column.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/r_draw_column.c b/src/r_draw_column.c index d6ae577f7..dc825e5d6 100644 --- a/src/r_draw_column.c +++ b/src/r_draw_column.c @@ -27,7 +27,6 @@ void R_DrawColumn(drawcolumndata_t* dc) INT32 count; register UINT8 *restrict dest; intptr_t frac; - intptr_t fracstep; count = dc->yh - dc->yl; @@ -47,7 +46,7 @@ void R_DrawColumn(drawcolumndata_t* dc) count++; // Determine scaling, which is the only mapping to be done. - fracstep = dc->iscale; + const intptr_t fracstep = dc->iscale; frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep)); // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. @@ -147,7 +146,6 @@ void R_Draw2sMultiPatchColumn(drawcolumndata_t* dc) INT32 count; register UINT8 *restrict dest; intptr_t frac; - intptr_t fracstep; count = dc->yh - dc->yl; @@ -167,7 +165,7 @@ void R_Draw2sMultiPatchColumn(drawcolumndata_t* dc) count++; // Determine scaling, which is the only mapping to be done. - fracstep = dc->iscale; + const intptr_t fracstep = dc->iscale; frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep)); // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. @@ -286,7 +284,6 @@ void R_Draw2sMultiPatchTranslucentColumn(drawcolumndata_t* dc) INT32 count; register UINT8 *restrict dest; intptr_t frac; - intptr_t fracstep; count = dc->yh - dc->yl; @@ -306,7 +303,7 @@ void R_Draw2sMultiPatchTranslucentColumn(drawcolumndata_t* dc) count++; // Determine scaling, which is the only mapping to be done. - fracstep = dc->iscale; + const intptr_t fracstep = dc->iscale; frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep)); // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. @@ -430,7 +427,6 @@ void R_DrawTranslucentColumn(drawcolumndata_t* dc) register INT32 count; register UINT8 *restrict dest; intptr_t frac; - intptr_t fracstep; count = dc->yh - dc->yl + 1; @@ -448,7 +444,7 @@ void R_DrawTranslucentColumn(drawcolumndata_t* dc) dest = R_Address(dc->x, dc->yl); // Looks familiar. - fracstep = dc->iscale; + const intptr_t fracstep = dc->iscale; frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep)); // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. @@ -530,7 +526,6 @@ void R_DrawTranslatedTranslucentColumn(drawcolumndata_t* dc) register INT32 count; register UINT8 *restrict dest; intptr_t frac; - intptr_t fracstep; count = dc->yh - dc->yl + 1; @@ -548,7 +543,7 @@ void R_DrawTranslatedTranslucentColumn(drawcolumndata_t* dc) dest = R_Address(dc->x, dc->yl); // Looks familiar. - fracstep = dc->iscale; + const intptr_t fracstep = dc->iscale; frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep)); // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. @@ -627,7 +622,7 @@ void R_DrawTranslatedColumn(drawcolumndata_t* dc) { register INT32 count; register UINT8 *dest; - register fixed_t frac, fracstep; + register fixed_t frac; count = dc->yh - dc->yl; @@ -645,7 +640,7 @@ void R_DrawTranslatedColumn(drawcolumndata_t* dc) dest = R_Address(dc->x, dc->yl); // Looks familiar. - fracstep = dc->iscale; + const fixed_t fracstep = dc->iscale; frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep)); register const INT32 stride = vid.width; -- 2.54.0 From d73532d0191a86e3eed92dcf85f15c1370df4ad0 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 9 Jun 2025 17:04:13 +0200 Subject: [PATCH 085/141] fix some fofs not rendering in software i did an oopsie in 7.2 X) --- src/r_plane.cpp | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 882275c59..cca0f121f 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -719,8 +719,12 @@ static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), b INT32 x; drawcolumndata_t dc = {}; + // If we're not supposed to draw the sky (e.g. for skyboxes), don't do anything! + // This probably utterly ruins sky rendering for FOFs and polyobjects, unfortunately if (!newview->sky) { + // Mark that the sky was visible here for next tic + // (note: this is a hack and it sometimes can cause HOMs to appear for a tic IIRC) skyVisible = true; return; } @@ -972,15 +976,18 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle // Don't draw planes that shouldn't be drawn. for (rover = pl->ffloor->target->ffloors; rover; rover = rover->next) { - if (!((pl->ffloor->flags & FF_CUTEXTRA) && (rover->flags & FF_EXTRA))) - continue; + if ((pl->ffloor->flags & FF_CUTEXTRA) && (rover->flags & FF_EXTRA)) + { + if (!(rover->flags & FF_EXTRA)) + continue; - // The plane is from an extra 3D floor... Check the flags so - // there are no undesired cuts. - if (((pl->ffloor->flags & (FF_FOG|FF_SWIMMABLE)) == (rover->flags & (FF_FOG|FF_SWIMMABLE))) - && pl->height < *rover->topheight - && pl->height > *rover->bottomheight) - return; + // The plane is from an extra 3D floor... Check the flags so + // there are no undesired cuts. + if (((pl->ffloor->flags & (FF_FOG|FF_SWIMMABLE)) == (rover->flags & (FF_FOG|FF_SWIMMABLE))) + && pl->height < *rover->topheight + && pl->height > *rover->bottomheight) + return; + } } if (pl->ffloor->flags & FF_TRANSLUCENT) @@ -994,6 +1001,7 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle INT32 trans = (10*((256+12) - pl->ffloor->alpha))/255; if (trans >= 10) return; // Don't even draw it + if (pl->ffloor->blend) // additive, (reverse) subtractive, modulative ds->transmap = R_GetBlendTable(pl->ffloor->blend, trans); else if (!(ds->transmap = R_GetTranslucencyTable(trans)) || trans == 0) -- 2.54.0 From 88d62c93a110d97ff670e080e6d407fb86516218 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 9 Jun 2025 17:04:39 +0200 Subject: [PATCH 086/141] fix SHITPLANESPARENCY and QUINCUNX maybe --- src/r_plane.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/r_plane.cpp b/src/r_plane.cpp index cca0f121f..cef2d2f50 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -961,7 +961,7 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle spanfunctype = SPANDRAWFUNC_SPLAT; #ifdef SHITPLANESPARENCY - if (spanfunc == splatfunc || (pl->extra_colormap && pl->extra_colormap->fog)) + if (spanfunc == spanfuncs[SPANDRAWFUNC_SPLAT] || (pl->extra_colormap && pl->extra_colormap->fog)) #else if (!pl->extra_colormap || !(pl->extra_colormap->fog & 2)) #endif @@ -1009,7 +1009,7 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle } #ifdef SHITPLANESPARENCY - if (spanfunc == splatfunc || (pl->extra_colormap && pl->extra_colormap->fog)) + if (spanfunc == spanfuncs[SPANDRAWFUNC_SPLAT] || (pl->extra_colormap && pl->extra_colormap->fog)) #else if (!pl->extra_colormap || !(pl->extra_colormap->fog & 2)) #endif @@ -1229,12 +1229,15 @@ a 'smoothing' of the texture while using the palette colors. */ #ifdef QUINCUNX - if (spanfunc == R_DrawSpan) + if (spanfunc == spanfuncs[BASEDRAWFUNC]) { INT32 i; - ds_transmap = R_GetTranslucencyTable(tr_trans50); - spanfunc = R_DrawTranslucentSpan; - for (i=0; i<4; i++) + + ds->transmap = R_GetTranslucencyTable(tr_trans50); + + R_SetSpanFunc(SPANDRAWFUNC_TRANS); + + for (i = 0; i < 4; i++) { ds->xoffs = pl->xoffs; ds->yoffs = pl->yoffs; -- 2.54.0 From e7db9bf1fd6ccca938ab4e06e9d9d51116f614e0 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 9 Jun 2025 17:09:42 +0200 Subject: [PATCH 087/141] fix bad copy paste lul --- src/r_main.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/r_main.cpp b/src/r_main.cpp index 79b31dca2..80c176ca5 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1469,8 +1469,7 @@ void R_RenderPlayerView(player_t *player) // Render the BSP from the new viewpoint, and clip // any sprites with the new clipsegs and window. - - R_RenderViewpoint(&masks[nummasks - 1], nummasks - 1); + R_RenderViewpoint(&masks[nummasks - 1], true); R_ClipSprites(ds_p - (masks[nummasks - 1].drawsegs[1] - masks[nummasks - 1].drawsegs[0]), portal); -- 2.54.0 From 793ccff6e68c4045af6888f7f166b1f8fa08895d Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 9 Jun 2025 19:02:48 +0200 Subject: [PATCH 088/141] fix the goddamn portal use after free https://git.do.srb2.org/STJr/SRB2/-/commit/f536ab34674fb8d3ee262a0009753f552074305c --- src/r_segs.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/r_segs.cpp b/src/r_segs.cpp index 53d155705..7bb80f6b1 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -1679,6 +1679,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) { size_t pos = lastopening - openings; size_t need = (rw_stopx - start)*4 + pos; + if (need > maxopenings) { drawseg_t *ds; //needed for fix from *cough* zdoom *cough* @@ -1697,9 +1698,9 @@ void R_StoreWallRange(INT32 start, INT32 stop) // borrowed fix from *cough* zdoom *cough* // [RH] We also need to adjust the openings pointers that // were already stored in drawsegs. - for (ds = curdrawsegs; ds < ds_p; ds++) + for (ds = drawsegs; ds < ds_p; ds++) { -#define ADJUST(p) if (ds->p + ds->x1 >= oldopenings && ds->p + ds->x1 <= oldlast) ds->p = ds->p - oldopenings + openings; +#define ADJUST(p) if (ds->p + ds->x1 >= oldopenings && ds->p + ds->x1 <= oldlast) ds->p = (ds->p - oldopenings) + openings; ADJUST(maskedtexturecol); ADJUST(sprtopclip); ADJUST(sprbottomclip); -- 2.54.0 From a8005d5cec6ed8c1a2fe06e194101f4d832f03e7 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 9 Jun 2025 19:22:14 +0200 Subject: [PATCH 089/141] fix portals dying due to nummasks being too small and causing an overflow ty hannu! --- src/r_main.cpp | 2 +- src/r_things.cpp | 4 ++-- src/r_things.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/r_main.cpp b/src/r_main.cpp index 80c176ca5..bfbf8781a 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1355,7 +1355,7 @@ static fixed_t viewfov[MAXSPLITSCREENPLAYERS]; void R_RenderPlayerView(player_t *player) { - UINT8 nummasks = 1; + INT32 nummasks = 1; maskcount_t* masks = static_cast(malloc(sizeof(maskcount_t))); const boolean skybox = (skyboxmo[0] && cv_skybox.value); UINT8 i; diff --git a/src/r_things.cpp b/src/r_things.cpp index ba2fa82a5..12286995f 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -3016,9 +3016,9 @@ static void R_DrawMaskedList(drawnode_t* head) } } -void R_DrawMasked(maskcount_t* masks, UINT8 nummasks) +void R_DrawMasked(maskcount_t* masks, INT32 nummasks) { - UINT8 i; + INT32 i; drawnode_t *heads; /**< Drawnode lists; as many as number of views/portals. */ heads = static_cast(calloc(nummasks, sizeof(drawnode_t))); diff --git a/src/r_things.h b/src/r_things.h index e042806fa..45f1fc30e 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -80,7 +80,7 @@ typedef struct sector_t* viewsector; } maskcount_t; -void R_DrawMasked(maskcount_t* masks, UINT8 nummasks); +void R_DrawMasked(maskcount_t* masks, INT32 nummasks); boolean R_ThingVisible(mobj_t *thing); boolean R_ThingWithinDist(mobj_t *thing, INT32 limit_dist); -- 2.54.0 From da706d89a561de271d366c1cd9beb494637b03f6 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 9 Jun 2025 22:18:57 +0200 Subject: [PATCH 090/141] absolutely disgusting hack for sky issues instead of homremoval, we draw the fucking skyplane before everything lmao there probably is a right way to fix this, but im too dumb for that needs some performance testing, but since i could move the semaphores back, its even better in some instances --- src/r_main.cpp | 6 +++++- src/r_plane.cpp | 45 +++++++++++++++++++++++++++++++++++++-------- src/r_plane.h | 1 + 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/src/r_main.cpp b/src/r_main.cpp index bfbf8781a..fca456509 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1391,13 +1391,15 @@ void R_RenderPlayerView(player_t *player) R_ClearClipSegs(); R_ClearDrawSegs(); + R_DrawSkyPlanes(); R_ClearPlanes(); R_ClearSprites(); + R_RenderViewpoint(&masks[nummasks - 1], false); R_ClipSprites(drawsegs, NULL); + R_DrawSkyPlanes(); // draw the fucker again to prevent some artifacts R_DrawPlanes(); - // well sometimes synchronization is off and may result in some visual glitching, oh well R_DrawMasked(masks, nummasks); } PS_STOP_TIMING(ps_skyboxtime); @@ -1479,6 +1481,8 @@ void R_RenderPlayerView(player_t *player) PS_STOP_TIMING(ps_sw_portaltime); PS_START_TIMING(ps_sw_planetime); + if (!skybox) + R_DrawSkyPlanes(); R_DrawPlanes(); PS_STOP_TIMING(ps_sw_planetime); // draw mid texture and sprite diff --git a/src/r_plane.cpp b/src/r_plane.cpp index cef2d2f50..2b0d8ae0e 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -698,9 +698,9 @@ void R_DrawPlanes(void) R_UpdatePlaneRipple(&ds); + srb2::g_main_threadpool->begin_sema(); for (i = 0; i < MAXVISPLANES; i++, pl++) { - srb2::g_main_threadpool->begin_sema(); for (pl = visplanes[i]; pl; pl = pl->next) { if (pl->ffloor != NULL || pl->polyobj != NULL) @@ -708,10 +708,37 @@ void R_DrawPlanes(void) R_DrawSinglePlane(&ds, pl, cv_parallelsoftware.value); } - tp_sema = srb2::g_main_threadpool->end_sema(); - srb2::g_main_threadpool->notify_sema(tp_sema); - srb2::g_main_threadpool->wait_sema(tp_sema); } + tp_sema = srb2::g_main_threadpool->end_sema(); + srb2::g_main_threadpool->notify_sema(tp_sema); + srb2::g_main_threadpool->wait_sema(tp_sema); +} + +static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), boolean allow_parallel); + +void R_DrawSkyPlanes(void) +{ + visplane_t *pl; + INT32 i; + srb2::ThreadPool::Sema tp_sema; + + srb2::g_main_threadpool->begin_sema(); + for (i = 0; i < MAXVISPLANES; i++, pl++) + { + for (pl = visplanes[i]; pl; pl = pl->next) + { + if (pl->ffloor != NULL || pl->polyobj != NULL) + continue; + + if (pl->picnum != skyflatnum) + continue; + + R_DrawSkyPlane(pl, colfunc, cv_parallelsoftware.value); + } + } + tp_sema = srb2::g_main_threadpool->end_sema(); + srb2::g_main_threadpool->notify_sema(tp_sema); + srb2::g_main_threadpool->wait_sema(tp_sema); } static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), boolean allow_parallel) @@ -723,9 +750,6 @@ static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), b // This probably utterly ruins sky rendering for FOFs and polyobjects, unfortunately if (!newview->sky) { - // Mark that the sky was visible here for next tic - // (note: this is a hack and it sometimes can cause HOMs to appear for a tic IIRC) - skyVisible = true; return; } @@ -941,7 +965,12 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle // sky flat if (pl->picnum == skyflatnum) { - R_DrawSkyPlane(pl, colfunc, allow_parallel); + // horrific + if (!newview->sky) + { + skyVisible = true; + } + return; } diff --git a/src/r_plane.h b/src/r_plane.h index 78b92cc83..35e3f2b08 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -79,6 +79,7 @@ void R_AllocPlaneMemory(void); void R_ClearPlanes(void); void R_ClearFFloorClips (void); +void R_DrawSkyPlanes(void); void R_DrawPlanes(void); visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, fixed_t xoff, fixed_t yoff, angle_t plangle, -- 2.54.0 From 2984795175f73d420afafd9144b886acd6a5d778 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 9 Jun 2025 23:44:19 +0200 Subject: [PATCH 091/141] =?UTF-8?q?kill=20the=20splitscreen=20l=C3=B6?= =?UTF-8?q?=C3=B6ps=20from=20R=5FRenderPlayerView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this already gets called from within the one that assigns viewssnum which we can just use here --- src/r_main.cpp | 35 ++++++++--------------------------- 1 file changed, 8 insertions(+), 27 deletions(-) diff --git a/src/r_main.cpp b/src/r_main.cpp index fca456509..69b95b42a 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1355,31 +1355,19 @@ static fixed_t viewfov[MAXSPLITSCREENPLAYERS]; void R_RenderPlayerView(player_t *player) { - INT32 nummasks = 1; - maskcount_t* masks = static_cast(malloc(sizeof(maskcount_t))); - const boolean skybox = (skyboxmo[0] && cv_skybox.value); - UINT8 i; + INT32 nummasks = 1; + maskcount_t* masks = static_cast(malloc(sizeof(maskcount_t))); + const boolean skybox = (skyboxmo[0] && cv_skybox.value); // load previous saved value of skyVisible for the player - for (i = 0; i <= splitscreen; i++) - { - if (player != &players[displayplayers[i]]) - continue; - - skyVisible = skyVisiblePerPlayer[i]; - break; - } + skyVisible = skyVisiblePerPlayer[viewssnum]; fixed_t fov = R_GetPlayerFov(player); - for (UINT8 j = 0; j <= splitscreen; j++) + if (viewfov[viewssnum] != fov) { - if (player == &players[displayplayers[j]] - && viewfov[j] != fov) - { - viewfov[j] = fov; - R_SetFov(fov); - } + viewfov[viewssnum] = fov; + R_SetFov(fov); } Portal_InitList(); @@ -1498,14 +1486,7 @@ void R_RenderPlayerView(player_t *player) // save value to skyVisiblePerPlayer // this is so that P1 can't affect whether P2 can see a skybox or not, or vice versa - for (i = 0; i <= splitscreen; i++) - { - if (player != &players[displayplayers[i]]) - continue; - - skyVisiblePerPlayer[i] = skyVisible; - break; - } + skyVisiblePerPlayer[viewssnum] = skyVisible; } // ========================================================================= -- 2.54.0 From 62a660bfe1f6c6a8312f1920b34d008e3c89110c Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 9 Jun 2025 22:28:15 +0200 Subject: [PATCH 092/141] maybe this makes perf better somehow --- src/r_segs.cpp | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/src/r_segs.cpp b/src/r_segs.cpp index 7bb80f6b1..ca887f033 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -1878,6 +1878,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) else { // two sided line + boolean bothceilingssky = false; // turned on if both back and front ceilings are sky + SLOPEPARAMS(backsector->c_slope, worldhigh, worldhighslope, backsector->ceilingheight) SLOPEPARAMS(backsector->f_slope, worldlow, worldlowslope, backsector->floorheight) worldhigh -= viewz; @@ -1892,6 +1894,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) { worldtopslope = worldhighslope = worldtop = worldhigh; + + bothceilingssky = true; } ds_p->sprtopclip = ds_p->sprbottomclip = NULL; @@ -1912,18 +1916,22 @@ void R_StoreWallRange(INT32 start, INT32 stop) // ds_p->sprbottomclip = negonearray; } - if (worldtopslope < worldhighslope || worldtop < worldhigh) + if (!bothceilingssky) { - ds_p->silhouette |= SIL_TOP; - if (P_GetSectorCeilingZAt(backsector, viewx, viewy) < viewz) + if (worldtopslope < worldhighslope || worldtop < worldhigh) + { + ds_p->silhouette |= SIL_TOP; + if (P_GetSectorCeilingZAt(backsector, viewx, viewy) < viewz) + ds_p->tsilheight = INT32_MIN; + else + ds_p->tsilheight = (frontsector->c_slope ? INT32_MIN : frontsector->ceilingheight); + } + else if (P_GetSectorCeilingZAt(backsector, viewx, viewy) < viewz) + { + ds_p->silhouette |= SIL_TOP; ds_p->tsilheight = INT32_MIN; - else - ds_p->tsilheight = (frontsector->c_slope ? INT32_MIN : frontsector->ceilingheight); - } - else if (P_GetSectorCeilingZAt(backsector, viewx, viewy) < viewz) - { - ds_p->silhouette |= SIL_TOP; - ds_p->tsilheight = INT32_MIN; + // ds_p->sprtopclip = screenheightarray; + } } if (viewsector != frontsector && viewsector != backsector) @@ -2001,7 +2009,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) } // check TOP TEXTURE - if (worldhigh < worldtop || worldhighslope < worldtopslope) + if (!bothceilingssky // never draw the top texture if on + && (worldhigh < worldtop || worldhighslope < worldtopslope)) { fixed_t texheight; // top texture @@ -2043,6 +2052,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) rw_toptextureslide = ceilingbackslide; } } + // check BOTTOM TEXTURE if (worldlow > worldbottom || worldlowslope > worldbottomslope) // Only if VISIBLE!!! { @@ -2403,7 +2413,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) topstep = -FixedMul (rw_scalestep, worldtop); topfrac = (centeryfrac>>4) - FixedMul (worldtop, rw_scale); - bottomstep = -FixedMul (rw_scalestep,worldbottom); + bottomstep = -FixedMul (rw_scalestep, worldbottom); bottomfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale); if (frontsector->c_slope) @@ -2520,7 +2530,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (toptexture) { - fixed_t topfracend = (centeryfrac>>4) - FixedMul (worldhighslope, ds_p->scale2); + fixed_t topfracend = (centeryfrac>>4) - FixedMul(worldhighslope, ds_p->scale2); pixhigh = (centeryfrac>>4) - FixedMul (worldhigh, rw_scale); pixhighstep = (topfracend-pixhigh)/(range); -- 2.54.0 From 1d722be4bce47ef8dca565f307c2ef57694966a0 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 10 Jun 2025 01:21:22 +0200 Subject: [PATCH 093/141] few smoler optimizations r_segs --- src/r_segs.cpp | 60 ++++++++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/src/r_segs.cpp b/src/r_segs.cpp index ca887f033..2891f1d7b 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -465,9 +465,9 @@ static boolean R_CheckBlendMode(drawcolumndata_t* dc, const line_t *ldef) } else if (ldef->special == 909) { - R_SetColumnFunc(COLDRAWFUNC_FOG); windowtop = frontsector->ceilingheight; windowbottom = frontsector->floorheight; + R_SetColumnFunc(COLDRAWFUNC_FOG); } else { @@ -585,7 +585,7 @@ static void R_DrawRepeatMaskedColumn(drawcolumndata_t* dc, column_t *col) static boolean R_IsFFloorTranslucent(visffloor_t *pfloor) { if (pfloor->polyobj) - return (pfloor->polyobj->translucency > 0); + return true; // Polyobjects have no ffloors, and they're handled in the conditional above. if (pfloor->ffloor != NULL) @@ -851,12 +851,10 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf } } - if (slopeskew) + if (slopeskew && skewslope) { angle_t lineangle = R_PointToAngle2(curline->v1->x, curline->v1->y, curline->v2->x, curline->v2->y); - - if (skewslope) - ffloortextureslide = FixedMul(skewslope->zdelta, FINECOSINE((lineangle-skewslope->xydirection)>>ANGLETOFINESHIFT)); + ffloortextureslide = FixedMul(skewslope->zdelta, FINECOSINE((lineangle-skewslope->xydirection)>>ANGLETOFINESHIFT)); } dc->texturemid += offsetvalue; @@ -1131,9 +1129,9 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf // R_FFloorCanClip // // Returns true if a fake floor can clip a column away. -static boolean R_FFloorCanClip(visffloor_t *pfloor) +static inline boolean R_FFloorCanClip(visffloor_t *pfloor) { - return (cv_ffloorclip.value && !R_IsFFloorTranslucent(pfloor) && !pfloor->polyobj); + return (cv_ffloorclip.value && !R_IsFFloorTranslucent(pfloor)); } // R_ExpandPlaneY @@ -1823,19 +1821,25 @@ void R_StoreWallRange(INT32 start, INT32 stop) rw_toptextureslide = rw_midtextureslide = rw_bottomtextureslide = 0; ceilingfrontslide = floorfrontslide = ceilingbackslide = floorbackslide = 0; - angle_t lineangle = R_PointToAngle2(curline->v1->x, curline->v1->y, curline->v2->x, curline->v2->y); + if (backsector || frontsector->f_slope || frontsector->c_slope) + { + angle_t lineangle = R_PointToAngle2(curline->v1->x, curline->v1->y, curline->v2->x, curline->v2->y); - if (frontsector->f_slope) - floorfrontslide = FixedMul(frontsector->f_slope->zdelta, FINECOSINE((lineangle-frontsector->f_slope->xydirection)>>ANGLETOFINESHIFT)); + if (frontsector->f_slope) + floorfrontslide = FixedMul(frontsector->f_slope->zdelta, FINECOSINE((lineangle-frontsector->f_slope->xydirection)>>ANGLETOFINESHIFT)); - if (frontsector->c_slope) - ceilingfrontslide = FixedMul(frontsector->c_slope->zdelta, FINECOSINE((lineangle-frontsector->c_slope->xydirection)>>ANGLETOFINESHIFT)); + if (frontsector->c_slope) + ceilingfrontslide = FixedMul(frontsector->c_slope->zdelta, FINECOSINE((lineangle-frontsector->c_slope->xydirection)>>ANGLETOFINESHIFT)); - if (backsector && backsector->f_slope) - floorbackslide = FixedMul(backsector->f_slope->zdelta, FINECOSINE((lineangle-backsector->f_slope->xydirection)>>ANGLETOFINESHIFT)); + if (backsector) + { + if (backsector->f_slope) + floorbackslide = FixedMul(backsector->f_slope->zdelta, FINECOSINE((lineangle-backsector->f_slope->xydirection)>>ANGLETOFINESHIFT)); - if (backsector && backsector->c_slope) - ceilingbackslide = FixedMul(backsector->c_slope->zdelta, FINECOSINE((lineangle-backsector->c_slope->xydirection)>>ANGLETOFINESHIFT)); + if (backsector->c_slope) + ceilingbackslide = FixedMul(backsector->c_slope->zdelta, FINECOSINE((lineangle-backsector->c_slope->xydirection)>>ANGLETOFINESHIFT)); + } + } if (!backsector) { @@ -2328,7 +2332,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) } // calculate rw_offset (only needed for textured lines) - segtextured = midtexture || toptexture || bottomtexture || maskedtexture || (numthicksides > 0); + segtextured = (midtexture || toptexture || bottomtexture || maskedtexture || (numthicksides > 0)); if (segtextured) { @@ -2829,15 +2833,19 @@ void R_StoreWallRange(INT32 start, INT32 stop) lastopening += rw_stopx - start; } - if (maskedtexture && !(ds_p->silhouette & SIL_TOP)) + if (maskedtexture) { - ds_p->silhouette |= SIL_TOP; - ds_p->tsilheight = (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) ? INT32_MIN: INT32_MAX; - } - if (maskedtexture && !(ds_p->silhouette & SIL_BOTTOM)) - { - ds_p->silhouette |= SIL_BOTTOM; - ds_p->bsilheight = (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) ? INT32_MAX: INT32_MIN; + if (!(ds_p->silhouette & SIL_TOP)) + { + ds_p->silhouette |= SIL_TOP; + ds_p->tsilheight = (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) ? INT32_MIN: INT32_MAX; + } + + if (!(ds_p->silhouette & SIL_BOTTOM)) + { + ds_p->silhouette |= SIL_BOTTOM; + ds_p->bsilheight = (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) ? INT32_MAX: INT32_MIN; + } } ds_p++; -- 2.54.0 From f1a82106634f88a91a53b19c0a559808ea805b0f Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 10 Jun 2025 18:00:33 +0200 Subject: [PATCH 094/141] another attempt at actually fixing sky issues absolutely fucking horrible but this also does account for single sided lines aswell and gets rid of artifacts and perf --- src/r_main.cpp | 1 - src/r_segs.cpp | 20 ++++++++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/r_main.cpp b/src/r_main.cpp index 69b95b42a..c30574d46 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1379,7 +1379,6 @@ void R_RenderPlayerView(player_t *player) R_ClearClipSegs(); R_ClearDrawSegs(); - R_DrawSkyPlanes(); R_ClearPlanes(); R_ClearSprites(); diff --git a/src/r_segs.cpp b/src/r_segs.cpp index 2891f1d7b..9638a458e 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -17,6 +17,7 @@ #include "r_portal.h" #include "r_splats.h" +#include "r_fps.h" // newview #include "w_wad.h" #include "z_zone.h" @@ -2414,8 +2415,23 @@ void R_StoreWallRange(INT32 start, INT32 stop) } else { - topstep = -FixedMul (rw_scalestep, worldtop); - topfrac = (centeryfrac>>4) - FixedMul (worldtop, rw_scale); + // this is an attempt to fix issues with textureless midtextures drawing nothing where they should just draw sky instead + if ((newview->sky // only do this for skyrender + && viewz < P_GetSectorCeilingZAt(frontsector, viewx, viewy) + && (!midtexture && !curline->sidedef->midtexture && !curline->polyseg) + && ((!backsector && frontsector->ceilingpic == skyflatnum) + || ((backsector && backsector->ceilingpic == skyflatnum) + && (worldhigh <= worldtop && worldhighslope <= worldtopslope) + && (worldhigh != worldtop || worldhighslope != worldtopslope))))) + { + topstep = -FixedMul (rw_scalestep, worldbottom); + topfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale); + } + else + { + topstep = -FixedMul (rw_scalestep, worldtop); + topfrac = (centeryfrac>>4) - FixedMul (worldtop, rw_scale); + } bottomstep = -FixedMul (rw_scalestep, worldbottom); bottomfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale); -- 2.54.0 From 82407c356098db3aa2ff872148f8fe0349704211 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 10 Jun 2025 23:01:58 +0200 Subject: [PATCH 095/141] add missing plane bounds check to R_DrawSkyPlane --- src/r_plane.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 2b0d8ae0e..26b593b9f 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -746,6 +746,9 @@ static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), b INT32 x; drawcolumndata_t dc = {}; + if (!(pl->minx <= pl->maxx)) + return; + // If we're not supposed to draw the sky (e.g. for skyboxes), don't do anything! // This probably utterly ruins sky rendering for FOFs and polyobjects, unfortunately if (!newview->sky) -- 2.54.0 From eb132b08c016c205e89de6ae7675d0ac1968caaa Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 10 Jun 2025 23:27:16 +0200 Subject: [PATCH 096/141] make the check a little more robust + account for slopes a little --- src/r_segs.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/r_segs.cpp b/src/r_segs.cpp index 9638a458e..b0edd3285 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -2419,13 +2419,19 @@ void R_StoreWallRange(INT32 start, INT32 stop) if ((newview->sky // only do this for skyrender && viewz < P_GetSectorCeilingZAt(frontsector, viewx, viewy) && (!midtexture && !curline->sidedef->midtexture && !curline->polyseg) - && ((!backsector && frontsector->ceilingpic == skyflatnum) - || ((backsector && backsector->ceilingpic == skyflatnum) + && ((!backsector && frontsector->ceilingpic == skyflatnum && frontsector->floorpic != skyflatnum) + || ((backsector && backsector->ceilingpic == skyflatnum && frontsector->ceilingpic != skyflatnum) && (worldhigh <= worldtop && worldhighslope <= worldtopslope) && (worldhigh != worldtop || worldhighslope != worldtopslope))))) { topstep = -FixedMul (rw_scalestep, worldbottom); topfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale); + + if (frontsector->f_slope || (backsector && backsector->f_slope)) + { + topstep = -FixedMul (rw_scalestep, worldbottomslope); + topfrac = (centeryfrac>>4) - FixedMul (worldbottomslope, rw_scale); + } } else { -- 2.54.0 From e90c84c9ac4fb44f65c27c1075f3b55020b2c22d Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 11 Jun 2025 16:32:25 +0200 Subject: [PATCH 097/141] we have a var for that lul --- src/r_plane.cpp | 5 +---- src/r_segs.cpp | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 26b593b9f..b3aa29f7b 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -727,10 +727,7 @@ void R_DrawSkyPlanes(void) { for (pl = visplanes[i]; pl; pl = pl->next) { - if (pl->ffloor != NULL || pl->polyobj != NULL) - continue; - - if (pl->picnum != skyflatnum) + if (pl->picnum != skyflatnum || pl->ffloor != NULL || pl->polyobj != NULL) continue; R_DrawSkyPlane(pl, colfunc, cv_parallelsoftware.value); diff --git a/src/r_segs.cpp b/src/r_segs.cpp index b0edd3285..4038c7a0b 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -1421,7 +1421,7 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) // single sided line if (yl <= yh && yh >= 0 && yl < viewheight) { - R_DrawWallColumn(dc, yl, yh, rw_midtexturemid, texturecolumn, midtexture, (encoremap && !(curline->linedef->flags & ML_TFERLINE))); + R_DrawWallColumn(dc, yl, yh, rw_midtexturemid, texturecolumn, midtexture, midremap); // dont draw anything more for this column, since // a midtexture blocks the view -- 2.54.0 From 918a4e8cd944dee29d587fc4fcfdb5635ae9a2f2 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 11 Jun 2025 17:10:47 +0200 Subject: [PATCH 098/141] add tilted fog span drawer fixes the red fog blocks on mkrevamp --- src/r_draw.h | 2 ++ src/r_draw_span.c | 40 ++++++++++++++++++++++++++++++++++++++++ src/r_plane.cpp | 3 +++ src/screen.c | 1 + 4 files changed, 46 insertions(+) diff --git a/src/r_draw.h b/src/r_draw.h index 946139ac1..fc8b344e7 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -141,6 +141,7 @@ enum SPANDRAWFUNC_TILTEDWATER, SPANDRAWFUNC_FOG, + SPANDRAWFUNC_TILTEDFOG, SPANDRAWFUNC_MAX }; @@ -258,6 +259,7 @@ void R_DrawTranslucentSpan(drawspandata_t* ds); void R_DrawTranslucentWaterSpan(drawspandata_t* ds); void R_DrawFogSpan(drawspandata_t* ds); +void R_DrawFogSpan_Tilted(drawspandata_t* ds); void R_DrawSplat_Tilted(drawspandata_t* ds); void R_DrawSplat(drawspandata_t* ds); diff --git a/src/r_draw_span.c b/src/r_draw_span.c index 54400fac4..15ae7b1a2 100644 --- a/src/r_draw_span.c +++ b/src/r_draw_span.c @@ -1188,3 +1188,43 @@ void R_DrawSplat_Tilted(drawspandata_t* ds) } #endif } + +void R_DrawFogSpan_Tilted(drawspandata_t* ds) +{ + int width = ds->x2 - ds->x1; + float iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); + register UINT8 *dest; + + local_for_thread INT32 *tiltlighting = NULL; + local_for_thread INT32 oldviewwidth = 0; + + // dont realloc every frame pls thx + if (tiltlighting == NULL || oldviewwidth != viewwidth) + { + tiltlighting = realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth); + oldviewwidth = viewwidth; + } + + dest = R_Address(ds->x1, ds->y); + + // Lighting is simple. It's just linear interpolation from start to end + { + float planelightfloat = PLANELIGHTFLOAT; + float lightstart, lightend; + + lightend = (iz + ds->szp.x*width) * planelightfloat; + lightstart = iz * planelightfloat; + + R_CalcTiltedLighting(tiltlighting, ds->x1, ds->x2, FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); + //CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf); + } + + do + { + UINT8 *colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); + *dest = colormap[*dest]; + dest++; + } + while (--width >= 0); +} + diff --git a/src/r_plane.cpp b/src/r_plane.cpp index b3aa29f7b..c7a5f793b 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -1213,6 +1213,9 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle case SPANDRAWFUNC_SPLAT: spanfunctype = SPANDRAWFUNC_TILTEDSPLAT; break; + case SPANDRAWFUNC_FOG: + spanfunctype = SPANDRAWFUNC_TILTEDFOG; + break; default: spanfunctype = SPANDRAWFUNC_TILTED; break; diff --git a/src/screen.c b/src/screen.c index 3d83d57fb..cec9b4b9b 100644 --- a/src/screen.c +++ b/src/screen.c @@ -94,6 +94,7 @@ static void SCR_SetDrawFuncs(void) spanfuncs[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan; spanfuncs[SPANDRAWFUNC_TILTEDWATER] = R_DrawTranslucentWaterSpan_Tilted; spanfuncs[SPANDRAWFUNC_FOG] = R_DrawFogSpan; + spanfuncs[SPANDRAWFUNC_TILTEDFOG] = R_DrawFogSpan_Tilted; colfuncs[BASEDRAWFUNC] = R_DrawColumn; colfuncs[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn; -- 2.54.0 From bf78ad9c75d8caeb903cf22d4f762bcb8afefc43 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 11 Jun 2025 19:07:36 +0200 Subject: [PATCH 099/141] absolute insanity to hopefully fix all sky issues while keeping skyvisible --- src/r_segs.cpp | 62 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 18 deletions(-) diff --git a/src/r_segs.cpp b/src/r_segs.cpp index 4038c7a0b..76b0b7ea0 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -2415,29 +2415,55 @@ void R_StoreWallRange(INT32 start, INT32 stop) } else { - // this is an attempt to fix issues with textureless midtextures drawing nothing where they should just draw sky instead - if ((newview->sky // only do this for skyrender - && viewz < P_GetSectorCeilingZAt(frontsector, viewx, viewy) - && (!midtexture && !curline->sidedef->midtexture && !curline->polyseg) - && ((!backsector && frontsector->ceilingpic == skyflatnum && frontsector->floorpic != skyflatnum) - || ((backsector && backsector->ceilingpic == skyflatnum && frontsector->ceilingpic != skyflatnum) - && (worldhigh <= worldtop && worldhighslope <= worldtopslope) - && (worldhigh != worldtop || worldhighslope != worldtopslope))))) - { - topstep = -FixedMul (rw_scalestep, worldbottom); - topfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale); + // for everyone that sees this + // dont. + // this is absolute shit-tier hacks + // but i just cant determine this in any sane way + // but this checks a shitton of things to make software handle skies better - if (frontsector->f_slope || (backsector && backsector->f_slope)) - { - topstep = -FixedMul (rw_scalestep, worldbottomslope); - topfrac = (centeryfrac>>4) - FixedMul (worldbottomslope, rw_scale); - } - } - else + const bool emptymid = (!midtexture && !curline->sidedef->midtexture && !curline->polyseg); + + auto set_topstep_normal = [&] { topstep = -FixedMul (rw_scalestep, worldtop); topfrac = (centeryfrac>>4) - FixedMul (worldtop, rw_scale); + }; + + if (emptymid) + { + const bool tophigh = (backsector && worldhigh <= worldtop && worldhighslope <= worldtopslope) + && (worldhigh != worldtop || worldhighslope != worldtopslope); + + // if we cant see the goddamn skyplane, well there wont be any skybox + // we could kill skyVisible instead, but i want to keep the performance improvemnts it yields + // so we do this absolute trash + if ((frontsector->floorpic != skyflatnum && frontsector->ceilingpic != skyflatnum) + && ((!backsector && frontsector->ceilingpic != skyflatnum && frontsector->floorpic != skyflatnum) + || (tophigh && (frontsector->ceilingpic != skyflatnum) + && (backsector->floorheight > frontsector->ceilingheight || backsector->ceilingheight < frontsector->floorheight)))) + skyVisible = true; + + // this is an attempt to fix issues with textureless midtextures drawing nothing where they should just draw sky instead + if ((newview->sky // only do this for skyrender + && viewz < P_GetSectorCeilingZAt(frontsector, viewx, viewy) // looks ugly while our cam is in the sky + && ((!backsector && frontsector->ceilingpic == skyflatnum && frontsector->floorpic != skyflatnum) + || (tophigh && (backsector->ceilingpic == skyflatnum && frontsector->ceilingpic != skyflatnum))))) + { + topstep = -FixedMul (rw_scalestep, worldbottom); + topfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale); + + // account for slopes to try and get rid of sharp edges from the black void + if (frontsector->f_slope || (backsector && backsector->f_slope)) + { + topstep = -FixedMul (rw_scalestep, worldbottomslope); + topfrac = (centeryfrac>>4) - FixedMul (worldbottomslope, rw_scale); + } + } + else + set_topstep_normal(); } + else + set_topstep_normal(); bottomstep = -FixedMul (rw_scalestep, worldbottom); bottomfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale); -- 2.54.0 From ab30fb2e5e7315e92ed004f21923de6da9eceaa2 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 12 Jun 2025 17:08:09 +0200 Subject: [PATCH 100/141] check if seg has any texture at all seems to work even better and less "false positives" also removing some redundant conditons --- src/r_segs.cpp | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/r_segs.cpp b/src/r_segs.cpp index 76b0b7ea0..a4f384af4 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -2415,21 +2415,20 @@ void R_StoreWallRange(INT32 start, INT32 stop) } else { - // for everyone that sees this + // for anyone that sees this // dont. // this is absolute shit-tier hacks // but i just cant determine this in any sane way // but this checks a shitton of things to make software handle skies better - const bool emptymid = (!midtexture && !curline->sidedef->midtexture && !curline->polyseg); - auto set_topstep_normal = [&] { topstep = -FixedMul (rw_scalestep, worldtop); topfrac = (centeryfrac>>4) - FixedMul (worldtop, rw_scale); }; - if (emptymid) + // untextured seg + if (!segtextured && !curline->polyseg) { const bool tophigh = (backsector && worldhigh <= worldtop && worldhighslope <= worldtopslope) && (worldhigh != worldtop || worldhighslope != worldtopslope); @@ -2437,17 +2436,15 @@ void R_StoreWallRange(INT32 start, INT32 stop) // if we cant see the goddamn skyplane, well there wont be any skybox // we could kill skyVisible instead, but i want to keep the performance improvemnts it yields // so we do this absolute trash - if ((frontsector->floorpic != skyflatnum && frontsector->ceilingpic != skyflatnum) - && ((!backsector && frontsector->ceilingpic != skyflatnum && frontsector->floorpic != skyflatnum) - || (tophigh && (frontsector->ceilingpic != skyflatnum) - && (backsector->floorheight > frontsector->ceilingheight || backsector->ceilingheight < frontsector->floorheight)))) + if ((frontsector->floorpic != skyflatnum && frontsector->ceilingpic != skyflatnum) // try to guess if its a "window" + && ((!backsector) // single sided + || (tophigh && (backsector->floorheight > frontsector->ceilingheight || backsector->ceilingheight < frontsector->floorheight)))) // check if there is a "thok" sector behind it skyVisible = true; // this is an attempt to fix issues with textureless midtextures drawing nothing where they should just draw sky instead if ((newview->sky // only do this for skyrender - && viewz < P_GetSectorCeilingZAt(frontsector, viewx, viewy) // looks ugly while our cam is in the sky - && ((!backsector && frontsector->ceilingpic == skyflatnum && frontsector->floorpic != skyflatnum) - || (tophigh && (backsector->ceilingpic == skyflatnum && frontsector->ceilingpic != skyflatnum))))) + && ((!backsector && frontsector->ceilingpic == skyflatnum) // single sided line with sky ceiling + || (tophigh && (backsector->ceilingpic == skyflatnum && frontsector->ceilingpic != skyflatnum))))) // double sided with back ceiling sky but not front ceiling sky { topstep = -FixedMul (rw_scalestep, worldbottom); topfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale); -- 2.54.0 From b6d771b48fa1b45a3c92277fab9bd0a8e3c8d82b Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 12 Jun 2025 17:09:06 +0200 Subject: [PATCH 101/141] unnest the skybox scale setup stuff --- src/r_main.cpp | 142 ++++++++++++++++++++++++++---------------------- src/r_plane.cpp | 2 +- 2 files changed, 79 insertions(+), 65 deletions(-) diff --git a/src/r_main.cpp b/src/r_main.cpp index c30574d46..fa3293ee1 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1107,17 +1107,88 @@ static void R_SetupAimingFrame(player_t *player, camera_t *thiscam) } } +static void R_SetupSkyScale(player_t *player, camera_t *thiscam, mapheader_t *mh) +{ + if (!mh->skybox_scalex && !mh->skybox_scaley && !mh->skybox_scalez) + return; + + auto setup_skyscale = [&](fixed_t mox, fixed_t moy, fixed_t zscale) + { + if (skyboxmo[1]) + { + fixed_t x = 0, y = 0; + + if (mh->skybox_scalex > 0) + x = (mox - skyboxmo[1]->x) / mh->skybox_scalex; + else if (mh->skybox_scalex < 0) + x = (mox - skyboxmo[1]->x) * -mh->skybox_scalex; + + if (mh->skybox_scaley > 0) + y = (moy - skyboxmo[1]->y) / mh->skybox_scaley; + else if (mh->skybox_scaley < 0) + y = (moy - skyboxmo[1]->y) * -mh->skybox_scaley; + + if (viewmobj->angle == 0) + { + newview->x += x; + newview->y += y; + } + else if (viewmobj->angle == ANGLE_90) + { + newview->x -= y; + newview->y += x; + } + else if (viewmobj->angle == ANGLE_180) + { + newview->x -= x;\ + newview->y -= y;\ + } + else if (viewmobj->angle == ANGLE_270) + { + newview->x += y; + newview->y -= x; + } + else + { + angle_t ang = viewmobj->angle>>ANGLETOFINESHIFT; + newview->x += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang)); + newview->y += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang)); + } + } + + if (mh->skybox_scalez > 0) + newview->z += zscale / mh->skybox_scalez; + else if (mh->skybox_scalez < 0) + newview->z += zscale * -mh->skybox_scalez; + }; + + if (player->awayviewtics && player->awayviewmobj) + { + setup_skyscale(player->awayviewmobj->x, player->awayviewmobj->y, (player->awayviewmobj->z + 20*FRACUNIT)); + } + else if (thiscam && thiscam->chase) + { + setup_skyscale(thiscam->x, thiscam->y, (thiscam->z + (thiscam->height>>1))); + } + else + { + setup_skyscale(player->mo->x, player->mo->y, player->viewz); + } +} + void R_SkyboxFrame(int s) { player_t *player = &players[displayplayers[s]]; camera_t *thiscam = &camera[s]; subsector_t * subsector = NULL; + mapheader_t *mh = mapheaderinfo[gamemap-1]; R_SetViewContext(static_cast(VIEWCONTEXT_SKY1 + s)); // cut-away view stuff newview->sky = true; viewmobj = skyboxmo[0]; + #ifdef PARANOIA if (P_MobjWasRemoved(viewmobj)) { @@ -1125,78 +1196,19 @@ void R_SkyboxFrame(int s) I_Error("R_SkyboxFrame: viewmobj null (player %s)", sizeu1(playeri)); } #endif + R_SetupAimingFrame(player, thiscam); newview->angle += viewmobj->angle; newview->x = viewmobj->x; newview->y = viewmobj->y; - newview->z = 0; - if (viewmobj->spawnpoint) - newview->z = ((fixed_t)viewmobj->spawnpoint->angle)<z = (viewmobj->spawnpoint) ? (((fixed_t)viewmobj->spawnpoint->angle)<skybox_scalex > 0)\ - x = (viewmo->x - skyboxmo[1]->x) / mh->skybox_scalex;\ - else if (mh->skybox_scalex < 0)\ - x = (viewmo->x - skyboxmo[1]->x) * -mh->skybox_scalex;\ - if (mh->skybox_scaley > 0)\ - y = (viewmo->y - skyboxmo[1]->y) / mh->skybox_scaley;\ - else if (mh->skybox_scaley < 0)\ - y = (viewmo->y - skyboxmo[1]->y) * -mh->skybox_scaley;\ - if (viewmobj->angle == 0)\ - {\ - newview->x += x;\ - newview->y += y;\ - }\ - else if (viewmobj->angle == ANGLE_90)\ - {\ - newview->x -= y;\ - newview->y += x;\ - }\ - else if (viewmobj->angle == ANGLE_180)\ - {\ - newview->x -= x;\ - newview->y -= y;\ - }\ - else if (viewmobj->angle == ANGLE_270)\ - {\ - newview->x += y;\ - newview->y -= x;\ - }\ - else\ - {\ - angle_t ang = viewmobj->angle>>ANGLETOFINESHIFT;\ - newview->x += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));\ - newview->y += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));\ - }\ - }\ - if (mh->skybox_scalez > 0)\ - newview->z += zscale / mh->skybox_scalez;\ - else if (mh->skybox_scalez < 0)\ - newview->z += zscale * -mh->skybox_scalez; - - if (mapheaderinfo[gamemap-1]) + if (mh) { - mapheader_t *mh = mapheaderinfo[gamemap-1]; - - if (player->awayviewtics && player->awayviewmobj) - { - SETUPSKYVIEW(player->awayviewmobj, (player->awayviewmobj->z + 20*FRACUNIT)); - } - else if (thiscam->chase) - { - SETUPSKYVIEW(thiscam, (thiscam->z + (thiscam->height>>1))); - } - else - { - SETUPSKYVIEW(player->mo, player->viewz); - } + R_SetupSkyScale(player, thiscam, mh); } -#undef SETUPSKYVIEW if (!P_MobjWasRemoved(viewmobj) && viewmobj->subsector && viewmobj->subsector->sector) subsector = viewmobj->subsector; @@ -1258,12 +1270,13 @@ void R_SetupFrame(int s, boolean skybox) else if (thiscam && chasecam) // use outside cam view { viewmobj = NULL; + I_Assert(thiscam != NULL); newview->x = thiscam->x; newview->y = thiscam->y; newview->z = thiscam->z + (thiscam->height>>1); - if (thiscam != NULL && thiscam->subsector && thiscam->subsector->sector) + if (thiscam->subsector && thiscam->subsector->sector) sector = thiscam->subsector->sector; R_SetupCommonFrame(player, sector); @@ -1526,6 +1539,7 @@ void R_RegisterEngineStuff(void) { CV_RegisterVar(&cv_chasecam[i]); } + CV_RegisterVar(&cv_shadow); CV_RegisterVar(&cv_shadowoffs); CV_RegisterVar(&cv_skybox); diff --git a/src/r_plane.cpp b/src/r_plane.cpp index c7a5f793b..33935dda8 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -727,7 +727,7 @@ void R_DrawSkyPlanes(void) { for (pl = visplanes[i]; pl; pl = pl->next) { - if (pl->picnum != skyflatnum || pl->ffloor != NULL || pl->polyobj != NULL) + if (pl->picnum != skyflatnum || pl->ffloor || pl->polyobj) continue; R_DrawSkyPlane(pl, colfunc, cv_parallelsoftware.value); -- 2.54.0 From 56021ed9995a4828b64e6a5f6b64cc2291478336 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 12 Jun 2025 19:48:25 +0200 Subject: [PATCH 102/141] dont compile with software multithread if NOTHREADS/HAVE_THREADS=0 might be useful for smth ig --- src/d_netfil.c | 8 ++++++ src/r_draw_span.c | 4 +++ src/r_main.cpp | 2 -- src/r_plane.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++-- src/r_segs.cpp | 1 - src/r_things.cpp | 4 +++ src/sdl/i_system.cpp | 10 ++++++- 7 files changed, 85 insertions(+), 6 deletions(-) diff --git a/src/d_netfil.c b/src/d_netfil.c index 0650f3c34..d45570a0e 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -111,7 +111,9 @@ static fileused_t transferFiles[UINT8_MAX + 1]; // Receiver structure INT32 fileneedednum; // Number of files needed to join the server fileneeded_t fileneeded[MAX_WADFILES]; // List of needed files +#ifdef HAVE_THREADS static I_mutex downloadmutex; +#endif char downloaddir[512] = "DOWNLOAD"; file_download_t filedownload; @@ -1351,14 +1353,18 @@ void CURLAbortFile(void) { filedownload.http_running = false; +#ifdef HAVE_THREADS // lock and unlock to wait for the download thread to exit I_lock_mutex(&downloadmutex); I_unlock_mutex(downloadmutex); +#endif } void CURLGetFile(void) { +#ifdef HAVE_THREADS I_lock_mutex(&downloadmutex); +#endif CURLMcode mc; /* return code used by curl_multi_wait() */ CURLcode easyres; /* Return from easy interface */ CURLMsg *m; /* for picking up messages with the transfer status */ @@ -1453,7 +1459,9 @@ void CURLGetFile(void) } filedownload.http_running = false; +#ifdef HAVE_THREADS I_unlock_mutex(downloadmutex); +#endif } HTTP_login * diff --git a/src/r_draw_span.c b/src/r_draw_span.c index 15ae7b1a2..d7a9aaa68 100644 --- a/src/r_draw_span.c +++ b/src/r_draw_span.c @@ -15,6 +15,7 @@ // SPANS // ========================================================================== +#ifdef HAVE_THREADS #ifdef _WIN32 #include #define local_for_thread static __thread @@ -22,6 +23,9 @@ #include #define local_for_thread thread_local static #endif +#else +#define local_for_thread static +#endif #define SPANSIZE 16 #define INVSPAN 0.0625f diff --git a/src/r_main.cpp b/src/r_main.cpp index fa3293ee1..e0d75b6df 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -39,8 +39,6 @@ #include "r_fps.h" // Frame interpolation/uncapped #include "tables.h" -#include "core/thread_pool.h" - #ifdef HWRENDER #include "hardware/hw_main.h" #endif diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 33935dda8..24c3cb086 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -32,7 +32,9 @@ #include "r_fps.h" #include "r_portal.h" +#ifdef HAVE_THREADS #include "core/thread_pool.h" +#endif // // opening @@ -248,6 +250,7 @@ static void R_MapPlane(drawspandata_t *ds, spandrawfunc_t *localspanfunc, INT32 pindex = distance >> LIGHTZSHIFT; if (pindex >= MAXLIGHTZ) pindex = MAXLIGHTZ - 1; + ds->colormap = ds->planezlight[pindex]; if (encoremap && !ds->currentplane->noencore) @@ -356,6 +359,7 @@ void R_ClearPlanes(void) static visplane_t *new_visplane(unsigned hash) { visplane_t *check = freetail; + if (!check) { check = static_cast(calloc(1, sizeof (*check))); @@ -372,8 +376,10 @@ static visplane_t *new_visplane(unsigned hash) if (!freetail) freehead = &freetail; } + check->next = visplanes[hash]; visplanes[hash] = check; + return check; } @@ -618,12 +624,14 @@ static void R_MakeSpans(void (*mapfunc)(drawspandata_t* ds, void(*spanfunc)(draw if (b2 >= vidheight) b2 = vidheight-1; if (x-1 >= vid.width) x = vid.width; + drawspandata_t dc_copy = *ds; + +#ifdef HAVE_THREADS // We want to draw N spans per subtask to ensure the work is // coarse enough to not be too slow due to task scheduling overhead. // To safely do this, we need to copy part of spanstart to a local. // This is essentially loop unrolling across threads. constexpr const int kSpanTaskGranularity = 8; - drawspandata_t dc_copy = *ds; while (t1 < t2 && t1 <= b1) { INT32 spanstartcopy[kSpanTaskGranularity] = {0}; @@ -682,6 +690,20 @@ static void R_MakeSpans(void (*mapfunc)(drawspandata_t* ds, void(*spanfunc)(draw } b1 -= taskspans; } +#else + (void)allow_parallel; + + while (t1 < t2 && t1 <= b1) + { + mapfunc(&dc_copy, localspanfunc, t1, spanstart[t1], x - 1, false); + t1++; + } + while (b1 > b2 && b1 >= t1) + { + mapfunc(&dc_copy, localspanfunc, b1, spanstart[b1], x - 1, false); + b1--; + } +#endif while (t2 < t1 && t2 <= b2) spanstart[t2++] = x; @@ -694,11 +716,15 @@ void R_DrawPlanes(void) visplane_t *pl; INT32 i; drawspandata_t ds = {}; +#ifdef HAVE_THREADS srb2::ThreadPool::Sema tp_sema; +#endif R_UpdatePlaneRipple(&ds); +#ifdef HAVE_THREADS srb2::g_main_threadpool->begin_sema(); +#endif for (i = 0; i < MAXVISPLANES; i++, pl++) { for (pl = visplanes[i]; pl; pl = pl->next) @@ -709,9 +735,11 @@ void R_DrawPlanes(void) R_DrawSinglePlane(&ds, pl, cv_parallelsoftware.value); } } +#ifdef HAVE_THREADS tp_sema = srb2::g_main_threadpool->end_sema(); srb2::g_main_threadpool->notify_sema(tp_sema); srb2::g_main_threadpool->wait_sema(tp_sema); +#endif } static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), boolean allow_parallel); @@ -720,9 +748,11 @@ void R_DrawSkyPlanes(void) { visplane_t *pl; INT32 i; - srb2::ThreadPool::Sema tp_sema; +#ifdef HAVE_THREADS + srb2::ThreadPool::Sema tp_sema; srb2::g_main_threadpool->begin_sema(); +#endif for (i = 0; i < MAXVISPLANES; i++, pl++) { for (pl = visplanes[i]; pl; pl = pl->next) @@ -733,9 +763,11 @@ void R_DrawSkyPlanes(void) R_DrawSkyPlane(pl, colfunc, cv_parallelsoftware.value); } } +#ifdef HAVE_THREADS tp_sema = srb2::g_main_threadpool->end_sema(); srb2::g_main_threadpool->notify_sema(tp_sema); srb2::g_main_threadpool->wait_sema(tp_sema); +#endif } static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), boolean allow_parallel) @@ -781,6 +813,7 @@ static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), b R_GenerateTexture(texturetranslation[skytexture]); } +#ifdef HAVE_THREADS while (x <= pl->maxx) { // Tune concurrency granularity here to maximize throughput @@ -820,6 +853,31 @@ static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), b x += kSkyPlaneMacroColumns; } +#else + (void)allow_parallel; + + for (x = pl->minx; x <= pl->maxx; x++) + { + dc.yl = pl->top[x]; + dc.yh = pl->bottom[x]; + + if (dc.yl > dc.yh) + { + continue; + } + + INT32 angle = (pl->viewangle + xtoviewangle[x])>>ANGLETOSKYSHIFT; + angle -= (skytextureoffset >> FRACBITS); + + dc.iscale = FixedMul(skyscale, FINECOSINE(xtoviewangle[x]>>ANGLETOFINESHIFT)); + dc.x = x; + dc.source = + R_GetColumn(texturetranslation[skytexture], + -angle); // get negative of angle for each column to display sky correct way round! --Monster Iestyn 27/01/18 + + colfunc2(&dc); + } +#endif } // Returns the height of the sloped plane at (x, y) as a 32.16 fixed_t diff --git a/src/r_segs.cpp b/src/r_segs.cpp index a4f384af4..df4eebf56 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -30,7 +30,6 @@ #include "screen.h" #include "core/memory.h" -#include "core/thread_pool.h" #define HEIGHTBITS 12 #define HEIGHTUNIT (1<prev; +#ifdef HAVE_THREADS srb2::ThreadPool::Sema tp_sema; srb2::g_main_threadpool->begin_sema(); +#endif R_DrawSinglePlane(&ds, r2->plane, cv_parallelsoftware.value); +#ifdef HAVE_THREADS tp_sema = srb2::g_main_threadpool->end_sema(); srb2::g_main_threadpool->notify_sema(tp_sema); srb2::g_main_threadpool->wait_sema(tp_sema); +#endif R_DoneWithNode(r2); r2 = next; } diff --git a/src/sdl/i_system.cpp b/src/sdl/i_system.cpp index faf1bcbff..5282fc9d3 100644 --- a/src/sdl/i_system.cpp +++ b/src/sdl/i_system.cpp @@ -190,7 +190,6 @@ static char returnWadPath[256]; #include "../r_fps.h" #include "../s_sound.h" -#include "../core/thread_pool.h" #ifdef MAC_ALERT #include "macosx/mac_alert.h" @@ -204,7 +203,10 @@ static char returnWadPath[256]; #include "../byteptr.h" #endif +#ifdef HAVE_THREADS +#include "../core/thread_pool.h" static std::thread::id g_main_thread_id; +#endif INT32 numcontrollers = 0; @@ -500,6 +502,7 @@ static void I_ReportSignal(int num, int coredumped) #ifndef NEWSIGNALHANDLER FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num) { +#ifdef HAVE_THREADS if (g_main_thread_id != std::this_thread::get_id()) { // Do not attempt any sort of recovery if this signal triggers off the main thread @@ -507,6 +510,7 @@ FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num) raise(num); exit(-2); } +#endif g_in_exiting_signal_handler = true; @@ -870,7 +874,9 @@ static inline void I_ShutdownConsole(void){} // static void I_RegisterSignals (void) { +#ifdef HAVE_THREADS g_main_thread_id = std::this_thread::get_id(); +#endif #ifdef SIGINT signal(SIGINT , quit_handler); @@ -2015,11 +2021,13 @@ void I_Error(const char *error, ...) va_list argptr; char buffer[8192]; +#ifdef HAVE_THREADS if (std::this_thread::get_id() != g_main_thread_id) { // Do not attempt a graceful shutdown. Errors off the main thread are unresolvable. exit(-2); } +#endif // recursive error detecting if (shutdowning) -- 2.54.0 From ad15bf0ea3fcda6823af10f8ab58bb3d3d2fd9de Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 12 Jun 2025 19:48:44 +0200 Subject: [PATCH 103/141] readd some lost comments in r_bsp --- src/r_bsp.c | 49 +++++++++++++++++++++++-------------------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/src/r_bsp.c b/src/r_bsp.c index 1957ec862..833e378c5 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -349,6 +349,8 @@ static void R_AddLine(seg_t *line) // The seg is in the view range, but not necessarily visible. angle1 = (angle1+ANGLE_90)>>ANGLETOFINESHIFT; angle2 = (angle2+ANGLE_90)>>ANGLETOFINESHIFT; + + // killough 1/31/98: Here is where "slime trails" can SOMETIMES occur: x1 = viewangletox[angle1]; x2 = viewangletox[angle2]; @@ -494,20 +496,10 @@ static boolean R_CheckBBox(const fixed_t *bspcoord) INT32 sx1, sx2, boxpos; const INT32* check; - // Find the corners of the box that define the edges from current viewpoint. - if (viewx <= bspcoord[BOXLEFT]) - boxpos = 0; - else if (viewx < bspcoord[BOXRIGHT]) - boxpos = 1; - else - boxpos = 2; - - if (viewy >= bspcoord[BOXTOP]) - boxpos |= 0; - else if (viewy > bspcoord[BOXBOTTOM]) - boxpos |= 1<<2; - else - boxpos |= 2<<2; + // Find the corners of the box + // that define the edges from current viewpoint. + boxpos = (viewx <= bspcoord[BOXLEFT] ? 0 : viewx < bspcoord[BOXRIGHT ] ? 1 : 2) + + (viewy >= bspcoord[BOXTOP ] ? 0 : viewy > bspcoord[BOXBOTTOM] ? 4 : 8); if (boxpos == 5) return true; @@ -518,18 +510,23 @@ static boolean R_CheckBBox(const fixed_t *bspcoord) angle1 = R_PointToAngle64(bspcoord[check[0]], bspcoord[check[1]]) - viewangle; angle2 = R_PointToAngle64(bspcoord[check[2]], bspcoord[check[3]]) - viewangle; - if ((signed)angle1 < (signed)angle2) + // cph - replaced old code, which was unclear and badly commented + // Much more efficient code now + if ((signed)angle1 < (signed)angle2) /* it's "behind" us */ { + /* Either angle1 or angle2 is behind us, so it doesn't matter if we + * change it to the corect sign + */ if ((angle1 >= ANGLE_180) && (angle1 < ANGLE_270)) angle1 = ANGLE_180-1; else angle2 = ANGLE_180; } - if ((signed)angle2 >= (signed)clipangle) return false; - if ((signed)angle1 <= -(signed)clipangle) return false; - if ((signed)angle1 >= (signed)clipangle) angle1 = clipangle; - if ((signed)angle2 <= -(signed)clipangle) angle2 = 0-clipangle; + if ((signed)angle2 >= (signed)clipangle) return false; // Both off left edge + if ((signed)angle1 <= -(signed)clipangle) return false; // Both off right edge + if ((signed)angle1 >= (signed)clipangle) angle1 = clipangle; // Clip at left edge + if ((signed)angle2 <= -(signed)clipangle) angle2 = -(signed)clipangle; // Clip at right edge // Find the first clippost that touches the source post (adjacent pixels are touching). angle1 = (angle1+ANGLE_90)>>ANGLETOFINESHIFT; @@ -550,10 +547,9 @@ static boolean R_CheckBBox(const fixed_t *bspcoord) return true; } - size_t numpolys; // number of polyobjects in current subsector size_t num_po_ptrs; // number of polyobject pointers allocated -polyobj_t **po_ptrs; // temp ptr array to sort polyobject pointers +polyobj_t **po_ptrs; // temp ptr array to sort polyobject pointers // // R_PolyobjCompare @@ -738,14 +734,15 @@ static void R_Subsector(size_t num) fixed_t floorcenterz, ceilingcenterz; ffloor_t *rover; -#ifdef RANGECHECK - if (num >= numsubsectors) - I_Error("R_Subsector: ss %s with numss = %s\n", sizeu1(num), sizeu2(numsubsectors)); -#endif - // subsectors added at run-time if (num >= numsubsectors) + { +#ifdef RANGECHECK + I_Error("R_Subsector: ss %s with numss = %s\n", sizeu1(num), sizeu2(numsubsectors)); +#else return; +#endif + } sub = &subsectors[num]; frontsector = sub->sector; -- 2.54.0 From d4016444477c6477d6a12a008d4d9f4e89bb8741 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 13 Jun 2025 00:02:33 +0200 Subject: [PATCH 104/141] tweak the sky checks even more apparently koda has a skybox, and checking like this makes it not trigger, lets hope this has no bad side effects Zzz... --- src/r_segs.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/r_segs.cpp b/src/r_segs.cpp index df4eebf56..81a42783c 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -2429,21 +2429,23 @@ void R_StoreWallRange(INT32 start, INT32 stop) // untextured seg if (!segtextured && !curline->polyseg) { - const bool tophigh = (backsector && worldhigh <= worldtop && worldhighslope <= worldtopslope) - && (worldhigh != worldtop || worldhighslope != worldtopslope); + const bool tophigh = (worldhigh <= worldtop && worldhighslope <= worldtopslope); + const bool topnothigh = (backsector && (worldhigh != worldtop || worldhighslope != worldtopslope)); // if we cant see the goddamn skyplane, well there wont be any skybox // we could kill skyVisible instead, but i want to keep the performance improvemnts it yields // so we do this absolute trash - if ((frontsector->floorpic != skyflatnum && frontsector->ceilingpic != skyflatnum) // try to guess if its a "window" + if ((tophigh + && (frontsector->floorpic != skyflatnum && frontsector->ceilingpic != skyflatnum)) // try to guess if its a "window" && ((!backsector) // single sided - || (tophigh && (backsector->floorheight > frontsector->ceilingheight || backsector->ceilingheight < frontsector->floorheight)))) // check if there is a "thok" sector behind it + || (topnothigh && (backsector->floorheight > frontsector->ceilingheight || backsector->ceilingheight < frontsector->floorheight)))) // check if there is a "thok" sector behind it skyVisible = true; // this is an attempt to fix issues with textureless midtextures drawing nothing where they should just draw sky instead - if ((newview->sky // only do this for skyrender + if ((tophigh + && newview->sky) // only do this for skyrender && ((!backsector && frontsector->ceilingpic == skyflatnum) // single sided line with sky ceiling - || (tophigh && (backsector->ceilingpic == skyflatnum && frontsector->ceilingpic != skyflatnum))))) // double sided with back ceiling sky but not front ceiling sky + || (topnothigh && (backsector->ceilingpic == skyflatnum && frontsector->ceilingpic != skyflatnum)))) // double sided with back ceiling sky but not front ceiling sky { topstep = -FixedMul (rw_scalestep, worldbottom); topfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale); -- 2.54.0 From 7a3faf34e790f63f40563fc2f0fdfb41cfec8230 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 13 Jun 2025 00:02:51 +0200 Subject: [PATCH 105/141] move this into an if else saves us a little work --- src/r_plane.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 24c3cb086..e7a9d008c 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -442,7 +442,13 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, } } - if (slope != NULL && P_ApplyLightOffset(lightlevel >> LIGHTSEGSHIFT, lighting_sector)) + // This appears to fix the Nimbus Ruins sky bug. + if (picnum == skyflatnum && pfloor) + { + height = 0; // all skies map together + lightlevel = 0; + } + else if (slope != NULL && P_ApplyLightOffset(lightlevel >> LIGHTSEGSHIFT, lighting_sector)) { if (reverseLight) { @@ -454,20 +460,15 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, } } - // This appears to fix the Nimbus Ruins sky bug. - if (picnum == skyflatnum && pfloor) - { - height = 0; // all skies map together - lightlevel = 0; - } - if (!pfloor) { hash = visplane_hash(picnum, lightlevel, height); + for (check = visplanes[hash]; check; check = check->next) { if (polyobj != check->polyobj) continue; + if (height == check->height && picnum == check->picnum && lightlevel == check->lightlevel && xoff == check->xoffs && yoff == check->yoffs -- 2.54.0 From 2eae9b197ce0150ab08a0640a930e84f72913a3d Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 13 Jun 2025 03:23:25 +0200 Subject: [PATCH 106/141] port the span and column drawer templates + tilted translucent splat drawer took the liberty to also carry over our optimizations, this is actually slightly faster than what we had before --- src/k_kart.h | 8 + src/{r_draw.c => r_draw.cpp} | 43 +- src/r_draw.h | 2 + src/r_draw_column.c | 780 --------------------- src/r_draw_column.cpp | 333 +++++++++ src/r_draw_span.c | 1234 ---------------------------------- src/r_draw_span.cpp | 446 ++++++++++++ src/r_plane.cpp | 3 + src/screen.c | 1 + 9 files changed, 814 insertions(+), 2036 deletions(-) rename src/{r_draw.c => r_draw.cpp} (91%) delete mode 100644 src/r_draw_column.c create mode 100644 src/r_draw_column.cpp delete mode 100644 src/r_draw_span.c create mode 100644 src/r_draw_span.cpp diff --git a/src/k_kart.h b/src/k_kart.h index 411bb0512..b10989618 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -6,6 +6,10 @@ #ifndef __K_KART__ #define __K_KART__ +#ifdef __cplusplus +extern "C" { +#endif + #include "doomdef.h" #include "d_player.h" // Need for player_t @@ -132,5 +136,9 @@ INT32 K_getMinimapTrans(void); void K_getLapsDrawinfo(drawinfo_t *out); void K_getMinimapDrawinfo(drawinfo_t *out); +#ifdef __cplusplus +} // extern "C" +#endif + // ========================================================================= #endif // __K_KART__ diff --git a/src/r_draw.c b/src/r_draw.cpp similarity index 91% rename from src/r_draw.c rename to src/r_draw.cpp index 3b3540bc6..9e0f12cb4 100644 --- a/src/r_draw.c +++ b/src/r_draw.cpp @@ -15,6 +15,8 @@ /// not the architecture of the frame buffer. /// The frame buffer is a linear one, and we need only the base address. +#include + #include "doomdef.h" #include "doomstat.h" #include "r_local.h" @@ -115,8 +117,7 @@ void R_InitTranslucencyTables(void) // Load here the transparency lookup tables 'TRANSx0' // NOTE: the TRANSx0 resources MUST BE aligned on 64k for the asm // optimised code (in other words, transtables pointer low word is 0) - transtables = Z_MallocAlign(NUMTRANSTABLES*0x10000, PU_STATIC, - NULL, 16); + transtables = static_cast(Z_MallocAlign(NUMTRANSTABLES*0x10000, PU_STATIC, NULL, 16)); W_ReadLump(W_GetNumForName("TRANS10"), transtables); W_ReadLump(W_GetNumForName("TRANS20"), transtables+0x10000); @@ -177,10 +178,10 @@ static void BlendTab_Subtractive(UINT8 *table, int style, UINT8 blendamt) RGBA_t frontrgba = V_GetColor(fg); RGBA_t result; - result.rgba = ASTBlendPixel(backrgba, frontrgba, style, 0xFF); - result.s.red = max(0, result.s.red - blendamt); - result.s.green = max(0, result.s.green - blendamt); - result.s.blue = max(0, result.s.blue - blendamt); + result.rgba = ASTBlendPixel(backrgba, frontrgba, style, 0xFF); + result.s.red = std::max(0, result.s.red - blendamt); + result.s.green = std::max(0, result.s.green - blendamt); + result.s.blue = std::max(0, result.s.blue - blendamt); table[((bg * 0x100) + fg)] = GetColorLUT(&transtab_lut, result.s.red, result.s.green, result.s.blue); } @@ -233,7 +234,7 @@ static void BlendTab_GenerateMaps(INT32 tab, INT32 style, void (*genfunc)(UINT8 for (; i < num; i++) { const size_t offs = (0x10000 * i); - const UINT16 alpha = min(amtmul * i, 0xFF); + const UINT16 alpha = std::fmin(amtmul * i, 0xFF); genfunc(blendtables[tab] + offs, style, alpha); } } @@ -243,7 +244,7 @@ void R_GenerateBlendTables(void) INT32 i; for (i = 0; i < NUMBLENDMAPS; i++) - blendtables[i] = Z_MallocAlign(BlendTab_Count[i] * 0x10000, PU_STATIC, NULL, 16); + blendtables[i] = static_cast(Z_MallocAlign(BlendTab_Count[i] * 0x10000, PU_STATIC, NULL, 16)); InitColorLUT(&transtab_lut, pLocalPalette, false); @@ -264,8 +265,8 @@ void R_GenerateBlendTables(void) BlendTab_Modulative(blendtables[blendtab_modulate]); } -#define ClipBlendLevel(style, trans) max(min((trans), BlendTab_Count[BlendTab_FromStyle[style]]-1), 0) -#define ClipTransLevel(trans) max(min((trans), NUMTRANSMAPS-2), 0) +#define ClipBlendLevel(style, trans) std::max(std::min((trans), BlendTab_Count[BlendTab_FromStyle[style]]-1), 0) +#define ClipTransLevel(trans) std::max(std::min((trans), NUMTRANSMAPS-2), 0) UINT8 *R_GetTranslucencyTable(INT32 alphalevel) { @@ -352,7 +353,7 @@ static UINT8* RGetTranslationColormap(INT32 skinnum, skincolors_t color, UINT8 f { // Allocate table for skin if necessary if (!tt[skintableindex]) - tt[skintableindex] = Z_Calloc(MAXTRANSLATIONS * sizeof(UINT8**), PU_STATIC, NULL); + tt[skintableindex] = static_cast(Z_Calloc(MAXTRANSLATIONS * sizeof(UINT8**), PU_STATIC, NULL)); // Get colormap ret = tt[skintableindex][color]; @@ -362,7 +363,7 @@ static UINT8* RGetTranslationColormap(INT32 skinnum, skincolors_t color, UINT8 f // Generate the colormap if necessary if (!ret) { - ret = Z_MallocAlign(NUM_PALETTE_ENTRIES, (flags & GTC_CACHE) ? PU_LEVEL : PU_STATIC, NULL, 8); + ret = static_cast(Z_MallocAlign(NUM_PALETTE_ENTRIES, (flags & GTC_CACHE) ? PU_LEVEL : PU_STATIC, NULL, 8)); K_GenerateKartColormap(ret, skinnum, color, local); //R_GenerateTranslationColormap(ret, skinnum, color); // SRB2kart // Cache the colormap if desired @@ -457,17 +458,15 @@ void R_FlushTranslationColormapCache(void) static void R_AllocViewMemory(void) { - negonearray = Z_Realloc(negonearray, sizeof(*negonearray) * viewwidth, PU_STATIC, NULL); - screenheightarray = Z_Realloc(screenheightarray, sizeof(*screenheightarray) * viewwidth, PU_STATIC, NULL); + negonearray = static_cast(Z_Realloc(negonearray, sizeof(*negonearray) * viewwidth, PU_STATIC, NULL)); + screenheightarray = static_cast(Z_Realloc(screenheightarray, sizeof(*screenheightarray) * viewwidth, PU_STATIC, NULL)); - floorclip = Z_Realloc(floorclip, sizeof(*floorclip) * viewwidth, PU_STATIC, NULL); - ceilingclip = Z_Realloc(ceilingclip, sizeof(*ceilingclip) * viewwidth, PU_STATIC, NULL); + floorclip = static_cast(Z_Realloc(floorclip, sizeof(*floorclip) * viewwidth, PU_STATIC, NULL)); + ceilingclip = static_cast(Z_Realloc(ceilingclip, sizeof(*ceilingclip) * viewwidth, PU_STATIC, NULL)); - frontscale = Z_Realloc(frontscale, sizeof(*frontscale) * viewwidth, PU_STATIC, NULL); + frontscale = static_cast(Z_Realloc(frontscale, sizeof(*frontscale) * viewwidth, PU_STATIC, NULL)); - xtoviewangle = Z_Realloc(xtoviewangle, sizeof(*xtoviewangle) * (viewwidth + 1), PU_STATIC, NULL); - - //tiltlighting = Z_Realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth, PU_STATIC, NULL); + xtoviewangle = static_cast(Z_Realloc(xtoviewangle, sizeof(*xtoviewangle) * (viewwidth + 1), PU_STATIC, NULL)); R_AllocSegMemory(); R_AllocClipSegMemory(); @@ -662,5 +661,5 @@ void R_DrawViewBorder(void) // INCLUDE DRAWING CODE HERE // ========================================================================== -#include "r_draw_column.c" -#include "r_draw_span.c" +#include "r_draw_column.cpp" +#include "r_draw_span.cpp" diff --git a/src/r_draw.h b/src/r_draw.h index fc8b344e7..68106480b 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -136,6 +136,7 @@ enum SPANDRAWFUNC_SPLAT, SPANDRAWFUNC_TRANSSPLAT, SPANDRAWFUNC_TILTEDSPLAT, + SPANDRAWFUNC_TILTEDTRANSSPLAT, SPANDRAWFUNC_WATER, SPANDRAWFUNC_TILTEDWATER, @@ -264,6 +265,7 @@ void R_DrawFogSpan_Tilted(drawspandata_t* ds); void R_DrawSplat_Tilted(drawspandata_t* ds); void R_DrawSplat(drawspandata_t* ds); void R_DrawTranslucentSplat(drawspandata_t* ds); +void R_DrawTranslucentSplat_Tilted(drawspandata_t* ds); #ifdef __cplusplus } // extern "C" diff --git a/src/r_draw_column.c b/src/r_draw_column.c deleted file mode 100644 index dc825e5d6..000000000 --- a/src/r_draw_column.c +++ /dev/null @@ -1,780 +0,0 @@ -// SONIC ROBO BLAST 2 -//----------------------------------------------------------------------------- -// Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. -// -// This program is free software distributed under the -// terms of the GNU General Public License, version 2. -// See the 'LICENSE' file for more details. -//----------------------------------------------------------------------------- -/// \file r_draw_column.c -/// \brief column drawer functions -/// \note no includes because this is included as part of r_draw.c - -// ========================================================================== -// COLUMNS -// ========================================================================== - -// A column is a vertical slice/span of a wall texture that uses -// a has a constant z depth from top to bottom. -// - -/** \brief The R_DrawColumn function - Experiment to make software go faster. Taken from the Boom source -*/ -void R_DrawColumn(drawcolumndata_t* dc) -{ - INT32 count; - register UINT8 *restrict dest; - intptr_t frac; - - count = dc->yh - dc->yl; - - if (count < 0) // Zero length, column does not exceed a pixel. - { - return; - } - - if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height) - { - return; - } - - // Framebuffer destination address. - dest = R_Address(dc->x, dc->yl); - - count++; - - // Determine scaling, which is the only mapping to be done. - const intptr_t fracstep = dc->iscale; - frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep)); - - // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. - // This is as fast as it gets. - const UINT8 *restrict source = dc->source; - const lighttable_t *restrict colormap = dc->colormap; - intptr_t heightmask = dc->sourcelength-1; - - static const INT32 npow2min = -1; - const INT32 npow2max = dc->sourcelength; - - register const INT32 stride = vid.width; - - if (heightmask == -1) - { - // texture has no height, so just go - while (--count > 0) - { - *dest = colormap[source[frac>>FRACBITS]]; - dest += stride; - frac += fracstep; - } - } - else if (dc->sourcelength & heightmask) // not a power of 2 -- killough - { - heightmask = dc->texheight << FRACBITS; - - if (frac < 0) - { - while ((frac += heightmask) < 0) - { - ; - } - } - else - { - while (frac >= heightmask) - { - frac -= heightmask; - } - } - - do - { - // Re-map color indices from wall texture column - // using a lighting/special effects LUT. - // heightmask is the Tutti-Frutti fix - - // -1 is the lower clamp bound because column posts have a "safe" byte before the real data - // and a few bytes after as well - *dest = colormap[source[CLAMP(frac >> FRACBITS, npow2min, npow2max)]]; - - dest += stride; - -#if __SIZEOF_POINTER__ < 8 // 64-bit systems have large enough numbers for this to be a non-issue - // Avoid overflow. - if (fracstep > 0x7FFFFFFF - frac) - { - frac += fracstep - heightmask; - } - else -#endif - { - frac += fracstep; - } - - while (frac >= heightmask) - { - frac -= heightmask; - } - } while (--count); - } - else - { - while ((count -= 2) >= 0) // texture height is a power of 2 - { - *dest = colormap[source[(frac>>FRACBITS) & heightmask]]; - - dest += stride; - frac += fracstep; - - *dest = colormap[source[(frac>>FRACBITS) & heightmask]]; - - dest += stride; - frac += fracstep; - } - - if (count & 1) - { - *dest = colormap[source[(frac>>FRACBITS) & heightmask]]; - } - } -} - -void R_Draw2sMultiPatchColumn(drawcolumndata_t* dc) -{ - INT32 count; - register UINT8 *restrict dest; - intptr_t frac; - - count = dc->yh - dc->yl; - - if (count < 0) // Zero length, column does not exceed a pixel. - { - return; - } - - if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height) - { - return; - } - - // Framebuffer destination address. - dest = R_Address(dc->x, dc->yl); - - count++; - - // Determine scaling, which is the only mapping to be done. - const intptr_t fracstep = dc->iscale; - frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep)); - - // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. - // This is as fast as it gets. - const UINT8 *restrict source = dc->source; - const lighttable_t *restrict colormap = dc->colormap; - intptr_t heightmask = dc->sourcelength-1; - UINT8 val; - - static const INT32 npow2min = -1; - const INT32 npow2max = dc->sourcelength; - - register const INT32 stride = vid.width; - - if (heightmask == -1) - { - // texture has no height, so just go - while (--count > 0) - { - *dest = colormap[source[frac>>FRACBITS]]; - dest += stride; - frac += fracstep; - } - } - else if (dc->sourcelength & heightmask) // not a power of 2 -- killough - { - heightmask = dc->texheight << FRACBITS; - - if (frac < 0) - { - while ((frac += heightmask) < 0) - { - ; - } - } - else - { - while (frac >= heightmask) - { - frac -= heightmask; - } - } - - do - { - // Re-map color indices from wall texture column - // using a lighting/special effects LUT. - // heightmask is the Tutti-Frutti fix - - // -1 is the lower clamp bound because column posts have a "safe" byte before the real data - // and a few bytes after as well - val = source[CLAMP(frac >> FRACBITS, npow2min, npow2max)]; - - if (val != TRANSPARENTPIXEL) - { - *dest = colormap[val]; - } - - dest += stride; - - // Avoid overflow. -#if __SIZEOF_POINTER__ < 8 - if (fracstep > 0x7FFFFFFF - frac) - { - frac += fracstep - heightmask; - } - else -#endif - { - frac += fracstep; - } - - while (frac >= heightmask) - { - frac -= heightmask; - } - } while (--count); - } - else - { - while ((count -= 2) >= 0) // texture height is a power of 2 - { - val = source[(frac>>FRACBITS) & heightmask]; - - if (val != TRANSPARENTPIXEL) - { - *dest = colormap[val]; - } - - dest += stride; - frac += fracstep; - - val = source[(frac>>FRACBITS) & heightmask]; - if (val != TRANSPARENTPIXEL) - { - *dest = colormap[val]; - } - - dest += stride; - frac += fracstep; - } - - if (count & 1) - { - val = source[CLAMP(frac >> FRACBITS, -1, dc->sourcelength)]; - if (val != TRANSPARENTPIXEL) - { - *dest = colormap[val]; - } - } - } -} - -void R_Draw2sMultiPatchTranslucentColumn(drawcolumndata_t* dc) -{ - INT32 count; - register UINT8 *restrict dest; - intptr_t frac; - - count = dc->yh - dc->yl; - - if (count < 0) // Zero length, column does not exceed a pixel. - { - return; - } - - if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height) - { - return; - } - - // Framebuffer destination address. - dest = R_Address(dc->x, dc->yl); - - count++; - - // Determine scaling, which is the only mapping to be done. - const intptr_t fracstep = dc->iscale; - frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep)); - - // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. - // This is as fast as it gets. - const UINT8 *restrict source = dc->source; - const UINT8 *transmap = dc->transmap; - const lighttable_t *restrict colormap = dc->colormap; - intptr_t heightmask = dc->sourcelength-1; - register UINT8 val; - - static const INT32 npow2min = -1; - const INT32 npow2max = dc->sourcelength; - - register const INT32 stride = vid.width; - - if (heightmask == -1) - { - // texture has no height, so just go - while (--count > 0) - { - *dest = colormap[source[frac>>FRACBITS]]; - dest += stride; - frac += fracstep; - } - } - else if (dc->sourcelength & heightmask) // not a power of 2 -- killough - { - heightmask = dc->texheight << FRACBITS; - - if (frac < 0) - { - while ((frac += heightmask) < 0) - { - ; - } - } - else - { - while (frac >= heightmask) - { - frac -= heightmask; - } - } - - do - { - // Re-map color indices from wall texture column - // using a lighting/special effects LUT. - // heightmask is the Tutti-Frutti fix - - // -1 is the lower clamp bound because column posts have a "safe" byte before the real data - // and a few bytes after as well - val = source[CLAMP(frac >> FRACBITS, npow2min, npow2max)]; - - if (val != TRANSPARENTPIXEL) - { - *dest = *(transmap + (colormap[val]<<8) + (*dest)); - } - - dest += stride; - - // Avoid overflow. -#if __SIZEOF_POINTER__ < 8 - if (fracstep > 0x7FFFFFFF - frac) - { - frac += fracstep - heightmask; - } - else -#endif - { - frac += fracstep; - } - - while (frac >= heightmask) - { - frac -= heightmask; - } - } while (--count); - } - else - { - while ((count -= 2) >= 0) // texture height is a power of 2 - { - val = source[(frac>>FRACBITS) & heightmask]; - if (val != TRANSPARENTPIXEL) - { - *dest = *(transmap + (colormap[val]<<8) + (*dest)); - } - - dest += stride; - frac += fracstep; - - val = source[(frac>>FRACBITS) & heightmask]; - if (val != TRANSPARENTPIXEL) - { - *dest = *(transmap + (colormap[val]<<8) + (*dest)); - } - - dest += stride; - frac += fracstep; - } - - if (count & 1) - { - val = source[(frac>>FRACBITS) & heightmask]; - if (val != TRANSPARENTPIXEL) - { - *dest = *(transmap + (colormap[val]<<8) + (*dest)); - } - } - } -} - -/** \brief The R_DrawTranslucentColumn function - I've made an asm routine for the transparency, because it slows down - a lot in 640x480 with big sprites (bfg on all screen, or transparent - walls on fullscreen) -*/ -void R_DrawTranslucentColumn(drawcolumndata_t* dc) -{ - register INT32 count; - register UINT8 *restrict dest; - intptr_t frac; - - count = dc->yh - dc->yl + 1; - - if (count <= 0) // Zero length, column does not exceed a pixel. - { - return; - } - - if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height) - { - return; - } - - // Framebuffer destination address. - dest = R_Address(dc->x, dc->yl); - - // Looks familiar. - const intptr_t fracstep = dc->iscale; - frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep)); - - // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. - // This is as fast as it gets. - const UINT8 *restrict source = dc->source; - const UINT8 *transmap = dc->transmap; - const lighttable_t *restrict colormap = dc->colormap; - intptr_t heightmask = dc->sourcelength-1; - - static const INT32 npow2min = -1; - const INT32 npow2max = dc->sourcelength; - - register const INT32 stride = vid.width; - - if (dc->sourcelength & heightmask) - { - heightmask = dc->texheight << FRACBITS; - - if (frac < 0) - { - while ((frac += heightmask) < 0) - { - ; - } - } - else - { - while (frac >= heightmask) - { - frac -= heightmask; - } - } - - do - { - // Re-map color indices from wall texture column - // using a lighting/special effects LUT. - // heightmask is the Tutti-Frutti fix - - // -1 is the lower clamp bound because column posts have a "safe" byte before the real data - // and a few bytes after as well - *dest = *(transmap + (colormap[source[CLAMP(frac >> FRACBITS, npow2min, npow2max)]]<<8) + (*dest)); - - dest += stride; - - if ((frac += fracstep) >= heightmask) - { - frac -= heightmask; - } - } - while (--count); - } - else - { - while ((count -= 2) >= 0) // texture height is a power of 2 - { - *dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); - dest += stride; - frac += fracstep; - - *dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); - dest += stride; - frac += fracstep; - } - - if (count & 1) - { - *dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest)); - } - } -} - -/** \brief The R_DrawTranslatedTranslucentColumn function - Spiffy function. Not only does it colormap a sprite, but does translucency as well. - Uber-kudos to Cyan Helkaraxe -*/ -void R_DrawTranslatedTranslucentColumn(drawcolumndata_t* dc) -{ - register INT32 count; - register UINT8 *restrict dest; - intptr_t frac; - - count = dc->yh - dc->yl + 1; - - if (count <= 0) // Zero length, column does not exceed a pixel. - { - return; - } - - if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height) - { - return; - } - - // Framebuffer destination address. - dest = R_Address(dc->x, dc->yl); - - // Looks familiar. - const intptr_t fracstep = dc->iscale; - frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep)); - - // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. - // This is as fast as it gets. - intptr_t heightmask = dc->sourcelength-1; - - static const INT32 npow2min = -1; - const INT32 npow2max = dc->sourcelength; - - register const INT32 stride = vid.width; - - if (dc->sourcelength & heightmask) - { - heightmask = dc->texheight << FRACBITS; - - if (frac < 0) - { - while ((frac += heightmask) < 0) - { - ; - } - } - else - { - while (frac >= heightmask) - { - frac -= heightmask; - } - } - - do - { - // Re-map color indices from wall texture column - // using a lighting/special effects LUT. - // heightmask is the Tutti-Frutti fix - - // -1 is the lower clamp bound because column posts have a "safe" byte before the real data - // and a few bytes after as well - *dest = *(dc->transmap + (dc->colormap[dc->translation[dc->source[CLAMP(frac >> FRACBITS, npow2min, npow2max)]]]<<8) + (*dest)); - - dest += stride; - - if ((frac += fracstep) >= heightmask) - { - frac -= heightmask; - } - } - while (--count); - } - else - { - while ((count -= 2) >= 0) // texture height is a power of 2 - { - *dest = *(dc->transmap + (dc->colormap[dc->translation[dc->source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); - dest += stride; - frac += fracstep; - - *dest = *(dc->transmap + (dc->colormap[dc->translation[dc->source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); - dest += stride; - frac += fracstep; - } - - if (count & 1) - { - *dest = *(dc->transmap + (dc->colormap[dc->translation[dc->source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest)); - } - } -} - -/** \brief The R_DrawTranslatedColumn function - Draw columns up to 128 high but remap the green ramp to other colors - - \warning STILL NOT IN ASM, TO DO.. -*/ -void R_DrawTranslatedColumn(drawcolumndata_t* dc) -{ - register INT32 count; - register UINT8 *dest; - register fixed_t frac; - - count = dc->yh - dc->yl; - - if (count < 0) - { - return; - } - - if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height) - { - return; - } - - // Framebuffer destination address. - dest = R_Address(dc->x, dc->yl); - - // Looks familiar. - const fixed_t fracstep = dc->iscale; - frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep)); - - register const INT32 stride = vid.width; - - // Here we do an additional index re-mapping. - do - { - // Translation tables are used - // to map certain colorramps to other ones, - // used with PLAY sprites. - // Thus the "green" ramp of the player 0 sprite - // is mapped to gray, red, black/indigo. - *dest = dc->colormap[dc->translation[dc->source[frac>>FRACBITS]]]; - - dest += stride; - - frac += fracstep; - } while (count--); -} - -/** \brief The R_DrawFogColumn function - Fog wall. -*/ -void R_DrawFogColumn(drawcolumndata_t* dc) -{ - register INT32 count; - register UINT8 *dest; - - count = dc->yh - dc->yl; - - // Zero length, column does not exceed a pixel. - if (count < 0) - { - return; - } - - if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height) - { - return; - } - - // Framebuffer destination address. - dest = R_Address(dc->x, dc->yl); - - register const INT32 stride = vid.width; - - // Determine scaling, which is the only mapping to be done. - do - { - // Simple. Apply the colormap to what's already on the screen. - *dest = dc->colormap[*dest]; - dest += stride; - } while (count--); -} - -/** \brief The R_DrawShadeColumn function - This is for 3D floors that cast shadows on walls. - - This function just cuts the column up into sections and calls R_DrawColumn -*/ -void R_DrawColumnShadowed(drawcolumndata_t* dc) -{ - register INT32 count; - INT32 realyh, i, height, bheight = 0, solid = 0; - - count = dc->yh - dc->yl; - - // Zero length, column does not exceed a pixel. - if (count < 0) - { - return; - } - - if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height) - { - return; - } - - realyh = dc->yh; - - // This runs through the lightlist from top to bottom and cuts up the column accordingly. - for (i = 0; i < dc->numlights; i++) - { - // If the height of the light is above the column, get the colormap - // anyway because the lighting of the top should be affected. - solid = dc->lightlist[i].flags & FF_CUTSOLIDS; - - height = dc->lightlist[i].height >> LIGHTSCALESHIFT; - - if (solid) - { - bheight = dc->lightlist[i].botheight >> LIGHTSCALESHIFT; - if (bheight < height) - { - // confounded slopes sometimes allow partial invertedness, - // even including cases where the top and bottom heights - // should actually be the same! - // swap the height values as a workaround for this quirk - INT32 temp = height; - height = bheight; - bheight = temp; - } - } - - if (height <= dc->yl) - { - dc->colormap = dc->lightlist[i].rcolormap; - if (encoremap) - dc->colormap += COLORMAP_REMAPOFFSET; - if (solid && dc->yl < bheight) - dc->yl = bheight; - continue; - } - - // Found a break in the column! - dc->yh = height; - - if (dc->yh > realyh) - dc->yh = realyh; - - (colfuncs[BASEDRAWFUNC])(dc); // R_DrawColumn_8 for the appropriate architecture - - if (solid) - dc->yl = bheight; - else - dc->yl = dc->yh + 1; - - dc->colormap = dc->lightlist[i].rcolormap; - if (encoremap) - dc->colormap += COLORMAP_REMAPOFFSET; - } - - dc->yh = realyh; - - if (dc->yl <= realyh) - (colfuncs[BASEDRAWFUNC])(dc); // R_DrawWallColumn_8 for the appropriate architecture -} diff --git a/src/r_draw_column.cpp b/src/r_draw_column.cpp new file mode 100644 index 000000000..b546c66ea --- /dev/null +++ b/src/r_draw_column.cpp @@ -0,0 +1,333 @@ +// SONIC ROBO BLAST 2 KART +//----------------------------------------------------------------------------- +// Copyright (C) 2025 by Kart Krew. +// Copyright (C) 2020 by Sonic Team Junior. +// Copyright (C) 2000 by DooM Legacy Team. +// Copyright (C) 1996 by id Software, Inc. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file r_draw_column.cpp +/// \brief column drawer functions +/// \note no includes because this is included as part of r_draw.cpp + +// ========================================================================== +// COLUMNS +// ========================================================================== + +// A column is a vertical slice/span of a wall texture that uses +// a has a constant z depth from top to bottom. +// + +enum DrawColumnType +{ + DC_BASIC = 0x0000, + DC_COLORMAP = 0x0001, + DC_TRANSMAP = 0x0002, + DC_HOLES = 0x0004, + DC_LIGHTLIST = 0x0008, +}; + +template +static constexpr UINT8 R_GetColumnTranslated(drawcolumndata_t* dc, UINT8 col, const UINT8 *colormap) +{ + if constexpr (Type & DrawColumnType::DC_COLORMAP) + { + col = dc->translation[col]; + } + + return colormap[col]; +} + +template +static constexpr UINT8 R_GetColumnTranslucent(drawcolumndata_t* dc, UINT8 *dest, UINT8 col, const UINT8 *colormap) +{ + col = R_GetColumnTranslated(dc, col, colormap); + + if constexpr (Type & DrawColumnType::DC_TRANSMAP) + { + return *(dc->transmap + (col << 8) + (*dest)); + } + else + { + return col; + } +} + +template +static constexpr UINT8 R_DrawColumnPixel(drawcolumndata_t* dc, UINT8 *dest, UINT32 bit, const UINT8 *source, const UINT8 *colormap) +{ + UINT8 col = source[bit]; + + if constexpr (Type & DrawColumnType::DC_HOLES) + { + if (col == TRANSPARENTPIXEL) + { + return *dest; + } + } + + return R_GetColumnTranslucent(dc, dest, col, colormap); +} + +/** \brief The R_DrawColumn function + Experiment to make software go faster. Taken from the Boom source +*/ +template +static void R_DrawColumnTemplate(drawcolumndata_t *dc) +{ + INT32 count; + + count = dc->yh - dc->yl; + + if (count < 0) // Zero length, column does not exceed a pixel. + { + return; + } + + if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height) + { + return; + } + + if constexpr (Type & DrawColumnType::DC_LIGHTLIST) + { + constexpr DrawColumnType NewType = static_cast(Type & ~DC_LIGHTLIST); + INT32 i, height, bheight = 0, solid = 0; + drawcolumndata_t dc_copy = *dc; + + const INT32 realyh = dc_copy.yh; + + // This runs through the lightlist from top to bottom and cuts up the column accordingly. + for (i = 0; i < dc_copy.numlights; i++) + { + // If the height of the light is above the column, get the colormap + // anyway because the lighting of the top should be affected. + solid = dc_copy.lightlist[i].flags & FF_CUTSOLIDS; + height = dc_copy.lightlist[i].height >> LIGHTSCALESHIFT; + + if (solid) + { + bheight = dc_copy.lightlist[i].botheight >> LIGHTSCALESHIFT; + + if (bheight < height) + { + // confounded slopes sometimes allow partial invertedness, + // even including cases where the top and bottom heights + // should actually be the same! + // swap the height values as a workaround for this quirk + INT32 temp = height; + height = bheight; + bheight = temp; + } + } + + if (height <= dc_copy.yl) + { + dc_copy.colormap = dc_copy.lightlist[i].rcolormap; + + if (encoremap) + { + dc_copy.colormap += COLORMAP_REMAPOFFSET; + } + + if (solid && dc_copy.yl < bheight) + { + dc_copy.yl = bheight; + } + + continue; + } + + // Found a break in the column! + dc_copy.yh = height; + + if (dc_copy.yh > realyh) + { + dc_copy.yh = realyh; + } + + R_DrawColumnTemplate(&dc_copy); + if (solid) + { + dc_copy.yl = bheight; + } + else + { + dc_copy.yl = dc_copy.yh + 1; + } + + dc_copy.colormap = dc_copy.lightlist[i].rcolormap; + + if (encoremap) + { + dc_copy.colormap += COLORMAP_REMAPOFFSET; + } + } + + dc_copy.yh = realyh; + + if (dc_copy.yl <= realyh) + { + R_DrawColumnTemplate(&dc_copy); + } + } + else + { + // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. + // This is as fast as it gets. + fixed_t frac; + const intptr_t fracstep = dc->iscale; + intptr_t heightmask = dc->sourcelength-1; + static const INT32 npow2min = -1; + const INT32 npow2max = dc->sourcelength; + const INT32 stride = vid.width; + + const UINT8 *source = dc->source; + const lighttable_t *colormap = dc->colormap; + + // Framebuffer destination address. + UINT8 *dest = R_Address(dc->x, dc->yl); + + count++; + + // Determine scaling, which is the only mapping to be done. + frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep)); + + if (heightmask == -1) + { + if (frac < 0) + // adjust in case we underread + frac += FRACUNIT; + + // texture has no height, so just go + while (--count > 0) + { + *dest = R_DrawColumnPixel(dc, dest, frac>>FRACBITS, source, colormap); + dest += stride; + frac += fracstep; + } + } + else if (dc->sourcelength & heightmask) // not a power of 2 -- killough + { + heightmask = dc->texheight << FRACBITS; + + if (frac < 0) + { + while ((frac += heightmask) < 0) + { + ; + } + } + else + { + while (frac >= heightmask) + { + frac -= heightmask; + } + } + + do + { + // Re-map color indices from wall texture column + // using a lighting/special effects LUT. + // heightmask is the Tutti-Frutti fix + + // -1 is the lower clamp bound because column posts have a "safe" byte before the real data + // and a few bytes after as well + *dest = R_DrawColumnPixel(dc, dest, std::clamp((frac >> FRACBITS), npow2min, npow2max), source, colormap); + + dest += stride; + +#if __SIZEOF_POINTER__ < 8 // 64-bit systems have large enough numbers for this to be a non-issue + // Avoid overflow. + if (fracstep > 0x7FFFFFFF - frac) + { + frac += fracstep - heightmask; + } + else +#endif + { + frac += fracstep; + } + + while (frac >= heightmask) + { + frac -= heightmask; + } + } + while (--count); + } + else + { + while ((count -= 2) >= 0) // texture height is a power of 2 + { + *dest = R_DrawColumnPixel(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap); + dest += stride; + frac += fracstep; + + *dest = R_DrawColumnPixel(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap); + dest += stride; + frac += fracstep; + } + + if (count & 1) + { + *dest = R_DrawColumnPixel(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap); + } + } + } +} + +#define DEFINE_COLUMN_FUNC(name, flags) \ + void name(drawcolumndata_t *dc) \ + { \ + constexpr DrawColumnType opt = static_cast(flags); \ + R_DrawColumnTemplate(dc); \ + } + +DEFINE_COLUMN_FUNC(R_DrawColumn, DC_BASIC) +DEFINE_COLUMN_FUNC(R_DrawTranslucentColumn, DC_TRANSMAP) +DEFINE_COLUMN_FUNC(R_DrawTranslatedColumn, DC_COLORMAP) +DEFINE_COLUMN_FUNC(R_DrawColumnShadowed, DC_LIGHTLIST) +DEFINE_COLUMN_FUNC(R_DrawTranslatedTranslucentColumn, DC_COLORMAP|DC_TRANSMAP) +DEFINE_COLUMN_FUNC(R_Draw2sMultiPatchColumn, DC_HOLES) +DEFINE_COLUMN_FUNC(R_Draw2sMultiPatchTranslucentColumn, DC_HOLES|DC_TRANSMAP) + +/** \brief The R_DrawFogColumn function + Fog wall. +*/ +void R_DrawFogColumn(drawcolumndata_t* dc) +{ + INT32 count; + UINT8 *dest; + + count = dc->yh - dc->yl; + + // Zero length, column does not exceed a pixel. + if (count < 0) + { + return; + } + + if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height) + { + return; + } + + // Framebuffer destination address. + dest = R_Address(dc->x, dc->yl); + + const INT32 stride = vid.width; + const lighttable_t *colormap = dc->colormap; + + // Determine scaling, which is the only mapping to be done. + do + { + // Simple. Apply the colormap to what's already on the screen. + *dest = colormap[*dest]; + dest += stride; + } while (count--); +} diff --git a/src/r_draw_span.c b/src/r_draw_span.c deleted file mode 100644 index d7a9aaa68..000000000 --- a/src/r_draw_span.c +++ /dev/null @@ -1,1234 +0,0 @@ -// SONIC ROBO BLAST 2 -//----------------------------------------------------------------------------- -// Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. -// -// This program is free software distributed under the -// terms of the GNU General Public License, version 2. -// See the 'LICENSE' file for more details. -//----------------------------------------------------------------------------- -/// \file r_draw_span.c -/// \brief span drawer functions -/// \note no includes because this is included as part of r_draw.c - -// ========================================================================== -// SPANS -// ========================================================================== - -#ifdef HAVE_THREADS -#ifdef _WIN32 -#include -#define local_for_thread static __thread -#else -#include -#define local_for_thread thread_local static -#endif -#else -#define local_for_thread static -#endif - -#define SPANSIZE 16 -#define INVSPAN 0.0625f - -// 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size) -#define MAXFLATBYTES 4194303 - -/** \brief The R_DrawSpan function - Draws the actual span. -*/ -void R_DrawSpan(drawspandata_t* ds) -{ - UINT32 xposition; - UINT32 yposition; - UINT32 xstep, ystep; - register UINT32 bit; - - UINT8 *restrict source = ds->source; - UINT8 *restrict colormap = ds->colormap; - UINT8 *restrict dest = R_Address(ds->x1, ds->y); - const UINT8 *restrict deststop = vid.screens[0] + vid.rowbytes * vid.height; - - register intptr_t count = (ds->x2 - ds->x1 + 1); - - xposition = ds->xfrac; yposition = ds->yfrac; - xstep = ds->xstep; ystep = ds->ystep; - - // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest - // can be used for the fraction part. This allows calculation of the memory address in the - // texture with two shifts, an OR and one AND. (see below) - // for texture sizes > 64 the amount of precision we can allow will decrease, but only by one - // bit per power of two (obviously) - // Ok, because I was able to eliminate the variable spot below, this function is now FASTER - // than the original span renderer. Whodathunkit? - xposition <<= ds->nflatshiftup; yposition <<= ds->nflatshiftup; - xstep <<= ds->nflatshiftup; ystep <<= ds->nflatshiftup; - - if (dest+8 > deststop) - { - return; - } - - while (count >= 8) - { - // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't - // have the uber complicated math to calculate it now, so that was a memory write we didn't - // need! - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[0] = colormap[source[bit]]; - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[1] = colormap[source[bit]]; - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[2] = colormap[source[bit]]; - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[3] = colormap[source[bit]]; - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[4] = colormap[source[bit]]; - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[5] = colormap[source[bit]]; - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[6] = colormap[source[bit]]; - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[7] = colormap[source[bit]]; - xposition += xstep; - yposition += ystep; - - dest += 8; - count -= 8; - } - - while (count-- && dest <= deststop) - { - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - *dest++ = colormap[source[bit]]; - xposition += xstep; - yposition += ystep; - } -} - -/** \brief The R_DrawTranslucentSpan function - Draws the actual span with translucent. -*/ -void R_DrawTranslucentSpan(drawspandata_t* ds) -{ - UINT32 xposition; - UINT32 yposition; - UINT32 xstep, ystep; - register UINT32 bit; - - UINT8 *restrict source = ds->source; - UINT8 *restrict colormap = ds->colormap; - UINT8 *restrict dest = R_Address(ds->x1, ds->y); - const UINT8 *restrict deststop = vid.screens[0] + vid.rowbytes * vid.height; - - register intptr_t count = (ds->x2 - ds->x1 + 1); - - register const UINT8 *tranmap = ds->transmap; - - xposition = ds->xfrac; yposition = ds->yfrac; - xstep = ds->xstep; ystep = ds->ystep; - - // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest - // can be used for the fraction part. This allows calculation of the memory address in the - // texture with two shifts, an OR and one AND. (see below) - // for texture sizes > 64 the amount of precision we can allow will decrease, but only by one - // bit per power of two (obviously) - // Ok, because I was able to eliminate the variable spot below, this function is now FASTER - // than the original span renderer. Whodathunkit? - xposition <<= ds->nflatshiftup; yposition <<= ds->nflatshiftup; - xstep <<= ds->nflatshiftup; ystep <<= ds->nflatshiftup; - - while (count >= 8) - { - // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't - // have the uber complicated math to calculate it now, so that was a memory write we didn't - // need! - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[0] = *(tranmap + (colormap[source[bit]] << 8) + dest[0]); - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[1] = *(tranmap + (colormap[source[bit]] << 8) + dest[1]); - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[2] = *(tranmap + (colormap[source[bit]] << 8) + dest[2]); - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[3] = *(tranmap + (colormap[source[bit]] << 8) + dest[3]); - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[4] = *(tranmap + (colormap[source[bit]] << 8) + dest[4]); - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[5] = *(tranmap + (colormap[source[bit]] << 8) + dest[5]); - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[6] = *(tranmap + (colormap[source[bit]] << 8) + dest[6]); - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[7] = *(tranmap + (colormap[source[bit]] << 8) + dest[7]); - xposition += xstep; - yposition += ystep; - - dest += 8; - count -= 8; - } - while (count-- && dest <= deststop) - { - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - *dest = *(tranmap + (colormap[source[bit]] << 8) + *dest); - dest++; - xposition += xstep; - yposition += ystep; - } -} - -void R_DrawTranslucentWaterSpan(drawspandata_t* ds) -{ - UINT32 xposition; - UINT32 yposition; - UINT32 xstep, ystep; - register UINT32 bit; - - UINT8 *restrict source = ds->source; - UINT8 *restrict colormap = ds->colormap; - UINT8 *restrict dest = R_Address(ds->x1, ds->y); - const UINT8 *restrict dsrc = vid.screens[1] + (ds->y+ds->bgofs)*vid.width + ds->x1; - - register intptr_t count = (ds->x2 - ds->x1 + 1); - - register const UINT8 *tranmap = ds->transmap; - - xposition = ds->xfrac; yposition = (ds->yfrac + ds->waterofs); - xstep = ds->xstep; ystep = ds->ystep; - - // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest - // can be used for the fraction part. This allows calculation of the memory address in the - // texture with two shifts, an OR and one AND. (see below) - // for texture sizes > 64 the amount of precision we can allow will decrease, but only by one - // bit per power of two (obviously) - // Ok, because I was able to eliminate the variable spot below, this function is now FASTER - // than the original span renderer. Whodathunkit? - xposition <<= ds->nflatshiftup; yposition <<= ds->nflatshiftup; - xstep <<= ds->nflatshiftup; ystep <<= ds->nflatshiftup; - - while (count >= 8) - { - // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't - // have the uber complicated math to calculate it now, so that was a memory write we didn't - // need! - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[0] = colormap[*(tranmap + (source[bit] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[1] = colormap[*(tranmap + (source[bit] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[2] = colormap[*(tranmap + (source[bit] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[3] = colormap[*(tranmap + (source[bit] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[4] = colormap[*(tranmap + (source[bit] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[5] = colormap[*(tranmap + (source[bit] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[6] = colormap[*(tranmap + (source[bit] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - dest[7] = colormap[*(tranmap + (source[bit] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest += 8; - count -= 8; - } - while (count--) - { - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - *dest++ = colormap[*(tranmap + (source[bit] << 8) + *dsrc++)]; - - xposition += xstep; - yposition += ystep; - } -} - -/** \brief The R_DrawSplat function - Just like R_DrawSpan, but skips transparent pixels. -*/ -void R_DrawSplat(drawspandata_t* ds) -{ - UINT32 xposition; - UINT32 yposition; - UINT32 xstep, ystep; - register UINT32 bit; - register UINT32 val; - - const UINT8 *restrict source = ds->source; - const UINT8 *restrict colormap = ds->colormap; - UINT8 *restrict dest = R_Address(ds->x1, ds->y); - - register intptr_t count = (ds->x2 - ds->x1 + 1); - - xposition = ds->xfrac; yposition = ds->yfrac; - xstep = ds->xstep; ystep = ds->ystep; - - // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest - // can be used for the fraction part. This allows calculation of the memory address in the - // texture with two shifts, an OR and one AND. (see below) - // for texture sizes > 64 the amount of precision we can allow will decrease, but only by one - // bit per power of two (obviously) - // Ok, because I was able to eliminate the variable spot below, this function is now FASTER - // than the original span renderer. Whodathunkit? - xposition <<= ds->nflatshiftup; yposition <<= ds->nflatshiftup; - xstep <<= ds->nflatshiftup; ystep <<= ds->nflatshiftup; - - while (count >= 8) - { - // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't - // have the uber complicated math to calculate it now, so that was a memory write we didn't - // need! - // - // 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size) - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - bit &= MAXFLATBYTES; - val = source[bit]; - if (val != TRANSPARENTPIXEL) - dest[0] = colormap[val]; - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - bit &= MAXFLATBYTES; - val = source[bit]; - if (val != TRANSPARENTPIXEL) - dest[1] = colormap[val]; - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - bit &= MAXFLATBYTES; - val = source[bit]; - if (val != TRANSPARENTPIXEL) - dest[2] = colormap[val]; - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - bit &= MAXFLATBYTES; - val = source[bit]; - if (val != TRANSPARENTPIXEL) - dest[3] = colormap[val]; - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - bit &= MAXFLATBYTES; - val = source[bit]; - if (val != TRANSPARENTPIXEL) - dest[4] = colormap[val]; - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - bit &= MAXFLATBYTES; - val = source[bit]; - if (val != TRANSPARENTPIXEL) - dest[5] = colormap[val]; - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - bit &= MAXFLATBYTES; - val = source[bit]; - if (val != TRANSPARENTPIXEL) - dest[6] = colormap[val]; - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - bit &= MAXFLATBYTES; - val = source[bit]; - if (val != TRANSPARENTPIXEL) - dest[7] = colormap[val]; - xposition += xstep; - yposition += ystep; - - dest += 8; - count -= 8; - } - while (count--) - { - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - val = source[bit]; - if (val != TRANSPARENTPIXEL) - { - *dest = colormap[val]; - } - - dest++; - xposition += xstep; - yposition += ystep; - } -} - -/** \brief The R_DrawTranslucentSplat function - Just like R_DrawSplat, but is translucent! -*/ -void R_DrawTranslucentSplat(drawspandata_t* ds) -{ - UINT32 xposition; - UINT32 yposition; - UINT32 xstep, ystep; - register UINT32 bit; - register UINT32 val; - - const UINT8 *restrict source = ds->source; - const UINT8 *restrict colormap = ds->colormap; - UINT8 *restrict dest = R_Address(ds->x1, ds->y); - - register intptr_t count = (ds->x2 - ds->x1 + 1); - - xposition = ds->xfrac; yposition = ds->yfrac; - xstep = ds->xstep; ystep = ds->ystep; - - // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest - // can be used for the fraction part. This allows calculation of the memory address in the - // texture with two shifts, an OR and one AND. (see below) - // for texture sizes > 64 the amount of precision we can allow will decrease, but only by one - // bit per power of two (obviously) - // Ok, because I was able to eliminate the variable spot below, this function is now FASTER - // than the original span renderer. Whodathunkit? - xposition <<= ds->nflatshiftup; yposition <<= ds->nflatshiftup; - xstep <<= ds->nflatshiftup; ystep <<= ds->nflatshiftup; - - while (count >= 8) - { - // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't - // have the uber complicated math to calculate it now, so that was a memory write we didn't - // need! - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - val = source[bit]; - if (val != TRANSPARENTPIXEL) - dest[0] = *(ds->transmap + (colormap[val] << 8) + dest[0]); - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - val = source[bit]; - if (val != TRANSPARENTPIXEL) - dest[1] = *(ds->transmap + (colormap[val] << 8) + dest[1]); - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - val = source[bit]; - if (val != TRANSPARENTPIXEL) - dest[2] = *(ds->transmap + (colormap[val] << 8) + dest[2]); - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - val = source[bit]; - if (val != TRANSPARENTPIXEL) - dest[3] = *(ds->transmap + (colormap[val] << 8) + dest[3]); - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - val = source[bit]; - if (val != TRANSPARENTPIXEL) - dest[4] = *(ds->transmap + (colormap[val] << 8) + dest[4]); - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - val = source[bit]; - if (val != TRANSPARENTPIXEL) - dest[5] = *(ds->transmap + (colormap[val] << 8) + dest[5]); - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - val = source[bit]; - if (val != TRANSPARENTPIXEL) - dest[6] = *(ds->transmap + (colormap[val] << 8) + dest[6]); - xposition += xstep; - yposition += ystep; - - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - val = source[bit]; - if (val != TRANSPARENTPIXEL) - dest[7] = *(ds->transmap + (colormap[val] << 8) + dest[7]); - xposition += xstep; - yposition += ystep; - - dest += 8; - count -= 8; - } - while (count--) - { - bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); - val = source[bit]; - if (val != TRANSPARENTPIXEL) - *dest = *(ds->transmap + (colormap[val] << 8) + *dest); - - dest++; - xposition += xstep; - yposition += ystep; - } -} - -/** \brief The R_DrawFogSpan function - Draws the actual span with fogging. -*/ -void R_DrawFogSpan(drawspandata_t* ds) -{ - const UINT8 *restrict colormap = ds->colormap; - UINT8 *restrict dest = R_Address(ds->x1, ds->y); - - register intptr_t count = ds->x2 - ds->x1 + 1; - - while (count >= 4) - { - dest[0] = colormap[dest[0]]; - dest[1] = colormap[dest[1]]; - dest[2] = colormap[dest[2]]; - dest[3] = colormap[dest[3]]; - - dest += 4; - count -= 4; - } - - while (count--) - { - *dest = colormap[*dest]; - dest++; - } -} - -// R_CalcTiltedLighting -// Exactly what it says on the tin. I wish I wasn't too lazy to explain things properly. -static void R_CalcTiltedLighting(INT32 *lightbuffer, INT32 x1, INT32 x2, fixed_t start, fixed_t end) -{ - // ZDoom uses a different lighting setup to us, and I couldn't figure out how to adapt their version - // of this function. Here's my own. - INT32 left = x1, right = x2; - fixed_t step = (end-start)/(x2 - x1 + 1); - INT32 i; - - // I wanna do some optimizing by checking for out-of-range segments on either side to fill in all at once, - // but I'm too bad at coding to not crash the game trying to do that. I guess this is fast enough for now... - - for (i = left; i <= right; i++) - { - lightbuffer[i] = (start += step) >> FRACBITS; - - if (lightbuffer[i] < 0) - { - lightbuffer[i] = 0; - } - else if (lightbuffer[i] >= MAXLIGHTSCALE) - { - lightbuffer[i] = MAXLIGHTSCALE-1; - } - } -} - -#define PLANELIGHTFLOAT ((float)BASEVIDWIDTH * BASEVIDWIDTH / vid.width / ds->zeroheight / 21.0f * FIXED_TO_FLOAT(fovtan)) - -/** \brief The R_DrawTiltedSpan function - Draw slopes! Holy sheit! -*/ -void R_DrawSpan_Tilted(drawspandata_t* ds) -{ - int width = ds->x2 - ds->x1; - float iz, uz, vz; - UINT32 u, v; - int i; - - UINT8 *source; - UINT8 *colormap; - register UINT8 *dest; - - float startz, startu, startv; - float izstep, uzstep, vzstep; - float endz, endu, endv; - UINT32 stepu, stepv; - register UINT32 bit; - local_for_thread INT32 *tiltlighting = NULL; - local_for_thread INT32 oldviewwidth = 0; - - // dont realloc every frame pls thx - if (tiltlighting == NULL || oldviewwidth != viewwidth) - { - tiltlighting = realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth); - oldviewwidth = viewwidth; - } - - iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); - - // Lighting is simple. It's just linear interpolation from start to end - { - float planelightfloat = PLANELIGHTFLOAT; - float lightstart, lightend; - - lightend = (iz + ds->szp.x*width) * planelightfloat; - lightstart = iz * planelightfloat; - - R_CalcTiltedLighting(tiltlighting, ds->x1, ds->x2, FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); - //CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf); - } - - uz = ds->sup.z + ds->sup.y*(centery-ds->y) + ds->sup.x*(ds->x1-centerx); - vz = ds->svp.z + ds->svp.y*(centery-ds->y) + ds->svp.x*(ds->x1-centerx); - - dest = R_Address(ds->x1, ds->y); - - source = ds->source; - -#if 0 // The "perfect" reference version of this routine. Pretty slow. - // Use it only to see how things are supposed to look. - i = 0; - do - { - double z = 1.f/iz; - u = (INT64)(uz*z); - v = (INT64)(vz*z); - - bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); - colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); - *dest = colormap[source[bit]]; - - dest++; - iz += ds->szp.x; - uz += ds->sup.x; - vz += ds->svp.x; - } while (--width >= 0); -#else - startz = 1.f/iz; - startu = uz*startz; - startv = vz*startz; - - izstep = ds->szp.x * SPANSIZE; - uzstep = ds->sup.x * SPANSIZE; - vzstep = ds->svp.x * SPANSIZE; - width++; - - while (width >= SPANSIZE) - { - iz += izstep; - uz += uzstep; - vz += vzstep; - - endz = 1.f/iz; - endu = uz*endz; - endv = vz*endz; - stepu = (INT64)((endu - startu) * INVSPAN); - stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu); - v = (INT64)(startv); - - for (i = SPANSIZE-1; i >= 0; i--) - { - bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); - colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); - *dest = colormap[source[bit]]; - - dest++; - u += stepu; - v += stepv; - } - startu = endu; - startv = endv; - width -= SPANSIZE; - } - if (width > 0) - { - if (width == 1) - { - u = (INT64)(startu); - v = (INT64)(startv); - bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); - colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); - *dest = colormap[source[bit]]; - } - else - { - float left = width; - iz += ds->szp.x * left; - uz += ds->sup.x * left; - vz += ds->svp.x * left; - - endz = 1.f/iz; - endu = uz*endz; - endv = vz*endz; - left = 1.f/left; - stepu = (INT64)((endu - startu) * left); - stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu); - v = (INT64)(startv); - - for (; width != 0; width--) - { - bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); - colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); - *dest = colormap[source[bit]]; - - dest++; - u += stepu; - v += stepv; - } - } - } -#endif -} - -/** \brief The R_DrawTiltedTranslucentSpan function - Like DrawTiltedSpan, but translucent -*/ -void R_DrawTranslucentSpan_Tilted(drawspandata_t* ds) -{ - int width = ds->x2 - ds->x1; - float iz, uz, vz; - UINT32 u, v; - int i; - - UINT8 *source; - UINT8 *colormap; - register UINT8 *dest; - - float startz, startu, startv; - float izstep, uzstep, vzstep; - float endz, endu, endv; - UINT32 stepu, stepv; - register UINT32 bit; - local_for_thread INT32 *tiltlighting = NULL; - local_for_thread INT32 oldviewwidth = 0; - - // dont realloc every frame pls thx - if (tiltlighting == NULL || oldviewwidth != viewwidth) - { - tiltlighting = realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth); - oldviewwidth = viewwidth; - } - - iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); - - // Lighting is simple. It's just linear interpolation from start to end - { - float planelightfloat = PLANELIGHTFLOAT; - float lightstart, lightend; - - lightend = (iz + ds->szp.x*width) * planelightfloat; - lightstart = iz * planelightfloat; - - R_CalcTiltedLighting(tiltlighting, ds->x1, ds->x2, FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); - //CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf); - } - - uz = ds->sup.z + ds->sup.y*(centery-ds->y) + ds->sup.x*(ds->x1-centerx); - vz = ds->svp.z + ds->svp.y*(centery-ds->y) + ds->svp.x*(ds->x1-centerx); - - dest = R_Address(ds->x1, ds->y); - - source = ds->source; - -#if 0 // The "perfect" reference version of this routine. Pretty slow. - // Use it only to see how things are supposed to look. - i = 0; - do - { - double z = 1.f/iz; - u = (INT64)(uz*z); - v = (INT64)(vz*z); - - bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); - colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); - *dest = *(ds->transmap + (colormap[source[bit]] << 8) + *dest); - - dest++; - iz += ds->szp.x; - uz += ds->sup.x; - vz += ds->svp.x; - } while (--width >= 0); -#else - startz = 1.f/iz; - startu = uz*startz; - startv = vz*startz; - - izstep = ds->szp.x * SPANSIZE; - uzstep = ds->sup.x * SPANSIZE; - vzstep = ds->svp.x * SPANSIZE; - width++; - - while (width >= SPANSIZE) - { - iz += izstep; - uz += uzstep; - vz += vzstep; - - endz = 1.f/iz; - endu = uz*endz; - endv = vz*endz; - stepu = (INT64)((endu - startu) * INVSPAN); - stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu); - v = (INT64)(startv); - - for (i = SPANSIZE-1; i >= 0; i--) - { - bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); - colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); - *dest = *(ds->transmap + (colormap[source[bit]] << 8) + *dest); - - dest++; - u += stepu; - v += stepv; - } - startu = endu; - startv = endv; - width -= SPANSIZE; - } - if (width > 0) - { - if (width == 1) - { - u = (INT64)(startu); - v = (INT64)(startv); - bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); - colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); - *dest = *(ds->transmap + (colormap[source[bit]] << 8) + *dest); - } - else - { - float left = width; - iz += ds->szp.x * left; - uz += ds->sup.x * left; - vz += ds->svp.x * left; - - endz = 1.f/iz; - endu = uz*endz; - endv = vz*endz; - left = 1.f/left; - stepu = (INT64)((endu - startu) * left); - stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu); - v = (INT64)(startv); - - for (; width != 0; width--) - { - bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); - colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); - *dest = *(ds->transmap + (colormap[source[bit]] << 8) + *dest); - - dest++; - u += stepu; - v += stepv; - } - } - } -#endif -} - -/** \brief The R_DrawTiltedTranslucentWaterSpan function - Like DrawTiltedTranslucentSpan, but for water -*/ -void R_DrawTranslucentWaterSpan_Tilted(drawspandata_t* ds) -{ - int width = ds->x2 - ds->x1; - float iz, uz, vz; - UINT32 u, v; - int i; - - UINT8 *source; - UINT8 *colormap; - register UINT8 *dest; - UINT8 *dsrc; - - float startz, startu, startv; - float izstep, uzstep, vzstep; - float endz, endu, endv; - UINT32 stepu, stepv; - register UINT32 bit; - local_for_thread INT32 *tiltlighting = NULL; - local_for_thread INT32 oldviewwidth = 0; - - // dont realloc every frame pls thx - if (tiltlighting == NULL || oldviewwidth != viewwidth) - { - tiltlighting = realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth); - oldviewwidth = viewwidth; - } - - iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); - - // Lighting is simple. It's just linear interpolation from start to end - { - float planelightfloat = PLANELIGHTFLOAT; - float lightstart, lightend; - - lightend = (iz + ds->szp.x*width) * planelightfloat; - lightstart = iz * planelightfloat; - - R_CalcTiltedLighting(tiltlighting, ds->x1, ds->x2, FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); - //CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf); - } - - uz = ds->sup.z + ds->sup.y*(centery-ds->y) + ds->sup.x*(ds->x1-centerx); - vz = ds->svp.z + ds->svp.y*(centery-ds->y) + ds->svp.x*(ds->x1-centerx); - - dest = R_Address(ds->x1, ds->y); - dsrc = vid.screens[1] + (ds->y+ds->bgofs)*vid.width + ds->x1; - - source = ds->source; - -#if 0 // The "perfect" reference version of this routine. Pretty slow. - // Use it only to see how things are supposed to look. - i = 0; - do - { - double z = 1.f/iz; - u = (INT64)(uz*z); - v = (INT64)(vz*z); - - bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); - colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); - *dest = *(ds->transmap + (colormap[source[bit]] << 8) + *dsrc++); - - dest++; - iz += ds->szp.x; - uz += ds->sup.x; - vz += ds->svp.x; - } while (--width >= 0); -#else - startz = 1.f/iz; - startu = uz*startz; - startv = vz*startz; - - izstep = ds->szp.x * SPANSIZE; - uzstep = ds->sup.x * SPANSIZE; - vzstep = ds->svp.x * SPANSIZE; - width++; - - while (width >= SPANSIZE) - { - iz += izstep; - uz += uzstep; - vz += vzstep; - - endz = 1.f/iz; - endu = uz*endz; - endv = vz*endz; - stepu = (INT64)((endu - startu) * INVSPAN); - stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu); - v = (INT64)(startv); - - for (i = SPANSIZE-1; i >= 0; i--) - { - bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); - colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); - *dest = *(ds->transmap + (colormap[source[bit]] << 8) + *dsrc++); - - dest++; - u += stepu; - v += stepv; - } - startu = endu; - startv = endv; - width -= SPANSIZE; - } - if (width > 0) - { - if (width == 1) - { - u = (INT64)(startu); - v = (INT64)(startv); - bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); - colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); - *dest = *(ds->transmap + (colormap[source[bit]] << 8) + *dsrc++); - } - else - { - float left = width; - iz += ds->szp.x * left; - uz += ds->sup.x * left; - vz += ds->svp.x * left; - - endz = 1.f/iz; - endu = uz*endz; - endv = vz*endz; - left = 1.f/left; - stepu = (INT64)((endu - startu) * left); - stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu); - v = (INT64)(startv); - - for (; width != 0; width--) - { - bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); - colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); - *dest = *(ds->transmap + (colormap[source[bit]] << 8) + *dsrc++); - - dest++; - u += stepu; - v += stepv; - } - } - } -#endif -} - -void R_DrawSplat_Tilted(drawspandata_t* ds) -{ - // x1, x2 = ds->x1, ds->x2 - int width = ds->x2 - ds->x1; - float iz, uz, vz; - UINT32 u, v; - int i; - - UINT8 *source; - UINT8 *colormap; - register UINT8 *dest; - - UINT8 val; - - float startz, startu, startv; - float izstep, uzstep, vzstep; - float endz, endu, endv; - UINT32 stepu, stepv; - register UINT32 bit; - local_for_thread INT32 *tiltlighting = NULL; - local_for_thread INT32 oldviewwidth = 0; - - // dont realloc every frame pls thx - if (tiltlighting == NULL || oldviewwidth != viewwidth) - { - tiltlighting = realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth); - oldviewwidth = viewwidth; - } - - iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); - - // Lighting is simple. It's just linear interpolation from start to end - { - float planelightfloat = PLANELIGHTFLOAT; - float lightstart, lightend; - - lightend = (iz + ds->szp.x*width) * planelightfloat; - lightstart = iz * planelightfloat; - - R_CalcTiltedLighting(tiltlighting, ds->x1, ds->x2, FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); - //CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf); - } - - uz = ds->sup.z + ds->sup.y*(centery-ds->y) + ds->sup.x*(ds->x1-centerx); - vz = ds->svp.z + ds->svp.y*(centery-ds->y) + ds->svp.x*(ds->x1-centerx); - - dest = R_Address(ds->x1, ds->y); - - source = ds->source; - //colormap = ds->colormap; - -#if 0 // The "perfect" reference version of this routine. Pretty slow. - // Use it only to see how things are supposed to look. - i = 0; - do - { - double z = 1.f/iz; - u = (INT64)(uz*z); - v = (INT64)(vz*z); - - bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); - val = source[bit]; - - if (val != TRANSPARENTPIXEL) - { - colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); - *dest = colormap[val]; - } - dest++; - iz += ds->szp.x; - uz += ds->sup.x; - vz += ds->svp.x; - } while (--width >= 0); -#else - startz = 1.f/iz; - startu = uz*startz; - startv = vz*startz; - - izstep = ds->szp.x * SPANSIZE; - uzstep = ds->sup.x * SPANSIZE; - vzstep = ds->svp.x * SPANSIZE; - //x1 = 0; - width++; - - while (width >= SPANSIZE) - { - iz += izstep; - uz += uzstep; - vz += vzstep; - - endz = 1.f/iz; - endu = uz*endz; - endv = vz*endz; - stepu = (INT64)((endu - startu) * INVSPAN); - stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu); - v = (INT64)(startv); - - for (i = SPANSIZE-1; i >= 0; i--) - { - bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); - val = source[bit]; - if (val != TRANSPARENTPIXEL) - { - colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); - *dest = colormap[val]; - } - dest++; - u += stepu; - v += stepv; - } - startu = endu; - startv = endv; - width -= SPANSIZE; - } - if (width > 0) - { - if (width == 1) - { - u = (INT64)(startu); - v = (INT64)(startv); - bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); - val = source[bit]; - if (val != TRANSPARENTPIXEL) - { - colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); - *dest = colormap[val]; - } - } - else - { - float left = width; - iz += ds->szp.x * left; - uz += ds->sup.x * left; - vz += ds->svp.x * left; - - endz = 1.f/iz; - endu = uz*endz; - endv = vz*endz; - left = 1.f/left; - stepu = (INT64)((endu - startu) * left); - stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu); - v = (INT64)(startv); - - for (; width != 0; width--) - { - bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); - val = source[bit]; - if (val != TRANSPARENTPIXEL) - { - colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); - *dest = colormap[val]; - } - dest++; - u += stepu; - v += stepv; - } - } - } -#endif -} - -void R_DrawFogSpan_Tilted(drawspandata_t* ds) -{ - int width = ds->x2 - ds->x1; - float iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); - register UINT8 *dest; - - local_for_thread INT32 *tiltlighting = NULL; - local_for_thread INT32 oldviewwidth = 0; - - // dont realloc every frame pls thx - if (tiltlighting == NULL || oldviewwidth != viewwidth) - { - tiltlighting = realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth); - oldviewwidth = viewwidth; - } - - dest = R_Address(ds->x1, ds->y); - - // Lighting is simple. It's just linear interpolation from start to end - { - float planelightfloat = PLANELIGHTFLOAT; - float lightstart, lightend; - - lightend = (iz + ds->szp.x*width) * planelightfloat; - lightstart = iz * planelightfloat; - - R_CalcTiltedLighting(tiltlighting, ds->x1, ds->x2, FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); - //CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf); - } - - do - { - UINT8 *colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); - *dest = colormap[*dest]; - dest++; - } - while (--width >= 0); -} - diff --git a/src/r_draw_span.cpp b/src/r_draw_span.cpp new file mode 100644 index 000000000..07a76b7cc --- /dev/null +++ b/src/r_draw_span.cpp @@ -0,0 +1,446 @@ +// SONIC ROBO BLAST 2 KART +//----------------------------------------------------------------------------- +// Copyright (C) 2025 by Kart Krew. +// Copyright (C) 2020 by Sonic Team Junior. +// Copyright (C) 2000 by DooM Legacy Team. +// Copyright (C) 1996 by id Software, Inc. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file r_draw_span.cpp +/// \brief span drawer functions +/// \note no includes because this is included as part of r_draw.cpp + +#ifdef HAVE_THREADS +#ifdef _WIN32 +#include +#define local_for_thread static __thread +#else +#include +#define local_for_thread thread_local static +#endif +#else +#define local_for_thread static +#endif + +// ========================================================================== +// SPANS +// ========================================================================== + +#define SPANSIZE 16 +#define INVSPAN 0.0625f + +// 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size) +#define MAXFLATBYTES 4194303 + +#define PLANELIGHTFLOAT ((float)BASEVIDWIDTH * BASEVIDWIDTH / stride / ds->zeroheight / 21.0f * FIXED_TO_FLOAT(fovtan)) + +enum DrawSpanType +{ + DS_BASIC = 0x0000, + DS_COLORMAP = 0x0001, + DS_TRANSMAP = 0x0002, + DS_HOLES = 0x0004, + DS_RIPPLE = 0x0008, +}; + +template +static constexpr UINT8 R_GetSpanTranslucent(drawspandata_t* ds, UINT8 *dsrc, const UINT8 *colormap, UINT8 col) +{ + col = colormap[col]; + + if constexpr (Type & DrawSpanType::DS_TRANSMAP) + { + return *(ds->transmap + (col << 8) + (*dsrc)); + } + else + { + return col; + } +} + +template +static constexpr UINT8 R_DrawSpanPixel(drawspandata_t* ds, UINT8 *dsrc, const UINT8 *colormap, UINT32 bit, const UINT8 *source) +{ + UINT8 col = source[bit]; + + if constexpr (Type & DrawSpanType::DS_HOLES) + { + if (col == TRANSPARENTPIXEL) + { + return *dsrc; + } + } + + return R_GetSpanTranslucent(ds, dsrc, colormap, col); +} + +/** \brief The R_DrawSpan_8 function + Draws the actual span. +*/ +template +static void R_DrawSpanTemplate(drawspandata_t* ds) +{ + UINT32 xposition; + UINT32 yposition; + UINT32 xstep, ystep; + UINT32 bit; + + UINT8 *dest = R_Address(ds->x1, ds->y); + UINT8 *dsrc; + + const UINT8 *deststop = vid.screens[0] + vid.rowbytes * vid.height; + + if (dest+8 > deststop) + { + return; + } + + intptr_t count = (ds->x2 - ds->x1 + 1); + size_t i; + + xposition = ds->xfrac; yposition = ds->yfrac; + xstep = ds->xstep; ystep = ds->ystep; + + const UINT8 *source = ds->source; + const UINT8 *colormap = ds->colormap; + + if constexpr (Type & DS_RIPPLE) + { + yposition += ds->waterofs; + } + + // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest + // can be used for the fraction part. This allows calculation of the memory address in the + // texture with two shifts, an OR and one AND. (see below) + // for texture sizes > 64 the amount of precision we can allow will decrease, but only by one + // bit per power of two (obviously) + // Ok, because I was able to eliminate the variable spot below, this function is now FASTER + // than the original span renderer. Whodathunkit? + xposition <<= ds->nflatshiftup; yposition <<= ds->nflatshiftup; + xstep <<= ds->nflatshiftup; ystep <<= ds->nflatshiftup; + + if constexpr (Type & DS_RIPPLE) + { + dsrc = vid.screens[1] + (ds->y + ds->bgofs) * vid.width + ds->x1; + } + else + { + dsrc = dest; + } + + while (count >= 8) + { + // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't + // have the uber complicated math to calculate it now, so that was a memory write we didn't + // need! + + for (i = 0; i < 8; i++) + { + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + + dest[i] = R_DrawSpanPixel(ds, &dsrc[i], colormap, bit, source); + + xposition += xstep; + yposition += ystep; + } + + dest += 8; + dsrc += 8; + + count -= 8; + } + + while (count-- && dest <= deststop) + { + bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + + *dest = R_DrawSpanPixel(ds, dsrc, colormap, bit, source); + + dest++; + dsrc++; + + xposition += xstep; + yposition += ystep; + } +} + +// R_CalcTiltedLighting +// Exactly what it says on the tin. I wish I wasn't too lazy to explain things properly. +static void R_CalcTiltedLighting(INT32 *lightbuffer, INT32 x1, INT32 x2, fixed_t start, fixed_t end) +{ + // ZDoom uses a different lighting setup to us, and I couldn't figure out how to adapt their version + // of this function. Here's my own. + INT32 i, left = x1, right = x2; + const fixed_t step = (end-start)/(x2 - x1 + 1); + + // I wanna do some optimizing by checking for out-of-range segments on either side to fill in all at once, + // but I'm too bad at coding to not crash the game trying to do that. I guess this is fast enough for now... + + for (i = left; i <= right; i++) + { + lightbuffer[i] = (start += step) >> FRACBITS; + + if (lightbuffer[i] < 0) + { + lightbuffer[i] = 0; + } + else if (lightbuffer[i] >= MAXLIGHTSCALE) + { + lightbuffer[i] = MAXLIGHTSCALE-1; + } + } +} + +template +static void R_DrawTiltedSpanTemplate(drawspandata_t* ds) +{ + int width = ds->x2 - ds->x1; + float iz, uz, vz; + UINT32 u, v; + int i; + + UINT8 *dest = R_Address(ds->x1, ds->y); + UINT8 *dsrc; + + float startz, startu, startv; + float izstep, uzstep, vzstep; + float endz, endu, endv; + UINT32 stepu, stepv; + UINT32 bit; + local_for_thread INT32 *tiltlighting = NULL; + local_for_thread INT32 oldviewwidth = 0; + + // dont realloc every frame pls thx + if (tiltlighting == NULL || oldviewwidth != viewwidth) + { + tiltlighting = static_cast(realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth)); + oldviewwidth = viewwidth; + } + + INT32 x1 = ds->x1; + const INT32 nflatxshift = ds->nflatxshift; + const INT32 nflatyshift = ds->nflatyshift; + const INT32 nflatmask = ds->nflatmask; + const INT32 stride = vid.width; + + iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); + + // Lighting is simple. It's just linear interpolation from start to end + { + float planelightfloat = PLANELIGHTFLOAT; + float lightstart, lightend; + + lightend = (iz + ds->szp.x*width) * planelightfloat; + lightstart = iz * planelightfloat; + + R_CalcTiltedLighting(tiltlighting, ds->x1, ds->x2, FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); + //CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf); + } + + uz = ds->sup.z + ds->sup.y*(centery-ds->y) + ds->sup.x*(ds->x1-centerx); + vz = ds->svp.z + ds->svp.y*(centery-ds->y) + ds->svp.x*(ds->x1-centerx); + + const UINT8 *source = ds->source; + const UINT8 *colormap = ds->colormap; + + if constexpr (Type & DS_RIPPLE) + { + dsrc = vid.screens[1] + (ds->y + ds->bgofs) * stride + ds->x1; + } + else + { + dsrc = dest; + } + +#if 0 // The "perfect" reference version of this routine. Pretty slow. + // Use it only to see how things are supposed to look. + i = 0; + do + { + double z = 1.f/iz; + u = (INT64)(uz*z); + v = (INT64)(vz*z); + + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + colormap = planezlight[tiltlighting[ds->x1]] + (ds->colormap - colormaps); + + *dest = R_DrawSpanPixel(ds, dsrc, colormap, bit); + dest++; + ds->x1++; + dsrc++; + iz += ds_szp->x; + uz += ds_sup->x; + vz += ds_svp->x; + } while (--width >= 0); +#else + startz = 1.f/iz; + startu = uz*startz; + startv = vz*startz; + + izstep = ds->szp.x * SPANSIZE; + uzstep = ds->sup.x * SPANSIZE; + vzstep = ds->svp.x * SPANSIZE; + //x1 = 0; + width++; + + while (width >= SPANSIZE) + { + iz += izstep; + uz += uzstep; + vz += vzstep; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + stepu = (INT64)((endu - startu) * INVSPAN); + stepv = (INT64)((endv - startv) * INVSPAN); + u = (INT64)(startu); + v = (INT64)(startv); + + x1 = ds->x1; + + for (i = 0; i < SPANSIZE; i++) + { + bit = (((v + stepv * i) >> nflatyshift) & nflatmask) | ((u + stepu * i) >> nflatxshift); + colormap = ds->planezlight[tiltlighting[x1 + i]] + (ds->colormap - colormaps); + dest[i] = R_DrawSpanPixel(ds, &dsrc[i], colormap, bit, source); + } + + ds->x1 += SPANSIZE; + dest += SPANSIZE; + dsrc += SPANSIZE; + startu = endu; + startv = endv; + width -= SPANSIZE; + } + + if (width > 0) + { + if (width == 1) + { + u = (INT64)(startu); + v = (INT64)(startv); + bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); + colormap = ds->planezlight[tiltlighting[ds->x1]] + (ds->colormap - colormaps); + *dest = R_DrawSpanPixel(ds, dsrc, colormap, bit, source); + ds->x1++; + } + else + { + double left = width; + iz += ds->szp.x * left; + uz += ds->sup.x * left; + vz += ds->svp.x * left; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + left = 1.f/left; + stepu = (INT64)((endu - startu) * left); + stepv = (INT64)((endv - startv) * left); + u = (INT64)(startu); + v = (INT64)(startv); + + for (; width != 0; width--) + { + bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift); + colormap = ds->planezlight[tiltlighting[ds->x1]] + (ds->colormap - colormaps); + *dest = R_DrawSpanPixel(ds, dsrc, colormap, bit, source); + dest++; + ds->x1++; + dsrc++; + u += stepu; + v += stepv; + } + } + } +#endif +} + +#define DEFINE_SPAN_FUNC(name, flags, template) \ +void name(drawspandata_t* ds) \ +{ \ + constexpr DrawSpanType opt = static_cast(flags); \ + template(ds); \ +} + +#define DEFINE_SPAN_COMBO(name, flags) \ +DEFINE_SPAN_FUNC(name, flags, R_DrawSpanTemplate) \ +DEFINE_SPAN_FUNC(name ## _Tilted, flags, R_DrawTiltedSpanTemplate) \ + +DEFINE_SPAN_COMBO(R_DrawSpan, DS_BASIC) +DEFINE_SPAN_COMBO(R_DrawTranslucentSpan, DS_TRANSMAP) +DEFINE_SPAN_COMBO(R_DrawSplat, DS_HOLES) +DEFINE_SPAN_COMBO(R_DrawTranslucentSplat, DS_TRANSMAP|DS_HOLES) +DEFINE_SPAN_COMBO(R_DrawTranslucentWaterSpan, DS_TRANSMAP|DS_RIPPLE) + +/** \brief The R_DrawFogSpan function + Draws the actual span with fogging. +*/ +void R_DrawFogSpan(drawspandata_t* ds) +{ + const UINT8 *colormap = ds->colormap; + UINT8 *dest = R_Address(ds->x1, ds->y); + + intptr_t count = ds->x2 - ds->x1 + 1; + + while (count >= 4) + { + dest[0] = colormap[dest[0]]; + dest[1] = colormap[dest[1]]; + dest[2] = colormap[dest[2]]; + dest[3] = colormap[dest[3]]; + + dest += 4; + count -= 4; + } + + while (count--) + { + *dest = colormap[*dest]; + dest++; + } +} + +void R_DrawFogSpan_Tilted(drawspandata_t* ds) +{ + int width = ds->x2 - ds->x1; + float iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); + UINT8 *dest; + + local_for_thread INT32 *tiltlighting = NULL; + local_for_thread INT32 oldviewwidth = 0; + + // dont realloc every frame pls thx + if (tiltlighting == NULL || oldviewwidth != viewwidth) + { + tiltlighting = static_cast(realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth)); + oldviewwidth = viewwidth; + } + + dest = R_Address(ds->x1, ds->y); + const INT32 stride = vid.width; + + // Lighting is simple. It's just linear interpolation from start to end + { + float planelightfloat = PLANELIGHTFLOAT; + float lightstart, lightend; + + lightend = (iz + ds->szp.x*width) * planelightfloat; + lightstart = iz * planelightfloat; + + R_CalcTiltedLighting(tiltlighting, ds->x1, ds->x2, FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); + //CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf); + } + + do + { + UINT8 *colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps); + *dest = colormap[*dest]; + dest++; + } + while (--width >= 0); +} diff --git a/src/r_plane.cpp b/src/r_plane.cpp index e7a9d008c..9610c0c84 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -1272,6 +1272,9 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle case SPANDRAWFUNC_SPLAT: spanfunctype = SPANDRAWFUNC_TILTEDSPLAT; break; + case SPANDRAWFUNC_TRANSSPLAT: + spanfunctype = SPANDRAWFUNC_TILTEDTRANSSPLAT; + break; case SPANDRAWFUNC_FOG: spanfunctype = SPANDRAWFUNC_TILTEDFOG; break; diff --git a/src/screen.c b/src/screen.c index cec9b4b9b..67ef0f1dd 100644 --- a/src/screen.c +++ b/src/screen.c @@ -91,6 +91,7 @@ static void SCR_SetDrawFuncs(void) spanfuncs[SPANDRAWFUNC_SPLAT] = R_DrawSplat; spanfuncs[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat; spanfuncs[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawSplat_Tilted; + spanfuncs[SPANDRAWFUNC_TILTEDTRANSSPLAT] = R_DrawTranslucentSpan_Tilted; spanfuncs[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan; spanfuncs[SPANDRAWFUNC_TILTEDWATER] = R_DrawTranslucentWaterSpan_Tilted; spanfuncs[SPANDRAWFUNC_FOG] = R_DrawFogSpan; -- 2.54.0 From 57f15e02136796c9c8980afeeedaa45e29adba1b Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 13 Jun 2025 03:22:36 +0200 Subject: [PATCH 107/141] R_GenerateBlendTables can be static --- src/r_draw.cpp | 4 +++- src/r_draw.h | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/r_draw.cpp b/src/r_draw.cpp index 9e0f12cb4..23d512a19 100644 --- a/src/r_draw.cpp +++ b/src/r_draw.cpp @@ -110,6 +110,8 @@ static UINT8 **localtranslationtablecache[MAXLOCALSKINS] = {NULL}; CV_PossibleValue_t Color_cons_t[MAXSKINCOLORS+1]; +static void R_GenerateBlendTables(void); + /** \brief Initializes the translucency tables used by the Software renderer. */ void R_InitTranslucencyTables(void) @@ -239,7 +241,7 @@ static void BlendTab_GenerateMaps(INT32 tab, INT32 style, void (*genfunc)(UINT8 } } -void R_GenerateBlendTables(void) +static void R_GenerateBlendTables(void) { INT32 i; diff --git a/src/r_draw.h b/src/r_draw.h index 68106480b..a28a09e79 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -209,7 +209,6 @@ enum extern UINT8 *blendtables[NUMBLENDMAPS]; void R_InitTranslucencyTables(void); -void R_GenerateBlendTables(void); UINT8 *R_GetTranslucencyTable(INT32 alphalevel); UINT8 *R_GetBlendTable(int style, INT32 alphalevel); -- 2.54.0 From e94737945a13510493c01bf5d72c3fca2918c750 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 13 Jun 2025 08:11:32 +0200 Subject: [PATCH 108/141] fix double sided skies per addline clipping code fixes greencave skybox hopefully this is it and doesent break anything else sigh --- src/r_bsp.c | 23 ++++++++++++++--------- src/r_segs.cpp | 11 ++++------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/r_bsp.c b/src/r_bsp.c index 833e378c5..b0a509b50 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -298,6 +298,7 @@ static void R_AddLine(seg_t *line) INT32 x1, x2; angle_t angle1, angle2, span, tspan; static sector_t tempsec; + boolean bothfloorssky = false; g_portal = NULL; @@ -390,6 +391,10 @@ static void R_AddLine(seg_t *line) doorclosed = 0; + // likewise, but for floors and upper textures + if (backsector->floorpic == skyflatnum && frontsector->floorpic == skyflatnum) + bothfloorssky = true; + fixed_t frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends fixed_t backf1, backf2, backc1, backc2; // back floor ceiling ends @@ -417,19 +422,19 @@ static void R_AddLine(seg_t *line) if (viewsector != backsector && viewsector != frontsector) { // here we're talking about a CEILING lower than a floor. ...yeah we don't even need to bother. - if (backc1 <= frontf1 && backc2 <= frontf2) + const boolean ceillow = (backc1 <= frontf1 && backc2 <= frontf2); + + // this tries to fix some skyboxes drawing a black void as a midtexture lel + if (ceillow && (!bothfloorssky && backsector->ceilingpic == skyflatnum && frontsector->ceilingpic != skyflatnum) // double sided with back ceiling sky but not front ceiling sky + && !line->sidedef->midtexture && !line->sidedef->bottomtexture && !line->sidedef->toptexture && !line->polyseg) // effectively empty { - goto clipsolid; - } - - // here we're talking about floors higher than ceilings, don't even bother either. - if (backf1 >= frontc1 && backf2 >= frontc2) - { - goto clipsolid; + goto clippass; } + doorclosed = ceillow + || (backf1 >= frontc1 && backf2 >= frontc2) // Check for automap fix. Store in doorclosed for r_segs.c - doorclosed = (backc1 <= backf1 && backc2 <= backf2 + || (backc1 <= backf1 && backc2 <= backf2 && ((backc1 >= frontc1 && backc2 >= frontc2) || curline->sidedef->toptexture) && ((backf1 <= frontf1 && backf2 >= frontf2) || curline->sidedef->bottomtexture) && (backsector->ceilingpic != skyflatnum || frontsector->ceilingpic != skyflatnum)); diff --git a/src/r_segs.cpp b/src/r_segs.cpp index 81a42783c..f049b3789 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -2430,7 +2430,6 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (!segtextured && !curline->polyseg) { const bool tophigh = (worldhigh <= worldtop && worldhighslope <= worldtopslope); - const bool topnothigh = (backsector && (worldhigh != worldtop || worldhighslope != worldtopslope)); // if we cant see the goddamn skyplane, well there wont be any skybox // we could kill skyVisible instead, but i want to keep the performance improvemnts it yields @@ -2438,14 +2437,12 @@ void R_StoreWallRange(INT32 start, INT32 stop) if ((tophigh && (frontsector->floorpic != skyflatnum && frontsector->ceilingpic != skyflatnum)) // try to guess if its a "window" && ((!backsector) // single sided - || (topnothigh && (backsector->floorheight > frontsector->ceilingheight || backsector->ceilingheight < frontsector->floorheight)))) // check if there is a "thok" sector behind it + || ((backsector && (worldhigh != worldtop || worldhighslope != worldtopslope)) + && (backsector->floorheight >= frontsector->ceilingheight || backsector->ceilingheight <= frontsector->floorheight)))) // check if there is a "thok" sector behind it skyVisible = true; - // this is an attempt to fix issues with textureless midtextures drawing nothing where they should just draw sky instead - if ((tophigh - && newview->sky) // only do this for skyrender - && ((!backsector && frontsector->ceilingpic == skyflatnum) // single sided line with sky ceiling - || (topnothigh && (backsector->ceilingpic == skyflatnum && frontsector->ceilingpic != skyflatnum)))) // double sided with back ceiling sky but not front ceiling sky + // this is an attempt to fix issues with textureless single sided lines drawing nothing where they should just draw sky instead + if (tophigh && !backsector && frontsector->ceilingpic == skyflatnum) { topstep = -FixedMul (rw_scalestep, worldbottom); topfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale); -- 2.54.0 From 97075ca5c52a6eb8168abbeee23ac609bca95c33 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 13 Jun 2025 16:07:38 +0200 Subject: [PATCH 109/141] remove some code dupe starting to like those lambda things --- src/r_segs.cpp | 115 +++++++++++++++++++++---------------------------- 1 file changed, 48 insertions(+), 67 deletions(-) diff --git a/src/r_segs.cpp b/src/r_segs.cpp index f049b3789..bfdb24dd6 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -2089,7 +2089,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) rw_bottomtexturemid += sidedef->rowoffset; // allocate space for masked texture tables - if (frontsector && backsector && frontsector->tag != backsector->tag && (backsector->ffloors || frontsector->ffloors)) + if (frontsector && backsector && (frontsector->tag != backsector->tag) && (backsector->ffloors || frontsector->ffloors)) { ffloor_t *rover; ffloor_t *r2; @@ -2109,6 +2109,14 @@ void R_StoreWallRange(INT32 start, INT32 stop) lowcutslope = std::max(worldbottomslope, worldlowslope) + viewz; highcutslope = std::min(worldtopslope, worldhighslope) + viewz; + auto check_fof_offscreen = [&](INT32 bottom, INT32 bottomslope, INT32 top, INT32 topslope) + { + return ((P_GetFFloorTopZAt (rover, segleft .x, segleft .y) <= bottom + viewz + && P_GetFFloorTopZAt (rover, segright.x, segright.y) <= bottomslope + viewz) + || ( P_GetFFloorBottomZAt (rover, segleft .x, segleft .y) >= top + viewz + && P_GetFFloorBottomZAt (rover, segright.x, segright.y) >= topslope + viewz)); + }; + if (frontsector->ffloors && backsector->ffloors) { i = 0; @@ -2230,14 +2238,12 @@ void R_StoreWallRange(INT32 start, INT32 stop) { if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS) || rover->flags & FF_INVERTSIDES) continue; + if (rover->norender == leveltime) continue; // Oy vey. - if ( ((P_GetFFloorTopZAt (rover, segleft .x, segleft .y)) <= worldbottom + viewz - && (P_GetFFloorTopZAt (rover, segright.x, segright.y)) <= worldbottomslope + viewz) - ||((P_GetFFloorBottomZAt(rover, segleft .x, segleft .y)) >= worldtop + viewz - && (P_GetFFloorBottomZAt(rover, segright.x, segright.y)) >= worldtopslope + viewz)) + if (check_fof_offscreen(worldbottom, worldbottomslope, worldtop, worldtopslope)) continue; ds_p->thicksides[i] = rover; @@ -2250,20 +2256,15 @@ void R_StoreWallRange(INT32 start, INT32 stop) { if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS) || !(rover->flags & FF_ALLSIDES)) continue; + if (rover->norender == leveltime) continue; // Oy vey. - if ( (P_GetFFloorTopZAt (rover, segleft .x, segleft .y) <= worldbottom + viewz - && P_GetFFloorTopZAt (rover, segright.x, segright.y) <= worldbottomslope + viewz) - ||(P_GetFFloorBottomZAt(rover, segleft .x, segleft .y) >= worldtop + viewz - && P_GetFFloorBottomZAt(rover, segright.x, segright.y) >= worldtopslope + viewz)) + if (check_fof_offscreen(worldbottom, worldbottomslope, worldtop, worldtopslope)) continue; - if ( (P_GetFFloorTopZAt (rover, segleft .x, segleft .y) <= worldlow + viewz - && P_GetFFloorTopZAt (rover, segright.x, segright.y) <= worldlowslope + viewz) - ||(P_GetFFloorBottomZAt(rover, segleft .x, segleft .y) >= worldhigh + viewz - && P_GetFFloorBottomZAt(rover, segright.x, segright.y) >= worldhighslope + viewz)) + if (check_fof_offscreen(worldlow, worldlowslope, worldhigh, worldhighslope)) continue; ds_p->thicksides[i] = rover; @@ -2605,12 +2606,25 @@ void R_StoreWallRange(INT32 start, INT32 stop) fixed_t planevistest; i = 0; + auto setup_back_fof = [&] + { + //ffloor[i].slope = *rover->b_slope; + ffloor[i].b_pos = roverleft; + ffloor[i].b_pos_slope = roverright; + ffloor[i].b_pos >>= 4; + ffloor[i].b_pos_slope >>= 4; + ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); + ffloor[i].b_step = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos_slope, ds_p->scale2); + ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(range); + }; + if (backsector->ffloors) { for (rover = backsector->ffloors; rover && i < MAXFFLOORS; rover = rover->next) { if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES)) continue; + if (rover->norender == leveltime) continue; @@ -2627,14 +2641,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) ((viewz < planevistest && !(rover->flags & FF_INVERTPLANES)) || (viewz > planevistest && (rover->flags & FF_BOTHPLANES)))) { - //ffloor[i].slope = *rover->b_slope; - ffloor[i].b_pos = roverleft; - ffloor[i].b_pos_slope = roverright; - ffloor[i].b_pos >>= 4; - ffloor[i].b_pos_slope >>= 4; - ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); - ffloor[i].b_step = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos_slope, ds_p->scale2); - ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(range); + setup_back_fof(); i++; } @@ -2650,14 +2657,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) ((viewz > planevistest && !(rover->flags & FF_INVERTPLANES)) || (viewz < planevistest && (rover->flags & FF_BOTHPLANES)))) { - //ffloor[i].slope = *rover->t_slope; - ffloor[i].b_pos = roverleft; - ffloor[i].b_pos_slope = roverright; - ffloor[i].b_pos >>= 4; - ffloor[i].b_pos_slope >>= 4; - ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); - ffloor[i].b_step = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos_slope, ds_p->scale2); - ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(range); + setup_back_fof(); i++; } } @@ -2684,14 +2684,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) ((viewz < planevistest && !(rover->flags & FF_INVERTPLANES)) || (viewz > planevistest && (rover->flags & FF_BOTHPLANES)))) { - //ffloor[i].slope = *rover->b_slope; - ffloor[i].b_pos = roverleft; - ffloor[i].b_pos_slope = roverright; - ffloor[i].b_pos >>= 4; - ffloor[i].b_pos_slope >>= 4; - ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); - ffloor[i].b_step = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos_slope, ds_p->scale2); - ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(range); + setup_back_fof(); i++; } @@ -2707,14 +2700,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) ((viewz > planevistest && !(rover->flags & FF_INVERTPLANES)) || (viewz < planevistest && (rover->flags & FF_BOTHPLANES)))) { - //ffloor[i].slope = *rover->t_slope; - ffloor[i].b_pos = roverleft; - ffloor[i].b_pos_slope = roverright; - ffloor[i].b_pos >>= 4; - ffloor[i].b_pos_slope >>= 4; - ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); - ffloor[i].b_step = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos_slope, ds_p->scale2); - ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(range); + setup_back_fof(); i++; } } @@ -2722,6 +2708,21 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (curline->polyseg && frontsector && (curline->polyseg->flags & POF_RENDERPLANES)) { + auto setup_back_polyobj = [&](fixed_t height) + { + if (ffloor[i].plane->minx > ds_p->x1) + ffloor[i].plane->minx = ds_p->x1; + + if (ffloor[i].plane->maxx < ds_p->x2) + ffloor[i].plane->maxx = ds_p->x2; + + ffloor[i].slope = NULL; + ffloor[i].b_pos = height; + ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4; + ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos); + ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); + }; + while (i < numffloors && ffloor[i].polyobj != curline->polyseg) i++; @@ -2729,17 +2730,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) backsector->floorheight >= frontsector->floorheight && (viewz < backsector->floorheight)) { - if (ffloor[i].plane->minx > ds_p->x1) - ffloor[i].plane->minx = ds_p->x1; - - if (ffloor[i].plane->maxx < ds_p->x2) - ffloor[i].plane->maxx = ds_p->x2; - - ffloor[i].slope = NULL; - ffloor[i].b_pos = backsector->floorheight; - ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4; - ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos); - ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); + setup_back_polyobj(backsector->floorheight); i++; } @@ -2747,17 +2738,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) backsector->ceilingheight <= frontsector->ceilingheight && (viewz > backsector->ceilingheight)) { - if (ffloor[i].plane->minx > ds_p->x1) - ffloor[i].plane->minx = ds_p->x1; - - if (ffloor[i].plane->maxx < ds_p->x2) - ffloor[i].plane->maxx = ds_p->x2; - - ffloor[i].slope = NULL; - ffloor[i].b_pos = backsector->ceilingheight; - ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4; - ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos); - ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); + setup_back_polyobj(backsector->ceilingheight); i++; } } -- 2.54.0 From 5011b17f884651b6f7490fe6d2788901c674fa09 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 18 Jun 2025 09:13:13 +0200 Subject: [PATCH 110/141] attempt at optimizing drawcolumn drawers a bit more inspired by dsda/prboom seems to be super slighty faster --- src/r_draw_column.cpp | 175 ++++++++++++++++++++++++------------------ 1 file changed, 99 insertions(+), 76 deletions(-) diff --git a/src/r_draw_column.cpp b/src/r_draw_column.cpp index b546c66ea..97273e728 100644 --- a/src/r_draw_column.cpp +++ b/src/r_draw_column.cpp @@ -176,11 +176,15 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) } else { - // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. - // This is as fast as it gets. + // Inner loop that does the actual texture mapping, + // e.g. a DDA-lile scaling. + // This is as fast as it gets. (Yeah, right!!! -- killough) + // + // killough 2/1/98: more performance tuning + fixed_t frac; const intptr_t fracstep = dc->iscale; - intptr_t heightmask = dc->sourcelength-1; + const intptr_t heightmask = dc->sourcelength-1; static const INT32 npow2min = -1; const INT32 npow2max = dc->sourcelength; const INT32 stride = vid.width; @@ -196,87 +200,106 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) // Determine scaling, which is the only mapping to be done. frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep)); - if (heightmask == -1) + switch (heightmask) { - if (frac < 0) - // adjust in case we underread - frac += FRACUNIT; - - // texture has no height, so just go - while (--count > 0) - { - *dest = R_DrawColumnPixel(dc, dest, frac>>FRACBITS, source, colormap); - dest += stride; - frac += fracstep; - } - } - else if (dc->sourcelength & heightmask) // not a power of 2 -- killough - { - heightmask = dc->texheight << FRACBITS; - - if (frac < 0) - { - while ((frac += heightmask) < 0) + case 255: + case 127: { - ; + while(count--) + { + *dest = R_DrawColumnPixel(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap); + dest += stride; + frac += fracstep; + } } - } - else - { - while (frac >= heightmask) + break; + case -1: { - frac -= heightmask; + if (frac < 0) + // adjust in case we underread + frac += FRACUNIT; + + // texture has no height, so just go + while (--count > 0) + { + *dest = R_DrawColumnPixel(dc, dest, frac>>FRACBITS, source, colormap); + dest += stride; + frac += fracstep; + } } - } - - do - { - // Re-map color indices from wall texture column - // using a lighting/special effects LUT. - // heightmask is the Tutti-Frutti fix - - // -1 is the lower clamp bound because column posts have a "safe" byte before the real data - // and a few bytes after as well - *dest = R_DrawColumnPixel(dc, dest, std::clamp((frac >> FRACBITS), npow2min, npow2max), source, colormap); - - dest += stride; - -#if __SIZEOF_POINTER__ < 8 // 64-bit systems have large enough numbers for this to be a non-issue - // Avoid overflow. - if (fracstep > 0x7FFFFFFF - frac) + break; + default: { - frac += fracstep - heightmask; - } - else + if (!(dc->sourcelength & heightmask)) // power of 2 -- killough + { + while ((count -= 2) >= 0) // texture height is a power of 2 -- killough + { + *dest = R_DrawColumnPixel(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap); + dest += stride; + frac += fracstep; + + *dest = R_DrawColumnPixel(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap); + dest += stride; + frac += fracstep; + } + + if (count & 1) + { + *dest = R_DrawColumnPixel(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap); + } + } + else + { + const intptr_t fixed_heightmask = dc->texheight << FRACBITS; + + if (frac < 0) + { + while ((frac += fixed_heightmask) < 0) + { + ; + } + } + else + { + while (frac >= fixed_heightmask) + { + frac -= fixed_heightmask; + } + } + + do + { + // Re-map color indices from wall texture column + // using a lighting/special effects LUT. + // heightmask is the Tutti-Frutti fix + + // -1 is the lower clamp bound because column posts have a "safe" byte before the real data + // and a few bytes after as well + *dest = R_DrawColumnPixel(dc, dest, std::clamp((frac >> FRACBITS), npow2min, npow2max), source, colormap); + + dest += stride; + +#if __SIZEOF_POINTER__ < 8 // 64-bit systems have large enough numbers for this to be a non-issue + // Avoid overflow. + if (fracstep > 0x7FFFFFFF - frac) + { + frac += fracstep - fixed_heightmask; + } + else #endif - { - frac += fracstep; + { + frac += fracstep; + } + + while (frac >= fixed_heightmask) + { + frac -= fixed_heightmask; + } + } + while (--count); + } } - - while (frac >= heightmask) - { - frac -= heightmask; - } - } - while (--count); - } - else - { - while ((count -= 2) >= 0) // texture height is a power of 2 - { - *dest = R_DrawColumnPixel(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap); - dest += stride; - frac += fracstep; - - *dest = R_DrawColumnPixel(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap); - dest += stride; - frac += fracstep; - } - - if (count & 1) - { - *dest = R_DrawColumnPixel(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap); - } + break; } } } -- 2.54.0 From ab85d6a69378adcedd75439bf17c4e437857cd34 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 19 Jun 2025 16:29:52 +0200 Subject: [PATCH 111/141] shut the up -Waggregate-return --- src/r_plane.cpp | 6 ++++++ src/r_things.cpp | 3 +++ 2 files changed, 9 insertions(+) diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 9610c0c84..81e02c370 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -737,9 +737,12 @@ void R_DrawPlanes(void) } } #ifdef HAVE_THREADS +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Waggregate-return" tp_sema = srb2::g_main_threadpool->end_sema(); srb2::g_main_threadpool->notify_sema(tp_sema); srb2::g_main_threadpool->wait_sema(tp_sema); +#pragma GCC diagnostic pop #endif } @@ -765,9 +768,12 @@ void R_DrawSkyPlanes(void) } } #ifdef HAVE_THREADS +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Waggregate-return" tp_sema = srb2::g_main_threadpool->end_sema(); srb2::g_main_threadpool->notify_sema(tp_sema); srb2::g_main_threadpool->wait_sema(tp_sema); +#pragma GCC diagnostic pop #endif } diff --git a/src/r_things.cpp b/src/r_things.cpp index 522caf546..9aaa47c9f 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -2978,9 +2978,12 @@ static void R_DrawMaskedList(drawnode_t* head) #endif R_DrawSinglePlane(&ds, r2->plane, cv_parallelsoftware.value); #ifdef HAVE_THREADS +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Waggregate-return" tp_sema = srb2::g_main_threadpool->end_sema(); srb2::g_main_threadpool->notify_sema(tp_sema); srb2::g_main_threadpool->wait_sema(tp_sema); +#pragma GCC diagnostic pop #endif R_DoneWithNode(r2); r2 = next; -- 2.54.0 From 09507d635b4934bdf0b2bf542e6784e7f3d070bd Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 19 Jun 2025 16:30:54 +0200 Subject: [PATCH 112/141] remove now unecessary type cast --- src/r_draw_span.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/r_draw_span.cpp b/src/r_draw_span.cpp index 07a76b7cc..bd74b4f83 100644 --- a/src/r_draw_span.cpp +++ b/src/r_draw_span.cpp @@ -139,7 +139,7 @@ static void R_DrawSpanTemplate(drawspandata_t* ds) for (i = 0; i < 8; i++) { - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); dest[i] = R_DrawSpanPixel(ds, &dsrc[i], colormap, bit, source); @@ -155,7 +155,7 @@ static void R_DrawSpanTemplate(drawspandata_t* ds) while (count-- && dest <= deststop) { - bit = (((UINT32)yposition >> ds->nflatyshift) & ds->nflatmask) | ((UINT32)xposition >> ds->nflatxshift); + bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift); *dest = R_DrawSpanPixel(ds, dsrc, colormap, bit, source); -- 2.54.0 From 707701f317edfdb9cb47fc2a231abc4d978b4902 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 20 Jun 2025 09:53:06 +0200 Subject: [PATCH 113/141] do palette stuff in st_ticker cleanup and dont call it in normal ogl at all unless palette render with flashpals is enabled inspired by Nyan-Doom/Woof --- src/hardware/hw_batching.c | 5 ++-- src/hardware/hw_main.c | 3 +- src/st_stuff.c | 59 ++++++++++++++++---------------------- src/st_stuff.h | 4 +-- 4 files changed, 30 insertions(+), 41 deletions(-) diff --git a/src/hardware/hw_batching.c b/src/hardware/hw_batching.c index 801442b6f..c861bba71 100644 --- a/src/hardware/hw_batching.c +++ b/src/hardware/hw_batching.c @@ -129,7 +129,6 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt } } - static int comparePolygons(const void *p1, const void *p2) { const PolygonArrayEntry *poly1 = *(PolygonArrayEntry *const *)p1; @@ -378,8 +377,8 @@ void HWR_RenderBatches(void) currentSurfaceInfo.TintColor.rgba != nextSurfaceInfo.TintColor.rgba || currentSurfaceInfo.FadeColor.rgba != nextSurfaceInfo.FadeColor.rgba || currentSurfaceInfo.LightInfo.light_level != nextSurfaceInfo.LightInfo.light_level || - currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start || - currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end || + currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start || + currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end || currentSurfaceInfo.LightInfo.directional != nextSurfaceInfo.LightInfo.directional) { changeState = true; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 0e0658567..906ac9161 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5570,8 +5570,6 @@ static void HWR_RenderFrame(player_t *player, boolean skybox) // Clear view, set viewport (glViewport), set perspective... HWR_ClearView(); - ST_doPaletteStuff(); - // Draw the sky background. HWR_DrawSkyBackground(); if (skybox) @@ -5728,6 +5726,7 @@ void HWR_LoadLevel(boolean reloadinggamestate) static void HWR_TogglePaletteRendering(void) { V_ResetPaletteCVars(); // dont carry over changed palettes + ST_ResetPaletteStuff(); // which state should we go to? if (HWR_ShouldUsePaletteRendering()) diff --git a/src/st_stuff.c b/src/st_stuff.c index 4f5401aae..7e4dd8840 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -167,48 +167,50 @@ boolean ST_SameTeam(player_t *a, player_t *b) static boolean st_stopped = true; -void ST_Ticker(void) -{ - if (st_stopped) - return; -} - // 0 is default, any others are special palettes. INT32 st_palette = 0; -void ST_doPaletteStuff(void) +void ST_ResetPaletteStuff(void) { - INT32 palette; + st_palette = 0; + V_SetPalette(0); +} - if (stplyr && stplyr->flashcount) - palette = stplyr->flashpal; - else - palette = 0; +static void ST_doPaletteStuff(void) +{ + INT32 palette = 0; #ifdef HWRENDER if (rendermode == render_opengl && !HWR_PalRenderFlashpal()) - palette = 0; // Don't set the palette to a flashpal in OpenGL's truecolor mode + return; #endif - palette = min(max(palette, 0), 13); + if (stplyr && stplyr->flashcount) + palette = CLAMP(stplyr->flashpal, 0, 13); if (palette != st_palette) { st_palette = palette; -#ifdef HWRENDER - if (rendermode == render_soft || (rendermode == render_opengl && HWR_PalRenderFlashpal())) -#else - if (rendermode != render_none) -#endif + if (!splitscreen) { - //V_SetPaletteLump(GetPalette()); // Reset the palette -- is this needed? - if (!splitscreen) - V_SetPalette(palette); + V_SetPalette(palette); } } } +void ST_Ticker(void) +{ + if (st_stopped) + return; + + // Do red-/gold-shifts from damage/items + //25/08/99: Hurdler: palette changes is done for all players, + // not only player1! That's why this part + // of code is moved somewhere else. + ST_doPaletteStuff(); +} + void ST_UnloadGraphics(void) { Patch_FreeTag(PU_HUDGFX); @@ -306,9 +308,7 @@ static inline void ST_Stop(void) void ST_Start(void) { - if (!st_stopped) - ST_Stop(); - + ST_Stop(); ST_InitData(); if (!dedicated) @@ -757,15 +757,6 @@ void ST_Drawer(void) if (vid.recalc) st_palette = -1; - // Do red-/gold-shifts from damage/items -#ifdef HWRENDER - //25/08/99: Hurdler: palette changes is done for all players, - // not only player1! That's why this part - // of code is moved somewhere else. - if (rendermode == render_soft || (rendermode == render_opengl && HWR_PalRenderFlashpal())) -#endif - if (rendermode != render_none) ST_doPaletteStuff(); - if (st_overlay) { if (renderisnewtic) diff --git a/src/st_stuff.h b/src/st_stuff.h index 54d2483ee..d0ed92b1a 100644 --- a/src/st_stuff.h +++ b/src/st_stuff.h @@ -28,6 +28,8 @@ extern tic_t directortoggletimer; // Called by main loop. void ST_Ticker(void); +void ST_ResetPaletteStuff(void); + // Called when naming a replay. void ST_DrawDemoTitleEntry(void); @@ -56,8 +58,6 @@ void ST_LoadFaceGraphics(char *rankstr, char *wantstr, char *mmapstr, INT32 play void ST_LoadLocalFaceGraphics(char *rankstr, char *wantstr, char *mmapstr, INT32 playernum); void ST_ReloadSkinFaceGraphics(void); -void ST_doPaletteStuff(void); - // return if player a is in the same team as player b boolean ST_SameTeam(player_t *a, player_t *b); -- 2.54.0 From 38950d580f61ebf2d3001b82128b20135b5c1b82 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 20 Jun 2025 09:53:18 +0200 Subject: [PATCH 114/141] fix a clang warning --- src/r_segs.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/r_segs.cpp b/src/r_segs.cpp index bfdb24dd6..9e39d29e7 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -542,8 +542,7 @@ void R_RenderMaskedSegRange(drawseg_t *drawseg, INT32 x1, INT32 x2) template static constexpr T saturating_add(T x, T y) noexcept { - INT64 z; - z = static_cast(x) + static_cast(y); + INT64 z = static_cast(x) + static_cast(y); if (z > static_cast(std::numeric_limits::max())) { z = static_cast(std::numeric_limits::max()); @@ -558,8 +557,7 @@ static constexpr T saturating_add(T x, T y) noexcept template static constexpr T saturating_mul(T x, T y) noexcept { - INT64 z; - z = static_cast(x) * static_cast(y); + INT64 z = static_cast(x) * static_cast(y); if (z > static_cast(std::numeric_limits::max())) { z = static_cast(std::numeric_limits::max()); -- 2.54.0 From ddf7d7cdcb3b8e58eeaf3e847c6e4d8ac1537c75 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 21 Jun 2025 18:07:11 +0200 Subject: [PATCH 115/141] use templates for R_ClipWallSegment actual slight speedup --- src/qs22j.h | 9 +++++++ src/{r_bsp.c => r_bsp.cpp} | 53 ++++++++++++++++++++++++++------------ 2 files changed, 46 insertions(+), 16 deletions(-) rename src/{r_bsp.c => r_bsp.cpp} (96%) diff --git a/src/qs22j.h b/src/qs22j.h index c388b9c46..cf522b73d 100644 --- a/src/qs22j.h +++ b/src/qs22j.h @@ -16,6 +16,15 @@ #ifndef __QS22J__ #define __QS22J__ + +#ifdef __cplusplus +extern "C" { +#endif + void qs22j(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); + +#ifdef __cplusplus +} // extern "C" +#endif #endif diff --git a/src/r_bsp.c b/src/r_bsp.cpp similarity index 96% rename from src/r_bsp.c rename to src/r_bsp.cpp index b0a509b50..f0fb7cb4e 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.cpp @@ -81,15 +81,32 @@ UINT8 *solidcol; void R_AllocClipSegMemory(void) { - solidcol = Z_Realloc(solidcol, sizeof(*solidcol) * viewwidth, PU_STATIC, NULL); + solidcol = static_cast(Z_Realloc(solidcol, sizeof(*solidcol) * viewwidth, PU_STATIC, NULL)); } +namespace +{ + +enum class ClipType +{ + // Does handle solid walls, + // e.g. single sided LineDefs (middle texture) + // that entirely block the view. + kSolid, + kSolidDontRender, + + // Clips the given range of columns, but does not include it in the clip list. + // Does handle windows, e.g. LineDefs with upper and lower texture. + kPass, +}; + // CPhipps - // R_ClipWallSegment // // Replaces the old R_Clip*WallSegment functions. It draws bits of walls in those // columns which aren't solid, and updates the solidcol[] array appropriately -static void R_ClipWallSegment(int first, int last, boolean solid, boolean soliddontrender) +template +static void R_ClipWallSegment(int first, int last) { while (first < last) { @@ -97,7 +114,7 @@ static void R_ClipWallSegment(int first, int last, boolean solid, boolean solidd if (solidcol[first]) { - p = memchr(solidcol+first, 0, last-first); + p = static_cast(memchr(solidcol+first, 0, last-first)); if (!p) return; // All solid @@ -105,7 +122,7 @@ static void R_ClipWallSegment(int first, int last, boolean solid, boolean solidd } else { - p = memchr(solidcol+first, 1, last-first); + p = static_cast(memchr(solidcol+first, 1, last-first)); int to; if (!p) @@ -113,17 +130,23 @@ static void R_ClipWallSegment(int first, int last, boolean solid, boolean solidd else to = p - solidcol; - if (!soliddontrender) + if constexpr (Type != ClipType::kSolidDontRender) + { R_StoreWallRange(first, to-1); + } - if (solid) + if constexpr (Type != ClipType::kPass) + { memset(solidcol+first, 1, to-first); + } first = to; } } } +}; // namespace + // // R_ClearClipSegs // @@ -459,15 +482,15 @@ static void R_AddLine(seg_t *line) clippass: g_walloffscreen = false; - R_ClipWallSegment(x1, x2, false, false); + R_ClipWallSegment(x1, x2); if (g_walloffscreen) - R_ClipWallSegment(x1, x2, false, true); + R_ClipWallSegment(x1, x2); return; clipsolid: g_walloffscreen = false; - R_ClipWallSegment(x1, x2, true, false); + R_ClipWallSegment(x1, x2); } // @@ -592,8 +615,7 @@ void R_SortPolyObjects(subsector_t *sub) { // use free instead realloc since faster (thanks Lee ^_^) free(po_ptrs); - po_ptrs = malloc((num_po_ptrs = numpolys*2) - * sizeof(*po_ptrs)); + po_ptrs = static_cast(malloc((num_po_ptrs = numpolys*2)* sizeof(*po_ptrs))); } po = sub->polyList; @@ -610,8 +632,7 @@ void R_SortPolyObjects(subsector_t *sub) // 03/10/06: only bother if there are actually polys to sort if (numpolys >= 2) { - qs22j(po_ptrs, numpolys, sizeof(polyobj_t *), - R_PolyobjCompare); + qs22j(po_ptrs, numpolys, sizeof(polyobj_t *), R_PolyobjCompare); } } } @@ -637,8 +658,8 @@ static int R_PolysegCompare(const void *p1, const void *p2) dist2v1 = vxdist(seg2->v1); dist2v2 = vxdist(seg2->v2); - if (min(dist1v1, dist1v2) != min(dist2v1, dist2v2)) - return min(dist1v1, dist1v2) - min(dist2v1, dist2v2); + if (std::min(dist1v1, dist1v2) != std::min(dist2v1, dist2v2)) + return std::min(dist1v1, dist1v2) - std::min(dist2v1, dist2v2); { // That didn't work, so now let's try this....... fixed_t delta1, delta2, x1, y1, x2, y2; @@ -1056,7 +1077,7 @@ void R_Prep3DFloors(sector_t *sector) if (count != sector->numlights) { Z_Free(sector->lightlist); - sector->lightlist = Z_Calloc(sizeof (*sector->lightlist) * count, PU_LEVEL, NULL); + sector->lightlist = static_cast(Z_Calloc(sizeof (*sector->lightlist) * count, PU_LEVEL, NULL)); sector->numlights = count; } else -- 2.54.0 From 36c68d055c9b22031e328d3440e661c549836ef8 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 21 Jun 2025 18:07:29 +0200 Subject: [PATCH 116/141] minor optimizations r_things --- src/r_things.cpp | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/src/r_things.cpp b/src/r_things.cpp index 9aaa47c9f..7569c00f7 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -1923,7 +1923,6 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) // aspect ratio stuff : xscale = FixedDiv(projection, tz); - yscale = FixedDiv(projectiony, tz); // decide which patch to use for sprite relative to player #ifdef RANGECHECK @@ -1985,6 +1984,9 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) return; } + // aspect ratio stuff : + yscale = FixedDiv(projectiony, tz); + // store information in a vissprite vis = R_NewVisSprite(); vis->scale = FixedMul(yscale, this_scale); @@ -2158,7 +2160,8 @@ static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 e { dsprev = ds; ds = dsnext; - if (i < end - 1) dsnext = R_GetVisSprite(i + 1); + if (i < end - 1) + dsnext = R_GetVisSprite(i + 1); ds->next = dsnext; ds->prev = dsprev; @@ -2630,8 +2633,10 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* port while (++curr <= last) { + __builtin_prefetch(curr + 1, 0, 3); + // determine if the drawseg obscures the sprite - if (curr->x1 > spr->x2 || curr->x2 < spr->x1) + if (curr->x1 > x2 || curr->x2 < x1) { // does not cover sprite continue; @@ -2657,15 +2662,15 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* port if (scale < spr->sortscale || (lowscale < spr->sortscale && - !R_PointOnSegSide (spr->gx, spr->gy, ds->curline))) + !R_PointOnSegSide(spr->gx, spr->gy, ds->curline))) { // seg is behind sprite continue; } } - r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1; - r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2; + r1 = ds->x1 < x1 ? x1 : ds->x1; + r2 = ds->x2 > x2 ? x2 : ds->x2; // clip this piece of the sprite silhouette = ds->silhouette; @@ -2707,20 +2712,21 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* port if (spr->heightsec != -1) // only things in specially marked sectors { fixed_t mh, h; - INT32 phs = viewplayer->mo->subsector->sector->heightsec; + const INT32 phs = viewplayer->mo->subsector->sector->heightsec; + if ((mh = sectors[spr->heightsec].floorheight) > spr->gz && (h = centeryfrac - FixedMul(mh -= viewz, spr->sortscale)) >= 0 && (h >>= FRACBITS) < viewheight) { if (mh <= 0 || (phs != -1 && viewz > sectors[phs].floorheight)) { // clip bottom - for (x = spr->x1; x <= spr->x2; x++) + for (x = x1; x <= x2; x++) if (spr->clipbot[x] == -2 || h < spr->clipbot[x]) spr->clipbot[x] = (INT16)h; } else // clip top { - for (x = spr->x1; x <= spr->x2; x++) + for (x = x1; x <= x2; x++) if (spr->cliptop[x] == -2 || h > spr->cliptop[x]) spr->cliptop[x] = (INT16)h; } @@ -2732,21 +2738,22 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* port { if (phs != -1 && viewz >= sectors[phs].ceilingheight) { // clip bottom - for (x = spr->x1; x <= spr->x2; x++) + for (x = x1; x <= x2; x++) if (spr->clipbot[x] == -2 || h < spr->clipbot[x]) spr->clipbot[x] = (INT16)h; } else // clip top { - for (x = spr->x1; x <= spr->x2; x++) + for (x = x1; x <= x2; x++) if (spr->cliptop[x] == -2 || h > spr->cliptop[x]) spr->cliptop[x] = (INT16)h; } } } + if (spr->cut & SC_TOP && spr->cut & SC_BOTTOM) { - for (x = spr->x1; x <= spr->x2; x++) + for (x = x1; x <= x2; x++) { if (spr->cliptop[x] == -2 || spr->szt > spr->cliptop[x]) spr->cliptop[x] = spr->szt; @@ -2757,7 +2764,7 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* port } else if (spr->cut & SC_TOP) { - for (x = spr->x1; x <= spr->x2; x++) + for (x = x1; x <= x2; x++) { if (spr->cliptop[x] == -2 || spr->szt > spr->cliptop[x]) spr->cliptop[x] = spr->szt; @@ -2765,7 +2772,7 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* port } else if (spr->cut & SC_BOTTOM) { - for (x = spr->x1; x <= spr->x2; x++) + for (x = x1; x <= x2; x++) { if (spr->clipbot[x] == -2 || spr->sz < spr->clipbot[x]) spr->clipbot[x] = spr->sz; @@ -2775,7 +2782,7 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* port // all clipping has been performed, so store the values - what, did you think we were drawing them NOW? // check for unclipped columns - for (x = spr->x1; x <= spr->x2; x++) + for (x = x1; x <= x2; x++) { if (spr->clipbot[x] == -2) spr->clipbot[x] = (INT16)viewheight; @@ -2796,6 +2803,7 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* port { INT32 start_index = std::max(portal->start, x1); INT32 end_index = std::min(portal->start + portal->end - portal->start, x2); + for (x = x1; x < start_index; x++) { spr->clipbot[x] = -1; -- 2.54.0 From 044ff158a1a9c4edc86de4acee1548489c94725f Mon Sep 17 00:00:00 2001 From: Indev Date: Mon, 23 Jun 2025 18:37:57 +0300 Subject: [PATCH 117/141] SF_HIRES is already handled via spritexscale and spriteyscale --- src/r_things.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/r_things.cpp b/src/r_things.cpp index 7569c00f7..5f40d79ca 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -848,8 +848,8 @@ static void R_DrawVisSprite(vissprite_t *vis) frac = vis->startfrac; windowtop = windowbottom = sprbotscreen = INT32_MAX; - if ((vis->mobj->skin || vis->mobj->localskin) && K_GetMobjSkin(vis->mobj)->flags & SF_HIRES) - this_scale = FixedMul(this_scale, K_GetMobjSkin(vis->mobj)->highresscale); + //if ((vis->mobj->skin || vis->mobj->localskin) && K_GetMobjSkin(vis->mobj)->flags & SF_HIRES) + // this_scale = FixedMul(this_scale, K_GetMobjSkin(vis->mobj)->highresscale); if (this_scale <= 0) this_scale = 1; -- 2.54.0 From 09ce33abb9fd72c2840fd13c02b86055d32fabf1 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 23 Jun 2025 19:16:00 +0200 Subject: [PATCH 118/141] just always clamp the non psprite texture column MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this may underflow, which the check in the lööp body does not account for --- src/r_things.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/r_things.cpp b/src/r_things.cpp index 5f40d79ca..9d91ae19f 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -919,12 +919,10 @@ static void R_DrawVisSprite(vissprite_t *vis) else { // Non-paper drawing loop - for (dc.x = vis->x1; dc.x <= vis->x2 && (frac>>FRACBITS) < pwidth; dc.x++, frac += vis->xiscale) + for (dc.x = vis->x1; dc.x <= vis->x2; dc.x++, frac += vis->xiscale) { - //texturecolumn = CLAMP(frac >> FRACBITS, 0, pwidth - 1); - texturecolumn = (frac >> FRACBITS); + texturecolumn = CLAMP(frac >> FRACBITS, 0, pwidth - 1); column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); - localcolfunc(&dc, column); } } -- 2.54.0 From 24eb888af3ebe07700d2fc7fd61f6c7a7e8dd2cb Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 23 Jun 2025 19:20:20 +0200 Subject: [PATCH 119/141] make skytextures support texture offsets in software --- src/r_data.c | 6 +++++- src/r_data.h | 9 +++++++++ src/r_plane.cpp | 2 ++ src/r_sky.c | 25 ++++++++++++++++++++++--- src/r_sky.h | 10 +++++++++- 5 files changed, 47 insertions(+), 5 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index ca73e7e42..7ac8ffe2d 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -649,6 +649,7 @@ void R_LoadTextures(void) M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name)); texture->width = SHORT(patchlump->width); texture->height = SHORT(patchlump->height); + texture->type = TEXTURETYPE_SINGLEPATCH; texture->patchcount = 1; texture->holes = false; @@ -915,19 +916,22 @@ static texture_t *R_ParseTexture(boolean actuallyLoadTexture) // Left Curly Brace texturesToken = M_GetToken(NULL); + if (texturesToken == NULL) { I_Error("Error parsing TEXTURES lump: Unexpected end of file where open curly brace for texture \"%s\" should be",newTextureName); } + if (strcmp(texturesToken,"{")==0) { if (actuallyLoadTexture) { // Allocate memory for a zero-patch texture. Obviously, we'll be adding patches momentarily. - resultTexture = (texture_t *)Z_Calloc(sizeof(texture_t),PU_STATIC,NULL); + resultTexture = (texture_t *)Z_Calloc(sizeof(texture_t), PU_STATIC, NULL); M_Memcpy(resultTexture->name, newTextureName, 8); resultTexture->width = newTextureWidth; resultTexture->height = newTextureHeight; + resultTexture->type = TEXTURETYPE_COMPOSITE; } Z_Free(texturesToken); texturesToken = M_GetToken(NULL); diff --git a/src/r_data.h b/src/r_data.h index 45f7ee484..c3abab0c1 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -37,6 +37,14 @@ typedef struct UINT16 wad, lump; } texpatch_t; +// texture type +enum +{ + TEXTURETYPE_UNKNOWN, + TEXTURETYPE_SINGLEPATCH, + TEXTURETYPE_COMPOSITE, +}; + // A maptexturedef_t describes a rectangular texture, // which is composed of one or more mappatch_t structures // that arrange graphic patches. @@ -44,6 +52,7 @@ typedef struct { // Keep name for switch changing, etc. char name[8]; + UINT8 type; // TEXTURETYPE_ INT16 width, height; boolean holes; diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 81e02c370..b46912b2f 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -839,6 +839,8 @@ static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), b } INT32 angle = (pl->viewangle + xtoviewangle[x + i])>>ANGLETOSKYSHIFT; + angle -= (skytextureoffset >> FRACBITS); + dc.iscale = FixedMul(skyscale, FINECOSINE(xtoviewangle[x + i]>>ANGLETOFINESHIFT)); dc.x = x + i; dc.source = diff --git a/src/r_sky.c b/src/r_sky.c index 1ed47d43b..8cbdd3a59 100644 --- a/src/r_sky.c +++ b/src/r_sky.c @@ -41,6 +41,10 @@ INT32 skytexture; */ INT32 skytexturemid; +/** \brief the x offset of the sky texture + */ +INT32 skytextureoffset; + /** \brief the scale of the sky */ fixed_t skyscale; @@ -50,6 +54,7 @@ fixed_t skyscale; INT32 levelskynum; INT32 globallevelskynum; + /** \brief The R_SetupSkyDraw function Called at loadlevel after skytexture is set, or when sky texture changes. @@ -61,8 +66,20 @@ INT32 globallevelskynum; */ void R_SetupSkyDraw(void) { - // the horizon line in a 256x128 sky texture - skytexturemid = (textures[skytexture]->height/2)<height / 2) << FRACBITS; + skytextureoffset = 0; + + if (textures[skytexture]->type == TEXTURETYPE_SINGLEPATCH) + { + // Sal: Allow for sky offsets + texpatch_t *const tex_patch = &textures[skytexture]->patches[0]; + patch_t *patch = W_CachePatchNumPwad(tex_patch->wad, tex_patch->lump, PU_CACHE); + + skytexturemid += (patch->topoffset << FRACBITS); + skytextureoffset += (patch->leftoffset << FRACBITS); + } + R_SetSkyScale(); } @@ -74,5 +91,7 @@ void R_SetupSkyDraw(void) */ void R_SetSkyScale(void) { - skyscale = FixedDiv(fovtan, FixedDiv(vid.width*FRACUNIT, BASEVIDWIDTH*FRACUNIT)); + //skyscale = FixedDiv(fovtan, FixedDiv(vid.width*FRACUNIT, BASEVIDWIDTH*FRACUNIT)); + fixed_t difference = vid.fdupx-(vid.dupx< Date: Mon, 23 Jun 2025 19:23:56 +0200 Subject: [PATCH 120/141] use const_cast for colfunccopy idk its from rr idk why it was like this --- src/r_things.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/r_things.cpp b/src/r_things.cpp index 9d91ae19f..1b63d302a 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -664,9 +664,7 @@ void R_DrawMaskedColumn(drawcolumndata_t* dc, column_t *column) drawcolumndata_t dc_copy = *dc; void (*colfunccopy)(drawcolumndata_t*); colfunccopy = colfunc; - colfunccopy((drawcolumndata_t*)(&dc_copy)); - - //colfunc(); + colfunccopy(const_cast(&dc_copy)); } column = (column_t *)((UINT8 *)column + column->length + 4); } @@ -729,9 +727,7 @@ static void R_DrawFlippedMaskedColumn(drawcolumndata_t* dc, column_t *column) drawcolumndata_t dc_copy = *dc; void (*colfunccopy)(drawcolumndata_t*); colfunccopy = colfunc; - colfunccopy((drawcolumndata_t*)(&dc_copy)); - - //colfunc(); + colfunccopy(const_cast(&dc_copy)); Z_Free(dc->source); } -- 2.54.0 From 4fb3b631528d3c4204f2e6a3a562ed934fc8e66e Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 23 Jun 2025 19:38:37 +0200 Subject: [PATCH 121/141] optimize R_StoreWallRange with cut down version of rendersegloop when a seg is untextured from srb2, its just a cut down rendersegloop with alot less things to check and such --- src/r_segs.cpp | 95 +++++++++++++++++++++++++++++++++++++++++++++--- src/r_things.cpp | 3 -- 2 files changed, 90 insertions(+), 8 deletions(-) diff --git a/src/r_segs.cpp b/src/r_segs.cpp index 9e39d29e7..8d9f28b03 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -1554,6 +1554,74 @@ static void R_RenderSegLoop(drawcolumndata_t* dc) } } +static void R_MarkSegBounds(void) +{ + INT32 yl, yh; + INT32 top, bottom; + INT16 topclip, bottomclip; + + for (; rw_x < rw_stopx; rw_x++) + { + // mark floor / ceiling areas + yl = (topfrac+HEIGHTUNIT-1)>>HEIGHTBITS; + + // no space above wall? + top = ceilingclip[rw_x]+1; + + // no space above wall? + if (yl < top) + yl = top; + + if (markceiling) + { + bottom = yl > floorclip[rw_x] ? floorclip[rw_x] : yl; + + if (top <= --bottom && ceilingplane) + { + R_ExpandPlaneY(ceilingplane, rw_x, top, bottom); + } + } + + yh = bottomfrac>>HEIGHTBITS; + + bottom = floorclip[rw_x]-1; + + if (yh > bottom) + yh = bottom; + + if (markfloor) + { + top = yh < ceilingclip[rw_x] ? ceilingclip[rw_x] : yh; + + if (++top <= bottom && floorplane) + { + 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; + + if (floorclip[rw_x] <= ceilingclip[rw_x] + 1) + { + solidcol[rw_x] = 1; + didsolidcol = true; + } + + rw_scale += rw_scalestep; + topfrac += topstep; + bottomfrac += bottomstep; + } +} + // Uses precalculated seg->length static INT64 R_CalcSegDist(seg_t* seg, INT64 x2, INT64 y2) { @@ -2811,13 +2879,30 @@ void R_StoreWallRange(INT32 start, INT32 stop) } - rw_silhouette = &(ds_p->silhouette); - rw_tsilheight = &(ds_p->tsilheight); - rw_bsilheight = &(ds_p->bsilheight); - didsolidcol = false; - R_RenderSegLoop(&dc); + if (!segtextured && !numffloors) + { + 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(&dc); + } + R_SetColumnFunc(BASEDRAWFUNC); if (g_portal) // if curline is a portal, set portalrender for drawseg diff --git a/src/r_things.cpp b/src/r_things.cpp index 1b63d302a..bf33fb97c 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -844,9 +844,6 @@ static void R_DrawVisSprite(vissprite_t *vis) frac = vis->startfrac; windowtop = windowbottom = sprbotscreen = INT32_MAX; - //if ((vis->mobj->skin || vis->mobj->localskin) && K_GetMobjSkin(vis->mobj)->flags & SF_HIRES) - // this_scale = FixedMul(this_scale, K_GetMobjSkin(vis->mobj)->highresscale); - if (this_scale <= 0) this_scale = 1; -- 2.54.0 From 07432c038108b93cecb370546c4b0f180ab59c41 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 25 Jun 2025 12:27:13 +0200 Subject: [PATCH 122/141] turn angle stuff into a switch in R_SetupSkyScale --- src/r_main.cpp | 47 +++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/src/r_main.cpp b/src/r_main.cpp index e0d75b6df..d9ae9a70c 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1114,6 +1114,7 @@ static void R_SetupSkyScale(player_t *player, camera_t *thiscam, mapheader_t *mh { if (skyboxmo[1]) { + angle_t ang; fixed_t x = 0, y = 0; if (mh->skybox_scalex > 0) @@ -1126,31 +1127,29 @@ static void R_SetupSkyScale(player_t *player, camera_t *thiscam, mapheader_t *mh else if (mh->skybox_scaley < 0) y = (moy - skyboxmo[1]->y) * -mh->skybox_scaley; - if (viewmobj->angle == 0) + switch (viewmobj->angle) { - newview->x += x; - newview->y += y; - } - else if (viewmobj->angle == ANGLE_90) - { - newview->x -= y; - newview->y += x; - } - else if (viewmobj->angle == ANGLE_180) - { - newview->x -= x;\ - newview->y -= y;\ - } - else if (viewmobj->angle == ANGLE_270) - { - newview->x += y; - newview->y -= x; - } - else - { - angle_t ang = viewmobj->angle>>ANGLETOFINESHIFT; - newview->x += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang)); - newview->y += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang)); + case 0: + newview->x += x; + newview->y += y; + break; + case ANGLE_90: + newview->x -= y; + newview->y += x; + break; + case ANGLE_180: + newview->x -= x;\ + newview->y -= y;\ + break; + case ANGLE_270: + newview->x += y; + newview->y -= x; + break; + default: + ang = viewmobj->angle>>ANGLETOFINESHIFT; + newview->x += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang)); + newview->y += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang)); + break; } } -- 2.54.0 From d19a2e09128fd162306973808dd18553a7d1fef0 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 25 Jun 2025 12:45:14 +0200 Subject: [PATCH 123/141] attempt to make fofs in software always cut cyan pixels if they do contain cyan pixels lel kinda meh, and needs a toggle --- src/p_setup.c | 26 ++++++++++++++++++++++++++ src/p_setup.h | 1 + src/r_plane.cpp | 5 +++++ src/r_plane.h | 1 + src/r_segs.cpp | 3 +++ 5 files changed, 36 insertions(+) diff --git a/src/p_setup.c b/src/p_setup.c index fc4f6d892..7457b44ee 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -672,6 +672,19 @@ INT32 P_AddLevelFlat(const char *flatname, levelflat_t *levelflat) levelflat->lumpnum = R_GetFlatNumForName(flatname); levelflat->baselumpnum = LUMPERROR; + { + UINT8 *flat = (UINT8 *)W_CacheLumpNum(levelflat->lumpnum, PU_LEVEL); + size_t size = W_LumpLength(levelflat->lumpnum); + for (size_t steppy = 0; steppy < size; steppy++) + { + if (flat[steppy] == TRANSPARENTPIXEL) + { + levelflat->cyan = true; + break; + } + } + } + #ifndef ZDEBUG CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name); #endif @@ -717,6 +730,19 @@ INT32 P_AddLevelFlatRuntime(const char *flatname) levelflat->lumpnum = R_GetFlatNumForName(flatname); levelflat->baselumpnum = LUMPERROR; + { + UINT8 *flat = (UINT8 *)W_CacheLumpNum(levelflat->lumpnum, PU_LEVEL); + size_t size = W_LumpLength(levelflat->lumpnum); + for (size_t steppy = 0; steppy < size; steppy++) + { + if (flat[steppy] == TRANSPARENTPIXEL) + { + levelflat->cyan = true; + break; + } + } + } + #ifndef ZDEBUG CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name); #endif diff --git a/src/p_setup.h b/src/p_setup.h index 86b958adf..646415d28 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -52,6 +52,7 @@ typedef struct INT32 animseq; // start pos. in the anim sequence INT32 numpics; INT32 speed; + boolean cyan; } levelflat_t; extern size_t numlevelflats; diff --git a/src/r_plane.cpp b/src/r_plane.cpp index b46912b2f..a875f3eea 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -507,6 +507,7 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, check->polyobj = polyobj; check->slope = slope; check->noencore = noencore; + check->cyan = levelflats[picnum].cyan; memset(check->top, 0xff, sizeof(*check->top) * viewwidth); memset(check->bottom, 0x00, sizeof(*check->bottom) * viewwidth); @@ -583,6 +584,7 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop) new_pl->polyobj = pl->polyobj; new_pl->slope = pl->slope; new_pl->noencore = pl->noencore; + new_pl->cyan = pl->cyan; pl = new_pl; pl->minx = start; pl->maxx = stop; @@ -1086,6 +1088,9 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle } } + if (pl->cyan && !(pl->ffloor->flags & FF_RIPPLE)) + spanfunctype = SPANDRAWFUNC_SPLAT; + if (pl->ffloor->flags & FF_TRANSLUCENT) { spanfunctype = SPANDRAWFUNC_TRANS; diff --git a/src/r_plane.h b/src/r_plane.h index 35e3f2b08..f330baa3d 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -58,6 +58,7 @@ typedef struct visplane_s pslope_t *slope; boolean noencore; + boolean cyan; } visplane_t; extern visplane_t *visplanes[MAXVISPLANES]; diff --git a/src/r_segs.cpp b/src/r_segs.cpp index 8d9f28b03..0cafdeb6f 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -582,6 +582,9 @@ static void R_DrawRepeatMaskedColumn(drawcolumndata_t* dc, column_t *col) // Returns true if a fake floor is translucent. static boolean R_IsFFloorTranslucent(visffloor_t *pfloor) { + if (pfloor->plane->cyan) + return true; + if (pfloor->polyobj) return true; -- 2.54.0 From 8353c1efddbdb2c3b3cf193ec4d4b2f76122d8d8 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 25 Jun 2025 12:47:25 +0200 Subject: [PATCH 124/141] add toggle for software cyan cut stuff "softwarecyancut" this is disabled by default, since some vanilla maps were designed around this also costs a bit of performance (splat span drawers are slooooow) --- src/p_setup.c | 8 ++++++-- src/r_main.cpp | 50 ++++++++++++++++++++++++------------------------- src/r_main.h | 1 + src/r_plane.cpp | 2 +- src/r_segs.cpp | 2 +- 5 files changed, 34 insertions(+), 29 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 7457b44ee..8218e045e 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -672,8 +672,10 @@ INT32 P_AddLevelFlat(const char *flatname, levelflat_t *levelflat) levelflat->lumpnum = R_GetFlatNumForName(flatname); levelflat->baselumpnum = LUMPERROR; + // check if our flat contains cyan pixels + // not sure if this is the best way to do it but it works { - UINT8 *flat = (UINT8 *)W_CacheLumpNum(levelflat->lumpnum, PU_LEVEL); + const UINT8 *flat = (UINT8 *)W_CacheLumpNum(levelflat->lumpnum, PU_LEVEL); size_t size = W_LumpLength(levelflat->lumpnum); for (size_t steppy = 0; steppy < size; steppy++) { @@ -730,8 +732,10 @@ INT32 P_AddLevelFlatRuntime(const char *flatname) levelflat->lumpnum = R_GetFlatNumForName(flatname); levelflat->baselumpnum = LUMPERROR; + // check if our flat contains cyan pixels + // not sure if this is the best way to do it but it works { - UINT8 *flat = (UINT8 *)W_CacheLumpNum(levelflat->lumpnum, PU_LEVEL); + const UINT8 *flat = (UINT8 *)W_CacheLumpNum(levelflat->lumpnum, PU_LEVEL); size_t size = W_LumpLength(levelflat->lumpnum); for (size_t steppy = 0; steppy < size; steppy++) { diff --git a/src/r_main.cpp b/src/r_main.cpp index d9ae9a70c..4c21a76c7 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -183,38 +183,37 @@ consvar_t cv_flipcam[MAXSPLITSCREENPLAYERS] = { {"flipcam4", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam4_OnChange, 0, NULL, NULL, 0, 0, NULL} }; -consvar_t cv_shadow = {"shadow", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_shadowoffs = {"offsetshadows", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_skybox = {"skybox", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_ffloorclip = {"r_ffloorclip", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_spriteclip = {"r_spriteclip", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_soniccd = {"soniccd", "Off", CV_NETVAR|CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_allowmlook = {"allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_showhud = {"showhud", "Yes", CV_CALL, CV_YesNo, R_SetViewSize, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_translucenthud = {"translucenthud", "10", CV_SAVE, translucenthud_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_uncappedhud = {"uncappedhud", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; - -consvar_t cv_translucency = {"translucency", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_drawdist = {"drawdist", "Infinite", CV_SAVE, drawdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_shadow = {"shadow", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_shadowoffs = {"offsetshadows", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_skybox = {"skybox", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_ffloorclip = {"r_ffloorclip", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_spriteclip = {"r_spriteclip", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_softcyancut = {"softwarecyancut", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_translucency = {"translucency", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_drawdist = {"drawdist", "Infinite", CV_SAVE, drawdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_drawdist_precip = {"drawdist_precip", "1024", CV_SAVE|CV_CALL|CV_NOINIT, drawdist_precip_cons_t, Precipstuff_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_lessprecip = {"lessweathereffects", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, Precipstuff_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_lessprecip = {"lessweathereffects", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, Precipstuff_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_mobjscaleprecip = {"scaleprecipmobjscale", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, Precipstuff_OnChange, 0, NULL, NULL, 0, 0, NULL}; - -consvar_t cv_maxinterpdist = {"maxinterpdist", "Infinite", CV_SAVE, maxinterpdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; - -consvar_t cv_ripplewater = {"waterripples", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; - -// cap fov, fov too high tears software apart. -consvar_t cv_fov = {"fov", "90", CV_FLOAT|CV_CALL|CV_SAVE, fov_cons_t, Fov_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_fovchange = {"fovchange", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_maxinterpdist = {"maxinterpdist", "Infinite", CV_SAVE, maxinterpdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_ripplewater = {"waterripples", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; // Okay, whoever said homremoval causes a performance hit should be shot. -consvar_t cv_homremoval = {"homremoval", "Yes", CV_SAVE, homremoval_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_homremoval = {"homremoval", "Yes", CV_SAVE, homremoval_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_maxportals = {"maxportals", "2", CV_SAVE, maxportals_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_maxportals = {"maxportals", "2", CV_SAVE, maxportals_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + +// cap fov, fov too high tears software apart. +consvar_t cv_fov = {"fov", "90", CV_FLOAT|CV_CALL|CV_SAVE, fov_cons_t, Fov_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_fovchange = {"fovchange", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; // randomized directional lightning -consvar_t cv_randomdirlight = {"randomdirectionallight", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, DirLight_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_randomdirlight = {"randomdirectionallight", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, DirLight_OnChange, 0, NULL, NULL, 0, 0, NULL}; + +consvar_t cv_showhud = {"showhud", "Yes", CV_CALL, CV_YesNo, R_SetViewSize, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_translucenthud = {"translucenthud", "10", CV_SAVE, translucenthud_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_uncappedhud = {"uncappedhud", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_soniccd = {"soniccd", "Off", CV_NETVAR|CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_allowmlook = {"allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; // tells to reset the maplight at next map change static void DirLight_OnChange(void) @@ -1542,6 +1541,7 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_skybox); CV_RegisterVar(&cv_ffloorclip); CV_RegisterVar(&cv_spriteclip); + CV_RegisterVar(&cv_softcyancut); for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) { diff --git a/src/r_main.h b/src/r_main.h index 6f62855da..808f11b6f 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -211,6 +211,7 @@ extern consvar_t cv_chasecam[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_flipcam[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_shadow, cv_shadowoffs; extern consvar_t cv_ffloorclip, cv_spriteclip; +extern consvar_t cv_softcyancut; extern consvar_t cv_translucency; extern consvar_t cv_drawdist, cv_drawdist_precip, cv_lessprecip, cv_mobjscaleprecip; extern consvar_t cv_fov, cv_fovchange; diff --git a/src/r_plane.cpp b/src/r_plane.cpp index a875f3eea..5cb48b355 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -1088,7 +1088,7 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle } } - if (pl->cyan && !(pl->ffloor->flags & FF_RIPPLE)) + if (cv_softcyancut.value && pl->cyan && !(pl->ffloor->flags & FF_RIPPLE)) spanfunctype = SPANDRAWFUNC_SPLAT; if (pl->ffloor->flags & FF_TRANSLUCENT) diff --git a/src/r_segs.cpp b/src/r_segs.cpp index 0cafdeb6f..452d1eb8e 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -582,7 +582,7 @@ static void R_DrawRepeatMaskedColumn(drawcolumndata_t* dc, column_t *col) // Returns true if a fake floor is translucent. static boolean R_IsFFloorTranslucent(visffloor_t *pfloor) { - if (pfloor->plane->cyan) + if (cv_softcyancut.value && pfloor->plane->cyan) return true; if (pfloor->polyobj) -- 2.54.0 From be8ddebd804ec08063aa92bb10d2747c81b48883 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 26 Jun 2025 00:38:48 +0200 Subject: [PATCH 125/141] forgor about the new signal handler oop --- src/sdl/i_system.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/sdl/i_system.cpp b/src/sdl/i_system.cpp index 249f1f6f2..2d8ae4e70 100644 --- a/src/sdl/i_system.cpp +++ b/src/sdl/i_system.cpp @@ -533,6 +533,16 @@ FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num) FUNCNORETURN static ATTRNORETURN void quit_handler(int num) { +#ifdef HAVE_THREADS + if (g_main_thread_id != std::this_thread::get_id()) + { + // Do not attempt any sort of recovery if this signal triggers off the main thread + signal(num, SIG_DFL); + raise(num); + exit(-2); + } +#endif + signal(num, SIG_DFL); //default signal action raise(num); I_Quit(); -- 2.54.0 From 604bc400211ba3f298cbfef8195cd5cb1f68b595 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 23 Jun 2025 20:06:09 +0200 Subject: [PATCH 126/141] add "for_each" to srb2 threadpool this exectures something for EACH thread not some abritatrily choosen ones --- src/core/thread_pool.h | 55 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/src/core/thread_pool.h b/src/core/thread_pool.h index 75961614e..535e77a9f 100644 --- a/src/core/thread_pool.h +++ b/src/core/thread_pool.h @@ -80,6 +80,7 @@ public: /// Enqueue but don't notify template void schedule(T&& thunk); + template void for_each(F&& task); /// Notify threads after several schedules void notify(); void notify_sema(const Sema& sema); @@ -143,6 +144,60 @@ void ThreadPool::schedule(T&& thunk) } } +template +void ThreadPool::for_each(F&& thunk) +{ + static_assert(sizeof(std::decay_t) <= sizeof(std::declval().raw)); + + if (immediate_mode_) + { + thunk(); + return; + } + + Sema sync_sema; + begin_sema(); + + auto counter = std::make_shared>(threads_.size()); + + for (size_t i = 0; i < threads_.size(); i++) { + std::shared_ptr q = work_queues_[i]; + Task task; + + struct TaskData { + std::decay_t func; + std::shared_ptr> counter; + Sema sema; + ThreadPool* pool; + }; + static_assert(sizeof(TaskData) <= sizeof(task.raw)); + + new (task.raw.data()) TaskData{ + std::forward(thunk), + counter, + sync_sema, + this + }; + + task.thunk = [](void* ptr) { + auto* data = static_cast(ptr); + data->func(); + if (--(*data->counter) == 0) { + data->pool->notify_sema(data->sema); + } + }; + + task.deleter = [](void* ptr) { + static_cast(ptr)->~TaskData(); + }; + + task.pseudosema = cur_sema_; + q->push(std::move(task)); + } + + wait_sema(sync_sema); +} + } // namespace srb2 extern "C" { -- 2.54.0 From b541de4f8cad976eb2c26c3ec0b7d7ed2775a08d Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 23 Jun 2025 20:08:04 +0200 Subject: [PATCH 127/141] allocate tiltlighting buffer in R_AllocViewMemory again just removes the ugly stuff in the span drawers needs to be tested a little, but should be fine --- src/r_draw.cpp | 27 ++++++++++++++++++++++++++- src/r_draw_span.cpp | 31 ------------------------------- 2 files changed, 26 insertions(+), 32 deletions(-) diff --git a/src/r_draw.cpp b/src/r_draw.cpp index 23d512a19..83fbe82ae 100644 --- a/src/r_draw.cpp +++ b/src/r_draw.cpp @@ -34,6 +34,10 @@ #include "hardware/hw_main.h" #endif +#ifdef HAVE_THREADS +#include "core/thread_pool.h" +#endif + // ========================================================================== // COMMON DATA FOR 8bpp AND 16bpp // ========================================================================== @@ -77,7 +81,19 @@ floatv3_t *ds_su, *ds_sv, *ds_sz; float focallengthf; // For, uh, tilted lighting, duh. -//static INT32 *tiltlighting; +#ifdef HAVE_THREADS +#ifdef _WIN32 +#include +#define local_for_thread static __thread +#else +#include +#define local_for_thread thread_local static +#endif +#else +#define local_for_thread static +#endif + +local_for_thread INT32 *tiltlighting; // -------------------------------------------- // c drawer routines @@ -470,6 +486,15 @@ static void R_AllocViewMemory(void) xtoviewangle = static_cast(Z_Realloc(xtoviewangle, sizeof(*xtoviewangle) * (viewwidth + 1), PU_STATIC, NULL)); + auto init_tiltlighting = [] { + tiltlighting = static_cast(realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth)); // dont use Zone memory since its not thread safe + }; + + init_tiltlighting(); +#ifdef HAVE_THREADS + srb2::g_main_threadpool->for_each(std::move(init_tiltlighting)); +#endif + R_AllocSegMemory(); R_AllocClipSegMemory(); R_AllocPlaneMemory(); diff --git a/src/r_draw_span.cpp b/src/r_draw_span.cpp index bd74b4f83..833b5c1eb 100644 --- a/src/r_draw_span.cpp +++ b/src/r_draw_span.cpp @@ -13,18 +13,6 @@ /// \brief span drawer functions /// \note no includes because this is included as part of r_draw.cpp -#ifdef HAVE_THREADS -#ifdef _WIN32 -#include -#define local_for_thread static __thread -#else -#include -#define local_for_thread thread_local static -#endif -#else -#define local_for_thread static -#endif - // ========================================================================== // SPANS // ========================================================================== @@ -210,15 +198,6 @@ static void R_DrawTiltedSpanTemplate(drawspandata_t* ds) float endz, endu, endv; UINT32 stepu, stepv; UINT32 bit; - local_for_thread INT32 *tiltlighting = NULL; - local_for_thread INT32 oldviewwidth = 0; - - // dont realloc every frame pls thx - if (tiltlighting == NULL || oldviewwidth != viewwidth) - { - tiltlighting = static_cast(realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth)); - oldviewwidth = viewwidth; - } INT32 x1 = ds->x1; const INT32 nflatxshift = ds->nflatxshift; @@ -411,16 +390,6 @@ void R_DrawFogSpan_Tilted(drawspandata_t* ds) float iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); UINT8 *dest; - local_for_thread INT32 *tiltlighting = NULL; - local_for_thread INT32 oldviewwidth = 0; - - // dont realloc every frame pls thx - if (tiltlighting == NULL || oldviewwidth != viewwidth) - { - tiltlighting = static_cast(realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth)); - oldviewwidth = viewwidth; - } - dest = R_Address(ds->x1, ds->y); const INT32 stride = vid.width; -- 2.54.0 From e351c1e62a90730c3147f49cf5a5c6ac577f4c02 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 26 Jun 2025 12:44:51 +0200 Subject: [PATCH 128/141] omit realloc and use unique_ptr for our tiltlighting buffer this makes asan shut up, since those effectively clean up after themselves --- src/r_draw.cpp | 32 ++++++++++++++------------------ src/r_draw_span.cpp | 2 ++ 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/r_draw.cpp b/src/r_draw.cpp index 83fbe82ae..6cec68b9f 100644 --- a/src/r_draw.cpp +++ b/src/r_draw.cpp @@ -36,6 +36,15 @@ #ifdef HAVE_THREADS #include "core/thread_pool.h" +#ifdef _WIN32 +#include +#define local_for_thread static __thread +#else +#include +#define local_for_thread thread_local static +#endif +#else +#define local_for_thread static #endif // ========================================================================== @@ -81,19 +90,7 @@ floatv3_t *ds_su, *ds_sv, *ds_sz; float focallengthf; // For, uh, tilted lighting, duh. -#ifdef HAVE_THREADS -#ifdef _WIN32 -#include -#define local_for_thread static __thread -#else -#include -#define local_for_thread thread_local static -#endif -#else -#define local_for_thread static -#endif - -local_for_thread INT32 *tiltlighting; +local_for_thread std::unique_ptr tiltlight; // -------------------------------------------- // c drawer routines @@ -486,13 +483,12 @@ static void R_AllocViewMemory(void) xtoviewangle = static_cast(Z_Realloc(xtoviewangle, sizeof(*xtoviewangle) * (viewwidth + 1), PU_STATIC, NULL)); - auto init_tiltlighting = [] { - tiltlighting = static_cast(realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth)); // dont use Zone memory since its not thread safe + auto init_tiltlighting = [](INT32 size) { + tiltlight = std::make_unique(size); }; - - init_tiltlighting(); + init_tiltlighting(viewwidth); // allocate for main thread #ifdef HAVE_THREADS - srb2::g_main_threadpool->for_each(std::move(init_tiltlighting)); + srb2::g_main_threadpool->for_each([=] { init_tiltlighting(viewwidth); }); #endif R_AllocSegMemory(); diff --git a/src/r_draw_span.cpp b/src/r_draw_span.cpp index 833b5c1eb..c8b051913 100644 --- a/src/r_draw_span.cpp +++ b/src/r_draw_span.cpp @@ -204,6 +204,7 @@ static void R_DrawTiltedSpanTemplate(drawspandata_t* ds) const INT32 nflatyshift = ds->nflatyshift; const INT32 nflatmask = ds->nflatmask; const INT32 stride = vid.width; + INT32 * __restrict tiltlighting = tiltlight.get(); iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); @@ -392,6 +393,7 @@ void R_DrawFogSpan_Tilted(drawspandata_t* ds) dest = R_Address(ds->x1, ds->y); const INT32 stride = vid.width; + INT32 * __restrict tiltlighting = tiltlight.get(); // Lighting is simple. It's just linear interpolation from start to end { -- 2.54.0 From 0db437aadde436842878f9768288ae2baa33487b Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 26 Jun 2025 12:46:53 +0200 Subject: [PATCH 129/141] do some more tiny optimizations -those can all be declared with restrict -our ternary clamp macro is slightly faster than std::clamp --- src/r_draw_column.cpp | 22 +++++++++++----------- src/r_draw_span.cpp | 20 ++++++++++---------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/r_draw_column.cpp b/src/r_draw_column.cpp index 97273e728..7754a2705 100644 --- a/src/r_draw_column.cpp +++ b/src/r_draw_column.cpp @@ -31,7 +31,7 @@ enum DrawColumnType }; template -static constexpr UINT8 R_GetColumnTranslated(drawcolumndata_t* dc, UINT8 col, const UINT8 *colormap) +static constexpr UINT8 R_GetColumnTranslated(drawcolumndata_t* dc, UINT8 col, const UINT8 * __restrict colormap) { if constexpr (Type & DrawColumnType::DC_COLORMAP) { @@ -42,7 +42,7 @@ static constexpr UINT8 R_GetColumnTranslated(drawcolumndata_t* dc, UINT8 col, co } template -static constexpr UINT8 R_GetColumnTranslucent(drawcolumndata_t* dc, UINT8 *dest, UINT8 col, const UINT8 *colormap) +static constexpr UINT8 R_GetColumnTranslucent(drawcolumndata_t* dc, UINT8 * __restrict dest, UINT8 col, const UINT8 * __restrict colormap) { col = R_GetColumnTranslated(dc, col, colormap); @@ -57,7 +57,7 @@ static constexpr UINT8 R_GetColumnTranslucent(drawcolumndata_t* dc, UINT8 *dest, } template -static constexpr UINT8 R_DrawColumnPixel(drawcolumndata_t* dc, UINT8 *dest, UINT32 bit, const UINT8 *source, const UINT8 *colormap) +static constexpr UINT8 R_DrawColumnPixel(drawcolumndata_t* dc, UINT8 * __restrict dest, UINT32 bit, const __restrict UINT8 *source, const __restrict UINT8 *colormap) { UINT8 col = source[bit]; @@ -182,18 +182,18 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) // // killough 2/1/98: more performance tuning - fixed_t frac; + intptr_t frac; const intptr_t fracstep = dc->iscale; const intptr_t heightmask = dc->sourcelength-1; - static const INT32 npow2min = -1; + constexpr INT32 npow2min = -1; const INT32 npow2max = dc->sourcelength; const INT32 stride = vid.width; - const UINT8 *source = dc->source; - const lighttable_t *colormap = dc->colormap; + const UINT8 * __restrict source = dc->source; + const lighttable_t * __restrict colormap = dc->colormap; // Framebuffer destination address. - UINT8 *dest = R_Address(dc->x, dc->yl); + UINT8 * __restrict dest = R_Address(dc->x, dc->yl); count++; @@ -275,7 +275,7 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) // -1 is the lower clamp bound because column posts have a "safe" byte before the real data // and a few bytes after as well - *dest = R_DrawColumnPixel(dc, dest, std::clamp((frac >> FRACBITS), npow2min, npow2max), source, colormap); + *dest = R_DrawColumnPixel(dc, dest, CLAMP((frac >> FRACBITS), npow2min, npow2max), source, colormap); dest += stride; @@ -325,7 +325,7 @@ DEFINE_COLUMN_FUNC(R_Draw2sMultiPatchTranslucentColumn, DC_HOLES|DC_TRANSMAP) void R_DrawFogColumn(drawcolumndata_t* dc) { INT32 count; - UINT8 *dest; + UINT8 * __restrict dest; count = dc->yh - dc->yl; @@ -344,7 +344,7 @@ void R_DrawFogColumn(drawcolumndata_t* dc) dest = R_Address(dc->x, dc->yl); const INT32 stride = vid.width; - const lighttable_t *colormap = dc->colormap; + const lighttable_t * __restrict colormap = dc->colormap; // Determine scaling, which is the only mapping to be done. do diff --git a/src/r_draw_span.cpp b/src/r_draw_span.cpp index c8b051913..8ea30a80a 100644 --- a/src/r_draw_span.cpp +++ b/src/r_draw_span.cpp @@ -76,10 +76,10 @@ static void R_DrawSpanTemplate(drawspandata_t* ds) UINT32 xstep, ystep; UINT32 bit; - UINT8 *dest = R_Address(ds->x1, ds->y); - UINT8 *dsrc; + UINT8 * __restrict dest = R_Address(ds->x1, ds->y); + UINT8 * __restrict dsrc; - const UINT8 *deststop = vid.screens[0] + vid.rowbytes * vid.height; + const UINT8 * __restrict deststop = vid.screens[0] + vid.rowbytes * vid.height; if (dest+8 > deststop) { @@ -92,8 +92,8 @@ static void R_DrawSpanTemplate(drawspandata_t* ds) xposition = ds->xfrac; yposition = ds->yfrac; xstep = ds->xstep; ystep = ds->ystep; - const UINT8 *source = ds->source; - const UINT8 *colormap = ds->colormap; + const UINT8 * __restrict source = ds->source; + const UINT8 * __restrict colormap = ds->colormap; if constexpr (Type & DS_RIPPLE) { @@ -190,8 +190,8 @@ static void R_DrawTiltedSpanTemplate(drawspandata_t* ds) UINT32 u, v; int i; - UINT8 *dest = R_Address(ds->x1, ds->y); - UINT8 *dsrc; + UINT8 * __restrict dest = R_Address(ds->x1, ds->y); + UINT8 * __restrict dsrc; float startz, startu, startv; float izstep, uzstep, vzstep; @@ -362,8 +362,8 @@ DEFINE_SPAN_COMBO(R_DrawTranslucentWaterSpan, DS_TRANSMAP|DS_RIPPLE) */ void R_DrawFogSpan(drawspandata_t* ds) { - const UINT8 *colormap = ds->colormap; - UINT8 *dest = R_Address(ds->x1, ds->y); + const UINT8 * __restrict colormap = ds->colormap; + UINT8 * __restrict dest = R_Address(ds->x1, ds->y); intptr_t count = ds->x2 - ds->x1 + 1; @@ -389,7 +389,7 @@ void R_DrawFogSpan_Tilted(drawspandata_t* ds) { int width = ds->x2 - ds->x1; float iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); - UINT8 *dest; + UINT8 * __restrict dest; dest = R_Address(ds->x1, ds->y); const INT32 stride = vid.width; -- 2.54.0 From d23c51e70701ad1aefcb1a4dda69e9a8980c69a7 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 26 Jun 2025 12:47:10 +0200 Subject: [PATCH 130/141] mark node as restrict again pointonside --- src/r_main.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_main.h b/src/r_main.h index 808f11b6f..e95862c57 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -88,7 +88,7 @@ extern lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ]; // // killough 5/2/98: reformatted // -FUNCINLINE static ATTRINLINE PUREFUNC INT32 R_PointOnSide(fixed_t x, fixed_t y, const node_t *node) +FUNCINLINE static ATTRINLINE PUREFUNC INT32 R_PointOnSide(fixed_t x, fixed_t y, const node_t * __restrict node) { if (!node->dx) return x <= node->x ? node->dy > 0 : node->dy < 0; -- 2.54.0 From 36e485b2a3c070df99936af1783b9c72d99cdca5 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 26 Jun 2025 15:13:54 +0200 Subject: [PATCH 131/141] move gl portalcullsector check back to the right place lel oopsie --- src/hardware/hw_main.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 906ac9161..c3cd01ad7 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3199,17 +3199,6 @@ static void HWR_RenderBSPNode(INT32 bspnum) bspnum = bsp->children[side^1]; } - // PORTAL CULLING - if (portalcullsector) - { - // skip all subsectors encountered before the portal - // destination's front sector - if (portalcullsector != subsectors[bspnum & ~NF_SUBSECTOR].sector) - return; - else - portalcullsector = NULL; - } - // e6y: support for extended nodes HWR_Subsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR); } @@ -3241,6 +3230,17 @@ static void HWR_RenderPortalBSPNode(INT32 bspnum) bspnum = bsp->children[side^1]; } + // PORTAL CULLING + if (portalcullsector) + { + // skip all subsectors encountered before the portal + // destination's front sector + if (portalcullsector != subsectors[bspnum & ~NF_SUBSECTOR].sector) + return; + else + portalcullsector = NULL; + } + // e6y: support for extended nodes HWR_Subsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR); } -- 2.54.0 From aef02cb3478c7048ae8d10b9bef1d1c9567620be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Thu, 26 Jun 2025 19:51:01 +0200 Subject: [PATCH 132/141] Fix one-pixel wide gaps in tall sprites --- src/r_draw_column.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_draw_column.cpp b/src/r_draw_column.cpp index 7754a2705..bc91ef0d3 100644 --- a/src/r_draw_column.cpp +++ b/src/r_draw_column.cpp @@ -220,7 +220,7 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) frac += FRACUNIT; // texture has no height, so just go - while (--count > 0) + while (--count >= 0) { *dest = R_DrawColumnPixel(dc, dest, frac>>FRACBITS, source, colormap); dest += stride; -- 2.54.0 From 972ee5cf7629afb2f96b2434a2ce61920587ca91 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 26 Jun 2025 20:11:23 +0200 Subject: [PATCH 133/141] remove erronous BACKSLASH was from when this was a macro lel edit: screw you comptime --- src/r_main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/r_main.cpp b/src/r_main.cpp index 044aa918a..836fb66e8 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1129,8 +1129,8 @@ static void R_SetupSkyScale(player_t *player, camera_t *thiscam, mapheader_t *mh newview->y += x; break; case ANGLE_180: - newview->x -= x;\ - newview->y -= y;\ + newview->x -= x; + newview->y -= y; break; case ANGLE_270: newview->x += y; -- 2.54.0 From 054a40a4b2d4d7a981ad3a9f53c4025e7d5547c4 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 27 Jun 2025 16:38:13 +0200 Subject: [PATCH 134/141] Revert "omit realloc and use unique_ptr for our tiltlighting buffer" This reverts commit e351c1e62a90730c3147f49cf5a5c6ac577f4c02. --- src/r_draw.cpp | 32 ++++++++++++++++++-------------- src/r_draw_span.cpp | 2 -- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/r_draw.cpp b/src/r_draw.cpp index 6cec68b9f..83fbe82ae 100644 --- a/src/r_draw.cpp +++ b/src/r_draw.cpp @@ -36,15 +36,6 @@ #ifdef HAVE_THREADS #include "core/thread_pool.h" -#ifdef _WIN32 -#include -#define local_for_thread static __thread -#else -#include -#define local_for_thread thread_local static -#endif -#else -#define local_for_thread static #endif // ========================================================================== @@ -90,7 +81,19 @@ floatv3_t *ds_su, *ds_sv, *ds_sz; float focallengthf; // For, uh, tilted lighting, duh. -local_for_thread std::unique_ptr tiltlight; +#ifdef HAVE_THREADS +#ifdef _WIN32 +#include +#define local_for_thread static __thread +#else +#include +#define local_for_thread thread_local static +#endif +#else +#define local_for_thread static +#endif + +local_for_thread INT32 *tiltlighting; // -------------------------------------------- // c drawer routines @@ -483,12 +486,13 @@ static void R_AllocViewMemory(void) xtoviewangle = static_cast(Z_Realloc(xtoviewangle, sizeof(*xtoviewangle) * (viewwidth + 1), PU_STATIC, NULL)); - auto init_tiltlighting = [](INT32 size) { - tiltlight = std::make_unique(size); + auto init_tiltlighting = [] { + tiltlighting = static_cast(realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth)); // dont use Zone memory since its not thread safe }; - init_tiltlighting(viewwidth); // allocate for main thread + + init_tiltlighting(); #ifdef HAVE_THREADS - srb2::g_main_threadpool->for_each([=] { init_tiltlighting(viewwidth); }); + srb2::g_main_threadpool->for_each(std::move(init_tiltlighting)); #endif R_AllocSegMemory(); diff --git a/src/r_draw_span.cpp b/src/r_draw_span.cpp index 8ea30a80a..ebdb4b8d7 100644 --- a/src/r_draw_span.cpp +++ b/src/r_draw_span.cpp @@ -204,7 +204,6 @@ static void R_DrawTiltedSpanTemplate(drawspandata_t* ds) const INT32 nflatyshift = ds->nflatyshift; const INT32 nflatmask = ds->nflatmask; const INT32 stride = vid.width; - INT32 * __restrict tiltlighting = tiltlight.get(); iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); @@ -393,7 +392,6 @@ void R_DrawFogSpan_Tilted(drawspandata_t* ds) dest = R_Address(ds->x1, ds->y); const INT32 stride = vid.width; - INT32 * __restrict tiltlighting = tiltlight.get(); // Lighting is simple. It's just linear interpolation from start to end { -- 2.54.0 From 96501394704e5c04ac775819a65e0fe18ac32c58 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 27 Jun 2025 16:38:16 +0200 Subject: [PATCH 135/141] Revert "allocate tiltlighting buffer in R_AllocViewMemory again" This reverts commit b541de4f8cad976eb2c26c3ec0b7d7ed2775a08d. --- src/r_draw.cpp | 27 +-------------------------- src/r_draw_span.cpp | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/r_draw.cpp b/src/r_draw.cpp index 83fbe82ae..23d512a19 100644 --- a/src/r_draw.cpp +++ b/src/r_draw.cpp @@ -34,10 +34,6 @@ #include "hardware/hw_main.h" #endif -#ifdef HAVE_THREADS -#include "core/thread_pool.h" -#endif - // ========================================================================== // COMMON DATA FOR 8bpp AND 16bpp // ========================================================================== @@ -81,19 +77,7 @@ floatv3_t *ds_su, *ds_sv, *ds_sz; float focallengthf; // For, uh, tilted lighting, duh. -#ifdef HAVE_THREADS -#ifdef _WIN32 -#include -#define local_for_thread static __thread -#else -#include -#define local_for_thread thread_local static -#endif -#else -#define local_for_thread static -#endif - -local_for_thread INT32 *tiltlighting; +//static INT32 *tiltlighting; // -------------------------------------------- // c drawer routines @@ -486,15 +470,6 @@ static void R_AllocViewMemory(void) xtoviewangle = static_cast(Z_Realloc(xtoviewangle, sizeof(*xtoviewangle) * (viewwidth + 1), PU_STATIC, NULL)); - auto init_tiltlighting = [] { - tiltlighting = static_cast(realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth)); // dont use Zone memory since its not thread safe - }; - - init_tiltlighting(); -#ifdef HAVE_THREADS - srb2::g_main_threadpool->for_each(std::move(init_tiltlighting)); -#endif - R_AllocSegMemory(); R_AllocClipSegMemory(); R_AllocPlaneMemory(); diff --git a/src/r_draw_span.cpp b/src/r_draw_span.cpp index ebdb4b8d7..7ead430c4 100644 --- a/src/r_draw_span.cpp +++ b/src/r_draw_span.cpp @@ -13,6 +13,18 @@ /// \brief span drawer functions /// \note no includes because this is included as part of r_draw.cpp +#ifdef HAVE_THREADS +#ifdef _WIN32 +#include +#define local_for_thread static __thread +#else +#include +#define local_for_thread thread_local static +#endif +#else +#define local_for_thread static +#endif + // ========================================================================== // SPANS // ========================================================================== @@ -198,6 +210,15 @@ static void R_DrawTiltedSpanTemplate(drawspandata_t* ds) float endz, endu, endv; UINT32 stepu, stepv; UINT32 bit; + local_for_thread INT32 *tiltlighting = NULL; + local_for_thread INT32 oldviewwidth = 0; + + // dont realloc every frame pls thx + if (tiltlighting == NULL || oldviewwidth != viewwidth) + { + tiltlighting = static_cast(realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth)); + oldviewwidth = viewwidth; + } INT32 x1 = ds->x1; const INT32 nflatxshift = ds->nflatxshift; @@ -390,6 +411,16 @@ void R_DrawFogSpan_Tilted(drawspandata_t* ds) float iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); UINT8 * __restrict dest; + local_for_thread INT32 *tiltlighting = NULL; + local_for_thread INT32 oldviewwidth = 0; + + // dont realloc every frame pls thx + if (tiltlighting == NULL || oldviewwidth != viewwidth) + { + tiltlighting = static_cast(realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth)); + oldviewwidth = viewwidth; + } + dest = R_Address(ds->x1, ds->y); const INT32 stride = vid.width; -- 2.54.0 From 4e9f9b7e0e4272d3210d80b1bcf972c0097d0c0e Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 27 Jun 2025 16:38:19 +0200 Subject: [PATCH 136/141] Revert "add "for_each" to srb2 threadpool" This reverts commit 604bc400211ba3f298cbfef8195cd5cb1f68b595. --- src/core/thread_pool.h | 55 ------------------------------------------ 1 file changed, 55 deletions(-) diff --git a/src/core/thread_pool.h b/src/core/thread_pool.h index 535e77a9f..75961614e 100644 --- a/src/core/thread_pool.h +++ b/src/core/thread_pool.h @@ -80,7 +80,6 @@ public: /// Enqueue but don't notify template void schedule(T&& thunk); - template void for_each(F&& task); /// Notify threads after several schedules void notify(); void notify_sema(const Sema& sema); @@ -144,60 +143,6 @@ void ThreadPool::schedule(T&& thunk) } } -template -void ThreadPool::for_each(F&& thunk) -{ - static_assert(sizeof(std::decay_t) <= sizeof(std::declval().raw)); - - if (immediate_mode_) - { - thunk(); - return; - } - - Sema sync_sema; - begin_sema(); - - auto counter = std::make_shared>(threads_.size()); - - for (size_t i = 0; i < threads_.size(); i++) { - std::shared_ptr q = work_queues_[i]; - Task task; - - struct TaskData { - std::decay_t func; - std::shared_ptr> counter; - Sema sema; - ThreadPool* pool; - }; - static_assert(sizeof(TaskData) <= sizeof(task.raw)); - - new (task.raw.data()) TaskData{ - std::forward(thunk), - counter, - sync_sema, - this - }; - - task.thunk = [](void* ptr) { - auto* data = static_cast(ptr); - data->func(); - if (--(*data->counter) == 0) { - data->pool->notify_sema(data->sema); - } - }; - - task.deleter = [](void* ptr) { - static_cast(ptr)->~TaskData(); - }; - - task.pseudosema = cur_sema_; - q->push(std::move(task)); - } - - wait_sema(sync_sema); -} - } // namespace srb2 extern "C" { -- 2.54.0 From d47e20b54e41c294cf453bd640e0bc14bf7c2450 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 29 Jun 2025 11:42:58 +0200 Subject: [PATCH 137/141] those can be const --- src/r_main.cpp | 5 ++--- src/r_plane.cpp | 10 ++++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/r_main.cpp b/src/r_main.cpp index 836fb66e8..ebea32638 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -491,7 +491,7 @@ boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixe // Returns search dimensions within a blockmap, in the direction of viewangle and out to a certain distance. void R_GetRenderBlockMapDimensions(fixed_t drawdist, INT32 *xl, INT32 *xh, INT32 *yl, INT32 *yh) { - const angle_t left = viewangle - clipangle; + const angle_t left = viewangle - clipangle; const angle_t right = viewangle + clipangle; const fixed_t vxleft = viewx + FixedMul(drawdist, FCOS(left)); @@ -657,7 +657,6 @@ void R_CheckViewMorph(void) rollangle >>= ANGLETOFINESHIFT; rollangle = ((rollangle+2) & ~3) & FINEMASK; // Limit the distinct number of angles to reduce recalcs from angles changing a lot. - if (rollangle == viewmorph.rollangle && viewmorph.scrmapsize == vid.width*vid.height) return; // No change @@ -1363,7 +1362,7 @@ void R_RenderPlayerView(player_t *player) // load previous saved value of skyVisible for the player skyVisible = skyVisiblePerPlayer[viewssnum]; - fixed_t fov = R_GetPlayerFov(player); + const fixed_t fov = R_GetPlayerFov(player); if (viewfov[viewssnum] != fov) { diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 5cb48b355..54a0f04da 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -149,7 +149,7 @@ void R_AllocPlaneMemory(void) // static fixed_t R_CalculateRippleOffset(drawspandata_t* ds, INT32 y) { - fixed_t distance = FixedMul(ds->planeheight, yslope[y]); + const fixed_t distance = FixedMul(ds->planeheight, yslope[y]); const INT32 yay = (ds->planeripple.offset + (distance>>9)) & 8191; return FixedDiv(FINESINE(yay), (1<<12) + (distance>>11)); } @@ -559,6 +559,7 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop) else /* Cannot use existing plane; create a new one */ { visplane_t *new_pl; + if (pl->ffloor) { new_pl = new_visplane(MAXVISPLANES - 1); @@ -782,7 +783,6 @@ void R_DrawSkyPlanes(void) static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), boolean allow_parallel) { INT32 x; - drawcolumndata_t dc = {}; if (!(pl->minx <= pl->maxx)) return; @@ -794,6 +794,8 @@ static void R_DrawSkyPlane(visplane_t *pl, void(*colfunc2)(drawcolumndata_t*), b return; } + drawcolumndata_t dc = {}; + // Reset column drawer function (note: couldn't we just call walldrawerfunc directly?) // (that is, unless we'll need to switch drawers in future for some reason) R_SetColumnFunc(BASEDRAWFUNC); @@ -1006,8 +1008,8 @@ static inline void R_AdjustSlopeCoordinates(drawspandata_t* ds, vector3_t *origi { const fixed_t modmask = ((1 << (32-ds->nflatshiftup)) - 1); - fixed_t ox = (origin->x & modmask); - fixed_t oy = -(origin->y & modmask); + const fixed_t ox = (origin->x & modmask); + const fixed_t oy = -(origin->y & modmask); ds->xoffs &= modmask; ds->yoffs &= modmask; -- 2.54.0 From 465fea8bb3415a9fb9265064dd81e565faef3a3c Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 30 Jun 2025 12:18:21 +0200 Subject: [PATCH 138/141] "restrict" macro for c++ since it does not have it, use __restrict instead --- src/doomdef.h | 8 ++++++++ src/r_draw_column.cpp | 16 ++++++++-------- src/r_draw_span.cpp | 20 ++++++++++---------- src/r_main.h | 2 +- src/r_plane.cpp | 10 +++++----- 5 files changed, 32 insertions(+), 24 deletions(-) diff --git a/src/doomdef.h b/src/doomdef.h index dbeabce63..ce846ee27 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -566,6 +566,14 @@ UINT32 quickncasehash (const char *p, size_t n) #define UNLIKELY(x) (x) #endif +#ifdef __cplusplus +#if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER) + #define restrict __restrict +#else + #define restrict +#endif +#endif + // An assert-type mechanism. #ifdef PARANOIA #define I_Assert(e) ((e) ? (void)0 : I_Error("assert failed: %s, file %s, line %d", #e, __FILE__, __LINE__)) diff --git a/src/r_draw_column.cpp b/src/r_draw_column.cpp index bc91ef0d3..dcc1a5b90 100644 --- a/src/r_draw_column.cpp +++ b/src/r_draw_column.cpp @@ -31,7 +31,7 @@ enum DrawColumnType }; template -static constexpr UINT8 R_GetColumnTranslated(drawcolumndata_t* dc, UINT8 col, const UINT8 * __restrict colormap) +static constexpr UINT8 R_GetColumnTranslated(drawcolumndata_t* dc, UINT8 col, const UINT8 * restrict colormap) { if constexpr (Type & DrawColumnType::DC_COLORMAP) { @@ -42,7 +42,7 @@ static constexpr UINT8 R_GetColumnTranslated(drawcolumndata_t* dc, UINT8 col, co } template -static constexpr UINT8 R_GetColumnTranslucent(drawcolumndata_t* dc, UINT8 * __restrict dest, UINT8 col, const UINT8 * __restrict colormap) +static constexpr UINT8 R_GetColumnTranslucent(drawcolumndata_t* dc, UINT8 * restrict dest, UINT8 col, const UINT8 * restrict colormap) { col = R_GetColumnTranslated(dc, col, colormap); @@ -57,7 +57,7 @@ static constexpr UINT8 R_GetColumnTranslucent(drawcolumndata_t* dc, UINT8 * __re } template -static constexpr UINT8 R_DrawColumnPixel(drawcolumndata_t* dc, UINT8 * __restrict dest, UINT32 bit, const __restrict UINT8 *source, const __restrict UINT8 *colormap) +static constexpr UINT8 R_DrawColumnPixel(drawcolumndata_t* dc, UINT8 * restrict dest, UINT32 bit, const restrict UINT8 *source, const restrict UINT8 *colormap) { UINT8 col = source[bit]; @@ -189,11 +189,11 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc) const INT32 npow2max = dc->sourcelength; const INT32 stride = vid.width; - const UINT8 * __restrict source = dc->source; - const lighttable_t * __restrict colormap = dc->colormap; + const UINT8 * restrict source = dc->source; + const lighttable_t * restrict colormap = dc->colormap; // Framebuffer destination address. - UINT8 * __restrict dest = R_Address(dc->x, dc->yl); + UINT8 * restrict dest = R_Address(dc->x, dc->yl); count++; @@ -325,7 +325,7 @@ DEFINE_COLUMN_FUNC(R_Draw2sMultiPatchTranslucentColumn, DC_HOLES|DC_TRANSMAP) void R_DrawFogColumn(drawcolumndata_t* dc) { INT32 count; - UINT8 * __restrict dest; + UINT8 * restrict dest; count = dc->yh - dc->yl; @@ -344,7 +344,7 @@ void R_DrawFogColumn(drawcolumndata_t* dc) dest = R_Address(dc->x, dc->yl); const INT32 stride = vid.width; - const lighttable_t * __restrict colormap = dc->colormap; + const lighttable_t * restrict colormap = dc->colormap; // Determine scaling, which is the only mapping to be done. do diff --git a/src/r_draw_span.cpp b/src/r_draw_span.cpp index 7ead430c4..cf7878184 100644 --- a/src/r_draw_span.cpp +++ b/src/r_draw_span.cpp @@ -88,10 +88,10 @@ static void R_DrawSpanTemplate(drawspandata_t* ds) UINT32 xstep, ystep; UINT32 bit; - UINT8 * __restrict dest = R_Address(ds->x1, ds->y); - UINT8 * __restrict dsrc; + UINT8 * restrict dest = R_Address(ds->x1, ds->y); + UINT8 * restrict dsrc; - const UINT8 * __restrict deststop = vid.screens[0] + vid.rowbytes * vid.height; + const UINT8 * restrict deststop = vid.screens[0] + vid.rowbytes * vid.height; if (dest+8 > deststop) { @@ -104,8 +104,8 @@ static void R_DrawSpanTemplate(drawspandata_t* ds) xposition = ds->xfrac; yposition = ds->yfrac; xstep = ds->xstep; ystep = ds->ystep; - const UINT8 * __restrict source = ds->source; - const UINT8 * __restrict colormap = ds->colormap; + const UINT8 * restrict source = ds->source; + const UINT8 * restrict colormap = ds->colormap; if constexpr (Type & DS_RIPPLE) { @@ -202,8 +202,8 @@ static void R_DrawTiltedSpanTemplate(drawspandata_t* ds) UINT32 u, v; int i; - UINT8 * __restrict dest = R_Address(ds->x1, ds->y); - UINT8 * __restrict dsrc; + UINT8 * restrict dest = R_Address(ds->x1, ds->y); + UINT8 * restrict dsrc; float startz, startu, startv; float izstep, uzstep, vzstep; @@ -382,8 +382,8 @@ DEFINE_SPAN_COMBO(R_DrawTranslucentWaterSpan, DS_TRANSMAP|DS_RIPPLE) */ void R_DrawFogSpan(drawspandata_t* ds) { - const UINT8 * __restrict colormap = ds->colormap; - UINT8 * __restrict dest = R_Address(ds->x1, ds->y); + const UINT8 * restrict colormap = ds->colormap; + UINT8 * restrict dest = R_Address(ds->x1, ds->y); intptr_t count = ds->x2 - ds->x1 + 1; @@ -409,7 +409,7 @@ void R_DrawFogSpan_Tilted(drawspandata_t* ds) { int width = ds->x2 - ds->x1; float iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx); - UINT8 * __restrict dest; + UINT8 * restrict dest; local_for_thread INT32 *tiltlighting = NULL; local_for_thread INT32 oldviewwidth = 0; diff --git a/src/r_main.h b/src/r_main.h index e95862c57..29a6b308e 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -88,7 +88,7 @@ extern lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ]; // // killough 5/2/98: reformatted // -FUNCINLINE static ATTRINLINE PUREFUNC INT32 R_PointOnSide(fixed_t x, fixed_t y, const node_t * __restrict node) +FUNCINLINE static ATTRINLINE PUREFUNC INT32 R_PointOnSide(fixed_t x, fixed_t y, const node_t * restrict node) { if (!node->dx) return x <= node->x ? node->dy > 0 : node->dy < 0; diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 54a0f04da..c52771bc4 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -100,7 +100,7 @@ static void R_ReallocPlaneBounds(visplane_t *pl) { pl->top_memory = static_cast(Z_Realloc(pl->top_memory, sizeof(UINT16) * (viewwidth + 2), PU_STATIC, NULL)); pl->bottom_memory = static_cast(Z_Realloc(pl->bottom_memory, sizeof(UINT16) * (viewwidth + 2), PU_STATIC, NULL)); - pl->top = pl->top_memory + 1; + pl->top = pl->top_memory + 1; pl->bottom = pl->bottom_memory + 1; } @@ -203,14 +203,14 @@ static void R_MapPlane(drawspandata_t *ds, spandrawfunc_t *localspanfunc, INT32 if (!R_CheckMapPlane(__func__, y, x1, x2)) return; - angle = (ds->currentplane->viewangle + ds->currentplane->plangle)>>ANGLETOFINESHIFT; + angle = (ds->currentplane->viewangle + ds->currentplane->plangle)>>ANGLETOFINESHIFT; planecos = FINECOSINE(angle); planesin = FINESINE(angle); // [RH] Notice that I dumped the caching scheme used by Doom. // It did not offer any appreciable speedup. distance = FixedMul(ds->planeheight, yslope[y]); - span = abs(centery - y); + span = abs(centery - y); if (span) // don't divide by zero { @@ -259,7 +259,7 @@ static void R_MapPlane(drawspandata_t *ds, spandrawfunc_t *localspanfunc, INT32 if (ds->currentplane->extra_colormap) ds->colormap = ds->currentplane->extra_colormap->colormap + (ds->colormap - colormaps); - ds->y = y; + ds->y = y; ds->x1 = x1; ds->x2 = x2; @@ -301,7 +301,7 @@ static void R_MapTiltedPlane(drawspandata_t *ds, spandrawfunc_t *localspanfunc, ds->colormap += COLORMAP_REMAPOFFSET; } - ds->y = y; + ds->y = y; ds->x1 = x1; ds->x2 = x2; -- 2.54.0 From f4d40bd55f790175b78e04b4385c0c515a5c129a Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 1 Jul 2025 14:38:32 +0200 Subject: [PATCH 139/141] "-Wno-aggregate-return" for c++ --- src/Makefile.d/versions.mk | 3 +++ src/r_plane.cpp | 6 ------ src/r_things.cpp | 3 --- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/Makefile.d/versions.mk b/src/Makefile.d/versions.mk index a3cdbbd4b..ce23c3e4e 100644 --- a/src/Makefile.d/versions.mk +++ b/src/Makefile.d/versions.mk @@ -16,6 +16,9 @@ $(foreach v,$(join $(wordlist 2,$(_n),- $(gcc_versions)),\ $(and $(findstring =,$(v)),\ $(eval $(call _predecessor,$(subst =, ,$(v)))))) +# aggregate returns seem to happen alot in c++ so just supress em lel +CXXFLAGS+= -Wno-aggregate-return + # -W -Wno-unused ifdef GCC150 diff --git a/src/r_plane.cpp b/src/r_plane.cpp index c52771bc4..4d6244468 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -740,12 +740,9 @@ void R_DrawPlanes(void) } } #ifdef HAVE_THREADS -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Waggregate-return" tp_sema = srb2::g_main_threadpool->end_sema(); srb2::g_main_threadpool->notify_sema(tp_sema); srb2::g_main_threadpool->wait_sema(tp_sema); -#pragma GCC diagnostic pop #endif } @@ -771,12 +768,9 @@ void R_DrawSkyPlanes(void) } } #ifdef HAVE_THREADS -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Waggregate-return" tp_sema = srb2::g_main_threadpool->end_sema(); srb2::g_main_threadpool->notify_sema(tp_sema); srb2::g_main_threadpool->wait_sema(tp_sema); -#pragma GCC diagnostic pop #endif } diff --git a/src/r_things.cpp b/src/r_things.cpp index bf33fb97c..06c346645 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -2977,12 +2977,9 @@ static void R_DrawMaskedList(drawnode_t* head) #endif R_DrawSinglePlane(&ds, r2->plane, cv_parallelsoftware.value); #ifdef HAVE_THREADS -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Waggregate-return" tp_sema = srb2::g_main_threadpool->end_sema(); srb2::g_main_threadpool->notify_sema(tp_sema); srb2::g_main_threadpool->wait_sema(tp_sema); -#pragma GCC diagnostic pop #endif R_DoneWithNode(r2); r2 = next; -- 2.54.0 From 3c282b5022d85e0667ea4a92f4568fd832ff69af Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 1 Jul 2025 14:42:17 +0200 Subject: [PATCH 140/141] this can use min/max --- src/r_plane.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 4d6244468..653353a2b 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -1096,6 +1096,7 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle // and mercilessly shoved into saturn by chearii 02-02-2025 { INT32 trans = (10*((256+12) - pl->ffloor->alpha))/255; + if (trans >= 10) return; // Don't even draw it @@ -1132,13 +1133,8 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle spanfunctype = SPANDRAWFUNC_WATER; // Copy the current scene, ugh - top = pl->high-8; - bottom = pl->low+8; - - if (top < 0) - top = 0; - if (bottom > vid.height) - bottom = vid.height; + top = std::max(0, pl->high - 8); + bottom = std::min(viewheight, pl->low + 8); // Only copy the part of the screen we need UINT8 i = R_GetViewNumber(); -- 2.54.0 From 5a44afcd9fdee9be513bfca839a2483941331391 Mon Sep 17 00:00:00 2001 From: Indev Date: Tue, 1 Jul 2025 16:07:51 +0300 Subject: [PATCH 141/141] Disable multithreading in R_DrawMaskedList --- src/r_things.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/r_things.cpp b/src/r_things.cpp index 06c346645..683904ccb 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -2971,16 +2971,8 @@ static void R_DrawMaskedList(drawnode_t* head) { drawspandata_t ds = {}; next = r2->prev; -#ifdef HAVE_THREADS - srb2::ThreadPool::Sema tp_sema; - srb2::g_main_threadpool->begin_sema(); -#endif - R_DrawSinglePlane(&ds, r2->plane, cv_parallelsoftware.value); -#ifdef HAVE_THREADS - tp_sema = srb2::g_main_threadpool->end_sema(); - srb2::g_main_threadpool->notify_sema(tp_sema); - srb2::g_main_threadpool->wait_sema(tp_sema); -#endif + // Force disable multithreading since it is usually slower because of waiting for each plane to render + R_DrawSinglePlane(&ds, r2->plane, false); R_DoneWithNode(r2); r2 = next; } -- 2.54.0