Compare commits
202
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a44afcd9f | ||
|
|
3c282b5022 | ||
|
|
f4d40bd55f | ||
|
|
465fea8bb3 | ||
|
|
d47e20b54e | ||
|
|
4e9f9b7e0e | ||
|
|
9650139470 | ||
|
|
054a40a4b2 | ||
|
|
972ee5cf76 | ||
|
|
aef02cb347 | ||
|
|
36e485b2a3 | ||
|
|
d23c51e707 | ||
|
|
0db437aadd | ||
|
|
e351c1e62a | ||
|
|
b541de4f8c | ||
|
|
604bc40021 | ||
|
|
be8ddebd80 | ||
|
|
b2a36850cb | ||
|
|
8353c1efdd | ||
|
|
d19a2e0912 | ||
|
|
07432c0381 | ||
|
|
4fb3b63152 | ||
|
|
85b736620a | ||
|
|
9f770993d4 | ||
|
|
4bd02ad325 | ||
|
|
6e7b45d15c | ||
|
|
99ebca51d5 | ||
|
|
24eb888af3 | ||
|
|
09ce33abb9 | ||
|
|
044ff158a1 | ||
|
|
36c68d055c | ||
|
|
ddf7d7cdcb | ||
|
|
38950d580f | ||
|
|
707701f317 | ||
|
|
09507d635b | ||
|
|
ab85d6a693 | ||
|
|
5011b17f88 | ||
|
|
7bef45f701 | ||
|
|
40cbce8f9f | ||
|
|
70a70084c9 | ||
|
|
b6da6359d3 | ||
|
|
97075ca5c5 | ||
|
|
e94737945a | ||
|
|
57f15e0213 | ||
|
|
2eae9b197c | ||
|
|
68c7620349 | ||
|
|
7a3faf34e7 | ||
|
|
d401644447 | ||
|
|
dfc349b230 | ||
|
|
687d2bd894 | ||
|
|
78b642cf2d | ||
|
|
cb3b6ca34b | ||
|
|
ad15bf0ea3 | ||
|
|
56021ed999 | ||
|
|
3d22a5906f | ||
|
|
b6d771b48f | ||
|
|
ab30fb2e5e | ||
|
|
618d9e4cdf | ||
|
|
bf78ad9c75 | ||
|
|
918a4e8cd9 | ||
|
|
e90c84c9ac | ||
|
|
a9209a4887 | ||
|
|
0a3e7ba09f | ||
|
|
eb132b08c0 | ||
|
|
82407c3560 | ||
|
|
f1a8210663 | ||
|
|
1d722be4bc | ||
|
|
62a660bfe1 | ||
|
|
2984795175 | ||
|
|
da706d89a5 | ||
|
|
a8005d5cec | ||
|
|
793ccff6e6 | ||
|
|
e7db9bf1fd | ||
|
|
88d62c93a1 | ||
|
|
d73532d019 | ||
|
|
84d3d23936 | ||
|
|
717947843b | ||
|
|
968584a316 | ||
|
|
ccd67f621a | ||
|
|
80b301dbbe | ||
|
|
001e61d39d | ||
|
|
19c98a436a | ||
|
|
8dd6d7cfdd | ||
|
|
7456b6e02c | ||
|
|
5e8096f74c | ||
|
|
6af77afc44 | ||
|
|
42eeb7bdf5 | ||
|
|
6f4b1e5125 | ||
|
|
22e65cdda8 | ||
|
|
9d342d0f3d | ||
|
|
9583bed718 | ||
|
|
b69ce75712 | ||
|
|
a1cd19b023 | ||
|
|
6e50710b25 | ||
|
|
989a971d27 | ||
|
|
24ee56ce7a | ||
|
|
52f99dd9c1 | ||
|
|
6374fda570 | ||
|
|
cdd2d6323e | ||
|
|
c508a7ea78 | ||
|
|
1380a394c7 | ||
|
|
2c937099d4 | ||
|
|
0a936b3bba | ||
|
|
0a31e0a65e | ||
|
|
8627a18452 | ||
|
|
be528adea5 | ||
|
|
5eb4ed8391 | ||
|
|
9a00d30c0c | ||
|
|
71237c5e11 | ||
|
|
9c6e32a1ab | ||
|
|
1bc18801c8 | ||
|
|
221f2a956e | ||
|
|
b450abdf4d | ||
|
|
d36eed3c09 | ||
|
|
43ee791d4a | ||
|
|
c921945922 | ||
|
|
5f8c77e752 | ||
|
|
064db977aa | ||
|
|
5868cd9777 | ||
|
|
b0ddde996a | ||
|
|
e03c3766f0 | ||
|
|
953c0d7451 | ||
|
|
97b303c362 | ||
|
|
2ffe736a20 | ||
|
|
21f2032f34 | ||
|
|
2f66207205 | ||
|
|
5a14b09c1f | ||
|
|
7e9da92dbe | ||
|
|
a27550b95b | ||
|
|
556883487d | ||
|
|
96f8533479 | ||
|
|
f3cca27448 | ||
|
|
252563725d | ||
|
|
9a934a55e2 | ||
|
|
f07d5d381e | ||
|
|
3faab66ef4 | ||
|
|
2a023246be | ||
|
|
006e7fe8f8 | ||
|
|
1a7ff21a04 | ||
|
|
98cb0fdcb2 | ||
|
|
1fd7e9cdac | ||
|
|
0a2eac4d3a | ||
|
|
9ac6fffd4d | ||
|
|
da20f4a087 | ||
|
|
dbf822ced9 | ||
|
|
095842f4aa | ||
|
|
8c290d7597 | ||
|
|
8a6f4db9af | ||
|
|
99186a86db | ||
|
|
c67bf97f7b | ||
|
|
33a1540fcd | ||
|
|
529b0d643a | ||
|
|
4576efbe5c | ||
|
|
185375ece1 | ||
|
|
d11521954e | ||
|
|
41c4300ec2 | ||
|
|
51d5023f29 | ||
|
|
d2878f8834 | ||
|
|
7808159d23 | ||
|
|
e759431948 | ||
|
|
268ccce955 | ||
|
|
f2d3432bf5 | ||
|
|
2da89f1946 | ||
|
|
6153733df4 | ||
|
|
d280b39f9f | ||
|
|
236e7b8d45 | ||
|
|
dcccf672c9 | ||
|
|
03f81bed16 | ||
|
|
fc51c1ba88 | ||
|
|
d50c1ab6d7 | ||
|
|
984c2ff8d6 | ||
|
|
74646acdca | ||
|
|
45ffe87ba6 | ||
|
|
37eb8cfa57 | ||
|
|
a0f903f162 | ||
|
|
f1f0782256 | ||
|
|
0e9a825f63 | ||
|
|
5c53a90eea | ||
|
|
55c6ba6d12 | ||
|
|
6617382f54 | ||
|
|
dd499a410f | ||
|
|
c04ba992a7 | ||
|
|
27c053cd48 | ||
|
|
7d68c0598c | ||
|
|
201c725dc7 | ||
|
|
57b2316c42 | ||
|
|
fe682a8071 | ||
|
|
bf44a054a1 | ||
|
|
eca9c60d9b | ||
|
|
cf42c35b9f | ||
|
|
a364068abb | ||
|
|
e88093d9cf | ||
|
|
5e532a76cf | ||
|
|
fb9c459269 | ||
|
|
a6898bd1cd | ||
|
|
ff474d18ee | ||
|
|
f15d3be263 | ||
|
|
19e5366c5b | ||
|
|
346dee019c | ||
|
|
18914f22f2 | ||
|
|
1219ecf818 | ||
|
|
b6923d0d0d |
No files matched your search
+7
-19
@@ -181,7 +181,8 @@ objdir:=$(makedir)/objs
|
||||
|
||||
# very sophisticated dependency
|
||||
sources+=\
|
||||
$(call List,Sourcefile)
|
||||
$(call List,Sourcefile)\
|
||||
$(call List,core/Sourcefile)
|
||||
|
||||
sources+=\
|
||||
$(call List,blua/Sourcefile)
|
||||
@@ -262,12 +263,10 @@ opts+=$(debug_opts)
|
||||
opts+=$(foreach v,$(passthru_opts),$(if $($(v)),-D$(v)))
|
||||
|
||||
opts+=$(WFLAGS) $(CPPFLAGS) $(CFLAGS)
|
||||
libs+=$(LDFLAGS) -lstdc++
|
||||
asflags:=$(ASFLAGS) -x assembler-with-cpp
|
||||
cxxopts:=$(opts) $(CXXFLAGS) -std=c++17
|
||||
|
||||
cxxopts:=$(opts)
|
||||
cxxopts+=-std=c++17
|
||||
cxxopts+=$(CXXFLAGS)
|
||||
libs+=$(LDFLAGS) -lstdc++ -lpthread
|
||||
asflags:=$(ASFLAGS) -x assembler-with-cpp
|
||||
|
||||
cc=$(CC)
|
||||
cxx=$(CXX)
|
||||
@@ -288,6 +287,7 @@ ifndef SILENT
|
||||
ifndef MAKE_RESTARTS
|
||||
ifndef destructive
|
||||
$(shell $(CC) -v)
|
||||
#$(shell $(CXX) -v)
|
||||
define flags =
|
||||
|
||||
SHELL ..... $(SHELL)
|
||||
@@ -315,6 +315,7 @@ endif
|
||||
|
||||
LD:=$(CC)
|
||||
cc:=$(cc) $(opts)
|
||||
cxx:=$(cxx) $(cxxopts)
|
||||
ifdef UPX
|
||||
upx=$(UPX) $(UPX_OPTS)
|
||||
endif
|
||||
@@ -377,19 +378,6 @@ endif
|
||||
$(.)$(cc) -MM -MF $$@ -MT $(objdir)/$$*.o $(2) $$<
|
||||
endef
|
||||
|
||||
# dependency recipe template (C++)
|
||||
# 1: source file suffix
|
||||
# 2: extra flags to gcc
|
||||
define _recipecxx =
|
||||
$(depdir)/%.d : %.$(1) | $$$$(@D)/
|
||||
ifndef WINDOWSHELL
|
||||
ifdef Echo_name
|
||||
@printf '%-20.20s\r' $$<
|
||||
endif
|
||||
endif
|
||||
$(.)$(cxx) -MM -MF $$@ -MT $(objdir)/$$*.o $(2) $$<
|
||||
endef
|
||||
|
||||
$(eval $(call _recipe,c))
|
||||
$(eval $(call _recipe,cpp))
|
||||
$(eval $(call _recipe,s,$(asflags)))
|
||||
|
||||
@@ -4,8 +4,6 @@ sources+=$(call List,dedicated/Sourcefile)
|
||||
|
||||
opts+=-DDEDICATED
|
||||
|
||||
libs+=-lpthread
|
||||
|
||||
ifdef MINGW
|
||||
libs+=-mconsole
|
||||
endif
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
|
||||
makedir:=$(makedir)/SDL
|
||||
|
||||
sources+=$(call List,sdl/Sourcefile)
|
||||
opts+=-DDIRECTFULLSCREEN -DHAVE_SDL
|
||||
sources+=$(call List,sdl/Sourcefile)
|
||||
|
||||
NOUPNP=1
|
||||
|
||||
|
||||
@@ -16,6 +16,9 @@ $(foreach v,$(join $(wordlist 2,$(_n),- $(gcc_versions)),\
|
||||
$(and $(findstring =,$(v)),\
|
||||
$(eval $(call _predecessor,$(subst =, ,$(v))))))
|
||||
|
||||
# aggregate returns seem to happen alot in c++ so just supress em lel
|
||||
CXXFLAGS+= -Wno-aggregate-return
|
||||
|
||||
# -W -Wno-unused
|
||||
|
||||
ifdef GCC150
|
||||
|
||||
+5
-4
@@ -49,14 +49,15 @@ r_bsp.c
|
||||
r_data.c
|
||||
r_draw.c
|
||||
r_fps.c
|
||||
r_main.c
|
||||
r_main.cpp
|
||||
r_patch.c
|
||||
r_patchrotation.c
|
||||
r_plane.c
|
||||
r_segs.c
|
||||
r_plane.cpp
|
||||
r_segs.cpp
|
||||
r_skins.c
|
||||
r_sky.c
|
||||
r_splats.c
|
||||
r_things.c
|
||||
r_things.cpp
|
||||
r_portal.c
|
||||
p_ceilng.c
|
||||
p_enemy.c
|
||||
|
||||
+8
-4
@@ -197,7 +197,7 @@ static fixed_t scale_mtof = (fixed_t)INITSCALEMTOF;
|
||||
// used by FTOM to scale from frame-buffer-to-map coords (=1/scale_mtof)
|
||||
static fixed_t scale_ftom;
|
||||
|
||||
static player_t *plr; // the player represented by an arrow
|
||||
static player_t *plr = NULL; // the player represented by an arrow
|
||||
|
||||
static boolean followplayer = true; // specifies whether to follow the player around
|
||||
|
||||
@@ -237,7 +237,7 @@ static inline void AM_restoreScaleAndLoc(void)
|
||||
m_x = old_m_x;
|
||||
m_y = old_m_y;
|
||||
}
|
||||
else
|
||||
else if (plr && plr->mo)
|
||||
{
|
||||
m_x = (plr->mo->x >> FRACTOMAPBITS) - m_w/2;
|
||||
m_y = (plr->mo->y >> FRACTOMAPBITS) - m_h/2;
|
||||
@@ -318,7 +318,8 @@ static void AM_initVariables(void)
|
||||
break;
|
||||
|
||||
plr = &players[pnum];
|
||||
if (plr != NULL && plr->mo != NULL)
|
||||
|
||||
if (plr && plr->mo)
|
||||
{
|
||||
m_x = (plr->mo->x >> FRACTOMAPBITS) - m_w/2;
|
||||
m_y = (plr->mo->y >> FRACTOMAPBITS) - m_h/2;
|
||||
@@ -340,7 +341,7 @@ static void AM_FrameBufferInit(void)
|
||||
f_x = f_y = 0;
|
||||
f_w = vid.width;
|
||||
f_h = vid.height;
|
||||
am_buf = screens[0];
|
||||
am_buf = vid.screens[0];
|
||||
}
|
||||
|
||||
//
|
||||
@@ -597,6 +598,9 @@ static inline void AM_changeWindowScale(void)
|
||||
|
||||
static inline void AM_doFollowPlayer(void)
|
||||
{
|
||||
if (!plr || !plr->mo)
|
||||
return;
|
||||
|
||||
if (f_oldloc.x != plr->mo->x || f_oldloc.y != plr->mo->y)
|
||||
{
|
||||
m_x = FTOM(MTOF(plr->mo->x >> FRACTOMAPBITS)) - m_w/2;
|
||||
|
||||
@@ -46,7 +46,6 @@ INT32 VID_SetMode(INT32 modenum)
|
||||
vid.modenum = 0;
|
||||
vid.width = 320;
|
||||
vid.height = 240;
|
||||
vid.bpp = 1;
|
||||
vid.buffer = android_surface;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#define WRITEUINT8(p,b) do { UINT8 *p_tmp = (void *)p; const UINT8 tv = ( UINT8)(b); memcpy(p, &tv, sizeof( UINT8)); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
#define WRITESINT8(p,b) do { SINT8 *p_tmp = (void *)p; const SINT8 tv = ( UINT8)(b); memcpy(p, &tv, sizeof( UINT8)); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
#define WRITEINT16(p,b) do { INT16 *p_tmp = (void *)p; const INT16 tv = ( INT16)(b); memcpy(p, &tv, sizeof( INT16)); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
#define WRITEINT16_2(p,b) do { INT16 *p_tmp = ( INT16 *)p; const INT16 tv = ( INT16)(b); memcpy(p, &tv, sizeof( INT16)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) // dumb hack for mumble
|
||||
#define WRITEUINT16(p,b) do { UINT16 *p_tmp = (void *)p; const UINT16 tv = ( UINT16)(b); memcpy(p, &tv, sizeof( UINT16)); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
#define WRITEINT32(p,b) do { INT32 *p_tmp = (void *)p; const INT32 tv = ( INT32)(b); memcpy(p, &tv, sizeof( INT32)); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
#define WRITEUINT32(p,b) do { UINT32 *p_tmp = (void *)p; const UINT32 tv = ( UINT32)(b); memcpy(p, &tv, sizeof( UINT32)); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
@@ -38,6 +39,7 @@
|
||||
#define WRITEUINT8(p,b) do { UINT8 *p_tmp = ( UINT8 *)p; *p_tmp = ( UINT8)(b); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
#define WRITESINT8(p,b) do { SINT8 *p_tmp = ( SINT8 *)p; *p_tmp = ( SINT8)(b); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
#define WRITEINT16(p,b) do { INT16 *p_tmp = ( INT16 *)p; *p_tmp = ( INT16)(b); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
#define WRITEINT16_2(p,b) do { INT16 *p_tmp = ( INT16 *)p; *p_tmp = ( INT16)(b); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) // dumb hack for mumble
|
||||
#define WRITEUINT16(p,b) do { UINT16 *p_tmp = ( UINT16 *)p; *p_tmp = ( UINT16)(b); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
#define WRITEINT32(p,b) do { INT32 *p_tmp = ( INT32 *)p; *p_tmp = ( INT32)(b); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
#define WRITEUINT32(p,b) do { UINT32 *p_tmp = ( UINT32 *)p; *p_tmp = ( UINT32)(b); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
|
||||
+35
-15
@@ -240,7 +240,6 @@ void COM_ImmedExecute(const char *ptext)
|
||||
|
||||
while (i < strlen(ptext))
|
||||
{
|
||||
|
||||
quotes = 0;
|
||||
for (j = 0; i < strlen(ptext); i++,j++)
|
||||
{
|
||||
@@ -817,12 +816,17 @@ static void COM_Help_f(void)
|
||||
cvar = CV_FindVar(help);
|
||||
if (cvar)
|
||||
{
|
||||
boolean floatmode = false;
|
||||
const char *cvalue = NULL;
|
||||
CONS_Printf("\x82""Variable %s:\n", cvar->name);
|
||||
CONS_Printf(M_GetText(" flags: "));
|
||||
if (cvar->flags & CV_SAVE)
|
||||
CONS_Printf("AUTOSAVE ");
|
||||
if (cvar->flags & CV_FLOAT)
|
||||
{
|
||||
CONS_Printf("FLOAT ");
|
||||
floatmode = true;
|
||||
}
|
||||
if (cvar->flags & CV_NETVAR)
|
||||
CONS_Printf("NETVAR ");
|
||||
if (cvar->flags & CV_CALL)
|
||||
@@ -832,30 +836,43 @@ static void COM_Help_f(void)
|
||||
CONS_Printf("\n");
|
||||
if (cvar->PossibleValue)
|
||||
{
|
||||
if (!stricmp(cvar->PossibleValue[0].strvalue, "MIN") && !stricmp(cvar->PossibleValue[1].strvalue, "MAX"))
|
||||
{
|
||||
CONS_Printf(" range from %d to %d\n", cvar->PossibleValue[0].value,
|
||||
cvar->PossibleValue[1].value);
|
||||
i = 2;
|
||||
}
|
||||
if (!stricmp(cvar->PossibleValue[0].strvalue, "MIN") && !stricmp(cvar->PossibleValue[1].strvalue, "MAX"))
|
||||
{
|
||||
if (floatmode)
|
||||
{
|
||||
float fu = FIXED_TO_FLOAT(cvar->PossibleValue[0].value);
|
||||
float ck = FIXED_TO_FLOAT(cvar->PossibleValue[1].value);
|
||||
CONS_Printf(" range from %ld%s to %ld%s\n",
|
||||
(long)fu, M_Ftrim(fu),
|
||||
(long)ck, M_Ftrim(ck));
|
||||
}
|
||||
else
|
||||
CONS_Printf(" range from %d to %d\n", cvar->PossibleValue[0].value,
|
||||
cvar->PossibleValue[1].value);
|
||||
i = 2;
|
||||
}
|
||||
|
||||
{
|
||||
const char *cvalue = NULL;
|
||||
//CONS_Printf(M_GetText(" possible value : %s\n"), cvar->name);
|
||||
while (cvar->PossibleValue[i].strvalue)
|
||||
{
|
||||
CONS_Printf(" %-2d : %s\n", cvar->PossibleValue[i].value,
|
||||
cvar->PossibleValue[i].strvalue);
|
||||
if (floatmode)
|
||||
CONS_Printf(" %-2f : %s\n", FIXED_TO_FLOAT(cvar->PossibleValue[i].value),
|
||||
cvar->PossibleValue[i].strvalue);
|
||||
else
|
||||
CONS_Printf(" %-2d : %s\n", cvar->PossibleValue[i].value,
|
||||
cvar->PossibleValue[i].strvalue);
|
||||
if (cvar->PossibleValue[i].value == cvar->value)
|
||||
cvalue = cvar->PossibleValue[i].strvalue;
|
||||
i++;
|
||||
}
|
||||
if (cvalue)
|
||||
CONS_Printf(" Current value: %s\n", cvalue);
|
||||
else
|
||||
CONS_Printf(" Current value: %d\n", cvar->value);
|
||||
}
|
||||
}
|
||||
|
||||
if (cvalue)
|
||||
CONS_Printf(" Current value: %s\n", cvalue);
|
||||
else if (cvar->string)
|
||||
CONS_Printf(" Current value: %s\n", cvar->string);
|
||||
else
|
||||
CONS_Printf(" Current value: %d\n", cvar->value);
|
||||
}
|
||||
@@ -1026,7 +1043,10 @@ static void COM_Add_f(void)
|
||||
}
|
||||
|
||||
if (( cvar->flags & CV_FLOAT ))
|
||||
CV_Set(cvar, va("%f", FIXED_TO_FLOAT (cvar->value) + atof(COM_Argv(2))));
|
||||
{
|
||||
float n =FIXED_TO_FLOAT (cvar->value) + atof(COM_Argv(2));
|
||||
CV_Set(cvar, va("%ld%s", (long)n, M_Ftrim(n)));
|
||||
}
|
||||
else
|
||||
CV_AddValue(cvar, atoi(COM_Argv(2)));
|
||||
}
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
#ifndef __COMMAND_H__
|
||||
#define __COMMAND_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "doomdef.h"
|
||||
|
||||
@@ -189,4 +193,8 @@ UINT8 CV_CheatsEnabled(void);
|
||||
// Returns cvar by name. Exposed here for Lua.
|
||||
consvar_t *CV_FindVar(const char *name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __COMMAND_H__
|
||||
@@ -1321,13 +1321,6 @@ void CONS_Debug(INT32 debugflags, const char *fmt, ...)
|
||||
//
|
||||
void CONS_Error(const char *msg)
|
||||
{
|
||||
#ifdef RPC_NO_WINDOWS_H
|
||||
if (!graphics_started)
|
||||
{
|
||||
MessageBoxA(vid.WndParent, msg, "SRB2Kart Warning", MB_OK);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
CONS_Printf("\x82%s", msg); // write error msg in different colour
|
||||
CONS_Printf(M_GetText("Press ENTER to continue\n"));
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
target_sourcefile(cpp)
|
||||
@@ -0,0 +1,2 @@
|
||||
memory.cpp
|
||||
thread_pool.cpp
|
||||
@@ -0,0 +1,71 @@
|
||||
// BLANKART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2024 by Ronald "Eidolon" Kinard
|
||||
// Copyright (C) 2024 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "memory.h"
|
||||
|
||||
#include <array>
|
||||
#include <new>
|
||||
|
||||
#include "../z_zone.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
class LinearMemory
|
||||
{
|
||||
size_t size_;
|
||||
size_t height_;
|
||||
void* memory_;
|
||||
|
||||
public:
|
||||
constexpr explicit LinearMemory(size_t size) noexcept;
|
||||
|
||||
void* allocate(size_t size);
|
||||
void reset() noexcept;
|
||||
};
|
||||
|
||||
constexpr LinearMemory::LinearMemory(size_t size) noexcept : size_(size), height_{0}, memory_{nullptr} {}
|
||||
|
||||
void* LinearMemory::allocate(size_t size)
|
||||
{
|
||||
size_t aligned_size = (size + 15) & ~15;
|
||||
if (height_ + aligned_size > size_)
|
||||
{
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
if (memory_ == nullptr)
|
||||
{
|
||||
memory_ = Z_Malloc(size_, PU_STATIC, nullptr);
|
||||
}
|
||||
|
||||
void* ptr = (void*)((uintptr_t)(memory_) + height_);
|
||||
height_ += aligned_size;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void LinearMemory::reset() noexcept
|
||||
{
|
||||
height_ = 0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
static LinearMemory g_frame_memory {4 * 1024 * 1024};
|
||||
|
||||
void* Z_Frame_Alloc(size_t size)
|
||||
{
|
||||
return g_frame_memory.allocate(size);
|
||||
}
|
||||
|
||||
void Z_Frame_Reset()
|
||||
{
|
||||
g_frame_memory.reset();
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// BLANKART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2024 by Ronald "Eidolon" Kinard
|
||||
// Copyright (C) 2024 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __SRB2_CORE_MEMORY_H__
|
||||
#define __SRB2_CORE_MEMORY_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cpluspplus
|
||||
|
||||
/// @brief Allocate a block of memory with a lifespan of the current main-thread frame.
|
||||
/// This function is NOT thread-safe, but the allocated memory may be used across threads.
|
||||
/// @return a pointer to a block of memory aligned with libc malloc alignment, or null if allocation fails
|
||||
void* Z_Frame_Alloc(size_t size);
|
||||
|
||||
/// @brief Resets per-frame memory. Not thread safe.
|
||||
void Z_Frame_Reset(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // __SRB2_CORE_MEMORY_H__
|
||||
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
// This class is derived from Conor Williams' implementation of a concurrent deque
|
||||
// https://github.com/ConorWilliams/ConcurrentDeque
|
||||
// Copyright (C) 2021 Conor Williams
|
||||
|
||||
// The original version was for C++23. This one has been shrunk slightly and adapted to our conventions.
|
||||
|
||||
#ifndef __SRB2_CORE_SPMC_QUEUE_HPP__
|
||||
#define __SRB2_CORE_SPMC_QUEUE_HPP__
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
//#include <tracy/tracy/Tracy.hpp>
|
||||
|
||||
#include "../cxxutil.hpp"
|
||||
|
||||
namespace srb2
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
class SpMcQueue
|
||||
{
|
||||
struct RingBuff {
|
||||
public:
|
||||
explicit RingBuff(int64_t cap) : _cap{cap}, _mask{cap - 1}
|
||||
{
|
||||
SRB2_ASSERT(cap && (!(cap & (cap - 1))) && "Capacity must be buf power of 2!");
|
||||
_buff = std::unique_ptr<T[]>(new T[_cap]);
|
||||
}
|
||||
|
||||
std::int64_t capacity() const noexcept { return _cap; }
|
||||
|
||||
// Store (copy) at modulo index
|
||||
void store(int64_t i, T&& x) noexcept
|
||||
{
|
||||
_buff[i & _mask] = std::move(x);
|
||||
}
|
||||
|
||||
// Load (copy) at modulo index
|
||||
T load(int64_t i) const noexcept
|
||||
{
|
||||
return _buff[i & _mask];
|
||||
}
|
||||
|
||||
// Allocates and returns a new ring buffer, copies elements in range [b, t) into the new buffer.
|
||||
RingBuff* resize(std::int64_t b, std::int64_t t) const
|
||||
{
|
||||
//ZoneScoped;
|
||||
RingBuff* ptr = new RingBuff{2 * _cap};
|
||||
for (std::int64_t i = t; i != b; ++i) {
|
||||
ptr->store(i, load(i));
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
int64_t _cap; // Capacity of the buffer
|
||||
int64_t _mask; // Bit mask to perform modulo capacity operations
|
||||
|
||||
std::unique_ptr<T[]> _buff;
|
||||
};
|
||||
|
||||
alignas(64) std::atomic<int64_t> bottom_;
|
||||
alignas(64) std::atomic<int64_t> top_;
|
||||
alignas(64) std::atomic<RingBuff*> buffer_;
|
||||
|
||||
std::vector<std::unique_ptr<RingBuff>> garbage_;
|
||||
|
||||
public:
|
||||
SpMcQueue(size_t capacity) : bottom_(0), top_(0), buffer_(new RingBuff(capacity))
|
||||
{
|
||||
garbage_.reserve(32);
|
||||
}
|
||||
~SpMcQueue() noexcept
|
||||
{
|
||||
delete buffer_.load(std::memory_order_relaxed);
|
||||
};
|
||||
|
||||
size_t size() const noexcept
|
||||
{
|
||||
int64_t bottom = bottom_.load(std::memory_order_relaxed);
|
||||
int64_t top = top_.load(std::memory_order_relaxed);
|
||||
return static_cast<size_t>(bottom >= top ? bottom - top : 0);
|
||||
}
|
||||
|
||||
bool empty() const noexcept
|
||||
{
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
void push(T&& v) noexcept
|
||||
{
|
||||
int64_t bottom = bottom_.load(std::memory_order_relaxed);
|
||||
int64_t top = top_.load(std::memory_order_acquire);
|
||||
RingBuff* buf = buffer_.load(std::memory_order_relaxed);
|
||||
|
||||
if (buf->capacity() < (bottom - top) + 1)
|
||||
{
|
||||
// Queue is full, build a new one
|
||||
RingBuff* newbuf = buf->resize(bottom, top);
|
||||
garbage_.emplace_back(buf);
|
||||
buffer_.store(newbuf, std::memory_order_relaxed);
|
||||
buf = newbuf;
|
||||
}
|
||||
|
||||
// Construct new object, this does not have to be atomic as no one can steal this item until after we
|
||||
// store the new value of bottom, ordering is maintained by surrounding atomics.
|
||||
buf->store(bottom, std::move(v));
|
||||
|
||||
std::atomic_thread_fence(std::memory_order_release);
|
||||
bottom_.store(bottom + 1, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
std::optional<T> pop() noexcept
|
||||
{
|
||||
int64_t bottom = bottom_.load(std::memory_order_relaxed) - 1;
|
||||
RingBuff* buf = buffer_.load(std::memory_order_relaxed);
|
||||
|
||||
bottom_.store(bottom, std::memory_order_relaxed); // Stealers can no longer steal
|
||||
|
||||
std::atomic_thread_fence(std::memory_order_seq_cst);
|
||||
int64_t top = top_.load(std::memory_order_relaxed);
|
||||
|
||||
if (top <= bottom)
|
||||
{
|
||||
// Non-empty deque
|
||||
if (top == bottom)
|
||||
{
|
||||
// The last item could get stolen, by a stealer that loaded bottom before our write above
|
||||
if (!top_.compare_exchange_strong(top, top + 1, std::memory_order_seq_cst, std::memory_order_relaxed))
|
||||
{
|
||||
// Failed race, thief got the last item.
|
||||
bottom_.store(bottom + 1, std::memory_order_relaxed);
|
||||
return std::nullopt;
|
||||
}
|
||||
bottom_.store(bottom + 1, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
// Can delay load until after acquiring slot as only this thread can push(), this load is not
|
||||
// required to be atomic as we are the exclusive writer.
|
||||
return buf->load(bottom);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
bottom_.store(bottom + 1, std::memory_order_relaxed);
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<T> steal() noexcept
|
||||
{
|
||||
int64_t top = top_.load(std::memory_order_acquire);
|
||||
std::atomic_thread_fence(std::memory_order_seq_cst);
|
||||
int64_t bottom = bottom_.load(std::memory_order_acquire);
|
||||
|
||||
if (top < bottom)
|
||||
{
|
||||
// Must load *before* acquiring the slot as slot may be overwritten immediately after acquiring.
|
||||
// This load is NOT required to be atomic even-though it may race with an overrite as we only
|
||||
// return the value if we win the race below garanteeing we had no race during our read. If we
|
||||
// loose the race then 'x' could be corrupt due to read-during-write race but as T is trivially
|
||||
// destructible this does not matter.
|
||||
T x = buffer_.load(std::memory_order_consume)->load(top);
|
||||
|
||||
if (!top_.compare_exchange_strong(top, top + 1, std::memory_order_seq_cst, std::memory_order_relaxed))
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return x;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace srb2
|
||||
|
||||
#endif // __SRB2_CORE_SPMC_QUEUE_HPP__
|
||||
@@ -0,0 +1,255 @@
|
||||
// BLANKART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2024 by Ronald "Eidolon" Kinard
|
||||
// Copyright (C) 2024 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __SRB2_CORE_STATIC_VEC_HPP__
|
||||
#define __SRB2_CORE_STATIC_VEC_HPP__
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <iterator>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
|
||||
#include "../cxxutil.hpp"
|
||||
|
||||
namespace srb2
|
||||
{
|
||||
|
||||
template <typename T, size_t Limit>
|
||||
class StaticVec;
|
||||
|
||||
template <typename T, size_t Limit>
|
||||
class StaticVec
|
||||
{
|
||||
std::array<T, Limit> arr_ {{}};
|
||||
size_t size_ = 0;
|
||||
|
||||
public:
|
||||
using value_type = T;
|
||||
|
||||
constexpr StaticVec() {}
|
||||
|
||||
StaticVec(const StaticVec& rhs)
|
||||
{
|
||||
for (size_t i = size_; i > 0; i--)
|
||||
{
|
||||
arr_[i] = T();
|
||||
}
|
||||
size_ = rhs.size();
|
||||
for (size_t i = 0; i < size_; i++)
|
||||
{
|
||||
arr_[i] = rhs.arr_[i];
|
||||
}
|
||||
}
|
||||
|
||||
StaticVec(StaticVec&& rhs) noexcept(std::is_nothrow_move_assignable_v<T>)
|
||||
{
|
||||
for (size_t i = size_; i > 0; i--)
|
||||
{
|
||||
arr_[i] = T();
|
||||
}
|
||||
size_ = rhs.size();
|
||||
for (size_t i = 0; i < size_; i++)
|
||||
{
|
||||
arr_[i] = std::move(rhs.arr_[i]);
|
||||
}
|
||||
while (rhs.size() > 0)
|
||||
{
|
||||
rhs.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
constexpr StaticVec(std::initializer_list<T> list) noexcept(std::is_nothrow_move_assignable_v<T>)
|
||||
{
|
||||
size_ = list.size();
|
||||
size_t i = 0;
|
||||
for (auto itr = list.begin(); itr != list.end(); itr++)
|
||||
{
|
||||
arr_[i] = *itr;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
~StaticVec() = default;
|
||||
|
||||
StaticVec& operator=(const StaticVec& rhs)
|
||||
{
|
||||
for (size_t i = size_; i > 0; i--)
|
||||
{
|
||||
arr_[i] = T();
|
||||
}
|
||||
size_ = rhs.size();
|
||||
for (size_t i = 0; i < size_; i++)
|
||||
{
|
||||
arr_[i] = rhs.arr_[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
StaticVec& operator=(StaticVec&& rhs) noexcept(std::is_nothrow_move_constructible_v<T>)
|
||||
{
|
||||
for (size_t i = size_; i > 0; i--)
|
||||
{
|
||||
arr_[i] = T();
|
||||
}
|
||||
size_ = rhs.size();
|
||||
for (size_t i = 0; i < size_; i++)
|
||||
{
|
||||
arr_[i] = std::move(rhs.arr_[i]);
|
||||
}
|
||||
while (rhs.size() > 0)
|
||||
{
|
||||
rhs.pop_back();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void push_back(const T& value) { arr_[size_++] = value; }
|
||||
|
||||
void pop_back() { arr_[--size_] = T(); }
|
||||
|
||||
void resize(size_t size, T value = T())
|
||||
{
|
||||
if (size >= Limit)
|
||||
{
|
||||
throw std::length_error("new size >= Capacity");
|
||||
}
|
||||
|
||||
if (size == size_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (size < size_)
|
||||
{
|
||||
while (size_ > size)
|
||||
{
|
||||
pop_back();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (size_ < size)
|
||||
{
|
||||
push_back(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
arr_ = {{}};
|
||||
size_ = 0;
|
||||
}
|
||||
|
||||
using iterator = typename std::array<T, Limit>::iterator;
|
||||
using const_iterator = typename std::array<T, Limit>::const_iterator;
|
||||
|
||||
constexpr iterator begin() noexcept { return arr_.begin(); }
|
||||
|
||||
constexpr const_iterator begin() const noexcept { return arr_.cbegin(); }
|
||||
|
||||
constexpr const_iterator cbegin() const noexcept { return arr_.cbegin(); }
|
||||
|
||||
constexpr iterator end() noexcept { return std::next(arr_.begin(), size_); }
|
||||
|
||||
constexpr const_iterator end() const noexcept { return cend(); }
|
||||
|
||||
constexpr const_iterator cend() const noexcept { return std::next(arr_.cbegin(), size_); }
|
||||
|
||||
constexpr std::reverse_iterator<iterator> rbegin() noexcept { return std::reverse_iterator(this->end()); }
|
||||
|
||||
constexpr std::reverse_iterator<const_iterator> crbegin() const noexcept { return std::reverse_iterator(this->cend()); }
|
||||
|
||||
constexpr std::reverse_iterator<iterator> rend() noexcept { return std::reverse_iterator(this->begin()); }
|
||||
|
||||
constexpr std::reverse_iterator<const_iterator> crend() const noexcept { return std::reverse_iterator(this->cbegin()); }
|
||||
|
||||
constexpr bool empty() const noexcept { return size_ == 0; }
|
||||
|
||||
constexpr size_t size() const noexcept { return size_; }
|
||||
|
||||
constexpr size_t capacity() const noexcept { return Limit; }
|
||||
|
||||
constexpr size_t max_size() const noexcept { return Limit; }
|
||||
|
||||
constexpr T& operator[](size_t index) noexcept { return arr_[index]; }
|
||||
|
||||
T& at(size_t index)
|
||||
{
|
||||
if (index >= size_)
|
||||
{
|
||||
throw std::out_of_range("index >= size");
|
||||
}
|
||||
return this[index];
|
||||
}
|
||||
|
||||
constexpr const T& operator[](size_t index) const noexcept { return arr_[index]; }
|
||||
|
||||
const T& at(size_t index) const
|
||||
{
|
||||
if (index >= size_)
|
||||
{
|
||||
throw std::out_of_range("index >= size");
|
||||
}
|
||||
return this[index];
|
||||
}
|
||||
|
||||
T& front() { return *arr_[0]; }
|
||||
|
||||
T& back() { return *arr_[size_ - 1]; }
|
||||
};
|
||||
|
||||
} // namespace srb2
|
||||
|
||||
template <typename T, size_t L1, size_t L2>
|
||||
bool operator==(const srb2::StaticVec<T, L1>& lhs, const srb2::StaticVec<T, L2>& rhs)
|
||||
{
|
||||
const size_t size = lhs.size();
|
||||
if (size != rhs.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < lhs; i++)
|
||||
{
|
||||
if (rhs[i] != lhs[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T, size_t L1, size_t L2>
|
||||
bool operator!=(const srb2::StaticVec<T, L1>& lhs, const srb2::StaticVec<T, L2>& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
template <typename T, size_t Limit>
|
||||
struct std::hash<srb2::StaticVec<T, Limit>>
|
||||
{
|
||||
size_t operator()(const srb2::StaticVec<T, Limit>& input) const
|
||||
{
|
||||
constexpr size_t prime = sizeof(size_t) == 8 ? 0x00000100000001B3 : 0x01000193;
|
||||
constexpr size_t basis = sizeof(size_t) == 8 ? 0xcbf29ce484222325 : 0x811c9dc5;
|
||||
|
||||
size_t ret = basis;
|
||||
for (auto itr = input.begin(); itr != input.end(); itr++)
|
||||
{
|
||||
ret = (ret * prime) ^ std::hash<T>(*itr);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __SRB2_CORE_STATIC_VEC_HPP__
|
||||
@@ -0,0 +1,346 @@
|
||||
// BLANKART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2024 by Ronald "Eidolon" Kinard
|
||||
// Copyright (C) 2024 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "thread_pool.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <condition_variable>
|
||||
#include <exception>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
|
||||
//#include <fmt/format.h>
|
||||
//#include <tracy/tracy/Tracy.hpp>
|
||||
|
||||
#include "../cxxutil.hpp"
|
||||
#include "../m_argv.h"
|
||||
|
||||
using namespace srb2;
|
||||
|
||||
static void do_work(ThreadPool::Task& work)
|
||||
{
|
||||
try
|
||||
{
|
||||
//ZoneScoped;
|
||||
(work.thunk)(work.raw.data());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// can't do anything
|
||||
}
|
||||
|
||||
(work.deleter)(work.raw.data());
|
||||
if (work.pseudosema)
|
||||
{
|
||||
work.pseudosema->fetch_sub(1, std::memory_order_relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
static void pool_executor(
|
||||
//int thread_index,
|
||||
std::shared_ptr<std::atomic<bool>> pool_alive,
|
||||
std::shared_ptr<std::mutex> worker_ready_mutex,
|
||||
std::shared_ptr<std::condition_variable> worker_ready_condvar,
|
||||
std::shared_ptr<ThreadPool::Queue> my_wq,
|
||||
std::vector<std::shared_ptr<ThreadPool::Queue>> other_wqs
|
||||
)
|
||||
{
|
||||
{
|
||||
//std::string thread_name = fmt::format("Thread Pool Thread {}", thread_index);
|
||||
//tracy::SetThreadName(thread_name.c_str());
|
||||
}
|
||||
|
||||
int spins = 0;
|
||||
while (true)
|
||||
{
|
||||
std::optional<ThreadPool::Task> work = my_wq->steal();
|
||||
bool did_work = false;
|
||||
if (work)
|
||||
{
|
||||
do_work(*work);
|
||||
|
||||
did_work = true;
|
||||
spins = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto& q : other_wqs)
|
||||
{
|
||||
work = q->steal();
|
||||
if (work)
|
||||
{
|
||||
do_work(*work);
|
||||
|
||||
did_work = true;
|
||||
spins = 0;
|
||||
|
||||
// We only want to steal one work item at a time, to prioritize our own queue
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!did_work)
|
||||
{
|
||||
// Spin a few loops to avoid yielding, then wait for the ready lock
|
||||
spins += 1;
|
||||
if (spins > 100)
|
||||
{
|
||||
std::unique_lock<std::mutex> ready_lock {*worker_ready_mutex};
|
||||
while (my_wq->empty() && pool_alive->load())
|
||||
{
|
||||
worker_ready_condvar->wait(ready_lock);
|
||||
}
|
||||
|
||||
if (!pool_alive->load())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ThreadPool::ThreadPool()
|
||||
{
|
||||
immediate_mode_ = true;
|
||||
}
|
||||
|
||||
ThreadPool::ThreadPool(size_t threads)
|
||||
{
|
||||
next_queue_index_ = 0;
|
||||
pool_alive_ = std::make_shared<std::atomic<bool>>(true);
|
||||
|
||||
for (size_t i = 0; i < threads; i++)
|
||||
{
|
||||
std::shared_ptr<Queue> wsq = std::make_shared<Queue>(2048);
|
||||
work_queues_.push_back(wsq);
|
||||
|
||||
std::shared_ptr<std::mutex> mutex = std::make_shared<std::mutex>();
|
||||
worker_ready_mutexes_.push_back(std::move(mutex));
|
||||
std::shared_ptr<std::condition_variable> condvar = std::make_shared<std::condition_variable>();
|
||||
worker_ready_condvars_.push_back(std::move(condvar));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < threads; i++)
|
||||
{
|
||||
std::shared_ptr<Queue> my_queue = work_queues_[i];
|
||||
std::vector<std::shared_ptr<Queue>> other_queues;
|
||||
for (size_t j = 0; j < threads; j++)
|
||||
{
|
||||
// Order the other queues starting from the next adjacent worker
|
||||
// i.e. if this is worker 2 of 8, then other queues is 3, 4, 5, 6, 7, 0, 1
|
||||
// This tries to balance out work stealing behavior
|
||||
|
||||
size_t other_index = j + i;
|
||||
if (other_index >= threads)
|
||||
{
|
||||
other_index -= threads;
|
||||
}
|
||||
|
||||
if (other_index != i)
|
||||
{
|
||||
other_queues.push_back(work_queues_[other_index]);
|
||||
}
|
||||
}
|
||||
|
||||
std::thread thread;
|
||||
try
|
||||
{
|
||||
thread = std::thread
|
||||
{
|
||||
pool_executor,
|
||||
//i,
|
||||
pool_alive_,
|
||||
worker_ready_mutexes_[i],
|
||||
worker_ready_condvars_[i],
|
||||
my_queue,
|
||||
other_queues
|
||||
};
|
||||
}
|
||||
catch (const std::system_error& error)
|
||||
{
|
||||
// Safe shutdown and rethrow
|
||||
pool_alive_->store(false);
|
||||
for (auto& t : threads_)
|
||||
{
|
||||
t.join();
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
|
||||
threads_.push_back(std::move(thread));
|
||||
}
|
||||
}
|
||||
|
||||
ThreadPool::ThreadPool(ThreadPool&&) = default;
|
||||
ThreadPool::~ThreadPool() = default;
|
||||
|
||||
ThreadPool& ThreadPool::operator=(ThreadPool&&) = default;
|
||||
|
||||
void ThreadPool::begin_sema()
|
||||
{
|
||||
sema_begun_ = true;
|
||||
}
|
||||
|
||||
ThreadPool::Sema ThreadPool::end_sema()
|
||||
{
|
||||
Sema ret = Sema(std::move(cur_sema_));
|
||||
cur_sema_ = nullptr;
|
||||
sema_begun_ = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ThreadPool::notify()
|
||||
{
|
||||
for (size_t i = 0; i < work_queues_.size(); i++)
|
||||
{
|
||||
auto& q = work_queues_[i];
|
||||
size_t count = q->size();
|
||||
if (count > 0)
|
||||
{
|
||||
worker_ready_condvars_[i]->notify_one();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadPool::notify_sema(const ThreadPool::Sema& sema)
|
||||
{
|
||||
if (!sema.pseudosema_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
notify();
|
||||
}
|
||||
|
||||
void ThreadPool::wait_idle()
|
||||
{
|
||||
if (immediate_mode_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//ZoneScoped;
|
||||
|
||||
for (size_t i = 0; i < work_queues_.size(); i++)
|
||||
{
|
||||
auto& q = work_queues_[i];
|
||||
|
||||
std::optional<Task> work;
|
||||
while ((work = q->pop()).has_value())
|
||||
{
|
||||
do_work(*work);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadPool::wait_sema(const Sema& sema)
|
||||
{
|
||||
if (!sema.pseudosema_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//ZoneScoped;
|
||||
|
||||
while (sema.pseudosema_->load(std::memory_order_seq_cst) > 0)
|
||||
{
|
||||
// spin to win
|
||||
for (size_t i = 0; i < work_queues_.size(); i++)
|
||||
{
|
||||
auto& q = work_queues_[i];
|
||||
|
||||
std::optional<Task> work;
|
||||
if ((work = q->pop()).has_value())
|
||||
{
|
||||
do_work(*work);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sema.pseudosema_->load(std::memory_order_seq_cst) != 0)
|
||||
{
|
||||
throw std::exception();
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadPool::shutdown()
|
||||
{
|
||||
if (immediate_mode_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
wait_idle();
|
||||
|
||||
pool_alive_->store(false);
|
||||
|
||||
for (auto& condvar : worker_ready_condvars_)
|
||||
{
|
||||
condvar->notify_all();
|
||||
}
|
||||
for (auto& t : threads_)
|
||||
{
|
||||
t.join();
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<ThreadPool> srb2::g_main_threadpool;
|
||||
|
||||
void I_ThreadPoolInit(void)
|
||||
{
|
||||
SRB2_ASSERT(g_main_threadpool == nullptr);
|
||||
size_t thread_count = std::min(static_cast<unsigned int>(9), std::thread::hardware_concurrency());
|
||||
if (thread_count > 1)
|
||||
{
|
||||
// The main thread will act as a worker when waiting for pool idle
|
||||
// Make one less worker thread to avoid unnecessary context switching
|
||||
thread_count -= 1;
|
||||
}
|
||||
|
||||
if (M_CheckParm("-singlethreaded"))
|
||||
{
|
||||
g_main_threadpool = std::make_unique<ThreadPool>();
|
||||
}
|
||||
else
|
||||
{
|
||||
g_main_threadpool = std::make_unique<ThreadPool>(thread_count);
|
||||
}
|
||||
}
|
||||
|
||||
void I_ThreadPoolShutdown(void)
|
||||
{
|
||||
if (!g_main_threadpool)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
g_main_threadpool->shutdown();
|
||||
g_main_threadpool = nullptr;
|
||||
}
|
||||
|
||||
void I_ThreadPoolSubmit(srb2cthunk_t thunk, void* data)
|
||||
{
|
||||
SRB2_ASSERT(g_main_threadpool != nullptr);
|
||||
|
||||
g_main_threadpool->schedule([=]() {
|
||||
(thunk)(data);
|
||||
});
|
||||
g_main_threadpool->notify();
|
||||
}
|
||||
|
||||
void I_ThreadPoolWaitIdle(void)
|
||||
{
|
||||
SRB2_ASSERT(g_main_threadpool != nullptr);
|
||||
|
||||
g_main_threadpool->wait_idle();
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
// BLANKART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2024 by Ronald "Eidolon" Kinard
|
||||
// Copyright (C) 2024 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __SRB2_CORE_THREAD_POOL_H__
|
||||
#define __SRB2_CORE_THREAD_POOL_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <condition_variable>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "spmc_queue.hpp"
|
||||
|
||||
namespace srb2
|
||||
{
|
||||
|
||||
class ThreadPool
|
||||
{
|
||||
public:
|
||||
struct Task
|
||||
{
|
||||
void (*thunk)(void*);
|
||||
void (*deleter)(void*);
|
||||
std::shared_ptr<std::atomic<uint32_t>> pseudosema;
|
||||
std::array<std::byte, 512 - sizeof(void(*)(void*)) * 2 - sizeof(std::shared_ptr<std::atomic<uint32_t>>)> raw;
|
||||
};
|
||||
|
||||
using Queue = SpMcQueue<Task>;
|
||||
|
||||
class Sema
|
||||
{
|
||||
std::shared_ptr<std::atomic<uint32_t>> pseudosema_;
|
||||
|
||||
explicit Sema(std::shared_ptr<std::atomic<uint32_t>> sema) : pseudosema_(sema) {}
|
||||
|
||||
friend class ThreadPool;
|
||||
public:
|
||||
Sema() = default;
|
||||
};
|
||||
|
||||
private:
|
||||
std::shared_ptr<std::atomic<bool>> pool_alive_;
|
||||
std::vector<std::shared_ptr<std::mutex>> worker_ready_mutexes_;
|
||||
std::vector<std::shared_ptr<std::condition_variable>> worker_ready_condvars_;
|
||||
std::vector<std::shared_ptr<Queue>> work_queues_;
|
||||
std::vector<std::thread> threads_;
|
||||
size_t next_queue_index_ = 0;
|
||||
std::shared_ptr<std::atomic<uint32_t>> cur_sema_;
|
||||
|
||||
bool immediate_mode_ = false;
|
||||
bool sema_begun_ = false;
|
||||
|
||||
public:
|
||||
ThreadPool();
|
||||
explicit ThreadPool(size_t threads);
|
||||
ThreadPool(const ThreadPool&) = delete;
|
||||
ThreadPool(ThreadPool&&);
|
||||
~ThreadPool();
|
||||
|
||||
ThreadPool& operator=(const ThreadPool&) = delete;
|
||||
ThreadPool& operator=(ThreadPool&&);
|
||||
|
||||
void begin_sema();
|
||||
ThreadPool::Sema end_sema();
|
||||
|
||||
/// Enqueue but don't notify
|
||||
template <typename T> void schedule(T&& thunk);
|
||||
/// Notify threads after several schedules
|
||||
void notify();
|
||||
void notify_sema(const Sema& sema);
|
||||
void wait_idle();
|
||||
void wait_sema(const Sema& sema);
|
||||
void shutdown();
|
||||
};
|
||||
|
||||
extern std::unique_ptr<ThreadPool> g_main_threadpool;
|
||||
|
||||
template <typename F>
|
||||
void callable_caller(F* f)
|
||||
{
|
||||
(*f)();
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
void callable_destroyer(F* f)
|
||||
{
|
||||
f->~F();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ThreadPool::schedule(T&& thunk)
|
||||
{
|
||||
static_assert(sizeof(T) <= sizeof(std::declval<Task>().raw));
|
||||
|
||||
if (immediate_mode_)
|
||||
{
|
||||
(thunk)();
|
||||
return;
|
||||
}
|
||||
|
||||
if (sema_begun_)
|
||||
{
|
||||
if (cur_sema_ == nullptr)
|
||||
{
|
||||
cur_sema_ = std::make_shared<std::atomic<uint32_t>>(0);
|
||||
}
|
||||
cur_sema_->fetch_add(1, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
size_t qi = next_queue_index_;
|
||||
|
||||
{
|
||||
std::shared_ptr<Queue> q = work_queues_[qi];
|
||||
Task task;
|
||||
task.thunk = reinterpret_cast<void(*)(void*)>(callable_caller<T>);
|
||||
task.deleter = reinterpret_cast<void(*)(void*)>(callable_destroyer<T>);
|
||||
task.pseudosema = cur_sema_;
|
||||
new (reinterpret_cast<T*>(task.raw.data())) T(std::move(thunk));
|
||||
|
||||
q->push(std::move(task));
|
||||
}
|
||||
// worker_ready_condvars_[qi]->notify_one();
|
||||
|
||||
next_queue_index_ += 1;
|
||||
if (next_queue_index_ >= threads_.size())
|
||||
{
|
||||
next_queue_index_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace srb2
|
||||
|
||||
extern "C" {
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
typedef void (*srb2cthunk_t)(void*);
|
||||
|
||||
void I_ThreadPoolInit(void);
|
||||
void I_ThreadPoolShutdown(void);
|
||||
void I_ThreadPoolSubmit(srb2cthunk_t thunk, void* data);
|
||||
void I_ThreadPoolWaitIdle(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __SRB2_CORE_THREAD_POOL_H__
|
||||
+152
@@ -0,0 +1,152 @@
|
||||
#ifndef __SRB2_CXXUTIL_HPP__
|
||||
#define __SRB2_CXXUTIL_HPP__
|
||||
|
||||
#include <cstdlib>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "doomdef.h"
|
||||
|
||||
namespace srb2 {
|
||||
|
||||
template <class F>
|
||||
class Finally {
|
||||
public:
|
||||
explicit Finally(const F& f) noexcept : f_(f) {}
|
||||
explicit Finally(F&& f) noexcept : f_(f) {}
|
||||
|
||||
Finally(Finally&& from) noexcept : f_(std::move(from.f_)), call_(std::exchange(from.call_, false)) {}
|
||||
|
||||
Finally(const Finally& from) = delete;
|
||||
void operator=(const Finally& from) = delete;
|
||||
void operator=(Finally&& from) = delete;
|
||||
|
||||
~Finally() noexcept {
|
||||
if (call_)
|
||||
f_();
|
||||
}
|
||||
|
||||
private:
|
||||
F f_;
|
||||
bool call_ = true;
|
||||
};
|
||||
|
||||
template <class F>
|
||||
Finally<std::decay_t<F>> finally(F&& f) noexcept {
|
||||
return Finally {std::forward<F>(f)};
|
||||
}
|
||||
|
||||
struct SourceLocation {
|
||||
const char* file_name;
|
||||
unsigned int line_number;
|
||||
};
|
||||
|
||||
#define SRB2_SOURCE_LOCATION \
|
||||
srb2::SourceLocation { __FILE__, __LINE__ }
|
||||
|
||||
#ifndef SRB2_ASSERT_HANDLER
|
||||
#define SRB2_ASSERT_HANDLER srb2::IErrorAssertHandler
|
||||
#endif
|
||||
|
||||
#if !defined(NDEBUG) || defined(PARANOIA)
|
||||
// An assertion level of 2 will activate all invocations of the SRB2_ASSERT macro
|
||||
#define SRB2_ASSERTION_LEVEL 2
|
||||
#else
|
||||
// The minimum assertion level is 1
|
||||
#define SRB2_ASSERTION_LEVEL 1
|
||||
#endif
|
||||
|
||||
/// Assert a precondition expression in debug builds.
|
||||
#define SRB2_ASSERT(expr) srb2::do_assert<2, SRB2_ASSERT_HANDLER>([&] { return (expr); }, SRB2_SOURCE_LOCATION, #expr)
|
||||
|
||||
class IErrorAssertHandler {
|
||||
public:
|
||||
static void handle(const SourceLocation& source_location, const char* expression) {
|
||||
I_Error("Assertion failed at %s:%u: %s != true",
|
||||
source_location.file_name,
|
||||
source_location.line_number,
|
||||
expression);
|
||||
}
|
||||
};
|
||||
|
||||
class NoOpAssertHandler {
|
||||
public:
|
||||
static void handle(const SourceLocation& source_location, const char* expression) {(void)source_location; (void)expression;}
|
||||
};
|
||||
|
||||
/// @brief Assert a precondition expression, aborting the application if it fails.
|
||||
/// @tparam Expr
|
||||
/// @tparam Level the level of this assertion; if it is less than or equal to SRB2_ASSERTION_LEVEL, this overload will
|
||||
/// activate.
|
||||
/// @param expr a callable which returns a bool
|
||||
/// @param source_location a struct containing the source location of the assertion, e.g. SRB2_SOURCE_LOCATION
|
||||
/// @param expression the expression evaluated in the expression callable
|
||||
/// @param message an optional message to display for the assertion
|
||||
template <unsigned int Level, class Handler, class Expr>
|
||||
std::enable_if_t<(Level <= SRB2_ASSERTION_LEVEL), void>
|
||||
do_assert(const Expr& expr, const SourceLocation& source_location, const char* expression = "") noexcept {
|
||||
static_assert(Level > 0, "level of an assertion must not be 0");
|
||||
if (!expr()) {
|
||||
Handler::handle(source_location, expression);
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
|
||||
template <unsigned int Level, class, class Expr>
|
||||
std::enable_if_t<(Level > SRB2_ASSERTION_LEVEL), void>
|
||||
do_assert(const Expr&, const SourceLocation&, const char* = "") noexcept {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class NotNull final {
|
||||
T ptr_;
|
||||
|
||||
public:
|
||||
static_assert(std::is_convertible_v<decltype(std::declval<T>() != nullptr), bool>,
|
||||
"T is not comparable with nullptr_t");
|
||||
|
||||
/// @brief Move-construct from the pointer value U, asserting that it is not null. Allows construction of a
|
||||
/// NotNull<T> from any compatible pointer U, for example with polymorphic classes.
|
||||
template <typename U, typename = std::enable_if_t<std::is_convertible_v<U, T>>>
|
||||
constexpr NotNull(U&& rhs) : ptr_(std::forward<U>(rhs)) {
|
||||
SRB2_ASSERT(ptr_ != nullptr);
|
||||
}
|
||||
|
||||
/// @brief Wrap the pointer type T, asserting that the pointer is not null.
|
||||
template <typename = std::enable_if_t<!std::is_same_v<std::nullptr_t, T>>>
|
||||
constexpr NotNull(T rhs) : ptr_(std::move(rhs)) {
|
||||
SRB2_ASSERT(ptr_ != nullptr);
|
||||
}
|
||||
|
||||
/// @brief Copy construction from NotNull of convertible type U. Only if the incoming pointer is NotNull already.
|
||||
template <typename U, typename = std::enable_if_t<std::is_convertible_v<U, T>>>
|
||||
constexpr NotNull(const NotNull<U>& rhs) : NotNull(rhs.get()) {
|
||||
// Value is guaranteed to be not null by construction; no assertion necessary
|
||||
}
|
||||
|
||||
NotNull(const NotNull& rhs) = default;
|
||||
NotNull& operator=(const NotNull& rhs) = default;
|
||||
|
||||
/// @brief Get the stored pointer.
|
||||
constexpr T get() const { return ptr_; }
|
||||
|
||||
/// @brief Convert to T (the pointer type).
|
||||
constexpr operator T() const { return get(); }
|
||||
|
||||
/// @brief Arrow-dereference to *T (the actual value pointed to).
|
||||
constexpr decltype(auto) operator->() const { return get(); }
|
||||
|
||||
/// @brief Dereference to *T (the actual value pointed to).
|
||||
constexpr decltype(auto) operator*() const { return *get(); }
|
||||
|
||||
// It is not allowed to construct NotNull<T> with nullptr regardless of T.
|
||||
NotNull(std::nullptr_t) = delete;
|
||||
NotNull& operator=(std::nullptr_t) = delete;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
NotNull(T) -> NotNull<T>;
|
||||
|
||||
} // namespace srb2
|
||||
|
||||
#endif // __SRB2_CXXUTIL_HPP__
|
||||
+158
-35
@@ -87,6 +87,9 @@ boolean serverrunning = false;
|
||||
INT32 serverplayer = 0;
|
||||
char motd[254], server_context[8]; // Message of the Day, Unique Context (even without Mumble support)
|
||||
|
||||
plrinfo playerinfo[MAXPLAYERS];
|
||||
SINT8 joinnode = 0; // used for CL_VIEWSERVER
|
||||
|
||||
// Server specific vars
|
||||
UINT8 playernode[MAXPLAYERS];
|
||||
|
||||
@@ -95,7 +98,7 @@ UINT8 playernode[MAXPLAYERS];
|
||||
tic_t jointimeout = (3*TICRATE);
|
||||
static boolean sendingsavegame[MAXNETNODES]; // Are we sending the savegame?
|
||||
#ifdef SATURNPAK
|
||||
static boolean resendingsavegame[MAXNETNODES]; // Are we resending the savegame?
|
||||
static tic_t resendingsavegame[MAXNETNODES]; // Are we resending the savegame?
|
||||
static tic_t savegameresendcooldown[MAXNETNODES]; // How long before we can resend again?
|
||||
#endif
|
||||
static tic_t freezetimeout[MAXNETNODES]; // Until when can this node freeze the server before getting a timeout?
|
||||
@@ -1068,6 +1071,7 @@ static void SV_RequireResynch(INT32 node)
|
||||
|
||||
// Initial setup
|
||||
memset(resynch_sent[node], 0, MAXPLAYERS);
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; ++i)
|
||||
{
|
||||
if (!playeringame[i]) // Player not in game so just drop it from required synch
|
||||
@@ -1184,6 +1188,7 @@ typedef enum
|
||||
#endif
|
||||
CL_CONNECTED,
|
||||
CL_ABORTED,
|
||||
CL_VIEWSERVER,
|
||||
CL_ASKFULLFILELIST,
|
||||
CL_CONFIRMCONNECT,
|
||||
#ifdef HAVE_CURL
|
||||
@@ -1247,7 +1252,7 @@ static inline void CL_DrawConnectionStatus(void)
|
||||
if (!menuactive) // menu already draws its own fade
|
||||
V_DrawFadeScreen(0xFF00, 16); // force default
|
||||
|
||||
if (cl_mode != CL_DOWNLOADFILES && cl_mode != CL_LOADFILES && cl_mode != CL_CHECKFILES
|
||||
if (cl_mode != CL_DOWNLOADFILES && cl_mode != CL_LOADFILES && cl_mode != CL_CHECKFILES && cl_mode != CL_VIEWSERVER
|
||||
#ifdef HAVE_CURL
|
||||
&& cl_mode != CL_DOWNLOADHTTPFILES
|
||||
#endif
|
||||
@@ -1367,6 +1372,78 @@ static inline void CL_DrawConnectionStatus(void)
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE|MENUCAPS,
|
||||
va(" %2u/%2u Files",loadcompletednum,fileneedednum));
|
||||
}
|
||||
else if (cl_mode == CL_VIEWSERVER)
|
||||
{
|
||||
V_DrawFill(8, 16, BASEVIDWIDTH - 16, 54, 239);
|
||||
|
||||
V_DrawThinString(12 + 80, 18, V_ALLOWLOWERCASE, va("%s", serverlist[joinnode].info.servername));
|
||||
|
||||
const char *map = va("%sP", serverlist[joinnode].info.mapname);
|
||||
patch_t *current_map = W_LumpExists(map) ? W_CachePatchName(map, PU_CACHE) : W_CachePatchName("BLANKLVL", PU_CACHE);
|
||||
V_DrawSmallScaledPatch(10, 18, 0, current_map);
|
||||
|
||||
V_DrawThinString(12 + 80, 38, V_ALLOWLOWERCASE, va("%s", serverlist[joinnode].info.maptitle));
|
||||
V_DrawThinString(12 + 80, 48, V_ALLOWLOWERCASE, va("%s", Gametype_Names[serverlist[joinnode].info.gametype]));
|
||||
|
||||
if (fileneedednum > 0)
|
||||
{
|
||||
V_DrawThinString(12 + 80, 58, V_ALLOWLOWERCASE|V_ORANGEMAP, va("%i Addons", fileneedednum));
|
||||
}
|
||||
else
|
||||
{
|
||||
V_DrawThinString(12 + 80, 58, V_ALLOWLOWERCASE|V_YELLOWMAP, "Vanilla");
|
||||
}
|
||||
|
||||
if (serverlist[joinnode].info.cheatsenabled)
|
||||
{
|
||||
V_DrawRightAlignedThinString(BASEVIDWIDTH - 12, 58, V_ALLOWLOWERCASE|V_GREENMAP, "Cheats");
|
||||
}
|
||||
|
||||
V_DrawFill(8, 72, BASEVIDWIDTH - 16, 112, 239);
|
||||
|
||||
V_DrawString(12, 74, V_ALLOWLOWERCASE|V_YELLOWMAP, "Players");
|
||||
V_DrawRightAlignedString(BASEVIDWIDTH - 12, 74, V_ALLOWLOWERCASE|V_YELLOWMAP, va("%i / %i", serverlist[joinnode].info.numberofplayer, serverlist[joinnode].info.maxplayer));
|
||||
|
||||
INT32 i;
|
||||
INT32 count = 0;
|
||||
INT32 x = 14;
|
||||
INT32 y = 84;
|
||||
INT32 statuscolor = 1;
|
||||
char player_name[MAXPLAYERNAME+1];
|
||||
if (serverlist[joinnode].info.numberofplayer > 0)
|
||||
{
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playerinfo[i].node < 255)
|
||||
{
|
||||
strncpy(player_name, playerinfo[i].name, MAXPLAYERNAME);
|
||||
V_DrawThinString(x + 10, y, V_ALLOWLOWERCASE|V_6WIDTHSPACE, player_name);
|
||||
|
||||
if (playerinfo[i].team == 0) { statuscolor = 184; } // playing
|
||||
if (playerinfo[i].data & 0x20) { statuscolor = 86; } // tag IT
|
||||
if (playerinfo[i].team == 1) { statuscolor = 128; } // ctf red team
|
||||
if (playerinfo[i].team == 2) { statuscolor = 232; } // ctf blue team
|
||||
if (playerinfo[i].team == 255) { statuscolor = 16; } // spectator or non-team
|
||||
|
||||
V_DrawFill(x, y, 7, 7, 31);
|
||||
V_DrawFill(x, y, 6, 6, statuscolor);
|
||||
|
||||
y += 9;
|
||||
count++;
|
||||
if ((count == 11) || (count == 22))
|
||||
{
|
||||
x += 104;
|
||||
y = 84;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Buttons
|
||||
V_DrawFill(8, BASEVIDHEIGHT - 14, BASEVIDWIDTH - 16, 12, 239);
|
||||
V_DrawThinString(16, BASEVIDHEIGHT - 12, V_ALLOWLOWERCASE, va("[%sESC%s] = Abort", "\x82", "\x80"));
|
||||
V_DrawRightAlignedThinString(BASEVIDWIDTH - 12, BASEVIDHEIGHT - 12, V_ALLOWLOWERCASE, va("[%sENTER%s] = Join", "\x82", "\x80"));
|
||||
}
|
||||
else if (filedownload.current != -1)
|
||||
{
|
||||
INT32 dldlength;
|
||||
@@ -1687,13 +1764,7 @@ static void SV_SendPlayerInfo(INT32 node)
|
||||
|
||||
for (i = 0; i < MSCOMPAT_MAXPLAYERS; i++)
|
||||
{
|
||||
if (i >= MAXPLAYERS)
|
||||
{
|
||||
netbuffer->u.playerinfo[i].node = 255;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (playeringame[i] == UINT8_MAX || !playeringame[i])
|
||||
if ((i >= MAXPLAYERS) || !playeringame[i])
|
||||
{
|
||||
netbuffer->u.playerinfo[i].node = 255; // This slot is empty.
|
||||
continue;
|
||||
@@ -1778,8 +1849,6 @@ static boolean SV_SendServerConfig(INT32 node)
|
||||
memset(netbuffer->u.servercfg.playerskins, 0xFF, sizeof(netbuffer->u.servercfg.playerskins));
|
||||
memset(netbuffer->u.servercfg.playercolor, 0xFF, sizeof(netbuffer->u.servercfg.playercolor));
|
||||
|
||||
memset(netbuffer->u.servercfg.adminplayers, -1, sizeof(netbuffer->u.servercfg.adminplayers));
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
netbuffer->u.servercfg.adminplayers[i] = (SINT8)adminplayers[i];
|
||||
@@ -2476,6 +2545,7 @@ static boolean CL_ServerConnectionSearchTicker(tic_t *asksent)
|
||||
if (i < 0)
|
||||
return true;
|
||||
}
|
||||
joinnode = i;
|
||||
|
||||
// Quit here rather than downloading files and being refused later.
|
||||
if (serverlist[i].info.numberofplayer >= serverlist[i].info.maxplayer)
|
||||
@@ -2502,7 +2572,7 @@ static boolean CL_ServerConnectionSearchTicker(tic_t *asksent)
|
||||
return true;
|
||||
}
|
||||
|
||||
cl_mode = CL_CHECKFILES;
|
||||
cl_mode = (cv_serverinfoscreen.value) ? CL_VIEWSERVER : CL_CHECKFILES;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2556,7 +2626,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
|
||||
|
||||
case CL_ASKFULLFILELIST:
|
||||
if (cl_lastcheckedfilecount == UINT16_MAX) // All files retrieved
|
||||
cl_mode = CL_CHECKFILES;
|
||||
cl_mode = (cv_serverinfoscreen.value) ? CL_VIEWSERVER : CL_CHECKFILES;
|
||||
else if (fileneedednum != cl_lastcheckedfilecount || I_GetTime() >= *asksent)
|
||||
{
|
||||
if (CL_AskFileList(fileneedednum))
|
||||
@@ -2722,6 +2792,15 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
|
||||
D_ProcessEvents(); //needed for menu system to receive inputs
|
||||
|
||||
key = I_GetKey();
|
||||
|
||||
if (cl_mode == CL_VIEWSERVER)
|
||||
{
|
||||
if (key == KEY_ENTER || key == KEY_JOY1)
|
||||
cl_mode = CL_CHECKFILES;
|
||||
else if (key == KEY_ESCAPE || key == KEY_JOY1+1)
|
||||
cl_mode = CL_ABORTED;
|
||||
}
|
||||
|
||||
// Only ESC and non-keyboard keys abort connection
|
||||
if (!modeattacking && (key == KEY_ESCAPE || key == KEY_JOY1+1 || cl_mode == CL_ABORTED))
|
||||
{
|
||||
@@ -3275,7 +3354,7 @@ void CL_ClearPlayer(INT32 playernum)
|
||||
P_RemoveMobj(players[playernum].mo);
|
||||
}
|
||||
|
||||
memset(&players[playernum], 0, sizeof (player_t));
|
||||
memset(&players[playernum], 0, sizeof(player_t));
|
||||
}
|
||||
|
||||
//
|
||||
@@ -4149,6 +4228,8 @@ consvar_t cv_downloadspeed = {"downloadspeed", "300", CV_SAVE, downloadspeed_con
|
||||
static CV_PossibleValue_t connectawaittime_cons_t[] = {{1, "MIN"}, {60, "MAX"}, {0, "Inf"}, {0, NULL}};
|
||||
consvar_t cv_connectawaittime = {"connectawaittime", "5", CV_SAVE, connectawaittime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_serverinfoscreen = {"serverinfoscreen", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
static void Got_AddPlayer(UINT8 **p, INT32 playernum);
|
||||
static void Got_RemovePlayer(UINT8 **p, INT32 playernum);
|
||||
|
||||
@@ -4251,7 +4332,7 @@ static void ResetNode(INT32 node)
|
||||
// SATURN
|
||||
#ifdef SATURNPAK
|
||||
is_client_saturn[node] = false;
|
||||
resendingsavegame[node] = false;
|
||||
resendingsavegame[node] = 0;
|
||||
savegameresendcooldown[node] = 0;
|
||||
gamestate_resend_counter[node] = 0;
|
||||
#endif
|
||||
@@ -4284,14 +4365,14 @@ void SV_ResetServer(void)
|
||||
sprintf(player_names[i], "Player %d", i + 1);
|
||||
}
|
||||
|
||||
memset(player_name_changes, 0, sizeof player_name_changes);
|
||||
memset(player_name_changes, 0, sizeof(player_name_changes));
|
||||
|
||||
memset(playeringame, false, sizeof playeringame);
|
||||
memset(playernode, UINT8_MAX, sizeof playernode);
|
||||
memset(playeringame, false, sizeof(playeringame));
|
||||
memset(playernode, UINT8_MAX, sizeof(playernode));
|
||||
|
||||
pingmeasurecount = 1;
|
||||
memset(realpingtable, 0, sizeof realpingtable);
|
||||
memset(playerpingtable, 0, sizeof playerpingtable);
|
||||
memset(realpingtable, 0, sizeof(realpingtable));
|
||||
memset(playerpingtable, 0, sizeof(playerpingtable));
|
||||
|
||||
ClearAdminPlayers();
|
||||
|
||||
@@ -4916,6 +4997,16 @@ static void HandleServerInfo(SINT8 node)
|
||||
if (client && cl_mode > CL_SEARCHING && node == servernode)
|
||||
memcpy(connectedservername, netbuffer->u.serverinfo.servername, MAXSERVERNAME);
|
||||
}
|
||||
|
||||
|
||||
static void HandlePlayerInfo(SINT8 node)
|
||||
{
|
||||
(void)node;
|
||||
|
||||
INT32 i;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
playerinfo[i] = netbuffer->u.playerinfo[i];
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SATURNPAK
|
||||
@@ -4952,7 +5043,7 @@ static void PT_CanReceiveGamestate(SINT8 node)
|
||||
CONS_Printf(M_GetText("Resending game state to %s...\n"), player_names[nodetoplayer[node]]);
|
||||
|
||||
SV_SendSaveGame(node, true); // Resend a complete game state
|
||||
resendingsavegame[node] = true;
|
||||
resendingsavegame[node] = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -5204,6 +5295,10 @@ static void HandlePacketFromAwayNode(SINT8 node)
|
||||
|
||||
case PT_CLIENTCMD:
|
||||
break; // This is not an "unknown packet"
|
||||
|
||||
case PT_PLAYERINFO:
|
||||
HandlePlayerInfo(node);
|
||||
break;
|
||||
|
||||
case PT_SERVERTICS:
|
||||
// Do not remove my own server (we have just get a out of order packet)
|
||||
@@ -5324,18 +5419,18 @@ static void HandlePacketFromPlayer(SINT8 node)
|
||||
/// \todo Use a separate cvar for that kind of timeout?
|
||||
freezetimeout[node] = I_GetTime() + connectiontimeout;
|
||||
|
||||
// If we've alredy received a ticcmd for this tic, just submit it for the next one.
|
||||
tic_t faketic = maketic;
|
||||
if ((!!(netcmds[maketic % TICQUEUE][netconsole].angleturn & TICCMD_RECEIVED))
|
||||
&& (maketic - firstticstosend < TICQUEUE - 1))
|
||||
faketic++;
|
||||
|
||||
// Don't do anything for packets of type NODEKEEPALIVE?
|
||||
// Sryder 2018/07/01: Update the freezetimeout still!
|
||||
if (netbuffer->packettype == PT_NODEKEEPALIVE
|
||||
|| netbuffer->packettype == PT_NODEKEEPALIVEMIS)
|
||||
break;
|
||||
|
||||
// If we've alredy received a ticcmd for this tic, just submit it for the next one.
|
||||
tic_t faketic = maketic;
|
||||
if ((!!(netcmds[maketic % TICQUEUE][netconsole].angleturn & TICCMD_RECEIVED))
|
||||
&& (maketic - firstticstosend < TICQUEUE - 1))
|
||||
faketic++;
|
||||
|
||||
// Copy ticcmd
|
||||
G_MoveTiccmd(&netcmds[faketic%TICQUEUE][netconsole], &netbuffer->u.clientpak.cmd, 1);
|
||||
|
||||
@@ -5395,11 +5490,11 @@ static void HandlePacketFromPlayer(SINT8 node)
|
||||
|
||||
// Check player consistancy during the level
|
||||
if (gamestate == GS_LEVEL
|
||||
&& (realstart > gametic - TICQUEUE+1 && realstart <= gametic)
|
||||
&& (realstart <= gametic && realstart + TICQUEUE - 1 > gametic)
|
||||
&& consistancy[realstart%TICQUEUE] != SHORT(netbuffer->u.clientpak.consistancy)
|
||||
&& (!UseSaturnSynch(node) || (!resendingsavegame[node] && savegameresendcooldown[node] <= I_GetTime() && !SV_ResendingSavegameToAnyone())))
|
||||
{
|
||||
resendingsavegame[node] = false; // reset this before just in case
|
||||
resendingsavegame[node] = 0; // reset this before just in case
|
||||
|
||||
// Check if a client is saturn before sending ANYTHING!
|
||||
// this way we only send stuff to clients we know can use the gamestate resend
|
||||
@@ -5409,7 +5504,7 @@ static void HandlePacketFromPlayer(SINT8 node)
|
||||
// Tell the client we are about to resend them the gamestate
|
||||
netbuffer->packettype = PT_WILLRESENDGAMESTATE;
|
||||
HSendPacket(node, true, 0, 0);
|
||||
resendingsavegame[node] = true;
|
||||
resendingsavegame[node] = 1;
|
||||
}
|
||||
else if (UseVanillaSynch(node))
|
||||
{
|
||||
@@ -5425,10 +5520,13 @@ static void HandlePacketFromPlayer(SINT8 node)
|
||||
}
|
||||
|
||||
if (cv_blamecfail.value)
|
||||
{
|
||||
CONS_Printf(M_GetText("Synch failure for player %d (%s); expected %hd, got %hd\n"),
|
||||
netconsole+1, player_names[netconsole],
|
||||
consistancy[realstart%TICQUEUE],
|
||||
SHORT(netbuffer->u.clientpak.consistancy));
|
||||
}
|
||||
|
||||
DEBFILE(va("Restoring player %d (synch failure) [%update] %d!=%d\n",
|
||||
netconsole, realstart, consistancy[realstart%TICQUEUE],
|
||||
SHORT(netbuffer->u.clientpak.consistancy)));
|
||||
@@ -5700,7 +5798,7 @@ static void HandlePacketFromPlayer(SINT8 node)
|
||||
break;
|
||||
}
|
||||
|
||||
//Update client ping table from the server.
|
||||
// Update client ping table from the server.
|
||||
if (client)
|
||||
{
|
||||
UINT8 i;
|
||||
@@ -5736,7 +5834,7 @@ static void HandlePacketFromPlayer(SINT8 node)
|
||||
break;
|
||||
case PT_RECEIVEDGAMESTATE:
|
||||
sendingsavegame[node] = false;
|
||||
resendingsavegame[node] = false;
|
||||
resendingsavegame[node] = 0;
|
||||
savegameresendcooldown[node] = I_GetTime() + cv_resynchcooldown.value * TICRATE; // I_GetTime() + 5 * TICRATE;
|
||||
break;
|
||||
case PT_WILLRESENDGAMESTATE:
|
||||
@@ -5796,8 +5894,9 @@ static void GetPackets(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (netbuffer->packettype == PT_PLAYERINFO)
|
||||
continue; // We do nothing with PLAYERINFO, that's for the MS browser.
|
||||
/*if (netbuffer->packettype == PT_PLAYERINFO)
|
||||
continue; // We do nothing with PLAYERINFO, that's for the MS browser. Not quite true anymore :p*/
|
||||
|
||||
|
||||
// We also count unknown packets, hence "<="
|
||||
if (netbuffer->packettype <= NUMPACKETTYPE)
|
||||
@@ -6366,10 +6465,35 @@ static void SV_Maketic(void)
|
||||
maketic++;
|
||||
}
|
||||
|
||||
#ifdef SATURNPAK
|
||||
static void SV_UpdateResendGamestateTimeout(void)
|
||||
{
|
||||
for (INT32 i = 0; i < MAXNETNODES; ++i)
|
||||
{
|
||||
if (!resendingsavegame[i])
|
||||
continue;
|
||||
|
||||
resendingsavegame[i]++;
|
||||
|
||||
// Resending savegame took too long
|
||||
if (resendingsavegame[i] > (tic_t)TICRATE*cv_pingtimeout.value)
|
||||
{
|
||||
resendingsavegame[i] = 0;
|
||||
SendKick(i, KICK_MSG_CON_FAIL);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
boolean TryRunTics(tic_t realtics)
|
||||
{
|
||||
boolean ticking;
|
||||
|
||||
#ifdef SATURNPAK
|
||||
if (server)
|
||||
SV_UpdateResendGamestateTimeout();
|
||||
#endif
|
||||
|
||||
// the machine has lagged but it is not so bad
|
||||
if (realtics > TICRATE/7) // FIXME: consistency failure!!
|
||||
{
|
||||
@@ -6510,7 +6634,6 @@ static inline void PingUpdate(void)
|
||||
if (pingtimeout[i] > 0)
|
||||
pingtimeout[i]--;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//kick lagging players... unless everyone but the server's ping sucks.
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
#ifndef __D_CLISRV__
|
||||
#define __D_CLISRV__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "d_ticcmd.h"
|
||||
#include "d_net.h"
|
||||
#include "d_netcmd.h"
|
||||
@@ -577,6 +581,9 @@ extern boolean acceptnewnode;
|
||||
extern SINT8 servernode;
|
||||
extern char connectedservername[MAXSERVERNAME+1];
|
||||
|
||||
extern plrinfo playerinfo[MAXPLAYERS];
|
||||
extern SINT8 joinnode;
|
||||
|
||||
void Command_Ping_f(void);
|
||||
extern tic_t connectiontimeout;
|
||||
extern tic_t jointimeout;
|
||||
@@ -608,6 +615,8 @@ extern consvar_t cv_connectawaittime;
|
||||
|
||||
extern consvar_t cv_discordinvites;
|
||||
|
||||
extern consvar_t cv_serverinfoscreen;
|
||||
|
||||
// Used in d_net, the only dependence
|
||||
//tic_t ExpandTics(INT32 low, tic_t basetic);
|
||||
void D_ClientServerInit(void);
|
||||
@@ -689,4 +698,9 @@ typedef struct rewind_s {
|
||||
void CL_ClearRewinds(void);
|
||||
rewind_t *CL_SaveRewindPoint(size_t demopos);
|
||||
rewind_t *CL_RewindToTime(tic_t time);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+154
-125
@@ -73,6 +73,8 @@
|
||||
#include "m_perfstats.h"
|
||||
#include "k_kart.h"
|
||||
|
||||
#include "core/memory.h"
|
||||
|
||||
#include "lua_script.h"
|
||||
|
||||
#ifdef CMAKECONFIG
|
||||
@@ -197,12 +199,10 @@ static void D_PadMenuScrollInput(UINT8 input)
|
||||
// and pass it to the eventlist
|
||||
static void D_GamePadMenuScrollTicker(void)
|
||||
{
|
||||
UINT8 i;
|
||||
static UINT8 menuInputDelayTimer = 0;
|
||||
|
||||
if (dedicated)
|
||||
return;
|
||||
|
||||
for (UINT8 i = 0; i < 4; i++)
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
if (dpadscrollstate[i])
|
||||
{
|
||||
@@ -222,10 +222,10 @@ static void D_GamePadMenuScrollTicker(void)
|
||||
static void D_DeviceLEDTick(void)
|
||||
{
|
||||
UINT8 i;
|
||||
static UINT16 color[MAXSPLITSCREENPLAYERS] = {0, 0, 0, 0};
|
||||
static UINT16 curcolor[MAXSPLITSCREENPLAYERS] = {0, 0, 0, 0};
|
||||
static UINT16 color[MAXSPLITSCREENPLAYERS] = {0};
|
||||
static UINT16 curcolor[MAXSPLITSCREENPLAYERS] = {0};
|
||||
|
||||
if (dedicated || numcontrollers == 0)
|
||||
if (numcontrollers == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -252,7 +252,6 @@ static void D_DeviceLEDTick(void)
|
||||
void D_ProcessEvents(void)
|
||||
{
|
||||
event_t *ev;
|
||||
|
||||
boolean eaten;
|
||||
|
||||
for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1))
|
||||
@@ -291,8 +290,10 @@ void D_ProcessEvents(void)
|
||||
|
||||
// Demo input:
|
||||
if (demo.playback)
|
||||
{
|
||||
if (M_DemoResponder(ev))
|
||||
continue; // demo ate the event
|
||||
}
|
||||
|
||||
// console input
|
||||
#ifdef HAVE_THREADS
|
||||
@@ -317,6 +318,110 @@ void D_ProcessEvents(void)
|
||||
// draw current display, possibly wiping it from the previous
|
||||
//
|
||||
|
||||
static void D_Renderview(void)
|
||||
{
|
||||
UINT8 i;
|
||||
|
||||
if (automapactive)
|
||||
return;
|
||||
|
||||
R_ApplyLevelInterpolators(rendertimefrac);
|
||||
|
||||
if (rendermode == render_soft)
|
||||
{
|
||||
// if this is display player 1
|
||||
if (cv_homremoval.value)
|
||||
{
|
||||
if (cv_homremoval.value == 1)
|
||||
{
|
||||
// Clear the software screen buffer to remove HOM
|
||||
memset(vid.screens[0], 31, vid.width * vid.height);
|
||||
}
|
||||
else if (cv_homremoval.value == 2)
|
||||
{
|
||||
//'development' HOM removal -- makes it blindingly obvious if HOM is spotted.
|
||||
memset(vid.screens[0], 32+(timeinmap&15), vid.width * vid.height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw over the fourth screen so you don't have to stare at a HOM :V
|
||||
if (splitscreen == 2)
|
||||
{
|
||||
// V_DrawPatchFill, but for the fourth screen only
|
||||
patch_t *pat = W_CachePatchName("SRB2BACK", PU_CACHE);
|
||||
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
|
||||
INT32 x, y, pw = SHORT(pat->width) * dupz, ph = SHORT(pat->height) * dupz;
|
||||
|
||||
for (x = vid.width>>1; x < vid.width; x += pw)
|
||||
{
|
||||
for (y = vid.height>>1; y < vid.height; y += ph)
|
||||
V_DrawScaledPatch(x, y, V_NOSCALESTART, pat);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i <= splitscreen; i++)
|
||||
{
|
||||
const boolean issplitscreen = (i > 0);
|
||||
|
||||
if (!P_MobjWasRemoved(players[displayplayers[i]].mo) || players[displayplayers[i]].playerstate == PST_DEAD)
|
||||
{
|
||||
viewssnum = i;
|
||||
|
||||
if (!issplitscreen) // Initialize for P1
|
||||
{
|
||||
viewwindowy = viewwindowx = 0;
|
||||
objectsdrawn = 0;
|
||||
}
|
||||
|
||||
#ifdef HWRENDER
|
||||
if (rendermode == render_opengl)
|
||||
{
|
||||
HWR_RenderPlayerView();
|
||||
R_RestoreLevelInterpolators();
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (issplitscreen) // Splitscreen-specific
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (splitscreen > 1)
|
||||
{
|
||||
viewwindowx = viewwidth;
|
||||
viewwindowy = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
viewwindowx = 0;
|
||||
viewwindowy = viewheight;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
viewwindowx = 0;
|
||||
viewwindowy = viewheight;
|
||||
break;
|
||||
case 3:
|
||||
viewwindowx = viewwidth;
|
||||
viewwindowy = viewheight;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
R_RenderPlayerView(&players[displayplayers[i]]);
|
||||
}
|
||||
|
||||
if (!issplitscreen)
|
||||
R_ApplyViewMorph();
|
||||
|
||||
V_DoPostProcessor(i, postimgparam[i]);
|
||||
}
|
||||
|
||||
R_RestoreLevelInterpolators();
|
||||
}
|
||||
|
||||
// wipegamestate can be set to -1 to force a wipe on the next draw
|
||||
// added comment : there is a wipe eatch change of the gamestate
|
||||
gamestate_t wipegamestate = GS_LEVEL;
|
||||
@@ -327,7 +432,6 @@ static boolean D_Display(void)
|
||||
boolean forcerefresh = false;
|
||||
static boolean wipe = false;
|
||||
INT32 wipedefindex = 0;
|
||||
UINT8 i;
|
||||
|
||||
if (!dedicated)
|
||||
{
|
||||
@@ -366,6 +470,7 @@ static boolean D_Display(void)
|
||||
{
|
||||
// set for all later
|
||||
wipedefindex = gamestate; // wipe_xxx_toblack
|
||||
|
||||
if (gamestate == GS_TITLESCREEN && wipegamestate != GS_INTRO)
|
||||
wipedefindex = wipe_timeattack_toblack;
|
||||
else if (gamestate == GS_INTERMISSION)
|
||||
@@ -378,26 +483,28 @@ static boolean D_Display(void)
|
||||
|
||||
if (!dedicated)
|
||||
{
|
||||
// Fade to black first
|
||||
if (gamestate != GS_LEVEL // fades to black on its own timing, always
|
||||
&& wipedefs[wipedefindex] != UINT8_MAX)
|
||||
if (gamestate != GS_LEVEL)
|
||||
{
|
||||
F_WipeStartScreen();
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
|
||||
F_WipeEndScreen();
|
||||
F_RunWipe(wipedefs[wipedefindex], gamestate != GS_TIMEATTACK);
|
||||
ranwipe = true;
|
||||
}
|
||||
// Fade to black first
|
||||
if (wipedefs[wipedefindex] != UINT8_MAX) // fades to black on its own timing, always
|
||||
{
|
||||
F_WipeStartScreen();
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
|
||||
F_WipeEndScreen();
|
||||
F_RunWipe(wipedefs[wipedefindex], gamestate != GS_TIMEATTACK);
|
||||
ranwipe = true;
|
||||
}
|
||||
|
||||
if (gamestate != GS_LEVEL && rendermode != render_none)
|
||||
{
|
||||
V_SetPaletteLump("PLAYPAL"); // Reset the palette
|
||||
R_ReInitColormaps(0, LUMPERROR);
|
||||
if (rendermode != render_none)
|
||||
{
|
||||
V_SetPaletteLump("PLAYPAL"); // Reset the palette
|
||||
R_ReInitColormaps(0, LUMPERROR);
|
||||
}
|
||||
}
|
||||
|
||||
F_WipeStartScreen();
|
||||
}
|
||||
else //dedicated servers
|
||||
else // dedicated servers
|
||||
{
|
||||
F_RunWipe(wipedefs[wipedefindex], gamestate != GS_TIMEATTACK);
|
||||
ranwipe = true;
|
||||
@@ -405,7 +512,7 @@ static boolean D_Display(void)
|
||||
}
|
||||
}
|
||||
|
||||
if (dedicated) //bail out after wipe logic
|
||||
if (dedicated) // bail out after wipe logic
|
||||
return false;
|
||||
|
||||
// do buffered drawing
|
||||
@@ -430,9 +537,6 @@ static boolean D_Display(void)
|
||||
HU_Drawer();
|
||||
break;
|
||||
|
||||
case GS_TIMEATTACK:
|
||||
break;
|
||||
|
||||
case GS_INTRO:
|
||||
F_IntroDrawer();
|
||||
if (wipegamestate == (gamestate_t)-1)
|
||||
@@ -484,6 +588,7 @@ static boolean D_Display(void)
|
||||
HU_Erase();
|
||||
HU_Drawer();
|
||||
}
|
||||
case GS_TIMEATTACK:
|
||||
case GS_DEDICATEDSERVER:
|
||||
case GS_NULL:
|
||||
break;
|
||||
@@ -492,89 +597,10 @@ static boolean D_Display(void)
|
||||
if (gamestate == GS_LEVEL)
|
||||
{
|
||||
// draw the view directly
|
||||
if (cv_renderview.value && !automapactive)
|
||||
if (cv_renderview.value)
|
||||
{
|
||||
PS_START_TIMING(ps_rendercalltime);
|
||||
|
||||
R_ApplyLevelInterpolators(rendertimefrac);
|
||||
|
||||
for (i = 0; i <= splitscreen; i++)
|
||||
{
|
||||
if (!P_MobjWasRemoved(players[displayplayers[i]].mo) || players[displayplayers[i]].playerstate == PST_DEAD)
|
||||
{
|
||||
viewssnum = i;
|
||||
|
||||
if (i == 0) // Initialize for P1
|
||||
{
|
||||
viewwindowy = 0;
|
||||
viewwindowx = 0;
|
||||
|
||||
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
|
||||
objectsdrawn = 0;
|
||||
}
|
||||
|
||||
#ifdef HWRENDER
|
||||
if (rendermode == render_opengl)
|
||||
HWR_RenderPlayerView();
|
||||
else
|
||||
#endif
|
||||
if (rendermode != render_none)
|
||||
{
|
||||
if (i > 0) // Splitscreen-specific
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (splitscreen > 1)
|
||||
{
|
||||
viewwindowx = viewwidth;
|
||||
viewwindowy = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
viewwindowx = 0;
|
||||
viewwindowy = viewheight;
|
||||
}
|
||||
M_Memcpy(ylookup, ylookup2, viewheight*sizeof (ylookup[0]));
|
||||
break;
|
||||
case 2:
|
||||
viewwindowx = 0;
|
||||
viewwindowy = viewheight;
|
||||
M_Memcpy(ylookup, ylookup3, viewheight*sizeof (ylookup[0]));
|
||||
break;
|
||||
case 3:
|
||||
viewwindowx = viewwidth;
|
||||
viewwindowy = viewheight;
|
||||
M_Memcpy(ylookup, ylookup4, viewheight*sizeof (ylookup[0]));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
|
||||
}
|
||||
|
||||
R_RenderPlayerView(&players[displayplayers[i]]);
|
||||
|
||||
if (i > 0)
|
||||
M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rendermode == render_soft)
|
||||
{
|
||||
if (!splitscreen)
|
||||
R_ApplyViewMorph();
|
||||
|
||||
for (i = 0; i <= splitscreen; i++)
|
||||
{
|
||||
V_DoPostProcessor(i, postimgparam[i]);
|
||||
}
|
||||
}
|
||||
|
||||
R_RestoreLevelInterpolators();
|
||||
|
||||
D_Renderview();
|
||||
PS_STOP_TIMING(ps_rendercalltime);
|
||||
}
|
||||
|
||||
@@ -582,8 +608,9 @@ static boolean D_Display(void)
|
||||
{
|
||||
if (rendermode == render_soft)
|
||||
{
|
||||
VID_BlitLinearScreen(screens[0], screens[1], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes);
|
||||
VID_BlitLinearScreen(vid.screens[0], vid.screens[1], vid.width, vid.height, vid.width, vid.rowbytes);
|
||||
}
|
||||
|
||||
lastdraw = false;
|
||||
}
|
||||
|
||||
@@ -606,13 +633,8 @@ static boolean D_Display(void)
|
||||
// draw pause pic
|
||||
if (paused && cv_showhud.value && !demo.playback)
|
||||
{
|
||||
INT32 py;
|
||||
patch_t *patch;
|
||||
if (automapactive)
|
||||
py = 4;
|
||||
else
|
||||
py = viewwindowy + 4;
|
||||
patch = W_CachePatchName("M_PAUSE", PU_PATCH);
|
||||
INT32 py = (automapactive) ? 4 : (viewwindowy + 4);
|
||||
patch_t *patch = W_CachePatchName("M_PAUSE", PU_PATCH);
|
||||
V_DrawScaledPatch(viewwindowx + (BASEVIDWIDTH - patch->width)/2, py, V_SNAPTOTOP, patch);
|
||||
}
|
||||
|
||||
@@ -620,7 +642,7 @@ static boolean D_Display(void)
|
||||
V_DrawFadeScreen(TC_RAINBOW, (leveltime & 0x20) ? SKINCOLOR_PASTEL : SKINCOLOR_MOONSLAM);
|
||||
|
||||
// vid size change is now finished if it was on...
|
||||
vid.recalc = 0;
|
||||
vid.recalc = false;
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
I_lock_mutex(&m_menu_mutex);
|
||||
@@ -752,9 +774,11 @@ void D_SRB2Loop(void)
|
||||
precise_t enterprecise = I_GetPreciseTime();
|
||||
precise_t finishprecise = enterprecise;
|
||||
|
||||
Z_Frame_Reset();
|
||||
|
||||
// Casting the return value of a function is bad practice (apparently)
|
||||
double budget = ((R_GetFramerateCap() == 0) ? 0.0 : round((1.0 / R_GetFramerateCap()) * I_GetPrecisePrecision()));
|
||||
capbudget = (precise_t) budget;
|
||||
capbudget = (precise_t)budget;
|
||||
|
||||
boolean ranwipe = false;
|
||||
|
||||
@@ -824,12 +848,15 @@ void D_SRB2Loop(void)
|
||||
doDisplay = true;
|
||||
}
|
||||
|
||||
if (menuactive)
|
||||
if (!dedicated)
|
||||
{
|
||||
D_GamePadMenuScrollTicker();
|
||||
}
|
||||
if (menuactive)
|
||||
{
|
||||
D_GamePadMenuScrollTicker();
|
||||
}
|
||||
|
||||
D_DeviceLEDTick();
|
||||
D_DeviceLEDTick();
|
||||
}
|
||||
}
|
||||
|
||||
if (interp)
|
||||
@@ -841,7 +868,9 @@ void D_SRB2Loop(void)
|
||||
ps_interp_frac.value.p = (precise_t)((FIXED_TO_FLOAT(g_time.timefrac)) * 1000.0f);
|
||||
ps_interp_lag.value.p = (precise_t)((deltasecs) * 1000.0f);
|
||||
|
||||
if (!(paused || P_AutoPause()) && deltatics < 1.0 && !hu_stopped)
|
||||
const boolean lagging = ((deltatics >= 1.0) || hu_stopped);
|
||||
|
||||
if (!(paused || P_AutoPause()) && !lagging)
|
||||
{
|
||||
rendertimefrac = g_time.timefrac;
|
||||
}
|
||||
@@ -850,7 +879,7 @@ void D_SRB2Loop(void)
|
||||
rendertimefrac = FRACUNIT;
|
||||
}
|
||||
|
||||
if ((deltatics < 1.0) && !hu_stopped)
|
||||
if (!lagging)
|
||||
{
|
||||
rendertimefrac_unpaused = g_time.timefrac;
|
||||
}
|
||||
@@ -923,7 +952,7 @@ void D_SRB2Loop(void)
|
||||
|
||||
if ((elapsed > 0) && ((INT64)capbudget > elapsed) && !vsync_with_match_refresh)
|
||||
{
|
||||
I_SleepDuration(capbudget - (finishprecise - enterprecise));
|
||||
I_SleepDuration(capbudget - elapsed);
|
||||
}
|
||||
}
|
||||
// Capture the time once more to get the real delta time.
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef __D_MAIN__
|
||||
#define __D_MAIN__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "d_event.h"
|
||||
#include "w_wad.h" // for MAX_WADFILES
|
||||
|
||||
@@ -90,4 +94,8 @@ const char *D_Home(void);
|
||||
//
|
||||
void D_StartTitle(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif //__D_MAIN__
|
||||
+8
-2
@@ -18,6 +18,10 @@
|
||||
#ifndef __D_NET__
|
||||
#define __D_NET__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Max computers in a game
|
||||
// 127 is probably as high as this can go, because
|
||||
// SINT8 is used for nodes sometimes >:(
|
||||
@@ -43,8 +47,6 @@ extern SINT8 nodetoplayer4[MAXNETNODES]; // Say the numplayer for this node if a
|
||||
extern UINT8 playerpernode[MAXNETNODES]; // Used specially for splitscreen
|
||||
extern boolean nodeingame[MAXNETNODES]; // Set false as nodes leave game
|
||||
|
||||
extern boolean serverrunning;
|
||||
|
||||
void Net_AckTicker(void);
|
||||
|
||||
// If reliable return true if packet sent, 0 else
|
||||
@@ -65,4 +67,8 @@ void Net_SendAcks(INT32 node);
|
||||
void Net_WaitAllAckReceived(UINT32 timeout);
|
||||
const char *Net_GetPacketName(UINT8 packettype);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+12
-12
@@ -204,11 +204,6 @@ static void Command_Archivetest_f(void);
|
||||
// CLIENT VARIABLES
|
||||
// =========================================================================
|
||||
|
||||
void SendWeaponPref(void);
|
||||
void SendWeaponPref2(void);
|
||||
void SendWeaponPref3(void);
|
||||
void SendWeaponPref4(void);
|
||||
|
||||
static CV_PossibleValue_t usemouse_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Force"}, {0, NULL}};
|
||||
|
||||
static CV_PossibleValue_t autobalance_cons_t[] = {{0, "MIN"}, {4, "MAX"}, {0, NULL}};
|
||||
@@ -216,11 +211,8 @@ static CV_PossibleValue_t teamscramble_cons_t[] = {{0, "Off"}, {1, "Random"}, {2
|
||||
|
||||
static CV_PossibleValue_t startingliveslimit_cons_t[] = {{1, "MIN"}, {99, "MAX"}, {0, NULL}};
|
||||
static CV_PossibleValue_t sleeping_cons_t[] = {{0, "MIN"}, {1000/TICRATE, "MAX"}, {0, NULL}};
|
||||
static CV_PossibleValue_t competitionboxes_cons_t[] = {{0, "Normal"}, {1, "Random"}, {2, "Teleports"},
|
||||
{3, "None"}, {0, NULL}};
|
||||
|
||||
static CV_PossibleValue_t matchboxes_cons_t[] = {{0, "Normal"}, {1, "Random"}, {2, "Non-Random"},
|
||||
{3, "None"}, {0, NULL}};
|
||||
static CV_PossibleValue_t competitionboxes_cons_t[] = {{0, "Normal"}, {1, "Random"}, {2, "Teleports"}, {3, "None"}, {0, NULL}};
|
||||
static CV_PossibleValue_t matchboxes_cons_t[] = {{0, "Normal"}, {1, "Random"}, {2, "Non-Random"}, {3, "None"}, {0, NULL}};
|
||||
|
||||
//static CV_PossibleValue_t chances_cons_t[] = {{0, "MIN"}, {9, "MAX"}, {0, NULL}};
|
||||
static CV_PossibleValue_t match_scoring_cons_t[] = {{0, "Normal"}, {1, "Classic"}, {0, NULL}};
|
||||
@@ -903,6 +895,7 @@ void D_RegisterClientCommands(void)
|
||||
CV_RegisterVar(&cv_netticbuffer);
|
||||
CV_RegisterVar(&cv_mindelay);
|
||||
CV_RegisterVar(&cv_gentlemens);
|
||||
CV_RegisterVar(&cv_serverinfoscreen);
|
||||
|
||||
#ifdef NETGAME_DEVMODE
|
||||
CV_RegisterVar(&cv_fishcake);
|
||||
@@ -1032,6 +1025,8 @@ void D_RegisterClientCommands(void)
|
||||
CV_RegisterVar(&cv_scr_width);
|
||||
CV_RegisterVar(&cv_scr_height);
|
||||
|
||||
CV_RegisterVar(&cv_parallelsoftware);
|
||||
|
||||
CV_RegisterVar(&cv_soundtest);
|
||||
|
||||
CV_RegisterVar(&cv_perfstats);
|
||||
@@ -2775,7 +2770,7 @@ static void Command_Map_f(void)
|
||||
// G_TOLFlag handles both multiplayer gametype and ignores it for !multiplayer
|
||||
else
|
||||
{
|
||||
if (!mapheaderinfo[newmapnum-1] || mapheaderinfo[newmapnum-1] == NULL)
|
||||
if (!mapheaderinfo[newmapnum-1])
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Invalid mapheaderinfo for Course %s (%s)\n"), realmapname, G_BuildMapName(newmapnum));
|
||||
Z_Free(realmapname);
|
||||
@@ -3029,9 +3024,14 @@ static void Command_ReplayMarker(void)
|
||||
adjustedleveltime = 0;
|
||||
|
||||
char *title = G_BuildMapTitle(gamemap);
|
||||
snprintf(demo.titlename, 64, "%s [%i:%02d/%.5s]", title, G_TicsToMinutes(adjustedleveltime, false), G_TicsToSeconds(adjustedleveltime), modeattacking ? "Record Attack" : connectedservername);
|
||||
|
||||
if (title)
|
||||
{
|
||||
snprintf(demo.titlename, 64, "%s [%i:%02d/%.5s]", title, G_TicsToMinutes(adjustedleveltime, false), G_TicsToSeconds(adjustedleveltime), modeattacking ? "Record Attack" : connectedservername);
|
||||
Z_Free(title);
|
||||
}
|
||||
else
|
||||
snprintf(demo.titlename, 64, "[%i:%02d/%.5s]", G_TicsToMinutes(adjustedleveltime, false), G_TicsToSeconds(adjustedleveltime), modeattacking ? "Record Attack" : connectedservername);
|
||||
|
||||
CONS_Printf("Replay will be saved!\n");
|
||||
}
|
||||
|
||||
@@ -15,8 +15,17 @@
|
||||
#ifndef __D_NETCMD__
|
||||
#define __D_NETCMD__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "command.h"
|
||||
|
||||
void SendWeaponPref(void);
|
||||
void SendWeaponPref2(void);
|
||||
void SendWeaponPref3(void);
|
||||
void SendWeaponPref4(void);
|
||||
|
||||
// console vars
|
||||
extern consvar_t cv_playername;
|
||||
extern consvar_t cv_playercolor;
|
||||
@@ -318,4 +327,8 @@ void D_SetPassword(const char *pw);
|
||||
// used for the player setup menu
|
||||
UINT8 CanChangeSkin(INT32 playernum);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -111,7 +111,9 @@ static fileused_t transferFiles[UINT8_MAX + 1];
|
||||
// Receiver structure
|
||||
INT32 fileneedednum; // Number of files needed to join the server
|
||||
fileneeded_t fileneeded[MAX_WADFILES]; // List of needed files
|
||||
#ifdef HAVE_THREADS
|
||||
static I_mutex downloadmutex;
|
||||
#endif
|
||||
char downloaddir[512] = "DOWNLOAD";
|
||||
|
||||
file_download_t filedownload;
|
||||
@@ -1351,14 +1353,18 @@ void CURLAbortFile(void)
|
||||
{
|
||||
filedownload.http_running = false;
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
// lock and unlock to wait for the download thread to exit
|
||||
I_lock_mutex(&downloadmutex);
|
||||
I_unlock_mutex(downloadmutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CURLGetFile(void)
|
||||
{
|
||||
#ifdef HAVE_THREADS
|
||||
I_lock_mutex(&downloadmutex);
|
||||
#endif
|
||||
CURLMcode mc; /* return code used by curl_multi_wait() */
|
||||
CURLcode easyres; /* Return from easy interface */
|
||||
CURLMsg *m; /* for picking up messages with the transfer status */
|
||||
@@ -1453,7 +1459,9 @@ void CURLGetFile(void)
|
||||
}
|
||||
|
||||
filedownload.http_running = false;
|
||||
#ifdef HAVE_THREADS
|
||||
I_unlock_mutex(downloadmutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
HTTP_login *
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
#ifndef __D_NETFIL__
|
||||
#define __D_NETFIL__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "d_clisrv.h"
|
||||
#include "w_wad.h"
|
||||
|
||||
@@ -125,4 +129,8 @@ HTTP_login * CURLGetLogin (const char *url, HTTP_login ***return_prev_next);
|
||||
size_t curlwrite_data(void *ptr, size_t size, size_t nmemb, FILE *stream);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __D_NETFIL__
|
||||
+10
-4
@@ -388,7 +388,7 @@ static void DRPC_GotServerIP(UINT32 address)
|
||||
--------------------------------------------------*/
|
||||
static const char *DRPC_GetServerIP(void)
|
||||
{
|
||||
const char *address;
|
||||
const char *address;
|
||||
|
||||
// If you're connected
|
||||
if (I_GetNodeAddress && (address = I_GetNodeAddress(servernode)) != NULL)
|
||||
@@ -489,7 +489,7 @@ void DRPC_UpdatePresence(void)
|
||||
{
|
||||
#endif
|
||||
discordPresence.state = "Private";
|
||||
#ifdef MASTERSERVER
|
||||
#ifdef MASTERSERVER
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -571,9 +571,15 @@ void DRPC_UpdatePresence(void)
|
||||
{
|
||||
// Map name on tool tip
|
||||
char *title = G_BuildMapTitle(gamemap);
|
||||
snprintf(mapname, 48, "Map: %s", title);
|
||||
if (title)
|
||||
{
|
||||
snprintf(mapname, 48, "Map: %s", title);
|
||||
Z_Free(title);
|
||||
}
|
||||
else
|
||||
snprintf(mapname, 48, "Map: UNKNOWN");
|
||||
|
||||
discordPresence.largeImageText = mapname;
|
||||
Z_Free(title);
|
||||
}
|
||||
|
||||
if (gamestate == GS_LEVEL && Playing())
|
||||
|
||||
@@ -58,6 +58,9 @@
|
||||
// warning C4152: nonstandard extension, function/data pointer conversion in expression
|
||||
// warning C4213: nonstandard extension used : cast on l-value
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "doomtype.h"
|
||||
|
||||
@@ -524,12 +527,15 @@ UINT32 quickncasehash (const char *p, size_t n)
|
||||
return x;
|
||||
}
|
||||
|
||||
#ifndef __cplusplus
|
||||
#ifndef min // Double-Check with WATTCP-32's cdefs.h
|
||||
#define min(x, y) (((x) < (y)) ? (x) : (y))
|
||||
#endif
|
||||
#ifndef max // Double-Check with WATTCP-32's cdefs.h
|
||||
#define max(x, y) (((x) > (y)) ? (x) : (y))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CLAMP
|
||||
#define CLAMP(x, y, z) ((x) < (y) ? (y) : ((x) > (z) ? (z) : (x)))
|
||||
#endif
|
||||
@@ -560,6 +566,14 @@ UINT32 quickncasehash (const char *p, size_t n)
|
||||
#define UNLIKELY(x) (x)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER)
|
||||
#define restrict __restrict
|
||||
#else
|
||||
#define restrict
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// An assert-type mechanism.
|
||||
#ifdef PARANOIA
|
||||
#define I_Assert(e) ((e) ? (void)0 : I_Error("assert failed: %s, file %s, line %d", #e, __FILE__, __LINE__))
|
||||
@@ -657,4 +671,8 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
|
||||
#undef UPDATE_ALERT
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __DOOMDEF__
|
||||
+1
-1
@@ -125,7 +125,7 @@ extern boolean lastdraw;
|
||||
extern INT32 postimgparam[MAXSPLITSCREENPLAYERS];
|
||||
|
||||
extern INT32 viewwindowx, viewwindowy;
|
||||
extern INT32 viewwidth, scaledviewwidth;
|
||||
extern INT32 viewwidth;
|
||||
|
||||
extern boolean gamedataloaded;
|
||||
|
||||
|
||||
+23
-16
@@ -17,6 +17,10 @@
|
||||
#ifndef __DOOMTYPE__
|
||||
#define __DOOMTYPE__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined (_WIN32)
|
||||
//#define WIN32_LEAN_AND_MEAN
|
||||
#define RPC_NO_WINDOWS_H
|
||||
@@ -100,8 +104,10 @@ typedef long ssize_t;
|
||||
#define strnicmp(x,y,n) strncasecmp(x,y,n)
|
||||
#endif
|
||||
|
||||
#ifndef __cplusplus
|
||||
char *strcasestr(const char *in, const char *what);
|
||||
#define stristr strcasestr
|
||||
#endif
|
||||
|
||||
#if defined (macintosh) //|| defined (__APPLE__) //skip all boolean/Boolean crap
|
||||
#define true 1
|
||||
@@ -156,22 +162,19 @@ size_t strlcpy(char *dst, const char *src, size_t siz);
|
||||
|
||||
/* Boolean type definition */
|
||||
|
||||
// \note __BYTEBOOL__ used to be set above if "macintosh" was defined,
|
||||
// if macintosh's version of boolean type isn't needed anymore, then isn't this macro pointless now?
|
||||
#ifndef __BYTEBOOL__
|
||||
#define __BYTEBOOL__
|
||||
|
||||
//faB: clean that up !!
|
||||
#if defined( _MSC_VER) && (_MSC_VER >= 1800) // MSVC 2013 and forward
|
||||
#include "stdbool.h"
|
||||
#elif defined (_WIN32)
|
||||
#define false FALSE // use windows types
|
||||
#define true TRUE
|
||||
#define boolean BOOL
|
||||
#else
|
||||
typedef enum {false, true} boolean;
|
||||
#endif
|
||||
#endif // __BYTEBOOL__
|
||||
#ifndef _WIN32
|
||||
#include <stdbool.h>
|
||||
// dont use stdbools _BOOL type
|
||||
// its smaller (1 byte) than the old interger bool (4 bytes)
|
||||
// which results in packed struct sizes being mismatched between vanilla and this
|
||||
// however we gotta still include stdbool cause since c23 true and false are keywords
|
||||
// which we cant use as enumeration constants
|
||||
typedef int32_t boolean;
|
||||
#else
|
||||
#define false FALSE
|
||||
#define true TRUE
|
||||
#define boolean BOOL
|
||||
#endif
|
||||
|
||||
/* 7.18.2.1 Limits of exact-width integer types */
|
||||
#ifndef INT8_MIN
|
||||
@@ -385,4 +388,8 @@ unset_bit_array (bitarray_t * const array, const int value)
|
||||
|
||||
typedef UINT64 precise_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif //__DOOMTYPE__
|
||||
+3
-2
@@ -531,8 +531,8 @@ static const char *credits[] = {
|
||||
"\"Xyzzy\"",
|
||||
"\"Chearii\"",
|
||||
" ",
|
||||
"\"Sunflower\" aka \"AnimeSonic\"",
|
||||
"\"Yuz\" aka \"Yuzler\"",
|
||||
"\"Sunflower\"",
|
||||
"\"Yuz\"",
|
||||
"\"Democrab\"",
|
||||
"\"EXpand\"",
|
||||
"\"Nexit\"",
|
||||
@@ -543,6 +543,7 @@ static const char *credits[] = {
|
||||
"\"Achii\"",
|
||||
"\"Anonimus\"",
|
||||
"\"scizor300\"",
|
||||
"\"Lugent\"",
|
||||
"",
|
||||
"\1Special Thanks",
|
||||
"SEGA",
|
||||
|
||||
+3
-3
@@ -313,7 +313,7 @@ void F_WipeStartScreen(void)
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
wipe_scr_start = screens[3];
|
||||
wipe_scr_start = vid.screens[3];
|
||||
I_ReadScreen(wipe_scr_start);
|
||||
#endif
|
||||
}
|
||||
@@ -330,7 +330,7 @@ void F_WipeEndScreen(void)
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
wipe_scr_end = screens[4];
|
||||
wipe_scr_end = vid.screens[4];
|
||||
I_ReadScreen(wipe_scr_end);
|
||||
V_DrawBlock(0, 0, 0, vid.width, vid.height, wipe_scr_start);
|
||||
#endif
|
||||
@@ -353,7 +353,7 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu)
|
||||
|
||||
// Init the wipe
|
||||
WipeInAction = true;
|
||||
wipe_scr = screens[0];
|
||||
wipe_scr = vid.screens[0];
|
||||
|
||||
// lastwipetic should either be 0 or the tic we last wiped
|
||||
// on for fade-to-black
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
#ifndef __FILESRCH_H__
|
||||
#define __FILESRCH_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "d_netfil.h"
|
||||
#include "m_menu.h" // MAXSTRINGLENGTH
|
||||
@@ -96,4 +100,8 @@ void closefilemenu(boolean validsize);
|
||||
void searchfilemenu(char *tempname);
|
||||
boolean preparefilemenu(boolean samedepth, boolean replayhut);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __FILESRCH_H__
|
||||
+41
-29
@@ -385,7 +385,8 @@ consvar_t cv_consolechat = {"chatmode", "Window", CV_SAVE, consolechat_cons_t, N
|
||||
consvar_t cv_pauseifunfocused = {"pauseifunfocused", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
// Display song credits
|
||||
consvar_t cv_songcredits = {"songcredits", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
static CV_PossibleValue_t songcredits_cons_t[] = {{0, "Off"}, {1, "Default"}, {2, "Box"}, {0, NULL}};
|
||||
consvar_t cv_songcredits = {"songcredits", "Default", CV_SAVE, songcredits_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
// Show "FREE PLAY" when you're alone. :(
|
||||
consvar_t cv_showfreeplay = { "showfreeplay", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
@@ -3998,7 +3999,6 @@ void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, bool
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char *G_BuildMapTitle(INT32 mapnum)
|
||||
{
|
||||
char *title = NULL;
|
||||
@@ -5465,33 +5465,36 @@ void G_GhostTicker(void)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (type == MT_GHOST)
|
||||
if (type != -1)
|
||||
{
|
||||
mobj = P_SpawnGhostMobj(g->mo); // does a large portion of the work for us
|
||||
mobj->frame = (mobj->frame & ~FF_FRAMEMASK)|tr_trans60<<FF_TRANSSHIFT; // P_SpawnGhostMobj sets trans50, we want trans60
|
||||
}
|
||||
else
|
||||
{
|
||||
mobj = P_SpawnMobj(g->mo->x, g->mo->y, g->mo->z - FixedDiv(FixedMul(g->mo->info->height, g->mo->scale) - g->mo->height,3*FRACUNIT), MT_THOK);
|
||||
mobj->sprite = states[mobjinfo[type].spawnstate].sprite;
|
||||
mobj->frame = (states[mobjinfo[type].spawnstate].frame & FF_FRAMEMASK) | tr_trans60<<FF_TRANSSHIFT;
|
||||
mobj->tics = -1; // nope.
|
||||
mobj->color = g->mo->color;
|
||||
if (g->mo->eflags & MFE_VERTICALFLIP)
|
||||
if (type == MT_GHOST)
|
||||
{
|
||||
mobj->flags2 |= MF2_OBJECTFLIP;
|
||||
mobj->eflags |= MFE_VERTICALFLIP;
|
||||
mobj = P_SpawnGhostMobj(g->mo); // does a large portion of the work for us
|
||||
mobj->frame = (mobj->frame & ~FF_FRAMEMASK)|tr_trans60<<FF_TRANSSHIFT; // P_SpawnGhostMobj sets trans50, we want trans60
|
||||
}
|
||||
P_SetScale(mobj, g->mo->scale);
|
||||
mobj->destscale = g->mo->scale;
|
||||
else
|
||||
{
|
||||
mobj = P_SpawnMobj(g->mo->x, g->mo->y, g->mo->z - FixedDiv(FixedMul(g->mo->info->height, g->mo->scale) - g->mo->height,3*FRACUNIT), MT_THOK);
|
||||
mobj->sprite = states[mobjinfo[type].spawnstate].sprite;
|
||||
mobj->frame = (states[mobjinfo[type].spawnstate].frame & FF_FRAMEMASK) | tr_trans60<<FF_TRANSSHIFT;
|
||||
mobj->tics = -1; // nope.
|
||||
mobj->color = g->mo->color;
|
||||
if (g->mo->eflags & MFE_VERTICALFLIP)
|
||||
{
|
||||
mobj->flags2 |= MF2_OBJECTFLIP;
|
||||
mobj->eflags |= MFE_VERTICALFLIP;
|
||||
}
|
||||
P_SetScale(mobj, g->mo->scale);
|
||||
mobj->destscale = g->mo->scale;
|
||||
}
|
||||
mobj->floorz = mobj->z;
|
||||
mobj->ceilingz = mobj->z+mobj->height;
|
||||
P_UnsetThingPosition(mobj);
|
||||
mobj->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up...
|
||||
P_SetThingPosition(mobj);
|
||||
mobj->fuse = 8;
|
||||
P_SetTarget(&mobj->target, g->mo);
|
||||
}
|
||||
mobj->floorz = mobj->z;
|
||||
mobj->ceilingz = mobj->z+mobj->height;
|
||||
P_UnsetThingPosition(mobj);
|
||||
mobj->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up...
|
||||
P_SetThingPosition(mobj);
|
||||
mobj->fuse = 8;
|
||||
P_SetTarget(&mobj->target, g->mo);
|
||||
}
|
||||
if (ziptic & EZT_HIT)
|
||||
{ // Spawn hit poofs for killing things!
|
||||
@@ -6068,15 +6071,19 @@ void G_BeginRecording(void)
|
||||
char *title = G_BuildMapTitle(gamemap);
|
||||
|
||||
// Print to a separate temp buffer instead of demo.titlename, so we can use it in M_TextInputSetString
|
||||
snprintf(demotitlename, 64, "%s - %s", title, modeattacking ? "Time Attack" : connectedservername);
|
||||
if (title)
|
||||
{
|
||||
snprintf(demotitlename, 64, "%s - %s", title, modeattacking ? "Time Attack" : connectedservername);
|
||||
Z_Free(title);
|
||||
}
|
||||
else
|
||||
snprintf(demotitlename, 64, "%s", modeattacking ? "Time Attack" : connectedservername);
|
||||
|
||||
// Init just in case it isn't initialized already
|
||||
M_TextInputInit(&demo.titlenameinput, demo.titlename, sizeof(demo.titlename));
|
||||
|
||||
// This will indirectly assign to demo.titlename too
|
||||
M_TextInputSetString(&demo.titlenameinput, demotitlename);
|
||||
|
||||
Z_Free(title);
|
||||
}
|
||||
|
||||
// demo checksum
|
||||
@@ -8137,7 +8144,7 @@ void G_SaveDemo(void)
|
||||
size_t i, strindex = 0;
|
||||
boolean dash = true;
|
||||
|
||||
for (i = 0; i < 127 && demo.titlename[i]; i++)
|
||||
for (i = 0; demo.titlename[i] && i < 127; i++)
|
||||
{
|
||||
if ((demo.titlename[i] >= 'a' && demo.titlename[i] <= 'z') ||
|
||||
(demo.titlename[i] >= '0' && demo.titlename[i] <= '9'))
|
||||
@@ -8228,6 +8235,11 @@ boolean G_DemoTitleResponder(event_t *ev)
|
||||
void G_SetGamestate(gamestate_t newstate)
|
||||
{
|
||||
gamestate = newstate;
|
||||
|
||||
//HACK: reset musiccredits whenever we change gamestate
|
||||
// since we allow them to run everywhere now
|
||||
S_ResetMusicCredit();
|
||||
|
||||
#ifdef HAVE_DISCORDRPC
|
||||
DRPC_UpdatePresence();
|
||||
#endif
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef __G_GAME__
|
||||
#define __G_GAME__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "doomstat.h"
|
||||
#include "d_event.h"
|
||||
@@ -484,4 +488,8 @@ void G_AddMapToBuffer(INT16 map);
|
||||
|
||||
void G_FixCamera(UINT8 view);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+1
-1
@@ -1030,7 +1030,7 @@ INT32 G_KeyStringtoNum(const char *keystr)
|
||||
if (!keystr[0])
|
||||
return 0;
|
||||
|
||||
if (!keystr[0] || (!keystr[1] && keystr[0] > ' ' && keystr[0] <= 'z'))
|
||||
if (!keystr[1] && keystr[0] > ' ' && keystr[0] <= 'z')
|
||||
return keystr[0];
|
||||
|
||||
if (!strncmp(keystr, "KEY", 3) && keystr[3] >= '0' && keystr[3] <= '9')
|
||||
|
||||
+13
-32
@@ -89,32 +89,23 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt
|
||||
{
|
||||
if (!pSurf)
|
||||
{
|
||||
I_Error("Got a null FSurfaceInfo in batching");// nulls should not come in the stuff that batching currently applies to
|
||||
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
|
||||
// ran out of space, double the array size
|
||||
polygonArrayAllocSize *= 2;
|
||||
new_array = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry));
|
||||
memcpy(new_array, polygonArray, polygonArraySize * sizeof(PolygonArrayEntry));
|
||||
free(polygonArray);
|
||||
polygonArray = new_array;
|
||||
polygonArray = realloc(polygonArray, polygonArrayAllocSize * sizeof(PolygonArrayEntry));
|
||||
// also need to redo the index array, dont need to copy it though
|
||||
free(polygonArraySorted);
|
||||
polygonArraySorted = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry *));
|
||||
polygonArraySorted = realloc(polygonArraySorted, polygonArrayAllocSize * sizeof(PolygonArrayEntry*));
|
||||
}
|
||||
|
||||
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;
|
||||
unsortedVertexArray = realloc(unsortedVertexArray, unsortedVertexArrayAllocSize * sizeof(FOutVector));
|
||||
}
|
||||
|
||||
// add the polygon data to the arrays
|
||||
@@ -124,7 +115,7 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt
|
||||
polygonArray[polygonArraySize].numVerts = iNumPts;
|
||||
polygonArray[polygonArraySize].polyFlags = PolyFlags;
|
||||
polygonArray[polygonArraySize].texture = current_texture;
|
||||
polygonArray[polygonArraySize].shader = (shader_target != -1) ? HWR_GetShaderFromTarget(shader_target) : shader_target;
|
||||
polygonArray[polygonArraySize].shader = (shader_target != SHADER_NONE) ? HWR_GetShaderFromTarget(shader_target) : shader_target;
|
||||
polygonArray[polygonArraySize].horizonSpecial = horizonSpecial;
|
||||
polygonArraySize++;
|
||||
|
||||
@@ -140,8 +131,8 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt
|
||||
|
||||
static int comparePolygons(const void *p1, const void *p2)
|
||||
{
|
||||
PolygonArrayEntry *poly1 = *(PolygonArrayEntry *const *)p1;
|
||||
PolygonArrayEntry *poly2 = *(PolygonArrayEntry *const *)p2;
|
||||
const PolygonArrayEntry *poly1 = *(PolygonArrayEntry *const *)p1;
|
||||
const PolygonArrayEntry *poly2 = *(PolygonArrayEntry *const *)p2;
|
||||
int diff;
|
||||
INT64 diff64;
|
||||
|
||||
@@ -177,9 +168,7 @@ static int comparePolygons(const void *p1, const void *p2)
|
||||
diff = poly1->surf.LightInfo.fade_end - poly2->surf.LightInfo.fade_end;
|
||||
if (diff != 0) return diff;
|
||||
|
||||
diff = poly1->surf.LightInfo.directional - poly2->surf.LightInfo.directional;
|
||||
|
||||
return diff;
|
||||
return poly1->surf.LightInfo.directional - poly2->surf.LightInfo.directional;
|
||||
}
|
||||
|
||||
static int comparePolygonsNoShaders(const void *p1, const void *p2)
|
||||
@@ -328,19 +317,11 @@ void HWR_RenderBatches(void)
|
||||
// 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;
|
||||
finalVertexArray = realloc(finalVertexArray, finalVertexArrayAllocSize * sizeof(FOutVector));
|
||||
// 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;
|
||||
finalVertexIndexArray = realloc(finalVertexIndexArray, finalVertexArrayAllocSize * 3 * sizeof(UINT32));
|
||||
}
|
||||
// write the vertices of the polygon
|
||||
memcpy(&finalVertexArray[finalVertexWritePos], &unsortedVertexArray[entry->vertsIndex],
|
||||
@@ -396,8 +377,8 @@ void HWR_RenderBatches(void)
|
||||
currentSurfaceInfo.TintColor.rgba != nextSurfaceInfo.TintColor.rgba ||
|
||||
currentSurfaceInfo.FadeColor.rgba != nextSurfaceInfo.FadeColor.rgba ||
|
||||
currentSurfaceInfo.LightInfo.light_level != nextSurfaceInfo.LightInfo.light_level ||
|
||||
currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start ||
|
||||
currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end ||
|
||||
currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start ||
|
||||
currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end ||
|
||||
currentSurfaceInfo.LightInfo.directional != nextSurfaceInfo.LightInfo.directional)
|
||||
{
|
||||
changeState = true;
|
||||
|
||||
+14
-9
@@ -46,12 +46,16 @@ RGBA_t *HWR_GetTexturePalette(void)
|
||||
|
||||
static INT32 format2bpp(GLTextureFormat_t format)
|
||||
{
|
||||
if (format == GL_TEXFMT_RGBA)
|
||||
return 4;
|
||||
else if (format == GL_TEXFMT_ALPHA_INTENSITY_88 || format == GL_TEXFMT_AP_88)
|
||||
return 2;
|
||||
else
|
||||
return 1;
|
||||
switch (format)
|
||||
{
|
||||
case GL_TEXFMT_RGBA:
|
||||
return 4;
|
||||
case GL_TEXFMT_ALPHA_INTENSITY_88:
|
||||
case GL_TEXFMT_AP_88:
|
||||
return 2;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// This code was originally placed directly in HWR_DrawPatchInCache.
|
||||
@@ -221,8 +225,6 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap,
|
||||
if (texture->width <= 0 || texture->height <= 0)
|
||||
return;
|
||||
|
||||
palette = HWR_GetTexturePalette();
|
||||
|
||||
x1 = patch->originx;
|
||||
width = SHORT(realpatch->width);
|
||||
height = SHORT(realpatch->height);
|
||||
@@ -234,6 +236,8 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap,
|
||||
if (patch->originy > texture->height || (patch->originy + height) < 0)
|
||||
return; // patch not located within texture's y bounds, ignore
|
||||
|
||||
palette = HWR_GetTexturePalette();
|
||||
|
||||
// patch is actually inside the texture!
|
||||
// now check if texture is partly off-screen and adjust accordingly
|
||||
|
||||
@@ -323,7 +327,6 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *gltex, boolean noe
|
||||
boolean skyspecial = false; // poor hack for Legacy large skies..
|
||||
|
||||
RGBA_t *palette;
|
||||
palette = HWR_GetTexturePalette();
|
||||
|
||||
texture = textures[texnum];
|
||||
|
||||
@@ -361,6 +364,8 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *gltex, boolean noe
|
||||
INT32 j;
|
||||
RGBA_t col;
|
||||
|
||||
palette = HWR_GetTexturePalette();
|
||||
|
||||
col = palette[HWR_CHROMAKEY_EQUIVALENTCOLORINDEX];
|
||||
|
||||
for (idx = 0, j = 0; j < blockheight; j++)
|
||||
|
||||
@@ -318,6 +318,8 @@ enum hwdsetspecialstate
|
||||
HWD_SET_TEXTUREFILTERMODE,
|
||||
HWD_SET_TEXTUREANISOTROPICMODE,
|
||||
|
||||
HWD_SET_WIREFRAME,
|
||||
|
||||
HWD_SET_MSAA,
|
||||
|
||||
HWD_SET_SCREEN_TEXTURES,
|
||||
|
||||
+34
-25
@@ -96,12 +96,12 @@ void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option)
|
||||
pdupx = pdupy = 2.0f;
|
||||
break;
|
||||
case V_SMALLSCALEPATCH:
|
||||
pdupx = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupx);
|
||||
pdupy = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupy);
|
||||
pdupx = 2.0f * FIXED_TO_FLOAT(vid.smalldupx*FRACUNIT);
|
||||
pdupy = 2.0f * FIXED_TO_FLOAT(vid.smalldupy*FRACUNIT);
|
||||
break;
|
||||
case V_MEDSCALEPATCH:
|
||||
pdupx = 2.0f * FIXED_TO_FLOAT(vid.fmeddupx);
|
||||
pdupy = 2.0f * FIXED_TO_FLOAT(vid.fmeddupy);
|
||||
pdupx = 2.0f * FIXED_TO_FLOAT(vid.meddupx*FRACUNIT);
|
||||
pdupy = 2.0f * FIXED_TO_FLOAT(vid.meddupx*FRACUNIT);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -241,16 +241,16 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p
|
||||
if (option & V_SNAPTORIGHT)
|
||||
cx += (fvw - (FLOATBASEVIDWIDTH * dupx));
|
||||
else if (!(option & V_SNAPTOLEFT))
|
||||
cx += (fvw - (FLOATBASEVIDWIDTH * dupx))/2;
|
||||
cx += (fvw - (FLOATBASEVIDWIDTH * dupx))/2.0f;
|
||||
}
|
||||
if (fabsf(fvh - FLOATBASEVIDHEIGHT * dupy) > 1.0E-36f)
|
||||
{
|
||||
if ((option & (V_SPLITSCREEN|V_SNAPTOTOP)) == (V_SPLITSCREEN|V_SNAPTOTOP))
|
||||
cy += (fvh/2 - (FLOATBASEVIDHEIGHT/2 * dupy));
|
||||
cy += (fvh/2.0f - (FLOATBASEVIDHEIGHT/2.0f * dupy));
|
||||
else if (option & V_SNAPTOBOTTOM)
|
||||
cy += (fvh - (FLOATBASEVIDHEIGHT * dupy));
|
||||
else if (!(option & V_SNAPTOTOP))
|
||||
cy += (fvh - (FLOATBASEVIDHEIGHT * dupy))/2;
|
||||
cy += (fvh - (FLOATBASEVIDHEIGHT * dupy))/2.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -305,10 +305,13 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p
|
||||
FSurfaceInfo Surf;
|
||||
Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff;
|
||||
|
||||
if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[hudtrans];
|
||||
else if (alphalevel == 14) Surf.PolyColor.s.alpha = softwaretranstogl[hudtrans];
|
||||
else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[hudtrans];
|
||||
else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel];
|
||||
switch (alphalevel)
|
||||
{
|
||||
case 13: Surf.PolyColor.s.alpha = softwaretranstogl_lo[hudtrans]; break;
|
||||
case 14: Surf.PolyColor.s.alpha = softwaretranstogl[hudtrans]; break;
|
||||
case 15: Surf.PolyColor.s.alpha = softwaretranstogl_hi[hudtrans]; break;
|
||||
default: Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel]; break;
|
||||
}
|
||||
|
||||
flags |= PF_Modulated;
|
||||
GL_DrawPolygon(&Surf, v, 4, flags);
|
||||
@@ -392,16 +395,16 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
|
||||
if (option & V_SNAPTORIGHT)
|
||||
cx += (fvw - (FLOATBASEVIDWIDTH * dupx));
|
||||
else if (!(option & V_SNAPTOLEFT))
|
||||
cx += (fvw - (FLOATBASEVIDWIDTH * dupx))/2;
|
||||
cx += (fvw - (FLOATBASEVIDWIDTH * dupx))/2.0f;
|
||||
}
|
||||
if (fabsf(fvh - FLOATBASEVIDHEIGHT * dupy) > 1.0E-36f)
|
||||
{
|
||||
if ((option & (V_SPLITSCREEN|V_SNAPTOTOP)) == (V_SPLITSCREEN|V_SNAPTOTOP))
|
||||
cy += (fvh/2 - (FLOATBASEVIDHEIGHT/2 * dupy));
|
||||
cy += (fvh/2.0f - (FLOATBASEVIDHEIGHT/2.0f * dupy));
|
||||
else if (option & V_SNAPTOBOTTOM)
|
||||
cy += (fvh - (FLOATBASEVIDHEIGHT * dupy));
|
||||
else if (!(option & V_SNAPTOTOP))
|
||||
cy += (fvh - (FLOATBASEVIDHEIGHT * dupy))/2;
|
||||
cy += (fvh - (FLOATBASEVIDHEIGHT * dupy))/2.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -467,10 +470,13 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
|
||||
FSurfaceInfo Surf;
|
||||
Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff;
|
||||
|
||||
if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[cv_translucenthud.value];
|
||||
else if (alphalevel == 14) Surf.PolyColor.s.alpha = softwaretranstogl[cv_translucenthud.value];
|
||||
else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[cv_translucenthud.value];
|
||||
else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel];
|
||||
switch (alphalevel)
|
||||
{
|
||||
case 13: Surf.PolyColor.s.alpha = softwaretranstogl_lo[cv_translucenthud.value]; break;
|
||||
case 14: Surf.PolyColor.s.alpha = softwaretranstogl[cv_translucenthud.value]; break;
|
||||
case 15: Surf.PolyColor.s.alpha = softwaretranstogl_hi[cv_translucenthud.value]; break;
|
||||
default: Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel]; break;
|
||||
}
|
||||
|
||||
flags |= PF_Modulated;
|
||||
GL_DrawPolygon(&Surf, v, 4, flags);
|
||||
@@ -487,7 +493,7 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
|
||||
// --------------------------------------------------------------------------
|
||||
// Fills a box of pixels using a flat texture as a pattern
|
||||
// --------------------------------------------------------------------------
|
||||
void HWR_DrawFlatFill (INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum)
|
||||
void HWR_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum)
|
||||
{
|
||||
FOutVector v[4];
|
||||
double dflatsize;
|
||||
@@ -840,7 +846,7 @@ void HWR_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 color)
|
||||
if (color & V_SNAPTORIGHT)
|
||||
fx += (fvw - (FLOATBASEVIDWIDTH * dupx));
|
||||
else if (!(color & V_SNAPTOLEFT))
|
||||
fx += (fvw - (FLOATBASEVIDWIDTH * dupx)) / 2;
|
||||
fx += (fvw - (FLOATBASEVIDWIDTH * dupx)) / 2.0f;
|
||||
}
|
||||
if (fabsf(fvh - (FLOATBASEVIDHEIGHT * dupy)) > 1.0E-36f)
|
||||
{
|
||||
@@ -848,7 +854,7 @@ void HWR_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 color)
|
||||
if (color & V_SNAPTOBOTTOM)
|
||||
fy += (fvh - (FLOATBASEVIDHEIGHT * dupy));
|
||||
else if (!(color & V_SNAPTOTOP))
|
||||
fy += (fvh - (FLOATBASEVIDHEIGHT * dupy)) / 2;
|
||||
fy += (fvh - (FLOATBASEVIDHEIGHT * dupy)) / 2.0f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1122,10 +1128,13 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
|
||||
|
||||
if (alphalevel)
|
||||
{
|
||||
if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[hudtrans];
|
||||
else if (alphalevel == 14) Surf.PolyColor.s.alpha = softwaretranstogl[hudtrans];
|
||||
else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[hudtrans];
|
||||
else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel];
|
||||
switch (alphalevel)
|
||||
{
|
||||
case 13: Surf.PolyColor.s.alpha = softwaretranstogl_lo[hudtrans]; break;
|
||||
case 14: Surf.PolyColor.s.alpha = softwaretranstogl[hudtrans]; break;
|
||||
case 15: Surf.PolyColor.s.alpha = softwaretranstogl_hi[hudtrans]; break;
|
||||
default: Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel]; break;
|
||||
}
|
||||
}
|
||||
|
||||
GL_DrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
|
||||
|
||||
+44
-45
@@ -226,6 +226,8 @@ consvar_t cv_glsolvetjoin = {"gr_solvetjoin", "On", 0, CV_OnOff, NULL, 0, NULL,
|
||||
|
||||
consvar_t cv_glbatching = {"gr_batching", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_glwireframe = {"gr_wireframe", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_glrenderdistance = {"gr_renderdistance", "Max", CV_SAVE, glrenderdistance_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_glhorizonlines = {"gr_horizonlines", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
@@ -338,6 +340,11 @@ static void HWR_SetShaderState(void)
|
||||
GL_SetSpecialState(HWD_SET_SHADERS, HWR_UseShader() ? 1 : 0);
|
||||
}
|
||||
|
||||
static boolean HWR_IsWireframeMode(void)
|
||||
{
|
||||
return (cv_glwireframe.value /*&& cv_debug*/);
|
||||
}
|
||||
|
||||
static boolean HWR_OverrideObjectLightLevel(mobj_t *thing, INT32 *lightlevel)
|
||||
{
|
||||
if (R_ThingIsFullBright(thing))
|
||||
@@ -541,7 +548,7 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
|
||||
size_t len;
|
||||
|
||||
float tempxsow, tempytow;
|
||||
float scrollx = 0.0f, scrolly = 0.0f;
|
||||
float scrollx = 0.0f, scrolly = 0.0f, anglef = 0.0f;
|
||||
angle_t angle = 0;
|
||||
|
||||
static FOutVector *planeVerts = NULL;
|
||||
@@ -661,14 +668,11 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
|
||||
|
||||
if (angle) // Only needs to be done if there's an altered angle
|
||||
{
|
||||
angle = InvAngle(angle)>>ANGLETOFINESHIFT;
|
||||
|
||||
// This needs to be done so everything aligns after rotation
|
||||
// It would be done so that rotation is done, THEN the translation, but I couldn't get it to rotate AND scroll like software does
|
||||
tempxsow = FloatToFixed(flatxref);
|
||||
tempytow = FloatToFixed(flatyref);
|
||||
flatxref = (FixedToFloat(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));
|
||||
flatyref = (FixedToFloat(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));
|
||||
tempxsow = flatxref;
|
||||
tempytow = flatyref;
|
||||
anglef = ANG2RAD(InvAngle(angle));
|
||||
flatxref = (tempxsow * cos(anglef)) - (tempytow * sin(anglef));
|
||||
flatyref = (tempxsow * sin(anglef)) + (tempytow * cos(anglef));
|
||||
}
|
||||
|
||||
#define SETUP3DVERT(vert, vx, vy) {\
|
||||
@@ -679,10 +683,10 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
|
||||
/* Need to rotate before translate */\
|
||||
if (angle) /* Only needs to be done if there's an altered angle */\
|
||||
{\
|
||||
tempxsow = FloatToFixed(vert->s);\
|
||||
tempytow = FloatToFixed(vert->t);\
|
||||
vert->s = (FixedToFloat(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));\
|
||||
vert->t = (FixedToFloat(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));\
|
||||
tempxsow = vert->s;\
|
||||
tempytow = vert->t;\
|
||||
vert->s = (tempxsow * cos(anglef)) - (tempytow * sin(anglef));\
|
||||
vert->t = (tempxsow * sin(anglef)) + (tempytow * cos(anglef));\
|
||||
}\
|
||||
\
|
||||
vert->x = (vx);\
|
||||
@@ -4227,7 +4231,6 @@ static void *HWR_CreateDrawNode(gl_drawnode_type_t type)
|
||||
Z_Realloc(drawnodes, alloceddrawnodes * sizeof(gl_drawnode_t), PU_LEVEL, &drawnodes);
|
||||
}
|
||||
|
||||
|
||||
drawnode = &drawnodes[numdrawnodes++];
|
||||
drawnode->type = type;
|
||||
|
||||
@@ -4458,7 +4461,10 @@ static void HWR_DrawModels(void)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
|
||||
if (!spr->mobj)
|
||||
continue;
|
||||
|
||||
if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
|
||||
{
|
||||
md2_t *md2;
|
||||
|
||||
@@ -5259,6 +5265,9 @@ static void HWR_DrawSkyBackground(void)
|
||||
if (drewsky)
|
||||
return;
|
||||
|
||||
if (HWR_IsWireframeMode())
|
||||
return;
|
||||
|
||||
GL_SetBlend(PF_Translucent|PF_NoDepthTest|PF_Modulated);
|
||||
|
||||
memcpy(&dometransform, &atransform, sizeof(FTransform));
|
||||
@@ -5461,8 +5470,8 @@ void HWR_RenderViewpoint(gl_portal_t *rootportal, const float fpov, player_t *pl
|
||||
HWR_PortalClipping(rootportal);
|
||||
}
|
||||
|
||||
// Set transform.
|
||||
GL_SetTransform(&atransform);
|
||||
if (HWR_IsWireframeMode())
|
||||
GL_SetSpecialState(HWD_SET_WIREFRAME, 1);
|
||||
|
||||
ps_numbspcalls.value.i = 0;
|
||||
ps_numpolyobjects.value.i = 0;
|
||||
@@ -5527,6 +5536,9 @@ void HWR_RenderViewpoint(gl_portal_t *rootportal, const float fpov, player_t *pl
|
||||
ps_hw_nodedrawtime.value.p = 0;
|
||||
HWR_RenderDrawNodes();
|
||||
|
||||
if (HWR_IsWireframeMode())
|
||||
GL_SetSpecialState(HWD_SET_WIREFRAME, 0);
|
||||
|
||||
HWR_FreePortalList(portallist);
|
||||
}
|
||||
|
||||
@@ -5552,28 +5564,12 @@ static void HWR_RenderFrame(player_t *player, boolean skybox)
|
||||
gl_viewwindowx += gl_viewwidth;
|
||||
}
|
||||
|
||||
if (splitscreen == 2 && player == &players[displayplayers[2]])
|
||||
{
|
||||
// V_DrawPatchFill, but for the fourth screen only
|
||||
patch_t *gpatch = W_CachePatchName("SRB2BACK", PU_PATCH);
|
||||
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
|
||||
INT32 x, y, pw = (gpatch->width * dupz), ph = (gpatch->height * dupz);
|
||||
|
||||
for (x = vid.width >> 1; x < vid.width; x += pw)
|
||||
{
|
||||
for (y = vid.height >> 1; y < vid.height; y += ph)
|
||||
HWR_DrawStretchyFixedPatch(gpatch, (x)<<FRACBITS, (y)<<FRACBITS, FRACUNIT, FRACUNIT, V_NOSCALESTART, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// check for new console commands.
|
||||
NetUpdate();
|
||||
|
||||
// Clear view, set viewport (glViewport), set perspective...
|
||||
HWR_ClearView();
|
||||
|
||||
ST_doPaletteStuff();
|
||||
|
||||
// Draw the sky background.
|
||||
HWR_DrawSkyBackground();
|
||||
if (skybox)
|
||||
@@ -5730,6 +5726,7 @@ void HWR_LoadLevel(boolean reloadinggamestate)
|
||||
static void HWR_TogglePaletteRendering(void)
|
||||
{
|
||||
V_ResetPaletteCVars(); // dont carry over changed palettes
|
||||
ST_ResetPaletteStuff();
|
||||
|
||||
// which state should we go to?
|
||||
if (HWR_ShouldUsePaletteRendering())
|
||||
@@ -5750,7 +5747,7 @@ static void HWR_TogglePaletteRendering(void)
|
||||
// If the r_opengl "texture palette" stays the same during this switch, these textures
|
||||
// will not be cleared out. However they are still out of date since the
|
||||
// composite texture blending method has changed. Therefore they need to be cleared.
|
||||
GL_ClearMipMapCache();
|
||||
HWR_LoadMapTextures(numtextures);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -5764,7 +5761,7 @@ static void HWR_TogglePaletteRendering(void)
|
||||
// If the r_opengl "texture palette" stays the same during this switch, these textures
|
||||
// will not be cleared out. However they are still out of date since the
|
||||
// composite texture blending method has changed. Therefore they need to be cleared.
|
||||
GL_ClearMipMapCache();
|
||||
HWR_LoadMapTextures(numtextures);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5801,6 +5798,8 @@ void HWR_AddCommands(void)
|
||||
|
||||
CV_RegisterVar(&cv_glbatching);
|
||||
|
||||
CV_RegisterVar(&cv_glwireframe);
|
||||
|
||||
CV_RegisterVar(&cv_glrenderdistance);
|
||||
|
||||
CV_RegisterVar(&cv_glhorizonlines);
|
||||
@@ -5873,7 +5872,6 @@ static void COM_HWR_glinfo(void)
|
||||
CONS_Printf("Unrecognized argument: %s\n", argv);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CONS_Printf("\x88OpenGL %s\x80\n", gl_version);
|
||||
@@ -5993,19 +5991,19 @@ static void HWR_DoPostProcessor(player_t *player)
|
||||
if (cv_glscreentextures.value != 2) // screen textures are needed for the rest of the effects
|
||||
return;
|
||||
|
||||
// Capture the screen for intermission and screen waving
|
||||
if (gamestate != GS_INTERMISSION)
|
||||
GL_MakeScreenTexture(HWD_SCREENTEXTURE_GENERIC1);
|
||||
|
||||
if (splitscreen) // Not supported in splitscreen - someone want to add support?
|
||||
return;
|
||||
|
||||
//UINT8 viewnum = R_GetViewNumber(); // see above
|
||||
//UINT8 viewnum = R_GetViewNumber(); // see below
|
||||
//camera_t *thiscam = &camera[viewnum];
|
||||
camera_t *thiscam = &camera[0];
|
||||
|
||||
// Not supported in splitscreen - someone want to add support?
|
||||
const boolean screenwave = (!splitscreen && (thiscam->postimg & POSTIMG_WATER || thiscam->postimg & POSTIMG_HEAT));
|
||||
|
||||
// Capture the screen for intermission and screen waving
|
||||
if ((lastdraw || screenwave) && gamestate != GS_INTERMISSION)
|
||||
GL_MakeScreenTexture(HWD_SCREENTEXTURE_GENERIC1);
|
||||
|
||||
// Drunken vision! WooOOooo~
|
||||
if (thiscam->postimg & POSTIMG_WATER || thiscam->postimg & POSTIMG_HEAT)
|
||||
if (screenwave)
|
||||
{
|
||||
// 10 by 10 grid. 2 coordinates (xy)
|
||||
float v[SCREENVERTS][SCREENVERTS][2];
|
||||
@@ -6039,6 +6037,7 @@ static void HWR_DoPostProcessor(player_t *player)
|
||||
v[x][y][1] = (y/((float)(SCREENVERTS-1.0f)/9.0f))-4.5f;
|
||||
}
|
||||
}
|
||||
|
||||
GL_PostImgRedraw(v);
|
||||
|
||||
// Capture the screen again for screen waving on the intermission
|
||||
|
||||
+11
-1
@@ -34,6 +34,10 @@
|
||||
|
||||
#define GLENCORE
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Startup & Shutdown the hardware mode renderer
|
||||
void HWR_Startup(void);
|
||||
void HWR_Shutdown(void);
|
||||
@@ -202,6 +206,8 @@ extern consvar_t cv_glsolvetjoin;
|
||||
|
||||
extern consvar_t cv_glbatching;
|
||||
|
||||
extern consvar_t cv_glwireframe;
|
||||
|
||||
extern consvar_t cv_glrenderdistance;
|
||||
|
||||
extern consvar_t cv_glhorizonlines;
|
||||
@@ -223,7 +229,11 @@ FUNCINLINE static ATTRINLINE boolean HWR_ShouldUsePaletteRendering(void)
|
||||
|
||||
FUNCINLINE static ATTRINLINE boolean HWR_PalRenderFlashpal(void)
|
||||
{
|
||||
return (HWR_ShouldUsePaletteRendering() && cv_glflashpal.value);
|
||||
return (cv_glflashpal.value && HWR_ShouldUsePaletteRendering());
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}// extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -15,6 +15,10 @@
|
||||
#ifndef _HW_MD2_H_
|
||||
#define _HW_MD2_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "hw_glob.h"
|
||||
#include "hw_model.h"
|
||||
|
||||
@@ -46,4 +50,8 @@ void HWR_DrawMD2(gl_vissprite_t *spr);
|
||||
void HWR_AddPlayerMD2(INT32 skin, boolean local);
|
||||
void HWR_AddSpriteMD2(size_t spritenum);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // _HW_MD2_H_
|
||||
@@ -66,6 +66,7 @@ void HWR_FreePortalList(gl_portallist_t freelist)
|
||||
|
||||
// free memory from portal list allocated by calls to Add2Lines
|
||||
gl_portal_t *gl_portal_temp = freelist.base;
|
||||
|
||||
while (gl_portal_temp)
|
||||
{
|
||||
gl_portal_t *nextportal = gl_portal_temp->next;
|
||||
@@ -125,8 +126,7 @@ void HWR_PortalFrame(gl_portal_t* portal)
|
||||
if (portal->clipline != -1)
|
||||
{
|
||||
portalclipline = &lines[portal->clipline];
|
||||
portalcullsector = portalclipline->frontsector;
|
||||
viewsector = portalclipline->frontsector;
|
||||
portalcullsector = viewsector = portalclipline->frontsector;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+183
-138
@@ -350,6 +350,8 @@ typedef void (APIENTRY * PFNglDisable) (GLenum cap);
|
||||
static PFNglDisable pglDisable;
|
||||
typedef void (APIENTRY * PFNglGetFloatv) (GLenum pname, GLfloat *params);
|
||||
static PFNglGetFloatv pglGetFloatv;
|
||||
typedef void (APIENTRY * PFNglPolygonMode) (GLenum, GLenum);
|
||||
static PFNglPolygonMode pglPolygonMode;
|
||||
|
||||
/* Depth Buffer */
|
||||
typedef void (APIENTRY * PFNglClearDepth) (GLclampd depth);
|
||||
@@ -549,6 +551,7 @@ boolean SetupGLfunc(void)
|
||||
GETOPENGLFUNC(pglGetFloatv, glGetFloatv)
|
||||
GETOPENGLFUNC(pglGetIntegerv, glGetIntegerv)
|
||||
GETOPENGLFUNC(pglGetString, glGetString)
|
||||
GETOPENGLFUNC(pglPolygonMode, glPolygonMode)
|
||||
|
||||
GETOPENGLFUNC(pglClearDepth, glClearDepth)
|
||||
GETOPENGLFUNC(pglDepthFunc, glDepthFunc)
|
||||
@@ -734,69 +737,78 @@ static boolean GLFramebuffer_CheckExt(void)
|
||||
return false;
|
||||
|
||||
// check if all needed gl extensions are available
|
||||
return (GL_isExtAvailable("GL_ARB_framebuffer_no_attachments", gl_extensions) && GL_isExtAvailable("GL_ARB_framebuffer_object", gl_extensions) && GL_isExtAvailable("GL_ARB_framebuffer_sRGB", gl_extensions));
|
||||
return (GL_isExtAvailable("GL_ARB_framebuffer_no_attachments", gl_extensions)
|
||||
&& GL_isExtAvailable("GL_ARB_framebuffer_object", gl_extensions)
|
||||
&& GL_isExtAvailable("GL_ARB_framebuffer_sRGB", gl_extensions));
|
||||
}
|
||||
#endif
|
||||
|
||||
void SetupGLFunc4(void)
|
||||
{
|
||||
#define GetGLfunc(func) \
|
||||
p##func = GetGLFunc(#func); \
|
||||
if (!p##func) \
|
||||
{ \
|
||||
GL_MSG_Warning("failed to get OpenGL function: %s", #func); \
|
||||
} \
|
||||
|
||||
/* 1.2 funcs */
|
||||
pglTexImage3D = GetGLFunc("glTexImage3D");
|
||||
GetGLfunc(glTexImage3D);
|
||||
/* 1.3 funcs */
|
||||
pglActiveTexture = GetGLFunc("glActiveTexture");
|
||||
pglMultiTexCoord2f = GetGLFunc("glMultiTexCoord2f");
|
||||
pglClientActiveTexture = GetGLFunc("glClientActiveTexture");
|
||||
pglMultiTexCoord2fv = GetGLFunc("glMultiTexCoord2fv");
|
||||
GetGLfunc(glActiveTexture);
|
||||
GetGLfunc(glMultiTexCoord2f);
|
||||
GetGLfunc(glClientActiveTexture);
|
||||
GetGLfunc(glMultiTexCoord2fv);
|
||||
|
||||
/* 1.5 funcs */
|
||||
pglGenBuffers = GetGLFunc("glGenBuffers");
|
||||
pglBindBuffer = GetGLFunc("glBindBuffer");
|
||||
pglBufferData = GetGLFunc("glBufferData");
|
||||
pglDeleteBuffers = GetGLFunc("glDeleteBuffers");
|
||||
pglColorPointer = GetGLFunc("glColorPointer");
|
||||
GetGLfunc(glGenBuffers);
|
||||
GetGLfunc(glBindBuffer);
|
||||
GetGLfunc(glBufferData);
|
||||
GetGLfunc(glDeleteBuffers);
|
||||
GetGLfunc(glColorPointer);
|
||||
|
||||
/* 2.0 funcs */
|
||||
pglBlendEquation = GetGLFunc("glBlendEquation");
|
||||
GetGLfunc(glBlendEquation);
|
||||
|
||||
pglStencilFuncSeparate = GetGLFunc("glStencilFuncSeparate");
|
||||
pglStencilOpSeparate = GetGLFunc("glStencilOpSeparate");
|
||||
GetGLfunc(glStencilFuncSeparate);
|
||||
GetGLfunc(glStencilOpSeparate);
|
||||
|
||||
pglCreateShader = GetGLFunc("glCreateShader");
|
||||
pglShaderSource = GetGLFunc("glShaderSource");
|
||||
pglCompileShader = GetGLFunc("glCompileShader");
|
||||
pglGetShaderiv = GetGLFunc("glGetShaderiv");
|
||||
pglGetShaderInfoLog = GetGLFunc("glGetShaderInfoLog");
|
||||
pglDeleteShader = GetGLFunc("glDeleteShader");
|
||||
pglCreateProgram = GetGLFunc("glCreateProgram");
|
||||
pglDeleteProgram = GetGLFunc("glDeleteProgram");
|
||||
pglAttachShader = GetGLFunc("glAttachShader");
|
||||
pglLinkProgram = GetGLFunc("glLinkProgram");
|
||||
pglGetProgramiv = GetGLFunc("glGetProgramiv");
|
||||
pglGetProgramInfoLog = GetGLFunc("glGetProgramInfoLog");
|
||||
pglUseProgram = GetGLFunc("glUseProgram");
|
||||
pglUniform1i = GetGLFunc("glUniform1i");
|
||||
pglUniform1f = GetGLFunc("glUniform1f");
|
||||
pglUniform2f = GetGLFunc("glUniform2f");
|
||||
pglUniform3f = GetGLFunc("glUniform3f");
|
||||
pglUniform4f = GetGLFunc("glUniform4f");
|
||||
pglUniform1fv = GetGLFunc("glUniform1fv");
|
||||
pglUniform2fv = GetGLFunc("glUniform2fv");
|
||||
pglUniform3fv = GetGLFunc("glUniform3fv");
|
||||
pglGetUniformLocation = GetGLFunc("glGetUniformLocation");
|
||||
GetGLfunc(glCreateShader);
|
||||
GetGLfunc(glShaderSource);
|
||||
GetGLfunc(glCompileShader);
|
||||
GetGLfunc(glGetShaderiv);
|
||||
GetGLfunc(glGetShaderInfoLog);
|
||||
GetGLfunc(glDeleteShader);
|
||||
GetGLfunc(glCreateProgram);
|
||||
GetGLfunc(glDeleteProgram);
|
||||
GetGLfunc(glAttachShader);
|
||||
GetGLfunc(glLinkProgram);
|
||||
GetGLfunc(glGetProgramiv);
|
||||
GetGLfunc(glGetProgramInfoLog);
|
||||
GetGLfunc(glUseProgram);
|
||||
GetGLfunc(glUniform1i);
|
||||
GetGLfunc(glUniform1f);
|
||||
GetGLfunc(glUniform2f);
|
||||
GetGLfunc(glUniform3f);
|
||||
GetGLfunc(glUniform4f);
|
||||
GetGLfunc(glUniform1fv);
|
||||
GetGLfunc(glUniform2fv);
|
||||
GetGLfunc(glUniform3fv);
|
||||
GetGLfunc(glGetUniformLocation);
|
||||
|
||||
#ifdef USE_FBO_OGL
|
||||
if (GLFramebuffer_CheckExt())
|
||||
{
|
||||
pglGenFramebuffers = GetGLFunc("glGenFramebuffers");
|
||||
pglBindFramebuffer = GetGLFunc("glBindFramebuffer");
|
||||
pglDeleteFramebuffers = GetGLFunc("glDeleteFramebuffers");
|
||||
pglFramebufferTexture2D = GetGLFunc("glFramebufferTexture2D");
|
||||
pglCheckFramebufferStatus = GetGLFunc("glCheckFramebufferStatus");
|
||||
pglGenRenderbuffers = GetGLFunc("glGenRenderbuffers");
|
||||
pglBindRenderbuffer = GetGLFunc("glBindRenderbuffer");
|
||||
pglDeleteRenderbuffers = GetGLFunc("glDeleteRenderbuffers");
|
||||
pglRenderbufferStorage = GetGLFunc("glRenderbufferStorage");
|
||||
pglFramebufferRenderbuffer = GetGLFunc("glFramebufferRenderbuffer");
|
||||
GetGLfunc(glGenFramebuffers);
|
||||
GetGLfunc(glBindFramebuffer);
|
||||
GetGLfunc(glDeleteFramebuffers);
|
||||
GetGLfunc(glFramebufferTexture2D);
|
||||
GetGLfunc(glCheckFramebufferStatus);
|
||||
GetGLfunc(glGenRenderbuffers);
|
||||
GetGLfunc(glBindRenderbuffer);
|
||||
GetGLfunc(glDeleteRenderbuffers);
|
||||
GetGLfunc(glRenderbufferStorage);
|
||||
GetGLfunc(glFramebufferRenderbuffer);
|
||||
|
||||
// check if ALL functions are availible
|
||||
if (pglGenFramebuffers && pglBindFramebuffer &&
|
||||
@@ -807,6 +819,7 @@ void SetupGLFunc4(void)
|
||||
supportFBO = true;
|
||||
}
|
||||
#endif
|
||||
#undef GetGLfunc
|
||||
}
|
||||
|
||||
boolean GL_InitShaders(void)
|
||||
@@ -956,6 +969,7 @@ static void GL_SetNoTexture(void)
|
||||
{
|
||||
if (NOTEXTURE_NUM == 0)
|
||||
pglGenTextures(1, &NOTEXTURE_NUM);
|
||||
|
||||
pglBindTexture(GL_TEXTURE_2D, NOTEXTURE_NUM);
|
||||
tex_downloaded = NOTEXTURE_NUM;
|
||||
}
|
||||
@@ -1105,10 +1119,12 @@ void GL_DeleteTexture(GLMipmap_t *pTexInfo)
|
||||
head->next->prev = head->prev;
|
||||
else // no next -> tail is being deleted -> update TexCacheTail
|
||||
TexCacheTail = head->prev;
|
||||
|
||||
if (head->prev)
|
||||
head->prev->next = head->next;
|
||||
else // no prev -> head is being deleted -> update TexCacheHead
|
||||
TexCacheHead = head->next;
|
||||
|
||||
free(head);
|
||||
break;
|
||||
}
|
||||
@@ -1129,7 +1145,7 @@ static void GL_Framebuffer_GenerateAttachments(void)
|
||||
pglBindFramebuffer(GL_FRAMEBUFFER, FramebufferObject);
|
||||
|
||||
// Generate the framebuffer texture
|
||||
if (FramebufferTexture == 0)
|
||||
if (!FramebufferTexture)
|
||||
{
|
||||
pglGenTextures(1, &FramebufferTexture);
|
||||
pglBindTexture(GL_TEXTURE_2D, FramebufferTexture);
|
||||
@@ -1143,7 +1159,7 @@ static void GL_Framebuffer_GenerateAttachments(void)
|
||||
}
|
||||
|
||||
// Generate the renderbuffer
|
||||
if (RenderbufferObject == 0)
|
||||
if (!RenderbufferObject)
|
||||
{
|
||||
pglGenRenderbuffers(1, &RenderbufferObject);
|
||||
|
||||
@@ -1165,10 +1181,10 @@ static void GL_Framebuffer_GenerateAttachments(void)
|
||||
|
||||
static void GL_Framebuffer_DeleteAttachments(void)
|
||||
{
|
||||
if (!supportFBO || fboinit == false)
|
||||
if (!supportFBO || !fboinit)
|
||||
return;
|
||||
|
||||
if (FramebufferObject == 0 && RenderbufferObject == 0 && FramebufferTexture == 0)
|
||||
if (!FramebufferObject && !RenderbufferObject && !FramebufferTexture)
|
||||
return;
|
||||
|
||||
// Unbind the framebuffer
|
||||
@@ -1192,7 +1208,7 @@ static void GL_Framebuffer_Generate(void)
|
||||
return;
|
||||
|
||||
// Generate the framebuffer
|
||||
if (FramebufferObject == 0)
|
||||
if (!FramebufferObject)
|
||||
pglGenFramebuffers(1, &FramebufferObject);
|
||||
|
||||
if (pglCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)
|
||||
@@ -1201,7 +1217,7 @@ static void GL_Framebuffer_Generate(void)
|
||||
|
||||
static void GL_Framebuffer_Delete(void)
|
||||
{
|
||||
if (!supportFBO || fboinit == false)
|
||||
if (!supportFBO || !fboinit)
|
||||
return;
|
||||
|
||||
if (FramebufferObject)
|
||||
@@ -1213,10 +1229,10 @@ static void GL_Framebuffer_Delete(void)
|
||||
|
||||
void GL_Framebuffer_Unbind(void)
|
||||
{
|
||||
if (!supportFBO || fboinit == false)
|
||||
if (!supportFBO || !fboinit)
|
||||
return;
|
||||
|
||||
if (FramebufferObject == 0 && RenderbufferObject == 0)
|
||||
if (!FramebufferObject && !RenderbufferObject)
|
||||
return;
|
||||
|
||||
pglBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
@@ -1230,7 +1246,7 @@ void GL_Framebuffer_Enable(void)
|
||||
|
||||
if (FramebufferObject == 0)
|
||||
GL_Framebuffer_Generate();
|
||||
else if (FramebufferTexture == 0 || RenderbufferObject == 0)
|
||||
else if (!FramebufferTexture || !RenderbufferObject)
|
||||
GL_Framebuffer_GenerateAttachments();
|
||||
|
||||
pglBindFramebuffer(GL_FRAMEBUFFER, FramebufferObject);
|
||||
@@ -1239,10 +1255,10 @@ void GL_Framebuffer_Enable(void)
|
||||
|
||||
void GL_Framebuffer_Disable(void)
|
||||
{
|
||||
if (!supportFBO || fboinit == false)
|
||||
if (!supportFBO || !fboinit)
|
||||
return;
|
||||
|
||||
if (FramebufferObject == 0 && RenderbufferObject == 0)
|
||||
if (!FramebufferObject && !RenderbufferObject)
|
||||
return;
|
||||
|
||||
pglBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
@@ -1292,20 +1308,29 @@ INT32 GL_isExtAvailable(const char *extension, const GLubyte *start)
|
||||
{
|
||||
GLubyte *where, *terminator;
|
||||
|
||||
if (!extension || !start) return 0;
|
||||
if (!extension || !start)
|
||||
return 0;
|
||||
|
||||
where = (GLubyte *) strchr(extension, ' ');
|
||||
|
||||
if (where || *extension == '\0')
|
||||
return 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
where = (GLubyte *) strstr((const char *) start, extension);
|
||||
|
||||
if (!where)
|
||||
break;
|
||||
|
||||
terminator = where + strlen(extension);
|
||||
|
||||
if (where == start || *(where - 1) == ' ')
|
||||
{
|
||||
if (*terminator == ' ' || *terminator == '\0')
|
||||
return 1;
|
||||
}
|
||||
|
||||
start = terminator;
|
||||
}
|
||||
return 0;
|
||||
@@ -1337,23 +1362,33 @@ void GL_ReadScreenTexture(int tex, UINT16 *dst_data)
|
||||
{
|
||||
INT32 i;
|
||||
int dst_stride = screen_width * 3; // stride between rows of image data
|
||||
GLubyte*top = (GLvoid*)dst_data, *bottom = top + dst_stride * (screen_height - 1);
|
||||
GLubyte *top, *bottom;
|
||||
GLubyte *row;
|
||||
|
||||
row = malloc(dst_stride);
|
||||
if (!row) return;
|
||||
|
||||
if (!row)
|
||||
return;
|
||||
|
||||
top = (GLvoid*)dst_data;
|
||||
bottom = top + dst_stride * (screen_height - 1);
|
||||
|
||||
// at the time this function is called, generic2 can be found drawn on the framebuffer
|
||||
// if some other screen texture is needed, draw it to the framebuffer
|
||||
// and draw generic2 back after reading the framebuffer.
|
||||
// this hack is for some reason **much** faster than the simple solution of using glGetTexImage.
|
||||
if (tex != HWD_SCREENTEXTURE_GENERIC2)
|
||||
GL_DrawScreenTexture(tex, NULL, 0);
|
||||
|
||||
pglPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
pglReadPixels(0, 0, screen_width, screen_height, GL_RGB, GL_UNSIGNED_BYTE, dst_data);
|
||||
|
||||
if (tex != HWD_SCREENTEXTURE_GENERIC2)
|
||||
GL_DrawScreenTexture(HWD_SCREENTEXTURE_GENERIC2, NULL, 0);
|
||||
|
||||
// Flip image upside down.
|
||||
// In other words, convert OpenGL's "bottom->top" row order into "top->bottom".
|
||||
for(i = 0; i < screen_height/2; i++)
|
||||
for (i = 0; i < screen_height/2; i++)
|
||||
{
|
||||
memcpy(row, top, dst_stride);
|
||||
memcpy(top, bottom, dst_stride);
|
||||
@@ -1361,6 +1396,7 @@ void GL_ReadScreenTexture(int tex, UINT16 *dst_data)
|
||||
top += dst_stride;
|
||||
bottom -= dst_stride;
|
||||
}
|
||||
|
||||
free(row);
|
||||
}
|
||||
|
||||
@@ -1413,10 +1449,8 @@ void GL_ClearBuffer(FBOOLEAN ColorMask, FBOOLEAN DepthMask, FBOOLEAN StencilMask
|
||||
if (ColorMask)
|
||||
{
|
||||
if (ClearColor)
|
||||
pglClearColor(ClearColor->red,
|
||||
ClearColor->green,
|
||||
ClearColor->blue,
|
||||
ClearColor->alpha);
|
||||
pglClearColor(ClearColor->red, ClearColor->green, ClearColor->blue, ClearColor->alpha);
|
||||
|
||||
ClearMask |= GL_COLOR_BUFFER_BIT;
|
||||
}
|
||||
if (DepthMask)
|
||||
@@ -1431,6 +1465,7 @@ void GL_ClearBuffer(FBOOLEAN ColorMask, FBOOLEAN DepthMask, FBOOLEAN StencilMask
|
||||
|
||||
if (StencilMask)
|
||||
ClearMask |= GL_STENCIL_BUFFER_BIT;// looks like sometimes stencil buffer needs clearing? had a problem with random black screens
|
||||
|
||||
pglClear(ClearMask);
|
||||
pglEnableClientState(GL_VERTEX_ARRAY); // We always use this one
|
||||
pglEnableClientState(GL_TEXTURE_COORD_ARRAY); // And mostly this one, too
|
||||
@@ -2055,7 +2090,7 @@ static boolean GL_Shader_CompileProgram(gl_shader_t *shader, GLint i)
|
||||
pglGetShaderiv(gl_fragShader, GL_COMPILE_STATUS, &result);
|
||||
if (result == GL_FALSE)
|
||||
{
|
||||
pglGetShaderInfoLog(gl_fragShader, 512, NULL, info_log);
|
||||
pglGetShaderInfoLog(gl_fragShader, 512, NULL, info_log);
|
||||
|
||||
GL_MSG_Error("Error compiling fragment shader: %s\n", info_log);
|
||||
pglDeleteShader(gl_vertShader);
|
||||
@@ -2093,25 +2128,25 @@ static boolean GL_Shader_CompileProgram(gl_shader_t *shader, GLint i)
|
||||
#define GETUNI(uniform) pglGetUniformLocation(shader->program, uniform);
|
||||
|
||||
// lighting
|
||||
shader->uniforms[gluniform_poly_color] = GETUNI("poly_color");
|
||||
shader->uniforms[gluniform_tint_color] = GETUNI("tint_color");
|
||||
shader->uniforms[gluniform_fade_color] = GETUNI("fade_color");
|
||||
shader->uniforms[gluniform_lighting] = GETUNI("lighting");
|
||||
shader->uniforms[gluniform_fade_start] = GETUNI("fade_start");
|
||||
shader->uniforms[gluniform_fade_end] = GETUNI("fade_end");
|
||||
shader->uniforms[gluniform_light_dir] = GETUNI("light_dir");
|
||||
shader->uniforms[gluniform_light_contrast] = GETUNI("light_contrast");
|
||||
shader->uniforms[gluniform_light_backlight] = GETUNI("light_backlight");
|
||||
shader->uniforms[gluniform_poly_color] = GETUNI("poly_color");
|
||||
shader->uniforms[gluniform_tint_color] = GETUNI("tint_color");
|
||||
shader->uniforms[gluniform_fade_color] = GETUNI("fade_color");
|
||||
shader->uniforms[gluniform_lighting] = GETUNI("lighting");
|
||||
shader->uniforms[gluniform_fade_start] = GETUNI("fade_start");
|
||||
shader->uniforms[gluniform_fade_end] = GETUNI("fade_end");
|
||||
shader->uniforms[gluniform_light_dir] = GETUNI("light_dir");
|
||||
shader->uniforms[gluniform_light_contrast] = GETUNI("light_contrast");
|
||||
shader->uniforms[gluniform_light_backlight] = GETUNI("light_backlight");
|
||||
|
||||
// palette rendering
|
||||
shader->uniforms[gluniform_palette_tex] = GETUNI("palette_tex");
|
||||
shader->uniforms[gluniform_palette_lookup_tex] = GETUNI("palette_lookup_tex");
|
||||
shader->uniforms[gluniform_lighttable_tex] = GETUNI("lighttable_tex");
|
||||
shader->uniforms[gluniform_palette_tex] = GETUNI("palette_tex");
|
||||
shader->uniforms[gluniform_palette_lookup_tex] = GETUNI("palette_lookup_tex");
|
||||
shader->uniforms[gluniform_lighttable_tex] = GETUNI("lighttable_tex");
|
||||
|
||||
shader->uniforms[gluniform_scr_resolution] = GETUNI("scr_resolution");
|
||||
shader->uniforms[gluniform_scr_resolution] = GETUNI("scr_resolution");
|
||||
|
||||
// misc.
|
||||
shader->uniforms[gluniform_leveltime] = GETUNI("leveltime");
|
||||
shader->uniforms[gluniform_leveltime] = GETUNI("leveltime");
|
||||
#undef GETUNI
|
||||
|
||||
// set permanent uniform values
|
||||
@@ -2319,49 +2354,54 @@ void GL_SetSpecialState(hwdspecialstate_t IdState, INT32 Value)
|
||||
gl_allowshaders = Value;
|
||||
break;
|
||||
case HWD_SET_TEXTUREFILTERMODE:
|
||||
|
||||
switch (Value)
|
||||
{
|
||||
case HWD_SET_TEXTUREFILTER_TRILINEAR:
|
||||
min_filter = GL_LINEAR_MIPMAP_LINEAR;
|
||||
mag_filter = GL_LINEAR;
|
||||
MipMap = GL_TRUE;
|
||||
break;
|
||||
case HWD_SET_TEXTUREFILTER_BILINEAR:
|
||||
min_filter = mag_filter = GL_LINEAR;
|
||||
switch (Value)
|
||||
{
|
||||
case HWD_SET_TEXTUREFILTER_TRILINEAR:
|
||||
min_filter = GL_LINEAR_MIPMAP_LINEAR;
|
||||
mag_filter = GL_LINEAR;
|
||||
MipMap = GL_TRUE;
|
||||
break;
|
||||
case HWD_SET_TEXTUREFILTER_BILINEAR:
|
||||
min_filter = mag_filter = GL_LINEAR;
|
||||
MipMap = GL_FALSE;
|
||||
break;
|
||||
case HWD_SET_TEXTUREFILTER_POINTSAMPLED:
|
||||
min_filter = mag_filter = GL_NEAREST;
|
||||
MipMap = GL_FALSE;
|
||||
break;
|
||||
case HWD_SET_TEXTUREFILTER_MIXED1:
|
||||
min_filter = GL_NEAREST;
|
||||
mag_filter = GL_LINEAR;
|
||||
MipMap = GL_FALSE;
|
||||
break;
|
||||
case HWD_SET_TEXTUREFILTER_MIXED2:
|
||||
min_filter = GL_LINEAR;
|
||||
mag_filter = GL_NEAREST;
|
||||
MipMap = GL_FALSE;
|
||||
break;
|
||||
case HWD_SET_TEXTUREFILTER_MIXED3:
|
||||
min_filter = GL_LINEAR_MIPMAP_LINEAR;
|
||||
mag_filter = GL_NEAREST;
|
||||
MipMap = GL_TRUE;
|
||||
break;
|
||||
default:
|
||||
min_filter = GL_NEAREST;
|
||||
mag_filter = GL_LINEAR;
|
||||
}
|
||||
|
||||
if (!supportMipMap)
|
||||
{
|
||||
MipMap = GL_FALSE;
|
||||
break;
|
||||
case HWD_SET_TEXTUREFILTER_POINTSAMPLED:
|
||||
min_filter = mag_filter = GL_NEAREST;
|
||||
MipMap = GL_FALSE;
|
||||
break;
|
||||
case HWD_SET_TEXTUREFILTER_MIXED1:
|
||||
min_filter = GL_NEAREST;
|
||||
mag_filter = GL_LINEAR;
|
||||
MipMap = GL_FALSE;
|
||||
break;
|
||||
case HWD_SET_TEXTUREFILTER_MIXED2:
|
||||
min_filter = GL_LINEAR;
|
||||
mag_filter = GL_NEAREST;
|
||||
MipMap = GL_FALSE;
|
||||
break;
|
||||
case HWD_SET_TEXTUREFILTER_MIXED3:
|
||||
min_filter = GL_LINEAR_MIPMAP_LINEAR;
|
||||
mag_filter = GL_NEAREST;
|
||||
MipMap = GL_TRUE;
|
||||
break;
|
||||
default:
|
||||
min_filter = GL_NEAREST;
|
||||
mag_filter = GL_LINEAR;
|
||||
}
|
||||
}
|
||||
|
||||
if (!supportMipMap)
|
||||
{
|
||||
MipMap = GL_FALSE;
|
||||
min_filter = GL_LINEAR;
|
||||
GL_Flush(); //??? if we want to change filter mode by texture, remove this
|
||||
}
|
||||
break;
|
||||
|
||||
GL_Flush(); //??? if we want to change filter mode by texture, remove this
|
||||
case HWD_SET_WIREFRAME:
|
||||
pglPolygonMode(GL_FRONT_AND_BACK, Value ? GL_LINE : GL_FILL);
|
||||
break;
|
||||
|
||||
case HWD_SET_TEXTURE_FORMAT:
|
||||
@@ -2699,7 +2739,7 @@ void GL_DrawModelEx(model_t *model, INT32 frameIndex, float duration, float tics
|
||||
|
||||
pglColor4ubv((GLubyte*)&Surface->PolyColor.s);
|
||||
|
||||
GL_SetBlend((poly.alpha < 1 ? Surface->PolyFlags : (PF_Masked|PF_Occlude))|PF_Modulated);
|
||||
GL_SetBlend(((poly.alpha < 1) ? Surface->PolyFlags : (PF_Masked|PF_Occlude))|PF_Modulated);
|
||||
|
||||
tint.red = byte2float[Surface->TintColor.s.red];
|
||||
tint.green = byte2float[Surface->TintColor.s.green];
|
||||
@@ -2743,9 +2783,9 @@ void GL_DrawModelEx(model_t *model, INT32 frameIndex, float duration, float tics
|
||||
if (hflipped)
|
||||
scalez = -scalez;
|
||||
|
||||
pglRotatef(pos->anglez, 0.0f, 0.0f, -1.0f);
|
||||
pglRotatef(pos->anglex, 1.0f, 0.0f, 0.0f);
|
||||
pglRotatef(pos->angley, 0.0f, -1.0f, 0.0f);
|
||||
pglRotatef(pos->anglez, 0.0f, 0.0f, -1.0f);
|
||||
pglRotatef(pos->anglex, 1.0f, 0.0f, 0.0f);
|
||||
pglRotatef(pos->angley, 0.0f, -1.0f, 0.0f);
|
||||
|
||||
if (pos->roll)
|
||||
{
|
||||
@@ -2916,8 +2956,10 @@ void GL_SetTransform(FTransform *stransform)
|
||||
if (shearing)
|
||||
{
|
||||
float dy = stransform->viewaiming * 2;
|
||||
|
||||
if (stransform->fliptype == TRANSFORM_FLIP || stransform->fliptype == TRANSFORM_MIRRORFLIP)
|
||||
dy *= -1.0f;
|
||||
|
||||
pglTranslatef(0.0f, -dy/BASEVIDHEIGHT, 0.0f);
|
||||
}
|
||||
|
||||
@@ -2969,9 +3011,9 @@ void GL_PostImgRedraw(float points[SCREENVERTS][SCREENVERTS][2])
|
||||
const float blackBack[16] =
|
||||
{
|
||||
-16.0f, -16.0f, 6.0f,
|
||||
-16.0f, 16.0f, 6.0f,
|
||||
16.0f, 16.0f, 6.0f,
|
||||
16.0f, -16.0f, 6.0f
|
||||
-16.0f, 16.0f, 6.0f,
|
||||
16.0f, 16.0f, 6.0f,
|
||||
16.0f, -16.0f, 6.0f
|
||||
};
|
||||
|
||||
if (gl_enable_screen_textures != 2)
|
||||
@@ -2993,9 +3035,9 @@ void GL_PostImgRedraw(float points[SCREENVERTS][SCREENVERTS][2])
|
||||
pglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
pglEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
for(x = 0; x < SCREENVERTS-1;x ++)
|
||||
for (x = 0; x < (SCREENVERTS-1); x ++)
|
||||
{
|
||||
for(y = 0; y < SCREENVERTS-1; y++)
|
||||
for (y = 0; y < (SCREENVERTS-1); y++)
|
||||
{
|
||||
float stCoords[8];
|
||||
float vertCoords[12];
|
||||
@@ -3047,23 +3089,22 @@ void GL_PostImgRedraw(float points[SCREENVERTS][SCREENVERTS][2])
|
||||
void GL_FlushScreenTextures(void)
|
||||
{
|
||||
pglDeleteTextures(NUMSCREENTEXTURES, screenTextures);
|
||||
memset(screenTextures, 0 , sizeof(screenTextures));
|
||||
memset(screenTextures, 0, sizeof(screenTextures));
|
||||
}
|
||||
|
||||
void GL_DrawScreenTexture(int tex, FSurfaceInfo *surf, FBITFIELD polyflags)
|
||||
{
|
||||
float fix[8];
|
||||
float xfix, yfix;
|
||||
|
||||
const float screenVerts[12] =
|
||||
{
|
||||
-1.0f, -1.0f, 1.0f,
|
||||
-1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f,
|
||||
1.0f, -1.0f, 1.0f
|
||||
-1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f,
|
||||
1.0f, -1.0f, 1.0f
|
||||
};
|
||||
|
||||
float fix[8];
|
||||
|
||||
if (gl_enable_screen_textures != 2)
|
||||
return;
|
||||
|
||||
@@ -3108,9 +3149,9 @@ void GL_DoScreenWipe(int wipeStart, int wipeEnd)
|
||||
const float screenVerts[12] =
|
||||
{
|
||||
-1.0f, -1.0f, 1.0f,
|
||||
-1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f,
|
||||
1.0f, -1.0f, 1.0f
|
||||
-1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f,
|
||||
1.0f, -1.0f, 1.0f
|
||||
};
|
||||
|
||||
float fix[8];
|
||||
@@ -3194,9 +3235,9 @@ void GL_RenderVhsEffect(fixed_t upbary, fixed_t downbary, UINT8 updistort, UINT8
|
||||
float screenVerts[12] =
|
||||
{
|
||||
-1.0f, -1.0f, 1.0f,
|
||||
-1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f,
|
||||
1.0f, -1.0f, 1.0f
|
||||
-1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f,
|
||||
1.0f, -1.0f, 1.0f
|
||||
};
|
||||
|
||||
if (gl_enable_screen_textures != 2)
|
||||
@@ -3295,6 +3336,7 @@ void GL_MakeScreenTexture(int tex)
|
||||
// Create screen texture
|
||||
if (firstTime)
|
||||
pglGenTextures(1, &screenTextures[tex]);
|
||||
|
||||
pglBindTexture(GL_TEXTURE_2D, screenTextures[tex]);
|
||||
|
||||
if (firstTime)
|
||||
@@ -3329,6 +3371,7 @@ void GL_DrawScreenFinalTexture(int tex, INT32 width, INT32 height, boolean usesh
|
||||
|
||||
origaspect = (float)screen_width / screen_height;
|
||||
newaspect = (float)width / height;
|
||||
|
||||
if (origaspect < newaspect)
|
||||
{
|
||||
xoff = origaspect / newaspect;
|
||||
@@ -3464,8 +3507,10 @@ void GL_SetScreenPalette(RGBA_t *palette)
|
||||
if (memcmp(screenPalette, palette, sizeof(screenPalette)))
|
||||
{
|
||||
memcpy(screenPalette, palette, sizeof(screenPalette));
|
||||
|
||||
if (!screenPaletteTex)
|
||||
pglGenTextures(1, &screenPaletteTex);
|
||||
|
||||
pglActiveTexture(GL_TEXTURE2);
|
||||
pglBindTexture(GL_TEXTURE_1D, screenPaletteTex);
|
||||
pglTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
+4
-4
@@ -220,9 +220,9 @@ HMS_connect (const char *format, ...)
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
|
||||
curl_easy_setopt(curl, CURLOPT_IPRESOLVE, (long)CURL_IPRESOLVE_V4);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, cv_masterserver_timeout.value);
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, (long)cv_masterserver_timeout.value);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HMS_on_read);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, buffer);
|
||||
|
||||
@@ -339,8 +339,8 @@ HMS_unlist (void)
|
||||
if (! hms)
|
||||
return 0;
|
||||
|
||||
curl_easy_setopt(hms->curl, CURLOPT_POST, 1);
|
||||
curl_easy_setopt(hms->curl, CURLOPT_POSTFIELDSIZE, 0);
|
||||
curl_easy_setopt(hms->curl, CURLOPT_POST, (long)1);
|
||||
curl_easy_setopt(hms->curl, CURLOPT_POSTFIELDSIZE, (long)0);
|
||||
|
||||
okay = HMS_do(hms);
|
||||
HMS_end(hms);
|
||||
|
||||
+65
-4
@@ -2133,7 +2133,7 @@ void HU_TickSongCredits(void)
|
||||
}
|
||||
}
|
||||
|
||||
void HU_DrawSongCredits(void)
|
||||
static void HU_DrawSongCreditsVanilla(void)
|
||||
{
|
||||
char *str;
|
||||
INT32 len;
|
||||
@@ -2141,9 +2141,6 @@ void HU_DrawSongCredits(void)
|
||||
INT32 y = (splitscreen ? (BASEVIDHEIGHT/2)-4 : 32);
|
||||
INT32 bgt;
|
||||
|
||||
if (!cursongcredit.def) // No def
|
||||
return;
|
||||
|
||||
str = va("\x1F"" %s", cursongcredit.def->source);
|
||||
len = V_ThinStringWidth(str, V_ALLOWLOWERCASE|V_6WIDTHSPACE);
|
||||
destx = (len + 7) * FRACUNIT;
|
||||
@@ -2173,6 +2170,70 @@ void HU_DrawSongCredits(void)
|
||||
V_DrawRightAlignedThinString(cursongcredit.x / FRACUNIT, y, V_ALLOWLOWERCASE|V_6WIDTHSPACE|V_SNAPTOLEFT|(cursongcredit.trans<<V_ALPHASHIFT), str);
|
||||
}
|
||||
|
||||
#define BOXCREDITSLIDEIN (5*TICRATE-TICRATE/2)
|
||||
#define BOXCREDITSLIDEOUT (TICRATE/2)
|
||||
#define BOXCREDITHEIGHT 8
|
||||
static void HU_DrawSongCreditsBox(void)
|
||||
{
|
||||
char *str = cursongcredit.def->source;
|
||||
INT32 strwidth = V_SmallStringWidth(str, V_ALLOWLOWERCASE) + 4;
|
||||
|
||||
// dup dup dup dup
|
||||
INT32 dup = min(vid.dupx, vid.dupy);
|
||||
|
||||
// Center it
|
||||
INT32 x = (BASEVIDWIDTH/2 - strwidth/2)*dup + ((vid.width - (BASEVIDWIDTH * vid.dupx)) / 2);
|
||||
INT32 y = 0;
|
||||
|
||||
INT32 flags = V_SNAPTOTOP|V_NOSCALESTART;
|
||||
INT32 t = cursongcredit.anim;
|
||||
INT32 bgt;
|
||||
|
||||
fixed_t interpoffset = FixedMul(BOXCREDITHEIGHT*dup*FRACUNIT/(TICRATE/2), R_GetHudUncap());
|
||||
|
||||
if (t > BOXCREDITSLIDEIN)
|
||||
{
|
||||
// Sliding in
|
||||
t = TICRATE/2 - (t - BOXCREDITSLIDEIN);
|
||||
y = -BOXCREDITHEIGHT*dup + (FixedMul(BOXCREDITHEIGHT*FRACUNIT, FixedDiv(t*FRACUNIT, TICRATE*FRACUNIT/2))*dup + interpoffset)/FRACUNIT;
|
||||
}
|
||||
else if (t < TICRATE/2)
|
||||
{
|
||||
// Sliding out
|
||||
y = -BOXCREDITHEIGHT*dup + (FixedMul(BOXCREDITHEIGHT*FRACUNIT, FixedDiv(t*FRACUNIT, TICRATE*FRACUNIT/2))*dup - interpoffset)/FRACUNIT;
|
||||
}
|
||||
|
||||
bgt = (NUMTRANSMAPS/2) + (cursongcredit.trans/2);
|
||||
|
||||
if (bgt < NUMTRANSMAPS)
|
||||
{
|
||||
V_DrawFill(x, y, strwidth*dup, BOXCREDITHEIGHT*dup, 28|flags|(bgt<<V_ALPHASHIFT));
|
||||
V_DrawFill(x+dup, y+dup, (strwidth-2)*dup, (BOXCREDITHEIGHT-2)*dup, 30|flags|(bgt<<V_ALPHASHIFT));
|
||||
}
|
||||
if (cursongcredit.trans < NUMTRANSMAPS)
|
||||
{
|
||||
V_DrawSmallString(x+2*dup, y+2*dup, V_ALLOWLOWERCASE|flags|(cursongcredit.trans<<V_ALPHASHIFT), str);
|
||||
}
|
||||
}
|
||||
|
||||
void HU_DrawSongCredits(void)
|
||||
{
|
||||
if (!cursongcredit.def) // No def
|
||||
return;
|
||||
|
||||
switch (cv_songcredits.value)
|
||||
{
|
||||
case 1:
|
||||
HU_DrawSongCreditsVanilla();
|
||||
break;
|
||||
case 2:
|
||||
HU_DrawSongCreditsBox();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Heads up displays drawer, call each frame
|
||||
//
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
#ifndef __I_JOY_H__
|
||||
#define __I_JOY_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "g_input.h"
|
||||
|
||||
/*!
|
||||
@@ -55,4 +59,8 @@ typedef struct JoyType_s JoyType_t;
|
||||
|
||||
extern JoyType_t Joystick[MAXSPLITSCREENPLAYERS];
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __I_JOY_H__
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef __I_NET__
|
||||
#define __I_NET__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface
|
||||
#endif
|
||||
@@ -180,4 +184,8 @@ extern bannednode_t *bannednode;
|
||||
/// \brief Called by D_SRB2Main to be defined by extern network driver
|
||||
boolean I_InitNetwork(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -13,6 +13,10 @@
|
||||
#ifndef __I_SOUND__
|
||||
#define __I_SOUND__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "sounds.h"
|
||||
#include "command.h"
|
||||
@@ -241,4 +245,8 @@ boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void));
|
||||
boolean I_FadeOutStopSong(UINT32 ms);
|
||||
boolean I_FadeInPlaySong(UINT32 ms, boolean looping);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef __I_SYSTEM__
|
||||
#define __I_SYSTEM__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "d_ticcmd.h"
|
||||
#include "d_event.h"
|
||||
|
||||
@@ -256,4 +260,8 @@ const char *I_ClipboardPaste(void);
|
||||
|
||||
void I_RegisterSysCommands(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef I_THREADS_H
|
||||
#define I_THREADS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*I_thread_fn)(void *userdata);
|
||||
|
||||
typedef void * I_mutex;
|
||||
@@ -35,5 +39,9 @@ void I_hold_cond (I_cond *, I_mutex);
|
||||
void I_wake_one_cond (I_cond *);
|
||||
void I_wake_all_cond (I_cond *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif/*I_THREADS_H*/
|
||||
#endif/*HAVE_THREADS*/
|
||||
+10
-8
@@ -37,18 +37,20 @@ tic_t I_GetTime(void)
|
||||
|
||||
void I_InitializeTime(void)
|
||||
{
|
||||
g_time.time = 0;
|
||||
g_time.timefrac = 0;
|
||||
|
||||
enterprecise = 0;
|
||||
oldenterprecise = 0;
|
||||
tictimer = 0.0;
|
||||
|
||||
CV_RegisterVar(&cv_timescale);
|
||||
|
||||
// I_StartupTimer is preserved for potential subsystems that need to setup
|
||||
// timing information for I_GetPreciseTime and sleeping
|
||||
I_StartupTimer();
|
||||
|
||||
g_time.time = 0;
|
||||
g_time.timefrac = 0;
|
||||
|
||||
enterprecise = I_GetPreciseTime();
|
||||
oldenterprecise = enterprecise;
|
||||
entertic = 0;
|
||||
oldentertics = 0;
|
||||
tictimer = 0.0;
|
||||
}
|
||||
|
||||
void I_UpdateTime(fixed_t timescale)
|
||||
@@ -61,7 +63,7 @@ void I_UpdateTime(fixed_t timescale)
|
||||
ticratescaled = (double)TICRATE * FixedToFloat(timescale);
|
||||
|
||||
enterprecise = I_GetPreciseTime();
|
||||
elapsedseconds = (double)((INT64)enterprecise - oldenterprecise) / I_GetPrecisePrecision();
|
||||
elapsedseconds = (double)(enterprecise - oldenterprecise) / I_GetPrecisePrecision();
|
||||
tictimer += elapsedseconds;
|
||||
while (tictimer > 1.0/ticratescaled)
|
||||
{
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef __I_VIDEO__
|
||||
#define __I_VIDEO__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "doomtype.h"
|
||||
|
||||
#ifdef __GNUG__
|
||||
@@ -149,4 +153,8 @@ boolean UseScreenFBO(void);
|
||||
extern boolean downsample;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+3
-2
@@ -10525,11 +10525,12 @@ static void K_drawKartWanted(void)
|
||||
{
|
||||
INT32 x = basex+(splitscreen > 1 ? 13 : 8), y = basey+(splitscreen > 1 ? 16 : 21);
|
||||
fixed_t scale = FRACUNIT/2;
|
||||
player_t *p = &players[battlewanted[i]];
|
||||
|
||||
if (battlewanted[i] == -1)
|
||||
break;
|
||||
|
||||
player_t *p = &players[battlewanted[i]];
|
||||
|
||||
if (numwanted == 1)
|
||||
scale = FRACUNIT;
|
||||
else
|
||||
@@ -10540,7 +10541,7 @@ static void K_drawKartWanted(void)
|
||||
y += 16;
|
||||
}
|
||||
|
||||
if (players[battlewanted[i]].skincolor)
|
||||
if (p->skincolor)
|
||||
{
|
||||
colormap = R_GetTranslationColormap(TC_RAINBOW, p->skincolor, GTC_CACHE);
|
||||
V_DrawFixedPatch(x<<FRACBITS, y<<FRACBITS, FRACUNIT, V_HUDTRANS|(splitscreen < 3 ? V_SNAPTORIGHT : 0)|V_SNAPTOBOTTOM, (scale == FRACUNIT ? R_GetSkinFaceWant(p) : R_GetSkinFaceRank(p)), colormap);
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
#ifndef __K_KART__
|
||||
#define __K_KART__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "d_player.h" // Need for player_t
|
||||
|
||||
@@ -132,5 +136,9 @@ INT32 K_getMinimapTrans(void);
|
||||
void K_getLapsDrawinfo(drawinfo_t *out);
|
||||
void K_getMinimapDrawinfo(drawinfo_t *out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
// =========================================================================
|
||||
#endif // __K_KART__
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "p_slopes.h" // P_GetZAt
|
||||
#include "z_zone.h"
|
||||
#include "r_main.h"
|
||||
#include "r_skins.h"
|
||||
#include "r_things.h"
|
||||
#include "m_random.h"
|
||||
#include "s_sound.h"
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "doomstat.h"
|
||||
#include "p_mobj.h"
|
||||
#include "g_game.h"
|
||||
#include "r_skins.h"
|
||||
#include "r_things.h"
|
||||
#include "b_bot.h"
|
||||
#include "z_zone.h"
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "doomdef.h"
|
||||
#include "fastcmp.h"
|
||||
#include "r_things.h"
|
||||
#include "r_skins.h"
|
||||
#include "r_main.h"
|
||||
#include "p_local.h"
|
||||
#include "g_game.h"
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "doomdef.h"
|
||||
#include "fastcmp.h"
|
||||
#include "r_main.h"
|
||||
#include "r_skins.h"
|
||||
#include "r_things.h"
|
||||
#include "p_mobj.h"
|
||||
#include "d_player.h"
|
||||
|
||||
+2
-1
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "fastcmp.h"
|
||||
#include "r_skins.h"
|
||||
#include "r_things.h"
|
||||
#include "sounds.h"
|
||||
|
||||
@@ -277,4 +278,4 @@ int LUA_SkinLib(lua_State *L)
|
||||
lua_setglobal(L, "skins");
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -495,7 +495,7 @@ static void GIF_rgbconvert(UINT8 *linear, UINT8 *scr)
|
||||
static void GIF_framewrite(void)
|
||||
{
|
||||
UINT8 *p;
|
||||
UINT8 *movie_screen = screens[2];
|
||||
UINT8 *movie_screen = vid.screens[2];
|
||||
INT32 blitx, blity, blitw, blith;
|
||||
|
||||
if (!gifframe_data)
|
||||
@@ -509,7 +509,7 @@ static void GIF_framewrite(void)
|
||||
if (gif_optimize && gif_frames > 0)
|
||||
{
|
||||
// before blit movie_screen points to last frame, cur_screen points to this frame
|
||||
UINT8 *cur_screen = screens[0];
|
||||
UINT8 *cur_screen = vid.screens[0];
|
||||
GIF_optimizeregion(cur_screen, movie_screen, &blitx, &blity, &blitw, &blith);
|
||||
|
||||
// blit to temp screen
|
||||
@@ -535,7 +535,7 @@ static void GIF_framewrite(void)
|
||||
if (rendermode == render_opengl)
|
||||
{
|
||||
UINT8 *linear = HWR_GetScreenshot();
|
||||
GIF_rgbconvert(linear, screens[0]);
|
||||
GIF_rgbconvert(linear, vid.screens[0]);
|
||||
//free(linear); // Allocated 'statically', no need to free now
|
||||
}
|
||||
#endif
|
||||
@@ -545,7 +545,7 @@ static void GIF_framewrite(void)
|
||||
if (gif_frames == 0 && rendermode == render_soft)
|
||||
I_ReadScreen(movie_screen);
|
||||
|
||||
movie_screen = screens[0];
|
||||
movie_screen = vid.screens[0];
|
||||
}
|
||||
|
||||
// screen regions are handled in GIF_lzw
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef __M_ARGV__
|
||||
#define __M_ARGV__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//
|
||||
// MISC
|
||||
//
|
||||
@@ -42,4 +46,8 @@ const char *M_GetNextParm(void);
|
||||
// Finds and loads a response file (@moreargs.txt)
|
||||
void M_FindResponseFile(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif //__M_ARGV__
|
||||
@@ -49,6 +49,20 @@ FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FloatToFixed(float f)
|
||||
return (fixed_t)(f * FRACUNIT);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief convert fixed_t into double-precision floating number
|
||||
*/
|
||||
|
||||
FUNCMATH FUNCINLINE static ATTRINLINE double FixedToDouble(fixed_t x)
|
||||
{
|
||||
return x / (double)FRACUNIT;
|
||||
}
|
||||
|
||||
FUNCMATH FUNCINLINE static ATTRINLINE fixed_t DoubleToFixed(double f)
|
||||
{
|
||||
return (fixed_t)(f * FRACUNIT);
|
||||
}
|
||||
|
||||
// for backwards compat
|
||||
#define FIXED_TO_FLOAT(x) FixedToFloat(x) // (((float)(x)) / ((float)FRACUNIT))
|
||||
#define FLOAT_TO_FIXED(f) FloatToFixed(f) // (fixed_t)((f) * ((float)FRACUNIT))
|
||||
|
||||
+79
-60
@@ -2188,29 +2188,30 @@ static menuitem_t OP_SaturnMenu[] =
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Minimum Input Delay", &cv_mindelay, 20},
|
||||
{IT_STRING | IT_CVAR, NULL, "Gentlemens Ping", &cv_gentlemens, 25},
|
||||
{IT_STRING | IT_CVAR, NULL, "Server Info Screen", &cv_serverinfoscreen, 30},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Skin Select Spinning Speed", &cv_skinselectspin, 35},
|
||||
{IT_STRING | IT_CVAR, NULL, "Skin Select Spinning Speed", &cv_skinselectspin, 40},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Colorized Speedlines", &cv_coloredspeedlines, 45},
|
||||
{IT_STRING | IT_CVAR, NULL, "Colorized Sneakertrails", &cv_coloredsneakertrail, 50},
|
||||
{IT_STRING | IT_CVAR, NULL, "Colorized Speedlines", &cv_coloredspeedlines, 50},
|
||||
{IT_STRING | IT_CVAR, NULL, "Colorized Sneakertrails", &cv_coloredsneakertrail, 55},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Player Blendeffects", &cv_playerblendeffects, 60},
|
||||
{IT_STRING | IT_CVAR, NULL, "Player Blendeffects", &cv_playerblendeffects, 65},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Bananadrag Jitter", &cv_bananajitter, 70},
|
||||
{IT_STRING | IT_CVAR, NULL, "Bananadrag Jitter", &cv_bananajitter, 75},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Midair Driftsparks", &cv_airsparks, 80},
|
||||
{IT_STRING | IT_CVAR, NULL, "Midair Driftsparks", &cv_airsparks, 85},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Show Localskin Menus", &cv_showlocalskinmenus, 90},
|
||||
{IT_STRING | IT_CVAR, NULL, "Show Localskin Menus", &cv_showlocalskinmenus, 95},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Uppercase Menu", &cv_menucaps, 100},
|
||||
{IT_STRING | IT_CVAR, NULL, "Uppercase Menu", &cv_menucaps, 105},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Keyboard Layout", &cv_keyboardlayout, 110},
|
||||
{IT_STRING | IT_CVAR, NULL, "Keyboard Layout", &cv_keyboardlayout, 115},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Less Midnight Channel Flicker", &cv_lessflicker, 120},
|
||||
{IT_STRING | IT_CVAR, NULL, "Less Midnight Channel Flicker", &cv_lessflicker, 125},
|
||||
|
||||
{IT_SUBMENU|IT_STRING, NULL, "Saturn Hud...", &OP_SaturnHudDef, 130},
|
||||
{IT_SUBMENU|IT_STRING, NULL, "Sprite Distortion...", &OP_PlayerDistortDef, 135},
|
||||
{IT_SUBMENU|IT_STRING, NULL, "Saturn Credits", &OP_SaturnCreditsDef, 140}, // uwu
|
||||
{IT_SUBMENU|IT_STRING, NULL, "Saturn Hud...", &OP_SaturnHudDef, 135},
|
||||
{IT_SUBMENU|IT_STRING, NULL, "Sprite Distortion...", &OP_PlayerDistortDef, 140},
|
||||
{IT_SUBMENU|IT_STRING, NULL, "Saturn Credits", &OP_SaturnCreditsDef, 145}, // uwu
|
||||
};
|
||||
|
||||
static const char* OP_SaturnTooltips[] =
|
||||
@@ -2219,6 +2220,7 @@ static const char* OP_SaturnTooltips[] =
|
||||
"How long can the game wait before it kicks you out from the server\nconnecting screen.",
|
||||
"Practice for online play! 0 = instant response.",
|
||||
"Simulate online input delay when hosting a server.\nValue choosen by Player with the lowest ping",
|
||||
"Show a screen before joining a server displaying important information about it",
|
||||
"How much speen do you want?",
|
||||
"Colourize the speedlines in your skincolor if you go fast enough!",
|
||||
"Colourize the sneaker flame trails in your skincolor!",
|
||||
@@ -2466,39 +2468,38 @@ static menuitem_t OP_HudOffsetMenu[] =
|
||||
|
||||
static menuitem_t OP_SaturnCreditsMenu[] =
|
||||
{
|
||||
{IT_HEADER, NULL, "Saturn Credits", NULL, 0},
|
||||
{IT_HEADER, NULL, "Thanks to all contributers <3", NULL, 0},
|
||||
|
||||
{IT_HEADER, NULL, "Thanks to all contributers <3", NULL, 7},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Alug", NULL, 10},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Indev", NULL, 20},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Haya", NULL, 30},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Nepdisk", NULL, 40},
|
||||
{IT_STRING2+IT_SPACE, NULL, "GenericHeroGuy", NULL, 50},
|
||||
{IT_STRING2+IT_SPACE, NULL, "xyzzy", NULL, 60},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Chearii", NULL, 70},
|
||||
|
||||
{IT_STRING2+IT_SPACE, NULL, "Alug", NULL, 17},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Indev", NULL, 27},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Haya", NULL, 37},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Nepdisk", NULL, 47},
|
||||
{IT_STRING2+IT_SPACE, NULL, "GenericHeroGuy", NULL, 57},
|
||||
{IT_STRING2+IT_SPACE, NULL, "xyzzy", NULL, 67},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Chearii", NULL, 77},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Sunflower", NULL, 80},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Yuz", NULL, 90},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Democrab", NULL, 100},
|
||||
{IT_STRING2+IT_SPACE, NULL, "EXpand", NULL, 110},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Nexit", NULL, 120},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Spee", NULL, 130},
|
||||
{IT_STRING2+IT_SPACE, NULL, "jin", NULL, 140},
|
||||
{IT_STRING2+IT_SPACE, NULL, "riomccloud", NULL, 150},
|
||||
{IT_STRING2+IT_SPACE, NULL, "chromaticpipe", NULL, 160},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Achii", NULL, 170},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Anonimus", NULL, 180},
|
||||
{IT_STRING2+IT_SPACE, NULL, "scizor300", NULL, 190},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Lugent", NULL, 200},
|
||||
|
||||
{IT_STRING2+IT_SPACE, NULL, "Sunflower aka AnimeSonic", NULL, 87},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Yuz aka Yuzler", NULL, 97},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Democrab", NULL, 107},
|
||||
{IT_STRING2+IT_SPACE, NULL, "EXpand", NULL, 117},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Nexit", NULL, 127},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Spee", NULL, 137},
|
||||
{IT_STRING2+IT_SPACE, NULL, "jin", NULL, 147},
|
||||
{IT_STRING2+IT_SPACE, NULL, "riomccloud", NULL, 157},
|
||||
{IT_STRING2+IT_SPACE, NULL, "chromaticpipe", NULL, 167},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Achii", NULL, 177},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Anonimus", NULL, 187},
|
||||
{IT_STRING2+IT_SPACE, NULL, "scizor300", NULL, 197},
|
||||
{IT_HEADER, NULL, "Special Thanks <3", NULL, 168},
|
||||
|
||||
{IT_HEADER, NULL, "Special Thanks <3", NULL, 167},
|
||||
{IT_STRING2+IT_SPACE, NULL, "All of Sunflower's Garden", NULL, 178},
|
||||
{IT_STRING2+IT_SPACE, NULL, "The Moe Mansion and Birdhouse Team", NULL, 188},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Galactice for Galaxy", NULL, 198},
|
||||
|
||||
{IT_STRING2+IT_SPACE, NULL, "All of Sunflower's Garden", NULL, 177},
|
||||
{IT_STRING2+IT_SPACE, NULL, "The Moe Mansion and Birdhouse Team", NULL, 187},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Galactice for Galaxy", NULL, 197},
|
||||
|
||||
{IT_STRING+IT_SPACE, NULL, "", NULL, 207}, // dummy text I
|
||||
{IT_STRING, NULL, "", NULL, 267}, // dummy text II
|
||||
{IT_STRING+IT_SPACE, NULL, "", NULL, 198}, // dummy text I
|
||||
{IT_STRING, NULL, "", NULL, 258}, // dummy text II
|
||||
};
|
||||
|
||||
// sry we dont have space for this anymore :/
|
||||
@@ -3600,8 +3601,8 @@ static void M_ChangeCvar(INT32 choice)
|
||||
char s[20];
|
||||
float increment;
|
||||
|
||||
increment = (currentMenu->menuitems[itemOn].status & IT_CV_BIGFLOAT) ? 0.5f : (1.0f/16.0f);
|
||||
sprintf(s, "%f",FIXED_TO_FLOAT(cv->value)+(choice)*increment);
|
||||
increment = FIXED_TO_FLOAT(cv->value)+(choice)*((currentMenu->menuitems[itemOn].status & IT_CV_BIGFLOAT) ? 0.5f : (1.0f/16.0f));
|
||||
sprintf(s,"%ld%s",(long)increment,M_Ftrim(increment));
|
||||
CV_Set(cv, s);
|
||||
}
|
||||
else
|
||||
@@ -7167,8 +7168,11 @@ static void DrawReplayHutReplayInfo(void)
|
||||
if (mapheaderinfo[demolist[dir_on[menudepthleft]].map-1])
|
||||
{
|
||||
char *title = G_BuildMapTitle(demolist[dir_on[menudepthleft]].map);
|
||||
V_DrawString(x, y, V_SNAPTOTOP|MENUCAPS, title);
|
||||
Z_Free(title);
|
||||
if (title)
|
||||
{
|
||||
V_DrawString(x, y, V_SNAPTOTOP|MENUCAPS, title);
|
||||
Z_Free(title);
|
||||
}
|
||||
}
|
||||
else
|
||||
V_DrawString(x, y, V_SNAPTOTOP|V_ALLOWLOWERCASE|V_TRANSLUCENT, "Level is not loaded.");
|
||||
@@ -8120,6 +8124,9 @@ UINT8 skyRoomMenuTranslations[MAXUNLOCKABLES];
|
||||
|
||||
static char *M_GetConditionString(condition_t cond)
|
||||
{
|
||||
char *title = NULL;
|
||||
char *response = NULL;
|
||||
|
||||
switch(cond.type)
|
||||
{
|
||||
case UC_PLAYTIME:
|
||||
@@ -8146,33 +8153,45 @@ static char *M_GetConditionString(condition_t cond)
|
||||
G_TicsToSeconds(cond.requirement));
|
||||
case UC_MAPVISITED:
|
||||
{
|
||||
char *title = G_BuildMapTitle(cond.requirement-1);
|
||||
char *response = va("Visit %s", title);
|
||||
Z_Free(title);
|
||||
title = G_BuildMapTitle(cond.requirement-1);
|
||||
if (title)
|
||||
{
|
||||
response = va("Visit %s", title);
|
||||
Z_Free(title);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
case UC_MAPBEATEN:
|
||||
{
|
||||
char *title = G_BuildMapTitle(cond.requirement-1);
|
||||
char *response = va("Beat %s", title);
|
||||
Z_Free(title);
|
||||
title = G_BuildMapTitle(cond.requirement-1);
|
||||
if (title)
|
||||
{
|
||||
response = va("Beat %s", title);
|
||||
Z_Free(title);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
case UC_MAPALLEMERALDS:
|
||||
{
|
||||
char *title = G_BuildMapTitle(cond.requirement-1);
|
||||
char *response = va("Beat %s w/ all emeralds", title);
|
||||
Z_Free(title);
|
||||
title = G_BuildMapTitle(cond.requirement-1);
|
||||
if (title)
|
||||
{
|
||||
response = va("Beat %s w/ all emeralds", title);
|
||||
Z_Free(title);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
case UC_MAPTIME:
|
||||
{
|
||||
char *title = G_BuildMapTitle(cond.extrainfo1-1);
|
||||
char *response = va("Beat %s in %i:%02i.%02i", title,
|
||||
G_TicsToMinutes(cond.requirement, true),
|
||||
G_TicsToSeconds(cond.requirement),
|
||||
G_TicsToCentiseconds(cond.requirement));
|
||||
Z_Free(title);
|
||||
title = G_BuildMapTitle(cond.extrainfo1-1);
|
||||
if (title)
|
||||
{
|
||||
response = va("Beat %s in %i:%02i.%02i", title,
|
||||
G_TicsToMinutes(cond.requirement, true),
|
||||
G_TicsToSeconds(cond.requirement),
|
||||
G_TicsToCentiseconds(cond.requirement));
|
||||
Z_Free(title);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
case UC_TOTALEMBLEMS:
|
||||
|
||||
@@ -15,6 +15,11 @@
|
||||
#ifndef __X_MENU__
|
||||
#define __X_MENU__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "r_skins.h"
|
||||
#include "d_event.h"
|
||||
#include "command.h"
|
||||
#include "i_threads.h"
|
||||
@@ -433,4 +438,8 @@ if (currentMenu == &menu)\
|
||||
}\
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif //__X_MENU__
|
||||
+32
-4
@@ -14,6 +14,10 @@
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
|
||||
// Ignore "argument might be clobbered by longjmp" warning in GCC
|
||||
// (if libpng is compiled with setjmp error handling)
|
||||
@@ -1060,7 +1064,7 @@ static boolean M_SetupaPNG(png_const_charp filename, png_bytep pal)
|
||||
png_init_io(apng_ptr, apng_FILE);
|
||||
|
||||
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
|
||||
png_set_user_limits(apng_ptr, MAXPNGWIDTH, MAXPNGHEIGHT);
|
||||
png_set_user_limits(apng_ptr, MAXVIDWIDTH, MAXVIDHEIGHT);
|
||||
#endif
|
||||
|
||||
//png_set_filter(apng_ptr, 0, PNG_ALL_FILTERS);
|
||||
@@ -1237,7 +1241,7 @@ void M_SaveFrame(void)
|
||||
if (rendermode == render_soft)
|
||||
{
|
||||
// munge planar buffer to linear
|
||||
linear = screens[2];
|
||||
linear = vid.screens[2];
|
||||
I_ReadScreen(linear);
|
||||
}
|
||||
#ifdef HWRENDER
|
||||
@@ -1375,7 +1379,7 @@ boolean M_SavePNG(const char *filename, void *data, int width, int height, const
|
||||
png_init_io(png_ptr, png_FILE);
|
||||
|
||||
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
|
||||
png_set_user_limits(png_ptr, MAXPNGWIDTH, MAXPNGHEIGHT);
|
||||
png_set_user_limits(png_ptr, MAXVIDWIDTH, MAXVIDHEIGHT);
|
||||
#endif
|
||||
|
||||
//png_set_filter(png_ptr, 0, PNG_ALL_FILTERS);
|
||||
@@ -1539,7 +1543,7 @@ void M_DoScreenShot(void)
|
||||
if (rendermode == render_soft)
|
||||
{
|
||||
// munge planar buffer to linear
|
||||
linear = screens[2];
|
||||
linear = vid.screens[2];
|
||||
I_ReadScreen(linear);
|
||||
}
|
||||
|
||||
@@ -1966,6 +1970,25 @@ char *M_GetToken(const char *inputString)
|
||||
return texturesToken;
|
||||
}
|
||||
|
||||
|
||||
const char * M_Ftrim (double f)
|
||||
{
|
||||
static char dig[9];/* "0." + 6 digits (6 is printf's default) */
|
||||
int i;
|
||||
/* I know I said it's the default, but just in case... */
|
||||
sprintf(dig, "%.6f", fabs(modf(f, &f)));
|
||||
/* trim trailing zeroes */
|
||||
for (i = strlen(dig)-1; dig[i] == '0'; --i)
|
||||
;
|
||||
if (dig[i] == '.')/* :NOTHING: */
|
||||
return "";
|
||||
else
|
||||
{
|
||||
dig[i + 1] = '\0';
|
||||
return &dig[1];/* skip the 0 */
|
||||
}
|
||||
}
|
||||
|
||||
/** Count bits in a number.
|
||||
*/
|
||||
UINT8 M_CountBits(UINT32 num, UINT8 size)
|
||||
@@ -2191,3 +2214,8 @@ void M_MkdirEach(const char *path, int start, int mode)
|
||||
{
|
||||
M_MkdirEachUntil(path, start, -1, mode);
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
@@ -15,6 +15,10 @@
|
||||
#ifndef __M_MISC__
|
||||
#define __M_MISC__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "tables.h"
|
||||
|
||||
@@ -104,10 +108,20 @@ boolean M_IsPathAbsolute (const char *path);
|
||||
void M_MkdirEach (const char *path, int start, int mode);
|
||||
void M_MkdirEachUntil (const char *path, int start, int end, int mode);
|
||||
|
||||
/*
|
||||
Return dot and then the fractional part of a float, without
|
||||
trailing zeros, or "" if the fractional part is zero.
|
||||
*/
|
||||
const char * M_Ftrim (double);
|
||||
|
||||
// counting bits, for weapon ammo code, usually
|
||||
FUNCMATH UINT8 M_CountBits(UINT32 num, UINT8 size);
|
||||
|
||||
#include "w_wad.h"
|
||||
extern char configfile[MAX_WADPATH];
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -26,12 +26,6 @@
|
||||
|
||||
#if defined (STDC_HEADERS) || defined (_LIBC)
|
||||
#include <stdlib.h>
|
||||
#else
|
||||
#ifndef HAVE_MEMCPY
|
||||
#if !(defined (_WIN32) && !defined (__CYGWIN__)) && !defined (__APPLE__)
|
||||
#define memcpy(d, s, n) bcopy ((s), (d), (n))
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "md5.h"
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "g_game.h"
|
||||
#include "p_local.h"
|
||||
#include "r_main.h"
|
||||
#include "r_skins.h"
|
||||
#include "r_state.h"
|
||||
#include "s_sound.h"
|
||||
#include "m_random.h"
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "p_setup.h"
|
||||
#include "r_fps.h"
|
||||
#include "r_main.h"
|
||||
#include "r_skins.h"
|
||||
#include "r_things.h"
|
||||
#include "r_sky.h"
|
||||
#include "r_splats.h"
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef __P_MOBJ__
|
||||
#define __P_MOBJ__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Basics.
|
||||
#include "tables.h"
|
||||
#include "m_fixed.h"
|
||||
@@ -536,4 +540,9 @@ extern mapthing_t *huntemeralds[MAXHUNTEMERALDS];
|
||||
extern INT32 numhuntemeralds;
|
||||
extern boolean runemeraldmanager;
|
||||
extern INT32 numstarposts;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "r_fps.h"
|
||||
#include "r_things.h"
|
||||
#include "r_state.h"
|
||||
#include "r_skins.h"
|
||||
#include "w_wad.h"
|
||||
#include "y_inter.h"
|
||||
#include "z_zone.h"
|
||||
|
||||
+32
-10
@@ -580,9 +580,6 @@ static void P_LoadRawSegs(UINT8 *data)
|
||||
else
|
||||
li->backsector = 0;
|
||||
|
||||
li->numlights = 0;
|
||||
li->rlights = NULL;
|
||||
|
||||
P_UpdateSegLightOffset(li);
|
||||
}
|
||||
}
|
||||
@@ -675,6 +672,21 @@ INT32 P_AddLevelFlat(const char *flatname, levelflat_t *levelflat)
|
||||
levelflat->lumpnum = R_GetFlatNumForName(flatname);
|
||||
levelflat->baselumpnum = LUMPERROR;
|
||||
|
||||
// check if our flat contains cyan pixels
|
||||
// not sure if this is the best way to do it but it works
|
||||
{
|
||||
const UINT8 *flat = (UINT8 *)W_CacheLumpNum(levelflat->lumpnum, PU_LEVEL);
|
||||
size_t size = W_LumpLength(levelflat->lumpnum);
|
||||
for (size_t steppy = 0; steppy < size; steppy++)
|
||||
{
|
||||
if (flat[steppy] == TRANSPARENTPIXEL)
|
||||
{
|
||||
levelflat->cyan = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef ZDEBUG
|
||||
CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name);
|
||||
#endif
|
||||
@@ -720,6 +732,21 @@ INT32 P_AddLevelFlatRuntime(const char *flatname)
|
||||
levelflat->lumpnum = R_GetFlatNumForName(flatname);
|
||||
levelflat->baselumpnum = LUMPERROR;
|
||||
|
||||
// check if our flat contains cyan pixels
|
||||
// not sure if this is the best way to do it but it works
|
||||
{
|
||||
const UINT8 *flat = (UINT8 *)W_CacheLumpNum(levelflat->lumpnum, PU_LEVEL);
|
||||
size_t size = W_LumpLength(levelflat->lumpnum);
|
||||
for (size_t steppy = 0; steppy < size; steppy++)
|
||||
{
|
||||
if (flat[steppy] == TRANSPARENTPIXEL)
|
||||
{
|
||||
levelflat->cyan = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef ZDEBUG
|
||||
CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name);
|
||||
#endif
|
||||
@@ -2747,8 +2774,6 @@ static void P_SetupPlayer(void)
|
||||
I_mkdir(va("%s"PATHSEP"replay", srb2home), 0755);
|
||||
I_mkdir(va("%s"PATHSEP"replay"PATHSEP"online", srb2home), 0755);
|
||||
G_RecordDemo(buf);
|
||||
if (dedicated)
|
||||
G_BeginRecording(); //this has to move here, since dedicated servers dont run got_mapcmd
|
||||
}
|
||||
|
||||
wantedcalcdelay = wantedfrequency*2;
|
||||
@@ -2868,12 +2893,9 @@ boolean P_SetupLevel(boolean fromnetsave, boolean reloadinggamestate)
|
||||
F_WipeStartScreen();
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol);
|
||||
F_WipeEndScreen();
|
||||
F_RunWipe(wipedefs[(encoremode ? wipe_level_final : wipe_level_toblack)], false);
|
||||
}
|
||||
else //dedicated servers
|
||||
{
|
||||
F_RunWipe(wipedefs[(encoremode ? wipe_level_final : wipe_level_toblack)], false);
|
||||
}
|
||||
|
||||
F_RunWipe(wipedefs[(encoremode ? wipe_level_final : wipe_level_toblack)], false);
|
||||
}
|
||||
|
||||
// Reset the palette now all fades have been done
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef __P_SETUP__
|
||||
#define __P_SETUP__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "doomdata.h"
|
||||
#include "doomstat.h"
|
||||
#include "r_defs.h"
|
||||
@@ -48,6 +52,7 @@ typedef struct
|
||||
INT32 animseq; // start pos. in the anim sequence
|
||||
INT32 numpics;
|
||||
INT32 speed;
|
||||
boolean cyan;
|
||||
} levelflat_t;
|
||||
|
||||
extern size_t numlevelflats;
|
||||
@@ -116,4 +121,8 @@ UINT8 P_GetGrade(UINT32 pscore, INT16 map, UINT8 mare);
|
||||
UINT8 P_HasGrades(INT16 map, UINT8 mare);
|
||||
UINT32 P_GetScoreForGrade(INT16 map, UINT8 mare, UINT8 grade);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -654,6 +654,7 @@ void P_Ticker(boolean run)
|
||||
{
|
||||
P_MapStart();
|
||||
R_UpdateMobjInterpolators();
|
||||
R_UpdateLevelInterpolators();
|
||||
OP_ObjectplaceMovement(&players[0]);
|
||||
P_MoveChaseCamera(&players[0], &camera[0], false);
|
||||
R_UpdateViewInterpolation();
|
||||
|
||||
@@ -16,6 +16,15 @@
|
||||
|
||||
#ifndef __QS22J__
|
||||
#define __QS22J__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void qs22j(void *base, size_t nmemb, size_t size,
|
||||
int (*compar)(const void *, const void *));
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
#endif
|
||||
+123
-189
@@ -35,6 +35,7 @@ sector_t *backsector;
|
||||
// very ugly realloc() of drawsegs at run-time, I upped it to 512
|
||||
// instead of 256.. and someone managed to send me a level with
|
||||
// 896 drawsegs! So too bad here's a limit removal a-la-Boom
|
||||
drawseg_t *curdrawsegs = NULL; /**< This is used to handle multiple lists for masked drawsegs. */
|
||||
drawseg_t *drawsegs = NULL;
|
||||
drawseg_t *ds_p = NULL;
|
||||
|
||||
@@ -73,165 +74,96 @@ void R_ClearDrawSegs(void)
|
||||
ds_p = drawsegs;
|
||||
}
|
||||
|
||||
// Fix from boom.
|
||||
#define MAXSEGS (MAXVIDWIDTH/2+1)
|
||||
// CPhipps -
|
||||
// Instead of clipsegs, let's try using an array with one entry for each column,
|
||||
// indicating whether it's blocked by a solid wall yet or not.
|
||||
UINT8 *solidcol;
|
||||
|
||||
// newend is one past the last valid seg
|
||||
static cliprange_t *newend;
|
||||
static cliprange_t solidsegs[MAXSEGS];
|
||||
|
||||
//
|
||||
// R_ClipSolidWallSegment
|
||||
// Does handle solid walls,
|
||||
// e.g. single sided LineDefs (middle texture)
|
||||
// that entirely block the view.
|
||||
//
|
||||
static void R_ClipSolidWallSegment(INT32 first, INT32 last)
|
||||
void R_AllocClipSegMemory(void)
|
||||
{
|
||||
cliprange_t *next;
|
||||
cliprange_t *start;
|
||||
solidcol = static_cast<UINT8*>(Z_Realloc(solidcol, sizeof(*solidcol) * viewwidth, PU_STATIC, NULL));
|
||||
}
|
||||
|
||||
// Find the first range that touches the range (adjacent pixels are touching).
|
||||
start = solidsegs;
|
||||
while (start->last < first - 1)
|
||||
start++;
|
||||
namespace
|
||||
{
|
||||
|
||||
if (first < start->first)
|
||||
enum class ClipType
|
||||
{
|
||||
// Does handle solid walls,
|
||||
// e.g. single sided LineDefs (middle texture)
|
||||
// that entirely block the view.
|
||||
kSolid,
|
||||
kSolidDontRender,
|
||||
|
||||
// Clips the given range of columns, but does not include it in the clip list.
|
||||
// Does handle windows, e.g. LineDefs with upper and lower texture.
|
||||
kPass,
|
||||
};
|
||||
|
||||
// CPhipps -
|
||||
// R_ClipWallSegment
|
||||
//
|
||||
// Replaces the old R_Clip*WallSegment functions. It draws bits of walls in those
|
||||
// columns which aren't solid, and updates the solidcol[] array appropriately
|
||||
template <ClipType Type>
|
||||
static void R_ClipWallSegment(int first, int last)
|
||||
{
|
||||
while (first < last)
|
||||
{
|
||||
if (last < start->first - 1)
|
||||
{
|
||||
// Post is entirely visible (above start), so insert a new clippost.
|
||||
R_StoreWallRange(first, last);
|
||||
next = newend;
|
||||
newend++;
|
||||
// NO MORE CRASHING!
|
||||
if (newend - solidsegs > MAXSEGS)
|
||||
I_Error("R_ClipSolidWallSegment: Solid Segs overflow!\n");
|
||||
UINT8 *p;
|
||||
|
||||
while (next != start)
|
||||
if (solidcol[first])
|
||||
{
|
||||
p = static_cast<UINT8*>(memchr(solidcol+first, 0, last-first));
|
||||
if (!p)
|
||||
return; // All solid
|
||||
|
||||
first = p - solidcol;
|
||||
}
|
||||
else
|
||||
{
|
||||
p = static_cast<UINT8*>(memchr(solidcol+first, 1, last-first));
|
||||
|
||||
int to;
|
||||
if (!p)
|
||||
to = last;
|
||||
else
|
||||
to = p - solidcol;
|
||||
|
||||
if constexpr (Type != ClipType::kSolidDontRender)
|
||||
{
|
||||
*next = *(next-1);
|
||||
next--;
|
||||
R_StoreWallRange(first, to-1);
|
||||
}
|
||||
next->first = first;
|
||||
next->last = last;
|
||||
return;
|
||||
}
|
||||
|
||||
// There is a fragment above *start.
|
||||
R_StoreWallRange(first, start->first - 1);
|
||||
// Now adjust the clip size.
|
||||
start->first = first;
|
||||
}
|
||||
if constexpr (Type != ClipType::kPass)
|
||||
{
|
||||
memset(solidcol+first, 1, to-first);
|
||||
}
|
||||
|
||||
// Bottom contained in start?
|
||||
if (last <= start->last)
|
||||
return;
|
||||
|
||||
next = start;
|
||||
while (last >= (next+1)->first - 1)
|
||||
{
|
||||
// There is a fragment between two posts.
|
||||
R_StoreWallRange(next->last + 1, (next+1)->first - 1);
|
||||
next++;
|
||||
|
||||
if (last <= next->last)
|
||||
{
|
||||
// Bottom is contained in next.
|
||||
// Adjust the clip size.
|
||||
start->last = next->last;
|
||||
goto crunch;
|
||||
first = to;
|
||||
}
|
||||
}
|
||||
|
||||
// There is a fragment after *next.
|
||||
R_StoreWallRange(next->last + 1, last);
|
||||
// Adjust the clip size.
|
||||
start->last = last;
|
||||
|
||||
// Remove start+1 to next from the clip list, because start now covers their area.
|
||||
crunch:
|
||||
if (next == start)
|
||||
return; // Post just extended past the bottom of one post.
|
||||
|
||||
while (next++ != newend)
|
||||
*++start = *next; // Remove a post.
|
||||
|
||||
newend = start + 1;
|
||||
|
||||
// NO MORE CRASHING!
|
||||
if (newend - solidsegs > MAXSEGS)
|
||||
I_Error("R_ClipSolidWallSegment: Solid Segs overflow!\n");
|
||||
}
|
||||
|
||||
//
|
||||
// R_ClipPassWallSegment
|
||||
// Clips the given range of columns, but does not include it in the clip list.
|
||||
// Does handle windows, e.g. LineDefs with upper and lower texture.
|
||||
//
|
||||
static inline void R_ClipPassWallSegment(INT32 first, INT32 last, boolean soliddontrender)
|
||||
{
|
||||
cliprange_t *start;
|
||||
|
||||
// Find the first range that touches the range
|
||||
// (adjacent pixels are touching).
|
||||
start = solidsegs;
|
||||
while (start->last < first - 1)
|
||||
start++;
|
||||
|
||||
if (first < start->first)
|
||||
{
|
||||
if (last < start->first - 1)
|
||||
{
|
||||
// Post is entirely visible (above start).
|
||||
if (!soliddontrender)
|
||||
R_StoreWallRange(first, last);
|
||||
return;
|
||||
}
|
||||
|
||||
// There is a fragment above *start.
|
||||
if (!soliddontrender)
|
||||
R_StoreWallRange(first, start->first - 1);
|
||||
}
|
||||
|
||||
// Bottom contained in start?
|
||||
if (last <= start->last)
|
||||
return;
|
||||
|
||||
while (last >= (start+1)->first - 1)
|
||||
{
|
||||
// There is a fragment between two posts.
|
||||
if (!soliddontrender)
|
||||
R_StoreWallRange(start->last + 1, (start+1)->first - 1);
|
||||
start++;
|
||||
|
||||
if (last <= start->last)
|
||||
return;
|
||||
}
|
||||
|
||||
// There is a fragment after *next.
|
||||
if (!soliddontrender)
|
||||
R_StoreWallRange(start->last + 1, last);
|
||||
}
|
||||
}; // namespace
|
||||
|
||||
//
|
||||
// R_ClearClipSegs
|
||||
//
|
||||
void R_ClearClipSegs(void)
|
||||
{
|
||||
solidsegs[0].first = -0x7fffffff;
|
||||
solidsegs[0].last = -1;
|
||||
solidsegs[1].first = viewwidth;
|
||||
solidsegs[1].last = 0x7fffffff;
|
||||
newend = solidsegs + 2;
|
||||
memset(solidcol, 0, viewwidth);
|
||||
}
|
||||
|
||||
void R_PortalClearClipSegs(INT32 start, INT32 end)
|
||||
{
|
||||
solidsegs[0].first = -0x7fffffff;
|
||||
solidsegs[0].last = start-1;
|
||||
solidsegs[1].first = end;
|
||||
solidsegs[1].last = 0x7fffffff;
|
||||
newend = solidsegs + 2;
|
||||
R_ClearClipSegs();
|
||||
|
||||
if (start > 0)
|
||||
memset(solidcol, 1, start);
|
||||
|
||||
if (end < viewwidth)
|
||||
memset(solidcol + end, 1, viewwidth - end);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -389,6 +321,7 @@ static void R_AddLine(seg_t *line)
|
||||
INT32 x1, x2;
|
||||
angle_t angle1, angle2, span, tspan;
|
||||
static sector_t tempsec;
|
||||
boolean bothfloorssky = false;
|
||||
|
||||
g_portal = NULL;
|
||||
|
||||
@@ -405,7 +338,7 @@ static void R_AddLine(seg_t *line)
|
||||
span = angle1 - angle2;
|
||||
|
||||
// Back side? i.e. backface culling?
|
||||
if (span >= ANGLE_180 || !line->linedef)
|
||||
if (span >= ANGLE_180)
|
||||
return;
|
||||
|
||||
// Global angle needed by segcalc.
|
||||
@@ -424,6 +357,7 @@ static void R_AddLine(seg_t *line)
|
||||
|
||||
angle1 = clipangle;
|
||||
}
|
||||
|
||||
tspan = clipangle - angle2;
|
||||
if (tspan > doubleclipangle)
|
||||
{
|
||||
@@ -439,6 +373,8 @@ static void R_AddLine(seg_t *line)
|
||||
// The seg is in the view range, but not necessarily visible.
|
||||
angle1 = (angle1+ANGLE_90)>>ANGLETOFINESHIFT;
|
||||
angle2 = (angle2+ANGLE_90)>>ANGLETOFINESHIFT;
|
||||
|
||||
// killough 1/31/98: Here is where "slime trails" can SOMETIMES occur:
|
||||
x1 = viewangletox[angle1];
|
||||
x2 = viewangletox[angle2];
|
||||
|
||||
@@ -455,8 +391,10 @@ static void R_AddLine(seg_t *line)
|
||||
{
|
||||
// Find the other side!
|
||||
INT32 line2 = P_FindSpecialLineFromTag(40, line->linedef->tag, -1);
|
||||
|
||||
if (line->linedef == &lines[line2])
|
||||
line2 = P_FindSpecialLineFromTag(40, line->linedef->tag, line2);
|
||||
|
||||
if (line2 >= 0) // found it!
|
||||
{
|
||||
Portal_Add2Lines(line->linedef-lines, line2, x1, x2); // Remember the lines for later rendering
|
||||
@@ -476,6 +414,10 @@ static void R_AddLine(seg_t *line)
|
||||
|
||||
doorclosed = 0;
|
||||
|
||||
// likewise, but for floors and upper textures
|
||||
if (backsector->floorpic == skyflatnum && frontsector->floorpic == skyflatnum)
|
||||
bothfloorssky = true;
|
||||
|
||||
fixed_t frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends
|
||||
fixed_t backf1, backf2, backc1, backc2; // back floor ceiling ends
|
||||
|
||||
@@ -503,19 +445,19 @@ static void R_AddLine(seg_t *line)
|
||||
if (viewsector != backsector && viewsector != frontsector)
|
||||
{
|
||||
// here we're talking about a CEILING lower than a floor. ...yeah we don't even need to bother.
|
||||
if (backc1 <= frontf1 && backc2 <= frontf2)
|
||||
const boolean ceillow = (backc1 <= frontf1 && backc2 <= frontf2);
|
||||
|
||||
// this tries to fix some skyboxes drawing a black void as a midtexture lel
|
||||
if (ceillow && (!bothfloorssky && backsector->ceilingpic == skyflatnum && frontsector->ceilingpic != skyflatnum) // double sided with back ceiling sky but not front ceiling sky
|
||||
&& !line->sidedef->midtexture && !line->sidedef->bottomtexture && !line->sidedef->toptexture && !line->polyseg) // effectively empty
|
||||
{
|
||||
goto clipsolid;
|
||||
}
|
||||
|
||||
// here we're talking about floors higher than ceilings, don't even bother either.
|
||||
if (backf1 >= frontc1 && backf2 >= frontc2)
|
||||
{
|
||||
goto clipsolid;
|
||||
goto clippass;
|
||||
}
|
||||
|
||||
doorclosed = ceillow
|
||||
|| (backf1 >= frontc1 && backf2 >= frontc2)
|
||||
// Check for automap fix. Store in doorclosed for r_segs.c
|
||||
doorclosed = (backc1 <= backf1 && backc2 <= backf2
|
||||
|| (backc1 <= backf1 && backc2 <= backf2
|
||||
&& ((backc1 >= frontc1 && backc2 >= frontc2) || curline->sidedef->toptexture)
|
||||
&& ((backf1 <= frontf1 && backf2 >= frontf2) || curline->sidedef->bottomtexture)
|
||||
&& (backsector->ceilingpic != skyflatnum || frontsector->ceilingpic != skyflatnum));
|
||||
@@ -540,15 +482,15 @@ static void R_AddLine(seg_t *line)
|
||||
|
||||
clippass:
|
||||
g_walloffscreen = false;
|
||||
R_ClipPassWallSegment(x1, x2 - 1, false);
|
||||
R_ClipWallSegment<ClipType::kPass>(x1, x2);
|
||||
|
||||
if (g_walloffscreen)
|
||||
R_ClipPassWallSegment(x1, x2 - 1, true);
|
||||
R_ClipWallSegment<ClipType::kSolidDontRender>(x1, x2);
|
||||
return;
|
||||
|
||||
clipsolid:
|
||||
g_walloffscreen = false;
|
||||
R_ClipSolidWallSegment(x1, x2 - 1);
|
||||
R_ClipWallSegment<ClipType::kSolid>(x1, x2);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -581,22 +523,11 @@ static boolean R_CheckBBox(const fixed_t *bspcoord)
|
||||
angle_t angle1, angle2;
|
||||
INT32 sx1, sx2, boxpos;
|
||||
const INT32* check;
|
||||
cliprange_t *start;
|
||||
|
||||
// Find the corners of the box that define the edges from current viewpoint.
|
||||
if (viewx <= bspcoord[BOXLEFT])
|
||||
boxpos = 0;
|
||||
else if (viewx < bspcoord[BOXRIGHT])
|
||||
boxpos = 1;
|
||||
else
|
||||
boxpos = 2;
|
||||
|
||||
if (viewy >= bspcoord[BOXTOP])
|
||||
boxpos |= 0;
|
||||
else if (viewy > bspcoord[BOXBOTTOM])
|
||||
boxpos |= 1<<2;
|
||||
else
|
||||
boxpos |= 2<<2;
|
||||
// Find the corners of the box
|
||||
// that define the edges from current viewpoint.
|
||||
boxpos = (viewx <= bspcoord[BOXLEFT] ? 0 : viewx < bspcoord[BOXRIGHT ] ? 1 : 2) +
|
||||
(viewy >= bspcoord[BOXTOP ] ? 0 : viewy > bspcoord[BOXBOTTOM] ? 4 : 8);
|
||||
|
||||
if (boxpos == 5)
|
||||
return true;
|
||||
@@ -607,18 +538,23 @@ static boolean R_CheckBBox(const fixed_t *bspcoord)
|
||||
angle1 = R_PointToAngle64(bspcoord[check[0]], bspcoord[check[1]]) - viewangle;
|
||||
angle2 = R_PointToAngle64(bspcoord[check[2]], bspcoord[check[3]]) - viewangle;
|
||||
|
||||
if ((signed)angle1 < (signed)angle2)
|
||||
// cph - replaced old code, which was unclear and badly commented
|
||||
// Much more efficient code now
|
||||
if ((signed)angle1 < (signed)angle2) /* it's "behind" us */
|
||||
{
|
||||
/* Either angle1 or angle2 is behind us, so it doesn't matter if we
|
||||
* change it to the corect sign
|
||||
*/
|
||||
if ((angle1 >= ANGLE_180) && (angle1 < ANGLE_270))
|
||||
angle1 = ANGLE_180-1;
|
||||
else
|
||||
angle2 = ANGLE_180;
|
||||
}
|
||||
|
||||
if ((signed)angle2 >= (signed)clipangle) return false;
|
||||
if ((signed)angle1 <= -(signed)clipangle) return false;
|
||||
if ((signed)angle1 >= (signed)clipangle) angle1 = clipangle;
|
||||
if ((signed)angle2 <= -(signed)clipangle) angle2 = 0-clipangle;
|
||||
if ((signed)angle2 >= (signed)clipangle) return false; // Both off left edge
|
||||
if ((signed)angle1 <= -(signed)clipangle) return false; // Both off right edge
|
||||
if ((signed)angle1 >= (signed)clipangle) angle1 = clipangle; // Clip at left edge
|
||||
if ((signed)angle2 <= -(signed)clipangle) angle2 = -(signed)clipangle; // Clip at right edge
|
||||
|
||||
// Find the first clippost that touches the source post (adjacent pixels are touching).
|
||||
angle1 = (angle1+ANGLE_90)>>ANGLETOFINESHIFT;
|
||||
@@ -630,20 +566,18 @@ static boolean R_CheckBBox(const fixed_t *bspcoord)
|
||||
if (sx1 >= sx2)
|
||||
return false;
|
||||
|
||||
start = solidsegs;
|
||||
while (start->last < sx2)
|
||||
start++;
|
||||
|
||||
if (sx1 >= start->first && sx2 <= start->last)
|
||||
return false; // The clippost contains the new span.
|
||||
if (!memchr(solidcol+sx1, 0, sx2-sx1))
|
||||
{
|
||||
// All columns it covers are already solidly covered
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
size_t numpolys; // number of polyobjects in current subsector
|
||||
size_t num_po_ptrs; // number of polyobject pointers allocated
|
||||
polyobj_t **po_ptrs; // temp ptr array to sort polyobject pointers
|
||||
polyobj_t **po_ptrs; // temp ptr array to sort polyobject pointers
|
||||
|
||||
//
|
||||
// R_PolyobjCompare
|
||||
@@ -681,8 +615,7 @@ void R_SortPolyObjects(subsector_t *sub)
|
||||
{
|
||||
// use free instead realloc since faster (thanks Lee ^_^)
|
||||
free(po_ptrs);
|
||||
po_ptrs = malloc((num_po_ptrs = numpolys*2)
|
||||
* sizeof(*po_ptrs));
|
||||
po_ptrs = static_cast<polyobj_t**>(malloc((num_po_ptrs = numpolys*2)* sizeof(*po_ptrs)));
|
||||
}
|
||||
|
||||
po = sub->polyList;
|
||||
@@ -699,8 +632,7 @@ void R_SortPolyObjects(subsector_t *sub)
|
||||
// 03/10/06: only bother if there are actually polys to sort
|
||||
if (numpolys >= 2)
|
||||
{
|
||||
qs22j(po_ptrs, numpolys, sizeof(polyobj_t *),
|
||||
R_PolyobjCompare);
|
||||
qs22j(po_ptrs, numpolys, sizeof(polyobj_t *), R_PolyobjCompare);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -726,8 +658,8 @@ static int R_PolysegCompare(const void *p1, const void *p2)
|
||||
dist2v1 = vxdist(seg2->v1);
|
||||
dist2v2 = vxdist(seg2->v2);
|
||||
|
||||
if (min(dist1v1, dist1v2) != min(dist2v1, dist2v2))
|
||||
return min(dist1v1, dist1v2) - min(dist2v1, dist2v2);
|
||||
if (std::min(dist1v1, dist1v2) != std::min(dist2v1, dist2v2))
|
||||
return std::min(dist1v1, dist1v2) - std::min(dist2v1, dist2v2);
|
||||
|
||||
{ // That didn't work, so now let's try this.......
|
||||
fixed_t delta1, delta2, x1, y1, x2, y2;
|
||||
@@ -828,14 +760,15 @@ static void R_Subsector(size_t num)
|
||||
fixed_t floorcenterz, ceilingcenterz;
|
||||
ffloor_t *rover;
|
||||
|
||||
#ifdef RANGECHECK
|
||||
if (num >= numsubsectors)
|
||||
I_Error("R_Subsector: ss %s with numss = %s\n", sizeu1(num), sizeu2(numsubsectors));
|
||||
#endif
|
||||
|
||||
// subsectors added at run-time
|
||||
if (num >= numsubsectors)
|
||||
{
|
||||
#ifdef RANGECHECK
|
||||
I_Error("R_Subsector: ss %s with numss = %s\n", sizeu1(num), sizeu2(numsubsectors));
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
sub = &subsectors[num];
|
||||
frontsector = sub->sector;
|
||||
@@ -1144,7 +1077,7 @@ void R_Prep3DFloors(sector_t *sector)
|
||||
if (count != sector->numlights)
|
||||
{
|
||||
Z_Free(sector->lightlist);
|
||||
sector->lightlist = Z_Calloc(sizeof (*sector->lightlist) * count, PU_LEVEL, NULL);
|
||||
sector->lightlist = static_cast<lightlist_t*>(Z_Calloc(sizeof (*sector->lightlist) * count, PU_LEVEL, NULL));
|
||||
sector->numlights = count;
|
||||
}
|
||||
else
|
||||
@@ -1194,6 +1127,7 @@ void R_Prep3DFloors(sector_t *sector)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!best)
|
||||
{
|
||||
sector->numlights = i;
|
||||
+12
@@ -14,6 +14,10 @@
|
||||
#ifndef __R_BSP__
|
||||
#define __R_BSP__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface
|
||||
#endif
|
||||
@@ -32,14 +36,17 @@ extern portal_t *g_portal; // is curline a portal seg?
|
||||
|
||||
extern INT32 checkcoord[12][4];
|
||||
|
||||
extern drawseg_t *curdrawsegs;
|
||||
extern drawseg_t *drawsegs;
|
||||
extern drawseg_t *ds_p;
|
||||
extern INT32 doorclosed;
|
||||
extern UINT8 *solidcol;
|
||||
extern boolean g_walloffscreen;
|
||||
|
||||
// BSP?
|
||||
void R_ClearClipSegs(void);
|
||||
void R_PortalClearClipSegs(INT32 start, INT32 end);
|
||||
void R_AllocClipSegMemory(void);
|
||||
void R_ClearDrawSegs(void);
|
||||
void R_RenderBSPNode(INT32 bspnum);
|
||||
|
||||
@@ -59,4 +66,9 @@ boolean R_IsEmptyLine(seg_t *line, const sector_t *front, const sector_t *back);
|
||||
|
||||
INT32 R_GetPlaneLight(sector_t *sector, fixed_t planeheight, boolean underside);
|
||||
void R_Prep3DFloors(sector_t *sector);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+23
-8
@@ -100,7 +100,7 @@ INT32 numtextures = 0; // total number of textures found,
|
||||
|
||||
texture_t **textures = NULL;
|
||||
static UINT32 **texturecolumnofs; // column offset lookup table for each texture
|
||||
static UINT8 **texturecache; // graphics data for each generated full-size texture
|
||||
UINT8 **texturecache; // graphics data for each generated full-size texture
|
||||
|
||||
// texture width is a power of 2, so it can easily repeat along sidedefs using a simple mask
|
||||
INT32 *texturewidthmask;
|
||||
@@ -296,7 +296,7 @@ static inline void R_DrawColumnInCache(column_t *patch, UINT8 *cache, INT32 orig
|
||||
// This is not optimised, but it's supposed to be executed only once
|
||||
// per level, when enough memory is available.
|
||||
//
|
||||
static UINT8 *R_GenerateTexture(size_t texnum)
|
||||
UINT8 *R_GenerateTexture(size_t texnum)
|
||||
{
|
||||
UINT8 *block;
|
||||
UINT8 *blocktex;
|
||||
@@ -649,6 +649,7 @@ void R_LoadTextures(void)
|
||||
M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name));
|
||||
texture->width = SHORT(patchlump->width);
|
||||
texture->height = SHORT(patchlump->height);
|
||||
texture->type = TEXTURETYPE_SINGLEPATCH;
|
||||
texture->patchcount = 1;
|
||||
texture->holes = false;
|
||||
|
||||
@@ -690,12 +691,15 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch)
|
||||
|
||||
// Patch identifier
|
||||
texturesToken = M_GetToken(NULL);
|
||||
|
||||
if (texturesToken == NULL)
|
||||
{
|
||||
I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch name should be");
|
||||
}
|
||||
|
||||
texturesTokenLength = strlen(texturesToken);
|
||||
if (texturesTokenLength>8)
|
||||
|
||||
if (texturesTokenLength > 8)
|
||||
{
|
||||
I_Error("Error parsing TEXTURES lump: Patch name \"%s\" exceeds 8 characters",texturesToken);
|
||||
}
|
||||
@@ -713,10 +717,12 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch)
|
||||
// Comma 1
|
||||
Z_Free(texturesToken);
|
||||
texturesToken = M_GetToken(NULL);
|
||||
|
||||
if (texturesToken == NULL)
|
||||
{
|
||||
I_Error("Error parsing TEXTURES lump: Unexpected end of file where comma after \"%s\"'s patch name should be",patchName);
|
||||
}
|
||||
|
||||
if (strcmp(texturesToken,",")!=0)
|
||||
{
|
||||
I_Error("Error parsing TEXTURES lump: Expected \",\" after %s's patch name, got \"%s\"",patchName,texturesToken);
|
||||
@@ -725,14 +731,17 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch)
|
||||
// XPos
|
||||
Z_Free(texturesToken);
|
||||
texturesToken = M_GetToken(NULL);
|
||||
|
||||
if (texturesToken == NULL)
|
||||
{
|
||||
I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch \"%s\"'s x coordinate should be",patchName);
|
||||
}
|
||||
|
||||
endPos = NULL;
|
||||
#ifndef AVOID_ERRNO
|
||||
errno = 0;
|
||||
#endif
|
||||
|
||||
patchXPos = strtol(texturesToken,&endPos,10);
|
||||
(void)patchXPos; //unused for now
|
||||
if (endPos == texturesToken // Empty string
|
||||
@@ -748,10 +757,12 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch)
|
||||
// Comma 2
|
||||
Z_Free(texturesToken);
|
||||
texturesToken = M_GetToken(NULL);
|
||||
|
||||
if (texturesToken == NULL)
|
||||
{
|
||||
I_Error("Error parsing TEXTURES lump: Unexpected end of file where comma after patch \"%s\"'s x coordinate should be",patchName);
|
||||
}
|
||||
|
||||
if (strcmp(texturesToken,",")!=0)
|
||||
{
|
||||
I_Error("Error parsing TEXTURES lump: Expected \",\" after patch \"%s\"'s x coordinate, got \"%s\"",patchName,texturesToken);
|
||||
@@ -760,6 +771,7 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch)
|
||||
// YPos
|
||||
Z_Free(texturesToken);
|
||||
texturesToken = M_GetToken(NULL);
|
||||
|
||||
if (texturesToken == NULL)
|
||||
{
|
||||
I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch \"%s\"'s y coordinate should be",patchName);
|
||||
@@ -904,19 +916,22 @@ static texture_t *R_ParseTexture(boolean actuallyLoadTexture)
|
||||
|
||||
// Left Curly Brace
|
||||
texturesToken = M_GetToken(NULL);
|
||||
|
||||
if (texturesToken == NULL)
|
||||
{
|
||||
I_Error("Error parsing TEXTURES lump: Unexpected end of file where open curly brace for texture \"%s\" should be",newTextureName);
|
||||
}
|
||||
|
||||
if (strcmp(texturesToken,"{")==0)
|
||||
{
|
||||
if (actuallyLoadTexture)
|
||||
{
|
||||
// Allocate memory for a zero-patch texture. Obviously, we'll be adding patches momentarily.
|
||||
resultTexture = (texture_t *)Z_Calloc(sizeof(texture_t),PU_STATIC,NULL);
|
||||
resultTexture = (texture_t *)Z_Calloc(sizeof(texture_t), PU_STATIC, NULL);
|
||||
M_Memcpy(resultTexture->name, newTextureName, 8);
|
||||
resultTexture->width = newTextureWidth;
|
||||
resultTexture->height = newTextureHeight;
|
||||
resultTexture->type = TEXTURETYPE_COMPOSITE;
|
||||
}
|
||||
Z_Free(texturesToken);
|
||||
texturesToken = M_GetToken(NULL);
|
||||
@@ -1131,9 +1146,9 @@ static void R_InitExtraColormaps(void)
|
||||
lumpnum_t R_GetFlatNumForName(const char *name)
|
||||
{
|
||||
INT32 i;
|
||||
lumpnum_t lump;
|
||||
lumpnum_t start;
|
||||
lumpnum_t end;
|
||||
lumpnum_t lump = LUMPERROR;
|
||||
lumpnum_t start = LUMPERROR;
|
||||
lumpnum_t end = LUMPERROR;
|
||||
|
||||
// Scan wad files backwards so patched flats take preference.
|
||||
for (i = numwadfiles - 1; i >= 0; i--)
|
||||
@@ -1608,7 +1623,7 @@ const char *R_ColormapNameForNum(INT32 num)
|
||||
if (num == -1)
|
||||
return "NONE";
|
||||
|
||||
if (num < 0 || num > MAXCOLORMAPS)
|
||||
if (num < 0 || num >= MAXCOLORMAPS)
|
||||
I_Error("R_ColormapNameForNum: num %d is invalid!\n", num);
|
||||
|
||||
if (foundcolormaps[num] == LUMPERROR)
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef __R_DATA__
|
||||
#define __R_DATA__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "r_defs.h"
|
||||
#include "r_state.h"
|
||||
|
||||
@@ -33,6 +37,14 @@ typedef struct
|
||||
UINT16 wad, lump;
|
||||
} texpatch_t;
|
||||
|
||||
// texture type
|
||||
enum
|
||||
{
|
||||
TEXTURETYPE_UNKNOWN,
|
||||
TEXTURETYPE_SINGLEPATCH,
|
||||
TEXTURETYPE_COMPOSITE,
|
||||
};
|
||||
|
||||
// A maptexturedef_t describes a rectangular texture,
|
||||
// which is composed of one or more mappatch_t structures
|
||||
// that arrange graphic patches.
|
||||
@@ -40,6 +52,7 @@ typedef struct
|
||||
{
|
||||
// Keep name for switch changing, etc.
|
||||
char name[8];
|
||||
UINT8 type; // TEXTURETYPE_
|
||||
INT16 width, height;
|
||||
boolean holes;
|
||||
|
||||
@@ -50,6 +63,7 @@ typedef struct
|
||||
|
||||
// all loaded and prepared textures from the start of the game
|
||||
extern texture_t **textures;
|
||||
extern UINT8 **texturecache; // graphics data for each generated full-size texture
|
||||
|
||||
// texture width is a power of 2, so it can easily repeat along sidedefs using a simple mask
|
||||
extern INT32 *texturewidthmask;
|
||||
@@ -68,6 +82,8 @@ extern CV_PossibleValue_t Color_cons_t[];
|
||||
void R_LoadTextures(void);
|
||||
void R_FlushTextureCache(void);
|
||||
|
||||
UINT8 *R_GenerateTexture(size_t texnum);
|
||||
|
||||
INT32 R_GetTextureNum(INT32 texnum);
|
||||
void R_CheckTextureCache(INT32 tex);
|
||||
|
||||
@@ -108,4 +124,8 @@ UINT8 NearestPaletteColor(UINT8 r, UINT8 g, UINT8 b, RGBA_t *palette);
|
||||
|
||||
extern INT32 numtextures;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+34
-6
@@ -68,6 +68,37 @@ typedef struct
|
||||
#endif
|
||||
} extracolormap_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
lighttable_t* colormap;
|
||||
|
||||
INT32 x;
|
||||
INT32 yl;
|
||||
INT32 yh;
|
||||
fixed_t iscale;
|
||||
fixed_t texturemid;
|
||||
|
||||
UINT8* source; // first pixel in a column
|
||||
UINT8* lightmap; // lighting only
|
||||
|
||||
// translucency stuff here
|
||||
UINT8* transmap;
|
||||
|
||||
// translation stuff here
|
||||
UINT8* translation;
|
||||
|
||||
struct r_lightlist_s* lightlist;
|
||||
|
||||
INT32 numlights;
|
||||
INT32 maxlights;
|
||||
|
||||
//Fix TUTIFRUTI
|
||||
INT32 texheight;
|
||||
INT32 sourcelength;
|
||||
} drawcolumndata_t;
|
||||
|
||||
extern drawcolumndata_t g_dc;
|
||||
|
||||
//
|
||||
// INTERNAL MAP TYPES used by play and refresh
|
||||
//
|
||||
@@ -527,9 +558,6 @@ typedef struct seg_s
|
||||
float flength; // length of the seg, used by hardware renderer
|
||||
#endif
|
||||
|
||||
// Why slow things down by calculating lightlists for every thick side?
|
||||
size_t numlights;
|
||||
r_lightlist_t *rlights;
|
||||
polyobj_t *polyseg;
|
||||
boolean dontrenderme;
|
||||
|
||||
@@ -610,11 +638,11 @@ typedef struct drawseg_s
|
||||
struct ffloor_s *thicksides[MAXFFLOORS];
|
||||
INT16 *thicksidecol;
|
||||
INT32 numthicksides;
|
||||
fixed_t frontscale[MAXVIDWIDTH];
|
||||
fixed_t *frontscale;
|
||||
|
||||
UINT8 portalpass; // if > 0 and <= portalrender, do not affect sprite clipping
|
||||
|
||||
fixed_t maskedtextureheight[MAXVIDWIDTH]; // For handling sloped midtextures
|
||||
fixed_t *maskedtextureheight; // For handling sloped midtextures
|
||||
|
||||
vertex_t leftpos, rightpos; // Used for rendering FOF walls with slopes
|
||||
} drawseg_t;
|
||||
@@ -668,7 +696,7 @@ typedef struct
|
||||
INT16 height;
|
||||
INT16 leftoffset; // pixels to the left of origin
|
||||
INT16 topoffset; // pixels below the origin
|
||||
INT32 columnofs[8]; // only [width] used
|
||||
INT32 columnofs[]; // only [width] used
|
||||
// the [0] is &columnofs[width]
|
||||
} ATTRPACK softwarepatch_t;
|
||||
|
||||
|
||||
+89
-200
@@ -15,6 +15,8 @@
|
||||
/// not the architecture of the frame buffer.
|
||||
/// The frame buffer is a linear one, and we need only the base address.
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "doomstat.h"
|
||||
#include "r_local.h"
|
||||
@@ -38,47 +40,14 @@
|
||||
|
||||
/** \brief view info
|
||||
*/
|
||||
INT32 viewwidth, scaledviewwidth, viewheight, viewwindowx, viewwindowy;
|
||||
|
||||
/** \brief pointer to the start of each line of the screen,
|
||||
*/
|
||||
UINT8 *ylookup[MAXVIDHEIGHT*4];
|
||||
|
||||
/** \brief pointer to the start of each line of the screen, for view1 (splitscreen)
|
||||
*/
|
||||
UINT8 *ylookup1[MAXVIDHEIGHT*4];
|
||||
|
||||
/** \brief pointer to the start of each line of the screen, for view2 (splitscreen)
|
||||
*/
|
||||
UINT8 *ylookup2[MAXVIDHEIGHT*4];
|
||||
|
||||
/** \brief pointer to the start of each line of the screen, for view3 (splitscreen)
|
||||
*/
|
||||
UINT8 *ylookup3[MAXVIDHEIGHT*4];
|
||||
|
||||
/** \brief pointer to the start of each line of the screen, for view4 (splitscreen)
|
||||
*/
|
||||
UINT8 *ylookup4[MAXVIDHEIGHT*4];
|
||||
|
||||
/** \brief x byte offset for columns inside the viewwindow,
|
||||
so the first column starts at (SCRWIDTH - VIEWWIDTH)/2
|
||||
*/
|
||||
INT32 columnofs[MAXVIDWIDTH*4];
|
||||
|
||||
UINT8 *topleft;
|
||||
INT32 linesize, viewwidth, viewheight, viewwindowx, viewwindowy;
|
||||
UINT8 *renderscreen; // haleyjd
|
||||
|
||||
// =========================================================================
|
||||
// COLUMN DRAWING CODE STUFF
|
||||
// =========================================================================
|
||||
|
||||
lighttable_t *dc_colormap;
|
||||
INT32 dc_x = 0, dc_yl = 0, dc_yh = 0;
|
||||
|
||||
fixed_t dc_iscale, dc_texturemid;
|
||||
UINT8 dc_hires; // under MSVC boolean is a byte, while on other systems, it a bit,
|
||||
// soo lets make it a byte on all system for the ASM code
|
||||
UINT8 *dc_source;
|
||||
INT32 dc_sourcelength;
|
||||
drawcolumndata_t g_dc;
|
||||
|
||||
// -----------------------
|
||||
// translucency stuff here
|
||||
@@ -88,42 +57,34 @@ INT32 dc_sourcelength;
|
||||
UINT8 *transtables; // translucency tables
|
||||
UINT8 *blendtables[NUMBLENDMAPS];
|
||||
|
||||
/** \brief R_DrawTransColumn uses this
|
||||
*/
|
||||
UINT8 *dc_transmap; // one of the translucency tables
|
||||
// --------------------------------------------
|
||||
// c drawer routines
|
||||
// --------------------------------------------
|
||||
|
||||
// ----------------------
|
||||
// translation stuff here
|
||||
// ----------------------
|
||||
|
||||
|
||||
/** \brief R_DrawTranslatedColumn uses this
|
||||
*/
|
||||
UINT8 *dc_translation;
|
||||
|
||||
struct r_lightlist_s *dc_lightlist = NULL;
|
||||
INT32 dc_numlights = 0, dc_maxlights, dc_texheight;
|
||||
coldrawfunc_t *colfunc;
|
||||
coldrawfunc_t *colfuncs[COLDRAWFUNC_MAX];
|
||||
int colfunctype;
|
||||
|
||||
// =========================================================================
|
||||
// SPAN DRAWING CODE STUFF
|
||||
// =========================================================================
|
||||
|
||||
INT32 ds_y, ds_x1, ds_x2;
|
||||
lighttable_t *ds_colormap;
|
||||
fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep;
|
||||
|
||||
UINT8 *ds_source; // points to the start of a flat
|
||||
UINT8 *ds_transmap; // one of the translucency tables
|
||||
drawspandata_t g_ds;
|
||||
|
||||
// Vectors for Software's tilted slope drawers
|
||||
floatv3_t *ds_su, *ds_sv, *ds_sz;
|
||||
floatv3_t *ds_sup, *ds_svp, *ds_szp;
|
||||
float focallengthf, zeroheight;
|
||||
|
||||
/** \brief Variable flat sizes
|
||||
*/
|
||||
float focallengthf;
|
||||
|
||||
UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask;
|
||||
// For, uh, tilted lighting, duh.
|
||||
//static INT32 *tiltlighting;
|
||||
|
||||
// --------------------------------------------
|
||||
// c drawer routines
|
||||
// --------------------------------------------
|
||||
|
||||
spandrawfunc_t *spanfunc;
|
||||
spandrawfunc_t *spanfuncs[SPANDRAWFUNC_MAX];
|
||||
|
||||
// ==========================================================================
|
||||
// OLD DOOM FUZZY EFFECT
|
||||
@@ -147,73 +108,10 @@ UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask;
|
||||
static UINT8 **translationtablecache[TT_CACHE_SIZE] = {NULL};
|
||||
static UINT8 **localtranslationtablecache[MAXLOCALSKINS] = {NULL};
|
||||
|
||||
|
||||
// See also the enum skincolors_t
|
||||
// TODO Callum: Can this be translated?
|
||||
/*
|
||||
const char *Color_Names[MAXSKINCOLORS] =
|
||||
{
|
||||
"None", // SKINCOLOR_NONE
|
||||
"White", // SKINCOLOR_WHITE
|
||||
"Silver", // SKINCOLOR_SILVER
|
||||
"Grey", // SKINCOLOR_GREY
|
||||
"Black", // SKINCOLOR_BLACK
|
||||
"Cyan", // SKINCOLOR_CYAN
|
||||
"Teal", // SKINCOLOR_TEAL
|
||||
"Steel_Blue",// SKINCOLOR_STEEL
|
||||
"Blue", // SKINCOLOR_BLUE
|
||||
"Peach", // SKINCOLOR_PEACH
|
||||
"Tan", // SKINCOLOR_TAN
|
||||
"Pink", // SKINCOLOR_PINK
|
||||
"Lavender", // SKINCOLOR_LAVENDER
|
||||
"Purple", // SKINCOLOR_PURPLE
|
||||
"Orange", // SKINCOLOR_ORANGE
|
||||
"Rosewood", // SKINCOLOR_ROSEWOOD
|
||||
"Beige", // SKINCOLOR_BEIGE
|
||||
"Brown", // SKINCOLOR_BROWN
|
||||
"Red", // SKINCOLOR_RED
|
||||
"Dark_Red", // SKINCOLOR_DARKRED
|
||||
"Neon_Green",// SKINCOLOR_NEONGREEN
|
||||
"Green", // SKINCOLOR_GREEN
|
||||
"Zim", // SKINCOLOR_ZIM
|
||||
"Olive", // SKINCOLOR_OLIVE
|
||||
"Yellow", // SKINCOLOR_YELLOW
|
||||
"Gold" // SKINCOLOR_GOLD
|
||||
};
|
||||
|
||||
const UINT8 Color_Opposite[MAXSKINCOLORS*2] =
|
||||
{
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_NONE
|
||||
SKINCOLOR_BLACK,10, // SKINCOLOR_WHITE
|
||||
SKINCOLOR_GREY,4, // SKINCOLOR_SILVER
|
||||
SKINCOLOR_SILVER,12,// SKINCOLOR_GREY
|
||||
SKINCOLOR_WHITE,8, // SKINCOLOR_BLACK
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_CYAN
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_TEAL
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_STEEL
|
||||
SKINCOLOR_ORANGE,9, // SKINCOLOR_BLUE
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_PEACH
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_TAN
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_PINK
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_LAVENDER
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_PURPLE
|
||||
SKINCOLOR_BLUE,12, // SKINCOLOR_ORANGE
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_ROSEWOOD
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_BEIGE
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_BROWN
|
||||
SKINCOLOR_GREEN,5, // SKINCOLOR_RED
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_DARKRED
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_NEONGREEN
|
||||
SKINCOLOR_RED,11, // SKINCOLOR_GREEN
|
||||
SKINCOLOR_PURPLE,3, // SKINCOLOR_ZIM
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_OLIVE
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_YELLOW
|
||||
SKINCOLOR_NONE,8 // SKINCOLOR_GOLD
|
||||
};
|
||||
*/
|
||||
|
||||
CV_PossibleValue_t Color_cons_t[MAXSKINCOLORS+1];
|
||||
|
||||
static void R_GenerateBlendTables(void);
|
||||
|
||||
/** \brief Initializes the translucency tables used by the Software renderer.
|
||||
*/
|
||||
void R_InitTranslucencyTables(void)
|
||||
@@ -221,8 +119,7 @@ void R_InitTranslucencyTables(void)
|
||||
// Load here the transparency lookup tables 'TRANSx0'
|
||||
// NOTE: the TRANSx0 resources MUST BE aligned on 64k for the asm
|
||||
// optimised code (in other words, transtables pointer low word is 0)
|
||||
transtables = Z_MallocAlign(NUMTRANSTABLES*0x10000, PU_STATIC,
|
||||
NULL, 16);
|
||||
transtables = static_cast<UINT8*>(Z_MallocAlign(NUMTRANSTABLES*0x10000, PU_STATIC, NULL, 16));
|
||||
|
||||
W_ReadLump(W_GetNumForName("TRANS10"), transtables);
|
||||
W_ReadLump(W_GetNumForName("TRANS20"), transtables+0x10000);
|
||||
@@ -283,10 +180,10 @@ static void BlendTab_Subtractive(UINT8 *table, int style, UINT8 blendamt)
|
||||
RGBA_t frontrgba = V_GetColor(fg);
|
||||
RGBA_t result;
|
||||
|
||||
result.rgba = ASTBlendPixel(backrgba, frontrgba, style, 0xFF);
|
||||
result.s.red = max(0, result.s.red - blendamt);
|
||||
result.s.green = max(0, result.s.green - blendamt);
|
||||
result.s.blue = max(0, result.s.blue - blendamt);
|
||||
result.rgba = ASTBlendPixel(backrgba, frontrgba, style, 0xFF);
|
||||
result.s.red = std::max(0, result.s.red - blendamt);
|
||||
result.s.green = std::max(0, result.s.green - blendamt);
|
||||
result.s.blue = std::max(0, result.s.blue - blendamt);
|
||||
|
||||
table[((bg * 0x100) + fg)] = GetColorLUT(&transtab_lut, result.s.red, result.s.green, result.s.blue);
|
||||
}
|
||||
@@ -339,17 +236,17 @@ static void BlendTab_GenerateMaps(INT32 tab, INT32 style, void (*genfunc)(UINT8
|
||||
for (; i < num; i++)
|
||||
{
|
||||
const size_t offs = (0x10000 * i);
|
||||
const UINT16 alpha = min(amtmul * i, 0xFF);
|
||||
const UINT16 alpha = std::fmin(amtmul * i, 0xFF);
|
||||
genfunc(blendtables[tab] + offs, style, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
void R_GenerateBlendTables(void)
|
||||
static void R_GenerateBlendTables(void)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; i < NUMBLENDMAPS; i++)
|
||||
blendtables[i] = Z_MallocAlign(BlendTab_Count[i] * 0x10000, PU_STATIC, NULL, 16);
|
||||
blendtables[i] = static_cast<UINT8*>(Z_MallocAlign(BlendTab_Count[i] * 0x10000, PU_STATIC, NULL, 16));
|
||||
|
||||
InitColorLUT(&transtab_lut, pLocalPalette, false);
|
||||
|
||||
@@ -370,8 +267,8 @@ void R_GenerateBlendTables(void)
|
||||
BlendTab_Modulative(blendtables[blendtab_modulate]);
|
||||
}
|
||||
|
||||
#define ClipBlendLevel(style, trans) max(min((trans), BlendTab_Count[BlendTab_FromStyle[style]]-1), 0)
|
||||
#define ClipTransLevel(trans) max(min((trans), NUMTRANSMAPS-2), 0)
|
||||
#define ClipBlendLevel(style, trans) std::max(std::min((trans), BlendTab_Count[BlendTab_FromStyle[style]]-1), 0)
|
||||
#define ClipTransLevel(trans) std::max(std::min((trans), NUMTRANSMAPS-2), 0)
|
||||
|
||||
UINT8 *R_GetTranslucencyTable(INT32 alphalevel)
|
||||
{
|
||||
@@ -458,7 +355,7 @@ static UINT8* RGetTranslationColormap(INT32 skinnum, skincolors_t color, UINT8 f
|
||||
{
|
||||
// Allocate table for skin if necessary
|
||||
if (!tt[skintableindex])
|
||||
tt[skintableindex] = Z_Calloc(MAXTRANSLATIONS * sizeof(UINT8**), PU_STATIC, NULL);
|
||||
tt[skintableindex] = static_cast<UINT8**>(Z_Calloc(MAXTRANSLATIONS * sizeof(UINT8**), PU_STATIC, NULL));
|
||||
|
||||
// Get colormap
|
||||
ret = tt[skintableindex][color];
|
||||
@@ -468,7 +365,7 @@ static UINT8* RGetTranslationColormap(INT32 skinnum, skincolors_t color, UINT8 f
|
||||
// Generate the colormap if necessary
|
||||
if (!ret)
|
||||
{
|
||||
ret = Z_MallocAlign(NUM_PALETTE_ENTRIES, (flags & GTC_CACHE) ? PU_LEVEL : PU_STATIC, NULL, 8);
|
||||
ret = static_cast<UINT8*>(Z_MallocAlign(NUM_PALETTE_ENTRIES, (flags & GTC_CACHE) ? PU_LEVEL : PU_STATIC, NULL, 8));
|
||||
K_GenerateKartColormap(ret, skinnum, color, local); //R_GenerateTranslationColormap(ret, skinnum, color); // SRB2kart
|
||||
|
||||
// Cache the colormap if desired
|
||||
@@ -540,19 +437,6 @@ void R_FlushTranslationColormapCache(void)
|
||||
memset(localtranslationtablecache[i], 0, MAXTRANSLATIONS * sizeof(UINT8**));
|
||||
}
|
||||
|
||||
/*
|
||||
UINT8 R_GetColorByName(const char *name)
|
||||
{
|
||||
UINT8 color = (UINT8)atoi(name);
|
||||
if (color > 0 && color < MAXSKINCOLORS)
|
||||
return color;
|
||||
for (color = 1; color < MAXSKINCOLORS; color++)
|
||||
if (!stricmp(Color_Names[color], name))
|
||||
return color;
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
// ==========================================================================
|
||||
// COMMON DRAWER FOR 8 AND 16 BIT COLOR MODES
|
||||
// ==========================================================================
|
||||
@@ -572,39 +456,44 @@ UINT8 R_GetColorByName(const char *name)
|
||||
\param height hieght of buffer
|
||||
|
||||
\return void
|
||||
|
||||
|
||||
*/
|
||||
|
||||
static void R_AllocViewMemory(void)
|
||||
{
|
||||
negonearray = static_cast<INT16*>(Z_Realloc(negonearray, sizeof(*negonearray) * viewwidth, PU_STATIC, NULL));
|
||||
screenheightarray = static_cast<INT16*>(Z_Realloc(screenheightarray, sizeof(*screenheightarray) * viewwidth, PU_STATIC, NULL));
|
||||
|
||||
floorclip = static_cast<INT16*>(Z_Realloc(floorclip, sizeof(*floorclip) * viewwidth, PU_STATIC, NULL));
|
||||
ceilingclip = static_cast<INT16*>(Z_Realloc(ceilingclip, sizeof(*ceilingclip) * viewwidth, PU_STATIC, NULL));
|
||||
|
||||
frontscale = static_cast<fixed_t*>(Z_Realloc(frontscale, sizeof(*frontscale) * viewwidth, PU_STATIC, NULL));
|
||||
|
||||
xtoviewangle = static_cast<angle_t*>(Z_Realloc(xtoviewangle, sizeof(*xtoviewangle) * (viewwidth + 1), PU_STATIC, NULL));
|
||||
|
||||
R_AllocSegMemory();
|
||||
R_AllocClipSegMemory();
|
||||
R_AllocPlaneMemory();
|
||||
#ifdef FLOORSPLATS
|
||||
R_AllocFloorSpriteTables();
|
||||
#endif
|
||||
R_AllocVisSpriteMemory();
|
||||
}
|
||||
|
||||
|
||||
void R_InitViewBuffer(INT32 width, INT32 height)
|
||||
{
|
||||
INT32 i, bytesperpixel = vid.bpp;
|
||||
|
||||
if (width > MAXVIDWIDTH)
|
||||
width = MAXVIDWIDTH;
|
||||
if (height > MAXVIDHEIGHT)
|
||||
height = MAXVIDHEIGHT;
|
||||
if (bytesperpixel < 1 || bytesperpixel > 4)
|
||||
I_Error("R_InitViewBuffer: wrong bytesperpixel value %d\n", bytesperpixel);
|
||||
|
||||
R_AllocViewMemory();
|
||||
|
||||
viewwindowx = 0;
|
||||
viewwindowy = 0;
|
||||
|
||||
// Column offset for those columns of the view window, but relative to the entire screen
|
||||
for (i = 0; i < width; i++)
|
||||
columnofs[i] = (viewwindowx + i) * bytesperpixel;
|
||||
|
||||
// Precalculate all row offsets.
|
||||
for (i = 0; i < height; i++)
|
||||
{
|
||||
ylookup[i] = ylookup1[i] = screens[0] + i*vid.width*bytesperpixel;
|
||||
if (splitscreen == 1)
|
||||
ylookup2[i] = screens[0] + (i+viewheight)*vid.width*bytesperpixel;
|
||||
else
|
||||
ylookup2[i] = screens[0] + i*vid.width*bytesperpixel + (viewwidth*bytesperpixel);
|
||||
ylookup3[i] = screens[0] + (i+viewheight)*vid.width*bytesperpixel;
|
||||
ylookup4[i] = screens[0] + (i+viewheight)*vid.width*bytesperpixel + (viewwidth*bytesperpixel);
|
||||
}
|
||||
linesize = vid.width; // killough 11/98
|
||||
renderscreen = vid.screens[0]; // haleyjd 07/02/14
|
||||
}
|
||||
|
||||
/** \brief viewborder patches lump numbers
|
||||
@@ -626,6 +515,28 @@ void R_InitViewBorder(void)
|
||||
viewborderlump[BRDR_BR] = W_GetNumForName("brdr_br");
|
||||
}
|
||||
|
||||
/** \brief The R_VideoErase function
|
||||
|
||||
Copy a screen buffer.
|
||||
|
||||
\param ofs offest from buffer
|
||||
\param count bytes to erase
|
||||
|
||||
\return void
|
||||
|
||||
|
||||
*/
|
||||
void R_VideoErase(size_t ofs, INT32 count)
|
||||
{
|
||||
// LFB copy.
|
||||
// This might not be a good idea if memcpy
|
||||
// is not optimal, e.g. byte by byte on
|
||||
// a 32bit CPU, as GNU GCC/Linux libc did
|
||||
// at one point.
|
||||
M_Memcpy(vid.screens[0] + ofs, vid.screens[1] + ofs, count);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/** \brief R_FillBackScreen
|
||||
|
||||
@@ -648,7 +559,7 @@ void R_FillBackScreen(void)
|
||||
return;
|
||||
|
||||
src = scr_borderpatch;
|
||||
dest = screens[1];
|
||||
dest = vid.screens[1];
|
||||
|
||||
for (y = 0; y < vid.height; y++)
|
||||
{
|
||||
@@ -699,30 +610,7 @@ void R_FillBackScreen(void)
|
||||
V_DrawPatch(viewwindowx + scaledviewwidth, viewwindowy + viewheight, 1,
|
||||
W_CacheLumpNum(viewborderlump[BRDR_BR], PU_CACHE));
|
||||
}
|
||||
#endif
|
||||
|
||||
/** \brief The R_VideoErase function
|
||||
|
||||
Copy a screen buffer.
|
||||
|
||||
\param ofs offest from buffer
|
||||
\param count bytes to erase
|
||||
|
||||
\return void
|
||||
|
||||
|
||||
*/
|
||||
void R_VideoErase(size_t ofs, INT32 count)
|
||||
{
|
||||
// LFB copy.
|
||||
// This might not be a good idea if memcpy
|
||||
// is not optimal, e.g. byte by byte on
|
||||
// a 32bit CPU, as GNU GCC/Linux libc did
|
||||
// at one point.
|
||||
M_Memcpy(screens[0] + ofs, screens[1] + ofs, count);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/** \brief The R_DrawViewBorder
|
||||
|
||||
Draws the border around the view
|
||||
@@ -766,13 +654,14 @@ void R_DrawViewBorder(void)
|
||||
side <<= 1;
|
||||
|
||||
// simpler using our VID_Blit routine
|
||||
VID_BlitLinearScreen(screens[1] + ofs, screens[0] + ofs, side, viewheight - 1,
|
||||
VID_BlitLinearScreen(vid.screens[1] + ofs, vid.screens[0] + ofs, side, viewheight - 1,
|
||||
vid.width, vid.width);
|
||||
}
|
||||
#endif
|
||||
|
||||
// ==========================================================================
|
||||
// INCLUDE 8bpp DRAWING CODE HERE
|
||||
// INCLUDE DRAWING CODE HERE
|
||||
// ==========================================================================
|
||||
|
||||
#include "r_draw8.c"
|
||||
#include "r_draw_column.cpp"
|
||||
#include "r_draw_span.cpp"
|
||||
+155
-74
@@ -14,72 +14,143 @@
|
||||
#ifndef __R_DRAW__
|
||||
#define __R_DRAW__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "r_defs.h"
|
||||
#include "r_things.h"
|
||||
#include "r_skins.h"
|
||||
|
||||
// -------------------------------
|
||||
// COMMON STUFF FOR 8bpp AND 16bpp
|
||||
// -------------------------------
|
||||
extern UINT8 *ylookup[MAXVIDHEIGHT*4];
|
||||
extern UINT8 *ylookup1[MAXVIDHEIGHT*4];
|
||||
extern UINT8 *ylookup2[MAXVIDHEIGHT*4];
|
||||
extern UINT8 *ylookup3[MAXVIDHEIGHT*4];
|
||||
extern UINT8 *ylookup4[MAXVIDHEIGHT*4];
|
||||
extern INT32 columnofs[MAXVIDWIDTH*4];
|
||||
extern UINT8 *topleft;
|
||||
extern UINT8 *renderscreen;
|
||||
extern INT32 linesize;
|
||||
|
||||
// -------------------------
|
||||
// COLUMN DRAWING CODE STUFF
|
||||
// -------------------------
|
||||
FUNCINLINE static ATTRINLINE UINT8 *R_Address(INT32 px, INT32 py)
|
||||
{
|
||||
return renderscreen + (py + viewwindowy) * linesize + (viewwindowx + px);
|
||||
}
|
||||
|
||||
extern lighttable_t *dc_colormap;
|
||||
extern INT32 dc_x, dc_yl, dc_yh;
|
||||
extern fixed_t dc_iscale, dc_texturemid;
|
||||
extern UINT8 dc_hires;
|
||||
|
||||
extern UINT8 *dc_source; // first pixel in a column
|
||||
|
||||
// translucency stuff here
|
||||
extern UINT8 *dc_transmap;
|
||||
|
||||
// translation stuff here
|
||||
|
||||
extern UINT8 *dc_translation;
|
||||
|
||||
extern struct r_lightlist_s *dc_lightlist;
|
||||
extern INT32 dc_numlights, dc_maxlights;
|
||||
|
||||
//Fix TUTIFRUTI
|
||||
extern INT32 dc_texheight;
|
||||
|
||||
// -----------------------
|
||||
// SPAN DRAWING CODE STUFF
|
||||
// -----------------------
|
||||
|
||||
extern INT32 ds_y, ds_x1, ds_x2;
|
||||
extern lighttable_t *ds_colormap;
|
||||
extern fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep;
|
||||
extern INT32 ds_waterofs, ds_bgofs;
|
||||
extern UINT8 *ds_source; // start of a 64*64 tile image
|
||||
extern INT32 dc_sourcelength;
|
||||
extern UINT8 *ds_transmap;
|
||||
|
||||
extern INT32 ds_bgofs;
|
||||
|
||||
typedef struct {
|
||||
float x, y, z;
|
||||
} floatv3_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
INT32 y;
|
||||
INT32 x1;
|
||||
INT32 x2;
|
||||
lighttable_t* colormap;
|
||||
lighttable_t* translation;
|
||||
|
||||
fixed_t xfrac;
|
||||
fixed_t yfrac;
|
||||
fixed_t xstep;
|
||||
fixed_t ystep;
|
||||
INT32 waterofs;
|
||||
INT32 bgofs;
|
||||
|
||||
fixed_t xoffs;
|
||||
fixed_t yoffs;
|
||||
|
||||
visplane_t *currentplane;
|
||||
UINT8 *source;
|
||||
UINT8 *transmap;
|
||||
|
||||
float zeroheight;
|
||||
|
||||
// Vectors for Software's tilted slope drawers
|
||||
floatv3_t sup;
|
||||
floatv3_t svp;
|
||||
floatv3_t szp;
|
||||
floatv3_t slope_origin;
|
||||
floatv3_t slope_u;
|
||||
floatv3_t slope_v;
|
||||
|
||||
// Variable flat sizes
|
||||
UINT32 nflatxshift;
|
||||
UINT32 nflatyshift;
|
||||
UINT32 nflatshiftup;
|
||||
UINT32 nflatmask;
|
||||
|
||||
fixed_t planeheight;
|
||||
lighttable_t **planezlight;
|
||||
|
||||
//
|
||||
// Water ripple effect
|
||||
// Needs the height of the plane, and the vertical position of the span.
|
||||
// Sets planeripple.xfrac and planeripple.yfrac, added to ds_xfrac and ds_yfrac, if the span is not tilted.
|
||||
//
|
||||
struct
|
||||
{
|
||||
INT32 offset;
|
||||
fixed_t xfrac, yfrac;
|
||||
boolean active;
|
||||
} planeripple;
|
||||
} drawspandata_t;
|
||||
|
||||
extern drawspandata_t g_ds;
|
||||
|
||||
// Draws a single visplane.
|
||||
void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_parallel);
|
||||
|
||||
// Vectors for Software's tilted slope drawers
|
||||
extern floatv3_t *ds_su, *ds_sv, *ds_sz;
|
||||
extern floatv3_t *ds_sup, *ds_svp, *ds_szp;
|
||||
extern float focallengthf, zeroheight;
|
||||
|
||||
// Variable flat sizes
|
||||
extern UINT32 nflatxshift;
|
||||
extern UINT32 nflatyshift;
|
||||
extern UINT32 nflatshiftup;
|
||||
extern UINT32 nflatmask;
|
||||
extern float focallengthf;
|
||||
|
||||
|
||||
typedef void (coldrawfunc_t)(drawcolumndata_t*);
|
||||
typedef void (spandrawfunc_t)(drawspandata_t*);
|
||||
|
||||
#define BASEDRAWFUNC 0
|
||||
|
||||
enum
|
||||
{
|
||||
COLDRAWFUNC_BASE = BASEDRAWFUNC,
|
||||
COLDRAWFUNC_FUZZY,
|
||||
COLDRAWFUNC_TRANS,
|
||||
COLDRAWFUNC_SHADOWED,
|
||||
COLDRAWFUNC_TRANSTRANS,
|
||||
COLDRAWFUNC_TWOSMULTIPATCH,
|
||||
COLDRAWFUNC_TWOSMULTIPATCHTRANS,
|
||||
COLDRAWFUNC_FOG,
|
||||
|
||||
COLDRAWFUNC_MAX
|
||||
};
|
||||
|
||||
extern int colfunctype;
|
||||
extern coldrawfunc_t *colfunc;
|
||||
extern coldrawfunc_t *colfuncs[COLDRAWFUNC_MAX];
|
||||
|
||||
enum
|
||||
{
|
||||
SPANDRAWFUNC_BASE = BASEDRAWFUNC,
|
||||
SPANDRAWFUNC_TRANS,
|
||||
SPANDRAWFUNC_TILTED,
|
||||
SPANDRAWFUNC_TILTEDTRANS,
|
||||
|
||||
SPANDRAWFUNC_SPLAT,
|
||||
SPANDRAWFUNC_TRANSSPLAT,
|
||||
SPANDRAWFUNC_TILTEDSPLAT,
|
||||
SPANDRAWFUNC_TILTEDTRANSSPLAT,
|
||||
|
||||
SPANDRAWFUNC_WATER,
|
||||
SPANDRAWFUNC_TILTEDWATER,
|
||||
|
||||
SPANDRAWFUNC_FOG,
|
||||
SPANDRAWFUNC_TILTEDFOG,
|
||||
|
||||
SPANDRAWFUNC_MAX
|
||||
};
|
||||
|
||||
extern spandrawfunc_t *spanfunc;
|
||||
extern spandrawfunc_t *spanfuncs[SPANDRAWFUNC_MAX];
|
||||
|
||||
void R_DrawMaskedColumn(drawcolumndata_t* dc, column_t *column);
|
||||
|
||||
/// \brief Top border
|
||||
#define BRDR_T 0
|
||||
@@ -138,7 +209,6 @@ enum
|
||||
extern UINT8 *blendtables[NUMBLENDMAPS];
|
||||
|
||||
void R_InitTranslucencyTables(void);
|
||||
void R_GenerateBlendTables(void);
|
||||
|
||||
UINT8 *R_GetTranslucencyTable(INT32 alphalevel);
|
||||
UINT8 *R_GetBlendTable(int style, INT32 alphalevel);
|
||||
@@ -161,33 +231,44 @@ void R_DrawViewBorder(void);
|
||||
#define TRANSPARENTPIXEL 247
|
||||
|
||||
// -----------------
|
||||
// 8bpp DRAWING CODE
|
||||
// DRAWING CODE
|
||||
// -----------------
|
||||
|
||||
void R_DrawColumn_8(void);
|
||||
#define R_DrawWallColumn_8 R_DrawColumn_8
|
||||
void R_DrawShadeColumn_8(void);
|
||||
void R_DrawTranslucentColumn_8(void);
|
||||
// column drawers
|
||||
void R_DrawColumn(drawcolumndata_t* dc);
|
||||
void R_DrawColumnShadowed(drawcolumndata_t* dc);
|
||||
|
||||
void R_DrawTranslatedColumn_8(void);
|
||||
void R_DrawTranslatedTranslucentColumn_8(void);
|
||||
void R_DrawSpan_8(void);
|
||||
void R_CalcTiltedLighting(fixed_t start, fixed_t end);
|
||||
void R_DrawTiltedSpan_8(void);
|
||||
void R_DrawTiltedTranslucentSpan_8(void);
|
||||
#ifndef NOWATER
|
||||
void R_DrawTiltedTranslucentWaterSpan_8(void);
|
||||
void R_DrawTranslucentColumn(drawcolumndata_t* dc);
|
||||
|
||||
void R_DrawTranslatedColumn(drawcolumndata_t* dc);
|
||||
void R_DrawTranslatedTranslucentColumn(drawcolumndata_t* dc);
|
||||
|
||||
void R_Draw2sMultiPatchColumn(drawcolumndata_t* dc);
|
||||
void R_Draw2sMultiPatchTranslucentColumn(drawcolumndata_t* dc);
|
||||
|
||||
void R_DrawFogColumn(drawcolumndata_t* dc);
|
||||
|
||||
// span drawers
|
||||
void R_DrawSpan(drawspandata_t* ds);
|
||||
|
||||
void R_DrawSpan_Tilted(drawspandata_t* ds);
|
||||
void R_DrawTranslucentSpan_Tilted(drawspandata_t* ds);
|
||||
void R_DrawTranslucentWaterSpan_Tilted(drawspandata_t* ds);
|
||||
|
||||
void R_DrawTranslucentSpan(drawspandata_t* ds);
|
||||
void R_DrawTranslucentWaterSpan(drawspandata_t* ds);
|
||||
|
||||
void R_DrawFogSpan(drawspandata_t* ds);
|
||||
void R_DrawFogSpan_Tilted(drawspandata_t* ds);
|
||||
|
||||
void R_DrawSplat_Tilted(drawspandata_t* ds);
|
||||
void R_DrawSplat(drawspandata_t* ds);
|
||||
void R_DrawTranslucentSplat(drawspandata_t* ds);
|
||||
void R_DrawTranslucentSplat_Tilted(drawspandata_t* ds);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
void R_DrawTiltedSplat_8(void);
|
||||
void R_DrawSplat_8(void);
|
||||
void R_DrawTranslucentSplat_8(void);
|
||||
void R_DrawTranslucentSpan_8(void);
|
||||
void R_DrawTranslucentWaterSpan_8(void);
|
||||
void R_Draw2sMultiPatchColumn_8(void);
|
||||
void R_Draw2sMultiPatchTranslucentColumn_8(void);
|
||||
void R_DrawFogSpan_8(void);
|
||||
void R_DrawFogColumn_8(void);
|
||||
void R_DrawColumnShadowed_8(void);
|
||||
|
||||
// =========================================================================
|
||||
#endif // __R_DRAW__
|
||||
-1818
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,356 @@
|
||||
// SONIC ROBO BLAST 2 KART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2025 by Kart Krew.
|
||||
// Copyright (C) 2020 by Sonic Team Junior.
|
||||
// Copyright (C) 2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1996 by id Software, Inc.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file r_draw_column.cpp
|
||||
/// \brief column drawer functions
|
||||
/// \note no includes because this is included as part of r_draw.cpp
|
||||
|
||||
// ==========================================================================
|
||||
// COLUMNS
|
||||
// ==========================================================================
|
||||
|
||||
// A column is a vertical slice/span of a wall texture that uses
|
||||
// a has a constant z depth from top to bottom.
|
||||
//
|
||||
|
||||
enum DrawColumnType
|
||||
{
|
||||
DC_BASIC = 0x0000,
|
||||
DC_COLORMAP = 0x0001,
|
||||
DC_TRANSMAP = 0x0002,
|
||||
DC_HOLES = 0x0004,
|
||||
DC_LIGHTLIST = 0x0008,
|
||||
};
|
||||
|
||||
template<DrawColumnType Type>
|
||||
static constexpr UINT8 R_GetColumnTranslated(drawcolumndata_t* dc, UINT8 col, const UINT8 * restrict colormap)
|
||||
{
|
||||
if constexpr (Type & DrawColumnType::DC_COLORMAP)
|
||||
{
|
||||
col = dc->translation[col];
|
||||
}
|
||||
|
||||
return colormap[col];
|
||||
}
|
||||
|
||||
template<DrawColumnType Type>
|
||||
static constexpr UINT8 R_GetColumnTranslucent(drawcolumndata_t* dc, UINT8 * restrict dest, UINT8 col, const UINT8 * restrict colormap)
|
||||
{
|
||||
col = R_GetColumnTranslated<Type>(dc, col, colormap);
|
||||
|
||||
if constexpr (Type & DrawColumnType::DC_TRANSMAP)
|
||||
{
|
||||
return *(dc->transmap + (col << 8) + (*dest));
|
||||
}
|
||||
else
|
||||
{
|
||||
return col;
|
||||
}
|
||||
}
|
||||
|
||||
template<DrawColumnType Type>
|
||||
static constexpr UINT8 R_DrawColumnPixel(drawcolumndata_t* dc, UINT8 * restrict dest, UINT32 bit, const restrict UINT8 *source, const restrict UINT8 *colormap)
|
||||
{
|
||||
UINT8 col = source[bit];
|
||||
|
||||
if constexpr (Type & DrawColumnType::DC_HOLES)
|
||||
{
|
||||
if (col == TRANSPARENTPIXEL)
|
||||
{
|
||||
return *dest;
|
||||
}
|
||||
}
|
||||
|
||||
return R_GetColumnTranslucent<Type>(dc, dest, col, colormap);
|
||||
}
|
||||
|
||||
/** \brief The R_DrawColumn function
|
||||
Experiment to make software go faster. Taken from the Boom source
|
||||
*/
|
||||
template<DrawColumnType Type>
|
||||
static void R_DrawColumnTemplate(drawcolumndata_t *dc)
|
||||
{
|
||||
INT32 count;
|
||||
|
||||
count = dc->yh - dc->yl;
|
||||
|
||||
if (count < 0) // Zero length, column does not exceed a pixel.
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if constexpr (Type & DrawColumnType::DC_LIGHTLIST)
|
||||
{
|
||||
constexpr DrawColumnType NewType = static_cast<DrawColumnType>(Type & ~DC_LIGHTLIST);
|
||||
INT32 i, height, bheight = 0, solid = 0;
|
||||
drawcolumndata_t dc_copy = *dc;
|
||||
|
||||
const INT32 realyh = dc_copy.yh;
|
||||
|
||||
// This runs through the lightlist from top to bottom and cuts up the column accordingly.
|
||||
for (i = 0; i < dc_copy.numlights; i++)
|
||||
{
|
||||
// If the height of the light is above the column, get the colormap
|
||||
// anyway because the lighting of the top should be affected.
|
||||
solid = dc_copy.lightlist[i].flags & FF_CUTSOLIDS;
|
||||
height = dc_copy.lightlist[i].height >> LIGHTSCALESHIFT;
|
||||
|
||||
if (solid)
|
||||
{
|
||||
bheight = dc_copy.lightlist[i].botheight >> LIGHTSCALESHIFT;
|
||||
|
||||
if (bheight < height)
|
||||
{
|
||||
// confounded slopes sometimes allow partial invertedness,
|
||||
// even including cases where the top and bottom heights
|
||||
// should actually be the same!
|
||||
// swap the height values as a workaround for this quirk
|
||||
INT32 temp = height;
|
||||
height = bheight;
|
||||
bheight = temp;
|
||||
}
|
||||
}
|
||||
|
||||
if (height <= dc_copy.yl)
|
||||
{
|
||||
dc_copy.colormap = dc_copy.lightlist[i].rcolormap;
|
||||
|
||||
if (encoremap)
|
||||
{
|
||||
dc_copy.colormap += COLORMAP_REMAPOFFSET;
|
||||
}
|
||||
|
||||
if (solid && dc_copy.yl < bheight)
|
||||
{
|
||||
dc_copy.yl = bheight;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Found a break in the column!
|
||||
dc_copy.yh = height;
|
||||
|
||||
if (dc_copy.yh > realyh)
|
||||
{
|
||||
dc_copy.yh = realyh;
|
||||
}
|
||||
|
||||
R_DrawColumnTemplate<NewType>(&dc_copy);
|
||||
if (solid)
|
||||
{
|
||||
dc_copy.yl = bheight;
|
||||
}
|
||||
else
|
||||
{
|
||||
dc_copy.yl = dc_copy.yh + 1;
|
||||
}
|
||||
|
||||
dc_copy.colormap = dc_copy.lightlist[i].rcolormap;
|
||||
|
||||
if (encoremap)
|
||||
{
|
||||
dc_copy.colormap += COLORMAP_REMAPOFFSET;
|
||||
}
|
||||
}
|
||||
|
||||
dc_copy.yh = realyh;
|
||||
|
||||
if (dc_copy.yl <= realyh)
|
||||
{
|
||||
R_DrawColumnTemplate<NewType>(&dc_copy);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Inner loop that does the actual texture mapping,
|
||||
// e.g. a DDA-lile scaling.
|
||||
// This is as fast as it gets. (Yeah, right!!! -- killough)
|
||||
//
|
||||
// killough 2/1/98: more performance tuning
|
||||
|
||||
intptr_t frac;
|
||||
const intptr_t fracstep = dc->iscale;
|
||||
const intptr_t heightmask = dc->sourcelength-1;
|
||||
constexpr INT32 npow2min = -1;
|
||||
const INT32 npow2max = dc->sourcelength;
|
||||
const INT32 stride = vid.width;
|
||||
|
||||
const UINT8 * restrict source = dc->source;
|
||||
const lighttable_t * restrict colormap = dc->colormap;
|
||||
|
||||
// Framebuffer destination address.
|
||||
UINT8 * restrict dest = R_Address(dc->x, dc->yl);
|
||||
|
||||
count++;
|
||||
|
||||
// Determine scaling, which is the only mapping to be done.
|
||||
frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep));
|
||||
|
||||
switch (heightmask)
|
||||
{
|
||||
case 255:
|
||||
case 127:
|
||||
{
|
||||
while(count--)
|
||||
{
|
||||
*dest = R_DrawColumnPixel<Type>(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap);
|
||||
dest += stride;
|
||||
frac += fracstep;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case -1:
|
||||
{
|
||||
if (frac < 0)
|
||||
// adjust in case we underread
|
||||
frac += FRACUNIT;
|
||||
|
||||
// texture has no height, so just go
|
||||
while (--count >= 0)
|
||||
{
|
||||
*dest = R_DrawColumnPixel<Type>(dc, dest, frac>>FRACBITS, source, colormap);
|
||||
dest += stride;
|
||||
frac += fracstep;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if (!(dc->sourcelength & heightmask)) // power of 2 -- killough
|
||||
{
|
||||
while ((count -= 2) >= 0) // texture height is a power of 2 -- killough
|
||||
{
|
||||
*dest = R_DrawColumnPixel<Type>(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap);
|
||||
dest += stride;
|
||||
frac += fracstep;
|
||||
|
||||
*dest = R_DrawColumnPixel<Type>(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap);
|
||||
dest += stride;
|
||||
frac += fracstep;
|
||||
}
|
||||
|
||||
if (count & 1)
|
||||
{
|
||||
*dest = R_DrawColumnPixel<Type>(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const intptr_t fixed_heightmask = dc->texheight << FRACBITS;
|
||||
|
||||
if (frac < 0)
|
||||
{
|
||||
while ((frac += fixed_heightmask) < 0)
|
||||
{
|
||||
;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (frac >= fixed_heightmask)
|
||||
{
|
||||
frac -= fixed_heightmask;
|
||||
}
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
// Re-map color indices from wall texture column
|
||||
// using a lighting/special effects LUT.
|
||||
// heightmask is the Tutti-Frutti fix
|
||||
|
||||
// -1 is the lower clamp bound because column posts have a "safe" byte before the real data
|
||||
// and a few bytes after as well
|
||||
*dest = R_DrawColumnPixel<Type>(dc, dest, CLAMP((frac >> FRACBITS), npow2min, npow2max), source, colormap);
|
||||
|
||||
dest += stride;
|
||||
|
||||
#if __SIZEOF_POINTER__ < 8 // 64-bit systems have large enough numbers for this to be a non-issue
|
||||
// Avoid overflow.
|
||||
if (fracstep > 0x7FFFFFFF - frac)
|
||||
{
|
||||
frac += fracstep - fixed_heightmask;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
frac += fracstep;
|
||||
}
|
||||
|
||||
while (frac >= fixed_heightmask)
|
||||
{
|
||||
frac -= fixed_heightmask;
|
||||
}
|
||||
}
|
||||
while (--count);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define DEFINE_COLUMN_FUNC(name, flags) \
|
||||
void name(drawcolumndata_t *dc) \
|
||||
{ \
|
||||
constexpr DrawColumnType opt = static_cast<DrawColumnType>(flags); \
|
||||
R_DrawColumnTemplate<opt>(dc); \
|
||||
}
|
||||
|
||||
DEFINE_COLUMN_FUNC(R_DrawColumn, DC_BASIC)
|
||||
DEFINE_COLUMN_FUNC(R_DrawTranslucentColumn, DC_TRANSMAP)
|
||||
DEFINE_COLUMN_FUNC(R_DrawTranslatedColumn, DC_COLORMAP)
|
||||
DEFINE_COLUMN_FUNC(R_DrawColumnShadowed, DC_LIGHTLIST)
|
||||
DEFINE_COLUMN_FUNC(R_DrawTranslatedTranslucentColumn, DC_COLORMAP|DC_TRANSMAP)
|
||||
DEFINE_COLUMN_FUNC(R_Draw2sMultiPatchColumn, DC_HOLES)
|
||||
DEFINE_COLUMN_FUNC(R_Draw2sMultiPatchTranslucentColumn, DC_HOLES|DC_TRANSMAP)
|
||||
|
||||
/** \brief The R_DrawFogColumn function
|
||||
Fog wall.
|
||||
*/
|
||||
void R_DrawFogColumn(drawcolumndata_t* dc)
|
||||
{
|
||||
INT32 count;
|
||||
UINT8 * restrict dest;
|
||||
|
||||
count = dc->yh - dc->yl;
|
||||
|
||||
// Zero length, column does not exceed a pixel.
|
||||
if (count < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Framebuffer destination address.
|
||||
dest = R_Address(dc->x, dc->yl);
|
||||
|
||||
const INT32 stride = vid.width;
|
||||
const lighttable_t * restrict colormap = dc->colormap;
|
||||
|
||||
// Determine scaling, which is the only mapping to be done.
|
||||
do
|
||||
{
|
||||
// Simple. Apply the colormap to what's already on the screen.
|
||||
*dest = colormap[*dest];
|
||||
dest += stride;
|
||||
} while (count--);
|
||||
}
|
||||
@@ -0,0 +1,446 @@
|
||||
// SONIC ROBO BLAST 2 KART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2025 by Kart Krew.
|
||||
// Copyright (C) 2020 by Sonic Team Junior.
|
||||
// Copyright (C) 2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1996 by id Software, Inc.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file r_draw_span.cpp
|
||||
/// \brief span drawer functions
|
||||
/// \note no includes because this is included as part of r_draw.cpp
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#define local_for_thread static __thread
|
||||
#else
|
||||
#include <threads.h>
|
||||
#define local_for_thread thread_local static
|
||||
#endif
|
||||
#else
|
||||
#define local_for_thread static
|
||||
#endif
|
||||
|
||||
// ==========================================================================
|
||||
// SPANS
|
||||
// ==========================================================================
|
||||
|
||||
#define SPANSIZE 16
|
||||
#define INVSPAN 0.0625f
|
||||
|
||||
// <Callum> 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size)
|
||||
#define MAXFLATBYTES 4194303
|
||||
|
||||
#define PLANELIGHTFLOAT ((float)BASEVIDWIDTH * BASEVIDWIDTH / stride / ds->zeroheight / 21.0f * FIXED_TO_FLOAT(fovtan))
|
||||
|
||||
enum DrawSpanType
|
||||
{
|
||||
DS_BASIC = 0x0000,
|
||||
DS_COLORMAP = 0x0001,
|
||||
DS_TRANSMAP = 0x0002,
|
||||
DS_HOLES = 0x0004,
|
||||
DS_RIPPLE = 0x0008,
|
||||
};
|
||||
|
||||
template<DrawSpanType Type>
|
||||
static constexpr UINT8 R_GetSpanTranslucent(drawspandata_t* ds, UINT8 *dsrc, const UINT8 *colormap, UINT8 col)
|
||||
{
|
||||
col = colormap[col];
|
||||
|
||||
if constexpr (Type & DrawSpanType::DS_TRANSMAP)
|
||||
{
|
||||
return *(ds->transmap + (col << 8) + (*dsrc));
|
||||
}
|
||||
else
|
||||
{
|
||||
return col;
|
||||
}
|
||||
}
|
||||
|
||||
template<DrawSpanType Type>
|
||||
static constexpr UINT8 R_DrawSpanPixel(drawspandata_t* ds, UINT8 *dsrc, const UINT8 *colormap, UINT32 bit, const UINT8 *source)
|
||||
{
|
||||
UINT8 col = source[bit];
|
||||
|
||||
if constexpr (Type & DrawSpanType::DS_HOLES)
|
||||
{
|
||||
if (col == TRANSPARENTPIXEL)
|
||||
{
|
||||
return *dsrc;
|
||||
}
|
||||
}
|
||||
|
||||
return R_GetSpanTranslucent<Type>(ds, dsrc, colormap, col);
|
||||
}
|
||||
|
||||
/** \brief The R_DrawSpan_8 function
|
||||
Draws the actual span.
|
||||
*/
|
||||
template<DrawSpanType Type>
|
||||
static void R_DrawSpanTemplate(drawspandata_t* ds)
|
||||
{
|
||||
UINT32 xposition;
|
||||
UINT32 yposition;
|
||||
UINT32 xstep, ystep;
|
||||
UINT32 bit;
|
||||
|
||||
UINT8 * restrict dest = R_Address(ds->x1, ds->y);
|
||||
UINT8 * restrict dsrc;
|
||||
|
||||
const UINT8 * restrict deststop = vid.screens[0] + vid.rowbytes * vid.height;
|
||||
|
||||
if (dest+8 > deststop)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
intptr_t count = (ds->x2 - ds->x1 + 1);
|
||||
size_t i;
|
||||
|
||||
xposition = ds->xfrac; yposition = ds->yfrac;
|
||||
xstep = ds->xstep; ystep = ds->ystep;
|
||||
|
||||
const UINT8 * restrict source = ds->source;
|
||||
const UINT8 * restrict colormap = ds->colormap;
|
||||
|
||||
if constexpr (Type & DS_RIPPLE)
|
||||
{
|
||||
yposition += ds->waterofs;
|
||||
}
|
||||
|
||||
// SoM: we only need 6 bits for the integer part (0 thru 63) so the rest
|
||||
// can be used for the fraction part. This allows calculation of the memory address in the
|
||||
// texture with two shifts, an OR and one AND. (see below)
|
||||
// for texture sizes > 64 the amount of precision we can allow will decrease, but only by one
|
||||
// bit per power of two (obviously)
|
||||
// Ok, because I was able to eliminate the variable spot below, this function is now FASTER
|
||||
// than the original span renderer. Whodathunkit?
|
||||
xposition <<= ds->nflatshiftup; yposition <<= ds->nflatshiftup;
|
||||
xstep <<= ds->nflatshiftup; ystep <<= ds->nflatshiftup;
|
||||
|
||||
if constexpr (Type & DS_RIPPLE)
|
||||
{
|
||||
dsrc = vid.screens[1] + (ds->y + ds->bgofs) * vid.width + ds->x1;
|
||||
}
|
||||
else
|
||||
{
|
||||
dsrc = dest;
|
||||
}
|
||||
|
||||
while (count >= 8)
|
||||
{
|
||||
// SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't
|
||||
// have the uber complicated math to calculate it now, so that was a memory write we didn't
|
||||
// need!
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift);
|
||||
|
||||
dest[i] = R_DrawSpanPixel<Type>(ds, &dsrc[i], colormap, bit, source);
|
||||
|
||||
xposition += xstep;
|
||||
yposition += ystep;
|
||||
}
|
||||
|
||||
dest += 8;
|
||||
dsrc += 8;
|
||||
|
||||
count -= 8;
|
||||
}
|
||||
|
||||
while (count-- && dest <= deststop)
|
||||
{
|
||||
bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift);
|
||||
|
||||
*dest = R_DrawSpanPixel<Type>(ds, dsrc, colormap, bit, source);
|
||||
|
||||
dest++;
|
||||
dsrc++;
|
||||
|
||||
xposition += xstep;
|
||||
yposition += ystep;
|
||||
}
|
||||
}
|
||||
|
||||
// R_CalcTiltedLighting
|
||||
// Exactly what it says on the tin. I wish I wasn't too lazy to explain things properly.
|
||||
static void R_CalcTiltedLighting(INT32 *lightbuffer, INT32 x1, INT32 x2, fixed_t start, fixed_t end)
|
||||
{
|
||||
// ZDoom uses a different lighting setup to us, and I couldn't figure out how to adapt their version
|
||||
// of this function. Here's my own.
|
||||
INT32 i, left = x1, right = x2;
|
||||
const fixed_t step = (end-start)/(x2 - x1 + 1);
|
||||
|
||||
// I wanna do some optimizing by checking for out-of-range segments on either side to fill in all at once,
|
||||
// but I'm too bad at coding to not crash the game trying to do that. I guess this is fast enough for now...
|
||||
|
||||
for (i = left; i <= right; i++)
|
||||
{
|
||||
lightbuffer[i] = (start += step) >> FRACBITS;
|
||||
|
||||
if (lightbuffer[i] < 0)
|
||||
{
|
||||
lightbuffer[i] = 0;
|
||||
}
|
||||
else if (lightbuffer[i] >= MAXLIGHTSCALE)
|
||||
{
|
||||
lightbuffer[i] = MAXLIGHTSCALE-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<DrawSpanType Type>
|
||||
static void R_DrawTiltedSpanTemplate(drawspandata_t* ds)
|
||||
{
|
||||
int width = ds->x2 - ds->x1;
|
||||
float iz, uz, vz;
|
||||
UINT32 u, v;
|
||||
int i;
|
||||
|
||||
UINT8 * restrict dest = R_Address(ds->x1, ds->y);
|
||||
UINT8 * restrict dsrc;
|
||||
|
||||
float startz, startu, startv;
|
||||
float izstep, uzstep, vzstep;
|
||||
float endz, endu, endv;
|
||||
UINT32 stepu, stepv;
|
||||
UINT32 bit;
|
||||
local_for_thread INT32 *tiltlighting = NULL;
|
||||
local_for_thread INT32 oldviewwidth = 0;
|
||||
|
||||
// dont realloc every frame pls thx
|
||||
if (tiltlighting == NULL || oldviewwidth != viewwidth)
|
||||
{
|
||||
tiltlighting = static_cast<INT32*>(realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth));
|
||||
oldviewwidth = viewwidth;
|
||||
}
|
||||
|
||||
INT32 x1 = ds->x1;
|
||||
const INT32 nflatxshift = ds->nflatxshift;
|
||||
const INT32 nflatyshift = ds->nflatyshift;
|
||||
const INT32 nflatmask = ds->nflatmask;
|
||||
const INT32 stride = vid.width;
|
||||
|
||||
iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx);
|
||||
|
||||
// Lighting is simple. It's just linear interpolation from start to end
|
||||
{
|
||||
float planelightfloat = PLANELIGHTFLOAT;
|
||||
float lightstart, lightend;
|
||||
|
||||
lightend = (iz + ds->szp.x*width) * planelightfloat;
|
||||
lightstart = iz * planelightfloat;
|
||||
|
||||
R_CalcTiltedLighting(tiltlighting, ds->x1, ds->x2, FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend));
|
||||
//CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf);
|
||||
}
|
||||
|
||||
uz = ds->sup.z + ds->sup.y*(centery-ds->y) + ds->sup.x*(ds->x1-centerx);
|
||||
vz = ds->svp.z + ds->svp.y*(centery-ds->y) + ds->svp.x*(ds->x1-centerx);
|
||||
|
||||
const UINT8 *source = ds->source;
|
||||
const UINT8 *colormap = ds->colormap;
|
||||
|
||||
if constexpr (Type & DS_RIPPLE)
|
||||
{
|
||||
dsrc = vid.screens[1] + (ds->y + ds->bgofs) * stride + ds->x1;
|
||||
}
|
||||
else
|
||||
{
|
||||
dsrc = dest;
|
||||
}
|
||||
|
||||
#if 0 // The "perfect" reference version of this routine. Pretty slow.
|
||||
// Use it only to see how things are supposed to look.
|
||||
i = 0;
|
||||
do
|
||||
{
|
||||
double z = 1.f/iz;
|
||||
u = (INT64)(uz*z);
|
||||
v = (INT64)(vz*z);
|
||||
|
||||
bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift);
|
||||
colormap = planezlight[tiltlighting[ds->x1]] + (ds->colormap - colormaps);
|
||||
|
||||
*dest = R_DrawSpanPixel<Type>(ds, dsrc, colormap, bit);
|
||||
dest++;
|
||||
ds->x1++;
|
||||
dsrc++;
|
||||
iz += ds_szp->x;
|
||||
uz += ds_sup->x;
|
||||
vz += ds_svp->x;
|
||||
} while (--width >= 0);
|
||||
#else
|
||||
startz = 1.f/iz;
|
||||
startu = uz*startz;
|
||||
startv = vz*startz;
|
||||
|
||||
izstep = ds->szp.x * SPANSIZE;
|
||||
uzstep = ds->sup.x * SPANSIZE;
|
||||
vzstep = ds->svp.x * SPANSIZE;
|
||||
//x1 = 0;
|
||||
width++;
|
||||
|
||||
while (width >= SPANSIZE)
|
||||
{
|
||||
iz += izstep;
|
||||
uz += uzstep;
|
||||
vz += vzstep;
|
||||
|
||||
endz = 1.f/iz;
|
||||
endu = uz*endz;
|
||||
endv = vz*endz;
|
||||
stepu = (INT64)((endu - startu) * INVSPAN);
|
||||
stepv = (INT64)((endv - startv) * INVSPAN);
|
||||
u = (INT64)(startu);
|
||||
v = (INT64)(startv);
|
||||
|
||||
x1 = ds->x1;
|
||||
|
||||
for (i = 0; i < SPANSIZE; i++)
|
||||
{
|
||||
bit = (((v + stepv * i) >> nflatyshift) & nflatmask) | ((u + stepu * i) >> nflatxshift);
|
||||
colormap = ds->planezlight[tiltlighting[x1 + i]] + (ds->colormap - colormaps);
|
||||
dest[i] = R_DrawSpanPixel<Type>(ds, &dsrc[i], colormap, bit, source);
|
||||
}
|
||||
|
||||
ds->x1 += SPANSIZE;
|
||||
dest += SPANSIZE;
|
||||
dsrc += SPANSIZE;
|
||||
startu = endu;
|
||||
startv = endv;
|
||||
width -= SPANSIZE;
|
||||
}
|
||||
|
||||
if (width > 0)
|
||||
{
|
||||
if (width == 1)
|
||||
{
|
||||
u = (INT64)(startu);
|
||||
v = (INT64)(startv);
|
||||
bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift);
|
||||
colormap = ds->planezlight[tiltlighting[ds->x1]] + (ds->colormap - colormaps);
|
||||
*dest = R_DrawSpanPixel<Type>(ds, dsrc, colormap, bit, source);
|
||||
ds->x1++;
|
||||
}
|
||||
else
|
||||
{
|
||||
double left = width;
|
||||
iz += ds->szp.x * left;
|
||||
uz += ds->sup.x * left;
|
||||
vz += ds->svp.x * left;
|
||||
|
||||
endz = 1.f/iz;
|
||||
endu = uz*endz;
|
||||
endv = vz*endz;
|
||||
left = 1.f/left;
|
||||
stepu = (INT64)((endu - startu) * left);
|
||||
stepv = (INT64)((endv - startv) * left);
|
||||
u = (INT64)(startu);
|
||||
v = (INT64)(startv);
|
||||
|
||||
for (; width != 0; width--)
|
||||
{
|
||||
bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift);
|
||||
colormap = ds->planezlight[tiltlighting[ds->x1]] + (ds->colormap - colormaps);
|
||||
*dest = R_DrawSpanPixel<Type>(ds, dsrc, colormap, bit, source);
|
||||
dest++;
|
||||
ds->x1++;
|
||||
dsrc++;
|
||||
u += stepu;
|
||||
v += stepv;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#define DEFINE_SPAN_FUNC(name, flags, template) \
|
||||
void name(drawspandata_t* ds) \
|
||||
{ \
|
||||
constexpr DrawSpanType opt = static_cast<DrawSpanType>(flags); \
|
||||
template<opt>(ds); \
|
||||
}
|
||||
|
||||
#define DEFINE_SPAN_COMBO(name, flags) \
|
||||
DEFINE_SPAN_FUNC(name, flags, R_DrawSpanTemplate) \
|
||||
DEFINE_SPAN_FUNC(name ## _Tilted, flags, R_DrawTiltedSpanTemplate) \
|
||||
|
||||
DEFINE_SPAN_COMBO(R_DrawSpan, DS_BASIC)
|
||||
DEFINE_SPAN_COMBO(R_DrawTranslucentSpan, DS_TRANSMAP)
|
||||
DEFINE_SPAN_COMBO(R_DrawSplat, DS_HOLES)
|
||||
DEFINE_SPAN_COMBO(R_DrawTranslucentSplat, DS_TRANSMAP|DS_HOLES)
|
||||
DEFINE_SPAN_COMBO(R_DrawTranslucentWaterSpan, DS_TRANSMAP|DS_RIPPLE)
|
||||
|
||||
/** \brief The R_DrawFogSpan function
|
||||
Draws the actual span with fogging.
|
||||
*/
|
||||
void R_DrawFogSpan(drawspandata_t* ds)
|
||||
{
|
||||
const UINT8 * restrict colormap = ds->colormap;
|
||||
UINT8 * restrict dest = R_Address(ds->x1, ds->y);
|
||||
|
||||
intptr_t count = ds->x2 - ds->x1 + 1;
|
||||
|
||||
while (count >= 4)
|
||||
{
|
||||
dest[0] = colormap[dest[0]];
|
||||
dest[1] = colormap[dest[1]];
|
||||
dest[2] = colormap[dest[2]];
|
||||
dest[3] = colormap[dest[3]];
|
||||
|
||||
dest += 4;
|
||||
count -= 4;
|
||||
}
|
||||
|
||||
while (count--)
|
||||
{
|
||||
*dest = colormap[*dest];
|
||||
dest++;
|
||||
}
|
||||
}
|
||||
|
||||
void R_DrawFogSpan_Tilted(drawspandata_t* ds)
|
||||
{
|
||||
int width = ds->x2 - ds->x1;
|
||||
float iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx);
|
||||
UINT8 * restrict dest;
|
||||
|
||||
local_for_thread INT32 *tiltlighting = NULL;
|
||||
local_for_thread INT32 oldviewwidth = 0;
|
||||
|
||||
// dont realloc every frame pls thx
|
||||
if (tiltlighting == NULL || oldviewwidth != viewwidth)
|
||||
{
|
||||
tiltlighting = static_cast<INT32*>(realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth));
|
||||
oldviewwidth = viewwidth;
|
||||
}
|
||||
|
||||
dest = R_Address(ds->x1, ds->y);
|
||||
const INT32 stride = vid.width;
|
||||
|
||||
// Lighting is simple. It's just linear interpolation from start to end
|
||||
{
|
||||
float planelightfloat = PLANELIGHTFLOAT;
|
||||
float lightstart, lightend;
|
||||
|
||||
lightend = (iz + ds->szp.x*width) * planelightfloat;
|
||||
lightstart = iz * planelightfloat;
|
||||
|
||||
R_CalcTiltedLighting(tiltlighting, ds->x1, ds->x2, FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend));
|
||||
//CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf);
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
UINT8 *colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps);
|
||||
*dest = colormap[*dest];
|
||||
dest++;
|
||||
}
|
||||
while (--width >= 0);
|
||||
}
|
||||
+3
-3
@@ -173,7 +173,7 @@ static vector3_t *R_LerpVector3(const vector3_t *from, const vector3_t *to, fixe
|
||||
|
||||
// recalc necessary stuff for mouseaiming
|
||||
// slopes are already calculated for the full possible view (which is 4*viewheight).
|
||||
// 18/08/18: (No it's actually 16*viewheight, thanks Jimita for finding this out)
|
||||
// 18/08/18: (No it's actually 16*viewheight, thanks Lactozilla for finding this out)
|
||||
static void R_SetupFreelook(void)
|
||||
{
|
||||
// clip it in the case we are looking a hardware 90 degrees full aiming
|
||||
@@ -494,8 +494,8 @@ void R_CreateInterpolator_Polyobj(thinker_t *thinker, polyobj_t *polyobj)
|
||||
interp->polyobj.polyobj = polyobj;
|
||||
interp->polyobj.vertices_size = polyobj->numVertices;
|
||||
|
||||
interp->polyobj.oldvertices = Z_CallocAlign(sizeof(fixed_t) * 2 * polyobj->numVertices, PU_LEVEL, NULL, 32);
|
||||
interp->polyobj.bakvertices = Z_CallocAlign(sizeof(fixed_t) * 2 * polyobj->numVertices, PU_LEVEL, NULL, 32);
|
||||
interp->polyobj.oldvertices = Z_Calloc(sizeof(fixed_t) * 2 * polyobj->numVertices, PU_LEVEL, NULL);
|
||||
interp->polyobj.bakvertices = Z_Calloc(sizeof(fixed_t) * 2 * polyobj->numVertices, PU_LEVEL, NULL);
|
||||
for (size_t i = 0; i < polyobj->numVertices; i++)
|
||||
{
|
||||
interp->polyobj.oldvertices[i * 2 ] = interp->polyobj.bakvertices[i * 2 ] = polyobj->vertices[i]->x;
|
||||
|
||||
@@ -15,6 +15,10 @@
|
||||
#ifndef __R_FPS_H__
|
||||
#define __R_FPS_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "m_fixed.h"
|
||||
#include "p_local.h"
|
||||
#include "r_state.h"
|
||||
@@ -175,4 +179,8 @@ void R_UpdateMobjInterpolators(void);
|
||||
void R_ResetMobjInterpolationState(mobj_t *mobj);
|
||||
void R_ResetPrecipitationMobjInterpolationState(precipmobj_t *mobj);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef __R_LOCAL__
|
||||
#define __R_LOCAL__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Screen size related parameters.
|
||||
#include "doomdef.h"
|
||||
|
||||
@@ -38,4 +42,8 @@ extern drawseg_t *firstseg;
|
||||
|
||||
void SplitScreen_OnChange(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __R_LOCAL__
|
||||
+257
-255
@@ -13,6 +13,8 @@
|
||||
/// utility functions (BSP, geometry, trigonometry).
|
||||
/// See tables.c, too.
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "g_game.h"
|
||||
#include "g_input.h"
|
||||
@@ -88,7 +90,7 @@ INT32 viewangletox[FINEANGLES/2];
|
||||
// The xtoviewangleangle[] table maps a screen pixel
|
||||
// to the lowest viewangle that maps back to x ranges
|
||||
// from clipangle to -clipangle.
|
||||
angle_t xtoviewangle[MAXVIDWIDTH+1];
|
||||
angle_t *xtoviewangle;
|
||||
|
||||
lighttable_t *scalelight[LIGHTLEVELS][MAXLIGHTSCALE];
|
||||
lighttable_t *scalelightfixed[MAXLIGHTSCALE];
|
||||
@@ -100,23 +102,23 @@ extracolormap_t extra_colormaps[MAXCOLORMAPS];
|
||||
|
||||
// Performance stats
|
||||
precise_t ps_prevframetime = 0;
|
||||
ps_metric_t ps_rendercalltime = {0};
|
||||
ps_metric_t ps_otherrendertime = {0};
|
||||
ps_metric_t ps_uitime = {0};
|
||||
ps_metric_t ps_swaptime = {0};
|
||||
ps_metric_t ps_rendercalltime = {};
|
||||
ps_metric_t ps_otherrendertime = {};
|
||||
ps_metric_t ps_uitime = {};
|
||||
ps_metric_t ps_swaptime = {};
|
||||
|
||||
ps_metric_t ps_skyboxtime = {0};
|
||||
ps_metric_t ps_bsptime = {0};
|
||||
ps_metric_t ps_skyboxtime = {};
|
||||
ps_metric_t ps_bsptime = {};
|
||||
|
||||
ps_metric_t ps_sw_spritecliptime = {0};
|
||||
ps_metric_t ps_sw_portaltime = {0};
|
||||
ps_metric_t ps_sw_planetime = {0};
|
||||
ps_metric_t ps_sw_maskedtime = {0};
|
||||
ps_metric_t ps_sw_spritecliptime = {};
|
||||
ps_metric_t ps_sw_portaltime = {};
|
||||
ps_metric_t ps_sw_planetime = {};
|
||||
ps_metric_t ps_sw_maskedtime = {};
|
||||
|
||||
ps_metric_t ps_numbspcalls = {0};
|
||||
ps_metric_t ps_numsprites = {0};
|
||||
ps_metric_t ps_numdrawnodes = {0};
|
||||
ps_metric_t ps_numpolyobjects = {0};
|
||||
ps_metric_t ps_numbspcalls = {};
|
||||
ps_metric_t ps_numsprites = {};
|
||||
ps_metric_t ps_numdrawnodes = {};
|
||||
ps_metric_t ps_numpolyobjects = {};
|
||||
|
||||
static CV_PossibleValue_t drawdist_cons_t[] = {
|
||||
/*{256, "256"},*/ {512, "512"}, {768, "768"},
|
||||
@@ -125,16 +127,17 @@ static CV_PossibleValue_t drawdist_cons_t[] = {
|
||||
{8192, "8192"}, {12288, "12288"}, {20480, "20480"},
|
||||
{24576, "24576"},{0, "Infinite"}, {0, NULL}};
|
||||
|
||||
#if defined(__x86_64__) || defined(__amd64__) || defined(__aarch64__) || defined(__arm64__) // only for 64bit (idk how else to proper check lmao)
|
||||
#if __SIZEOF_POINTER__ < 8 // only for 64bit
|
||||
static CV_PossibleValue_t drawdist_precip_cons_t[] = {
|
||||
{256, "256"}, {512, "512"}, {768, "768"},
|
||||
{256, "256"}, {512, "512"}, {768, "768"},
|
||||
{1024, "1024"}, {1536, "1536"}, {2048, "2048"},
|
||||
{3072, "3072"}, {4096, "4096"}, {0, "None"}, {0, NULL}};
|
||||
{0, "None"}, {0, NULL}};
|
||||
|
||||
#else
|
||||
static CV_PossibleValue_t drawdist_precip_cons_t[] = {
|
||||
{256, "256"}, {512, "512"}, {768, "768"},
|
||||
{1024, "1024"}, {1536, "1536"}, {2048, "2048"},
|
||||
{0, "None"}, {0, NULL}};
|
||||
{256, "256"}, {512, "512"}, {768, "768"},
|
||||
{1024, "1024"}, {1536, "1536"}, {2048, "2048"},
|
||||
{3072, "3072"}, {4096, "4096"}, {0, "None"}, {0, NULL}};
|
||||
#endif
|
||||
|
||||
static CV_PossibleValue_t maxinterpdist_cons_t[] = {
|
||||
@@ -156,10 +159,6 @@ static void FlipCam_OnChange(void);
|
||||
static void FlipCam2_OnChange(void);
|
||||
static void FlipCam3_OnChange(void);
|
||||
static void FlipCam4_OnChange(void);
|
||||
void SendWeaponPref(void);
|
||||
void SendWeaponPref2(void);
|
||||
void SendWeaponPref3(void);
|
||||
void SendWeaponPref4(void);
|
||||
|
||||
static void DirLight_OnChange(void);
|
||||
|
||||
@@ -184,38 +183,37 @@ consvar_t cv_flipcam[MAXSPLITSCREENPLAYERS] = {
|
||||
{"flipcam4", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam4_OnChange, 0, NULL, NULL, 0, 0, NULL}
|
||||
};
|
||||
|
||||
consvar_t cv_shadow = {"shadow", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_shadowoffs = {"offsetshadows", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_skybox = {"skybox", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_ffloorclip = {"r_ffloorclip", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_spriteclip = {"r_spriteclip", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_soniccd = {"soniccd", "Off", CV_NETVAR|CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_allowmlook = {"allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_showhud = {"showhud", "Yes", CV_CALL, CV_YesNo, R_SetViewSize, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_translucenthud = {"translucenthud", "10", CV_SAVE, translucenthud_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_uncappedhud = {"uncappedhud", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_translucency = {"translucency", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_drawdist = {"drawdist", "Infinite", CV_SAVE, drawdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_shadow = {"shadow", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_shadowoffs = {"offsetshadows", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_skybox = {"skybox", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_ffloorclip = {"r_ffloorclip", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_spriteclip = {"r_spriteclip", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_softcyancut = {"softwarecyancut", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_translucency = {"translucency", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_drawdist = {"drawdist", "Infinite", CV_SAVE, drawdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_drawdist_precip = {"drawdist_precip", "1024", CV_SAVE|CV_CALL|CV_NOINIT, drawdist_precip_cons_t, Precipstuff_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_lessprecip = {"lessweathereffects", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, Precipstuff_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_lessprecip = {"lessweathereffects", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, Precipstuff_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_mobjscaleprecip = {"scaleprecipmobjscale", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, Precipstuff_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_maxinterpdist = {"maxinterpdist", "Infinite", CV_SAVE, maxinterpdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_ripplewater = {"waterripples", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
// cap fov, fov too high tears software apart.
|
||||
consvar_t cv_fov = {"fov", "90", CV_FLOAT|CV_CALL|CV_SAVE, fov_cons_t, Fov_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_fovchange = {"fovchange", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_maxinterpdist = {"maxinterpdist", "Infinite", CV_SAVE, maxinterpdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_ripplewater = {"waterripples", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
// Okay, whoever said homremoval causes a performance hit should be shot.
|
||||
consvar_t cv_homremoval = {"homremoval", "Yes", CV_SAVE, homremoval_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_homremoval = {"homremoval", "Yes", CV_SAVE, homremoval_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_maxportals = {"maxportals", "2", CV_SAVE, maxportals_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_maxportals = {"maxportals", "2", CV_SAVE, maxportals_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
// cap fov, fov too high tears software apart.
|
||||
consvar_t cv_fov = {"fov", "90", CV_FLOAT|CV_CALL|CV_SAVE, fov_cons_t, Fov_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_fovchange = {"fovchange", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
// randomized directional lightning
|
||||
consvar_t cv_randomdirlight = {"randomdirectionallight", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, DirLight_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_randomdirlight = {"randomdirectionallight", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, DirLight_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_showhud = {"showhud", "Yes", CV_CALL, CV_YesNo, R_SetViewSize, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_translucenthud = {"translucenthud", "10", CV_SAVE, translucenthud_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_uncappedhud = {"uncappedhud", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_soniccd = {"soniccd", "Off", CV_NETVAR|CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_allowmlook = {"allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
// tells to reset the maplight at next map change
|
||||
static void DirLight_OnChange(void)
|
||||
@@ -493,7 +491,7 @@ boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixe
|
||||
// Returns search dimensions within a blockmap, in the direction of viewangle and out to a certain distance.
|
||||
void R_GetRenderBlockMapDimensions(fixed_t drawdist, INT32 *xl, INT32 *xh, INT32 *yl, INT32 *yh)
|
||||
{
|
||||
const angle_t left = viewangle - clipangle;
|
||||
const angle_t left = viewangle - clipangle;
|
||||
const angle_t right = viewangle + clipangle;
|
||||
|
||||
const fixed_t vxleft = viewx + FixedMul(drawdist, FCOS(left));
|
||||
@@ -503,10 +501,10 @@ void R_GetRenderBlockMapDimensions(fixed_t drawdist, INT32 *xl, INT32 *xh, INT32
|
||||
const fixed_t vyright = viewy + FixedMul(drawdist, FSIN(right));
|
||||
|
||||
// Try to narrow the search to within only the field of view
|
||||
*xl = (unsigned)(min(viewx, min(vxleft, vxright)) - bmaporgx)>>MAPBLOCKSHIFT;
|
||||
*xh = (unsigned)(max(viewx, max(vxleft, vxright)) - bmaporgx)>>MAPBLOCKSHIFT;
|
||||
*yl = (unsigned)(min(viewy, min(vyleft, vyright)) - bmaporgy)>>MAPBLOCKSHIFT;
|
||||
*yh = (unsigned)(max(viewy, max(vyleft, vyright)) - bmaporgy)>>MAPBLOCKSHIFT;
|
||||
*xl = (unsigned)(std::min(viewx, std::min(vxleft, vxright)) - bmaporgx)>>MAPBLOCKSHIFT;
|
||||
*xh = (unsigned)(std::max(viewx, std::max(vxleft, vxright)) - bmaporgx)>>MAPBLOCKSHIFT;
|
||||
*yl = (unsigned)(std::min(viewy, std::min(vyleft, vyright)) - bmaporgy)>>MAPBLOCKSHIFT;
|
||||
*yh = (unsigned)(std::max(viewy, std::max(vyleft, vyright)) - bmaporgy)>>MAPBLOCKSHIFT;
|
||||
|
||||
if (*xh >= bmapwidth)
|
||||
*xh = bmapwidth - 1;
|
||||
@@ -630,7 +628,7 @@ static struct {
|
||||
INT32 scrmapsize;
|
||||
|
||||
INT32 x1; // clip rendering horizontally for efficiency
|
||||
INT16 ceilingclip[MAXVIDWIDTH], floorclip[MAXVIDWIDTH];
|
||||
INT16 *ceilingclip, *floorclip;
|
||||
|
||||
boolean use;
|
||||
} viewmorph = {
|
||||
@@ -641,7 +639,7 @@ static struct {
|
||||
0,
|
||||
|
||||
0,
|
||||
{}, {},
|
||||
NULL, NULL,
|
||||
|
||||
false
|
||||
};
|
||||
@@ -659,7 +657,6 @@ void R_CheckViewMorph(void)
|
||||
rollangle >>= ANGLETOFINESHIFT;
|
||||
rollangle = ((rollangle+2) & ~3) & FINEMASK; // Limit the distinct number of angles to reduce recalcs from angles changing a lot.
|
||||
|
||||
|
||||
if (rollangle == viewmorph.rollangle &&
|
||||
viewmorph.scrmapsize == vid.width*vid.height)
|
||||
return; // No change
|
||||
@@ -679,10 +676,10 @@ void R_CheckViewMorph(void)
|
||||
|
||||
if (viewmorph.scrmapsize != vid.width*vid.height)
|
||||
{
|
||||
if (viewmorph.scrmap)
|
||||
free(viewmorph.scrmap);
|
||||
viewmorph.scrmap = malloc(vid.width*vid.height * sizeof(INT32));
|
||||
viewmorph.scrmapsize = vid.width*vid.height;
|
||||
viewmorph.scrmap = static_cast<INT32*>(realloc(viewmorph.scrmap, vid.width*vid.height * sizeof(INT32)));
|
||||
viewmorph.ceilingclip = static_cast<INT16*>(realloc(viewmorph.ceilingclip, vid.width * sizeof(INT16)));
|
||||
viewmorph.floorclip = static_cast<INT16*>(realloc(viewmorph.floorclip, vid.width * sizeof(INT16)));
|
||||
}
|
||||
|
||||
temp = FINECOSINE(rollangle);
|
||||
@@ -694,7 +691,7 @@ void R_CheckViewMorph(void)
|
||||
x1 = (vid.width*fabsf(rollcos) + vid.height*fabsf(rollsin)) / vid.width;
|
||||
y1 = (vid.height*fabsf(rollcos) + vid.width*fabsf(rollsin)) / vid.height;
|
||||
|
||||
temp = max(x1, y1)*FRACUNIT;
|
||||
temp = std::max(x1, y1)*FRACUNIT;
|
||||
if (temp < FRACUNIT)
|
||||
temp = FRACUNIT;
|
||||
else
|
||||
@@ -740,10 +737,10 @@ void R_CheckViewMorph(void)
|
||||
xb = vid.width-1-xa;
|
||||
yb = vid.height-1-ya;
|
||||
|
||||
viewmorph.ceilingclip[xa] = min(viewmorph.ceilingclip[xa], ya);
|
||||
viewmorph.floorclip[xa] = max(viewmorph.floorclip[xa], ya);
|
||||
viewmorph.ceilingclip[xb] = min(viewmorph.ceilingclip[xb], yb);
|
||||
viewmorph.floorclip[xb] = max(viewmorph.floorclip[xb], yb);
|
||||
viewmorph.ceilingclip[xa] = std::min(viewmorph.ceilingclip[xa], ya);
|
||||
viewmorph.floorclip[xa] = std::max(viewmorph.floorclip[xa], ya);
|
||||
viewmorph.ceilingclip[xb] = std::min(viewmorph.ceilingclip[xb], yb);
|
||||
viewmorph.floorclip[xb] = std::max(viewmorph.floorclip[xb], yb);
|
||||
x2 += rollcos;
|
||||
y2 += rollsin;
|
||||
}
|
||||
@@ -757,10 +754,10 @@ void R_CheckViewMorph(void)
|
||||
xb = vid.width-1-xa;
|
||||
yb = vid.height-1-ya;
|
||||
|
||||
viewmorph.ceilingclip[xa] = min(viewmorph.ceilingclip[xa], ya);
|
||||
viewmorph.floorclip[xa] = max(viewmorph.floorclip[xa], ya);
|
||||
viewmorph.ceilingclip[xb] = min(viewmorph.ceilingclip[xb], yb);
|
||||
viewmorph.floorclip[xb] = max(viewmorph.floorclip[xb], yb);
|
||||
viewmorph.ceilingclip[xa] = std::min(viewmorph.ceilingclip[xa], ya);
|
||||
viewmorph.floorclip[xa] = std::max(viewmorph.floorclip[xa], ya);
|
||||
viewmorph.ceilingclip[xb] = std::min(viewmorph.ceilingclip[xb], yb);
|
||||
viewmorph.floorclip[xb] = std::max(viewmorph.floorclip[xb], yb);
|
||||
x2 -= rollsin;
|
||||
y2 += rollcos;
|
||||
}
|
||||
@@ -798,8 +795,8 @@ void R_CheckViewMorph(void)
|
||||
|
||||
void R_ApplyViewMorph(void)
|
||||
{
|
||||
UINT8 *tmpscr = screens[4];
|
||||
UINT8 *srcscr = screens[0];
|
||||
UINT8 *tmpscr = vid.screens[4];
|
||||
UINT8 *srcscr = vid.screens[0];
|
||||
INT32 p, end = vid.width * vid.height;
|
||||
|
||||
if (!viewmorph.use)
|
||||
@@ -834,8 +831,7 @@ void R_ApplyViewMorph(void)
|
||||
for (p = 0; p < end; p++)
|
||||
tmpscr[p] = srcscr[viewmorph.scrmap[p]];
|
||||
|
||||
VID_BlitLinearScreen(tmpscr, screens[0],
|
||||
vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.width);
|
||||
VID_BlitLinearScreen(tmpscr, vid.screens[0], vid.width, vid.height, vid.width, vid.width);
|
||||
}
|
||||
|
||||
angle_t R_ViewRollAngle(const player_t *player)
|
||||
@@ -888,6 +884,8 @@ void R_SetViewSize(void)
|
||||
setsizeneeded = true;
|
||||
}
|
||||
|
||||
static void R_SetupViewBuffers(void);
|
||||
|
||||
//
|
||||
// R_ExecuteSetViewSize
|
||||
//
|
||||
@@ -906,18 +904,15 @@ void R_ExecuteSetViewSize(void)
|
||||
// status bar overlay
|
||||
st_overlay = cv_showhud.value;
|
||||
|
||||
scaledviewwidth = vid.width;
|
||||
viewwidth = vid.width;
|
||||
viewheight = vid.height;
|
||||
|
||||
if (splitscreen)
|
||||
viewheight >>= 1;
|
||||
|
||||
viewwidth = scaledviewwidth;
|
||||
|
||||
if (splitscreen > 1)
|
||||
{
|
||||
viewwidth >>= 1;
|
||||
scaledviewwidth >>= 1;
|
||||
}
|
||||
|
||||
centerx = viewwidth/2;
|
||||
@@ -925,9 +920,7 @@ void R_ExecuteSetViewSize(void)
|
||||
centerxfrac = centerx<<FRACBITS;
|
||||
centeryfrac = centery<<FRACBITS;
|
||||
|
||||
R_SetFov(cv_fov.value);
|
||||
|
||||
R_InitViewBuffer(scaledviewwidth, viewheight);
|
||||
R_SetupViewBuffers();
|
||||
|
||||
// why did we calc all the software crap?
|
||||
#ifdef HWRENDER
|
||||
@@ -941,7 +934,10 @@ void R_ExecuteSetViewSize(void)
|
||||
|
||||
// thing clipping
|
||||
for (i = 0; i < viewwidth; i++)
|
||||
{
|
||||
negonearray[i] = -1;
|
||||
screenheightarray[i] = (INT16)viewheight;
|
||||
}
|
||||
|
||||
if (ds_su)
|
||||
Z_Free(ds_su);
|
||||
@@ -951,7 +947,6 @@ void R_ExecuteSetViewSize(void)
|
||||
Z_Free(ds_sz);
|
||||
|
||||
ds_su = ds_sv = ds_sz = NULL;
|
||||
ds_sup = ds_svp = ds_szp = NULL;
|
||||
|
||||
memset(scalelight, 0xFF, sizeof(scalelight));
|
||||
|
||||
@@ -979,33 +974,52 @@ void R_ExecuteSetViewSize(void)
|
||||
fixed_t R_GetPlayerFov(player_t *player)
|
||||
{
|
||||
fixed_t fov = cv_fov.value + player->fovadd;
|
||||
return max(MINFOV*FRACUNIT, min(fov, MAXFOV*FRACUNIT));
|
||||
return std::max(MINFOV*FRACUNIT, std::min(fov, MAXFOV*FRACUNIT));
|
||||
}
|
||||
|
||||
static void R_SetFov(fixed_t playerfov)
|
||||
static void R_CalcFov(fixed_t playerfov)
|
||||
{
|
||||
angle_t fov = FixedAngle(playerfov/2) + ANGLE_90;
|
||||
fovtan = FixedMul(FINETANGENT(fov >> ANGLETOFINESHIFT), viewmorph.zoomneeded);
|
||||
if (splitscreen == 1) // Splitscreen FOV should be adjusted to maintain expected vertical view
|
||||
fovtan = 17*fovtan/10;
|
||||
|
||||
// this is only used for planes rendering in software mode
|
||||
INT32 j = viewheight*16;
|
||||
for (INT32 i = 0; i < j; i++)
|
||||
{
|
||||
fixed_t dy = (i - viewheight*8)<<FRACBITS;
|
||||
dy = FixedMul(abs(dy), fovtan);
|
||||
yslopetab[i] = FixedDiv(centerx*FRACUNIT, dy);
|
||||
}
|
||||
|
||||
projection = projectiony = FixedDiv(centerxfrac, fovtan);
|
||||
}
|
||||
|
||||
static void R_InitViewMapping(void)
|
||||
{
|
||||
R_InitTextureMapping();
|
||||
|
||||
if (rendermode == render_soft)
|
||||
{
|
||||
// this is only used for planes rendering in software mode
|
||||
INT32 j = viewheight*16;
|
||||
|
||||
for (INT32 i = 0; i < j; i++)
|
||||
{
|
||||
fixed_t dy = (i - viewheight*8)<<FRACBITS;
|
||||
dy = FixedMul(abs(dy), fovtan);
|
||||
yslopetab[i] = FixedDiv(centerx*FRACUNIT, dy);
|
||||
}
|
||||
}
|
||||
|
||||
// setup sky scaling
|
||||
R_SetSkyScale();
|
||||
}
|
||||
|
||||
static void R_SetupViewBuffers(void)
|
||||
{
|
||||
R_CalcFov(cv_fov.value);
|
||||
R_InitViewBuffer(viewwidth, viewheight);
|
||||
R_InitViewMapping();
|
||||
}
|
||||
|
||||
static void R_SetFov(fixed_t playerfov)
|
||||
{
|
||||
R_CalcFov(playerfov);
|
||||
R_InitViewMapping();
|
||||
}
|
||||
|
||||
//
|
||||
// R_Init
|
||||
@@ -1021,9 +1035,6 @@ void R_Init(void)
|
||||
R_InitViewBorder();
|
||||
R_SetViewSize(); // setsizeneeded is set true
|
||||
|
||||
//I_OutputMsg("\nR_InitPlanes");
|
||||
R_InitPlanes();
|
||||
|
||||
// this is now done by SCR_Recalc() at the first mode set
|
||||
//I_OutputMsg("\nR_InitLightTables");
|
||||
R_InitLightTables();
|
||||
@@ -1062,33 +1073,93 @@ static void R_SetupCommonFrame(player_t * player, sector_t * sector)
|
||||
|
||||
static void R_SetupAimingFrame(player_t *player, camera_t *thiscam)
|
||||
{
|
||||
if (player->awayviewtics)
|
||||
if (player->awayviewtics && player->awayviewmobj)
|
||||
{
|
||||
newview->aim = player->awayviewaiming;
|
||||
newview->angle = player->awayviewmobj->angle;
|
||||
}
|
||||
else if (thiscam->chase)
|
||||
else if (thiscam && thiscam->chase)
|
||||
{
|
||||
newview->aim = thiscam->aiming;
|
||||
newview->angle = thiscam->angle;
|
||||
}
|
||||
else if (P_IsLocalPlayer(player) && !demo.playback && player->playerstate != PST_DEAD)
|
||||
{
|
||||
newview->aim = localaiming[viewssnum];
|
||||
newview->angle = localangle[viewssnum];
|
||||
}
|
||||
else
|
||||
{
|
||||
newview->aim = player->aiming;
|
||||
newview->angle = player->mo->angle;
|
||||
}
|
||||
}
|
||||
|
||||
if (!demo.playback && player->playerstate != PST_DEAD)
|
||||
static void R_SetupSkyScale(player_t *player, camera_t *thiscam, mapheader_t *mh)
|
||||
{
|
||||
if (!mh->skybox_scalex && !mh->skybox_scaley && !mh->skybox_scalez)
|
||||
return;
|
||||
|
||||
auto setup_skyscale = [&](fixed_t mox, fixed_t moy, fixed_t zscale)
|
||||
{
|
||||
if (skyboxmo[1])
|
||||
{
|
||||
for (UINT8 i = 0; i <= splitscreen; i++)
|
||||
angle_t ang;
|
||||
fixed_t x = 0, y = 0;
|
||||
|
||||
if (mh->skybox_scalex > 0)
|
||||
x = (mox - skyboxmo[1]->x) / mh->skybox_scalex;
|
||||
else if (mh->skybox_scalex < 0)
|
||||
x = (mox - skyboxmo[1]->x) * -mh->skybox_scalex;
|
||||
|
||||
if (mh->skybox_scaley > 0)
|
||||
y = (moy - skyboxmo[1]->y) / mh->skybox_scaley;
|
||||
else if (mh->skybox_scaley < 0)
|
||||
y = (moy - skyboxmo[1]->y) * -mh->skybox_scaley;
|
||||
|
||||
switch (viewmobj->angle)
|
||||
{
|
||||
if (player == (i == 0 ? &players[consoleplayer] : &players[displayplayers[i]]))
|
||||
{
|
||||
newview->angle = localangle[i];
|
||||
newview->aim = localaiming[i];
|
||||
case 0:
|
||||
newview->x += x;
|
||||
newview->y += y;
|
||||
break;
|
||||
case ANGLE_90:
|
||||
newview->x -= y;
|
||||
newview->y += x;
|
||||
break;
|
||||
case ANGLE_180:
|
||||
newview->x -= x;
|
||||
newview->y -= y;
|
||||
break;
|
||||
case ANGLE_270:
|
||||
newview->x += y;
|
||||
newview->y -= x;
|
||||
break;
|
||||
default:
|
||||
ang = viewmobj->angle>>ANGLETOFINESHIFT;
|
||||
newview->x += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));
|
||||
newview->y += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mh->skybox_scalez > 0)
|
||||
newview->z += zscale / mh->skybox_scalez;
|
||||
else if (mh->skybox_scalez < 0)
|
||||
newview->z += zscale * -mh->skybox_scalez;
|
||||
};
|
||||
|
||||
if (player->awayviewtics && player->awayviewmobj)
|
||||
{
|
||||
setup_skyscale(player->awayviewmobj->x, player->awayviewmobj->y, (player->awayviewmobj->z + 20*FRACUNIT));
|
||||
}
|
||||
else if (thiscam && thiscam->chase)
|
||||
{
|
||||
setup_skyscale(thiscam->x, thiscam->y, (thiscam->z + (thiscam->height>>1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
setup_skyscale(player->mo->x, player->mo->y, player->viewz);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1097,12 +1168,14 @@ void R_SkyboxFrame(int s)
|
||||
player_t *player = &players[displayplayers[s]];
|
||||
camera_t *thiscam = &camera[s];
|
||||
subsector_t * subsector = NULL;
|
||||
mapheader_t *mh = mapheaderinfo[gamemap-1];
|
||||
|
||||
R_SetViewContext(VIEWCONTEXT_SKY1 + s);
|
||||
R_SetViewContext(static_cast<viewcontext_e>(VIEWCONTEXT_SKY1 + s));
|
||||
|
||||
// cut-away view stuff
|
||||
newview->sky = true;
|
||||
viewmobj = skyboxmo[0];
|
||||
|
||||
#ifdef PARANOIA
|
||||
if (P_MobjWasRemoved(viewmobj))
|
||||
{
|
||||
@@ -1110,78 +1183,19 @@ void R_SkyboxFrame(int s)
|
||||
I_Error("R_SkyboxFrame: viewmobj null (player %s)", sizeu1(playeri));
|
||||
}
|
||||
#endif
|
||||
|
||||
R_SetupAimingFrame(player, thiscam);
|
||||
|
||||
newview->angle += viewmobj->angle;
|
||||
|
||||
newview->x = viewmobj->x;
|
||||
newview->y = viewmobj->y;
|
||||
newview->z = 0;
|
||||
if (viewmobj->spawnpoint)
|
||||
newview->z = ((fixed_t)viewmobj->spawnpoint->angle)<<FRACBITS;
|
||||
newview->z = (viewmobj->spawnpoint) ? (((fixed_t)viewmobj->spawnpoint->angle)<<FRACBITS) : 0;
|
||||
|
||||
#define SETUPSKYVIEW(viewmo, zscale)\
|
||||
if (skyboxmo[1])\
|
||||
{\
|
||||
fixed_t x = 0, y = 0;\
|
||||
if (mh->skybox_scalex > 0)\
|
||||
x = (viewmo->x - skyboxmo[1]->x) / mh->skybox_scalex;\
|
||||
else if (mh->skybox_scalex < 0)\
|
||||
x = (viewmo->x - skyboxmo[1]->x) * -mh->skybox_scalex;\
|
||||
if (mh->skybox_scaley > 0)\
|
||||
y = (viewmo->y - skyboxmo[1]->y) / mh->skybox_scaley;\
|
||||
else if (mh->skybox_scaley < 0)\
|
||||
y = (viewmo->y - skyboxmo[1]->y) * -mh->skybox_scaley;\
|
||||
if (viewmobj->angle == 0)\
|
||||
{\
|
||||
newview->x += x;\
|
||||
newview->y += y;\
|
||||
}\
|
||||
else if (viewmobj->angle == ANGLE_90)\
|
||||
{\
|
||||
newview->x -= y;\
|
||||
newview->y += x;\
|
||||
}\
|
||||
else if (viewmobj->angle == ANGLE_180)\
|
||||
{\
|
||||
newview->x -= x;\
|
||||
newview->y -= y;\
|
||||
}\
|
||||
else if (viewmobj->angle == ANGLE_270)\
|
||||
{\
|
||||
newview->x += y;\
|
||||
newview->y -= x;\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
angle_t ang = viewmobj->angle>>ANGLETOFINESHIFT;\
|
||||
newview->x += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));\
|
||||
newview->y += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));\
|
||||
}\
|
||||
}\
|
||||
if (mh->skybox_scalez > 0)\
|
||||
newview->z += zscale / mh->skybox_scalez;\
|
||||
else if (mh->skybox_scalez < 0)\
|
||||
newview->z += zscale * -mh->skybox_scalez;
|
||||
|
||||
if (mapheaderinfo[gamemap-1])
|
||||
if (mh)
|
||||
{
|
||||
mapheader_t *mh = mapheaderinfo[gamemap-1];
|
||||
|
||||
if (player->awayviewtics)
|
||||
{
|
||||
SETUPSKYVIEW(player->awayviewmobj, (player->awayviewmobj->z + 20*FRACUNIT));
|
||||
}
|
||||
else if (thiscam->chase)
|
||||
{
|
||||
SETUPSKYVIEW(thiscam, (thiscam->z + (thiscam->height>>1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
SETUPSKYVIEW(player->mo, player->viewz);
|
||||
}
|
||||
R_SetupSkyScale(player, thiscam, mh);
|
||||
}
|
||||
#undef SETUPSKYVIEW
|
||||
|
||||
if (!P_MobjWasRemoved(viewmobj) && viewmobj->subsector && viewmobj->subsector->sector)
|
||||
subsector = viewmobj->subsector;
|
||||
@@ -1196,7 +1210,8 @@ void R_SetupFrame(int s, boolean skybox)
|
||||
boolean chasecam = (cv_chasecam[s].value);
|
||||
sector_t * sector = NULL;
|
||||
|
||||
R_SetViewContext(VIEWCONTEXT_PLAYER1 + s);
|
||||
R_SetViewContext(static_cast<viewcontext_e>(VIEWCONTEXT_PLAYER1 + s));
|
||||
|
||||
if (thiscam->reset)
|
||||
{
|
||||
R_ResetViewInterpolation(s);
|
||||
@@ -1225,7 +1240,7 @@ void R_SetupFrame(int s, boolean skybox)
|
||||
|
||||
R_SetupAimingFrame(player, thiscam);
|
||||
|
||||
if (player->awayviewtics) // cut-away view stuff
|
||||
if (player->awayviewtics && player->awayviewmobj) // cut-away view stuff
|
||||
{
|
||||
viewmobj = player->awayviewmobj; // should be a MT_ALTVIEWMAN
|
||||
I_Assert(viewmobj != NULL);
|
||||
@@ -1234,7 +1249,7 @@ void R_SetupFrame(int s, boolean skybox)
|
||||
newview->y = viewmobj->y;
|
||||
newview->z = viewmobj->z + 20*FRACUNIT;
|
||||
|
||||
if (!P_MobjWasRemoved(viewmobj) && viewmobj->subsector && viewmobj->subsector->sector)
|
||||
if (viewmobj->subsector && viewmobj->subsector->sector)
|
||||
sector = viewmobj->subsector->sector;
|
||||
|
||||
R_SetupCommonFrame(player, sector);
|
||||
@@ -1242,17 +1257,18 @@ void R_SetupFrame(int s, boolean skybox)
|
||||
else if (thiscam && chasecam) // use outside cam view
|
||||
{
|
||||
viewmobj = NULL;
|
||||
I_Assert(thiscam != NULL);
|
||||
|
||||
newview->x = thiscam->x;
|
||||
newview->y = thiscam->y;
|
||||
newview->z = thiscam->z + (thiscam->height>>1);
|
||||
|
||||
if (thiscam != NULL && thiscam->subsector && thiscam->subsector->sector)
|
||||
if (thiscam->subsector && thiscam->subsector->sector)
|
||||
sector = thiscam->subsector->sector;
|
||||
|
||||
R_SetupCommonFrame(player, sector);
|
||||
}
|
||||
else // use the player's eyes view
|
||||
else if (player->mo) // use the player's eyes view
|
||||
{
|
||||
viewmobj = player->mo;
|
||||
I_Assert(viewmobj != NULL);
|
||||
@@ -1261,7 +1277,7 @@ void R_SetupFrame(int s, boolean skybox)
|
||||
newview->y = viewmobj->y;
|
||||
newview->z = player->viewz;
|
||||
|
||||
if (!P_MobjWasRemoved(viewmobj) && viewmobj->subsector && viewmobj->subsector->sector)
|
||||
if (viewmobj->subsector && viewmobj->subsector->sector)
|
||||
sector = viewmobj->subsector->sector;
|
||||
|
||||
R_SetupCommonFrame(player, sector);
|
||||
@@ -1275,8 +1291,8 @@ static void R_PortalFrame(portal_t *portal)
|
||||
viewz = portal->viewz;
|
||||
|
||||
viewangle = portal->viewangle;
|
||||
// viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
|
||||
// viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
|
||||
//viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
|
||||
//viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
|
||||
|
||||
portalclipstart = portal->start;
|
||||
portalclipend = portal->end;
|
||||
@@ -1284,8 +1300,7 @@ static void R_PortalFrame(portal_t *portal)
|
||||
if (portal->clipline != -1)
|
||||
{
|
||||
portalclipline = &lines[portal->clipline];
|
||||
portalcullsector = portalclipline->frontsector;
|
||||
viewsector = portalclipline->frontsector;
|
||||
viewsector = portalcullsector = portalclipline->frontsector;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1295,10 +1310,41 @@ static void R_PortalFrame(portal_t *portal)
|
||||
}
|
||||
}
|
||||
|
||||
static void Mask_Pre (maskcount_t* m)
|
||||
{
|
||||
m->drawsegs[0] = ds_p - drawsegs;
|
||||
m->vissprites[0] = visspritecount;
|
||||
m->viewx = viewx;
|
||||
m->viewy = viewy;
|
||||
m->viewz = viewz;
|
||||
m->viewsector = viewsector;
|
||||
}
|
||||
|
||||
static void Mask_Post (maskcount_t* m)
|
||||
{
|
||||
m->drawsegs[1] = ds_p - drawsegs;
|
||||
m->vissprites[1] = visspritecount;
|
||||
}
|
||||
|
||||
// ================
|
||||
// R_RenderView
|
||||
// ================
|
||||
|
||||
// viewx, viewy, viewangle, all that good stuff must be set
|
||||
static void R_RenderViewpoint(maskcount_t* mask, boolean drawprecip)
|
||||
{
|
||||
Mask_Pre(mask);
|
||||
|
||||
curdrawsegs = ds_p;
|
||||
|
||||
R_RenderBSPNode((INT32)numnodes - 1);
|
||||
|
||||
if (drawprecip)
|
||||
R_AddPrecipitationSprites();
|
||||
|
||||
Mask_Post(mask);
|
||||
}
|
||||
|
||||
// FAB NOTE FOR WIN32 PORT !! I'm not finished already,
|
||||
// but I suspect network may have problems with the video buffer being locked
|
||||
// for all duration of rendering, and being released only once at the end..
|
||||
@@ -1309,52 +1355,19 @@ static fixed_t viewfov[MAXSPLITSCREENPLAYERS];
|
||||
|
||||
void R_RenderPlayerView(player_t *player)
|
||||
{
|
||||
const boolean skybox = (skyboxmo[0] && cv_skybox.value);
|
||||
UINT8 i;
|
||||
|
||||
// if this is display player 1
|
||||
if (cv_homremoval.value && player == &players[displayplayers[0]])
|
||||
{
|
||||
if (cv_homremoval.value == 1)
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); // No HOM effect!
|
||||
else //'development' HOM removal -- makes it blindingly obvious if HOM is spotted.
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 128+(timeinmap&15));
|
||||
}
|
||||
// Draw over the fourth screen so you don't have to stare at a HOM :V
|
||||
else if (splitscreen == 2 && player == &players[displayplayers[2]])
|
||||
{
|
||||
// V_DrawPatchFill, but for the fourth screen only
|
||||
patch_t *pat = W_CachePatchName("SRB2BACK", PU_CACHE);
|
||||
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
|
||||
INT32 x, y, pw = SHORT(pat->width) * dupz, ph = SHORT(pat->height) * dupz;
|
||||
|
||||
for (x = vid.width>>1; x < vid.width; x += pw)
|
||||
{
|
||||
for (y = vid.height>>1; y < vid.height; y += ph)
|
||||
V_DrawScaledPatch(x, y, V_NOSCALESTART, pat);
|
||||
}
|
||||
}
|
||||
INT32 nummasks = 1;
|
||||
maskcount_t* masks = static_cast<maskcount_t*>(malloc(sizeof(maskcount_t)));
|
||||
const boolean skybox = (skyboxmo[0] && cv_skybox.value);
|
||||
|
||||
// load previous saved value of skyVisible for the player
|
||||
for (i = 0; i <= splitscreen; i++)
|
||||
skyVisible = skyVisiblePerPlayer[viewssnum];
|
||||
|
||||
const fixed_t fov = R_GetPlayerFov(player);
|
||||
|
||||
if (viewfov[viewssnum] != fov)
|
||||
{
|
||||
if (player != &players[displayplayers[i]])
|
||||
continue;
|
||||
|
||||
skyVisible = skyVisiblePerPlayer[i];
|
||||
break;
|
||||
}
|
||||
|
||||
fixed_t fov = R_GetPlayerFov(player);
|
||||
|
||||
for (UINT8 j = 0; j <= splitscreen; j++)
|
||||
{
|
||||
if (player == &players[displayplayers[i]]
|
||||
&& viewfov[i] != fov)
|
||||
{
|
||||
viewfov[i] = fov;
|
||||
R_SetFov(fov);
|
||||
}
|
||||
viewfov[viewssnum] = fov;
|
||||
R_SetFov(fov);
|
||||
}
|
||||
|
||||
Portal_InitList();
|
||||
@@ -1368,17 +1381,13 @@ void R_RenderPlayerView(player_t *player)
|
||||
R_ClearDrawSegs();
|
||||
R_ClearPlanes();
|
||||
R_ClearSprites();
|
||||
#ifdef FLOORSPLATS
|
||||
R_ClearVisibleFloorSplats();
|
||||
#endif
|
||||
|
||||
R_RenderBSPNode((INT32)numnodes - 1);
|
||||
R_ClipSprites();
|
||||
R_RenderViewpoint(&masks[nummasks - 1], false);
|
||||
|
||||
R_ClipSprites(drawsegs, NULL);
|
||||
R_DrawSkyPlanes(); // draw the fucker again to prevent some artifacts
|
||||
R_DrawPlanes();
|
||||
#ifdef FLOORSPLATS
|
||||
R_DrawVisibleFloorSplats();
|
||||
#endif
|
||||
R_DrawMasked();
|
||||
R_DrawMasked(masks, nummasks);
|
||||
}
|
||||
PS_STOP_TIMING(ps_skyboxtime);
|
||||
|
||||
@@ -1405,22 +1414,16 @@ void R_RenderPlayerView(player_t *player)
|
||||
}
|
||||
R_ClearDrawSegs();
|
||||
R_ClearSprites();
|
||||
#ifdef FLOORSPLATS
|
||||
R_ClearVisibleFloorSplats();
|
||||
#endif
|
||||
|
||||
// check for new console commands.
|
||||
NetUpdate();
|
||||
|
||||
// The head node is the last node output.
|
||||
|
||||
ps_numbspcalls.value.i = ps_numpolyobjects.value.i = ps_numdrawnodes.value.i = 0;
|
||||
PS_START_TIMING(ps_bsptime);
|
||||
R_RenderBSPNode((INT32)numnodes - 1);
|
||||
R_RenderViewpoint(&masks[nummasks - 1], true);
|
||||
PS_STOP_TIMING(ps_bsptime);
|
||||
R_AddPrecipitationSprites();
|
||||
PS_START_TIMING(ps_sw_spritecliptime);
|
||||
R_ClipSprites();
|
||||
R_ClipSprites(drawsegs, NULL);
|
||||
PS_STOP_TIMING(ps_sw_spritecliptime);
|
||||
|
||||
ps_numsprites.value.i = numvisiblesprites;
|
||||
@@ -1449,43 +1452,40 @@ void R_RenderPlayerView(player_t *player)
|
||||
// that were previously stored.
|
||||
Portal_ClipApply(portal);
|
||||
|
||||
validcount++;
|
||||
|
||||
masks = static_cast<maskcount_t*>(realloc(masks, (++nummasks)*sizeof(maskcount_t)));
|
||||
|
||||
// Render the BSP from the new viewpoint, and clip
|
||||
// any sprites with the new clipsegs and window.
|
||||
R_RenderBSPNode((INT32)numnodes - 1);
|
||||
R_ClipSprites();
|
||||
R_RenderViewpoint(&masks[nummasks - 1], true);
|
||||
|
||||
R_ClipSprites(ds_p - (masks[nummasks - 1].drawsegs[1] - masks[nummasks - 1].drawsegs[0]), portal);
|
||||
|
||||
Portal_Remove(portal);
|
||||
|
||||
validcount++;
|
||||
}
|
||||
}
|
||||
PS_STOP_TIMING(ps_sw_portaltime);
|
||||
|
||||
PS_START_TIMING(ps_sw_planetime);
|
||||
if (!skybox)
|
||||
R_DrawSkyPlanes();
|
||||
R_DrawPlanes();
|
||||
PS_STOP_TIMING(ps_sw_planetime);
|
||||
#ifdef FLOORSPLATS
|
||||
R_DrawVisibleFloorSplats();
|
||||
#endif
|
||||
// draw mid texture and sprite
|
||||
// And now 3D floors/sides!
|
||||
PS_START_TIMING(ps_sw_maskedtime);
|
||||
R_DrawMasked();
|
||||
R_DrawMasked(masks, nummasks);
|
||||
PS_STOP_TIMING(ps_sw_maskedtime);
|
||||
|
||||
free(masks);
|
||||
|
||||
// Check for new console commands.
|
||||
NetUpdate();
|
||||
|
||||
// save value to skyVisiblePerPlayer
|
||||
// this is so that P1 can't affect whether P2 can see a skybox or not, or vice versa
|
||||
for (i = 0; i <= splitscreen; i++)
|
||||
{
|
||||
if (player != &players[displayplayers[i]])
|
||||
continue;
|
||||
|
||||
skyVisiblePerPlayer[i] = skyVisible;
|
||||
break;
|
||||
}
|
||||
skyVisiblePerPlayer[viewssnum] = skyVisible;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
@@ -1526,11 +1526,13 @@ void R_RegisterEngineStuff(void)
|
||||
{
|
||||
CV_RegisterVar(&cv_chasecam[i]);
|
||||
}
|
||||
|
||||
CV_RegisterVar(&cv_shadow);
|
||||
CV_RegisterVar(&cv_shadowoffs);
|
||||
CV_RegisterVar(&cv_skybox);
|
||||
CV_RegisterVar(&cv_ffloorclip);
|
||||
CV_RegisterVar(&cv_spriteclip);
|
||||
CV_RegisterVar(&cv_softcyancut);
|
||||
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
+11
-1
@@ -14,6 +14,10 @@
|
||||
#ifndef __R_MAIN__
|
||||
#define __R_MAIN__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "d_player.h"
|
||||
#include "r_data.h"
|
||||
#include "m_perfstats.h"
|
||||
@@ -84,7 +88,7 @@ extern lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ];
|
||||
//
|
||||
// killough 5/2/98: reformatted
|
||||
//
|
||||
FUNCINLINE static ATTRINLINE PUREFUNC INT32 R_PointOnSide(fixed_t x, fixed_t y, const node_t *restrict node)
|
||||
FUNCINLINE static ATTRINLINE PUREFUNC INT32 R_PointOnSide(fixed_t x, fixed_t y, const node_t * restrict node)
|
||||
{
|
||||
if (!node->dx)
|
||||
return x <= node->x ? node->dy > 0 : node->dy < 0;
|
||||
@@ -207,6 +211,7 @@ extern consvar_t cv_chasecam[MAXSPLITSCREENPLAYERS];
|
||||
extern consvar_t cv_flipcam[MAXSPLITSCREENPLAYERS];
|
||||
extern consvar_t cv_shadow, cv_shadowoffs;
|
||||
extern consvar_t cv_ffloorclip, cv_spriteclip;
|
||||
extern consvar_t cv_softcyancut;
|
||||
extern consvar_t cv_translucency;
|
||||
extern consvar_t cv_drawdist, cv_drawdist_precip, cv_lessprecip, cv_mobjscaleprecip;
|
||||
extern consvar_t cv_fov, cv_fovchange;
|
||||
@@ -245,4 +250,9 @@ void R_RegisterEngineStuff(void);
|
||||
INT32 R_GetHudUncap(void);
|
||||
// same as above but keeps interpolation during pause
|
||||
INT32 R_GetMenuUncap(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "doomdef.h"
|
||||
#include "r_patch.h"
|
||||
#include "r_things.h"
|
||||
#include "r_skins.h"
|
||||
#include "z_zone.h"
|
||||
#include "w_wad.h"
|
||||
|
||||
|
||||
@@ -12,6 +12,10 @@
|
||||
#ifndef __R_PATCHROTATION__
|
||||
#define __R_PATCHROTATION__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "r_fps.h"
|
||||
|
||||
// Sprite rotation
|
||||
@@ -27,4 +31,8 @@ extern fixed_t rollcosang[ROTANGLES];
|
||||
extern fixed_t rollsinang[ROTANGLES];
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __R_PATCHROTATION__
|
||||
-1201
File diff suppressed because it is too large.
Load diff
+1408
File diff suppressed because it is too large.
Load diff
+21
-19
@@ -14,6 +14,10 @@
|
||||
#ifndef __R_PLANE__
|
||||
#define __R_PLANE__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "screen.h" // needs MAXVIDWIDTH/MAXVIDHEIGHT
|
||||
#include "r_data.h"
|
||||
#include "p_polyobj.h"
|
||||
@@ -43,9 +47,8 @@ typedef struct visplane_s
|
||||
// colormaps per sector
|
||||
extracolormap_t *extra_colormap;
|
||||
|
||||
// leave pads for [minx-1]/[maxx+1]
|
||||
UINT16 padtopstart, top[MAXVIDWIDTH], padtopend;
|
||||
UINT16 padbottomstart, bottom[MAXVIDWIDTH], padbottomend;
|
||||
UINT16 *top, *top_memory;
|
||||
UINT16 *bottom, *bottom_memory;
|
||||
INT32 high, low; // R_PlaneBounds should set these.
|
||||
|
||||
fixed_t xoffs, yoffs; // Scrolling flats.
|
||||
@@ -55,8 +58,11 @@ typedef struct visplane_s
|
||||
pslope_t *slope;
|
||||
|
||||
boolean noencore;
|
||||
boolean cyan;
|
||||
} visplane_t;
|
||||
|
||||
extern visplane_t *visplanes[MAXVISPLANES];
|
||||
|
||||
extern visplane_t *floorplane;
|
||||
extern visplane_t *ceilingplane;
|
||||
|
||||
@@ -64,25 +70,19 @@ extern visplane_t *ceilingplane;
|
||||
extern INT16 *lastopening, *openings;
|
||||
extern size_t maxopenings;
|
||||
|
||||
extern INT16 floorclip[MAXVIDWIDTH], ceilingclip[MAXVIDWIDTH];
|
||||
extern fixed_t frontscale[MAXVIDWIDTH], yslopetab[MAXVIDHEIGHT*16];
|
||||
extern fixed_t cachedheight[MAXVIDHEIGHT];
|
||||
extern fixed_t cacheddistance[MAXVIDHEIGHT];
|
||||
extern fixed_t cachedxstep[MAXVIDHEIGHT];
|
||||
extern fixed_t cachedystep[MAXVIDHEIGHT];
|
||||
extern INT16 *floorclip, *ceilingclip;
|
||||
extern fixed_t *frontscale, *yslopetab;
|
||||
extern fixed_t basexscale, baseyscale;
|
||||
|
||||
extern fixed_t *yslope;
|
||||
extern lighttable_t **planezlight;
|
||||
|
||||
void R_InitPlanes(void);
|
||||
void R_AllocPlaneMemory(void);
|
||||
void R_ClearPlanes(void);
|
||||
void R_ClearFFloorClips (void);
|
||||
|
||||
void R_MapPlane(INT32 y, INT32 x1, INT32 x2);
|
||||
void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2);
|
||||
void R_DrawSkyPlanes(void);
|
||||
void R_DrawPlanes(void);
|
||||
void R_CalculateSlopeVectors(pslope_t *slope, fixed_t planeviewx, fixed_t planeviewy, fixed_t planeviewz, fixed_t planexscale, fixed_t planeyscale, fixed_t planexoffset, fixed_t planeyoffset, angle_t planeviewangle, angle_t planeangle, float fudge);
|
||||
|
||||
visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, fixed_t xoff, fixed_t yoff, angle_t plangle,
|
||||
extracolormap_t *planecolormap, ffloor_t *ffloor
|
||||
, polyobj_t *polyobj
|
||||
@@ -93,9 +93,6 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop);
|
||||
void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop);
|
||||
void R_PlaneBounds(visplane_t *plane);
|
||||
|
||||
// Draws a single visplane.
|
||||
void R_DrawSinglePlane(visplane_t *pl);
|
||||
|
||||
typedef struct planemgr_s
|
||||
{
|
||||
visplane_t *plane;
|
||||
@@ -104,8 +101,8 @@ typedef struct planemgr_s
|
||||
fixed_t b_pos; // B for Back sector
|
||||
fixed_t f_frac, f_step;
|
||||
fixed_t b_frac, b_step;
|
||||
INT16 f_clip[MAXVIDWIDTH];
|
||||
INT16 c_clip[MAXVIDWIDTH];
|
||||
INT16 *f_clip;
|
||||
INT16 *c_clip;
|
||||
|
||||
// For slope rendering; the height at the other end
|
||||
fixed_t f_pos_slope;
|
||||
@@ -119,4 +116,9 @@ typedef struct planemgr_s
|
||||
|
||||
extern visffloor_t ffloor[MAXFFLOORS];
|
||||
extern INT32 numffloors;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Loaded 100 of 132 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user