Merge remote-tracking branch 'origin/next' into more-platform-fixes

This commit is contained in:
Lachlan 2020-07-04 05:25:38 +08:00
commit e2bdb56f97
94 changed files with 4576 additions and 3208 deletions

View file

@ -418,6 +418,7 @@ endif()
if(${SRB2_CONFIG_HWRENDER}) if(${SRB2_CONFIG_HWRENDER})
add_definitions(-DHWRENDER) add_definitions(-DHWRENDER)
set(SRB2_HWRENDER_SOURCES set(SRB2_HWRENDER_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_batching.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_bsp.c ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_bsp.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_cache.c ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_cache.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.c ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.c
@ -433,6 +434,7 @@ if(${SRB2_CONFIG_HWRENDER})
) )
set (SRB2_HWRENDER_HEADERS set (SRB2_HWRENDER_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_batching.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.h ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_data.h ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_data.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_defs.h ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_defs.h

View file

@ -222,12 +222,10 @@ endif
ifdef NOHW ifdef NOHW
OPTS+=-DNOHW OPTS+=-DNOHW
else else
#Hurdler: not really supported and not tested recently
#OPTS+=-DUSE_PALETTED_TEXTURE
OPTS+=-DHWRENDER OPTS+=-DHWRENDER
OBJS+=$(OBJDIR)/hw_bsp.o $(OBJDIR)/hw_draw.o $(OBJDIR)/hw_light.o \ OBJS+=$(OBJDIR)/hw_bsp.o $(OBJDIR)/hw_draw.o $(OBJDIR)/hw_light.o \
$(OBJDIR)/hw_main.o $(OBJDIR)/hw_clip.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o $(OBJDIR)/hw_trick.o \ $(OBJDIR)/hw_main.o $(OBJDIR)/hw_clip.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o $(OBJDIR)/hw_trick.o \
$(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o $(OBJDIR)/u_list.o $(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o $(OBJDIR)/u_list.o $(OBJDIR)/hw_batching.o
endif endif
ifdef NOHS ifdef NOHS

View file

@ -770,7 +770,7 @@ boolean CON_Responder(event_t *ev)
// check for console toggle key // check for console toggle key
if (ev->type != ev_console) if (ev->type != ev_console)
{ {
if (modeattacking || metalrecording) if (modeattacking || metalrecording || marathonmode)
return false; return false;
if (key == gamecontrol[gc_console][0] || key == gamecontrol[gc_console][1]) if (key == gamecontrol[gc_console][0] || key == gamecontrol[gc_console][1])
@ -1649,10 +1649,7 @@ void CON_Drawer(void)
return; return;
if (needpatchrecache) if (needpatchrecache)
{
W_FlushCachedPatches();
HU_LoadGraphics(); HU_LoadGraphics();
}
if (con_recalc) if (con_recalc)
{ {

View file

@ -45,7 +45,7 @@
#include "lua_hook.h" #include "lua_hook.h"
#include "md5.h" #include "md5.h"
#ifdef CLIENT_LOADINGSCREEN #ifndef NONET
// cl loading screen // cl loading screen
#include "v_video.h" #include "v_video.h"
#include "f_finale.h" #include "f_finale.h"
@ -1107,19 +1107,13 @@ static void SV_AcknowledgeResynchAck(INT32 node, UINT8 rsg)
static INT16 Consistancy(void); static INT16 Consistancy(void);
#ifndef NONET
#define JOININGAME
#endif
typedef enum typedef enum
{ {
CL_SEARCHING, CL_SEARCHING,
CL_DOWNLOADFILES, CL_DOWNLOADFILES,
CL_ASKJOIN, CL_ASKJOIN,
CL_WAITJOINRESPONSE, CL_WAITJOINRESPONSE,
#ifdef JOININGAME
CL_DOWNLOADSAVEGAME, CL_DOWNLOADSAVEGAME,
#endif
CL_CONNECTED, CL_CONNECTED,
CL_ABORTED CL_ABORTED
} cl_mode_t; } cl_mode_t;
@ -1162,7 +1156,7 @@ static void CV_LoadPlayerNames(UINT8 **p)
} }
} }
#ifdef CLIENT_LOADINGSCREEN #ifndef NONET
#define SNAKE_SPEED 5 #define SNAKE_SPEED 5
#define SNAKE_NUM_BLOCKS_X 20 #define SNAKE_NUM_BLOCKS_X 20
@ -1684,7 +1678,6 @@ static inline void CL_DrawConnectionStatus(void)
switch (cl_mode) switch (cl_mode)
{ {
#ifdef JOININGAME
case CL_DOWNLOADSAVEGAME: case CL_DOWNLOADSAVEGAME:
if (lastfilenum != -1) if (lastfilenum != -1)
{ {
@ -1710,7 +1703,6 @@ static inline void CL_DrawConnectionStatus(void)
else else
cltext = M_GetText("Waiting to download game state..."); cltext = M_GetText("Waiting to download game state...");
break; break;
#endif
case CL_ASKJOIN: case CL_ASKJOIN:
case CL_WAITJOINRESPONSE: case CL_WAITJOINRESPONSE:
cltext = M_GetText("Requesting to join..."); cltext = M_GetText("Requesting to join...");
@ -2048,7 +2040,7 @@ static boolean SV_SendServerConfig(INT32 node)
return waspacketsent; return waspacketsent;
} }
#ifdef JOININGAME #ifndef NONET
#define SAVEGAMESIZE (768*1024) #define SAVEGAMESIZE (768*1024)
static void SV_SendSaveGame(INT32 node) static void SV_SendSaveGame(INT32 node)
@ -2494,7 +2486,9 @@ static boolean CL_ServerConnectionSearchTicker(boolean viams, tic_t *asksent)
if (CL_SendFileRequest()) if (CL_SendFileRequest())
{ {
cl_mode = CL_DOWNLOADFILES; cl_mode = CL_DOWNLOADFILES;
#ifndef NONET
Snake_Initialise(); Snake_Initialise();
#endif
} }
} }
} }
@ -2559,18 +2553,20 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic
if (waitmore) if (waitmore)
break; // exit the case break; // exit the case
#ifndef NONET
if (snake) if (snake)
{ {
free(snake); free(snake);
snake = NULL; snake = NULL;
} }
#endif
cl_mode = CL_ASKJOIN; // don't break case continue to cljoin request now cl_mode = CL_ASKJOIN; // don't break case continue to cljoin request now
/* FALLTHRU */ /* FALLTHRU */
case CL_ASKJOIN: case CL_ASKJOIN:
CL_LoadServerFiles(); CL_LoadServerFiles();
#ifdef JOININGAME #ifndef NONET
// prepare structures to save the file // prepare structures to save the file
// WARNING: this can be useless in case of server not in GS_LEVEL // WARNING: this can be useless in case of server not in GS_LEVEL
// but since the network layer doesn't provide ordered packets... // but since the network layer doesn't provide ordered packets...
@ -2580,7 +2576,7 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic
cl_mode = CL_WAITJOINRESPONSE; cl_mode = CL_WAITJOINRESPONSE;
break; break;
#ifdef JOININGAME #ifndef NONET
case CL_DOWNLOADSAVEGAME: case CL_DOWNLOADSAVEGAME:
// At this state, the first (and only) needed file is the gamestate // At this state, the first (and only) needed file is the gamestate
if (fileneeded[0].status == FS_FOUND) if (fileneeded[0].status == FS_FOUND)
@ -2620,11 +2616,13 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic
CONS_Printf(M_GetText("Network game synchronization aborted.\n")); CONS_Printf(M_GetText("Network game synchronization aborted.\n"));
// M_StartMessage(M_GetText("Network game synchronization aborted.\n\nPress ESC\n"), NULL, MM_NOTHING); // M_StartMessage(M_GetText("Network game synchronization aborted.\n\nPress ESC\n"), NULL, MM_NOTHING);
#ifndef NONET
if (snake) if (snake)
{ {
free(snake); free(snake);
snake = NULL; snake = NULL;
} }
#endif
D_QuitNetGame(); D_QuitNetGame();
CL_Reset(); CL_Reset();
@ -2632,8 +2630,10 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic
memset(gamekeydown, 0, NUMKEYS); memset(gamekeydown, 0, NUMKEYS);
return false; return false;
} }
#ifndef NONET
else if (cl_mode == CL_DOWNLOADFILES && snake) else if (cl_mode == CL_DOWNLOADFILES && snake)
Snake_Handle(); Snake_Handle();
#endif
if (client && (cl_mode == CL_DOWNLOADFILES || cl_mode == CL_DOWNLOADSAVEGAME)) if (client && (cl_mode == CL_DOWNLOADFILES || cl_mode == CL_DOWNLOADSAVEGAME))
FileReceiveTicker(); FileReceiveTicker();
@ -2644,7 +2644,7 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic
//FileSendTicker(); //FileSendTicker();
*oldtic = I_GetTime(); *oldtic = I_GetTime();
#ifdef CLIENT_LOADINGSCREEN #ifndef NONET
if (client && cl_mode != CL_CONNECTED && cl_mode != CL_ABORTED) if (client && cl_mode != CL_CONNECTED && cl_mode != CL_ABORTED)
{ {
if (cl_mode != CL_DOWNLOADFILES && cl_mode != CL_DOWNLOADSAVEGAME) if (cl_mode != CL_DOWNLOADFILES && cl_mode != CL_DOWNLOADSAVEGAME)
@ -2683,20 +2683,16 @@ static void CL_ConnectToServer(boolean viams)
tic_t oldtic; tic_t oldtic;
#ifndef NONET #ifndef NONET
tic_t asksent; tic_t asksent;
#endif
#ifdef JOININGAME
char tmpsave[256]; char tmpsave[256];
sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home); sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home);
lastfilenum = -1;
#endif #endif
cl_mode = CL_SEARCHING; cl_mode = CL_SEARCHING;
#ifdef CLIENT_LOADINGSCREEN #ifndef NONET
lastfilenum = -1;
#endif
#ifdef JOININGAME
// Don't get a corrupt savegame error because tmpsave already exists // Don't get a corrupt savegame error because tmpsave already exists
if (FIL_FileExists(tmpsave) && unlink(tmpsave) == -1) if (FIL_FileExists(tmpsave) && unlink(tmpsave) == -1)
I_Error("Can't delete %s\n", tmpsave); I_Error("Can't delete %s\n", tmpsave);
@ -3576,6 +3572,8 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
if (pnum == consoleplayer) if (pnum == consoleplayer)
{ {
if (Playing())
LUAh_GameQuit();
#ifdef DUMPCONSISTENCY #ifdef DUMPCONSISTENCY
if (msg == KICK_MSG_CON_FAIL) SV_SavedGame(); if (msg == KICK_MSG_CON_FAIL) SV_SavedGame();
#endif #endif
@ -4215,7 +4213,7 @@ static void HandleConnect(SINT8 node)
G_SetGamestate(backupstate); G_SetGamestate(backupstate);
DEBFILE("new node joined\n"); DEBFILE("new node joined\n");
} }
#ifdef JOININGAME #ifndef NONET
if (nodewaiting[node]) if (nodewaiting[node])
{ {
if ((gamestate == GS_LEVEL || gamestate == GS_INTERMISSION) && newnode) if ((gamestate == GS_LEVEL || gamestate == GS_INTERMISSION) && newnode)
@ -4227,11 +4225,6 @@ static void HandleConnect(SINT8 node)
joindelay += cv_joindelay.value * TICRATE; joindelay += cv_joindelay.value * TICRATE;
player_joining = true; player_joining = true;
} }
#else
#ifndef NONET
// I guess we have no use for this if we aren't doing mid-level joins?
(void)newnode;
#endif
#endif #endif
} }
} }
@ -4244,6 +4237,8 @@ static void HandleConnect(SINT8 node)
static void HandleShutdown(SINT8 node) static void HandleShutdown(SINT8 node)
{ {
(void)node; (void)node;
if (Playing())
LUAh_GameQuit();
D_QuitNetGame(); D_QuitNetGame();
CL_Reset(); CL_Reset();
D_StartTitle(); D_StartTitle();
@ -4258,6 +4253,8 @@ static void HandleShutdown(SINT8 node)
static void HandleTimeout(SINT8 node) static void HandleTimeout(SINT8 node)
{ {
(void)node; (void)node;
if (Playing())
LUAh_GameQuit();
D_QuitNetGame(); D_QuitNetGame();
CL_Reset(); CL_Reset();
D_StartTitle(); D_StartTitle();
@ -4409,7 +4406,7 @@ static void HandlePacketFromAwayNode(SINT8 node)
playernode[(UINT8)serverplayer] = servernode; playernode[(UINT8)serverplayer] = servernode;
if (netgame) if (netgame)
#ifdef JOININGAME #ifndef NONET
CONS_Printf(M_GetText("Join accepted, waiting for complete game state...\n")); CONS_Printf(M_GetText("Join accepted, waiting for complete game state...\n"));
#else #else
CONS_Printf(M_GetText("Join accepted, waiting for next level change...\n")); CONS_Printf(M_GetText("Join accepted, waiting for next level change...\n"));
@ -4433,7 +4430,7 @@ static void HandlePacketFromAwayNode(SINT8 node)
scp = netbuffer->u.servercfg.varlengthinputs; scp = netbuffer->u.servercfg.varlengthinputs;
CV_LoadPlayerNames(&scp); CV_LoadPlayerNames(&scp);
CV_LoadNetVars(&scp); CV_LoadNetVars(&scp);
#ifdef JOININGAME #ifndef NONET
/// \note Wait. What if a Lua script uses some global custom variables synched with the NetVars hook? /// \note Wait. What if a Lua script uses some global custom variables synched with the NetVars hook?
/// Shouldn't them be downloaded even at intermission time? /// Shouldn't them be downloaded even at intermission time?
/// Also, according to HandleConnect, the server will send the savegame even during intermission... /// Also, according to HandleConnect, the server will send the savegame even during intermission...
@ -5499,7 +5496,7 @@ void NetUpdate(void)
// update node latency values so we can take an average later. // update node latency values so we can take an average later.
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && playernode[i] != UINT8_MAX) if (playeringame[i] && playernode[i] != UINT8_MAX)
realpingtable[i] += G_TicsToMilliseconds(GetLag(playernode[i])); realpingtable[i] += GetLag(playernode[i]) * (1000.00f / TICRATE);
pingmeasurecount++; pingmeasurecount++;
} }

View file

@ -33,7 +33,7 @@ applications may follow different packet versions.
// be transmitted. // be transmitted.
// Networking and tick handling related. // Networking and tick handling related.
#define BACKUPTICS 96 #define BACKUPTICS 1024
#define CLIENTBACKUPTICS 32 #define CLIENTBACKUPTICS 32
#define MAXTEXTCMD 256 #define MAXTEXTCMD 256
// //

View file

@ -129,6 +129,7 @@ UINT16 numskincolors;
menucolor_t *menucolorhead, *menucolortail; menucolor_t *menucolorhead, *menucolortail;
char savegamename[256]; char savegamename[256];
char liveeventbackup[256];
char srb2home[256] = "."; char srb2home[256] = ".";
char srb2path[256] = "."; char srb2path[256] = ".";
@ -416,6 +417,7 @@ static void D_Display(void)
if (!automapactive && !dedicated && cv_renderview.value) if (!automapactive && !dedicated && cv_renderview.value)
{ {
rs_rendercalltime = I_GetTimeMicros();
if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD) if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD)
{ {
topleft = screens[0] + viewwindowy*vid.width + viewwindowx; topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
@ -462,6 +464,7 @@ static void D_Display(void)
if (postimgtype2) if (postimgtype2)
V_DoPostProcessor(1, postimgtype2, postimgparam2); V_DoPostProcessor(1, postimgtype2, postimgparam2);
} }
rs_rendercalltime = I_GetTimeMicros() - rs_rendercalltime;
} }
if (lastdraw) if (lastdraw)
@ -597,22 +600,96 @@ static void D_Display(void)
V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-10, V_YELLOWMAP, s); V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-10, V_YELLOWMAP, s);
} }
if (cv_renderstats.value)
{
char s[50];
int frametime = I_GetTimeMicros() - rs_prevframetime;
int divisor = 1;
rs_prevframetime = I_GetTimeMicros();
if (rs_rendercalltime > 10000) divisor = 1000;
snprintf(s, sizeof s - 1, "ft %d", frametime / divisor);
V_DrawThinString(30, 10, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "rtot %d", rs_rendercalltime / divisor);
V_DrawThinString(30, 20, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "bsp %d", rs_bsptime / divisor);
V_DrawThinString(30, 30, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "nbsp %d", rs_numbspcalls);
V_DrawThinString(80, 10, V_MONOSPACE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "nspr %d", rs_numsprites);
V_DrawThinString(80, 20, V_MONOSPACE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "nnod %d", rs_numdrawnodes);
V_DrawThinString(80, 30, V_MONOSPACE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "npob %d", rs_numpolyobjects);
V_DrawThinString(80, 40, V_MONOSPACE | V_BLUEMAP, s);
if (rendermode == render_opengl) // OpenGL specific stats
{
snprintf(s, sizeof s - 1, "nsrt %d", rs_hw_nodesorttime / divisor);
V_DrawThinString(30, 40, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "ndrw %d", rs_hw_nodedrawtime / divisor);
V_DrawThinString(30, 50, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "ssrt %d", rs_hw_spritesorttime / divisor);
V_DrawThinString(30, 60, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "sdrw %d", rs_hw_spritedrawtime / divisor);
V_DrawThinString(30, 70, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "fin %d", rs_swaptime / divisor);
V_DrawThinString(30, 80, V_MONOSPACE | V_YELLOWMAP, s);
if (cv_grbatching.value)
{
snprintf(s, sizeof s - 1, "bsrt %d", rs_hw_batchsorttime / divisor);
V_DrawThinString(80, 55, V_MONOSPACE | V_REDMAP, s);
snprintf(s, sizeof s - 1, "bdrw %d", rs_hw_batchdrawtime / divisor);
V_DrawThinString(80, 65, V_MONOSPACE | V_REDMAP, s);
snprintf(s, sizeof s - 1, "npol %d", rs_hw_numpolys);
V_DrawThinString(130, 10, V_MONOSPACE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "ndc %d", rs_hw_numcalls);
V_DrawThinString(130, 20, V_MONOSPACE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "nshd %d", rs_hw_numshaders);
V_DrawThinString(130, 30, V_MONOSPACE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "nvrt %d", rs_hw_numverts);
V_DrawThinString(130, 40, V_MONOSPACE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "ntex %d", rs_hw_numtextures);
V_DrawThinString(185, 10, V_MONOSPACE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "npf %d", rs_hw_numpolyflags);
V_DrawThinString(185, 20, V_MONOSPACE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "ncol %d", rs_hw_numcolors);
V_DrawThinString(185, 30, V_MONOSPACE | V_PURPLEMAP, s);
}
}
else // software specific stats
{
snprintf(s, sizeof s - 1, "prtl %d", rs_sw_portaltime / divisor);
V_DrawThinString(30, 40, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "plns %d", rs_sw_planetime / divisor);
V_DrawThinString(30, 50, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "mskd %d", rs_sw_maskedtime / divisor);
V_DrawThinString(30, 60, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "fin %d", rs_swaptime / divisor);
V_DrawThinString(30, 70, V_MONOSPACE | V_YELLOWMAP, s);
}
}
rs_swaptime = I_GetTimeMicros();
I_FinishUpdate(); // page flip or blit buffer I_FinishUpdate(); // page flip or blit buffer
rs_swaptime = I_GetTimeMicros() - rs_swaptime;
} }
needpatchflush = false; needpatchflush = false;
needpatchrecache = false; needpatchrecache = false;
} }
// Lactozilla: Check the renderer's state // Check the renderer's state
// after a possible renderer switch. // after a possible renderer switch.
void D_CheckRendererState(void) void D_CheckRendererState(void)
{ {
// flush all patches from memory // flush all patches from memory
// (also frees memory tagged with PU_CACHE)
// (which are not necessarily patches but I don't care)
if (needpatchflush) if (needpatchflush)
{
Z_FlushCachedPatches(); Z_FlushCachedPatches();
needpatchflush = false;
}
// some patches have been freed, // some patches have been freed,
// so cache them again // so cache them again
@ -668,7 +745,7 @@ void D_SRB2Loop(void)
*/ */
/* Smells like a hack... Don't fade Sonic's ass into the title screen. */ /* Smells like a hack... Don't fade Sonic's ass into the title screen. */
if (gamestate != GS_TITLESCREEN) if (gamestate != GS_TITLESCREEN)
V_DrawScaledPatch(0, 0, 0, W_CachePatchNum(W_GetNumForName("CONSBACK"), PU_CACHE)); V_DrawScaledPatch(0, 0, 0, W_CachePatchNum(W_GetNumForName("CONSBACK"), PU_PATCH));
for (;;) for (;;)
{ {
@ -820,6 +897,7 @@ void D_StartTitle(void)
// In case someone exits out at the same time they start a time attack run, // In case someone exits out at the same time they start a time attack run,
// reset modeattacking // reset modeattacking
modeattacking = ATTACKING_NONE; modeattacking = ATTACKING_NONE;
marathonmode = 0;
// empty maptol so mario/etc sounds don't play in sound test when they shouldn't // empty maptol so mario/etc sounds don't play in sound test when they shouldn't
maptol = 0; maptol = 0;
@ -1136,6 +1214,7 @@ void D_SRB2Main(void)
// default savegame // default savegame
strcpy(savegamename, SAVEGAMENAME"%u.ssg"); strcpy(savegamename, SAVEGAMENAME"%u.ssg");
strcpy(liveeventbackup, "live"SAVEGAMENAME".bkp"); // intentionally not ending with .ssg
{ {
const char *userhome = D_Home(); //Alam: path to home const char *userhome = D_Home(); //Alam: path to home
@ -1164,6 +1243,7 @@ void D_SRB2Main(void)
// can't use sprintf since there is %u in savegamename // can't use sprintf since there is %u in savegamename
strcatbf(savegamename, srb2home, PATHSEP); strcatbf(savegamename, srb2home, PATHSEP);
strcatbf(liveeventbackup, srb2home, PATHSEP);
snprintf(luafiledir, sizeof luafiledir, "%s" PATHSEP "luafiles", srb2home); snprintf(luafiledir, sizeof luafiledir, "%s" PATHSEP "luafiles", srb2home);
#else // DEFAULTDIR #else // DEFAULTDIR
@ -1176,6 +1256,7 @@ void D_SRB2Main(void)
// can't use sprintf since there is %u in savegamename // can't use sprintf since there is %u in savegamename
strcatbf(savegamename, userhome, PATHSEP); strcatbf(savegamename, userhome, PATHSEP);
strcatbf(liveeventbackup, userhome, PATHSEP);
snprintf(luafiledir, sizeof luafiledir, "%s" PATHSEP "luafiles", userhome); snprintf(luafiledir, sizeof luafiledir, "%s" PATHSEP "luafiles", userhome);
#endif // DEFAULTDIR #endif // DEFAULTDIR

View file

@ -1156,7 +1156,7 @@ UINT8 CanChangeSkin(INT32 playernum)
// Server has skin change restrictions. // Server has skin change restrictions.
if (cv_restrictskinchange.value) if (cv_restrictskinchange.value)
{ {
if (gametype == GT_COOP) if (gametyperules & GTR_FRIENDLY)
return true; return true;
// Can change skin during initial countdown. // Can change skin during initial countdown.
@ -1747,7 +1747,7 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pultmode, boolean rese
} }
CONS_Debug(DBG_GAMELOGIC, "Map change: mapnum=%d gametype=%d ultmode=%d resetplayers=%d delay=%d skipprecutscene=%d\n", CONS_Debug(DBG_GAMELOGIC, "Map change: mapnum=%d gametype=%d ultmode=%d resetplayers=%d delay=%d skipprecutscene=%d\n",
mapnum, newgametype, pultmode, resetplayers, delay, skipprecutscene); mapnum, newgametype, pultmode, resetplayers, delay, skipprecutscene);
if ((netgame || multiplayer) && !((gametype == newgametype) && (newgametype == GT_COOP))) if ((netgame || multiplayer) && !((gametype == newgametype) && (gametypedefaultrules[newgametype] & GTR_CAMPAIGN)))
FLS = false; FLS = false;
if (delay != 2) if (delay != 2)
@ -1989,7 +1989,7 @@ static void Command_Map_f(void)
fromlevelselect = fromlevelselect =
( netgame || multiplayer ) && ( netgame || multiplayer ) &&
newgametype == gametype && newgametype == gametype &&
newgametype == GT_COOP; gametypedefaultrules[newgametype] & GTR_CAMPAIGN;
} }
} }
@ -2779,7 +2779,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
players[playernum].spectator = false; players[playernum].spectator = false;
//If joining after hidetime in normal tag, default to being IT. //If joining after hidetime in normal tag, default to being IT.
if (gametype == GT_TAG && (leveltime > (hidetime * TICRATE))) if (((gametyperules & (GTR_TAG|GTR_HIDEFROZEN)) == GTR_TAG) && (leveltime > (hidetime * TICRATE)))
{ {
NetPacket.packet.newteam = 1; //minor hack, causes the "is it" message to be printed later. NetPacket.packet.newteam = 1; //minor hack, causes the "is it" message to be printed later.
players[playernum].pflags |= PF_TAGIT; //make the player IT. players[playernum].pflags |= PF_TAGIT; //make the player IT.
@ -3570,6 +3570,8 @@ static void Command_Playintro_f(void)
*/ */
FUNCNORETURN static ATTRNORETURN void Command_Quit_f(void) FUNCNORETURN static ATTRNORETURN void Command_Quit_f(void)
{ {
if (Playing())
LUAh_GameQuit();
I_Quit(); I_Quit();
} }
@ -3627,7 +3629,7 @@ static void PointLimit_OnChange(void)
static void NumLaps_OnChange(void) static void NumLaps_OnChange(void)
{ {
// Just don't be verbose // Just don't be verbose
if (gametype == GT_RACE) if ((gametyperules & (GTR_RACE|GTR_LIVES)) == GTR_RACE)
CONS_Printf(M_GetText("Number of laps set to %d\n"), cv_numlaps.value); CONS_Printf(M_GetText("Number of laps set to %d\n"), cv_numlaps.value);
} }
@ -3741,7 +3743,7 @@ static void ExitMove_OnChange(void)
{ {
UINT8 i; UINT8 i;
if (!(netgame || multiplayer) || gametype != GT_COOP) if (!(netgame || multiplayer) || !(gametyperules & GTR_FRIENDLY))
return; return;
if (cv_exitmove.value) if (cv_exitmove.value)
@ -4231,6 +4233,9 @@ void Command_ExitGame_f(void)
{ {
INT32 i; INT32 i;
if (Playing())
LUAh_GameQuit();
D_QuitNetGame(); D_QuitNetGame();
CL_Reset(); CL_Reset();
CV_ClearChangedFlags(); CV_ClearChangedFlags();
@ -4615,7 +4620,7 @@ static void Command_ShowTime_f(void)
static void BaseNumLaps_OnChange(void) static void BaseNumLaps_OnChange(void)
{ {
if (gametype == GT_RACE) if ((gametyperules & (GTR_RACE|GTR_LIVES)) == GTR_RACE)
{ {
if (cv_basenumlaps.value) if (cv_basenumlaps.value)
CONS_Printf(M_GetText("Number of laps will be changed to map defaults next round.\n")); CONS_Printf(M_GetText("Number of laps will be changed to map defaults next round.\n"));

View file

@ -106,7 +106,7 @@ typedef struct
} pauseddownload_t; } pauseddownload_t;
static pauseddownload_t *pauseddownload = NULL; static pauseddownload_t *pauseddownload = NULL;
#ifdef CLIENT_LOADINGSCREEN #ifndef NONET
// for cl loading screen // for cl loading screen
INT32 lastfilenum = -1; INT32 lastfilenum = -1;
#endif #endif
@ -188,7 +188,7 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr)
void CL_PrepareDownloadSaveGame(const char *tmpsave) void CL_PrepareDownloadSaveGame(const char *tmpsave)
{ {
#ifdef CLIENT_LOADINGSCREEN #ifndef NONET
lastfilenum = -1; lastfilenum = -1;
#endif #endif
@ -1360,7 +1360,7 @@ void PT_FileFragment(void)
I_Error("Received a file not requested (file id: %d, file status: %s)\n", filenum, s); I_Error("Received a file not requested (file id: %d, file status: %s)\n", filenum, s);
} }
#ifdef CLIENT_LOADINGSCREEN #ifndef NONET
lastfilenum = filenum; lastfilenum = filenum;
#endif #endif
} }

View file

@ -58,7 +58,7 @@ extern INT32 fileneedednum;
extern fileneeded_t fileneeded[MAX_WADFILES]; extern fileneeded_t fileneeded[MAX_WADFILES];
extern char downloaddir[512]; extern char downloaddir[512];
#ifdef CLIENT_LOADINGSCREEN #ifndef NONET
extern INT32 lastfilenum; extern INT32 lastfilenum;
#endif #endif

View file

@ -1669,6 +1669,22 @@ static void readlevelheader(MYFILE *f, INT32 num)
mapheaderinfo[num-1]->nextlevel = (INT16)i; mapheaderinfo[num-1]->nextlevel = (INT16)i;
} }
else if (fastcmp(word, "MARATHONNEXT"))
{
if (fastcmp(word2, "TITLE")) i = 1100;
else if (fastcmp(word2, "EVALUATION")) i = 1101;
else if (fastcmp(word2, "CREDITS")) i = 1102;
else if (fastcmp(word2, "ENDING")) i = 1103;
else
// Support using the actual map name,
// i.e., MarathonNext = AB, MarathonNext = FZ, etc.
// Convert to map number
if (word2[0] >= 'A' && word2[0] <= 'Z' && word2[2] == '\0')
i = M_MapNumber(word2[0], word2[1]);
mapheaderinfo[num-1]->marathonnext = (INT16)i;
}
else if (fastcmp(word, "TYPEOFLEVEL")) else if (fastcmp(word, "TYPEOFLEVEL"))
{ {
if (i) // it's just a number if (i) // it's just a number
@ -4011,7 +4027,20 @@ static void readmaincfg(MYFILE *f)
else else
value = get_number(word2); value = get_number(word2);
spstage_start = (INT16)value; spstage_start = spmarathon_start = (INT16)value;
}
else if (fastcmp(word, "SPMARATHON_START"))
{
// Support using the actual map name,
// i.e., Level AB, Level FZ, etc.
// Convert to map number
if (word2[0] >= 'A' && word2[0] <= 'Z')
value = M_MapNumber(word2[0], word2[1]);
else
value = get_number(word2);
spmarathon_start = (INT16)value;
} }
else if (fastcmp(word, "SSTAGE_START")) else if (fastcmp(word, "SSTAGE_START"))
{ {
@ -4105,6 +4134,17 @@ static void readmaincfg(MYFILE *f)
introtoplay = 128; introtoplay = 128;
introchanged = true; introchanged = true;
} }
else if (fastcmp(word, "CREDITSCUTSCENE"))
{
creditscutscene = (UINT8)get_number(word2);
// range check, you morons.
if (creditscutscene > 128)
creditscutscene = 128;
}
else if (fastcmp(word, "USEBLACKROCK"))
{
useBlackRock = (UINT8)(value || word2[0] == 'T' || word2[0] == 'Y');
}
else if (fastcmp(word, "LOOPTITLE")) else if (fastcmp(word, "LOOPTITLE"))
{ {
looptitle = (value || word2[0] == 'T' || word2[0] == 'Y'); looptitle = (value || word2[0] == 'T' || word2[0] == 'Y');
@ -4206,13 +4246,6 @@ static void readmaincfg(MYFILE *f)
titlescrollyspeed = get_number(word2); titlescrollyspeed = get_number(word2);
titlechanged = true; titlechanged = true;
} }
else if (fastcmp(word, "CREDITSCUTSCENE"))
{
creditscutscene = (UINT8)get_number(word2);
// range check, you morons.
if (creditscutscene > 128)
creditscutscene = 128;
}
else if (fastcmp(word, "DISABLESPEEDADJUST")) else if (fastcmp(word, "DISABLESPEEDADJUST"))
{ {
disableSpeedAdjust = (value || word2[0] == 'T' || word2[0] == 'Y'); disableSpeedAdjust = (value || word2[0] == 'T' || word2[0] == 'Y');
@ -4269,6 +4302,9 @@ static void readmaincfg(MYFILE *f)
// can't use sprintf since there is %u in savegamename // can't use sprintf since there is %u in savegamename
strcatbf(savegamename, srb2home, PATHSEP); strcatbf(savegamename, srb2home, PATHSEP);
strcpy(liveeventbackup, va("live%s.bkp", timeattackfolder));
strcatbf(liveeventbackup, srb2home, PATHSEP);
gamedataadded = true; gamedataadded = true;
titlechanged = true; titlechanged = true;
} }
@ -5720,10 +5756,12 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_FANG_PINCHPATHINGSTART1", "S_FANG_PINCHPATHINGSTART1",
"S_FANG_PINCHPATHINGSTART2", "S_FANG_PINCHPATHINGSTART2",
"S_FANG_PINCHPATHING", "S_FANG_PINCHPATHING",
"S_FANG_PINCHBOUNCE0",
"S_FANG_PINCHBOUNCE1", "S_FANG_PINCHBOUNCE1",
"S_FANG_PINCHBOUNCE2", "S_FANG_PINCHBOUNCE2",
"S_FANG_PINCHBOUNCE3", "S_FANG_PINCHBOUNCE3",
"S_FANG_PINCHBOUNCE4", "S_FANG_PINCHBOUNCE4",
"S_FANG_PINCHFALL0",
"S_FANG_PINCHFALL1", "S_FANG_PINCHFALL1",
"S_FANG_PINCHFALL2", "S_FANG_PINCHFALL2",
"S_FANG_PINCHSKID1", "S_FANG_PINCHSKID1",
@ -9364,8 +9402,6 @@ static const char *const MENUTYPES_LIST[] = {
"OP_COLOR", "OP_COLOR",
"OP_OPENGL", "OP_OPENGL",
"OP_OPENGL_LIGHTING", "OP_OPENGL_LIGHTING",
"OP_OPENGL_FOG",
"OP_OPENGL_COLOR",
"OP_SOUND", "OP_SOUND",
@ -9470,6 +9506,7 @@ struct {
{"FF_GLOBALANIM",FF_GLOBALANIM}, {"FF_GLOBALANIM",FF_GLOBALANIM},
{"FF_FULLBRIGHT",FF_FULLBRIGHT}, {"FF_FULLBRIGHT",FF_FULLBRIGHT},
{"FF_VERTICALFLIP",FF_VERTICALFLIP}, {"FF_VERTICALFLIP",FF_VERTICALFLIP},
{"FF_HORIZONTALFLIP",FF_HORIZONTALFLIP},
{"FF_PAPERSPRITE",FF_PAPERSPRITE}, {"FF_PAPERSPRITE",FF_PAPERSPRITE},
{"FF_TRANSMASK",FF_TRANSMASK}, {"FF_TRANSMASK",FF_TRANSMASK},
{"FF_TRANSSHIFT",FF_TRANSSHIFT}, {"FF_TRANSSHIFT",FF_TRANSSHIFT},
@ -9998,6 +10035,12 @@ struct {
{"TC_BLINK",TC_BLINK}, {"TC_BLINK",TC_BLINK},
{"TC_DASHMODE",TC_DASHMODE}, {"TC_DASHMODE",TC_DASHMODE},
// marathonmode flags
{"MA_INIT",MA_INIT},
{"MA_RUNNING",MA_RUNNING},
{"MA_NOCUTSCENES",MA_NOCUTSCENES},
{"MA_INGAME",MA_INGAME},
{NULL,0} {NULL,0}
}; };

View file

@ -90,6 +90,9 @@ static unsigned long nombre = NEWTICRATE*10;
static void I_BlitScreenVesa1(void); //see later static void I_BlitScreenVesa1(void); //see later
void I_FinishUpdate (void) void I_FinishUpdate (void)
{ {
if (marathonmode)
SCR_DisplayMarathonInfo();
// draw captions if enabled // draw captions if enabled
if (cv_closedcaptioning.value) if (cv_closedcaptioning.value)
SCR_ClosedCaptions(); SCR_ClosedCaptions();

View file

@ -479,6 +479,7 @@ void CONS_Debug(INT32 debugflags, const char *fmt, ...) FUNCDEBUG;
// Things that used to be in dstrings.h // Things that used to be in dstrings.h
#define SAVEGAMENAME "srb2sav" #define SAVEGAMENAME "srb2sav"
extern char savegamename[256]; extern char savegamename[256];
extern char liveeventbackup[256];
// m_misc.h // m_misc.h
#ifdef GETTEXT #ifdef GETTEXT
@ -616,11 +617,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
/// memory that never gets touched. /// memory that never gets touched.
#define ALLOW_RESETDATA #define ALLOW_RESETDATA
#ifndef NONET
/// Display a connection screen on join attempts.
#define CLIENT_LOADINGSCREEN
#endif
/// Experimental tweaks to analog mode. (Needs a lot of work before it's ready for primetime.) /// Experimental tweaks to analog mode. (Needs a lot of work before it's ready for primetime.)
//#define REDSANALOG //#define REDSANALOG
@ -638,17 +634,13 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
/// SRB2CB itself ported this from PrBoom+ /// SRB2CB itself ported this from PrBoom+
#define NEWCLIP #define NEWCLIP
/// OpenGL shaders
#define GL_SHADERS
/// Handle touching sector specials in P_PlayerAfterThink instead of P_PlayerThink. /// Handle touching sector specials in P_PlayerAfterThink instead of P_PlayerThink.
/// \note Required for proper collision with moving sloped surfaces that have sector specials on them. /// \note Required for proper collision with moving sloped surfaces that have sector specials on them.
#define SECTORSPECIALSAFTERTHINK #define SECTORSPECIALSAFTERTHINK
/// FINALLY some real clipping that doesn't make walls dissappear AND speeds the game up
/// (that was the original comment from SRB2CB, sadly it is a lie and actually slows game down)
/// on the bright side it fixes some weird issues with translucent walls
/// \note SRB2CB port.
/// SRB2CB itself ported this from PrBoom+
#define NEWCLIP
/// Cache patches in Lua in a way that renderer switching will work flawlessly. /// Cache patches in Lua in a way that renderer switching will work flawlessly.
//#define LUA_PATCH_SAFETY //#define LUA_PATCH_SAFETY

View file

@ -45,7 +45,19 @@ extern INT32 curWeather;
extern INT32 cursaveslot; extern INT32 cursaveslot;
//extern INT16 lastmapsaved; //extern INT16 lastmapsaved;
extern INT16 lastmaploaded; extern INT16 lastmaploaded;
extern boolean gamecomplete; extern UINT8 gamecomplete;
// Extra abilities/settings for skins (combinable stuff)
typedef enum
{
MA_RUNNING = 1, // In action
MA_INIT = 1<<1, // Initialisation
MA_NOCUTSCENES = 1<<2, // No cutscenes
MA_INGAME = 1<<3 // Timer ignores loads
} marathonmode_t;
extern marathonmode_t marathonmode;
extern tic_t marathontime;
#define maxgameovers 13 #define maxgameovers 13
extern UINT8 numgameovers; extern UINT8 numgameovers;
@ -127,7 +139,7 @@ extern INT32 displayplayer;
extern INT32 secondarydisplayplayer; // for splitscreen extern INT32 secondarydisplayplayer; // for splitscreen
// Maps of special importance // Maps of special importance
extern INT16 spstage_start; extern INT16 spstage_start, spmarathon_start;
extern INT16 sstage_start, sstage_end, smpstage_start, smpstage_end; extern INT16 sstage_start, sstage_end, smpstage_start, smpstage_end;
extern INT16 titlemap; extern INT16 titlemap;
@ -289,6 +301,7 @@ typedef struct
UINT8 actnum; ///< Act number or 0 for none. UINT8 actnum; ///< Act number or 0 for none.
UINT32 typeoflevel; ///< Combination of typeoflevel flags. UINT32 typeoflevel; ///< Combination of typeoflevel flags.
INT16 nextlevel; ///< Map number of next level, or 1100-1102 to end. INT16 nextlevel; ///< Map number of next level, or 1100-1102 to end.
INT16 marathonnext; ///< See nextlevel, but for Marathon mode. Necessary to support hub worlds ala SUGOI.
char keywords[33]; ///< Keywords separated by space to search for. 32 characters. char keywords[33]; ///< Keywords separated by space to search for. 32 characters.
char musname[7]; ///< Music track to play. "" for no music. char musname[7]; ///< Music track to play. "" for no music.
UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore. UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore.
@ -575,11 +588,12 @@ extern UINT16 nightslinktics;
extern UINT8 introtoplay; extern UINT8 introtoplay;
extern UINT8 creditscutscene; extern UINT8 creditscutscene;
extern UINT8 useBlackRock;
extern UINT8 use1upSound; extern UINT8 use1upSound;
extern UINT8 maxXtraLife; // Max extra lives from rings extern UINT8 maxXtraLife; // Max extra lives from rings
extern UINT8 useContinues; extern UINT8 useContinues;
#define continuesInSession (!multiplayer && (useContinues || ultimatemode || !(cursaveslot > 0))) #define continuesInSession (!multiplayer && (ultimatemode || (useContinues && !marathonmode) || (!modeattacking && !(cursaveslot > 0))))
extern mobj_t *hunt1, *hunt2, *hunt3; // Emerald hunt locations extern mobj_t *hunt1, *hunt2, *hunt3; // Emerald hunt locations

View file

@ -16,6 +16,11 @@ tic_t I_GetTime(void)
return 0; return 0;
} }
int I_GetTimeMicros(void)
{
return 0;
}
void I_Sleep(void){} void I_Sleep(void){}
void I_GetEvent(void){} void I_GetEvent(void){}

View file

@ -1118,9 +1118,6 @@ static const char *credits[] = {
"\1Sonic Robo Blast II", "\1Sonic Robo Blast II",
"\1Credits", "\1Credits",
"", "",
"\1Producer",
"Rob Tisdell",
"",
"\1Game Design", "\1Game Design",
"Ben \"Mystic\" Geyer", "Ben \"Mystic\" Geyer",
"\"SSNTails\"", "\"SSNTails\"",
@ -1151,11 +1148,13 @@ static const char *credits[] = {
"", "",
"\1Programming", "\1Programming",
"\1Assistance", "\1Assistance",
"Colette \"fickleheart\" Bordelon",
"\"chi.miru\"", // helped port slope drawing code from ZDoom "\"chi.miru\"", // helped port slope drawing code from ZDoom
"Andrew \"orospakr\" Clunis", "Andrew \"orospakr\" Clunis",
"Sally \"TehRealSalt\" Cochenour", "Sally \"TehRealSalt\" Cochenour",
"Gregor \"Oogaland\" Dick", "Gregor \"Oogaland\" Dick",
"Julio \"Chaos Zero 64\" Guir", "Julio \"Chaos Zero 64\" Guir",
"\"Hannu_Hanhi\"", // For many OpenGL performance improvements!
"\"Kalaron\"", // Coded some of Sryder13's collection of OpenGL fixes, especially fog "\"Kalaron\"", // Coded some of Sryder13's collection of OpenGL fixes, especially fog
"\"Lat'\"", // SRB2-CHAT, the chat window from Kart "\"Lat'\"", // SRB2-CHAT, the chat window from Kart
"Matthew \"Shuffle\" Marsalko", "Matthew \"Shuffle\" Marsalko",
@ -1174,6 +1173,7 @@ static const char *credits[] = {
"\1Art", "\1Art",
"Victor \"VAdaPEGA\" Ara\x1Fjo", // Araújo -- sorry for our limited font! D: "Victor \"VAdaPEGA\" Ara\x1Fjo", // Araújo -- sorry for our limited font! D:
"Ryan \"Blaze Hedgehog\" Bloom", "Ryan \"Blaze Hedgehog\" Bloom",
"\"ChrispyPixels\"",
"Paul \"Boinciel\" Clempson", "Paul \"Boinciel\" Clempson",
"Sally \"TehRealSalt\" Cochenour", "Sally \"TehRealSalt\" Cochenour",
"\"Dave Lite\"", "\"Dave Lite\"",
@ -1220,6 +1220,7 @@ static const char *credits[] = {
"\"SSNTails\"", "\"SSNTails\"",
"", "",
"\1Level Design", "\1Level Design",
"Colette \"fickleheart\" Bordelon",
"Hank \"FuriousFox\" Brannock", "Hank \"FuriousFox\" Brannock",
"Matthew \"Fawfulfan\" Chapman", "Matthew \"Fawfulfan\" Chapman",
"Paul \"Boinciel\" Clempson", "Paul \"Boinciel\" Clempson",
@ -1255,6 +1256,7 @@ static const char *credits[] = {
"Johnny \"Sonikku\" Wallbank", "Johnny \"Sonikku\" Wallbank",
"", "",
"\1Testing", "\1Testing",
"Discord Community Testers",
"Hank \"FuriousFox\" Brannock", "Hank \"FuriousFox\" Brannock",
"Cody \"SRB2 Playah\" Koester", "Cody \"SRB2 Playah\" Koester",
"Skye \"OmegaVelocity\" Meredith", "Skye \"OmegaVelocity\" Meredith",
@ -1330,10 +1332,6 @@ void F_StartCredits(void)
// Just in case they're open ... somehow // Just in case they're open ... somehow
M_ClearMenus(true); M_ClearMenus(true);
// Save the second we enter the credits
if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && cursaveslot > 0)
G_SaveGame((UINT32)cursaveslot);
if (creditscutscene) if (creditscutscene)
{ {
F_StartCustomCutscene(creditscutscene - 1, false, false); F_StartCustomCutscene(creditscutscene - 1, false, false);
@ -1529,12 +1527,6 @@ void F_StartGameEvaluation(void)
// Just in case they're open ... somehow // Just in case they're open ... somehow
M_ClearMenus(true); M_ClearMenus(true);
// Save the second we enter the evaluation
// We need to do this again! Remember, it's possible a mod designed skipped
// the credits sequence!
if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && cursaveslot > 0)
G_SaveGame((UINT32)cursaveslot);
goodending = (ALL7EMERALDS(emeralds)); goodending = (ALL7EMERALDS(emeralds));
gameaction = ga_nothing; gameaction = ga_nothing;
@ -1551,13 +1543,20 @@ void F_GameEvaluationDrawer(void)
angle_t fa; angle_t fa;
INT32 eemeralds_cur; INT32 eemeralds_cur;
char patchname[7] = "CEMGx0"; char patchname[7] = "CEMGx0";
const char* endingtext = (goodending ? "CONGRATULATIONS!" : "TRY AGAIN..."); const char* endingtext;
if (marathonmode)
endingtext = "THANKS FOR THE RUN!";
else if (goodending)
endingtext = "CONGRATULATIONS!";
else
endingtext = "TRY AGAIN...";
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
// Draw all the good crap here. // Draw all the good crap here.
if (finalecount > 0) if (finalecount > 0 && useBlackRock)
{ {
INT32 scale = FRACUNIT; INT32 scale = FRACUNIT;
patch_t *rockpat; patch_t *rockpat;
@ -1684,7 +1683,9 @@ void F_GameEvaluationTicker(void)
return; return;
} }
if (!goodending) if (!useBlackRock)
;
else if (!goodending)
{ {
if (sparklloop) if (sparklloop)
sparklloop--; sparklloop--;
@ -1841,10 +1842,6 @@ void F_StartEnding(void)
// Just in case they're open ... somehow // Just in case they're open ... somehow
M_ClearMenus(true); M_ClearMenus(true);
// Save before the credits sequence.
if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && cursaveslot > 0)
G_SaveGame((UINT32)cursaveslot);
gameaction = ga_nothing; gameaction = ga_nothing;
paused = false; paused = false;
CON_ToggleOff(); CON_ToggleOff();
@ -3959,6 +3956,7 @@ static void F_AdvanceToNextScene(void)
animtimer = pictime = cutscenes[cutnum]->scene[scenenum].picduration[picnum]; animtimer = pictime = cutscenes[cutnum]->scene[scenenum].picduration[picnum];
} }
// See also G_AfterIntermission, the only other place which handles intra-map/ending transitions
void F_EndCutScene(void) void F_EndCutScene(void)
{ {
cutsceneover = true; // do this first, just in case G_EndGame or something wants to turn it back false later cutsceneover = true; // do this first, just in case G_EndGame or something wants to turn it back false later

View file

@ -82,7 +82,10 @@ INT32 curWeather = PRECIP_NONE;
INT32 cursaveslot = 0; // Auto-save 1p savegame slot INT32 cursaveslot = 0; // Auto-save 1p savegame slot
//INT16 lastmapsaved = 0; // Last map we auto-saved at //INT16 lastmapsaved = 0; // Last map we auto-saved at
INT16 lastmaploaded = 0; // Last map the game loaded INT16 lastmaploaded = 0; // Last map the game loaded
boolean gamecomplete = false; UINT8 gamecomplete = 0;
marathonmode_t marathonmode = 0;
tic_t marathontime = 0;
UINT8 numgameovers = 0; // for startinglives balance UINT8 numgameovers = 0; // for startinglives balance
SINT8 startinglivesbalance[maxgameovers+1] = {3, 5, 7, 9, 12, 15, 20, 25, 30, 40, 50, 75, 99, 0x7F}; SINT8 startinglivesbalance[maxgameovers+1] = {3, 5, 7, 9, 12, 15, 20, 25, 30, 40, 50, 75, 99, 0x7F};
@ -118,7 +121,7 @@ UINT32 ssspheres; // old special stage
INT16 lastmap; // last level you were at (returning from special stages) INT16 lastmap; // last level you were at (returning from special stages)
tic_t timeinmap; // Ticker for time spent in level (used for levelcard display) tic_t timeinmap; // Ticker for time spent in level (used for levelcard display)
INT16 spstage_start; INT16 spstage_start, spmarathon_start;
INT16 sstage_start, sstage_end, smpstage_start, smpstage_end; INT16 sstage_start, sstage_end, smpstage_start, smpstage_end;
INT16 titlemap = 0; INT16 titlemap = 0;
@ -223,6 +226,7 @@ UINT8 useContinues = 0; // Set to 1 to enable continues outside of no-save scena
UINT8 introtoplay; UINT8 introtoplay;
UINT8 creditscutscene; UINT8 creditscutscene;
UINT8 useBlackRock = 1;
// Emerald locations // Emerald locations
mobj_t *hunt1; mobj_t *hunt1;
@ -716,14 +720,14 @@ void G_SetNightsRecords(void)
I_Error("Out of memory for replay filepath\n"); I_Error("Out of memory for replay filepath\n");
sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap)); sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap));
snprintf(lastdemo, 255, "%s-last.lmp", gpath); snprintf(lastdemo, 255, "%s-%s-last.lmp", gpath, skins[cv_chooseskin.value-1].name);
if (FIL_FileExists(lastdemo)) if (FIL_FileExists(lastdemo))
{ {
UINT8 *buf; UINT8 *buf;
size_t len = FIL_ReadFile(lastdemo, &buf); size_t len = FIL_ReadFile(lastdemo, &buf);
snprintf(bestdemo, 255, "%s-time-best.lmp", gpath); snprintf(bestdemo, 255, "%s-%s-time-best.lmp", gpath, skins[cv_chooseskin.value-1].name);;
if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & 1) if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & 1)
{ // Better time, save this demo. { // Better time, save this demo.
if (FIL_FileExists(bestdemo)) if (FIL_FileExists(bestdemo))
@ -732,7 +736,7 @@ void G_SetNightsRecords(void)
CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD TIME!"), M_GetText("Saved replay as"), bestdemo); CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD TIME!"), M_GetText("Saved replay as"), bestdemo);
} }
snprintf(bestdemo, 255, "%s-score-best.lmp", gpath); snprintf(bestdemo, 255, "%s-%s-score-best.lmp", gpath, skins[cv_chooseskin.value-1].name);
if (!FIL_FileExists(bestdemo) || (G_CmpDemoTime(bestdemo, lastdemo) & (1<<1))) if (!FIL_FileExists(bestdemo) || (G_CmpDemoTime(bestdemo, lastdemo) & (1<<1)))
{ // Better score, save this demo. { // Better score, save this demo.
if (FIL_FileExists(bestdemo)) if (FIL_FileExists(bestdemo))
@ -769,6 +773,8 @@ void G_SetGameModified(boolean silent)
// If in record attack recording, cancel it. // If in record attack recording, cancel it.
if (modeattacking) if (modeattacking)
M_EndModeAttackRun(); M_EndModeAttackRun();
else if (marathonmode)
Command_ExitGame_f();
} }
/** Builds an original game map name from a map number. /** Builds an original game map name from a map number.
@ -2061,7 +2067,7 @@ boolean G_Responder(event_t *ev)
&& players[displayplayer].ctfteam != players[consoleplayer].ctfteam) && players[displayplayer].ctfteam != players[consoleplayer].ctfteam)
continue; continue;
} }
else if (gametype == GT_HIDEANDSEEK) else if (gametyperules & GTR_HIDEFROZEN)
{ {
if (players[consoleplayer].pflags & PF_TAGIT) if (players[consoleplayer].pflags & PF_TAGIT)
continue; continue;
@ -2179,6 +2185,10 @@ void G_Ticker(boolean run)
UINT32 i; UINT32 i;
INT32 buf; INT32 buf;
// see also SCR_DisplayMarathonInfo
if ((marathonmode & (MA_INIT|MA_INGAME)) == MA_INGAME && gamestate == GS_LEVEL)
marathontime++;
P_MapStart(); P_MapStart();
// do player reborns if needed // do player reborns if needed
if (gamestate == GS_LEVEL) if (gamestate == GS_LEVEL)
@ -2195,8 +2205,13 @@ void G_Ticker(boolean run)
} }
else else
{ {
// Costs a life to retry ... unless the player in question is dead already. // Costs a life to retry ... unless the player in question is dead already, or you haven't even touched the first starpost in marathon run.
if (G_GametypeUsesLives() && players[consoleplayer].playerstate == PST_LIVE && players[consoleplayer].lives != INFLIVES) if (marathonmode && gamemap == spmarathon_start && !players[consoleplayer].starposttime)
{
marathonmode |= MA_INIT;
marathontime = 0;
}
else if (G_GametypeUsesLives() && players[consoleplayer].playerstate == PST_LIVE && players[consoleplayer].lives != INFLIVES)
players[consoleplayer].lives -= 1; players[consoleplayer].lives -= 1;
G_DoReborn(consoleplayer); G_DoReborn(consoleplayer);
@ -2603,7 +2618,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0); S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
} }
if (gametype == GT_COOP) if (gametyperules & GTR_EMERALDHUNT)
P_FindEmerald(); // scan for emeralds to hunt for P_FindEmerald(); // scan for emeralds to hunt for
// If NiGHTS, find lowest mare to start with. // If NiGHTS, find lowest mare to start with.
@ -2771,6 +2786,26 @@ mapthing_t *G_FindCoopStart(INT32 playernum)
return NULL; return NULL;
} }
// Find a Co-op start, or fallback into other types of starts.
static inline mapthing_t *G_FindCoopStartOrFallback(INT32 playernum)
{
mapthing_t *spawnpoint = NULL;
if (!(spawnpoint = G_FindCoopStart(playernum)) // find a Co-op start
&& !(spawnpoint = G_FindMatchStart(playernum))) // find a DM start
spawnpoint = G_FindCTFStart(playernum); // fallback
return spawnpoint;
}
// Find a Match start, or fallback into other types of starts.
static inline mapthing_t *G_FindMatchStartOrFallback(INT32 playernum)
{
mapthing_t *spawnpoint = NULL;
if (!(spawnpoint = G_FindMatchStart(playernum)) // find a DM start
&& !(spawnpoint = G_FindCTFStart(playernum))) // find a CTF start
spawnpoint = G_FindCoopStart(playernum); // fallback
return spawnpoint;
}
mapthing_t *G_FindMapStart(INT32 playernum) mapthing_t *G_FindMapStart(INT32 playernum)
{ {
mapthing_t *spawnpoint; mapthing_t *spawnpoint;
@ -2778,9 +2813,22 @@ mapthing_t *G_FindMapStart(INT32 playernum)
if (!playeringame[playernum]) if (!playeringame[playernum])
return NULL; return NULL;
// -- Spectators --
// Order in platform gametypes: Coop->DM->CTF
// And, with deathmatch starts: DM->CTF->Coop
if (players[playernum].spectator)
{
// In platform gametypes, spawn in Co-op starts first
// Overriden by GTR_DEATHMATCHSTARTS.
if (G_PlatformGametype() && !(gametyperules & GTR_DEATHMATCHSTARTS))
spawnpoint = G_FindCoopStartOrFallback(playernum);
else
spawnpoint = G_FindMatchStartOrFallback(playernum);
}
// -- CTF -- // -- CTF --
// Order: CTF->DM->Coop // Order: CTF->DM->Coop
if ((gametyperules & (GTR_TEAMFLAGS|GTR_TEAMS)) && players[playernum].ctfteam) else if ((gametyperules & (GTR_TEAMFLAGS|GTR_TEAMS)) && players[playernum].ctfteam)
{ {
if (!(spawnpoint = G_FindCTFStart(playernum)) // find a CTF start if (!(spawnpoint = G_FindCTFStart(playernum)) // find a CTF start
&& !(spawnpoint = G_FindMatchStart(playernum))) // find a DM start && !(spawnpoint = G_FindMatchStart(playernum))) // find a DM start
@ -2789,21 +2837,13 @@ mapthing_t *G_FindMapStart(INT32 playernum)
// -- DM/Tag/CTF-spectator/etc -- // -- DM/Tag/CTF-spectator/etc --
// Order: DM->CTF->Coop // Order: DM->CTF->Coop
else if ((gametyperules & GTR_DEATHMATCHSTARTS) && !(players[playernum].pflags & PF_TAGIT)) else if (G_TagGametype() ? (!(players[playernum].pflags & PF_TAGIT)) : (gametyperules & GTR_DEATHMATCHSTARTS))
{ spawnpoint = G_FindMatchStartOrFallback(playernum);
if (!(spawnpoint = G_FindMatchStart(playernum)) // find a DM start
&& !(spawnpoint = G_FindCTFStart(playernum))) // find a CTF start
spawnpoint = G_FindCoopStart(playernum); // fallback
}
// -- Other game modes -- // -- Other game modes --
// Order: Coop->DM->CTF // Order: Coop->DM->CTF
else else
{ spawnpoint = G_FindCoopStartOrFallback(playernum);
if (!(spawnpoint = G_FindCoopStart(playernum)) // find a Co-op start
&& !(spawnpoint = G_FindMatchStart(playernum))) // find a DM start
spawnpoint = G_FindCTFStart(playernum); // fallback
}
//No spawns found. ANYWHERE. //No spawns found. ANYWHERE.
if (!spawnpoint) if (!spawnpoint)
@ -2889,7 +2929,7 @@ void G_DoReborn(INT32 playernum)
return; return;
} }
if (countdowntimeup || (!(netgame || multiplayer) && gametype == GT_COOP)) if (countdowntimeup || (!(netgame || multiplayer) && (gametyperules & GTR_CAMPAIGN)))
resetlevel = true; resetlevel = true;
else if ((G_GametypeUsesCoopLives() || G_GametypeUsesCoopStarposts()) && (netgame || multiplayer) && !G_IsSpecialStage(gamemap)) else if ((G_GametypeUsesCoopLives() || G_GametypeUsesCoopStarposts()) && (netgame || multiplayer) && !G_IsSpecialStage(gamemap))
{ {
@ -2963,7 +3003,7 @@ void G_DoReborn(INT32 playernum)
players[i].starpostnum = 0; players[i].starpostnum = 0;
} }
} }
if (!countdowntimeup && (mapheaderinfo[gamemap-1]->levelflags & LF_NORELOAD)) if (!countdowntimeup && (mapheaderinfo[gamemap-1]->levelflags & LF_NORELOAD) && !(marathonmode & MA_INIT))
{ {
P_RespawnThings(); P_RespawnThings();
@ -3094,7 +3134,7 @@ void G_AddPlayer(INT32 playernum)
p->height = mobjinfo[MT_PLAYER].height; p->height = mobjinfo[MT_PLAYER].height;
if (G_GametypeUsesLives() || ((netgame || multiplayer) && gametype == GT_COOP)) if (G_GametypeUsesLives() || ((netgame || multiplayer) && (gametyperules & GTR_FRIENDLY)))
p->lives = cv_startinglives.value; p->lives = cv_startinglives.value;
if ((countplayers && !notexiting) || G_IsSpecialStage(gamemap)) if ((countplayers && !notexiting) || G_IsSpecialStage(gamemap))
@ -3143,7 +3183,7 @@ void G_ExitLevel(void)
CV_SetValue(&cv_teamscramble, cv_scrambleonchange.value); CV_SetValue(&cv_teamscramble, cv_scrambleonchange.value);
} }
if (!(gametyperules & GTR_CAMPAIGN)) if (!(gametyperules & (GTR_FRIENDLY|GTR_CAMPAIGN)))
CONS_Printf(M_GetText("The round has ended.\n")); CONS_Printf(M_GetText("The round has ended.\n"));
// Remove CEcho text on round end. // Remove CEcho text on round end.
@ -3209,7 +3249,7 @@ UINT32 gametypedefaultrules[NUMGAMETYPES] =
// Tag // Tag
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_OVERTIME|GTR_STARTCOUNTDOWN|GTR_BLINDFOLDED|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY, GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_OVERTIME|GTR_STARTCOUNTDOWN|GTR_BLINDFOLDED|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY,
// Hide and Seek // Hide and Seek
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_OVERTIME|GTR_STARTCOUNTDOWN|GTR_BLINDFOLDED|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY, GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_OVERTIME|GTR_STARTCOUNTDOWN|GTR_HIDEFROZEN|GTR_BLINDFOLDED|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY,
// CTF // CTF
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_TEAMFLAGS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_OVERTIME|GTR_POWERSTONES|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD, GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_TEAMFLAGS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_OVERTIME|GTR_POWERSTONES|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD,
@ -3554,6 +3594,16 @@ boolean G_PlatformGametype(void)
return (!(gametyperules & GTR_RINGSLINGER)); return (!(gametyperules & GTR_RINGSLINGER));
} }
//
// G_CoopGametype
//
// Returns true if a gametype is a Co-op gametype.
//
boolean G_CoopGametype(void)
{
return ((gametyperules & (GTR_FRIENDLY|GTR_CAMPAIGN)) == (GTR_FRIENDLY|GTR_CAMPAIGN));
}
// //
// G_TagGametype // G_TagGametype
// //
@ -3661,6 +3711,24 @@ static void G_UpdateVisited(void)
} }
} }
static boolean CanSaveLevel(INT32 mapnum)
{
// You can never save in a special stage.
if (G_IsSpecialStage(mapnum))
return false;
// If the game is complete for this save slot, then any level can save!
if (gamecomplete)
return true;
// Be kind with Marathon Mode live event backups.
if (marathonmode)
return true;
// Any levels that have the savegame flag can save normally.
return (mapheaderinfo[mapnum-1] && (mapheaderinfo[mapnum-1]->levelflags & LF_SAVEGAME));
}
// //
// G_DoCompleted // G_DoCompleted
// //
@ -3696,19 +3764,22 @@ static void G_DoCompleted(void)
// nextmap is 0-based, unlike gamemap // nextmap is 0-based, unlike gamemap
if (nextmapoverride != 0) if (nextmapoverride != 0)
nextmap = (INT16)(nextmapoverride-1); nextmap = (INT16)(nextmapoverride-1);
else if (marathonmode && mapheaderinfo[gamemap-1]->marathonnext)
nextmap = (INT16)(mapheaderinfo[gamemap-1]->marathonnext-1);
else else
{
nextmap = (INT16)(mapheaderinfo[gamemap-1]->nextlevel-1); nextmap = (INT16)(mapheaderinfo[gamemap-1]->nextlevel-1);
if (marathonmode && nextmap == spmarathon_start-1)
// Remember last map for when you come out of the special stage. nextmap = 1100-1; // No infinite loop for you
if (!spec) }
lastmap = nextmap;
// If nextmap is actually going to get used, make sure it points to // If nextmap is actually going to get used, make sure it points to
// a map of the proper gametype -- skip levels that don't support // a map of the proper gametype -- skip levels that don't support
// the current gametype. (Helps avoid playing boss levels in Race, // the current gametype. (Helps avoid playing boss levels in Race,
// for instance). // for instance).
if (!token && !spec if (!spec)
&& (nextmap >= 0 && nextmap < NUMMAPS)) {
if (nextmap >= 0 && nextmap < NUMMAPS)
{ {
register INT16 cm = nextmap; register INT16 cm = nextmap;
UINT32 tolflag = G_TOLFlag(gametype); UINT32 tolflag = G_TOLFlag(gametype);
@ -3721,10 +3792,12 @@ static void G_DoCompleted(void)
visitedmap[cm/8] |= (1<<(cm&7)); visitedmap[cm/8] |= (1<<(cm&7));
if (!mapheaderinfo[cm]) if (!mapheaderinfo[cm])
cm = -1; // guarantee error execution cm = -1; // guarantee error execution
else if (marathonmode && mapheaderinfo[cm]->marathonnext)
cm = (INT16)(mapheaderinfo[cm]->marathonnext-1);
else else
cm = (INT16)(mapheaderinfo[cm]->nextlevel-1); cm = (INT16)(mapheaderinfo[cm]->nextlevel-1);
if (cm >= NUMMAPS || cm < 0) // out of range (either 1100-1102 or error) if (cm >= NUMMAPS || cm < 0) // out of range (either 1100ish or error)
{ {
cm = nextmap; //Start the loop again so that the error checking below is executed. cm = nextmap; //Start the loop again so that the error checking below is executed.
@ -3749,13 +3822,16 @@ static void G_DoCompleted(void)
nextmap = cm; nextmap = cm;
} }
if (nextmap < 0 || (nextmap >= NUMMAPS && nextmap < 1100-1) || nextmap > 1103-1)
I_Error("Followed map %d to invalid map %d\n", prevmap + 1, nextmap + 1);
// wrap around in race // wrap around in race
if (nextmap >= 1100-1 && nextmap <= 1102-1 && !(gametyperules & GTR_CAMPAIGN)) if (nextmap >= 1100-1 && nextmap <= 1102-1 && !(gametyperules & GTR_CAMPAIGN))
nextmap = (INT16)(spstage_start-1); nextmap = (INT16)(spstage_start-1);
if (nextmap < 0 || (nextmap >= NUMMAPS && nextmap < 1100-1) || nextmap > 1103-1)
I_Error("Followed map %d to invalid map %d\n", prevmap + 1, nextmap + 1);
lastmap = nextmap; // Remember last map for when you come out of the special stage.
}
if ((gottoken = ((gametyperules & GTR_SPECIALSTAGES) && token))) if ((gottoken = ((gametyperules & GTR_SPECIALSTAGES) && token)))
{ {
token--; token--;
@ -3793,7 +3869,10 @@ static void G_DoCompleted(void)
if (nextmap < NUMMAPS && !mapheaderinfo[nextmap]) if (nextmap < NUMMAPS && !mapheaderinfo[nextmap])
P_AllocMapHeader(nextmap); P_AllocMapHeader(nextmap);
if ((skipstats && !modeattacking) || (spec && modeattacking && stagefailed)) // If the current gametype has no intermission screen set, then don't start it.
Y_DetermineIntermissionType();
if ((skipstats && !modeattacking) || (spec && modeattacking && stagefailed) || (intertype == int_none))
{ {
G_UpdateVisited(); G_UpdateVisited();
G_AfterIntermission(); G_AfterIntermission();
@ -3804,8 +3883,32 @@ static void G_DoCompleted(void)
Y_StartIntermission(); Y_StartIntermission();
G_UpdateVisited(); G_UpdateVisited();
} }
// do this before running the intermission or custom cutscene, mostly for the sake of marathon mode but it also massively reduces redundant file save events in f_finale.c
if (nextmap >= 1100-1)
{
if (!gamecomplete)
gamecomplete = 2; // special temporary mode to prevent using SP level select in pause menu until the intermission is over without restricting it in every intermission
if (cursaveslot > 0)
{
if (marathonmode)
{
// don't keep a backup around when the run is done!
if (FIL_FileExists(liveeventbackup))
remove(liveeventbackup);
cursaveslot = 0;
}
else if ((!modifiedgame || savemoddata) && !(netgame || multiplayer || ultimatemode || demorecording || metalrecording || modeattacking))
G_SaveGame((UINT32)cursaveslot, spstage_start);
}
}
// and doing THIS here means you don't lose your progress if you close the game mid-intermission
else if (!(ultimatemode || netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking)
&& (!modifiedgame || savemoddata) && cursaveslot > 0 && CanSaveLevel(lastmap+1))
G_SaveGame((UINT32)cursaveslot, lastmap+1); // not nextmap+1 to route around special stages
} }
// See also F_EndCutscene, the only other place which handles intra-map/ending transitions
void G_AfterIntermission(void) void G_AfterIntermission(void)
{ {
Y_CleanupScreenBuffer(); Y_CleanupScreenBuffer();
@ -3816,9 +3919,12 @@ void G_AfterIntermission(void)
return; return;
} }
if (gamecomplete == 2) // special temporary mode to prevent using SP level select in pause menu until the intermission is over without restricting it in every intermission
gamecomplete = 1;
HU_ClearCEcho(); HU_ClearCEcho();
if ((gametyperules & GTR_CUTSCENES) && mapheaderinfo[gamemap-1]->cutscenenum && !modeattacking && skipstats <= 1) // Start a custom cutscene. if ((gametyperules & GTR_CUTSCENES) && mapheaderinfo[gamemap-1]->cutscenenum && !modeattacking && skipstats <= 1 && (gamecomplete || !(marathonmode & MA_NOCUTSCENES))) // Start a custom cutscene.
F_StartCustomCutscene(mapheaderinfo[gamemap-1]->cutscenenum-1, false, false); F_StartCustomCutscene(mapheaderinfo[gamemap-1]->cutscenenum-1, false, false);
else else
{ {
@ -3844,7 +3950,7 @@ static void G_DoWorldDone(void)
{ {
if (server) if (server)
{ {
if (gametype == GT_COOP) if (gametyperules & GTR_CAMPAIGN)
// don't reset player between maps // don't reset player between maps
D_MapChange(nextmap+1, gametype, ultimatemode, false, 0, false, false); D_MapChange(nextmap+1, gametype, ultimatemode, false, 0, false, false);
else else
@ -3959,7 +4065,7 @@ void G_EndGame(void)
void G_LoadGameSettings(void) void G_LoadGameSettings(void)
{ {
// defaults // defaults
spstage_start = 1; spstage_start = spmarathon_start = 1;
sstage_start = 50; sstage_start = 50;
sstage_end = 56; // 7 special stages in vanilla SRB2 sstage_end = 56; // 7 special stages in vanilla SRB2
sstage_end++; // plus one weirdo sstage_end++; // plus one weirdo
@ -4279,6 +4385,9 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
startonmapnum = mapoverride; startonmapnum = mapoverride;
#endif #endif
if (marathonmode)
strcpy(savename, liveeventbackup);
else
sprintf(savename, savegamename, slot); sprintf(savename, savegamename, slot);
length = FIL_ReadFile(savename, &savebuffer); length = FIL_ReadFile(savename, &savebuffer);
@ -4291,7 +4400,7 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
save_p = savebuffer; save_p = savebuffer;
memset(vcheck, 0, sizeof (vcheck)); memset(vcheck, 0, sizeof (vcheck));
sprintf(vcheck, "version %d", VERSION); sprintf(vcheck, (marathonmode ? "back-up %d" : "version %d"), VERSION);
if (strcmp((const char *)save_p, (const char *)vcheck)) if (strcmp((const char *)save_p, (const char *)vcheck))
{ {
#ifdef SAVEGAME_OTHERVERSIONS #ifdef SAVEGAME_OTHERVERSIONS
@ -4331,6 +4440,11 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
memset(&savedata, 0, sizeof(savedata)); memset(&savedata, 0, sizeof(savedata));
return; return;
} }
if (marathonmode)
{
marathontime = READUINT32(save_p);
marathonmode |= READUINT8(save_p);
}
// done // done
Z_Free(savebuffer); Z_Free(savebuffer);
@ -4353,19 +4467,18 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
// G_SaveGame // G_SaveGame
// Saves your game. // Saves your game.
// //
void G_SaveGame(UINT32 slot) void G_SaveGame(UINT32 slot, INT16 mapnum)
{ {
boolean saved; boolean saved;
char savename[256] = ""; char savename[256] = "";
const char *backup; const char *backup;
if (marathonmode)
strcpy(savename, liveeventbackup);
else
sprintf(savename, savegamename, slot); sprintf(savename, savegamename, slot);
backup = va("%s",savename); backup = va("%s",savename);
// save during evaluation or credits? game's over, folks!
if (gamestate == GS_ENDING || gamestate == GS_CREDITS || gamestate == GS_EVALUATION)
gamecomplete = true;
gameaction = ga_nothing; gameaction = ga_nothing;
{ {
char name[VERSIONSIZE]; char name[VERSIONSIZE];
@ -4379,10 +4492,15 @@ void G_SaveGame(UINT32 slot)
} }
memset(name, 0, sizeof (name)); memset(name, 0, sizeof (name));
sprintf(name, "version %d", VERSION); sprintf(name, (marathonmode ? "back-up %d" : "version %d"), VERSION);
WRITEMEM(save_p, name, VERSIONSIZE); WRITEMEM(save_p, name, VERSIONSIZE);
P_SaveGame(); P_SaveGame(mapnum);
if (marathonmode)
{
WRITEUINT32(save_p, marathontime);
WRITEUINT8(save_p, (marathonmode & ~MA_INIT));
}
length = save_p - savebuffer; length = save_p - savebuffer;
saved = FIL_WriteFile(backup, savebuffer, length); saved = FIL_WriteFile(backup, savebuffer, length);
@ -4395,7 +4513,7 @@ void G_SaveGame(UINT32 slot)
if (cv_debug && saved) if (cv_debug && saved)
CONS_Printf(M_GetText("Game saved.\n")); CONS_Printf(M_GetText("Game saved.\n"));
else if (!saved) else if (!saved)
CONS_Alert(CONS_ERROR, M_GetText("Error while writing to %s for save slot %u, base: %s\n"), backup, slot, savegamename); CONS_Alert(CONS_ERROR, M_GetText("Error while writing to %s for save slot %u, base: %s\n"), backup, slot, (marathonmode ? liveeventbackup : savegamename));
} }
#define BADSAVE goto cleanup; #define BADSAVE goto cleanup;
@ -4408,6 +4526,9 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives)
char savename[255]; char savename[255];
const char *backup; const char *backup;
if (marathonmode)
strcpy(savename, liveeventbackup);
else
sprintf(savename, savegamename, slot); sprintf(savename, savegamename, slot);
backup = va("%s",savename); backup = va("%s",savename);
@ -4427,7 +4548,7 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives)
save_p = savebuffer; save_p = savebuffer;
// Version check // Version check
memset(vcheck, 0, sizeof (vcheck)); memset(vcheck, 0, sizeof (vcheck));
sprintf(vcheck, "version %d", VERSION); sprintf(vcheck, (marathonmode ? "back-up %d" : "version %d"), VERSION);
if (strcmp((const char *)save_p, (const char *)vcheck)) BADSAVE if (strcmp((const char *)save_p, (const char *)vcheck)) BADSAVE
save_p += VERSIONSIZE; save_p += VERSIONSIZE;
@ -4494,7 +4615,7 @@ cleanup:
if (cv_debug && saved) if (cv_debug && saved)
CONS_Printf(M_GetText("Game saved.\n")); CONS_Printf(M_GetText("Game saved.\n"));
else if (!saved) else if (!saved)
CONS_Alert(CONS_ERROR, M_GetText("Error while writing to %s for save slot %u, base: %s\n"), backup, slot, savegamename); CONS_Alert(CONS_ERROR, M_GetText("Error while writing to %s for save slot %u, base: %s\n"), backup, slot, (marathonmode ? liveeventbackup : savegamename));
Z_Free(savebuffer); Z_Free(savebuffer);
save_p = savebuffer = NULL; save_p = savebuffer = NULL;
@ -4632,7 +4753,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean
automapactive = false; automapactive = false;
imcontinuing = false; imcontinuing = false;
if ((gametyperules & GTR_CUTSCENES) && !skipprecutscene && mapheaderinfo[gamemap-1]->precutscenenum && !modeattacking) // Start a custom cutscene. if ((gametyperules & GTR_CUTSCENES) && !skipprecutscene && mapheaderinfo[gamemap-1]->precutscenenum && !modeattacking && !(marathonmode & MA_NOCUTSCENES)) // Start a custom cutscene.
F_StartCustomCutscene(mapheaderinfo[gamemap-1]->precutscenenum-1, true, resetplayer); F_StartCustomCutscene(mapheaderinfo[gamemap-1]->precutscenenum-1, true, resetplayer);
else else
G_DoLoadLevel(resetplayer); G_DoLoadLevel(resetplayer);

View file

@ -166,7 +166,7 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride);
void G_SaveGameData(void); void G_SaveGameData(void);
void G_SaveGame(UINT32 slot); void G_SaveGame(UINT32 slot, INT16 mapnum);
void G_SaveGameOver(UINT32 slot, boolean modifylives); void G_SaveGameOver(UINT32 slot, boolean modifylives);
@ -191,6 +191,7 @@ boolean G_GametypeHasTeams(void);
boolean G_GametypeHasSpectators(void); boolean G_GametypeHasSpectators(void);
boolean G_RingSlingerGametype(void); boolean G_RingSlingerGametype(void);
boolean G_PlatformGametype(void); boolean G_PlatformGametype(void);
boolean G_CoopGametype(void);
boolean G_TagGametype(void); boolean G_TagGametype(void);
boolean G_CompetitionGametype(void); boolean G_CompetitionGametype(void);
boolean G_EnoughPlayersFinished(void); boolean G_EnoughPlayersFinished(void);

View file

@ -1,20 +1,12 @@
// Emacs style mode select -*- C++ -*- // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//
// Copyright (C) 2001 by DooM Legacy Team. // Copyright (C) 2001 by DooM Legacy Team.
// //
// This program is free software; you can redistribute it and/or // This program is free software distributed under the
// modify it under the terms of the GNU General Public License // terms of the GNU General Public License, version 2.
// as published by the Free Software Foundation; either version 2 // See the 'LICENSE' file for more details.
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/// \file /// \file hw3dsdrv.h
/// \brief 3D sound import/export prototypes for low-level hardware interface /// \brief 3D sound import/export prototypes for low-level hardware interface
#ifndef __HW_3DS_DRV_H__ #ifndef __HW_3DS_DRV_H__

View file

@ -1,19 +1,12 @@
// Emacs style mode select -*- C++ -*- // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//
// Copyright (C) 2001 by DooM Legacy Team. // Copyright (C) 2001 by DooM Legacy Team.
// //
// This program is free software; you can redistribute it and/or // This program is free software distributed under the
// modify it under the terms of the GNU General Public License // terms of the GNU General Public License, version 2.
// as published by the Free Software Foundation; either version 2 // See the 'LICENSE' file for more details.
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/// \file /// \file hw3sound.c
/// \brief Hardware 3D sound general code /// \brief Hardware 3D sound general code
#include "../doomdef.h" #include "../doomdef.h"

View file

@ -1,20 +1,12 @@
// Emacs style mode select -*- C++ -*- // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//
// Copyright (C) 2001 by DooM Legacy Team. // Copyright (C) 2001 by DooM Legacy Team.
// //
// This program is free software; you can redistribute it and/or // This program is free software distributed under the
// modify it under the terms of the GNU General Public License // terms of the GNU General Public License, version 2.
// as published by the Free Software Foundation; either version 2 // See the 'LICENSE' file for more details.
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/// \file /// \file hw3sound.h
/// \brief High-level functions of hardware 3D sound /// \brief High-level functions of hardware 3D sound
#ifndef __HW3_SOUND_H__ #ifndef __HW3_SOUND_H__

454
src/hardware/hw_batching.c Normal file
View file

@ -0,0 +1,454 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-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 hw_batching.c
/// \brief Draw call batching and related things.
#ifdef HWRENDER
#include "hw_glob.h"
#include "hw_batching.h"
#include "../i_system.h"
// The texture for the next polygon given to HWR_ProcessPolygon.
// Set with HWR_SetCurrentTexture.
GLMipmap_t *current_texture = NULL;
boolean currently_batching = false;
FOutVector* finalVertexArray = NULL;// contains subset of sorted vertices and texture coordinates to be sent to gpu
UINT32* finalVertexIndexArray = NULL;// contains indexes for glDrawElements, taking into account fan->triangles conversion
// NOTE have this alloced as 3x finalVertexArray size
int finalVertexArrayAllocSize = 65536;
//GLubyte* colorArray = NULL;// contains color data to be sent to gpu, if needed
//int colorArrayAllocSize = 65536;
// not gonna use this for now, just sort by color and change state when it changes
// later maybe when using vertex attributes if it's needed
PolygonArrayEntry* polygonArray = NULL;// contains the polygon data from DrawPolygon, waiting to be processed
int polygonArraySize = 0;
UINT32* polygonIndexArray = NULL;// contains sorting pointers for polygonArray
int polygonArrayAllocSize = 65536;
FOutVector* unsortedVertexArray = NULL;// contains unsorted vertices and texture coordinates from DrawPolygon
int unsortedVertexArraySize = 0;
int unsortedVertexArrayAllocSize = 65536;
// Enables batching mode. HWR_ProcessPolygon will collect polygons instead of passing them directly to the rendering backend.
// Call HWR_RenderBatches to render all the collected geometry.
void HWR_StartBatching(void)
{
if (currently_batching)
I_Error("Repeat call to HWR_StartBatching without HWR_RenderBatches");
// init arrays if that has not been done yet
if (!finalVertexArray)
{
finalVertexArray = malloc(finalVertexArrayAllocSize * sizeof(FOutVector));
finalVertexIndexArray = malloc(finalVertexArrayAllocSize * 3 * sizeof(UINT32));
polygonArray = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry));
polygonIndexArray = malloc(polygonArrayAllocSize * sizeof(UINT32));
unsortedVertexArray = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector));
}
currently_batching = true;
}
// This replaces the direct calls to pfnSetTexture in cases where batching is available.
// The texture selection is saved for the next HWR_ProcessPolygon call.
// Doing this was easier than getting a texture pointer to HWR_ProcessPolygon.
void HWR_SetCurrentTexture(GLMipmap_t *texture)
{
if (currently_batching)
{
current_texture = texture;
}
else
{
HWD.pfnSetTexture(texture);
}
}
// If batching is enabled, this function collects the polygon data and the chosen texture
// for later use in HWR_RenderBatches. Otherwise the rendering backend is used to
// render the polygon immediately.
void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader, boolean horizonSpecial)
{
if (currently_batching)
{
if (!pSurf)
I_Error("Got a null FSurfaceInfo in batching");// nulls should not come in the stuff that batching currently applies to
if (polygonArraySize == polygonArrayAllocSize)
{
PolygonArrayEntry* new_array;
// ran out of space, make new array double the size
polygonArrayAllocSize *= 2;
new_array = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry));
memcpy(new_array, polygonArray, polygonArraySize * sizeof(PolygonArrayEntry));
free(polygonArray);
polygonArray = new_array;
// also need to redo the index array, dont need to copy it though
free(polygonIndexArray);
polygonIndexArray = malloc(polygonArrayAllocSize * sizeof(UINT32));
}
while (unsortedVertexArraySize + (int)iNumPts > unsortedVertexArrayAllocSize)
{
FOutVector* new_array;
// need more space for vertices in unsortedVertexArray
unsortedVertexArrayAllocSize *= 2;
new_array = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector));
memcpy(new_array, unsortedVertexArray, unsortedVertexArraySize * sizeof(FOutVector));
free(unsortedVertexArray);
unsortedVertexArray = new_array;
}
// add the polygon data to the arrays
polygonArray[polygonArraySize].surf = *pSurf;
polygonArray[polygonArraySize].vertsIndex = unsortedVertexArraySize;
polygonArray[polygonArraySize].numVerts = iNumPts;
polygonArray[polygonArraySize].polyFlags = PolyFlags;
polygonArray[polygonArraySize].texture = current_texture;
polygonArray[polygonArraySize].shader = shader;
polygonArray[polygonArraySize].horizonSpecial = horizonSpecial;
polygonArraySize++;
memcpy(&unsortedVertexArray[unsortedVertexArraySize], pOutVerts, iNumPts * sizeof(FOutVector));
unsortedVertexArraySize += iNumPts;
}
else
{
if (shader)
HWD.pfnSetShader(shader);
HWD.pfnDrawPolygon(pSurf, pOutVerts, iNumPts, PolyFlags);
}
}
static int comparePolygons(const void *p1, const void *p2)
{
unsigned int index1 = *(const unsigned int*)p1;
unsigned int index2 = *(const unsigned int*)p2;
PolygonArrayEntry* poly1 = &polygonArray[index1];
PolygonArrayEntry* poly2 = &polygonArray[index2];
int diff;
INT64 diff64;
int shader1 = poly1->shader;
int shader2 = poly2->shader;
// make skywalls and horizon lines first in order
if (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial)
shader1 = -1;
if (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial)
shader2 = -1;
diff = shader1 - shader2;
if (diff != 0) return diff;
// skywalls and horizon lines must retain their order for horizon lines to work
if (shader1 == -1 && shader2 == -1)
return index1 - index2;
diff64 = poly1->texture - poly2->texture;
if (diff64 != 0) return diff64;
diff = poly1->polyFlags - poly2->polyFlags;
if (diff != 0) return diff;
diff64 = poly1->surf.PolyColor.rgba - poly2->surf.PolyColor.rgba;
if (diff64 < 0) return -1; else if (diff64 > 0) return 1;
diff64 = poly1->surf.TintColor.rgba - poly2->surf.TintColor.rgba;
if (diff64 < 0) return -1; else if (diff64 > 0) return 1;
diff64 = poly1->surf.FadeColor.rgba - poly2->surf.FadeColor.rgba;
if (diff64 < 0) return -1; else if (diff64 > 0) return 1;
diff = poly1->surf.LightInfo.light_level - poly2->surf.LightInfo.light_level;
if (diff != 0) return diff;
diff = poly1->surf.LightInfo.fade_start - poly2->surf.LightInfo.fade_start;
if (diff != 0) return diff;
diff = poly1->surf.LightInfo.fade_end - poly2->surf.LightInfo.fade_end;
return diff;
}
static int comparePolygonsNoShaders(const void *p1, const void *p2)
{
unsigned int index1 = *(const unsigned int*)p1;
unsigned int index2 = *(const unsigned int*)p2;
PolygonArrayEntry* poly1 = &polygonArray[index1];
PolygonArrayEntry* poly2 = &polygonArray[index2];
int diff;
INT64 diff64;
GLMipmap_t *texture1 = poly1->texture;
GLMipmap_t *texture2 = poly2->texture;
if (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial)
texture1 = NULL;
if (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial)
texture2 = NULL;
diff64 = texture1 - texture2;
if (diff64 != 0) return diff64;
// skywalls and horizon lines must retain their order for horizon lines to work
if (texture1 == NULL && texture2 == NULL)
return index1 - index2;
diff = poly1->polyFlags - poly2->polyFlags;
if (diff != 0) return diff;
diff64 = poly1->surf.PolyColor.rgba - poly2->surf.PolyColor.rgba;
if (diff64 < 0) return -1; else if (diff64 > 0) return 1;
return 0;
}
// This function organizes the geometry collected by HWR_ProcessPolygon calls into batches and uses
// the rendering backend to draw them.
void HWR_RenderBatches(void)
{
int finalVertexWritePos = 0;// position in finalVertexArray
int finalIndexWritePos = 0;// position in finalVertexIndexArray
int polygonReadPos = 0;// position in polygonIndexArray
int currentShader;
int nextShader = 0;
GLMipmap_t *currentTexture;
GLMipmap_t *nextTexture = NULL;
FBITFIELD currentPolyFlags = 0;
FBITFIELD nextPolyFlags = 0;
FSurfaceInfo currentSurfaceInfo;
FSurfaceInfo nextSurfaceInfo;
int i;
if (!currently_batching)
I_Error("HWR_RenderBatches called without starting batching");
nextSurfaceInfo.LightInfo.fade_end = 0;
nextSurfaceInfo.LightInfo.fade_start = 0;
nextSurfaceInfo.LightInfo.light_level = 0;
currently_batching = false;// no longer collecting batches
if (!polygonArraySize)
{
rs_hw_numpolys = rs_hw_numcalls = rs_hw_numshaders = rs_hw_numtextures = rs_hw_numpolyflags = rs_hw_numcolors = 0;
return;// nothing to draw
}
// init stats vars
rs_hw_numpolys = polygonArraySize;
rs_hw_numcalls = rs_hw_numverts = 0;
rs_hw_numshaders = rs_hw_numtextures = rs_hw_numpolyflags = rs_hw_numcolors = 1;
// init polygonIndexArray
for (i = 0; i < polygonArraySize; i++)
{
polygonIndexArray[i] = i;
}
// sort polygons
rs_hw_batchsorttime = I_GetTimeMicros();
if (cv_grshaders.value && gr_shadersavailable)
qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygons);
else
qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygonsNoShaders);
rs_hw_batchsorttime = I_GetTimeMicros() - rs_hw_batchsorttime;
// sort order
// 1. shader
// 2. texture
// 3. polyflags
// 4. colors + light level
// not sure about what order of the last 2 should be, or if it even matters
rs_hw_batchdrawtime = I_GetTimeMicros();
currentShader = polygonArray[polygonIndexArray[0]].shader;
currentTexture = polygonArray[polygonIndexArray[0]].texture;
currentPolyFlags = polygonArray[polygonIndexArray[0]].polyFlags;
currentSurfaceInfo = polygonArray[polygonIndexArray[0]].surf;
// For now, will sort and track the colors. Vertex attributes could be used instead of uniforms
// and a color array could replace the color calls.
// set state for first batch
if (cv_grshaders.value && gr_shadersavailable)
{
HWD.pfnSetShader(currentShader);
}
if (currentPolyFlags & PF_NoTexture)
currentTexture = NULL;
else
HWD.pfnSetTexture(currentTexture);
while (1)// note: remember handling notexture polyflag as having texture number 0 (also in comparePolygons)
{
int firstIndex;
int lastIndex;
boolean stopFlag = false;
boolean changeState = false;
boolean changeShader = false;
boolean changeTexture = false;
boolean changePolyFlags = false;
boolean changeSurfaceInfo = false;
// steps:
// write vertices
// check for changes or end, otherwise go back to writing
// changes will affect the next vars and the change bools
// end could set flag for stopping
// execute draw call
// could check ending flag here
// change states according to next vars and change bools, updating the current vars and reseting the bools
// reset write pos
// repeat loop
int index = polygonIndexArray[polygonReadPos++];
int numVerts = polygonArray[index].numVerts;
// before writing, check if there is enough room
// using 'while' instead of 'if' here makes sure that there will *always* be enough room.
// probably never will this loop run more than once though
while (finalVertexWritePos + numVerts > finalVertexArrayAllocSize)
{
FOutVector* new_array;
unsigned int* new_index_array;
finalVertexArrayAllocSize *= 2;
new_array = malloc(finalVertexArrayAllocSize * sizeof(FOutVector));
memcpy(new_array, finalVertexArray, finalVertexWritePos * sizeof(FOutVector));
free(finalVertexArray);
finalVertexArray = new_array;
// also increase size of index array, 3x of vertex array since
// going from fans to triangles increases vertex count to 3x
new_index_array = malloc(finalVertexArrayAllocSize * 3 * sizeof(UINT32));
memcpy(new_index_array, finalVertexIndexArray, finalIndexWritePos * sizeof(UINT32));
free(finalVertexIndexArray);
finalVertexIndexArray = new_index_array;
}
// write the vertices of the polygon
memcpy(&finalVertexArray[finalVertexWritePos], &unsortedVertexArray[polygonArray[index].vertsIndex],
numVerts * sizeof(FOutVector));
// write the indexes, pointing to the fan vertexes but in triangles format
firstIndex = finalVertexWritePos;
lastIndex = finalVertexWritePos + numVerts;
finalVertexWritePos += 2;
while (finalVertexWritePos < lastIndex)
{
finalVertexIndexArray[finalIndexWritePos++] = firstIndex;
finalVertexIndexArray[finalIndexWritePos++] = finalVertexWritePos - 1;
finalVertexIndexArray[finalIndexWritePos++] = finalVertexWritePos++;
}
if (polygonReadPos >= polygonArraySize)
{
stopFlag = true;
}
else
{
// check if a state change is required, set the change bools and next vars
int nextIndex = polygonIndexArray[polygonReadPos];
nextShader = polygonArray[nextIndex].shader;
nextTexture = polygonArray[nextIndex].texture;
nextPolyFlags = polygonArray[nextIndex].polyFlags;
nextSurfaceInfo = polygonArray[nextIndex].surf;
if (nextPolyFlags & PF_NoTexture)
nextTexture = 0;
if (currentShader != nextShader && cv_grshaders.value && gr_shadersavailable)
{
changeState = true;
changeShader = true;
}
if (currentTexture != nextTexture)
{
changeState = true;
changeTexture = true;
}
if (currentPolyFlags != nextPolyFlags)
{
changeState = true;
changePolyFlags = true;
}
if (cv_grshaders.value && gr_shadersavailable)
{
if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba ||
currentSurfaceInfo.TintColor.rgba != nextSurfaceInfo.TintColor.rgba ||
currentSurfaceInfo.FadeColor.rgba != nextSurfaceInfo.FadeColor.rgba ||
currentSurfaceInfo.LightInfo.light_level != nextSurfaceInfo.LightInfo.light_level ||
currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start ||
currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end)
{
changeState = true;
changeSurfaceInfo = true;
}
}
else
{
if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba)
{
changeState = true;
changeSurfaceInfo = true;
}
}
}
if (changeState || stopFlag)
{
// execute draw call
HWD.pfnDrawIndexedTriangles(&currentSurfaceInfo, finalVertexArray, finalIndexWritePos, currentPolyFlags, finalVertexIndexArray);
// update stats
rs_hw_numcalls++;
rs_hw_numverts += finalIndexWritePos;
// reset write positions
finalVertexWritePos = 0;
finalIndexWritePos = 0;
}
else continue;
// if we're here then either its time to stop or time to change state
if (stopFlag) break;
// change state according to change bools and next vars, update current vars and reset bools
if (changeShader)
{
HWD.pfnSetShader(nextShader);
currentShader = nextShader;
changeShader = false;
rs_hw_numshaders++;
}
if (changeTexture)
{
// texture should be already ready for use from calls to SetTexture during batch collection
HWD.pfnSetTexture(nextTexture);
currentTexture = nextTexture;
changeTexture = false;
rs_hw_numtextures++;
}
if (changePolyFlags)
{
currentPolyFlags = nextPolyFlags;
changePolyFlags = false;
rs_hw_numpolyflags++;
}
if (changeSurfaceInfo)
{
currentSurfaceInfo = nextSurfaceInfo;
changeSurfaceInfo = false;
rs_hw_numcolors++;
}
// and that should be it?
}
// reset the arrays (set sizes to 0)
polygonArraySize = 0;
unsortedVertexArraySize = 0;
rs_hw_batchdrawtime = I_GetTimeMicros() - rs_hw_batchdrawtime;
}
#endif // HWRENDER

View file

@ -0,0 +1,37 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-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 hw_batching.h
/// \brief Draw call batching and related things.
#ifndef __HWR_BATCHING_H__
#define __HWR_BATCHING_H__
#include "hw_defs.h"
#include "hw_data.h"
#include "hw_drv.h"
typedef struct
{
FSurfaceInfo surf;// surf also has its own polyflags for some reason, but it seems unused
unsigned int vertsIndex;// location of verts in unsortedVertexArray
FUINT numVerts;
FBITFIELD polyFlags;
GLMipmap_t *texture;
int shader;
// this tells batching that the plane belongs to a horizon line and must be drawn in correct order with the skywalls
boolean horizonSpecial;
} PolygonArrayEntry;
void HWR_StartBatching(void);
void HWR_SetCurrentTexture(GLMipmap_t *texture);
void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader, boolean horizonSpecial);
void HWR_RenderBatches(void);
#endif

View file

@ -1,19 +1,12 @@
// Emacs style mode select -*- C++ -*- // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// //
// This program is free software; you can redistribute it and/or // This program is free software distributed under the
// modify it under the terms of the GNU General Public License // terms of the GNU General Public License, version 2.
// as published by the Free Software Foundation; either version 2 // See the 'LICENSE' file for more details.
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/// \file /// \file hw_bsp.c
/// \brief convert SRB2 map /// \brief convert SRB2 map
#include "../doomdef.h" #include "../doomdef.h"

View file

@ -1,20 +1,13 @@
// Emacs style mode select -*- C++ -*- // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2020 by Sonic Team Junior.
// //
// This program is free software; you can redistribute it and/or // This program is free software distributed under the
// modify it under the terms of the GNU General Public License // terms of the GNU General Public License, version 2.
// as published by the Free Software Foundation; either version 2 // See the 'LICENSE' file for more details.
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/// \file /// \file hw_cache.c
/// \brief load and convert graphics to the hardware format /// \brief load and convert graphics to the hardware format
#include "../doomdef.h" #include "../doomdef.h"
@ -22,6 +15,7 @@
#ifdef HWRENDER #ifdef HWRENDER
#include "hw_glob.h" #include "hw_glob.h"
#include "hw_drv.h" #include "hw_drv.h"
#include "hw_batching.h"
#include "../doomstat.h" //gamemode #include "../doomstat.h" //gamemode
#include "../i_video.h" //rendermode #include "../i_video.h" //rendermode
@ -33,9 +27,6 @@
#include "../r_patch.h" #include "../r_patch.h"
#include "../p_setup.h" #include "../p_setup.h"
// Values set after a call to HWR_ResizeBlock()
static INT32 blocksize, blockwidth, blockheight;
INT32 patchformat = GR_TEXFMT_AP_88; // use alpha for holes INT32 patchformat = GR_TEXFMT_AP_88; // use alpha for holes
INT32 textureformat = GR_TEXFMT_P_8; // use chromakey for hole INT32 textureformat = GR_TEXFMT_P_8; // use chromakey for hole
@ -308,13 +299,13 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap,
if (pwidth <= 0 || pheight <= 0) if (pwidth <= 0 || pheight <= 0)
return; return;
ncols = (pwidth * pblockwidth) / pwidth; ncols = pwidth;
// source advance // source advance
xfrac = 0; xfrac = 0;
xfracstep = (pwidth << FRACBITS) / pblockwidth; xfracstep = FRACUNIT;
yfracstep = (pheight << FRACBITS) / pblockheight; yfracstep = FRACUNIT;
scale_y = (pblockheight << FRACBITS) / pheight; scale_y = FRACUNIT;
bpp = format2bpp[mipmap->grInfo.format]; bpp = format2bpp[mipmap->grInfo.format];
@ -322,7 +313,7 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap,
I_Error("HWR_DrawPatchInCache: no drawer defined for this bpp (%d)\n",bpp); I_Error("HWR_DrawPatchInCache: no drawer defined for this bpp (%d)\n",bpp);
// NOTE: should this actually be pblockwidth*bpp? // NOTE: should this actually be pblockwidth*bpp?
blockmodulo = blockwidth*bpp; blockmodulo = pblockwidth*bpp;
// Draw each column to the block cache // Draw each column to the block cache
for (; ncols--; block += bpp, xfrac += xfracstep) for (; ncols--; block += bpp, xfrac += xfracstep)
@ -415,7 +406,7 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap,
I_Error("HWR_DrawPatchInCache: no drawer defined for this bpp (%d)\n",bpp); I_Error("HWR_DrawPatchInCache: no drawer defined for this bpp (%d)\n",bpp);
// NOTE: should this actually be pblockwidth*bpp? // NOTE: should this actually be pblockwidth*bpp?
blockmodulo = blockwidth*bpp; blockmodulo = pblockwidth*bpp;
// Draw each column to the block cache // Draw each column to the block cache
for (block += col*bpp; ncols--; block += bpp, xfrac += xfracstep) for (block += col*bpp; ncols--; block += bpp, xfrac += xfracstep)
@ -433,142 +424,12 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap,
} }
} }
// resize the patch to be 3dfx compliant
// set : blocksize = blockwidth * blockheight (no bpp used)
// blockwidth
// blockheight
//note : 8bit (1 byte per pixel) palettized format
static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight,
GrTexInfo *grInfo)
{
#ifdef GLIDE_API_COMPATIBILITY
// Build the full textures from patches.
static const GrLOD_t gr_lods[9] =
{
GR_LOD_LOG2_256,
GR_LOD_LOG2_128,
GR_LOD_LOG2_64,
GR_LOD_LOG2_32,
GR_LOD_LOG2_16,
GR_LOD_LOG2_8,
GR_LOD_LOG2_4,
GR_LOD_LOG2_2,
GR_LOD_LOG2_1
};
typedef struct
{
GrAspectRatio_t aspect;
float max_s;
float max_t;
} booring_aspect_t;
static const booring_aspect_t gr_aspects[8] =
{
{GR_ASPECT_LOG2_1x1, 255, 255},
{GR_ASPECT_LOG2_2x1, 255, 127},
{GR_ASPECT_LOG2_4x1, 255, 63},
{GR_ASPECT_LOG2_8x1, 255, 31},
{GR_ASPECT_LOG2_1x1, 255, 255},
{GR_ASPECT_LOG2_1x2, 127, 255},
{GR_ASPECT_LOG2_1x4, 63, 255},
{GR_ASPECT_LOG2_1x8, 31, 255}
};
INT32 j,k;
INT32 max,min;
#else
(void)grInfo;
#endif
// find a power of 2 width/height
if (cv_grrounddown.value)
{
blockwidth = 256;
while (originalwidth < blockwidth)
blockwidth >>= 1;
if (blockwidth < 1)
I_Error("3D GenerateTexture : too small");
blockheight = 256;
while (originalheight < blockheight)
blockheight >>= 1;
if (blockheight < 1)
I_Error("3D GenerateTexture : too small");
}
else
{
#ifdef GLIDE_API_COMPATIBILITY
//size up to nearest power of 2
blockwidth = 1;
while (blockwidth < originalwidth)
blockwidth <<= 1;
// scale down the original graphics to fit in 256
if (blockwidth > 2048)
blockwidth = 2048;
//I_Error("3D GenerateTexture : too big");
//size up to nearest power of 2
blockheight = 1;
while (blockheight < originalheight)
blockheight <<= 1;
// scale down the original graphics to fit in 256
if (blockheight > 2048)
blockheight = 2048;
//I_Error("3D GenerateTexture : too big");
#else
blockwidth = originalwidth;
blockheight = originalheight;
#endif
}
// do the boring LOD stuff.. blech!
#ifdef GLIDE_API_COMPATIBILITY
if (blockwidth >= blockheight)
{
max = blockwidth;
min = blockheight;
}
else
{
max = blockheight;
min = blockwidth;
}
for (k = 2048, j = 0; k > max; j++)
k>>=1;
grInfo->smallLodLog2 = gr_lods[j];
grInfo->largeLodLog2 = gr_lods[j];
for (k = max, j = 0; k > min && j < 4; j++)
k>>=1;
// aspect ratio too small for 3Dfx (eg: 8x128 is 1x16 : use 1x8)
if (j == 4)
{
j = 3;
//CONS_Debug(DBG_RENDER, "HWR_ResizeBlock : bad aspect ratio %dx%d\n", blockwidth,blockheight);
if (blockwidth < blockheight)
blockwidth = max>>3;
else
blockheight = max>>3;
}
if (blockwidth < blockheight)
j += 4;
grInfo->aspectRatioLog2 = gr_aspects[j].aspect;
#endif
blocksize = blockwidth * blockheight;
//CONS_Debug(DBG_RENDER, "Width is %d, Height is %d\n", blockwidth, blockheight);
}
static UINT8 *MakeBlock(GLMipmap_t *grMipmap) static UINT8 *MakeBlock(GLMipmap_t *grMipmap)
{ {
UINT8 *block; UINT8 *block;
INT32 bpp, i; INT32 bpp, i;
UINT16 bu16 = ((0x00 <<8) | HWR_PATCHES_CHROMAKEY_COLORINDEX); UINT16 bu16 = ((0x00 <<8) | HWR_PATCHES_CHROMAKEY_COLORINDEX);
INT32 blocksize = (grMipmap->width * grMipmap->height);
bpp = format2bpp[grMipmap->grInfo.format]; bpp = format2bpp[grMipmap->grInfo.format];
block = Z_Malloc(blocksize*bpp, PU_HWRCACHE, &(grMipmap->grInfo.data)); block = Z_Malloc(blocksize*bpp, PU_HWRCACHE, &(grMipmap->grInfo.data));
@ -599,6 +460,7 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex)
texpatch_t *patch; texpatch_t *patch;
patch_t *realpatch; patch_t *realpatch;
UINT8 *pdata; UINT8 *pdata;
INT32 blockwidth, blockheight, blocksize;
INT32 i; INT32 i;
boolean skyspecial = false; //poor hack for Legacy large skies.. boolean skyspecial = false; //poor hack for Legacy large skies..
@ -619,11 +481,13 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex)
else else
grtex->mipmap.flags = TF_CHROMAKEYED | TF_WRAPXY; grtex->mipmap.flags = TF_CHROMAKEYED | TF_WRAPXY;
HWR_ResizeBlock (texture->width, texture->height, &grtex->mipmap.grInfo); grtex->mipmap.width = (UINT16)texture->width;
grtex->mipmap.width = (UINT16)blockwidth; grtex->mipmap.height = (UINT16)texture->height;
grtex->mipmap.height = (UINT16)blockheight;
grtex->mipmap.grInfo.format = textureformat; grtex->mipmap.grInfo.format = textureformat;
blockwidth = texture->width;
blockheight = texture->height;
blocksize = (blockwidth * blockheight);
block = MakeBlock(&grtex->mipmap); block = MakeBlock(&grtex->mipmap);
if (skyspecial) //Hurdler: not efficient, but better than holes in the sky (and it's done only at level loading) if (skyspecial) //Hurdler: not efficient, but better than holes in the sky (and it's done only at level loading)
@ -692,8 +556,6 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex)
// patch may be NULL if grMipmap has been initialised already and makebitmap is false // patch may be NULL if grMipmap has been initialised already and makebitmap is false
void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap) void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap)
{ {
INT32 newwidth, newheight;
#ifndef NO_PNG_LUMPS #ifndef NO_PNG_LUMPS
// lump is a png so convert it // lump is a png so convert it
size_t len = W_LumpLengthPwad(grPatch->wadnum, grPatch->lumpnum); size_t len = W_LumpLengthPwad(grPatch->wadnum, grPatch->lumpnum);
@ -712,51 +574,32 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm
grPatch->leftoffset = SHORT(patch->leftoffset); grPatch->leftoffset = SHORT(patch->leftoffset);
grPatch->topoffset = SHORT(patch->topoffset); grPatch->topoffset = SHORT(patch->topoffset);
// find the good 3dfx size (boring spec) grMipmap->width = grMipmap->height = 1;
HWR_ResizeBlock (SHORT(patch->width), SHORT(patch->height), &grMipmap->grInfo); while (grMipmap->width < grPatch->width) grMipmap->width <<= 1;
grMipmap->width = (UINT16)blockwidth; while (grMipmap->height < grPatch->height) grMipmap->height <<= 1;
grMipmap->height = (UINT16)blockheight;
// no wrap around, no chroma key // no wrap around, no chroma key
grMipmap->flags = 0; grMipmap->flags = 0;
// setup the texture info // setup the texture info
grMipmap->grInfo.format = patchformat; grMipmap->grInfo.format = patchformat;
}
else //grPatch->max_s = grPatch->max_t = 1.0f;
{ grPatch->max_s = (float)grPatch->width / (float)grMipmap->width;
blockwidth = grMipmap->width; grPatch->max_t = (float)grPatch->height / (float)grMipmap->height;
blockheight = grMipmap->height;
blocksize = blockwidth * blockheight;
} }
Z_Free(grMipmap->grInfo.data); Z_Free(grMipmap->grInfo.data);
grMipmap->grInfo.data = NULL; grMipmap->grInfo.data = NULL;
// if rounddown, rounddown patches as well as textures
if (cv_grrounddown.value)
{
newwidth = blockwidth;
newheight = blockheight;
}
else
{
// no rounddown, do not size up patches, so they don't look 'scaled'
newwidth = min(grPatch->width, blockwidth);
newheight = min(grPatch->height, blockheight);
}
if (makebitmap) if (makebitmap)
{ {
MakeBlock(grMipmap); MakeBlock(grMipmap);
HWR_DrawPatchInCache(grMipmap, HWR_DrawPatchInCache(grMipmap,
newwidth, newheight, grMipmap->width, grMipmap->height,
grPatch->width, grPatch->height, grPatch->width, grPatch->height,
patch); patch);
} }
grPatch->max_s = (float)newwidth / (float)blockwidth;
grPatch->max_t = (float)newheight / (float)blockheight;
} }
@ -896,9 +739,12 @@ GLTexture_t *HWR_GetTexture(INT32 tex)
if (!grtex->mipmap.grInfo.data && !grtex->mipmap.downloaded) if (!grtex->mipmap.grInfo.data && !grtex->mipmap.downloaded)
HWR_GenerateTexture(tex, grtex); HWR_GenerateTexture(tex, grtex);
// Tell the hardware driver to bind the current texture to the flat's mipmap // If hardware does not have the texture, then call pfnSetTexture to upload it
if (!grtex->mipmap.downloaded)
HWD.pfnSetTexture(&grtex->mipmap); HWD.pfnSetTexture(&grtex->mipmap);
HWR_SetCurrentTexture(&grtex->mipmap);
// The system-memory data can be purged now. // The system-memory data can be purged now.
Z_ChangeTag(grtex->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED); Z_ChangeTag(grtex->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED);
@ -910,11 +756,6 @@ static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum)
size_t size, pflatsize; size_t size, pflatsize;
// setup the texture info // setup the texture info
#ifdef GLIDE_API_COMPATIBILITY
grMipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_64;
grMipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_64;
grMipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
#endif
grMipmap->grInfo.format = GR_TEXFMT_P_8; grMipmap->grInfo.format = GR_TEXFMT_P_8;
grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED; grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED;
@ -957,15 +798,7 @@ static void HWR_CacheTextureAsFlat(GLMipmap_t *grMipmap, INT32 texturenum)
{ {
UINT8 *flat; UINT8 *flat;
if (needpatchflush)
W_FlushCachedPatches();
// setup the texture info // setup the texture info
#ifdef GLIDE_API_COMPATIBILITY
grMipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_64;
grMipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_64;
grMipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
#endif
grMipmap->grInfo.format = GR_TEXFMT_P_8; grMipmap->grInfo.format = GR_TEXFMT_P_8;
grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED; grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED;
@ -985,15 +818,16 @@ void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum)
if (flatlumpnum == LUMPERROR) if (flatlumpnum == LUMPERROR)
return; return;
if (needpatchflush)
W_FlushCachedPatches();
grmip = HWR_GetCachedGLPatch(flatlumpnum)->mipmap; grmip = HWR_GetCachedGLPatch(flatlumpnum)->mipmap;
if (!grmip->downloaded && !grmip->grInfo.data) if (!grmip->downloaded && !grmip->grInfo.data)
HWR_CacheFlat(grmip, flatlumpnum); HWR_CacheFlat(grmip, flatlumpnum);
// If hardware does not have the texture, then call pfnSetTexture to upload it
if (!grmip->downloaded)
HWD.pfnSetTexture(grmip); HWD.pfnSetTexture(grmip);
HWR_SetCurrentTexture(grmip);
// The system-memory data can be purged now. // The system-memory data can be purged now.
Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED); Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED);
} }
@ -1026,14 +860,17 @@ void HWR_GetLevelFlat(levelflat_t *levelflat)
if (!grtex->mipmap.grInfo.data && !grtex->mipmap.downloaded) if (!grtex->mipmap.grInfo.data && !grtex->mipmap.downloaded)
HWR_CacheTextureAsFlat(&grtex->mipmap, texturenum); HWR_CacheTextureAsFlat(&grtex->mipmap, texturenum);
// Tell the hardware driver to bind the current texture to the flat's mipmap // If hardware does not have the texture, then call pfnSetTexture to upload it
if (!grtex->mipmap.downloaded)
HWD.pfnSetTexture(&grtex->mipmap); HWD.pfnSetTexture(&grtex->mipmap);
HWR_SetCurrentTexture(&grtex->mipmap);
// The system-memory data can be purged now. // The system-memory data can be purged now.
Z_ChangeTag(grtex->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED); Z_ChangeTag(grtex->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED);
} }
else // set no texture else // set no texture
HWD.pfnSetTexture(NULL); HWR_SetCurrentTexture(NULL);
} }
// //
@ -1055,8 +892,12 @@ static void HWR_LoadMappedPatch(GLMipmap_t *grmip, GLPatch_t *gpatch)
Z_Free(patch); Z_Free(patch);
} }
// If hardware does not have the texture, then call pfnSetTexture to upload it
if (!grmip->downloaded)
HWD.pfnSetTexture(grmip); HWD.pfnSetTexture(grmip);
HWR_SetCurrentTexture(grmip);
// The system-memory data can be purged now. // The system-memory data can be purged now.
Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED); Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED);
} }
@ -1066,9 +907,6 @@ static void HWR_LoadMappedPatch(GLMipmap_t *grmip, GLPatch_t *gpatch)
// -----------------+ // -----------------+
void HWR_GetPatch(GLPatch_t *gpatch) void HWR_GetPatch(GLPatch_t *gpatch)
{ {
if (needpatchflush)
W_FlushCachedPatches();
// is it in hardware cache // is it in hardware cache
if (!gpatch->mipmap->downloaded && !gpatch->mipmap->grInfo.data) if (!gpatch->mipmap->downloaded && !gpatch->mipmap->grInfo.data)
{ {
@ -1085,8 +923,12 @@ void HWR_GetPatch(GLPatch_t *gpatch)
Z_Free(ptr); Z_Free(ptr);
} }
// If hardware does not have the texture, then call pfnSetTexture to upload it
if (!gpatch->mipmap->downloaded)
HWD.pfnSetTexture(gpatch->mipmap); HWD.pfnSetTexture(gpatch->mipmap);
HWR_SetCurrentTexture(gpatch->mipmap);
// The system-memory patch data can be purged now. // The system-memory patch data can be purged now.
Z_ChangeTag(gpatch->mipmap->grInfo.data, PU_HWRCACHE_UNLOCKED); Z_ChangeTag(gpatch->mipmap->grInfo.data, PU_HWRCACHE_UNLOCKED);
} }
@ -1099,9 +941,6 @@ void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap)
{ {
GLMipmap_t *grmip, *newmip; GLMipmap_t *grmip, *newmip;
if (needpatchflush)
W_FlushCachedPatches();
if (colormap == colormaps || colormap == NULL) if (colormap == colormaps || colormap == NULL)
{ {
// Load the default (green) color in doom cache (temporary?) AND hardware cache // Load the default (green) color in doom cache (temporary?) AND hardware cache
@ -1225,19 +1064,12 @@ static void HWR_DrawPicInCache(UINT8 *block, INT32 pblockwidth, INT32 pblockheig
// -----------------+ // -----------------+
GLPatch_t *HWR_GetPic(lumpnum_t lumpnum) GLPatch_t *HWR_GetPic(lumpnum_t lumpnum)
{ {
GLPatch_t *grpatch; GLPatch_t *grpatch = HWR_GetCachedGLPatch(lumpnum);
if (needpatchflush)
W_FlushCachedPatches();
grpatch = HWR_GetCachedGLPatch(lumpnum);
if (!grpatch->mipmap->downloaded && !grpatch->mipmap->grInfo.data) if (!grpatch->mipmap->downloaded && !grpatch->mipmap->grInfo.data)
{ {
pic_t *pic; pic_t *pic;
UINT8 *block; UINT8 *block;
size_t len; size_t len;
INT32 newwidth, newheight;
pic = W_CacheLumpNum(lumpnum, PU_CACHE); pic = W_CacheLumpNum(lumpnum, PU_CACHE);
grpatch->width = SHORT(pic->width); grpatch->width = SHORT(pic->width);
@ -1247,10 +1079,8 @@ GLPatch_t *HWR_GetPic(lumpnum_t lumpnum)
grpatch->leftoffset = 0; grpatch->leftoffset = 0;
grpatch->topoffset = 0; grpatch->topoffset = 0;
// find the good 3dfx size (boring spec) grpatch->mipmap->width = (UINT16)grpatch->width;
HWR_ResizeBlock (grpatch->width, grpatch->height, &grpatch->mipmap->grInfo); grpatch->mipmap->height = (UINT16)grpatch->height;
grpatch->mipmap->width = (UINT16)blockwidth;
grpatch->mipmap->height = (UINT16)blockheight;
if (pic->mode == PALETTE) if (pic->mode == PALETTE)
grpatch->mipmap->grInfo.format = textureformat; // can be set by driver grpatch->mipmap->grInfo.format = textureformat; // can be set by driver
@ -1262,30 +1092,16 @@ GLPatch_t *HWR_GetPic(lumpnum_t lumpnum)
// allocate block // allocate block
block = MakeBlock(grpatch->mipmap); block = MakeBlock(grpatch->mipmap);
// if rounddown, rounddown patches as well as textures if (grpatch->width == SHORT(pic->width) &&
if (cv_grrounddown.value) grpatch->height == SHORT(pic->height) &&
{
newwidth = blockwidth;
newheight = blockheight;
}
else
{
// no rounddown, do not size up patches, so they don't look 'scaled'
newwidth = min(SHORT(pic->width),blockwidth);
newheight = min(SHORT(pic->height),blockheight);
}
if (grpatch->width == blockwidth &&
grpatch->height == blockheight &&
format2bpp[grpatch->mipmap->grInfo.format] == format2bpp[picmode2GR[pic->mode]]) format2bpp[grpatch->mipmap->grInfo.format] == format2bpp[picmode2GR[pic->mode]])
{ {
// no conversion needed // no conversion needed
M_Memcpy(grpatch->mipmap->grInfo.data, pic->data,len); M_Memcpy(grpatch->mipmap->grInfo.data, pic->data,len);
} }
else else
HWR_DrawPicInCache(block, newwidth, newheight, HWR_DrawPicInCache(block, SHORT(pic->width), SHORT(pic->height),
blockwidth*format2bpp[grpatch->mipmap->grInfo.format], SHORT(pic->width)*format2bpp[grpatch->mipmap->grInfo.format],
pic, pic,
format2bpp[grpatch->mipmap->grInfo.format]); format2bpp[grpatch->mipmap->grInfo.format]);
@ -1293,8 +1109,7 @@ GLPatch_t *HWR_GetPic(lumpnum_t lumpnum)
Z_ChangeTag(block, PU_HWRCACHE_UNLOCKED); Z_ChangeTag(block, PU_HWRCACHE_UNLOCKED);
grpatch->mipmap->flags = 0; grpatch->mipmap->flags = 0;
grpatch->max_s = (float)newwidth / (float)blockwidth; grpatch->max_s = grpatch->max_t = 1.0f;
grpatch->max_t = (float)newheight / (float)blockheight;
} }
HWD.pfnSetTexture(grpatch->mipmap); HWD.pfnSetTexture(grpatch->mipmap);
//CONS_Debug(DBG_RENDER, "picloaded at %x as texture %d\n",grpatch->mipmap.grInfo.data, grpatch->mipmap.downloaded); //CONS_Debug(DBG_RENDER, "picloaded at %x as texture %d\n",grpatch->mipmap.grInfo.data, grpatch->mipmap.downloaded);
@ -1330,7 +1145,7 @@ static void HWR_DrawFadeMaskInCache(GLMipmap_t *mipmap, INT32 pblockwidth, INT32
{ {
INT32 i,j; INT32 i,j;
fixed_t posx, posy, stepx, stepy; fixed_t posx, posy, stepx, stepy;
UINT8 *block = mipmap->grInfo.data; // places the data directly into here, it already has the space allocated from HWR_ResizeBlock UINT8 *block = mipmap->grInfo.data; // places the data directly into here
UINT8 *flat; UINT8 *flat;
UINT8 *dest, *src, texel; UINT8 *dest, *src, texel;
RGBA_t col; RGBA_t col;
@ -1345,7 +1160,7 @@ static void HWR_DrawFadeMaskInCache(GLMipmap_t *mipmap, INT32 pblockwidth, INT32
for (j = 0; j < pblockheight; j++) for (j = 0; j < pblockheight; j++)
{ {
posx = 0; posx = 0;
dest = &block[j*blockwidth]; // 1bpp dest = &block[j*(mipmap->width)]; // 1bpp
src = &flat[(posy>>FRACBITS)*SHORT(fmwidth)]; src = &flat[(posy>>FRACBITS)*SHORT(fmwidth)];
for (i = 0; i < pblockwidth;i++) for (i = 0; i < pblockwidth;i++)
{ {
@ -1399,14 +1214,12 @@ static void HWR_CacheFadeMask(GLMipmap_t *grMipmap, lumpnum_t fademasklumpnum)
} }
// Thankfully, this will still work for this scenario // Thankfully, this will still work for this scenario
HWR_ResizeBlock(fmwidth, fmheight, &grMipmap->grInfo); grMipmap->width = fmwidth;
grMipmap->height = fmheight;
grMipmap->width = blockwidth;
grMipmap->height = blockheight;
MakeBlock(grMipmap); MakeBlock(grMipmap);
HWR_DrawFadeMaskInCache(grMipmap, blockwidth, blockheight, fademasklumpnum, fmwidth, fmheight); HWR_DrawFadeMaskInCache(grMipmap, fmwidth, fmheight, fademasklumpnum, fmwidth, fmheight);
// I DO need to convert this because it isn't power of 2 and we need the alpha // I DO need to convert this because it isn't power of 2 and we need the alpha
} }
@ -1414,13 +1227,7 @@ static void HWR_CacheFadeMask(GLMipmap_t *grMipmap, lumpnum_t fademasklumpnum)
void HWR_GetFadeMask(lumpnum_t fademasklumpnum) void HWR_GetFadeMask(lumpnum_t fademasklumpnum)
{ {
GLMipmap_t *grmip; GLMipmap_t *grmip = HWR_GetCachedGLPatch(fademasklumpnum)->mipmap;
if (needpatchflush)
W_FlushCachedPatches();
grmip = HWR_GetCachedGLPatch(fademasklumpnum)->mipmap;
if (!grmip->downloaded && !grmip->grInfo.data) if (!grmip->downloaded && !grmip->grInfo.data)
HWR_CacheFadeMask(grmip, fademasklumpnum); HWR_CacheFadeMask(grmip, fademasklumpnum);

View file

@ -78,8 +78,8 @@
#include "r_opengl/r_opengl.h" #include "r_opengl/r_opengl.h"
#ifdef HAVE_SPHEREFRUSTRUM #ifdef HAVE_SPHEREFRUSTRUM
static GLfloat viewMatrix[16]; static GLdouble viewMatrix[16];
static GLfloat projMatrix[16]; static GLdouble projMatrix[16];
float frustum[6][4]; float frustum[6][4];
#endif #endif
@ -320,12 +320,12 @@ void gld_clipper_Clear(void)
#define RMUL (1.6f/1.333333f) #define RMUL (1.6f/1.333333f)
angle_t gld_FrustumAngle(void) angle_t gld_FrustumAngle(angle_t tiltangle)
{ {
double floatangle; double floatangle;
angle_t a1; angle_t a1;
float tilt = (float)fabs(((double)(int)aimingangle) / ANG1); float tilt = (float)fabs(((double)(int)tiltangle) / ANG1);
// NEWCLIP TODO: SRB2CBTODO: make a global render_fov for this function // NEWCLIP TODO: SRB2CBTODO: make a global render_fov for this function
@ -339,7 +339,7 @@ angle_t gld_FrustumAngle(void)
} }
// If the pitch is larger than this you can look all around at a FOV of 90 // If the pitch is larger than this you can look all around at a FOV of 90
if (abs((signed)aimingangle) > 46 * ANG1) if (abs((signed)tiltangle) > 46 * ANG1)
return 0xffffffff; return 0xffffffff;
// ok, this is a gross hack that barely works... // ok, this is a gross hack that barely works...
@ -352,7 +352,7 @@ angle_t gld_FrustumAngle(void)
} }
// SRB2CB I don't think used any of this stuff, let's disable for now since SRB2 probably doesn't want it either // SRB2CB I don't think used any of this stuff, let's disable for now since SRB2 probably doesn't want it either
// compiler complains about (p)glGetDoublev anyway, in case anyone wants this // compiler complains about (p)glGetFloatv anyway, in case anyone wants this
// only r_opengl.c can use the base gl funcs as it turns out, that's a problem for whoever wants sphere frustum checks // only r_opengl.c can use the base gl funcs as it turns out, that's a problem for whoever wants sphere frustum checks
// btw to renable define HAVE_SPHEREFRUSTRUM in hw_clip.h // btw to renable define HAVE_SPHEREFRUSTRUM in hw_clip.h
#ifdef HAVE_SPHEREFRUSTRUM #ifdef HAVE_SPHEREFRUSTRUM
@ -381,7 +381,7 @@ void gld_FrustrumSetup(void)
float t; float t;
float clip[16]; float clip[16];
pglGeFloatv(GL_PROJECTION_MATRIX, projMatrix); pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix);
pglGetFloatv(GL_MODELVIEW_MATRIX, viewMatrix); pglGetFloatv(GL_MODELVIEW_MATRIX, viewMatrix);
clip[0] = CALCMATRIX(0, 0, 1, 4, 2, 8, 3, 12); clip[0] = CALCMATRIX(0, 0, 1, 4, 2, 8, 3, 12);

View file

@ -17,7 +17,7 @@
boolean gld_clipper_SafeCheckRange(angle_t startAngle, angle_t endAngle); boolean gld_clipper_SafeCheckRange(angle_t startAngle, angle_t endAngle);
void gld_clipper_SafeAddClipRange(angle_t startangle, angle_t endangle); void gld_clipper_SafeAddClipRange(angle_t startangle, angle_t endangle);
void gld_clipper_Clear(void); void gld_clipper_Clear(void);
angle_t gld_FrustumAngle(void); angle_t gld_FrustumAngle(angle_t tiltangle);
#ifdef HAVE_SPHEREFRUSTRUM #ifdef HAVE_SPHEREFRUSTRUM
void gld_FrustrumSetup(void); void gld_FrustrumSetup(void);
boolean gld_SphereInFrustum(float x, float y, float z, float radius); boolean gld_SphereInFrustum(float x, float y, float z, float radius);

View file

@ -1,21 +1,14 @@
// Emacs style mode select -*- C++ -*- // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2020 by Sonic Team Junior.
// //
// This program is free software; you can redistribute it and/or // This program is free software distributed under the
// modify it under the terms of the GNU General Public License // terms of the GNU General Public License, version 2.
// as published by the Free Software Foundation; either version 2 // See the 'LICENSE' file for more details.
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/// \file /// \file hw_data.h
/// \brief defines structures and exports for the standard 3D driver DLL used by Doom Legacy /// \brief defines structures and exports for the hardware interface used by Sonic Robo Blast 2
#ifndef _HWR_DATA_ #ifndef _HWR_DATA_
#define _HWR_DATA_ #define _HWR_DATA_

View file

@ -1,24 +1,19 @@
// Emacs style mode select -*- C++ -*- // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2020 by Sonic Team Junior.
// //
// This program is free software; you can redistribute it and/or // This program is free software distributed under the
// modify it under the terms of the GNU General Public License // terms of the GNU General Public License, version 2.
// as published by the Free Software Foundation; either version 2 // See the 'LICENSE' file for more details.
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/// \file /// \file hw_defs.h
/// \brief 3D hardware renderer definitions /// \brief 3D hardware renderer definitions
#ifndef _HWR_DEFS_ #ifndef _HWR_DEFS_
#define _HWR_DEFS_ #define _HWR_DEFS_
#include "../doomtype.h" #include "../doomtype.h"
#include "../r_defs.h"
#define ZCLIP_PLANE 4.0f // Used for the actual game drawing #define ZCLIP_PLANE 4.0f // Used for the actual game drawing
#define NZCLIP_PLANE 0.9f // Seems to be only used for the HUD and screen textures #define NZCLIP_PLANE 0.9f // Seems to be only used for the HUD and screen textures
@ -85,13 +80,15 @@ typedef struct FVector
FLOAT x,y,z; FLOAT x,y,z;
} FVector; } FVector;
// 3D model vector (coords + texture coords) // ======================
typedef struct // wallVert3D
{ // ----------------------
//FVector Point; // :crab: IS GONE! :crab:
FLOAT x,y,z; // ======================
FLOAT s,t,w; // texture coordinates
} v3d_t, wallVert3D; // -----------
// structures
// -----------
//Hurdler: Transform (coords + angles) //Hurdler: Transform (coords + angles)
//BP: transform order : scale(rotation_x(rotation_y(translation(v)))) //BP: transform order : scale(rotation_x(rotation_y(translation(v))))
@ -123,15 +120,16 @@ typedef struct
#ifdef USE_FTRANSFORM_MIRROR #ifdef USE_FTRANSFORM_MIRROR
boolean mirror; // SRB2Kart: Encore Mode boolean mirror; // SRB2Kart: Encore Mode
#endif #endif
boolean shearing; // 14042019
float viewaiming; // 17052019
} FTransform; } FTransform;
// Transformed vector, as passed to HWR API // Transformed vector, as passed to HWR API
typedef struct typedef struct
{ {
FLOAT x,y,z; FLOAT x,y,z;
FUINT argb; // flat-shaded color FLOAT s; // s texture ordinate (s over w)
FLOAT sow; // s texture ordinate (s over w) FLOAT t; // t texture ordinate (t over w)
FLOAT tow; // t texture ordinate (t over w)
} FOutVector; } FOutVector;
@ -162,10 +160,10 @@ enum EPolyFlags
PF_Invisible = 0x00000400, // Disable write to color buffer PF_Invisible = 0x00000400, // Disable write to color buffer
PF_Decal = 0x00000800, // Enable polygon offset PF_Decal = 0x00000800, // Enable polygon offset
PF_Modulated = 0x00001000, // Modulation (multiply output with constant ARGB) PF_Modulated = 0x00001000, // Modulation (multiply output with constant ARGB)
// When set, pass the color constant into the FSurfaceInfo -> FlatColor // When set, pass the color constant into the FSurfaceInfo -> PolyColor
PF_NoTexture = 0x00002000, // Use the small white texture PF_NoTexture = 0x00002000, // Use the small white texture
PF_Corona = 0x00004000, // Tell the rendrer we are drawing a corona PF_Corona = 0x00004000, // Tell the rendrer we are drawing a corona
PF_Unused = 0x00008000, // Unused PF_Ripple = 0x00008000, // Water shader effect
PF_RemoveYWrap = 0x00010000, // Force clamp texture on Y PF_RemoveYWrap = 0x00010000, // Force clamp texture on Y
PF_ForceWrapX = 0x00020000, // Force repeat texture on X PF_ForceWrapX = 0x00020000, // Force repeat texture on X
PF_ForceWrapY = 0x00040000, // Force repeat texture on Y PF_ForceWrapY = 0x00040000, // Force repeat texture on Y
@ -178,7 +176,6 @@ enum EPolyFlags
enum ESurfFlags enum ESurfFlags
{ {
SF_DYNLIGHT = 0x00000001, SF_DYNLIGHT = 0x00000001,
}; };
enum ETextureFlags enum ETextureFlags
@ -190,38 +187,36 @@ enum ETextureFlags
TF_TRANSPARENT = 0x00000040, // texture with some alpha == 0 TF_TRANSPARENT = 0x00000040, // texture with some alpha == 0
}; };
#ifdef TODO
struct FTextureInfo
{
FUINT Width; // Pixels
FUINT Height; // Pixels
FUBYTE *TextureData; // Image data
FUINT Format; // FORMAT_RGB, ALPHA ...
FBITFIELD Flags; // Flags to tell driver about texture (see ETextureFlags)
void DriverExtra; // (OpenGL texture object nr, ...)
// chromakey enabled,...
struct FTextureInfo *Next; // Manage list of downloaded textures.
};
#else
typedef struct GLMipmap_s FTextureInfo; typedef struct GLMipmap_s FTextureInfo;
#endif
// jimita 14032019
struct FLightInfo
{
FUINT light_level;
FUINT fade_start;
FUINT fade_end;
};
typedef struct FLightInfo FLightInfo;
// Description of a renderable surface // Description of a renderable surface
struct FSurfaceInfo struct FSurfaceInfo
{ {
FUINT PolyFlags; // Surface flags -- UNUSED YET -- FUINT PolyFlags;
RGBA_t FlatColor; // Flat-shaded color used with PF_Modulated mode RGBA_t PolyColor;
RGBA_t TintColor;
RGBA_t FadeColor;
FLightInfo LightInfo; // jimita 14032019
}; };
typedef struct FSurfaceInfo FSurfaceInfo; typedef struct FSurfaceInfo FSurfaceInfo;
#define GL_DEFAULTMIX 0x00000000
#define GL_DEFAULTFOG 0xFF000000
//Hurdler: added for backward compatibility //Hurdler: added for backward compatibility
enum hwdsetspecialstate enum hwdsetspecialstate
{ {
HWD_SET_MODEL_LIGHTING = 1, HWD_SET_MODEL_LIGHTING = 1,
HWD_SET_FOG_MODE, HWD_SET_SHADERS,
HWD_SET_FOG_COLOR,
HWD_SET_FOG_DENSITY,
HWD_SET_TEXTUREFILTERMODE, HWD_SET_TEXTUREFILTERMODE,
HWD_SET_TEXTUREANISOTROPICMODE, HWD_SET_TEXTUREANISOTROPICMODE,
HWD_NUMSTATE HWD_NUMSTATE
@ -229,6 +224,15 @@ enum hwdsetspecialstate
typedef enum hwdsetspecialstate hwdspecialstate_t; typedef enum hwdsetspecialstate hwdspecialstate_t;
// Lactozilla: Shader info
// Generally set at the start of the frame.
enum hwdshaderinfo
{
HWD_SHADERINFO_LEVELTIME = 1,
};
typedef enum hwdshaderinfo hwdshaderinfo_t;
enum hwdfiltermode enum hwdfiltermode
{ {
HWD_SET_TEXTUREFILTER_POINTSAMPLED, HWD_SET_TEXTUREFILTER_POINTSAMPLED,

View file

@ -1,19 +1,12 @@
// Emacs style mode select -*- C++ -*- // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 2005 by Sonic Team Junior.
// //
// Copyright (C) 2005 by SRB2 Jr. Team. // This program is free software distributed under the
// // terms of the GNU General Public License, version 2.
// This program is free software; you can redistribute it and/or // See the 'LICENSE' file for more details.
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/// \file /// \file hw_dll.h
/// \brief Win32 DLL and Shared Objects API definitions /// \brief Win32 DLL and Shared Objects API definitions
#ifndef __HWR_DLL_H__ #ifndef __HWR_DLL_H__
@ -54,8 +47,6 @@
#endif #endif
#endif #endif
typedef void (*I_Error_t) (const char *error, ...) FUNCIERROR;
// ========================================================================== // ==========================================================================
// MATHS // MATHS
// ========================================================================== // ==========================================================================
@ -63,7 +54,7 @@ typedef void (*I_Error_t) (const char *error, ...) FUNCIERROR;
// Constants // Constants
#define DEGREE (0.017453292519943295769236907684883l) // 2*PI/360 #define DEGREE (0.017453292519943295769236907684883l) // 2*PI/360
void DBG_Printf(const char *lpFmt, ...) /*FUNCPRINTF*/; void GL_DBG_Printf(const char *format, ...) /*FUNCPRINTF*/;
#ifdef _WINDOWS #ifdef _WINDOWS
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved); BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);

View file

@ -1,19 +1,13 @@
// Emacs style mode select -*- C++ -*- // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2020 by Sonic Team Junior.
// //
// This program is free software; you can redistribute it and/or // This program is free software distributed under the
// modify it under the terms of the GNU General Public License // terms of the GNU General Public License, version 2.
// as published by the Free Software Foundation; either version 2 // See the 'LICENSE' file for more details.
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/// \file /// \file hw_draw.c
/// \brief miscellaneous drawing (mainly 2d) /// \brief miscellaneous drawing (mainly 2d)
#ifdef __GNUC__ #ifdef __GNUC__
@ -23,6 +17,7 @@
#include "../doomdef.h" #include "../doomdef.h"
#ifdef HWRENDER #ifdef HWRENDER
#include "hw_main.h"
#include "hw_glob.h" #include "hw_glob.h"
#include "hw_drv.h" #include "hw_drv.h"
@ -43,9 +38,6 @@
#define O_BINARY 0 #define O_BINARY 0
#endif #endif
float gr_patch_scalex;
float gr_patch_scaley;
#if defined(_MSC_VER) #if defined(_MSC_VER)
#pragma pack(1) #pragma pack(1)
#endif #endif
@ -65,9 +57,6 @@ typedef struct
#if defined(_MSC_VER) #if defined(_MSC_VER)
#pragma pack() #pragma pack()
#endif #endif
typedef UINT8 GLRGB[3];
#define BLENDMODE PF_Translucent
static UINT8 softwaretranstogl[11] = { 0, 25, 51, 76,102,127,153,178,204,229,255}; static UINT8 softwaretranstogl[11] = { 0, 25, 51, 76,102,127,153,178,204,229,255};
static UINT8 softwaretranstogl_hi[11] = { 0, 51,102,153,204,255,255,255,255,255,255}; static UINT8 softwaretranstogl_hi[11] = { 0, 51,102,153,204,255,255,255,255,255,255};
@ -121,12 +110,12 @@ void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option)
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
v[0].sow = v[3].sow = 0.0f; v[0].s = v[3].s = 0.0f;
v[2].sow = v[1].sow = gpatch->max_s; v[2].s = v[1].s = gpatch->max_s;
v[0].tow = v[1].tow = 0.0f; v[0].t = v[1].t = 0.0f;
v[2].tow = v[3].tow = gpatch->max_t; v[2].t = v[3].t = gpatch->max_t;
flags = BLENDMODE|PF_Clip|PF_NoZClip|PF_NoDepthTest; flags = PF_Translucent|PF_NoDepthTest;
if (option & V_WRAPX) if (option & V_WRAPX)
flags |= PF_ForceWrapX; flags |= PF_ForceWrapX;
@ -356,19 +345,19 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t
if (option & V_FLIP) if (option & V_FLIP)
{ {
v[0].sow = v[3].sow = gpatch->max_s; v[0].s = v[3].s = gpatch->max_s;
v[2].sow = v[1].sow = 0.0f; v[2].s = v[1].s = 0.0f;
} }
else else
{ {
v[0].sow = v[3].sow = 0.0f; v[0].s = v[3].s = 0.0f;
v[2].sow = v[1].sow = gpatch->max_s; v[2].s = v[1].s = gpatch->max_s;
} }
v[0].tow = v[1].tow = 0.0f; v[0].t = v[1].t = 0.0f;
v[2].tow = v[3].tow = gpatch->max_t; v[2].t = v[3].t = gpatch->max_t;
flags = BLENDMODE|PF_Clip|PF_NoZClip|PF_NoDepthTest; flags = PF_Translucent|PF_NoDepthTest;
if (option & V_WRAPX) if (option & V_WRAPX)
flags |= PF_ForceWrapX; flags |= PF_ForceWrapX;
@ -379,11 +368,11 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t
if (alphalevel) if (alphalevel)
{ {
FSurfaceInfo Surf; FSurfaceInfo Surf;
Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff;
if (alphalevel == 13) Surf.FlatColor.s.alpha = softwaretranstogl_lo[st_translucency]; if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[st_translucency];
else if (alphalevel == 14) Surf.FlatColor.s.alpha = softwaretranstogl[st_translucency]; else if (alphalevel == 14) Surf.PolyColor.s.alpha = softwaretranstogl[st_translucency];
else if (alphalevel == 15) Surf.FlatColor.s.alpha = softwaretranstogl_hi[st_translucency]; else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[st_translucency];
else Surf.FlatColor.s.alpha = softwaretranstogl[10-alphalevel]; else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel];
flags |= PF_Modulated; flags |= PF_Modulated;
HWD.pfnDrawPolygon(&Surf, v, 4, flags); HWD.pfnDrawPolygon(&Surf, v, 4, flags);
} }
@ -514,19 +503,19 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
v[0].sow = v[3].sow = ((sx )/(float)SHORT(gpatch->width) )*gpatch->max_s; v[0].s = v[3].s = ((sx )/(float)SHORT(gpatch->width) )*gpatch->max_s;
if (sx + w > SHORT(gpatch->width)) if (sx + w > SHORT(gpatch->width))
v[2].sow = v[1].sow = gpatch->max_s; v[2].s = v[1].s = gpatch->max_s;
else else
v[2].sow = v[1].sow = ((sx+w)/(float)SHORT(gpatch->width) )*gpatch->max_s; v[2].s = v[1].s = ((sx+w)/(float)SHORT(gpatch->width) )*gpatch->max_s;
v[0].tow = v[1].tow = ((sy )/(float)SHORT(gpatch->height))*gpatch->max_t; v[0].t = v[1].t = ((sy )/(float)SHORT(gpatch->height))*gpatch->max_t;
if (sy + h > SHORT(gpatch->height)) if (sy + h > SHORT(gpatch->height))
v[2].tow = v[3].tow = gpatch->max_t; v[2].t = v[3].t = gpatch->max_t;
else else
v[2].tow = v[3].tow = ((sy+h)/(float)SHORT(gpatch->height))*gpatch->max_t; v[2].t = v[3].t = ((sy+h)/(float)SHORT(gpatch->height))*gpatch->max_t;
flags = BLENDMODE|PF_Clip|PF_NoZClip|PF_NoDepthTest; flags = PF_Translucent|PF_NoDepthTest;
if (option & V_WRAPX) if (option & V_WRAPX)
flags |= PF_ForceWrapX; flags |= PF_ForceWrapX;
@ -537,11 +526,11 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
if (alphalevel) if (alphalevel)
{ {
FSurfaceInfo Surf; FSurfaceInfo Surf;
Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff;
if (alphalevel == 13) Surf.FlatColor.s.alpha = softwaretranstogl_lo[st_translucency]; if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[st_translucency];
else if (alphalevel == 14) Surf.FlatColor.s.alpha = softwaretranstogl[st_translucency]; else if (alphalevel == 14) Surf.PolyColor.s.alpha = softwaretranstogl[st_translucency];
else if (alphalevel == 15) Surf.FlatColor.s.alpha = softwaretranstogl_hi[st_translucency]; else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[st_translucency];
else Surf.FlatColor.s.alpha = softwaretranstogl[10-alphalevel]; else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel];
flags |= PF_Modulated; flags |= PF_Modulated;
HWD.pfnDrawPolygon(&Surf, v, 4, flags); HWD.pfnDrawPolygon(&Surf, v, 4, flags);
} }
@ -569,10 +558,10 @@ void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum)
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
v[0].sow = v[3].sow = 0; v[0].s = v[3].s = 0;
v[2].sow = v[1].sow = patch->max_s; v[2].s = v[1].s = patch->max_s;
v[0].tow = v[1].tow = 0; v[0].t = v[1].t = 0;
v[2].tow = v[3].tow = patch->max_t; v[2].t = v[3].t = patch->max_t;
//Hurdler: Boris, the same comment as above... but maybe for pics //Hurdler: Boris, the same comment as above... but maybe for pics
@ -581,7 +570,7 @@ void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum)
// But then, the question is: why not 0 instead of PF_Masked ? // But then, the question is: why not 0 instead of PF_Masked ?
// or maybe PF_Environment ??? (like what I said above) // or maybe PF_Environment ??? (like what I said above)
// BP: PF_Environment don't change anything ! and 0 is undifined // BP: PF_Environment don't change anything ! and 0 is undifined
HWD.pfnDrawPolygon(NULL, v, 4, BLENDMODE | PF_NoDepthTest | PF_Clip | PF_NoZClip); HWD.pfnDrawPolygon(NULL, v, 4, PF_Translucent | PF_NoDepthTest | PF_Clip | PF_NoZClip);
} }
// ========================================================================== // ==========================================================================
@ -644,10 +633,10 @@ void HWR_DrawFlatFill (INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
// flat is 64x64 lod and texture offsets are [0.0, 1.0] // flat is 64x64 lod and texture offsets are [0.0, 1.0]
v[0].sow = v[3].sow = (float)((x & flatflag)/dflatsize); v[0].s = v[3].s = (float)((x & flatflag)/dflatsize);
v[2].sow = v[1].sow = (float)(v[0].sow + w/dflatsize); v[2].s = v[1].s = (float)(v[0].s + w/dflatsize);
v[0].tow = v[1].tow = (float)((y & flatflag)/dflatsize); v[0].t = v[1].t = (float)((y & flatflag)/dflatsize);
v[2].tow = v[3].tow = (float)(v[0].tow + h/dflatsize); v[2].t = v[3].t = (float)(v[0].t + h/dflatsize);
HWR_LiterallyGetFlat(flatlumpnum); HWR_LiterallyGetFlat(flatlumpnum);
@ -679,20 +668,20 @@ void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength)
v[2].y = v[3].y = 1.0f; v[2].y = v[3].y = 1.0f;
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
v[0].sow = v[3].sow = 0.0f; v[0].s = v[3].s = 0.0f;
v[2].sow = v[1].sow = 1.0f; v[2].s = v[1].s = 1.0f;
v[0].tow = v[1].tow = 1.0f; v[0].t = v[1].t = 1.0f;
v[2].tow = v[3].tow = 0.0f; v[2].t = v[3].t = 0.0f;
if (color & 0xFF00) // Do COLORMAP fade. if (color & 0xFF00) // Do COLORMAP fade.
{ {
Surf.FlatColor.rgba = UINT2RGBA(0x01010160); Surf.PolyColor.rgba = UINT2RGBA(0x01010160);
Surf.FlatColor.s.alpha = (strength*8); Surf.PolyColor.s.alpha = (strength*8);
} }
else // Do TRANSMAP** fade. else // Do TRANSMAP** fade.
{ {
Surf.FlatColor.rgba = V_GetColor(color).rgba; Surf.PolyColor.rgba = V_GetColor(color).rgba;
Surf.FlatColor.s.alpha = softwaretranstogl[strength]; Surf.PolyColor.s.alpha = softwaretranstogl[strength];
} }
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
} }
@ -850,24 +839,22 @@ void HWR_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT16 ac
v[0].y = v[1].y = fy; v[0].y = v[1].y = fy;
v[2].y = v[3].y = fy - fh; v[2].y = v[3].y = fy - fh;
//Hurdler: do we still use this argb color? if not, we should remove it
v[0].argb = v[1].argb = v[2].argb = v[3].argb = 0xff00ff00; //;
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
v[0].sow = v[3].sow = 0.0f; v[0].s = v[3].s = 0.0f;
v[2].sow = v[1].sow = 1.0f; v[2].s = v[1].s = 1.0f;
v[0].tow = v[1].tow = 0.0f; v[0].t = v[1].t = 0.0f;
v[2].tow = v[3].tow = 1.0f; v[2].t = v[3].t = 1.0f;
if (actualcolor & 0xFF00) // Do COLORMAP fade. if (actualcolor & 0xFF00) // Do COLORMAP fade.
{ {
Surf.FlatColor.rgba = UINT2RGBA(0x01010160); Surf.PolyColor.rgba = UINT2RGBA(0x01010160);
Surf.FlatColor.s.alpha = (strength*8); Surf.PolyColor.s.alpha = (strength*8);
} }
else // Do TRANSMAP** fade. else // Do TRANSMAP** fade.
{ {
Surf.FlatColor.rgba = V_GetColor(actualcolor).rgba; Surf.PolyColor.rgba = V_GetColor(actualcolor).rgba;
Surf.FlatColor.s.alpha = softwaretranstogl[strength]; Surf.PolyColor.s.alpha = softwaretranstogl[strength];
} }
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
} }
@ -888,13 +875,13 @@ void HWR_DrawConsoleBack(UINT32 color, INT32 height)
v[2].y = v[3].y = 1.0f; v[2].y = v[3].y = 1.0f;
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
v[0].sow = v[3].sow = 0.0f; v[0].s = v[3].s = 0.0f;
v[2].sow = v[1].sow = 1.0f; v[2].s = v[1].s = 1.0f;
v[0].tow = v[1].tow = 1.0f; v[0].t = v[1].t = 1.0f;
v[2].tow = v[3].tow = 0.0f; v[2].t = v[3].t = 0.0f;
Surf.FlatColor.rgba = UINT2RGBA(color); Surf.PolyColor.rgba = UINT2RGBA(color);
Surf.FlatColor.s.alpha = 0x80; Surf.PolyColor.s.alpha = 0x80;
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
} }
@ -904,7 +891,11 @@ void HWR_DrawTutorialBack(UINT32 color, INT32 boxheight)
{ {
FOutVector v[4]; FOutVector v[4];
FSurfaceInfo Surf; FSurfaceInfo Surf;
INT32 height = (boxheight * 4) + (boxheight/2)*5; // 4 lines of space plus gaps between and some leeway INT32 height;
if (boxheight < 0)
height = -boxheight;
else
height = (boxheight * 4) + (boxheight/2)*5; // 4 lines of space plus gaps between and some leeway
// setup some neat-o translucency effect // setup some neat-o translucency effect
@ -914,13 +905,13 @@ void HWR_DrawTutorialBack(UINT32 color, INT32 boxheight)
v[2].y = v[3].y = -1.0f+((height<<1)/(float)vid.height); v[2].y = v[3].y = -1.0f+((height<<1)/(float)vid.height);
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
v[0].sow = v[3].sow = 0.0f; v[0].s = v[3].s = 0.0f;
v[2].sow = v[1].sow = 1.0f; v[2].s = v[1].s = 1.0f;
v[0].tow = v[1].tow = 1.0f; v[0].t = v[1].t = 1.0f;
v[2].tow = v[3].tow = 0.0f; v[2].t = v[3].t = 0.0f;
Surf.FlatColor.rgba = UINT2RGBA(color); Surf.PolyColor.rgba = UINT2RGBA(color);
Surf.FlatColor.s.alpha = (color == 0 ? 0xC0 : 0x80); // make black darker, like software Surf.PolyColor.s.alpha = (color == 0 ? 0xC0 : 0x80); // make black darker, like software
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
} }
@ -1232,17 +1223,15 @@ void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT32
v[0].y = v[1].y = fy; v[0].y = v[1].y = fy;
v[2].y = v[3].y = fy - fh; v[2].y = v[3].y = fy - fh;
//Hurdler: do we still use this argb color? if not, we should remove it
v[0].argb = v[1].argb = v[2].argb = v[3].argb = 0xff00ff00; //;
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
v[0].sow = v[3].sow = 0.0f; v[0].s = v[3].s = 0.0f;
v[2].sow = v[1].sow = 1.0f; v[2].s = v[1].s = 1.0f;
v[0].tow = v[1].tow = 0.0f; v[0].t = v[1].t = 0.0f;
v[2].tow = v[3].tow = 1.0f; v[2].t = v[3].t = 1.0f;
Surf.FlatColor.rgba = UINT2RGBA(actualcolor); Surf.PolyColor.rgba = UINT2RGBA(actualcolor);
Surf.FlatColor.s.alpha = 0x80; Surf.PolyColor.s.alpha = 0x80;
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
} }
@ -1412,16 +1401,14 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
v[0].y = v[1].y = fy; v[0].y = v[1].y = fy;
v[2].y = v[3].y = fy - fh; v[2].y = v[3].y = fy - fh;
//Hurdler: do we still use this argb color? if not, we should remove it
v[0].argb = v[1].argb = v[2].argb = v[3].argb = 0xff00ff00; //;
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
v[0].sow = v[3].sow = 0.0f; v[0].s = v[3].s = 0.0f;
v[2].sow = v[1].sow = 1.0f; v[2].s = v[1].s = 1.0f;
v[0].tow = v[1].tow = 0.0f; v[0].t = v[1].t = 0.0f;
v[2].tow = v[3].tow = 1.0f; v[2].t = v[3].t = 1.0f;
Surf.FlatColor = V_GetColor(color); Surf.PolyColor = V_GetColor(color);
HWD.pfnDrawPolygon(&Surf, v, 4, HWD.pfnDrawPolygon(&Surf, v, 4,
PF_Modulated|PF_NoTexture|PF_NoDepthTest); PF_Modulated|PF_NoTexture|PF_NoDepthTest);

View file

@ -1,20 +1,13 @@
// Emacs style mode select -*- C++ -*- // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2020 by Sonic Team Junior.
// //
// This program is free software; you can redistribute it and/or // This program is free software distributed under the
// modify it under the terms of the GNU General Public License // terms of the GNU General Public License, version 2.
// as published by the Free Software Foundation; either version 2 // See the 'LICENSE' file for more details.
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/// \file /// \file hw_drv.h
/// \brief imports/exports for the 3D hardware low-level interface API /// \brief imports/exports for the 3D hardware low-level interface API
#ifndef __HWR_DRV_H__ #ifndef __HWR_DRV_H__
@ -32,7 +25,7 @@
// STANDARD DLL EXPORTS // STANDARD DLL EXPORTS
// ========================================================================== // ==========================================================================
EXPORT boolean HWRAPI(Init) (I_Error_t ErrorFunction); EXPORT boolean HWRAPI(Init) (void);
#ifndef HAVE_SDL #ifndef HAVE_SDL
EXPORT void HWRAPI(Shutdown) (void); EXPORT void HWRAPI(Shutdown) (void);
#endif #endif
@ -43,10 +36,12 @@ EXPORT void HWRAPI(SetPalette) (RGBA_t *ppal);
EXPORT void HWRAPI(FinishUpdate) (INT32 waitvbl); EXPORT void HWRAPI(FinishUpdate) (INT32 waitvbl);
EXPORT void HWRAPI(Draw2DLine) (F2DCoord *v1, F2DCoord *v2, RGBA_t Color); EXPORT void HWRAPI(Draw2DLine) (F2DCoord *v1, F2DCoord *v2, RGBA_t Color);
EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags); EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags);
EXPORT void HWRAPI(DrawIndexedTriangles) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, UINT32 *IndexArray);
EXPORT void HWRAPI(RenderSkyDome) (INT32 tex, INT32 texture_width, INT32 texture_height, FTransform transform); EXPORT void HWRAPI(RenderSkyDome) (INT32 tex, INT32 texture_width, INT32 texture_height, FTransform transform);
EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags); EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags);
EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat *ClearColor); EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat *ClearColor);
EXPORT void HWRAPI(SetTexture) (FTextureInfo *TexInfo); EXPORT void HWRAPI(SetTexture) (FTextureInfo *TexInfo);
EXPORT void HWRAPI(UpdateTexture) (FTextureInfo *TexInfo);
EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 *dst_data); EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 *dst_data);
EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip); EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip);
EXPORT void HWRAPI(ClearMipMapCache) (void); EXPORT void HWRAPI(ClearMipMapCache) (void);
@ -55,14 +50,11 @@ EXPORT void HWRAPI(ClearMipMapCache) (void);
EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value); EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value);
//Hurdler: added for new development //Hurdler: added for new development
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 *color); EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface);
EXPORT void HWRAPI(CreateModelVBOs) (model_t *model); EXPORT void HWRAPI(CreateModelVBOs) (model_t *model);
EXPORT void HWRAPI(SetTransform) (FTransform *ptransform); EXPORT void HWRAPI(SetTransform) (FTransform *ptransform);
EXPORT INT32 HWRAPI(GetTextureUsed) (void); EXPORT INT32 HWRAPI(GetTextureUsed) (void);
EXPORT INT32 HWRAPI(GetRenderVersion) (void);
#define SCREENVERTS 10
EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]);
EXPORT void HWRAPI(FlushScreenTextures) (void); EXPORT void HWRAPI(FlushScreenTextures) (void);
EXPORT void HWRAPI(StartScreenWipe) (void); EXPORT void HWRAPI(StartScreenWipe) (void);
EXPORT void HWRAPI(EndScreenWipe) (void); EXPORT void HWRAPI(EndScreenWipe) (void);
@ -71,6 +63,20 @@ EXPORT void HWRAPI(DrawIntermissionBG) (void);
EXPORT void HWRAPI(MakeScreenTexture) (void); EXPORT void HWRAPI(MakeScreenTexture) (void);
EXPORT void HWRAPI(MakeScreenFinalTexture) (void); EXPORT void HWRAPI(MakeScreenFinalTexture) (void);
EXPORT void HWRAPI(DrawScreenFinalTexture) (int width, int height); EXPORT void HWRAPI(DrawScreenFinalTexture) (int width, int height);
#define SCREENVERTS 10
EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]);
// jimita
EXPORT boolean HWRAPI(LoadShaders) (void);
EXPORT void HWRAPI(KillShaders) (void);
EXPORT void HWRAPI(SetShader) (int shader);
EXPORT void HWRAPI(UnSetShader) (void);
EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value);
EXPORT void HWRAPI(LoadCustomShader) (int number, char *shader, size_t size, boolean fragment);
EXPORT boolean HWRAPI(InitCustomShaders) (void);
// ========================================================================== // ==========================================================================
// HWR DRIVER OBJECT, FOR CLIENT PROGRAM // HWR DRIVER OBJECT, FOR CLIENT PROGRAM
// ========================================================================== // ==========================================================================
@ -84,10 +90,12 @@ struct hwdriver_s
FinishUpdate pfnFinishUpdate; FinishUpdate pfnFinishUpdate;
Draw2DLine pfnDraw2DLine; Draw2DLine pfnDraw2DLine;
DrawPolygon pfnDrawPolygon; DrawPolygon pfnDrawPolygon;
DrawIndexedTriangles pfnDrawIndexedTriangles;
RenderSkyDome pfnRenderSkyDome; RenderSkyDome pfnRenderSkyDome;
SetBlend pfnSetBlend; SetBlend pfnSetBlend;
ClearBuffer pfnClearBuffer; ClearBuffer pfnClearBuffer;
SetTexture pfnSetTexture; SetTexture pfnSetTexture;
UpdateTexture pfnUpdateTexture;
ReadRect pfnReadRect; ReadRect pfnReadRect;
GClipRect pfnGClipRect; GClipRect pfnGClipRect;
ClearMipMapCache pfnClearMipMapCache; ClearMipMapCache pfnClearMipMapCache;
@ -96,7 +104,6 @@ struct hwdriver_s
CreateModelVBOs pfnCreateModelVBOs; CreateModelVBOs pfnCreateModelVBOs;
SetTransform pfnSetTransform; SetTransform pfnSetTransform;
GetTextureUsed pfnGetTextureUsed; GetTextureUsed pfnGetTextureUsed;
GetRenderVersion pfnGetRenderVersion;
#ifdef _WINDOWS #ifdef _WINDOWS
GetModeList pfnGetModeList; GetModeList pfnGetModeList;
#endif #endif
@ -112,13 +119,19 @@ struct hwdriver_s
MakeScreenTexture pfnMakeScreenTexture; MakeScreenTexture pfnMakeScreenTexture;
MakeScreenFinalTexture pfnMakeScreenFinalTexture; MakeScreenFinalTexture pfnMakeScreenFinalTexture;
DrawScreenFinalTexture pfnDrawScreenFinalTexture; DrawScreenFinalTexture pfnDrawScreenFinalTexture;
LoadShaders pfnLoadShaders;
KillShaders pfnKillShaders;
SetShader pfnSetShader;
UnSetShader pfnUnSetShader;
SetShaderInfo pfnSetShaderInfo;
LoadCustomShader pfnLoadCustomShader;
InitCustomShaders pfnInitCustomShaders;
}; };
extern struct hwdriver_s hwdriver; extern struct hwdriver_s hwdriver;
//Hurdler: 16/10/99: added for OpenGL gamma correction
//extern RGBA_t gamma_correction;
#define HWD hwdriver #define HWD hwdriver
#endif //not defined _CREATE_DLL_ #endif //not defined _CREATE_DLL_

View file

@ -1,19 +1,12 @@
// Emacs style mode select -*- C++ -*- // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// //
// This program is free software; you can redistribute it and/or // This program is free software distributed under the
// modify it under the terms of the GNU General Public License // terms of the GNU General Public License, version 2.
// as published by the Free Software Foundation; either version 2 // See the 'LICENSE' file for more details.
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/// \file /// \file hw_glide.h
/// \brief Declaration needed by Glide renderer /// \brief Declaration needed by Glide renderer
/// !!! To be replaced by our own def in the future !!! /// !!! To be replaced by our own def in the future !!!
@ -25,26 +18,6 @@
typedef unsigned long FxU32; typedef unsigned long FxU32;
typedef long FxI32; typedef long FxI32;
typedef FxI32 GrAspectRatio_t;
#define GR_ASPECT_LOG2_8x1 3 /* 8W x 1H */
#define GR_ASPECT_LOG2_4x1 2 /* 4W x 1H */
#define GR_ASPECT_LOG2_2x1 1 /* 2W x 1H */
#define GR_ASPECT_LOG2_1x1 0 /* 1W x 1H */
#define GR_ASPECT_LOG2_1x2 -1 /* 1W x 2H */
#define GR_ASPECT_LOG2_1x4 -2 /* 1W x 4H */
#define GR_ASPECT_LOG2_1x8 -3 /* 1W x 8H */
typedef FxI32 GrLOD_t;
#define GR_LOD_LOG2_256 0x8
#define GR_LOD_LOG2_128 0x7
#define GR_LOD_LOG2_64 0x6
#define GR_LOD_LOG2_32 0x5
#define GR_LOD_LOG2_16 0x4
#define GR_LOD_LOG2_8 0x3
#define GR_LOD_LOG2_4 0x2
#define GR_LOD_LOG2_2 0x1
#define GR_LOD_LOG2_1 0x0
typedef FxI32 GrTextureFormat_t; typedef FxI32 GrTextureFormat_t;
#define GR_TEXFMT_ALPHA_8 0x2 /* (0..0xFF) alpha */ #define GR_TEXFMT_ALPHA_8 0x2 /* (0..0xFF) alpha */
#define GR_TEXFMT_INTENSITY_8 0x3 /* (0..0xFF) intensity */ #define GR_TEXFMT_INTENSITY_8 0x3 /* (0..0xFF) intensity */
@ -59,11 +32,6 @@ typedef FxI32 GrTextureFormat_t;
typedef struct typedef struct
{ {
#ifdef GLIDE_API_COMPATIBILITY
GrLOD_t smallLodLog2;
GrLOD_t largeLodLog2;
GrAspectRatio_t aspectRatioLog2;
#endif
GrTextureFormat_t format; GrTextureFormat_t format;
void *data; void *data;
} GrTexInfo; } GrTexInfo;

View file

@ -1,20 +1,13 @@
// Emacs style mode select -*- C++ -*- // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2020 by Sonic Team Junior.
// //
// This program is free software; you can redistribute it and/or // This program is free software distributed under the
// modify it under the terms of the GNU General Public License // terms of the GNU General Public License, version 2.
// as published by the Free Software Foundation; either version 2 // See the 'LICENSE' file for more details.
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/// \file /// \file hw_glob.h
/// \brief globals (shared data & code) for hw_ modules /// \brief globals (shared data & code) for hw_ modules
#ifndef _HWR_GLOB_H_ #ifndef _HWR_GLOB_H_
@ -68,9 +61,6 @@ typedef struct
// equivalent of the software renderer's vissprites // equivalent of the software renderer's vissprites
typedef struct gr_vissprite_s typedef struct gr_vissprite_s
{ {
// Doubly linked list
struct gr_vissprite_s *prev;
struct gr_vissprite_s *next;
float x1, x2; float x1, x2;
float tz, ty; float tz, ty;
//lumpnum_t patchlumpnum; //lumpnum_t patchlumpnum;
@ -118,11 +108,6 @@ void HWR_GetFadeMask(lumpnum_t fademasklumpnum);
// -------- // --------
// hw_draw.c // hw_draw.c
// -------- // --------
extern float gr_patch_scalex;
extern float gr_patch_scaley;
extern consvar_t cv_grrounddown; // on/off
extern INT32 patchformat; extern INT32 patchformat;
extern INT32 textureformat; extern INT32 textureformat;

View file

@ -1,19 +1,13 @@
// Emacs style mode select -*- C++ -*- // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2020 by Sonic Team Junior.
// //
// This program is free software; you can redistribute it and/or // This program is free software distributed under the
// modify it under the terms of the GNU General Public License // terms of the GNU General Public License, version 2.
// as published by the Free Software Foundation; either version 2 // See the 'LICENSE' file for more details.
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/// \file /// \file hw_light.c
/// \brief Corona/Dynamic/Static lighting add on by Hurdler /// \brief Corona/Dynamic/Static lighting add on by Hurdler
/// !!! Under construction !!! /// !!! Under construction !!!
@ -879,19 +873,19 @@ void HWR_WallLighting(FOutVector *wlVerts)
#endif #endif
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
{ {
wlVerts[i].sow = (float)(0.5f + d[i]*s); wlVerts[i].s = (float)(0.5f + d[i]*s);
wlVerts[i].tow = (float)(0.5f + (wlVerts[i].y-LIGHT_POS(j).y)*s*1.2f); wlVerts[i].t = (float)(0.5f + (wlVerts[i].y-LIGHT_POS(j).y)*s*1.2f);
} }
HWR_SetLight(); HWR_SetLight();
Surf.FlatColor.rgba = LONG(dynlights->p_lspr[j]->dynamic_color); Surf.PolyColor.rgba = LONG(dynlights->p_lspr[j]->dynamic_color);
#ifdef DL_HIGH_QUALITY #ifdef DL_HIGH_QUALITY
Surf.FlatColor.s.alpha = (UINT8)((1-dist_p2d/DL_SQRRADIUS(j))*Surf.FlatColor.s.alpha); Surf.PolyColor.s.alpha = (UINT8)((1-dist_p2d/DL_SQRRADIUS(j))*Surf.PolyColor.s.alpha);
#endif #endif
// next state is null so fade out with alpha // next state is null so fade out with alpha
if (dynlights->mo[j]->state->nextstate == S_NULL) if (dynlights->mo[j]->state->nextstate == S_NULL)
Surf.FlatColor.s.alpha = (UINT8)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.FlatColor.s.alpha); Surf.PolyColor.s.alpha = (UINT8)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.PolyColor.s.alpha);
HWD.pfnDrawPolygon (&Surf, wlVerts, 4, LIGHTMAPFLAGS); HWD.pfnDrawPolygon (&Surf, wlVerts, 4, LIGHTMAPFLAGS);
@ -948,19 +942,19 @@ void HWR_PlaneLighting(FOutVector *clVerts, int nrClipVerts)
#endif #endif
for (i = 0; i < nrClipVerts; i++) for (i = 0; i < nrClipVerts; i++)
{ {
clVerts[i].sow = 0.5f + (clVerts[i].x-LIGHT_POS(j).x)*s; clVerts[i].s = 0.5f + (clVerts[i].x-LIGHT_POS(j).x)*s;
clVerts[i].tow = 0.5f + (clVerts[i].z-LIGHT_POS(j).z)*s*1.2f; clVerts[i].t = 0.5f + (clVerts[i].z-LIGHT_POS(j).z)*s*1.2f;
} }
HWR_SetLight(); HWR_SetLight();
Surf.FlatColor.rgba = LONG(dynlights->p_lspr[j]->dynamic_color); Surf.PolyColor.rgba = LONG(dynlights->p_lspr[j]->dynamic_color);
#ifdef DL_HIGH_QUALITY #ifdef DL_HIGH_QUALITY
Surf.FlatColor.s.alpha = (unsigned char)((1 - dist_p2d/DL_SQRRADIUS(j))*Surf.FlatColor.s.alpha); Surf.PolyColor.s.alpha = (unsigned char)((1 - dist_p2d/DL_SQRRADIUS(j))*Surf.PolyColor.s.alpha);
#endif #endif
// next state is null so fade out with alpha // next state is null so fade out with alpha
if ((dynlights->mo[j]->state->nextstate == S_NULL)) if ((dynlights->mo[j]->state->nextstate == S_NULL))
Surf.FlatColor.s.alpha = (unsigned char)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.FlatColor.s.alpha); Surf.PolyColor.s.alpha = (unsigned char)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.PolyColor.s.alpha);
HWD.pfnDrawPolygon (&Surf, clVerts, nrClipVerts, LIGHTMAPFLAGS); HWD.pfnDrawPolygon (&Surf, clVerts, nrClipVerts, LIGHTMAPFLAGS);
@ -1027,11 +1021,11 @@ void HWR_DoCoronasLighting(FOutVector *outVerts, gr_vissprite_t *spr)
// more realistique corona ! // more realistique corona !
if (cz >= 255*8+250) if (cz >= 255*8+250)
return; return;
Surf.FlatColor.rgba = p_lspr->corona_color; Surf.PolyColor.rgba = p_lspr->corona_color;
if (cz > 250.0f) if (cz > 250.0f)
Surf.FlatColor.s.alpha = 0xff-((int)cz-250)/8; Surf.PolyColor.s.alpha = 0xff-((int)cz-250)/8;
else else
Surf.FlatColor.s.alpha = 0xff; Surf.PolyColor.s.alpha = 0xff;
// do not be hide by sprite of the light itself ! // do not be hide by sprite of the light itself !
cz = cz - 2.0f; cz = cz - 2.0f;
@ -1043,19 +1037,19 @@ void HWR_DoCoronasLighting(FOutVector *outVerts, gr_vissprite_t *spr)
// car comme l'offset est minime sa ce voit pas ! // car comme l'offset est minime sa ce voit pas !
light[0].x = cx-size; light[0].z = cz; light[0].x = cx-size; light[0].z = cz;
light[0].y = cy-size*1.33f+p_lspr->light_yoffset; light[0].y = cy-size*1.33f+p_lspr->light_yoffset;
light[0].sow = 0.0f; light[0].tow = 0.0f; light[0].s = 0.0f; light[0].t = 0.0f;
light[1].x = cx+size; light[1].z = cz; light[1].x = cx+size; light[1].z = cz;
light[1].y = cy-size*1.33f+p_lspr->light_yoffset; light[1].y = cy-size*1.33f+p_lspr->light_yoffset;
light[1].sow = 1.0f; light[1].tow = 0.0f; light[1].s = 1.0f; light[1].t = 0.0f;
light[2].x = cx+size; light[2].z = cz; light[2].x = cx+size; light[2].z = cz;
light[2].y = cy+size*1.33f+p_lspr->light_yoffset; light[2].y = cy+size*1.33f+p_lspr->light_yoffset;
light[2].sow = 1.0f; light[2].tow = 1.0f; light[2].s = 1.0f; light[2].t = 1.0f;
light[3].x = cx-size; light[3].z = cz; light[3].x = cx-size; light[3].z = cz;
light[3].y = cy+size*1.33f+p_lspr->light_yoffset; light[3].y = cy+size*1.33f+p_lspr->light_yoffset;
light[3].sow = 0.0f; light[3].tow = 1.0f; light[3].s = 0.0f; light[3].t = 1.0f;
HWR_GetPic(coronalumpnum); /// \todo use different coronas HWR_GetPic(coronalumpnum); /// \todo use different coronas
@ -1101,11 +1095,11 @@ void HWR_DrawCoronas(void)
// more realistique corona ! // more realistique corona !
if (cz >= 255*8+250) if (cz >= 255*8+250)
continue; continue;
Surf.FlatColor.rgba = p_lspr->corona_color; Surf.PolyColor.rgba = p_lspr->corona_color;
if (cz > 250.0f) if (cz > 250.0f)
Surf.FlatColor.s.alpha = (UINT8)(0xff-(UINT8)(((int)cz-250)/8)); Surf.PolyColor.s.alpha = (UINT8)(0xff-(UINT8)(((int)cz-250)/8));
else else
Surf.FlatColor.s.alpha = 0xff; Surf.PolyColor.s.alpha = 0xff;
switch (p_lspr->type) switch (p_lspr->type)
{ {
@ -1113,7 +1107,7 @@ void HWR_DrawCoronas(void)
size = p_lspr->corona_radius * ((cz+120.0f)/950.0f); // d'ou vienne ces constante ? size = p_lspr->corona_radius * ((cz+120.0f)/950.0f); // d'ou vienne ces constante ?
break; break;
case ROCKET_SPR: case ROCKET_SPR:
Surf.FlatColor.s.alpha = (UINT8)((M_RandomByte()>>1)&0xff); Surf.PolyColor.s.alpha = (UINT8)((M_RandomByte()>>1)&0xff);
// don't need a break // don't need a break
case CORONA_SPR: case CORONA_SPR:
size = p_lspr->corona_radius * ((cz+60.0f)/100.0f); // d'ou vienne ces constante ? size = p_lspr->corona_radius * ((cz+60.0f)/100.0f); // d'ou vienne ces constante ?
@ -1133,19 +1127,19 @@ void HWR_DrawCoronas(void)
light[0].x = cx-size; light[0].z = cz; light[0].x = cx-size; light[0].z = cz;
light[0].y = cy-size*1.33f; light[0].y = cy-size*1.33f;
light[0].sow = 0.0f; light[0].tow = 0.0f; light[0].s = 0.0f; light[0].t = 0.0f;
light[1].x = cx+size; light[1].z = cz; light[1].x = cx+size; light[1].z = cz;
light[1].y = cy-size*1.33f; light[1].y = cy-size*1.33f;
light[1].sow = 1.0f; light[1].tow = 0.0f; light[1].s = 1.0f; light[1].t = 0.0f;
light[2].x = cx+size; light[2].z = cz; light[2].x = cx+size; light[2].z = cz;
light[2].y = cy+size*1.33f; light[2].y = cy+size*1.33f;
light[2].sow = 1.0f; light[2].tow = 1.0f; light[2].s = 1.0f; light[2].t = 1.0f;
light[3].x = cx-size; light[3].z = cz; light[3].x = cx-size; light[3].z = cz;
light[3].y = cy+size*1.33f; light[3].y = cy+size*1.33f;
light[3].sow = 0.0f; light[3].tow = 1.0f; light[3].s = 0.0f; light[3].t = 1.0f;
HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_Additive | PF_Clip | PF_NoDepthTest | PF_Corona); HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_Additive | PF_Clip | PF_NoDepthTest | PF_Corona);
} }
@ -1254,11 +1248,6 @@ static void HWR_SetLight(void)
lightmappatch.height = 128; lightmappatch.height = 128;
lightmappatch.mipmap->width = 128; lightmappatch.mipmap->width = 128;
lightmappatch.mipmap->height = 128; lightmappatch.mipmap->height = 128;
#ifdef GLIDE_API_COMPATIBILITY
lightmappatch.mipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_128;
lightmappatch.mipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_128;
lightmappatch.mipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
#endif
lightmappatch.mipmap->flags = 0; //TF_WRAPXY; // DEBUG: view the overdraw ! lightmappatch.mipmap->flags = 0; //TF_WRAPXY; // DEBUG: view the overdraw !
} }
HWD.pfnSetTexture(lightmappatch.mipmap); HWD.pfnSetTexture(lightmappatch.mipmap);

View file

@ -1,19 +1,13 @@
// Emacs style mode select -*- C++ -*- // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2020 by Sonic Team Junior.
// //
// This program is free software; you can redistribute it and/or // This program is free software distributed under the
// modify it under the terms of the GNU General Public License // terms of the GNU General Public License, version 2.
// as published by the Free Software Foundation; either version 2 // See the 'LICENSE' file for more details.
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/// \file /// \file hw_light.h
/// \brief Dynamic lighting & coronas add on by Hurdler /// \brief Dynamic lighting & coronas add on by Hurdler
#ifndef _HW_LIGHTS_ #ifndef _HW_LIGHTS_

File diff suppressed because it is too large Load diff

View file

@ -1,20 +1,13 @@
// Emacs style mode select -*- C++ -*- // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2020 by Sonic Team Junior.
// //
// This program is free software; you can redistribute it and/or // This program is free software distributed under the
// modify it under the terms of the GNU General Public License // terms of the GNU General Public License, version 2.
// as published by the Free Software Foundation; either version 2 // See the 'LICENSE' file for more details.
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/// \file /// \file hw_main.h
/// \brief 3D render mode functions /// \brief 3D render mode functions
#ifndef __HWR_MAIN_H__ #ifndef __HWR_MAIN_H__
@ -73,8 +66,11 @@ void HWR_MakeScreenFinalTexture(void);
void HWR_DrawScreenFinalTexture(int width, int height); void HWR_DrawScreenFinalTexture(int width, int height);
// This stuff is put here so MD2's can use them // This stuff is put here so MD2's can use them
UINT32 HWR_Lighting(INT32 light, UINT32 color, UINT32 fadecolor, boolean fogblockpoly, boolean plane); void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap);
FUNCMATH UINT8 LightLevelToLum(INT32 l); UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap); // Let's see if this can work
void HWR_ReadShaders(UINT16 wadnum, boolean PK3);
boolean HWR_LoadShaders(void);
extern CV_PossibleValue_t granisotropicmode_cons_t[]; extern CV_PossibleValue_t granisotropicmode_cons_t[];
@ -84,21 +80,23 @@ extern consvar_t cv_grstaticlighting;
extern consvar_t cv_grcoronas; extern consvar_t cv_grcoronas;
extern consvar_t cv_grcoronasize; extern consvar_t cv_grcoronasize;
#endif #endif
extern consvar_t cv_grshaders;
extern consvar_t cv_grmodels; extern consvar_t cv_grmodels;
extern consvar_t cv_grmodelinterpolation; extern consvar_t cv_grmodelinterpolation;
extern consvar_t cv_grmodellighting; extern consvar_t cv_grmodellighting;
extern consvar_t cv_grfog;
extern consvar_t cv_grfogcolor;
extern consvar_t cv_grfogdensity;
extern consvar_t cv_grsoftwarefog;
extern consvar_t cv_grfiltermode; extern consvar_t cv_grfiltermode;
extern consvar_t cv_granisotropicmode; extern consvar_t cv_granisotropicmode;
extern consvar_t cv_grcorrecttricks; extern consvar_t cv_grcorrecttricks;
extern consvar_t cv_fovchange; extern consvar_t cv_fovchange;
extern consvar_t cv_grsolvetjoin; extern consvar_t cv_grsolvetjoin;
extern consvar_t cv_grshearing;
extern consvar_t cv_grspritebillboarding; extern consvar_t cv_grspritebillboarding;
extern consvar_t cv_grskydome; extern consvar_t cv_grskydome;
extern consvar_t cv_grfakecontrast; extern consvar_t cv_grfakecontrast;
extern consvar_t cv_grslopecontrast;
extern consvar_t cv_grbatching;
extern float gr_viewwidth, gr_viewheight, gr_baseviewwindowy; extern float gr_viewwidth, gr_viewheight, gr_baseviewwindowy;
@ -108,4 +106,24 @@ extern float gr_viewwindowx, gr_basewindowcentery;
extern fixed_t *hwbbox; extern fixed_t *hwbbox;
extern FTransform atransform; extern FTransform atransform;
// Render stats
extern int rs_hw_nodesorttime;
extern int rs_hw_nodedrawtime;
extern int rs_hw_spritesorttime;
extern int rs_hw_spritedrawtime;
// Render stats for batching
extern int rs_hw_numpolys;
extern int rs_hw_numverts;
extern int rs_hw_numcalls;
extern int rs_hw_numshaders;
extern int rs_hw_numtextures;
extern int rs_hw_numpolyflags;
extern int rs_hw_numcolors;
extern int rs_hw_batchsorttime;
extern int rs_hw_batchdrawtime;
extern boolean gr_shadersavailable;
#endif #endif

View file

@ -1,23 +1,16 @@
// Emacs style mode select -*- C++ -*- // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2020 by Sonic Team Junior.
// //
// This program is free software; you can redistribute it and/or // This program is free software distributed under the
// modify it under the terms of the GNU General Public License // terms of the GNU General Public License, version 2.
// as published by the Free Software Foundation; either version 2 // See the 'LICENSE' file for more details.
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/// \file /// \file hw_md2.c
/// \brief MD2 Handling /// \brief 3D Model Handling
/// Inspired from md2.c by Mete Ciragan (mete@swissquake.ch) /// Inspired from md2.c by Mete Ciragan (mete@swissquake.ch)
#ifdef __GNUC__ #ifdef __GNUC__
#include <unistd.h> #include <unistd.h>
#endif #endif
@ -382,7 +375,10 @@ static void md2_loadTexture(md2_t *model)
#endif #endif
grpatch->mipmap->grInfo.format = PCX_Load(filename, &w, &h, grpatch); grpatch->mipmap->grInfo.format = PCX_Load(filename, &w, &h, grpatch);
if (grpatch->mipmap->grInfo.format == 0) if (grpatch->mipmap->grInfo.format == 0)
{
model->notexturefile = true; // mark it so its not searched for again repeatedly
return; return;
}
grpatch->mipmap->downloaded = 0; grpatch->mipmap->downloaded = 0;
grpatch->mipmap->flags = 0; grpatch->mipmap->flags = 0;
@ -400,13 +396,6 @@ static void md2_loadTexture(md2_t *model)
V_CubeApply(&image->s.red, &image->s.green, &image->s.blue); V_CubeApply(&image->s.red, &image->s.green, &image->s.blue);
image++; image++;
} }
#ifdef GLIDE_API_COMPATIBILITY
// not correct!
grpatch->mipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_256;
grpatch->mipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_256;
grpatch->mipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
#endif
} }
HWD.pfnSetTexture(grpatch->mipmap); HWD.pfnSetTexture(grpatch->mipmap);
} }
@ -444,6 +433,7 @@ static void md2_loadBlendTexture(md2_t *model)
grpatch->mipmap->grInfo.format = PCX_Load(filename, &w, &h, grpatch); grpatch->mipmap->grInfo.format = PCX_Load(filename, &w, &h, grpatch);
if (grpatch->mipmap->grInfo.format == 0) if (grpatch->mipmap->grInfo.format == 0)
{ {
model->noblendfile = true; // mark it so its not searched for again repeatedly
Z_Free(filename); Z_Free(filename);
return; return;
} }
@ -455,13 +445,6 @@ static void md2_loadBlendTexture(md2_t *model)
grpatch->height = (INT16)h; grpatch->height = (INT16)h;
grpatch->mipmap->width = (UINT16)w; grpatch->mipmap->width = (UINT16)w;
grpatch->mipmap->height = (UINT16)h; grpatch->mipmap->height = (UINT16)h;
#ifdef GLIDE_API_COMPATIBILITY
// not correct!
grpatch->mipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_256;
grpatch->mipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_256;
grpatch->mipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
#endif
} }
HWD.pfnSetTexture(grpatch->mipmap); // We do need to do this so that it can be cleared and knows to recreate it when necessary HWD.pfnSetTexture(grpatch->mipmap); // We do need to do this so that it can be cleared and knows to recreate it when necessary
@ -486,6 +469,8 @@ void HWR_InitModels(void)
md2_playermodels[s].scale = -1.0f; md2_playermodels[s].scale = -1.0f;
md2_playermodels[s].model = NULL; md2_playermodels[s].model = NULL;
md2_playermodels[s].grpatch = NULL; md2_playermodels[s].grpatch = NULL;
md2_playermodels[s].notexturefile = false;
md2_playermodels[s].noblendfile = false;
md2_playermodels[s].skin = -1; md2_playermodels[s].skin = -1;
md2_playermodels[s].notfound = true; md2_playermodels[s].notfound = true;
md2_playermodels[s].error = false; md2_playermodels[s].error = false;
@ -495,6 +480,8 @@ void HWR_InitModels(void)
md2_models[i].scale = -1.0f; md2_models[i].scale = -1.0f;
md2_models[i].model = NULL; md2_models[i].model = NULL;
md2_models[i].grpatch = NULL; md2_models[i].grpatch = NULL;
md2_models[i].notexturefile = false;
md2_models[i].noblendfile = false;
md2_models[i].skin = -1; md2_models[i].skin = -1;
md2_models[i].notfound = true; md2_models[i].notfound = true;
md2_models[i].error = false; md2_models[i].error = false;
@ -949,11 +936,19 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch,
blendcolor = V_GetColor(translation[firsti]); blendcolor = V_GetColor(translation[firsti]);
if (secondi >= translen)
mul = 0;
if (mul > 0) // If it's 0, then we only need the first color. if (mul > 0) // If it's 0, then we only need the first color.
{ {
if (secondi >= translen) // blend to black #if 0
if (secondi >= translen)
{
// blend to black
nextcolor = V_GetColor(31); nextcolor = V_GetColor(31);
}
else else
#endif
nextcolor = V_GetColor(translation[secondi]); nextcolor = V_GetColor(translation[secondi]);
// Find difference between points // Find difference between points
@ -1188,15 +1183,14 @@ static UINT8 HWR_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t
boolean HWR_DrawModel(gr_vissprite_t *spr) boolean HWR_DrawModel(gr_vissprite_t *spr)
{ {
FSurfaceInfo Surf; md2_t *md2;
char filename[64]; char filename[64];
INT32 frame = 0; INT32 frame = 0;
INT32 nextFrame = -1; INT32 nextFrame = -1;
UINT8 spr2 = 0; UINT8 spr2 = 0;
FTransform p; FTransform p;
md2_t *md2; FSurfaceInfo Surf;
UINT8 color[4];
if (!cv_grmodels.value) if (!cv_grmodels.value)
return false; return false;
@ -1235,13 +1229,10 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
colormap = sector->extra_colormap; colormap = sector->extra_colormap;
} }
if (colormap) HWR_Lighting(&Surf, lightlevel, colormap);
Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false);
else
Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false);
} }
else else
Surf.FlatColor.rgba = 0xFFFFFFFF; Surf.PolyColor.rgba = 0xFFFFFFFF;
// Look at HWR_ProjectSprite for more // Look at HWR_ProjectSprite for more
{ {
@ -1251,6 +1242,7 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
//mdlframe_t *next = NULL; //mdlframe_t *next = NULL;
const boolean papersprite = (spr->mobj->frame & FF_PAPERSPRITE); const boolean papersprite = (spr->mobj->frame & FF_PAPERSPRITE);
const UINT8 flip = (UINT8)(!(spr->mobj->eflags & MFE_VERTICALFLIP) != !(spr->mobj->frame & FF_VERTICALFLIP)); const UINT8 flip = (UINT8)(!(spr->mobj->eflags & MFE_VERTICALFLIP) != !(spr->mobj->frame & FF_VERTICALFLIP));
const UINT8 hflip = (UINT8)(!(spr->mobj->mirrored) != !(spr->mobj->frame & FF_HORIZONTALFLIP));
spritedef_t *sprdef; spritedef_t *sprdef;
spriteframe_t *sprframe; spriteframe_t *sprframe;
spriteinfo_t *sprinfo; spriteinfo_t *sprinfo;
@ -1263,11 +1255,11 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
//durs = tics; //durs = tics;
if (spr->mobj->flags2 & MF2_SHADOW) if (spr->mobj->flags2 & MF2_SHADOW)
Surf.FlatColor.s.alpha = 0x40; Surf.PolyColor.s.alpha = 0x40;
else if (spr->mobj->frame & FF_TRANSMASK) else if (spr->mobj->frame & FF_TRANSMASK)
HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf); HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf);
else else
Surf.FlatColor.s.alpha = 0xFF; Surf.PolyColor.s.alpha = 0xFF;
// dont forget to enabled the depth test because we can't do this like // dont forget to enabled the depth test because we can't do this like
// before: polygons models are not sorted // before: polygons models are not sorted
@ -1315,12 +1307,14 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
finalscale = md2->scale; finalscale = md2->scale;
//Hurdler: arf, I don't like that implementation at all... too much crappy //Hurdler: arf, I don't like that implementation at all... too much crappy
gpatch = md2->grpatch; gpatch = md2->grpatch;
if (!gpatch || !gpatch->mipmap->grInfo.format || !gpatch->mipmap->downloaded) if (!gpatch || ((!gpatch->mipmap->grInfo.format || !gpatch->mipmap->downloaded) && !md2->notexturefile))
md2_loadTexture(md2); md2_loadTexture(md2);
gpatch = md2->grpatch; // Load it again, because it isn't being loaded into gpatch after md2_loadtexture... gpatch = md2->grpatch; // Load it again, because it isn't being loaded into gpatch after md2_loadtexture...
if ((gpatch && gpatch->mipmap->grInfo.format) // don't load the blend texture if the base texture isn't available if ((gpatch && gpatch->mipmap->grInfo.format) // don't load the blend texture if the base texture isn't available
&& (!md2->blendgrpatch || !((GLPatch_t *)md2->blendgrpatch)->mipmap->grInfo.format || !((GLPatch_t *)md2->blendgrpatch)->mipmap->downloaded)) && (!md2->blendgrpatch
|| ((!((GLPatch_t *)md2->blendgrpatch)->mipmap->grInfo.format || !((GLPatch_t *)md2->blendgrpatch)->mipmap->downloaded)
&& !md2->noblendfile)))
md2_loadBlendTexture(md2); md2_loadBlendTexture(md2);
if (gpatch && gpatch->mipmap->grInfo.format) // else if meant that if a texture couldn't be loaded, it would just end up using something else's texture if (gpatch && gpatch->mipmap->grInfo.format) // else if meant that if a texture couldn't be loaded, it would just end up using something else's texture
@ -1512,11 +1506,6 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
} }
#endif #endif
color[0] = Surf.FlatColor.s.red;
color[1] = Surf.FlatColor.s.green;
color[2] = Surf.FlatColor.s.blue;
color[3] = Surf.FlatColor.s.alpha;
// SRB2CBTODO: MD2 scaling support // SRB2CBTODO: MD2 scaling support
finalscale *= FIXED_TO_FLOAT(spr->mobj->scale); finalscale *= FIXED_TO_FLOAT(spr->mobj->scale);
@ -1525,7 +1514,8 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
p.mirror = atransform.mirror; // from Kart p.mirror = atransform.mirror; // from Kart
#endif #endif
HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, color); HWD.pfnSetShader(4); // model shader
HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, hflip, &Surf);
} }
return true; return true;

View file

@ -1,21 +1,14 @@
// Emacs style mode select -*- C++ -*- // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2020 by Sonic Team Junior.
// //
// This program is free software; you can redistribute it and/or // This program is free software distributed under the
// modify it under the terms of the GNU General Public License // terms of the GNU General Public License, version 2.
// as published by the Free Software Foundation; either version 2 // See the 'LICENSE' file for more details.
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/// \file /// \file hw_md2.h
/// \brief MD2 Handling /// \brief 3D Model Handling
/// Inspired from md2.h by Mete Ciragan (mete@swissquake.ch) /// Inspired from md2.h by Mete Ciragan (mete@swissquake.ch)
#ifndef _HW_MD2_H_ #ifndef _HW_MD2_H_
@ -35,7 +28,9 @@ typedef struct
float offset; float offset;
model_t *model; model_t *model;
void *grpatch; void *grpatch;
boolean notexturefile; // true if texture file was not found
void *blendgrpatch; void *blendgrpatch;
boolean noblendfile; // true if blend texture file was not found
boolean notfound; boolean notfound;
INT32 skin; INT32 skin;
boolean error; boolean error;

View file

@ -1,19 +1,12 @@
// Emacs style mode select -*- C++ -*- // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 2005 by Sonic Team Junior.
// //
// Copyright (C) 2005 by SRB2 Jr. Team. // This program is free software distributed under the
// // terms of the GNU General Public License, version 2.
// This program is free software; you can redistribute it and/or // See the 'LICENSE' file for more details.
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/// \file /// \file hws_data.h
/// \brief 3D sound definitions /// \brief 3D sound definitions
#ifndef __HWS_DATA_H__ #ifndef __HWS_DATA_H__

View file

@ -206,7 +206,7 @@ int SetupPixelFormat(INT32 WantColorBits, INT32 WantStencilBits, INT32 WantDepth
if (iLastPFD) if (iLastPFD)
{ {
DBG_Printf("WARNING : SetPixelFormat() called twise not supported by all drivers !\n"); GL_DBG_Printf("WARNING : SetPixelFormat() called twise not supported by all drivers !\n");
} }
// set the pixel format only if different than the current // set the pixel format only if different than the current
@ -215,17 +215,17 @@ int SetupPixelFormat(INT32 WantColorBits, INT32 WantStencilBits, INT32 WantDepth
else else
iLastPFD = iPFD; iLastPFD = iPFD;
DBG_Printf("SetupPixelFormat() - %d ColorBits - %d StencilBits - %d DepthBits\n", GL_DBG_Printf("SetupPixelFormat() - %d ColorBits - %d StencilBits - %d DepthBits\n",
WantColorBits, WantStencilBits, WantDepthBits); WantColorBits, WantStencilBits, WantDepthBits);
nPixelFormat = ChoosePixelFormat(hDC, &pfd); nPixelFormat = ChoosePixelFormat(hDC, &pfd);
if (nPixelFormat == 0) if (nPixelFormat == 0)
DBG_Printf("ChoosePixelFormat() FAILED\n"); GL_DBG_Printf("ChoosePixelFormat() FAILED\n");
if (SetPixelFormat(hDC, nPixelFormat, &pfd) == 0) if (SetPixelFormat(hDC, nPixelFormat, &pfd) == 0)
{ {
DBG_Printf("SetPixelFormat() FAILED\n"); GL_DBG_Printf("SetPixelFormat() FAILED\n");
return 0; return 0;
} }
@ -243,7 +243,7 @@ static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode)
BOOL WantFullScreen = !(lvid->u.windowed); //(lvid->u.windowed ? 0 : CDS_FULLSCREEN); BOOL WantFullScreen = !(lvid->u.windowed); //(lvid->u.windowed ? 0 : CDS_FULLSCREEN);
UNREFERENCED_PARAMETER(pcurrentmode); UNREFERENCED_PARAMETER(pcurrentmode);
DBG_Printf ("SetMode(): %dx%d %d bits (%s)\n", GL_DBG_Printf ("SetMode(): %dx%d %d bits (%s)\n",
lvid->width, lvid->height, lvid->bpp*8, lvid->width, lvid->height, lvid->bpp*8,
WantFullScreen ? "fullscreen" : "windowed"); WantFullScreen ? "fullscreen" : "windowed");
@ -301,7 +301,7 @@ static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode)
hDC = GetDC(hWnd); hDC = GetDC(hWnd);
if (!hDC) if (!hDC)
{ {
DBG_Printf("GetDC() FAILED\n"); GL_DBG_Printf("GetDC() FAILED\n");
return 0; return 0;
} }
@ -321,12 +321,12 @@ static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode)
hGLRC = pwglCreateContext(hDC); hGLRC = pwglCreateContext(hDC);
if (!hGLRC) if (!hGLRC)
{ {
DBG_Printf("pwglCreateContext() FAILED\n"); GL_DBG_Printf("pwglCreateContext() FAILED\n");
return 0; return 0;
} }
if (!pwglMakeCurrent(hDC, hGLRC)) if (!pwglMakeCurrent(hDC, hGLRC))
{ {
DBG_Printf("wglMakeCurrent() FAILED\n"); GL_DBG_Printf("wglMakeCurrent() FAILED\n");
return 0; return 0;
} }
} }
@ -337,15 +337,15 @@ static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode)
//BP: why don't we make it earlier ? //BP: why don't we make it earlier ?
//Hurdler: we cannot do that before intialising gl context //Hurdler: we cannot do that before intialising gl context
renderer = (LPCSTR)pglGetString(GL_RENDERER); renderer = (LPCSTR)pglGetString(GL_RENDERER);
DBG_Printf("Vendor : %s\n", pglGetString(GL_VENDOR)); GL_DBG_Printf("Vendor : %s\n", pglGetString(GL_VENDOR));
DBG_Printf("Renderer : %s\n", renderer); GL_DBG_Printf("Renderer : %s\n", renderer);
DBG_Printf("Version : %s\n", pglGetString(GL_VERSION)); GL_DBG_Printf("Version : %s\n", pglGetString(GL_VERSION));
DBG_Printf("Extensions : %s\n", gl_extensions); GL_DBG_Printf("Extensions : %s\n", gl_extensions);
// BP: disable advenced feature that don't work on somes hardware // BP: disable advenced feature that don't work on somes hardware
// Hurdler: Now works on G400 with bios 1.6 and certified drivers 6.04 // Hurdler: Now works on G400 with bios 1.6 and certified drivers 6.04
if (strstr(renderer, "810")) oglflags |= GLF_NOZBUFREAD; if (strstr(renderer, "810")) oglflags |= GLF_NOZBUFREAD;
DBG_Printf("oglflags : 0x%X\n", oglflags); GL_DBG_Printf("oglflags : 0x%X\n", oglflags);
#ifdef USE_WGL_SWAP #ifdef USE_WGL_SWAP
if (isExtAvailable("WGL_EXT_swap_control",gl_extensions)) if (isExtAvailable("WGL_EXT_swap_control",gl_extensions))
@ -386,7 +386,7 @@ static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode)
// -----------------+ // -----------------+
static void UnSetRes(void) static void UnSetRes(void)
{ {
DBG_Printf("UnSetRes()\n"); GL_DBG_Printf("UnSetRes()\n");
pwglMakeCurrent(hDC, NULL); pwglMakeCurrent(hDC, NULL);
pwglDeleteContext(hGLRC); pwglDeleteContext(hGLRC);
@ -437,7 +437,7 @@ EXPORT void HWRAPI(GetModeList) (vmode_t** pvidmodes, INT32 *numvidmodes)
video_modes[iMode].misc = 0; video_modes[iMode].misc = 0;
video_modes[iMode].name = malloc(12 * sizeof (CHAR)); video_modes[iMode].name = malloc(12 * sizeof (CHAR));
sprintf(video_modes[iMode].name, "%dx%d", (INT32)Tmp.dmPelsWidth, (INT32)Tmp.dmPelsHeight); sprintf(video_modes[iMode].name, "%dx%d", (INT32)Tmp.dmPelsWidth, (INT32)Tmp.dmPelsHeight);
DBG_Printf ("Mode: %s\n", video_modes[iMode].name); GL_DBG_Printf ("Mode: %s\n", video_modes[iMode].name);
video_modes[iMode].width = Tmp.dmPelsWidth; video_modes[iMode].width = Tmp.dmPelsWidth;
video_modes[iMode].height = Tmp.dmPelsHeight; video_modes[iMode].height = Tmp.dmPelsHeight;
video_modes[iMode].bytesperpixel = Tmp.dmBitsPerPel/8; video_modes[iMode].bytesperpixel = Tmp.dmBitsPerPel/8;
@ -474,7 +474,7 @@ EXPORT void HWRAPI(GetModeList) (vmode_t** pvidmodes, INT32 *numvidmodes)
HDC bpphdc; HDC bpphdc;
INT32 iBitsPerPel; INT32 iBitsPerPel;
DBG_Printf ("HWRAPI GetModeList()\n"); GL_DBG_Printf ("HWRAPI GetModeList()\n");
bpphdc = GetDC(NULL); // on obtient le bpp actuel bpphdc = GetDC(NULL); // on obtient le bpp actuel
iBitsPerPel = GetDeviceCaps(bpphdc, BITSPIXEL); iBitsPerPel = GetDeviceCaps(bpphdc, BITSPIXEL);
@ -490,7 +490,7 @@ EXPORT void HWRAPI(GetModeList) (vmode_t** pvidmodes, INT32 *numvidmodes)
video_modes[i].misc = 0; video_modes[i].misc = 0;
video_modes[i].name = malloc(12 * sizeof (CHAR)); video_modes[i].name = malloc(12 * sizeof (CHAR));
sprintf(video_modes[i].name, "%dx%d", res[i][0], res[i][1]); sprintf(video_modes[i].name, "%dx%d", res[i][0], res[i][1]);
DBG_Printf ("Mode: %s\n", video_modes[i].name); GL_DBG_Printf ("Mode: %s\n", video_modes[i].name);
video_modes[i].width = res[i][0]; video_modes[i].width = res[i][0];
video_modes[i].height = res[i][1]; video_modes[i].height = res[i][1];
video_modes[i].bytesperpixel = iBitsPerPel/8; video_modes[i].bytesperpixel = iBitsPerPel/8;
@ -511,9 +511,9 @@ EXPORT void HWRAPI(Shutdown) (void)
#ifdef DEBUG_TO_FILE #ifdef DEBUG_TO_FILE
long nb_centiemes; long nb_centiemes;
DBG_Printf ("HWRAPI Shutdown()\n"); GL_DBG_Printf ("HWRAPI Shutdown()\n");
nb_centiemes = ((clock()-my_clock)*100)/CLOCKS_PER_SEC; nb_centiemes = ((clock()-my_clock)*100)/CLOCKS_PER_SEC;
DBG_Printf("Nb frames: %li; Nb sec: %2.2f -> %2.1f fps\n", GL_DBG_Printf("Nb frames: %li; Nb sec: %2.2f -> %2.1f fps\n",
nb_frames, nb_centiemes/100.0f, (100*nb_frames)/(double)nb_centiemes); nb_frames, nb_centiemes/100.0f, (100*nb_frames)/(double)nb_centiemes);
#endif #endif
@ -530,7 +530,7 @@ EXPORT void HWRAPI(Shutdown) (void)
} }
FreeLibrary(GLU32); FreeLibrary(GLU32);
FreeLibrary(OGL32); FreeLibrary(OGL32);
DBG_Printf ("HWRAPI Shutdown(DONE)\n"); GL_DBG_Printf ("HWRAPI Shutdown(DONE)\n");
} }
// -----------------+ // -----------------+
@ -543,7 +543,7 @@ EXPORT void HWRAPI(FinishUpdate) (INT32 waitvbl)
#else #else
UNREFERENCED_PARAMETER(waitvbl); UNREFERENCED_PARAMETER(waitvbl);
#endif #endif
// DBG_Printf ("FinishUpdate()\n"); // GL_DBG_Printf ("FinishUpdate()\n");
#ifdef DEBUG_TO_FILE #ifdef DEBUG_TO_FILE
if ((++nb_frames)==2) // on ne commence pas <20> la premi<6D>re frame if ((++nb_frames)==2) // on ne commence pas <20> la premi<6D>re frame
my_clock = clock(); my_clock = clock();

File diff suppressed because it is too large Load diff

View file

@ -70,10 +70,6 @@
extern FILE *gllogstream; extern FILE *gllogstream;
#endif #endif
#ifndef DRIVER_STRING
#define DRIVER_STRING "HWRAPI Init(): SRB2 OpenGL renderer" // Tails
#endif
// ========================================================================== // ==========================================================================
// PROTOS // PROTOS
// ========================================================================== // ==========================================================================
@ -81,13 +77,11 @@ extern FILE *gllogstream;
boolean LoadGL(void); boolean LoadGL(void);
void *GetGLFunc(const char *proc); void *GetGLFunc(const char *proc);
boolean SetupGLfunc(void); boolean SetupGLfunc(void);
boolean SetupGLFunc13(void); void SetupGLFunc4(void);
void Flush(void); void Flush(void);
INT32 isExtAvailable(const char *extension, const GLubyte *start); INT32 isExtAvailable(const char *extension, const GLubyte *start);
int SetupPixelFormat(INT32 WantColorBits, INT32 WantStencilBits, INT32 WantDepthBits);
void SetModelView(GLint w, GLint h); void SetModelView(GLint w, GLint h);
void SetStates(void); void SetStates(void);
FUNCMATH float byteasfloat(UINT8 fbyte);
#ifndef GL_EXT_texture_filter_anisotropic #ifndef GL_EXT_texture_filter_anisotropic
#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE #define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
@ -123,7 +117,10 @@ static PFNglEnableClientState pglEnableClientState;
// GLOBAL // GLOBAL
// ========================================================================== // ==========================================================================
extern const GLubyte *gl_version;
extern const GLubyte *gl_renderer;
extern const GLubyte *gl_extensions; extern const GLubyte *gl_extensions;
extern RGBA_t myPaletteData[]; extern RGBA_t myPaletteData[];
extern GLint screen_width; extern GLint screen_width;
extern GLint screen_height; extern GLint screen_height;

View file

@ -2102,7 +2102,7 @@ void HU_Drawer(void)
{ {
if (LUA_HudEnabled(hud_rankings)) if (LUA_HudEnabled(hud_rankings))
HU_DrawRankings(); HU_DrawRankings();
if (gametype == GT_COOP) if (gametyperules & GTR_CAMPAIGN)
HU_DrawNetplayCoopOverlay(); HU_DrawNetplayCoopOverlay();
} }
else else

View file

@ -46,6 +46,8 @@ UINT32 I_GetFreeMem(UINT32 *total);
*/ */
tic_t I_GetTime(void); tic_t I_GetTime(void);
int I_GetTimeMicros(void);// provides microsecond counter for render stats
/** \brief The I_Sleep function /** \brief The I_Sleep function
\return void \return void

View file

@ -1430,11 +1430,13 @@ state_t states[NUMSTATES] =
{SPR_FANG, 8, 0, {A_PrepareRepeat}, 1, 0, S_FANG_PINCHPATHINGSTART2}, // S_FANG_PINCHPATHINGSTART1 {SPR_FANG, 8, 0, {A_PrepareRepeat}, 1, 0, S_FANG_PINCHPATHINGSTART2}, // S_FANG_PINCHPATHINGSTART1
{SPR_FANG, 8, 0, {A_PlayActiveSound}, 0, 0, S_FANG_PINCHPATHING}, // S_FANG_PINCHPATHINGSTART2 {SPR_FANG, 8, 0, {A_PlayActiveSound}, 0, 0, S_FANG_PINCHPATHING}, // S_FANG_PINCHPATHINGSTART2
{SPR_FANG, 8, 0, {A_Boss5FindWaypoint}, 1, 0, S_FANG_PINCHBOUNCE1}, // S_FANG_PINCHPATHING {SPR_FANG, 8, 0, {A_Boss5FindWaypoint}, 1, 0, S_FANG_PINCHBOUNCE0}, // S_FANG_PINCHPATHING
{SPR_FANG, 8, 0, {A_SetObjectFlags}, MF_NOCLIP|MF_NOCLIPHEIGHT, 2, S_FANG_PINCHBOUNCE1}, // S_FANG_PINCHBOUNCE0
{SPR_FANG, 8, 2, {A_Thrust}, 0, 1, S_FANG_PINCHBOUNCE2}, // S_FANG_PINCHBOUNCE1 {SPR_FANG, 8, 2, {A_Thrust}, 0, 1, S_FANG_PINCHBOUNCE2}, // S_FANG_PINCHBOUNCE1
{SPR_FANG, 9, 2, {NULL}, 0, 0, S_FANG_PINCHBOUNCE3}, // S_FANG_PINCHBOUNCE2 {SPR_FANG, 9, 2, {NULL}, 0, 0, S_FANG_PINCHBOUNCE3}, // S_FANG_PINCHBOUNCE2
{SPR_FANG, 10, 2, {A_Boss5Jump}, 0, 0, S_FANG_PINCHBOUNCE4}, // S_FANG_PINCHBOUNCE3 {SPR_FANG, 10, 2, {A_Boss5Jump}, 0, 0, S_FANG_PINCHBOUNCE4}, // S_FANG_PINCHBOUNCE3
{SPR_FANG, 10, 1, {A_Boss5CheckFalling}, S_FANG_PINCHSKID1, S_FANG_PINCHFALL1, S_FANG_PINCHBOUNCE4}, // S_FANG_PINCHBOUNCE4 {SPR_FANG, 10, 1, {A_Boss5CheckFalling}, S_FANG_PINCHSKID1, S_FANG_PINCHFALL0, S_FANG_PINCHBOUNCE4}, // S_FANG_PINCHBOUNCE4
{SPR_FANG, 12, 0, {A_SetObjectFlags}, MF_NOCLIP|MF_NOCLIPHEIGHT, 1, S_FANG_PINCHFALL1}, // S_FANG_PINCHFALL0
{SPR_FANG, 12, 1, {A_Boss5CheckOnGround}, S_FANG_PINCHSKID1, 0, S_FANG_PINCHFALL2}, // S_FANG_PINCHFALL1 {SPR_FANG, 12, 1, {A_Boss5CheckOnGround}, S_FANG_PINCHSKID1, 0, S_FANG_PINCHFALL2}, // S_FANG_PINCHFALL1
{SPR_FANG, 13, 1, {A_Boss5CheckOnGround}, S_FANG_PINCHSKID1, 0, S_FANG_PINCHFALL1}, // S_FANG_PINCHFALL2 {SPR_FANG, 13, 1, {A_Boss5CheckOnGround}, S_FANG_PINCHSKID1, 0, S_FANG_PINCHFALL1}, // S_FANG_PINCHFALL2
{SPR_FANG, 4, 0, {A_PlayAttackSound}, 0, 0, S_FANG_PINCHSKID2}, // S_FANG_PINCHSKID1 {SPR_FANG, 4, 0, {A_PlayAttackSound}, 0, 0, S_FANG_PINCHSKID2}, // S_FANG_PINCHSKID1
@ -5292,7 +5294,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass 100, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_SPECIAL|MF_SHOOTABLE|MF_ENEMY|MF_NOGRAVITY|MF_BOUNCE|MF_RUNSPAWNFUNC, // flags MF_SPECIAL|MF_SHOOTABLE|MF_ENEMY|MF_NOGRAVITY|MF_SLIDEME|MF_RUNSPAWNFUNC, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -21691,7 +21693,7 @@ skincolor_t skincolors[MAXSKINCOLORS] = {
{"Violet", {0xd0, 0xd1, 0xd2, 0xca, 0xcc, 0xb8, 0xb9, 0xb9, 0xba, 0xa8, 0xa8, 0xa9, 0xa9, 0xfd, 0xfe, 0xfe}, SKINCOLOR_MINT, 6, V_MAGENTAMAP, true}, // SKINCOLOR_VIOLET {"Violet", {0xd0, 0xd1, 0xd2, 0xca, 0xcc, 0xb8, 0xb9, 0xb9, 0xba, 0xa8, 0xa8, 0xa9, 0xa9, 0xfd, 0xfe, 0xfe}, SKINCOLOR_MINT, 6, V_MAGENTAMAP, true}, // SKINCOLOR_VIOLET
{"Lilac", {0x00, 0xd0, 0xd1, 0xd2, 0xd3, 0xc1, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xfe, 0x1f}, SKINCOLOR_VAPOR, 4, V_ROSYMAP, true}, // SKINCOLOR_LILAC {"Lilac", {0x00, 0xd0, 0xd1, 0xd2, 0xd3, 0xc1, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xfe, 0x1f}, SKINCOLOR_VAPOR, 4, V_ROSYMAP, true}, // SKINCOLOR_LILAC
{"Plum", {0xc8, 0xd3, 0xd5, 0xd6, 0xd7, 0xce, 0xcf, 0xb9, 0xb9, 0xba, 0xba, 0xa9, 0xa9, 0xa9, 0xfd, 0xfe}, SKINCOLOR_MINT, 7, V_ROSYMAP, true}, // SKINCOLOR_PLUM {"Plum", {0xc8, 0xd3, 0xd5, 0xd6, 0xd7, 0xce, 0xcf, 0xb9, 0xb9, 0xba, 0xba, 0xa9, 0xa9, 0xa9, 0xfd, 0xfe}, SKINCOLOR_MINT, 7, V_ROSYMAP, true}, // SKINCOLOR_PLUM
{"Raspberry", {0xc8, 0xc9, 0xca, 0xcb, 0xcb, 0xcc, 0xcd, 0xcd, 0xce, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xfe, 0xfe}, SKINCOLOR_APPLE, 15, V_MAGENTAMAP, true}, // SKINCOLOR_RASPBERRY {"Raspberry", {0xc8, 0xc9, 0xca, 0xcb, 0xcb, 0xcc, 0xcd, 0xcd, 0xce, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xfe, 0xfe}, SKINCOLOR_APPLE, 13, V_MAGENTAMAP, true}, // SKINCOLOR_RASPBERRY
{"Rosy", {0xfc, 0xc8, 0xc8, 0xc9, 0xc9, 0xca, 0xca, 0xcb, 0xcb, 0xcc, 0xcc, 0xcd, 0xcd, 0xce, 0xce, 0xcf}, SKINCOLOR_AQUA, 1, V_ROSYMAP, true}, // SKINCOLOR_ROSY {"Rosy", {0xfc, 0xc8, 0xc8, 0xc9, 0xc9, 0xca, 0xca, 0xcb, 0xcb, 0xcc, 0xcc, 0xcd, 0xcd, 0xce, 0xce, 0xcf}, SKINCOLOR_AQUA, 1, V_ROSYMAP, true}, // SKINCOLOR_ROSY
// super // super

View file

@ -1608,10 +1608,12 @@ typedef enum state
S_FANG_PINCHPATHINGSTART1, S_FANG_PINCHPATHINGSTART1,
S_FANG_PINCHPATHINGSTART2, S_FANG_PINCHPATHINGSTART2,
S_FANG_PINCHPATHING, S_FANG_PINCHPATHING,
S_FANG_PINCHBOUNCE0,
S_FANG_PINCHBOUNCE1, S_FANG_PINCHBOUNCE1,
S_FANG_PINCHBOUNCE2, S_FANG_PINCHBOUNCE2,
S_FANG_PINCHBOUNCE3, S_FANG_PINCHBOUNCE3,
S_FANG_PINCHBOUNCE4, S_FANG_PINCHBOUNCE4,
S_FANG_PINCHFALL0,
S_FANG_PINCHFALL1, S_FANG_PINCHFALL1,
S_FANG_PINCHFALL2, S_FANG_PINCHFALL2,
S_FANG_PINCHSKID1, S_FANG_PINCHSKID1,

View file

@ -2068,7 +2068,7 @@ msgstr ""
#: m_cheat.c:292 #: m_cheat.c:292
#, c-format #, c-format
msgid "Sissy Mode %s\n" msgid "Cheese Mode %s\n"
msgstr "" msgstr ""
#: m_cheat.c:315 m_cheat.c:349 m_cheat.c:514 m_cheat.c:538 m_cheat.c:557 #: m_cheat.c:315 m_cheat.c:349 m_cheat.c:514 m_cheat.c:538 m_cheat.c:557

View file

@ -2145,7 +2145,7 @@ msgstr ""
#: m_cheat.c:294 #: m_cheat.c:294
#, c-format #, c-format
msgid "Sissy Mode %s\n" msgid "Cheese Mode %s\n"
msgstr "" msgstr ""
#: m_cheat.c:314 #: m_cheat.c:314

View file

@ -3103,6 +3103,14 @@ static int lib_gPlatformGametype(lua_State *L)
return 1; return 1;
} }
static int lib_gCoopGametype(lua_State *L)
{
//HUDSAFE
INLEVEL
lua_pushboolean(L, G_CoopGametype());
return 1;
}
static int lib_gTagGametype(lua_State *L) static int lib_gTagGametype(lua_State *L)
{ {
//HUDSAFE //HUDSAFE
@ -3386,6 +3394,7 @@ static luaL_Reg lib[] = {
{"G_GametypeHasSpectators",lib_gGametypeHasSpectators}, {"G_GametypeHasSpectators",lib_gGametypeHasSpectators},
{"G_RingSlingerGametype",lib_gRingSlingerGametype}, {"G_RingSlingerGametype",lib_gRingSlingerGametype},
{"G_PlatformGametype",lib_gPlatformGametype}, {"G_PlatformGametype",lib_gPlatformGametype},
{"G_CoopGametype",lib_gCoopGametype},
{"G_TagGametype",lib_gTagGametype}, {"G_TagGametype",lib_gTagGametype},
{"G_CompetitionGametype",lib_gCompetitionGametype}, {"G_CompetitionGametype",lib_gCompetitionGametype},
{"G_TicsToHours",lib_gTicsToHours}, {"G_TicsToHours",lib_gTicsToHours},

View file

@ -58,6 +58,7 @@ enum hook {
hook_SeenPlayer, hook_SeenPlayer,
hook_PlayerThink, hook_PlayerThink,
hook_ShouldJingleContinue, hook_ShouldJingleContinue,
hook_GameQuit,
hook_MAX // last hook hook_MAX // last hook
}; };
@ -112,3 +113,4 @@ boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend); // Hook for MT_
#endif #endif
#define LUAh_PlayerThink(player) LUAh_PlayerHook(player, hook_PlayerThink) // Hook for P_PlayerThink #define LUAh_PlayerThink(player) LUAh_PlayerHook(player, hook_PlayerThink) // Hook for P_PlayerThink
boolean LUAh_ShouldJingleContinue(player_t *player, const char *musname); // Hook for whether a jingle of the given music should continue playing boolean LUAh_ShouldJingleContinue(player_t *player, const char *musname); // Hook for whether a jingle of the given music should continue playing
void LUAh_GameQuit(void); // Hook for game quitting

View file

@ -70,6 +70,7 @@ const char *const hookNames[hook_MAX+1] = {
"SeenPlayer", "SeenPlayer",
"PlayerThink", "PlayerThink",
"ShouldJingleContinue", "ShouldJingleContinue",
"GameQuit",
NULL NULL
}; };
@ -1769,3 +1770,29 @@ boolean LUAh_ShouldJingleContinue(player_t *player, const char *musname)
return keepplaying; return keepplaying;
} }
// Hook for game quitting
void LUAh_GameQuit(void)
{
hook_p hookp;
if (!gL || !(hooksAvailable[hook_GameQuit/8] & (1<<(hook_GameQuit%8))))
return;
lua_pushcfunction(gL, LUA_GetErrorMessage);
for (hookp = roothook; hookp; hookp = hookp->next)
{
if (hookp->type != hook_GameQuit)
continue;
PushHook(gL, hookp);
if (lua_pcall(gL, 0, 0, 1)) {
if (!hookp->error || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1);
hookp->error = true;
}
}
lua_pop(gL, 1); // Pop error handler
}

View file

@ -139,6 +139,7 @@ static const char *const side_opt[] = {
"toptexture", "toptexture",
"bottomtexture", "bottomtexture",
"midtexture", "midtexture",
"line",
"sector", "sector",
"special", "special",
"repeatcnt", "repeatcnt",
@ -2009,6 +2010,8 @@ static int mapheaderinfo_get(lua_State *L)
lua_pushinteger(L, header->typeoflevel); lua_pushinteger(L, header->typeoflevel);
else if (fastcmp(field,"nextlevel")) else if (fastcmp(field,"nextlevel"))
lua_pushinteger(L, header->nextlevel); lua_pushinteger(L, header->nextlevel);
else if (fastcmp(field,"marathonnext"))
lua_pushinteger(L, header->marathonnext);
else if (fastcmp(field,"keywords")) else if (fastcmp(field,"keywords"))
lua_pushstring(L, header->keywords); lua_pushstring(L, header->keywords);
else if (fastcmp(field,"musname")) else if (fastcmp(field,"musname"))

View file

@ -86,6 +86,7 @@ enum mobj_e {
mobj_cvmem, mobj_cvmem,
mobj_standingslope, mobj_standingslope,
mobj_colorized, mobj_colorized,
mobj_mirrored,
mobj_shadowscale mobj_shadowscale
}; };
@ -152,6 +153,7 @@ static const char *const mobj_opt[] = {
"cvmem", "cvmem",
"standingslope", "standingslope",
"colorized", "colorized",
"mirrored",
"shadowscale", "shadowscale",
NULL}; NULL};
@ -385,6 +387,9 @@ static int mobj_get(lua_State *L)
case mobj_colorized: case mobj_colorized:
lua_pushboolean(L, mo->colorized); lua_pushboolean(L, mo->colorized);
break; break;
case mobj_mirrored:
lua_pushboolean(L, mo->mirrored);
break;
case mobj_shadowscale: case mobj_shadowscale:
lua_pushfixed(L, mo->shadowscale); lua_pushfixed(L, mo->shadowscale);
break; break;
@ -713,6 +718,9 @@ static int mobj_set(lua_State *L)
case mobj_colorized: case mobj_colorized:
mo->colorized = luaL_checkboolean(L, 3); mo->colorized = luaL_checkboolean(L, 3);
break; break;
case mobj_mirrored:
mo->mirrored = luaL_checkboolean(L, 3);
break;
case mobj_shadowscale: case mobj_shadowscale:
mo->shadowscale = luaL_checkfixed(L, 3); mo->shadowscale = luaL_checkfixed(L, 3);
break; break;

View file

@ -167,7 +167,10 @@ int LUA_PushGlobals(lua_State *L, const char *word)
lua_pushboolean(L, splitscreen); lua_pushboolean(L, splitscreen);
return 1; return 1;
} else if (fastcmp(word,"gamecomplete")) { } else if (fastcmp(word,"gamecomplete")) {
lua_pushboolean(L, gamecomplete); lua_pushboolean(L, (gamecomplete != 0));
return 1;
} else if (fastcmp(word,"marathonmode")) {
lua_pushinteger(L, marathonmode);
return 1; return 1;
} else if (fastcmp(word,"devparm")) { } else if (fastcmp(word,"devparm")) {
lua_pushboolean(L, devparm); lua_pushboolean(L, devparm);
@ -197,6 +200,9 @@ int LUA_PushGlobals(lua_State *L, const char *word)
} else if (fastcmp(word,"spstage_start")) { } else if (fastcmp(word,"spstage_start")) {
lua_pushinteger(L, spstage_start); lua_pushinteger(L, spstage_start);
return 1; return 1;
} else if (fastcmp(word,"spmarathon_start")) {
lua_pushinteger(L, spmarathon_start);
return 1;
} else if (fastcmp(word,"sstage_start")) { } else if (fastcmp(word,"sstage_start")) {
lua_pushinteger(L, sstage_start); lua_pushinteger(L, sstage_start);
return 1; return 1;
@ -320,6 +326,12 @@ int LUA_PushGlobals(lua_State *L, const char *word)
return 0; return 0;
LUA_PushUserdata(L, &players[secondarydisplayplayer], META_PLAYER); LUA_PushUserdata(L, &players[secondarydisplayplayer], META_PLAYER);
return 1; return 1;
} else if (fastcmp(word,"isserver")) {
lua_pushboolean(L, server);
return 1;
} else if (fastcmp(word,"isdedicatedserver")) {
lua_pushboolean(L, dedicated);
return 1;
// end local player variables // end local player variables
} else if (fastcmp(word,"server")) { } else if (fastcmp(word,"server")) {
if ((!multiplayer || !netgame) && !playeringame[serverplayer]) if ((!multiplayer || !netgame) && !playeringame[serverplayer])

View file

@ -288,7 +288,7 @@ void Command_CheatGod_f(void)
plyr = &players[consoleplayer]; plyr = &players[consoleplayer];
plyr->pflags ^= PF_GODMODE; plyr->pflags ^= PF_GODMODE;
CONS_Printf(M_GetText("Sissy Mode %s\n"), plyr->pflags & PF_GODMODE ? M_GetText("On") : M_GetText("Off")); CONS_Printf(M_GetText("Cheese Mode %s\n"), plyr->pflags & PF_GODMODE ? M_GetText("On") : M_GetText("Off"));
G_SetGameModified(multiplayer); G_SetGameModified(multiplayer);
} }

File diff suppressed because it is too large Load diff

View file

@ -21,6 +21,9 @@
#include "r_skins.h" // for SKINNAMESIZE #include "r_skins.h" // for SKINNAMESIZE
#include "f_finale.h" // for ttmode_enum #include "f_finale.h" // for ttmode_enum
// Compatibility with old-style named NiGHTS replay files.
#define OLDNREPLAYNAME
// //
// MENUS // MENUS
// //
@ -61,6 +64,8 @@ typedef enum
MN_SP_NIGHTS_REPLAY, MN_SP_NIGHTS_REPLAY,
MN_SP_NIGHTS_GHOST, MN_SP_NIGHTS_GHOST,
MN_SP_MARATHON,
// Multiplayer // Multiplayer
MN_MP_MAIN, MN_MP_MAIN,
MN_MP_SPLITSCREEN, // SplitServer MN_MP_SPLITSCREEN, // SplitServer
@ -92,8 +97,6 @@ typedef enum
MN_OP_COLOR, MN_OP_COLOR,
MN_OP_OPENGL, MN_OP_OPENGL,
MN_OP_OPENGL_LIGHTING, MN_OP_OPENGL_LIGHTING,
MN_OP_OPENGL_FOG,
MN_OP_OPENGL_COLOR,
MN_OP_SOUND, MN_OP_SOUND,
@ -419,6 +422,7 @@ extern INT16 char_on, startchar;
#define MAXSAVEGAMES 31 #define MAXSAVEGAMES 31
#define NOSAVESLOT 0 //slot where Play Without Saving appears #define NOSAVESLOT 0 //slot where Play Without Saving appears
#define MARATHONSLOT 420 // just has to be nonzero, but let's use one that'll show up as an obvious error if something goes wrong while not using our existing saves
#define BwehHehHe() S_StartSound(NULL, sfx_bewar1+M_RandomKey(4)) // Bweh heh he #define BwehHehHe() S_StartSound(NULL, sfx_bewar1+M_RandomKey(4)) // Bweh heh he

View file

@ -4950,7 +4950,7 @@ void A_ThrownRing(mobj_t *actor)
continue; continue;
// Don't home in on teammates. // Don't home in on teammates.
if ((gametyperules & GTR_TEAMFLAGS) if ((gametyperules & GTR_TEAMS)
&& actor->target->player->ctfteam == player->ctfteam) && actor->target->player->ctfteam == player->ctfteam)
continue; continue;
} }
@ -5106,9 +5106,11 @@ void A_SignPlayer(mobj_t *actor)
INT32 locvar2 = var2; INT32 locvar2 = var2;
skin_t *skin = NULL; skin_t *skin = NULL;
mobj_t *ov; mobj_t *ov;
UINT16 facecolor, signcolor = (UINT16)locvar2; UINT16 facecolor, signcolor = 0;
UINT32 signframe = states[actor->info->raisestate].frame; UINT32 signframe = states[actor->info->raisestate].frame;
facecolor = signcolor = (UINT16)locvar2;
if (LUA_CallAction("A_SignPlayer", actor)) if (LUA_CallAction("A_SignPlayer", actor))
return; return;
@ -5140,12 +5142,10 @@ void A_SignPlayer(mobj_t *actor)
; ;
else if (!skin->sprites[SPR2_SIGN].numframes) else if (!skin->sprites[SPR2_SIGN].numframes)
signcolor = facecolor; signcolor = facecolor;
else if ((actor->target->player->skincolor == skin->prefcolor) && (skin->prefoppositecolor)) // Set it as the skin's preferred oppositecolor? else if ((facecolor == skin->prefcolor) && (skin->prefoppositecolor)) // Set it as the skin's preferred oppositecolor?
signcolor = skin->prefoppositecolor; signcolor = skin->prefoppositecolor;
else if (actor->target->player->skincolor) // Set the sign to be an appropriate background color for this player's skincolor. else if (facecolor) // Set the sign to be an appropriate background color for this player's skincolor.
signcolor = skincolors[actor->target->player->skincolor].invcolor; signcolor = skincolors[facecolor].invcolor;
else
signcolor = SKINCOLOR_NONE;
} }
else if (locvar1 != -3) // set to a defined skin else if (locvar1 != -3) // set to a defined skin
{ {
@ -5209,6 +5209,7 @@ void A_SignPlayer(mobj_t *actor)
P_SetMobjState(ov, actor->info->meleestate); // S_EGGMANSIGN P_SetMobjState(ov, actor->info->meleestate); // S_EGGMANSIGN
if (!signcolor) if (!signcolor)
signcolor = SKINCOLOR_CARBON; signcolor = SKINCOLOR_CARBON;
facecolor = signcolor;
} }
actor->tracer->color = signcolor; actor->tracer->color = signcolor;
@ -6522,7 +6523,7 @@ void A_OldRingExplode(mobj_t *actor) {
if (changecolor) if (changecolor)
{ {
if (!(gametyperules & GTR_TEAMFLAGS)) if (!(gametyperules & GTR_TEAMS))
mo->color = actor->target->color; //copy color mo->color = actor->target->color; //copy color
else if (actor->target->player->ctfteam == 2) else if (actor->target->player->ctfteam == 2)
mo->color = skincolor_bluering; mo->color = skincolor_bluering;
@ -6538,7 +6539,7 @@ void A_OldRingExplode(mobj_t *actor) {
if (changecolor) if (changecolor)
{ {
if (!(gametyperules & GTR_TEAMFLAGS)) if (!(gametyperules & GTR_TEAMS))
mo->color = actor->target->color; //copy color mo->color = actor->target->color; //copy color
else if (actor->target->player->ctfteam == 2) else if (actor->target->player->ctfteam == 2)
mo->color = skincolor_bluering; mo->color = skincolor_bluering;
@ -6553,7 +6554,7 @@ void A_OldRingExplode(mobj_t *actor) {
if (changecolor) if (changecolor)
{ {
if (!(gametyperules & GTR_TEAMFLAGS)) if (!(gametyperules & GTR_TEAMS))
mo->color = actor->target->color; //copy color mo->color = actor->target->color; //copy color
else if (actor->target->player->ctfteam == 2) else if (actor->target->player->ctfteam == 2)
mo->color = skincolor_bluering; mo->color = skincolor_bluering;

View file

@ -2278,7 +2278,7 @@ void P_CheckSurvivors(void)
if (!taggers) //If there are no taggers, pick a survivor at random to be it. if (!taggers) //If there are no taggers, pick a survivor at random to be it.
{ {
// Exception for hide and seek. If a round has started and the IT player leaves, end the round. // Exception for hide and seek. If a round has started and the IT player leaves, end the round.
if (gametype == GT_HIDEANDSEEK && (leveltime >= (hidetime * TICRATE))) if ((gametyperules & GTR_HIDEFROZEN) && (leveltime >= (hidetime * TICRATE)))
{ {
CONS_Printf(M_GetText("The IT player has left the game.\n")); CONS_Printf(M_GetText("The IT player has left the game.\n"));
if (server) if (server)
@ -2516,7 +2516,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
} }
P_RestoreMusic(target->player); P_RestoreMusic(target->player);
if (gametype != GT_COOP) if (!G_CoopGametype())
{ {
HU_SetCEchoFlags(0); HU_SetCEchoFlags(0);
HU_SetCEchoDuration(5); HU_SetCEchoDuration(5);
@ -2594,7 +2594,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
// allow them to try again, rather than sitting the whole thing out. // allow them to try again, rather than sitting the whole thing out.
if (leveltime >= hidetime * TICRATE) if (leveltime >= hidetime * TICRATE)
{ {
if (gametype == GT_TAG)//suiciding in survivor makes you IT. if (!(gametyperules & GTR_HIDEFROZEN))//suiciding in survivor makes you IT.
{ {
target->player->pflags |= PF_TAGIT; target->player->pflags |= PF_TAGIT;
CONS_Printf(M_GetText("%s is now IT!\n"), player_names[target->player-players]); // Tell everyone who is it! CONS_Printf(M_GetText("%s is now IT!\n"), player_names[target->player-players]); // Tell everyone who is it!
@ -3088,7 +3088,7 @@ static boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, IN
P_AddPlayerScore(source->player, 100); //award points to tagger. P_AddPlayerScore(source->player, 100); //award points to tagger.
P_HitDeathMessages(player, inflictor, source, 0); P_HitDeathMessages(player, inflictor, source, 0);
if (gametype == GT_TAG) //survivor if (!(gametyperules & GTR_HIDEFROZEN)) //survivor
{ {
player->pflags |= PF_TAGIT; //in survivor, the player becomes IT and helps hunt down the survivors. player->pflags |= PF_TAGIT; //in survivor, the player becomes IT and helps hunt down the survivors.
CONS_Printf(M_GetText("%s is now IT!\n"), player_names[player-players]); // Tell everyone who is it! CONS_Printf(M_GetText("%s is now IT!\n"), player_names[player-players]); // Tell everyone who is it!
@ -3149,7 +3149,7 @@ static boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj_t *sou
// In COOP/RACE, you can't hurt other players unless cv_friendlyfire is on // In COOP/RACE, you can't hurt other players unless cv_friendlyfire is on
if (!(cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE)) && (gametyperules & GTR_FRIENDLY)) if (!(cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE)) && (gametyperules & GTR_FRIENDLY))
{ {
if (gametype == GT_COOP && inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) // co-op only if ((gametyperules & GTR_FRIENDLY) && inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) // co-op only
{ {
if (player->revitem != MT_LHRT && player->spinitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers. if (player->revitem != MT_LHRT && player->spinitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers.
{ {
@ -3248,7 +3248,7 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage)
} }
// If the player was super, tell them he/she ain't so super nomore. // If the player was super, tell them he/she ain't so super nomore.
if (gametype != GT_COOP && player->powers[pw_super]) if (!G_CoopGametype() && player->powers[pw_super])
{ {
S_StartSound(NULL, sfx_s3k66); //let all players hear it. S_StartSound(NULL, sfx_s3k66); //let all players hear it.
HU_SetCEchoFlags(0); HU_SetCEchoFlags(0);
@ -3610,7 +3610,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
if (source == target) if (source == target)
return false; // Don't hit yourself with your own paraloop, baka return false; // Don't hit yourself with your own paraloop, baka
if (source && source->player && !(cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE)) if (source && source->player && !(cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE))
&& (gametype == GT_COOP && ((gametyperules & GTR_FRIENDLY)
|| (G_GametypeHasTeams() && player->ctfteam == source->player->ctfteam))) || (G_GametypeHasTeams() && player->ctfteam == source->player->ctfteam)))
return false; // Don't run eachother over in special stages and team games and such return false; // Don't run eachother over in special stages and team games and such
} }

View file

@ -1588,7 +1588,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
} }
// Force solid players in hide and seek to avoid corner stacking. // Force solid players in hide and seek to avoid corner stacking.
if (cv_tailspickup.value && gametype != GT_HIDEANDSEEK) if (cv_tailspickup.value && !(gametyperules & GTR_HIDEFROZEN))
{ {
if (tmthing->player && thing->player) if (tmthing->player && thing->player)
{ {

View file

@ -9206,10 +9206,11 @@ static void P_DragonbomberThink(mobj_t *mobj)
mobj->angle += DRAGONTURNSPEED; mobj->angle += DRAGONTURNSPEED;
else else
{ {
boolean flip = mobj->spawnpoint->options & MTF_OBJECTFLIP;
fixed_t vspeed = FixedMul(mobj->info->speed >> 3, mobj->scale); fixed_t vspeed = FixedMul(mobj->info->speed >> 3, mobj->scale);
fixed_t x = mobj->spawnpoint->x << FRACBITS; fixed_t x = mobj->spawnpoint->x << FRACBITS;
fixed_t y = mobj->spawnpoint->y << FRACBITS; fixed_t y = mobj->spawnpoint->y << FRACBITS;
fixed_t z = mobj->spawnpoint->z << FRACBITS; fixed_t z = (flip ? P_GetSectorCeilingZAt : P_GetSectorFloorZAt)(R_PointInSubsector(x, y)->sector, x, y) + (flip ? -1 : 1)*(mobj->spawnpoint->z << FRACBITS);
angle_t diff = R_PointToAngle2(mobj->x, mobj->y, x, y) - mobj->angle; angle_t diff = R_PointToAngle2(mobj->x, mobj->y, x, y) - mobj->angle;
if (diff > ANGLE_180) if (diff > ANGLE_180)
mobj->angle -= DRAGONTURNSPEED; mobj->angle -= DRAGONTURNSPEED;
@ -11309,7 +11310,7 @@ void P_SpawnPlayer(INT32 playernum)
if (!G_GametypeHasSpectators()) if (!G_GametypeHasSpectators())
{ {
p->spectator = p->outofcoop = p->spectator = p->outofcoop =
(((multiplayer || netgame) && gametype == GT_COOP) // only question status in coop (((multiplayer || netgame) && G_CoopGametype()) // only question status in coop
&& ((leveltime > 0 && ((leveltime > 0
&& ((G_IsSpecialStage(gamemap)) // late join special stage && ((G_IsSpecialStage(gamemap)) // late join special stage
|| (cv_coopstarposts.value == 2 && (p->jointime < 1 || p->outofcoop)))) // late join or die in new coop || (cv_coopstarposts.value == 2 && (p->jointime < 1 || p->outofcoop)))) // late join or die in new coop
@ -11768,7 +11769,7 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i)
case MT_EMERALD5: case MT_EMERALD5:
case MT_EMERALD6: case MT_EMERALD6:
case MT_EMERALD7: case MT_EMERALD7:
if (gametype != GT_COOP) // Don't place emeralds in non-coop modes if (!G_CoopGametype()) // Don't place emeralds in non-coop modes
return false; return false;
if (metalrecording) if (metalrecording)
@ -11788,7 +11789,7 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i)
runemeraldmanager = true; runemeraldmanager = true;
break; break;
case MT_ROSY: case MT_ROSY:
if (!(gametype == GT_COOP || (mthing->options & MTF_EXTRA))) if (!(G_CoopGametype() || (mthing->options & MTF_EXTRA)))
return false; // she doesn't hang out here return false; // she doesn't hang out here
if (!mariomode && !(netgame || multiplayer) && players[consoleplayer].skin == 3) if (!mariomode && !(netgame || multiplayer) && players[consoleplayer].skin == 3)
@ -11903,7 +11904,7 @@ static mobjtype_t P_GetMobjtypeSubstitute(mapthing_t *mthing, mobjtype_t i)
} }
} }
// Set powerup boxes to user settings for other netplay modes // Set powerup boxes to user settings for other netplay modes
else if (gametype != GT_COOP) else if (!G_CoopGametype())
{ {
switch (cv_matchboxes.value) switch (cv_matchboxes.value)
{ {

View file

@ -373,6 +373,7 @@ typedef struct mobj_s
struct pslope_s *standingslope; // The slope that the object is standing on (shouldn't need synced in savegames, right?) struct pslope_s *standingslope; // The slope that the object is standing on (shouldn't need synced in savegames, right?)
boolean colorized; // Whether the mobj uses the rainbow colormap boolean colorized; // Whether the mobj uses the rainbow colormap
boolean mirrored; // The object's rotations will be mirrored left to right, e.g., see frame AL from the right and AR from the left
fixed_t shadowscale; // If this object casts a shadow, and the size relative to radius fixed_t shadowscale; // If this object casts a shadow, and the size relative to radius
// WARNING: New fields must be added separately to savegame and Lua. // WARNING: New fields must be added separately to savegame and Lua.

View file

@ -1159,6 +1159,7 @@ static void Polyobj_rotateThings(polyobj_t *po, vector2_t origin, angle_t delta,
if (turnthings == 2 || (turnthings == 1 && !mo->player)) { if (turnthings == 2 || (turnthings == 1 && !mo->player)) {
mo->angle += delta; mo->angle += delta;
if (mo->player)
P_SetPlayerAngle(mo->player, (angle_t)(mo->player->angleturn << 16) + delta); P_SetPlayerAngle(mo->player, (angle_t)(mo->player->angleturn << 16) + delta);
} }
} }

View file

@ -64,8 +64,10 @@
#define FF_FULLBRIGHT 0x00100000 #define FF_FULLBRIGHT 0x00100000
/// \brief Frame flags: Flip sprite vertically (relative to what it should be for its gravity) /// \brief Frame flags: Flip sprite vertically (relative to what it should be for its gravity)
#define FF_VERTICALFLIP 0x00200000 #define FF_VERTICALFLIP 0x00200000
/// \brief Frame flags: Flip sprite horizontally
#define FF_HORIZONTALFLIP 0x00400000
/// \brief Frame flags: Thin, paper-like sprite (for collision equivalent, see MF_PAPERCOLLISION) /// \brief Frame flags: Thin, paper-like sprite (for collision equivalent, see MF_PAPERCOLLISION)
#define FF_PAPERSPRITE 0x00400000 #define FF_PAPERSPRITE 0x00800000
/// \brief Frame flags - Animate: Simple stateless animation /// \brief Frame flags - Animate: Simple stateless animation
#define FF_ANIMATE 0x01000000 #define FF_ANIMATE 0x01000000

View file

@ -1294,8 +1294,9 @@ typedef enum
MD2_CEILINGROVER = 1<<10, MD2_CEILINGROVER = 1<<10,
MD2_SLOPE = 1<<11, MD2_SLOPE = 1<<11,
MD2_COLORIZED = 1<<12, MD2_COLORIZED = 1<<12,
MD2_ROLLANGLE = 1<<13, MD2_MIRRORED = 1<<13,
MD2_SHADOWSCALE = 1<<14, MD2_ROLLANGLE = 1<<14,
MD2_SHADOWSCALE = 1<<15,
} mobj_diff2_t; } mobj_diff2_t;
typedef enum typedef enum
@ -1500,6 +1501,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
diff2 |= MD2_SLOPE; diff2 |= MD2_SLOPE;
if (mobj->colorized) if (mobj->colorized)
diff2 |= MD2_COLORIZED; diff2 |= MD2_COLORIZED;
if (mobj->mirrored)
diff2 |= MD2_MIRRORED;
if (mobj->rollangle) if (mobj->rollangle)
diff2 |= MD2_ROLLANGLE; diff2 |= MD2_ROLLANGLE;
if (mobj->shadowscale) if (mobj->shadowscale)
@ -1638,6 +1641,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
WRITEUINT16(save_p, mobj->standingslope->id); WRITEUINT16(save_p, mobj->standingslope->id);
if (diff2 & MD2_COLORIZED) if (diff2 & MD2_COLORIZED)
WRITEUINT8(save_p, mobj->colorized); WRITEUINT8(save_p, mobj->colorized);
if (diff2 & MD2_MIRRORED)
WRITEUINT8(save_p, mobj->mirrored);
if (diff2 & MD2_ROLLANGLE) if (diff2 & MD2_ROLLANGLE)
WRITEANGLE(save_p, mobj->rollangle); WRITEANGLE(save_p, mobj->rollangle);
if (diff2 & MD2_SHADOWSCALE) if (diff2 & MD2_SHADOWSCALE)
@ -2641,6 +2646,8 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
mobj->standingslope = P_SlopeById(READUINT16(save_p)); mobj->standingslope = P_SlopeById(READUINT16(save_p));
if (diff2 & MD2_COLORIZED) if (diff2 & MD2_COLORIZED)
mobj->colorized = READUINT8(save_p); mobj->colorized = READUINT8(save_p);
if (diff2 & MD2_MIRRORED)
mobj->mirrored = READUINT8(save_p);
if (diff2 & MD2_ROLLANGLE) if (diff2 & MD2_ROLLANGLE)
mobj->rollangle = READANGLE(save_p); mobj->rollangle = READANGLE(save_p);
if (diff2 & MD2_SHADOWSCALE) if (diff2 & MD2_SHADOWSCALE)
@ -3785,16 +3792,15 @@ static void P_NetUnArchiveSpecials(void)
// ======================================================================= // =======================================================================
// Misc // Misc
// ======================================================================= // =======================================================================
static inline void P_ArchiveMisc(void) static inline void P_ArchiveMisc(INT16 mapnum)
{ {
//lastmapsaved = mapnum;
lastmaploaded = mapnum;
if (gamecomplete) if (gamecomplete)
WRITEINT16(save_p, gamemap | 8192); mapnum |= 8192;
else
WRITEINT16(save_p, gamemap);
//lastmapsaved = gamemap;
lastmaploaded = gamemap;
WRITEINT16(save_p, mapnum);
WRITEUINT16(save_p, emeralds+357); WRITEUINT16(save_p, emeralds+357);
WRITESTRINGN(save_p, timeattackfolder, sizeof(timeattackfolder)); WRITESTRINGN(save_p, timeattackfolder, sizeof(timeattackfolder));
} }
@ -3808,10 +3814,10 @@ static inline void P_UnArchiveSPGame(INT16 mapoverride)
if (mapoverride != 0) if (mapoverride != 0)
{ {
gamemap = mapoverride; gamemap = mapoverride;
gamecomplete = true; gamecomplete = 1;
} }
else else
gamecomplete = false; gamecomplete = 0;
// gamemap changed; we assume that its map header is always valid, // gamemap changed; we assume that its map header is always valid,
// so make it so // so make it so
@ -4035,9 +4041,9 @@ static inline boolean P_UnArchiveLuabanksAndConsistency(void)
return true; return true;
} }
void P_SaveGame(void) void P_SaveGame(INT16 mapnum)
{ {
P_ArchiveMisc(); P_ArchiveMisc(mapnum);
P_ArchivePlayer(); P_ArchivePlayer();
P_ArchiveLuabanksAndConsistency(); P_ArchiveLuabanksAndConsistency();
} }

View file

@ -21,7 +21,7 @@
// Persistent storage/archiving. // Persistent storage/archiving.
// These are the load / save game routines. // These are the load / save game routines.
void P_SaveGame(void); void P_SaveGame(INT16 mapnum);
void P_SaveNetGame(void); void P_SaveNetGame(void);
boolean P_LoadGame(INT16 mapoverride); boolean P_LoadGame(INT16 mapoverride);
boolean P_LoadNetGame(void); boolean P_LoadNetGame(void);

View file

@ -344,6 +344,7 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
mapheaderinfo[num]->actnum = 0; mapheaderinfo[num]->actnum = 0;
mapheaderinfo[num]->typeoflevel = 0; mapheaderinfo[num]->typeoflevel = 0;
mapheaderinfo[num]->nextlevel = (INT16)(i + 1); mapheaderinfo[num]->nextlevel = (INT16)(i + 1);
mapheaderinfo[num]->marathonnext = 0;
mapheaderinfo[num]->startrings = 0; mapheaderinfo[num]->startrings = 0;
mapheaderinfo[num]->sstimer = 90; mapheaderinfo[num]->sstimer = 90;
mapheaderinfo[num]->ssspheres = 1; mapheaderinfo[num]->ssspheres = 1;
@ -3156,6 +3157,7 @@ static void P_LoadNightsGhosts(void)
{ {
const size_t glen = strlen(srb2home)+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1; const size_t glen = strlen(srb2home)+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1;
char *gpath = malloc(glen); char *gpath = malloc(glen);
INT32 i;
if (!gpath) if (!gpath)
return; return;
@ -3163,16 +3165,43 @@ static void P_LoadNightsGhosts(void)
sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap)); sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap));
// Best Score ghost // Best Score ghost
if (cv_ghost_bestscore.value && FIL_FileExists(va("%s-score-best.lmp", gpath))) if (cv_ghost_bestscore.value)
G_AddGhost(va("%s-score-best.lmp", gpath)); {
for (i = 0; i < numskins; ++i)
{
if (cv_ghost_bestscore.value == 1 && players[consoleplayer].skin != i)
continue;
if (FIL_FileExists(va("%s-%s-score-best.lmp", gpath, skins[i].name)))
G_AddGhost(va("%s-%s-score-best.lmp", gpath, skins[i].name));
}
}
// Best Time ghost // Best Time ghost
if (cv_ghost_besttime.value && FIL_FileExists(va("%s-time-best.lmp", gpath))) if (cv_ghost_besttime.value)
G_AddGhost(va("%s-time-best.lmp", gpath)); {
for (i = 0; i < numskins; ++i)
{
if (cv_ghost_besttime.value == 1 && players[consoleplayer].skin != i)
continue;
if (FIL_FileExists(va("%s-%s-time-best.lmp", gpath, skins[i].name)))
G_AddGhost(va("%s-%s-time-best.lmp", gpath, skins[i].name));
}
}
// Last ghost // Last ghost
if (cv_ghost_last.value && FIL_FileExists(va("%s-last.lmp", gpath))) if (cv_ghost_last.value)
G_AddGhost(va("%s-last.lmp", gpath)); {
for (i = 0; i < numskins; ++i)
{
if (cv_ghost_last.value == 1 && players[consoleplayer].skin != i)
continue;
if (FIL_FileExists(va("%s-%s-last.lmp", gpath, skins[i].name)))
G_AddGhost(va("%s-%s-last.lmp", gpath, skins[i].name));
}
}
// Guest ghost // Guest ghost
if (cv_ghost_guest.value && FIL_FileExists(va("%s-guest.lmp", gpath))) if (cv_ghost_guest.value && FIL_FileExists(va("%s-guest.lmp", gpath)))
@ -3296,21 +3325,6 @@ static void P_InitCamera(void)
} }
} }
static boolean CanSaveLevel(INT32 mapnum)
{
if (ultimatemode) // never save in ultimate (probably redundant with cursaveslot also being checked)
return false;
if (G_IsSpecialStage(mapnum) // don't save in special stages
|| mapnum == lastmaploaded) // don't save if the last map loaded was this one
return false;
// Any levels that have the savegame flag can save normally.
// If the game is complete for this save slot, then any level can save!
// On the other side of the spectrum, if lastmaploaded is 0, then the save file has only just been created and needs to save ASAP!
return (mapheaderinfo[mapnum-1]->levelflags & LF_SAVEGAME || gamecomplete || !lastmaploaded);
}
static void P_RunSpecialStageWipe(void) static void P_RunSpecialStageWipe(void)
{ {
tic_t starttime = I_GetTime(); tic_t starttime = I_GetTime();
@ -3473,7 +3487,7 @@ static void P_InitGametype(void)
if (G_TagGametype()) if (G_TagGametype())
P_InitTagGametype(); P_InitTagGametype();
else if (gametype == GT_RACE && server) else if (((gametyperules & (GTR_RACE|GTR_LIVES)) == GTR_RACE) && server)
CV_StealthSetValue(&cv_numlaps, CV_StealthSetValue(&cv_numlaps,
(cv_basenumlaps.value) (cv_basenumlaps.value)
? cv_basenumlaps.value ? cv_basenumlaps.value
@ -3747,11 +3761,19 @@ boolean P_LoadLevel(boolean fromnetsave)
P_RunCachedActions(); P_RunCachedActions();
if (!(netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking || players[consoleplayer].lives <= 0) // Took me 3 hours to figure out why my progression kept on getting overwritten with the titlemap...
&& (!modifiedgame || savemoddata) && cursaveslot > 0 && CanSaveLevel(gamemap)) if (!titlemapinaction)
G_SaveGame((UINT32)cursaveslot); {
if (!lastmaploaded) // Start a new game?
{
// I'd love to do this in the menu code instead of here, but everything's a mess and I can't guarantee saving proper player struct info before the first act's started. You could probably refactor it, but it'd be a lot of effort. Easier to just work off known good code. ~toast 22/06/2020
if (!(ultimatemode || netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking)
&& (!modifiedgame || savemoddata) && cursaveslot > 0)
G_SaveGame((UINT32)cursaveslot, gamemap);
// If you're looking for saving sp file progression (distinct from G_SaveGameOver), check G_DoCompleted.
}
lastmaploaded = gamemap; // HAS to be set after saving!! lastmaploaded = gamemap; // HAS to be set after saving!!
}
if (!fromnetsave) // uglier hack if (!fromnetsave) // uglier hack
{ // to make a newly loaded level start on the second frame. { // to make a newly loaded level start on the second frame.

View file

@ -4078,7 +4078,7 @@ void P_SetupSignExit(player_t *player)
if (!numfound if (!numfound
&& !(player->mo->target && player->mo->target->type == MT_SIGN) && !(player->mo->target && player->mo->target->type == MT_SIGN)
&& !(gametype == GT_COOP && (netgame || multiplayer) && cv_exitmove.value)) && !((gametyperules & GTR_FRIENDLY) && (netgame || multiplayer) && cv_exitmove.value))
P_SetTarget(&player->mo->target, thing); P_SetTarget(&player->mo->target, thing);
if (thing->state != &states[thing->info->spawnstate]) if (thing->state != &states[thing->info->spawnstate])
@ -4109,7 +4109,7 @@ void P_SetupSignExit(player_t *player)
if (!numfound if (!numfound
&& !(player->mo->target && player->mo->target->type == MT_SIGN) && !(player->mo->target && player->mo->target->type == MT_SIGN)
&& !(gametype == GT_COOP && (netgame || multiplayer) && cv_exitmove.value)) && !((gametyperules & GTR_FRIENDLY) && (netgame || multiplayer) && cv_exitmove.value))
P_SetTarget(&player->mo->target, thing); P_SetTarget(&player->mo->target, thing);
if (thing->state != &states[thing->info->spawnstate]) if (thing->state != &states[thing->info->spawnstate])
@ -4465,7 +4465,7 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers
continue; continue;
if (players[i].bot) if (players[i].bot)
continue; continue;
if (gametype == GT_COOP && players[i].lives <= 0) if (G_CoopGametype() && players[i].lives <= 0)
continue; continue;
if (roversector) if (roversector)
{ {
@ -4691,7 +4691,7 @@ DoneSection2:
// FOF custom exits not to work. // FOF custom exits not to work.
lineindex = P_FindSpecialLineFromTag(2, sector->tag, -1); lineindex = P_FindSpecialLineFromTag(2, sector->tag, -1);
if (gametype == GT_COOP && lineindex != -1) // Custom exit! if (G_CoopGametype() && lineindex != -1) // Custom exit!
{ {
// Special goodies with the block monsters flag depending on emeralds collected // Special goodies with the block monsters flag depending on emeralds collected
if ((lines[lineindex].flags & ML_BLOCKMONSTERS) && ALL7EMERALDS(emeralds)) if ((lines[lineindex].flags & ML_BLOCKMONSTERS) && ALL7EMERALDS(emeralds))
@ -4925,7 +4925,7 @@ DoneSection2:
break; break;
case 10: // Finish Line case 10: // Finish Line
if (gametype == GT_RACE && !player->exiting) if (((gametyperules & (GTR_RACE|GTR_LIVES)) == GTR_RACE) && !player->exiting)
{ {
if (player->starpostnum == numstarposts) // Must have touched all the starposts if (player->starpostnum == numstarposts) // Must have touched all the starposts
{ {
@ -6240,7 +6240,7 @@ void P_SpawnSpecials(boolean fromnetsave)
switch(GETSECSPECIAL(sector->special, 4)) switch(GETSECSPECIAL(sector->special, 4))
{ {
case 10: // Circuit finish line case 10: // Circuit finish line
if (gametype == GT_RACE) if ((gametyperules & (GTR_RACE|GTR_LIVES)) == GTR_RACE)
circuitmap = true; circuitmap = true;
break; break;
} }

View file

@ -692,7 +692,7 @@ void P_Ticker(boolean run)
if (run) if (run)
{ {
if (countdowntimer && G_PlatformGametype() && (gametype == GT_COOP || leveltime >= 4*TICRATE) && !stoppedclock && --countdowntimer <= 0) if (countdowntimer && G_PlatformGametype() && ((gametyperules & GTR_CAMPAIGN) || leveltime >= 4*TICRATE) && !stoppedclock && --countdowntimer <= 0)
{ {
countdowntimer = 0; countdowntimer = 0;
countdowntimeup = true; countdowntimeup = true;
@ -755,6 +755,9 @@ void P_PreTicker(INT32 frames)
postimgtype = postimgtype2 = postimg_none; postimgtype = postimgtype2 = postimg_none;
if (marathonmode & MA_INGAME)
marathonmode |= MA_INIT;
for (framecnt = 0; framecnt < frames; ++framecnt) for (framecnt = 0; framecnt < frames; ++framecnt)
{ {
P_MapStart(); P_MapStart();
@ -799,4 +802,7 @@ void P_PreTicker(INT32 frames)
P_MapEnd(); P_MapEnd();
} }
if (marathonmode & MA_INGAME)
marathonmode &= ~MA_INIT;
} }

View file

@ -1051,7 +1051,8 @@ void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor)
// Point penalty for hitting a hazard during tag. // Point penalty for hitting a hazard during tag.
// Discourages players from intentionally hurting themselves to avoid being tagged. // Discourages players from intentionally hurting themselves to avoid being tagged.
if (gametype == GT_TAG && (!(player->pflags & PF_GAMETYPEOVER) && !(player->pflags & PF_TAGIT))) if (((gametyperules & (GTR_TAG|GTR_HIDEFROZEN)) == GTR_TAG)
&& (!(player->pflags & PF_GAMETYPEOVER) && !(player->pflags & PF_TAGIT)))
{ {
if (player->score >= 50) if (player->score >= 50)
player->score -= 50; player->score -= 50;
@ -1351,7 +1352,7 @@ void P_DoSuperTransformation(player_t *player, boolean giverings)
player->powers[pw_sneakers] = 0; player->powers[pw_sneakers] = 0;
} }
if (gametype != GT_COOP) if (!G_CoopGametype())
{ {
HU_SetCEchoFlags(0); HU_SetCEchoFlags(0);
HU_SetCEchoDuration(5); HU_SetCEchoDuration(5);
@ -1418,7 +1419,7 @@ void P_AddPlayerScore(player_t *player, UINT32 amount)
} }
} }
if (gametype == GT_COOP) if (G_CoopGametype())
return; return;
} }
@ -1437,7 +1438,7 @@ void P_AddPlayerScore(player_t *player, UINT32 amount)
} }
// In team match, all awarded points are incremented to the team's running score. // In team match, all awarded points are incremented to the team's running score.
if (gametype == GT_TEAMMATCH) if ((gametyperules & (GTR_TEAMS|GTR_TEAMFLAGS)) == GTR_TEAMS)
{ {
if (player->ctfteam == 1) if (player->ctfteam == 1)
redscore += amount; redscore += amount;
@ -1471,7 +1472,7 @@ void P_StealPlayerScore(player_t *player, UINT32 amount)
if (stolen > 0) if (stolen > 0)
{ {
// In team match, all stolen points are removed from the enemy team's running score. // In team match, all stolen points are removed from the enemy team's running score.
if (gametype == GT_TEAMMATCH) if ((gametyperules & (GTR_TEAMS|GTR_TEAMFLAGS)) == GTR_TEAMS)
{ {
if (player->ctfteam == 1) if (player->ctfteam == 1)
bluescore -= amount; bluescore -= amount;
@ -3624,7 +3625,7 @@ static boolean PIT_CheckSolidsTeeter(mobj_t *thing)
if (thing == teeterer) if (thing == teeterer)
return true; return true;
if (thing->player && cv_tailspickup.value && gametype != GT_HIDEANDSEEK) if (thing->player && cv_tailspickup.value && !(gametyperules & GTR_HIDEFROZEN))
return true; return true;
blockdist = teeterer->radius + thing->radius; blockdist = teeterer->radius + thing->radius;
@ -4236,7 +4237,7 @@ static void P_DoSuperStuff(player_t *player)
G_GhostAddColor(GHC_NORMAL); G_GhostAddColor(GHC_NORMAL);
} }
if (gametype != GT_COOP) if (!G_CoopGametype())
{ {
HU_SetCEchoFlags(0); HU_SetCEchoFlags(0);
HU_SetCEchoDuration(5); HU_SetCEchoDuration(5);
@ -4286,14 +4287,14 @@ static void P_DoSuperStuff(player_t *player)
G_GhostAddColor(GHC_NORMAL); G_GhostAddColor(GHC_NORMAL);
} }
if (gametype != GT_COOP) if (!G_CoopGametype())
player->powers[pw_flashing] = flashingtics-1; player->powers[pw_flashing] = flashingtics-1;
if (player->mo->sprite2 & FF_SPR2SUPER) if (player->mo->sprite2 & FF_SPR2SUPER)
P_SetPlayerMobjState(player->mo, player->mo->state-states); P_SetPlayerMobjState(player->mo, player->mo->state-states);
// Inform the netgame that the champion has fallen in the heat of battle. // Inform the netgame that the champion has fallen in the heat of battle.
if (gametype != GT_COOP) if (!G_CoopGametype())
{ {
S_StartSound(NULL, sfx_s3k66); //let all players hear it. S_StartSound(NULL, sfx_s3k66); //let all players hear it.
HU_SetCEchoFlags(0); HU_SetCEchoFlags(0);
@ -7909,7 +7910,7 @@ static void P_MovePlayer(player_t *player)
if (player->pflags & PF_TAGIT) if (player->pflags & PF_TAGIT)
forcestasis = true; forcestasis = true;
} }
else if (gametype == GT_HIDEANDSEEK) else if (gametyperules & GTR_HIDEFROZEN)
{ {
if (!(player->pflags & PF_TAGIT)) if (!(player->pflags & PF_TAGIT))
{ {
@ -8582,7 +8583,7 @@ static void P_MovePlayer(player_t *player)
} }
#ifdef HWRENDER #ifdef HWRENDER
if (rendermode != render_soft && rendermode != render_none && cv_fovchange.value) if (rendermode == render_opengl && cv_fovchange.value)
{ {
fixed_t speed; fixed_t speed;
const fixed_t runnyspeed = 20*FRACUNIT; const fixed_t runnyspeed = 20*FRACUNIT;
@ -9437,7 +9438,7 @@ static void P_DeathThink(player_t *player)
} }
if ((cv_cooplives.value != 1) if ((cv_cooplives.value != 1)
&& (gametype == GT_COOP) && (G_GametypeUsesCoopLives())
&& (netgame || multiplayer) && (netgame || multiplayer)
&& (player->lives <= 0)) && (player->lives <= 0))
{ {
@ -9519,17 +9520,17 @@ static void P_DeathThink(player_t *player)
countdown2 = 1*TICRATE; countdown2 = 1*TICRATE;
} }
} }
//else if (gametype == GT_COOP) -- moved to G_DoReborn //else if (G_CoopGametype()) -- moved to G_DoReborn
} }
if (gametype == GT_COOP && (multiplayer || netgame) && (player->lives <= 0) && (player->deadtimer >= 8*TICRATE || ((cmd->buttons & BT_JUMP) && (player->deadtimer > TICRATE)))) if (G_CoopGametype() && (multiplayer || netgame) && (player->lives <= 0) && (player->deadtimer >= 8*TICRATE || ((cmd->buttons & BT_JUMP) && (player->deadtimer > TICRATE))))
{ {
//player->spectator = true; //player->spectator = true;
player->outofcoop = true; player->outofcoop = true;
player->playerstate = PST_REBORN; player->playerstate = PST_REBORN;
} }
if ((gametyperules & GTR_RACE) || (gametype == GT_COOP && (multiplayer || netgame))) if ((gametyperules & GTR_RACE) || (G_CoopGametype() && (multiplayer || netgame)))
{ {
// Keep time rolling in race mode // Keep time rolling in race mode
if (!(countdown2 && !countdown) && !player->exiting && !(player->pflags & PF_GAMETYPEOVER) && !stoppedclock) if (!(countdown2 && !countdown) && !player->exiting && !(player->pflags & PF_GAMETYPEOVER) && !stoppedclock)
@ -9546,7 +9547,7 @@ static void P_DeathThink(player_t *player)
} }
// Return to level music // Return to level music
if (gametype != GT_COOP && player->lives <= 0 && player->deadtimer == gameovertics) if (!G_CoopGametype() && player->lives <= 0 && player->deadtimer == gameovertics)
P_RestoreMultiMusic(player); P_RestoreMultiMusic(player);
} }
@ -9723,7 +9724,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
if (player->exiting) if (player->exiting)
{ {
if (mo->target && mo->target->type == MT_SIGN && mo->target->spawnpoint if (mo->target && mo->target->type == MT_SIGN && mo->target->spawnpoint
&& !(gametype == GT_COOP && (netgame || multiplayer) && cv_exitmove.value) && !((gametyperules & GTR_FRIENDLY) && (netgame || multiplayer) && cv_exitmove.value)
&& !(twodlevel || (mo->flags2 & MF2_TWOD))) && !(twodlevel || (mo->flags2 & MF2_TWOD)))
sign = mo->target; sign = mo->target;
else if ((player->powers[pw_carry] == CR_NIGHTSMODE) else if ((player->powers[pw_carry] == CR_NIGHTSMODE)
@ -9992,9 +9993,11 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
if (camorbit) //Sev here, I'm guessing this is where orbital cam lives if (camorbit) //Sev here, I'm guessing this is where orbital cam lives
{ {
if (rendermode == render_opengl) #ifdef HWRENDER
if (rendermode == render_opengl && !cv_grshearing.value)
distxy = FixedMul(dist, FINECOSINE((focusaiming>>ANGLETOFINESHIFT) & FINEMASK)); distxy = FixedMul(dist, FINECOSINE((focusaiming>>ANGLETOFINESHIFT) & FINEMASK));
else else
#endif
distxy = dist; distxy = dist;
distz = -FixedMul(dist, FINESINE((focusaiming>>ANGLETOFINESHIFT) & FINEMASK)) + slopez; distz = -FixedMul(dist, FINESINE((focusaiming>>ANGLETOFINESHIFT) & FINEMASK)) + slopez;
} }
@ -10390,7 +10393,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
boolean P_SpectatorJoinGame(player_t *player) boolean P_SpectatorJoinGame(player_t *player)
{ {
if (gametype != GT_COOP && !cv_allowteamchange.value) if (!G_CoopGametype() && !cv_allowteamchange.value)
{ {
if (P_IsLocalPlayer(player)) if (P_IsLocalPlayer(player))
CONS_Printf(M_GetText("Server does not allow team change.\n")); CONS_Printf(M_GetText("Server does not allow team change.\n"));
@ -10472,7 +10475,7 @@ boolean P_SpectatorJoinGame(player_t *player)
player->spectator = player->outofcoop = false; player->spectator = player->outofcoop = false;
player->playerstate = PST_REBORN; player->playerstate = PST_REBORN;
if (gametype == GT_TAG) if ((gametyperules & (GTR_TAG|GTR_HIDEFROZEN)) == GTR_TAG)
{ {
//Make joining players "it" after hidetime. //Make joining players "it" after hidetime.
if (leveltime > (hidetime * TICRATE)) if (leveltime > (hidetime * TICRATE))
@ -10493,7 +10496,7 @@ boolean P_SpectatorJoinGame(player_t *player)
displayplayer = consoleplayer; displayplayer = consoleplayer;
} }
if (gametype != GT_COOP) if (!G_CoopGametype())
CONS_Printf(M_GetText("%s entered the game.\n"), player_names[player-players]); CONS_Printf(M_GetText("%s entered the game.\n"), player_names[player-players]);
return true; // no more player->mo, cannot continue. return true; // no more player->mo, cannot continue.
} }
@ -11520,7 +11523,7 @@ void P_PlayerThink(player_t *player)
// so we can fade music // so we can fade music
if (!exitfadestarted && if (!exitfadestarted &&
player->exiting > 0 && player->exiting <= 1*TICRATE && player->exiting > 0 && player->exiting <= 1*TICRATE &&
(!multiplayer || gametype == GT_COOP ? !mapheaderinfo[gamemap-1]->musinterfadeout : true) && (!multiplayer || G_CoopGametype() ? !mapheaderinfo[gamemap-1]->musinterfadeout : true) &&
// don't fade if we're fading during intermission. follows Y_StartIntermission intertype = int_coop // don't fade if we're fading during intermission. follows Y_StartIntermission intertype = int_coop
((gametyperules & GTR_RACE) ? countdown2 == 0 : true) && // don't fade on timeout ((gametyperules & GTR_RACE) ? countdown2 == 0 : true) && // don't fade on timeout
player->lives > 0 && // don't fade on game over (competition) player->lives > 0 && // don't fade on game over (competition)
@ -11593,7 +11596,7 @@ void P_PlayerThink(player_t *player)
if (player->pflags & PF_FINISHED) if (player->pflags & PF_FINISHED)
{ {
if ((gametype == GT_COOP && cv_exitmove.value) && !G_EnoughPlayersFinished()) if (((gametyperules & GTR_FRIENDLY) && cv_exitmove.value) && !G_EnoughPlayersFinished())
player->exiting = 0; player->exiting = 0;
else else
P_DoPlayerExit(player); P_DoPlayerExit(player);
@ -11627,10 +11630,10 @@ void P_PlayerThink(player_t *player)
// Make sure spectators always have a score and ring count of 0. // Make sure spectators always have a score and ring count of 0.
if (player->spectator) if (player->spectator)
{ {
if (gametype != GT_COOP) if (!(gametyperules & GTR_CAMPAIGN))
player->score = 0; player->score = 0;
} }
else if ((netgame || multiplayer) && player->lives <= 0 && gametype != GT_COOP) else if ((netgame || multiplayer) && player->lives <= 0 && !G_CoopGametype())
{ {
// Outside of Co-Op, replenish a user's lives if they are depleted. // Outside of Co-Op, replenish a user's lives if they are depleted.
// of course, this is just a cheap hack, meh... // of course, this is just a cheap hack, meh...
@ -12494,7 +12497,7 @@ void P_PlayerAfterThink(player_t *player)
player->mo->momz = tails->momz; player->mo->momz = tails->momz;
} }
if (gametype == GT_COOP && (!tails->player || tails->player->bot != 1)) if (G_CoopGametype() && (!tails->player || tails->player->bot != 1))
{ {
player->mo->angle = tails->angle; player->mo->angle = tails->angle;

View file

@ -798,6 +798,9 @@ static void R_AddPolyObjects(subsector_t *sub)
po = (polyobj_t *)(po->link.next); po = (polyobj_t *)(po->link.next);
} }
// for render stats
rs_numpolyobjects += numpolys;
// sort polyobjects // sort polyobjects
R_SortPolyObjects(sub); R_SortPolyObjects(sub);
@ -1235,6 +1238,9 @@ void R_RenderBSPNode(INT32 bspnum)
{ {
node_t *bsp; node_t *bsp;
INT32 side; INT32 side;
rs_numbspcalls++;
while (!(bspnum & NF_SUBSECTOR)) // Found a subsector? while (!(bspnum & NF_SUBSECTOR)) // Found a subsector?
{ {
bsp = &nodes[bspnum]; bsp = &nodes[bspnum];

View file

@ -242,9 +242,10 @@ UINT32 ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alph
fullalpha = 0xFF; fullalpha = 0xFF;
alpha = (UINT8)fullalpha; alpha = (UINT8)fullalpha;
// if the background pixel is empty, match software and don't blend anything // if the background pixel is empty,
// match software and don't blend anything
if (!background.s.alpha) if (!background.s.alpha)
output.rgba = 0; output.s.alpha = 0;
else else
{ {
UINT8 beta = (0xFF - alpha); UINT8 beta = (0xFF - alpha);

View file

@ -33,6 +33,8 @@
#include "z_zone.h" #include "z_zone.h"
#include "m_random.h" // quake camera shake #include "m_random.h" // quake camera shake
#include "r_portal.h" #include "r_portal.h"
#include "r_main.h"
#include "i_system.h" // I_GetTimeMicros
#ifdef HWRENDER #ifdef HWRENDER
#include "hardware/hw_main.h" #include "hardware/hw_main.h"
@ -97,6 +99,22 @@ lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ];
// Hack to support extra boom colormaps. // Hack to support extra boom colormaps.
extracolormap_t *extra_colormaps = NULL; extracolormap_t *extra_colormaps = NULL;
// Render stats
int rs_prevframetime = 0;
int rs_rendercalltime = 0;
int rs_swaptime = 0;
int rs_bsptime = 0;
int rs_sw_portaltime = 0;
int rs_sw_planetime = 0;
int rs_sw_maskedtime = 0;
int rs_numbspcalls = 0;
int rs_numsprites = 0;
int rs_numdrawnodes = 0;
int rs_numpolyobjects = 0;
static CV_PossibleValue_t drawdist_cons_t[] = { static CV_PossibleValue_t drawdist_cons_t[] = {
{256, "256"}, {512, "512"}, {768, "768"}, {256, "256"}, {512, "512"}, {768, "768"},
{1024, "1024"}, {1536, "1536"}, {2048, "2048"}, {1024, "1024"}, {1536, "1536"}, {2048, "2048"},
@ -147,6 +165,8 @@ consvar_t cv_homremoval = {"homremoval", "No", CV_SAVE, homremoval_cons_t, NULL,
consvar_t cv_maxportals = {"maxportals", "2", CV_SAVE, maxportals_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_maxportals = {"maxportals", "2", CV_SAVE, maxportals_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_renderstats = {"renderstats", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
void SplitScreen_OnChange(void) void SplitScreen_OnChange(void)
{ {
if (!cv_debug && netgame) if (!cv_debug && netgame)
@ -900,11 +920,6 @@ void R_ExecuteSetViewSize(void)
R_InitTextureMapping(); R_InitTextureMapping();
#ifdef HWRENDER
if (rendermode != render_soft)
HWR_InitTextureMapping();
#endif
// thing clipping // thing clipping
for (i = 0; i < viewwidth; i++) for (i = 0; i < viewwidth; i++)
screenheightarray[i] = (INT16)viewheight; screenheightarray[i] = (INT16)viewheight;
@ -1038,29 +1053,34 @@ subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y)
// R_SetupFrame // R_SetupFrame
// //
// WARNING: a should be unsigned but to add with 2048, it isn't!
#define AIMINGTODY(a) ((FINETANGENT((2048+(((INT32)a)>>ANGLETOFINESHIFT)) & FINEMASK)*160)/fovtan)
// recalc necessary stuff for mouseaiming // recalc necessary stuff for mouseaiming
// slopes are already calculated for the full possible view (which is 4*viewheight). // slopes are already calculated for the full possible view (which is 4*viewheight).
// 18/08/18: (No it's actually 16*viewheight, thanks Jimita for finding this out) // 18/08/18: (No it's actually 16*viewheight, thanks Jimita for finding this out)
static void R_SetupFreelook(void) static void R_SetupFreelook(void)
{ {
INT32 dy = 0; INT32 dy = 0;
if (rendermode == render_soft)
{
// clip it in the case we are looking a hardware 90 degrees full aiming // clip it in the case we are looking a hardware 90 degrees full aiming
// (lmps, network and use F12...) // (lmps, network and use F12...)
if (rendermode == render_soft
#ifdef HWRENDER
|| cv_grshearing.value
#endif
)
{
G_SoftwareClipAimingPitch((INT32 *)&aimingangle); G_SoftwareClipAimingPitch((INT32 *)&aimingangle);
dy = AIMINGTODY(aimingangle) * viewwidth/BASEVIDWIDTH; }
if (rendermode == render_soft)
{
dy = (AIMINGTODY(aimingangle)>>FRACBITS) * viewwidth/BASEVIDWIDTH;
yslope = &yslopetab[viewheight*8 - (viewheight/2 + dy)]; yslope = &yslopetab[viewheight*8 - (viewheight/2 + dy)];
} }
centery = (viewheight/2) + dy; centery = (viewheight/2) + dy;
centeryfrac = centery<<FRACBITS; centeryfrac = centery<<FRACBITS;
} }
#undef AIMINGTODY
void R_SetupFrame(player_t *player) void R_SetupFrame(player_t *player)
{ {
camera_t *thiscam; camera_t *thiscam;
@ -1305,6 +1325,38 @@ void R_SkyboxFrame(player_t *player)
R_SetupFreelook(); R_SetupFreelook();
} }
boolean R_ViewpointHasChasecam(player_t *player)
{
boolean chasecam = false;
if (splitscreen && player == &players[secondarydisplayplayer] && player != &players[consoleplayer])
chasecam = (cv_chasecam2.value != 0);
else
chasecam = (cv_chasecam.value != 0);
if (player->climbing || (player->powers[pw_carry] == CR_NIGHTSMODE) || player->playerstate == PST_DEAD || gamestate == GS_TITLESCREEN || tutorialmode)
chasecam = true; // force chasecam on
else if (player->spectator) // no spectator chasecam
chasecam = false; // force chasecam off
return chasecam;
}
boolean R_IsViewpointThirdPerson(player_t *player, boolean skybox)
{
boolean chasecam = R_ViewpointHasChasecam(player);
// cut-away view stuff
if (player->awayviewtics || skybox)
return chasecam;
// use outside cam view
else if (!player->spectator && chasecam)
return true;
// use the player's eyes view
return false;
}
static void R_PortalFrame(portal_t *portal) static void R_PortalFrame(portal_t *portal)
{ {
viewx = portal->viewx; viewx = portal->viewx;
@ -1410,7 +1462,11 @@ void R_RenderPlayerView(player_t *player)
mytotal = 0; mytotal = 0;
ProfZeroTimer(); ProfZeroTimer();
#endif #endif
rs_numbspcalls = rs_numpolyobjects = rs_numdrawnodes = 0;
rs_bsptime = I_GetTimeMicros();
R_RenderBSPNode((INT32)numnodes - 1); R_RenderBSPNode((INT32)numnodes - 1);
rs_bsptime = I_GetTimeMicros() - rs_bsptime;
rs_numsprites = visspritecount;
#ifdef TIMING #ifdef TIMING
RDMSR(0x10, &mycount); RDMSR(0x10, &mycount);
mytotal += mycount; // 64bit add mytotal += mycount; // 64bit add
@ -1428,6 +1484,7 @@ void R_RenderPlayerView(player_t *player)
Portal_AddSkyboxPortals(); Portal_AddSkyboxPortals();
// Portal rendering. Hijacks the BSP traversal. // Portal rendering. Hijacks the BSP traversal.
rs_sw_portaltime = I_GetTimeMicros();
if (portal_base) if (portal_base)
{ {
portal_t *portal; portal_t *portal;
@ -1467,15 +1524,20 @@ void R_RenderPlayerView(player_t *player)
Portal_Remove(portal); Portal_Remove(portal);
} }
} }
rs_sw_portaltime = I_GetTimeMicros() - rs_sw_portaltime;
rs_sw_planetime = I_GetTimeMicros();
R_DrawPlanes(); R_DrawPlanes();
#ifdef FLOORSPLATS #ifdef FLOORSPLATS
R_DrawVisibleFloorSplats(); R_DrawVisibleFloorSplats();
#endif #endif
rs_sw_planetime = I_GetTimeMicros() - rs_sw_planetime;
// draw mid texture and sprite // draw mid texture and sprite
// And now 3D floors/sides! // And now 3D floors/sides!
rs_sw_maskedtime = I_GetTimeMicros();
R_DrawMasked(masks, nummasks); R_DrawMasked(masks, nummasks);
rs_sw_maskedtime = I_GetTimeMicros() - rs_sw_maskedtime;
free(masks); free(masks);
} }

View file

@ -26,7 +26,10 @@ extern INT32 centerx, centery;
extern fixed_t centerxfrac, centeryfrac; extern fixed_t centerxfrac, centeryfrac;
extern fixed_t projection, projectiony; extern fixed_t projection, projectiony;
extern fixed_t fovtan; // field of view extern fixed_t fovtan;
// WARNING: a should be unsigned but to add with 2048, it isn't!
#define AIMINGTODY(a) FixedDiv((FINETANGENT((2048+(((INT32)a)>>ANGLETOFINESHIFT)) & FINEMASK)*160), fovtan)
extern size_t validcount, linecount, loopcount, framecount; extern size_t validcount, linecount, loopcount, framecount;
@ -71,6 +74,25 @@ subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y);
boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixed_t bottomh, fixed_t toph); boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixed_t bottomh, fixed_t toph);
// Render stats
extern consvar_t cv_renderstats;
extern int rs_prevframetime;// time when previous frame was rendered
extern int rs_rendercalltime;
extern int rs_swaptime;
extern int rs_bsptime;
extern int rs_sw_portaltime;
extern int rs_sw_planetime;
extern int rs_sw_maskedtime;
extern int rs_numbspcalls;
extern int rs_numsprites;
extern int rs_numdrawnodes;
extern int rs_numpolyobjects;
// //
// REFRESH - the actual rendering functions. // REFRESH - the actual rendering functions.
// //
@ -104,10 +126,13 @@ void R_SetViewSize(void);
// do it (sometimes explicitly called) // do it (sometimes explicitly called)
void R_ExecuteSetViewSize(void); void R_ExecuteSetViewSize(void);
void R_SetupFrame(player_t *player);
void R_SkyboxFrame(player_t *player); void R_SkyboxFrame(player_t *player);
void R_SetupFrame(player_t *player); boolean R_ViewpointHasChasecam(player_t *player);
// Called by G_Drawer. boolean R_IsViewpointThirdPerson(player_t *player, boolean skybox);
// Called by D_Display.
void R_RenderPlayerView(player_t *player); void R_RenderPlayerView(player_t *player);
// add commands related to engine, at game startup // add commands related to engine, at game startup

View file

@ -1367,6 +1367,8 @@ static void R_ProjectSprite(mobj_t *thing)
size_t frame, rot; size_t frame, rot;
UINT16 flip; UINT16 flip;
boolean vflip = (!(thing->eflags & MFE_VERTICALFLIP) != !(thing->frame & FF_VERTICALFLIP)); boolean vflip = (!(thing->eflags & MFE_VERTICALFLIP) != !(thing->frame & FF_VERTICALFLIP));
boolean mirrored = thing->mirrored;
boolean hflip = (!(thing->frame & FF_HORIZONTALFLIP) != !mirrored);
INT32 lindex; INT32 lindex;
@ -1477,7 +1479,11 @@ static void R_ProjectSprite(mobj_t *thing)
#endif #endif
if (sprframe->rotate != SRF_SINGLE || papersprite) if (sprframe->rotate != SRF_SINGLE || papersprite)
{
ang = R_PointToAngle (thing->x, thing->y) - (thing->player ? thing->player->drawangle : thing->angle); ang = R_PointToAngle (thing->x, thing->y) - (thing->player ? thing->player->drawangle : thing->angle);
if (mirrored)
ang = InvAngle(ang);
}
if (sprframe->rotate == SRF_SINGLE) if (sprframe->rotate == SRF_SINGLE)
{ {
@ -1537,6 +1543,8 @@ static void R_ProjectSprite(mobj_t *thing)
} }
#endif #endif
flip = !flip != !hflip;
// calculate edges of the shape // calculate edges of the shape
if (flip) if (flip)
offset = spr_offset - spr_width; offset = spr_offset - spr_width;
@ -2505,6 +2513,8 @@ static drawnode_t *R_CreateDrawNode(drawnode_t *link)
node->thickseg = NULL; node->thickseg = NULL;
node->ffloor = NULL; node->ffloor = NULL;
node->sprite = NULL; node->sprite = NULL;
rs_numdrawnodes++;
return node; return node;
} }

View file

@ -622,3 +622,51 @@ void SCR_ClosedCaptions(void)
va("%c [%s]", dot, (closedcaptions[i].s->caption[0] ? closedcaptions[i].s->caption : closedcaptions[i].s->name))); va("%c [%s]", dot, (closedcaptions[i].s->caption[0] ? closedcaptions[i].s->caption : closedcaptions[i].s->name)));
} }
} }
void SCR_DisplayMarathonInfo(void)
{
INT32 flags = V_SNAPTOBOTTOM;
static tic_t entertic, oldentertics = 0, antisplice[2] = {48,0};
const char *str;
#if 0 // eh, this probably isn't going to be a problem
if (((signed)marathontime) < 0)
{
flags |= V_REDMAP;
str = "No waiting out the clock to submit a bogus time.";
}
else
#endif
{
entertic = I_GetTime();
if (gamecomplete)
flags |= V_YELLOWMAP;
else if (marathonmode & MA_INGAME)
; // see also G_Ticker
else if (marathonmode & MA_INIT)
marathonmode &= ~MA_INIT;
else
marathontime += entertic - oldentertics;
// Create a sequence of primes such that their LCM is nice and big.
#define PRIMEV1 13
#define PRIMEV2 17 // I can't believe it! I'm on TV!
antisplice[0] += (entertic - oldentertics)*PRIMEV2;
antisplice[0] %= PRIMEV1*((vid.width/vid.dupx)+1);
antisplice[1] += (entertic - oldentertics)*PRIMEV1;
antisplice[1] %= PRIMEV1*((vid.width/vid.dupx)+1);
str = va("%i:%02i:%02i.%02i",
G_TicsToHours(marathontime),
G_TicsToMinutes(marathontime, false),
G_TicsToSeconds(marathontime),
G_TicsToCentiseconds(marathontime));
oldentertics = entertic;
}
V_DrawFill((antisplice[0]/PRIMEV1)-1, BASEVIDHEIGHT-8, 1, 8, V_SNAPTOBOTTOM|V_SNAPTOLEFT);
V_DrawFill((antisplice[0]/PRIMEV1), BASEVIDHEIGHT-8, 1, 8, V_SNAPTOBOTTOM|V_SNAPTOLEFT|31);
V_DrawFill(BASEVIDWIDTH-((antisplice[1]/PRIMEV1)-1), BASEVIDHEIGHT-8, 1, 8, V_SNAPTOBOTTOM|V_SNAPTORIGHT);
V_DrawFill(BASEVIDWIDTH-((antisplice[1]/PRIMEV1)), BASEVIDHEIGHT-8, 1, 8, V_SNAPTOBOTTOM|V_SNAPTORIGHT|31);
#undef PRIMEV1
#undef PRIMEV2
V_DrawPromptBack(-8, cons_backcolor.value);
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-8, flags, str);
}

View file

@ -206,5 +206,6 @@ FUNCMATH boolean SCR_IsAspectCorrect(INT32 width, INT32 height);
void SCR_DisplayTicRate(void); void SCR_DisplayTicRate(void);
void SCR_ClosedCaptions(void); void SCR_ClosedCaptions(void);
void SCR_DisplayLocalPing(void); void SCR_DisplayLocalPing(void);
void SCR_DisplayMarathonInfo(void);
#undef DNWH #undef DNWH
#endif //__SCREEN_H__ #endif //__SCREEN_H__

View file

@ -220,6 +220,7 @@
<ClInclude Include="..\hardware\hw3dsdrv.h" /> <ClInclude Include="..\hardware\hw3dsdrv.h" />
<ClInclude Include="..\hardware\hw3sound.h" /> <ClInclude Include="..\hardware\hw3sound.h" />
<ClInclude Include="..\hardware\hws_data.h" /> <ClInclude Include="..\hardware\hws_data.h" />
<ClInclude Include="..\hardware\hw_batching.h" />
<ClInclude Include="..\hardware\hw_clip.h" /> <ClInclude Include="..\hardware\hw_clip.h" />
<ClInclude Include="..\hardware\hw_data.h" /> <ClInclude Include="..\hardware\hw_data.h" />
<ClInclude Include="..\hardware\hw_defs.h" /> <ClInclude Include="..\hardware\hw_defs.h" />
@ -370,6 +371,7 @@
<ClCompile Include="..\g_game.c" /> <ClCompile Include="..\g_game.c" />
<ClCompile Include="..\g_input.c" /> <ClCompile Include="..\g_input.c" />
<ClCompile Include="..\hardware\hw3sound.c" /> <ClCompile Include="..\hardware\hw3sound.c" />
<ClCompile Include="..\hardware\hw_batching.c" />
<ClCompile Include="..\hardware\hw_bsp.c" /> <ClCompile Include="..\hardware\hw_bsp.c" />
<ClCompile Include="..\hardware\hw_cache.c" /> <ClCompile Include="..\hardware\hw_cache.c" />
<ClCompile Include="..\hardware\hw_clip.c" /> <ClCompile Include="..\hardware\hw_clip.c" />

View file

@ -219,6 +219,9 @@
<ClInclude Include="..\hardware\hws_data.h"> <ClInclude Include="..\hardware\hws_data.h">
<Filter>Hw_Hardware</Filter> <Filter>Hw_Hardware</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\hardware\hw_batching.h">
<Filter>Hw_Hardware</Filter>
</ClInclude>
<ClInclude Include="..\hardware\hw_clip.h"> <ClInclude Include="..\hardware\hw_clip.h">
<Filter>Hw_Hardware</Filter> <Filter>Hw_Hardware</Filter>
</ClInclude> </ClInclude>
@ -636,6 +639,9 @@
<ClCompile Include="..\hardware\hw3sound.c"> <ClCompile Include="..\hardware\hw3sound.c">
<Filter>Hw_Hardware</Filter> <Filter>Hw_Hardware</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\hardware\hw_batching.c">
<Filter>Hw_Hardware</Filter>
</ClCompile>
<ClCompile Include="..\hardware\hw_bsp.c"> <ClCompile Include="..\hardware\hw_bsp.c">
<Filter>Hw_Hardware</Filter> <Filter>Hw_Hardware</Filter>
</ClCompile> </ClCompile>

View file

@ -76,13 +76,16 @@ void *hwSym(const char *funcName,void *handle)
#ifdef HWRENDER #ifdef HWRENDER
if (0 == strcmp("SetPalette", funcName)) if (0 == strcmp("SetPalette", funcName))
funcPointer = &OglSdlSetPalette; funcPointer = &OglSdlSetPalette;
GETFUNC(Init); GETFUNC(Init);
GETFUNC(Draw2DLine); GETFUNC(Draw2DLine);
GETFUNC(DrawPolygon); GETFUNC(DrawPolygon);
GETFUNC(DrawIndexedTriangles);
GETFUNC(RenderSkyDome); GETFUNC(RenderSkyDome);
GETFUNC(SetBlend); GETFUNC(SetBlend);
GETFUNC(ClearBuffer); GETFUNC(ClearBuffer);
GETFUNC(SetTexture); GETFUNC(SetTexture);
GETFUNC(UpdateTexture);
GETFUNC(ReadRect); GETFUNC(ReadRect);
GETFUNC(GClipRect); GETFUNC(GClipRect);
GETFUNC(ClearMipMapCache); GETFUNC(ClearMipMapCache);
@ -91,7 +94,6 @@ void *hwSym(const char *funcName,void *handle)
GETFUNC(DrawModel); GETFUNC(DrawModel);
GETFUNC(CreateModelVBOs); GETFUNC(CreateModelVBOs);
GETFUNC(SetTransform); GETFUNC(SetTransform);
GETFUNC(GetRenderVersion);
GETFUNC(PostImgRedraw); GETFUNC(PostImgRedraw);
GETFUNC(FlushScreenTextures); GETFUNC(FlushScreenTextures);
GETFUNC(StartScreenWipe); GETFUNC(StartScreenWipe);
@ -101,6 +103,16 @@ void *hwSym(const char *funcName,void *handle)
GETFUNC(MakeScreenTexture); GETFUNC(MakeScreenTexture);
GETFUNC(MakeScreenFinalTexture); GETFUNC(MakeScreenFinalTexture);
GETFUNC(DrawScreenFinalTexture); GETFUNC(DrawScreenFinalTexture);
GETFUNC(LoadShaders);
GETFUNC(KillShaders);
GETFUNC(SetShader);
GETFUNC(UnSetShader);
GETFUNC(SetShaderInfo);
GETFUNC(LoadCustomShader);
GETFUNC(InitCustomShaders);
#else //HWRENDER #else //HWRENDER
if (0 == strcmp("FinishUpdate", funcName)) if (0 == strcmp("FinishUpdate", funcName))
return funcPointer; //&FinishUpdate; return funcPointer; //&FinishUpdate;

View file

@ -54,6 +54,12 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T);
#include <fcntl.h> #include <fcntl.h>
#endif #endif
#if defined (_WIN32)
DWORD TimeFunction(int requested_frequency);
#else
int TimeFunction(int requested_frequency);
#endif
#include <stdio.h> #include <stdio.h>
#ifdef _WIN32 #ifdef _WIN32
#include <conio.h> #include <conio.h>
@ -2063,9 +2069,11 @@ static p_timeGetTime pfntimeGetTime = NULL;
// but lower precision on Windows NT // but lower precision on Windows NT
// --------- // ---------
tic_t I_GetTime(void) DWORD TimeFunction(int requested_frequency)
{ {
tic_t newtics = 0; DWORD newtics = 0;
// this var acts as a multiplier if sub-millisecond precision is asked but is not available
int excess_frequency = requested_frequency / 1000;
if (!starttickcount) // high precision timer if (!starttickcount) // high precision timer
{ {
@ -2085,7 +2093,7 @@ tic_t I_GetTime(void)
if (frequency.LowPart && QueryPerformanceCounter(&currtime)) if (frequency.LowPart && QueryPerformanceCounter(&currtime))
{ {
newtics = (INT32)((currtime.QuadPart - basetime.QuadPart) * NEWTICRATE newtics = (INT32)((currtime.QuadPart - basetime.QuadPart) * requested_frequency
/ frequency.QuadPart); / frequency.QuadPart);
} }
else if (pfntimeGetTime) else if (pfntimeGetTime)
@ -2093,11 +2101,19 @@ tic_t I_GetTime(void)
currtime.LowPart = pfntimeGetTime(); currtime.LowPart = pfntimeGetTime();
if (!basetime.LowPart) if (!basetime.LowPart)
basetime.LowPart = currtime.LowPart; basetime.LowPart = currtime.LowPart;
newtics = ((currtime.LowPart - basetime.LowPart)/(1000/NEWTICRATE)); if (requested_frequency > 1000)
newtics = currtime.LowPart - basetime.LowPart * excess_frequency;
else
newtics = (currtime.LowPart - basetime.LowPart)/(1000/requested_frequency);
} }
} }
else else
newtics = (GetTickCount() - starttickcount)/(1000/NEWTICRATE); {
if (requested_frequency > 1000)
newtics = (GetTickCount() - starttickcount) * excess_frequency;
else
newtics = (GetTickCount() - starttickcount)/(1000/requested_frequency);
}
return newtics; return newtics;
} }
@ -2119,7 +2135,9 @@ static void I_ShutdownTimer(void)
// I_GetTime // I_GetTime
// returns time in 1/TICRATE second tics // returns time in 1/TICRATE second tics
// //
tic_t I_GetTime (void)
// millisecond precision only
int TimeFunction(int requested_frequency)
{ {
static Uint64 basetime = 0; static Uint64 basetime = 0;
Uint64 ticks = SDL_GetTicks(); Uint64 ticks = SDL_GetTicks();
@ -2129,14 +2147,24 @@ tic_t I_GetTime (void)
ticks -= basetime; ticks -= basetime;
ticks = (ticks*TICRATE); ticks = (ticks*requested_frequency);
ticks = (ticks/1000); ticks = (ticks/1000);
return (tic_t)ticks; return ticks;
} }
#endif #endif
tic_t I_GetTime(void)
{
return TimeFunction(NEWTICRATE);
}
int I_GetTimeMicros(void)
{
return TimeFunction(1000000);
}
// //
//I_StartupTimer //I_StartupTimer
// //

View file

@ -73,6 +73,7 @@
#include "../console.h" #include "../console.h"
#include "../command.h" #include "../command.h"
#include "../r_main.h" #include "../r_main.h"
#include "../lua_hook.h"
#include "sdlmain.h" #include "sdlmain.h"
#ifdef HWRENDER #ifdef HWRENDER
#include "../hardware/hw_main.h" #include "../hardware/hw_main.h"
@ -357,11 +358,7 @@ static INT32 Impl_SDL_Scancode_To_Keycode(SDL_Scancode code)
case SDL_SCANCODE_RGUI: return KEY_RIGHTWIN; case SDL_SCANCODE_RGUI: return KEY_RIGHTWIN;
default: break; default: break;
} }
#ifdef HWRENDER
DBG_Printf("Unknown incoming scancode: %d, represented %c\n",
code,
SDL_GetKeyName(SDL_GetKeyFromScancode(code)));
#endif
return 0; return 0;
} }
@ -1061,8 +1058,9 @@ void I_GetEvent(void)
M_SetupJoystickMenu(0); M_SetupJoystickMenu(0);
break; break;
case SDL_QUIT: case SDL_QUIT:
if (Playing())
LUAh_GameQuit();
I_Quit(); I_Quit();
M_QuitResponse('y');
break; break;
} }
} }
@ -1204,6 +1202,9 @@ void I_FinishUpdate(void)
if (I_SkipFrame()) if (I_SkipFrame())
return; return;
if (marathonmode)
SCR_DisplayMarathonInfo();
// draw captions if enabled // draw captions if enabled
if (cv_closedcaptioning.value) if (cv_closedcaptioning.value)
SCR_ClosedCaptions(); SCR_ClosedCaptions();
@ -1480,6 +1481,7 @@ void VID_CheckGLLoaded(rendermode_t oldrender)
#ifdef HWRENDER #ifdef HWRENDER
if (vid_opengl_state == -1) // Well, it didn't work the first time anyway. if (vid_opengl_state == -1) // Well, it didn't work the first time anyway.
{ {
CONS_Alert(CONS_ERROR, "OpenGL never loaded\n");
rendermode = oldrender; rendermode = oldrender;
if (chosenrendermode == render_opengl) // fallback to software if (chosenrendermode == render_opengl) // fallback to software
rendermode = render_soft; rendermode = render_soft;
@ -1828,10 +1830,12 @@ void VID_StartupOpenGL(void)
HWD.pfnFinishUpdate = NULL; HWD.pfnFinishUpdate = NULL;
HWD.pfnDraw2DLine = hwSym("Draw2DLine",NULL); HWD.pfnDraw2DLine = hwSym("Draw2DLine",NULL);
HWD.pfnDrawPolygon = hwSym("DrawPolygon",NULL); HWD.pfnDrawPolygon = hwSym("DrawPolygon",NULL);
HWD.pfnDrawIndexedTriangles = hwSym("DrawIndexedTriangles",NULL);
HWD.pfnRenderSkyDome = hwSym("RenderSkyDome",NULL); HWD.pfnRenderSkyDome = hwSym("RenderSkyDome",NULL);
HWD.pfnSetBlend = hwSym("SetBlend",NULL); HWD.pfnSetBlend = hwSym("SetBlend",NULL);
HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL); HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL);
HWD.pfnSetTexture = hwSym("SetTexture",NULL); HWD.pfnSetTexture = hwSym("SetTexture",NULL);
HWD.pfnUpdateTexture = hwSym("UpdateTexture",NULL);
HWD.pfnReadRect = hwSym("ReadRect",NULL); HWD.pfnReadRect = hwSym("ReadRect",NULL);
HWD.pfnGClipRect = hwSym("GClipRect",NULL); HWD.pfnGClipRect = hwSym("GClipRect",NULL);
HWD.pfnClearMipMapCache = hwSym("ClearMipMapCache",NULL); HWD.pfnClearMipMapCache = hwSym("ClearMipMapCache",NULL);
@ -1841,7 +1845,6 @@ void VID_StartupOpenGL(void)
HWD.pfnDrawModel = hwSym("DrawModel",NULL); HWD.pfnDrawModel = hwSym("DrawModel",NULL);
HWD.pfnCreateModelVBOs = hwSym("CreateModelVBOs",NULL); HWD.pfnCreateModelVBOs = hwSym("CreateModelVBOs",NULL);
HWD.pfnSetTransform = hwSym("SetTransform",NULL); HWD.pfnSetTransform = hwSym("SetTransform",NULL);
HWD.pfnGetRenderVersion = hwSym("GetRenderVersion",NULL);
HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL); HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL);
HWD.pfnFlushScreenTextures=hwSym("FlushScreenTextures",NULL); HWD.pfnFlushScreenTextures=hwSym("FlushScreenTextures",NULL);
HWD.pfnStartScreenWipe = hwSym("StartScreenWipe",NULL); HWD.pfnStartScreenWipe = hwSym("StartScreenWipe",NULL);
@ -1852,14 +1855,16 @@ void VID_StartupOpenGL(void)
HWD.pfnMakeScreenFinalTexture=hwSym("MakeScreenFinalTexture",NULL); HWD.pfnMakeScreenFinalTexture=hwSym("MakeScreenFinalTexture",NULL);
HWD.pfnDrawScreenFinalTexture=hwSym("DrawScreenFinalTexture",NULL); HWD.pfnDrawScreenFinalTexture=hwSym("DrawScreenFinalTexture",NULL);
// check gl renderer lib HWD.pfnLoadShaders = hwSym("LoadShaders",NULL);
if (HWD.pfnGetRenderVersion() != VERSION) HWD.pfnKillShaders = hwSym("KillShaders",NULL);
{ HWD.pfnSetShader = hwSym("SetShader",NULL);
CONS_Alert(CONS_ERROR, M_GetText("The version of the renderer doesn't match the version of the executable!\nBe sure you have installed SRB2 properly.\n")); HWD.pfnUnSetShader = hwSym("UnSetShader",NULL);
vid_opengl_state = -1;
} HWD.pfnSetShaderInfo = hwSym("SetShaderInfo",NULL);
else HWD.pfnLoadCustomShader = hwSym("LoadCustomShader",NULL);
vid_opengl_state = HWD.pfnInit(I_Error) ? 1 : -1; // let load the OpenGL library HWD.pfnInitCustomShaders= hwSym("InitCustomShaders",NULL);
vid_opengl_state = HWD.pfnInit() ? 1 : -1; // let load the OpenGL library
if (vid_opengl_state == -1) if (vid_opengl_state == -1)
{ {

View file

@ -219,6 +219,28 @@ static void var_cleanup(void)
internal_volume = 100; internal_volume = 100;
} }
static const char* get_zlib_error(int zErr)
{
switch (zErr)
{
case Z_ERRNO:
return "Z_ERRNO";
case Z_STREAM_ERROR:
return "Z_STREAM_ERROR";
case Z_DATA_ERROR:
return "Z_DATA_ERROR";
case Z_MEM_ERROR:
return "Z_MEM_ERROR";
case Z_BUF_ERROR:
return "Z_BUF_ERROR";
case Z_VERSION_ERROR:
return "Z_VERSION_ERROR";
default:
return "unknown error";
}
}
/// ------------------------ /// ------------------------
/// Audio System /// Audio System
/// ------------------------ /// ------------------------
@ -475,7 +497,7 @@ void *I_GetSfx(sfxinfo_t *sfx)
zErr = inflate(&stream, Z_FINISH); zErr = inflate(&stream, Z_FINISH);
if (zErr == Z_STREAM_END) { if (zErr == Z_STREAM_END) {
// Run GME on new data // Run GME on new data
if (!gme_open_data(inflatedData, inflatedLen, &emu, 44100)) if (!gme_open_data(inflatedData, inflatedLen, &emu, SAMPLERATE))
{ {
short *mem; short *mem;
UINT32 len; UINT32 len;
@ -498,58 +520,18 @@ void *I_GetSfx(sfxinfo_t *sfx)
} }
} }
else else
{ CONS_Alert(CONS_ERROR,"Encountered %s when running inflate: %s\n", get_zlib_error(zErr), stream.msg);
const char *errorType;
switch (zErr)
{
case Z_ERRNO:
errorType = "Z_ERRNO"; break;
case Z_STREAM_ERROR:
errorType = "Z_STREAM_ERROR"; break;
case Z_DATA_ERROR:
errorType = "Z_DATA_ERROR"; break;
case Z_MEM_ERROR:
errorType = "Z_MEM_ERROR"; break;
case Z_BUF_ERROR:
errorType = "Z_BUF_ERROR"; break;
case Z_VERSION_ERROR:
errorType = "Z_VERSION_ERROR"; break;
default:
errorType = "unknown error";
}
CONS_Alert(CONS_ERROR,"Encountered %s when running inflate: %s\n", errorType, stream.msg);
}
(void)inflateEnd(&stream); (void)inflateEnd(&stream);
} }
else // Hold up, zlib's got a problem else // Hold up, zlib's got a problem
{ CONS_Alert(CONS_ERROR,"Encountered %s when running inflateInit: %s\n", get_zlib_error(zErr), stream.msg);
const char *errorType;
switch (zErr)
{
case Z_ERRNO:
errorType = "Z_ERRNO"; break;
case Z_STREAM_ERROR:
errorType = "Z_STREAM_ERROR"; break;
case Z_DATA_ERROR:
errorType = "Z_DATA_ERROR"; break;
case Z_MEM_ERROR:
errorType = "Z_MEM_ERROR"; break;
case Z_BUF_ERROR:
errorType = "Z_BUF_ERROR"; break;
case Z_VERSION_ERROR:
errorType = "Z_VERSION_ERROR"; break;
default:
errorType = "unknown error";
}
CONS_Alert(CONS_ERROR,"Encountered %s when running inflateInit: %s\n", errorType, stream.msg);
}
Z_Free(inflatedData); // GME didn't open jack, but don't let that stop us from freeing this up Z_Free(inflatedData); // GME didn't open jack, but don't let that stop us from freeing this up
#else #else
return NULL; // No zlib support return NULL; // No zlib support
#endif #endif
} }
// Try to read it as a GME sound // Try to read it as a GME sound
else if (!gme_open_data(lump, sfx->length, &emu, 44100)) else if (!gme_open_data(lump, sfx->length, &emu, SAMPLERATE))
{ {
short *mem; short *mem;
UINT32 len; UINT32 len;
@ -1175,77 +1157,30 @@ boolean I_LoadSong(char *data, size_t len)
if (zErr == Z_OK) // We're good to go if (zErr == Z_OK) // We're good to go
{ {
zErr = inflate(&stream, Z_FINISH); zErr = inflate(&stream, Z_FINISH);
if (zErr == Z_STREAM_END) { if (zErr == Z_STREAM_END)
// Run GME on new data {
if (!gme_open_data(inflatedData, inflatedLen, &gme, 44100)) // Run GME on new data
if (!gme_open_data(inflatedData, inflatedLen, &gme, SAMPLERATE))
{ {
gme_equalizer_t eq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0};
gme_start_track(gme, 0);
current_track = 0;
gme_set_equalizer(gme, &eq);
Mix_HookMusic(mix_gme, gme);
Z_Free(inflatedData); // GME supposedly makes a copy for itself, so we don't need this lying around Z_Free(inflatedData); // GME supposedly makes a copy for itself, so we don't need this lying around
return true; return true;
} }
} }
else else
{ CONS_Alert(CONS_ERROR, "Encountered %s when running inflate: %s\n", get_zlib_error(zErr), stream.msg);
const char *errorType;
switch (zErr)
{
case Z_ERRNO:
errorType = "Z_ERRNO"; break;
case Z_STREAM_ERROR:
errorType = "Z_STREAM_ERROR"; break;
case Z_DATA_ERROR:
errorType = "Z_DATA_ERROR"; break;
case Z_MEM_ERROR:
errorType = "Z_MEM_ERROR"; break;
case Z_BUF_ERROR:
errorType = "Z_BUF_ERROR"; break;
case Z_VERSION_ERROR:
errorType = "Z_VERSION_ERROR"; break;
default:
errorType = "unknown error";
}
CONS_Alert(CONS_ERROR,"Encountered %s when running inflate: %s\n", errorType, stream.msg);
}
(void)inflateEnd(&stream); (void)inflateEnd(&stream);
} }
else // Hold up, zlib's got a problem else // Hold up, zlib's got a problem
{ CONS_Alert(CONS_ERROR, "Encountered %s when running inflateInit: %s\n", get_zlib_error(zErr), stream.msg);
const char *errorType;
switch (zErr)
{
case Z_ERRNO:
errorType = "Z_ERRNO"; break;
case Z_STREAM_ERROR:
errorType = "Z_STREAM_ERROR"; break;
case Z_DATA_ERROR:
errorType = "Z_DATA_ERROR"; break;
case Z_MEM_ERROR:
errorType = "Z_MEM_ERROR"; break;
case Z_BUF_ERROR:
errorType = "Z_BUF_ERROR"; break;
case Z_VERSION_ERROR:
errorType = "Z_VERSION_ERROR"; break;
default:
errorType = "unknown error";
}
CONS_Alert(CONS_ERROR,"Encountered %s when running inflateInit: %s\n", errorType, stream.msg);
}
Z_Free(inflatedData); // GME didn't open jack, but don't let that stop us from freeing this up Z_Free(inflatedData); // GME didn't open jack, but don't let that stop us from freeing this up
return false;
#else #else
CONS_Alert(CONS_ERROR, "Cannot decompress VGZ; no zlib support\n"); CONS_Alert(CONS_ERROR, "Cannot decompress VGZ; no zlib support\n");
return true; return false;
#endif #endif
} }
else if (!gme_open_data(data, len, &gme, 44100)) else if (!gme_open_data(data, len, &gme, SAMPLERATE))
{
gme_equalizer_t eq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0};
gme_set_equalizer(gme, &eq);
return true; return true;
}
#endif #endif
#ifdef HAVE_MIXERX #ifdef HAVE_MIXERX
@ -1360,6 +1295,8 @@ boolean I_PlaySong(boolean looping)
#ifdef HAVE_LIBGME #ifdef HAVE_LIBGME
if (gme) if (gme)
{ {
gme_equalizer_t eq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0};
gme_set_equalizer(gme, &eq);
gme_start_track(gme, 0); gme_start_track(gme, 0);
current_track = 0; current_track = 0;
Mix_HookMusic(mix_gme, gme); Mix_HookMusic(mix_gme, gme);

View file

@ -37,6 +37,7 @@
#ifdef HWRENDER #ifdef HWRENDER
#include "../hardware/r_opengl/r_opengl.h" #include "../hardware/r_opengl/r_opengl.h"
#include "../hardware/hw_main.h"
#include "ogl_sdl.h" #include "ogl_sdl.h"
#include "../i_system.h" #include "../i_system.h"
#include "hwsym_sdl.h" #include "hwsym_sdl.h"
@ -98,7 +99,7 @@ boolean LoadGL(void)
CONS_Alert(CONS_ERROR, "Could not load OpenGL Library: %s\n" CONS_Alert(CONS_ERROR, "Could not load OpenGL Library: %s\n"
"Falling back to Software mode.\n", SDL_GetError()); "Falling back to Software mode.\n", SDL_GetError());
if (!M_CheckParm("-OGLlib")) if (!M_CheckParm("-OGLlib"))
CONS_Alert(CONS_ERROR, "If you know what is the OpenGL library's name, use -OGLlib\n"); CONS_Printf("If you know what is the OpenGL library's name, use -OGLlib\n");
return 0; return 0;
} }
@ -152,31 +153,29 @@ boolean LoadGL(void)
*/ */
boolean OglSdlSurface(INT32 w, INT32 h) boolean OglSdlSurface(INT32 w, INT32 h)
{ {
INT32 cbpp; INT32 cbpp = cv_scr_depth.value < 16 ? 16 : cv_scr_depth.value;
const GLvoid *glvendor = NULL, *glrenderer = NULL, *glversion = NULL; static boolean first_init = false;
cbpp = cv_scr_depth.value < 16 ? 16 : cv_scr_depth.value; oglflags = 0;
glvendor = pglGetString(GL_VENDOR); if (!first_init)
// Get info and extensions. {
//BP: why don't we make it earlier ? gl_version = pglGetString(GL_VERSION);
//Hurdler: we cannot do that before intialising gl context gl_renderer = pglGetString(GL_RENDERER);
glrenderer = pglGetString(GL_RENDERER);
glversion = pglGetString(GL_VERSION);
gl_extensions = pglGetString(GL_EXTENSIONS); gl_extensions = pglGetString(GL_EXTENSIONS);
DBG_Printf("Vendor : %s\n", glvendor); GL_DBG_Printf("OpenGL %s\n", gl_version);
DBG_Printf("Renderer : %s\n", glrenderer); GL_DBG_Printf("GPU: %s\n", gl_renderer);
DBG_Printf("Version : %s\n", glversion); GL_DBG_Printf("Extensions: %s\n", gl_extensions);
DBG_Printf("Extensions : %s\n", gl_extensions); }
oglflags = 0; first_init = true;
if (isExtAvailable("GL_EXT_texture_filter_anisotropic", gl_extensions)) if (isExtAvailable("GL_EXT_texture_filter_anisotropic", gl_extensions))
pglGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maximumAnisotropy); pglGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maximumAnisotropy);
else else
maximumAnisotropy = 1; maximumAnisotropy = 1;
SetupGLFunc13(); SetupGLFunc4();
granisotropicmode_cons_t[1].value = maximumAnisotropy; granisotropicmode_cons_t[1].value = maximumAnisotropy;

View file

@ -763,7 +763,7 @@ static void ST_drawTime(void)
ST_DrawPatchFromHud(HUD_TIMECOLON, sbocolon, V_HUDTRANS); // Colon ST_DrawPatchFromHud(HUD_TIMECOLON, sbocolon, V_HUDTRANS); // Colon
ST_DrawPadNumFromHud(HUD_SECONDS, seconds, 2, V_HUDTRANS); // Seconds ST_DrawPadNumFromHud(HUD_SECONDS, seconds, 2, V_HUDTRANS); // Seconds
if (cv_timetic.value == 1 || cv_timetic.value == 2 || modeattacking) // there's not enough room for tics in splitscreen, don't even bother trying! if (cv_timetic.value == 1 || cv_timetic.value == 2 || modeattacking || marathonmode)
{ {
ST_DrawPatchFromHud(HUD_TIMETICCOLON, sboperiod, V_HUDTRANS); // Period ST_DrawPatchFromHud(HUD_TIMETICCOLON, sboperiod, V_HUDTRANS); // Period
ST_DrawPadNumFromHud(HUD_TICS, tictrn, 2, V_HUDTRANS); // Tics ST_DrawPadNumFromHud(HUD_TICS, tictrn, 2, V_HUDTRANS); // Tics
@ -1450,7 +1450,7 @@ static void ST_drawPowerupHUD(void)
// --------- // ---------
// Let's have a power-like icon to represent finishing the level! // Let's have a power-like icon to represent finishing the level!
if (stplyr->pflags & PF_FINISHED && cv_exitmove.value) if (stplyr->pflags & PF_FINISHED && cv_exitmove.value && multiplayer)
{ {
finishoffs[q] = ICONSEP; finishoffs[q] = ICONSEP;
V_DrawSmallScaledPatch(offs, hudinfo[HUD_POWERUPS].y, V_PERPLAYER|hudinfo[HUD_POWERUPS].f|V_HUDTRANS, fnshico); V_DrawSmallScaledPatch(offs, hudinfo[HUD_POWERUPS].y, V_PERPLAYER|hudinfo[HUD_POWERUPS].f|V_HUDTRANS, fnshico);
@ -2215,7 +2215,7 @@ static void ST_drawTextHUD(void)
if (F_GetPromptHideHud(y)) if (F_GetPromptHideHud(y))
return; return;
if (stplyr->spectator && (gametype != GT_COOP || stplyr->playerstate == PST_LIVE)) if (stplyr->spectator && (!G_CoopGametype() || stplyr->playerstate == PST_LIVE))
textHUDdraw(M_GetText("\x86""Spectator mode:")) textHUDdraw(M_GetText("\x86""Spectator mode:"))
if (circuitmap) if (circuitmap)
@ -2226,7 +2226,7 @@ static void ST_drawTextHUD(void)
textHUDdraw(va("Lap:""\x82 %u/%d", stplyr->laps+1, cv_numlaps.value)) textHUDdraw(va("Lap:""\x82 %u/%d", stplyr->laps+1, cv_numlaps.value))
} }
if (gametype != GT_COOP && (stplyr->exiting || (G_GametypeUsesLives() && stplyr->lives <= 0 && countdown != 1))) if (!G_CoopGametype() && (stplyr->exiting || (G_GametypeUsesLives() && stplyr->lives <= 0 && countdown != 1)))
{ {
if (!splitscreen && !donef12) if (!splitscreen && !donef12)
{ {
@ -2243,7 +2243,7 @@ static void ST_drawTextHUD(void)
else else
textHUDdraw(M_GetText("\x82""JUMP:""\x80 Respawn")) textHUDdraw(M_GetText("\x82""JUMP:""\x80 Respawn"))
} }
else if (stplyr->spectator && (gametype != GT_COOP || stplyr->playerstate == PST_LIVE)) else if (stplyr->spectator && (!G_CoopGametype() || stplyr->playerstate == PST_LIVE))
{ {
if (!splitscreen && !donef12) if (!splitscreen && !donef12)
{ {
@ -2290,7 +2290,7 @@ static void ST_drawTextHUD(void)
textHUDdraw(M_GetText("\x82""FIRE:""\x80 Enter game")) textHUDdraw(M_GetText("\x82""FIRE:""\x80 Enter game"))
} }
if (gametype == GT_COOP && (!stplyr->spectator || (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap))) && (stplyr->exiting || (stplyr->pflags & PF_FINISHED))) if (G_CoopGametype() && (!stplyr->spectator || (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap))) && (stplyr->exiting || (stplyr->pflags & PF_FINISHED)))
{ {
UINT8 numneeded = (G_IsSpecialStage(gamemap) ? 4 : cv_playersforexit.value); UINT8 numneeded = (G_IsSpecialStage(gamemap) ? 4 : cv_playersforexit.value);
if (numneeded) if (numneeded)
@ -2339,19 +2339,18 @@ static void ST_drawTextHUD(void)
textHUDdraw(M_GetText("\x82""You are blindfolded!")) textHUDdraw(M_GetText("\x82""You are blindfolded!"))
textHUDdraw(M_GetText("Waiting for players to hide...")) textHUDdraw(M_GetText("Waiting for players to hide..."))
} }
else if (gametype == GT_HIDEANDSEEK) else if (gametyperules & GTR_HIDEFROZEN)
textHUDdraw(M_GetText("Hide before time runs out!")) textHUDdraw(M_GetText("Hide before time runs out!"))
else else
textHUDdraw(M_GetText("Flee before you are hunted!")) textHUDdraw(M_GetText("Flee before you are hunted!"))
} }
else if (gametype == GT_HIDEANDSEEK && !(stplyr->pflags & PF_TAGIT)) else if ((gametyperules & GTR_HIDEFROZEN) && !(stplyr->pflags & PF_TAGIT))
{ {
if (!splitscreen && !donef12) if (!splitscreen && !donef12)
{ {
textHUDdraw(M_GetText("\x82""VIEWPOINT:""\x80 Switch view")) textHUDdraw(M_GetText("\x82""VIEWPOINT:""\x80 Switch view"))
donef12 = true; donef12 = true;
} }
if (gametyperules & GTR_HIDEFROZEN)
textHUDdraw(M_GetText("You cannot move while hiding.")) textHUDdraw(M_GetText("You cannot move while hiding."))
} }
} }
@ -2628,11 +2627,11 @@ static void ST_overlayDrawer(void)
} }
// GAME OVER hud // GAME OVER hud
if ((gametype == GT_COOP) if (G_GametypeUsesCoopLives()
&& (netgame || multiplayer) && (netgame || multiplayer)
&& (cv_cooplives.value == 0)) && (cv_cooplives.value == 0))
; ;
else if ((G_GametypeUsesLives() || gametype == GT_RACE) && stplyr->lives <= 0 && !(hu_showscores && (netgame || multiplayer))) else if ((G_GametypeUsesLives() || ((gametyperules & (GTR_RACE|GTR_LIVES)) == GTR_RACE)) && stplyr->lives <= 0 && !(hu_showscores && (netgame || multiplayer)))
{ {
INT32 i = MAXPLAYERS; INT32 i = MAXPLAYERS;
INT32 deadtimer = stplyr->spectator ? TICRATE : (stplyr->deadtimer-(TICRATE<<1)); INT32 deadtimer = stplyr->spectator ? TICRATE : (stplyr->deadtimer-(TICRATE<<1));

View file

@ -418,7 +418,7 @@ void V_SetPalette(INT32 palettenum)
LoadMapPalette(); LoadMapPalette();
#ifdef HWRENDER #ifdef HWRENDER
if (rendermode != render_soft && rendermode != render_none) if (rendermode == render_opengl)
HWR_SetPalette(&pLocalPalette[palettenum*256]); HWR_SetPalette(&pLocalPalette[palettenum*256]);
#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) #if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL)
else else
@ -432,7 +432,7 @@ void V_SetPaletteLump(const char *pal)
{ {
LoadPalette(pal); LoadPalette(pal);
#ifdef HWRENDER #ifdef HWRENDER
if (rendermode != render_soft && rendermode != render_none) if (rendermode == render_opengl)
HWR_SetPalette(pLocalPalette); HWR_SetPalette(pLocalPalette);
#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) #if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL)
else else
@ -529,7 +529,7 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca
#ifdef HWRENDER #ifdef HWRENDER
//if (rendermode != render_soft && !con_startup) // Why? //if (rendermode != render_soft && !con_startup) // Why?
if (rendermode != render_soft) if (rendermode == render_opengl)
{ {
HWR_DrawStretchyFixedPatch((GLPatch_t *)patch, x, y, pscale, vscale, scrn, colormap); HWR_DrawStretchyFixedPatch((GLPatch_t *)patch, x, y, pscale, vscale, scrn, colormap);
return; return;
@ -829,7 +829,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_
#ifdef HWRENDER #ifdef HWRENDER
//if (rendermode != render_soft && !con_startup) // Not this again //if (rendermode != render_soft && !con_startup) // Not this again
if (rendermode != render_soft) if (rendermode == render_opengl)
{ {
HWR_DrawCroppedPatch((GLPatch_t*)patch,x,y,pscale,scrn,sx,sy,w,h); HWR_DrawCroppedPatch((GLPatch_t*)patch,x,y,pscale,scrn,sx,sy,w,h);
return; return;
@ -1153,7 +1153,7 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
#ifdef HWRENDER #ifdef HWRENDER
//if (rendermode != render_soft && !con_startup) // Not this again //if (rendermode != render_soft && !con_startup) // Not this again
if (rendermode != render_soft) if (rendermode == render_opengl)
{ {
HWR_DrawFill(x, y, w, h, c); HWR_DrawFill(x, y, w, h, c);
return; return;
@ -1350,7 +1350,7 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
return; return;
#ifdef HWRENDER #ifdef HWRENDER
if (rendermode != render_soft && rendermode != render_none) if (rendermode == render_opengl)
{ {
UINT32 hwcolor = V_GetHWConsBackColor(); UINT32 hwcolor = V_GetHWConsBackColor();
HWR_DrawConsoleFill(x, y, w, h, c, hwcolor); // we still use the regular color stuff but only for flags. actual draw color is "hwcolor" for this. HWR_DrawConsoleFill(x, y, w, h, c, hwcolor); // we still use the regular color stuff but only for flags. actual draw color is "hwcolor" for this.
@ -1547,7 +1547,7 @@ void V_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c, UINT16 color, U
return; return;
#ifdef HWRENDER #ifdef HWRENDER
if (rendermode != render_soft && rendermode != render_none) if (rendermode == render_opengl)
{ {
// ughhhhh please can someone else do this? thanks ~toast 25/7/19 in 38 degrees centigrade w/o AC // ughhhhh please can someone else do this? thanks ~toast 25/7/19 in 38 degrees centigrade w/o AC
HWR_DrawFadeFill(x, y, w, h, c, color, strength); // toast two days later - left above comment in 'cause it's funny HWR_DrawFadeFill(x, y, w, h, c, color, strength); // toast two days later - left above comment in 'cause it's funny
@ -1709,7 +1709,7 @@ void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum)
size_t size, lflatsize, flatshift; size_t size, lflatsize, flatshift;
#ifdef HWRENDER #ifdef HWRENDER
if (rendermode != render_soft && rendermode != render_none) if (rendermode == render_opengl)
{ {
HWR_DrawFlatFill(x, y, w, h, flatnum); HWR_DrawFlatFill(x, y, w, h, flatnum);
return; return;
@ -1819,7 +1819,7 @@ void V_DrawPatchFill(patch_t *pat)
void V_DrawFadeScreen(UINT16 color, UINT8 strength) void V_DrawFadeScreen(UINT16 color, UINT8 strength)
{ {
#ifdef HWRENDER #ifdef HWRENDER
if (rendermode != render_soft && rendermode != render_none) if (rendermode == render_opengl)
{ {
HWR_FadeScreenMenuBack(color, strength); HWR_FadeScreenMenuBack(color, strength);
return; return;
@ -1848,7 +1848,7 @@ void V_DrawFadeConsBack(INT32 plines)
UINT8 *deststop, *buf; UINT8 *deststop, *buf;
#ifdef HWRENDER // not win32 only 19990829 by Kin #ifdef HWRENDER // not win32 only 19990829 by Kin
if (rendermode != render_soft && rendermode != render_none) if (rendermode == render_opengl)
{ {
UINT32 hwcolor = V_GetHWConsBackColor(); UINT32 hwcolor = V_GetHWConsBackColor();
HWR_DrawConsoleBack(hwcolor, plines); HWR_DrawConsoleBack(hwcolor, plines);
@ -1870,6 +1870,9 @@ void V_DrawPromptBack(INT32 boxheight, INT32 color)
if (color >= 256 && color < 512) if (color >= 256 && color < 512)
{ {
if (boxheight < 0)
boxheight = -boxheight;
else // 4 lines of space plus gaps between and some leeway
boxheight = ((boxheight * 4) + (boxheight/2)*5); boxheight = ((boxheight * 4) + (boxheight/2)*5);
V_DrawFill((BASEVIDWIDTH-(vid.width/vid.dupx))/2, BASEVIDHEIGHT-boxheight, (vid.width/vid.dupx),boxheight, (color-256)|V_SNAPTOBOTTOM); V_DrawFill((BASEVIDWIDTH-(vid.width/vid.dupx))/2, BASEVIDHEIGHT-boxheight, (vid.width/vid.dupx),boxheight, (color-256)|V_SNAPTOBOTTOM);
return; return;
@ -1881,7 +1884,7 @@ void V_DrawPromptBack(INT32 boxheight, INT32 color)
color = cons_backcolor.value; color = cons_backcolor.value;
#ifdef HWRENDER #ifdef HWRENDER
if (rendermode != render_soft && rendermode != render_none) if (rendermode == render_opengl)
{ {
UINT32 hwcolor; UINT32 hwcolor;
switch (color) switch (color)
@ -1917,8 +1920,11 @@ void V_DrawPromptBack(INT32 boxheight, INT32 color)
// heavily simplified -- we don't need to know x or y position, // heavily simplified -- we don't need to know x or y position,
// just the start and stop positions // just the start and stop positions
deststop = screens[0] + vid.rowbytes * vid.height; buf = deststop = screens[0] + vid.rowbytes * vid.height;
buf = deststop - vid.rowbytes * ((boxheight * 4) + (boxheight/2)*5); // 4 lines of space plus gaps between and some leeway if (boxheight < 0)
buf += vid.rowbytes * boxheight;
else // 4 lines of space plus gaps between and some leeway
buf -= vid.rowbytes * ((boxheight * 4) + (boxheight/2)*5);
for (; buf < deststop; ++buf) for (; buf < deststop; ++buf)
*buf = promptbgmap[*buf]; *buf = promptbgmap[*buf];
} }
@ -3506,8 +3512,7 @@ void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param)
INT32 height, yoffset; INT32 height, yoffset;
#ifdef HWRENDER #ifdef HWRENDER
// draw a hardware converted patch if (rendermode != render_soft)
if (rendermode != render_soft && rendermode != render_none)
return; return;
#endif #endif

View file

@ -848,6 +848,15 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
wadfiles[numwadfiles] = wadfile; wadfiles[numwadfiles] = wadfile;
numwadfiles++; // must come BEFORE W_LoadDehackedLumps, so any addfile called by COM_BufInsertText called by Lua doesn't overwrite what we just loaded numwadfiles++; // must come BEFORE W_LoadDehackedLumps, so any addfile called by COM_BufInsertText called by Lua doesn't overwrite what we just loaded
#ifdef HWRENDER
// Read shaders from file
if (rendermode == render_opengl && (vid_opengl_state == 1))
{
HWR_ReadShaders(numwadfiles - 1, (type == RET_PK3));
HWR_LoadShaders();
}
#endif // HWRENDER
// TODO: HACK ALERT - Load Lua & SOC stuff right here. I feel like this should be out of this place, but... Let's stick with this for now. // TODO: HACK ALERT - Load Lua & SOC stuff right here. I feel like this should be out of this place, but... Let's stick with this for now.
switch (wadfile->type) switch (wadfile->type)
{ {
@ -1632,21 +1641,6 @@ boolean W_IsPatchCached(lumpnum_t lumpnum, void *ptr)
return W_IsPatchCachedPWAD(WADFILENUM(lumpnum),LUMPNUM(lumpnum), ptr); return W_IsPatchCachedPWAD(WADFILENUM(lumpnum),LUMPNUM(lumpnum), ptr);
} }
void W_FlushCachedPatches(void)
{
if (needpatchflush)
{
Z_FreeTag(PU_CACHE);
Z_FreeTag(PU_PATCH);
Z_FreeTag(PU_HUDGFX);
Z_FreeTag(PU_HWRPATCHINFO);
Z_FreeTag(PU_HWRMODELTEXTURE);
Z_FreeTag(PU_HWRCACHE);
Z_FreeTags(PU_HWRCACHE_UNLOCKED, PU_HWRMODELTEXTURE_UNLOCKED);
}
needpatchflush = false;
}
// ========================================================================== // ==========================================================================
// W_CacheLumpName // W_CacheLumpName
// ========================================================================== // ==========================================================================
@ -1674,9 +1668,6 @@ void *W_CacheSoftwarePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag)
{ {
lumpcache_t *lumpcache = NULL; lumpcache_t *lumpcache = NULL;
if (needpatchflush)
W_FlushCachedPatches();
if (!TestValidLump(wad, lump)) if (!TestValidLump(wad, lump))
return NULL; return NULL;
@ -1727,9 +1718,6 @@ void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag)
GLPatch_t *grPatch; GLPatch_t *grPatch;
#endif #endif
if (needpatchflush)
W_FlushCachedPatches();
if (!TestValidLump(wad, lump)) if (!TestValidLump(wad, lump))
return NULL; return NULL;
@ -1778,7 +1766,7 @@ void W_UnlockCachedPatch(void *patch)
// The hardware code does its own memory management, as its patches // The hardware code does its own memory management, as its patches
// have different lifetimes from software's. // have different lifetimes from software's.
#ifdef HWRENDER #ifdef HWRENDER
if (rendermode != render_soft && rendermode != render_none) if (rendermode == render_opengl)
HWR_UnlockCachedPatch((GLPatch_t*)patch); HWR_UnlockCachedPatch((GLPatch_t*)patch);
else else
#endif #endif

View file

@ -210,7 +210,6 @@ void *W_CacheSoftwarePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag);
void *W_CacheSoftwarePatchNum(lumpnum_t lumpnum, INT32 tag); void *W_CacheSoftwarePatchNum(lumpnum_t lumpnum, INT32 tag);
void W_UnlockCachedPatch(void *patch); void W_UnlockCachedPatch(void *patch);
void W_FlushCachedPatches(void);
void W_VerifyFileMD5(UINT16 wadfilenum, const char *matchmd5); void W_VerifyFileMD5(UINT16 wadfilenum, const char *matchmd5);

View file

@ -106,6 +106,7 @@ static loadfunc_t hwdFuncTable[] = {
{"SetBlend@4", &hwdriver.pfnSetBlend}, {"SetBlend@4", &hwdriver.pfnSetBlend},
{"ClearBuffer@12", &hwdriver.pfnClearBuffer}, {"ClearBuffer@12", &hwdriver.pfnClearBuffer},
{"SetTexture@4", &hwdriver.pfnSetTexture}, {"SetTexture@4", &hwdriver.pfnSetTexture},
{"UpdateTexture@4", &hwdriver.pfnUpdateTexture},
{"ReadRect@24", &hwdriver.pfnReadRect}, {"ReadRect@24", &hwdriver.pfnReadRect},
{"GClipRect@20", &hwdriver.pfnGClipRect}, {"GClipRect@20", &hwdriver.pfnGClipRect},
{"ClearMipMapCache@0", &hwdriver.pfnClearMipMapCache}, {"ClearMipMapCache@0", &hwdriver.pfnClearMipMapCache},
@ -120,7 +121,7 @@ static loadfunc_t hwdFuncTable[] = {
{"FlushScreenTextures@0",&hwdriver.pfnFlushScreenTextures}, {"FlushScreenTextures@0",&hwdriver.pfnFlushScreenTextures},
{"StartScreenWipe@0", &hwdriver.pfnStartScreenWipe}, {"StartScreenWipe@0", &hwdriver.pfnStartScreenWipe},
{"EndScreenWipe@0", &hwdriver.pfnEndScreenWipe}, {"EndScreenWipe@0", &hwdriver.pfnEndScreenWipe},
{"DoScreenWipe@4", &hwdriver.pfnDoScreenWipe}, {"DoScreenWipe@0", &hwdriver.pfnDoScreenWipe},
{"DrawIntermissionBG@0",&hwdriver.pfnDrawIntermissionBG}, {"DrawIntermissionBG@0",&hwdriver.pfnDrawIntermissionBG},
{"MakeScreenTexture@0", &hwdriver.pfnMakeScreenTexture}, {"MakeScreenTexture@0", &hwdriver.pfnMakeScreenTexture},
{"MakeScreenFinalTexture@0", &hwdriver.pfnMakeScreenFinalTexture}, {"MakeScreenFinalTexture@0", &hwdriver.pfnMakeScreenFinalTexture},
@ -137,6 +138,7 @@ static loadfunc_t hwdFuncTable[] = {
{"SetBlend", &hwdriver.pfnSetBlend}, {"SetBlend", &hwdriver.pfnSetBlend},
{"ClearBuffer", &hwdriver.pfnClearBuffer}, {"ClearBuffer", &hwdriver.pfnClearBuffer},
{"SetTexture", &hwdriver.pfnSetTexture}, {"SetTexture", &hwdriver.pfnSetTexture},
{"UpdateTexture", &hwdriver.pfnUpdateTexture},
{"ReadRect", &hwdriver.pfnReadRect}, {"ReadRect", &hwdriver.pfnReadRect},
{"GClipRect", &hwdriver.pfnGClipRect}, {"GClipRect", &hwdriver.pfnGClipRect},
{"ClearMipMapCache", &hwdriver.pfnClearMipMapCache}, {"ClearMipMapCache", &hwdriver.pfnClearMipMapCache},

View file

@ -326,7 +326,7 @@ static inline boolean I_SkipFrame(void)
if (!paused) if (!paused)
return false; return false;
//case GS_TIMEATTACK: -- sorry optimisation but now we have a cool level platter and that being laggardly looks terrible //case GS_TIMEATTACK: -- sorry optimisation but now we have a cool level platter and that being laggardly looks terrible
#ifndef CLIENT_LOADINGSCREEN #ifndef NONET
/* FALLTHRU */ /* FALLTHRU */
case GS_WAITINGPLAYERS: case GS_WAITINGPLAYERS:
#endif #endif
@ -366,6 +366,9 @@ void I_FinishUpdate(void)
if (I_SkipFrame()) if (I_SkipFrame())
return; return;
if (marathonmode)
SCR_DisplayMarathonInfo();
// draw captions if enabled // draw captions if enabled
if (cv_closedcaptioning.value) if (cv_closedcaptioning.value)
SCR_ClosedCaptions(); SCR_ClosedCaptions();

View file

@ -227,8 +227,7 @@ static void Y_IntermissionTokenDrawer(void)
// //
// Y_ConsiderScreenBuffer // Y_ConsiderScreenBuffer
// //
// Can we copy the current screen // Can we copy the current screen to a buffer?
// to a buffer?
// //
void Y_ConsiderScreenBuffer(void) void Y_ConsiderScreenBuffer(void)
{ {
@ -254,9 +253,7 @@ void Y_ConsiderScreenBuffer(void)
// //
// Y_RescaleScreenBuffer // Y_RescaleScreenBuffer
// //
// Write the rescaled source picture, // Write the rescaled source picture, to the destination picture that has the current screen's resolutions.
// to the destination picture that
// has the current screen's resolutions.
// //
static void Y_RescaleScreenBuffer(void) static void Y_RescaleScreenBuffer(void)
{ {
@ -323,16 +320,9 @@ void Y_IntermissionDrawer(void)
// Bonus loops // Bonus loops
INT32 i; INT32 i;
if (rendermode == render_none) if (intertype == int_none || rendermode == render_none)
return; return;
if (intertype == int_none)
{
LUAh_IntermissionHUD();
return;
}
if (!usebuffer)
// Lactozilla: Renderer switching // Lactozilla: Renderer switching
if (needpatchrecache) if (needpatchrecache)
{ {
@ -373,11 +363,11 @@ void Y_IntermissionDrawer(void)
{ {
if (widebgpatch && rendermode == render_soft && vid.width / vid.dupx == 400) 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 else if (bgpatch)
V_DrawScaledPatch(0, 0, 0, bgpatch); V_DrawScaledPatch(0, 0, 0, bgpatch);
} }
} }
else else if (bgtile)
V_DrawPatchFill(bgtile); V_DrawPatchFill(bgtile);
LUAh_IntermissionHUD(); LUAh_IntermissionHUD();
@ -392,7 +382,7 @@ dontdrawbg:
if (gottoken) // first to be behind everything else if (gottoken) // first to be behind everything else
Y_IntermissionTokenDrawer(); Y_IntermissionTokenDrawer();
if (!splitscreen) if (!splitscreen) // there's not enough room in splitscreen, don't even bother trying!
{ {
// draw score // draw score
ST_DrawPatchFromHud(HUD_SCORE, sboscore); ST_DrawPatchFromHud(HUD_SCORE, sboscore);
@ -414,7 +404,7 @@ dontdrawbg:
ST_DrawPatchFromHud(HUD_TIMECOLON, sbocolon); // Colon ST_DrawPatchFromHud(HUD_TIMECOLON, sbocolon); // Colon
ST_DrawPadNumFromHud(HUD_SECONDS, seconds, 2); // Seconds ST_DrawPadNumFromHud(HUD_SECONDS, seconds, 2); // Seconds
if (cv_timetic.value == 1 || cv_timetic.value == 2 || modeattacking) // there's not enough room for tics in splitscreen, don't even bother trying! if (cv_timetic.value == 1 || cv_timetic.value == 2 || modeattacking || marathonmode)
{ {
ST_DrawPatchFromHud(HUD_TIMETICCOLON, sboperiod); // Period ST_DrawPatchFromHud(HUD_TIMETICCOLON, sboperiod); // Period
ST_DrawPadNumFromHud(HUD_TICS, tictrn, 2); // Tics ST_DrawPadNumFromHud(HUD_TICS, tictrn, 2); // Tics
@ -1004,7 +994,7 @@ void Y_Ticker(void)
{ {
INT32 i; INT32 i;
UINT32 oldscore = data.coop.score; UINT32 oldscore = data.coop.score;
boolean skip = false; boolean skip = (marathonmode) ? true : false;
boolean anybonuses = false; boolean anybonuses = false;
if (!intertic) // first time only if (!intertic) // first time only
@ -1080,7 +1070,7 @@ void Y_Ticker(void)
{ {
INT32 i; INT32 i;
UINT32 oldscore = data.spec.score; UINT32 oldscore = data.spec.score;
boolean skip = false, super = false, anybonuses = false; boolean skip = (marathonmode) ? true : false, super = false, anybonuses = false;
if (!intertic) // first time only if (!intertic) // first time only
{ {
@ -1186,6 +1176,34 @@ void Y_Ticker(void)
} }
} }
//
// Y_DetermineIntermissionType
//
// Determines the intermission type from the current gametype.
//
void Y_DetermineIntermissionType(void)
{
// set to int_none initially
intertype = int_none;
if (intermissiontypes[gametype] != int_none)
intertype = intermissiontypes[gametype];
else if (gametype == GT_COOP)
intertype = (G_IsSpecialStage(gamemap)) ? int_spec : int_coop;
else if (gametype == GT_TEAMMATCH)
intertype = int_teammatch;
else if (gametype == GT_MATCH
|| gametype == GT_TAG
|| gametype == GT_HIDEANDSEEK)
intertype = int_match;
else if (gametype == GT_RACE)
intertype = int_race;
else if (gametype == GT_COMPETITION)
intertype = int_comp;
else if (gametype == GT_CTF)
intertype = int_ctf;
}
// //
// Y_StartIntermission // Y_StartIntermission
// //
@ -1207,12 +1225,11 @@ void Y_StartIntermission(void)
if (!multiplayer) if (!multiplayer)
{ {
timer = 0; timer = 0;
intertype = (G_IsSpecialStage(gamemap)) ? int_spec : int_coop; intertype = (G_IsSpecialStage(gamemap)) ? int_spec : int_coop;
} }
else else
{ {
if (cv_inttime.value == 0 && gametype == GT_COOP) if (cv_inttime.value == 0 && ((intertype == int_coop) || (intertype == int_spec)))
timer = 0; timer = 0;
else else
{ {
@ -1221,23 +1238,6 @@ void Y_StartIntermission(void)
if (!timer) if (!timer)
timer = 1; timer = 1;
} }
if (intermissiontypes[gametype] != int_none)
intertype = intermissiontypes[gametype];
else if (gametype == GT_COOP)
intertype = (G_IsSpecialStage(gamemap)) ? int_spec : int_coop;
else if (gametype == GT_TEAMMATCH)
intertype = int_teammatch;
else if (gametype == GT_MATCH
|| gametype == GT_TAG
|| gametype == GT_HIDEANDSEEK)
intertype = int_match;
else if (gametype == GT_RACE)
intertype = int_race;
else if (gametype == GT_COMPETITION)
intertype = int_comp;
else if (gametype == GT_CTF)
intertype = int_ctf;
} }
// We couldn't display the intermission even if we wanted to. // We couldn't display the intermission even if we wanted to.

View file

@ -13,11 +13,15 @@ extern boolean usebuffer;
void Y_IntermissionDrawer(void); void Y_IntermissionDrawer(void);
void Y_Ticker(void); void Y_Ticker(void);
void Y_StartIntermission(void); void Y_StartIntermission(void);
void Y_EndIntermission(void); void Y_EndIntermission(void);
void Y_ConsiderScreenBuffer(void); void Y_ConsiderScreenBuffer(void);
void Y_CleanupScreenBuffer(void); void Y_CleanupScreenBuffer(void);
void Y_DetermineIntermissionType(void);
typedef enum typedef enum
{ {
int_none, int_none,

View file

@ -499,17 +499,14 @@ void Z_FreeTags(INT32 lowtag, INT32 hightag)
// Utility functions // Utility functions
// ----------------- // -----------------
// for renderer switching, free a bunch of stuff // for renderer switching
boolean needpatchflush = false; boolean needpatchflush = false;
boolean needpatchrecache = false; boolean needpatchrecache = false;
// flush all patches from memory // flush all patches from memory
// (also frees memory tagged with PU_CACHE)
// (which are not necessarily patches but I don't care)
void Z_FlushCachedPatches(void) void Z_FlushCachedPatches(void)
{ {
CONS_Debug(DBG_RENDER, "Z_FlushCachedPatches()...\n"); CONS_Debug(DBG_RENDER, "Z_FlushCachedPatches()...\n");
Z_FreeTag(PU_CACHE);
Z_FreeTag(PU_PATCH); Z_FreeTag(PU_PATCH);
Z_FreeTag(PU_HUDGFX); Z_FreeTag(PU_HUDGFX);
Z_FreeTag(PU_HWRPATCHINFO); Z_FreeTag(PU_HWRPATCHINFO);
@ -808,7 +805,7 @@ static void Command_Memfree_f(void)
sizeu1(Z_TagsUsage(PU_PURGELEVEL, INT32_MAX)>>10)); sizeu1(Z_TagsUsage(PU_PURGELEVEL, INT32_MAX)>>10));
#ifdef HWRENDER #ifdef HWRENDER
if (rendermode != render_soft && rendermode != render_none) if (rendermode == render_opengl)
{ {
CONS_Printf(M_GetText("Patch info headers: %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPATCHINFO)>>10)); CONS_Printf(M_GetText("Patch info headers: %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPATCHINFO)>>10));
CONS_Printf(M_GetText("Mipmap patches : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPATCHCOLMIPMAP)>>10)); CONS_Printf(M_GetText("Mipmap patches : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPATCHCOLMIPMAP)>>10));