diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 520fc8929..1676fe5cb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -127,6 +127,7 @@ set(SRB2_CORE_RENDER_SOURCES r_splats.c r_things.c r_patch.c + r_rotsprite.c r_portal.c r_bsp.h @@ -143,6 +144,8 @@ set(SRB2_CORE_RENDER_SOURCES r_state.h r_things.h r_patch.h + r_rotsprite.h + r_patchtrees.h r_portal.h ) diff --git a/src/Makefile b/src/Makefile index 9ea1ea239..ffa02f147 100644 --- a/src/Makefile +++ b/src/Makefile @@ -470,6 +470,7 @@ OBJS:=$(i_main_o) \ $(OBJDIR)/r_splats.o \ $(OBJDIR)/r_things.o \ $(OBJDIR)/r_patch.o \ + $(OBJDIR)/r_rotsprite.o \ $(OBJDIR)/r_portal.o \ $(OBJDIR)/screen.o \ $(OBJDIR)/v_video.o \ diff --git a/src/android/i_video.c b/src/android/i_video.c index 1909cd71a..e0bf1e00e 100644 --- a/src/android/i_video.c +++ b/src/android/i_video.c @@ -9,6 +9,7 @@ #include "utils/Log.h" rendermode_t rendermode = render_soft; +rendermode_t chosenrendermode = render_none; boolean highcolor = false; @@ -40,8 +41,6 @@ INT32 VID_GetModeForSize(INT32 w, INT32 h) return 0; } -void VID_PrepareModeList(void){} - INT32 VID_SetMode(INT32 modenum) { vid.modenum = 0; @@ -52,7 +51,11 @@ INT32 VID_SetMode(INT32 modenum) return 0; } -void VID_CheckRenderer(void) {} +boolean VID_CheckRenderer(void) +{ + return false; +} + void VID_CheckGLLoaded(rendermode_t oldrender) {} const char *VID_GetModeName(INT32 modenum) diff --git a/src/console.c b/src/console.c index aac94d473..b23baaa2d 100644 --- a/src/console.c +++ b/src/console.c @@ -45,7 +45,8 @@ #define MAXHUDLINES 20 static boolean con_started = false; // console has been initialised - boolean con_startup = false; // true at game startup, screen need refreshing + boolean con_startup = false; // true at game startup + boolean con_refresh = false; // screen needs refreshing static boolean con_forcepic = true; // at startup toggle console translucency when first off boolean con_recalc; // set true when screen size has changed @@ -402,11 +403,11 @@ void CON_Init(void) con_destlines = vid.height; con_curlines = vid.height; - if (!dedicated) { con_started = true; - con_startup = true; // need explicit screen refresh until we are in Doom loop + con_startup = true; + con_refresh = true; // needs explicit screen refresh until we are in the main game loop consoletoggle = false; CV_RegisterVar(&cons_msgtimeout); CV_RegisterVar(&cons_hudlines); @@ -419,7 +420,8 @@ void CON_Init(void) else { con_started = true; - con_startup = false; // need explicit screen refresh until we are in Doom loop + con_startup = false; + con_refresh = false; // disable explicit screen refresh consoletoggle = true; } } @@ -1293,16 +1295,16 @@ void CONS_Printf(const char *fmt, ...) con_scrollup = 0; // if not in display loop, force screen update - if (con_startup && (!setrenderneeded)) + if (con_refresh) { -#ifdef _WINDOWS - patch_t *con_backpic = W_CachePatchName("CONSBACK", PU_PATCH); - - // Jimita: CON_DrawBackpic just called V_DrawScaledPatch - V_DrawScaledPatch(0, 0, 0, con_backpic); - - W_UnlockCachedPatch(con_backpic); - I_LoadingScreen(txt); // Win32/OS2 only +#if defined(_WINDOWS) + if (con_startup) + { + patch_t *con_backpic = W_CachePatchName("CONSBACK", PU_PATCH); + V_DrawScaledPatch(0, 0, 0, con_backpic); + W_UnlockCachedPatch(con_backpic); + I_LoadingScreen(txt); + } #else // here we display the console text CON_Drawer(); @@ -1369,7 +1371,7 @@ void CONS_Debug(INT32 debugflags, const char *fmt, ...) // void CONS_Error(const char *msg) { -#ifdef RPC_NO_WINDOWS_H +#if defined(RPC_NO_WINDOWS_H) && defined(_WINDOWS) if (!graphics_started) { MessageBoxA(vid.WndParent, msg, "SRB2 Warning", MB_OK); @@ -1648,9 +1650,6 @@ void CON_Drawer(void) if (!con_started || !graphics_started) return; - if (needpatchrecache) - HU_LoadGraphics(); - if (con_recalc) { CON_RecalcSize(); diff --git a/src/console.h b/src/console.h index 2be92d62b..6f38ca8d0 100644 --- a/src/console.h +++ b/src/console.h @@ -20,8 +20,12 @@ boolean CON_Responder(event_t *ev); // set true when screen size has changed, to adapt console extern boolean con_recalc; +// console being displayed at game startup extern boolean con_startup; +// needs explicit screen refresh until we are in the main game loop +extern boolean con_refresh; + // top clip value for view render: do not draw part of view hidden by console extern INT32 con_clipviewtop; diff --git a/src/d_main.c b/src/d_main.c index 6bc42da14..132605c13 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -110,8 +110,6 @@ boolean devparm = false; // started game with -devparm boolean singletics = false; // timedemo boolean lastdraw = false; -static void D_CheckRendererState(void); - postimg_t postimgtype = postimg_none; INT32 postimgparam; postimg_t postimgtype2 = postimg_none; @@ -222,7 +220,6 @@ INT16 wipetypepost = -1; static void D_Display(void) { - INT32 setrenderstillneeded = 0; boolean forcerefresh = false; static boolean wipe = false; INT32 wipedefindex = 0; @@ -233,60 +230,26 @@ static void D_Display(void) if (nodrawers) return; // for comparative timing/profiling - // Lactozilla: Switching renderers works by checking - // if the game has to do it right when the frame - // needs to render. If so, five things will happen: - // 1. Interface functions will be called so - // that switching to OpenGL creates a - // GL context, and switching to Software - // allocates screen buffers. - // 2. Software will set drawer functions, - // and OpenGL will load textures and - // create plane polygons, if necessary. - // 3. Functions related to switching video - // modes (resolution) are called. - // 4. Patch data is freed from memory, - // and recached if necessary. - // 5. The frame is ready to be drawn! - - // stop movie if needs to change renderer - if (setrenderneeded && (moviemode == MM_APNG)) - M_StopMovie(); - - // check for change of renderer or screen size (video mode) + // Check for change of renderer or screen size (video mode) if ((setrenderneeded || setmodeneeded) && !wipe) - { - if (setrenderneeded) - { - CONS_Debug(DBG_RENDER, "setrenderneeded set (%d)\n", setrenderneeded); - setrenderstillneeded = setrenderneeded; - } SCR_SetMode(); // change video mode - } - if (vid.recalc || setrenderstillneeded) - { + // Recalc the screen + if (vid.recalc) SCR_Recalc(); // NOTE! setsizeneeded is set by SCR_Recalc() -#ifdef HWRENDER - // Shoot! The screen texture was flushed! - if ((rendermode == render_opengl) && (gamestate == GS_INTERMISSION)) - usebuffer = false; -#endif - } + // View morph if (rendermode == render_soft && !splitscreen) R_CheckViewMorph(); - // change the view size if needed - if (setsizeneeded || setrenderstillneeded) + // Change the view size if needed + // Set by changing video mode or renderer + if (setsizeneeded) { - R_ExecuteSetViewSize(); + R_SetViewSize(); forcerefresh = true; // force background redraw } - // Lactozilla: Renderer switching - D_CheckRendererState(); - // draw buffered stuff to screen // Used only by linux GGI version I_UpdateNoBlit(); @@ -426,11 +389,11 @@ static void D_Display(void) { topleft = screens[0] + viewwindowy*vid.width + viewwindowx; objectsdrawn = 0; - #ifdef HWRENDER +#ifdef HWRENDER if (rendermode != render_soft) HWR_RenderPlayerView(0, &players[displayplayer]); else - #endif +#endif if (rendermode != render_none) R_RenderPlayerView(&players[displayplayer]); } @@ -438,11 +401,11 @@ static void D_Display(void) // render the second screen if (splitscreen && players[secondarydisplayplayer].mo) { - #ifdef HWRENDER +#ifdef HWRENDER if (rendermode != render_soft) HWR_RenderPlayerView(1, &players[secondarydisplayplayer]); else - #endif +#endif if (rendermode != render_none) { viewwindowy = vid.height / 2; @@ -595,13 +558,13 @@ static void D_Display(void) s[sizeof s - 1] = '\0'; snprintf(s, sizeof s - 1, "get %d b/s", getbps); - V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-40, V_YELLOWMAP, s); + V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-32-40, V_YELLOWMAP, s); snprintf(s, sizeof s - 1, "send %d b/s", sendbps); - V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-30, V_YELLOWMAP, s); + V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-32-30, V_YELLOWMAP, s); snprintf(s, sizeof s - 1, "GameMiss %.2f%%", gamelostpercent); - V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-20, V_YELLOWMAP, s); + V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-32-20, V_YELLOWMAP, s); snprintf(s, sizeof s - 1, "SysMiss %.2f%%", lostpercent); - V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-10, V_YELLOWMAP, s); + V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-32-10, V_YELLOWMAP, s); } if (cv_renderstats.value) @@ -679,26 +642,6 @@ static void D_Display(void) I_FinishUpdate(); // page flip or blit buffer rs_swaptime = I_GetTimeMicros() - rs_swaptime; } - - needpatchflush = false; - needpatchrecache = false; -} - -// Check the renderer's state -// after a possible renderer switch. -void D_CheckRendererState(void) -{ - // flush all patches from memory - if (needpatchflush) - { - Z_FlushCachedPatches(); - needpatchflush = false; - } - - // some patches have been freed, - // so cache them again - if (needpatchrecache) - R_ReloadHUDGraphics(); } // ========================================================================= @@ -723,7 +666,8 @@ void D_SRB2Loop(void) oldentertics = I_GetTime(); - // end of loading screen: CONS_Printf() will no more call FinishUpdate() + // end of loading screen: CONS_Printf() will no more call I_FinishUpdate() + con_refresh = false; con_startup = false; // make sure to do a d_display to init mode _before_ load a level @@ -1423,28 +1367,27 @@ void D_SRB2Main(void) G_LoadGameData(); #if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) - VID_PrepareModeList(); // Regenerate Modelist according to cv_fullscreen + // Under SDL2, we just use the windowed modes list, and scale in windowed fullscreen. + allow_fullscreen = true; #endif // set user default mode or mode set at cmdline SCR_CheckDefaultMode(); - // Lactozilla: Does the render mode need to change? - if ((setrenderneeded != 0) && (setrenderneeded != rendermode)) + // Check if the render mode needs to change. + if (setrenderneeded) { CONS_Printf(M_GetText("Switching the renderer...\n")); - Z_PreparePatchFlush(); - // set needpatchflush / needpatchrecache true for D_CheckRendererState - needpatchflush = true; - needpatchrecache = true; + // Switch the renderer in the interface + if (VID_CheckRenderer()) + con_refresh = true; // Allow explicit screen refresh again // Set cv_renderer to the new render mode - VID_CheckRenderer(); - SCR_ChangeRendererCVars(rendermode); - - // check the renderer's state - D_CheckRendererState(); + CV_StealthSetValue(&cv_renderer, rendermode); +#ifdef HWRENDER + CV_StealthSetValue(&cv_newrenderer, rendermode); +#endif } wipegamestate = gamestate; diff --git a/src/dehacked.c b/src/dehacked.c index 6276854f5..5ae67658a 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1041,11 +1041,6 @@ static void readspriteinfo(MYFILE *f, INT32 num, boolean sprite2) spriteinfo_t *info = Z_Calloc(sizeof(spriteinfo_t), PU_STATIC, NULL); info->available = true; -#ifdef ROTSPRITE - if ((sprites != NULL) && (!sprite2)) - R_FreeSingleRotSprite(&sprites[num]); -#endif - do { lastline = f->curpos; @@ -1164,19 +1159,18 @@ static void readspriteinfo(MYFILE *f, INT32 num, boolean sprite2) if (sprite2) { INT32 i; + if (!foundskins) { deh_warning("Sprite2 %s: no skins specified", spr2names[num]); break; } + for (i = 0; i < foundskins; i++) { size_t skinnum = skinnumbers[i]; skin_t *skin = &skins[skinnum]; spriteinfo_t *sprinfo = skin->sprinfo; -#ifdef ROTSPRITE - R_FreeSkinRotSprite(skinnum); -#endif M_Memcpy(&sprinfo[num], info, sizeof(spriteinfo_t)); } } @@ -9951,6 +9945,11 @@ struct { {"ANGLE_337h",ANGLE_337h}, {"ANGLE_MAX",ANGLE_MAX}, + // Sprite rotation + {"ROTANGLES",ROTANGLES}, + {"ROTANGDIFF",ROTANGDIFF}, + {"FEETADJUST",FEETADJUST}, + // P_Chase directions (dirtype_t) {"DI_NODIR",DI_NODIR}, {"DI_EAST",DI_EAST}, @@ -9963,7 +9962,7 @@ struct { {"DI_SOUTHEAST",DI_SOUTHEAST}, {"NUMDIRS",NUMDIRS}, - // Sprite rotation axis (rotaxis_t) + // Sprite rotation axes (rotaxis_t) {"ROTAXIS_X",ROTAXIS_X}, {"ROTAXIS_Y",ROTAXIS_Y}, {"ROTAXIS_Z",ROTAXIS_Z}, diff --git a/src/djgppdos/vid_vesa.c b/src/djgppdos/vid_vesa.c index 61ed18e4b..519ab4400 100644 --- a/src/djgppdos/vid_vesa.c +++ b/src/djgppdos/vid_vesa.c @@ -378,11 +378,13 @@ INT32 VID_SetMode (INT32 modenum) //, UINT8 *palette) return 1; } -void VID_CheckRenderer(void) {} +boolean VID_CheckRenderer(void) +{ + return false; +} + void VID_CheckGLLoaded(rendermode_t oldrender) {} - - // converts a segm:offs 32bit pair to a 32bit flat ptr #if 0 void *VID_ExtraFarToLinear (void *ptr) @@ -739,7 +741,7 @@ static INT32 VGA_InitMode (viddef_t *lvid, vmode_t *currentmodep) // here it is the standard VGA 64k window, not an LFB // (you could have 320x200x256c with LFB in the vesa modes) lvid->direct = (UINT8 *) real2ptr (0xa0000); - lvid->u.numpages = 1; + lvid->numpages = 1; lvid->bpp = currentmodep->bytesperpixel; return 1; @@ -773,7 +775,7 @@ INT32 VID_VesaInitMode (viddef_t *lvid, vmode_t *currentmodep) #endif //added:20-01-98:no page flipping now... TO DO!!! - lvid->u.numpages = 1; + lvid->numpages = 1; // clean up any old vid buffer lying around, alloc new if needed if (!VID_FreeAndAllocVidbuffer (lvid)) diff --git a/src/doomdef.h b/src/doomdef.h index fab83d38c..65cef9c7c 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -629,13 +629,11 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// \note Required for proper collision with moving sloped surfaces that have sector specials on them. #define SECTORSPECIALSAFTERTHINK -/// Cache patches in Lua in a way that renderer switching will work flawlessly. -//#define LUA_PATCH_SAFETY - /// Sprite rotation #define ROTSPRITE #define ROTANGLES 72 // Needs to be a divisor of 360 (45, 60, 90, 120...) #define ROTANGDIFF (360 / ROTANGLES) +#define ROTSPRITE_RENDER_PATCHES /// PNG support #ifndef HAVE_PNG diff --git a/src/dummy/i_video.c b/src/dummy/i_video.c index 56ead3672..5c54c1e71 100644 --- a/src/dummy/i_video.c +++ b/src/dummy/i_video.c @@ -3,6 +3,7 @@ #include "../i_video.h" rendermode_t rendermode = render_none; +rendermode_t chosenrendermode = render_none; boolean highcolor = false; @@ -32,15 +33,17 @@ INT32 VID_GetModeForSize(INT32 w, INT32 h) return 0; } -void VID_PrepareModeList(void){} - INT32 VID_SetMode(INT32 modenum) { (void)modenum; return 0; } -void VID_CheckRenderer(void) {} +boolean VID_CheckRenderer(void) +{ + return false; +} + void VID_CheckGLLoaded(rendermode_t oldrender) {} const char *VID_GetModeName(INT32 modenum) diff --git a/src/f_finale.c b/src/f_finale.c index 8d39a7533..dd77829bd 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -100,21 +100,21 @@ INT16 curttloop; UINT16 curtttics; // ttmode old -static patch_t *ttbanner; // white banner with "robo blast" and "2" -static patch_t *ttwing; // wing background -static patch_t *ttsonic; // "SONIC" -static patch_t *ttswave1; // Title Sonics -static patch_t *ttswave2; -static patch_t *ttswip1; -static patch_t *ttsprep1; -static patch_t *ttsprep2; -static patch_t *ttspop1; -static patch_t *ttspop2; -static patch_t *ttspop3; -static patch_t *ttspop4; -static patch_t *ttspop5; -static patch_t *ttspop6; -static patch_t *ttspop7; +static patch_t **ttbanner; // white banner with "robo blast" and "2" +static patch_t **ttwing; // wing background +static patch_t **ttsonic; // "SONIC" +static patch_t **ttswave1; // Title Sonics +static patch_t **ttswave2; +static patch_t **ttswip1; +static patch_t **ttsprep1; +static patch_t **ttsprep2; +static patch_t **ttspop1; +static patch_t **ttspop2; +static patch_t **ttspop3; +static patch_t **ttspop4; +static patch_t **ttspop5; +static patch_t **ttspop6; +static patch_t **ttspop7; // ttmode alacroix static SINT8 testttscale = 0; @@ -122,51 +122,51 @@ static SINT8 activettscale = 0; boolean ttavailable[6]; boolean ttloaded[6]; -static patch_t *ttribb[6][TTMAX_ALACROIX]; -static patch_t *ttsont[6][TTMAX_ALACROIX]; -static patch_t *ttrobo[6][TTMAX_ALACROIX]; -static patch_t *tttwot[6][TTMAX_ALACROIX]; -static patch_t *ttembl[6][TTMAX_ALACROIX]; -static patch_t *ttrbtx[6][TTMAX_ALACROIX]; -static patch_t *ttsoib[6][TTMAX_ALACROIX]; -static patch_t *ttsoif[6][TTMAX_ALACROIX]; -static patch_t *ttsoba[6][TTMAX_ALACROIX]; -static patch_t *ttsobk[6][TTMAX_ALACROIX]; -static patch_t *ttsodh[6][TTMAX_ALACROIX]; -static patch_t *tttaib[6][TTMAX_ALACROIX]; -static patch_t *tttaif[6][TTMAX_ALACROIX]; -static patch_t *tttaba[6][TTMAX_ALACROIX]; -static patch_t *tttabk[6][TTMAX_ALACROIX]; -static patch_t *tttabt[6][TTMAX_ALACROIX]; -static patch_t *tttaft[6][TTMAX_ALACROIX]; -static patch_t *ttknib[6][TTMAX_ALACROIX]; -static patch_t *ttknif[6][TTMAX_ALACROIX]; -static patch_t *ttknba[6][TTMAX_ALACROIX]; -static patch_t *ttknbk[6][TTMAX_ALACROIX]; -static patch_t *ttkndh[6][TTMAX_ALACROIX]; +static patch_t **ttribb[6][TTMAX_ALACROIX]; +static patch_t **ttsont[6][TTMAX_ALACROIX]; +static patch_t **ttrobo[6][TTMAX_ALACROIX]; +static patch_t **tttwot[6][TTMAX_ALACROIX]; +static patch_t **ttembl[6][TTMAX_ALACROIX]; +static patch_t **ttrbtx[6][TTMAX_ALACROIX]; +static patch_t **ttsoib[6][TTMAX_ALACROIX]; +static patch_t **ttsoif[6][TTMAX_ALACROIX]; +static patch_t **ttsoba[6][TTMAX_ALACROIX]; +static patch_t **ttsobk[6][TTMAX_ALACROIX]; +static patch_t **ttsodh[6][TTMAX_ALACROIX]; +static patch_t **tttaib[6][TTMAX_ALACROIX]; +static patch_t **tttaif[6][TTMAX_ALACROIX]; +static patch_t **tttaba[6][TTMAX_ALACROIX]; +static patch_t **tttabk[6][TTMAX_ALACROIX]; +static patch_t **tttabt[6][TTMAX_ALACROIX]; +static patch_t **tttaft[6][TTMAX_ALACROIX]; +static patch_t **ttknib[6][TTMAX_ALACROIX]; +static patch_t **ttknif[6][TTMAX_ALACROIX]; +static patch_t **ttknba[6][TTMAX_ALACROIX]; +static patch_t **ttknbk[6][TTMAX_ALACROIX]; +static patch_t **ttkndh[6][TTMAX_ALACROIX]; -#define TTEMBL (ttembl[activettscale-1]) -#define TTRIBB (ttribb[activettscale-1]) -#define TTSONT (ttsont[activettscale-1]) -#define TTROBO (ttrobo[activettscale-1]) -#define TTTWOT (tttwot[activettscale-1]) -#define TTRBTX (ttrbtx[activettscale-1]) -#define TTSOIB (ttsoib[activettscale-1]) -#define TTSOIF (ttsoif[activettscale-1]) -#define TTSOBA (ttsoba[activettscale-1]) -#define TTSOBK (ttsobk[activettscale-1]) -#define TTSODH (ttsodh[activettscale-1]) -#define TTTAIB (tttaib[activettscale-1]) -#define TTTAIF (tttaif[activettscale-1]) -#define TTTABA (tttaba[activettscale-1]) -#define TTTABK (tttabk[activettscale-1]) -#define TTTABT (tttabt[activettscale-1]) -#define TTTAFT (tttaft[activettscale-1]) -#define TTKNIB (ttknib[activettscale-1]) -#define TTKNIF (ttknif[activettscale-1]) -#define TTKNBA (ttknba[activettscale-1]) -#define TTKNBK (ttknbk[activettscale-1]) -#define TTKNDH (ttkndh[activettscale-1]) +#define TTEMBL *(ttembl[activettscale-1]) +#define TTRIBB *(ttribb[activettscale-1]) +#define TTSONT *(ttsont[activettscale-1]) +#define TTROBO *(ttrobo[activettscale-1]) +#define TTTWOT *(tttwot[activettscale-1]) +#define TTRBTX *(ttrbtx[activettscale-1]) +#define TTSOIB *(ttsoib[activettscale-1]) +#define TTSOIF *(ttsoif[activettscale-1]) +#define TTSOBA *(ttsoba[activettscale-1]) +#define TTSOBK *(ttsobk[activettscale-1]) +#define TTSODH *(ttsodh[activettscale-1]) +#define TTTAIB *(tttaib[activettscale-1]) +#define TTTAIF *(tttaif[activettscale-1]) +#define TTTABA *(tttaba[activettscale-1]) +#define TTTABK *(tttabk[activettscale-1]) +#define TTTABT *(tttabt[activettscale-1]) +#define TTTAFT *(tttaft[activettscale-1]) +#define TTKNIB *(ttknib[activettscale-1]) +#define TTKNIF *(ttknif[activettscale-1]) +#define TTKNBA *(ttknba[activettscale-1]) +#define TTKNBK *(ttknbk[activettscale-1]) +#define TTKNDH *(ttkndh[activettscale-1]) static boolean sonic_blink = false; static boolean sonic_blink_twice = false; @@ -185,18 +185,18 @@ static INT32 knux_idle_start = 0; static INT32 knux_idle_end = 0; // ttmode user -static patch_t *ttuser[TTMAX_USER]; +static patch_t **ttuser[TTMAX_USER]; static INT32 ttuser_count = 0; static boolean goodending; -static patch_t *endbrdr[2]; // border - blue, white, pink - where have i seen those colours before? -static patch_t *endbgsp[3]; // nebula, sun, planet -static patch_t *endegrk[2]; // eggrock - replaced midway through good ending -static patch_t *endfwrk[3]; // firework - replaced with skin when good ending -static patch_t *endspkl[3]; // sparkle -static patch_t *endglow[2]; // glow aura - replaced with black rock's midway through good ending -static patch_t *endxpld[4]; // mini explosion -static patch_t *endescp[5]; // escape pod + flame +static patch_t **endbrdr[2]; // border - blue, white, pink - where have i seen those colours before? +static patch_t **endbgsp[3]; // nebula, sun, planet +static patch_t **endegrk[2]; // eggrock - replaced midway through good ending +static patch_t **endfwrk[3]; // firework - replaced with skin when good ending +static patch_t **endspkl[3]; // sparkle +static patch_t **endglow[2]; // glow aura - replaced with black rock's midway through good ending +static patch_t **endxpld[4]; // mini explosion +static patch_t **endescp[5]; // escape pod + flame static INT32 sparkloffs[3][2]; // eggrock explosions/blackrock sparkles static INT32 sparklloop; @@ -1772,32 +1772,32 @@ void F_GameEvaluationTicker(void) static void F_CacheEnding(void) { - endbrdr[1] = W_CachePatchName("ENDBRDR1", PU_PATCH); + endbrdr[1] = (patch_t **)W_GetPatchPointerFromName("ENDBRDR1", PU_PATCH); - endegrk[0] = W_CachePatchName("ENDEGRK0", PU_PATCH); - endegrk[1] = W_CachePatchName("ENDEGRK1", PU_PATCH); + endegrk[0] = (patch_t **)W_GetPatchPointerFromName("ENDEGRK0", PU_PATCH); + endegrk[1] = (patch_t **)W_GetPatchPointerFromName("ENDEGRK1", PU_PATCH); - endglow[0] = W_CachePatchName("ENDGLOW0", PU_PATCH); - endglow[1] = W_CachePatchName("ENDGLOW1", PU_PATCH); + endglow[0] = (patch_t **)W_GetPatchPointerFromName("ENDGLOW0", PU_PATCH); + endglow[1] = (patch_t **)W_GetPatchPointerFromName("ENDGLOW1", PU_PATCH); - endbgsp[0] = W_CachePatchName("ENDBGSP0", PU_PATCH); - endbgsp[1] = W_CachePatchName("ENDBGSP1", PU_PATCH); - endbgsp[2] = W_CachePatchName("ENDBGSP2", PU_PATCH); + endbgsp[0] = (patch_t **)W_GetPatchPointerFromName("ENDBGSP0", PU_PATCH); + endbgsp[1] = (patch_t **)W_GetPatchPointerFromName("ENDBGSP1", PU_PATCH); + endbgsp[2] = (patch_t **)W_GetPatchPointerFromName("ENDBGSP2", PU_PATCH); - endspkl[0] = W_CachePatchName("ENDSPKL0", PU_PATCH); - endspkl[1] = W_CachePatchName("ENDSPKL1", PU_PATCH); - endspkl[2] = W_CachePatchName("ENDSPKL2", PU_PATCH); + endspkl[0] = (patch_t **)W_GetPatchPointerFromName("ENDSPKL0", PU_PATCH); + endspkl[1] = (patch_t **)W_GetPatchPointerFromName("ENDSPKL1", PU_PATCH); + endspkl[2] = (patch_t **)W_GetPatchPointerFromName("ENDSPKL2", PU_PATCH); - endxpld[0] = W_CachePatchName("ENDXPLD0", PU_PATCH); - endxpld[1] = W_CachePatchName("ENDXPLD1", PU_PATCH); - endxpld[2] = W_CachePatchName("ENDXPLD2", PU_PATCH); - endxpld[3] = W_CachePatchName("ENDXPLD3", PU_PATCH); + endxpld[0] = (patch_t **)W_GetPatchPointerFromName("ENDXPLD0", PU_PATCH); + endxpld[1] = (patch_t **)W_GetPatchPointerFromName("ENDXPLD1", PU_PATCH); + endxpld[2] = (patch_t **)W_GetPatchPointerFromName("ENDXPLD2", PU_PATCH); + endxpld[3] = (patch_t **)W_GetPatchPointerFromName("ENDXPLD3", PU_PATCH); - endescp[0] = W_CachePatchName("ENDESCP0", PU_PATCH); - endescp[1] = W_CachePatchName("ENDESCP1", PU_PATCH); - endescp[2] = W_CachePatchName("ENDESCP2", PU_PATCH); - endescp[3] = W_CachePatchName("ENDESCP3", PU_PATCH); - endescp[4] = W_CachePatchName("ENDESCP4", PU_PATCH); + endescp[0] = (patch_t **)W_GetPatchPointerFromName("ENDESCP0", PU_PATCH); + endescp[1] = (patch_t **)W_GetPatchPointerFromName("ENDESCP1", PU_PATCH); + endescp[2] = (patch_t **)W_GetPatchPointerFromName("ENDESCP2", PU_PATCH); + endescp[3] = (patch_t **)W_GetPatchPointerFromName("ENDESCP3", PU_PATCH); + endescp[4] = (patch_t **)W_GetPatchPointerFromName("ENDESCP4", PU_PATCH); // so we only need to check once if ((goodending = ALL7EMERALDS(emeralds))) @@ -1810,41 +1810,41 @@ static void F_CacheEnding(void) sprdef = &skins[skinnum].sprites[SPR2_XTRA]; // character head, skin specific sprframe = &sprdef->spriteframes[XTRA_ENDING]; - endfwrk[0] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); + endfwrk[0] = (patch_t **)W_GetPatchPointer(sprframe->lumppat[0], PU_PATCH); sprframe = &sprdef->spriteframes[XTRA_ENDING+1]; - endfwrk[1] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); + endfwrk[1] = (patch_t **)W_GetPatchPointer(sprframe->lumppat[0], PU_PATCH); sprframe = &sprdef->spriteframes[XTRA_ENDING+2]; - endfwrk[2] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); + endfwrk[2] = (patch_t **)W_GetPatchPointer(sprframe->lumppat[0], PU_PATCH); } else // Show a star if your character doesn't have an ending firework display. (Basically the MISSINGs for this) { - endfwrk[0] = W_CachePatchName("ENDFWRK3", PU_PATCH); - endfwrk[1] = W_CachePatchName("ENDFWRK4", PU_PATCH); - endfwrk[2] = W_CachePatchName("ENDFWRK5", PU_PATCH); + endfwrk[0] = (patch_t **)W_GetPatchPointerFromName("ENDFWRK3", PU_PATCH); + endfwrk[1] = (patch_t **)W_GetPatchPointerFromName("ENDFWRK4", PU_PATCH); + endfwrk[2] = (patch_t **)W_GetPatchPointerFromName("ENDFWRK5", PU_PATCH); } - endbrdr[0] = W_CachePatchName("ENDBRDR2", PU_PATCH); + endbrdr[0] = (patch_t **)W_GetPatchPointerFromName("ENDBRDR2", PU_PATCH); } else { // eggman, skin nonspecific - endfwrk[0] = W_CachePatchName("ENDFWRK0", PU_PATCH); - endfwrk[1] = W_CachePatchName("ENDFWRK1", PU_PATCH); - endfwrk[2] = W_CachePatchName("ENDFWRK2", PU_PATCH); + endfwrk[0] = (patch_t **)W_GetPatchPointerFromName("ENDFWRK0", PU_PATCH); + endfwrk[1] = (patch_t **)W_GetPatchPointerFromName("ENDFWRK1", PU_PATCH); + endfwrk[2] = (patch_t **)W_GetPatchPointerFromName("ENDFWRK2", PU_PATCH); - endbrdr[0] = W_CachePatchName("ENDBRDR0", PU_LEVEL); + endbrdr[0] = (patch_t **)W_GetPatchPointerFromName("ENDBRDR0", PU_LEVEL); } } static void F_CacheGoodEnding(void) { - endegrk[0] = W_CachePatchName("ENDEGRK2", PU_PATCH); - endegrk[1] = W_CachePatchName("ENDEGRK3", PU_PATCH); + endegrk[0] = (patch_t **)W_GetPatchPointerFromName("ENDEGRK2", PU_PATCH); + endegrk[1] = (patch_t **)W_GetPatchPointerFromName("ENDEGRK3", PU_PATCH); - endglow[0] = W_CachePatchName("ENDGLOW2", PU_PATCH); - endglow[1] = W_CachePatchName("ENDGLOW3", PU_PATCH); + endglow[0] = (patch_t **)W_GetPatchPointerFromName("ENDGLOW2", PU_PATCH); + endglow[1] = (patch_t **)W_GetPatchPointerFromName("ENDGLOW3", PU_PATCH); - endxpld[0] = W_CachePatchName("ENDEGRK4", PU_PATCH); + endxpld[0] = (patch_t **)W_GetPatchPointerFromName("ENDEGRK4", PU_PATCH); } void F_StartEnding(void) @@ -1901,13 +1901,6 @@ void F_EndingDrawer(void) INT32 x, y, i, j, parallaxticker; patch_t *rockpat; - if (needpatchrecache) - { - F_CacheEnding(); - if (goodending && finalecount >= INFLECTIONPOINT) // time to swap some assets - F_CacheGoodEnding(); - } - if (!goodending || finalecount < INFLECTIONPOINT) rockpat = W_CachePatchName("ROID0000", PU_PATCH); else @@ -1934,25 +1927,25 @@ void F_EndingDrawer(void) if (trans < 0) { trans = -trans; - V_DrawScaledPatch(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, 0, endbrdr[0]); + V_DrawScaledPatch(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, 0, *endbrdr[0]); } - V_DrawScaledPatch(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, trans< -19) { INT32 trans = (-parallaxticker)>>1; @@ -1977,7 +1970,7 @@ void F_EndingDrawer(void) trans = 0; V_DrawFixedPatch((200< 0) // gunchedrock @@ -2003,21 +1996,21 @@ void F_EndingDrawer(void) y <<= 1; // center detritrus - V_DrawFixedPatch(i-x, j-y, FRACUNIT, 0, endegrk[0], colormap); + V_DrawFixedPatch(i-x, j-y, FRACUNIT, 0, *endegrk[0], colormap); if (trans < 10) - V_DrawFixedPatch(i-x, j-y, FRACUNIT, trans< INFLECTIONPOINT) @@ -2105,7 +2098,7 @@ void F_EndingDrawer(void) if ((-parallaxticker/2) < -5) colormap[1] = R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE); - V_DrawFixedPatch(x, y, scale, 0, endegrk[0], colormap[1]); + V_DrawFixedPatch(x, y, scale, 0, *endegrk[0], colormap[1]); if ((-parallaxticker/2) < 5) { @@ -2113,7 +2106,7 @@ void F_EndingDrawer(void) if (trans < 0) trans = -trans; if (trans < 10) - V_DrawFixedPatch(x, y, scale, trans< INFLECTIONPOINT && finalecount < INFLECTIONPOINT+10) - V_DrawScaledPatch(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, (finalecount-INFLECTIONPOINT)< 0) - F_UnloadAlacroixGraphics(oldttscale); - } + // We have a new ttscale, so load gfx + if(oldttscale > 0) + F_UnloadAlacroixGraphics(oldttscale); testttscale = newttscale; @@ -2750,9 +2738,6 @@ void F_TitleScreenDrawer(void) if (modeattacking) return; // We likely came here from retrying. Don't do a damn thing. - if (needpatchrecache && (curttmode != TTMODE_ALACROIX)) - F_CacheTitleScreen(); - // Draw that sky! if (curbgcolor >= 0) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor); @@ -2776,42 +2761,42 @@ void F_TitleScreenDrawer(void) { case TTMODE_OLD: case TTMODE_NONE: - V_DrawSciencePatch(30<= 41 && finalecount <= 44) - V_DrawSciencePatch(109<= 45 && finalecount <= 48) - V_DrawSciencePatch(108<= 49 && finalecount <= 52) - V_DrawSciencePatch(107<= 53 && finalecount <= 56) - V_DrawSciencePatch(106<patches; i < texture->patchcount; i++, patch++) { - boolean dealloc = true; size_t lumplength = W_LumpLengthPwad(patch->wad, patch->lump); pdata = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE); realpatch = (patch_t *)pdata; @@ -517,15 +516,9 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex) realpatch = R_FlatToPatch(pdata, texture->width, texture->height, 0, 0, NULL, false); else #endif - { (void)lumplength; - dealloc = false; - } HWR_DrawTexturePatchInCache(&grtex->mipmap, blockwidth, blockheight, texture, patch, realpatch); - - if (dealloc) - Z_Unlock(realpatch); } //Hurdler: not efficient at all but I don't remember exactly how HWR_DrawPatchInCache works :( if (format2bpp(grtex->mipmap.format)==4) @@ -601,6 +594,7 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm static size_t gl_numtextures = 0; // Texture count static GLMapTexture_t *gl_textures; // For all textures static GLMapTexture_t *gl_flats; // For all (texture) flats, as normal flats don't need to be cached +boolean gl_leveltexturesloaded = false; void HWR_InitTextureCache(void) { @@ -663,7 +657,17 @@ void HWR_FreeMipmapCache(void) // Alam: free the Z_Blocks before freeing it's users // free all patch colormaps after each level: must be done after ClearMipMapCache! for (i = 0; i < numwadfiles; i++) - M_AATreeIterate(wadfiles[i]->hwrcache, FreeMipmapColormap); + { + M_AATreeIterate(Patch_GetRendererBaseSubTree(i, render_opengl), FreeMipmapColormap); + +#ifdef ROTSPRITE + // free non-flipped rotated subtree + M_AATreeIterate(Patch_GetRendererRotatedSubTree(i, render_opengl, false), FreeMipmapColormap); + + // free flipped rotated subtree + M_AATreeIterate(Patch_GetRendererRotatedSubTree(i, render_opengl, true), FreeMipmapColormap); +#endif + } } void HWR_FreeTextureCache(void) @@ -680,6 +684,7 @@ void HWR_FreeTextureCache(void) gl_textures = NULL; gl_flats = NULL; gl_numtextures = 0; + gl_leveltexturesloaded = false; } void HWR_LoadTextures(size_t pnumtextures) @@ -696,6 +701,8 @@ void HWR_LoadTextures(size_t pnumtextures) // should never ever happen (right?!) if ((gl_textures == NULL) || (gl_flats == NULL)) I_Error("HWR_LoadTextures: ran out of memory for OpenGL textures. Sad!"); + + gl_leveltexturesloaded = true; } void HWR_SetPalette(RGBA_t *palette) @@ -872,15 +879,18 @@ static void HWR_LoadMappedPatch(GLMipmap_t *grmip, GLPatch_t *gpatch) { if (!grmip->downloaded && !grmip->data) { - patch_t *patch = gpatch->rawpatch; - if (!patch) - patch = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC); - HWR_MakePatch(patch, gpatch, grmip, true); + patch_t *lumppatch = NULL; - // You can't free rawpatch for some reason? - // (Obviously I can't, sprite rotation needs that...) - if (!gpatch->rawpatch) - Z_Free(patch); + if (gpatch->patch) + HWR_MakePatch(gpatch->patch, gpatch, grmip, true); + else + { + lumppatch = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC); + HWR_MakePatch(lumppatch, gpatch, grmip, true); + } + + if (lumppatch) + Z_Free(lumppatch); } // If hardware does not have the texture, then call pfnSetTexture to upload it @@ -898,20 +908,25 @@ static void HWR_LoadMappedPatch(GLMipmap_t *grmip, GLPatch_t *gpatch) // -----------------+ void HWR_GetPatch(GLPatch_t *gpatch) { - // is it in hardware cache + // is it in hardware cache? if (!gpatch->mipmap->downloaded && !gpatch->mipmap->data) { // load the software patch, PU_STATIC or the Z_Malloc for hardware patch will // flush the software patch before the conversion! oh yeah I suffered - patch_t *ptr = gpatch->rawpatch; - if (!ptr) - ptr = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC); - HWR_MakePatch(ptr, gpatch, gpatch->mipmap, true); + patch_t *lumppatch = NULL; + + if (gpatch->patch) + HWR_MakePatch(gpatch->patch, gpatch, gpatch->mipmap, true); + else + { + lumppatch = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC); + HWR_MakePatch(lumppatch, gpatch, gpatch->mipmap, true); + } // this is inefficient.. but the hardware patch in heap is purgeable so it should // not fragment memory, and besides the REAL cache here is the hardware memory - if (!gpatch->rawpatch) - Z_Free(ptr); + if (lumppatch) + Z_Free(lumppatch); } // If hardware does not have the texture, then call pfnSetTexture to upload it @@ -1096,7 +1111,6 @@ GLPatch_t *HWR_GetPic(lumpnum_t lumpnum) pic, format2bpp(grpatch->mipmap->format)); - Z_Unlock(pic); Z_ChangeTag(block, PU_HWRCACHE_UNLOCKED); grpatch->mipmap->flags = 0; @@ -1108,18 +1122,17 @@ GLPatch_t *HWR_GetPic(lumpnum_t lumpnum) return grpatch; } -GLPatch_t *HWR_GetCachedGLPatchPwad(UINT16 wadnum, UINT16 lumpnum) +GLPatch_t *HWR_GetCachedGLPatchPwad(UINT16 wadnum, UINT16 lumpnum, void *hwrcache) { - aatree_t *hwrcache = wadfiles[wadnum]->hwrcache; GLPatch_t *grpatch; - if (!(grpatch = M_AATreeGet(hwrcache, lumpnum))) + if (!(grpatch = M_AATreeGet((aatree_t *)hwrcache, lumpnum))) { grpatch = Z_Calloc(sizeof(GLPatch_t), PU_HWRPATCHINFO, NULL); grpatch->wadnum = wadnum; grpatch->lumpnum = lumpnum; grpatch->mipmap = Z_Calloc(sizeof(GLMipmap_t), PU_HWRPATCHINFO, NULL); - M_AATreeSet(hwrcache, lumpnum, grpatch); + M_AATreeSet((aatree_t *)hwrcache, lumpnum, grpatch); } return grpatch; @@ -1127,7 +1140,8 @@ GLPatch_t *HWR_GetCachedGLPatchPwad(UINT16 wadnum, UINT16 lumpnum) GLPatch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum) { - return HWR_GetCachedGLPatchPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum)); + UINT16 wad = WADFILENUM(lumpnum); + return HWR_GetCachedGLPatchPwad(wad, LUMPNUM(lumpnum), Patch_GetRendererBaseSubTree(wad, render_opengl)); } // Need to do this because they aren't powers of 2 diff --git a/src/hardware/hw_data.h b/src/hardware/hw_data.h index e5477d729..e86fba36a 100644 --- a/src/hardware/hw_data.h +++ b/src/hardware/hw_data.h @@ -89,7 +89,7 @@ struct GLPatch_s float max_s,max_t; UINT16 wadnum; // the software patch lump num for when the hardware patch UINT16 lumpnum; // was flushed, and we need to re-create it - void *rawpatch; // :^) + void *patch; GLMipmap_t *mipmap; } ATTRPACK; typedef struct GLPatch_s GLPatch_t; diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index 6ede8448b..5899e6325 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -62,7 +62,10 @@ typedef struct typedef struct gl_vissprite_s { float x1, x2; + float z1, z2; float tz, ty; + float originx, originy, originz; + angle_t angle; float tracertz; // for MF2_LINKDRAW sprites, this contains tracer's tz for use in sorting //lumpnum_t patchlumpnum; GLPatch_t *gpatch; @@ -74,7 +77,10 @@ typedef struct gl_vissprite_s //Hurdler: 25/04/2000: now support colormap in hardware mode UINT8 *colormap; INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing - float z1, z2; +#ifdef ROTSPRITE + angle_t rollangle; + float pivotx, pivoty; +#endif } gl_vissprite_t; // -------- @@ -102,10 +108,12 @@ void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap); void HWR_UnlockCachedPatch(GLPatch_t *gpatch); GLPatch_t *HWR_GetPic(lumpnum_t lumpnum); void HWR_SetPalette(RGBA_t *palette); -GLPatch_t *HWR_GetCachedGLPatchPwad(UINT16 wad, UINT16 lump); +GLPatch_t *HWR_GetCachedGLPatchPwad(UINT16 wadnum, UINT16 lumpnum, void *hwrcache); GLPatch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum); void HWR_GetFadeMask(lumpnum_t fademasklumpnum); +extern boolean gl_leveltexturesloaded; + // -------- // hw_draw.c // -------- diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 0d7404c77..fdeb8f5d6 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -26,6 +26,7 @@ #include "../p_setup.h" #include "../r_local.h" #include "../r_patch.h" +#include "../r_rotsprite.h" #include "../r_bsp.h" #include "../d_clisrv.h" #include "../w_wad.h" @@ -3701,6 +3702,87 @@ static void HWR_RotateSpritePolyToAim(gl_vissprite_t *spr, FOutVector *wallVerts } } +#if defined(ROTSPRITE) && !defined(ROTSPRITE_RENDER_PATCHES) +static void HWR_ApplyPitchRollYawToSprite(FOutVector *wallVerts, float pitch, float roll, float yaw) +{ + size_t i; + + float yawcos = cos(yaw); + float yawsin = sin(yaw); + float pitchcos = cos(pitch); + float pitchsin = sin(pitch); + float rollcos = cos(roll); + float rollsin = sin(roll); + + float xx = yawcos * pitchcos; + float xy = (yawcos * pitchsin * rollsin) - (yawsin * rollcos); + float xz = (yawcos * pitchsin * rollcos) + (yawsin * rollsin); + + float yx = yawsin * pitchcos; + float yy = (yawsin * pitchsin * rollsin) + (yawcos * rollcos); + float yz = (yawsin * pitchsin * rollcos) - (yawcos * rollsin); + + float zx = -pitchsin; + float zy = pitchcos * rollsin; + float zz = pitchcos * rollcos; + + for (i = 0; i < 4; i++) + { + float x = wallVerts[i].x; + float y = wallVerts[i].y; + float z = wallVerts[i].z; + wallVerts[i].x = xx*x + xy*y + xz*z; + wallVerts[i].y = yx*x + yy*y + yz*z; + wallVerts[i].z = zx*x + zy*y + zz*z; + } +} + +static void HWR_RotateSpritePolyToRollAngle(gr_vissprite_t *spr, FOutVector *wallVerts) +{ + INT32 i; + float radians = (M_PIl / 180.0f); + + float cx = (spr->gpatch->leftoffset - spr->pivotx); + float cy = spr->pivoty; + + fixed_t fa = AngleFixed(spr->rollangle); + float rotate = FIXED_TO_FLOAT(fa) * radians; + + // Translate sprite by its pivot + for (i = 0; i < 4; i++) + { + wallVerts[i].x -= cx; + wallVerts[i].y -= cy; + } + + // Apply sprite roll + HWR_ApplyPitchRollYawToSprite(wallVerts, 0.0f, 0.0f, rotate); + + // Translate sprite back + for (i = 0; i < 4; i++) + { + wallVerts[i].x += cx; + wallVerts[i].y += cy; + } + + // Apply sprite angle + fa = AngleFixed(spr->angle - ANGLE_180); + rotate = FIXED_TO_FLOAT(fa) * radians; + HWR_ApplyPitchRollYawToSprite(wallVerts, -rotate, 0.0f, 0.0f); + + // Translate the sprite to its intended position + for (i = 0; i < 4; i++) + { + wallVerts[i].x += spr->originx; + wallVerts[i].z += spr->originy; + } + + // Translate the sprite vertically + for (i = 0; i < 4; i++) + wallVerts[i].y += spr->originz; +} +#endif + static void HWR_SplitSprite(gl_vissprite_t *spr) { float this_scale = 1.0f; @@ -3793,6 +3875,12 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) // Let dispoffset work first since this adjust each vertex HWR_RotateSpritePolyToAim(spr, baseWallVerts, false); +#if defined(ROTSPRITE) && !defined(ROTSPRITE_RENDER_PATCHES) + // Rotate the sprite polygon, then translate it + if (spr->rollangle) + HWR_RotateSpritePolyToRollAngle(spr, baseWallVerts); +#endif + realtop = top = baseWallVerts[3].y; realbot = bot = baseWallVerts[0].y; ttop = baseWallVerts[3].t; @@ -4075,6 +4163,12 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) // Let dispoffset work first since this adjust each vertex HWR_RotateSpritePolyToAim(spr, wallVerts, false); +#if defined(ROTSPRITE) && !defined(ROTSPRITE_RENDER_PATCHES) + // Rotate the sprite polygon, then translate it + if (spr->rollangle) + HWR_RotateSpritePolyToRollAngle(spr, wallVerts); +#endif + // This needs to be AFTER the shadows so that the regular sprites aren't drawn completely black. // sprite lighting by modulating the RGB components /// \todo coloured @@ -4760,9 +4854,15 @@ static void HWR_ProjectSprite(mobj_t *thing) float rightsin, rightcos; float this_scale; float gz, gzt; + float topz, bottomz, originz; spritedef_t *sprdef; spriteframe_t *sprframe; +#ifdef ROTSPRITE spriteinfo_t *sprinfo; +#ifdef ROTSPRITE_RENDER_PATCHES + INT32 rollangle; +#endif +#endif md2_t *md2; size_t lumpoff; unsigned rot; @@ -4776,14 +4876,12 @@ static void HWR_ProjectSprite(mobj_t *thing) INT32 heightsec, phs; const boolean papersprite = (thing->frame & FF_PAPERSPRITE); angle_t mobjangle = (thing->player ? thing->player->drawangle : thing->angle); + angle_t spriteangle; float z1, z2; + GLPatch_t *spr_patch; fixed_t spr_width, spr_height; fixed_t spr_offset, spr_topoffset; -#ifdef ROTSPRITE - patch_t *rotsprite = NULL; - INT32 rollangle = 0; -#endif if (!thing) return; @@ -4832,12 +4930,16 @@ static void HWR_ProjectSprite(mobj_t *thing) if (thing->skin && thing->sprite == SPR_PLAY) { sprdef = &((skin_t *)thing->skin)->sprites[thing->sprite2]; +#ifdef ROTSPRITE sprinfo = &((skin_t *)thing->skin)->sprinfo[thing->sprite2]; +#endif } else { sprdef = &sprites[thing->sprite]; - sprinfo = NULL; +#ifdef ROTSPRITE + sprinfo = &spriteinfo[thing->sprite]; +#endif } if (rot >= sprdef->numframes) @@ -4847,7 +4949,9 @@ static void HWR_ProjectSprite(mobj_t *thing) thing->sprite = states[S_UNKNOWN].sprite; thing->frame = states[S_UNKNOWN].frame; sprdef = &sprites[thing->sprite]; - sprinfo = NULL; +#ifdef ROTSPRITE + sprinfo = &spriteinfo[thing->sprite]; +#endif rot = thing->frame&FF_FRAMEMASK; thing->state->sprite = thing->sprite; thing->state->frame = thing->frame; @@ -4900,40 +5004,44 @@ static void HWR_ProjectSprite(mobj_t *thing) if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES) this_scale = this_scale * FIXED_TO_FLOAT(((skin_t *)thing->skin)->highresscale); + spr_patch = (GLPatch_t *)W_CachePatchNum(sprframe->lumppat[rot], PU_CACHE); spr_width = spritecachedinfo[lumpoff].width; spr_height = spritecachedinfo[lumpoff].height; spr_offset = spritecachedinfo[lumpoff].offset; spr_topoffset = spritecachedinfo[lumpoff].topoffset; -#ifdef ROTSPRITE - if (thing->rollangle) +#if defined(ROTSPRITE) && defined(ROTSPRITE_RENDER_PATCHES) + rollangle = R_GetRollAngle(thing->rollangle); + if (rollangle) { - rollangle = R_GetRollAngle(thing->rollangle); - if (!(sprframe->rotsprite.cached & (1<sprite, (thing->frame & FF_FRAMEMASK), sprinfo, sprframe, rot, flip); - rotsprite = sprframe->rotsprite.patch[rot][rollangle]; - if (rotsprite != NULL) - { - spr_width = SHORT(rotsprite->width) << FRACBITS; - spr_height = SHORT(rotsprite->height) << FRACBITS; - spr_offset = SHORT(rotsprite->leftoffset) << FRACBITS; - spr_topoffset = SHORT(rotsprite->topoffset) << FRACBITS; - // flip -> rotate, not rotate -> flip - flip = 0; - } + spriteframepivot_t *pivot = (sprinfo->available) ? &sprinfo->pivot[(thing->frame & FF_FRAMEMASK)] : NULL; + static rotsprite_vars_t rsvars; + patch_t *rotpatch; + + rsvars.rollangle = rollangle; + rsvars.sprite = true; + rsvars.pivot = pivot; + rsvars.flip = (flip != 0); + + rotpatch = Patch_CacheRotatedForSprite(sprframe->lumppat[rot], PU_LEVEL, rsvars, false); + spr_patch = (GLPatch_t *)rotpatch; + spr_width = SHORT(rotpatch->width) << FRACBITS; + spr_height = SHORT(rotpatch->height) << FRACBITS; + spr_offset = SHORT(rotpatch->leftoffset) << FRACBITS; + spr_topoffset = SHORT(rotpatch->topoffset) << FRACBITS; + + // flip -> rotate, not rotate -> flip + flip = 0; } #endif if (papersprite) - { - rightsin = FIXED_TO_FLOAT(FINESINE((mobjangle)>>ANGLETOFINESHIFT)); - rightcos = FIXED_TO_FLOAT(FINECOSINE((mobjangle)>>ANGLETOFINESHIFT)); - } + spriteangle = mobjangle; else - { - rightsin = FIXED_TO_FLOAT(FINESINE((viewangle + ANGLE_90)>>ANGLETOFINESHIFT)); - rightcos = FIXED_TO_FLOAT(FINECOSINE((viewangle + ANGLE_90)>>ANGLETOFINESHIFT)); - } + spriteangle = (viewangle + ANGLE_90); + + rightsin = FIXED_TO_FLOAT(FINESINE((spriteangle)>>ANGLETOFINESHIFT)); + rightcos = FIXED_TO_FLOAT(FINECOSINE((spriteangle)>>ANGLETOFINESHIFT)); flip = !flip != !hflip; @@ -4948,31 +5056,35 @@ static void HWR_ProjectSprite(mobj_t *thing) x2 = (FIXED_TO_FLOAT(spr_width - spr_offset) * this_scale); } - // test if too close -/* - if (papersprite) + originz = FIXED_TO_FLOAT(thing->z); + +#if defined(ROTSPRITE) && !defined(ROTSPRITE_RENDER_PATCHES) + // Don't transform the sprite if it has a roll angle. + if (thing->rollangle) { - z1 = tz - x1 * angle_scalez; - z2 = tz + x2 * angle_scalez; - - if (max(z1, z2) < ZCLIP_PLANE) - return; + z1 = z2 = 0.0f; + x1 = -x1; + topz = bottomz = 0.0; + } + else +#endif + { + z1 = tr_y + x1 * rightsin; + z2 = tr_y - x2 * rightsin; + x1 = tr_x + x1 * rightcos; + x2 = tr_x - x2 * rightcos; + topz = originz + FIXED_TO_FLOAT(thing->height); + bottomz = originz; } -*/ - - z1 = tr_y + x1 * rightsin; - z2 = tr_y - x2 * rightsin; - x1 = tr_x + x1 * rightcos; - x2 = tr_x - x2 * rightcos; if (vflip) { - gz = FIXED_TO_FLOAT(thing->z+thing->height) - FIXED_TO_FLOAT(spr_topoffset) * this_scale; + gz = topz - FIXED_TO_FLOAT(spr_topoffset) * this_scale; gzt = gz + FIXED_TO_FLOAT(spr_height) * this_scale; } else { - gzt = FIXED_TO_FLOAT(thing->z) + FIXED_TO_FLOAT(spr_topoffset) * this_scale; + gzt = bottomz + FIXED_TO_FLOAT(spr_topoffset) * this_scale; gz = gzt - FIXED_TO_FLOAT(spr_height) * this_scale; } @@ -5031,19 +5143,35 @@ static void HWR_ProjectSprite(mobj_t *thing) vis->x1 = x1; vis->x2 = x2; vis->tz = tz; // Keep tz for the simple sprite sorting that happens + vis->gpatch = spr_patch; vis->tracertz = tracertz; vis->dispoffset = dispoffset; // Monster Iestyn: 23/11/15: HARDWARE SUPPORT AT LAST - //vis->patchlumpnum = sprframe->lumppat[rot]; -#ifdef ROTSPRITE - if (rotsprite) - vis->gpatch = (GLPatch_t *)rotsprite; - else -#endif - vis->gpatch = (GLPatch_t *)W_CachePatchNum(sprframe->lumppat[rot], PU_CACHE); vis->flip = flip; vis->mobj = thing; vis->z1 = z1; vis->z2 = z2; + vis->angle = spriteangle; + vis->originx = tr_x; + vis->originy = tr_y; + vis->originz = originz; + +#if defined(ROTSPRITE) && !defined(ROTSPRITE_RENDER_PATCHES) + if (thing->rollangle) + { + if (sprinfo->available) + { + spriteframepivot_t *pivot = &sprinfo->pivot[thing->frame & FF_FRAMEMASK]; + vis->pivotx = (float)(pivot->x) * this_scale; + vis->pivoty = (float)(pivot->y) * this_scale; + } + else + { + vis->pivotx = (float)(spr_patch->leftoffset) * this_scale; + vis->pivoty = (float)(spr_patch->height / 2) * this_scale; + } + } + vis->rollangle = thing->rollangle; +#endif //Hurdler: 25/04/2000: now support colormap in hardware mode if ((vis->mobj->flags & (MF_ENEMY|MF_BOSS)) && (vis->mobj->flags2 & MF2_FRET) && !(vis->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash" @@ -5173,8 +5301,11 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) vis->z1 = z1; vis->z2 = z2; vis->tz = tz; + vis->angle = 0; + vis->originx = tr_x; + vis->originy = tr_y; + vis->originz = FIXED_TO_FLOAT(thing->z); vis->dispoffset = 0; // Monster Iestyn: 23/11/15: HARDWARE SUPPORT AT LAST - //vis->patchlumpnum = sprframe->lumppat[rot]; vis->gpatch = (GLPatch_t *)W_CachePatchNum(sprframe->lumppat[rot], PU_CACHE); vis->flip = flip; vis->mobj = (mobj_t *)thing; @@ -5182,10 +5313,16 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) vis->colormap = colormaps; // set top/bottom coords - vis->ty = FIXED_TO_FLOAT(thing->z + spritecachedinfo[lumpoff].topoffset); + vis->ty = vis->originz + FIXED_TO_FLOAT(spritecachedinfo[lumpoff].topoffset); vis->precip = true; +#ifdef ROTSPRITE + vis->rollangle = 0; + vis->pivotx = 0.0f; + vis->pivoty = 0.0f; +#endif + // okay... this is a hack, but weather isn't networked, so it should be ok if (!(thing->precipflags & PCF_THUNK)) { @@ -5975,9 +6112,20 @@ void HWR_Startup(void) // -------------------------------------------------------------------------- void HWR_Switch(void) { + // Add session commands + HWR_AddSessionCommands(); + // Set special states from CVARs HWD.pfnSetSpecialState(HWD_SET_TEXTUREFILTERMODE, cv_glfiltermode.value); HWD.pfnSetSpecialState(HWD_SET_TEXTUREANISOTROPICMODE, cv_glanisotropicmode.value); + + // Load textures + if (!gl_leveltexturesloaded) + HWR_LoadTextures(numtextures); + + // Create plane polygons + if (gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction)) + HWR_LoadLevel(); } // -------------------------------------------------------------------------- diff --git a/src/hardware/r_opengl/ogl_win.c b/src/hardware/r_opengl/ogl_win.c index c9bf60144..01ac5798e 100644 --- a/src/hardware/r_opengl/ogl_win.c +++ b/src/hardware/r_opengl/ogl_win.c @@ -240,7 +240,7 @@ int SetupPixelFormat(INT32 WantColorBits, INT32 WantStencilBits, INT32 WantDepth static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode) { LPCSTR renderer; - BOOL WantFullScreen = !(lvid->u.windowed); //(lvid->u.windowed ? 0 : CDS_FULLSCREEN); + BOOL WantFullScreen = !(lvid->windowed); //(lvid->windowed ? 0 : CDS_FULLSCREEN); UNREFERENCED_PARAMETER(pcurrentmode); GL_DBG_Printf ("SetMode(): %dx%d %d bits (%s)\n", diff --git a/src/hu_stuff.c b/src/hu_stuff.c index b61192533..507968f48 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -27,7 +27,7 @@ #include "i_video.h" #include "i_system.h" -#include "st_stuff.h" // ST_HEIGHT +#include "st_stuff.h" #include "r_local.h" #include "keys.h" @@ -82,10 +82,10 @@ static boolean headsupactive = false; boolean hu_showscores; // draw rankings static char hu_tick; -patch_t *rflagico; -patch_t *bflagico; -patch_t *rmatcico; -patch_t *bmatcico; +patch_t **rflagico; +patch_t **bflagico; +patch_t **rmatcico; +patch_t **bmatcico; patch_t *tagico; patch_t *tallminus; patch_t *tallinfin; @@ -2038,9 +2038,6 @@ static void HU_DrawDemoInfo(void) // void HU_Drawer(void) { - if (needpatchrecache) - R_ReloadHUDGraphics(); - #ifndef NONET // draw chat string plus cursor if (chat_on) @@ -2468,9 +2465,9 @@ static void HU_Draw32TeamTabRankings(playersort_t *tab, INT32 whiteplayer) if (gametyperules & GTR_TEAMFLAGS) { if (players[tab[i].num].gotflag & GF_REDFLAG) // Red - V_DrawFixedPatch((x-10)*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, 0, rflagico, 0); + V_DrawFixedPatch((x-10)*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, 0, *rflagico, 0); else if (players[tab[i].num].gotflag & GF_BLUEFLAG) // Blue - V_DrawFixedPatch((x-10)*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, 0, bflagico, 0); + V_DrawFixedPatch((x-10)*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, 0, *bflagico, 0); } // Draw emeralds @@ -2596,9 +2593,9 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) if (gametyperules & GTR_TEAMFLAGS) { if (players[tab[i].num].gotflag & GF_REDFLAG) // Red - V_DrawSmallScaledPatch(x-28, y-4, 0, rflagico); + V_DrawSmallScaledPatch(x-28, y-4, 0, *rflagico); else if (players[tab[i].num].gotflag & GF_BLUEFLAG) // Blue - V_DrawSmallScaledPatch(x-28, y-4, 0, bflagico); + V_DrawSmallScaledPatch(x-28, y-4, 0, *bflagico); } // Draw emeralds diff --git a/src/hu_stuff.h b/src/hu_stuff.h index 63d85f1b8..2e52cb59f 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -87,10 +87,10 @@ extern patch_t *ntb_font[NT_FONTSIZE]; extern patch_t *nto_font[NT_FONTSIZE]; extern patch_t *ttlnum[10]; extern patch_t *emeraldpics[3][8]; -extern patch_t *rflagico; -extern patch_t *bflagico; -extern patch_t *rmatcico; -extern patch_t *bmatcico; +extern patch_t **rflagico; +extern patch_t **bflagico; +extern patch_t **rmatcico; +extern patch_t **bmatcico; extern patch_t *tagico; extern patch_t *tallminus; extern patch_t *tallinfin; diff --git a/src/i_video.h b/src/i_video.h index 98ed7f38a..b9450ec7a 100644 --- a/src/i_video.h +++ b/src/i_video.h @@ -20,26 +20,33 @@ #pragma interface #endif -typedef enum +typedef enum rendermode_e { - /// Software - render_soft = 1, + // No renderer chosen. Used on dedicated mode. + render_none = 0, - /// OpenGL - render_opengl = 2, + // First renderer choice. + // Must start from 1. + render_first = 1, - /// Dedicated - render_none = 3 // for dedicated server + // Main renderer choices. + render_soft = render_first, + render_opengl, + + // Last renderer choice. + render_last, + + // Renderer count. + num_renderers = (render_last - 1), } rendermode_t; /** \brief current render mode */ extern rendermode_t rendermode; -/** \brief OpenGL state - 0 = never loaded, 1 = loaded successfully, -1 = failed loading +/** \brief render mode set by command line arguments */ -extern INT32 vid_opengl_state; +extern rendermode_t chosenrendermode; /** \brief use highcolor modes if true */ @@ -89,9 +96,19 @@ INT32 VID_GetModeForSize(INT32 w, INT32 h); */ INT32 VID_SetMode(INT32 modenum); -/** \brief Checks the render state +/** \brief The VID_GetModeName function + + \param modenum video mode number + + \return name of video mode */ -void VID_CheckRenderer(void); +const char *VID_GetModeName(INT32 modenum); + +/** \brief Checks the render state + + \return true if the renderer changed +*/ +boolean VID_CheckRenderer(void); /** \brief Load OpenGL mode */ @@ -101,16 +118,6 @@ void VID_StartupOpenGL(void); */ void VID_CheckGLLoaded(rendermode_t oldrender); -/** \brief The VID_GetModeName function - - \param modenum video mode number - - \return name of video mode -*/ -const char *VID_GetModeName(INT32 modenum); -void VID_PrepareModeList(void); /// note hack for SDL - - /** \brief can video system do fullscreen */ extern boolean allow_fullscreen; diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 3f62ef890..d9ec32d73 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -19,6 +19,7 @@ #include "r_main.h" #include "r_draw.h" #include "r_things.h" // R_Frame2Char etc +#include "r_rotsprite.h" // R_GetRollAngle #include "m_random.h" #include "s_sound.h" #include "g_game.h" @@ -2434,6 +2435,16 @@ static int lib_rPointInSubsectorOrNil(lua_State *L) return 1; } +#ifdef ROTSPRITE +// R_ROTSPRITE +//////////// +static int lib_rGetRollAngle(lua_State *L) +{ + lua_pushinteger(L, R_GetRollAngle(luaL_checkangle(L, 1))); + return 1; +} +#endif + // R_THINGS //////////// @@ -3489,6 +3500,11 @@ static luaL_Reg lib[] = { {"R_PointInSubsector",lib_rPointInSubsector}, {"R_PointInSubsectorOrNil",lib_rPointInSubsectorOrNil}, +#ifdef ROTSPRITE + // r_rotsprite + {"R_GetRollAngle",lib_rGetRollAngle}, +#endif + // r_things (sprite) {"R_Char2Frame",lib_rChar2Frame}, {"R_Frame2Char",lib_rFrame2Char}, diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 4aa70574b..ede8e7961 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -14,6 +14,7 @@ #include "fastcmp.h" #include "r_defs.h" #include "r_local.h" +#include "r_rotsprite.h" #include "st_stuff.h" // hudinfo[] #include "g_game.h" #include "i_video.h" // rendermode @@ -35,11 +36,6 @@ static UINT8 hud_enabled[(hud_MAX/8)+1]; static UINT8 hudAvailable; // hud hooks field -#ifdef LUA_PATCH_SAFETY -static patchinfo_t *patchinfo, *patchinfohead; -static int numluapatches; -#endif - // must match enum hud in lua_hud.h static const char *const hud_disable_options[] = { "stagetitle", @@ -292,14 +288,9 @@ static int colormap_get(lua_State *L) static int patch_get(lua_State *L) { -#ifdef LUA_PATCH_SAFETY - patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH)); -#else - patchinfo_t *patch = *((patchinfo_t **)luaL_checkudata(L, 1, META_PATCH)); -#endif + patch_t *patch = **((patch_t ***)luaL_checkudata(L, 1, META_PATCH)); enum patch field = luaL_checkoption(L, 2, NULL, patch_opt); - // patches are invalidated when switching renderers if (!patch) { if (field == patch_valid) { lua_pushboolean(L, 0); @@ -403,59 +394,18 @@ static int libd_patchExists(lua_State *L) static int libd_cachePatch(lua_State *L) { -#ifdef LUA_PATCH_SAFETY - int i; - lumpnum_t lumpnum; - patchinfo_t *luapat; - patch_t *realpatch; - - HUDONLY - - luapat = patchinfohead; - lumpnum = W_CheckNumForLongName(luaL_checkstring(L, 1)); - if (lumpnum == LUMPERROR) - lumpnum = W_GetNumForLongName("MISSING"); - - for (i = 0; i < numluapatches; i++) - { - // check if already cached - if (luapat->wadnum == WADFILENUM(lumpnum) && luapat->lumpnum == LUMPNUM(lumpnum)) - { - LUA_PushUserdata(L, luapat, META_PATCH); - return 1; - } - luapat = luapat->next; - if (!luapat) - break; - } - - if (numluapatches > 0) - { - patchinfo->next = Z_Malloc(sizeof(patchinfo_t), PU_STATIC, NULL); - patchinfo = patchinfo->next; - } - else - { - patchinfo = Z_Malloc(sizeof(patchinfo_t), PU_STATIC, NULL); - patchinfohead = patchinfo; - } - - realpatch = W_CachePatchNum(lumpnum, PU_PATCH); - - patchinfo->width = realpatch->width; - patchinfo->height = realpatch->height; - patchinfo->leftoffset = realpatch->leftoffset; - patchinfo->topoffset = realpatch->topoffset; - - patchinfo->wadnum = WADFILENUM(lumpnum); - patchinfo->lumpnum = LUMPNUM(lumpnum); - - LUA_PushUserdata(L, patchinfo, META_PATCH); - numluapatches++; -#else - HUDONLY - LUA_PushUserdata(L, W_CachePatchLongName(luaL_checkstring(L, 1), PU_PATCH), META_PATCH); +#ifdef ROTSPRITE + INT32 rollangle = R_GetRollAngle(luaL_optinteger(L, 2, 0)); #endif + HUDONLY + +#ifdef ROTSPRITE + if (rollangle) + LUA_PushUserdata(L, W_GetRotatedPatchPointerFromLongName(luaL_checkstring(L, 1), PU_PATCH, rollangle, false, NULL, lua_optboolean(L, 3)), META_PATCH); + else +#endif + LUA_PushUserdata(L, W_GetPatchPointerFromLongName(luaL_checkstring(L, 1), PU_PATCH), META_PATCH); + return 1; } @@ -517,10 +467,9 @@ static int libd_getSpritePatch(lua_State *L) angle_t rollangle = luaL_checkangle(L, 4); INT32 rot = R_GetRollAngle(rollangle); - if (rot) { - if (!(sprframe->rotsprite.cached & (1<flip & (1<rotsprite.patch[angle][rot], META_PATCH); + if (rot) + { + LUA_PushUserdata(L, W_GetRotatedPatchPointer(sprframe->lumppat[angle], PU_PATCH, rot, true, NULL, sprframe->flip & (1<lumppat[angle], PU_PATCH), META_PATCH); + // push both the patch and its "flip" value + LUA_PushUserdata(L, W_GetPatchPointer(sprframe->lumppat[angle], PU_PATCH), META_PATCH); lua_pushboolean(L, (sprframe->flip & (1<rotsprite.cached & (1<flip & (1<rotsprite.patch[angle][rot], META_PATCH); + spriteinfo_t *sprinfo = &skins[i].sprinfo[j]; + spriteframepivot_t *pivot = (sprinfo->available) ? &sprinfo->pivot[frame] : NULL; + LUA_PushUserdata(L, W_GetRotatedPatchPointer(sprframe->lumppat[angle], PU_PATCH, rot, true, pivot, sprframe->flip & (1<lumppat[angle], PU_PATCH), META_PATCH); + // push both the patch and its "flip" value + LUA_PushUserdata(L, W_GetPatchPointer(sprframe->lumppat[angle], PU_PATCH), META_PATCH); lua_pushboolean(L, (sprframe->flip & (1<wadnum<<16)+luapat->lumpnum, PU_PATCH); -#else - patch = *((patch_t **)luaL_checkudata(L, 3, META_PATCH)); + patch = **((patch_t ***)luaL_checkudata(L, 3, META_PATCH)); if (!patch) return LUA_ErrInvalid(L, "patch_t"); -#endif flags = luaL_optinteger(L, 4, 0); if (!lua_isnoneornil(L, 5)) colormap = *((UINT8 **)luaL_checkudata(L, 5, META_COLORMAP)); @@ -682,9 +623,6 @@ static int libd_drawScaled(lua_State *L) fixed_t x, y, scale; INT32 flags; patch_t *patch; -#ifdef LUA_PATCH_SAFETY - patchinfo_t *luapat; -#endif const UINT8 *colormap = NULL; HUDONLY @@ -693,14 +631,9 @@ static int libd_drawScaled(lua_State *L) scale = luaL_checkinteger(L, 3); if (scale < 0) return luaL_error(L, "negative scale"); -#ifdef LUA_PATCH_SAFETY - luapat = *((patchinfo_t **)luaL_checkudata(L, 4, META_PATCH)); - patch = W_CachePatchNum((luapat->wadnum<<16)+luapat->lumpnum, PU_PATCH); -#else - patch = *((patch_t **)luaL_checkudata(L, 4, META_PATCH)); + patch = **((patch_t ***)luaL_checkudata(L, 4, META_PATCH)); if (!patch) return LUA_ErrInvalid(L, "patch_t"); -#endif flags = luaL_optinteger(L, 5, 0); if (!lua_isnoneornil(L, 6)) colormap = *((UINT8 **)luaL_checkudata(L, 6, META_COLORMAP)); @@ -727,7 +660,9 @@ static int libd_drawStretched(lua_State *L) vscale = luaL_checkinteger(L, 4); if (vscale < 0) return luaL_error(L, "negative vertical scale"); - patch = *((patch_t **)luaL_checkudata(L, 5, META_PATCH)); + patch = **((patch_t ***)luaL_checkudata(L, 5, META_PATCH)); + if (!patch) + return LUA_ErrInvalid(L, "patch_t"); flags = luaL_optinteger(L, 6, 0); if (!lua_isnoneornil(L, 7)) colormap = *((UINT8 **)luaL_checkudata(L, 7, META_COLORMAP)); @@ -1247,10 +1182,6 @@ int LUA_HudLib(lua_State *L) { memset(hud_enabled, 0xff, (hud_MAX/8)+1); -#ifdef LUA_PATCH_SAFETY - numluapatches = 0; -#endif - lua_newtable(L); // HUD registry table lua_newtable(L); luaL_register(L, NULL, lib_draw); diff --git a/src/lua_infolib.c b/src/lua_infolib.c index fe0ca759f..bc7843f8e 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -18,6 +18,7 @@ #include "p_local.h" #include "z_zone.h" #include "r_patch.h" +#include "r_rotsprite.h" #include "r_things.h" #include "r_draw.h" // R_GetColorByName #include "doomstat.h" // luabanks[] @@ -377,10 +378,6 @@ static int lib_setSpriteInfo(lua_State *L) UINT32 i = luaL_checkinteger(L, 1); if (i == 0 || i >= NUMSPRITES) return luaL_error(L, "spriteinfo[] index %d out of range (1 - %d)", i, NUMSPRITES-1); -#ifdef ROTSPRITE - if (sprites != NULL) - R_FreeSingleRotSprite(&sprites[i]); -#endif info = &spriteinfo[i]; // get the spriteinfo to assign to. } luaL_checktype(L, 2, LUA_TTABLE); // check that we've been passed a table. @@ -462,11 +459,6 @@ static int spriteinfo_set(lua_State *L) lua_remove(L, 1); // remove field lua_settop(L, 1); // leave only one value -#ifdef ROTSPRITE - if (sprites != NULL) - R_FreeSingleRotSprite(&sprites[sprinfo-spriteinfo]); -#endif - if (fastcmp(field, "pivot")) { // pivot[] is a table diff --git a/src/lua_libs.h b/src/lua_libs.h index a78128e9f..bf1186dfe 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -62,7 +62,7 @@ extern lua_State *gL; #define META_BBOX "BOUNDING_BOX" #define META_HUDINFO "HUDINFO_T*" -#define META_PATCH "PATCH_T*" +#define META_PATCH "PATCH_T**" #define META_COLORMAP "COLORMAP" #define META_CAMERA "CAMERA_T*" diff --git a/src/m_menu.c b/src/m_menu.c index ddadec799..70480f925 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -203,7 +203,7 @@ menu_t SPauseDef; // Level Select static levelselect_t levelselect = {0, NULL}; static UINT8 levelselectselect[3]; -static patch_t *levselp[2][3]; +static patch_t **levselp[2][3]; static INT32 lsoffs[2]; #define lsrow levelselectselect[0] @@ -342,7 +342,7 @@ static void M_EraseData(INT32 choice); static void M_Addons(INT32 choice); static void M_AddonsOptions(INT32 choice); -static patch_t *addonsp[NUM_EXT+5]; +static patch_t **addonsp[NUM_EXT+5]; #define addonmenusize 9 // number of items actually displayed in the addons menu view, formerly (2*numaddonsshown + 1) #define numaddonsshown 4 // number of items to each side of the currently selected item, unless at top/bottom ends of directory @@ -1345,11 +1345,7 @@ static menuitem_t OP_VideoOptionsMenu[] = {IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 11}, #endif {IT_STRING | IT_CVAR, NULL, "Vertical Sync", &cv_vidwait, 16}, -#ifdef HWRENDER - {IT_STRING | IT_CVAR, NULL, "Renderer", &cv_newrenderer, 21}, -#else - {IT_TRANSTEXT | IT_PAIR, "Renderer", "Software", &cv_renderer, 21}, -#endif + {IT_STRING | IT_CVAR, NULL, "Renderer", &cv_newrenderer, 21}, {IT_HEADER, NULL, "Color Profile", NULL, 30}, {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Brightness (F11)", &cv_globalgamma,36}, @@ -2147,15 +2143,21 @@ menu_t OP_PlaystyleDef = { static void M_VideoOptions(INT32 choice) { (void)choice; -#ifdef HWRENDER - if (vid_opengl_state == -1) - { - OP_VideoOptionsMenu[op_video_renderer].status = (IT_TRANSTEXT | IT_PAIR); - OP_VideoOptionsMenu[op_video_renderer].patch = "Renderer"; - OP_VideoOptionsMenu[op_video_renderer].text = "Software"; - } + OP_VideoOptionsMenu[op_video_renderer].status = (IT_TRANSTEXT | IT_PAIR); + OP_VideoOptionsMenu[op_video_renderer].patch = "Renderer"; + OP_VideoOptionsMenu[op_video_renderer].text = "Software"; + +#ifdef HWRENDER + if (vid.glstate != VID_GL_LIBRARY_ERROR) + { + OP_VideoOptionsMenu[op_video_renderer].status = (IT_STRING | IT_CVAR); + OP_VideoOptionsMenu[op_video_renderer].patch = NULL; + OP_VideoOptionsMenu[op_video_renderer].text = "Renderer"; + } + CV_StealthSetValue(&cv_newrenderer, cv_renderer.value); #endif + M_SetupNextMenu(&OP_VideoOptionsDef); } @@ -5206,13 +5208,13 @@ static INT32 M_CountRowsToShowOnPlatter(INT32 gt) // static void M_CacheLevelPlatter(void) { - levselp[0][0] = W_CachePatchName("SLCT1LVL", PU_PATCH); - levselp[0][1] = W_CachePatchName("SLCT2LVL", PU_PATCH); - levselp[0][2] = W_CachePatchName("BLANKLVL", PU_PATCH); + levselp[0][0] = (patch_t **)W_GetPatchPointerFromName("SLCT1LVL", PU_PATCH); + levselp[0][1] = (patch_t **)W_GetPatchPointerFromName("SLCT2LVL", PU_PATCH); + levselp[0][2] = (patch_t **)W_GetPatchPointerFromName("BLANKLVL", PU_PATCH); - levselp[1][0] = W_CachePatchName("SLCT1LVW", PU_PATCH); - levselp[1][1] = W_CachePatchName("SLCT2LVW", PU_PATCH); - levselp[1][2] = W_CachePatchName("BLANKLVW", PU_PATCH); + levselp[1][0] = (patch_t **)W_GetPatchPointerFromName("SLCT1LVW", PU_PATCH); + levselp[1][1] = (patch_t **)W_GetPatchPointerFromName("SLCT2LVW", PU_PATCH); + levselp[1][2] = (patch_t **)W_GetPatchPointerFromName("BLANKLVW", PU_PATCH); } // @@ -5591,13 +5593,10 @@ static void M_DrawLevelPlatterWideMap(UINT8 row, UINT8 col, INT32 x, INT32 y, bo if (map <= 0) return; - if (needpatchrecache) - M_CacheLevelPlatter(); - // A 564x100 image of the level as entry MAPxxW if (!(levelselect.rows[row].mapavailable[col])) { - V_DrawSmallScaledPatch(x, y, 0, levselp[1][2]); + V_DrawSmallScaledPatch(x, y, 0, *levselp[1][2]); M_DrawStaticBox(x, y, V_80TRANS, 282, 50); } else @@ -5605,7 +5604,7 @@ static void M_DrawLevelPlatterWideMap(UINT8 row, UINT8 col, INT32 x, INT32 y, bo if (W_CheckNumForName(va("%sW", G_BuildMapName(map))) != LUMPERROR) patch = W_CachePatchName(va("%sW", G_BuildMapName(map)), PU_PATCH); else - patch = levselp[1][2]; // don't static to indicate that it's just a normal level + patch = *levselp[1][2]; // don't static to indicate that it's just a normal level V_DrawSmallScaledPatch(x, y, 0, patch); } @@ -5625,13 +5624,10 @@ static void M_DrawLevelPlatterMap(UINT8 row, UINT8 col, INT32 x, INT32 y, boolea if (map <= 0) return; - if (needpatchrecache) - M_CacheLevelPlatter(); - // A 160x100 image of the level as entry MAPxxP if (!(levelselect.rows[row].mapavailable[col])) { - V_DrawSmallScaledPatch(x, y, 0, levselp[0][2]); + V_DrawSmallScaledPatch(x, y, 0, *levselp[0][2]); M_DrawStaticBox(x, y, V_80TRANS, 80, 50); } else @@ -5639,7 +5635,7 @@ static void M_DrawLevelPlatterMap(UINT8 row, UINT8 col, INT32 x, INT32 y, boolea if (W_CheckNumForName(va("%sP", G_BuildMapName(map))) != LUMPERROR) patch = W_CachePatchName(va("%sP", G_BuildMapName(map)), PU_PATCH); else - patch = levselp[0][2]; // don't static to indicate that it's just a normal level + patch = *levselp[0][2]; // don't static to indicate that it's just a normal level V_DrawSmallScaledPatch(x, y, 0, patch); } @@ -5913,7 +5909,7 @@ static void M_DrawLevelPlatterMenu(void) // draw cursor box if (levellistmode != LLM_CREATESERVER || lsrow) - V_DrawSmallScaledPatch(lsbasex + cursorx + lsoffs[1], lsbasey+lsoffs[0], 0, (levselp[sizeselect][((skullAnimCounter/4) ? 1 : 0)])); + V_DrawSmallScaledPatch(lsbasex + cursorx + lsoffs[1], lsbasey+lsoffs[0], 0, (*levselp[sizeselect][((skullAnimCounter/4) ? 1 : 0)])); #if 0 if (levelselect.rows[lsrow].maplist[lscol] > 0) @@ -6248,23 +6244,23 @@ static void M_AddonsOptions(INT32 choice) static void M_LoadAddonsPatches(void) { - addonsp[EXT_FOLDER] = W_CachePatchName("M_FFLDR", PU_PATCH); - addonsp[EXT_UP] = W_CachePatchName("M_FBACK", PU_PATCH); - addonsp[EXT_NORESULTS] = W_CachePatchName("M_FNOPE", PU_PATCH); - addonsp[EXT_TXT] = W_CachePatchName("M_FTXT", PU_PATCH); - addonsp[EXT_CFG] = W_CachePatchName("M_FCFG", PU_PATCH); - addonsp[EXT_WAD] = W_CachePatchName("M_FWAD", PU_PATCH); + addonsp[EXT_FOLDER] = (patch_t **)W_GetPatchPointerFromName("M_FFLDR", PU_PATCH); + addonsp[EXT_UP] = (patch_t **)W_GetPatchPointerFromName("M_FBACK", PU_PATCH); + addonsp[EXT_NORESULTS] = (patch_t **)W_GetPatchPointerFromName("M_FNOPE", PU_PATCH); + addonsp[EXT_TXT] = (patch_t **)W_GetPatchPointerFromName("M_FTXT", PU_PATCH); + addonsp[EXT_CFG] = (patch_t **)W_GetPatchPointerFromName("M_FCFG", PU_PATCH); + addonsp[EXT_WAD] = (patch_t **)W_GetPatchPointerFromName("M_FWAD", PU_PATCH); #ifdef USE_KART - addonsp[EXT_KART] = W_CachePatchName("M_FKART", PU_PATCH); + addonsp[EXT_KART] = (patch_t **)W_GetPatchPointerFromName("M_FKART", PU_PATCH); #endif - addonsp[EXT_PK3] = W_CachePatchName("M_FPK3", PU_PATCH); - addonsp[EXT_SOC] = W_CachePatchName("M_FSOC", PU_PATCH); - addonsp[EXT_LUA] = W_CachePatchName("M_FLUA", PU_PATCH); - addonsp[NUM_EXT] = W_CachePatchName("M_FUNKN", PU_PATCH); - addonsp[NUM_EXT+1] = W_CachePatchName("M_FSEL", PU_PATCH); - addonsp[NUM_EXT+2] = W_CachePatchName("M_FLOAD", PU_PATCH); - addonsp[NUM_EXT+3] = W_CachePatchName("M_FSRCH", PU_PATCH); - addonsp[NUM_EXT+4] = W_CachePatchName("M_FSAVE", PU_PATCH); + addonsp[EXT_PK3] = (patch_t **)W_GetPatchPointerFromName("M_FPK3", PU_PATCH); + addonsp[EXT_SOC] = (patch_t **)W_GetPatchPointerFromName("M_FSOC", PU_PATCH); + addonsp[EXT_LUA] = (patch_t **)W_GetPatchPointerFromName("M_FLUA", PU_PATCH); + addonsp[NUM_EXT] = (patch_t **)W_GetPatchPointerFromName("M_FUNKN", PU_PATCH); + addonsp[NUM_EXT+1] = (patch_t **)W_GetPatchPointerFromName("M_FSEL", PU_PATCH); + addonsp[NUM_EXT+2] = (patch_t **)W_GetPatchPointerFromName("M_FLOAD", PU_PATCH); + addonsp[NUM_EXT+3] = (patch_t **)W_GetPatchPointerFromName("M_FSRCH", PU_PATCH); + addonsp[NUM_EXT+4] = (patch_t **)W_GetPatchPointerFromName("M_FSAVE", PU_PATCH); } static void M_Addons(INT32 choice) @@ -6450,10 +6446,6 @@ static void M_DrawAddons(void) return; } - // Lactozilla: Load addons menu patches. - if (needpatchrecache) - M_LoadAddonsPatches(); - if (Playing()) V_DrawCenteredString(BASEVIDWIDTH/2, 5, warningflags, "Adding files mid-game may cause problems."); else @@ -6548,16 +6540,16 @@ static void M_DrawAddons(void) if (type & EXT_LOADED) { flags |= V_TRANSLUCENT; - V_DrawSmallScaledPatch(x-(16+4), y, V_TRANSLUCENT, addonsp[(type & ~EXT_LOADED)]); - V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[NUM_EXT+2]); + V_DrawSmallScaledPatch(x-(16+4), y, V_TRANSLUCENT, *addonsp[(type & ~EXT_LOADED)]); + V_DrawSmallScaledPatch(x-(16+4), y, 0, *addonsp[NUM_EXT+2]); } else - V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[(type & ~EXT_LOADED)]); + V_DrawSmallScaledPatch(x-(16+4), y, 0, *addonsp[(type & ~EXT_LOADED)]); // draw selection box for the item currently selected if ((size_t)i == dir_on[menudepthleft]) { - V_DrawFixedPatch((x-(16+4))<spriteframes[XTRA_CHARSEL]; - description[i].charpic = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); + description[i].charpic = (patch_t **)W_GetPatchPointer(sprframe->lumppat[0], PU_PATCH); } else - description[i].charpic = W_CachePatchName("MISSING", PU_PATCH); + description[i].charpic = (patch_t **)W_GetPatchPointerFromName("MISSING", PU_PATCH); } else - description[i].charpic = W_CachePatchName(description[i].picname, PU_PATCH); + description[i].charpic = (patch_t **)W_GetPatchPointerFromName(description[i].picname, PU_PATCH); if (description[i].nametag[0]) - description[i].namepic = W_CachePatchName(description[i].nametag, PU_PATCH); -} - -static void M_CacheCharacterSelect(void) -{ - INT32 i, skinnum; - - for (i = 0; i < MAXSKINS; i++) - { - if (!description[i].used) - continue; - - // Already set in M_SetupChoosePlayer - skinnum = description[i].skinnum[0]; - if ((skinnum != -1) && (R_SkinUsable(-1, skinnum))) - M_CacheCharacterSelectEntry(i, skinnum); - } + description[i].namepic = (patch_t **)W_GetPatchPointerFromName(description[i].nametag, PU_PATCH); } static UINT8 M_SetupChoosePlayerDirect(INT32 choice) @@ -9207,10 +9176,6 @@ static void M_DrawSetupChoosePlayerMenu(void) INT32 x, y; INT32 w = (vid.width/vid.dupx); - // lactozilla: the renderer changed so recache patches - if (needpatchrecache) - M_CacheCharacterSelect(); - if (abs(char_scroll) > FRACUNIT) char_scroll -= (char_scroll>>2); else // close enough. @@ -9264,11 +9229,11 @@ static void M_DrawSetupChoosePlayerMenu(void) { x = 8; y = (my+16) - FixedInt(char_scroll); - V_DrawScaledPatch(x, y, 0, description[char_on].charpic); + V_DrawScaledPatch(x, y, 0, *description[char_on].charpic); if (prev != -1) - V_DrawScaledPatch(x, y - 144, 0, description[prev].charpic); + V_DrawScaledPatch(x, y - 144, 0, *description[prev].charpic); if (next != -1) - V_DrawScaledPatch(x, y + 144, 0, description[next].charpic); + V_DrawScaledPatch(x, y + 144, 0, *description[next].charpic); } // Character description @@ -9292,14 +9257,14 @@ static void M_DrawSetupChoosePlayerMenu(void) curtextcolor = description[char_on].tagtextcolor; curoutlinecolor = description[char_on].tagoutlinecolor; if (curtext[0] == '\0') - curpatch = description[char_on].namepic; + curpatch = *description[char_on].namepic; if (!curtextcolor) curtextcolor = charskin->prefcolor; if (!curoutlinecolor) curoutlinecolor = col = skincolors[charskin->prefcolor].invcolor; txsh = oxsh; - ox = 8 + SHORT((description[char_on].charpic)->width)/2; + ox = 8 + SHORT((*description[char_on].charpic)->width)/2; y = my + 144; // cur @@ -9330,7 +9295,7 @@ static void M_DrawSetupChoosePlayerMenu(void) prevtextcolor = description[prev].tagtextcolor; prevoutlinecolor = description[prev].tagoutlinecolor; if (prevtext[0] == '\0') - prevpatch = description[prev].namepic; + prevpatch = *description[prev].namepic; charskin = &skins[description[prev].skinnum[0]]; if (!prevtextcolor) prevtextcolor = charskin->prefcolor; @@ -9360,7 +9325,7 @@ static void M_DrawSetupChoosePlayerMenu(void) nexttextcolor = description[next].tagtextcolor; nextoutlinecolor = description[next].tagoutlinecolor; if (nexttext[0] == '\0') - nextpatch = description[next].namepic; + nextpatch = *description[next].namepic; charskin = &skins[description[next].skinnum[0]]; if (!nexttextcolor) nexttextcolor = charskin->prefcolor; @@ -10582,10 +10547,6 @@ void M_DrawMarathon(void) angle_t fa; INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy), xspan = (vid.width/dupz), yspan = (vid.height/dupz), diffx = (xspan - BASEVIDWIDTH)/2, diffy = (yspan - BASEVIDHEIGHT)/2, maxy = BASEVIDHEIGHT + diffy; - // lactozilla: the renderer changed so recache patches - if (needpatchrecache) - M_CacheCharacterSelect(); - curbgxspeed = 0; curbgyspeed = 18; @@ -10719,10 +10680,10 @@ void M_DrawMarathon(void) if (dispstatus == IT_STRING || dispstatus == IT_WHITESTRING) { soffset = 68; - if (description[char_on].charpic->width >= 256) - V_DrawTinyScaledPatch(224, 120, 0, description[char_on].charpic); + if ((*description[char_on].charpic)->width >= 256) + V_DrawTinyScaledPatch(224, 120, 0, *description[char_on].charpic); else - V_DrawSmallScaledPatch(224, 120, 0, description[char_on].charpic); + V_DrawSmallScaledPatch(224, 120, 0, *description[char_on].charpic); } else soffset = 0; @@ -12836,9 +12797,6 @@ static void M_VideoModeMenu(INT32 choice) memset(modedescs, 0, sizeof(modedescs)); -#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) - VID_PrepareModeList(); // FIXME: hack -#endif vidm_nummodes = 0; vidm_selected = 0; nummodes = VID_NumModes(); diff --git a/src/m_menu.h b/src/m_menu.h index 52bdb0dea..944e1269a 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -351,7 +351,7 @@ typedef struct char notes[441]; char picname[8]; char skinname[SKINNAMESIZE*2+2]; // skin&skin\0 - patch_t *charpic; + patch_t **charpic; UINT8 prev; UINT8 next; @@ -360,7 +360,7 @@ typedef struct SINT8 skinnum[2]; UINT16 oppositecolor; char nametag[8]; - patch_t *namepic; + patch_t **namepic; UINT16 tagtextcolor; UINT16 tagoutlinecolor; } description_t; diff --git a/src/p_setup.c b/src/p_setup.c index 2fd7ba5b0..d5fb07e9a 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -29,6 +29,7 @@ #include "r_data.h" #include "r_things.h" // for R_AddSpriteDefs #include "r_patch.h" +#include "r_rotsprite.h" #include "r_sky.h" #include "r_draw.h" @@ -3703,14 +3704,12 @@ boolean P_LoadLevel(boolean fromnetsave) P_SpawnPrecipitation(); #ifdef HWRENDER // not win32 only 19990829 by Kin - // Lactozilla: Free extrasubsectors regardless of renderer. - // Maybe we're not in OpenGL anymore. - if (extrasubsectors) - free(extrasubsectors); - extrasubsectors = NULL; - // stuff like HWR_CreatePlanePolygons is called there + // Free extrasubsectors regardless of the renderer. + HWR_FreeExtraSubsectors(); + + // Create plane polygons. if (rendermode == render_opengl) - HWR_SetupLevel(); + HWR_LoadLevel(); #endif // oh god I hope this helps @@ -3796,7 +3795,7 @@ boolean P_LoadLevel(boolean fromnetsave) } #ifdef HWRENDER -void HWR_SetupLevel(void) +void HWR_LoadLevel(void) { // Lactozilla (December 8, 2019) // Level setup used to free EVERY mipmap from memory. @@ -4054,6 +4053,13 @@ boolean P_AddWadFile(const char *wadfilename) // S_LoadMusicDefs(wadnum); + // + // recache sprite rotation data + // +#ifdef ROTSPRITE + RotSprite_RecreateAll(); +#endif + // // search for maps // diff --git a/src/p_setup.h b/src/p_setup.h index e7150c0ae..497870628 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -99,7 +99,7 @@ void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum); void P_RespawnThings(void); boolean P_LoadLevel(boolean fromnetsave); #ifdef HWRENDER -void HWR_SetupLevel(void); +void HWR_LoadLevel(void); #endif boolean P_AddWadFile(const char *wadfilename); boolean P_RunSOC(const char *socfilename); diff --git a/src/r_data.c b/src/r_data.c index d10919d81..53a483abf 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -471,7 +471,7 @@ static inline void R_DrawBlendFlippedColumnInCache(column_t *patch, UINT8 *cache // Allocate space for full size texture, either single patch or 'composite' // Build the full textures from patches. // The texture caching system is a little more hungry of memory, but has -// been simplified for the sake of highcolor (lol), dynamic ligthing, & speed. +// been simplified for the sake of highcolor, dynamic ligthing, & speed. // // This is not optimised, but it's supposed to be executed only once // per level, when enough memory is available. @@ -838,8 +838,6 @@ Rloadflats (INT32 i, INT32 w) patch->lump = texstart + j; patch->flip = 0; - Z_Unlock(flatlump); - texturewidth[i] = texture->width; textureheight[i] = texture->height << FRACBITS; i++; @@ -939,8 +937,6 @@ Rloadtextures (INT32 i, INT32 w) patch->lump = texstart + j; patch->flip = 0; - Z_Unlock(patchlump); - texturewidth[i] = texture->width; textureheight[i] = texture->height << FRACBITS; i++; diff --git a/src/r_defs.h b/src/r_defs.h index fd868ee97..9e5894ffa 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -688,14 +688,21 @@ typedef struct #pragma pack() #endif -// rotsprite -#ifdef ROTSPRITE typedef struct { - patch_t *patch[16][ROTANGLES]; - UINT16 cached; -} rotsprite_t; -#endif/*ROTSPRITE*/ + UINT8 *data; + void **columnofs; + size_t *columnsize; +} pmcache_t; + +typedef struct +{ + UINT32 width, height; + INT16 leftoffset, topoffset; + size_t size; + INT32 *map; + pmcache_t cache; +} pixelmap_t; typedef enum { @@ -709,24 +716,6 @@ typedef enum SRF_NONE = 0xff // Initial value } spriterotateflags_t; // SRF's up! -// Same as a patch_t, except just the header -// and the wadnum/lumpnum combination that points -// to wherever the patch is in memory. -struct patchinfo_s -{ - INT16 width; // bounding box size - INT16 height; - INT16 leftoffset; // pixels to the left of origin - INT16 topoffset; // pixels below the origin - - UINT16 wadnum; // the software patch lump num for when the patch - UINT16 lumpnum; // was flushed, and we need to re-create it - - // next patchinfo_t in memory - struct patchinfo_s *next; -}; -typedef struct patchinfo_s patchinfo_t; - // // Sprites are patches with a special naming convention so they can be // recognized by R_InitSprites. @@ -754,10 +743,6 @@ typedef struct // Flip bits (1 = flip) to use for view angles 0-7/15. UINT16 flip; - -#ifdef ROTSPRITE - rotsprite_t rotsprite; -#endif } spriteframe_t; // diff --git a/src/r_draw.c b/src/r_draw.c index 6492d9d36..16e1b5f0c 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -18,7 +18,7 @@ #include "doomdef.h" #include "doomstat.h" #include "r_local.h" -#include "st_stuff.h" // need ST_HEIGHT +#include "st_stuff.h" #include "i_video.h" #include "v_video.h" #include "m_misc.h" @@ -65,9 +65,11 @@ lighttable_t *dc_colormap; INT32 dc_x = 0, dc_yl = 0, dc_yh = 0; fixed_t dc_iscale, dc_texturemid; + +UINT8 *dc_source; + 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; // ----------------------- // translucency stuff here diff --git a/src/r_main.c b/src/r_main.c index ead1403be..e7e1d77f6 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -150,7 +150,7 @@ consvar_t cv_flipcam2 = {"flipcam2", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, consvar_t cv_shadow = {"shadow", "On", 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_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_showhud = {"showhud", "Yes", CV_CALL, CV_YesNo, R_ViewSizeChanged, 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_translucency = {"translucency", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -180,7 +180,7 @@ void SplitScreen_OnChange(void) } // recompute screen size - R_ExecuteSetViewSize(); + R_SetViewSize(); if (!demoplayback && !botingame) { @@ -210,7 +210,7 @@ static void Fov_OnChange(void) //if ((netgame || multiplayer) && !cv_debug && cv_fov.value != 90*FRACUNIT) // CV_Set(&cv_fov, cv_fov.defaultvalue); - R_SetViewSize(); + R_ViewSizeChanged(); } static void ChaseCam_OnChange(void) @@ -642,7 +642,7 @@ void R_CheckViewMorph(void) viewmorph.use = false; viewmorph.x1 = 0; if (viewmorph.zoomneeded != FRACUNIT) - R_SetViewSize(); + R_ViewSizeChanged(); viewmorph.zoomneeded = FRACUNIT; return; @@ -692,7 +692,7 @@ void R_CheckViewMorph(void) if (temp != viewmorph.zoomneeded) { viewmorph.zoomneeded = temp; - R_SetViewSize(); + R_ViewSizeChanged(); } zoomfactor = FIXED_TO_FLOAT(viewmorph.zoomneeded); @@ -864,22 +864,22 @@ void R_ApplyViewMorph(void) // -// R_SetViewSize +// R_ViewSizeChanged // Do not really change anything here, // because it might be in the middle of a refresh. // The change will take effect next refresh. // boolean setsizeneeded; -void R_SetViewSize(void) +void R_ViewSizeChanged(void) { setsizeneeded = true; } // -// R_ExecuteSetViewSize +// R_SetViewSize // -void R_ExecuteSetViewSize(void) +void R_SetViewSize(void) { fixed_t dy; INT32 i; @@ -981,7 +981,7 @@ void R_Init(void) //I_OutputMsg("\nR_InitViewBorder"); R_InitViewBorder(); - R_SetViewSize(); // setsizeneeded is set true + R_ViewSizeChanged(); // setsizeneeded is set true //I_OutputMsg("\nR_InitPlanes"); R_InitPlanes(); @@ -1542,26 +1542,6 @@ void R_RenderPlayerView(player_t *player) free(masks); } -// Lactozilla: Renderer switching -#ifdef HWRENDER -void R_InitHardwareMode(void) -{ - HWR_AddSessionCommands(); - HWR_Switch(); - HWR_LoadTextures(numtextures); - if (gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction)) - HWR_SetupLevel(); -} -#endif - -void R_ReloadHUDGraphics(void) -{ - CONS_Debug(DBG_RENDER, "R_ReloadHUDGraphics()...\n"); - ST_LoadGraphics(); - HU_LoadGraphics(); - ST_ReloadSkinFaceGraphics(); -} - // ========================================================================= // ENGINE COMMANDS & VARS // ========================================================================= diff --git a/src/r_main.h b/src/r_main.h index 99a25d86e..6b102d75f 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -111,21 +111,14 @@ extern consvar_t cv_tailspickup; // Called by startup code. void R_Init(void); -#ifdef HWRENDER -void R_InitHardwareMode(void); -#endif -void R_ReloadHUDGraphics(void); void R_CheckViewMorph(void); void R_ApplyViewMorph(void); -// just sets setsizeneeded true extern boolean setsizeneeded; +void R_ViewSizeChanged(void); // sets setsizeneeded true void R_SetViewSize(void); -// do it (sometimes explicitly called) -void R_ExecuteSetViewSize(void); - void R_SetupFrame(player_t *player); void R_SkyboxFrame(player_t *player); diff --git a/src/r_patch.c b/src/r_patch.c index 8980eda58..e4cc21b4f 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -10,7 +10,7 @@ // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- /// \file r_patch.c -/// \brief Patch generation. +/// \brief Patch caching and generation. #include "byteptr.h" #include "dehacked.h" @@ -19,6 +19,7 @@ #include "r_draw.h" #include "r_patch.h" #include "r_things.h" +#include "r_rotsprite.h" #include "z_zone.h" #include "w_wad.h" @@ -50,6 +51,356 @@ static unsigned char imgbuf[1<<26]; +// ========================================================================== +// CACHING OF GRAPHIC PATCH RESOURCES +// ========================================================================== + +// Graphic 'patches' are loaded, and if necessary, converted into the format +// the most useful for the current render mode. For the software renderer, the +// graphic patches are kept as is. For the hardware renderer, graphic patches +// are 'unpacked', and are kept into the cache in that unpacked format, and +// the heap memory cache then acts as a 'level 2' cache just after the +// graphics card memory. + +// If patches need to be cached only once, references to those patches +// can be obtained with W_GetPatchPointer and relatives. By returning a +// double pointer that can be dereferenced, the addresses of the patches +// can be swapped out to point to another patch instead. The main use case +// for this is renderer switching. + +static patchreference_t *patchlist_head = NULL; +static patchreference_t *patchlist_tail = NULL; + +// Find patch in list +patchreference_t *Patch_FindReference(UINT16 wad, UINT16 lump, INT32 rollangle, boolean flip) +{ + patchreference_t *patch = patchlist_head; + + CONS_Debug(DBG_RENDER, "Patch_FindReference: searching for %s (%d)\n", W_CheckNameForNumPwad(wad, lump), rollangle); + + while (patch) + { + patchreference_t *prev = NULL, *next = NULL; + + if (patch->wad == wad && patch->lump == lump && patch->rollangle == rollangle && patch->flip == flip) + { + CONS_Debug(DBG_RENDER, "found\n"); + return patch; + } + + // Lazy memory deallocation. + // References aren't removed until an iteration + // knows the pointer isn't valid anymore. + next = patch->next; + if (patch->ptr == NULL) + { + CONS_Debug(DBG_RENDER, "freeing %s (%d) in the list\n", W_CheckNameForNumPwad(patch->wad, patch->lump), patch->rollangle); + prev = patch->prev; + if (prev) + prev->next = next; + Z_Free(patch); + } + patch = next; + } + + CONS_Debug(DBG_RENDER, "not found\n"); + return NULL; +} + +// Insert patch in list +patchreference_t *Patch_StoreReference(UINT16 wad, UINT16 lump, INT32 tag, void *ptr, INT32 rollangle, boolean flip) +{ + patchreference_t *found = Patch_FindReference(wad, lump, rollangle, flip); + if (found) + return found; + + CONS_Debug(DBG_RENDER, "Patch_StoreReference: storing %s (%d)\n", W_CheckNameForNumPwad(wad, lump), rollangle); + + if (!patchlist_head) + { + patchlist_head = Z_Calloc(sizeof(patchreference_t), PU_STATIC, NULL); + patchlist_head->wad = wad; + patchlist_head->lump = lump; + patchlist_head->tag = tag; + patchlist_head->ptr = ptr; + patchlist_head->rollangle = rollangle; + patchlist_head->flip = flip; + patchlist_tail = patchlist_head; + return patchlist_head; + } + else + { + patchreference_t *list = Z_Calloc(sizeof(patchreference_t), PU_STATIC, NULL); + list->wad = wad; + list->lump = lump; + list->tag = tag; + list->ptr = ptr; + list->rollangle = rollangle; + list->flip = flip; + list->prev = patchlist_tail; // set the previous item to the tail + patchlist_tail->next = list; // set the tail's next item to the new item + patchlist_tail = list; // set the tail to the new item + return list; + } +} + +// Get patch tree type from a render mode. +patchtreetype_t Patch_GetTreeType(rendermode_t mode) +{ + return (mode == render_opengl) ? patchtree_mipmap : patchtree_software; +} + +// Get patch tree. +patchtree_t *Patch_GetRendererTree(UINT16 wadnum, rendermode_t mode) +{ + return &(wadfiles[wadnum]->patchinfo.renderer[Patch_GetTreeType(mode)]); +} + +// Get patch base subtree. +aatree_t *Patch_GetRendererBaseSubTree(UINT16 wadnum, rendermode_t mode) +{ + return Patch_GetRendererTree(wadnum, mode)->base; +} + +#ifdef ROTSPRITE +// Get rotated patch subtree. +aatree_t *Patch_GetRendererRotatedSubTree(UINT16 wadnum, rendermode_t mode, boolean flip) +{ + UINT8 f = (flip == true) ? 1 : 0; + return Patch_GetRendererTree(wadnum, mode)->rotated[f]; +} +#endif + +// +// Initializes patch info for a WAD file. +// +void Patch_InitInfo(wadfile_t *wadfile) +{ + patchinfo_t *cache = &wadfile->patchinfo; + rendermode_t rmode; + + // Patch info is uninitialized. + memset(cache, 0x00, sizeof(patchinfo_t)); + + // Main patch cache for the current renderer + Z_Calloc(wadfile->numlumps * sizeof(lumpcache_t), PU_STATIC, &cache->current); + +#ifdef ROTSPRITE + // Rotated patch cache for the current renderer + Z_Calloc(wadfile->numlumps * sizeof(lumpcache_t *), PU_STATIC, &cache->rotated); +#endif + + // Patch trees for each renderer + for (rmode = render_first; rmode < render_last; rmode++) + { + patchtree_t *rcache = &(cache->renderer[Patch_GetTreeType(rmode)]); + + // Multiple renderers can point to the same tree. + // If this tree was already initialized, then + // don't try initializing it again. + if (rcache->base) + continue; + + rcache->base = M_AATreeAlloc(AATREE_ZUSER); + +#ifdef ROTSPRITE + RotSprite_InitPatchTree(rcache); +#endif + } +} + +// Get renderer patch info. +void *GetRendererPatchInfo(UINT16 wadnum, UINT16 lumpnum, rendermode_t mode) +{ + return M_AATreeGet(Patch_GetRendererBaseSubTree(wadnum, mode), lumpnum); +} + +// Set renderer patch info. +void SetRendererPatchInfo(UINT16 wadnum, UINT16 lumpnum, rendermode_t mode, void *ptr) +{ + M_AATreeSet(Patch_GetRendererBaseSubTree(wadnum, mode), lumpnum, ptr); +} + +// Update current patch info. +void UpdateCurrentPatchInfo(UINT16 wadnum, UINT16 lumpnum, rendermode_t mode) +{ + wadfiles[wadnum]->patchinfo.current[lumpnum] = GetRendererPatchInfo(wadnum, lumpnum, mode); +} + +#ifdef ROTSPRITE +void RotSprite_InitPatchTree(patchtree_t *rcache) +{ + INT32 i; + for (i = 0; i < 2; i++) + rcache->rotated[i] = M_AATreeAlloc(AATREE_ZUSER); +} + +int RotSprite_GetCurrentPatchInfoIdx(INT32 rollangle, boolean flip) +{ + UINT8 f = (flip == true) ? 1 : 0; + return rollangle + (ROTANGLES * f); +} + +void RotSprite_AllocCurrentPatchInfo(patchinfo_t *patchinfo, UINT16 lumpnum) +{ + patchinfo->rotated[lumpnum] = Z_Calloc((ROTANGLES * 2) * sizeof(lumpcache_t), PU_STATIC, NULL); +} + +// Get renderer rotated patch info. +void *GetRotatedPatchInfo(UINT16 wadnum, UINT16 lumpnum, rendermode_t mode, boolean flip) +{ + return M_AATreeGet(Patch_GetRendererRotatedSubTree(wadnum, mode, flip), lumpnum); +} + +// Set renderer rotated patch info. +void SetRotatedPatchInfo(UINT16 wadnum, UINT16 lumpnum, rendermode_t mode, boolean flip, void *ptr) +{ + M_AATreeSet(Patch_GetRendererRotatedSubTree(wadnum, mode, flip), lumpnum, ptr); +} + +// Update current rotated patch info. +void UpdateCurrentRotatedPatchInfo(UINT16 wadnum, UINT16 lumpnum, rendermode_t mode, INT32 rollangle, boolean flip) +{ + patchinfo_t *patchinfo = &wadfiles[wadnum]->patchinfo; + if (!patchinfo->rotated[lumpnum]) + RotSprite_AllocCurrentPatchInfo(patchinfo, lumpnum); + patchinfo->rotated[lumpnum][RotSprite_GetCurrentPatchInfoIdx(rollangle, flip)] = ((rotsprite_t *)GetRotatedPatchInfo(wadnum, lumpnum, mode, flip))->patches[rollangle]; +} +#endif + +void *Patch_CacheSoftware(UINT16 wad, UINT16 lump, INT32 tag, boolean store) +{ + void *cache = GetRendererPatchInfo(wad, lump, render_soft); + if (!GetRendererPatchInfo(wad, lump, render_soft)) + { + size_t len = W_LumpLengthPwad(wad, lump); + void *ptr, *lumpdata; +#ifndef NO_PNG_LUMPS + void *converted = NULL; +#endif + + ptr = Z_Malloc(len, tag, &cache); + lumpdata = Z_Malloc(len, tag, NULL); + + // read the lump in full + W_ReadLumpHeaderPwad(wad, lump, lumpdata, 0, 0); + +#ifndef NO_PNG_LUMPS + // lump is a png so convert it + if (R_IsLumpPNG((UINT8 *)lumpdata, len)) + { + size_t newlen; + converted = R_PNGToPatch((UINT8 *)lumpdata, len, &newlen); + ptr = Z_Realloc(ptr, newlen, tag, &cache); + M_Memcpy(ptr, converted, newlen); + Z_Free(converted); + } + else // just copy it into the patch cache +#endif + M_Memcpy(ptr, lumpdata, len); + + // insert into list + if (store) + Patch_StoreReference(wad, lump, tag, ptr, 0, false); + + SetRendererPatchInfo(wad, lump, render_soft, ptr); + UpdateCurrentPatchInfo(wad, lump, render_soft); + + return ptr; + } + else + Z_ChangeTag(cache, tag); + + return cache; +} + +#ifdef HWRENDER +void *Patch_CacheGL(UINT16 wad, UINT16 lump, INT32 tag, boolean store) +{ + GLPatch_t *grPatch = HWR_GetCachedGLPatchPwad(wad, lump, Patch_GetRendererBaseSubTree(wad, render_opengl)); + + if (grPatch->mipmap->data) + { + if (tag == PU_CACHE) + tag = PU_HWRCACHE; + Z_ChangeTag(grPatch->mipmap->data, tag); + } + else + { + patch_t *ptr = NULL; + + // Only load the patch if we haven't initialised the grPatch yet + if (grPatch->mipmap->width == 0) + ptr = W_CacheLumpNumPwad(grPatch->wadnum, grPatch->lumpnum, PU_STATIC); + + // Run HWR_MakePatch in all cases, to recalculate some things + HWR_MakePatch(ptr, grPatch, grPatch->mipmap, false); + Z_Free(ptr); + + // insert into list + if (store) + Patch_StoreReference(wad, lump, tag, (void *)grPatch, 0, false); + UpdateCurrentPatchInfo(wad, lump, render_opengl); + } + + // return GLPatch_t, which can be casted to (patch_t *) with valid patch header info + return (void *)grPatch; +} +#endif + +// +// Update patch references to point to the current renderer's patches. +// +void Patch_UpdateReferences(void) +{ + patchreference_t *patch = patchlist_head; + + while (patch) + { + CONS_Debug(DBG_RENDER, "Patch_UpdateReferences: %s (%d)\n", W_CheckNameForNumPwad(patch->wad, patch->lump), patch->rollangle); + +#ifdef ROTSPRITE + if (patch->rollangle) + { + static rotsprite_vars_t rsvars; + + rsvars.rollangle = patch->rollangle; + rsvars.flip = patch->flip; + + Patch_CacheRotatedPwad(patch->wad, patch->lump, patch->tag, rsvars, false); + UpdateCurrentRotatedPatchInfo(patch->wad, patch->lump, rendermode, patch->rollangle, patch->flip); + } + else +#endif + { +#ifdef HWRENDER + if (rendermode == render_opengl) + Patch_CacheGL(patch->wad, patch->lump, patch->tag, false); + else +#endif + Patch_CacheSoftware(patch->wad, patch->lump, patch->tag, false); + + UpdateCurrentPatchInfo(patch->wad, patch->lump, rendermode); + } + + patch = patch->next; + } +} + +// +// Free the patch reference list. +// +void Patch_FreeReferences(void) +{ + patchreference_t *patch = patchlist_head; + while (patch) + { + patchreference_t *next = patch->next; + Z_Free(patch); + patch = next; + } +} + // // R_CheckIfPatch // @@ -198,47 +549,6 @@ void R_PatchToFlat(patch_t *patch, UINT8 *flat) } } -// -// R_PatchToMaskedFlat -// -// Convert a patch to a masked flat. -// Now, what is a "masked" flat anyway? -// It means the flat uses two bytes to store image data. -// The upper byte is used to store the transparent pixel, -// and the lower byte stores a palette index. -// -void R_PatchToMaskedFlat(patch_t *patch, UINT16 *raw, boolean flip) -{ - fixed_t col, ofs; - column_t *column; - UINT16 *desttop, *dest, *deststop; - UINT8 *source; - - desttop = raw; - deststop = desttop + (SHORT(patch->width) * SHORT(patch->height)); - - for (col = 0; col < SHORT(patch->width); col++, desttop++) - { - INT32 topdelta, prevdelta = -1; - column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[flip ? (patch->width-1-col) : col])); - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - dest = desttop + (topdelta * SHORT(patch->width)); - source = (UINT8 *)(column) + 3; - for (ofs = 0; dest < deststop && ofs < column->length; ofs++) - { - *dest = source[ofs]; - dest += SHORT(patch->width); - } - column = (column_t *)((UINT8 *)column + column->length + 4); - } - } -} - // // R_FlatToPatch // @@ -354,12 +664,11 @@ patch_t *R_FlatToPatch(UINT8 *raw, UINT16 width, UINT16 height, UINT16 leftoffse } // -// R_MaskedFlatToPatch +// R_TransparentFlatToPatch // -// Convert a masked flat to a patch. -// Explanation of "masked" flats in R_PatchToMaskedFlat. +// Convert a transparent flat to a patch. // -patch_t *R_MaskedFlatToPatch(UINT16 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize) +patch_t *R_TransparentFlatToPatch(UINT16 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize) { UINT32 x, y; UINT8 *img; @@ -687,7 +996,7 @@ static UINT8 *PNG_RawConvert(const UINT8 *png, UINT16 *w, UINT16 *h, INT16 *topo } // Convert a PNG with transparency to a raw image. -static UINT16 *PNG_MaskedRawConvert(const UINT8 *png, UINT16 *w, UINT16 *h, INT16 *topoffset, INT16 *leftoffset, size_t size) +static UINT16 *PNG_TransparentRawConvert(const UINT8 *png, UINT16 *w, UINT16 *h, INT16 *topoffset, INT16 *leftoffset, size_t size) { UINT16 *flat; png_uint_32 x, y; @@ -696,7 +1005,7 @@ static UINT16 *PNG_MaskedRawConvert(const UINT8 *png, UINT16 *w, UINT16 *h, INT1 size_t flatsize, i; if (!row_pointers) - I_Error("PNG_MaskedRawConvert: conversion failed"); + I_Error("PNG_TransparentRawConvert: conversion failed"); // Convert the image to 16bpp flatsize = (width * height); @@ -740,12 +1049,12 @@ patch_t *R_PNGToPatch(const UINT8 *png, size_t size, size_t *destsize) { UINT16 width, height; INT16 topoffset = 0, leftoffset = 0; - UINT16 *raw = PNG_MaskedRawConvert(png, &width, &height, &topoffset, &leftoffset, size); + UINT16 *raw = PNG_TransparentRawConvert(png, &width, &height, &topoffset, &leftoffset, size); if (!raw) I_Error("R_PNGToPatch: conversion failed"); - return R_MaskedFlatToPatch(raw, width, height, leftoffset, topoffset, destsize); + return R_TransparentFlatToPatch(raw, width, height, leftoffset, topoffset, destsize); } // @@ -979,11 +1288,6 @@ static void R_ParseSpriteInfo(boolean spr2) info = Z_Calloc(sizeof(spriteinfo_t), PU_STATIC, NULL); info->available = true; -#ifdef ROTSPRITE - if ((sprites != NULL) && (!spr2)) - R_FreeSingleRotSprite(&sprites[sprnum]); -#endif - // Left Curly Brace sprinfoToken = M_GetToken(NULL); if (sprinfoToken == NULL) @@ -1035,18 +1339,17 @@ static void R_ParseSpriteInfo(boolean spr2) { R_ParseSpriteInfoFrame(info); Z_Free(sprinfoToken); + if (spr2) { if (!foundskins) I_Error("Error parsing SPRTINFO lump: No skins specified in this sprite2 definition"); + for (i = 0; i < foundskins; i++) { size_t skinnum = skinnumbers[i]; skin_t *skin = &skins[skinnum]; spriteinfo_t *sprinfo = skin->sprinfo; -#ifdef ROTSPRITE - R_FreeSkinRotSprite(skinnum); -#endif M_Memcpy(&sprinfo[spr2num], info, sizeof(spriteinfo_t)); } } @@ -1137,7 +1440,7 @@ void R_LoadSpriteInfoLumps(UINT16 wadnum, UINT16 numlumps) } } -static UINT16 GetPatchPixel(patch_t *patch, INT32 x, INT32 y, boolean flip) +UINT8 *Patch_GetPixel(patch_t *patch, INT32 x, INT32 y, boolean flip) { fixed_t ofs; column_t *column; @@ -1146,7 +1449,7 @@ static UINT16 GetPatchPixel(patch_t *patch, INT32 x, INT32 y, boolean flip) if (x >= 0 && x < SHORT(patch->width)) { INT32 topdelta, prevdelta = -1; - column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[flip ? (patch->width-1-x) : x])); + column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[flip ? (SHORT(patch->width)-1-x) : x])); while (column->topdelta != 0xff) { topdelta = column->topdelta; @@ -1157,324 +1460,200 @@ static UINT16 GetPatchPixel(patch_t *patch, INT32 x, INT32 y, boolean flip) for (ofs = 0; ofs < column->length; ofs++) { if ((topdelta + ofs) == y) - return source[ofs]; + return &source[ofs]; } column = (column_t *)((UINT8 *)column + column->length + 4); } } - return 0xFF00; + return NULL; +} + +boolean PixelMap_ApplyToColumn(pixelmap_t *pmap, INT32 *map, patch_t *patch, UINT8 *post, size_t *colsize, boolean flipped) +{ + INT32 x, y; + size_t pmsize = pmap->size; + size_t i = 0; + int lastStartY = 0; + int spanSize = 0; + UINT8 *px, *startofspan = NULL, *dest = post; + boolean written = false; + + while (i < pmap->height) + { + y = map[i]; + x = map[i + pmsize]; + px = Patch_GetPixel(patch, x, y, flipped); // If not NULL, we have a pixel + i++; + + // End span if we have a transparent pixel + if (px == NULL) + { + if (startofspan) + WRITEUINT8(dest, 0); + startofspan = NULL; + continue; + } + + // Start new column if we need to + if (!startofspan || spanSize == 255) + { + int writeY = i; + + // If we reached the span size limit, finish the previous span + if (startofspan) + WRITEUINT8(dest, 0); + + if (i > 254) + { + // Make sure we're aligned to 254 + if (lastStartY < 254) + { + WRITEUINT8(dest, 254); + WRITEUINT8(dest, 0); + dest += 2; + lastStartY = 254; + } + + // Write stopgap empty spans if needed + writeY = y - lastStartY; + + while (writeY > 254) + { + WRITEUINT8(dest, 254); + WRITEUINT8(dest, 0); + dest += 2; + writeY -= 254; + } + } + + startofspan = dest; + WRITEUINT8(dest, writeY); + dest += 2; + spanSize = 0; + + lastStartY = i; + } + + // Write the pixel + WRITEUINT8(dest, *px); + spanSize++; + startofspan[1] = spanSize; + written = true; + } + + if (startofspan) + WRITEUINT8(dest, 0); + WRITEUINT8(dest, 0xFF); + + if (colsize) + *colsize = (dest - post); + return written; } #ifdef ROTSPRITE -// -// R_GetRollAngle -// -// Angles precalculated in R_InitSprites. -// -fixed_t rollcosang[ROTANGLES]; -fixed_t rollsinang[ROTANGLES]; -INT32 R_GetRollAngle(angle_t rollangle) +/** Creates a rotated patch from another patch. + * + * \param wad The patch's wad number. + * \param lump The patch's lump number. + * \param tag Zone memory tag. + * \param rsvars Sprite rotation variables. + * \param store Store the rotated patch into the patch reference list. + * \return The rotated patch. + * \sa Patch_CacheRotatedPwad + */ +patch_t *Patch_CacheRotatedPwad(UINT16 wad, UINT16 lump, INT32 tag, rotsprite_vars_t rsvars, boolean store) { - INT32 ra = AngleFixed(rollangle)>>FRACBITS; -#if (ROTANGDIFF > 1) - ra += (ROTANGDIFF/2); -#endif - ra /= ROTANGDIFF; - ra %= ROTANGLES; - return ra; -} + rotsprite_t *rotsprite = RotSprite_GetFromPatchNumPwad(wad, lump, tag, rsvars, store); + patch_t *patch = NULL; -// -// R_CacheRotSprite -// -// Create a rotated sprite. -// -void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, spriteframe_t *sprframe, INT32 rot, UINT8 flip) -{ - UINT32 i; - INT32 angle; - patch_t *patch; - patch_t *newpatch; - UINT16 *rawdst; - size_t size; - INT32 bflip = (flip != 0x00); + if (rotsprite->patches[rsvars.rollangle]) + return rotsprite->patches[rsvars.rollangle]; -#define SPRITE_XCENTER (leftoffset) -#define SPRITE_YCENTER (height / 2) -#define ROTSPRITE_XCENTER (newwidth / 2) -#define ROTSPRITE_YCENTER (newheight / 2) + rsvars.sprite = false; + rotsprite->vars = rsvars; + rotsprite->tag = tag; - if (!(sprframe->rotsprite.cached & (1<lumppat[rot]; -#ifndef NO_PNG_LUMPS - size_t lumplength; -#endif + RotSprite_Create(rotsprite, rsvars); + patch = RotSprite_CreatePatch(rotsprite, rsvars); - if (lump == LUMPERROR) - return; - - patch = (patch_t *)W_CacheLumpNum(lump, PU_STATIC); -#ifndef NO_PNG_LUMPS - lumplength = W_LumpLength(lump); - - if (R_IsLumpPNG((UINT8 *)patch, lumplength)) - patch = R_PNGToPatch((UINT8 *)patch, lumplength, NULL); - else -#endif - // Because there's something wrong with SPR_DFLM, I guess - if (!R_CheckIfPatch(lump)) - return; - - width = SHORT(patch->width); - height = SHORT(patch->height); - leftoffset = SHORT(patch->leftoffset); - - // rotation pivot - px = SPRITE_XCENTER; - py = SPRITE_YCENTER; - - // get correct sprite info for sprite - if (sprinfo == NULL) - sprinfo = &spriteinfo[sprnum]; - if (sprinfo->available) - { - px = sprinfo->pivot[frame].x; - py = sprinfo->pivot[frame].y; - } - if (bflip) - { - px = width - px; - leftoffset = width - leftoffset; - } - - // Don't cache angle = 0 - for (angle = 1; angle < ROTANGLES; angle++) - { - INT32 newwidth, newheight; - - ca = rollcosang[angle]; - sa = rollsinang[angle]; - - // Find the dimensions of the rotated patch. - { - INT32 w1 = abs(FixedMul(width << FRACBITS, ca) - FixedMul(height << FRACBITS, sa)); - INT32 w2 = abs(FixedMul(-(width << FRACBITS), ca) - FixedMul(height << FRACBITS, sa)); - INT32 h1 = abs(FixedMul(width << FRACBITS, sa) + FixedMul(height << FRACBITS, ca)); - INT32 h2 = abs(FixedMul(-(width << FRACBITS), sa) + FixedMul(height << FRACBITS, ca)); - w1 = FixedInt(FixedCeil(w1 + (FRACUNIT/2))); - w2 = FixedInt(FixedCeil(w2 + (FRACUNIT/2))); - h1 = FixedInt(FixedCeil(h1 + (FRACUNIT/2))); - h2 = FixedInt(FixedCeil(h2 + (FRACUNIT/2))); - newwidth = max(width, max(w1, w2)); - newheight = max(height, max(h1, h2)); - } - - // check boundaries - { - fixed_t top[2][2]; - fixed_t bottom[2][2]; - - top[0][0] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS); - top[0][1] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS); - top[1][0] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS); - top[1][1] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS); - - bottom[0][0] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS); - bottom[0][1] = -FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS); - bottom[1][0] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS); - bottom[1][1] = -FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS); - - top[0][0] >>= FRACBITS; - top[0][1] >>= FRACBITS; - top[1][0] >>= FRACBITS; - top[1][1] >>= FRACBITS; - - bottom[0][0] >>= FRACBITS; - bottom[0][1] >>= FRACBITS; - bottom[1][0] >>= FRACBITS; - bottom[1][1] >>= FRACBITS; - -#define BOUNDARYWCHECK(b) (b[0] < 0 || b[0] >= width) -#define BOUNDARYHCHECK(b) (b[1] < 0 || b[1] >= height) -#define BOUNDARYADJUST(x) x *= 2 - // top left/right - if (BOUNDARYWCHECK(top[0]) || BOUNDARYWCHECK(top[1])) - BOUNDARYADJUST(newwidth); - // bottom left/right - else if (BOUNDARYWCHECK(bottom[0]) || BOUNDARYWCHECK(bottom[1])) - BOUNDARYADJUST(newwidth); - // top left/right - if (BOUNDARYHCHECK(top[0]) || BOUNDARYHCHECK(top[1])) - BOUNDARYADJUST(newheight); - // bottom left/right - else if (BOUNDARYHCHECK(bottom[0]) || BOUNDARYHCHECK(bottom[1])) - BOUNDARYADJUST(newheight); -#undef BOUNDARYWCHECK -#undef BOUNDARYHCHECK -#undef BOUNDARYADJUST - } - - // Draw the rotated sprite to a temporary buffer. - size = (newwidth * newheight); - if (!size) - size = (width * height); - - rawdst = Z_Malloc(size * sizeof(UINT16), PU_STATIC, NULL); - for (i = 0; i < size; i++) - rawdst[i] = 0xFF00; - - for (dy = 0; dy < newheight; dy++) - { - for (dx = 0; dx < newwidth; dx++) - { - INT32 x = (dx-ROTSPRITE_XCENTER) << FRACBITS; - INT32 y = (dy-ROTSPRITE_YCENTER) << FRACBITS; - INT32 sx = FixedMul(x, ca) + FixedMul(y, sa) + (px << FRACBITS); - INT32 sy = -FixedMul(x, sa) + FixedMul(y, ca) + (py << FRACBITS); - sx >>= FRACBITS; - sy >>= FRACBITS; - if (sx >= 0 && sy >= 0 && sx < width && sy < height) - rawdst[(dy*newwidth)+dx] = GetPatchPixel(patch, sx, sy, bflip); - } - } - - // make patch - newpatch = R_MaskedFlatToPatch(rawdst, newwidth, newheight, 0, 0, &size); - { - newpatch->leftoffset = (newpatch->width / 2) + (leftoffset - px); - newpatch->topoffset = (newpatch->height / 2) + (SHORT(patch->topoffset) - py); - } - - //BP: we cannot use special tric in hardware mode because feet in ground caused by z-buffer - if (rendermode != render_none) // not for psprite - newpatch->topoffset += FEETADJUST>>FRACBITS; - - // P_PrecacheLevel - if (devparm) spritememory += size; - - // convert everything to little-endian, for big-endian support - newpatch->width = SHORT(newpatch->width); - newpatch->height = SHORT(newpatch->height); - newpatch->leftoffset = SHORT(newpatch->leftoffset); - newpatch->topoffset = SHORT(newpatch->topoffset); + // Caveat: At the point RotSprite_GetFromPatchNum is called, no patch exists yet. + // So, the update has to be done right below here. + if (store) + UpdateCurrentRotatedPatchInfo(wad, lump, rendermode, rsvars.rollangle, rsvars.flip); #ifdef HWRENDER - if (rendermode == render_opengl) - { - GLPatch_t *grPatch = Z_Calloc(sizeof(GLPatch_t), PU_HWRPATCHINFO, NULL); - grPatch->mipmap = Z_Calloc(sizeof(GLMipmap_t), PU_HWRPATCHINFO, NULL); - grPatch->rawpatch = newpatch; - sprframe->rotsprite.patch[rot][angle] = (patch_t *)grPatch; - HWR_MakePatch(newpatch, grPatch, grPatch->mipmap, false); - } - else -#endif // HWRENDER - sprframe->rotsprite.patch[rot][angle] = newpatch; - - // free rotated image data - Z_Free(rawdst); - } - - // This rotation is cached now - sprframe->rotsprite.cached |= (1<patches[rsvars.rollangle])); } -#undef SPRITE_XCENTER -#undef SPRITE_YCENTER -#undef ROTSPRITE_XCENTER -#undef ROTSPRITE_YCENTER + + return patch; } -// -// R_FreeSingleRotSprite -// -// Free sprite rotation data from memory, for a single spritedef. -// -void R_FreeSingleRotSprite(spritedef_t *spritedef) +/** Creates a rotated patch from a sprite. + * + * \param wad The sprite's wad number. + * \param lump The sprite's lump number. + * \param tag Zone memory tag. + * \param rsvars Sprite rotation variables. + * \param store Store the rotated sprite into the patch reference list. + * \return The rotated sprite. + * \sa Patch_CacheRotatedPwad + */ +patch_t *Patch_CacheRotatedForSpritePwad(UINT16 wad, UINT16 lump, INT32 tag, rotsprite_vars_t rsvars, boolean store) { - UINT8 frame; - INT32 rot, ang; + lumpnum_t lumpnum = WADANDLUMP(wad, lump); + rotsprite_t *rotsprite = RotSprite_GetFromPatchNum(lumpnum, tag, rsvars, store); + patch_t *patch = NULL; + + if (rotsprite->patches[rsvars.rollangle]) + return rotsprite->patches[rsvars.rollangle]; + + rsvars.sprite = true; + rotsprite->vars = rsvars; + rotsprite->tag = tag; + + RotSprite_Create(rotsprite, rsvars); + patch = RotSprite_CreatePatch(rotsprite, rsvars); - for (frame = 0; frame < spritedef->numframes; frame++) - { - spriteframe_t *sprframe = &spritedef->spriteframes[frame]; - for (rot = 0; rot < 16; rot++) - { - if (sprframe->rotsprite.cached & (1<rotsprite.patch[rot][ang]; - if (rotsprite) - { #ifdef HWRENDER - if (rendermode == render_opengl) - { - GLPatch_t *grPatch = (GLPatch_t *)rotsprite; - if (grPatch->rawpatch) - { - Z_Free(grPatch->rawpatch); - grPatch->rawpatch = NULL; - } - if (grPatch->mipmap) - { - if (grPatch->mipmap->data) - { - Z_Free(grPatch->mipmap->data); - grPatch->mipmap->data = NULL; - } - Z_Free(grPatch->mipmap); - grPatch->mipmap = NULL; - } - } + if (rendermode != render_opengl) // uuggghhhhh #endif - Z_Free(rotsprite); - } - } - sprframe->rotsprite.cached &= ~(1<sprites; - for (i = 0; i < NUMPLAYERSPRITES*2; i++) { - R_FreeSingleRotSprite(skinsprites); - skinsprites++; + Z_ChangeTag(patch, tag); + Z_SetUser(patch, (void **)(&rotsprite->patches[rsvars.rollangle])); } + + return patch; } -// -// R_FreeAllRotSprite -// -// Free ALL sprite rotation data from memory. -// -void R_FreeAllRotSprite(void) +patch_t *Patch_CacheRotated(UINT32 lumpnum, INT32 tag, rotsprite_vars_t rsvars, boolean store) { - INT32 i; - size_t s; - for (s = 0; s < numsprites; s++) - R_FreeSingleRotSprite(&sprites[s]); - for (i = 0; i < numskins; ++i) - R_FreeSkinRotSprite(i); + return Patch_CacheRotatedPwad(WADFILENUM(lumpnum), LUMPNUM(lumpnum), tag, rsvars, store); } + +patch_t *Patch_CacheRotatedForSprite(UINT32 lumpnum, INT32 tag, rotsprite_vars_t rsvars, boolean store) +{ + return Patch_CacheRotatedForSpritePwad(WADFILENUM(lumpnum), LUMPNUM(lumpnum), tag, rsvars, store); +} + +patch_t *Patch_CacheRotatedName(const char *name, INT32 tag, rotsprite_vars_t rsvars, boolean store) +{ + lumpnum_t num = W_CheckNumForName(name); + if (num == LUMPERROR) + return Patch_CacheRotated(W_GetNumForName("MISSING"), tag, rsvars, store); + return Patch_CacheRotated(num, tag, rsvars, store); +} + +patch_t *Patch_CacheRotatedLongName(const char *name, INT32 tag, rotsprite_vars_t rsvars, boolean store) +{ + lumpnum_t num = W_CheckNumForLongName(name); + if (num == LUMPERROR) + return Patch_CacheRotated(W_GetNumForLongName("MISSING"), tag, rsvars, store); + return Patch_CacheRotated(num, tag, rsvars, store); +} + #endif diff --git a/src/r_patch.h b/src/r_patch.h index a2db6320c..bc7aba0c1 100644 --- a/src/r_patch.h +++ b/src/r_patch.h @@ -15,9 +15,53 @@ #define __R_PATCH__ #include "r_defs.h" +#include "r_patchtrees.h" +#include "w_wad.h" +#include "m_aatree.h" +#include "i_video.h" #include "doomdef.h" -// Structs +void Patch_InitInfo(wadfile_t *wadfile); + +void *Patch_CacheSoftware(UINT16 wad, UINT16 lump, INT32 tag, boolean store); +void *Patch_CacheGL(UINT16 wad, UINT16 lump, INT32 tag, boolean store); + +patchtreetype_t Patch_GetTreeType(rendermode_t mode); +patchtree_t *Patch_GetRendererTree(UINT16 wadnum, rendermode_t mode); +aatree_t *Patch_GetRendererBaseSubTree(UINT16 wadnum, rendermode_t mode); +#ifdef ROTSPRITE +aatree_t *Patch_GetRendererRotatedSubTree(UINT16 wadnum, rendermode_t mode, boolean flip); +#endif + +void *GetRendererPatchInfo(UINT16 wadnum, UINT16 lumpnum, rendermode_t mode); +void SetRendererPatchInfo(UINT16 wadnum, UINT16 lumpnum, rendermode_t mode, void *ptr); +void UpdateCurrentPatchInfo(UINT16 wadnum, UINT16 lumpnum, rendermode_t mode); + +#ifdef ROTSPRITE +void *GetRotatedPatchInfo(UINT16 wadnum, UINT16 lumpnum, rendermode_t mode, boolean flip); +void SetRotatedPatchInfo(UINT16 wadnum, UINT16 lumpnum, rendermode_t mode, boolean flip, void *ptr); +void UpdateCurrentRotatedPatchInfo(UINT16 wadnum, UINT16 lumpnum, rendermode_t mode, INT32 rollangle, boolean flip); +#endif + +struct patchreference_s +{ + struct patchreference_s *prev, *next; + UINT16 wad, lump; + INT32 tag; + boolean flip; + INT32 rollangle; + void *ptr; +}; +typedef struct patchreference_s patchreference_t; + +patchreference_t *Patch_FindReference(UINT16 wad, UINT16 lump, INT32 rollangle, boolean flip); +patchreference_t *Patch_StoreReference(UINT16 wad, UINT16 lump, INT32 tag, void *ptr, INT32 rollangle, boolean flip); + +void Patch_UpdateReferences(void); +void Patch_FreeReferences(void); + +// This should be in r_rotsprite.h, but that file +// includes this one, so this file can't include that one. typedef enum { ROTAXIS_X, // Roll (the default) @@ -33,19 +77,21 @@ typedef struct typedef struct { - spriteframepivot_t pivot[64]; + spriteframepivot_t pivot[64]; // Max number of frames in a sprite. boolean available; } spriteinfo_t; +boolean PixelMap_ApplyToColumn(pixelmap_t *pmap, INT32 *map, patch_t *patch, UINT8 *post, size_t *colsize, boolean flipped); +UINT8 *Patch_GetPixel(patch_t *patch, INT32 x, INT32 y, boolean flip); + // Conversions between patches / flats / textures... boolean R_CheckIfPatch(lumpnum_t lump); void R_TextureToFlat(size_t tex, UINT8 *flat); void R_PatchToFlat(patch_t *patch, UINT8 *flat); -void R_PatchToMaskedFlat(patch_t *patch, UINT16 *raw, boolean flip); patch_t *R_FlatToPatch(UINT8 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize, boolean transparency); -patch_t *R_MaskedFlatToPatch(UINT16 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize); +patch_t *R_TransparentFlatToPatch(UINT16 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize); -// Portable Network Graphics +// PNGs boolean R_IsLumpPNG(const UINT8 *d, size_t s); #define W_ThrowPNGError(lumpname, wadfilename) I_Error("W_Wad: Lump \"%s\" in file \"%s\" is a .png - please convert to either Doom or Flat (raw) image format.", lumpname, wadfilename); // Fears Of LJ Sonic @@ -62,13 +108,24 @@ void R_ParseSPRTINFOLump(UINT16 wadNum, UINT16 lumpNum); // Sprite rotation #ifdef ROTSPRITE -INT32 R_GetRollAngle(angle_t rollangle); -void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, spriteframe_t *sprframe, INT32 rot, UINT8 flip); -void R_FreeSingleRotSprite(spritedef_t *spritedef); -void R_FreeSkinRotSprite(size_t skinnum); +// Arguments for RotSprite_ functions. +typedef struct +{ + INT32 rollangle; + boolean flip; + boolean sprite; + spriteframepivot_t *pivot; +} rotsprite_vars_t; + +patch_t *Patch_CacheRotated(UINT32 lumpnum, INT32 tag, rotsprite_vars_t rsvars, boolean store); +patch_t *Patch_CacheRotatedForSprite(UINT32 lumpnum, INT32 tag, rotsprite_vars_t rsvars, boolean store); +patch_t *Patch_CacheRotatedPwad(UINT16 wad, UINT16 lump, INT32 tag, rotsprite_vars_t rsvars, boolean store); +patch_t *Patch_CacheRotatedForSpritePwad(UINT16 wad, UINT16 lump, INT32 tag, rotsprite_vars_t rsvars, boolean store); +patch_t *Patch_CacheRotatedName(const char *name, INT32 tag, rotsprite_vars_t rsvars, boolean store); +patch_t *Patch_CacheRotatedLongName(const char *name, INT32 tag, rotsprite_vars_t rsvars, boolean store); + extern fixed_t rollcosang[ROTANGLES]; extern fixed_t rollsinang[ROTANGLES]; -void R_FreeAllRotSprite(void); #endif #endif // __R_PATCH__ diff --git a/src/r_patchtrees.h b/src/r_patchtrees.h new file mode 100644 index 000000000..5530e6c04 --- /dev/null +++ b/src/r_patchtrees.h @@ -0,0 +1,36 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2020 by Jaime "Lactozilla" Passos. +// Copyright (C) 2020 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file r_patchtrees.h +/// \brief Patch tree definitions. + +#ifndef __R_PATCHTREES__ +#define __R_PATCHTREES__ + +#include "m_aatree.h" + +// Renderer tree types +typedef enum patchtreetype_e +{ + patchtree_software, // Software. + patchtree_mipmap, // OpenGL, or any hardware renderer. + + num_patchtrees, +} patchtreetype_t; + +// Renderer patch trees +typedef struct patchtree_s +{ + aatree_t *base; +#ifdef ROTSPRITE + aatree_t *rotated[2]; // Sprite rotation stores flipped and non-flipped variants of a patch. +#endif +} patchtree_t; + +#endif // __R_PATCHTREES__ diff --git a/src/r_rotsprite.c b/src/r_rotsprite.c new file mode 100644 index 000000000..deb5fce04 --- /dev/null +++ b/src/r_rotsprite.c @@ -0,0 +1,437 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2019-2020 by Jaime "Lactozilla" Passos. +// Copyright (C) 2019-2020 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file r_rotsprite.c +/// \brief Rotated patch generation. + +#include "byteptr.h" +#include "dehacked.h" +#include "i_video.h" +#include "r_data.h" +#include "r_draw.h" +#include "r_patch.h" +#include "r_rotsprite.h" +#include "r_things.h" +#include "z_zone.h" +#include "w_wad.h" + +#ifdef HWRENDER +#include "hardware/hw_glob.h" +#endif + +#ifdef ROTSPRITE +fixed_t rollcosang[ROTANGLES]; +fixed_t rollsinang[ROTANGLES]; + +static unsigned char imgbuf[1<<26]; + +/** Get a rotation angle from a roll angle. + * + * \param rollangle The roll angle. + * \return The rotation angle. + */ +INT32 R_GetRollAngle(angle_t rollangle) +{ + INT32 ra = AngleFixed(rollangle)>>FRACBITS; +#if (ROTANGDIFF > 1) + ra += (ROTANGDIFF/2); +#endif + ra /= ROTANGDIFF; + ra %= ROTANGLES; + return ra; +} + +/** Get rotated sprite info for a patch. + * + * \param wad The patch's wad number. + * \param lump The patch's lump number. + * \param tag Zone memory tag. + * \param rsvars Sprite rotation variables. + * \param store Store the rotated patch into the patch reference list. + * \return The rotated sprite info. + * \sa Patch_CacheRotatedPwad + */ +rotsprite_t *RotSprite_GetFromPatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag, rotsprite_vars_t rsvars, boolean store) +{ + void *cache = GetRotatedPatchInfo(wad, lump, rendermode, rsvars.flip); + if (!GetRotatedPatchInfo(wad, lump, rendermode, rsvars.flip)) + { + rotsprite_t *ptr = Z_Calloc(sizeof(rotsprite_t), tag, &cache); + ptr->lumpnum = WADANDLUMP(wad, lump); + SetRotatedPatchInfo(wad, lump, rendermode, rsvars.flip, cache); + return (void *)ptr; + } + else + Z_ChangeTag(cache, tag); + + // insert into list + if (store) + Patch_StoreReference(wad, lump, tag, cache, rsvars.rollangle, rsvars.flip); + + return cache; +} + +rotsprite_t *RotSprite_GetFromPatchNum(lumpnum_t lumpnum, INT32 tag, rotsprite_vars_t rsvars, boolean store) +{ + return RotSprite_GetFromPatchNumPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum),tag,rsvars,store); +} + +rotsprite_t *RotSprite_GetFromPatchName(const char *name, INT32 tag, rotsprite_vars_t rsvars, boolean store) +{ + lumpnum_t num = W_CheckNumForName(name); + if (num == LUMPERROR) + return RotSprite_GetFromPatchNum(W_GetNumForName("MISSING"), tag, rsvars, store); + return RotSprite_GetFromPatchNum(num, tag, rsvars, store); +} + +rotsprite_t *RotSprite_GetFromPatchLongName(const char *name, INT32 tag, rotsprite_vars_t rsvars, boolean store) +{ + lumpnum_t num = W_CheckNumForLongName(name); + if (num == LUMPERROR) + return RotSprite_GetFromPatchNum(W_GetNumForLongName("MISSING"), tag, rsvars, store); + return RotSprite_GetFromPatchNum(num, tag, rsvars, store); +} + +/** Creates a rotated sprite by calculating a pixel map. + * Caches column data and patches between levels. + * + * \param rotsprite The rotated sprite info. + * \param rsvars Sprite rotation variables. + * \sa RotSprite_CreatePatch + */ +void RotSprite_Create(rotsprite_t *rotsprite, rotsprite_vars_t rsvars) +{ + patch_t *patch; + pixelmap_t *pixelmap = &rotsprite->pixelmap[rsvars.rollangle]; + lumpnum_t lump = rotsprite->lumpnum; + + // Sprite lump is invalid. + if (lump == LUMPERROR) + return; + + // Cache the patch. + patch = (patch_t *)W_CacheSoftwarePatchNum(lump, PU_CACHE); + + // If this pixel map was not generated, do it. + if (!rotsprite->cached[rsvars.rollangle]) + { + RotSprite_CreatePixelMap(patch, pixelmap, rsvars); + rotsprite->cached[rsvars.rollangle] = true; + } +} + +/** Caches columns of a rotated sprite, applying the pixel map. + * + * \param pixelmap The source pixel map. + * \param cache The destination pixel map cache. + * \param patch The source patch. + * \param rsvars Sprite rotation variables. + * \sa RotSprite_CreatePatch + */ +void RotSprite_CreateColumns(pixelmap_t *pixelmap, pmcache_t *cache, patch_t *patch, rotsprite_vars_t rsvars) +{ + void **colofs; + UINT8 *data; + boolean *colexists; + size_t *coltbl; + static UINT8 pixelmapcol[0xFFFF]; + size_t totalsize = 0, colsize = 0; + INT16 width = pixelmap->width, x; + + Z_Malloc(width * sizeof(void **), PU_LEVEL, &cache->columnofs); + Z_Malloc(width * sizeof(void *), PU_LEVEL, &cache->columnsize); + + colexists = Z_Calloc(width * sizeof(boolean), PU_STATIC, NULL); + coltbl = Z_Calloc(width * sizeof(size_t), PU_STATIC, NULL); + colofs = cache->columnofs; + + for (x = 0; x < width; x++) + { + size_t colpos = totalsize; + colexists[x] = PixelMap_ApplyToColumn(pixelmap, &(pixelmap->map[x * pixelmap->height]), patch, pixelmapcol, &colsize, rsvars.flip); + cache->columnsize[x] = colsize; + totalsize += colsize; + + // copy pixels + if (colexists[x]) + { + data = Z_Realloc(cache->data, totalsize, PU_LEVEL, &cache->data); + data += colpos; + coltbl[x] = colpos; + M_Memcpy(data, pixelmapcol, colsize); + } + } + + for (x = 0; x < width; x++) + { + if (colexists[x]) + colofs[x] = &(cache->data[coltbl[x]]); + else + colofs[x] = NULL; + } + + Z_Free(colexists); + Z_Free(coltbl); +} + +/** Calculates the dimensions of a rotated rectangle. + * + * \param width Rectangle width. + * \param height Rectangle height. + * \param ca Cosine for the angle. + * \param sa Sine for the angle. + * \param pivot Rotation pivot. + * \param newwidth The width for the rotated rectangle. + * \param newheight The height for the rotated rectangle. + * \sa RotSprite_CreatePixelMap + */ +static void CalculateRotatedRectangleDimensions(INT16 width, INT16 height, fixed_t ca, fixed_t sa, spriteframepivot_t *pivot, INT16 *newwidth, INT16 *newheight) +{ + if (pivot) + { + *newwidth = width + (height * 2); + *newheight = height + (width * 2); + } + else + { + fixed_t fw = (width * FRACUNIT); + fixed_t fh = (height * FRACUNIT); + INT32 w1 = abs(FixedMul(fw, ca) - FixedMul(fh, sa)); + INT32 w2 = abs(FixedMul(-fw, ca) - FixedMul(fh, sa)); + INT32 h1 = abs(FixedMul(fw, sa) + FixedMul(fh, ca)); + INT32 h2 = abs(FixedMul(-fw, sa) + FixedMul(fh, ca)); + w1 = FixedInt(FixedCeil(w1 + (FRACUNIT/2))); + w2 = FixedInt(FixedCeil(w2 + (FRACUNIT/2))); + h1 = FixedInt(FixedCeil(h1 + (FRACUNIT/2))); + h2 = FixedInt(FixedCeil(h2 + (FRACUNIT/2))); + *newwidth = max(width, max(w1, w2)); + *newheight = max(height, max(h1, h2)); + } +} + +/** Creates a pixel map for a rotated patch. + * + * \param patch The source patch. + * \param pixelmap The destination pixel map. + * \param rsvars Sprite rotation variables. + * \sa RotSprite_CreatePixelMap + */ +void RotSprite_CreatePixelMap(patch_t *patch, pixelmap_t *pixelmap, rotsprite_vars_t rsvars) +{ + size_t size; + INT32 dx, dy; + INT16 newwidth, newheight; + fixed_t ca = rollcosang[rsvars.rollangle]; + fixed_t sa = rollsinang[rsvars.rollangle]; + + INT16 width = SHORT(patch->width); + INT16 height = SHORT(patch->height); + INT16 leftoffset = SHORT(patch->leftoffset); + + spriteframepivot_t pivot; + INT16 rotxcenter, rotycenter; + spriteframepivot_t *spritepivot = rsvars.pivot; + + pivot.x = (spritepivot ? spritepivot->x : (rsvars.sprite ? leftoffset : (width / 2))); + pivot.y = (spritepivot ? spritepivot->y : (height / 2)); + + if (rsvars.flip) + { + pivot.x = width - pivot.x; + leftoffset = width - leftoffset; + } + + // Find the dimensions of the rotated patch. + CalculateRotatedRectangleDimensions(width, height, ca, sa, (spritepivot ? &pivot : NULL), &newwidth, &newheight); + rotxcenter = (newwidth / 2); + rotycenter = (newheight / 2); + size = (newwidth * newheight); + + // Build pixel map. + if (pixelmap->map) + Z_Free(pixelmap->map); + pixelmap->map = Z_Calloc(size * sizeof(INT32) * 2, PU_STATIC, NULL); + pixelmap->size = size; + pixelmap->width = newwidth; + pixelmap->height = newheight; + + // Calculate the position of every pixel. + for (dy = 0; dy < newheight; dy++) + { + for (dx = 0; dx < newwidth; dx++) + { + INT32 dst = (dx*newheight)+dy; + INT32 x = (dx-rotxcenter) << FRACBITS; + INT32 y = (dy-rotycenter) << FRACBITS; + INT32 sx = FixedMul(x, ca) + FixedMul(y, sa) + (pivot.x << FRACBITS); + INT32 sy = -FixedMul(x, sa) + FixedMul(y, ca) + (pivot.y << FRACBITS); + sx >>= FRACBITS; + sy >>= FRACBITS; + pixelmap->map[dst] = sy; + pixelmap->map[dst + size] = sx; + } + } + + // Set offsets. + if (rsvars.sprite) + { + pixelmap->leftoffset = (newwidth / 2) + (leftoffset - pivot.x); + pixelmap->topoffset = (newheight / 2) + (SHORT(patch->topoffset) - pivot.y); + pixelmap->topoffset += FEETADJUST>>FRACBITS; + } + else + { + pixelmap->leftoffset = leftoffset; + pixelmap->topoffset = SHORT(patch->topoffset); + } +} + +/** Creates a rotated patch from sprite rotation data. + * + * \param rotsprite The rotated sprite info. + * \param rsvars Sprite rotation variables. + * \return The rotated patch. + * \sa RotSprite_CreatePixelMap + */ +patch_t *RotSprite_CreatePatch(rotsprite_t *rotsprite, rotsprite_vars_t rsvars) +{ + UINT8 *img, *imgptr = imgbuf; + pixelmap_t *pixelmap = &rotsprite->pixelmap[rsvars.rollangle]; + patch_t *patch = (patch_t *)W_CacheSoftwarePatchNum(rotsprite->lumpnum, PU_CACHE); + pmcache_t *pmcache = &pixelmap->cache; + UINT32 x, width = pixelmap->width; + UINT8 *colpointers; + void **colofs; + size_t size = 0; + + WRITEINT16(imgptr, (INT16)width); + WRITEINT16(imgptr, (INT16)pixelmap->height); + WRITEINT16(imgptr, pixelmap->leftoffset); + WRITEINT16(imgptr, pixelmap->topoffset); + + colpointers = imgptr; + imgptr += width*4; + + if (!pmcache->columnofs) + RotSprite_CreateColumns(pixelmap, pmcache, patch, rsvars); + colofs = pmcache->columnofs; + + for (x = 0; x < width; x++) + { + column_t *column = (column_t *)(colofs[x]); + WRITEINT32(colpointers, imgptr - imgbuf); + if (column) + { + size = pmcache->columnsize[x]; + WRITEMEM(imgptr, column, size); + } + else + WRITEUINT8(imgptr, 0xFF); + } + + size = imgptr-imgbuf; + img = Z_Malloc(size, PU_STATIC, NULL); + M_Memcpy(img, imgbuf, size); + +#ifdef HWRENDER + // Ugh + if (rendermode == render_opengl) + { + GLPatch_t *grPatch = Z_Calloc(sizeof(GLPatch_t), PU_HWRPATCHINFO, NULL); + grPatch->mipmap = Z_Calloc(sizeof(GLMipmap_t), PU_HWRPATCHINFO, NULL); + grPatch->patch = (patch_t *)img; + rotsprite->patches[rsvars.rollangle] = (patch_t *)grPatch; + HWR_MakePatch((patch_t *)img, grPatch, grPatch->mipmap, false); + } + else +#endif + rotsprite->patches[rsvars.rollangle] = (patch_t *)img; + + return rotsprite->patches[rsvars.rollangle]; +} + +/** Recreates sprite rotation data in memory. + * + * \param rotsprite The rotated sprite info. + * \sa RotSprite_RecreateAll + * \sa Patch_CacheRotated + * \sa Patch_CacheRotatedForSprite + */ +void RotSprite_Recreate(rotsprite_t *rotsprite, rendermode_t rmode) +{ + INT32 ang; + for (ang = 0; ang < ROTANGLES; ang++) + { + if (rotsprite->cached[ang]) + { + pixelmap_t *pixelmap = &rotsprite->pixelmap[ang]; + pmcache_t *cache = &pixelmap->cache; + + rotsprite->cached[ang] = false; + + if (pixelmap->map) + Z_Free(pixelmap->map); + if (cache->columnofs) + Z_Free(cache->columnofs); + if (cache->columnsize) + Z_Free(cache->columnsize); + if (cache->data) + Z_Free(cache->data); + + pixelmap->map = NULL; + cache->columnofs = NULL; + cache->columnsize = NULL; + cache->data = NULL; + +#ifdef HWRENDER + if (rmode == render_opengl) + { + GLPatch_t *grPatch = (GLPatch_t *)(rotsprite->patches[ang]); + if (grPatch && grPatch->patch) + { + Z_Free(grPatch->patch); + grPatch->patch = NULL; + } + } + else +#endif + if (rotsprite->patches[ang]) + Z_Free(rotsprite->patches[ang]); + rotsprite->patches[ang] = NULL; + + if (rotsprite->vars.sprite) + Patch_CacheRotatedForSprite(rotsprite->lumpnum, rotsprite->tag, rotsprite->vars, false); + else + Patch_CacheRotated(rotsprite->lumpnum, rotsprite->tag, rotsprite->vars, false); + } + } +} + +/** Recreates all sprite rotation data in memory. + * + * \sa RotSprite_Recreate + */ +void RotSprite_RecreateAll(void) +{ + // TODO: Write this in a more efficient way. + INT32 w, l, r, f; + for (r = render_first; r < render_last; r++) + for (w = 0; w < numwadfiles; w++) + for (l = 0; l < wadfiles[w]->numlumps; l++) + { + for (f = 0; f < 2; f++) + { + rotsprite_t *rotsprite = GetRotatedPatchInfo(w, l, r, (f ? true : false)); + if (rotsprite) + RotSprite_Recreate(rotsprite, r); + } + } +} + +#endif // ROTSPRITE diff --git a/src/r_rotsprite.h b/src/r_rotsprite.h new file mode 100644 index 000000000..a4447e253 --- /dev/null +++ b/src/r_rotsprite.h @@ -0,0 +1,53 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2019-2020 by Jaime "Lactozilla" Passos. +// Copyright (C) 2019-2020 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file r_rotsprite.h +/// \brief Rotated patch generation. + +#ifndef __R_ROTSPRITE__ +#define __R_ROTSPRITE__ + +#include "r_defs.h" +#include "r_patch.h" +#include "doomtype.h" + +#ifdef ROTSPRITE +INT32 R_GetRollAngle(angle_t rollangle); + +typedef struct +{ + pixelmap_t pixelmap[ROTANGLES]; + patch_t *patches[ROTANGLES]; + boolean cached[ROTANGLES]; + + UINT32 lumpnum; + rotsprite_vars_t vars; + INT32 tag; +} rotsprite_t; + +rotsprite_t *RotSprite_GetFromPatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag, rotsprite_vars_t rsvars, boolean store); +rotsprite_t *RotSprite_GetFromPatchNum(lumpnum_t lumpnum, INT32 tag, rotsprite_vars_t rsvars, boolean store); +rotsprite_t *RotSprite_GetFromPatchName(const char *name, INT32 tag, rotsprite_vars_t rsvars, boolean store); +rotsprite_t *RotSprite_GetFromPatchLongName(const char *name, INT32 tag, rotsprite_vars_t rsvars, boolean store); + +void RotSprite_Create(rotsprite_t *rotsprite, rotsprite_vars_t rsvars); +void RotSprite_CreateColumns(pixelmap_t *pixelmap, pmcache_t *cache, patch_t *patch, rotsprite_vars_t rsvars); +void RotSprite_CreatePixelMap(patch_t *patch, pixelmap_t *pixelmap, rotsprite_vars_t rsvars); +patch_t *RotSprite_CreatePatch(rotsprite_t *rotsprite, rotsprite_vars_t rsvars); + +void RotSprite_Recreate(rotsprite_t *rotsprite, rendermode_t rmode); +void RotSprite_RecreateAll(void); + +void RotSprite_InitPatchTree(patchtree_t *rcache); +void RotSprite_AllocCurrentPatchInfo(patchinfo_t *patchinfo, UINT16 lumpnum); +int RotSprite_GetCurrentPatchInfoIdx(INT32 rollangle, boolean flip); + +#endif // ROTSPRITE + +#endif // __R_ROTSPRITE__ diff --git a/src/r_sky.c b/src/r_sky.c index 7cdcfa44d..be194dfad 100644 --- a/src/r_sky.c +++ b/src/r_sky.c @@ -54,9 +54,6 @@ INT32 globallevelskynum; Called at loadlevel after skytexture is set, or when sky texture changes. - \warning wallcolfunc should be set at R_ExecuteSetViewSize() - I don't bother because we don't use low detail anymore - \return void */ void R_SetupSkyDraw(void) diff --git a/src/r_things.c b/src/r_things.c index d2647b811..57a4f365a 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -12,6 +12,7 @@ /// \brief Refresh of things, i.e. objects represented by sprites #include "doomdef.h" +#include "byteptr.h" #include "console.h" #include "g_game.h" #include "r_local.h" @@ -25,6 +26,7 @@ #include "i_system.h" #include "r_things.h" #include "r_patch.h" +#include "r_rotsprite.h" #include "r_plane.h" #include "r_portal.h" #include "p_tick.h" @@ -96,7 +98,7 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch { char cn = R_Frame2Char(frame), cr = R_Rotation2Char(rotation); // for debugging - INT32 r, ang; + INT32 r; lumpnum_t lumppat = wad; lumppat <<= 16; lumppat += lump; @@ -104,16 +106,6 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch if (maxframe ==(size_t)-1 || frame > maxframe) maxframe = frame; - // rotsprite -#ifdef ROTSPRITE - sprtemp[frame].rotsprite.cached = 0; - for (r = 0; r < 16; r++) - { - for (ang = 0; ang < ROTANGLES; ang++) - sprtemp[frame].rotsprite.patch[r][ang] = NULL; - } -#endif/*ROTSPRITE*/ - if (rotation == 0) { // the lump should be used for all rotations @@ -240,9 +232,6 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 // if so, it might patch only certain frames, not all if (spritedef->numframes) // (then spriteframes is not null) { -#ifdef ROTSPRITE - R_FreeSingleRotSprite(spritedef); -#endif // copy the already defined sprite frames M_Memcpy(sprtemp, spritedef->spriteframes, spritedef->numframes * sizeof (spriteframe_t)); @@ -397,9 +386,6 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 if (spritedef->numframes && // has been allocated spritedef->numframes < maxframe) // more frames are defined ? { -#ifdef ROTSPRITE - R_FreeSingleRotSprite(spritedef); -#endif Z_Free(spritedef->spriteframes); spritedef->spriteframes = NULL; } @@ -607,7 +593,7 @@ void R_DrawMaskedColumn(column_t *column) INT32 topscreen; INT32 bottomscreen; fixed_t basetexturemid; - INT32 topdelta, prevdelta = 0; + INT32 topdelta = 0, prevdelta = 0; basetexturemid = dc_texturemid; @@ -671,8 +657,8 @@ void R_DrawFlippedMaskedColumn(column_t *column) INT32 topscreen; INT32 bottomscreen; fixed_t basetexturemid = dc_texturemid; - INT32 topdelta, prevdelta = -1; - UINT8 *d,*s; + INT32 topdelta = 0, prevdelta = -1; + UINT8 *d, *s; for (; column->topdelta != 0xff ;) { @@ -744,6 +730,7 @@ static void R_DrawVisSprite(vissprite_t *vis) fixed_t this_scale = vis->mobj->scale; INT32 x1, x2; INT64 overflow_test; + int colfunctype = BASEDRAWFUNC; if (!patch) return; @@ -760,12 +747,11 @@ static void R_DrawVisSprite(vissprite_t *vis) if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return; // ditto } - colfunc = colfuncs[BASEDRAWFUNC]; // hack: this isn't resetting properly somewhere. dc_colormap = vis->colormap; if (!(vis->cut & SC_PRECIP) && (vis->mobj->flags & (MF_ENEMY|MF_BOSS)) && (vis->mobj->flags2 & MF2_FRET) && !(vis->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash" { // translate certain pixels to white - colfunc = colfuncs[COLDRAWFUNC_TRANS]; + colfunctype = COLDRAWFUNC_TRANS; if (vis->mobj->type == MT_CYBRAKDEMON || vis->mobj->colorized) dc_translation = R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE); else if (vis->mobj->type == MT_METALSONIC_BATTLE) @@ -775,7 +761,7 @@ static void R_DrawVisSprite(vissprite_t *vis) } else if (vis->mobj->color && vis->transmap) // Color mapping { - colfunc = colfuncs[COLDRAWFUNC_TRANSTRANS]; + colfunctype = COLDRAWFUNC_TRANSTRANS; dc_transmap = vis->transmap; if (!(vis->cut & SC_PRECIP) && vis->mobj->colorized) dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); @@ -799,13 +785,13 @@ static void R_DrawVisSprite(vissprite_t *vis) } else if (vis->transmap) { - colfunc = colfuncs[COLDRAWFUNC_FUZZY]; + colfunctype = COLDRAWFUNC_FUZZY; dc_transmap = vis->transmap; //Fab : 29-04-98: translucency table } else if (vis->mobj->color) { // translate green skin to another color - colfunc = colfuncs[COLDRAWFUNC_TRANS]; + colfunctype = COLDRAWFUNC_TRANS; // New colormap stuff for skins Tails 06-07-2002 if (!(vis->cut & SC_PRECIP) && vis->mobj->colorized) @@ -830,7 +816,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 = colfuncs[COLDRAWFUNC_TRANS]; + colfunctype = COLDRAWFUNC_TRANS; dc_translation = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_BLUE, GTC_CACHE); } @@ -890,6 +876,8 @@ static void R_DrawVisSprite(vissprite_t *vis) localcolfunc = (vis->cut & SC_VFLIP) ? R_DrawFlippedMaskedColumn : R_DrawMaskedColumn; lengthcol = SHORT(patch->height); + colfunc = colfuncs[colfunctype]; + // Split drawing loops for paper and non-paper to reduce conditional checks per sprite if (vis->scalestep) { @@ -925,9 +913,9 @@ static void R_DrawVisSprite(vissprite_t *vis) for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale, sprtopscreen += vis->shear.tan) { #ifdef RANGECHECK - texturecolumn = frac>>FRACBITS; + texturecolumn = (frac>>FRACBITS); if (texturecolumn < 0 || texturecolumn >= pwidth) - I_Error("R_DrawSpriteRange: bad texturecolumn at %d from end", vis->x2 - dc_x); + I_Error("R_DrawVisSprite: bad texturecolumn at %d from end", vis->x2 - dc_x); column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn])); #else column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[frac>>FRACBITS])); @@ -1394,11 +1382,11 @@ static void R_ProjectSprite(mobj_t *thing) INT32 light = 0; fixed_t this_scale = thing->scale; - // rotsprite + patch_t *spr_patch = NULL; fixed_t spr_width, spr_height; fixed_t spr_offset, spr_topoffset; + #ifdef ROTSPRITE - patch_t *rotsprite = NULL; INT32 rollangle = 0; #endif @@ -1443,7 +1431,7 @@ static void R_ProjectSprite(mobj_t *thing) thing->frame = states[S_UNKNOWN].frame; sprdef = &sprites[thing->sprite]; #ifdef ROTSPRITE - sprinfo = NULL; + sprinfo = &spriteinfo[thing->sprite]; #endif frame = thing->frame&FF_FRAMEMASK; } @@ -1452,7 +1440,7 @@ static void R_ProjectSprite(mobj_t *thing) { sprdef = &sprites[thing->sprite]; #ifdef ROTSPRITE - sprinfo = NULL; + sprinfo = &spriteinfo[thing->sprite]; #endif if (frame >= sprdef->numframes) @@ -1525,23 +1513,30 @@ static void R_ProjectSprite(mobj_t *thing) spr_topoffset = spritecachedinfo[lump].topoffset; #ifdef ROTSPRITE - if (thing->rollangle) + rollangle = R_GetRollAngle(thing->rollangle); + if (rollangle) { - rollangle = R_GetRollAngle(thing->rollangle); - if (!(sprframe->rotsprite.cached & (1<sprite, frame, sprinfo, sprframe, rot, flip); - rotsprite = sprframe->rotsprite.patch[rot][rollangle]; - if (rotsprite != NULL) - { - spr_width = SHORT(rotsprite->width) << FRACBITS; - spr_height = SHORT(rotsprite->height) << FRACBITS; - spr_offset = SHORT(rotsprite->leftoffset) << FRACBITS; - spr_topoffset = SHORT(rotsprite->topoffset) << FRACBITS; - // flip -> rotate, not rotate -> flip - flip = 0; - } + spriteframepivot_t *pivot = (sprinfo->available) ? &sprinfo->pivot[(thing->frame & FF_FRAMEMASK)] : NULL; + static rotsprite_vars_t rsvars; + + patch_t *rotpatch; + + rsvars.rollangle = rollangle; + rsvars.sprite = true; + rsvars.pivot = pivot; + rsvars.flip = (!!flip); + + rotpatch = Patch_CacheRotatedForSprite(sprframe->lumppat[rot], PU_LEVEL, rsvars, false); + spr_patch = rotpatch; + spr_width = SHORT(rotpatch->width) << FRACBITS; + spr_height = SHORT(rotpatch->height) << FRACBITS; + spr_offset = SHORT(rotpatch->leftoffset) << FRACBITS; + spr_topoffset = SHORT(rotpatch->topoffset) << FRACBITS; + + // flip -> rotate, not rotate -> flip + flip = 0; } -#endif +#endif // ROTSPRITE flip = !flip != !hflip; @@ -1794,6 +1789,7 @@ static void R_ProjectSprite(mobj_t *thing) iscale = FixedDiv(FRACUNIT, xscale); + // Flipping if (flip) { vis->startfrac = spr_width-1; @@ -1813,12 +1809,9 @@ static void R_ProjectSprite(mobj_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 -#ifdef ROTSPRITE - if (rotsprite != NULL) - vis->patch = rotsprite; - else -#endif - vis->patch = W_CachePatchNum(sprframe->lumppat[rot], PU_CACHE); + if (spr_patch == NULL) + spr_patch = W_CachePatchNum(sprframe->lumppat[rot], PU_CACHE); + vis->patch = spr_patch; // // determine the colormap (lightlevel & special effects) diff --git a/src/screen.c b/src/screen.c index e7ff9e735..d424264a2 100644 --- a/src/screen.c +++ b/src/screen.c @@ -28,6 +28,7 @@ #include "d_main.h" #include "d_clisrv.h" #include "f_finale.h" +#include "y_inter.h" // usebuffer #include "i_sound.h" // closed captions #include "s_sound.h" // ditto #include "g_game.h" // ditto @@ -63,7 +64,6 @@ consvar_t cv_scr_height = {"scr_height", "800", CV_SAVE, CV_Unsigned, NULL, 0, N consvar_t cv_scr_depth = {"scr_depth", "16 bits", CV_SAVE, scr_depth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_renderview = {"renderview", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -static void SCR_ActuallyChangeRenderer(void); CV_PossibleValue_t cv_renderer_t[] = { {1, "Software"}, #ifdef HWRENDER @@ -71,7 +71,7 @@ CV_PossibleValue_t cv_renderer_t[] = { #endif {0, NULL} }; -consvar_t cv_renderer = {"renderer", "Software", CV_SAVE|CV_NOLUA|CV_CALL, cv_renderer_t, SCR_ChangeRenderer, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_renderer = {"renderer", "Software", CV_SAVE|CV_NOLUA|CV_CALL, cv_renderer_t, SCR_SetTargetRenderer, 0, NULL, NULL, 0, 0, NULL}; static void SCR_ChangeFullscreen(void); @@ -81,7 +81,6 @@ consvar_t cv_fullscreen = {"fullscreen", "Yes", CV_SAVE|CV_CALL, CV_YesNo, SCR_C // 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() // ========================================================================= @@ -202,14 +201,15 @@ void SCR_SetMode(void) // Lactozilla: Renderer switching if (setrenderneeded) { - Z_PreparePatchFlush(); - needpatchflush = true; - needpatchrecache = true; + // stop recording movies (APNG only) + if (setrenderneeded && (moviemode == MM_APNG)) + M_StopMovie(); + VID_CheckRenderer(); - if (!setmodeneeded) - VID_SetMode(vid.modenum); + vid.recalc = 1; } + // Set the video mode in the video interface. if (setmodeneeded) VID_SetMode(--setmodeneeded); @@ -279,34 +279,9 @@ void SCR_Startup(void) vid.modenum = 0; - vid.dupx = vid.width / BASEVIDWIDTH; - vid.dupy = vid.height / BASEVIDHEIGHT; - vid.dupx = vid.dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); - vid.fdupx = FixedDiv(vid.width*FRACUNIT, BASEVIDWIDTH*FRACUNIT); - vid.fdupy = FixedDiv(vid.height*FRACUNIT, BASEVIDHEIGHT*FRACUNIT); - -#ifdef HWRENDER - if (rendermode != render_opengl && rendermode != render_none) // This was just placing it incorrectly at non aspect correct resolutions in opengl -#endif - vid.fdupx = vid.fdupy = (vid.fdupx < vid.fdupy ? vid.fdupx : vid.fdupy); - - 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(); + V_Recalc(); + CV_RegisterVar(&cv_ticrate); CV_RegisterVar(&cv_constextsize); @@ -320,41 +295,7 @@ 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; - vid.dupy = vid.height / BASEVIDHEIGHT; - vid.dupx = vid.dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); - vid.fdupx = FixedDiv(vid.width*FRACUNIT, BASEVIDWIDTH*FRACUNIT); - vid.fdupy = FixedDiv(vid.height*FRACUNIT, BASEVIDHEIGHT*FRACUNIT); - -#ifdef HWRENDER - //if (rendermode != render_opengl && rendermode != render_none) // This was just placing it incorrectly at non aspect correct resolutions in opengl - // 13/11/18: - // The above is no longer necessary, since we want OpenGL to be just like software now - // -- Monster Iestyn -#endif - 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 + V_Recalc(); // toggle off (then back on) the automap because some screensize-dependent values will // be calculated next time the automap is activated. @@ -369,11 +310,17 @@ void SCR_Recalc(void) // scr_viewsize doesn't change, neither detailLevel, but the pixels // per screenblock is different now, since we've changed resolution. - R_SetViewSize(); //just set setsizeneeded true now .. + R_ViewSizeChanged(); //just set setsizeneeded true now .. // vid.recalc lasts only for the next refresh... con_recalc = true; am_recalc = true; + +#ifdef HWRENDER + // Shoot! The screen texture was flushed! + if ((rendermode == render_opengl) && (gamestate == GS_INTERMISSION)) + usebuffer = false; +#endif } // Check for screen cmd-line parms: to force a resolution. @@ -411,7 +358,19 @@ void SCR_CheckDefaultMode(void) setmodeneeded = VID_GetModeForSize(cv_scr_width.value, cv_scr_height.value) + 1; } - SCR_ActuallyChangeRenderer(); + if (cv_renderer.value != (signed)rendermode) + { + if (chosenrendermode == render_none) // nothing set at command line + SCR_ChangeRenderer(); + else + { + // Set cv_renderer to the current render mode + CV_StealthSetValue(&cv_renderer, rendermode); +#ifdef HWRENDER + CV_StealthSetValue(&cv_newrenderer, rendermode); +#endif + } + } } // sets the modenum as the new default video mode to be saved in the config file @@ -427,81 +386,42 @@ void SCR_SetDefaultMode(void) void SCR_ChangeFullscreen(void) { #ifdef DIRECTFULLSCREEN - // allow_fullscreen is set by VID_PrepareModeList - // it is used to prevent switching to fullscreen during startup + // allow_fullscreen is used to prevent switching to fullscreen during startup if (!allow_fullscreen) return; if (graphics_started) - { - VID_PrepareModeList(); setmodeneeded = VID_GetModeForSize(vid.width, vid.height) + 1; - } - return; #endif } -static int target_renderer = 0; - -void SCR_ActuallyChangeRenderer(void) +void SCR_SetTargetRenderer(void) { - setrenderneeded = target_renderer; + if (!con_refresh) + SCR_ChangeRenderer(); +} + +void SCR_ChangeRenderer(void) +{ + if ((signed)rendermode == cv_renderer.value) + return; #ifdef HWRENDER - // Well, it didn't even load anyway. - if ((vid_opengl_state == -1) && (setrenderneeded == render_opengl)) + // Check if OpenGL loaded successfully (or wasn't disabled) before switching to it. + if ((vid.glstate == VID_GL_LIBRARY_ERROR) + && (cv_renderer.value == render_opengl)) { if (M_CheckParm("-nogl")) CONS_Alert(CONS_ERROR, "OpenGL rendering was disabled!\n"); else CONS_Alert(CONS_ERROR, "OpenGL never loaded\n"); - setrenderneeded = 0; return; } #endif - // setting the same renderer twice WILL crash your game, so let's not, please - if (rendermode == setrenderneeded) - setrenderneeded = 0; -} - -// Lactozilla: Renderer switching -void SCR_ChangeRenderer(void) -{ - setrenderneeded = 0; - - if (con_startup) - { - target_renderer = cv_renderer.value; -#ifdef HWRENDER - if (M_CheckParm("-opengl") && (vid_opengl_state == 1)) - target_renderer = rendermode = render_opengl; - else -#endif - if (M_CheckParm("-software")) - target_renderer = rendermode = render_soft; - // set cv_renderer back - SCR_ChangeRendererCVars(rendermode); - return; - } - - if (cv_renderer.value == 1) - target_renderer = render_soft; - else if (cv_renderer.value == 2) - target_renderer = render_opengl; - SCR_ActuallyChangeRenderer(); -} - -void SCR_ChangeRendererCVars(INT32 mode) -{ - // set cv_renderer back - if (mode == render_soft) - CV_StealthSetValue(&cv_renderer, 1); - else if (mode == render_opengl) - CV_StealthSetValue(&cv_renderer, 2); -#ifdef HWRENDER - CV_StealthSetValue(&cv_newrenderer, cv_renderer.value); -#endif + // Set the new render mode + setrenderneeded = cv_renderer.value; + con_refresh = false; } boolean SCR_IsAspectCorrect(INT32 width, INT32 height) diff --git a/src/screen.h b/src/screen.h index 91ec175f4..4f2a23b7a 100644 --- a/src/screen.h +++ b/src/screen.h @@ -30,10 +30,6 @@ #define NUMSCREENS 5 #endif -// Size of statusbar. -#define ST_HEIGHT 32 -#define ST_WIDTH 320 - // used now as a maximum video mode size for extra vesa modes. // we try to re-allocate a minimum of buffers for stability of the memory, @@ -48,34 +44,40 @@ typedef struct viddef_s { INT32 modenum; // vidmode num indexes videomodes list + UINT8 *buffer; // screen buffers + UINT8 *direct; // direct screen buffer (DOS VGA) - UINT8 *buffer; // invisible screens buffer + INT32 width, height; // screen dimensions 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. - 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 + INT32 recalc; // if true, recalc vid-based stuff + INT32 numpages; // page flipping + INT32 windowed; // windowed or fullscreen mode? (DirectDraw) - // for Win32 version - DNWH WndParent; // handle of the application's window + 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 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 + + // for Win32 version +#if defined(_WINDOWS) + DNWH WndParent; // handle of the application's window #endif } viddef_t; -#define VIDWIDTH vid.width -#define VIDHEIGHT vid.height + +enum +{ + VID_GL_LIBRARY_NOTLOADED = 0, + VID_GL_LIBRARY_LOADED = 1, + VID_GL_LIBRARY_ERROR = -1, +}; // internal additional info for vesa modes only typedef struct @@ -83,6 +85,7 @@ 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 @@ -171,12 +174,11 @@ extern boolean R_SSE2; extern viddef_t vid; extern INT32 setmodeneeded; // mode number to set if needed, or 0 - -void SCR_ChangeRenderer(void); -void SCR_ChangeRendererCVars(INT32 mode); extern UINT8 setrenderneeded; -extern INT32 scr_bpp; +void SCR_ChangeRenderer(void); +void SCR_SetTargetRenderer(void); + extern UINT8 *scr_borderpatch; // patch used to fill the view borders extern CV_PossibleValue_t cv_renderer_t[]; @@ -185,20 +187,25 @@ extern consvar_t cv_scr_width, cv_scr_height, cv_scr_depth, cv_renderview, cv_re #ifdef HWRENDER extern consvar_t cv_newrenderer; #endif -// wait for page flipping to end or not -extern consvar_t cv_vidwait; +extern consvar_t cv_vidwait; // wait for page flipping to end or not + +// Initialize the screen +void SCR_Startup(void); // Change video mode, only at the start of a refresh. void SCR_SetMode(void); + +// Set drawer functions for Software void SCR_SetDrawFuncs(void); + // Recalc screen size dependent stuff void SCR_Recalc(void); + // Check parms once at startup void SCR_CheckDefaultMode(void); -// Set the mode number which is saved in the config -void SCR_SetDefaultMode (void); -void SCR_Startup (void); +// Set the mode number which is saved in the config +void SCR_SetDefaultMode(void); FUNCMATH boolean SCR_IsAspectCorrect(INT32 width, INT32 height); diff --git a/src/sdl/Srb2SDL-vc10.vcxproj b/src/sdl/Srb2SDL-vc10.vcxproj index 5592de86b..af3eb0645 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj +++ b/src/sdl/Srb2SDL-vc10.vcxproj @@ -283,6 +283,8 @@ + + @@ -447,7 +449,8 @@ - + + diff --git a/src/sdl/Srb2SDL-vc10.vcxproj.filters b/src/sdl/Srb2SDL-vc10.vcxproj.filters index db1aa123f..0ff931f8b 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj.filters +++ b/src/sdl/Srb2SDL-vc10.vcxproj.filters @@ -474,6 +474,12 @@ R_Rend + + R_Rend + + + R_Rend + R_Rend @@ -946,6 +952,9 @@ R_Rend + + R_Rend + R_Rend diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 01194a02f..bddbc4884 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -73,6 +73,7 @@ #include "../console.h" #include "../command.h" #include "../r_main.h" +#include "../r_patch.h" // Patch_UpdateReferences #include "../lua_hook.h" #include "sdlmain.h" #ifdef HWRENDER @@ -95,7 +96,7 @@ static INT32 numVidModes = -1; static char vidModeName[33][32]; // allow 33 different modes rendermode_t rendermode = render_soft; -static rendermode_t chosenrendermode = render_soft; // set by command line arguments +rendermode_t chosenrendermode = render_none; // set by command line arguments boolean highcolor = false; @@ -105,9 +106,8 @@ static consvar_t cv_stretch = {"stretch", "Off", CV_SAVE|CV_NOSHOWHELP, CV_OnOff static consvar_t cv_alwaysgrabmouse = {"alwaysgrabmouse", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; UINT8 graphics_started = 0; // Is used in console.c and screen.c -INT32 vid_opengl_state = 0; -// To disable fullscreen at startup; is set in VID_PrepareModeList +// To disable fullscreen at startup; is set in I_PrepareVideoModeList boolean allow_fullscreen = false; static SDL_bool disable_fullscreen = SDL_FALSE; #define USE_FULLSCREEN (disable_fullscreen||!allow_fullscreen)?0:cv_fullscreen.value @@ -1340,110 +1340,14 @@ INT32 VID_GetModeForSize(INT32 w, INT32 h) } } return -1; -#if 0 - INT32 matchMode = -1, i; - VID_PrepareModeList(); - if (USE_FULLSCREEN && numVidModes != -1) - { - for (i=firstEntry; iw == w && - modeList[i]->h == h) - { - matchMode = i; - break; - } - } - if (-1 == matchMode) // use smaller mode - { - w -= w%BASEVIDWIDTH; - h -= h%BASEVIDHEIGHT; - for (i=firstEntry; iw == w && - modeList[i]->h == h) - { - matchMode = i; - break; - } - } - if (-1 == matchMode) // use smallest mode - matchMode = numVidModes-1; - } - matchMode -= firstEntry; - } - else - { - for (i=0; iw <= MAXVIDWIDTH && - modeList[i]->h <= MAXVIDHEIGHT) - { - firstEntry = i; - break; - } - } - } - } - allow_fullscreen = true; -#endif } static SDL_bool Impl_CreateContext(void) { // Renderer-specific stuff #ifdef HWRENDER - if ((rendermode == render_opengl) && (vid_opengl_state != -1)) + if ((rendermode == render_opengl) + && (vid.glstate != VID_GL_LIBRARY_ERROR)) { if (!sdlglcontext) sdlglcontext = SDL_GL_CreateContext(window); @@ -1479,30 +1383,29 @@ static SDL_bool Impl_CreateContext(void) void VID_CheckGLLoaded(rendermode_t oldrender) { #ifdef HWRENDER - if (vid_opengl_state == -1) // Well, it didn't work the first time anyway. + if (vid.glstate == VID_GL_LIBRARY_ERROR) // Well, it didn't work the first time anyway. { CONS_Alert(CONS_ERROR, "OpenGL never loaded\n"); rendermode = oldrender; if (chosenrendermode == render_opengl) // fallback to software rendermode = render_soft; - if (setrenderneeded) - { - CV_StealthSetValue(&cv_renderer, oldrender); - CV_StealthSetValue(&cv_newrenderer, oldrender); - setrenderneeded = 0; - } + + CV_StealthSetValue(&cv_renderer, oldrender); + CV_StealthSetValue(&cv_newrenderer, oldrender); } #endif } -void VID_CheckRenderer(void) +boolean VID_CheckRenderer(void) { boolean rendererchanged = false; boolean contextcreated = false; +#ifdef HWRENDER rendermode_t oldrenderer = rendermode; +#endif if (dedicated) - return; + return false; if (setrenderneeded) { @@ -1516,11 +1419,12 @@ void VID_CheckRenderer(void) // Initialise OpenGL before calling SDLSetMode!!! // This is because SDLSetMode calls OglSdlSurface. - if (vid_opengl_state == 0) + if (vid.glstate == VID_GL_LIBRARY_NOTLOADED) { VID_StartupOpenGL(); + // Loaded successfully! - if (vid_opengl_state == 1) + if (vid.glstate == VID_GL_LIBRARY_LOADED) { // Destroy the current window, if it exists. if (window) @@ -1543,11 +1447,17 @@ void VID_CheckRenderer(void) contextcreated = true; } } - else if (vid_opengl_state == -1) + else if (vid.glstate == VID_GL_LIBRARY_ERROR) rendererchanged = false; } #endif + if (rendererchanged) + { + Patch_UpdateReferences(); + V_ReloadHUDGraphics(); + } + if (!contextcreated) Impl_CreateContext(); @@ -1565,27 +1475,22 @@ void VID_CheckRenderer(void) bufSurface = NULL; } - if (rendererchanged) - { #ifdef HWRENDER - if (vid_opengl_state == 1) // Only if OpenGL ever loaded! - HWR_FreeTextureCache(); + if (rendererchanged && vid.glstate == VID_GL_LIBRARY_LOADED) // Only if OpenGL ever loaded! + HWR_FreeTextureCache(); #endif - SCR_SetDrawFuncs(); - } + + SCR_SetDrawFuncs(); } #ifdef HWRENDER - else if (rendermode == render_opengl) + else if (rendermode == render_opengl && rendererchanged) { - if (rendererchanged) - { - R_InitHardwareMode(); - V_SetPalette(0); - } + HWR_Switch(); + V_SetPalette(0); } -#else - (void)oldrenderer; #endif + + return rendererchanged; } INT32 VID_SetMode(INT32 modeNum) @@ -1626,7 +1531,7 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen) flags |= SDL_WINDOW_BORDERLESS; #ifdef HWRENDER - if (vid_opengl_state == 1) + if (vid.glstate == VID_GL_LIBRARY_LOADED) flags |= SDL_WINDOW_OPENGL; #endif @@ -1660,7 +1565,7 @@ static void Impl_SetWindowName(const char *title) static void Impl_SetWindowIcon(void) { if (window && icoSurface) - SDL_SetWindowIcon(window, icoSurface); + SDL_SetWindowIcon(window, icoSurface); } static void Impl_VideoSetupSDLBuffer(void) @@ -1747,12 +1652,44 @@ void I_StartupGraphics(void) framebuffer = SDL_TRUE; } -#ifdef HWRENDER - if (M_CheckParm("-opengl")) - chosenrendermode = rendermode = render_opengl; + // Renderer choices + // Takes priority over the config. + if (M_CheckParm("-renderer")) + { + INT32 i = 0; + CV_PossibleValue_t *renderer_list = cv_renderer_t; + const char *modeparm = M_GetNextParm(); + while (renderer_list[i].strvalue) + { + if (!stricmp(modeparm, renderer_list[i].strvalue)) + { + chosenrendermode = renderer_list[i].value; + break; + } + i++; + } + } + + // Choose Software renderer else if (M_CheckParm("-software")) + chosenrendermode = render_soft; + +#ifdef HWRENDER + // Choose OpenGL renderer + else if (M_CheckParm("-opengl")) + chosenrendermode = render_opengl; + + // Don't startup OpenGL + if (M_CheckParm("-nogl")) + { + vid.glstate = VID_GL_LIBRARY_ERROR; + if (chosenrendermode == render_opengl) + chosenrendermode = render_none; + } #endif - chosenrendermode = rendermode = render_soft; + + if (chosenrendermode != render_none) + rendermode = chosenrendermode; usesdl2soft = M_CheckParm("-softblit"); borderlesswindow = M_CheckParm("-borderless"); @@ -1761,16 +1698,14 @@ void I_StartupGraphics(void) VID_Command_ModeList_f(); #ifdef HWRENDER - if (M_CheckParm("-nogl")) - vid_opengl_state = -1; // Don't startup OpenGL - else if (chosenrendermode == render_opengl) + if (rendermode == render_opengl) VID_StartupOpenGL(); #endif // Window icon #ifdef HAVE_IMAGE icoSurface = IMG_ReadXPMFromArray(SDL_icon_xpm); -#endif +#endif // Fury: we do window initialization after GL setup to allow // SDL_GL_LoadLibrary to work well on Windows @@ -1782,10 +1717,9 @@ 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.recalc = true; // Set up the console stuff 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(); @@ -1854,19 +1788,17 @@ void VID_StartupOpenGL(void) HWD.pfnMakeScreenTexture= hwSym("MakeScreenTexture",NULL); HWD.pfnMakeScreenFinalTexture=hwSym("MakeScreenFinalTexture",NULL); HWD.pfnDrawScreenFinalTexture=hwSym("DrawScreenFinalTexture",NULL); - HWD.pfnLoadShaders = hwSym("LoadShaders",NULL); HWD.pfnKillShaders = hwSym("KillShaders",NULL); HWD.pfnSetShader = hwSym("SetShader",NULL); HWD.pfnUnSetShader = hwSym("UnSetShader",NULL); - HWD.pfnSetShaderInfo = hwSym("SetShaderInfo",NULL); HWD.pfnLoadCustomShader = hwSym("LoadCustomShader",NULL); HWD.pfnInitCustomShaders= hwSym("InitCustomShaders",NULL); - vid_opengl_state = HWD.pfnInit() ? 1 : -1; // let load the OpenGL library + vid.glstate = HWD.pfnInit() ? VID_GL_LIBRARY_LOADED : VID_GL_LIBRARY_ERROR; // let load the OpenGL library - if (vid_opengl_state == -1) + if (vid.glstate == VID_GL_LIBRARY_ERROR) { rendermode = render_soft; setrenderneeded = 0; diff --git a/src/st_stuff.c b/src/st_stuff.c index d5aa5fbac..8597e4512 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -302,13 +302,13 @@ void ST_LoadGraphics(void) sneakers = W_CachePatchName("TVSSICON", PU_HUDGFX); gravboots = W_CachePatchName("TVGVICON", PU_HUDGFX); - tagico = W_CachePatchName("TAGICO", PU_HUDGFX); - rflagico = W_CachePatchName("RFLAGICO", PU_HUDGFX); - bflagico = W_CachePatchName("BFLAGICO", PU_HUDGFX); - rmatcico = W_CachePatchName("RMATCICO", PU_HUDGFX); - bmatcico = W_CachePatchName("BMATCICO", PU_HUDGFX); + rflagico = (patch_t **)W_GetPatchPointerFromName("RFLAGICO", PU_HUDGFX); + bflagico = (patch_t **)W_GetPatchPointerFromName("BFLAGICO", PU_HUDGFX); + rmatcico = (patch_t **)W_GetPatchPointerFromName("RMATCICO", PU_HUDGFX); + bmatcico = (patch_t **)W_GetPatchPointerFromName("BMATCICO", PU_HUDGFX); gotrflag = W_CachePatchName("GOTRFLAG", PU_HUDGFX); gotbflag = W_CachePatchName("GOTBFLAG", PU_HUDGFX); + tagico = W_CachePatchName("TAGICO", PU_HUDGFX); fnshico = W_CachePatchName("FNSHICO", PU_HUDGFX); nonicon = W_CachePatchName("NONICON", PU_HUDGFX); nonicon2 = W_CachePatchName("NONICON2", PU_HUDGFX); @@ -2374,17 +2374,17 @@ static void ST_drawTeamHUD(void) return; if (gametyperules & GTR_TEAMFLAGS) - p = bflagico; + p = *bflagico; else - p = bmatcico; + p = *bmatcico; if (LUA_HudEnabled(hud_teamscores)) V_DrawSmallScaledPatch(BASEVIDWIDTH/2 - SEP - SHORT(p->width)/4, 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, p); if (gametyperules & GTR_TEAMFLAGS) - p = rflagico; + p = *rflagico; else - p = rmatcico; + p = *rmatcico; if (LUA_HudEnabled(hud_teamscores)) V_DrawSmallScaledPatch(BASEVIDWIDTH/2 + SEP - SHORT(p->width)/4, 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, p); @@ -2755,9 +2755,6 @@ static void ST_overlayDrawer(void) void ST_Drawer(void) { - if (needpatchrecache) - R_ReloadHUDGraphics(); - #ifdef SEENAMES if (cv_seenames.value && cv_allowseenames.value && displayplayer == consoleplayer && seenplayer && seenplayer->mo) { diff --git a/src/v_video.c b/src/v_video.c index b88c4838b..11b297352 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -3719,3 +3719,43 @@ void V_Init(void) CONS_Debug(DBG_RENDER, " screens[%d] = %x\n", i, screens[i]); #endif } + +void V_Recalc(void) +{ + // 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 and v_draw.c + vid.dupx = vid.width / BASEVIDWIDTH; + vid.dupy = vid.height / BASEVIDHEIGHT; + vid.dupx = vid.dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); + vid.fdupx = FixedDiv(vid.width*FRACUNIT, BASEVIDWIDTH*FRACUNIT); + vid.fdupy = FixedDiv(vid.height*FRACUNIT, BASEVIDHEIGHT*FRACUNIT); + +#ifdef HWRENDER + //if (rendermode != render_opengl && rendermode != render_none) // This was just placing it incorrectly at non aspect correct resolutions in opengl + // 13/11/18: + // The above is no longer necessary, since we want OpenGL to be just like software now + // -- Monster Iestyn +#endif + vid.fdupx = vid.fdupy = (vid.fdupx < vid.fdupy ? vid.fdupx : vid.fdupy); + + 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 +} + +void V_ReloadHUDGraphics(void) +{ + ST_LoadGraphics(); + HU_LoadGraphics(); + ST_ReloadSkinFaceGraphics(); +} diff --git a/src/v_video.h b/src/v_video.h index 9f7a9a9e9..962d1097c 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -37,6 +37,9 @@ cv_allcaps; // Allocates buffer screens, call before R_Init. void V_Init(void); +// Recalculates the viddef (dupx, dupy, etc.) according to the current screen resolution. +void V_Recalc(void); + // Color look-up table #define COLORBITS 6 #define SHIFTCOLORBITS (8-COLORBITS) @@ -264,6 +267,8 @@ INT32 V_SmallThinStringWidth(const char *string, INT32 option); void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param); +void V_ReloadHUDGraphics(void); + void V_DrawPatchFill(patch_t *pat); void VID_BlitLinearScreen(const UINT8 *srcptr, UINT8 *destptr, INT32 width, INT32 height, size_t srcrowbytes, diff --git a/src/w_wad.c b/src/w_wad.c index e6dedba22..ac801bbd3 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -56,6 +56,8 @@ #include "d_clisrv.h" #include "r_defs.h" #include "r_data.h" +#include "r_patch.h" +#include "r_rotsprite.h" #include "i_system.h" #include "md5.h" #include "lua_script.h" @@ -834,12 +836,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup) // set up caching // Z_Calloc(numlumps * sizeof (*wadfile->lumpcache), PU_STATIC, &wadfile->lumpcache); - Z_Calloc(numlumps * sizeof (*wadfile->patchcache), PU_STATIC, &wadfile->patchcache); - -#ifdef HWRENDER - // allocates GLPatch info structures and store them in a tree - wadfile->hwrcache = M_AATreeAlloc(AATREE_ZUSER); -#endif + Patch_InitInfo(wadfile); // // add the wadfile @@ -850,7 +847,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup) #ifdef HWRENDER // Read shaders from file - if (rendermode == render_opengl && (vid_opengl_state == 1)) + if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED)) { HWR_ReadShaders(numwadfiles - 1, (type == RET_PK3)); HWR_LoadShaders(); @@ -1609,38 +1606,6 @@ boolean W_IsLumpCached(lumpnum_t lumpnum, void *ptr) return W_IsLumpCachedPWAD(WADFILENUM(lumpnum),LUMPNUM(lumpnum), ptr); } -// -// W_IsPatchCached -// -// If a patch is already cached return true, otherwise -// return false. -// -// no outside code uses the PWAD form, for now -static inline boolean W_IsPatchCachedPWAD(UINT16 wad, UINT16 lump, void *ptr) -{ - void *lcache; - - if (!TestValidLump(wad, lump)) - return false; - - lcache = wadfiles[wad]->patchcache[lump]; - - if (ptr) - { - if (ptr == lcache) - return true; - } - else if (lcache) - return true; - - return false; -} - -boolean W_IsPatchCached(lumpnum_t lumpnum, void *ptr) -{ - return W_IsPatchCachedPWAD(WADFILENUM(lumpnum),LUMPNUM(lumpnum), ptr); -} - // ========================================================================== // W_CacheLumpName // ========================================================================== @@ -1649,62 +1614,12 @@ void *W_CacheLumpName(const char *name, INT32 tag) return W_CacheLumpNum(W_GetNumForName(name), tag); } -// ========================================================================== -// CACHING OF GRAPHIC PATCH RESOURCES -// ========================================================================== - -// Graphic 'patches' are loaded, and if necessary, converted into the format -// the most useful for the current rendermode. For software renderer, the -// graphic patches are kept as is. For the hardware renderer, graphic patches -// are 'unpacked', and are kept into the cache in that unpacked format, and -// the heap memory cache then acts as a 'level 2' cache just after the -// graphics card memory. - -// -// Cache a patch into heap memory, convert the patch format as necessary -// - void *W_CacheSoftwarePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) { - lumpcache_t *lumpcache = NULL; - if (!TestValidLump(wad, lump)) return NULL; - lumpcache = wadfiles[wad]->patchcache; - - if (!lumpcache[lump]) - { - size_t len = W_LumpLengthPwad(wad, lump); - void *ptr, *lumpdata; -#ifndef NO_PNG_LUMPS - void *srcdata = NULL; -#endif - - ptr = Z_Malloc(len, tag, &lumpcache[lump]); - lumpdata = Z_Malloc(len, tag, NULL); - - // read the lump in full - W_ReadLumpHeaderPwad(wad, lump, lumpdata, 0, 0); - -#ifndef NO_PNG_LUMPS - // lump is a png so convert it - if (R_IsLumpPNG((UINT8 *)lumpdata, len)) - { - size_t newlen; - srcdata = R_PNGToPatch((UINT8 *)lumpdata, len, &newlen); - ptr = Z_Realloc(ptr, newlen, tag, &lumpcache[lump]); - M_Memcpy(ptr, srcdata, newlen); - Z_Free(srcdata); - } - else // just copy it into the patch cache -#endif - M_Memcpy(ptr, lumpdata, len); - } - else - Z_ChangeTag(lumpcache[lump], tag); - - return lumpcache[lump]; + return Patch_CacheSoftware(wad, lump, tag, false); } void *W_CacheSoftwarePatchNum(lumpnum_t lumpnum, INT32 tag) @@ -1714,46 +1629,15 @@ void *W_CacheSoftwarePatchNum(lumpnum_t lumpnum, INT32 tag) void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) { -#ifdef HWRENDER - GLPatch_t *grPatch; -#endif - if (!TestValidLump(wad, lump)) return NULL; #ifdef HWRENDER - // Software-only compile cache the data without conversion - if (rendermode == render_soft || rendermode == render_none) -#endif - { - return W_CacheSoftwarePatchNumPwad(wad, lump, tag); - } -#ifdef HWRENDER - - grPatch = HWR_GetCachedGLPatchPwad(wad, lump); - - if (grPatch->mipmap->data) - { - if (tag == PU_CACHE) - tag = PU_HWRCACHE; - Z_ChangeTag(grPatch->mipmap->data, tag); - } + if (rendermode == render_opengl) + return (void *)Patch_CacheGL(wad, lump, tag, false); else - { - patch_t *ptr = NULL; - - // Only load the patch if we haven't initialised the grPatch yet - if (grPatch->mipmap->width == 0) - ptr = W_CacheLumpNumPwad(grPatch->wadnum, grPatch->lumpnum, PU_STATIC); - - // Run HWR_MakePatch in all cases, to recalculate some things - HWR_MakePatch(ptr, grPatch, grPatch->mipmap, false); - Z_Free(ptr); - } - - // return GLPatch_t, which can be casted to (patch_t) with valid patch header info - return (void *)grPatch; #endif + return Patch_CacheSoftware(wad, lump, tag, false); } void *W_CachePatchNum(lumpnum_t lumpnum, INT32 tag) @@ -1761,6 +1645,111 @@ void *W_CachePatchNum(lumpnum_t lumpnum, INT32 tag) return W_CachePatchNumPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum),tag); } +void *W_CachePatchName(const char *name, INT32 tag) +{ + lumpnum_t num = W_CheckNumForName(name); + if (num == LUMPERROR) + return W_CachePatchNum(W_GetNumForName("MISSING"), tag); + return W_CachePatchNum(num, tag); +} + +void *W_CachePatchLongName(const char *name, INT32 tag) +{ + lumpnum_t num = W_CheckNumForLongName(name); + if (num == LUMPERROR) + return W_CachePatchNum(W_GetNumForLongName("MISSING"), tag); + return W_CachePatchNum(num, tag); +} + +void **W_GetPatchPointerPwad(UINT16 wad, UINT16 lump, INT32 tag) +{ + void **pp; + if (!TestValidLump(wad, lump)) + return NULL; + + pp = (void **)(&(wadfiles[wad]->patchinfo.current[lump])); + if (*pp) // Already cached + return pp; + +#ifdef HWRENDER + if (rendermode == render_opengl) + Patch_CacheGL(wad, lump, tag, true); + else +#endif + Patch_CacheSoftware(wad, lump, tag, true); + + return pp; +} + +void **W_GetPatchPointer(lumpnum_t lumpnum, INT32 tag) +{ + return W_GetPatchPointerPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum),tag); +} + +void **W_GetPatchPointerFromName(const char *name, INT32 tag) +{ + lumpnum_t num = W_CheckNumForName(name); + if (num == LUMPERROR) + return W_GetPatchPointer(W_GetNumForName("MISSING"), tag); + return W_GetPatchPointer(num, tag); +} + +void **W_GetPatchPointerFromLongName(const char *name, INT32 tag) +{ + lumpnum_t num = W_CheckNumForLongName(name); + if (num == LUMPERROR) + return W_GetPatchPointer(W_CheckNumForLongName("MISSING"), tag); + return W_GetPatchPointer(num, tag); +} + +#ifdef ROTSPRITE +void **W_GetRotatedPatchPointerPwad(UINT16 wad, UINT16 lump, INT32 tag, INT32 rollangle, boolean sprite, void *pivot, boolean flip) +{ + static rotsprite_vars_t rsvars; + patchinfo_t *patchinfo = NULL; + + if (!TestValidLump(wad, lump)) + return NULL; + + patchinfo = &wadfiles[wad]->patchinfo; + if (!patchinfo->rotated[lump]) + RotSprite_AllocCurrentPatchInfo(patchinfo, lump); + + rsvars.rollangle = rollangle; + rsvars.sprite = sprite; + rsvars.pivot = pivot; + rsvars.flip = flip; + + if (sprite) + Patch_CacheRotatedForSpritePwad(wad, lump, tag, rsvars, true); + else + Patch_CacheRotatedPwad(wad, lump, tag, rsvars, true); + + return (void **)(&(patchinfo->rotated[lump][RotSprite_GetCurrentPatchInfoIdx(rollangle, flip)])); +} + +void **W_GetRotatedPatchPointer(lumpnum_t lumpnum, INT32 tag, INT32 rollangle, boolean sprite, void *pivot, boolean flip) +{ + return W_GetRotatedPatchPointerPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum),tag,rollangle,sprite,pivot,flip); +} + +void **W_GetRotatedPatchPointerFromName(const char *name, INT32 tag, INT32 rollangle, boolean sprite, void *pivot, boolean flip) +{ + lumpnum_t num = W_CheckNumForName(name); + if (num == LUMPERROR) + return W_GetRotatedPatchPointer(W_GetNumForName("MISSING"), tag, rollangle, sprite, pivot, flip); + return W_GetRotatedPatchPointer(num, tag, rollangle, sprite, pivot, flip); +} + +void **W_GetRotatedPatchPointerFromLongName(const char *name, INT32 tag, INT32 rollangle, boolean sprite, void *pivot, boolean flip) +{ + lumpnum_t num = W_CheckNumForLongName(name); + if (num == LUMPERROR) + return W_GetRotatedPatchPointer(W_CheckNumForLongName("MISSING"), tag, rollangle, sprite, pivot, flip); + return W_GetRotatedPatchPointer(num, tag, rollangle, sprite, pivot, flip); +} +#endif + void W_UnlockCachedPatch(void *patch) { // The hardware code does its own memory management, as its patches @@ -1768,32 +1757,9 @@ void W_UnlockCachedPatch(void *patch) #ifdef HWRENDER if (rendermode == render_opengl) HWR_UnlockCachedPatch((GLPatch_t*)patch); - else #endif - Z_Unlock(patch); } -void *W_CachePatchName(const char *name, INT32 tag) -{ - lumpnum_t num; - - num = W_CheckNumForName(name); - - if (num == LUMPERROR) - return W_CachePatchNum(W_GetNumForName("MISSING"), tag); - return W_CachePatchNum(num, tag); -} - -void *W_CachePatchLongName(const char *name, INT32 tag) -{ - lumpnum_t num; - - num = W_CheckNumForLongName(name); - - if (num == LUMPERROR) - return W_CachePatchNum(W_GetNumForLongName("MISSING"), tag); - return W_CachePatchNum(num, tag); -} #ifndef NOMD5 #define MD5_LEN 16 diff --git a/src/w_wad.h b/src/w_wad.h index fddc65529..a41b5dd90 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -22,6 +22,8 @@ #pragma interface #endif +#define lumpcache_t void * + // a raw entry of the wad directory // NOTE: This sits here and not in w_wad.c because p_setup.c makes use of it to load map WADs inside PK3s. #if defined(_MSC_VER) @@ -37,7 +39,6 @@ typedef struct #pragma pack() #endif - // ============================================================== // WAD FILE STRUCTURE DEFINITIONS // ============================================================== @@ -92,6 +93,22 @@ virtres_t* vres_GetMap(lumpnum_t); void vres_Free(virtres_t*); virtlump_t* vres_Find(const virtres_t*, const char*); +// ========================================================================= +// PATCH INFO +// ========================================================================= + +#include "r_patchtrees.h" + +typedef struct patchinfo_s +{ + patchtree_t renderer[num_patchtrees]; + + lumpcache_t *current; +#ifdef ROTSPRITE + lumpcache_t **rotated; +#endif +} patchinfo_t; + // ========================================================================= // DYNAMIC WAD LOADING // ========================================================================= @@ -100,12 +117,6 @@ virtlump_t* vres_Find(const virtres_t*, const char*); #define MAX_WADFILES 48 // maximum of wad files used at the same time // (there is a max of simultaneous open files anyway, and this should be plenty) -#define lumpcache_t void * - -#ifdef HWRENDER -#include "m_aatree.h" -#endif - // Resource type of the WAD. Yeah, I know this sounds dumb, but I'll leave it like this until I clean up the code further. typedef enum restype { @@ -122,10 +133,7 @@ typedef struct wadfile_s restype_t type; lumpinfo_t *lumpinfo; lumpcache_t *lumpcache; - lumpcache_t *patchcache; -#ifdef HWRENDER - aatree_t *hwrcache; // patches are cached in renderer's native format -#endif + patchinfo_t patchinfo; UINT16 numlumps; // this wad's number of resources FILE *handle; UINT32 filesize; // for network @@ -134,8 +142,9 @@ typedef struct wadfile_s boolean important; // also network - !W_VerifyNMUSlumps } wadfile_t; -#define WADFILENUM(lumpnum) (UINT16)((lumpnum)>>16) // wad flumpnum>>16) // wad file number in upper word +#define WADFILENUM(lumpnum) (UINT16)((lumpnum)>>16) // wad file number in upper word #define LUMPNUM(lumpnum) (UINT16)((lumpnum)&0xFFFF) // lump number for this pwad +#define WADANDLUMP(wad, lump) (UINT32)(((wad)<<16)|((lump)&0xFFFF)) // wad and lump number extern UINT16 numwadfiles; extern wadfile_t *wadfiles[MAX_WADFILES]; @@ -193,7 +202,6 @@ void *W_CacheLumpNum(lumpnum_t lump, INT32 tag); void *W_CacheLumpNumForce(lumpnum_t lumpnum, INT32 tag); boolean W_IsLumpCached(lumpnum_t lump, void *ptr); -boolean W_IsPatchCached(lumpnum_t lump, void *ptr); void *W_CacheLumpName(const char *name, INT32 tag); void *W_CachePatchName(const char *name, INT32 tag); @@ -209,6 +217,20 @@ void *W_CachePatchNum(lumpnum_t lumpnum, INT32 tag); void *W_CacheSoftwarePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag); void *W_CacheSoftwarePatchNum(lumpnum_t lumpnum, INT32 tag); +// Returns patch pointers. +void **W_GetPatchPointerPwad(UINT16 wad, UINT16 lump, INT32 tag); +void **W_GetPatchPointer(lumpnum_t lumpnum, INT32 tag); +void **W_GetPatchPointerFromName(const char *name, INT32 tag); +void **W_GetPatchPointerFromLongName(const char *name, INT32 tag); + +#ifdef ROTSPRITE +// Returns rotated patch pointers. +void **W_GetRotatedPatchPointerPwad(UINT16 wad, UINT16 lump, INT32 tag, INT32 rollangle, boolean sprite, void *pivot, boolean flip); +void **W_GetRotatedPatchPointer(lumpnum_t lumpnum, INT32 tag, INT32 rollangle, boolean sprite, void *pivot, boolean flip); +void **W_GetRotatedPatchPointerFromName(const char *name, INT32 tag, INT32 rollangle, boolean sprite, void *pivot, boolean flip); +void **W_GetRotatedPatchPointerFromLongName(const char *name, INT32 tag, INT32 rollangle, boolean sprite, void *pivot, boolean flip); +#endif + void W_UnlockCachedPatch(void *patch); void W_VerifyFileMD5(UINT16 wadfilenum, const char *matchmd5); diff --git a/src/win32/Srb2win-vc10.vcxproj b/src/win32/Srb2win-vc10.vcxproj index 6855a4135..8c40a9aae 100644 --- a/src/win32/Srb2win-vc10.vcxproj +++ b/src/win32/Srb2win-vc10.vcxproj @@ -300,6 +300,7 @@ + @@ -454,7 +455,9 @@ - + + + diff --git a/src/win32/Srb2win-vc10.vcxproj.filters b/src/win32/Srb2win-vc10.vcxproj.filters index 4a980c6bd..71b718bf7 100644 --- a/src/win32/Srb2win-vc10.vcxproj.filters +++ b/src/win32/Srb2win-vc10.vcxproj.filters @@ -472,6 +472,9 @@ R_Rend + + R_Rend + R_Rend @@ -889,6 +892,12 @@ R_Rend + + R_Rend + + + R_Rend + R_Rend diff --git a/src/win32/win_vid.c b/src/win32/win_vid.c index 716f38089..32adbdefa 100644 --- a/src/win32/win_vid.c +++ b/src/win32/win_vid.c @@ -48,6 +48,7 @@ // this is the CURRENT rendermode!! very important: used by w_wad, and much other code rendermode_t rendermode = render_soft; +rendermode_t chosenrendermode = render_none; // set by command line arguments static void OnTop_OnChange(void); // synchronize page flipping with screen refresh static CV_PossibleValue_t CV_NeverOnOff[] = {{-1, "Never"}, {0, "Off"}, {1, "On"}, {0, NULL}}; @@ -56,7 +57,6 @@ static consvar_t cv_stretch = {"stretch", "On", CV_SAVE|CV_NOSHOWHELP, CV_OnOff, static consvar_t cv_ontop = {"ontop", "Never", 0, CV_NeverOnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; boolean highcolor; -int vid_opengl_state = 0; static BOOL bDIBMode; // means we are using DIB instead of DirectDraw surfaces static LPBITMAPINFO bmiMain = NULL; @@ -778,7 +778,7 @@ static INT32 WINAPI VID_SetWindowedDisplayMode(viddef_t *lvid, vmode_t *currentm I_OutputMsg("VID_SetWindowedDisplayMode()\n"); - lvid->u.numpages = 1; // not used + lvid->numpages = 1; // not used lvid->direct = NULL; // DOS remains lvid->buffer = NULL; @@ -903,9 +903,9 @@ INT32 VID_SetMode(INT32 modenum) if (cv_scr_depth.value < 16) CV_SetValue(&cv_scr_depth, 16); vid.bpp = cv_scr_depth.value/8; - vid.u.windowed = (bWinParm || !cv_fullscreen.value); + vid.windowed = (bWinParm || !cv_fullscreen.value); pcurrentmode->bytesperpixel = vid.bpp; - pcurrentmode->windowed = vid.u.windowed; + pcurrentmode->windowed = vid.windowed; } } @@ -952,7 +952,11 @@ INT32 VID_SetMode(INT32 modenum) return 1; } -void VID_CheckRenderer(void) {} +boolean VID_CheckRenderer(void) +{ + return false; +} + void VID_CheckGLLoaded(rendermode_t oldrender) { (void)oldrender; @@ -995,7 +999,7 @@ static INT32 WINAPI VID_SetDirectDrawMode(viddef_t *lvid, vmode_t *currentmode) // DD modes do double-buffer page flipping, but the game engine doesn't need this.. - lvid->u.numpages = 2; + lvid->numpages = 2; // release ddraw surfaces etc.. ReleaseChtuff(); diff --git a/src/y_inter.c b/src/y_inter.c index 58e0c4a88..a4f7d07a4 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -66,7 +66,7 @@ typedef union INT32 passedx2; y_bonus_t bonuses[4]; - patch_t *bonuspatches[4]; + patch_t **bonuspatches[4]; SINT8 gotperfbonus; // Used for visitation flags. @@ -74,7 +74,7 @@ typedef union UINT32 tics; // time UINT8 actnum; // act number being displayed - patch_t *ptotal; // TOTAL + patch_t **ptotal; // TOTAL UINT8 gotlife; // Number of extra lives obtained } coop; @@ -90,14 +90,14 @@ typedef union INT32 passedx4; y_bonus_t bonuses[2]; - patch_t *bonuspatches[2]; + patch_t **bonuspatches[2]; - patch_t *pscore; // SCORE + patch_t **pscore; // SCORE UINT32 score; // fake score // Continues UINT8 continues; - patch_t *pcontinues; + patch_t **pcontinues; INT32 *playerchar; // Continue HUD UINT16 *playercolor; @@ -112,9 +112,9 @@ typedef union INT32 *character[MAXPLAYERS]; // Winner's character # INT32 num[MAXPLAYERS]; // Winner's player # char *name[MAXPLAYERS]; // Winner's name - patch_t *result; // RESULT - patch_t *blueflag; - patch_t *redflag; // int_ctf uses this struct too. + patch_t **result; // RESULT + patch_t **blueflag; + patch_t **redflag; // int_ctf uses this struct too. INT32 numplayers; // Number of players being displayed char levelstring[40]; // holds levelnames up to 32 characters } match; @@ -140,10 +140,10 @@ typedef union static y_data data; // graphics -static patch_t *bgpatch = NULL; // INTERSCR -static patch_t *widebgpatch = NULL; // INTERSCW -static patch_t *bgtile = NULL; // SPECTILE/SRB2BACK -static patch_t *interpic = NULL; // custom picture defined in map header +static patch_t **bgpatch = NULL; // INTERSCR +static patch_t **widebgpatch = NULL; // INTERSCW +static patch_t **bgtile = NULL; // SPECTILE/SRB2BACK +static patch_t **interpic = NULL; // custom picture defined in map header static boolean usetile; static INT32 timer; @@ -176,7 +176,6 @@ static void Y_CalculateCompetitionWinners(void); static void Y_CalculateTimeRaceWinners(void); static void Y_CalculateMatchWinners(void); static void Y_UnloadData(void); -static void Y_CleanupData(void); // Stuff copy+pasted from st_stuff.c #define ST_DrawNumFromHud(h,n) V_DrawTallNum(hudinfo[h].x, hudinfo[h].y, hudinfo[h].f, n) @@ -323,13 +322,6 @@ void Y_IntermissionDrawer(void) if (intertype == int_none || rendermode == render_none) return; - // Lactozilla: Renderer switching - if (needpatchrecache) - { - Y_CleanupData(); - safetorender = false; - } - if (!usebuffer || !safetorender) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); @@ -337,7 +329,7 @@ void Y_IntermissionDrawer(void) goto dontdrawbg; if (useinterpic) - V_DrawScaledPatch(0, 0, 0, interpic); + V_DrawScaledPatch(0, 0, 0, *interpic); else if (!usetile) { if (rendermode == render_soft && usebuffer) @@ -362,13 +354,13 @@ void Y_IntermissionDrawer(void) else { if (widebgpatch && rendermode == render_soft && vid.width / vid.dupx == 400) - V_DrawScaledPatch(0, 0, V_SNAPTOLEFT, widebgpatch); + V_DrawScaledPatch(0, 0, V_SNAPTOLEFT, *widebgpatch); else if (bgpatch) - V_DrawScaledPatch(0, 0, 0, bgpatch); + V_DrawScaledPatch(0, 0, 0, *bgpatch); } } else if (bgtile) - V_DrawPatchFill(bgtile); + V_DrawPatchFill(*bgtile); LUAh_IntermissionHUD(); if (!LUA_HudEnabled(hud_intermissiontally)) @@ -426,7 +418,7 @@ dontdrawbg: // Total if (safetorender) { - V_DrawScaledPatch(152, bonusy, 0, data.coop.ptotal); + V_DrawScaledPatch(152, bonusy, 0, *data.coop.ptotal); V_DrawTallNum(BASEVIDWIDTH - 68, bonusy + 1, 0, data.coop.total); } bonusy -= (3*SHORT(tallnum[0]->height)/2) + 1; @@ -436,7 +428,7 @@ dontdrawbg: { if (data.coop.bonuses[i].display && safetorender) { - V_DrawScaledPatch(152, bonusy, 0, data.coop.bonuspatches[i]); + V_DrawScaledPatch(152, bonusy, 0, *data.coop.bonuspatches[i]); V_DrawTallNum(BASEVIDWIDTH - 68, bonusy + 1, 0, data.coop.bonuses[i].points); } bonusy -= (3*SHORT(tallnum[0]->height)/2) + 1; @@ -539,18 +531,18 @@ dontdrawbg: V_DrawLevelTitle(data.spec.passedx2 + xoffset1, ttheight, 0, data.spec.passed2); } - V_DrawScaledPatch(152 + xoffset3, 108, 0, data.spec.bonuspatches[0]); + V_DrawScaledPatch(152 + xoffset3, 108, 0, *data.spec.bonuspatches[0]); V_DrawTallNum(BASEVIDWIDTH + xoffset3 - 68, 109, 0, data.spec.bonuses[0].points); if (data.spec.bonuses[1].display) { - V_DrawScaledPatch(152 + xoffset4, 124, 0, data.spec.bonuspatches[1]); + V_DrawScaledPatch(152 + xoffset4, 124, 0, *data.spec.bonuspatches[1]); V_DrawTallNum(BASEVIDWIDTH + xoffset4 - 68, 125, 0, data.spec.bonuses[1].points); yoffset = 16; // hack; pass the buck along... xoffset4 = xoffset5; xoffset5 = xoffset6; } - V_DrawScaledPatch(152 + xoffset4, 124+yoffset, 0, data.spec.pscore); + V_DrawScaledPatch(152 + xoffset4, 124+yoffset, 0, *data.spec.pscore); V_DrawTallNum(BASEVIDWIDTH + xoffset4 - 68, 125+yoffset, 0, data.spec.score); // Draw continues! @@ -558,7 +550,7 @@ dontdrawbg: { UINT8 continues = data.spec.continues & 0x7F; - V_DrawScaledPatch(152 + xoffset5, 150+yoffset, 0, data.spec.pcontinues); + V_DrawScaledPatch(152 + xoffset5, 150+yoffset, 0, *data.spec.pcontinues); if (continues > 5) { INT32 leftx = (continues >= 10) ? 216 : 224; @@ -664,7 +656,7 @@ dontdrawbg: // draw the header if (safetorender) - V_DrawScaledPatch(112, 2, 0, data.match.result); + V_DrawScaledPatch(112, 2, 0, *data.match.result); // draw the level name V_DrawCenteredString(BASEVIDWIDTH/2, 20, 0, data.match.levelstring); @@ -777,10 +769,10 @@ dontdrawbg: char name[MAXPLAYERNAME+1]; // Show the team flags and the team score at the top instead of "RESULTS" - V_DrawSmallScaledPatch(128 - SHORT(data.match.blueflag->width)/4, 2, 0, data.match.blueflag); + V_DrawSmallScaledPatch(128 - SHORT((*data.match.blueflag)->width)/4, 2, 0, *data.match.blueflag); V_DrawCenteredString(128, 16, 0, va("%u", bluescore)); - V_DrawSmallScaledPatch(192 - SHORT(data.match.redflag->width)/4, 2, 0, data.match.redflag); + V_DrawSmallScaledPatch(192 - SHORT((*data.match.redflag)->width)/4, 2, 0, *data.match.redflag); V_DrawCenteredString(192, 16, 0, va("%u", redscore)); // draw the level name @@ -1259,20 +1251,20 @@ void Y_StartIntermission(void) data.coop.tics = players[consoleplayer].realtime; for (i = 0; i < 4; ++i) - data.coop.bonuspatches[i] = W_CachePatchName(data.coop.bonuses[i].patch, PU_PATCH); - data.coop.ptotal = W_CachePatchName("YB_TOTAL", PU_PATCH); + data.coop.bonuspatches[i] = (patch_t **)W_GetPatchPointerFromName(data.coop.bonuses[i].patch, PU_PATCH); + data.coop.ptotal = (patch_t **)W_GetPatchPointerFromName("YB_TOTAL", PU_PATCH); // get act number data.coop.actnum = mapheaderinfo[gamemap-1]->actnum; // get background patches - widebgpatch = W_CachePatchName("INTERSCW", PU_PATCH); - bgpatch = W_CachePatchName("INTERSCR", PU_PATCH); + widebgpatch = (patch_t **)W_GetPatchPointerFromName("INTERSCW", PU_PATCH); + bgpatch = (patch_t **)W_GetPatchPointerFromName("INTERSCR", PU_PATCH); // grab an interscreen if appropriate if (mapheaderinfo[gamemap-1]->interscreen[0] != '#') { - interpic = W_CachePatchName(mapheaderinfo[gamemap-1]->interscreen, PU_PATCH); + interpic = (patch_t **)W_GetPatchPointerFromName(mapheaderinfo[gamemap-1]->interscreen, PU_PATCH); useinterpic = true; usebuffer = false; } @@ -1330,18 +1322,18 @@ void Y_StartIntermission(void) Y_AwardSpecialStageBonus(); for (i = 0; i < 2; ++i) - data.spec.bonuspatches[i] = W_CachePatchName(data.spec.bonuses[i].patch, PU_PATCH); + data.spec.bonuspatches[i] = (patch_t **)W_GetPatchPointerFromName(data.spec.bonuses[i].patch, PU_PATCH); - data.spec.pscore = W_CachePatchName("YB_SCORE", PU_PATCH); - data.spec.pcontinues = W_CachePatchName("YB_CONTI", PU_PATCH); + data.spec.pscore = (patch_t **)W_GetPatchPointerFromName("YB_SCORE", PU_PATCH); + data.spec.pcontinues = (patch_t **)W_GetPatchPointerFromName("YB_CONTI", PU_PATCH); // get background tile - bgtile = W_CachePatchName("SPECTILE", PU_PATCH); + bgtile = (patch_t **)W_GetPatchPointerFromName("SPECTILE", PU_PATCH); // grab an interscreen if appropriate if (mapheaderinfo[gamemap-1]->interscreen[0] != '#') { - interpic = W_CachePatchName(mapheaderinfo[gamemap-1]->interscreen, PU_PATCH); + interpic = (patch_t **)W_GetPatchPointerFromName(mapheaderinfo[gamemap-1]->interscreen, PU_PATCH); useinterpic = true; } else @@ -1353,14 +1345,14 @@ void Y_StartIntermission(void) // get special stage specific patches /* if (!stagefailed && ALL7EMERALDS(emeralds)) { - data.spec.cemerald = W_CachePatchName("GOTEMALL", PU_PATCH); + data.spec.cemerald = (patch_t **)W_GetPatchPointerFromName("GOTEMALL", PU_PATCH); data.spec.headx = 70; data.spec.nowsuper = players[consoleplayer].skin - ? NULL : W_CachePatchName("NOWSUPER", PU_PATCH); + ? NULL : W_GetPatchPointerFromName("NOWSUPER", PU_PATCH); } else { - data.spec.cemerald = W_CachePatchName("CEMERALD", PU_PATCH); + data.spec.cemerald = (patch_t **)W_GetPatchPointerFromName("CEMERALD", PU_PATCH); data.spec.headx = 48; data.spec.nowsuper = NULL; } */ @@ -1437,10 +1429,9 @@ void Y_StartIntermission(void) data.match.levelstring[sizeof data.match.levelstring - 1] = '\0'; // get RESULT header - data.match.result = - W_CachePatchName("RESULT", PU_PATCH); + data.match.result = (patch_t **)W_GetPatchPointerFromName("RESULT", PU_PATCH); - bgtile = W_CachePatchName("SRB2BACK", PU_PATCH); + bgtile = (patch_t **)W_GetPatchPointerFromName("SRB2BACK", PU_PATCH); usetile = true; useinterpic = false; break; @@ -1466,9 +1457,9 @@ void Y_StartIntermission(void) data.match.levelstring[sizeof data.match.levelstring - 1] = '\0'; // get RESULT header - data.match.result = W_CachePatchName("RESULT", PU_PATCH); + data.match.result = (patch_t **)W_GetPatchPointerFromName("RESULT", PU_PATCH); - bgtile = W_CachePatchName("SRB2BACK", PU_PATCH); + bgtile = (patch_t **)W_GetPatchPointerFromName("SRB2BACK", PU_PATCH); usetile = true; useinterpic = false; break; @@ -1505,7 +1496,7 @@ void Y_StartIntermission(void) data.match.blueflag = bmatcico; } - bgtile = W_CachePatchName("SRB2BACK", PU_PATCH); + bgtile = (patch_t **)W_GetPatchPointerFromName("SRB2BACK", PU_PATCH); usetile = true; useinterpic = false; break; @@ -1531,7 +1522,7 @@ void Y_StartIntermission(void) data.competition.levelstring[sizeof data.competition.levelstring - 1] = '\0'; // get background tile - bgtile = W_CachePatchName("SRB2BACK", PU_PATCH); + bgtile = (patch_t **)W_GetPatchPointerFromName("SRB2BACK", PU_PATCH); usetile = true; useinterpic = false; break; @@ -2069,15 +2060,14 @@ void Y_EndIntermission(void) usebuffer = false; } -#define UNLOAD(x) if (x) {Z_ChangeTag(x, PU_CACHE);} x = NULL; -#define CLEANUP(x) x = NULL; +#define UNLOAD(x) if (x) {Z_ChangeTag(*x, PU_CACHE);} x = NULL; // // Y_UnloadData // static void Y_UnloadData(void) { - // In hardware mode, don't Z_ChangeTag a pointer returned by W_CachePatchName(). + // In hardware mode, don't Z_ChangeTag a pointer returned by W_GetPatchPointerFromName(). // It doesn't work and is unnecessary. if (rendermode != render_soft) return; @@ -2122,46 +2112,3 @@ static void Y_UnloadData(void) break; } } - -static void Y_CleanupData(void) -{ - // unload the background patches - CLEANUP(bgpatch); - CLEANUP(widebgpatch); - CLEANUP(bgtile); - CLEANUP(interpic); - - switch (intertype) - { - case int_coop: - // unload the coop and single player patches - CLEANUP(data.coop.bonuspatches[3]); - CLEANUP(data.coop.bonuspatches[2]); - CLEANUP(data.coop.bonuspatches[1]); - CLEANUP(data.coop.bonuspatches[0]); - CLEANUP(data.coop.ptotal); - break; - case int_spec: - // unload the special stage patches - //CLEANUP(data.spec.cemerald); - //CLEANUP(data.spec.nowsuper); - CLEANUP(data.spec.bonuspatches[1]); - CLEANUP(data.spec.bonuspatches[0]); - CLEANUP(data.spec.pscore); - CLEANUP(data.spec.pcontinues); - break; - case int_match: - case int_race: - CLEANUP(data.match.result); - break; - case int_ctf: - CLEANUP(data.match.blueflag); - CLEANUP(data.match.redflag); - break; - default: - //without this default, - //int_none, int_tag, int_chaos, and int_classicrace - //are not handled - break; - } -} diff --git a/src/z_zone.c b/src/z_zone.c index 2387a1143..67c909a7a 100644 --- a/src/z_zone.c +++ b/src/z_zone.c @@ -27,7 +27,6 @@ #include "doomdef.h" #include "doomstat.h" -#include "r_patch.h" #include "i_system.h" // I_GetFreeMem #include "i_video.h" // rendermode #include "z_zone.h" @@ -499,33 +498,6 @@ void Z_FreeTags(INT32 lowtag, INT32 hightag) // Utility functions // ----------------- -// for renderer switching -boolean needpatchflush = false; -boolean needpatchrecache = false; - -// flush all patches from memory -void Z_FlushCachedPatches(void) -{ - CONS_Debug(DBG_RENDER, "Z_FlushCachedPatches()...\n"); - Z_FreeTag(PU_PATCH); - Z_FreeTag(PU_HUDGFX); - Z_FreeTag(PU_HWRPATCHINFO); - Z_FreeTag(PU_HWRMODELTEXTURE); - Z_FreeTag(PU_HWRCACHE); - Z_FreeTag(PU_HWRCACHE_UNLOCKED); - Z_FreeTag(PU_HWRPATCHINFO_UNLOCKED); - Z_FreeTag(PU_HWRMODELTEXTURE_UNLOCKED); -} - -// happens before a renderer switch -void Z_PreparePatchFlush(void) -{ - CONS_Debug(DBG_RENDER, "Z_PreparePatchFlush()...\n"); -#ifdef ROTSPRITE - R_FreeAllRotSprite(); -#endif -} - // starting value of nextcleanup #define CLEANUPCOUNT 2000 diff --git a/src/z_zone.h b/src/z_zone.h index 5cbcc6655..2c872c352 100644 --- a/src/z_zone.h +++ b/src/z_zone.h @@ -142,12 +142,5 @@ size_t Z_TagsUsage(INT32 lowtag, INT32 hightag); // Miscellaneous functions // char *Z_StrDup(const char *in); -#define Z_Unlock(p) (void)p // TODO: remove this now that NDS code has been removed - -// For renderer switching -extern boolean needpatchflush; -extern boolean needpatchrecache; -void Z_FlushCachedPatches(void); -void Z_PreparePatchFlush(void); #endif